From 4721523ea8eedd501fbe11f397b0dcd469d17062 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Ba=C4=8Do?= Date: Thu, 7 May 2026 10:30:56 +0200 Subject: [PATCH 1/8] Improve project tests --- .../Projects/ProjectsConsoleClientTest.php | 430 +++++++++++++++++- 1 file changed, 428 insertions(+), 2 deletions(-) diff --git a/tests/e2e/Services/Projects/ProjectsConsoleClientTest.php b/tests/e2e/Services/Projects/ProjectsConsoleClientTest.php index 3a9037c368..f3643f0959 100644 --- a/tests/e2e/Services/Projects/ProjectsConsoleClientTest.php +++ b/tests/e2e/Services/Projects/ProjectsConsoleClientTest.php @@ -787,12 +787,117 @@ class ProjectsConsoleClientTest extends Scope 'projectId' => ID::unique(), 'name' => 'Project Test', 'teamId' => $team['body']['$id'], - 'region' => System::getEnv('_APP_REGION', 'default') + 'region' => System::getEnv('_APP_REGION', 'default'), + 'description' => 'My description', + 'logo' => 'https://google.com/logo.png', + 'url' => 'https://myapp.com/', + 'legalName' => 'Legal company', + 'legalCountry' => 'Slovakia', + 'legalState' => 'Custom state', + 'legalCity' => 'Košice', + 'legalAddress' => 'Main street 32', + 'legalTaxId' => 'TAXID_123456' ]); - + $this->assertEquals(201, $response['headers']['status-code']); $id = $response['body']['$id']; + // Add mock numbers + $response = $this->client->call(Client::METHOD_POST, '/project/' . $id . '/mock-phones', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'number' => '+421123456789', + 'otp' => '123456' + ]); + $this->assertEquals(201, $response['headers']['status-code']); + + $response = $this->client->call(Client::METHOD_POST, '/project/' . $id . '/mock-phones', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'number' => '+420987654321', + 'otp' => '654321' + ]); + $this->assertEquals(201, $response['headers']['status-code']); + + // Setup custom values for project policies + $response = $this->client->call(Client::METHOD_PATCH, '/project/' . $id . '/policies/session-duration', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'duration' => 135 + ]); + $this->assertEquals(200, $response['headers']['status-code']); + + $response = $this->client->call(Client::METHOD_PATCH, '/project/' . $id . '/policies/user-limit', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'total' => 54 + ]); + $this->assertEquals(200, $response['headers']['status-code']); + + $response = $this->client->call(Client::METHOD_PATCH, '/project/' . $id . '/policies/session-limit', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'total' => 7 + ]); + $this->assertEquals(200, $response['headers']['status-code']); + + $response = $this->client->call(Client::METHOD_PATCH, '/project/' . $id . '/policies/password-history', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'total' => 9 + ]); + $this->assertEquals(200, $response['headers']['status-code']); + + $response = $this->client->call(Client::METHOD_PATCH, '/project/' . $id . '/policies/password-dictionary', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'enabled' => true + ]); + $this->assertEquals(200, $response['headers']['status-code']); + + $response = $this->client->call(Client::METHOD_PATCH, '/project/' . $id . '/policies/password-personal-data', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'enabled' => true + ]); + $this->assertEquals(200, $response['headers']['status-code']); + + $response = $this->client->call(Client::METHOD_PATCH, '/project/' . $id . '/policies/session-alert', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'enabled' => true + ]); + $this->assertEquals(200, $response['headers']['status-code']); + + $response = $this->client->call(Client::METHOD_PATCH, '/project/' . $id . '/policies/membership-privacy', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'userId' => true, + 'userEmail' => true, + 'userPhone' => true, + 'userName' => true, + 'userMFA' => true, + ]); + $this->assertEquals(200, $response['headers']['status-code']); + + $response = $this->client->call(Client::METHOD_PATCH, '/project/' . $id . '/policies/session-invalidation', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'enabled' => false + ]); + $this->assertEquals(200, $response['headers']['status-code']); + /** * Test for SUCCESS */ @@ -806,6 +911,327 @@ class ProjectsConsoleClientTest extends Scope $this->assertEquals($id, $response['body']['$id']); $this->assertEquals('Project Test', $response['body']['name']); + $this->assertArrayHasKey('$createdAt', $response); + $this->assertIsString($response['$createdAt']); + $this->assertNotFalse(\strtotime($response['$createdAt'])); + + $this->assertArrayHasKey('$updatedAt', $response); + $this->assertIsString($response['$updatedAt']); + $this->assertNotFalse(\strtotime($response['$updatedAt'])); + + $this->assertArrayHasKey('description', $response); + $this->assertIsString($response['description']); + $this->assertEquals('My description', $response['description']); + + $this->assertArrayHasKey('teamId', $response); + $this->assertIsString($response['teamId']); + $this->assertEquals($team['body']['$id'], $response['teamId']); + + $this->assertArrayHasKey('logo', $response); + $this->assertIsString($response['logo']); + $this->assertEquals('https://google.com/logo.png', $response['logo']); + + $this->assertArrayHasKey('url', $response); + $this->assertIsString($response['url']); + $this->assertEquals('https://myapp.com/', $response['url']); + + $this->assertArrayHasKey('legalName', $response); + $this->assertIsString($response['legalName']); + $this->assertEquals('Legal company', $response['legalName']); + + $this->assertArrayHasKey('legalCountry', $response); + $this->assertIsString($response['legalCountry']); + $this->assertEquals('Slovakia', $response['legalCountry']); + + $this->assertArrayHasKey('legalState', $response); + $this->assertIsString($response['legalState']); + $this->assertEquals('Custom state', $response['legalState']); + + $this->assertArrayHasKey('legalCity', $response); + $this->assertIsString($response['legalCity']); + $this->assertEquals('Košice', $response['legalCity']); + + $this->assertArrayHasKey('legalAddress', $response); + $this->assertIsString($response['legalAddress']); + $this->assertEquals('Main street 32', $response['legalAddress']); + + $this->assertArrayHasKey('legalTaxId', $response); + $this->assertIsString($response['legalTaxId']); + $this->assertEquals('TAXID_123456', $response['legalTaxId']); + + $this->assertArrayHasKey('authDuration', $response); + $this->assertIsInt($response['authDuration']); + $this->assertEquals(135, $response['authDuration']); + + $this->assertArrayHasKey('authLimit', $response); + $this->assertIsInt($response['authLimit']); + $this->assertEquals(54, $response['authLimit']); + + $this->assertArrayHasKey('authSessionsLimit', $response); + $this->assertIsInt($response['authSessionsLimit']); + $this->assertEquals(7, $response['authLimit']); + + $this->assertArrayHasKey('authPasswordHistory', $response); + $this->assertIsInt($response['authPasswordHistory']); + $this->assertEquals(9, $response['authPasswordHistory']); + + $this->assertArrayHasKey('authPasswordDictionary', $response); + $this->assertIsBool($response['authPasswordDictionary']); + $this->assertTrue($response['authPasswordDictionary']); + + $this->assertArrayHasKey('authPersonalDataCheck', $response); + $this->assertIsBool($response['authPersonalDataCheck']); + $this->assertTrue($response['authPersonalDataCheck']); + + $this->assertArrayHasKey('authDisposableEmails', $response); + $this->assertIsBool($response['authDisposableEmails']); + $this->assertFalse($response['authDisposableEmails']); + + $this->assertArrayHasKey('authCanonicalEmails', $response); + $this->assertIsBool($response['authCanonicalEmails']); + $this->assertFalse($response['authCanonicalEmails']); + + $this->assertArrayHasKey('authFreeEmails', $response); + $this->assertIsBool($response['authFreeEmails']); + $this->assertFalse($response['authFreeEmails']); + + $this->assertArrayHasKey('authMockNumbers', $response); + $this->assertIsArray($response['authMockNumbers']); + $this->assertCount(2, $response['authMockNumbers']); + + $this->assertEquals('+421123456789', $response['authMockNumbers'][0]['number']); + $this->assertEquals('+420987654321', $response['authMockNumbers'][1]['number']); + + $this->assertEquals('123456', $response['authMockNumbers'][0]['otp']); + $this->assertEquals('654321', $response['authMockNumbers'][1]['otp']); + + foreach($response['authMockNumbers'] as $mockNumber) { + $this->assertArrayHasKey('$createdAt', $mockNumber); + $this->assertIsString($mockNumber['$createdAt']); + $this->assertNotFalse(\strtotime($mockNumber['$createdAt'])); + + $this->assertArrayHasKey('$updatedAt', $mockNumber); + $this->assertIsString($mockNumber['$updatedAt']); + $this->assertNotFalse(\strtotime($mockNumber['$updatedAt'])); + + $this->assertArrayHasKey('number', $mockNumber); + $this->assertIsString($mockNumber['number']); + $this->assertNotEmpty($mockNumber['number']); + + $this->assertArrayHasKey('otp', $mockNumber); + $this->assertIsString($mockNumber['otp']); + $this->assertNotEmpty($mockNumber['otp']); + } + + $this->assertArrayHasKey('authSessionAlerts', $response); + $this->assertIsBool($response['authSessionAlerts']); + $this->assertTrue($response['authSessionAlerts']); + + $this->assertArrayHasKey('authMembershipsUserName', $response); + $this->assertIsBool($response['authMembershipsUserName']); + $this->assertTrue($response['authMembershipsUserName']); + + $this->assertArrayHasKey('authMembershipsUserEmail', $response); + $this->assertIsBool($response['authMembershipsUserEmail']); + $this->assertTrue($response['authMembershipsUserEmail']); + + $this->assertArrayHasKey('authMembershipsMfa', $response); + $this->assertIsBool($response['authMembershipsMfa']); + $this->assertTrue($response['authMembershipsMfa']); + + $this->assertArrayHasKey('authMembershipsUserId', $response); + $this->assertIsBool($project['authMembershipsUserId']); + $this->assertTrue($response['authMembershipsUserId']); + + $this->assertArrayHasKey('authMembershipsUserPhone', $response); + $this->assertIsBool($response['authMembershipsUserPhone']); + $this->assertTrue($response['authMembershipsUserPhone']); + + $this->assertArrayHasKey('authInvalidateSessions', $response); + $this->assertIsBool($response['authInvalidateSessions']); + $this->assertTrue($response['authInvalidateSessions']); + + /* + $this->assertArrayHasKey('oAuthProviders', $project); + $this->assertIsArray($project['oAuthProviders']); + + $this->assertArrayHasKey('platforms', $project); + $this->assertIsArray($project['platforms']); + + $this->assertArrayHasKey('webhooks', $project); + $this->assertIsArray($project['webhooks']); + + $this->assertArrayHasKey('keys', $project); + $this->assertIsArray($project['keys']); + + $this->assertArrayHasKey('devKeys', $project); + $this->assertIsArray($project['devKeys']); + */ + + /* + $this->assertArrayHasKey('smtpEnabled', $project); + $this->assertIsBool($project['smtpEnabled']); + + $this->assertArrayHasKey('smtpSenderName', $project); + $this->assertIsString($project['smtpSenderName']); + + $this->assertArrayHasKey('smtpSenderEmail', $project); + $this->assertIsString($project['smtpSenderEmail']); + + $this->assertArrayHasKey('smtpReplyToName', $project); + $this->assertIsString($project['smtpReplyToName']); + + $this->assertArrayHasKey('smtpReplyToEmail', $project); + $this->assertIsString($project['smtpReplyToEmail']); + + $this->assertArrayHasKey('smtpHost', $project); + $this->assertIsString($project['smtpHost']); + + $this->assertArrayHasKey('smtpPort', $project); + $this->assertTrue( + is_int($project['smtpPort']) || $project['smtpPort'] === '', + 'smtpPort should be an integer or an empty string' + ); + + $this->assertArrayHasKey('smtpUsername', $project); + $this->assertIsString($project['smtpUsername']); + + $this->assertArrayHasKey('smtpPassword', $project); + $this->assertIsString($project['smtpPassword']); + + $this->assertArrayHasKey('smtpSecure', $project); + $this->assertIsString($project['smtpSecure']); + */ + + + /* + $this->assertArrayHasKey('pingCount', $project); + $this->assertIsInt($project['pingCount']); + + $this->assertArrayHasKey('pingedAt', $project); + $this->assertIsString($project['pingedAt']); + + $this->assertArrayHasKey('labels', $project); + $this->assertIsArray($project['labels']); + + $this->assertArrayHasKey('status', $project); + $this->assertIsString($project['status']); + */ + + /* + $auth = require(__DIR__ . '/../../../../app/config/auth.php'); + foreach ($auth as $method) { + $key = 'auth' . ucfirst($method['key'] ?? ''); + $this->assertArrayHasKey($key, $project, 'Missing auth field: ' . $key); + $this->assertIsBool($project[$key], 'Auth field should be boolean: ' . $key); + } + + $services = require(__DIR__ . '/../../../../app/config/services.php'); + foreach ($services as $service) { + if (!($service['optional'] ?? false)) { + continue; + } + $key = 'serviceStatusFor' . ucfirst($service['key'] ?? ''); + $this->assertArrayHasKey($key, $project, 'Missing service field: ' . $key); + $this->assertIsBool($project[$key], 'Service field should be boolean: ' . $key); + } + + // Dynamic protocol status fields + $protocols = require(__DIR__ . '/../../../../app/config/protocols.php'); + foreach ($protocols as $protocol) { + $key = 'protocolStatusFor' . ucfirst($protocol['key'] ?? ''); + $this->assertArrayHasKey($key, $project, 'Missing protocol field: ' . $key); + $this->assertIsBool($project[$key], 'Protocol field should be boolean: ' . $key); + } + */ + + // Ensure policies can be falsy + + $response = $this->client->call(Client::METHOD_PATCH, '/project/' . $id . '/policies/password-dictionary', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'enabled' => false + ]); + $this->assertEquals(200, $response['headers']['status-code']); + + $response = $this->client->call(Client::METHOD_PATCH, '/project/' . $id . '/policies/password-personal-data', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'enabled' => false + ]); + $this->assertEquals(200, $response['headers']['status-code']); + + $response = $this->client->call(Client::METHOD_PATCH, '/project/' . $id . '/policies/session-alert', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'enabled' => false + ]); + $this->assertEquals(200, $response['headers']['status-code']); + + $response = $this->client->call(Client::METHOD_PATCH, '/project/' . $id . '/policies/membership-privacy', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'userId' => false, + 'userEmail' => false, + 'userPhone' => false, + 'userName' => false, + 'userMFA' => false, + ]); + $this->assertEquals(200, $response['headers']['status-code']); + + $response = $this->client->call(Client::METHOD_PATCH, '/project/' . $id . '/policies/session-invalidation', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'enabled' => false + ]); + $this->assertEquals(200, $response['headers']['status-code']); + + $response = $this->client->call(Client::METHOD_GET, '/projects/' . $id, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertArrayHasKey('authPasswordDictionary', $response); + $this->assertIsBool($response['authPasswordDictionary']); + $this->assertFalse($response['authPasswordDictionary']); + + $this->assertArrayHasKey('authPersonalDataCheck', $response); + $this->assertIsBool($response['authPersonalDataCheck']); + $this->assertFalse($response['authPersonalDataCheck']); + + $this->assertArrayHasKey('authSessionAlerts', $response); + $this->assertIsBool($response['authSessionAlerts']); + $this->assertFalse($response['authSessionAlerts']); + + $this->assertArrayHasKey('authMembershipsUserName', $response); + $this->assertIsBool($response['authMembershipsUserName']); + $this->assertFalse($response['authMembershipsUserName']); + + $this->assertArrayHasKey('authMembershipsUserEmail', $response); + $this->assertIsBool($response['authMembershipsUserEmail']); + $this->assertFalse($response['authMembershipsUserEmail']); + + $this->assertArrayHasKey('authMembershipsMfa', $response); + $this->assertIsBool($response['authMembershipsMfa']); + $this->assertFalse($response['authMembershipsMfa']); + + $this->assertArrayHasKey('authMembershipsUserId', $response); + $this->assertIsBool($project['authMembershipsUserId']); + $this->assertFalse($response['authMembershipsUserId']); + + $this->assertArrayHasKey('authMembershipsUserPhone', $response); + $this->assertIsBool($response['authMembershipsUserPhone']); + $this->assertFalse($response['authMembershipsUserPhone']); + + $this->assertArrayHasKey('authInvalidateSessions', $response); + $this->assertIsBool($response['authInvalidateSessions']); + $this->assertFalse($response['authInvalidateSessions']); + /** * Test for FAILURE */ From 8ad106632e1e1442cde72726864137d3c2863079 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Ba=C4=8Do?= Date: Thu, 7 May 2026 10:40:54 +0200 Subject: [PATCH 2/8] Improve tests further --- phpunit.xml | 2 +- .../Projects/ProjectsConsoleClientTest.php | 181 ++++++++++++------ 2 files changed, 128 insertions(+), 55 deletions(-) diff --git a/phpunit.xml b/phpunit.xml index 9748c5a5c8..b566e232cd 100644 --- a/phpunit.xml +++ b/phpunit.xml @@ -5,7 +5,7 @@ bootstrap="app/init.php" colors="true" processIsolation="false" - stopOnFailure="false" + stopOnFailure="true" stopOnError="false" cacheDirectory=".phpunit.cache" > diff --git a/tests/e2e/Services/Projects/ProjectsConsoleClientTest.php b/tests/e2e/Services/Projects/ProjectsConsoleClientTest.php index f3643f0959..6ed45e36df 100644 --- a/tests/e2e/Services/Projects/ProjectsConsoleClientTest.php +++ b/tests/e2e/Services/Projects/ProjectsConsoleClientTest.php @@ -802,19 +802,41 @@ class ProjectsConsoleClientTest extends Scope $this->assertEquals(201, $response['headers']['status-code']); $id = $response['body']['$id']; + // Configure SMTP + $response = $this->client->call( + Client::METHOD_PATCH, + '/project/smtp', + array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $id, + ], $this->getHeaders()), + [ + 'enabled' => true, + 'senderName' => 'Custom sender', + 'senderEmail' => 'email@custom.com', + 'host' => 'maildev', + 'port' => 1025, + 'replyTo' => 'replyto@custom.com', + 'replyToName' => 'Reply sender', + ], + ); + // Add mock numbers - $response = $this->client->call(Client::METHOD_POST, '/project/' . $id . '/mock-phones', array_merge([ + $response = $this->client->call(Client::METHOD_POST, '/project/mock-phones', array_merge([ 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-project' => $id, + 'x-appwrite-mode' => 'admin', ], $this->getHeaders()), [ 'number' => '+421123456789', 'otp' => '123456' ]); + \var_dump($id); + \var_dump($this->getHeaders()); $this->assertEquals(201, $response['headers']['status-code']); - $response = $this->client->call(Client::METHOD_POST, '/project/' . $id . '/mock-phones', array_merge([ + $response = $this->client->call(Client::METHOD_POST, '/project/mock-phones', array_merge([ 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-project' => $id ], $this->getHeaders()), [ 'number' => '+420987654321', 'otp' => '654321' @@ -822,65 +844,65 @@ class ProjectsConsoleClientTest extends Scope $this->assertEquals(201, $response['headers']['status-code']); // Setup custom values for project policies - $response = $this->client->call(Client::METHOD_PATCH, '/project/' . $id . '/policies/session-duration', array_merge([ + $response = $this->client->call(Client::METHOD_PATCH, '/project/policies/session-duration', array_merge([ 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-project' => $id ], $this->getHeaders()), [ 'duration' => 135 ]); $this->assertEquals(200, $response['headers']['status-code']); - $response = $this->client->call(Client::METHOD_PATCH, '/project/' . $id . '/policies/user-limit', array_merge([ + $response = $this->client->call(Client::METHOD_PATCH, '/project/policies/user-limit', array_merge([ 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-project' => $id, ], $this->getHeaders()), [ 'total' => 54 ]); $this->assertEquals(200, $response['headers']['status-code']); - $response = $this->client->call(Client::METHOD_PATCH, '/project/' . $id . '/policies/session-limit', array_merge([ + $response = $this->client->call(Client::METHOD_PATCH, '/project/policies/session-limit', array_merge([ 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-project' => $id, ], $this->getHeaders()), [ 'total' => 7 ]); $this->assertEquals(200, $response['headers']['status-code']); - $response = $this->client->call(Client::METHOD_PATCH, '/project/' . $id . '/policies/password-history', array_merge([ + $response = $this->client->call(Client::METHOD_PATCH, '/project/policies/password-history', array_merge([ 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-project' => $id, ], $this->getHeaders()), [ 'total' => 9 ]); $this->assertEquals(200, $response['headers']['status-code']); - $response = $this->client->call(Client::METHOD_PATCH, '/project/' . $id . '/policies/password-dictionary', array_merge([ + $response = $this->client->call(Client::METHOD_PATCH, '/project/policies/password-dictionary', array_merge([ 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-project' => $id, ], $this->getHeaders()), [ 'enabled' => true ]); $this->assertEquals(200, $response['headers']['status-code']); - $response = $this->client->call(Client::METHOD_PATCH, '/project/' . $id . '/policies/password-personal-data', array_merge([ + $response = $this->client->call(Client::METHOD_PATCH, '/project/policies/password-personal-data', array_merge([ 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-project' => $id, ], $this->getHeaders()), [ 'enabled' => true ]); $this->assertEquals(200, $response['headers']['status-code']); - $response = $this->client->call(Client::METHOD_PATCH, '/project/' . $id . '/policies/session-alert', array_merge([ + $response = $this->client->call(Client::METHOD_PATCH, '/project/policies/session-alert', array_merge([ 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-project' => $id, ], $this->getHeaders()), [ 'enabled' => true ]); $this->assertEquals(200, $response['headers']['status-code']); - $response = $this->client->call(Client::METHOD_PATCH, '/project/' . $id . '/policies/membership-privacy', array_merge([ + $response = $this->client->call(Client::METHOD_PATCH, '/project/policies/membership-privacy', array_merge([ 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-project' => $id, ], $this->getHeaders()), [ 'userId' => true, 'userEmail' => true, @@ -890,9 +912,9 @@ class ProjectsConsoleClientTest extends Scope ]); $this->assertEquals(200, $response['headers']['status-code']); - $response = $this->client->call(Client::METHOD_PATCH, '/project/' . $id . '/policies/session-invalidation', array_merge([ + $response = $this->client->call(Client::METHOD_PATCH, '/project/policies/session-invalidation', array_merge([ 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-project' => $id, ], $this->getHeaders()), [ 'enabled' => false ]); @@ -1051,6 +1073,46 @@ class ProjectsConsoleClientTest extends Scope $this->assertIsBool($response['authInvalidateSessions']); $this->assertTrue($response['authInvalidateSessions']); + $this->assertArrayHasKey('smtpEnabled', $response); + $this->assertIsBool($response['smtpEnabled']); + $this->assertTrue($response['smtpEnabled']); + + $this->assertArrayHasKey('smtpSenderName', $response); + $this->assertIsString($response['smtpSenderName']); + $this->assertSame('Custom sender', $response['smtpSenderName']); + + $this->assertArrayHasKey('smtpSenderEmail', $response); + $this->assertIsString($response['smtpSenderEmail']); + $this->assertSame('email@custom.com', $response['smtpSenderEmail']); + + $this->assertArrayHasKey('smtpReplyToName', $response); + $this->assertIsString($response['smtpReplyToName']); + $this->assertSame('Reply sender', $response['smtpReplyToName']); + + $this->assertArrayHasKey('smtpReplyToEmail', $response); + $this->assertIsString($response['smtpReplyToEmail']); + $this->assertSame('replyto@custom.com', $response['smtpReplyToEmail']); + + $this->assertArrayHasKey('smtpHost', $response); + $this->assertIsString($response['smtpHost']); + $this->assertSame('maildev', $response['smtpHost']); + + $this->assertArrayHasKey('smtpPort', $response); + $this->assertIsInt($response['smtpPort']); + $this->assertSame(1025, $response['smtpPort']); + + $this->assertArrayHasKey('smtpUsername', $response); + $this->assertIsString($response['smtpUsername']); + $this->assertSame('', $response['smtpUsername']); + + $this->assertArrayHasKey('smtpPassword', $response); + $this->assertIsString($response['smtpPassword']); + $this->assertSame('', $response['smtpPassword']); + + $this->assertArrayHasKey('smtpSecure', $response); + $this->assertIsString($response['smtpSecure']); + $this->assertSame('', $response['smtpSecure']); + /* $this->assertArrayHasKey('oAuthProviders', $project); $this->assertIsArray($project['oAuthProviders']); @@ -1069,38 +1131,7 @@ class ProjectsConsoleClientTest extends Scope */ /* - $this->assertArrayHasKey('smtpEnabled', $project); - $this->assertIsBool($project['smtpEnabled']); - - $this->assertArrayHasKey('smtpSenderName', $project); - $this->assertIsString($project['smtpSenderName']); - - $this->assertArrayHasKey('smtpSenderEmail', $project); - $this->assertIsString($project['smtpSenderEmail']); - - $this->assertArrayHasKey('smtpReplyToName', $project); - $this->assertIsString($project['smtpReplyToName']); - - $this->assertArrayHasKey('smtpReplyToEmail', $project); - $this->assertIsString($project['smtpReplyToEmail']); - - $this->assertArrayHasKey('smtpHost', $project); - $this->assertIsString($project['smtpHost']); - - $this->assertArrayHasKey('smtpPort', $project); - $this->assertTrue( - is_int($project['smtpPort']) || $project['smtpPort'] === '', - 'smtpPort should be an integer or an empty string' - ); - - $this->assertArrayHasKey('smtpUsername', $project); - $this->assertIsString($project['smtpUsername']); - - $this->assertArrayHasKey('smtpPassword', $project); - $this->assertIsString($project['smtpPassword']); - - $this->assertArrayHasKey('smtpSecure', $project); - $this->assertIsString($project['smtpSecure']); + */ @@ -1190,6 +1221,24 @@ class ProjectsConsoleClientTest extends Scope 'enabled' => false ]); $this->assertEquals(200, $response['headers']['status-code']); + + // Configure SMTP + $response = $this->client->call( + Client::METHOD_PATCH, + '/project/smtp', + array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), + [ + 'enabled' => false, + 'host' => 'customhost.com', + 'port' => 4444, + 'username' => 'myuser', + 'password' => 'mypassword', + 'secure' => 'ssl', + ], + ); $response = $this->client->call(Client::METHOD_GET, '/projects/' . $id, array_merge([ 'content-type' => 'application/json', @@ -1232,6 +1281,30 @@ class ProjectsConsoleClientTest extends Scope $this->assertIsBool($response['authInvalidateSessions']); $this->assertFalse($response['authInvalidateSessions']); + $this->assertArrayHasKey('smtpEnabled', $response); + $this->assertIsBool($response['smtpEnabled']); + $this->assertFalse($response['smtpEnabled']); + + $this->assertArrayHasKey('smtpHost', $response); + $this->assertIsString($response['smtpHost']); + $this->assertSame('customhost.com', $response['smtpHost']); + + $this->assertArrayHasKey('smtpPort', $response); + $this->assertIsInt($response['smtpPort']); + $this->assertSame(4444, $response['smtpPort']); + + $this->assertArrayHasKey('smtpUsername', $response); + $this->assertIsString($response['smtpUsername']); + $this->assertSame('myuser', $response['smtpUsername']); + + $this->assertArrayHasKey('smtpPassword', $response); + $this->assertIsString($response['smtpPassword']); + $this->assertSame('', $response['smtpPassword']); + + $this->assertArrayHasKey('smtpSecure', $response); + $this->assertIsString($response['smtpSecure']); + $this->assertSame('ssl', $response['smtpSecure']); + /** * Test for FAILURE */ From fe27ae058406963ad8f1ec9fd3c2b8a076fface6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Ba=C4=8Do?= Date: Thu, 7 May 2026 10:58:05 +0200 Subject: [PATCH 3/8] Fix failing tests --- .../Projects/ProjectsConsoleClientTest.php | 405 ++++++------------ 1 file changed, 129 insertions(+), 276 deletions(-) diff --git a/tests/e2e/Services/Projects/ProjectsConsoleClientTest.php b/tests/e2e/Services/Projects/ProjectsConsoleClientTest.php index 6ed45e36df..a8bfaa0f7f 100644 --- a/tests/e2e/Services/Projects/ProjectsConsoleClientTest.php +++ b/tests/e2e/Services/Projects/ProjectsConsoleClientTest.php @@ -798,7 +798,7 @@ class ProjectsConsoleClientTest extends Scope 'legalAddress' => 'Main street 32', 'legalTaxId' => 'TAXID_123456' ]); - + $this->assertEquals(201, $response['headers']['status-code']); $id = $response['body']['$id']; @@ -809,6 +809,7 @@ class ProjectsConsoleClientTest extends Scope array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $id, + 'x-appwrite-mode' => 'admin', ], $this->getHeaders()), [ 'enabled' => true, @@ -816,10 +817,11 @@ class ProjectsConsoleClientTest extends Scope 'senderEmail' => 'email@custom.com', 'host' => 'maildev', 'port' => 1025, - 'replyTo' => 'replyto@custom.com', + 'replyToEmail' => 'replyto@custom.com', 'replyToName' => 'Reply sender', ], ); + $this->assertEquals(200, $response['headers']['status-code']); // Add mock numbers $response = $this->client->call(Client::METHOD_POST, '/project/mock-phones', array_merge([ @@ -830,13 +832,12 @@ class ProjectsConsoleClientTest extends Scope 'number' => '+421123456789', 'otp' => '123456' ]); - \var_dump($id); - \var_dump($this->getHeaders()); $this->assertEquals(201, $response['headers']['status-code']); $response = $this->client->call(Client::METHOD_POST, '/project/mock-phones', array_merge([ 'content-type' => 'application/json', - 'x-appwrite-project' => $id + 'x-appwrite-project' => $id, + 'x-appwrite-mode' => 'admin', ], $this->getHeaders()), [ 'number' => '+420987654321', 'otp' => '654321' @@ -846,15 +847,17 @@ class ProjectsConsoleClientTest extends Scope // Setup custom values for project policies $response = $this->client->call(Client::METHOD_PATCH, '/project/policies/session-duration', array_merge([ 'content-type' => 'application/json', - 'x-appwrite-project' => $id + 'x-appwrite-project' => $id, + 'x-appwrite-mode' => 'admin', ], $this->getHeaders()), [ 'duration' => 135 ]); $this->assertEquals(200, $response['headers']['status-code']); - + $response = $this->client->call(Client::METHOD_PATCH, '/project/policies/user-limit', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $id, + 'x-appwrite-mode' => 'admin', ], $this->getHeaders()), [ 'total' => 54 ]); @@ -863,22 +866,25 @@ class ProjectsConsoleClientTest extends Scope $response = $this->client->call(Client::METHOD_PATCH, '/project/policies/session-limit', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $id, + 'x-appwrite-mode' => 'admin', ], $this->getHeaders()), [ 'total' => 7 ]); $this->assertEquals(200, $response['headers']['status-code']); - + $response = $this->client->call(Client::METHOD_PATCH, '/project/policies/password-history', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $id, + 'x-appwrite-mode' => 'admin', ], $this->getHeaders()), [ 'total' => 9 ]); $this->assertEquals(200, $response['headers']['status-code']); - + $response = $this->client->call(Client::METHOD_PATCH, '/project/policies/password-dictionary', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $id, + 'x-appwrite-mode' => 'admin', ], $this->getHeaders()), [ 'enabled' => true ]); @@ -887,6 +893,7 @@ class ProjectsConsoleClientTest extends Scope $response = $this->client->call(Client::METHOD_PATCH, '/project/policies/password-personal-data', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $id, + 'x-appwrite-mode' => 'admin', ], $this->getHeaders()), [ 'enabled' => true ]); @@ -894,7 +901,8 @@ class ProjectsConsoleClientTest extends Scope $response = $this->client->call(Client::METHOD_PATCH, '/project/policies/session-alert', array_merge([ 'content-type' => 'application/json', - 'x-appwrite-project' => $id, + 'x-appwrite-project' => $id, + 'x-appwrite-mode' => 'admin', ], $this->getHeaders()), [ 'enabled' => true ]); @@ -903,6 +911,7 @@ class ProjectsConsoleClientTest extends Scope $response = $this->client->call(Client::METHOD_PATCH, '/project/policies/membership-privacy', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $id, + 'x-appwrite-mode' => 'admin', ], $this->getHeaders()), [ 'userId' => true, 'userEmail' => true, @@ -915,8 +924,9 @@ class ProjectsConsoleClientTest extends Scope $response = $this->client->call(Client::METHOD_PATCH, '/project/policies/session-invalidation', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $id, + 'x-appwrite-mode' => 'admin', ], $this->getHeaders()), [ - 'enabled' => false + 'enabled' => true ]); $this->assertEquals(200, $response['headers']['status-code']); @@ -929,190 +939,76 @@ class ProjectsConsoleClientTest extends Scope ], $this->getHeaders())); $this->assertEquals(200, $response['headers']['status-code']); - $this->assertNotEmpty($response['body']); $this->assertEquals($id, $response['body']['$id']); $this->assertEquals('Project Test', $response['body']['name']); - $this->assertArrayHasKey('$createdAt', $response); - $this->assertIsString($response['$createdAt']); - $this->assertNotFalse(\strtotime($response['$createdAt'])); + $this->assertIsString($response['body']['$createdAt']); + $this->assertNotEmpty($response['body']['$createdAt']); + $this->assertNotFalse(\strtotime($response['body']['$createdAt'])); - $this->assertArrayHasKey('$updatedAt', $response); - $this->assertIsString($response['$updatedAt']); - $this->assertNotFalse(\strtotime($response['$updatedAt'])); + $this->assertIsString($response['body']['$updatedAt']); + $this->assertNotEmpty($response['body']['$updatedAt']); + $this->assertNotFalse(\strtotime($response['body']['$updatedAt'])); - $this->assertArrayHasKey('description', $response); - $this->assertIsString($response['description']); - $this->assertEquals('My description', $response['description']); + $this->assertEquals('My description', $response['body']['description']); + $this->assertEquals($team['body']['$id'], $response['body']['teamId']); + $this->assertEquals('https://google.com/logo.png', $response['body']['logo']); + $this->assertEquals('https://myapp.com/', $response['body']['url']); + $this->assertEquals('Legal company', $response['body']['legalName']); + $this->assertEquals('Slovakia', $response['body']['legalCountry']); + $this->assertEquals('Custom state', $response['body']['legalState']); + $this->assertEquals('Košice', $response['body']['legalCity']); + $this->assertEquals('Main street 32', $response['body']['legalAddress']); + $this->assertEquals('TAXID_123456', $response['body']['legalTaxId']); + $this->assertEquals(135, $response['body']['authDuration']); + $this->assertEquals(54, $response['body']['authLimit']); + $this->assertEquals(7, $response['body']['authSessionsLimit']); + $this->assertEquals(9, $response['body']['authPasswordHistory']); + $this->assertTrue($response['body']['authPasswordDictionary']); + $this->assertTrue($response['body']['authPersonalDataCheck']); + $this->assertFalse($response['body']['authDisposableEmails']); + $this->assertFalse($response['body']['authCanonicalEmails']); + $this->assertFalse($response['body']['authFreeEmails']); + $this->assertTrue($response['body']['authSessionAlerts']); + $this->assertTrue($response['body']['authMembershipsUserName']); + $this->assertTrue($response['body']['authMembershipsUserEmail']); + $this->assertTrue($response['body']['authMembershipsMfa']); + $this->assertTrue($response['body']['authMembershipsUserId']); + $this->assertTrue($response['body']['authMembershipsUserPhone']); + $this->assertTrue($response['body']['authInvalidateSessions']); + $this->assertTrue($response['body']['smtpEnabled']); + $this->assertSame('Custom sender', $response['body']['smtpSenderName']); + $this->assertSame('email@custom.com', $response['body']['smtpSenderEmail']); + $this->assertSame('Reply sender', $response['body']['smtpReplyToName']); + $this->assertSame('replyto@custom.com', $response['body']['smtpReplyToEmail']); + $this->assertSame('maildev', $response['body']['smtpHost']); + $this->assertSame(1025, $response['body']['smtpPort']); + $this->assertSame('', $response['body']['smtpUsername']); + $this->assertSame('', $response['body']['smtpPassword']); // Write only + $this->assertSame('', $response['body']['smtpSecure']); - $this->assertArrayHasKey('teamId', $response); - $this->assertIsString($response['teamId']); - $this->assertEquals($team['body']['$id'], $response['teamId']); + $this->assertCount(2, $response['body']['authMockNumbers']); + $this->assertEquals('+421123456789', $response['body']['authMockNumbers'][0]['phone']); + $this->assertEquals('+420987654321', $response['body']['authMockNumbers'][1]['phone']); + $this->assertEquals('123456', $response['body']['authMockNumbers'][0]['otp']); + $this->assertEquals('654321', $response['body']['authMockNumbers'][1]['otp']); - $this->assertArrayHasKey('logo', $response); - $this->assertIsString($response['logo']); - $this->assertEquals('https://google.com/logo.png', $response['logo']); - - $this->assertArrayHasKey('url', $response); - $this->assertIsString($response['url']); - $this->assertEquals('https://myapp.com/', $response['url']); - - $this->assertArrayHasKey('legalName', $response); - $this->assertIsString($response['legalName']); - $this->assertEquals('Legal company', $response['legalName']); - - $this->assertArrayHasKey('legalCountry', $response); - $this->assertIsString($response['legalCountry']); - $this->assertEquals('Slovakia', $response['legalCountry']); - - $this->assertArrayHasKey('legalState', $response); - $this->assertIsString($response['legalState']); - $this->assertEquals('Custom state', $response['legalState']); - - $this->assertArrayHasKey('legalCity', $response); - $this->assertIsString($response['legalCity']); - $this->assertEquals('Košice', $response['legalCity']); - - $this->assertArrayHasKey('legalAddress', $response); - $this->assertIsString($response['legalAddress']); - $this->assertEquals('Main street 32', $response['legalAddress']); - - $this->assertArrayHasKey('legalTaxId', $response); - $this->assertIsString($response['legalTaxId']); - $this->assertEquals('TAXID_123456', $response['legalTaxId']); - - $this->assertArrayHasKey('authDuration', $response); - $this->assertIsInt($response['authDuration']); - $this->assertEquals(135, $response['authDuration']); - - $this->assertArrayHasKey('authLimit', $response); - $this->assertIsInt($response['authLimit']); - $this->assertEquals(54, $response['authLimit']); - - $this->assertArrayHasKey('authSessionsLimit', $response); - $this->assertIsInt($response['authSessionsLimit']); - $this->assertEquals(7, $response['authLimit']); - - $this->assertArrayHasKey('authPasswordHistory', $response); - $this->assertIsInt($response['authPasswordHistory']); - $this->assertEquals(9, $response['authPasswordHistory']); - - $this->assertArrayHasKey('authPasswordDictionary', $response); - $this->assertIsBool($response['authPasswordDictionary']); - $this->assertTrue($response['authPasswordDictionary']); - - $this->assertArrayHasKey('authPersonalDataCheck', $response); - $this->assertIsBool($response['authPersonalDataCheck']); - $this->assertTrue($response['authPersonalDataCheck']); - - $this->assertArrayHasKey('authDisposableEmails', $response); - $this->assertIsBool($response['authDisposableEmails']); - $this->assertFalse($response['authDisposableEmails']); - - $this->assertArrayHasKey('authCanonicalEmails', $response); - $this->assertIsBool($response['authCanonicalEmails']); - $this->assertFalse($response['authCanonicalEmails']); - - $this->assertArrayHasKey('authFreeEmails', $response); - $this->assertIsBool($response['authFreeEmails']); - $this->assertFalse($response['authFreeEmails']); - - $this->assertArrayHasKey('authMockNumbers', $response); - $this->assertIsArray($response['authMockNumbers']); - $this->assertCount(2, $response['authMockNumbers']); - - $this->assertEquals('+421123456789', $response['authMockNumbers'][0]['number']); - $this->assertEquals('+420987654321', $response['authMockNumbers'][1]['number']); - - $this->assertEquals('123456', $response['authMockNumbers'][0]['otp']); - $this->assertEquals('654321', $response['authMockNumbers'][1]['otp']); - - foreach($response['authMockNumbers'] as $mockNumber) { - $this->assertArrayHasKey('$createdAt', $mockNumber); + foreach ($response['body']['authMockNumbers'] as $mockNumber) { $this->assertIsString($mockNumber['$createdAt']); + $this->assertNotEmpty($mockNumber['$createdAt']); $this->assertNotFalse(\strtotime($mockNumber['$createdAt'])); - - $this->assertArrayHasKey('$updatedAt', $mockNumber); + $this->assertIsString($mockNumber['$updatedAt']); + $this->assertNotEmpty($mockNumber['$updatedAt']); $this->assertNotFalse(\strtotime($mockNumber['$updatedAt'])); - $this->assertArrayHasKey('number', $mockNumber); - $this->assertIsString($mockNumber['number']); - $this->assertNotEmpty($mockNumber['number']); - - $this->assertArrayHasKey('otp', $mockNumber); + $this->assertIsString($mockNumber['phone']); + $this->assertNotEmpty($mockNumber['phone']); + $this->assertIsString($mockNumber['otp']); $this->assertNotEmpty($mockNumber['otp']); } - $this->assertArrayHasKey('authSessionAlerts', $response); - $this->assertIsBool($response['authSessionAlerts']); - $this->assertTrue($response['authSessionAlerts']); - - $this->assertArrayHasKey('authMembershipsUserName', $response); - $this->assertIsBool($response['authMembershipsUserName']); - $this->assertTrue($response['authMembershipsUserName']); - - $this->assertArrayHasKey('authMembershipsUserEmail', $response); - $this->assertIsBool($response['authMembershipsUserEmail']); - $this->assertTrue($response['authMembershipsUserEmail']); - - $this->assertArrayHasKey('authMembershipsMfa', $response); - $this->assertIsBool($response['authMembershipsMfa']); - $this->assertTrue($response['authMembershipsMfa']); - - $this->assertArrayHasKey('authMembershipsUserId', $response); - $this->assertIsBool($project['authMembershipsUserId']); - $this->assertTrue($response['authMembershipsUserId']); - - $this->assertArrayHasKey('authMembershipsUserPhone', $response); - $this->assertIsBool($response['authMembershipsUserPhone']); - $this->assertTrue($response['authMembershipsUserPhone']); - - $this->assertArrayHasKey('authInvalidateSessions', $response); - $this->assertIsBool($response['authInvalidateSessions']); - $this->assertTrue($response['authInvalidateSessions']); - - $this->assertArrayHasKey('smtpEnabled', $response); - $this->assertIsBool($response['smtpEnabled']); - $this->assertTrue($response['smtpEnabled']); - - $this->assertArrayHasKey('smtpSenderName', $response); - $this->assertIsString($response['smtpSenderName']); - $this->assertSame('Custom sender', $response['smtpSenderName']); - - $this->assertArrayHasKey('smtpSenderEmail', $response); - $this->assertIsString($response['smtpSenderEmail']); - $this->assertSame('email@custom.com', $response['smtpSenderEmail']); - - $this->assertArrayHasKey('smtpReplyToName', $response); - $this->assertIsString($response['smtpReplyToName']); - $this->assertSame('Reply sender', $response['smtpReplyToName']); - - $this->assertArrayHasKey('smtpReplyToEmail', $response); - $this->assertIsString($response['smtpReplyToEmail']); - $this->assertSame('replyto@custom.com', $response['smtpReplyToEmail']); - - $this->assertArrayHasKey('smtpHost', $response); - $this->assertIsString($response['smtpHost']); - $this->assertSame('maildev', $response['smtpHost']); - - $this->assertArrayHasKey('smtpPort', $response); - $this->assertIsInt($response['smtpPort']); - $this->assertSame(1025, $response['smtpPort']); - - $this->assertArrayHasKey('smtpUsername', $response); - $this->assertIsString($response['smtpUsername']); - $this->assertSame('', $response['smtpUsername']); - - $this->assertArrayHasKey('smtpPassword', $response); - $this->assertIsString($response['smtpPassword']); - $this->assertSame('', $response['smtpPassword']); - - $this->assertArrayHasKey('smtpSecure', $response); - $this->assertIsString($response['smtpSecure']); - $this->assertSame('', $response['smtpSecure']); - /* $this->assertArrayHasKey('oAuthProviders', $project); $this->assertIsArray($project['oAuthProviders']); @@ -1130,12 +1026,7 @@ class ProjectsConsoleClientTest extends Scope $this->assertIsArray($project['devKeys']); */ - /* - - */ - - - /* + /* $this->assertArrayHasKey('pingCount', $project); $this->assertIsInt($project['pingCount']); @@ -1147,64 +1038,68 @@ class ProjectsConsoleClientTest extends Scope $this->assertArrayHasKey('status', $project); $this->assertIsString($project['status']); - */ + */ - /* + /* $auth = require(__DIR__ . '/../../../../app/config/auth.php'); foreach ($auth as $method) { - $key = 'auth' . ucfirst($method['key'] ?? ''); - $this->assertArrayHasKey($key, $project, 'Missing auth field: ' . $key); - $this->assertIsBool($project[$key], 'Auth field should be boolean: ' . $key); + $key = 'auth' . ucfirst($method['key'] ?? ''); + $this->assertArrayHasKey($key, $project, 'Missing auth field: ' . $key); + $this->assertIsBool($project[$key], 'Auth field should be boolean: ' . $key); } $services = require(__DIR__ . '/../../../../app/config/services.php'); foreach ($services as $service) { - if (!($service['optional'] ?? false)) { - continue; - } - $key = 'serviceStatusFor' . ucfirst($service['key'] ?? ''); - $this->assertArrayHasKey($key, $project, 'Missing service field: ' . $key); - $this->assertIsBool($project[$key], 'Service field should be boolean: ' . $key); + if (!($service['optional'] ?? false)) { + continue; + } + $key = 'serviceStatusFor' . ucfirst($service['key'] ?? ''); + $this->assertArrayHasKey($key, $project, 'Missing service field: ' . $key); + $this->assertIsBool($project[$key], 'Service field should be boolean: ' . $key); } // Dynamic protocol status fields $protocols = require(__DIR__ . '/../../../../app/config/protocols.php'); foreach ($protocols as $protocol) { - $key = 'protocolStatusFor' . ucfirst($protocol['key'] ?? ''); - $this->assertArrayHasKey($key, $project, 'Missing protocol field: ' . $key); - $this->assertIsBool($project[$key], 'Protocol field should be boolean: ' . $key); + $key = 'protocolStatusFor' . ucfirst($protocol['key'] ?? ''); + $this->assertArrayHasKey($key, $project, 'Missing protocol field: ' . $key); + $this->assertIsBool($project[$key], 'Protocol field should be boolean: ' . $key); } */ // Ensure policies can be falsy - $response = $this->client->call(Client::METHOD_PATCH, '/project/' . $id . '/policies/password-dictionary', array_merge([ + $response = $this->client->call(Client::METHOD_PATCH, '/project/policies/password-dictionary', array_merge([ 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-project' => $id, + 'x-appwrite-mode' => 'admin', ], $this->getHeaders()), [ 'enabled' => false ]); $this->assertEquals(200, $response['headers']['status-code']); - $response = $this->client->call(Client::METHOD_PATCH, '/project/' . $id . '/policies/password-personal-data', array_merge([ + $response = $this->client->call(Client::METHOD_PATCH, '/project/policies/password-personal-data', array_merge([ 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getProject()['$id'], - ], $this->getHeaders()), [ - 'enabled' => false - ]); - $this->assertEquals(200, $response['headers']['status-code']); - - $response = $this->client->call(Client::METHOD_PATCH, '/project/' . $id . '/policies/session-alert', array_merge([ - 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-project' => $id, + 'x-appwrite-mode' => 'admin', ], $this->getHeaders()), [ 'enabled' => false ]); $this->assertEquals(200, $response['headers']['status-code']); - $response = $this->client->call(Client::METHOD_PATCH, '/project/' . $id . '/policies/membership-privacy', array_merge([ + $response = $this->client->call(Client::METHOD_PATCH, '/project/policies/session-alert', array_merge([ 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-project' => $id, + 'x-appwrite-mode' => 'admin', + ], $this->getHeaders()), [ + 'enabled' => false + ]); + $this->assertEquals(200, $response['headers']['status-code']); + + $response = $this->client->call(Client::METHOD_PATCH, '/project/policies/membership-privacy', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $id, + 'x-appwrite-mode' => 'admin', ], $this->getHeaders()), [ 'userId' => false, 'userEmail' => false, @@ -1214,9 +1109,10 @@ class ProjectsConsoleClientTest extends Scope ]); $this->assertEquals(200, $response['headers']['status-code']); - $response = $this->client->call(Client::METHOD_PATCH, '/project/' . $id . '/policies/session-invalidation', array_merge([ + $response = $this->client->call(Client::METHOD_PATCH, '/project/policies/session-invalidation', array_merge([ 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-project' => $id, + 'x-appwrite-mode' => 'admin', ], $this->getHeaders()), [ 'enabled' => false ]); @@ -1228,7 +1124,8 @@ class ProjectsConsoleClientTest extends Scope '/project/smtp', array_merge([ 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-project' => $id, + 'x-appwrite-mode' => 'admin', ], $this->getHeaders()), [ 'enabled' => false, @@ -1239,71 +1136,27 @@ class ProjectsConsoleClientTest extends Scope 'secure' => 'ssl', ], ); - + $response = $this->client->call(Client::METHOD_GET, '/projects/' . $id, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); - - $this->assertArrayHasKey('authPasswordDictionary', $response); - $this->assertIsBool($response['authPasswordDictionary']); - $this->assertFalse($response['authPasswordDictionary']); - $this->assertArrayHasKey('authPersonalDataCheck', $response); - $this->assertIsBool($response['authPersonalDataCheck']); - $this->assertFalse($response['authPersonalDataCheck']); - - $this->assertArrayHasKey('authSessionAlerts', $response); - $this->assertIsBool($response['authSessionAlerts']); - $this->assertFalse($response['authSessionAlerts']); - - $this->assertArrayHasKey('authMembershipsUserName', $response); - $this->assertIsBool($response['authMembershipsUserName']); - $this->assertFalse($response['authMembershipsUserName']); - - $this->assertArrayHasKey('authMembershipsUserEmail', $response); - $this->assertIsBool($response['authMembershipsUserEmail']); - $this->assertFalse($response['authMembershipsUserEmail']); - - $this->assertArrayHasKey('authMembershipsMfa', $response); - $this->assertIsBool($response['authMembershipsMfa']); - $this->assertFalse($response['authMembershipsMfa']); - - $this->assertArrayHasKey('authMembershipsUserId', $response); - $this->assertIsBool($project['authMembershipsUserId']); - $this->assertFalse($response['authMembershipsUserId']); - - $this->assertArrayHasKey('authMembershipsUserPhone', $response); - $this->assertIsBool($response['authMembershipsUserPhone']); - $this->assertFalse($response['authMembershipsUserPhone']); - - $this->assertArrayHasKey('authInvalidateSessions', $response); - $this->assertIsBool($response['authInvalidateSessions']); - $this->assertFalse($response['authInvalidateSessions']); - - $this->assertArrayHasKey('smtpEnabled', $response); - $this->assertIsBool($response['smtpEnabled']); - $this->assertFalse($response['smtpEnabled']); - - $this->assertArrayHasKey('smtpHost', $response); - $this->assertIsString($response['smtpHost']); - $this->assertSame('customhost.com', $response['smtpHost']); - - $this->assertArrayHasKey('smtpPort', $response); - $this->assertIsInt($response['smtpPort']); - $this->assertSame(4444, $response['smtpPort']); - - $this->assertArrayHasKey('smtpUsername', $response); - $this->assertIsString($response['smtpUsername']); - $this->assertSame('myuser', $response['smtpUsername']); - - $this->assertArrayHasKey('smtpPassword', $response); - $this->assertIsString($response['smtpPassword']); - $this->assertSame('', $response['smtpPassword']); - - $this->assertArrayHasKey('smtpSecure', $response); - $this->assertIsString($response['smtpSecure']); - $this->assertSame('ssl', $response['smtpSecure']); + $this->assertFalse($response['body']['authPasswordDictionary']); + $this->assertFalse($response['body']['authPersonalDataCheck']); + $this->assertFalse($response['body']['authSessionAlerts']); + $this->assertFalse($response['body']['authMembershipsUserName']); + $this->assertFalse($response['body']['authMembershipsUserEmail']); + $this->assertFalse($response['body']['authMembershipsMfa']); + $this->assertFalse($response['body']['authMembershipsUserId']); + $this->assertFalse($response['body']['authMembershipsUserPhone']); + $this->assertFalse($response['body']['authInvalidateSessions']); + $this->assertFalse($response['body']['smtpEnabled']); + $this->assertSame('customhost.com', $response['body']['smtpHost']); + $this->assertSame(4444, $response['body']['smtpPort']); + $this->assertSame('myuser', $response['body']['smtpUsername']); + $this->assertSame('', $response['body']['smtpPassword']); // Write only + $this->assertSame('ssl', $response['body']['smtpSecure']); /** * Test for FAILURE From 38575d7620c62dae3c54c80f4331c0c5b58112f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Ba=C4=8Do?= Date: Thu, 7 May 2026 11:06:47 +0200 Subject: [PATCH 4/8] Improve get project tests --- .../Projects/ProjectsConsoleClientTest.php | 60 ++++++++++++------- 1 file changed, 39 insertions(+), 21 deletions(-) diff --git a/tests/e2e/Services/Projects/ProjectsConsoleClientTest.php b/tests/e2e/Services/Projects/ProjectsConsoleClientTest.php index a8bfaa0f7f..4ab57a3012 100644 --- a/tests/e2e/Services/Projects/ProjectsConsoleClientTest.php +++ b/tests/e2e/Services/Projects/ProjectsConsoleClientTest.php @@ -1040,32 +1040,50 @@ class ProjectsConsoleClientTest extends Scope $this->assertIsString($project['status']); */ - /* - $auth = require(__DIR__ . '/../../../../app/config/auth.php'); - foreach ($auth as $method) { - $key = 'auth' . ucfirst($method['key'] ?? ''); - $this->assertArrayHasKey($key, $project, 'Missing auth field: ' . $key); - $this->assertIsBool($project[$key], 'Auth field should be boolean: ' . $key); + $authsKeys = [ + 'authEmailPassword', + 'authUsersAuthMagicURL', + 'authEmailOtp', + 'authAnonymous', + 'authInvites', + 'authJWT', + 'authPhone', + ]; + foreach ($authsKeys as $authsKey) { + $this->assertTrue($response['body'][$authsKey], 'Auth method should be enabled: ' . $authsKey); } - $services = require(__DIR__ . '/../../../../app/config/services.php'); - foreach ($services as $service) { - if (!($service['optional'] ?? false)) { - continue; - } - $key = 'serviceStatusFor' . ucfirst($service['key'] ?? ''); - $this->assertArrayHasKey($key, $project, 'Missing service field: ' . $key); - $this->assertIsBool($project[$key], 'Service field should be boolean: ' . $key); + $serviceKeys = [ + 'serviceStatusForAccount', + 'serviceStatusForAvatars', + 'serviceStatusForDatabases', + 'serviceStatusForTablesdb', + 'serviceStatusForLocale', + 'serviceStatusForHealth', + 'serviceStatusForProject', + 'serviceStatusForStorage', + 'serviceStatusForTeams', + 'serviceStatusForUsers', + 'serviceStatusForVcs', + 'serviceStatusForSites', + 'serviceStatusForFunctions', + 'serviceStatusForProxy', + 'serviceStatusForGraphql', + 'serviceStatusForMigrations', + 'serviceStatusForMessaging', + ]; + foreach ($serviceKeys as $serviceKey) { + $this->assertTrue($response['body'][$serviceKey], 'Service should be enabled: ' . $serviceKey); } - // Dynamic protocol status fields - $protocols = require(__DIR__ . '/../../../../app/config/protocols.php'); - foreach ($protocols as $protocol) { - $key = 'protocolStatusFor' . ucfirst($protocol['key'] ?? ''); - $this->assertArrayHasKey($key, $project, 'Missing protocol field: ' . $key); - $this->assertIsBool($project[$key], 'Protocol field should be boolean: ' . $key); + $protocolKeys = [ + 'protocolStatusForRest', + 'protocolStatusForGraphql', + 'protocolStatusForWebsocket', + ]; + foreach ($protocolKeys as $protocolKey) { + $this->assertTrue($response['body'][$protocolKey], 'Protocol should be enabled: ' . $protocolKey); } - */ // Ensure policies can be falsy From 379a388f61d33751618b2e7a0a4196b9f6f4a618 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Ba=C4=8Do?= Date: Thu, 7 May 2026 11:12:05 +0200 Subject: [PATCH 5/8] auth security get project tests --- .../Projects/ProjectsConsoleClientTest.php | 128 +++++++++++++++++- 1 file changed, 124 insertions(+), 4 deletions(-) diff --git a/tests/e2e/Services/Projects/ProjectsConsoleClientTest.php b/tests/e2e/Services/Projects/ProjectsConsoleClientTest.php index 4ab57a3012..324d7d2bdb 100644 --- a/tests/e2e/Services/Projects/ProjectsConsoleClientTest.php +++ b/tests/e2e/Services/Projects/ProjectsConsoleClientTest.php @@ -1050,7 +1050,7 @@ class ProjectsConsoleClientTest extends Scope 'authPhone', ]; foreach ($authsKeys as $authsKey) { - $this->assertTrue($response['body'][$authsKey], 'Auth method should be enabled: ' . $authsKey); + $this->assertTrue($response['body'][$authsKey], 'Auth method should be enabled: ' . $authsKey); } $serviceKeys = [ @@ -1073,7 +1073,7 @@ class ProjectsConsoleClientTest extends Scope 'serviceStatusForMessaging', ]; foreach ($serviceKeys as $serviceKey) { - $this->assertTrue($response['body'][$serviceKey], 'Service should be enabled: ' . $serviceKey); + $this->assertTrue($response['body'][$serviceKey], 'Service should be enabled: ' . $serviceKey); } $protocolKeys = [ @@ -1082,10 +1082,10 @@ class ProjectsConsoleClientTest extends Scope 'protocolStatusForWebsocket', ]; foreach ($protocolKeys as $protocolKey) { - $this->assertTrue($response['body'][$protocolKey], 'Protocol should be enabled: ' . $protocolKey); + $this->assertTrue($response['body'][$protocolKey], 'Protocol should be enabled: ' . $protocolKey); } - // Ensure policies can be falsy + // Ensure booleans can be falsy $response = $this->client->call(Client::METHOD_PATCH, '/project/policies/password-dictionary', array_merge([ 'content-type' => 'application/json', @@ -1136,6 +1136,78 @@ class ProjectsConsoleClientTest extends Scope ]); $this->assertEquals(200, $response['headers']['status-code']); + // Toggle auth methods, services, protocols + + $authMethods = ['email-password', 'magic-url', 'email-otp', 'anonymous', 'invites', 'jwt', 'phone']; + foreach ($authMethods as $authMethod) { + $response = $this->client->call( + Client::METHOD_PATCH, + '/project/auth-methods/' . $authMethod, + array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $id, + 'x-appwrite-mode' => 'admin', + ], $this->getHeaders()), + [ + 'enabled' => false, + ], + ); + $this->assertEquals(200, $response['headers']['status-code']); + } + + $protocols = ['rest', 'graphql', 'websocket']; + foreach ($protocols as $protocol) { + $response = $this->client->call( + Client::METHOD_PATCH, + '/project/protocols/' . $protocol, + array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $id, + 'x-appwrite-mode' => 'admin', + ], $this->getHeaders()), + [ + 'enabled' => false, + ], + ); + $this->assertEquals(200, $response['headers']['status-code']); + } + + $services = [ + 'account', + 'avatars', + 'databases', + 'tablesdb', + 'locale', + 'health', + 'project', + 'storage', + 'teams', + 'users', + 'vcs', + 'sites', + 'functions', + 'proxy', + 'graphql', + 'migrations', + 'messaging', + ]; + + foreach ($services as $service) { + $response = $this->client->call( + Client::METHOD_PATCH, + '/project/services/' . $service, + array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $id, + 'x-appwrite-mode' => 'admin', + ], $this->getHeaders()), + [ + 'enabled' => false, + ], + ); + $this->assertEquals(200, $response['headers']['status-code']); + } + // Configure SMTP $response = $this->client->call( Client::METHOD_PATCH, @@ -1154,12 +1226,15 @@ class ProjectsConsoleClientTest extends Scope 'secure' => 'ssl', ], ); + $this->assertEquals(200, $response['headers']['status-code']); $response = $this->client->call(Client::METHOD_GET, '/projects/' . $id, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertFalse($response['body']['authPasswordDictionary']); $this->assertFalse($response['body']['authPersonalDataCheck']); $this->assertFalse($response['body']['authSessionAlerts']); @@ -1176,6 +1251,51 @@ class ProjectsConsoleClientTest extends Scope $this->assertSame('', $response['body']['smtpPassword']); // Write only $this->assertSame('ssl', $response['body']['smtpSecure']); + $authsKeys = [ + 'authEmailPassword', + 'authUsersAuthMagicURL', + 'authEmailOtp', + 'authAnonymous', + 'authInvites', + 'authJWT', + 'authPhone', + ]; + foreach ($authsKeys as $authsKey) { + $this->assertFalse($response['body'][$authsKey], 'Auth method should be enabled: ' . $authsKey); + } + + $serviceKeys = [ + 'serviceStatusForAccount', + 'serviceStatusForAvatars', + 'serviceStatusForDatabases', + 'serviceStatusForTablesdb', + 'serviceStatusForLocale', + 'serviceStatusForHealth', + 'serviceStatusForProject', + 'serviceStatusForStorage', + 'serviceStatusForTeams', + 'serviceStatusForUsers', + 'serviceStatusForVcs', + 'serviceStatusForSites', + 'serviceStatusForFunctions', + 'serviceStatusForProxy', + 'serviceStatusForGraphql', + 'serviceStatusForMigrations', + 'serviceStatusForMessaging', + ]; + foreach ($serviceKeys as $serviceKey) { + $this->assertFalse($response['body'][$serviceKey], 'Service should be enabled: ' . $serviceKey); + } + + $protocolKeys = [ + 'protocolStatusForRest', + 'protocolStatusForGraphql', + 'protocolStatusForWebsocket', + ]; + foreach ($protocolKeys as $protocolKey) { + $this->assertFalse($response['body'][$protocolKey], 'Protocol should be enabled: ' . $protocolKey); + } + /** * Test for FAILURE */ From c4a941015ff453ad0090154dad96ad6b39ee6264 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Ba=C4=8Do?= Date: Thu, 7 May 2026 11:26:55 +0200 Subject: [PATCH 6/8] Continue adding project get tests --- .../Projects/ProjectsConsoleClientTest.php | 97 +++++++++++++++---- 1 file changed, 80 insertions(+), 17 deletions(-) diff --git a/tests/e2e/Services/Projects/ProjectsConsoleClientTest.php b/tests/e2e/Services/Projects/ProjectsConsoleClientTest.php index 324d7d2bdb..96416cbd5a 100644 --- a/tests/e2e/Services/Projects/ProjectsConsoleClientTest.php +++ b/tests/e2e/Services/Projects/ProjectsConsoleClientTest.php @@ -15,6 +15,7 @@ use Utopia\Database\Helpers\ID; use Utopia\Database\Helpers\Permission; use Utopia\Database\Helpers\Role; use Utopia\Database\Query; +use Utopia\Database\Validator\Datetime as ValidatorDatetime; use Utopia\System\System; class ProjectsConsoleClientTest extends Scope @@ -802,6 +803,19 @@ class ProjectsConsoleClientTest extends Scope $this->assertEquals(201, $response['headers']['status-code']); $id = $response['body']['$id']; + // Increase ping 3x + for ($i = 0; $i < 3; $i++) { + $response = $this->client->call( + Client::METHOD_GET, + '/ping', + array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $id, + ], $this->getHeaders()), + ); + $this->assertEquals(200, $response['headers']['status-code']); + } + // Configure SMTP $response = $this->client->call( Client::METHOD_PATCH, @@ -834,6 +848,33 @@ class ProjectsConsoleClientTest extends Scope ]); $this->assertEquals(201, $response['headers']['status-code']); + // Add labels + $response = $this->client->call(Client::METHOD_PUT, '/project/labels', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $id, + 'x-appwrite-mode' => 'admin', + ], $this->getHeaders()), [ + 'labels' => ['custom1', 'custom2'] + ]); + $this->assertEquals(200, $response['headers']['status-code']); + + // Create dev keys + $response = $this->client->call(Client::METHOD_POST, '/projects/' . $id . '/dev-keys', array_merge([ + 'content-type' => 'application/json', + ], $this->getHeaders()), [ + 'name' => 'Custom key 1', + 'expire' => '2026-05-07 09:23:30.713', + ]); + $this->assertEquals(201, $response['headers']['status-code']); + + $response = $this->client->call(Client::METHOD_POST, '/projects/' . $id . '/dev-keys', array_merge([ + 'content-type' => 'application/json', + ], $this->getHeaders()), [ + 'name' => 'Custom key 2', + 'expire' => '2026-05-07 11:23:30.713' + ]); + $this->assertEquals(201, $response['headers']['status-code']); + $response = $this->client->call(Client::METHOD_POST, '/project/mock-phones', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $id, @@ -952,6 +993,7 @@ class ProjectsConsoleClientTest extends Scope $this->assertEquals('My description', $response['body']['description']); $this->assertEquals($team['body']['$id'], $response['body']['teamId']); + $this->assertEquals('active', $response['body']['status']); $this->assertEquals('https://google.com/logo.png', $response['body']['logo']); $this->assertEquals('https://myapp.com/', $response['body']['url']); $this->assertEquals('Legal company', $response['body']['legalName']); @@ -986,7 +1028,44 @@ class ProjectsConsoleClientTest extends Scope $this->assertSame('', $response['body']['smtpUsername']); $this->assertSame('', $response['body']['smtpPassword']); // Write only $this->assertSame('', $response['body']['smtpSecure']); + $this->assertSame(3, $response['body']['pingCount']); + $this->assertIsString($response['body']['pingedAt']); + $this->assertNotEmpty($response['body']['pingedAt']); + $this->assertNotFalse(\strtotime($response['body']['pingedAt'])); + + $this->assertCount(2, $response['body']['labels']); + $this->assertEquals('custom1', $response['body']['labels'][0]); + $this->assertEquals('custom2', $response['body']['labels'][1]); + + $this->assertCount(2, $response['body']['devKeys']); + $this->assertEquals('Custom key 1', $response['body']['devKeys'][0]['name']); + $this->assertEquals('Custom key 2', $response['body']['devKeys'][1]['name']); + $this->assertEquals('2026-05-07T09:23:30.713+00:00', $response['body']['devKeys'][0]['expire']); + $this->assertEquals('2026-05-07T11:23:30.713+00:00', $response['body']['devKeys'][1]['expire']); + + foreach ($response['body']['devKeys'] as $devKey) { + $this->assertIsString($devKey['$id']); + $this->assertNotEmpty($devKey['$id']); + + $this->assertIsString($devKey['secret']); + $this->assertNotEmpty($devKey['secret']); + + $this->assertIsString($devKey['accessedAt']); + $this->assertEmpty($devKey['accessedAt']); + + $this->assertIsString($devKey['$createdAt']); + $this->assertNotEmpty($devKey['$createdAt']); + $this->assertNotFalse(\strtotime($devKey['$createdAt'])); + + $this->assertIsString($devKey['$updatedAt']); + $this->assertNotEmpty($devKey['$updatedAt']); + $this->assertNotFalse(\strtotime($devKey['$updatedAt'])); + + $this->assertIsArray($devKey['sdks']); + $this->assertCount(0, $devKey['sdks']); + } + $this->assertCount(2, $response['body']['authMockNumbers']); $this->assertEquals('+421123456789', $response['body']['authMockNumbers'][0]['phone']); $this->assertEquals('+420987654321', $response['body']['authMockNumbers'][1]['phone']); @@ -1010,6 +1089,7 @@ class ProjectsConsoleClientTest extends Scope } /* + TODO: $this->assertArrayHasKey('oAuthProviders', $project); $this->assertIsArray($project['oAuthProviders']); @@ -1021,25 +1101,8 @@ class ProjectsConsoleClientTest extends Scope $this->assertArrayHasKey('keys', $project); $this->assertIsArray($project['keys']); - - $this->assertArrayHasKey('devKeys', $project); - $this->assertIsArray($project['devKeys']); */ - /* - $this->assertArrayHasKey('pingCount', $project); - $this->assertIsInt($project['pingCount']); - - $this->assertArrayHasKey('pingedAt', $project); - $this->assertIsString($project['pingedAt']); - - $this->assertArrayHasKey('labels', $project); - $this->assertIsArray($project['labels']); - - $this->assertArrayHasKey('status', $project); - $this->assertIsString($project['status']); - */ - $authsKeys = [ 'authEmailPassword', 'authUsersAuthMagicURL', From 0b881ec58ae29147bbc44a2df5742f0067b9bc32 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Ba=C4=8Do?= Date: Thu, 7 May 2026 11:45:25 +0200 Subject: [PATCH 7/8] Finish test improvements for get project --- .../Projects/ProjectsConsoleClientTest.php | 149 ++++++++++++++++-- 1 file changed, 133 insertions(+), 16 deletions(-) diff --git a/tests/e2e/Services/Projects/ProjectsConsoleClientTest.php b/tests/e2e/Services/Projects/ProjectsConsoleClientTest.php index 96416cbd5a..95859f8dea 100644 --- a/tests/e2e/Services/Projects/ProjectsConsoleClientTest.php +++ b/tests/e2e/Services/Projects/ProjectsConsoleClientTest.php @@ -15,7 +15,6 @@ use Utopia\Database\Helpers\ID; use Utopia\Database\Helpers\Permission; use Utopia\Database\Helpers\Role; use Utopia\Database\Query; -use Utopia\Database\Validator\Datetime as ValidatorDatetime; use Utopia\System\System; class ProjectsConsoleClientTest extends Scope @@ -866,7 +865,7 @@ class ProjectsConsoleClientTest extends Scope 'expire' => '2026-05-07 09:23:30.713', ]); $this->assertEquals(201, $response['headers']['status-code']); - + $response = $this->client->call(Client::METHOD_POST, '/projects/' . $id . '/dev-keys', array_merge([ 'content-type' => 'application/json', ], $this->getHeaders()), [ @@ -971,6 +970,57 @@ class ProjectsConsoleClientTest extends Scope ]); $this->assertEquals(200, $response['headers']['status-code']); + // Create webhook + $webhook = $this->client->call(Client::METHOD_POST, '/webhooks', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $id, + 'x-appwrite-mode' => 'admin', + ], $this->getHeaders()), [ + 'webhookId' => 'unique()', + 'name' => 'Webhook Test', + 'events' => ['users.*.create', 'users.*.update.email'], + 'url' => 'https://appwrite.io', + 'tls' => true, + 'authUsername' => 'username', + 'authPassword' => 'password', + ]); + $this->assertEquals(201, $webhook['headers']['status-code']); + + // Create API key + $key = $this->client->call(Client::METHOD_POST, '/projects/' . $id . '/keys', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'keyId' => ID::unique(), + 'name' => 'Key Test', + 'scopes' => ['teams.read', 'teams.write'], + ]); + $this->assertEquals(201, $key['headers']['status-code']); + + // Create platform + $platform = $this->client->call(Client::METHOD_POST, '/projects/' . $id . '/platforms', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'platformId' => ID::unique(), + 'type' => 'web', + 'name' => 'Web App', + 'hostname' => 'localhost', + ]); + $this->assertEquals(201, $platform['headers']['status-code']); + + // Configure OAuth provider + $oauth = $this->client->call(Client::METHOD_PATCH, '/project/oauth2/github', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $id, + 'x-appwrite-mode' => 'admin', + ], $this->getHeaders()), [ + 'clientId' => 'github-client-id', + 'clientSecret' => 'github-client-secret', + 'enabled' => false, + ]); + $this->assertEquals(200, $oauth['headers']['status-code']); + /** * Test for SUCCESS */ @@ -1053,7 +1103,7 @@ class ProjectsConsoleClientTest extends Scope $this->assertIsString($devKey['accessedAt']); $this->assertEmpty($devKey['accessedAt']); - + $this->assertIsString($devKey['$createdAt']); $this->assertNotEmpty($devKey['$createdAt']); $this->assertNotFalse(\strtotime($devKey['$createdAt'])); @@ -1061,11 +1111,11 @@ class ProjectsConsoleClientTest extends Scope $this->assertIsString($devKey['$updatedAt']); $this->assertNotEmpty($devKey['$updatedAt']); $this->assertNotFalse(\strtotime($devKey['$updatedAt'])); - + $this->assertIsArray($devKey['sdks']); $this->assertCount(0, $devKey['sdks']); } - + $this->assertCount(2, $response['body']['authMockNumbers']); $this->assertEquals('+421123456789', $response['body']['authMockNumbers'][0]['phone']); $this->assertEquals('+420987654321', $response['body']['authMockNumbers'][1]['phone']); @@ -1088,20 +1138,87 @@ class ProjectsConsoleClientTest extends Scope $this->assertNotEmpty($mockNumber['otp']); } - /* - TODO: - $this->assertArrayHasKey('oAuthProviders', $project); - $this->assertIsArray($project['oAuthProviders']); + $this->assertIsArray($response['body']['oAuthProviders']); + $this->assertGreaterThan(0, count($response['body']['oAuthProviders'])); - $this->assertArrayHasKey('platforms', $project); - $this->assertIsArray($project['platforms']); + $githubProvider = null; + foreach ($response['body']['oAuthProviders'] as $provider) { + $this->assertIsString($provider['key']); + $this->assertNotEmpty($provider['key']); - $this->assertArrayHasKey('webhooks', $project); - $this->assertIsArray($project['webhooks']); + $this->assertIsString($provider['name']); + $this->assertIsString($provider['appId']); + $this->assertIsString($provider['secret']); + $this->assertIsBool($provider['enabled']); - $this->assertArrayHasKey('keys', $project); - $this->assertIsArray($project['keys']); - */ + if ($provider['key'] === 'github') { + $githubProvider = $provider; + } + } + + $this->assertNotNull($githubProvider, 'GitHub provider not found'); + $this->assertEquals('github-client-id', $githubProvider['appId']); + $this->assertEquals('', $githubProvider['secret']); // Write only + $this->assertEquals(false, $githubProvider['enabled']); + + $this->assertIsArray($response['body']['platforms']); + $this->assertCount(1, $response['body']['platforms']); + $this->assertIsString($response['body']['platforms'][0]['$id']); + $this->assertNotEmpty($response['body']['platforms'][0]['$id']); + $this->assertEquals('Web App', $response['body']['platforms'][0]['name']); + $this->assertEquals('web', $response['body']['platforms'][0]['type']); + $this->assertEquals('localhost', $response['body']['platforms'][0]['hostname']); + + $this->assertIsString($response['body']['platforms'][0]['$createdAt']); + $this->assertNotEmpty($response['body']['platforms'][0]['$createdAt']); + $this->assertNotFalse(\strtotime($response['body']['platforms'][0]['$createdAt'])); + + $this->assertIsString($response['body']['platforms'][0]['$updatedAt']); + $this->assertNotEmpty($response['body']['platforms'][0]['$updatedAt']); + $this->assertNotFalse(\strtotime($response['body']['platforms'][0]['$updatedAt'])); + + $this->assertArrayHasKey('webhooks', $response['body']); + $this->assertIsArray($response['body']['webhooks']); + $this->assertCount(1, $response['body']['webhooks']); + $this->assertIsString($response['body']['webhooks'][0]['$id']); + $this->assertNotEmpty($response['body']['webhooks'][0]['$id']); + $this->assertEquals('Webhook Test', $response['body']['webhooks'][0]['name']); + $this->assertEquals('https://appwrite.io', $response['body']['webhooks'][0]['url']); + $this->assertContains('users.*.create', $response['body']['webhooks'][0]['events']); + $this->assertContains('users.*.update.email', $response['body']['webhooks'][0]['events']); + $this->assertCount(2, $response['body']['webhooks'][0]['events']); + $this->assertTrue($response['body']['webhooks'][0]['tls']); + $this->assertEquals('username', $response['body']['webhooks'][0]['authUsername']); + $this->assertEquals('password', $response['body']['webhooks'][0]['authPassword']); + $this->assertTrue($response['body']['webhooks'][0]['enabled']); + $this->assertIsString($response['body']['webhooks'][0]['secret']); + $this->assertNotEmpty($response['body']['webhooks'][0]['secret']); + $this->assertIsString($response['body']['webhooks'][0]['$createdAt']); + $this->assertNotEmpty($response['body']['webhooks'][0]['$createdAt']); + $this->assertNotFalse(\strtotime($response['body']['webhooks'][0]['$createdAt'])); + $this->assertIsString($response['body']['webhooks'][0]['$updatedAt']); + $this->assertNotEmpty($response['body']['webhooks'][0]['$updatedAt']); + $this->assertNotFalse(\strtotime($response['body']['webhooks'][0]['$updatedAt'])); + + $this->assertArrayHasKey('keys', $response['body']); + $this->assertIsArray($response['body']['keys']); + $this->assertCount(1, $response['body']['keys']); + $this->assertIsString($response['body']['keys'][0]['$id']); + $this->assertNotEmpty($response['body']['keys'][0]['$id']); + $this->assertEquals('Key Test', $response['body']['keys'][0]['name']); + $this->assertContains('teams.read', $response['body']['keys'][0]['scopes']); + $this->assertContains('teams.write', $response['body']['keys'][0]['scopes']); + $this->assertCount(2, $response['body']['keys'][0]['scopes']); + $this->assertNotEmpty($response['body']['keys'][0]['secret']); + $this->assertEmpty($response['body']['keys'][0]['accessedAt']); + $this->assertIsArray($response['body']['keys'][0]['sdks']); + $this->assertCount(0, $response['body']['keys'][0]['sdks']); + $this->assertIsString($response['body']['keys'][0]['$createdAt']); + $this->assertNotEmpty($response['body']['keys'][0]['$createdAt']); + $this->assertNotFalse(\strtotime($response['body']['keys'][0]['$createdAt'])); + $this->assertIsString($response['body']['keys'][0]['$updatedAt']); + $this->assertNotEmpty($response['body']['keys'][0]['$updatedAt']); + $this->assertNotFalse(\strtotime($response['body']['keys'][0]['$updatedAt'])); $authsKeys = [ 'authEmailPassword', From a1e51d27eb0b1c4f6ed96c6968d6927e0cf0ed49 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Ba=C4=8Do?= Date: Thu, 7 May 2026 11:57:14 +0200 Subject: [PATCH 8/8] PR review fixes --- phpunit.xml | 2 +- .../Projects/ProjectsConsoleClientTest.php | 14 +++++++------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/phpunit.xml b/phpunit.xml index b566e232cd..9748c5a5c8 100644 --- a/phpunit.xml +++ b/phpunit.xml @@ -5,7 +5,7 @@ bootstrap="app/init.php" colors="true" processIsolation="false" - stopOnFailure="true" + stopOnFailure="false" stopOnError="false" cacheDirectory=".phpunit.cache" > diff --git a/tests/e2e/Services/Projects/ProjectsConsoleClientTest.php b/tests/e2e/Services/Projects/ProjectsConsoleClientTest.php index 95859f8dea..8b0c1af57f 100644 --- a/tests/e2e/Services/Projects/ProjectsConsoleClientTest.php +++ b/tests/e2e/Services/Projects/ProjectsConsoleClientTest.php @@ -862,7 +862,7 @@ class ProjectsConsoleClientTest extends Scope 'content-type' => 'application/json', ], $this->getHeaders()), [ 'name' => 'Custom key 1', - 'expire' => '2026-05-07 09:23:30.713', + 'expire' => '2099-05-07 09:23:30.713', ]); $this->assertEquals(201, $response['headers']['status-code']); @@ -870,7 +870,7 @@ class ProjectsConsoleClientTest extends Scope 'content-type' => 'application/json', ], $this->getHeaders()), [ 'name' => 'Custom key 2', - 'expire' => '2026-05-07 11:23:30.713' + 'expire' => '2099-05-07 11:23:30.713' ]); $this->assertEquals(201, $response['headers']['status-code']); @@ -1091,8 +1091,8 @@ class ProjectsConsoleClientTest extends Scope $this->assertCount(2, $response['body']['devKeys']); $this->assertEquals('Custom key 1', $response['body']['devKeys'][0]['name']); $this->assertEquals('Custom key 2', $response['body']['devKeys'][1]['name']); - $this->assertEquals('2026-05-07T09:23:30.713+00:00', $response['body']['devKeys'][0]['expire']); - $this->assertEquals('2026-05-07T11:23:30.713+00:00', $response['body']['devKeys'][1]['expire']); + $this->assertEquals('2099-05-07T09:23:30.713+00:00', $response['body']['devKeys'][0]['expire']); + $this->assertEquals('2099-05-07T11:23:30.713+00:00', $response['body']['devKeys'][1]['expire']); foreach ($response['body']['devKeys'] as $devKey) { $this->assertIsString($devKey['$id']); @@ -1441,7 +1441,7 @@ class ProjectsConsoleClientTest extends Scope 'authPhone', ]; foreach ($authsKeys as $authsKey) { - $this->assertFalse($response['body'][$authsKey], 'Auth method should be enabled: ' . $authsKey); + $this->assertFalse($response['body'][$authsKey], 'Auth method should be disabled: ' . $authsKey); } $serviceKeys = [ @@ -1464,7 +1464,7 @@ class ProjectsConsoleClientTest extends Scope 'serviceStatusForMessaging', ]; foreach ($serviceKeys as $serviceKey) { - $this->assertFalse($response['body'][$serviceKey], 'Service should be enabled: ' . $serviceKey); + $this->assertFalse($response['body'][$serviceKey], 'Service should be disabled: ' . $serviceKey); } $protocolKeys = [ @@ -1473,7 +1473,7 @@ class ProjectsConsoleClientTest extends Scope 'protocolStatusForWebsocket', ]; foreach ($protocolKeys as $protocolKey) { - $this->assertFalse($response['body'][$protocolKey], 'Protocol should be enabled: ' . $protocolKey); + $this->assertFalse($response['body'][$protocolKey], 'Protocol should be disabled: ' . $protocolKey); } /**