diff --git a/app/controllers/api/database.php b/app/controllers/api/database.php index 75eab37142..c923fd85b0 100644 --- a/app/controllers/api/database.php +++ b/app/controllers/api/database.php @@ -182,17 +182,26 @@ App::get('/v1/database/collections') ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) ->param('limit', 25, new Range(0, 100), 'Results limit value. By default will return maximum 25 results. Maximum of 100 results allowed per request.', true) ->param('offset', 0, new Range(0, 40000), 'Results offset. The default value is 0. Use this param to manage pagination.', true) + ->param('after', '', new UID(), 'ID of the collection used as the starting point for the query, excluding the collection itself. Should be used for efficient pagination when working with large sets of data.', true) ->param('orderType', 'ASC', new WhiteList(['ASC', 'DESC'], true), 'Order result by ASC or DESC order.', true) ->inject('response') ->inject('dbForExternal') - ->action(function ($search, $limit, $offset, $orderType, $response, $dbForExternal) { + ->action(function ($search, $limit, $offset, $after, $orderType, $response, $dbForExternal) { /** @var Appwrite\Utopia\Response $response */ /** @var Utopia\Database\Database $dbForExternal */ $queries = ($search) ? [new Query('name', Query::TYPE_SEARCH, [$search])] : []; + if (!empty($after)) { + $afterCollection = $dbForExternal->getDocument('collections', $after); + + if ($afterCollection->isEmpty()) { + throw new Exception("Collection '{$after}' for the 'after' value not found.", 400); + } + } + $response->dynamic(new Document([ - 'collections' => $dbForExternal->find(Database::COLLECTIONS, $queries, $limit, $offset, ['_id'], [$orderType]), + 'collections' => $dbForExternal->find(Database::COLLECTIONS, $queries, $limit, $offset, [], [$orderType], $afterCollection ?? null), 'sum' => $dbForExternal->count(Database::COLLECTIONS, $queries, APP_LIMIT_COUNT), ]), Response::MODEL_COLLECTION_LIST); }); @@ -1062,12 +1071,12 @@ App::get('/v1/database/collections/:collectionId/documents') ->param('queries', [], new ArrayList(new Text(128)), 'Array of query strings.', true) ->param('limit', 25, new Range(0, 100), 'Maximum number of documents to return in response. Use this value to manage pagination. By default will return maximum 25 results. Maximum of 100 results allowed per request.', true) ->param('offset', 0, new Range(0, 900000000), 'Offset value. The default value is 0. Use this param to manage pagination.', true) - // TODO@kodumbeats 'after' param for pagination + ->param('after', '', new UID(), 'ID of the document used as the starting point for the query, excluding the document itself. Should be used for efficient pagination when working with large sets of data.', true) ->param('orderAttributes', [], new ArrayList(new Text(128)), 'Array of attributes used to sort results.', true) ->param('orderTypes', [], new ArrayList(new WhiteList(['DESC', 'ASC'], true)), 'Array of order directions for sorting attribtues. Possible values are DESC for descending order, or ASC for ascending order.', true) ->inject('response') ->inject('dbForExternal') - ->action(function ($collectionId, $queries, $limit, $offset, $orderAttributes, $orderTypes, $response, $dbForExternal) { + ->action(function ($collectionId, $queries, $limit, $offset, $after, $orderAttributes, $orderTypes, $response, $dbForExternal) { /** @var Appwrite\Utopia\Response $response */ /** @var Utopia\Database\Database $dbForExternal */ @@ -1093,7 +1102,15 @@ App::get('/v1/database/collections/:collectionId/documents') throw new Exception($validator->getDescription(), 400); } - $documents = $dbForExternal->find($collectionId, $queries, $limit, $offset, $orderAttributes, $orderTypes); + if (!empty($after)) { + $afterDocument = $dbForExternal->getDocument($collectionId, $after); + + if ($afterDocument->isEmpty()) { + throw new Exception("Document '{$after}' for the 'after' value not found.", 400); + } + } + + $documents = $dbForExternal->find($collectionId, $queries, $limit, $offset, $orderAttributes, $orderTypes, $afterDocument ?? null); $response->dynamic(new Document([ 'sum' => \count($documents), diff --git a/app/controllers/api/functions.php b/app/controllers/api/functions.php index a0bcb535be..1441707559 100644 --- a/app/controllers/api/functions.php +++ b/app/controllers/api/functions.php @@ -88,17 +88,26 @@ App::get('/v1/functions') ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) ->param('limit', 25, new Range(0, 100), 'Results limit value. By default will return maximum 25 results. Maximum of 100 results allowed per request.', true) ->param('offset', 0, new Range(0, 2000), 'Results offset. The default value is 0. Use this param to manage pagination.', true) + ->param('after', '', new UID(), 'ID of the function used as the starting point for the query, excluding the function itself. Should be used for efficient pagination when working with large sets of data.', true) ->param('orderType', 'ASC', new WhiteList(['ASC', 'DESC'], true), 'Order result by ASC or DESC order.', true) ->inject('response') ->inject('dbForInternal') - ->action(function ($search, $limit, $offset, $orderType, $response, $dbForInternal) { + ->action(function ($search, $limit, $offset, $after, $orderType, $response, $dbForInternal) { /** @var Appwrite\Utopia\Response $response */ /** @var Utopia\Database\Database $dbForInternal */ $queries = ($search) ? [new Query('name', Query::TYPE_SEARCH, [$search])] : []; + if (!empty($after)) { + $afterFunction = $dbForInternal->getDocument('functions', $after); + + if ($afterFunction->isEmpty()) { + throw new Exception("Function '{$after}' for the 'after' value not found.", 400); + } + } + $response->dynamic(new Document([ - 'functions' => $dbForInternal->find('functions', $queries, $limit, $offset, ['_id'], [$orderType]), + 'functions' => $dbForInternal->find('functions', $queries, $limit, $offset, [], [$orderType], $afterFunction ?? null), 'sum' => $dbForInternal->count('functions', $queries, APP_LIMIT_COUNT), ]), Response::MODEL_FUNCTION_LIST); }); @@ -506,10 +515,11 @@ App::get('/v1/functions/:functionId/tags') ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) ->param('limit', 25, new Range(0, 100), 'Results limit value. By default will return maximum 25 results. Maximum of 100 results allowed per request.', true) ->param('offset', 0, new Range(0, 2000), 'Results offset. The default value is 0. Use this param to manage pagination.', true) + ->param('after', '', new UID(), 'ID of the tag used as the starting point for the query, excluding the tag itself. Should be used for efficient pagination when working with large sets of data.', true) ->param('orderType', 'ASC', new WhiteList(['ASC', 'DESC'], true), 'Order result by ASC or DESC order.', true) ->inject('response') ->inject('dbForInternal') - ->action(function ($functionId, $search, $limit, $offset, $orderType, $response, $dbForInternal) { + ->action(function ($functionId, $search, $limit, $offset, $after, $orderType, $response, $dbForInternal) { /** @var Appwrite\Utopia\Response $response */ /** @var Utopia\Database\Database $dbForInternal */ @@ -520,8 +530,16 @@ App::get('/v1/functions/:functionId/tags') } $queries[] = new Query('functionId', Query::TYPE_EQUAL, [$function->getId()]); - - $results = $dbForInternal->find('tags', $queries, $limit, $offset, ['_id'], [$orderType]); + + if (!empty($after)) { + $afterTag = $dbForInternal->getDocument('tags', $after); + + if ($afterTag->isEmpty()) { + throw new Exception("Tag '{$after}' for the 'after' value not found.", 400); + } + } + + $results = $dbForInternal->find('tags', $queries, $limit, $offset, [], [$orderType], $afterTag ?? null); $sum = $dbForInternal->count('tags', $queries, APP_LIMIT_COUNT); $response->dynamic(new Document([ @@ -748,12 +766,13 @@ App::get('/v1/functions/:functionId/executions') ->param('functionId', '', new UID(), 'Function unique ID.') ->param('limit', 25, new Range(0, 100), 'Results limit value. By default will return maximum 25 results. Maximum of 100 results allowed per request.', true) ->param('offset', 0, new Range(0, 2000), 'Results offset. The default value is 0. Use this param to manage pagination.', true) + ->param('after', '', new UID(), 'ID of the execution used as the starting point for the query, excluding the execution itself. Should be used for efficient pagination when working with large sets of data.', true) ->inject('response') ->inject('dbForInternal') - ->action(function ($functionId, $limit, $offset, $response, $dbForInternal) { + ->action(function ($functionId, $limit, $offset, $after, $response, $dbForInternal) { /** @var Appwrite\Utopia\Response $response */ /** @var Utopia\Database\Database $dbForInternal */ - + Authorization::disable(); $function = $dbForInternal->getDocument('functions', $functionId); Authorization::reset(); @@ -762,10 +781,18 @@ App::get('/v1/functions/:functionId/executions') throw new Exception('Function not found', 404); } + if (!empty($after)) { + $afterExecution = $dbForInternal->getDocument('executions', $after); + + if ($afterExecution->isEmpty()) { + throw new Exception("Execution '{$after}' for the 'after' value not found.", 400); + } + } + $results = $dbForInternal->find('executions', [ new Query('functionId', Query::TYPE_EQUAL, [$function->getId()]), - ], $limit, $offset, ['_id'], [Database::ORDER_DESC]); - + ], $limit, $offset, [], [Database::ORDER_DESC], $afterExecution ?? null); + $sum = $dbForInternal->count('executions', [ new Query('functionId', Query::TYPE_EQUAL, [$function->getId()]), ], APP_LIMIT_COUNT); diff --git a/app/controllers/api/projects.php b/app/controllers/api/projects.php index 493eb65dcb..e34c948837 100644 --- a/app/controllers/api/projects.php +++ b/app/controllers/api/projects.php @@ -164,16 +164,25 @@ App::get('/v1/projects') ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) ->param('limit', 25, new Range(0, 100), 'Results limit value. By default will return maximum 25 results. Maximum of 100 results allowed per request.', true) ->param('offset', 0, new Range(0, 2000), 'Results offset. The default value is 0. Use this param to manage pagination.', true) + ->param('after', '', new UID(), 'ID of the project used as the starting point for the query, excluding the project itself. Should be used for efficient pagination when working with large sets of data.', true) ->param('orderType', 'ASC', new WhiteList(['ASC', 'DESC'], true), 'Order result by ASC or DESC order.', true) ->inject('response') ->inject('dbForConsole') - ->action(function ($search, $limit, $offset, $orderType, $response, $dbForConsole) { + ->action(function ($search, $limit, $offset, $after, $orderType, $response, $dbForConsole) { /** @var Appwrite\Utopia\Response $response */ /** @var Utopia\Database\Database $dbForConsole */ $queries = ($search) ? [new Query('name', Query::TYPE_SEARCH, [$search])] : []; - $results = $dbForConsole->find('projects', $queries, $limit, $offset, ['_id'], [$orderType]); + if (!empty($after)) { + $afterProject = $dbForConsole->getDocument('projects', $after); + + if ($afterProject->isEmpty()) { + throw new Exception("Project '{$after}' for the 'after' value not found.", 400); + } + } + + $results = $dbForConsole->find('projects', $queries, $limit, $offset, [], [$orderType], $afterProject ?? null); $sum = $dbForConsole->count('projects', $queries, APP_LIMIT_COUNT); $response->dynamic(new Document([ diff --git a/app/controllers/api/storage.php b/app/controllers/api/storage.php index 4f579a1b31..5a5c43de58 100644 --- a/app/controllers/api/storage.php +++ b/app/controllers/api/storage.php @@ -171,17 +171,26 @@ App::get('/v1/storage/files') ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) ->param('limit', 25, new Range(0, 100), 'Results limit value. By default will return maximum 25 results. Maximum of 100 results allowed per request.', true) ->param('offset', 0, new Range(0, 2000), 'Results offset. The default value is 0. Use this param to manage pagination.', true) + ->param('after', '', new UID(), 'ID of the file used as the starting point for the query, excluding the file itself. Should be used for efficient pagination when working with large sets of data.', true) ->param('orderType', 'ASC', new WhiteList(['ASC', 'DESC'], true), 'Order result by ASC or DESC order.', true) ->inject('response') ->inject('dbForInternal') - ->action(function ($search, $limit, $offset, $orderType, $response, $dbForInternal) { + ->action(function ($search, $limit, $offset, $after, $orderType, $response, $dbForInternal) { /** @var Appwrite\Utopia\Response $response */ /** @var Utopia\Database\Database $dbForInternal */ $queries = ($search) ? [new Query('name', Query::TYPE_SEARCH, $search)] : []; + if (!empty($after)) { + $afterFile = $dbForInternal->getDocument('files', $after); + + if ($afterFile->isEmpty()) { + throw new Exception("File '{$after}' for the 'after' value not found.", 400); + } + } + $response->dynamic(new Document([ - 'files' => $dbForInternal->find('files', $queries, $limit, $offset, ['_id'], [$orderType]), + 'files' => $dbForInternal->find('files', $queries, $limit, $offset, [], [$orderType], $afterFile ?? null), 'sum' => $dbForInternal->count('files', $queries, APP_LIMIT_COUNT), ]), Response::MODEL_FILE_LIST); }); diff --git a/app/controllers/api/teams.php b/app/controllers/api/teams.php index 01ce3c82fd..569940c42e 100644 --- a/app/controllers/api/teams.php +++ b/app/controllers/api/teams.php @@ -99,16 +99,25 @@ App::get('/v1/teams') ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) ->param('limit', 25, new Range(0, 100), 'Results limit value. By default will return maximum 25 results. Maximum of 100 results allowed per request.', true) ->param('offset', 0, new Range(0, 2000), 'Results offset. The default value is 0. Use this param to manage pagination.', true) + ->param('after', '', new UID(), 'ID of the team used as the starting point for the query, excluding the team itself. Should be used for efficient pagination when working with large sets of data.', true) ->param('orderType', 'ASC', new WhiteList(['ASC', 'DESC'], true), 'Order result by ASC or DESC order.', true) ->inject('response') ->inject('dbForInternal') - ->action(function ($search, $limit, $offset, $orderType, $response, $dbForInternal) { + ->action(function ($search, $limit, $offset, $after, $orderType, $response, $dbForInternal) { /** @var Appwrite\Utopia\Response $response */ /** @var Utopia\Database\Database $dbForInternal */ $queries = ($search) ? [new Query('name', Query::TYPE_SEARCH, [$search])] : []; - $results = $dbForInternal->find('teams', $queries, $limit, $offset, ['_id'], [$orderType]); + if (!empty($after)) { + $afterTeam = $dbForInternal->getDocument('teams', $after); + + if ($afterTeam->isEmpty()) { + throw new Exception("Team '{$after}' for the 'after' value not found.", 400); + } + } + + $results = $dbForInternal->find('teams', $queries, $limit, $offset, [], [$orderType], $afterTeam ?? null); $sum = $dbForInternal->count('teams', $queries, APP_LIMIT_COUNT); $response->dynamic(new Document([ @@ -415,10 +424,11 @@ App::get('/v1/teams/:teamId/memberships') ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) ->param('limit', 25, new Range(0, 100), 'Results limit value. By default will return maximum 25 results. Maximum of 100 results allowed per request.', true) ->param('offset', 0, new Range(0, 2000), 'Results offset. The default value is 0. Use this param to manage pagination.', true) + ->param('after', '', new UID(), 'ID of the membership used as the starting point for the query, excluding the membership itself. Should be used for efficient pagination when working with large sets of data.', true) ->param('orderType', 'ASC', new WhiteList(['ASC', 'DESC'], true), 'Order result by ASC or DESC order.', true) ->inject('response') ->inject('dbForInternal') - ->action(function ($teamId, $search, $limit, $offset, $orderType, $response, $dbForInternal) { + ->action(function ($teamId, $search, $limit, $offset, $after, $orderType, $response, $dbForInternal) { /** @var Appwrite\Utopia\Response $response */ /** @var Utopia\Database\Database $dbForInternal */ @@ -428,7 +438,15 @@ App::get('/v1/teams/:teamId/memberships') throw new Exception('Team not found', 404); } - $memberships = $dbForInternal->find('memberships', [new Query('teamId', Query::TYPE_EQUAL, [$teamId])], $limit, $offset, ['_id'], [$orderType]); + if (!empty($after)) { + $afterMembership = $dbForInternal->getDocument('memberships', $after); + + if ($afterMembership->isEmpty()) { + throw new Exception("Membership '{$after}' for the 'after' value not found.", 400); + } + } + + $memberships = $dbForInternal->find('memberships', [new Query('teamId', Query::TYPE_EQUAL, [$teamId])], $limit, $offset, [], [$orderType], $afterMembership ?? null); $sum = $dbForInternal->count('memberships', [new Query('teamId', Query::TYPE_EQUAL, [$teamId])], APP_LIMIT_COUNT); $users = []; diff --git a/app/controllers/api/users.php b/app/controllers/api/users.php index d57be233ef..11beca048b 100644 --- a/app/controllers/api/users.php +++ b/app/controllers/api/users.php @@ -83,14 +83,23 @@ App::get('/v1/users') ->param('search', '', new Text(256), 'Search term to filter your list results. Max length: 256 chars.', true) ->param('limit', 25, new Range(0, 100), 'Results limit value. By default will return maximum 25 results. Maximum of 100 results allowed per request.', true) ->param('offset', 0, new Range(0, 2000), 'Results offset. The default value is 0. Use this param to manage pagination.', true) + ->param('after', '', new UID(), 'ID of the user used as the starting point for the query, excluding the user itself. Should be used for efficient pagination when working with large sets of data.', true) ->param('orderType', 'ASC', new WhiteList(['ASC', 'DESC'], true), 'Order result by ASC or DESC order.', true) ->inject('response') ->inject('dbForInternal') - ->action(function ($search, $limit, $offset, $orderType, $response, $dbForInternal) { + ->action(function ($search, $limit, $offset, $after, $orderType, $response, $dbForInternal) { /** @var Appwrite\Utopia\Response $response */ /** @var Utopia\Database\Database $dbForInternal */ - $results = $dbForInternal->find('users', [], $limit, $offset, ['_id'], [$orderType]); + if (!empty($after)) { + $afterUser = $dbForInternal->getDocument('users', $after); + + if ($afterUser->isEmpty()) { + throw new Exception('User for after not found', 400); + } + } + + $results = $dbForInternal->find('users', [], $limit, $offset, [], [$orderType], $afterUser ?? null); $sum = $dbForInternal->count('users', [], APP_LIMIT_COUNT); $response->dynamic(new Document([ diff --git a/composer.json b/composer.json index b3593e34d9..ba45139b98 100644 --- a/composer.json +++ b/composer.json @@ -45,7 +45,7 @@ "utopia-php/cache": "0.4.*", "utopia-php/cli": "0.11.*", "utopia-php/config": "0.2.*", - "utopia-php/database": "0.6.*", + "utopia-php/database": "0.7.*", "utopia-php/locale": "0.4.*", "utopia-php/registry": "0.5.*", "utopia-php/preloader": "0.2.*", diff --git a/composer.lock b/composer.lock index c528f39540..db07f5df2b 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "c2bda60e7b774a0c813f52033a268c6c", + "content-hash": "7de5dc8a9fe3cbc14696c685d1cdddee", "packages": [ { "name": "adhocore/jwt", @@ -1666,22 +1666,22 @@ }, { "name": "utopia-php/abuse", - "version": "0.6.1", + "version": "0.6.2", "source": { "type": "git", "url": "https://github.com/utopia-php/abuse.git", - "reference": "c9078aa3a87750d66060f0ed7642e03e5815da17" + "reference": "4cd9c16610f7398d2e1737663ef682fa721ae736" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/abuse/zipball/c9078aa3a87750d66060f0ed7642e03e5815da17", - "reference": "c9078aa3a87750d66060f0ed7642e03e5815da17", + "url": "https://api.github.com/repos/utopia-php/abuse/zipball/4cd9c16610f7398d2e1737663ef682fa721ae736", + "reference": "4cd9c16610f7398d2e1737663ef682fa721ae736", "shasum": "" }, "require": { "ext-pdo": "*", "php": ">=7.4", - "utopia-php/database": "0.6.*" + "utopia-php/database": "0.7.*" }, "require-dev": { "phpunit/phpunit": "^9.4", @@ -1713,9 +1713,9 @@ ], "support": { "issues": "https://github.com/utopia-php/abuse/issues", - "source": "https://github.com/utopia-php/abuse/tree/0.6.1" + "source": "https://github.com/utopia-php/abuse/tree/0.6.2" }, - "time": "2021-08-03T19:31:07+00:00" + "time": "2021-08-13T07:52:34+00:00" }, { "name": "utopia-php/analytics", @@ -1774,22 +1774,22 @@ }, { "name": "utopia-php/audit", - "version": "0.6.1", + "version": "0.6.2", "source": { "type": "git", "url": "https://github.com/utopia-php/audit.git", - "reference": "971dcd5c88309656df31ac20f326d3ac8b555594" + "reference": "2ec39a53eb98a5f9d230550ad56c7c04de5d77df" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/audit/zipball/971dcd5c88309656df31ac20f326d3ac8b555594", - "reference": "971dcd5c88309656df31ac20f326d3ac8b555594", + "url": "https://api.github.com/repos/utopia-php/audit/zipball/2ec39a53eb98a5f9d230550ad56c7c04de5d77df", + "reference": "2ec39a53eb98a5f9d230550ad56c7c04de5d77df", "shasum": "" }, "require": { "ext-pdo": "*", "php": ">=7.4", - "utopia-php/database": "0.6.*" + "utopia-php/database": "0.7.*" }, "require-dev": { "phpunit/phpunit": "^9.3", @@ -1821,9 +1821,9 @@ ], "support": { "issues": "https://github.com/utopia-php/audit/issues", - "source": "https://github.com/utopia-php/audit/tree/0.6.1" + "source": "https://github.com/utopia-php/audit/tree/0.6.2" }, - "time": "2021-08-03T19:29:34+00:00" + "time": "2021-08-13T08:05:20+00:00" }, { "name": "utopia-php/cache", @@ -1984,16 +1984,16 @@ }, { "name": "utopia-php/database", - "version": "0.6.1", + "version": "0.7.0", "source": { "type": "git", "url": "https://github.com/utopia-php/database.git", - "reference": "59d9d34164b6fb896bc43085a9a82a292b43473a" + "reference": "46c4a99347397e362a9429826e1888b0aefb2056" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/database/zipball/59d9d34164b6fb896bc43085a9a82a292b43473a", - "reference": "59d9d34164b6fb896bc43085a9a82a292b43473a", + "url": "https://api.github.com/repos/utopia-php/database/zipball/46c4a99347397e362a9429826e1888b0aefb2056", + "reference": "46c4a99347397e362a9429826e1888b0aefb2056", "shasum": "" }, "require": { @@ -2041,9 +2041,9 @@ ], "support": { "issues": "https://github.com/utopia-php/database/issues", - "source": "https://github.com/utopia-php/database/tree/0.6.1" + "source": "https://github.com/utopia-php/database/tree/0.7.0" }, - "time": "2021-08-05T17:19:16+00:00" + "time": "2021-08-10T19:09:58+00:00" }, { "name": "utopia-php/domains", @@ -6278,5 +6278,5 @@ "platform-overrides": { "php": "8.0" }, - "plugin-api-version": "2.1.0" + "plugin-api-version": "2.0.0" } diff --git a/tests/e2e/Services/Database/DatabaseBase.php b/tests/e2e/Services/Database/DatabaseBase.php index 74d5af5836..ba0c2d3a48 100644 --- a/tests/e2e/Services/Database/DatabaseBase.php +++ b/tests/e2e/Services/Database/DatabaseBase.php @@ -296,6 +296,115 @@ trait DatabaseBase return []; } + /** + * @depends testCreateDocument + */ + public function testListDocumentsAfterPagination(array $data):array + { + /** + * Test after without order. + */ + $base = $this->client->call(Client::METHOD_GET, '/database/collections/' . $data['moviesId'] . '/documents', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals('Captain America', $base['body']['documents'][0]['title']); + $this->assertEquals('Spider-Man: Far From Home', $base['body']['documents'][1]['title']); + $this->assertEquals('Spider-Man: Homecoming', $base['body']['documents'][2]['title']); + $this->assertCount(3, $base['body']['documents']); + + $documents = $this->client->call(Client::METHOD_GET, '/database/collections/' . $data['moviesId'] . '/documents', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'after' => $base['body']['documents'][0]['$id'] + ]); + + $this->assertEquals($base['body']['documents'][1]['$id'], $documents['body']['documents'][0]['$id']); + $this->assertEquals($base['body']['documents'][2]['$id'], $documents['body']['documents'][1]['$id']); + $this->assertCount(2, $documents['body']['documents']); + + $documents = $this->client->call(Client::METHOD_GET, '/database/collections/' . $data['moviesId'] . '/documents', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'after' => $base['body']['documents'][2]['$id'] + ]); + + $this->assertEmpty($documents['body']['documents']); + + /** + * Test with ASC order and after. + */ + $base = $this->client->call(Client::METHOD_GET, '/database/collections/' . $data['moviesId'] . '/documents', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'orderAttributes' => ['releaseYear'], + 'orderTypes' => ['ASC'], + ]); + + $this->assertEquals(1944, $base['body']['documents'][0]['releaseYear']); + $this->assertEquals(2017, $base['body']['documents'][1]['releaseYear']); + $this->assertEquals(2019, $base['body']['documents'][2]['releaseYear']); + $this->assertCount(3, $base['body']['documents']); + + $documents = $this->client->call(Client::METHOD_GET, '/database/collections/' . $data['moviesId'] . '/documents', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'orderAttributes' => ['releaseYear'], + 'orderTypes' => ['ASC'], + 'after' => $base['body']['documents'][1]['$id'] + ]); + + $this->assertEquals($base['body']['documents'][2]['$id'], $documents['body']['documents'][0]['$id']); + $this->assertCount(1, $documents['body']['documents']); + + /** + * Test with DESC order and after. + */ + $base = $this->client->call(Client::METHOD_GET, '/database/collections/' . $data['moviesId'] . '/documents', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'orderAttributes' => ['releaseYear'], + 'orderTypes' => ['DESC'], + ]); + + $this->assertEquals(1944, $base['body']['documents'][2]['releaseYear']); + $this->assertEquals(2017, $base['body']['documents'][1]['releaseYear']); + $this->assertEquals(2019, $base['body']['documents'][0]['releaseYear']); + $this->assertCount(3, $base['body']['documents']); + + $documents = $this->client->call(Client::METHOD_GET, '/database/collections/' . $data['moviesId'] . '/documents', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'orderAttributes' => ['releaseYear'], + 'orderTypes' => ['DESC'], + 'after' => $base['body']['documents'][1]['$id'] + ]); + + $this->assertEquals($base['body']['documents'][2]['$id'], $documents['body']['documents'][0]['$id']); + $this->assertCount(1, $documents['body']['documents']); + + /** + * Test after with unknown document. + */ + $documents = $this->client->call(Client::METHOD_GET, '/database/collections/' . $data['moviesId'] . '/documents', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'after' => 'unknown' + ]); + + $this->assertEquals($documents['headers']['status-code'], 400); + + return []; + } + /** * @depends testCreateDocument */ diff --git a/tests/e2e/Services/Database/DatabaseCustomServerTest.php b/tests/e2e/Services/Database/DatabaseCustomServerTest.php index 421055fde9..5341025dcb 100644 --- a/tests/e2e/Services/Database/DatabaseCustomServerTest.php +++ b/tests/e2e/Services/Database/DatabaseCustomServerTest.php @@ -13,6 +13,86 @@ class DatabaseCustomServerTest extends Scope use ProjectCustom; use SideServer; + public function testListCollections() + { + /** + * Test for SUCCESS + */ + $test1 = $this->client->call(Client::METHOD_POST, '/database/collections', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'name' => 'Test 1', + 'collectionId' => 'first', + 'read' => ['role:all'], + 'write' => ['role:all'], + ]); + + $test2 = $this->client->call(Client::METHOD_POST, '/database/collections', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'name' => 'Test 2', + 'collectionId' => 'second', + 'read' => ['role:all'], + 'write' => ['role:all'], + ]); + + $collections = $this->client->call(Client::METHOD_GET, '/database/collections', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals(2, $collections['body']['sum']); + $this->assertEquals($test1['body']['$id'], $collections['body']['collections'][0]['$id']); + $this->assertEquals($test2['body']['$id'], $collections['body']['collections'][1]['$id']); + + /** + * Test for Order + */ + $base = array_reverse($collections['body']['collections']); + $collections = $this->client->call(Client::METHOD_GET, '/database/collections', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'orderType' => 'DESC' + ]); + + $this->assertEquals(2, $collections['body']['sum']); + $this->assertEquals($base[0]['$id'], $collections['body']['collections'][0]['$id']); + $this->assertEquals($base[1]['$id'], $collections['body']['collections'][1]['$id']); + + /** + * Test for After + */ + $base = $this->client->call(Client::METHOD_GET, '/database/collections', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $collections = $this->client->call(Client::METHOD_GET, '/database/collections', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'after' => $base['body']['collections'][0]['$id'] + ]); + + $this->assertCount(1, $collections['body']['collections']); + $this->assertEquals($base['body']['collections'][1]['$id'], $collections['body']['collections'][0]['$id']); + + $collections = $this->client->call(Client::METHOD_GET, '/database/collections', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'after' => $base['body']['collections'][1]['$id'] + ]); + + $this->assertCount(0, $collections['body']['collections']); + $this->assertEmpty($collections['body']['collections']); + } + public function testDeleteAttribute(): array { /** diff --git a/tests/e2e/Services/Functions/FunctionsCustomClientTest.php b/tests/e2e/Services/Functions/FunctionsCustomClientTest.php index 1ebc654892..86f6fde482 100644 --- a/tests/e2e/Services/Functions/FunctionsCustomClientTest.php +++ b/tests/e2e/Services/Functions/FunctionsCustomClientTest.php @@ -112,7 +112,7 @@ class FunctionsCustomClientTest extends Scope ]); $this->assertEquals(201, $execution['headers']['status-code']); - + $execution = $this->client->call(Client::METHOD_POST, '/functions/'.$function['body']['$id'].'/executions', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], @@ -121,7 +121,7 @@ class FunctionsCustomClientTest extends Scope ]); $this->assertEquals(401, $execution['headers']['status-code']); - + return []; } @@ -187,7 +187,7 @@ class FunctionsCustomClientTest extends Scope $this->assertEquals(201, $execution['headers']['status-code']); $executionId = $execution['body']['$id'] ?? ''; - + sleep(10); $executions = $this->client->call(Client::METHOD_GET, '/functions/'.$functionId.'/executions/'.$executionId, [ @@ -212,19 +212,52 @@ class FunctionsCustomClientTest extends Scope $this->assertEquals($this->getUser()['$id'], $output['APPWRITE_FUNCTION_USER_ID']); $this->assertNotEmpty($output['APPWRITE_FUNCTION_JWT']); - $executions = $this->client->call(Client::METHOD_GET, '/functions/'.$functionId.'/executions', [ + return [ + 'functionId' => $functionId + ]; + } + + /** + * @depends testCreateCustomExecution + */ + public function testListExecutions(array $data) + { + $functionId = $data['functionId']; + $projectId = $this->getProject()['$id']; + $apikey = $this->getProject()['apiKey']; + + $execution = $this->client->call(Client::METHOD_POST, '/functions/'.$functionId.'/executions', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $projectId, + ], $this->getHeaders()), [ + 'data' => 'foobar', + ]); + + $this->assertEquals(201, $execution['headers']['status-code']); + + sleep(10); + + $base = $this->client->call(Client::METHOD_GET, '/functions/'.$functionId.'/executions', [ 'content-type' => 'application/json', 'x-appwrite-project' => $projectId, 'x-appwrite-key' => $apikey, ]); - $this->assertEquals(200, $executions['headers']['status-code']); - $this->assertCount(1, $executions['body']['executions']); - $this->assertEquals('completed', $executions['body']['executions'][0]['status']); - $this->assertStringContainsString('foobar', $executions['body']['executions'][0]['stdout']); - $this->assertStringContainsString($this->getUser()['$id'], $executions['body']['executions'][0]['stdout']); - - return []; - } + $this->assertEquals(200, $base['headers']['status-code']); + $this->assertCount(2, $base['body']['executions']); + $this->assertEquals('completed', $base['body']['executions'][0]['status']); + $this->assertEquals('completed', $base['body']['executions'][1]['status']); + $executions = $this->client->call(Client::METHOD_GET, '/functions/'.$functionId.'/executions', [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $projectId, + 'x-appwrite-key' => $apikey, + ], [ + 'after' => $base['body']['executions'][0]['$id'] + ]); + + $this->assertCount(1, $executions['body']['executions']); + $this->assertEquals($base['body']['executions'][1]['$id'], $executions['body']['executions'][0]['$id']); + + } } diff --git a/tests/e2e/Services/Functions/FunctionsCustomServerTest.php b/tests/e2e/Services/Functions/FunctionsCustomServerTest.php index b78f9d42ff..cb820b45c3 100644 --- a/tests/e2e/Services/Functions/FunctionsCustomServerTest.php +++ b/tests/e2e/Services/Functions/FunctionsCustomServerTest.php @@ -77,16 +77,51 @@ class FunctionsCustomServerTest extends Scope /** * Test for SUCCESS */ - $function = $this->client->call(Client::METHOD_GET, '/functions', array_merge([ + + $response = $this->client->call(Client::METHOD_POST, '/functions', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'functionId' => 'unique()', + 'name' => 'Test 2', + 'runtime' => 'php-8.0', + 'vars' => [ + 'funcKey1' => 'funcValue1', + 'funcKey2' => 'funcValue2', + 'funcKey3' => 'funcValue3', + ], + 'events' => [ + 'account.create', + 'account.delete', + ], + 'schedule' => '0 0 1 1 *', + 'timeout' => 10, + ]); + $this->assertNotEmpty($response['body']['$id']); + + $functions = $this->client->call(Client::METHOD_GET, '/functions', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); - $this->assertEquals($function['headers']['status-code'], 200); - $this->assertEquals($function['body']['sum'], 1); - $this->assertIsArray($function['body']['functions']); - $this->assertCount(1, $function['body']['functions']); - $this->assertEquals($function['body']['functions'][0]['name'], 'Test'); + $this->assertEquals($functions['headers']['status-code'], 200); + $this->assertEquals($functions['body']['sum'], 2); + $this->assertIsArray($functions['body']['functions']); + $this->assertCount(2, $functions['body']['functions']); + $this->assertEquals($functions['body']['functions'][0]['name'], 'Test'); + $this->assertEquals($functions['body']['functions'][1]['name'], 'Test 2'); + + $response = $this->client->call(Client::METHOD_GET, '/functions', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'after' => $functions['body']['functions'][0]['$id'] + ]); + + $this->assertEquals($response['headers']['status-code'], 200); + $this->assertCount(1, $response['body']['functions']); + $this->assertEquals($response['body']['functions'][0]['name'], 'Test 2'); + return $data; } diff --git a/tests/e2e/Services/Projects/ProjectsConsoleClientTest.php b/tests/e2e/Services/Projects/ProjectsConsoleClientTest.php index fd5b708797..4d83efb416 100644 --- a/tests/e2e/Services/Projects/ProjectsConsoleClientTest.php +++ b/tests/e2e/Services/Projects/ProjectsConsoleClientTest.php @@ -63,7 +63,7 @@ class ProjectsConsoleClientTest extends Scope ]); $this->assertEquals(400, $response['headers']['status-code']); - + $response = $this->client->call(Client::METHOD_POST, '/projects', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], @@ -97,6 +97,60 @@ class ProjectsConsoleClientTest extends Scope $this->assertEquals($id, $response['body']['projects'][0]['$id']); $this->assertEquals('Project Test', $response['body']['projects'][0]['name']); + /** + * Test after pagination + */ + $team = $this->client->call(Client::METHOD_POST, '/teams', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'teamId' => 'unique()', + 'name' => 'Project Test 2', + ]); + + $this->assertEquals(201, $team['headers']['status-code']); + $this->assertEquals('Project Test 2', $team['body']['name']); + $this->assertNotEmpty($team['body']['$id']); + + $response = $this->client->call(Client::METHOD_POST, '/projects', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'projectId' => 'unique()', + 'name' => 'Project Test 2', + 'teamId' => $team['body']['$id'], + ]); + + $this->assertEquals(201, $response['headers']['status-code']); + $this->assertNotEmpty($response['body']['$id']); + $this->assertEquals('Project Test 2', $response['body']['name']); + $this->assertEquals($team['body']['$id'], $response['body']['teamId']); + $this->assertArrayHasKey('platforms', $response['body']); + $this->assertArrayHasKey('webhooks', $response['body']); + $this->assertArrayHasKey('keys', $response['body']); + + $response = $this->client->call(Client::METHOD_GET, '/projects', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertNotEmpty($response['body']); + $this->assertCount(2, $response['body']['projects']); + $this->assertEquals('Project Test', $response['body']['projects'][0]['name']); + $this->assertEquals('Project Test 2', $response['body']['projects'][1]['name']); + + $response = $this->client->call(Client::METHOD_GET, '/projects', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()),[ + 'after' => $response['body']['projects'][0]['$id'] + ]); + + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertNotEmpty($response['body']); + $this->assertCount(1, $response['body']['projects']); + $this->assertEquals('Project Test 2', $response['body']['projects'][0]['name']); /** * Test for FAILURE */ diff --git a/tests/e2e/Services/Storage/StorageBase.php b/tests/e2e/Services/Storage/StorageBase.php index da6430135c..57a5ee6972 100644 --- a/tests/e2e/Services/Storage/StorageBase.php +++ b/tests/e2e/Services/Storage/StorageBase.php @@ -35,7 +35,7 @@ trait StorageBase */ return ['fileId' => $file['body']['$id']]; } - + /** * @depends testCreateFile */ @@ -158,19 +158,49 @@ trait StorageBase /** * Test for SUCCESS */ + $file = $this->client->call(Client::METHOD_POST, '/storage/files', array_merge([ + 'content-type' => 'multipart/form-data', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'fileId' => 'unique()', + 'file' => new CURLFile(realpath(__DIR__ . '/../../../resources/logo.png'), 'image/png', 'logo.png'), + 'read' => ['role:all'], + 'write' => ['role:all'], + ]); + + $this->assertEquals($file['headers']['status-code'], 201); + $this->assertNotEmpty($file['body']['$id']); + $this->assertIsInt($file['body']['dateCreated']); + $this->assertEquals('logo.png', $file['body']['name']); + $this->assertEquals('image/png', $file['body']['mimeType']); + $this->assertEquals(47218, $file['body']['sizeOriginal']); + $files = $this->client->call(Client::METHOD_GET, '/storage/files', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - ], $this->getHeaders())); + ], $this->getHeaders()), [ + 'limit' => 2 + ]); $this->assertEquals(200, $files['headers']['status-code']); - $this->assertGreaterThan(0, $files['body']['sum']); - $this->assertGreaterThan(0, count($files['body']['files'])); + $this->assertCount(2, $files['body']['files']); + + $response = $this->client->call(Client::METHOD_GET, '/storage/files', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'limit' => 1, + 'after' => $files['body']['files'][0]['$id'] + ]); + + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertEquals($files['body']['files'][1]['$id'], $response['body']['files'][0]['$id']); + $this->assertCount(1, $response['body']['files']); /** * Test for FAILURE */ - + return $data; } diff --git a/tests/e2e/Services/Teams/TeamsBase.php b/tests/e2e/Services/Teams/TeamsBase.php index 3e4a4971fa..6c1ebbe36a 100644 --- a/tests/e2e/Services/Teams/TeamsBase.php +++ b/tests/e2e/Services/Teams/TeamsBase.php @@ -133,7 +133,7 @@ trait TeamsBase $this->assertGreaterThan(0, $response['body']['sum']); $this->assertIsInt($response['body']['sum']); $this->assertCount(2, $response['body']['teams']); - + $response = $this->client->call(Client::METHOD_GET, '/teams', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], @@ -145,7 +145,7 @@ trait TeamsBase $this->assertGreaterThan(0, $response['body']['sum']); $this->assertIsInt($response['body']['sum']); $this->assertGreaterThan(2, $response['body']['teams']); - + $response = $this->client->call(Client::METHOD_GET, '/teams', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], @@ -158,7 +158,7 @@ trait TeamsBase $this->assertIsInt($response['body']['sum']); $this->assertCount(1, $response['body']['teams']); $this->assertEquals('Manchester United', $response['body']['teams'][0]['name']); - + $response = $this->client->call(Client::METHOD_GET, '/teams', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], @@ -172,6 +172,32 @@ trait TeamsBase $this->assertCount(1, $response['body']['teams']); $this->assertEquals('Manchester United', $response['body']['teams'][0]['name']); + $teams = $this->client->call(Client::METHOD_GET, '/teams', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'limit' => 2, + ]); + + $this->assertEquals(200, $teams['headers']['status-code']); + $this->assertGreaterThan(0, $teams['body']['sum']); + $this->assertIsInt($teams['body']['sum']); + $this->assertCount(2, $teams['body']['teams']); + + $response = $this->client->call(Client::METHOD_GET, '/teams', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'limit' => 1, + 'after' => $teams['body']['teams'][0]['$id'] + ]); + + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertGreaterThan(0, $response['body']['sum']); + $this->assertIsInt($response['body']['sum']); + $this->assertCount(1, $response['body']['teams']); + $this->assertEquals($teams['body']['teams'][1]['$id'], $response['body']['teams'][0]['$id']); + /** * Test for FAILURE */ diff --git a/tests/e2e/Services/Teams/TeamsBaseClient.php b/tests/e2e/Services/Teams/TeamsBaseClient.php index ad57737297..90964c4f6e 100644 --- a/tests/e2e/Services/Teams/TeamsBaseClient.php +++ b/tests/e2e/Services/Teams/TeamsBaseClient.php @@ -138,6 +138,35 @@ trait TeamsBaseClient ]; } + /** + * @depends testCreateTeamMembership + */ + public function testListTeamMemberships($data): void + { + $memberships = $this->client->call(Client::METHOD_GET, '/teams/'.$data['teamUid'].'/memberships', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals(200, $memberships['headers']['status-code']); + $this->assertIsInt($memberships['body']['sum']); + $this->assertNotEmpty($memberships['body']['memberships']); + $this->assertCount(2, $memberships['body']['memberships']); + + $response = $this->client->call(Client::METHOD_GET, '/teams/'.$data['teamUid'].'/memberships', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'after' => $memberships['body']['memberships'][0]['$id'] + ]); + + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertIsInt($response['body']['sum']); + $this->assertNotEmpty($response['body']['memberships']); + $this->assertCount(1, $response['body']['memberships']); + $this->assertEquals($memberships['body']['memberships'][1]['$id'], $response['body']['memberships'][0]['$id']); + } + /** * @depends testCreateTeamMembership */ diff --git a/tests/e2e/Services/Users/UsersBase.php b/tests/e2e/Services/Users/UsersBase.php index e5907105e2..b35f355c90 100644 --- a/tests/e2e/Services/Users/UsersBase.php +++ b/tests/e2e/Services/Users/UsersBase.php @@ -50,6 +50,42 @@ trait UsersBase return ['userId' => $user['body']['$id']]; } + /** + * @depends testCreateUser + */ + public function testListUsers(array $data): void + { + /** + * Test for SUCCESS + */ + $response = $this->client->call(Client::METHOD_GET, '/users', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals($response['headers']['status-code'], 200); + $this->assertNotEmpty($response['body']); + $this->assertNotEmpty($response['body']['users']); + $this->assertCount(2, $response['body']['users']); + + $this->assertEquals($response['body']['users'][0]['$id'], $data['userId']); + $this->assertEquals($response['body']['users'][1]['$id'], 'user1'); + + $response = $this->client->call(Client::METHOD_GET, '/users', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'after' => $response['body']['users'][0]['$id'] + ]); + + $this->assertEquals($response['headers']['status-code'], 200); + $this->assertNotEmpty($response['body']); + $this->assertNotEmpty($response['body']['users']); + $this->assertCount(1, $response['body']['users']); + + $this->assertEquals($response['body']['users'][0]['$id'], 'user1'); + } + /** * @depends testCreateUser */