-
Notifications
You must be signed in to change notification settings - Fork 130
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
9 changed files
with
368 additions
and
12 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
name: Test | ||
on: | ||
push: | ||
branches: | ||
- master | ||
- stable* | ||
pull_request: | ||
|
||
jobs: | ||
test-api: | ||
runs-on: ubuntu-latest | ||
steps: | ||
- name: where is PHPUnit? | ||
run: | | ||
which phpunit | ||
find / -name PHPUnit -o -name phpunit | ||
- name: Checkout | ||
uses: actions/checkout@v2 | ||
- name: Set up php | ||
uses: shivammathur/setup-php@v2 | ||
- name: Install Dependencies | ||
run: composer install --prefer-dist | ||
- name: Prepare MySQL database | ||
run: | | ||
sudo systemctl start mysql | ||
mysql -u root -proot -e "CREATE DATABASE nextcloud;" | ||
mysql -u root -proot -e "CREATE USER 'nextcloud'@'localhost' IDENTIFIED BY '';" | ||
mysql -u root -proot -e "GRANT ALL ON nextcloud.* TO 'nextcloud'@'localhost';" | ||
- name: Prepare Nextcloud server | ||
working-directory: ../ | ||
run: | | ||
git clone https://github.com/nextcloud/server.git --recursive --depth 1 -b master server | ||
cp -r notes server/apps/ | ||
- name: Setup Nextcloud server | ||
working-directory: ../server/ | ||
run: | | ||
php occ maintenance:install --database-name nextcloud --database-user nextcloud --admin-user admin --admin-pass admin --database mysql --database-pass='' | ||
OC_PASS=test php occ user:add --password-from-env --display-name="Test" test | ||
OC_PASS=test php occ user:add --password-from-env --display-name="QuotaTest" quotatest | ||
php occ user:setting quotatest files quota "0" | ||
- name: Setup Notes app | ||
working-directory: ../server/ | ||
run: | | ||
php occ app:enable notes | ||
php occ app:check-code notes | ||
- name: Create some reference notes | ||
working-directory: ../ | ||
run: | | ||
mkdir -p server/data/test/files/ | ||
mkdir -p server/data/quotatest/files/ | ||
cp -r notes/tests/reference-notes server/data/test/files/Notes | ||
cp -r notes/tests/reference-notes server/data/quotatest/files/Notes | ||
php server/occ files:scan --all | ||
- name: Start Nextcloud server | ||
working-directory: ../server/ | ||
run: "php -S localhost:8080 &" | ||
- name: Test API | ||
run: make test-api | ||
- name: Show nextcloud.log | ||
if: always() | ||
run: "cat ../server/data/nextcloud.log" | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,168 @@ | ||
<?php declare(strict_types=1); | ||
|
||
require_once 'AbstractAPITest.php'; | ||
|
||
class APIv02Test extends AbstractAPITest { | ||
|
||
public function __construct() { | ||
parent::__construct('v0.2'); | ||
} | ||
|
||
public function testCheckForReferenceNotes() : array { | ||
$response = $this->http->request('GET', 'notes'); | ||
$this->checkResponse($response, 'Get existing notes', 200); | ||
$notes = json_decode($response->getBody()->getContents()); | ||
$this->assertNotEmpty($notes, 'List of notes'); | ||
return $notes; | ||
} | ||
|
||
/** @depends testCheckForReferenceNotes */ | ||
public function testGetNotesWithExclude(array $refNotes) : void { | ||
$this->checkGetReferenceNotes($refNotes, 'exclude content', '?exclude=content', false, ['content']); | ||
$this->checkGetReferenceNotes($refNotes, 'exclude content and category', '?exclude=content,category', false, ['content','category']); | ||
} | ||
|
||
/** @depends testCheckForReferenceNotes */ | ||
public function testGetNotesWithEtag(array $refNotes) : void { | ||
$response1 = $this->http->request('GET', 'notes'); | ||
$this->checkResponse($response1, 'Initial response', 200); | ||
$this->assertTrue($response1->hasHeader('ETag'), 'Initial response has ETag header'); | ||
$etag = $response1->getHeaderLine('ETag'); | ||
$this->assertRegExp('/^"[[:alnum:]]{32}"$/', $etag, 'ETag format'); | ||
|
||
// Test If-None-Match with ETag | ||
$response2 = $this->http->request('GET', 'notes', [ 'headers' => [ 'If-None-Match' => $etag ] ]); | ||
$this->checkResponse($response2, 'ETag response', 304); | ||
$this->assertEquals('', $response2->getBody(), 'ETag response body'); | ||
} | ||
|
||
/** @depends testCheckForReferenceNotes */ | ||
public function testGetNotesWithPruneBefore(array $refNotes) : void { | ||
sleep(1); // wait for 'Last-Modified' to be >= Last-change + 1 | ||
$response1 = $this->http->request('GET', 'notes'); | ||
$this->checkResponse($response1, 'Initial response', 200); | ||
$this->assertTrue($response1->hasHeader('Last-Modified'), 'Initial response has Last-Modified header'); | ||
$lastModified = $response1->getHeaderLine('Last-Modified'); | ||
$dt = \DateTime::createFromFormat(\DateTime::RFC2822, $lastModified); | ||
$this->assertInstanceOf(\DateTime::class, $dt); | ||
|
||
$this->checkGetReferenceNotes($refNotes, 'pruneBefore with Last-Modified', '?pruneBefore='.$dt->getTimestamp(), true); | ||
$this->checkGetReferenceNotes($refNotes, 'pruneBefore with 1', '?pruneBefore=1', false); | ||
$this->checkGetReferenceNotes($refNotes, 'pruneBefore with PHP_INT_MAX (32bit)', '?pruneBefore=2147483647', true); // 2038-01-19 03:14:07 | ||
$this->checkGetReferenceNotes($refNotes, 'pruneBefore with PHP_INT_MAX (64bit)', '?pruneBefore=9223372036854775807', true); | ||
} | ||
|
||
/** @depends testCheckForReferenceNotes */ | ||
public function testCreateNotes(array $refNotes) : array { | ||
$this->checkGetReferenceNotes($refNotes, 'Pre-condition'); | ||
$testNotes = []; | ||
$testNotes[] = $this->createNote((object)[ | ||
'title' => 'This is not used', | ||
'content' => '# *First* test/ note'.PHP_EOL.'This is some body content with some data.', | ||
'favorite' => true, | ||
'category' => 'Test/../New Category', | ||
'modified' => mktime(8, 14, 30, 10, 2, 2020), | ||
], (object)[ | ||
'title' => 'First test note', | ||
'category' => 'Test/New Category', | ||
]); | ||
$testNotes[] = $this->createNote((object)[ | ||
'content' => 'Note with Defaults'.PHP_EOL.'This is some body content with some data.', | ||
], (object)[ | ||
'title' => 'Note with Defaults', | ||
'favorite' => false, | ||
'category' => '', | ||
'modified' => time(), | ||
]); | ||
$this->checkGetReferenceNotes(array_merge($refNotes, $testNotes), 'After creating notes'); | ||
return $testNotes; | ||
} | ||
|
||
/** | ||
* @depends testCheckForReferenceNotes | ||
* @depends testCreateNotes | ||
*/ | ||
public function testGetSingleNote(array $refNotes, array $testNotes) : void { | ||
foreach($testNotes as $testNote) { | ||
$response = $this->http->request('GET', 'notes/'.$testNote->id); | ||
$this->checkResponse($response, 'Get note '.$testNote->title, 200); | ||
$note = json_decode($response->getBody()->getContents()); | ||
$this->checkReferenceNote($testNote, $note, 'Get single note'); | ||
} | ||
// test non-existing note | ||
$response = $this->http->request('GET', 'notes/1'); | ||
$this->assertEquals(404, $response->getStatusCode()); | ||
} | ||
|
||
|
||
/** | ||
* @depends testCheckForReferenceNotes | ||
* @depends testCreateNotes | ||
*/ | ||
public function testUpdateNotes(array $refNotes, array $testNotes) : array { | ||
$this->checkGetReferenceNotes(array_merge($refNotes, $testNotes), 'Pre-condition'); | ||
$note = $testNotes[0]; | ||
// test update note with all attributes | ||
$this->updateNote($note, (object)[ | ||
'title' => 'This is not used', | ||
'content' => '# *First* edited/ note'.PHP_EOL.'This is some body content with some data.', | ||
'favorite' => false, | ||
'category' => 'Test/Another Category', | ||
'modified' => mktime(11, 46, 23, 4, 3, 2020), | ||
], (object)[ | ||
'title' => 'First edited note', | ||
]); | ||
// test update note with single attributes | ||
/* TODO this doesn't work (content is null) | ||
$this->updateNote($note, (object)[ | ||
'category' => 'Test/Third Category', | ||
], (object)[]); | ||
*/ | ||
$this->updateNote($note, (object)[ | ||
'favorite' => true, | ||
], (object)[]); | ||
$this->updateNote($note, (object)[ | ||
'content' => '# First multi edited note'.PHP_EOL.'This is some body content with some data.', | ||
], (object)[ | ||
'title' => 'First multi edited note', | ||
'modified' => time(), | ||
]); | ||
$this->checkGetReferenceNotes(array_merge($refNotes, $testNotes), 'After updating notes'); | ||
return $testNotes; | ||
} | ||
|
||
/** | ||
* @depends testCheckForReferenceNotes | ||
* @depends testUpdateNotes | ||
*/ | ||
public function testDeleteNotes(array $refNotes, array $testNotes) : void { | ||
$this->checkGetReferenceNotes(array_merge($refNotes, $testNotes), 'Pre-condition'); | ||
foreach($testNotes as $note) { | ||
$response = $this->http->request('DELETE', 'notes/'.$note->id); | ||
$this->checkResponse($response, 'Delete note '.$note->title, 200); | ||
} | ||
// test non-existing note | ||
$response = $this->http->request('DELETE', 'notes/1'); | ||
$this->checkResponse($response, 'Delete non-existing note', 404); | ||
$this->checkGetReferenceNotes($refNotes, 'After deletion'); | ||
} | ||
|
||
public function testInsuficientStorage() { | ||
$auth = ['quotatest', 'test']; | ||
// get notes must still work | ||
$response = $this->http->request('GET', 'notes', [ 'auth' => $auth ]); | ||
$this->checkResponse($response, 'Get existing notes', 200); | ||
$notes = json_decode($response->getBody()->getContents()); | ||
$this->assertNotEmpty($notes, 'List of notes'); | ||
$note = $notes[0]; // @phan-suppress-current-line PhanTypeArraySuspiciousNullable | ||
$request = (object)[ 'content' => 'New test content' ]; | ||
// update will fail | ||
$response1 = $this->http->request('PUT', 'notes/'.$note->id, [ 'auth' => $auth, 'json' => $request]); | ||
$this->assertEquals(507, $response1->getStatusCode()); | ||
// craete will fail | ||
$response2 = $this->http->request('POST', 'notes', [ 'auth' => $auth, 'json' => $request]); | ||
$this->assertEquals(507, $response2->getStatusCode()); | ||
} | ||
|
||
// TODO Test settings (switch to another notes folder) | ||
} |
Oops, something went wrong.