mirror of
https://github.com/appwrite/appwrite
synced 2026-05-22 16:38:32 +00:00
Merge pull request #9182 from appwrite/feat-add-tests-for-sites
Add tests for sites
This commit is contained in:
commit
d30af2c561
16 changed files with 1271 additions and 27 deletions
1
.github/workflows/tests.yml
vendored
1
.github/workflows/tests.yml
vendored
|
|
@ -122,6 +122,7 @@ jobs:
|
|||
Locale,
|
||||
Projects,
|
||||
Realtime,
|
||||
Sites,
|
||||
Storage,
|
||||
Teams,
|
||||
Users,
|
||||
|
|
|
|||
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -3,6 +3,7 @@
|
|||
/node_modules/
|
||||
/tests/resources/storage/
|
||||
/tests/resources/functions/**/code.tar.gz
|
||||
/tests/resources/sites/**/code.tar.gz
|
||||
/app/sdks/*
|
||||
/.idea/
|
||||
!/.idea/workspace.xml
|
||||
|
|
|
|||
51
app/config/frameworks/specifications.php
Normal file
51
app/config/frameworks/specifications.php
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
<?php
|
||||
|
||||
use Appwrite\Sites\Specification;
|
||||
|
||||
return [
|
||||
Specification::S_05VCPU_512MB => [
|
||||
'slug' => Specification::S_05VCPU_512MB,
|
||||
'memory' => 512,
|
||||
'cpus' => 0.5
|
||||
],
|
||||
Specification::S_1VCPU_512MB => [
|
||||
'slug' => Specification::S_1VCPU_512MB,
|
||||
'memory' => 512,
|
||||
'cpus' => 1
|
||||
],
|
||||
Specification::S_1VCPU_1GB => [
|
||||
'slug' => Specification::S_1VCPU_1GB,
|
||||
'memory' => 1024,
|
||||
'cpus' => 1
|
||||
],
|
||||
Specification::S_2VCPU_2GB => [
|
||||
'slug' => Specification::S_2VCPU_2GB,
|
||||
'memory' => 2048,
|
||||
'cpus' => 2
|
||||
],
|
||||
Specification::S_2VCPU_4GB => [
|
||||
'slug' => Specification::S_2VCPU_4GB,
|
||||
'memory' => 4096,
|
||||
'cpus' => 2
|
||||
],
|
||||
Specification::S_4VCPU_4GB => [
|
||||
'slug' => Specification::S_4VCPU_4GB,
|
||||
'memory' => 4096,
|
||||
'cpus' => 4
|
||||
],
|
||||
Specification::S_4VCPU_8GB => [
|
||||
'slug' => Specification::S_4VCPU_8GB,
|
||||
'memory' => 8192,
|
||||
'cpus' => 4
|
||||
],
|
||||
Specification::S_8VCPU_4GB => [
|
||||
'slug' => Specification::S_8VCPU_4GB,
|
||||
'memory' => 4096,
|
||||
'cpus' => 8
|
||||
],
|
||||
Specification::S_8VCPU_8GB => [
|
||||
'slug' => Specification::S_8VCPU_8GB,
|
||||
'memory' => 8192,
|
||||
'cpus' => 8
|
||||
]
|
||||
];
|
||||
|
|
@ -426,13 +426,13 @@ App::get('/v1/proxy/subdomains')
|
|||
->param('resourceType', null, new WhiteList(['function', 'site']), 'Action definition for the rule. Possible values are "function" and "site"')
|
||||
->param('subdomain', '', new Text(256), 'Subdomain name.')
|
||||
->inject('response')
|
||||
->inject('dbForConsole')
|
||||
->action(function (string $resourceType, string $subdomain, Response $response, Database $dbForConsole) {
|
||||
->inject('dbForPlatform')
|
||||
->action(function (string $resourceType, string $subdomain, Response $response, Database $dbForPlatform) {
|
||||
//TODO: Add tests for this endpoint
|
||||
$resourceDomain = $resourceType === 'site' ? System::getEnv('_APP_DOMAIN_SITES', '') : System::getEnv('_APP_DOMAIN_FUNCTIONS', '');
|
||||
$domain = $subdomain . '.' . $resourceDomain;
|
||||
|
||||
$document = $dbForConsole->findOne('rules', [
|
||||
$document = $dbForPlatform->findOne('rules', [
|
||||
Query::equal('domain', [$domain]),
|
||||
]);
|
||||
|
||||
|
|
|
|||
|
|
@ -240,7 +240,7 @@ $createGitDeployments = function (GitHub $github, string $providerInstallationId
|
|||
$ruleId = md5($domain);
|
||||
|
||||
$rule = Authorization::skip(
|
||||
fn () => $dbForConsole->createDocument('rules', new Document([
|
||||
fn () => $dbForPlatform->createDocument('rules', new Document([
|
||||
'$id' => $ruleId,
|
||||
'projectId' => $project->getId(),
|
||||
'projectInternalId' => $project->getInternalId(),
|
||||
|
|
|
|||
|
|
@ -378,6 +378,7 @@ Config::load('storage-mimes', __DIR__ . '/config/storage/mimes.php');
|
|||
Config::load('storage-inputs', __DIR__ . '/config/storage/inputs.php');
|
||||
Config::load('storage-outputs', __DIR__ . '/config/storage/outputs.php');
|
||||
Config::load('runtime-specifications', __DIR__ . '/config/runtimes/specifications.php');
|
||||
Config::load('framework-specifications', __DIR__ . '/config/frameworks/specifications.php');
|
||||
Config::load('function-templates', __DIR__ . '/config/function-templates.php');
|
||||
Config::load('site-templates', __DIR__ . '/config/site-templates.php');
|
||||
|
||||
|
|
|
|||
|
|
@ -93,7 +93,7 @@ class Base extends Action
|
|||
->setTemplate($template);
|
||||
}
|
||||
|
||||
public function redeployVcsSite(Request $request, Document $site, Document $project, Document $installation, Database $dbForProject, Database $dbForConsole, Build $queueForBuilds, Document $template, GitHub $github)
|
||||
public function redeployVcsSite(Request $request, Document $site, Document $project, Document $installation, Database $dbForProject, Database $dbForPlatform, Build $queueForBuilds, Document $template, GitHub $github)
|
||||
{
|
||||
$deploymentId = ID::unique();
|
||||
$providerInstallationId = $installation->getAttribute('providerInstallationId', '');
|
||||
|
|
@ -169,7 +169,7 @@ class Base extends Action
|
|||
$ruleId = md5($domain);
|
||||
|
||||
$rule = Authorization::skip(
|
||||
fn () => $dbForConsole->createDocument('rules', new Document([
|
||||
fn () => $dbForPlatform->createDocument('rules', new Document([
|
||||
'$id' => $ruleId,
|
||||
'projectId' => $project->getId(),
|
||||
'projectInternalId' => $project->getInternalId(),
|
||||
|
|
|
|||
|
|
@ -65,7 +65,7 @@ class CreateDeployment extends Action
|
|||
->inject('request')
|
||||
->inject('response')
|
||||
->inject('dbForProject')
|
||||
->inject('dbForConsole')
|
||||
->inject('dbForPlatform')
|
||||
->inject('project')
|
||||
->inject('queueForEvents')
|
||||
->inject('deviceForSites')
|
||||
|
|
@ -75,7 +75,7 @@ class CreateDeployment extends Action
|
|||
->callback([$this, 'action']);
|
||||
}
|
||||
|
||||
public function action(string $siteId, ?string $installCommand, ?string $buildCommand, ?string $outputDirectory, mixed $code, mixed $activate, Request $request, Response $response, Database $dbForProject, Database $dbForConsole, Document $project, Event $queueForEvents, Device $deviceForSites, Device $deviceForFunctions, Device $deviceForLocal, Build $queueForBuilds)
|
||||
public function action(string $siteId, ?string $installCommand, ?string $buildCommand, ?string $outputDirectory, mixed $code, mixed $activate, Request $request, Response $response, Database $dbForProject, Database $dbForPlatform, Document $project, Event $queueForEvents, Device $deviceForSites, Device $deviceForFunctions, Device $deviceForLocal, Build $queueForBuilds)
|
||||
{
|
||||
$activate = \strval($activate) === 'true' || \strval($activate) === '1';
|
||||
|
||||
|
|
@ -225,7 +225,7 @@ class CreateDeployment extends Action
|
|||
$ruleId = md5($domain);
|
||||
|
||||
$rule = Authorization::skip(
|
||||
fn () => $dbForConsole->createDocument('rules', new Document([
|
||||
fn () => $dbForPlatform->createDocument('rules', new Document([
|
||||
'$id' => $ruleId,
|
||||
'projectId' => $project->getId(),
|
||||
'projectInternalId' => $project->getInternalId(),
|
||||
|
|
@ -280,7 +280,7 @@ class CreateDeployment extends Action
|
|||
$ruleId = md5($domain);
|
||||
|
||||
$rule = Authorization::skip(
|
||||
fn () => $dbForConsole->createDocument('rules', new Document([
|
||||
fn () => $dbForPlatform->createDocument('rules', new Document([
|
||||
'$id' => $ruleId,
|
||||
'projectId' => $project->getId(),
|
||||
'projectInternalId' => $project->getInternalId(),
|
||||
|
|
|
|||
|
|
@ -54,11 +54,11 @@ class ListDeployments extends Action
|
|||
->inject('response')
|
||||
->inject('project')
|
||||
->inject('dbForProject')
|
||||
->inject('dbForConsole')
|
||||
->inject('dbForPlatform')
|
||||
->callback([$this, 'action']);
|
||||
}
|
||||
|
||||
public function action(string $siteId, array $queries, string $search, Response $response, Document $project, Database $dbForProject, Database $dbForConsole)
|
||||
public function action(string $siteId, array $queries, string $search, Response $response, Document $project, Database $dbForProject, Database $dbForPlatform)
|
||||
{
|
||||
$site = $dbForProject->getDocument('sites', $siteId);
|
||||
|
||||
|
|
@ -118,7 +118,7 @@ class ListDeployments extends Action
|
|||
$result->setAttribute('buildSize', $build->getAttribute('size', 0));
|
||||
$result->setAttribute('size', $result->getAttribute('size', 0));
|
||||
|
||||
$rule = Authorization::skip(fn () => $dbForConsole->findOne('rules', [
|
||||
$rule = Authorization::skip(fn () => $dbForPlatform->findOne('rules', [
|
||||
Query::equal("projectInternalId", [$project->getInternalId()]),
|
||||
Query::equal("resourceType", ["deployment"]),
|
||||
Query::equal("resourceInternalId", [$result->getInternalId()])
|
||||
|
|
|
|||
|
|
@ -90,12 +90,12 @@ class CreateSite extends Base
|
|||
->inject('user')
|
||||
->inject('queueForEvents')
|
||||
->inject('queueForBuilds')
|
||||
->inject('dbForConsole')
|
||||
->inject('dbForPlatform')
|
||||
->inject('gitHub')
|
||||
->callback([$this, 'action']);
|
||||
}
|
||||
|
||||
public function action(string $siteId, string $name, string $framework, bool $enabled, int $timeout, string $installCommand, string $buildCommand, string $outputDirectory, string $subdomain, string $buildRuntime, string $adapter, string $installationId, ?string $fallbackFile, string $providerRepositoryId, string $providerBranch, bool $providerSilentMode, string $providerRootDirectory, string $templateRepository, string $templateOwner, string $templateRootDirectory, string $templateVersion, string $specification, Request $request, Response $response, Database $dbForProject, Document $project, Document $user, Event $queueForEvents, Build $queueForBuilds, Database $dbForConsole, GitHub $github)
|
||||
public function action(string $siteId, string $name, string $framework, bool $enabled, int $timeout, string $installCommand, string $buildCommand, string $outputDirectory, string $subdomain, string $buildRuntime, string $adapter, string $installationId, ?string $fallbackFile, string $providerRepositoryId, string $providerBranch, bool $providerSilentMode, string $providerRootDirectory, string $templateRepository, string $templateOwner, string $templateRootDirectory, string $templateVersion, string $specification, Request $request, Response $response, Database $dbForProject, Document $project, Document $user, Event $queueForEvents, Build $queueForBuilds, Database $dbForPlatform, GitHub $github)
|
||||
{
|
||||
if (!empty($adapter)) {
|
||||
$configFramework = Config::getParam('frameworks')[$framework] ?? [];
|
||||
|
|
@ -114,7 +114,7 @@ class CreateSite extends Base
|
|||
$routeSubdomain = $subdomain ?: ID::unique();
|
||||
$domain = "{$routeSubdomain}.{$sitesDomain}";
|
||||
|
||||
$subdomain = Authorization::skip(fn () => $dbForConsole->getDocument('rules', \md5($domain)));
|
||||
$subdomain = Authorization::skip(fn () => $dbForPlatform->getDocument('rules', \md5($domain)));
|
||||
|
||||
if ($subdomain && !$subdomain->isEmpty()) {
|
||||
throw new Exception(Exception::GENERAL_ARGUMENT_INVALID, 'Subdomain already exists. Please choose a different subdomain.');
|
||||
|
|
@ -143,7 +143,7 @@ class CreateSite extends Base
|
|||
->setAttribute('version', $templateVersion);
|
||||
}
|
||||
|
||||
$installation = $dbForConsole->getDocument('installations', $installationId);
|
||||
$installation = $dbForPlatform->getDocument('installations', $installationId);
|
||||
|
||||
if (!empty($installationId) && $installation->isEmpty()) {
|
||||
throw new Exception(Exception::INSTALLATION_NOT_FOUND);
|
||||
|
|
@ -184,7 +184,7 @@ class CreateSite extends Base
|
|||
if (!empty($providerRepositoryId)) {
|
||||
$teamId = $project->getAttribute('teamId', '');
|
||||
|
||||
$repository = $dbForConsole->createDocument('repositories', new Document([
|
||||
$repository = $dbForPlatform->createDocument('repositories', new Document([
|
||||
'$id' => ID::unique(),
|
||||
'$permissions' => [
|
||||
Permission::read(Role::team(ID::custom($teamId))),
|
||||
|
|
@ -212,7 +212,7 @@ class CreateSite extends Base
|
|||
|
||||
if (!empty($providerRepositoryId)) {
|
||||
// Deploy VCS
|
||||
$this->redeployVcsSite($request, $site, $project, $installation, $dbForProject, $dbForConsole, $queueForBuilds, $template, $github);
|
||||
$this->redeployVcsSite($request, $site, $project, $installation, $dbForProject, $dbForPlatform, $queueForBuilds, $template, $github);
|
||||
} elseif (!$template->isEmpty()) {
|
||||
// Deploy non-VCS from template
|
||||
$deploymentId = ID::unique();
|
||||
|
|
@ -241,7 +241,7 @@ class CreateSite extends Base
|
|||
$previewDomain = "{$deploymentId}-{$projectId}.{$sitesDomain}";
|
||||
|
||||
$rule = Authorization::skip(
|
||||
fn () => $dbForConsole->createDocument('rules', new Document([
|
||||
fn () => $dbForPlatform->createDocument('rules', new Document([
|
||||
'$id' => \md5($previewDomain),
|
||||
'projectId' => $project->getId(),
|
||||
'projectInternalId' => $project->getInternalId(),
|
||||
|
|
@ -263,7 +263,7 @@ class CreateSite extends Base
|
|||
|
||||
if (!empty($sitesDomain)) {
|
||||
$rule = Authorization::skip(
|
||||
fn () => $dbForConsole->createDocument('rules', new Document([
|
||||
fn () => $dbForPlatform->createDocument('rules', new Document([
|
||||
'$id' => \md5($domain),
|
||||
'projectId' => $project->getId(),
|
||||
'projectInternalId' => $project->getInternalId(),
|
||||
|
|
|
|||
|
|
@ -82,12 +82,12 @@ class UpdateSite extends Base
|
|||
->inject('project')
|
||||
->inject('queueForEvents')
|
||||
->inject('queueForBuilds')
|
||||
->inject('dbForConsole')
|
||||
->inject('dbForPlatform')
|
||||
->inject('gitHub')
|
||||
->callback([$this, 'action']);
|
||||
}
|
||||
|
||||
public function action(string $siteId, string $name, string $framework, bool $enabled, int $timeout, string $installCommand, string $buildCommand, string $outputDirectory, string $buildRuntime, string $adapter, ?string $fallbackFile, string $installationId, ?string $providerRepositoryId, string $providerBranch, bool $providerSilentMode, string $providerRootDirectory, string $specification, Request $request, Response $response, Database $dbForProject, Document $project, Event $queueForEvents, Build $queueForBuilds, Database $dbForConsole, GitHub $github)
|
||||
public function action(string $siteId, string $name, string $framework, bool $enabled, int $timeout, string $installCommand, string $buildCommand, string $outputDirectory, string $buildRuntime, string $adapter, ?string $fallbackFile, string $installationId, ?string $providerRepositoryId, string $providerBranch, bool $providerSilentMode, string $providerRootDirectory, string $specification, Request $request, Response $response, Database $dbForProject, Document $project, Event $queueForEvents, Build $queueForBuilds, Database $dbForPlatform, GitHub $github)
|
||||
{
|
||||
if (!empty($adapter)) {
|
||||
$configFramework = Config::getParam('frameworks')[$framework] ?? [];
|
||||
|
|
@ -105,7 +105,7 @@ class UpdateSite extends Base
|
|||
throw new Exception(Exception::SITE_NOT_FOUND);
|
||||
}
|
||||
|
||||
$installation = $dbForConsole->getDocument('installations', $installationId);
|
||||
$installation = $dbForPlatform->getDocument('installations', $installationId);
|
||||
|
||||
if (!empty($installationId) && $installation->isEmpty()) {
|
||||
throw new Exception(Exception::INSTALLATION_NOT_FOUND);
|
||||
|
|
@ -132,7 +132,7 @@ class UpdateSite extends Base
|
|||
|
||||
// Git disconnect logic. Disconnecting only when providerRepositoryId is empty, allowing for continue updates without disconnecting git
|
||||
if ($isConnected && ($providerRepositoryId !== null && empty($providerRepositoryId))) {
|
||||
$repositories = $dbForConsole->find('repositories', [
|
||||
$repositories = $dbForPlatform->find('repositories', [
|
||||
Query::equal('projectInternalId', [$project->getInternalId()]),
|
||||
Query::equal('resourceInternalId', [$site->getInternalId()]),
|
||||
Query::equal('resourceType', ['site']),
|
||||
|
|
@ -140,7 +140,7 @@ class UpdateSite extends Base
|
|||
]);
|
||||
|
||||
foreach ($repositories as $repository) {
|
||||
$dbForConsole->deleteDocument('repositories', $repository->getId());
|
||||
$dbForPlatform->deleteDocument('repositories', $repository->getId());
|
||||
}
|
||||
|
||||
$providerRepositoryId = '';
|
||||
|
|
@ -156,7 +156,7 @@ class UpdateSite extends Base
|
|||
if (!$isConnected && !empty($providerRepositoryId)) {
|
||||
$teamId = $project->getAttribute('teamId', '');
|
||||
|
||||
$repository = $dbForConsole->createDocument('repositories', new Document([
|
||||
$repository = $dbForPlatform->createDocument('repositories', new Document([
|
||||
'$id' => ID::unique(),
|
||||
'$permissions' => [
|
||||
Permission::read(Role::team(ID::custom($teamId))),
|
||||
|
|
|
|||
16
src/Appwrite/Sites/Specification.php
Normal file
16
src/Appwrite/Sites/Specification.php
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
<?php
|
||||
|
||||
namespace Appwrite\Sites;
|
||||
|
||||
class Specification
|
||||
{
|
||||
public const S_05VCPU_512MB = 's-0.5vcpu-512mb';
|
||||
public const S_1VCPU_512MB = 's-1vcpu-512mb';
|
||||
public const S_1VCPU_1GB = 's-1vcpu-1gb';
|
||||
public const S_2VCPU_2GB = 's-2vcpu-2gb';
|
||||
public const S_2VCPU_4GB = 's-2vcpu-4gb';
|
||||
public const S_4VCPU_4GB = 's-4vcpu-4gb';
|
||||
public const S_4VCPU_8GB = 's-4vcpu-8gb';
|
||||
public const S_8VCPU_4GB = 's-8vcpu-4gb';
|
||||
public const S_8VCPU_8GB = 's-8vcpu-8gb';
|
||||
}
|
||||
|
|
@ -78,6 +78,8 @@ trait ProjectCustom
|
|||
'sites.write',
|
||||
'functions.read',
|
||||
'functions.write',
|
||||
'sites.read',
|
||||
'sites.write',
|
||||
'execution.read',
|
||||
'execution.write',
|
||||
'locale.read',
|
||||
|
|
|
|||
218
tests/e2e/Services/Sites/SitesBase.php
Normal file
218
tests/e2e/Services/Sites/SitesBase.php
Normal file
|
|
@ -0,0 +1,218 @@
|
|||
<?php
|
||||
|
||||
namespace Tests\E2E\Services\Sites;
|
||||
|
||||
use Appwrite\Tests\Async;
|
||||
use CURLFile;
|
||||
use Tests\E2E\Client;
|
||||
use Utopia\CLI\Console;
|
||||
|
||||
trait SitesBase
|
||||
{
|
||||
use Async;
|
||||
|
||||
protected string $stdout = '';
|
||||
protected string $stderr = '';
|
||||
|
||||
protected function setupSite(mixed $params): string
|
||||
{
|
||||
$site = $this->client->call(Client::METHOD_POST, '/sites', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey'],
|
||||
]), $params);
|
||||
|
||||
$this->assertEquals($site['headers']['status-code'], 201, 'Setup site failed with status code: ' . $site['headers']['status-code'] . ' and response: ' . json_encode($site['body'], JSON_PRETTY_PRINT));
|
||||
|
||||
$siteId = $site['body']['$id'];
|
||||
|
||||
return $siteId;
|
||||
}
|
||||
|
||||
protected function setupDeployment(string $siteId, mixed $params): string
|
||||
{
|
||||
$deployment = $this->client->call(Client::METHOD_POST, '/sites/' . $siteId . '/deployments', array_merge([
|
||||
'content-type' => 'multipart/form-data',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey'],
|
||||
]), $params);
|
||||
$this->assertEquals($deployment['headers']['status-code'], 202, 'Setup deployment failed with status code: ' . $deployment['headers']['status-code'] . ' and response: ' . json_encode($deployment['body'], JSON_PRETTY_PRINT));
|
||||
$deploymentId = $deployment['body']['$id'] ?? '';
|
||||
|
||||
$this->assertEventually(function () use ($siteId, $deploymentId) {
|
||||
$deployment = $this->client->call(Client::METHOD_GET, '/sites/' . $siteId . '/deployments/' . $deploymentId, array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey'],
|
||||
]));
|
||||
$this->assertEquals('ready', $deployment['body']['status'], 'Deployment status is not ready, deployment: ' . json_encode($deployment['body'], JSON_PRETTY_PRINT));
|
||||
}, 50000, 500);
|
||||
|
||||
return $deploymentId;
|
||||
}
|
||||
|
||||
protected function cleanupSite(string $siteId): void
|
||||
{
|
||||
$site = $this->client->call(Client::METHOD_DELETE, '/sites/' . $siteId, array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey'],
|
||||
]));
|
||||
|
||||
$this->assertEquals($site['headers']['status-code'], 204);
|
||||
}
|
||||
|
||||
protected function cleanupDeployment(string $siteId, string $deploymentId): void
|
||||
{
|
||||
$deployment = $this->client->call(Client::METHOD_DELETE, '/sites/' . $siteId . '/deployments/' . $deploymentId, array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey'],
|
||||
]));
|
||||
|
||||
$this->assertEquals($deployment['headers']['status-code'], 204);
|
||||
}
|
||||
|
||||
protected function createSite(mixed $params): mixed
|
||||
{
|
||||
$site = $this->client->call(Client::METHOD_POST, '/sites', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), $params);
|
||||
|
||||
return $site;
|
||||
}
|
||||
|
||||
protected function updateSite(mixed $params): mixed
|
||||
{
|
||||
$site = $this->client->call(Client::METHOD_PUT, '/sites/' . $params['$id'], array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), $params);
|
||||
|
||||
return $site;
|
||||
}
|
||||
|
||||
protected function createVariable(string $siteId, mixed $params): mixed
|
||||
{
|
||||
$variable = $this->client->call(Client::METHOD_POST, '/sites/' . $siteId . '/variables', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), $params);
|
||||
|
||||
return $variable;
|
||||
}
|
||||
|
||||
protected function getSite(string $siteId): mixed
|
||||
{
|
||||
$site = $this->client->call(Client::METHOD_GET, '/sites/' . $siteId, array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()));
|
||||
|
||||
return $site;
|
||||
}
|
||||
|
||||
protected function getDeployment(string $siteId, string $deploymentId): mixed
|
||||
{
|
||||
$deployment = $this->client->call(Client::METHOD_GET, '/sites/' . $siteId . '/deployments/' . $deploymentId, array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()));
|
||||
|
||||
return $deployment;
|
||||
}
|
||||
|
||||
protected function getLog(string $siteId, $logId): mixed
|
||||
{
|
||||
$log = $this->client->call(Client::METHOD_GET, '/sites/' . $siteId . '/logs/' . $logId, array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()));
|
||||
|
||||
return $log;
|
||||
}
|
||||
|
||||
protected function listSites(mixed $params = []): mixed
|
||||
{
|
||||
$sites = $this->client->call(Client::METHOD_GET, '/sites', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), $params);
|
||||
|
||||
return $sites;
|
||||
}
|
||||
|
||||
protected function listDeployments(string $siteId, $params = []): mixed
|
||||
{
|
||||
$deployments = $this->client->call(Client::METHOD_GET, '/sites/' . $siteId . '/deployments', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), $params);
|
||||
|
||||
return $deployments;
|
||||
}
|
||||
|
||||
protected function listLogs(string $siteId, mixed $params = []): mixed
|
||||
{
|
||||
$logs = $this->client->call(Client::METHOD_GET, '/sites/' . $siteId . '/logs', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), $params);
|
||||
|
||||
return $logs;
|
||||
}
|
||||
|
||||
protected function packageSite(string $site): CURLFile
|
||||
{
|
||||
$folderPath = realpath(__DIR__ . '/../../../resources/sites') . "/$site";
|
||||
$tarPath = "$folderPath/code.tar.gz";
|
||||
|
||||
Console::execute("cd $folderPath && tar --exclude code.tar.gz -czf code.tar.gz .", '', $this->stdout, $this->stderr);
|
||||
|
||||
if (filesize($tarPath) > 1024 * 1024 * 5) {
|
||||
throw new \Exception('Code package is too large. Use the chunked upload method instead.');
|
||||
}
|
||||
|
||||
return new CURLFile($tarPath, 'application/x-gzip', \basename($tarPath));
|
||||
}
|
||||
|
||||
protected function createDeployment(string $siteId, mixed $params = []): mixed
|
||||
{
|
||||
$deployment = $this->client->call(Client::METHOD_POST, '/sites/' . $siteId . '/deployments', array_merge([
|
||||
'content-type' => 'multipart/form-data',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), $params);
|
||||
|
||||
return $deployment;
|
||||
}
|
||||
|
||||
protected function getSiteUsage(string $siteId, mixed $params): mixed
|
||||
{
|
||||
$usage = $this->client->call(Client::METHOD_GET, '/sites/' . $siteId . '/usage', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), $params);
|
||||
|
||||
return $usage;
|
||||
}
|
||||
|
||||
protected function getTemplate(string $templateId)
|
||||
{
|
||||
$template = $this->client->call(Client::METHOD_GET, '/sites/templates/' . $templateId, array_merge([
|
||||
'content-type' => 'application/json'
|
||||
], $this->getHeaders()));
|
||||
|
||||
return $template;
|
||||
}
|
||||
|
||||
protected function deleteSite(string $siteId): mixed
|
||||
{
|
||||
$site = $this->client->call(Client::METHOD_DELETE, '/sites/' . $siteId, array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()));
|
||||
|
||||
return $site;
|
||||
}
|
||||
}
|
||||
943
tests/e2e/Services/Sites/SitesCustomServerTest.php
Normal file
943
tests/e2e/Services/Sites/SitesCustomServerTest.php
Normal file
|
|
@ -0,0 +1,943 @@
|
|||
<?php
|
||||
|
||||
namespace Tests\E2E\Services\Sites;
|
||||
|
||||
use Appwrite\Sites\Specification;
|
||||
use Tests\E2E\Client;
|
||||
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;
|
||||
use Utopia\Database\Validator\Datetime as DatetimeValidator;
|
||||
|
||||
class SitesCustomServerTest extends Scope
|
||||
{
|
||||
use SitesBase;
|
||||
use ProjectCustom;
|
||||
use SideServer;
|
||||
|
||||
public function testCreateSite(): void
|
||||
{
|
||||
/**
|
||||
* Test for SUCCESS
|
||||
*/
|
||||
$site = $this->createSite([
|
||||
'buildRuntime' => 'ssr-22',
|
||||
'fallbackFile' => null,
|
||||
'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('ssr-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 testListSites(): void
|
||||
{
|
||||
/**
|
||||
* Test for SUCCESS
|
||||
*/
|
||||
$siteId = $this->setupSite([
|
||||
'buildRuntime' => 'ssr-22',
|
||||
'fallbackFile' => null,
|
||||
'framework' => 'other',
|
||||
'name' => 'Test Site',
|
||||
'outputDirectory' => './',
|
||||
'providerBranch' => 'main',
|
||||
'providerRootDirectory' => './',
|
||||
'siteId' => ID::unique()
|
||||
]);
|
||||
|
||||
$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([
|
||||
'search' => 'other'
|
||||
]);
|
||||
|
||||
$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([
|
||||
'buildRuntime' => 'ssr-22',
|
||||
'fallbackFile' => null,
|
||||
'framework' => 'other',
|
||||
'name' => 'Test Site 2',
|
||||
'outputDirectory' => './',
|
||||
'providerBranch' => 'main',
|
||||
'providerRootDirectory' => './',
|
||||
'siteId' => ID::unique()
|
||||
]);
|
||||
|
||||
$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);
|
||||
}
|
||||
|
||||
public function testGetSite(): void
|
||||
{
|
||||
$siteId = $this->setupSite([
|
||||
'buildRuntime' => 'ssr-22',
|
||||
'fallbackFile' => null,
|
||||
'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' => 'ssr-22',
|
||||
'fallbackFile' => null,
|
||||
'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' => 'ssr-22',
|
||||
'fallbackFile' => null,
|
||||
'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 testCreateSiteAndDeploymentFromTemplate()
|
||||
{
|
||||
$starterTemplate = $this->getTemplate('nextjs-starter');
|
||||
$this->assertEquals(200, $starterTemplate['headers']['status-code']);
|
||||
|
||||
$nextjsFramework = array_values(array_filter($starterTemplate['body']['frameworks'], function ($framework) {
|
||||
return $framework['key'] === 'nextjs';
|
||||
}))[0];
|
||||
|
||||
// If this fails, the template has variables, and this test needs to be updated
|
||||
$this->assertEmpty($starterTemplate['body']['variables']);
|
||||
|
||||
$site = $this->createSite(
|
||||
[
|
||||
'siteId' => ID::unique(),
|
||||
'name' => $starterTemplate['body']['name'],
|
||||
'framework' => $nextjsFramework['key'],
|
||||
'adapter' => $nextjsFramework['adapter'],
|
||||
'buildCommand' => $nextjsFramework['buildCommand'],
|
||||
'buildRuntime' => $nextjsFramework['buildRuntime'],
|
||||
'fallbackFile' => $nextjsFramework['fallbackFile'],
|
||||
'installCommand' => $nextjsFramework['installCommand'],
|
||||
'outputDirectory' => $nextjsFramework['outputDirectory'],
|
||||
'providerRootDirectory' => $nextjsFramework['providerRootDirectory'],
|
||||
'templateOwner' => $starterTemplate['body']['providerOwner'],
|
||||
'templateRepository' => $starterTemplate['body']['providerRepositoryId'],
|
||||
'templateRootDirectory' => $nextjsFramework['providerRootDirectory'],
|
||||
'templateVersion' => $starterTemplate['body']['providerVersion'],
|
||||
'providerBranch' => 'main',
|
||||
]
|
||||
);
|
||||
|
||||
$this->assertEquals(201, $site['headers']['status-code']);
|
||||
$this->assertNotEmpty($site['body']['$id']);
|
||||
|
||||
$siteId = $site['body']['$id'] ?? '';
|
||||
|
||||
$deployments = $this->listDeployments($siteId);
|
||||
|
||||
$this->assertEquals(200, $deployments['headers']['status-code']);
|
||||
$this->assertEquals(1, $deployments['body']['total']);
|
||||
|
||||
$lastDeployment = $deployments['body']['deployments'][0];
|
||||
|
||||
$this->assertNotEmpty($lastDeployment['$id']);
|
||||
$this->assertEquals(0, $lastDeployment['size']);
|
||||
|
||||
$deploymentId = $lastDeployment['$id'];
|
||||
|
||||
$this->assertEventually(function () use ($siteId, $deploymentId) {
|
||||
$deployment = $this->getDeployment($siteId, $deploymentId);
|
||||
|
||||
$this->assertEquals(200, $deployment['headers']['status-code']);
|
||||
$this->assertEquals('ready', $deployment['body']['status']);
|
||||
}, 300000, 1000);
|
||||
|
||||
$site = $this->getSite($siteId);
|
||||
$this->assertEquals(200, $site['headers']['status-code']);
|
||||
|
||||
$this->cleanupSite($siteId);
|
||||
}
|
||||
|
||||
public function testCreateDeployment()
|
||||
{
|
||||
$siteId = $this->setupSite([
|
||||
'buildRuntime' => 'ssr-22',
|
||||
'fallbackFile' => null,
|
||||
'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']);
|
||||
$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);
|
||||
}
|
||||
|
||||
public function testCancelDeploymentBuild(): void
|
||||
{
|
||||
$siteId = $this->setupSite([
|
||||
'buildRuntime' => 'ssr-22',
|
||||
'fallbackFile' => null,
|
||||
'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);
|
||||
|
||||
// Cancel the deployment
|
||||
$cancel = $this->client->call(Client::METHOD_PATCH, '/sites/' . $siteId . '/deployments/' . $deploymentId . '/build', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()));
|
||||
|
||||
$this->assertEquals(200, $cancel['headers']['status-code']);
|
||||
$this->assertEquals('canceled', $cancel['body']['status']);
|
||||
|
||||
/**
|
||||
* Build worker still runs the build.
|
||||
* 30s 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' => 'ssr-22',
|
||||
'fallbackFile' => null,
|
||||
'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->client->call(Client::METHOD_PATCH, '/sites/' . $siteId . '/deployments/' . $deploymentId, array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), []);
|
||||
|
||||
$this->assertEquals(200, $response['headers']['status-code']);
|
||||
$this->assertNotEmpty($response['body']['$id']);
|
||||
$this->assertEquals(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' => 'ssr-22',
|
||||
'fallbackFile' => null,
|
||||
'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('size', $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('size', 10000)->toString(),
|
||||
],
|
||||
]
|
||||
);
|
||||
|
||||
$this->assertEquals($deployments['headers']['status-code'], 200);
|
||||
$this->assertEquals(0, $deployments['body']['total']);
|
||||
|
||||
$deployments = $this->listDeployments(
|
||||
$siteId,
|
||||
[
|
||||
'queries' => [
|
||||
Query::greaterThan('size', 0)->toString(),
|
||||
],
|
||||
]
|
||||
);
|
||||
|
||||
$this->assertEquals($deployments['headers']['status-code'], 200);
|
||||
$this->assertEquals(2, $deployments['body']['total']);
|
||||
|
||||
$deployments = $this->listDeployments(
|
||||
$siteId,
|
||||
[
|
||||
'queries' => [
|
||||
Query::greaterThan('size', -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]['size']);
|
||||
|
||||
$deploymentId = $deployments['body']['deployments'][0]['$id'];
|
||||
$deploymentSize = $deployments['body']['deployments'][0]['size'];
|
||||
|
||||
$deployments = $this->listDeployments(
|
||||
$siteId,
|
||||
[
|
||||
'queries' => [
|
||||
Query::equal('size', [$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['size']);
|
||||
}
|
||||
|
||||
$this->cleanupDeployment($siteId, $deploymentIdActive);
|
||||
$this->cleanupDeployment($siteId, $deploymentIdInactive);
|
||||
$this->cleanupSite($siteId);
|
||||
}
|
||||
|
||||
public function testGetDeployment(): void
|
||||
{
|
||||
$siteId = $this->setupSite([
|
||||
'buildRuntime' => 'ssr-22',
|
||||
'fallbackFile' => null,
|
||||
'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']['buildTime']);
|
||||
$this->assertNotEmpty($deployment['body']['status']);
|
||||
$this->assertNotEmpty($deployment['body']['buildLogs']);
|
||||
$this->assertArrayHasKey('size', $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 testLoadSite(): void
|
||||
// {
|
||||
// $site = $this->createSite([
|
||||
// 'buildRuntime' => 'ssr-22',
|
||||
// 'fallbackFile' => null,
|
||||
// 'framework' => 'other',
|
||||
// 'name' => 'Test Site',
|
||||
// 'outputDirectory' => './',
|
||||
// 'providerBranch' => 'main',
|
||||
// 'providerRootDirectory' => './',
|
||||
// 'siteId' => ID::unique()
|
||||
// ]);
|
||||
|
||||
// $siteId = $site['body']['$id'] ?? '';
|
||||
// $this->assertNotEmpty($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']);
|
||||
// }, 30000, 300);
|
||||
|
||||
// // get rule for this site from rules collection
|
||||
|
||||
// $response = $this->client->call(Client::METHOD_GET, $domain);
|
||||
// var_dump($response);
|
||||
// }
|
||||
|
||||
public function testUpdateSpecs(): void
|
||||
{
|
||||
$siteId = $this->setupSite([
|
||||
'buildRuntime' => 'ssr-22',
|
||||
'fallbackFile' => null,
|
||||
'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' => 'ssr-22',
|
||||
'fallbackFile' => null,
|
||||
'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' => 'ssr-22',
|
||||
'fallbackFile' => null,
|
||||
'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' => 'ssr-22',
|
||||
'fallbackFile' => null,
|
||||
'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' => 'ssr-22',
|
||||
'fallbackFile' => null,
|
||||
'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' => 'ssr-22',
|
||||
'fallbackFile' => null,
|
||||
'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);
|
||||
}
|
||||
|
||||
// TODO: Add tests for deletion of resources when site is deleted
|
||||
}
|
||||
11
tests/resources/sites/static/index.html
Normal file
11
tests/resources/sites/static/index.html
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Hello Appwrite</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Hello Appwrite</h1>
|
||||
</body>
|
||||
</html>
|
||||
Loading…
Reference in a new issue