From 63d2efdaac4e9f3bd032caa94c3cf9502ae5c334 Mon Sep 17 00:00:00 2001 From: Prem Palanisamy Date: Sun, 15 Feb 2026 22:46:00 +0000 Subject: [PATCH] Move schedule endpoints to projects group (/v1/projects/:projectId/schedules) --- .../Schedules/Http/Schedules/Create.php | 26 +- .../Modules/Schedules/Http/Schedules/Get.php | 21 +- .../Schedules/Http/Schedules/XList.php | 22 +- tests/e2e/Scopes/ProjectCustom.php | 2 - .../e2e/Services/Schedules/SchedulesBase.php | 65 +++-- .../Schedules/SchedulesCustomServerTest.php | 237 +++++++++++------- 6 files changed, 228 insertions(+), 145 deletions(-) diff --git a/src/Appwrite/Platform/Modules/Schedules/Http/Schedules/Create.php b/src/Appwrite/Platform/Modules/Schedules/Http/Schedules/Create.php index 5505a8ac8f..0aabe050cf 100644 --- a/src/Appwrite/Platform/Modules/Schedules/Http/Schedules/Create.php +++ b/src/Appwrite/Platform/Modules/Schedules/Http/Schedules/Create.php @@ -32,18 +32,18 @@ class Create extends Action { $this ->setHttpMethod(Action::HTTP_REQUEST_METHOD_POST) - ->setHttpPath('/v1/schedules') + ->setHttpPath('/v1/projects/:projectId/schedules') ->desc('Create schedule') - ->groups(['api', 'schedules']) + ->groups(['api', 'projects']) ->label('scope', 'schedules.write') ->label('audits.event', 'schedule.create') ->label('audits.resource', 'schedule/{response.$id}') ->label('sdk', new Method( - namespace: 'schedules', + namespace: 'projects', group: 'schedules', - name: 'create', + name: 'createSchedule', description: '/docs/references/schedules/create.md', - auth: [AuthType::ADMIN, AuthType::KEY], + auth: [AuthType::ADMIN], responses: [ new SDKResponse( code: Response::STATUS_CODE_CREATED, @@ -51,29 +51,37 @@ class Create extends Action ) ], )) + ->param('projectId', '', new UID(), 'Project unique ID.') ->param('resourceType', '', new WhiteList([SCHEDULE_RESOURCE_TYPE_FUNCTION, SCHEDULE_RESOURCE_TYPE_EXECUTION, SCHEDULE_RESOURCE_TYPE_MESSAGE], true), 'The resource type for the schedule. Possible values: ' . implode(', ', [SCHEDULE_RESOURCE_TYPE_FUNCTION, SCHEDULE_RESOURCE_TYPE_EXECUTION, SCHEDULE_RESOURCE_TYPE_MESSAGE]) . '.') ->param('resourceId', '', new UID(), 'The resource ID to associate with this schedule.') ->param('schedule', '', new Cron(), 'Schedule CRON expression.') ->param('active', false, new Boolean(), 'Whether the schedule is active.', true) ->inject('response') - ->inject('project') - ->inject('dbForProject') ->inject('dbForPlatform') + ->inject('getProjectDB') ->inject('authorization') ->callback($this->action(...)); } public function action( + string $projectId, string $resourceType, string $resourceId, string $schedule, bool $active, Response $response, - Document $project, - Database $dbForProject, Database $dbForPlatform, + callable $getProjectDB, Authorization $authorization, ): void { + $project = $dbForPlatform->getDocument('projects', $projectId); + + if ($project->isEmpty()) { + throw new Exception(Exception::PROJECT_NOT_FOUND); + } + + $dbForProject = $getProjectDB($project); + $collection = match ($resourceType) { SCHEDULE_RESOURCE_TYPE_FUNCTION => 'functions', SCHEDULE_RESOURCE_TYPE_EXECUTION => 'executions', diff --git a/src/Appwrite/Platform/Modules/Schedules/Http/Schedules/Get.php b/src/Appwrite/Platform/Modules/Schedules/Http/Schedules/Get.php index afc617c063..b16651dd0c 100644 --- a/src/Appwrite/Platform/Modules/Schedules/Http/Schedules/Get.php +++ b/src/Appwrite/Platform/Modules/Schedules/Http/Schedules/Get.php @@ -8,7 +8,6 @@ use Appwrite\SDK\Method; use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response; use Utopia\Database\Database; -use Utopia\Database\Document; use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\UID; use Utopia\Platform\Action; @@ -27,16 +26,16 @@ class Get extends Action { $this ->setHttpMethod(Action::HTTP_REQUEST_METHOD_GET) - ->setHttpPath('/v1/schedules/:scheduleId') + ->setHttpPath('/v1/projects/:projectId/schedules/:scheduleId') ->desc('Get schedule') - ->groups(['api', 'schedules']) + ->groups(['api', 'projects']) ->label('scope', 'schedules.read') ->label('sdk', new Method( - namespace: 'schedules', + namespace: 'projects', group: 'schedules', - name: 'get', + name: 'getSchedule', description: '/docs/references/schedules/get.md', - auth: [AuthType::ADMIN, AuthType::KEY], + auth: [AuthType::ADMIN], responses: [ new SDKResponse( code: Response::STATUS_CODE_OK, @@ -44,21 +43,27 @@ class Get extends Action ) ] )) + ->param('projectId', '', new UID(), 'Project unique ID.') ->param('scheduleId', '', new UID(), 'Schedule ID.') ->inject('response') - ->inject('project') ->inject('dbForPlatform') ->inject('authorization') ->callback($this->action(...)); } public function action( + string $projectId, string $scheduleId, Response $response, - Document $project, Database $dbForPlatform, Authorization $authorization, ): void { + $project = $dbForPlatform->getDocument('projects', $projectId); + + if ($project->isEmpty()) { + throw new Exception(Exception::PROJECT_NOT_FOUND); + } + $schedule = $authorization->skip( fn () => $dbForPlatform->getDocument('schedules', $scheduleId) ); diff --git a/src/Appwrite/Platform/Modules/Schedules/Http/Schedules/XList.php b/src/Appwrite/Platform/Modules/Schedules/Http/Schedules/XList.php index c140156804..77799b8593 100644 --- a/src/Appwrite/Platform/Modules/Schedules/Http/Schedules/XList.php +++ b/src/Appwrite/Platform/Modules/Schedules/Http/Schedules/XList.php @@ -15,6 +15,7 @@ use Utopia\Database\Exception\Query as QueryException; use Utopia\Database\Query; use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Query\Cursor; +use Utopia\Database\Validator\UID; use Utopia\Platform\Action; use Utopia\Platform\Scope\HTTP; use Utopia\Validator\Boolean; @@ -32,16 +33,16 @@ class XList extends Action { $this ->setHttpMethod(Action::HTTP_REQUEST_METHOD_GET) - ->setHttpPath('/v1/schedules') + ->setHttpPath('/v1/projects/:projectId/schedules') ->desc('List schedules') - ->groups(['api', 'schedules']) + ->groups(['api', 'projects']) ->label('scope', 'schedules.read') ->label('sdk', new Method( - namespace: 'schedules', + namespace: 'projects', group: 'schedules', - name: 'list', + name: 'listSchedules', description: '/docs/references/schedules/list.md', - auth: [AuthType::ADMIN, AuthType::KEY], + auth: [AuthType::ADMIN], responses: [ new SDKResponse( code: Response::STATUS_CODE_OK, @@ -49,30 +50,35 @@ class XList extends Action ) ] )) + ->param('projectId', '', new UID(), 'Project unique ID.') ->param('queries', [], new Schedules(), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' queries are allowed, each ' . APP_LIMIT_ARRAY_ELEMENT_SIZE . ' characters long. You may filter on the following attributes: ' . implode(', ', Schedules::ALLOWED_ATTRIBUTES), true) ->param('total', true, new Boolean(true), 'When set to false, the total count returned will be 0 and will not be calculated.', true) ->inject('response') - ->inject('project') ->inject('dbForPlatform') ->inject('authorization') ->callback($this->action(...)); } public function action( + string $projectId, array $queries, bool $includeTotal, Response $response, - Document $project, Database $dbForPlatform, Authorization $authorization, ): void { + $project = $dbForPlatform->getDocument('projects', $projectId); + + if ($project->isEmpty()) { + throw new Exception(Exception::PROJECT_NOT_FOUND); + } + try { $queries = Query::parseQueries($queries); } catch (QueryException $e) { throw new Exception(Exception::GENERAL_QUERY_INVALID, $e->getMessage()); } - // Always scope to the current project $queries[] = Query::equal('projectId', [$project->getId()]); $cursor = Query::getCursorQueries($queries, false); diff --git a/tests/e2e/Scopes/ProjectCustom.php b/tests/e2e/Scopes/ProjectCustom.php index 0bbaa13082..1859d551a4 100644 --- a/tests/e2e/Scopes/ProjectCustom.php +++ b/tests/e2e/Scopes/ProjectCustom.php @@ -109,8 +109,6 @@ trait ProjectCustom 'subscribers.read', 'migrations.write', 'migrations.read', - 'schedules.read', - 'schedules.write', 'tokens.read', 'tokens.write', ], diff --git a/tests/e2e/Services/Schedules/SchedulesBase.php b/tests/e2e/Services/Schedules/SchedulesBase.php index 93d24a572d..cd8f424f8d 100644 --- a/tests/e2e/Services/Schedules/SchedulesBase.php +++ b/tests/e2e/Services/Schedules/SchedulesBase.php @@ -4,44 +4,57 @@ namespace Tests\E2E\Services\Schedules; use Tests\E2E\Client; use Utopia\Database\Helpers\ID; +use Utopia\System\System; trait SchedulesBase { - protected function createSchedule(array $params = []): array + public function testCreateProject(): array { - return $this->client->call(Client::METHOD_POST, '/schedules', array_merge([ + $team = $this->client->call(Client::METHOD_POST, '/teams', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - ], $this->getHeaders()), $params); - } + ], $this->getHeaders()), [ + 'teamId' => ID::unique(), + 'name' => 'Schedule Test Team', + ]); - protected function getSchedule(string $scheduleId): array - { - return $this->client->call(Client::METHOD_GET, '/schedules/' . $scheduleId, array_merge([ - 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getProject()['$id'], - ], $this->getHeaders())); - } + $this->assertEquals(201, $team['headers']['status-code']); - protected function listSchedules(array $params = []): array - { - return $this->client->call(Client::METHOD_GET, '/schedules', array_merge([ + $project = $this->client->call(Client::METHOD_POST, '/projects', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - ], $this->getHeaders()), $params); - } + ], $this->getHeaders()), [ + 'projectId' => ID::unique(), + 'name' => 'Schedule Test Project', + 'teamId' => $team['body']['$id'], + 'region' => System::getEnv('_APP_REGION', 'default'), + ]); - protected function createFunction(array $params = []): array - { - return $this->client->call(Client::METHOD_POST, '/functions', array_merge([ + $this->assertEquals(201, $project['headers']['status-code']); + + $projectId = $project['body']['$id']; + + $key = $this->client->call(Client::METHOD_POST, '/projects/' . $projectId . '/keys', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - ], $this->getHeaders()), array_merge([ - 'functionId' => ID::unique(), - 'name' => 'Test Schedule Function', - 'runtime' => 'node-22', - 'entrypoint' => 'index.js', - 'execute' => ['any'], - ], $params)); + ], $this->getHeaders()), [ + 'keyId' => ID::unique(), + 'name' => 'Schedule Test Key', + 'scopes' => [ + 'functions.read', + 'functions.write', + 'execution.read', + 'execution.write', + 'messages.read', + 'messages.write', + ], + ]); + + $this->assertEquals(201, $key['headers']['status-code']); + + return [ + 'projectId' => $projectId, + 'apiKey' => $key['body']['secret'], + ]; } } diff --git a/tests/e2e/Services/Schedules/SchedulesCustomServerTest.php b/tests/e2e/Services/Schedules/SchedulesCustomServerTest.php index aff48202fa..8ba00e4d3e 100644 --- a/tests/e2e/Services/Schedules/SchedulesCustomServerTest.php +++ b/tests/e2e/Services/Schedules/SchedulesCustomServerTest.php @@ -2,28 +2,50 @@ namespace Tests\E2E\Services\Schedules; -use Tests\E2E\Scopes\ProjectCustom; +use Tests\E2E\Client; +use Tests\E2E\Scopes\ProjectConsole; use Tests\E2E\Scopes\Scope; -use Tests\E2E\Scopes\SideServer; +use Tests\E2E\Scopes\SideClient; use Utopia\Database\Helpers\ID; use Utopia\Database\Query; +use Utopia\System\System; class SchedulesCustomServerTest extends Scope { use SchedulesBase; - use ProjectCustom; - use SideServer; + use ProjectConsole; + use SideClient; - public function testCreateSchedule(): array + /** + * @depends testCreateProject + */ + public function testCreateSchedule($data): array { + $id = $data['projectId'] ?? ''; + $apiKey = $data['apiKey'] ?? ''; + /** * Test for SUCCESS */ - $function = $this->createFunction(); + $function = $this->client->call(Client::METHOD_POST, '/functions', [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $id, + 'x-appwrite-key' => $apiKey, + ], [ + 'functionId' => ID::unique(), + 'name' => 'Test Schedule Function', + 'runtime' => 'node-22', + 'entrypoint' => 'index.js', + 'execute' => ['any'], + ]); + $this->assertEquals(201, $function['headers']['status-code']); $functionId = $function['body']['$id']; - $response = $this->createSchedule([ + $response = $this->client->call(Client::METHOD_POST, '/projects/' . $id . '/schedules', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ 'resourceType' => 'function', 'resourceId' => $functionId, 'schedule' => '0 0 * * *', @@ -42,13 +64,20 @@ class SchedulesCustomServerTest extends Scope $this->assertTrue($response['body']['active']); $this->assertNotEmpty($response['body']['region']); - return ['scheduleId' => $response['body']['$id'], 'functionId' => $functionId]; - } + $data = array_merge($data, [ + 'scheduleId' => $response['body']['$id'], + 'functionId' => $functionId, + ]); - public function testCreateScheduleResourceNotFound(): void - { - // Function not found - $response = $this->createSchedule([ + /** + * Test for FAILURE + */ + + // Resource not found + $response = $this->client->call(Client::METHOD_POST, '/projects/' . $id . '/schedules', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ 'resourceType' => 'function', 'resourceId' => ID::unique(), 'schedule' => '0 0 * * *', @@ -56,51 +85,35 @@ class SchedulesCustomServerTest extends Scope $this->assertEquals(404, $response['headers']['status-code']); - // Execution not found - $response = $this->createSchedule([ - 'resourceType' => 'execution', - 'resourceId' => ID::unique(), - 'schedule' => '*/10 * * * *', - ]); - - $this->assertEquals(404, $response['headers']['status-code']); - - // Message not found - $response = $this->createSchedule([ - 'resourceType' => 'message', - 'resourceId' => ID::unique(), - 'schedule' => '0 9 * * 1', - ]); - - $this->assertEquals(404, $response['headers']['status-code']); - } - - public function testCreateScheduleInvalidResourceType(): void - { - $response = $this->createSchedule([ + // Invalid resource type + $response = $this->client->call(Client::METHOD_POST, '/projects/' . $id . '/schedules', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ 'resourceType' => 'invalid', 'resourceId' => ID::unique(), 'schedule' => '0 0 * * *', ]); $this->assertEquals(400, $response['headers']['status-code']); - } - public function testCreateScheduleInvalidCron(): void - { - $response = $this->createSchedule([ + // Invalid cron + $response = $this->client->call(Client::METHOD_POST, '/projects/' . $id . '/schedules', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ 'resourceType' => 'function', 'resourceId' => ID::unique(), 'schedule' => 'not-a-cron', ]); $this->assertEquals(400, $response['headers']['status-code']); - } - public function testCreateScheduleMissingRequired(): void - { // Missing resourceType - $response = $this->createSchedule([ + $response = $this->client->call(Client::METHOD_POST, '/projects/' . $id . '/schedules', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ 'resourceId' => ID::unique(), 'schedule' => '0 0 * * *', ]); @@ -108,7 +121,10 @@ class SchedulesCustomServerTest extends Scope $this->assertEquals(400, $response['headers']['status-code']); // Missing resourceId - $response = $this->createSchedule([ + $response = $this->client->call(Client::METHOD_POST, '/projects/' . $id . '/schedules', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ 'resourceType' => 'function', 'schedule' => '0 0 * * *', ]); @@ -116,49 +132,69 @@ class SchedulesCustomServerTest extends Scope $this->assertEquals(400, $response['headers']['status-code']); // Missing schedule - $response = $this->createSchedule([ + $response = $this->client->call(Client::METHOD_POST, '/projects/' . $id . '/schedules', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ 'resourceType' => 'function', 'resourceId' => ID::unique(), ]); $this->assertEquals(400, $response['headers']['status-code']); + + return $data; } /** * @depends testCreateSchedule */ - public function testGetSchedule(array $data): void + public function testGetSchedule($data): array { - $scheduleId = $data['scheduleId']; + $id = $data['projectId'] ?? ''; + $scheduleId = $data['scheduleId'] ?? ''; /** * Test for SUCCESS */ - $response = $this->getSchedule($scheduleId); + $response = $this->client->call(Client::METHOD_GET, '/projects/' . $id . '/schedules/' . $scheduleId, 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']['$id']); $this->assertEquals($scheduleId, $response['body']['$id']); $this->assertEquals('function', $response['body']['resourceType']); $this->assertEquals('0 0 * * *', $response['body']['schedule']); $this->assertTrue($response['body']['active']); - } - public function testGetScheduleNotFound(): void - { - $response = $this->getSchedule('nonexistent'); + /** + * Test for FAILURE + */ + $response = $this->client->call(Client::METHOD_GET, '/projects/' . $id . '/schedules/error', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), []); $this->assertEquals(404, $response['headers']['status-code']); + + return $data; } /** * @depends testCreateSchedule */ - public function testListSchedules(array $data): void + public function testListSchedules($data): array { + $id = $data['projectId'] ?? ''; + /** * Test for SUCCESS */ - $response = $this->listSchedules(); + $response = $this->client->call(Client::METHOD_GET, '/projects/' . $id . '/schedules', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), []); $this->assertEquals(200, $response['headers']['status-code']); $this->assertIsArray($response['body']['schedules']); @@ -176,15 +212,12 @@ class SchedulesCustomServerTest extends Scope $this->assertArrayHasKey('schedule', $schedule); $this->assertArrayHasKey('active', $schedule); $this->assertArrayHasKey('region', $schedule); - } - /** - * @depends testCreateSchedule - */ - public function testListSchedulesWithQuery(array $data): void - { - // Filter by resourceType - $response = $this->listSchedules([ + /** Filter by resourceType */ + $response = $this->client->call(Client::METHOD_GET, '/projects/' . $id . '/schedules', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ 'queries' => [Query::equal('resourceType', ['function'])->toString()], ]); @@ -195,8 +228,11 @@ class SchedulesCustomServerTest extends Scope $this->assertEquals('function', $schedule['resourceType']); } - // Filter by active status - $response = $this->listSchedules([ + /** Filter by active status */ + $response = $this->client->call(Client::METHOD_GET, '/projects/' . $id . '/schedules', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ 'queries' => [Query::equal('active', [true])->toString()], ]); @@ -205,61 +241,78 @@ class SchedulesCustomServerTest extends Scope foreach ($response['body']['schedules'] as $schedule) { $this->assertTrue($schedule['active']); } - } - public function testListSchedulesWithTotalDisabled(): void - { - $response = $this->listSchedules([ + /** List with total disabled */ + $response = $this->client->call(Client::METHOD_GET, '/projects/' . $id . '/schedules', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ 'total' => false, ]); $this->assertEquals(200, $response['headers']['status-code']); $this->assertEquals(0, $response['body']['total']); $this->assertIsArray($response['body']['schedules']); - } - public function testListSchedulesInvalidQuery(): void - { - $response = $this->listSchedules([ + /** + * Test for FAILURE + */ + $response = $this->client->call(Client::METHOD_GET, '/projects/' . $id . '/schedules', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ 'queries' => [Query::equal('nonexistent', ['value'])->toString()], ]); $this->assertEquals(400, $response['headers']['status-code']); + + return $data; } - public function testScheduleProjectIsolation(): void + /** + * @depends testCreateSchedule + */ + public function testScheduleProjectIsolation($data): void { - // Create a function and schedule in the current project - $function = $this->createFunction(); - $this->assertEquals(201, $function['headers']['status-code']); + $scheduleId = $data['scheduleId'] ?? ''; - $response = $this->createSchedule([ - 'resourceType' => 'function', - 'resourceId' => $function['body']['$id'], - 'schedule' => '0 12 * * *', + // Create a second project + $team = $this->client->call(Client::METHOD_POST, '/teams', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'teamId' => ID::unique(), + 'name' => 'Isolation Test Team', ]); - $this->assertEquals(201, $response['headers']['status-code']); - $scheduleId = $response['body']['$id']; + $this->assertEquals(201, $team['headers']['status-code']); - // Create a fresh project with its own key - $freshProject = $this->getProject(true); + $otherProject = $this->client->call(Client::METHOD_POST, '/projects', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'projectId' => ID::unique(), + 'name' => 'Isolation Test Project', + 'teamId' => $team['body']['$id'], + 'region' => System::getEnv('_APP_REGION', 'default'), + ]); + + $this->assertEquals(201, $otherProject['headers']['status-code']); + $otherProjectId = $otherProject['body']['$id']; // Try to get the schedule from the other project - $response = $this->client->call(\Tests\E2E\Client::METHOD_GET, '/schedules/' . $scheduleId, [ + $response = $this->client->call(Client::METHOD_GET, '/projects/' . $otherProjectId . '/schedules/' . $scheduleId, array_merge([ 'content-type' => 'application/json', - 'x-appwrite-project' => $freshProject['$id'], - 'x-appwrite-key' => $freshProject['apiKey'], - ]); + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), []); $this->assertEquals(404, $response['headers']['status-code']); // List should not include schedules from other projects - $response = $this->client->call(\Tests\E2E\Client::METHOD_GET, '/schedules', [ + $response = $this->client->call(Client::METHOD_GET, '/projects/' . $otherProjectId . '/schedules', array_merge([ 'content-type' => 'application/json', - 'x-appwrite-project' => $freshProject['$id'], - 'x-appwrite-key' => $freshProject['apiKey'], - ]); + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), []); $this->assertEquals(200, $response['headers']['status-code']);