2025-01-01 20:51:30 +00:00
< ? php
namespace Tests\E2E\Services\Sites ;
2025-03-08 22:33:37 +00:00
use Ahc\Jwt\JWT ;
use Appwrite\Platform\Modules\Compute\Specification ;
use Appwrite\Tests\Retry ;
2025-01-06 21:03:32 +00:00
use Tests\E2E\Client ;
2025-01-01 20:51:30 +00:00
use Tests\E2E\Scopes\ProjectCustom ;
use Tests\E2E\Scopes\Scope ;
use Tests\E2E\Scopes\SideServer ;
use Utopia\Database\Document ;
use Utopia\Database\Helpers\ID ;
use Utopia\Database\Query ;
2025-03-08 22:33:37 +00:00
use Utopia\Database\Validator\Datetime as DatetimeValidator ;
use Utopia\System\System ;
2025-01-01 20:51:30 +00:00
class SitesCustomServerTest extends Scope
{
use SitesBase ;
use ProjectCustom ;
use SideServer ;
2025-03-08 22:33:37 +00:00
public function testListSpecs () : void
{
$specifications = $this -> listSpecifications ();
$this -> assertEquals ( 200 , $specifications [ 'headers' ][ 'status-code' ]);
$this -> assertGreaterThan ( 0 , $specifications [ 'body' ][ 'total' ]);
$this -> assertArrayHasKey ( 0 , $specifications [ 'body' ][ 'specifications' ]);
$this -> assertArrayHasKey ( 'memory' , $specifications [ 'body' ][ 'specifications' ][ 0 ]);
$this -> assertArrayHasKey ( 'cpus' , $specifications [ 'body' ][ 'specifications' ][ 0 ]);
$this -> assertArrayHasKey ( 'enabled' , $specifications [ 'body' ][ 'specifications' ][ 0 ]);
$this -> assertArrayHasKey ( 'slug' , $specifications [ 'body' ][ 'specifications' ][ 0 ]);
$site = $this -> createSite ([
'buildRuntime' => 'node-22' ,
'framework' => 'other' ,
'name' => 'Specs site' ,
'siteId' => ID :: unique (),
'specification' => $specifications [ 'body' ][ 'specifications' ][ 0 ][ 'slug' ]
]);
$this -> assertEquals ( 201 , $site [ 'headers' ][ 'status-code' ]);
$this -> assertEquals ( $specifications [ 'body' ][ 'specifications' ][ 0 ][ 'slug' ], $site [ 'body' ][ 'specification' ]);
$site = $this -> getSite ( $site [ 'body' ][ '$id' ]);
$this -> assertEquals ( 200 , $site [ 'headers' ][ 'status-code' ]);
$this -> assertEquals ( $specifications [ 'body' ][ 'specifications' ][ 0 ][ 'slug' ], $site [ 'body' ][ 'specification' ]);
$this -> cleanupSite ( $site [ 'body' ][ '$id' ]);
$site = $this -> createSite ([
'buildRuntime' => 'node-22' ,
'framework' => 'other' ,
'name' => 'Specs site' ,
'siteId' => ID :: unique (),
'specification' => 'cheap-please'
]);
$this -> assertEquals ( 400 , $site [ 'headers' ][ 'status-code' ]);
}
public function testCreateSite () : void
{
/**
* Test for SUCCESS
*/
$site = $this -> createSite ([
'buildRuntime' => 'node-22' ,
'fallbackFile' => '' ,
'framework' => 'other' ,
'name' => 'Test Site' ,
'outputDirectory' => './' ,
'siteId' => ID :: unique ()
]);
$siteId = $site [ 'body' ][ '$id' ] ? ? '' ;
$dateValidator = new DateTimeValidator ();
$this -> assertEquals ( 201 , $site [ 'headers' ][ 'status-code' ]);
$this -> assertNotEmpty ( $site [ 'body' ][ '$id' ]);
$this -> assertEquals ( 'Test Site' , $site [ 'body' ][ 'name' ]);
$this -> assertEquals ( 'other' , $site [ 'body' ][ 'framework' ]);
$this -> assertEquals ( true , $dateValidator -> isValid ( $site [ 'body' ][ '$createdAt' ]));
$this -> assertEquals ( true , $dateValidator -> isValid ( $site [ 'body' ][ '$updatedAt' ]));
$this -> assertEquals ( 'node-22' , $site [ 'body' ][ 'buildRuntime' ]);
$this -> assertEquals ( null , $site [ 'body' ][ 'fallbackFile' ]);
$this -> assertEquals ( './' , $site [ 'body' ][ 'outputDirectory' ]);
$variable = $this -> createVariable ( $siteId , [
'key' => 'siteKey1' ,
'value' => 'siteValue1' ,
]);
$variable2 = $this -> createVariable ( $siteId , [
'key' => 'siteKey2' ,
'value' => 'siteValue2' ,
]);
$variable3 = $this -> createVariable ( $siteId , [
'key' => 'siteKey3' ,
'value' => 'siteValue3' ,
]);
$this -> assertEquals ( 201 , $variable [ 'headers' ][ 'status-code' ]);
$this -> assertEquals ( 201 , $variable2 [ 'headers' ][ 'status-code' ]);
$this -> assertEquals ( 201 , $variable3 [ 'headers' ][ 'status-code' ]);
$this -> cleanupSite ( $siteId );
}
public function testConsoleAvailabilityEndpoint () : void
{
$siteId = $this -> setupSite ([
'siteId' => ID :: unique (),
'name' => 'Test Site' ,
'framework' => 'other' ,
'buildRuntime' => 'node-22' ,
'outputDirectory' => './' ,
'fallbackFile' => '' ,
]);
$this -> assertNotEmpty ( $siteId );
$domain = $this -> setupSiteDomain ( $siteId );
$response = $this -> client -> call ( Client :: METHOD_GET , '/console/resources' , [
'origin' => 'http://localhost' ,
'content-type' => 'application/json' ,
'cookie' => 'a_session_console=' . $this -> getRoot ()[ 'session' ],
'x-appwrite-project' => 'console' ,
], [
'type' => 'rules' ,
'value' => $domain ,
]);
$this -> assertEquals ( 409 , $response [ 'headers' ][ 'status-code' ]); // domain unavailable
$nonExistingDomain = " non-existent-subdomain.sites.localhost " ;
$response = $this -> client -> call ( Client :: METHOD_GET , '/console/resources' , [
'origin' => 'http://localhost' ,
'content-type' => 'application/json' ,
'cookie' => 'a_session_console=' . $this -> getRoot ()[ 'session' ],
'x-appwrite-project' => 'console' ,
], [
'type' => 'rules' ,
'value' => $nonExistingDomain ,
]);
$this -> assertEquals ( 204 , $response [ 'headers' ][ 'status-code' ]); // domain available
$this -> cleanupSite ( $siteId );
$this -> assertEventually ( function () use ( $siteId ) {
$rule = $this -> client -> call ( Client :: METHOD_GET , '/proxy/rules' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()), [
'queries' => [
Query :: equal ( 'deploymentResourceId' , [ $siteId ])
]
]);
$this -> assertEquals ( 200 , $rule [ 'headers' ][ 'status-code' ]);
$this -> assertEquals ( 0 , $rule [ 'body' ][ 'total' ]);
}, 5000 , 500 );
$response = $this -> client -> call ( Client :: METHOD_GET , '/console/resources' , [
'origin' => 'http://localhost' ,
'content-type' => 'application/json' ,
'cookie' => 'a_session_console=' . $this -> getRoot ()[ 'session' ],
'x-appwrite-project' => 'console' ,
], [
'type' => 'rules' ,
'value' => $domain ,
]);
$this -> assertEquals ( 204 , $response [ 'headers' ][ 'status-code' ]); // domain available as site is deleted
}
public function testVariables () : void
{
$site = $this -> createSite ([
'buildRuntime' => 'node-22' ,
'fallbackFile' => '' ,
'framework' => 'other' ,
'name' => 'Test Site' ,
'outputDirectory' => './' ,
'siteId' => ID :: unique ()
]);
$siteId = $site [ 'body' ][ '$id' ] ? ? '' ;
$this -> assertEquals ( 201 , $site [ 'headers' ][ 'status-code' ]);
$this -> assertNotEmpty ( $site [ 'body' ][ '$id' ]);
$this -> assertEquals ( 'Test Site' , $site [ 'body' ][ 'name' ]);
$variable = $this -> createVariable ( $siteId , [
'key' => 'siteKey1' ,
'value' => 'siteValue1' ,
'secret' => false ,
]);
$this -> assertEquals ( 201 , $variable [ 'headers' ][ 'status-code' ]);
$this -> assertNotEmpty ( $variable [ 'body' ][ '$id' ]);
$this -> assertEquals ( 'siteKey1' , $variable [ 'body' ][ 'key' ]);
$this -> assertEquals ( 'siteValue1' , $variable [ 'body' ][ 'value' ]);
$this -> assertEquals ( false , $variable [ 'body' ][ 'secret' ]);
$variable2 = $this -> createVariable ( $siteId , [
'key' => 'siteKey2' ,
'value' => 'siteValue2' ,
'secret' => false ,
]);
$this -> assertEquals ( 201 , $variable2 [ 'headers' ][ 'status-code' ]);
$this -> assertNotEmpty ( $variable2 [ 'body' ][ '$id' ]);
$this -> assertEquals ( 'siteKey2' , $variable2 [ 'body' ][ 'key' ]);
$this -> assertEquals ( 'siteValue2' , $variable2 [ 'body' ][ 'value' ]);
$this -> assertEquals ( false , $variable2 [ 'body' ][ 'secret' ]);
$secretVariable = $this -> createVariable ( $siteId , [
'key' => 'siteKey3' ,
'value' => 'siteValue3' ,
'secret' => true ,
]);
$this -> assertEquals ( 201 , $secretVariable [ 'headers' ][ 'status-code' ]);
$this -> assertNotEmpty ( $secretVariable [ 'body' ][ '$id' ]);
$this -> assertEquals ( 'siteKey3' , $secretVariable [ 'body' ][ 'key' ]);
$this -> assertEquals ( '' , $secretVariable [ 'body' ][ 'value' ]);
$this -> assertEquals ( true , $secretVariable [ 'body' ][ 'secret' ]);
$variable = $this -> getVariable ( $siteId , $variable [ 'body' ][ '$id' ]);
$this -> assertEquals ( 200 , $variable [ 'headers' ][ 'status-code' ]);
$this -> assertNotEmpty ( $variable [ 'body' ][ '$id' ]);
$this -> assertEquals ( 'siteKey1' , $variable [ 'body' ][ 'key' ]);
$this -> assertEquals ( 'siteValue1' , $variable [ 'body' ][ 'value' ]);
$this -> assertEquals ( false , $variable [ 'body' ][ 'secret' ]);
$secretVariable = $this -> getVariable ( $siteId , $secretVariable [ 'body' ][ '$id' ]);
$this -> assertEquals ( 200 , $secretVariable [ 'headers' ][ 'status-code' ]);
$this -> assertNotEmpty ( $secretVariable [ 'body' ][ '$id' ]);
$this -> assertEquals ( 'siteKey3' , $secretVariable [ 'body' ][ 'key' ]);
$this -> assertEquals ( '' , $secretVariable [ 'body' ][ 'value' ]);
$this -> assertEquals ( true , $secretVariable [ 'body' ][ 'secret' ]);
$variable = $this -> updateVariable ( $siteId , $variable [ 'body' ][ '$id' ], [
'key' => 'siteKey1Updated' ,
'value' => 'siteValue1Updated' ,
]);
$this -> assertEquals ( 200 , $variable [ 'headers' ][ 'status-code' ]);
$this -> assertNotEmpty ( $variable [ 'body' ][ '$id' ]);
$this -> assertEquals ( 'siteKey1Updated' , $variable [ 'body' ][ 'key' ]);
$this -> assertEquals ( 'siteValue1Updated' , $variable [ 'body' ][ 'value' ]);
$this -> assertEquals ( false , $variable [ 'body' ][ 'secret' ]);
$variable = $this -> updateVariable ( $siteId , $variable [ 'body' ][ '$id' ], [
'key' => 'siteKey1Updated' ,
'secret' => true ,
]);
$this -> assertEquals ( 200 , $variable [ 'headers' ][ 'status-code' ]);
$this -> assertNotEmpty ( $variable [ 'body' ][ '$id' ]);
$this -> assertEquals ( 'siteKey1Updated' , $variable [ 'body' ][ 'key' ]);
$this -> assertEquals ( '' , $variable [ 'body' ][ 'value' ]);
$this -> assertEquals ( true , $variable [ 'body' ][ 'secret' ]);
$secretVariable = $this -> updateVariable ( $siteId , $secretVariable [ 'body' ][ '$id' ], [
'key' => 'siteKey3' ,
'value' => 'siteValue3Updated' ,
]);
$this -> assertEquals ( 200 , $secretVariable [ 'headers' ][ 'status-code' ]);
$this -> assertNotEmpty ( $secretVariable [ 'body' ][ '$id' ]);
$this -> assertEquals ( 'siteKey3' , $secretVariable [ 'body' ][ 'key' ]);
$this -> assertEquals ( '' , $secretVariable [ 'body' ][ 'value' ]);
$this -> assertEquals ( true , $secretVariable [ 'body' ][ 'secret' ]);
$response = $this -> updateVariable ( $siteId , $secretVariable [ 'body' ][ '$id' ], [
'key' => 'siteKey3' ,
'secret' => false ,
]);
$this -> assertEquals ( 400 , $response [ 'headers' ][ 'status-code' ]);
$secretVariable = $this -> getVariable ( $siteId , $secretVariable [ 'body' ][ '$id' ]);
$this -> assertEquals ( 200 , $secretVariable [ 'headers' ][ 'status-code' ]);
$this -> assertNotEmpty ( $secretVariable [ 'body' ][ '$id' ]);
$this -> assertEquals ( 'siteKey3' , $secretVariable [ 'body' ][ 'key' ]);
$this -> assertEquals ( '' , $secretVariable [ 'body' ][ 'value' ]);
$this -> assertEquals ( true , $secretVariable [ 'body' ][ 'secret' ]);
$variables = $this -> listVariables ( $siteId );
$this -> assertEquals ( 200 , $variables [ 'headers' ][ 'status-code' ]);
$this -> assertCount ( 3 , $variables [ 'body' ][ 'variables' ]);
$response = $this -> deleteVariable ( $siteId , $variable [ 'body' ][ '$id' ]);
$this -> assertEquals ( 204 , $response [ 'headers' ][ 'status-code' ]);
$response = $this -> deleteVariable ( $siteId , $variable2 [ 'body' ][ '$id' ]);
$this -> assertEquals ( 204 , $response [ 'headers' ][ 'status-code' ]);
$response = $this -> deleteVariable ( $siteId , $secretVariable [ 'body' ][ '$id' ]);
$this -> assertEquals ( 204 , $response [ 'headers' ][ 'status-code' ]);
$variables = $this -> listVariables ( $siteId );
$this -> assertEquals ( 200 , $variables [ 'headers' ][ 'status-code' ]);
$this -> assertCount ( 0 , $variables [ 'body' ][ 'variables' ]);
$this -> cleanupSite ( $siteId );
}
// This is first Sites test with Proxy
// If this fails, it may not be related to variables; but Router flow failing
public function testVariablesE2E () : void
{
$siteId = $this -> setupSite ([
'siteId' => ID :: unique (),
'name' => 'Astro site' ,
'framework' => 'astro' ,
'adapter' => 'ssr' ,
'buildRuntime' => 'node-22' ,
'outputDirectory' => './dist' ,
'buildCommand' => 'npm run build' ,
'installCommand' => 'npm install' ,
'fallbackFile' => '' ,
]);
$this -> assertNotEmpty ( $siteId );
$domain = $this -> setupSiteDomain ( $siteId );
$secretVariable = $this -> createVariable ( $siteId , [
'key' => 'name' ,
'value' => 'Appwrite' ,
]);
$this -> assertEquals ( 201 , $secretVariable [ 'headers' ][ 'status-code' ]);
$this -> assertNotEmpty ( $secretVariable [ 'body' ][ '$id' ]);
$this -> assertEquals ( 'name' , $secretVariable [ 'body' ][ 'key' ]);
$this -> assertEquals ( '' , $secretVariable [ 'body' ][ 'value' ]);
$this -> assertEquals ( true , $secretVariable [ 'body' ][ 'secret' ]);
$deploymentId = $this -> setupDeployment ( $siteId , [
'code' => $this -> packageSite ( 'astro' ),
'activate' => 'true'
]);
$this -> assertNotEmpty ( $deploymentId );
$domain = $this -> getSiteDomain ( $siteId );
$proxyClient = new Client ();
$proxyClient -> setEndpoint ( 'http://' . $domain );
$response = $proxyClient -> call ( Client :: METHOD_GET , '/' );
$this -> assertEquals ( 200 , $response [ 'headers' ][ 'status-code' ]);
$this -> assertStringContainsString ( " Env variable is Appwrite " , $response [ 'body' ]);
$this -> assertStringNotContainsString ( " Variable not found " , $response [ 'body' ]);
2025-03-17 16:35:03 +00:00
$deployment = $this -> getDeployment ( $siteId , $deploymentId );
$this -> assertEquals ( 200 , $deployment [ 'headers' ][ 'status-code' ]);
$this -> assertGreaterThan ( 0 , $deployment [ 'body' ][ 'sourceSize' ]);
$this -> assertGreaterThan ( 0 , $deployment [ 'body' ][ 'buildSize' ]);
$totalSize = $deployment [ 'body' ][ 'sourceSize' ] + $deployment [ 'body' ][ 'buildSize' ];
$this -> assertEquals ( $totalSize , $deployment [ 'body' ][ 'totalSize' ]);
2025-03-18 11:44:21 +00:00
$site = $this -> getSite ( $siteId );
$this -> assertEquals ( 200 , $site [ 'headers' ][ 'status-code' ]);
$this -> assertNotEmpty ( $site [ 'body' ][ 'deploymentId' ]);
$this -> assertNotEmpty ( $site [ 'body' ][ 'deploymentCreatedAt' ]);
$this -> assertEquals ( $deployment [ 'body' ][ '$id' ], $site [ 'body' ][ 'deploymentId' ]);
$this -> assertEquals ( $deployment [ 'body' ][ '$createdAt' ], $site [ 'body' ][ 'deploymentCreatedAt' ]);
2025-03-08 22:33:37 +00:00
$this -> cleanupSite ( $siteId );
}
public function testAdapterDetectionAstroSSR () : void
{
$siteId = $this -> setupSite ([
'siteId' => ID :: unique (),
'name' => 'Astro SSR site' ,
'framework' => 'astro' ,
'buildRuntime' => 'node-22' ,
'outputDirectory' => './dist' ,
'buildCommand' => 'npm run build' ,
'installCommand' => 'npm install' ,
]);
$this -> assertNotEmpty ( $siteId );
$site = $this -> getSite ( $siteId );
$this -> assertEquals ( '200' , $site [ 'headers' ][ 'status-code' ]);
$this -> assertArrayHasKey ( 'adapter' , $site [ 'body' ]);
$this -> assertEmpty ( $site [ 'body' ][ 'adapter' ]);
$domain = $this -> setupSiteDomain ( $siteId );
$this -> assertNotEmpty ( $domain );
$deploymentId = $this -> setupDeployment ( $siteId , [
'code' => $this -> packageSite ( 'astro' ),
'activate' => 'true'
]);
$this -> assertNotEmpty ( $deploymentId );
$site = $this -> getSite ( $siteId );
$this -> assertEquals ( 'ssr' , $site [ 'body' ][ 'adapter' ]);
$proxyClient = new Client ();
$proxyClient -> setEndpoint ( 'http://' . $domain );
$response = $proxyClient -> call ( Client :: METHOD_GET , '/' );
$this -> assertEquals ( 200 , $response [ 'headers' ][ 'status-code' ]);
$this -> cleanupSite ( $siteId );
}
public function testAdapterDetectionAstroStatic () : void
{
$siteId = $this -> setupSite ([
'siteId' => ID :: unique (),
'name' => 'Astro static site' ,
'framework' => 'astro' ,
'buildRuntime' => 'node-22' ,
'outputDirectory' => './dist' ,
'buildCommand' => 'npm run build' ,
'installCommand' => 'npm install' ,
]);
$this -> assertNotEmpty ( $siteId );
$site = $this -> getSite ( $siteId );
$this -> assertEquals ( '200' , $site [ 'headers' ][ 'status-code' ]);
$this -> assertArrayHasKey ( 'adapter' , $site [ 'body' ]);
$this -> assertEmpty ( $site [ 'body' ][ 'adapter' ]);
$domain = $this -> setupSiteDomain ( $siteId );
$this -> assertNotEmpty ( $domain );
$deploymentId = $this -> setupDeployment ( $siteId , [
'code' => $this -> packageSite ( 'astro-static' ),
'activate' => 'true'
]);
$this -> assertNotEmpty ( $deploymentId );
$site = $this -> getSite ( $siteId );
$this -> assertEquals ( '200' , $site [ 'headers' ][ 'status-code' ]);
$this -> assertEquals ( 'static' , $site [ 'body' ][ 'adapter' ]);
$proxyClient = new Client ();
$proxyClient -> setEndpoint ( 'http://' . $domain );
$response = $proxyClient -> call ( Client :: METHOD_GET , '/' );
$this -> assertEquals ( 200 , $response [ 'headers' ][ 'status-code' ]);
$this -> cleanupSite ( $siteId );
}
public function testAdapterDetectionStatic () : void
{
$siteId = $this -> setupSite ([
'siteId' => ID :: unique (),
'name' => 'Static site' ,
'framework' => 'other' ,
'buildRuntime' => 'node-22' ,
'outputDirectory' => '' ,
'buildCommand' => '' ,
'installCommand' => '' ,
]);
$this -> assertNotEmpty ( $siteId );
$site = $this -> getSite ( $siteId );
$this -> assertEquals ( '200' , $site [ 'headers' ][ 'status-code' ]);
$this -> assertArrayHasKey ( 'adapter' , $site [ 'body' ]);
$this -> assertEmpty ( $site [ 'body' ][ 'adapter' ]);
$domain = $this -> setupSiteDomain ( $siteId );
$this -> assertNotEmpty ( $domain );
$deploymentId = $this -> setupDeployment ( $siteId , [
'code' => $this -> packageSite ( 'static' ),
'activate' => 'true'
]);
$this -> assertNotEmpty ( $deploymentId );
$site = $this -> getSite ( $siteId );
$this -> assertEquals ( '200' , $site [ 'headers' ][ 'status-code' ]);
$this -> assertEquals ( 'static' , $site [ 'body' ][ 'adapter' ]);
$proxyClient = new Client ();
$proxyClient -> setEndpoint ( 'http://' . $domain );
$response = $proxyClient -> call ( Client :: METHOD_GET , '/' );
$this -> assertEquals ( 200 , $response [ 'headers' ][ 'status-code' ]);
$this -> cleanupSite ( $siteId );
}
2025-03-08 15:50:39 +00:00
public function testAdapterDetectionStaticSPA () : void
{
$siteId = $this -> setupSite ([
'siteId' => ID :: unique (),
'name' => 'Static site' ,
'framework' => 'other' ,
'buildRuntime' => 'node-22' ,
'outputDirectory' => '' ,
'buildCommand' => '' ,
'installCommand' => '' ,
]);
$this -> assertNotEmpty ( $siteId );
$site = $this -> getSite ( $siteId );
$this -> assertEquals ( '200' , $site [ 'headers' ][ 'status-code' ]);
$this -> assertArrayHasKey ( 'adapter' , $site [ 'body' ]);
$this -> assertArrayHasKey ( 'fallbackFile' , $site [ 'body' ]);
$this -> assertEmpty ( $site [ 'body' ][ 'adapter' ]);
$this -> assertEmpty ( $site [ 'body' ][ 'fallbackFile' ]);
$domain = $this -> setupSiteDomain ( $siteId );
$this -> assertNotEmpty ( $domain );
$deploymentId = $this -> setupDeployment ( $siteId , [
'code' => $this -> packageSite ( 'static-single-file' ),
'activate' => 'true'
]);
$this -> assertNotEmpty ( $deploymentId );
$site = $this -> getSite ( $siteId );
$this -> assertEquals ( '200' , $site [ 'headers' ][ 'status-code' ]);
$this -> assertEquals ( 'static' , $site [ 'body' ][ 'adapter' ]);
$this -> assertEquals ( 'main.html' , $site [ 'body' ][ 'fallbackFile' ]);
$proxyClient = new Client ();
$proxyClient -> setEndpoint ( 'http://' . $domain );
$response = $proxyClient -> call ( Client :: METHOD_GET , '/' );
$this -> assertEquals ( 200 , $response [ 'headers' ][ 'status-code' ]);
$this -> assertStringContainsString ( 'Main page' , $response [ 'body' ]);
$response = $proxyClient -> call ( Client :: METHOD_GET , '/something' );
2025-03-05 17:05:49 +00:00
$this -> assertEquals ( 200 , $response [ 'headers' ][ 'status-code' ]);
2025-03-08 15:50:39 +00:00
$this -> assertStringContainsString ( 'Main page' , $response [ 'body' ]);
2025-03-05 17:05:49 +00:00
$this -> cleanupSite ( $siteId );
}
2025-03-24 14:34:02 +00:00
public function testSettingsForRollback () : void
{
$siteId = $this -> setupSite ([
'siteId' => ID :: unique (),
'name' => 'Static site' ,
2025-03-25 13:01:14 +00:00
'framework' => 'astro' ,
2025-03-24 14:34:02 +00:00
'buildRuntime' => 'node-22' ,
2025-03-25 13:01:14 +00:00
'outputDirectory' => './dist' ,
'buildCommand' => 'npm run build' ,
'installCommand' => 'npm install' ,
2025-03-24 14:34:02 +00:00
]);
$this -> assertNotEmpty ( $siteId );
$site = $this -> getSite ( $siteId );
$this -> assertEquals ( '200' , $site [ 'headers' ][ 'status-code' ]);
$this -> assertEmpty ( $site [ 'body' ][ 'adapter' ]);
$this -> assertEmpty ( $site [ 'body' ][ 'fallbackFile' ]);
$domain = $this -> setupSiteDomain ( $siteId );
$this -> assertNotEmpty ( $domain );
$deploymentId1 = $this -> setupDeployment ( $siteId , [
2025-03-25 13:01:14 +00:00
'code' => $this -> packageSite ( 'astro-static' ),
2025-03-24 14:34:02 +00:00
'activate' => 'true'
]);
$this -> assertNotEmpty ( $deploymentId1 );
$site = $this -> getSite ( $siteId );
$this -> assertEquals ( '200' , $site [ 'headers' ][ 'status-code' ]);
$this -> assertEquals ( 'static' , $site [ 'body' ][ 'adapter' ]);
2025-03-25 13:01:14 +00:00
$this -> assertEquals ( 'index.html' , $site [ 'body' ][ 'fallbackFile' ]);
2025-03-24 14:34:02 +00:00
$site = $this -> updateSite ([
2025-03-25 13:01:14 +00:00
'name' => 'SSR site' ,
'framework' => 'astro' ,
'buildRuntime' => 'node-22' ,
'outputDirectory' => './dist' ,
2025-03-24 14:34:02 +00:00
'buildCommand' => 'npm run build' ,
'installCommand' => 'npm install' ,
2025-03-25 13:01:14 +00:00
'adapter' => 'ssr' ,
'fallbackFile' => '' ,
'$id' => $siteId ,
2025-03-24 14:34:02 +00:00
]);
2025-03-25 13:01:14 +00:00
$this -> assertEquals ( '200' , $site [ 'headers' ][ 'status-code' ]);
$this -> assertEquals ( 'ssr' , $site [ 'body' ][ 'adapter' ]);
$this -> assertEmpty ( $site [ 'body' ][ 'fallbackFile' ]);
2025-03-24 14:34:02 +00:00
$deploymentId2 = $this -> setupDeployment ( $siteId , [
'code' => $this -> packageSite ( 'astro' ),
'activate' => 'true'
]);
$this -> assertNotEmpty ( $deploymentId2 );
2025-03-25 13:01:14 +00:00
$site = $this -> getSite ( $siteId );
$this -> assertEquals ( '200' , $site [ 'headers' ][ 'status-code' ]);
$this -> assertEquals ( 'ssr' , $site [ 'body' ][ 'adapter' ]);
2025-03-24 14:34:02 +00:00
$proxyClient = new Client ();
$proxyClient -> setEndpoint ( 'http://' . $domain );
$response = $proxyClient -> call ( Client :: METHOD_GET , '/' );
2025-03-25 13:01:14 +00:00
$this -> assertEquals ( 200 , $response [ 'headers' ][ 'status-code' ]);
$this -> assertStringContainsString ( " Astro SSR " , $response [ 'body' ]);
$response = $proxyClient -> call ( Client :: METHOD_GET , '/not-found' );
2025-03-24 14:34:02 +00:00
$this -> assertEquals ( 404 , $response [ 'headers' ][ 'status-code' ]);
$response = $this -> updateSiteDeployment ( $siteId , $deploymentId1 );
$this -> assertEquals ( 200 , $response [ 'headers' ][ 'status-code' ]);
$this -> assertNotEmpty ( $response [ 'body' ][ '$id' ]);
$proxyClient = new Client ();
$proxyClient -> setEndpoint ( 'http://' . $domain );
$response = $proxyClient -> call ( Client :: METHOD_GET , '/' );
$this -> assertEquals ( 200 , $response [ 'headers' ][ 'status-code' ]);
2025-03-25 13:01:14 +00:00
$this -> assertStringContainsString ( " Astro static " , $response [ 'body' ]);
$response = $proxyClient -> call ( Client :: METHOD_GET , '/not-found' );
2025-03-05 17:05:49 +00:00
$this -> assertEquals ( 200 , $response [ 'headers' ][ 'status-code' ]);
2025-03-25 13:01:14 +00:00
$this -> assertStringContainsString ( " Astro static " , $response [ 'body' ]);
2025-03-05 17:05:49 +00:00
$this -> cleanupSite ( $siteId );
}
2025-01-01 20:51:30 +00:00
public function testListSites () : void
{
/**
* Test for SUCCESS
*/
$siteId = $this -> setupSite ([
2025-03-07 14:46:49 +00:00
'buildRuntime' => 'node-22' ,
2025-03-08 17:39:13 +00:00
'fallbackFile' => '' ,
2025-01-06 21:03:32 +00:00
'framework' => 'other' ,
2025-01-01 20:51:30 +00:00
'name' => 'Test Site' ,
2025-01-06 21:03:32 +00:00
'outputDirectory' => './' ,
2025-01-01 20:51:30 +00:00
'providerBranch' => 'main' ,
'providerRootDirectory' => './' ,
2025-01-06 21:03:32 +00:00
'siteId' => ID :: unique ()
2025-01-01 20:51:30 +00:00
]);
$sites = $this -> listSites ([
'search' => $siteId ,
]);
$this -> assertEquals ( $sites [ 'headers' ][ 'status-code' ], 200 );
$this -> assertCount ( 1 , $sites [ 'body' ][ 'sites' ]);
$this -> assertEquals ( $sites [ 'body' ][ 'sites' ][ 0 ][ 'name' ], 'Test Site' );
// Test pagination limit
$sites = $this -> listSites ([
'queries' => [
Query :: limit ( 1 ) -> toString (),
],
]);
$this -> assertEquals ( $sites [ 'headers' ][ 'status-code' ], 200 );
$this -> assertCount ( 1 , $sites [ 'body' ][ 'sites' ]);
// Test pagination offset
$sites = $this -> listSites ([
'queries' => [
Query :: offset ( 1 ) -> toString (),
],
]);
$this -> assertEquals ( $sites [ 'headers' ][ 'status-code' ], 200 );
$this -> assertCount ( 0 , $sites [ 'body' ][ 'sites' ]);
// Test filter enabled
$sites = $this -> listSites ([
'queries' => [
Query :: equal ( 'enabled' , [ true ]) -> toString (),
],
]);
$this -> assertEquals ( $sites [ 'headers' ][ 'status-code' ], 200 );
$this -> assertCount ( 1 , $sites [ 'body' ][ 'sites' ]);
// Test filter disabled
$sites = $this -> listSites ([
'queries' => [
Query :: equal ( 'enabled' , [ false ]) -> toString (),
],
]);
$this -> assertEquals ( $sites [ 'headers' ][ 'status-code' ], 200 );
$this -> assertCount ( 0 , $sites [ 'body' ][ 'sites' ]);
// Test search name
$sites = $this -> listSites ([
'search' => 'Test'
]);
$this -> assertEquals ( $sites [ 'headers' ][ 'status-code' ], 200 );
$this -> assertCount ( 1 , $sites [ 'body' ][ 'sites' ]);
$this -> assertEquals ( $sites [ 'body' ][ 'sites' ][ 0 ][ '$id' ], $siteId );
// Test search framework
$sites = $this -> listSites ([
2025-01-06 21:03:32 +00:00
'search' => 'other'
2025-01-01 20:51:30 +00:00
]);
$this -> assertEquals ( $sites [ 'headers' ][ 'status-code' ], 200 );
$this -> assertCount ( 1 , $sites [ 'body' ][ 'sites' ]);
$this -> assertEquals ( $sites [ 'body' ][ 'sites' ][ 0 ][ '$id' ], $siteId );
/**
* Test pagination
*/
$siteId2 = $this -> setupSite ([
2025-03-07 14:46:49 +00:00
'buildRuntime' => 'node-22' ,
2025-03-08 17:39:13 +00:00
'fallbackFile' => '' ,
2025-01-06 21:03:32 +00:00
'framework' => 'other' ,
2025-01-01 20:51:30 +00:00
'name' => 'Test Site 2' ,
2025-01-06 21:03:32 +00:00
'outputDirectory' => './' ,
2025-01-01 20:51:30 +00:00
'providerBranch' => 'main' ,
'providerRootDirectory' => './' ,
2025-01-06 21:03:32 +00:00
'siteId' => ID :: unique ()
2025-01-01 20:51:30 +00:00
]);
$sites = $this -> listSites ();
$this -> assertEquals ( $sites [ 'headers' ][ 'status-code' ], 200 );
$this -> assertEquals ( $sites [ 'body' ][ 'total' ], 2 );
$this -> assertIsArray ( $sites [ 'body' ][ 'sites' ]);
$this -> assertCount ( 2 , $sites [ 'body' ][ 'sites' ]);
$this -> assertEquals ( $sites [ 'body' ][ 'sites' ][ 0 ][ 'name' ], 'Test Site' );
$this -> assertEquals ( $sites [ 'body' ][ 'sites' ][ 1 ][ 'name' ], 'Test Site 2' );
$sites1 = $this -> listSites ([
'queries' => [
Query :: cursorAfter ( new Document ([ '$id' => $sites [ 'body' ][ 'sites' ][ 0 ][ '$id' ]])) -> toString (),
],
]);
$this -> assertEquals ( $sites1 [ 'headers' ][ 'status-code' ], 200 );
$this -> assertCount ( 1 , $sites1 [ 'body' ][ 'sites' ]);
$this -> assertEquals ( $sites1 [ 'body' ][ 'sites' ][ 0 ][ 'name' ], 'Test Site 2' );
$sites2 = $this -> listSites ([
'queries' => [
Query :: cursorBefore ( new Document ([ '$id' => $sites [ 'body' ][ 'sites' ][ 1 ][ '$id' ]])) -> toString (),
],
]);
$this -> assertEquals ( $sites2 [ 'headers' ][ 'status-code' ], 200 );
$this -> assertCount ( 1 , $sites2 [ 'body' ][ 'sites' ]);
$this -> assertEquals ( $sites2 [ 'body' ][ 'sites' ][ 0 ][ 'name' ], 'Test Site' );
/**
* Test for FAILURE
*/
$sites = $this -> listSites ([
'queries' => [
Query :: cursorAfter ( new Document ([ '$id' => 'unknown' ])) -> toString (),
],
]);
$this -> assertEquals ( $sites [ 'headers' ][ 'status-code' ], 400 );
$this -> cleanupSite ( $siteId );
$this -> cleanupSite ( $siteId2 );
}
2025-03-08 22:33:37 +00:00
public function testGetSite () : void
{
$siteId = $this -> setupSite ([
'buildRuntime' => 'node-22' ,
'fallbackFile' => '' ,
'framework' => 'other' ,
'name' => 'Test Site' ,
'outputDirectory' => './' ,
'providerBranch' => 'main' ,
'providerRootDirectory' => './' ,
'siteId' => ID :: unique ()
]);
$this -> assertNotNull ( $siteId );
/**
* Test for SUCCESS
*/
$site = $this -> getSite ( $siteId );
$this -> assertEquals ( $site [ 'headers' ][ 'status-code' ], 200 );
$this -> assertEquals ( $site [ 'body' ][ 'name' ], 'Test Site' );
/**
* Test for FAILURE
*/
$site = $this -> getSite ( 'x' );
$this -> assertEquals ( $site [ 'headers' ][ 'status-code' ], 404 );
$this -> cleanupSite ( $siteId );
}
public function testUpdateSite () : void
{
$site = $this -> createSite ([
'buildRuntime' => 'node-22' ,
'fallbackFile' => '' ,
'framework' => 'other' ,
'name' => 'Test Site' ,
'outputDirectory' => './' ,
'providerBranch' => 'main' ,
'providerRootDirectory' => './' ,
'siteId' => ID :: unique ()
]);
$siteId = $site [ 'body' ][ '$id' ] ? ? '' ;
$this -> assertEquals ( 201 , $site [ 'headers' ][ 'status-code' ]);
$this -> assertNotEmpty ( $site [ 'body' ][ '$id' ]);
$this -> assertEquals ( 'Test Site' , $site [ 'body' ][ 'name' ]);
$site = $this -> updateSite ([
'buildRuntime' => 'node-22' ,
'fallbackFile' => '' ,
'framework' => 'other' ,
'name' => 'Test Site Updated' ,
'outputDirectory' => './' ,
'providerBranch' => 'main' ,
'providerRootDirectory' => './' ,
'$id' => $siteId ,
'installCommand' => 'npm install'
]);
$dateValidator = new DatetimeValidator ();
$this -> assertEquals ( 200 , $site [ 'headers' ][ 'status-code' ]);
$this -> assertNotEmpty ( $site [ 'body' ][ '$id' ]);
$this -> assertEquals ( 'Test Site Updated' , $site [ 'body' ][ 'name' ]);
$this -> assertEquals ( true , $dateValidator -> isValid ( $site [ 'body' ][ '$createdAt' ]));
$this -> assertEquals ( true , $dateValidator -> isValid ( $site [ 'body' ][ '$updatedAt' ]));
$this -> assertEquals ( 'npm install' , $site [ 'body' ][ 'installCommand' ]);
$this -> cleanupSite ( $siteId );
}
// public function testCreateDeploymentFromCLI() {
// // TODO: Implement testCreateDeploymentFromCLI() later
// }
public function testCreateDeployment ()
{
$siteId = $this -> setupSite ([
'buildRuntime' => 'node-22' ,
'fallbackFile' => '' ,
'framework' => 'other' ,
'name' => 'Test Site' ,
'outputDirectory' => './' ,
'providerBranch' => 'main' ,
'providerRootDirectory' => './' ,
'siteId' => ID :: unique ()
]);
$this -> assertNotNull ( $siteId );
$deployment = $this -> createDeployment ( $siteId , [
'siteId' => $siteId ,
'code' => $this -> packageSite ( 'static' ),
'activate' => true ,
]);
$this -> assertEquals ( 202 , $deployment [ 'headers' ][ 'status-code' ]);
$this -> assertNotEmpty ( $deployment [ 'body' ][ '$id' ]);
2025-03-13 10:19:55 +00:00
$this -> assertEquals ( 'waiting' , $deployment [ 'body' ][ 'status' ]);
2025-03-08 22:33:37 +00:00
$this -> assertEquals ( true , ( new DatetimeValidator ()) -> isValid ( $deployment [ 'body' ][ '$createdAt' ]));
$deploymentIdActive = $deployment [ 'body' ][ '$id' ] ? ? '' ;
$this -> assertEventually ( function () use ( $siteId , $deploymentIdActive ) {
$deployment = $this -> getDeployment ( $siteId , $deploymentIdActive );
$this -> assertEquals ( 'ready' , $deployment [ 'body' ][ 'status' ]);
}, 50000 , 500 );
$deployment = $this -> createDeployment ( $siteId , [
'code' => $this -> packageSite ( 'static' ),
'activate' => 'false'
]);
$this -> assertEquals ( 202 , $deployment [ 'headers' ][ 'status-code' ]);
$this -> assertNotEmpty ( $deployment [ 'body' ][ '$id' ]);
$deploymentIdInactive = $deployment [ 'body' ][ '$id' ] ? ? '' ;
$this -> assertEventually ( function () use ( $siteId , $deploymentIdInactive ) {
$deployment = $this -> getDeployment ( $siteId , $deploymentIdInactive );
$this -> assertEquals ( 'ready' , $deployment [ 'body' ][ 'status' ]);
}, 50000 , 500 );
$site = $this -> getSite ( $siteId );
$this -> assertEquals ( 200 , $site [ 'headers' ][ 'status-code' ]);
$this -> assertEquals ( $deploymentIdActive , $site [ 'body' ][ 'deploymentId' ]);
$this -> assertNotEquals ( $deploymentIdInactive , $site [ 'body' ][ 'deploymentId' ]);
$this -> cleanupDeployment ( $siteId , $deploymentIdActive );
$this -> cleanupDeployment ( $siteId , $deploymentIdInactive );
$this -> cleanupSite ( $siteId );
}
#[Retry(count: 3)]
public function testCancelDeploymentBuild () : void
{
$siteId = $this -> setupSite ([
'buildRuntime' => 'node-22' ,
'fallbackFile' => '' ,
'framework' => 'other' ,
'name' => 'Test Site' ,
'outputDirectory' => './' ,
'providerBranch' => 'main' ,
'providerRootDirectory' => './' ,
'siteId' => ID :: unique ()
]);
$this -> assertNotNull ( $siteId );
$deployment = $this -> createDeployment ( $siteId , [
'code' => $this -> packageSite ( 'static' ),
'activate' => 'false'
]);
$deploymentId = $deployment [ 'body' ][ '$id' ] ? ? '' ;
$this -> assertEquals ( 202 , $deployment [ 'headers' ][ 'status-code' ]);
$this -> assertNotEmpty ( $deployment [ 'body' ][ '$id' ]);
$this -> assertEquals ( true , ( new DatetimeValidator ()) -> isValid ( $deployment [ 'body' ][ '$createdAt' ]));
$this -> assertEventually ( function () use ( $siteId , $deploymentId ) {
$deployment = $this -> getDeployment ( $siteId , $deploymentId );
$this -> assertEquals ( 200 , $deployment [ 'headers' ][ 'status-code' ]);
$this -> assertEquals ( 'building' , $deployment [ 'body' ][ 'status' ]);
}, 100000 , 250 );
$deployment = $this -> cancelDeployment ( $siteId , $deploymentId );
$this -> assertEquals ( 200 , $deployment [ 'headers' ][ 'status-code' ]);
$this -> assertEquals ( 'canceled' , $deployment [ 'body' ][ 'status' ]);
/**
* Build worker still runs the build .
* 30 s sleep gives worker enough time to finish build .
* After build finished , it should still be canceled , not ready .
*/
\sleep ( 30 );
$deployment = $this -> getDeployment ( $siteId , $deploymentId );
$this -> assertEquals ( 200 , $deployment [ 'headers' ][ 'status-code' ]);
$this -> assertEquals ( 'canceled' , $deployment [ 'body' ][ 'status' ]);
$this -> cleanupDeployment ( $siteId , $deploymentId );
$this -> cleanupSite ( $siteId );
}
public function testUpdateDeployment () : void
{
$siteId = $this -> setupSite ([
'buildRuntime' => 'node-22' ,
'fallbackFile' => '' ,
'framework' => 'other' ,
'name' => 'Test Site' ,
'outputDirectory' => './' ,
'providerBranch' => 'main' ,
'providerRootDirectory' => './' ,
'siteId' => ID :: unique ()
]);
$this -> assertNotNull ( $siteId );
$deployment = $this -> createDeployment ( $siteId , [
'code' => $this -> packageSite ( 'static' ),
'activate' => 'false'
]);
$deploymentId = $deployment [ 'body' ][ '$id' ] ? ? '' ;
$this -> assertEquals ( 202 , $deployment [ 'headers' ][ 'status-code' ]);
$this -> assertEventually ( function () use ( $siteId , $deploymentId ) {
$deployment = $this -> getDeployment ( $siteId , $deploymentId );
$this -> assertEquals ( 'ready' , $deployment [ 'body' ][ 'status' ]);
}, 50000 , 500 );
/**
* Test for SUCCESS
*/
$dateValidator = new DatetimeValidator ();
$response = $this -> updateSiteDeployment ( $siteId , $deploymentId );
$this -> assertEquals ( 200 , $response [ 'headers' ][ 'status-code' ]);
$this -> assertNotEmpty ( $response [ 'body' ][ '$id' ]);
$this -> assertEquals ( true , $dateValidator -> isValid ( $response [ 'body' ][ '$createdAt' ]));
$this -> assertEquals ( true , $dateValidator -> isValid ( $response [ 'body' ][ '$updatedAt' ]));
$this -> assertEquals ( $deploymentId , $response [ 'body' ][ 'deploymentId' ]);
$this -> cleanupDeployment ( $siteId , $deploymentId );
$this -> cleanupSite ( $siteId );
}
public function testListDeployments () : void
{
$siteId = $this -> setupSite ([
'buildRuntime' => 'node-22' ,
'fallbackFile' => '' ,
'framework' => 'other' ,
'name' => 'Test Site' ,
'outputDirectory' => './' ,
'providerBranch' => 'main' ,
'providerRootDirectory' => './' ,
'siteId' => ID :: unique ()
]);
$this -> assertNotNull ( $siteId );
$deployment = $this -> createDeployment ( $siteId , [
'code' => $this -> packageSite ( 'static' ),
'activate' => 'false'
]);
$deploymentIdActive = $deployment [ 'body' ][ '$id' ] ? ? '' ;
$this -> assertEquals ( 202 , $deployment [ 'headers' ][ 'status-code' ]);
$deployment = $this -> createDeployment ( $siteId , [
'code' => $this -> packageSite ( 'static' ),
'activate' => 'false'
]);
$this -> assertEquals ( 202 , $deployment [ 'headers' ][ 'status-code' ]);
$this -> assertNotEmpty ( $deployment [ 'body' ][ '$id' ]);
$deploymentIdInactive = $deployment [ 'body' ][ '$id' ] ? ? '' ;
$deployments = $this -> listDeployments ( $siteId );
$this -> assertEquals ( $deployments [ 'headers' ][ 'status-code' ], 200 );
$this -> assertEquals ( $deployments [ 'body' ][ 'total' ], 2 );
$this -> assertIsArray ( $deployments [ 'body' ][ 'deployments' ]);
$this -> assertCount ( 2 , $deployments [ 'body' ][ 'deployments' ]);
$this -> assertArrayHasKey ( 'sourceSize' , $deployments [ 'body' ][ 'deployments' ][ 0 ]);
$this -> assertArrayHasKey ( 'buildSize' , $deployments [ 'body' ][ 'deployments' ][ 0 ]);
$deployments = $this -> listDeployments ( $siteId , [
'queries' => [
Query :: limit ( 1 ) -> toString (),
],
]);
$this -> assertEquals ( $deployments [ 'headers' ][ 'status-code' ], 200 );
$this -> assertCount ( 1 , $deployments [ 'body' ][ 'deployments' ]);
$deployments = $this -> listDeployments ( $siteId , [
'queries' => [
Query :: offset ( 1 ) -> toString (),
],
]);
$this -> assertEquals ( $deployments [ 'headers' ][ 'status-code' ], 200 );
$this -> assertCount ( 1 , $deployments [ 'body' ][ 'deployments' ]);
$deployments = $this -> listDeployments (
$siteId ,
[
'queries' => [
Query :: equal ( 'type' , [ 'manual' ]) -> toString (),
],
]
);
$this -> assertEquals ( $deployments [ 'headers' ][ 'status-code' ], 200 );
$this -> assertEquals ( 2 , $deployments [ 'body' ][ 'total' ]);
$deployments = $this -> listDeployments (
$siteId ,
[
'queries' => [
Query :: equal ( 'type' , [ 'vcs' ]) -> toString (),
],
]
);
$this -> assertEquals ( $deployments [ 'headers' ][ 'status-code' ], 200 );
$this -> assertEquals ( 0 , $deployments [ 'body' ][ 'total' ]);
$deployments = $this -> listDeployments (
$siteId ,
[
'queries' => [
Query :: equal ( 'type' , [ 'invalid-string' ]) -> toString (),
],
]
);
$this -> assertEquals ( $deployments [ 'headers' ][ 'status-code' ], 200 );
$this -> assertEquals ( 0 , $deployments [ 'body' ][ 'total' ]);
$deployments = $this -> listDeployments (
$siteId ,
[
'queries' => [
Query :: greaterThan ( 'sourceSize' , 10000 ) -> toString (),
],
]
);
$this -> assertEquals ( $deployments [ 'headers' ][ 'status-code' ], 200 );
$this -> assertEquals ( 0 , $deployments [ 'body' ][ 'total' ]);
$deployments = $this -> listDeployments (
$siteId ,
[
'queries' => [
Query :: greaterThan ( 'sourceSize' , 0 ) -> toString (),
],
]
);
$this -> assertEquals ( $deployments [ 'headers' ][ 'status-code' ], 200 );
$this -> assertEquals ( 2 , $deployments [ 'body' ][ 'total' ]);
$deployments = $this -> listDeployments (
$siteId ,
[
'queries' => [
Query :: greaterThan ( 'sourceSize' , - 100 ) -> toString (),
],
]
);
$this -> assertEquals ( $deployments [ 'headers' ][ 'status-code' ], 200 );
$this -> assertEquals ( 2 , $deployments [ 'body' ][ 'total' ]);
/**
* Ensure size output and size filters work exactly .
* Prevents buildSize being counted towards deployment size
*/
$deployments = $this -> listDeployments (
$siteId ,
[
Query :: limit ( 1 ) -> toString (),
]
);
$this -> assertEquals ( 200 , $deployments [ 'headers' ][ 'status-code' ]);
$this -> assertGreaterThanOrEqual ( 1 , $deployments [ 'body' ][ 'total' ]);
$this -> assertNotEmpty ( $deployments [ 'body' ][ 'deployments' ][ 0 ][ '$id' ]);
$this -> assertNotEmpty ( $deployments [ 'body' ][ 'deployments' ][ 0 ][ 'sourceSize' ]);
$deploymentId = $deployments [ 'body' ][ 'deployments' ][ 0 ][ '$id' ];
$deploymentSize = $deployments [ 'body' ][ 'deployments' ][ 0 ][ 'sourceSize' ];
$deployments = $this -> listDeployments (
$siteId ,
[
'queries' => [
Query :: equal ( 'sourceSize' , [ $deploymentSize ]) -> toString (),
],
]
);
$this -> assertEquals ( 200 , $deployments [ 'headers' ][ 'status-code' ]);
$this -> assertGreaterThan ( 0 , $deployments [ 'body' ][ 'total' ]);
$matchingDeployment = array_filter (
$deployments [ 'body' ][ 'deployments' ],
fn ( $deployment ) => $deployment [ '$id' ] === $deploymentId
);
$this -> assertNotEmpty ( $matchingDeployment , " Deployment with ID { $deploymentId } not found " );
if ( ! empty ( $matchingDeployment )) {
$deployment = reset ( $matchingDeployment );
$this -> assertEquals ( $deploymentSize , $deployment [ 'sourceSize' ]);
}
$this -> cleanupDeployment ( $siteId , $deploymentIdActive );
$this -> cleanupDeployment ( $siteId , $deploymentIdInactive );
$this -> cleanupSite ( $siteId );
}
public function testGetDeployment () : void
{
$siteId = $this -> setupSite ([
'buildRuntime' => 'node-22' ,
'fallbackFile' => '' ,
'framework' => 'other' ,
'name' => 'Test Site' ,
'outputDirectory' => './' ,
'providerBranch' => 'main' ,
'providerRootDirectory' => './' ,
'siteId' => ID :: unique ()
]);
$this -> assertNotNull ( $siteId );
$deployment = $this -> createDeployment ( $siteId , [
'code' => $this -> packageSite ( 'static' ),
'activate' => 'false'
]);
$deploymentId = $deployment [ 'body' ][ '$id' ] ? ? '' ;
$this -> assertEventually ( function () use ( $siteId , $deploymentId ) {
$deployment = $this -> getDeployment ( $siteId , $deploymentId );
$this -> assertEquals ( 'ready' , $deployment [ 'body' ][ 'status' ]);
}, 50000 , 500 );
/**
* Test for SUCCESS
*/
$deployment = $this -> getDeployment ( $siteId , $deploymentId );
$this -> assertEquals ( 200 , $deployment [ 'headers' ][ 'status-code' ]);
$this -> assertGreaterThan ( 0 , $deployment [ 'body' ][ 'buildDuration' ]);
$this -> assertNotEmpty ( $deployment [ 'body' ][ 'status' ]);
$this -> assertNotEmpty ( $deployment [ 'body' ][ 'buildLogs' ]);
$this -> assertArrayHasKey ( 'sourceSize' , $deployment [ 'body' ]);
$this -> assertArrayHasKey ( 'buildSize' , $deployment [ 'body' ]);
/**
* Test for FAILURE
*/
$deployment = $this -> getDeployment ( $siteId , 'x' );
$this -> assertEquals ( $deployment [ 'headers' ][ 'status-code' ], 404 );
$this -> cleanupDeployment ( $siteId , $deploymentId );
$this -> cleanupSite ( $siteId );
}
public function testUpdateSpecs () : void
{
$siteId = $this -> setupSite ([
'buildRuntime' => 'node-22' ,
'fallbackFile' => '' ,
'framework' => 'other' ,
'name' => 'Test Site' ,
'outputDirectory' => './' ,
'providerBranch' => 'main' ,
'providerRootDirectory' => './' ,
'siteId' => ID :: unique ()
]);
$this -> assertNotNull ( $siteId );
/**
* Test for SUCCESS
*/
// Change the function specs
$site = $this -> updateSite ([
'buildRuntime' => 'node-22' ,
'fallbackFile' => '' ,
'framework' => 'other' ,
'name' => 'Test Site' ,
'outputDirectory' => './' ,
'providerBranch' => 'main' ,
'providerRootDirectory' => './' ,
'$id' => $siteId ,
'specification' => Specification :: S_1VCPU_1GB ,
]);
$this -> assertEquals ( 200 , $site [ 'headers' ][ 'status-code' ]);
$this -> assertNotEmpty ( $site [ 'body' ][ '$id' ]);
$this -> assertEquals ( Specification :: S_1VCPU_1GB , $site [ 'body' ][ 'specification' ]);
// Change the specs to 1vcpu 512mb
$site = $this -> updateSite ([
'buildRuntime' => 'node-22' ,
'fallbackFile' => '' ,
'framework' => 'other' ,
'name' => 'Test Site' ,
'outputDirectory' => './' ,
'providerBranch' => 'main' ,
'providerRootDirectory' => './' ,
'$id' => $siteId ,
'specification' => Specification :: S_1VCPU_512MB ,
]);
$this -> assertEquals ( 200 , $site [ 'headers' ][ 'status-code' ]);
$this -> assertNotEmpty ( $site [ 'body' ][ '$id' ]);
$this -> assertEquals ( Specification :: S_1VCPU_512MB , $site [ 'body' ][ 'specification' ]);
/**
* Test for FAILURE
*/
$site = $this -> updateSite ([
'buildRuntime' => 'node-22' ,
'fallbackFile' => '' ,
'framework' => 'other' ,
'name' => 'Test Site' ,
'outputDirectory' => './' ,
'providerBranch' => 'main' ,
'providerRootDirectory' => './' ,
'$id' => $siteId ,
'specification' => 's-2vcpu-512mb' , // Invalid specification
]);
$this -> assertEquals ( 400 , $site [ 'headers' ][ 'status-code' ]);
$this -> assertStringStartsWith ( 'Invalid `specification` param: Specification must be one of:' , $site [ 'body' ][ 'message' ]);
$this -> cleanupSite ( $siteId );
}
public function testDeleteDeployment () : void
{
$siteId = $this -> setupSite ([
'buildRuntime' => 'node-22' ,
'fallbackFile' => '' ,
'framework' => 'other' ,
'name' => 'Test Site' ,
'outputDirectory' => './' ,
'providerBranch' => 'main' ,
'providerRootDirectory' => './' ,
'siteId' => ID :: unique ()
]);
$this -> assertNotNull ( $siteId );
$deployment = $this -> createDeployment ( $siteId , [
'code' => $this -> packageSite ( 'static' ),
'activate' => 'false'
]);
$deploymentId = $deployment [ 'body' ][ '$id' ] ? ? '' ;
$this -> assertEventually ( function () use ( $siteId , $deploymentId ) {
$deployment = $this -> getDeployment ( $siteId , $deploymentId );
$this -> assertEquals ( 'ready' , $deployment [ 'body' ][ 'status' ]);
}, 50000 , 500 );
/**
* Test for SUCCESS
*/
$deployment = $this -> client -> call ( Client :: METHOD_DELETE , '/sites/' . $siteId . '/deployments/' . $deploymentId , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()));
$this -> assertEquals ( 204 , $deployment [ 'headers' ][ 'status-code' ]);
$this -> assertEmpty ( $deployment [ 'body' ]);
$deployment = $this -> getDeployment ( $siteId , $deploymentId );
$this -> assertEquals ( 404 , $deployment [ 'headers' ][ 'status-code' ]);
}
public function testDeleteSite () : void
{
$siteId = $this -> setupSite ([
'buildRuntime' => 'node-22' ,
'fallbackFile' => '' ,
'framework' => 'other' ,
'name' => 'Test Site' ,
'outputDirectory' => './' ,
'providerBranch' => 'main' ,
'providerRootDirectory' => './' ,
'siteId' => ID :: unique ()
]);
$this -> assertNotNull ( $siteId );
$site = $this -> deleteSite ( $siteId );
$this -> assertEquals ( 204 , $site [ 'headers' ][ 'status-code' ]);
$this -> assertEmpty ( $site [ 'body' ]);
$function = $this -> getSite ( $siteId );
$this -> assertEquals ( 404 , $function [ 'headers' ][ 'status-code' ]);
}
public function testGetFrameworks () : void
{
$frameworks = $this -> client -> call ( Client :: METHOD_GET , '/sites/frameworks' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()));
$this -> assertEquals ( 200 , $frameworks [ 'headers' ][ 'status-code' ]);
$this -> assertGreaterThan ( 0 , $frameworks [ 'body' ][ 'total' ]);
$framework = $frameworks [ 'body' ][ 'frameworks' ][ 0 ];
$this -> assertArrayHasKey ( 'name' , $framework );
$this -> assertArrayHasKey ( 'key' , $framework );
$this -> assertArrayHasKey ( 'buildRuntime' , $framework );
$this -> assertArrayHasKey ( 'runtimes' , $framework );
$this -> assertArrayHasKey ( 'adapters' , $framework );
2025-03-17 15:02:16 +00:00
$this -> assertIsArray ( $framework [ 'adapters' ]);
$this -> assertArrayHasKey ( 'key' , $framework [ 'adapters' ][ 0 ]);
$this -> assertArrayHasKey ( 'installCommand' , $framework [ 'adapters' ][ 0 ]);
$this -> assertArrayHasKey ( 'buildCommand' , $framework [ 'adapters' ][ 0 ]);
$this -> assertArrayHasKey ( 'outputDirectory' , $framework [ 'adapters' ][ 0 ]);
2025-03-08 22:33:37 +00:00
}
public function testSiteStatic () : void
{
$siteId = $this -> setupSite ([
'siteId' => ID :: unique (),
'name' => 'Non-SPA site' ,
'framework' => 'other' ,
'adapter' => 'static' ,
'buildRuntime' => 'static-1' ,
'outputDirectory' => './' ,
'buildCommand' => '' ,
'installCommand' => '' ,
'fallbackFile' => '' ,
]);
$this -> assertNotEmpty ( $siteId );
$deploymentId = $this -> setupDeployment ( $siteId , [
'code' => $this -> packageSite ( 'static-spa' ),
'activate' => 'true'
]);
$this -> assertNotEmpty ( $deploymentId );
$domain = $this -> setupSiteDomain ( $siteId );
$proxyClient = new Client ();
$proxyClient -> setEndpoint ( 'http://' . $domain );
$response = $proxyClient -> call ( Client :: METHOD_GET , '/' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
]));
$this -> assertEquals ( 200 , $response [ 'headers' ][ 'status-code' ]);
$this -> assertStringContainsString ( " Index page " , $response [ 'body' ]);
$response = $proxyClient -> call ( Client :: METHOD_GET , '/contact' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
]));
$this -> assertEquals ( 200 , $response [ 'headers' ][ 'status-code' ]);
$this -> assertStringContainsString ( " Contact page " , $response [ 'body' ]);
$response = $proxyClient -> call ( Client :: METHOD_GET , '/non-existing' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
]));
$this -> assertEquals ( 404 , $response [ 'headers' ][ 'status-code' ]);
$this -> assertStringContainsString ( " Page not found " , $response [ 'body' ]); // Title
$this -> assertStringContainsString ( " Go to homepage " , $response [ 'body' ]); // Button
$this -> assertStringContainsString ( " Powered by " , $response [ 'body' ]); // Brand
$this -> cleanupSite ( $siteId );
}
public function testSiteStaticSPA () : void
{
$siteId = $this -> setupSite ([
'siteId' => ID :: unique (),
'name' => 'SPA site' ,
'framework' => 'other' ,
'adapter' => 'static' ,
'buildRuntime' => 'static-1' ,
'outputDirectory' => './' ,
'buildCommand' => '' ,
'installCommand' => '' ,
'fallbackFile' => '404.html' ,
]);
$this -> assertNotEmpty ( $siteId );
$deploymentId = $this -> setupDeployment ( $siteId , [
'code' => $this -> packageSite ( 'static-spa' ),
'activate' => 'true'
]);
$this -> assertNotEmpty ( $deploymentId );
$domain = $this -> setupSiteDomain ( $siteId );
$proxyClient = new Client ();
$proxyClient -> setEndpoint ( 'http://' . $domain );
$response = $proxyClient -> call ( Client :: METHOD_GET , '/' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
]));
$this -> assertEquals ( 200 , $response [ 'headers' ][ 'status-code' ]);
$this -> assertStringContainsString ( " Index page " , $response [ 'body' ]);
$response = $proxyClient -> call ( Client :: METHOD_GET , '/contact' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
]));
$this -> assertEquals ( 200 , $response [ 'headers' ][ 'status-code' ]);
$this -> assertStringContainsString ( " Contact page " , $response [ 'body' ]);
$response = $proxyClient -> call ( Client :: METHOD_GET , '/non-existing' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
]));
$this -> assertEquals ( 200 , $response [ 'headers' ][ 'status-code' ]);
$this -> assertStringContainsString ( " Customized 404 page " , $response [ 'body' ]);
$this -> assertStringNotContainsString ( " Powered by " , $response [ 'body' ]); // Brand
$this -> cleanupSite ( $siteId );
}
public function testSiteTemplate () : void
{
$template = $this -> getTemplate ( 'astro-starter' );
$this -> assertEquals ( 200 , $template [ 'headers' ][ 'status-code' ]);
$template = $template [ 'body' ];
$siteId = $this -> setupSite ([
'siteId' => ID :: unique (),
'name' => 'Template site' ,
'framework' => $template [ 'frameworks' ][ 0 ][ 'key' ],
'adapter' => $template [ 'frameworks' ][ 0 ][ 'adapter' ],
'buildRuntime' => $template [ 'frameworks' ][ 0 ][ 'buildRuntime' ],
'outputDirectory' => $template [ 'frameworks' ][ 0 ][ 'outputDirectory' ],
'buildCommand' => $template [ 'frameworks' ][ 0 ][ 'buildCommand' ],
'installCommand' => $template [ 'frameworks' ][ 0 ][ 'installCommand' ],
'fallbackFile' => $template [ 'frameworks' ][ 0 ][ 'fallbackFile' ],
]);
$this -> assertNotEmpty ( $siteId );
$deployment = $this -> createTemplateDeployment ( $siteId , [
'repository' => $template [ 'providerRepositoryId' ],
'owner' => $template [ 'providerOwner' ],
'rootDirectory' => $template [ 'frameworks' ][ 0 ][ 'providerRootDirectory' ],
'version' => $template [ 'providerVersion' ],
'activate' => true
]);
$this -> assertEquals ( 202 , $deployment [ 'headers' ][ 'status-code' ]);
$this -> assertNotEmpty ( $deployment [ 'body' ][ '$id' ]);
2025-03-17 16:35:03 +00:00
$deployment = $this -> getDeployment ( $siteId , $deployment [ 'body' ][ '$id' ]);
$this -> assertEquals ( 200 , $deployment [ 'headers' ][ 'status-code' ]);
$this -> assertEquals ( 0 , $deployment [ 'body' ][ 'sourceSize' ]);
$this -> assertEquals ( 0 , $deployment [ 'body' ][ 'buildSize' ]);
$this -> assertEquals ( 0 , $deployment [ 'body' ][ 'totalSize' ]);
2025-03-08 22:33:37 +00:00
$this -> assertEventually ( function () use ( $siteId ) {
$site = $this -> getSite ( $siteId );
$this -> assertNotEmpty ( $site [ 'body' ][ 'deploymentId' ]);
}, 50000 , 500 );
$domain = $this -> setupSiteDomain ( $siteId );
$proxyClient = new Client ();
$proxyClient -> setEndpoint ( 'http://' . $domain );
$response = $proxyClient -> call ( Client :: METHOD_GET , '/' );
$this -> assertEquals ( 200 , $response [ 'headers' ][ 'status-code' ]);
$this -> assertStringContainsString ( " Astro Blog " , $response [ 'body' ]);
$this -> assertStringContainsString ( " Hello, Astronaut! " , $response [ 'body' ]);
$response = $proxyClient -> call ( Client :: METHOD_GET , '/about' );
$this -> assertEquals ( 200 , $response [ 'headers' ][ 'status-code' ]);
$this -> assertStringContainsString ( " Astro Blog " , $response [ 'body' ]);
$this -> assertStringContainsString ( " About Me " , $response [ 'body' ]);
2025-03-17 16:35:03 +00:00
$deployment = $this -> getDeployment ( $siteId , $deployment [ 'body' ][ '$id' ]);
$this -> assertEquals ( 200 , $deployment [ 'headers' ][ 'status-code' ]);
$this -> assertGreaterThan ( 0 , $deployment [ 'body' ][ 'sourceSize' ]);
$this -> assertGreaterThan ( 0 , $deployment [ 'body' ][ 'buildSize' ]);
$totalSize = $deployment [ 'body' ][ 'sourceSize' ] + $deployment [ 'body' ][ 'buildSize' ];
$this -> assertEquals ( $totalSize , $deployment [ 'body' ][ 'totalSize' ]);
2025-03-08 22:33:37 +00:00
$this -> cleanupSite ( $siteId );
}
public function testSiteDomainReclaiming () : void
{
$siteId = $this -> setupSite ([
'siteId' => ID :: unique (),
'name' => 'Startup site' ,
'framework' => 'other' ,
'adapter' => 'static' ,
'buildRuntime' => 'static-1' ,
'outputDirectory' => './' ,
'buildCommand' => '' ,
'installCommand' => '' ,
'fallbackFile' => '' ,
]);
$this -> assertNotEmpty ( $siteId );
$subdomain = 'startup' . \uniqid ();
$domain = $this -> setupSiteDomain ( $siteId , $subdomain );
$deploymentId = $this -> setupDeployment ( $siteId , [
'code' => $this -> packageSite ( 'static' ),
'activate' => 'true'
]);
$this -> assertNotEmpty ( $deploymentId );
$domain = $this -> getSiteDomain ( $siteId );
$proxyClient = new Client ();
$proxyClient -> setEndpoint ( 'http://' . $domain );
$response = $proxyClient -> call ( Client :: METHOD_GET , '/' );
$this -> assertEquals ( 200 , $response [ 'headers' ][ 'status-code' ]);
$this -> assertStringNotContainsString ( " This domain is not connected to any Appwrite resource yet " , $response [ 'body' ]);
$site2 = $this -> createSite ([
'siteId' => ID :: unique (),
'name' => 'Startup 2 site' ,
'framework' => 'other' ,
'adapter' => 'static' ,
'buildRuntime' => 'static-1' ,
'outputDirectory' => './' ,
'buildCommand' => '' ,
'installCommand' => '' ,
'fallbackFile' => '' ,
]);
$siteId2 = $site2 [ 'body' ][ '$id' ];
$rule = $this -> client -> call ( Client :: METHOD_POST , '/proxy/rules/site' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()), [
'domain' => $subdomain . '.' . System :: getEnv ( '_APP_DOMAIN_SITES' , '' ),
'siteId' => $siteId2 ,
]);
$this -> assertEquals ( 409 , $rule [ 'headers' ][ 'status-code' ]);
$this -> cleanupSite ( $siteId );
$this -> assertEventually ( function () use ( $domain ) {
$rules = $this -> client -> call ( Client :: METHOD_GET , '/proxy/rules' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
], $this -> getHeaders ()), [
'queries' => [
Query :: equal ( 'domain' , [ $domain ]) -> toString (),
],
]);
$this -> assertEquals ( 200 , $rules [ 'headers' ][ 'status-code' ]);
$this -> assertEquals ( 0 , $rules [ 'body' ][ 'total' ]);
}, 50000 , 500 );
$response = $proxyClient -> call ( Client :: METHOD_GET , '/' );
$this -> assertEquals ( 401 , $response [ 'headers' ][ 'status-code' ]);
$this -> assertStringContainsString ( " This domain is not connected to any Appwrite resource yet " , $response [ 'body' ]);
$site = $this -> createSite ([
'siteId' => ID :: unique (),
'name' => 'Startup 2 site' ,
'framework' => 'other' ,
'adapter' => 'static' ,
'buildRuntime' => 'static-1' ,
'outputDirectory' => './' ,
'buildCommand' => '' ,
'installCommand' => '' ,
'fallbackFile' => '' ,
]);
$this -> assertEquals ( 201 , $site [ 'headers' ][ 'status-code' ]);
$this -> assertNotEmpty ( $site [ 'body' ][ '$id' ]);
$siteId = $site [ 'body' ][ '$id' ];
$domain = $this -> setupSiteDomain ( $siteId , $subdomain );
$this -> assertNotEmpty ( $domain );
$this -> cleanupSite ( $site [ 'body' ][ '$id' ]);
}
public function testSitePreviewBranding () : void
{
$siteId = $this -> setupSite ([
'siteId' => ID :: unique (),
'name' => 'A site' ,
'framework' => 'other' ,
'adapter' => 'static' ,
'buildRuntime' => 'static-1' ,
'outputDirectory' => './' ,
'buildCommand' => '' ,
'installCommand' => '' ,
'fallbackFile' => '' ,
]);
$this -> assertNotEmpty ( $siteId );
$deploymentId = $this -> setupDeployment ( $siteId , [
'code' => $this -> packageSite ( 'static' ),
'activate' => 'true'
]);
$this -> assertNotEmpty ( $deploymentId );
2025-03-13 09:33:28 +00:00
$siteDomain = $this -> setupSiteDomain ( $siteId );
$this -> assertNotEmpty ( $siteDomain );
2025-03-08 22:33:37 +00:00
2025-03-13 09:33:28 +00:00
$delpoymentDomain = $this -> getDeploymentDomain ( $deploymentId );
$this -> assertNotEmpty ( $delpoymentDomain );
2025-03-08 22:33:37 +00:00
$proxyClient = new Client ();
2025-03-13 09:33:28 +00:00
$proxyClient -> setEndpoint ( 'http://' . $siteDomain );
2025-03-08 22:33:37 +00:00
$response = $proxyClient -> call ( Client :: METHOD_GET , '/' );
$this -> assertEquals ( 200 , $response [ 'headers' ][ 'status-code' ]);
$this -> assertStringContainsString ( " Hello Appwrite " , $response [ 'body' ]);
$this -> assertStringNotContainsString ( " Preview by " , $response [ 'body' ]);
$contentLength = $response [ 'headers' ][ 'content-length' ];
$proxyClient = new Client ();
2025-03-13 09:33:28 +00:00
$proxyClient -> setEndpoint ( 'http://' . $delpoymentDomain );
2025-03-08 22:33:37 +00:00
$response = $proxyClient -> call ( Client :: METHOD_GET , '/' , followRedirects : false );
$this -> assertEquals ( 301 , $response [ 'headers' ][ 'status-code' ]);
$this -> assertStringContainsString ( '/console/auth/preview' , $response [ 'headers' ][ 'location' ]);
$jwtObj = new JWT ( System :: getEnv ( '_APP_OPENSSL_KEY_V1' ), 'HS256' , 900 , 0 );
$apiKey = $jwtObj -> encode ([
'projectCheckDisabled' => true ,
'previewAuthDisabled' => true ,
]);
$response = $proxyClient -> call ( Client :: METHOD_GET , '/' , followRedirects : false , headers : [
'x-appwrite-key' => API_KEY_DYNAMIC . '_' . $apiKey ,
]);
$this -> assertEquals ( 200 , $response [ 'headers' ][ 'status-code' ]);
$this -> assertStringContainsString ( " Hello Appwrite " , $response [ 'body' ]);
$this -> assertStringContainsString ( " Preview by " , $response [ 'body' ]);
$this -> assertGreaterThan ( $contentLength , $response [ 'headers' ][ 'content-length' ]);
$this -> cleanupSite ( $siteId );
}
public function testSiteCors () : void
{
// Create rule together with site
$subdomain = 'startup' . \uniqid ();
$siteId = $this -> setupSite ([
'siteId' => ID :: unique (),
'name' => 'Startup site' ,
'framework' => 'other' ,
'adapter' => 'static' ,
'buildRuntime' => 'static-1' ,
'outputDirectory' => './' ,
'buildCommand' => '' ,
'installCommand' => '' ,
'fallbackFile' => '' ,
'subdomain' => $subdomain
]);
$this -> assertNotEmpty ( $siteId );
$this -> setupSiteDomain ( $siteId , $subdomain );
$domain = $this -> getSiteDomain ( $siteId );
$this -> assertNotEmpty ( $domain );
$url = 'http://' . $domain ;
$response = $this -> client -> call ( Client :: METHOD_GET , '/account' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
'referer' => $url ,
'origin' => $url
]));
$this -> assertEquals ( $url , $response [ 'headers' ][ 'access-control-allow-origin' ]);
$response = $this -> client -> call ( Client :: METHOD_GET , '/account' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => 'unknown' ,
'referer' => $url ,
'origin' => $url
]));
$this -> assertNotEquals ( $url , $response [ 'headers' ][ 'access-control-allow-origin' ]);
$this -> assertEquals ( 'http://localhost' , $response [ 'headers' ][ 'access-control-allow-origin' ]);
$response = $this -> client -> call ( Client :: METHOD_GET , '/account' , array_merge ([
'content-type' => 'application/json' ,
'x-appwrite-project' => $this -> getProject ()[ '$id' ],
'referer' => 'http://unknown.com' ,
'origin' => 'http://unknown.com'
]));
$this -> assertNotEquals ( $url , $response [ 'headers' ][ 'access-control-allow-origin' ]);
$this -> assertEquals ( 'http://localhost' , $response [ 'headers' ][ 'access-control-allow-origin' ]);
}
public function testSiteScreenshot () : void
{
$siteId = $this -> setupSite ([
'siteId' => ID :: unique (),
'name' => 'Themed site' ,
'framework' => 'other' ,
'adapter' => 'static' ,
'buildRuntime' => 'static-1' ,
'outputDirectory' => './' ,
'buildCommand' => '' ,
'installCommand' => '' ,
'fallbackFile' => '' ,
]);
$this -> assertNotEmpty ( $siteId );
$domain = $this -> setupSiteDomain ( $siteId );
$deploymentId = $this -> setupDeployment ( $siteId , [
'code' => $this -> packageSite ( 'static-themed' ),
'activate' => 'true'
]);
$this -> assertNotEmpty ( $deploymentId );
$domain = $this -> getSiteDomain ( $siteId );
$this -> assertNotEmpty ( $domain );
$proxyClient = new Client ();
$proxyClient -> setEndpoint ( 'http://' . $domain );
$response = $proxyClient -> call ( Client :: METHOD_GET , '/' );
$this -> assertEquals ( 200 , $response [ 'headers' ][ 'status-code' ]);
$this -> assertStringContainsString ( " Themed website " , $response [ 'body' ]);
$this -> assertStringContainsString ( " @media (prefers-color-scheme: dark) " , $response [ 'body' ]);
$deployment = $this -> getDeployment ( $siteId , $deploymentId );
$this -> assertEquals ( 200 , $deployment [ 'headers' ][ 'status-code' ]);
$this -> assertNotEmpty ( $deployment [ 'body' ][ 'screenshotLight' ]);
$this -> assertNotEmpty ( $deployment [ 'body' ][ 'screenshotDark' ]);
2025-03-18 11:01:30 +00:00
$site = $this -> getSite ( $siteId );
$this -> assertEquals ( 200 , $site [ 'headers' ][ 'status-code' ]);
$this -> assertEquals ( $deployment [ 'body' ][ 'screenshotLight' ], $site [ 'body' ][ 'deploymentScreenshotLight' ]);
$this -> assertEquals ( $deployment [ 'body' ][ 'screenshotDark' ], $site [ 'body' ][ 'deploymentScreenshotDark' ]);
2025-03-08 22:33:37 +00:00
$screenshotId = $deployment [ 'body' ][ 'screenshotLight' ];
2025-03-11 13:17:23 +00:00
$file = $this -> client -> call ( Client :: METHOD_GET , " /storage/buckets/screenshots/files/ $screenshotId /view?project=console " , array_merge ([
2025-03-08 22:33:37 +00:00
], $this -> getHeaders ()));
$this -> assertEquals ( 200 , $file [ 'headers' ][ 'status-code' ]);
$this -> assertNotEmpty ( 200 , $file [ 'body' ]);
$this -> assertGreaterThan ( 1 , $file [ 'headers' ][ 'content-length' ]);
$this -> assertEquals ( 'image/png' , $file [ 'headers' ][ 'content-type' ]);
$screenshotHash = \md5 ( $file [ 'body' ]);
$this -> assertNotEmpty ( $screenshotHash );
$screenshotId = $deployment [ 'body' ][ 'screenshotDark' ];
2025-03-11 13:17:23 +00:00
$file = $this -> client -> call ( Client :: METHOD_GET , " /storage/buckets/screenshots/files/ $screenshotId /view?project=console " , array_merge ([
2025-03-08 22:33:37 +00:00
], $this -> getHeaders ()));
$this -> assertEquals ( 200 , $file [ 'headers' ][ 'status-code' ]);
$this -> assertNotEmpty ( 200 , $file [ 'body' ]);
$this -> assertGreaterThan ( 1 , $file [ 'headers' ][ 'content-length' ]);
$this -> assertEquals ( 'image/png' , $file [ 'headers' ][ 'content-type' ]);
$screenshotDarkHash = \md5 ( $file [ 'body' ]);
$this -> assertNotEmpty ( $screenshotDarkHash );
$this -> assertNotEquals ( $screenshotDarkHash , $screenshotHash );
2025-03-11 13:17:23 +00:00
$file = $this -> client -> call ( Client :: METHOD_GET , " /storage/buckets/screenshots/files/ $screenshotId /view?project=console " );
2025-03-08 22:33:37 +00:00
$this -> assertEquals ( 404 , $file [ 'headers' ][ 'status-code' ]);
2025-03-11 13:17:23 +00:00
$file = $this -> client -> call ( Client :: METHOD_GET , " /storage/buckets/screenshots/files/ $screenshotId /view?project=console " );
2025-03-08 22:33:37 +00:00
$this -> assertEquals ( 404 , $file [ 'headers' ][ 'status-code' ]);
$this -> cleanupSite ( $siteId );
}
public function testSiteDownload () : void
{
$siteId = $this -> setupSite ([
'buildRuntime' => 'node-22' ,
'fallbackFile' => '' ,
'framework' => 'other' ,
'name' => 'Test Site' ,
'adapter' => 'static' ,
'outputDirectory' => './' ,
'providerBranch' => 'main' ,
'providerRootDirectory' => './' ,
'siteId' => ID :: unique ()
]);
$deploymentId = $this -> setupDeployment ( $siteId , [
'code' => $this -> packageSite ( 'static' ),
'activate' => true
]);
$this -> assertNotEmpty ( $deploymentId );
$response = $this -> getDeploymentDownload ( $siteId , $deploymentId , 'source' );
$this -> assertEquals ( 200 , $response [ 'headers' ][ 'status-code' ]);
$this -> assertEquals ( 'application/gzip' , $response [ 'headers' ][ 'content-type' ]);
$this -> assertGreaterThan ( 0 , $response [ 'headers' ][ 'content-length' ]);
$this -> assertGreaterThan ( 0 , \strlen ( $response [ 'body' ]));
$deploymentMd5 = \md5 ( $response [ 'body' ]);
$response = $this -> getDeploymentDownload ( $siteId , $deploymentId , 'output' );
$this -> assertEquals ( 200 , $response [ 'headers' ][ 'status-code' ]);
$this -> assertEquals ( 'application/gzip' , $response [ 'headers' ][ 'content-type' ]);
$this -> assertGreaterThan ( 0 , $response [ 'headers' ][ 'content-length' ]);
$this -> assertGreaterThan ( 0 , \strlen ( $response [ 'body' ]));
$buildMd5 = \md5 ( $response [ 'body' ]);
$this -> assertNotEquals ( $deploymentMd5 , $buildMd5 );
$this -> cleanupSite ( $siteId );
}
public function testSSRLogs () : void
{
$siteId = $this -> setupSite ([
'siteId' => ID :: unique (),
'name' => 'SSR site' ,
'framework' => 'astro' ,
'adapter' => 'ssr' ,
'buildRuntime' => 'node-22' ,
'outputDirectory' => './dist' ,
'buildCommand' => 'npm run build' ,
'installCommand' => 'npm install' ,
'fallbackFile' => '' ,
]);
$this -> assertNotEmpty ( $siteId );
$domain = $this -> setupSiteDomain ( $siteId );
$deploymentId = $this -> setupDeployment ( $siteId , [
'code' => $this -> packageSite ( 'astro' ),
'activate' => 'true'
]);
$this -> assertNotEmpty ( $deploymentId );
$domain = $this -> getSiteDomain ( $siteId );
$proxyClient = new Client ();
$proxyClient -> setEndpoint ( 'http://' . $domain );
$response = $proxyClient -> call ( Client :: METHOD_GET , '/logs-inline' );
$this -> assertEquals ( 200 , $response [ 'headers' ][ 'status-code' ]);
$this -> assertStringContainsString ( " Inline logs printed. " , $response [ 'body' ]);
$logs = $this -> listLogs ( $siteId , [
Query :: orderDesc ( '$createdAt' ) -> toString (),
Query :: limit ( 1 ) -> toString (),
]);
$this -> assertEquals ( 200 , $logs [ 'headers' ][ 'status-code' ]);
$this -> assertStringContainsString ( " GET " , $logs [ 'body' ][ 'executions' ][ 0 ][ 'requestMethod' ]);
$this -> assertStringContainsString ( " /logs-inline " , $logs [ 'body' ][ 'executions' ][ 0 ][ 'requestPath' ]);
$this -> assertStringContainsString ( " Log1 " , $logs [ 'body' ][ 'executions' ][ 0 ][ 'logs' ]);
$this -> assertStringContainsString ( " Log2 " , $logs [ 'body' ][ 'executions' ][ 0 ][ 'logs' ]);
$this -> assertStringContainsString ( " Error1 " , $logs [ 'body' ][ 'executions' ][ 0 ][ 'errors' ]);
$this -> assertStringContainsString ( " Error2 " , $logs [ 'body' ][ 'executions' ][ 0 ][ 'errors' ]);
$log1Id = $logs [ 'body' ][ 'executions' ][ 0 ][ '$id' ];
$this -> assertNotEmpty ( $log1Id );
$response = $proxyClient -> call ( Client :: METHOD_GET , '/logs-action' );
$this -> assertEquals ( 200 , $response [ 'headers' ][ 'status-code' ]);
$this -> assertStringContainsString ( " Action logs printed. " , $response [ 'body' ]);
$logs = $this -> listLogs ( $siteId , [
Query :: orderDesc ( '$createdAt' ) -> toString (),
Query :: limit ( 1 ) -> toString (),
]);
$this -> assertEquals ( 200 , $logs [ 'headers' ][ 'status-code' ]);
$this -> assertStringContainsString ( " GET " , $logs [ 'body' ][ 'executions' ][ 0 ][ 'requestMethod' ]);
$this -> assertStringContainsString ( " /logs-action " , $logs [ 'body' ][ 'executions' ][ 0 ][ 'requestPath' ]);
$this -> assertStringContainsString ( " Log1 " , $logs [ 'body' ][ 'executions' ][ 0 ][ 'logs' ]);
$this -> assertStringContainsString ( " Log2 " , $logs [ 'body' ][ 'executions' ][ 0 ][ 'logs' ]);
$this -> assertStringContainsString ( " Error1 " , $logs [ 'body' ][ 'executions' ][ 0 ][ 'errors' ]);
$this -> assertStringContainsString ( " Error2 " , $logs [ 'body' ][ 'executions' ][ 0 ][ 'errors' ]);
$log2Id = $logs [ 'body' ][ 'executions' ][ 0 ][ '$id' ];
$this -> assertNotEmpty ( $log2Id );
$this -> assertNotEquals ( $log1Id , $log2Id );
2025-03-25 13:44:14 +00:00
$site = $this -> updateSite (
[
'$id' => $siteId ,
'name' => 'SSR site' ,
'framework' => 'astro' ,
'adapter' => 'ssr' ,
'buildRuntime' => 'node-22' ,
'outputDirectory' => './dist' ,
'buildCommand' => 'npm run build' ,
'installCommand' => 'npm install' ,
'fallbackFile' => '' ,
'logging' => false // set logging to false
]
);
$this -> assertEquals ( 200 , $site [ 'headers' ][ 'status-code' ]);
$response = $proxyClient -> call ( Client :: METHOD_GET , '/logs-inline' );
$this -> assertEquals ( 200 , $response [ 'headers' ][ 'status-code' ]);
$this -> assertStringContainsString ( " Inline logs printed. " , $response [ 'body' ]);
$logs = $this -> listLogs ( $siteId , [
Query :: orderDesc ( '$createdAt' ) -> toString (),
Query :: limit ( 1 ) -> toString (),
]);
$this -> assertEquals ( 200 , $logs [ 'headers' ][ 'status-code' ]);
2025-03-25 14:32:29 +00:00
$this -> assertEquals ( " GET " , $logs [ 'body' ][ 'executions' ][ 0 ][ 'requestMethod' ]);
$this -> assertEquals ( " /logs-inline " , $logs [ 'body' ][ 'executions' ][ 0 ][ 'requestPath' ]);
$this -> assertEmpty ( $logs [ 'body' ][ 'executions' ][ 0 ][ 'logs' ]);
$this -> assertEmpty ( $logs [ 'body' ][ 'executions' ][ 0 ][ 'logs' ]);
$this -> assertEmpty ( $logs [ 'body' ][ 'executions' ][ 0 ][ 'errors' ]);
$this -> assertEmpty ( $logs [ 'body' ][ 'executions' ][ 0 ][ 'errors' ]);
2025-03-25 13:44:14 +00:00
$log1Id = $logs [ 'body' ][ 'executions' ][ 0 ][ '$id' ];
$this -> assertNotEmpty ( $log1Id );
$response = $proxyClient -> call ( Client :: METHOD_GET , '/logs-action' );
$this -> assertEquals ( 200 , $response [ 'headers' ][ 'status-code' ]);
$this -> assertStringContainsString ( " Action logs printed. " , $response [ 'body' ]);
$logs = $this -> listLogs ( $siteId , [
Query :: orderDesc ( '$createdAt' ) -> toString (),
Query :: limit ( 1 ) -> toString (),
]);
$this -> assertEquals ( 200 , $logs [ 'headers' ][ 'status-code' ]);
2025-03-25 14:32:29 +00:00
$this -> assertEquals ( " GET " , $logs [ 'body' ][ 'executions' ][ 0 ][ 'requestMethod' ]);
$this -> assertEquals ( " /logs-action " , $logs [ 'body' ][ 'executions' ][ 0 ][ 'requestPath' ]);
$this -> assertEmpty ( $logs [ 'body' ][ 'executions' ][ 0 ][ 'logs' ]);
$this -> assertEmpty ( $logs [ 'body' ][ 'executions' ][ 0 ][ 'logs' ]);
$this -> assertEmpty ( $logs [ 'body' ][ 'executions' ][ 0 ][ 'errors' ]);
$this -> assertEmpty ( $logs [ 'body' ][ 'executions' ][ 0 ][ 'errors' ]);
2025-03-25 13:44:14 +00:00
$log2Id = $logs [ 'body' ][ 'executions' ][ 0 ][ '$id' ];
$this -> assertNotEmpty ( $log2Id );
2025-03-08 22:33:37 +00:00
$this -> cleanupSite ( $siteId );
}
public function testDuplicateDeployment () : void
{
$siteId = $this -> setupSite ([
'buildRuntime' => 'node-22' ,
'framework' => 'other' ,
'name' => 'Duplicate deployment Site' ,
'adapter' => 'static' ,
'fallbackFile' => '404.html' ,
'siteId' => ID :: unique ()
]);
$this -> assertNotEmpty ( $siteId );
$domain = $this -> setupSiteDomain ( $siteId );
$this -> assertNotEmpty ( $domain );
$proxyClient = new Client ();
$proxyClient -> setEndpoint ( 'http://' . $domain );
$deploymentId1 = $this -> setupDeployment ( $siteId , [
'code' => $this -> packageSite ( 'static-spa' ),
'activate' => true
]);
$this -> assertNotEmpty ( $deploymentId1 );
$response = $proxyClient -> call ( Client :: METHOD_GET , '/not-found' );
$this -> assertStringContainsString ( " Customized 404 page " , $response [ 'body' ]);
$site = $this -> updateSite ([
'$id' => $siteId ,
'buildRuntime' => 'node-22' ,
'framework' => 'other' ,
'name' => 'Duplicate deployment Site' ,
'adapter' => 'static' ,
'fallbackFile' => 'index.html' ,
]);
$this -> assertEquals ( 200 , $site [ 'headers' ][ 'status-code' ]);
$this -> assertEquals ( 'index.html' , $site [ 'body' ][ 'fallbackFile' ]);
2025-03-17 16:35:03 +00:00
$deployment = $this -> createDuplicateDeployment ( $siteId , $deploymentId1 );
$this -> assertEquals ( 202 , $deployment [ 'headers' ][ 'status-code' ]);
$deploymentId2 = $deployment [ 'body' ][ '$id' ];
2025-03-08 22:33:37 +00:00
$this -> assertNotEmpty ( $deploymentId2 );
2025-03-17 16:35:03 +00:00
$deployment = $this -> getDeployment ( $siteId , $deploymentId2 );
$this -> assertEquals ( 200 , $deployment [ 'headers' ][ 'status-code' ]);
$this -> assertGreaterThan ( 0 , $deployment [ 'body' ][ 'sourceSize' ]);
$this -> assertEquals ( 0 , $deployment [ 'body' ][ 'buildSize' ]);
$this -> assertEquals ( $deployment [ 'body' ][ 'sourceSize' ], $deployment [ 'body' ][ 'totalSize' ]);
$this -> assertEventually ( function () use ( $siteId , $deploymentId2 ) {
$site = $this -> getSite ( $siteId );
$this -> assertEquals ( $deploymentId2 , $site [ 'body' ][ 'deploymentId' ]);
}, 50000 , 500 );
2025-03-08 22:33:37 +00:00
$response = $proxyClient -> call ( Client :: METHOD_GET , '/not-found' );
$this -> assertStringContainsString ( " Index page " , $response [ 'body' ]);
2025-03-17 16:35:03 +00:00
$deployment = $this -> getDeployment ( $siteId , $deploymentId2 );
$this -> assertEquals ( 200 , $deployment [ 'headers' ][ 'status-code' ]);
$this -> assertGreaterThan ( 0 , $deployment [ 'body' ][ 'sourceSize' ]);
$this -> assertGreaterThan ( 0 , $deployment [ 'body' ][ 'buildSize' ]);
$totalSize = $deployment [ 'body' ][ 'sourceSize' ] + $deployment [ 'body' ][ 'buildSize' ];
$this -> assertEquals ( $totalSize , $deployment [ 'body' ][ 'totalSize' ]);
2025-03-08 22:33:37 +00:00
$this -> cleanupSite ( $siteId );
}
public function testUpdateDeploymentStatus () : void
{
$siteId = $this -> setupSite ([
'buildRuntime' => 'node-22' ,
'framework' => 'other' ,
'name' => 'Activate test Site' ,
'siteId' => ID :: unique (),
'adapter' => 'static' ,
]);
$this -> assertNotEmpty ( $siteId );
2025-03-20 14:22:35 +00:00
$site = $this -> getSite ( $siteId );
$this -> assertEquals ( 200 , $site [ 'headers' ][ 'status-code' ]);
$this -> assertArrayHasKey ( 'latestDeploymentId' , $site [ 'body' ]);
$this -> assertArrayHasKey ( 'latestDeploymentCreatedAt' , $site [ 'body' ]);
$this -> assertArrayHasKey ( 'latestDeploymentStatus' , $site [ 'body' ]);
$this -> assertEmpty ( $site [ 'body' ][ 'latestDeploymentId' ]);
$this -> assertEmpty ( $site [ 'body' ][ 'latestDeploymentCreatedAt' ]);
$this -> assertEmpty ( $site [ 'body' ][ 'latestDeploymentStatus' ]);
2025-03-08 22:33:37 +00:00
$domain = $this -> setupSiteDomain ( $siteId );
$this -> assertNotEmpty ( $domain );
$proxyClient = new Client ();
$proxyClient -> setEndpoint ( 'http://' . $domain );
$deploymentId1 = $this -> setupDeployment ( $siteId , [
'code' => $this -> packageSite ( 'static' ),
'activate' => true
]);
$this -> assertNotEmpty ( $deploymentId1 );
2025-03-20 14:22:35 +00:00
$site = $this -> getSite ( $siteId );
$this -> assertEquals ( 200 , $site [ 'headers' ][ 'status-code' ]);
$this -> assertEquals ( $deploymentId1 , $site [ 'body' ][ 'latestDeploymentId' ]);
$this -> assertEquals ( 'ready' , $site [ 'body' ][ 'latestDeploymentStatus' ]);
2025-03-08 22:33:37 +00:00
$response = $proxyClient -> call ( Client :: METHOD_GET , '/' );
$this -> assertEquals ( 200 , $response [ 'headers' ][ 'status-code' ]);
$this -> assertStringContainsString ( 'Hello Appwrite' , $response [ 'body' ]);
$deploymentId2 = $this -> setupDeployment ( $siteId , [
'code' => $this -> packageSite ( 'static-spa' ),
'activate' => true
]);
$this -> assertNotEmpty ( $deploymentId2 );
2025-03-20 14:22:35 +00:00
$site = $this -> getSite ( $siteId );
$this -> assertEquals ( 200 , $site [ 'headers' ][ 'status-code' ]);
$this -> assertEquals ( $deploymentId2 , $site [ 'body' ][ 'latestDeploymentId' ]);
$this -> assertEquals ( 'ready' , $site [ 'body' ][ 'latestDeploymentStatus' ]);
2025-03-08 22:33:37 +00:00
$response = $proxyClient -> call ( Client :: METHOD_GET , '/' );
$this -> assertEquals ( 200 , $response [ 'headers' ][ 'status-code' ]);
$this -> assertStringContainsString ( 'Index page' , $response [ 'body' ]);
2025-03-20 14:22:35 +00:00
$site = $this -> getSite ( $siteId );
$this -> assertEquals ( 200 , $site [ 'headers' ][ 'status-code' ]);
$this -> assertEquals ( $deploymentId2 , $site [ 'body' ][ 'deploymentId' ]);
$this -> assertEquals ( $deploymentId2 , $site [ 'body' ][ 'latestDeploymentId' ]);
$this -> assertEquals ( 'ready' , $site [ 'body' ][ 'latestDeploymentStatus' ]);
2025-03-08 22:33:37 +00:00
2025-03-20 14:22:35 +00:00
$site = $this -> updateSiteDeployment ( $siteId , $deploymentId1 );
$this -> assertEquals ( 200 , $site [ 'headers' ][ 'status-code' ]);
$this -> assertEquals ( $deploymentId1 , $site [ 'body' ][ 'deploymentId' ]);
2025-03-08 22:33:37 +00:00
2025-03-20 14:22:35 +00:00
$site = $this -> getSite ( $siteId );
$this -> assertEquals ( 200 , $site [ 'headers' ][ 'status-code' ]);
$this -> assertEquals ( $deploymentId1 , $site [ 'body' ][ 'deploymentId' ]);
$this -> assertEquals ( $deploymentId2 , $site [ 'body' ][ 'latestDeploymentId' ]);
$this -> assertEquals ( 'ready' , $site [ 'body' ][ 'latestDeploymentStatus' ]);
2025-03-08 22:33:37 +00:00
$response = $proxyClient -> call ( Client :: METHOD_GET , '/' );
$this -> assertEquals ( 200 , $response [ 'headers' ][ 'status-code' ]);
$this -> assertStringContainsString ( 'Hello Appwrite' , $response [ 'body' ]);
2025-03-20 14:22:35 +00:00
$deployment = $this -> deleteDeployment ( $siteId , $deploymentId2 );
$this -> assertEquals ( 204 , $deployment [ 'headers' ][ 'status-code' ]);
$site = $this -> getSite ( $siteId );
$this -> assertEquals ( 200 , $site [ 'headers' ][ 'status-code' ]);
$this -> assertEquals ( $deploymentId1 , $site [ 'body' ][ 'latestDeploymentId' ]);
$this -> assertEquals ( 'ready' , $site [ 'body' ][ 'latestDeploymentStatus' ]);
2025-03-08 22:33:37 +00:00
$this -> cleanupSite ( $siteId );
}
public function testPreviewDomain () : void
{
$siteId = $this -> setupSite ([
'buildRuntime' => 'node-22' ,
'framework' => 'other' ,
'name' => 'Authorized preview site' ,
'siteId' => ID :: unique (),
'adapter' => 'static' ,
]);
$this -> assertNotEmpty ( $siteId );
$deploymentId = $this -> setupDeployment ( $siteId , [
'code' => $this -> packageSite ( 'static' ),
'activate' => true
]);
$this -> assertNotEmpty ( $deploymentId );
$domain = $this -> getDeploymentDomain ( $deploymentId );
$this -> assertNotEmpty ( $domain );
$proxyClient = new Client ();
$proxyClient -> setEndpoint ( 'http://' . $domain );
$response = $proxyClient -> call ( Client :: METHOD_GET , '/contact' , followRedirects : false );
$this -> assertEquals ( 301 , $response [ 'headers' ][ 'status-code' ]);
$this -> assertStringContainsString ( '/console/auth/preview' , $response [ 'headers' ][ 'location' ]);
$this -> assertStringContainsString ( 'projectId=' . $this -> getProject ()[ '$id' ], $response [ 'headers' ][ 'location' ]);
$this -> assertStringContainsString ( 'origin=' , $response [ 'headers' ][ 'location' ]);
$this -> assertStringContainsString ( 'path=%2Fcontact' , $response [ 'headers' ][ 'location' ]);
$session = $this -> client -> call ( Client :: METHOD_POST , '/account/sessions/email' , array_merge ([
'origin' => 'http://localhost' ,
'content-type' => 'application/json' ,
'x-appwrite-project' => 'console' ,
]), [
'email' => $this -> getRoot ()[ 'email' ],
'password' => 'password'
]);
$this -> assertEquals ( 201 , $session [ 'headers' ][ 'status-code' ]);
$this -> assertNotEmpty ( $session [ 'cookies' ][ 'a_session_console' ]);
$this -> assertNotEmpty ( $session [ 'body' ][ '$id' ]);
$cookie = 'a_session_console=' . $session [ 'cookies' ][ 'a_session_console' ];
$jwt = $this -> client -> call ( Client :: METHOD_POST , '/account/jwts' , array_merge ([
'origin' => 'http://localhost' ,
'content-type' => 'application/json' ,
'cookie' => $cookie ,
'x-appwrite-project' => 'console' ,
]), []);
$this -> assertEquals ( 201 , $jwt [ 'headers' ][ 'status-code' ]);
$this -> assertNotEmpty ( $jwt [ 'body' ][ 'jwt' ]);
$response = $proxyClient -> call ( Client :: METHOD_GET , '/_appwrite/authorize' , params : [
'jwt' => $jwt [ 'body' ][ 'jwt' ],
'path' => '/contact'
], followRedirects : false );
$this -> assertEquals ( 301 , $response [ 'headers' ][ 'status-code' ]);
$this -> assertArrayHasKey ( 'set-cookie' , $response [ 'headers' ]);
$this -> assertStringContainsString ( 'a_jwt_console=' , $response [ 'headers' ][ 'set-cookie' ]);
$this -> assertStringContainsString ( 'httponly' , $response [ 'headers' ][ 'set-cookie' ]);
$this -> assertStringContainsString ( 'domain=' . $domain , $response [ 'headers' ][ 'set-cookie' ]);
$this -> assertStringContainsString ( 'path=/' , $response [ 'headers' ][ 'set-cookie' ]);
$this -> assertNotEmpty ( $response [ 'cookies' ][ 'a_jwt_console' ]);
$this -> assertEquals ( $jwt [ 'body' ][ 'jwt' ], $response [ 'cookies' ][ 'a_jwt_console' ]);
$response = $proxyClient -> call ( Client :: METHOD_GET , '/contact' , headers : [
'cookie' => 'a_jwt_console=' . $jwt [ 'body' ][ 'jwt' ]
], followRedirects : false );
$this -> assertEquals ( 200 , $response [ 'headers' ][ 'status-code' ]);
$this -> assertStringContainsString ( " Contact page " , $response [ 'body' ]);
$this -> assertStringContainsString ( " Preview by " , $response [ 'body' ]);
// Failure: Session missing (old bad, new ok)
$session = $this -> client -> call ( Client :: METHOD_DELETE , '/account/sessions/current' , array_merge ([
'origin' => 'http://localhost' ,
'content-type' => 'application/json' ,
'cookie' => $cookie ,
'x-appwrite-project' => 'console' ,
]), []);
$this -> assertEquals ( 204 , $session [ 'headers' ][ 'status-code' ]);
$response = $proxyClient -> call ( Client :: METHOD_GET , '/contact' , headers : [
'cookie' => 'a_jwt_console=' . $jwt [ 'body' ][ 'jwt' ]
], followRedirects : false );
$this -> assertEquals ( 301 , $response [ 'headers' ][ 'status-code' ]);
$this -> assertStringContainsString ( '/console/auth/preview' , $response [ 'headers' ][ 'location' ]);
// Failure: User missing
$cookie = 'a_session_console=' . $this -> getRoot ()[ 'session' ];
$jwt = $this -> client -> call ( Client :: METHOD_POST , '/account/jwts' , array_merge ([
'origin' => 'http://localhost' ,
'content-type' => 'application/json' ,
'cookie' => $cookie ,
'x-appwrite-project' => 'console' ,
]), []);
$this -> assertEquals ( 201 , $jwt [ 'headers' ][ 'status-code' ]);
$this -> assertNotEmpty ( $jwt [ 'body' ][ 'jwt' ]);
$response = $proxyClient -> call ( Client :: METHOD_GET , '/contact' , headers : [
'cookie' => 'a_jwt_console=' . $jwt [ 'body' ][ 'jwt' ]
], followRedirects : false );
$this -> assertEquals ( 200 , $response [ 'headers' ][ 'status-code' ]);
$this -> assertStringContainsString ( " Contact page " , $response [ 'body' ]);
$this -> assertStringContainsString ( " Preview by " , $response [ 'body' ]);
$user = $this -> client -> call ( Client :: METHOD_PATCH , '/account/status' , array_merge ([
'origin' => 'http://localhost' ,
'content-type' => 'application/json' ,
'cookie' => $cookie ,
'x-appwrite-project' => 'console' ,
]), []);
$this -> assertEquals ( 200 , $user [ 'headers' ][ 'status-code' ]);
$this -> assertFalse ( $user [ 'body' ][ 'status' ]);
$response = $proxyClient -> call ( Client :: METHOD_GET , '/contact' , headers : [
'cookie' => 'a_jwt_console=' . $jwt [ 'body' ][ 'jwt' ]
], followRedirects : false );
$this -> assertEquals ( 301 , $response [ 'headers' ][ 'status-code' ]);
$this -> assertStringContainsString ( '/console/auth/preview' , $response [ 'headers' ][ 'location' ]);
// Failure: Membership missing
2025-03-13 09:33:28 +00:00
$email = \uniqid () . 'newuser@appwrite.io' ;
2025-03-08 22:33:37 +00:00
$user = $this -> client -> call ( Client :: METHOD_POST , '/account' , [
'origin' => 'http://localhost' ,
'content-type' => 'application/json' ,
'x-appwrite-project' => 'console' ,
], [
'userId' => ID :: unique (),
2025-03-13 09:33:28 +00:00
'email' => $email ,
2025-03-08 22:33:37 +00:00
'password' => 'password'
]);
$this -> assertEquals ( 201 , $user [ 'headers' ][ 'status-code' ]);
$session = $this -> client -> call ( Client :: METHOD_POST , '/account/sessions/email' , [
'origin' => 'http://localhost' ,
'content-type' => 'application/json' ,
'x-appwrite-project' => 'console' ,
], [
2025-03-13 09:33:28 +00:00
'email' => $email ,
2025-03-08 22:33:37 +00:00
'password' => 'password' ,
]);
$this -> assertEquals ( 201 , $session [ 'headers' ][ 'status-code' ]);
$this -> assertNotEmpty ( $session [ 'cookies' ][ 'a_session_console' ]);
$cookie = 'a_session_console=' . $session [ 'cookies' ][ 'a_session_console' ];
$jwt = $this -> client -> call ( Client :: METHOD_POST , '/account/jwts' , array_merge ([
'origin' => 'http://localhost' ,
'content-type' => 'application/json' ,
'cookie' => $cookie ,
'x-appwrite-project' => 'console' ,
]), []);
$this -> assertEquals ( 201 , $jwt [ 'headers' ][ 'status-code' ]);
$this -> assertNotEmpty ( $jwt [ 'body' ][ 'jwt' ]);
$response = $proxyClient -> call ( Client :: METHOD_GET , '/contact' , headers : [
'cookie' => 'a_jwt_console=' . $jwt [ 'body' ][ 'jwt' ]
], followRedirects : false );
$this -> assertEquals ( 301 , $response [ 'headers' ][ 'status-code' ]);
$this -> assertStringContainsString ( '/console/auth/preview' , $response [ 'headers' ][ 'location' ]);
$this -> cleanupSite ( $siteId );
}
2025-03-12 11:13:46 +00:00
public function testInvalidSSRSource () : void
{
$siteId = $this -> setupSite ([
'siteId' => ID :: unique (),
'name' => 'Astro SSR Site' ,
'framework' => 'astro' ,
'adapter' => 'ssr' ,
'buildRuntime' => 'node-22' ,
'outputDirectory' => './dist' ,
'buildCommand' => 'npm run build' ,
'installCommand' => 'npm install' ,
]);
$this -> assertNotEmpty ( $siteId );
$site = $this -> getSite ( $siteId );
$this -> assertEquals ( 200 , $site [ 'headers' ][ 'status-code' ]);
$this -> assertArrayHasKey ( 'adapter' , $site [ 'body' ]);
$this -> assertEquals ( 'ssr' , $site [ 'body' ][ 'adapter' ]);
$deployment = $this -> createDeployment ( $siteId , [
'code' => $this -> packageSite ( 'astro-static' ),
'activate' => true
]);
$this -> assertEquals ( 202 , $deployment [ 'headers' ][ 'status-code' ]);
$deploymentId = $deployment [ 'body' ][ '$id' ];
$this -> assertNotEmpty ( $deploymentId );
$this -> assertEventually ( function () use ( $siteId , $deploymentId ) {
$deployment = $this -> getDeployment ( $siteId , $deploymentId );
$this -> assertEquals ( 'failed' , $deployment [ 'body' ][ 'status' ], 'Deployment status is failed, deployment: ' . json_encode ( $deployment [ 'body' ], JSON_PRETTY_PRINT ));
}, 100000 , 500 );
$this -> cleanupSite ( $siteId );
}
2025-03-21 12:23:22 +00:00
2025-03-21 12:24:07 +00:00
public function testPermanentRedirect () : void
2025-03-21 12:23:22 +00:00
{
$siteId = $this -> setupSite ([
'siteId' => ID :: unique (),
'name' => 'Sub project site' ,
'framework' => 'other' ,
'buildRuntime' => 'node-22' ,
'outputDirectory' => './'
]);
$this -> assertNotEmpty ( $siteId );
$site = $this -> getSite ( $siteId );
$this -> assertEquals ( '200' , $site [ 'headers' ][ 'status-code' ]);
$this -> assertArrayHasKey ( 'adapter' , $site [ 'body' ]);
$domain = $this -> setupSiteDomain ( $siteId );
$this -> assertNotEmpty ( $domain );
$deploymentId = $this -> setupDeployment ( $siteId , [
'code' => $this -> packageSite ( 'subProjects' ),
'activate' => 'true'
]);
$this -> assertNotEmpty ( $deploymentId );
$site = $this -> getSite ( $siteId );
$proxyClient = new Client ();
$proxyClient -> setEndpoint ( 'http://' . $domain );
$response = $proxyClient -> call ( Client :: METHOD_GET , '/' );
$this -> assertEquals ( 200 , $response [ 'headers' ][ 'status-code' ]);
$response1 = $proxyClient -> call ( Client :: METHOD_GET , '/project1' );
$this -> assertEquals ( 200 , $response1 [ 'headers' ][ 'status-code' ]);
$response2 = $proxyClient -> call ( Client :: METHOD_GET , '/project1/' );
$this -> assertEquals ( 308 , $response2 [ 'headers' ][ 'status-code' ]);
$this -> cleanupSite ( $siteId );
}
2025-01-01 20:51:30 +00:00
}