appwrite/tests/e2e/Services/GraphQL/TablesDB/DatabaseServerTest.php
2026-03-31 22:04:37 +05:30

2752 lines
99 KiB
PHP

<?php
namespace Tests\E2E\Services\GraphQL\TablesDB;
use Exception;
use Tests\E2E\Client;
use Tests\E2E\Scopes\ProjectCustom;
use Tests\E2E\Scopes\Scope;
use Tests\E2E\Scopes\SideServer;
use Tests\E2E\Services\GraphQL\Base;
use Utopia\Database\Database;
use Utopia\Database\Helpers\ID;
use Utopia\Database\Helpers\Permission;
use Utopia\Database\Helpers\Role;
use Utopia\Database\Query;
class DatabaseServerTest extends Scope
{
use ProjectCustom;
use SideServer;
use Base;
private static array $cachedDatabase = [];
private static array $cachedTableData = [];
private static array $cachedStringColumnData = [];
private static array $cachedIntegerColumnData = [];
private static array $cachedBooleanColumnData = [];
private static array $cachedFloatColumnData = [];
private static array $cachedEmailColumnData = [];
private static array $cachedEnumColumnData = [];
private static array $cachedDatetimeColumnData = [];
private static array $cachedRelationshipColumnData = [];
private static array $cachedIPColumnData = [];
private static array $cachedURLColumnData = [];
private static array $cachedIndexData = [];
private static array $cachedRowData = [];
private static array $cachedBulkData = [];
protected function setupDatabase(): array
{
$cacheKey = $this->getProject()['$id'] ?? 'default';
if (!empty(self::$cachedDatabase[$cacheKey])) {
return self::$cachedDatabase[$cacheKey];
}
$projectId = $this->getProject()['$id'];
$headers = array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $projectId,
], $this->getHeaders());
$query = $this->getQuery(self::TABLESDB_CREATE_DATABASE);
$gqlPayload = [
'query' => $query,
'variables' => [
'databaseId' => ID::unique(),
'name' => 'Actors',
]
];
$database = $this->client->call(Client::METHOD_POST, '/graphql', $headers, $gqlPayload);
$this->assertArrayNotHasKey('errors', $database['body']);
self::$cachedDatabase[$cacheKey] = $database['body']['data']['tablesDBCreate'];
return self::$cachedDatabase[$cacheKey];
}
protected function setupTable(): array
{
$cacheKey = $this->getProject()['$id'] ?? 'default';
if (!empty(self::$cachedTableData[$cacheKey])) {
return self::$cachedTableData[$cacheKey];
}
$database = $this->setupDatabase();
$projectId = $this->getProject()['$id'];
$headers = array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $projectId,
], $this->getHeaders());
// Create 'actors' table
$query = $this->getQuery(self::CREATE_TABLE);
$gqlPayload = [
'query' => $query,
'variables' => [
'databaseId' => $database['_id'],
'tableId' => ID::unique(),
'name' => 'Actors',
'rowSecurity' => false,
'permissions' => [
Permission::read(Role::any()),
Permission::create(Role::users()),
Permission::update(Role::users()),
Permission::delete(Role::users()),
],
]
];
$table = $this->client->call(Client::METHOD_POST, '/graphql', $headers, $gqlPayload);
$this->assertArrayNotHasKey('errors', $table['body']);
$table = $table['body']['data']['tablesDBCreateTable'];
// Create 'movies' table
$query = $this->getQuery(self::CREATE_TABLE);
$gqlPayload = [
'query' => $query,
'variables' => [
'databaseId' => $database['_id'],
'tableId' => ID::unique(),
'name' => 'Movies',
'rowSecurity' => false,
'permissions' => [
Permission::read(Role::any()),
Permission::create(Role::users()),
Permission::update(Role::users()),
Permission::delete(Role::users()),
],
]
];
$table2 = $this->client->call(Client::METHOD_POST, '/graphql', $headers, $gqlPayload);
$this->assertArrayNotHasKey('errors', $table2['body']);
$table2 = $table2['body']['data']['tablesDBCreateTable'];
self::$cachedTableData[$cacheKey] = [
'database' => $database,
'table' => $table,
'table2' => $table2,
];
return self::$cachedTableData[$cacheKey];
}
protected function setupStringColumn(): array
{
$cacheKey = $this->getProject()['$id'] ?? 'default';
if (!empty(self::$cachedStringColumnData[$cacheKey])) {
return self::$cachedStringColumnData[$cacheKey];
}
$data = $this->setupTable();
$projectId = $this->getProject()['$id'];
$query = $this->getQuery(self::CREATE_STRING_COLUMN);
$gqlPayload = [
'query' => $query,
'variables' => [
'databaseId' => $data['database']['_id'],
'tableId' => $data['table']['_id'],
'key' => 'name',
'size' => 256,
'required' => true,
]
];
$this->client->call(Client::METHOD_POST, '/graphql', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $projectId,
], $this->getHeaders()), $gqlPayload);
self::$cachedStringColumnData[$cacheKey] = $data;
return self::$cachedStringColumnData[$cacheKey];
}
protected function setupUpdatedStringColumn(): array
{
$data = $this->setupStringColumn();
// Check if already updated by looking for default value
$projectId = $this->getProject()['$id'];
$databaseId = $data['database']['_id'];
$tableId = $data['table']['_id'];
$this->assertEventually(function () use ($databaseId, $tableId) {
$response = $this->client->call(Client::METHOD_GET, '/tablesdb/' . $databaseId . '/tables/' . $tableId . '/columns/name', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
'x-appwrite-key' => $this->getProject()['apiKey'],
]));
$this->assertEquals('available', $response['body']['status']);
}, 240000, 500);
$query = $this->getQuery(self::UPDATE_STRING_COLUMN);
$gqlPayload = [
'query' => $query,
'variables' => [
'databaseId' => $databaseId,
'tableId' => $tableId,
'key' => 'name',
'required' => false,
'default' => 'Default Value',
]
];
$this->client->call(Client::METHOD_POST, '/graphql', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $projectId,
], $this->getHeaders()), $gqlPayload);
return $data;
}
protected function setupIntegerColumn(): array
{
$cacheKey = $this->getProject()['$id'] ?? 'default';
if (!empty(self::$cachedIntegerColumnData[$cacheKey])) {
return self::$cachedIntegerColumnData[$cacheKey];
}
$data = $this->setupTable();
$projectId = $this->getProject()['$id'];
$query = $this->getQuery(self::CREATE_INTEGER_COLUMN);
$gqlPayload = [
'query' => $query,
'variables' => [
'databaseId' => $data['database']['_id'],
'tableId' => $data['table']['_id'],
'key' => 'age',
'min' => 18,
'max' => 150,
'required' => true,
]
];
$this->client->call(Client::METHOD_POST, '/graphql', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $projectId,
], $this->getHeaders()), $gqlPayload);
self::$cachedIntegerColumnData[$cacheKey] = $data;
return self::$cachedIntegerColumnData[$cacheKey];
}
protected function setupUpdatedIntegerColumn(): array
{
$data = $this->setupIntegerColumn();
$projectId = $this->getProject()['$id'];
$databaseId = $data['database']['_id'];
$tableId = $data['table']['_id'];
$this->assertEventually(function () use ($databaseId, $tableId) {
$response = $this->client->call(Client::METHOD_GET, '/tablesdb/' . $databaseId . '/tables/' . $tableId . '/columns/age', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
'x-appwrite-key' => $this->getProject()['apiKey'],
]));
$this->assertEquals('available', $response['body']['status']);
}, 240000, 500);
$query = $this->getQuery(self::UPDATE_INTEGER_COLUMN);
$gqlPayload = [
'query' => $query,
'variables' => [
'databaseId' => $databaseId,
'tableId' => $tableId,
'key' => 'age',
'required' => false,
'min' => 12,
'max' => 160,
'default' => 50
]
];
$this->client->call(Client::METHOD_POST, '/graphql', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $projectId,
], $this->getHeaders()), $gqlPayload);
return $data;
}
protected function setupBooleanColumn(): array
{
$cacheKey = $this->getProject()['$id'] ?? 'default';
if (!empty(self::$cachedBooleanColumnData[$cacheKey])) {
return self::$cachedBooleanColumnData[$cacheKey];
}
$data = $this->setupTable();
$projectId = $this->getProject()['$id'];
$query = $this->getQuery(self::CREATE_BOOLEAN_COLUMN);
$gqlPayload = [
'query' => $query,
'variables' => [
'databaseId' => $data['database']['_id'],
'tableId' => $data['table']['_id'],
'key' => 'alive',
'required' => true,
]
];
$this->client->call(Client::METHOD_POST, '/graphql', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $projectId,
], $this->getHeaders()), $gqlPayload);
self::$cachedBooleanColumnData[$cacheKey] = $data;
return self::$cachedBooleanColumnData[$cacheKey];
}
protected function setupUpdatedBooleanColumn(): array
{
$data = $this->setupBooleanColumn();
$projectId = $this->getProject()['$id'];
$databaseId = $data['database']['_id'];
$tableId = $data['table']['_id'];
$this->assertEventually(function () use ($databaseId, $tableId) {
$response = $this->client->call(Client::METHOD_GET, '/tablesdb/' . $databaseId . '/tables/' . $tableId . '/columns/alive', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
'x-appwrite-key' => $this->getProject()['apiKey'],
]));
$this->assertEquals('available', $response['body']['status']);
}, 240000, 500);
$query = $this->getQuery(self::UPDATE_BOOLEAN_COLUMN);
$gqlPayload = [
'query' => $query,
'variables' => [
'databaseId' => $databaseId,
'tableId' => $tableId,
'key' => 'alive',
'required' => false,
'default' => true
]
];
$this->client->call(Client::METHOD_POST, '/graphql', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $projectId,
], $this->getHeaders()), $gqlPayload);
return $data;
}
protected function setupFloatColumn(): array
{
$cacheKey = $this->getProject()['$id'] ?? 'default';
if (!empty(self::$cachedFloatColumnData[$cacheKey])) {
return self::$cachedFloatColumnData[$cacheKey];
}
$data = $this->setupTable();
$projectId = $this->getProject()['$id'];
$query = $this->getQuery(self::CREATE_FLOAT_COLUMN);
$gqlPayload = [
'query' => $query,
'variables' => [
'databaseId' => $data['database']['_id'],
'tableId' => $data['table']['_id'],
'key' => 'salary',
'min' => 1000.0,
'max' => 999999.99,
'default' => 1000.0,
'required' => false,
]
];
$this->client->call(Client::METHOD_POST, '/graphql', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $projectId,
], $this->getHeaders()), $gqlPayload);
self::$cachedFloatColumnData[$cacheKey] = $data;
return self::$cachedFloatColumnData[$cacheKey];
}
protected function setupUpdatedFloatColumn(): array
{
$data = $this->setupFloatColumn();
$projectId = $this->getProject()['$id'];
$databaseId = $data['database']['_id'];
$tableId = $data['table']['_id'];
$this->assertEventually(function () use ($databaseId, $tableId) {
$response = $this->client->call(Client::METHOD_GET, '/tablesdb/' . $databaseId . '/tables/' . $tableId . '/columns/salary', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
'x-appwrite-key' => $this->getProject()['apiKey'],
]));
$this->assertEquals('available', $response['body']['status']);
}, 240000, 500);
$query = $this->getQuery(self::UPDATE_FLOAT_COLUMN);
$gqlPayload = [
'query' => $query,
'variables' => [
'databaseId' => $databaseId,
'tableId' => $tableId,
'key' => 'salary',
'required' => false,
'min' => 100.0,
'max' => 1000000.0,
'default' => 2500.0
]
];
$this->client->call(Client::METHOD_POST, '/graphql', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $projectId,
], $this->getHeaders()), $gqlPayload);
return $data;
}
protected function setupEmailColumn(): array
{
$cacheKey = $this->getProject()['$id'] ?? 'default';
if (!empty(self::$cachedEmailColumnData[$cacheKey])) {
return self::$cachedEmailColumnData[$cacheKey];
}
$data = $this->setupTable();
$projectId = $this->getProject()['$id'];
$query = $this->getQuery(self::CREATE_EMAIL_COLUMN);
$gqlPayload = [
'query' => $query,
'variables' => [
'databaseId' => $data['database']['_id'],
'tableId' => $data['table']['_id'],
'key' => 'email',
'required' => true,
]
];
$this->client->call(Client::METHOD_POST, '/graphql', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $projectId,
], $this->getHeaders()), $gqlPayload);
self::$cachedEmailColumnData[$cacheKey] = $data;
return self::$cachedEmailColumnData[$cacheKey];
}
protected function setupUpdatedEmailColumn(): array
{
$data = $this->setupEmailColumn();
$projectId = $this->getProject()['$id'];
$databaseId = $data['database']['_id'];
$tableId = $data['table']['_id'];
$this->assertEventually(function () use ($databaseId, $tableId) {
$response = $this->client->call(Client::METHOD_GET, '/tablesdb/' . $databaseId . '/tables/' . $tableId . '/columns/email', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
'x-appwrite-key' => $this->getProject()['apiKey'],
]));
$this->assertEquals('available', $response['body']['status']);
}, 240000, 500);
$query = $this->getQuery(self::UPDATE_EMAIL_COLUMN);
$gqlPayload = [
'query' => $query,
'variables' => [
'databaseId' => $databaseId,
'tableId' => $tableId,
'key' => 'email',
'required' => false,
'default' => 'torsten@appwrite.io',
]
];
$this->client->call(Client::METHOD_POST, '/graphql', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $projectId,
], $this->getHeaders()), $gqlPayload);
return $data;
}
protected function setupEnumColumn(): array
{
$cacheKey = $this->getProject()['$id'] ?? 'default';
if (!empty(self::$cachedEnumColumnData[$cacheKey])) {
return self::$cachedEnumColumnData[$cacheKey];
}
$data = $this->setupTable();
$projectId = $this->getProject()['$id'];
$query = $this->getQuery(self::CREATE_ENUM_COLUMN);
$gqlPayload = [
'query' => $query,
'variables' => [
'databaseId' => $data['database']['_id'],
'tableId' => $data['table']['_id'],
'key' => 'role',
'elements' => [
'crew',
'actor',
'guest',
],
'required' => true,
]
];
$this->client->call(Client::METHOD_POST, '/graphql', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $projectId,
], $this->getHeaders()), $gqlPayload);
self::$cachedEnumColumnData[$cacheKey] = $data;
return self::$cachedEnumColumnData[$cacheKey];
}
protected function setupUpdatedEnumColumn(): array
{
$data = $this->setupEnumColumn();
$projectId = $this->getProject()['$id'];
$databaseId = $data['database']['_id'];
$tableId = $data['table']['_id'];
$this->assertEventually(function () use ($databaseId, $tableId) {
$response = $this->client->call(Client::METHOD_GET, '/tablesdb/' . $databaseId . '/tables/' . $tableId . '/columns/role', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
'x-appwrite-key' => $this->getProject()['apiKey'],
]));
$this->assertEquals('available', $response['body']['status']);
}, 240000, 500);
$query = $this->getQuery(self::UPDATE_ENUM_COLUMN);
$gqlPayload = [
'query' => $query,
'variables' => [
'databaseId' => $databaseId,
'tableId' => $tableId,
'key' => 'role',
'required' => false,
'elements' => [
'crew',
'tech',
'actor'
],
'default' => 'tech'
]
];
$this->client->call(Client::METHOD_POST, '/graphql', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $projectId,
], $this->getHeaders()), $gqlPayload);
return $data;
}
protected function setupDatetimeColumn(): array
{
$cacheKey = $this->getProject()['$id'] ?? 'default';
if (!empty(self::$cachedDatetimeColumnData[$cacheKey])) {
return self::$cachedDatetimeColumnData[$cacheKey];
}
$data = $this->setupTable();
$projectId = $this->getProject()['$id'];
$query = $this->getQuery(self::CREATE_DATETIME_COLUMN);
$gqlPayload = [
'query' => $query,
'variables' => [
'databaseId' => $data['database']['_id'],
'tableId' => $data['table']['_id'],
'key' => 'dob',
'required' => true,
]
];
$this->client->call(Client::METHOD_POST, '/graphql', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $projectId,
], $this->getHeaders()), $gqlPayload);
self::$cachedDatetimeColumnData[$cacheKey] = $data;
return self::$cachedDatetimeColumnData[$cacheKey];
}
protected function setupUpdatedDatetimeColumn(): array
{
$data = $this->setupDatetimeColumn();
$projectId = $this->getProject()['$id'];
$databaseId = $data['database']['_id'];
$tableId = $data['table']['_id'];
$this->assertEventually(function () use ($databaseId, $tableId) {
$response = $this->client->call(Client::METHOD_GET, '/tablesdb/' . $databaseId . '/tables/' . $tableId . '/columns/dob', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
'x-appwrite-key' => $this->getProject()['apiKey'],
]));
$this->assertEquals('available', $response['body']['status']);
}, 240000, 500);
$query = $this->getQuery(self::UPDATE_DATETIME_COLUMN);
$gqlPayload = [
'query' => $query,
'variables' => [
'databaseId' => $databaseId,
'tableId' => $tableId,
'key' => 'dob',
'required' => false,
'default' => '2000-01-01T00:00:00Z'
]
];
$this->client->call(Client::METHOD_POST, '/graphql', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $projectId,
], $this->getHeaders()), $gqlPayload);
return $data;
}
protected function setupRelationshipColumn(): array
{
$cacheKey = $this->getProject()['$id'] ?? 'default';
if (!empty(self::$cachedRelationshipColumnData[$cacheKey])) {
return self::$cachedRelationshipColumnData[$cacheKey];
}
$data = $this->setupTable();
$projectId = $this->getProject()['$id'];
$query = $this->getQuery(self::CREATE_RELATIONSHIP_COLUMN);
$gqlPayload = [
'query' => $query,
'variables' => [
'databaseId' => $data['database']['_id'],
'tableId' => $data['table2']['_id'], // Movies
'relatedTableId' => $data['table']['_id'], // Actors
'type' => Database::RELATION_ONE_TO_MANY,
'twoWay' => true,
'key' => 'actors',
'twoWayKey' => 'movie'
]
];
$this->client->call(Client::METHOD_POST, '/graphql', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $projectId,
], $this->getHeaders()), $gqlPayload);
self::$cachedRelationshipColumnData[$cacheKey] = $data;
return self::$cachedRelationshipColumnData[$cacheKey];
}
protected function setupUpdatedRelationshipColumn(): array
{
$data = $this->setupRelationshipColumn();
$projectId = $this->getProject()['$id'];
$databaseId = $data['database']['_id'];
$tableId = $data['table2']['_id'];
$this->assertEventually(function () use ($databaseId, $tableId) {
$response = $this->client->call(Client::METHOD_GET, '/tablesdb/' . $databaseId . '/tables/' . $tableId . '/columns/actors', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
'x-appwrite-key' => $this->getProject()['apiKey'],
]));
$this->assertEquals('available', $response['body']['status']);
}, 240000, 500);
$query = $this->getQuery(self::UPDATE_RELATIONSHIP_COLUMN);
$gqlPayload = [
'query' => $query,
'variables' => [
'databaseId' => $databaseId,
'tableId' => $tableId,
'key' => 'actors',
'onDelete' => Database::RELATION_MUTATE_CASCADE,
]
];
$this->client->call(Client::METHOD_POST, '/graphql', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $projectId,
], $this->getHeaders()), $gqlPayload);
return $data;
}
protected function setupIPColumn(): array
{
$cacheKey = $this->getProject()['$id'] ?? 'default';
if (!empty(self::$cachedIPColumnData[$cacheKey])) {
return self::$cachedIPColumnData[$cacheKey];
}
$data = $this->setupTable();
$projectId = $this->getProject()['$id'];
$query = $this->getQuery(self::CREATE_IP_COLUMN);
$gqlPayload = [
'query' => $query,
'variables' => [
'databaseId' => $data['database']['_id'],
'tableId' => $data['table']['_id'],
'key' => 'ip',
'required' => false,
'default' => '::1',
]
];
$this->client->call(Client::METHOD_POST, '/graphql', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $projectId,
], $this->getHeaders()), $gqlPayload);
self::$cachedIPColumnData[$cacheKey] = $data;
return self::$cachedIPColumnData[$cacheKey];
}
protected function setupUpdatedIPColumn(): array
{
$data = $this->setupIPColumn();
$projectId = $this->getProject()['$id'];
$databaseId = $data['database']['_id'];
$tableId = $data['table']['_id'];
$this->assertEventually(function () use ($databaseId, $tableId) {
$response = $this->client->call(Client::METHOD_GET, '/tablesdb/' . $databaseId . '/tables/' . $tableId . '/columns/ip', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
'x-appwrite-key' => $this->getProject()['apiKey'],
]));
$this->assertEquals('available', $response['body']['status']);
}, 240000, 500);
$query = $this->getQuery(self::UPDATE_IP_COLUMN);
$gqlPayload = [
'query' => $query,
'variables' => [
'databaseId' => $databaseId,
'tableId' => $tableId,
'key' => 'ip',
'required' => false,
'default' => '127.0.0.1'
]
];
$this->client->call(Client::METHOD_POST, '/graphql', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $projectId,
], $this->getHeaders()), $gqlPayload);
return $data;
}
protected function setupURLColumn(): array
{
$cacheKey = $this->getProject()['$id'] ?? 'default';
if (!empty(self::$cachedURLColumnData[$cacheKey])) {
return self::$cachedURLColumnData[$cacheKey];
}
$data = $this->setupTable();
$projectId = $this->getProject()['$id'];
$query = $this->getQuery(self::CREATE_URL_COLUMN);
$gqlPayload = [
'query' => $query,
'variables' => [
'databaseId' => $data['database']['_id'],
'tableId' => $data['table']['_id'],
'key' => 'url',
'required' => false,
'default' => 'https://appwrite.io',
]
];
$this->client->call(Client::METHOD_POST, '/graphql', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $projectId,
], $this->getHeaders()), $gqlPayload);
self::$cachedURLColumnData[$cacheKey] = $data;
return self::$cachedURLColumnData[$cacheKey];
}
protected function setupUpdatedURLColumn(): array
{
$data = $this->setupURLColumn();
$projectId = $this->getProject()['$id'];
$databaseId = $data['database']['_id'];
$tableId = $data['table']['_id'];
$this->assertEventually(function () use ($databaseId, $tableId) {
$response = $this->client->call(Client::METHOD_GET, '/tablesdb/' . $databaseId . '/tables/' . $tableId . '/columns/url', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
'x-appwrite-key' => $this->getProject()['apiKey'],
]));
$this->assertEquals('available', $response['body']['status']);
}, 240000, 500);
$query = $this->getQuery(self::UPDATE_URL_COLUMN);
$gqlPayload = [
'query' => $query,
'variables' => [
'databaseId' => $databaseId,
'tableId' => $tableId,
'key' => 'url',
'required' => false,
'default' => 'https://cloud.appwrite.io'
]
];
$this->client->call(Client::METHOD_POST, '/graphql', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $projectId,
], $this->getHeaders()), $gqlPayload);
return $data;
}
protected function setupIndex(): array
{
$cacheKey = $this->getProject()['$id'] ?? 'default';
if (!empty(self::$cachedIndexData[$cacheKey])) {
return self::$cachedIndexData[$cacheKey];
}
// Need updated string and integer columns first
$this->setupUpdatedStringColumn();
$data = $this->setupUpdatedIntegerColumn();
$projectId = $this->getProject()['$id'];
$query = $this->getQuery(self::CREATE_COLUMN_INDEX);
$gqlPayload = [
'query' => $query,
'variables' => [
'databaseId' => $data['database']['_id'],
'tableId' => $data['table']['_id'],
'key' => 'index',
'type' => 'key',
'columns' => [
'name',
'age',
],
]
];
$index = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $projectId,
], $this->getHeaders()), $gqlPayload);
// Handle 409 conflict - index may already exist from testCreateIndex
if (isset($index['body']['errors'])) {
$errorMessage = $index['body']['errors'][0]['message'] ?? '';
if (strpos($errorMessage, 'already exists') !== false || strpos($errorMessage, 'Document with the requested ID already exists') !== false) {
self::$cachedIndexData[$cacheKey] = [
'database' => $data['database'],
'table' => $data['table'],
'index' => ['key' => 'index'],
];
return self::$cachedIndexData[$cacheKey];
}
}
$this->assertArrayNotHasKey('errors', $index['body']);
self::$cachedIndexData[$cacheKey] = [
'database' => $data['database'],
'table' => $data['table'],
'index' => $index['body']['data']['tablesDBCreateIndex'],
];
return self::$cachedIndexData[$cacheKey];
}
protected function setupRow(): array
{
$cacheKey = $this->getProject()['$id'] ?? 'default';
if (!empty(self::$cachedRowData[$cacheKey])) {
return self::$cachedRowData[$cacheKey];
}
// Need all columns that the row data references
$this->setupUpdatedStringColumn();
$this->setupUpdatedIntegerColumn();
$this->setupUpdatedBooleanColumn();
$this->setupUpdatedFloatColumn();
$this->setupUpdatedEmailColumn();
$this->setupUpdatedDatetimeColumn();
$data = $this->setupUpdatedEnumColumn();
$projectId = $this->getProject()['$id'];
$databaseId = $data['database']['_id'];
$tableId = $data['table']['_id'];
// Wait for all columns to be available
$columns = ['name', 'age', 'alive', 'salary', 'email', 'dob', 'role'];
foreach ($columns as $columnKey) {
$this->assertEventually(function () use ($databaseId, $tableId, $columnKey) {
$response = $this->client->call(Client::METHOD_GET, '/tablesdb/' . $databaseId . '/tables/' . $tableId . '/columns/' . $columnKey, array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
'x-appwrite-key' => $this->getProject()['apiKey'],
]));
$this->assertEquals('available', $response['body']['status']);
}, 240000, 500);
}
$query = $this->getQuery(self::CREATE_ROW);
$gqlPayload = [
'query' => $query,
'variables' => [
'databaseId' => $databaseId,
'tableId' => $tableId,
'rowId' => ID::unique(),
'data' => [
'name' => 'John Doe',
'email' => 'example@appwrite.io',
'age' => 30,
'alive' => true,
'salary' => 9999.9,
'role' => 'crew',
'dob' => '2000-01-01T00:00:00Z',
],
'permissions' => [
Permission::read(Role::any()),
Permission::update(Role::any()),
Permission::delete(Role::any()),
],
]
];
$row = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $projectId,
], $this->getHeaders()), $gqlPayload);
$this->assertArrayNotHasKey('errors', $row['body']);
$row = $row['body']['data']['tablesDBCreateRow'];
self::$cachedRowData[$cacheKey] = [
'database' => $data['database'],
'table' => $data['table'],
'row' => $row,
];
return self::$cachedRowData[$cacheKey];
}
protected function setupBulkData(): array
{
$cacheKey = $this->getProject()['$id'] ?? 'default';
if (!empty(self::$cachedBulkData[$cacheKey])) {
return self::$cachedBulkData[$cacheKey];
}
$project = $this->getProject();
$projectId = $project['$id'];
$headers = array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $projectId,
], $this->getHeaders());
// Step 1: Create database
$query = $this->getQuery(self::TABLESDB_CREATE_DATABASE);
$payload = [
'query' => $query,
'variables' => [
'databaseId' => ID::unique(),
'name' => 'Bulk',
],
];
$res = $this->client->call(Client::METHOD_POST, '/graphql', $headers, $payload);
$this->assertArrayNotHasKey('errors', $res['body']);
$databaseId = $res['body']['data']['tablesDBCreate']['_id'];
// Step 2: Create table
$query = $this->getQuery(self::CREATE_TABLE);
$payload['query'] = $query;
$payload['variables'] = [
'databaseId' => $databaseId,
'tableId' => ID::unique(),
'name' => 'Operations',
'rowSecurity' => false,
'permissions' => [
Permission::read(Role::any()),
Permission::update(Role::any()),
Permission::delete(Role::any()),
],
];
$res = $this->client->call(Client::METHOD_POST, '/graphql', $headers, $payload);
$this->assertArrayNotHasKey('errors', $res['body']);
$tableId = $res['body']['data']['tablesDBCreateTable']['_id'];
// Step 3: Create column
$query = $this->getQuery(self::CREATE_STRING_COLUMN);
$payload['query'] = $query;
$payload['variables'] = [
'databaseId' => $databaseId,
'tableId' => $tableId,
'key' => 'name',
'size' => 256,
'required' => true,
];
$this->client->call(Client::METHOD_POST, '/graphql', $headers, $payload);
$this->assertEventually(function () use ($databaseId, $tableId) {
$response = $this->client->call(Client::METHOD_GET, '/tablesdb/' . $databaseId . '/tables/' . $tableId . '/columns/name', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
'x-appwrite-key' => $this->getProject()['apiKey'],
]));
$this->assertEquals('available', $response['body']['status']);
}, 240000, 500);
// Step 4: Create rows
$query = $this->getQuery(self::CREATE_ROWS);
$rows = [];
for ($i = 1; $i <= 10; $i++) {
$rows[] = ['$id' => ID::unique(), 'name' => 'Row #' . $i];
}
$payload['query'] = $query;
$payload['variables'] = [
'databaseId' => $databaseId,
'tableId' => $tableId,
'rows' => $rows,
];
$this->client->call(Client::METHOD_POST, '/graphql', $headers, $payload);
self::$cachedBulkData[$cacheKey] = compact('databaseId', 'tableId', 'projectId');
return self::$cachedBulkData[$cacheKey];
}
public function testCreateDatabase(): void
{
// Use setupDatabase() to create and cache the database
$database = $this->setupDatabase();
$this->assertEquals('Actors', $database['name']);
}
/**
* @throws Exception
*/
public function testCreateTable(): void
{
// Use setupTable() to create and cache both tables
$data = $this->setupTable();
$this->assertEquals('Actors', $data['table']['name']);
$this->assertEquals('Movies', $data['table2']['name']);
}
/**
* @throws Exception
*/
public function testCreateStringColumn(): void
{
$data = $this->setupTable();
$projectId = $this->getProject()['$id'];
$query = $this->getQuery(self::CREATE_STRING_COLUMN);
$gqlPayload = [
'query' => $query,
'variables' => [
'databaseId' => $data['database']['_id'],
'tableId' => $data['table']['_id'],
'key' => 'name',
'size' => 256,
'required' => true,
]
];
$column = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $projectId,
], $this->getHeaders()), $gqlPayload);
// TODO: @itznotabug - check for `encrypt` attribute in string column's response body as well!
$this->assertArrayNotHasKey('errors', $column['body']);
$this->assertIsArray($column['body']['data']);
$this->assertIsArray($column['body']['data']['tablesDBCreateStringColumn']);
// Store for caching
$cacheKey = $this->getProject()['$id'] ?? 'default';
self::$cachedStringColumnData[$cacheKey] = $data;
}
/**
* @throws Exception
*/
public function testUpdateStringColumn(): void
{
$data = $this->setupStringColumn();
$projectId = $this->getProject()['$id'];
$databaseId = $data['database']['_id'];
$tableId = $data['table']['_id'];
$this->assertEventually(function () use ($databaseId, $tableId) {
$response = $this->client->call(Client::METHOD_GET, '/tablesdb/' . $databaseId . '/tables/' . $tableId . '/columns/name', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
'x-appwrite-key' => $this->getProject()['apiKey'],
]));
$this->assertEquals('available', $response['body']['status']);
}, 240000, 500);
$query = $this->getQuery(self::UPDATE_STRING_COLUMN);
$gqlPayload = [
'query' => $query,
'variables' => [
'databaseId' => $databaseId,
'tableId' => $tableId,
'key' => 'name',
'required' => false,
'default' => 'Default Value',
]
];
$column = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $projectId,
], $this->getHeaders()), $gqlPayload);
$this->assertIsArray($column['body']['data']);
$this->assertIsArray($column['body']['data']['tablesDBUpdateStringColumn']);
$this->assertFalse($column['body']['data']['tablesDBUpdateStringColumn']['required']);
$this->assertEquals('Default Value', $column['body']['data']['tablesDBUpdateStringColumn']['default']);
$this->assertEquals(200, $column['headers']['status-code']);
}
/**
* @throws Exception
*/
public function testCreateIntegerColumn(): void
{
$data = $this->setupTable();
$projectId = $this->getProject()['$id'];
$query = $this->getQuery(self::CREATE_INTEGER_COLUMN);
$gqlPayload = [
'query' => $query,
'variables' => [
'databaseId' => $data['database']['_id'],
'tableId' => $data['table']['_id'],
'key' => 'age',
'min' => 18,
'max' => 150,
'required' => true,
]
];
$column = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $projectId,
], $this->getHeaders()), $gqlPayload);
$this->assertArrayNotHasKey('errors', $column['body']);
$this->assertIsArray($column['body']['data']);
$this->assertIsArray($column['body']['data']['tablesDBCreateIntegerColumn']);
// Store for caching
$cacheKey = $this->getProject()['$id'] ?? 'default';
self::$cachedIntegerColumnData[$cacheKey] = $data;
}
/**
* @throws Exception
*/
public function testUpdateIntegerColumn(): void
{
$data = $this->setupIntegerColumn();
$projectId = $this->getProject()['$id'];
$databaseId = $data['database']['_id'];
$tableId = $data['table']['_id'];
$this->assertEventually(function () use ($databaseId, $tableId) {
$response = $this->client->call(Client::METHOD_GET, '/tablesdb/' . $databaseId . '/tables/' . $tableId . '/columns/age', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
'x-appwrite-key' => $this->getProject()['apiKey'],
]));
$this->assertEquals('available', $response['body']['status']);
}, 240000, 500);
$query = $this->getQuery(self::UPDATE_INTEGER_COLUMN);
$gqlPayload = [
'query' => $query,
'variables' => [
'databaseId' => $databaseId,
'tableId' => $tableId,
'key' => 'age',
'required' => false,
'min' => 12,
'max' => 160,
'default' => 50
]
];
$column = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $projectId,
], $this->getHeaders()), $gqlPayload);
$this->assertIsArray($column['body']['data']);
$this->assertIsArray($column['body']['data']['tablesDBUpdateIntegerColumn']);
$this->assertFalse($column['body']['data']['tablesDBUpdateIntegerColumn']['required']);
$this->assertEquals(12, $column['body']['data']['tablesDBUpdateIntegerColumn']['min']);
$this->assertEquals(160, $column['body']['data']['tablesDBUpdateIntegerColumn']['max']);
$this->assertEquals(50, $column['body']['data']['tablesDBUpdateIntegerColumn']['default']);
$this->assertEquals(200, $column['headers']['status-code']);
}
/**
* @throws Exception
*/
public function testCreateBooleanColumn(): void
{
$data = $this->setupTable();
$projectId = $this->getProject()['$id'];
$query = $this->getQuery(self::CREATE_BOOLEAN_COLUMN);
$gqlPayload = [
'query' => $query,
'variables' => [
'databaseId' => $data['database']['_id'],
'tableId' => $data['table']['_id'],
'key' => 'alive',
'required' => true,
]
];
$column = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $projectId,
], $this->getHeaders()), $gqlPayload);
$this->assertArrayNotHasKey('errors', $column['body']);
$this->assertIsArray($column['body']['data']);
$this->assertIsArray($column['body']['data']['tablesDBCreateBooleanColumn']);
// Store for caching
$cacheKey = $this->getProject()['$id'] ?? 'default';
self::$cachedBooleanColumnData[$cacheKey] = $data;
}
/**
* @throws Exception
*/
public function testUpdateBooleanColumn(): void
{
$data = $this->setupBooleanColumn();
$projectId = $this->getProject()['$id'];
$databaseId = $data['database']['_id'];
$tableId = $data['table']['_id'];
$this->assertEventually(function () use ($databaseId, $tableId) {
$response = $this->client->call(Client::METHOD_GET, '/tablesdb/' . $databaseId . '/tables/' . $tableId . '/columns/alive', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
'x-appwrite-key' => $this->getProject()['apiKey'],
]));
$this->assertEquals('available', $response['body']['status']);
}, 240000, 500);
$query = $this->getQuery(self::UPDATE_BOOLEAN_COLUMN);
$gqlPayload = [
'query' => $query,
'variables' => [
'databaseId' => $databaseId,
'tableId' => $tableId,
'key' => 'alive',
'required' => false,
'default' => true
]
];
$column = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $projectId,
], $this->getHeaders()), $gqlPayload);
$this->assertIsArray($column['body']['data']);
$this->assertIsArray($column['body']['data']['tablesDBUpdateBooleanColumn']);
$this->assertFalse($column['body']['data']['tablesDBUpdateBooleanColumn']['required']);
$this->assertTrue($column['body']['data']['tablesDBUpdateBooleanColumn']['default']);
$this->assertEquals(200, $column['headers']['status-code']);
}
/**
* @throws Exception
*/
public function testCreateFloatColumn(): void
{
$data = $this->setupTable();
$projectId = $this->getProject()['$id'];
$query = $this->getQuery(self::CREATE_FLOAT_COLUMN);
$gqlPayload = [
'query' => $query,
'variables' => [
'databaseId' => $data['database']['_id'],
'tableId' => $data['table']['_id'],
'key' => 'salary',
'min' => 1000.0,
'max' => 999999.99,
'default' => 1000.0,
'required' => false,
]
];
$column = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $projectId,
], $this->getHeaders()), $gqlPayload);
$this->assertArrayNotHasKey('errors', $column['body']);
$this->assertIsArray($column['body']['data']);
$this->assertIsArray($column['body']['data']['tablesDBCreateFloatColumn']);
// Store for caching
$cacheKey = $this->getProject()['$id'] ?? 'default';
self::$cachedFloatColumnData[$cacheKey] = $data;
}
/**
* @throws Exception
*/
public function testUpdateFloatColumn(): void
{
$data = $this->setupFloatColumn();
$projectId = $this->getProject()['$id'];
$databaseId = $data['database']['_id'];
$tableId = $data['table']['_id'];
$this->assertEventually(function () use ($databaseId, $tableId) {
$response = $this->client->call(Client::METHOD_GET, '/tablesdb/' . $databaseId . '/tables/' . $tableId . '/columns/salary', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
'x-appwrite-key' => $this->getProject()['apiKey'],
]));
$this->assertEquals('available', $response['body']['status']);
}, 240000, 500);
$query = $this->getQuery(self::UPDATE_FLOAT_COLUMN);
$gqlPayload = [
'query' => $query,
'variables' => [
'databaseId' => $databaseId,
'tableId' => $tableId,
'key' => 'salary',
'required' => false,
'min' => 100.0,
'max' => 1000000.0,
'default' => 2500.0
]
];
$column = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $projectId,
], $this->getHeaders()), $gqlPayload);
$this->assertIsArray($column['body']['data']);
$this->assertIsArray($column['body']['data']['tablesDBUpdateFloatColumn']);
$this->assertFalse($column['body']['data']['tablesDBUpdateFloatColumn']['required']);
$this->assertEquals(100.0, $column['body']['data']['tablesDBUpdateFloatColumn']['min']);
$this->assertEquals(1000000.0, $column['body']['data']['tablesDBUpdateFloatColumn']['max']);
$this->assertEquals(2500.0, $column['body']['data']['tablesDBUpdateFloatColumn']['default']);
$this->assertEquals(200, $column['headers']['status-code']);
}
/**
* @throws Exception
*/
public function testCreateEmailColumn(): void
{
$data = $this->setupTable();
$projectId = $this->getProject()['$id'];
$query = $this->getQuery(self::CREATE_EMAIL_COLUMN);
$gqlPayload = [
'query' => $query,
'variables' => [
'databaseId' => $data['database']['_id'],
'tableId' => $data['table']['_id'],
'key' => 'email',
'required' => true,
]
];
$column = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $projectId,
], $this->getHeaders()), $gqlPayload);
$this->assertArrayNotHasKey('errors', $column['body']);
$this->assertIsArray($column['body']['data']);
$this->assertIsArray($column['body']['data']['tablesDBCreateEmailColumn']);
// Store for caching
$cacheKey = $this->getProject()['$id'] ?? 'default';
self::$cachedEmailColumnData[$cacheKey] = $data;
}
/**
* @throws Exception
*/
public function testUpdateEmailColumn(): void
{
$data = $this->setupEmailColumn();
$projectId = $this->getProject()['$id'];
$databaseId = $data['database']['_id'];
$tableId = $data['table']['_id'];
$this->assertEventually(function () use ($databaseId, $tableId) {
$response = $this->client->call(Client::METHOD_GET, '/tablesdb/' . $databaseId . '/tables/' . $tableId . '/columns/email', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
'x-appwrite-key' => $this->getProject()['apiKey'],
]));
$this->assertEquals('available', $response['body']['status']);
}, 240000, 500);
$query = $this->getQuery(self::UPDATE_EMAIL_COLUMN);
$gqlPayload = [
'query' => $query,
'variables' => [
'databaseId' => $databaseId,
'tableId' => $tableId,
'key' => 'email',
'required' => false,
'default' => 'torsten@appwrite.io',
]
];
$column = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $projectId,
], $this->getHeaders()), $gqlPayload);
$this->assertIsArray($column['body']['data']);
$this->assertIsArray($column['body']['data']['tablesDBUpdateEmailColumn']);
$this->assertFalse($column['body']['data']['tablesDBUpdateEmailColumn']['required']);
$this->assertEquals('torsten@appwrite.io', $column['body']['data']['tablesDBUpdateEmailColumn']['default']);
$this->assertEquals(200, $column['headers']['status-code']);
}
/**
* @throws Exception
*/
public function testCreateEnumColumn(): void
{
$data = $this->setupTable();
$projectId = $this->getProject()['$id'];
$query = $this->getQuery(self::CREATE_ENUM_COLUMN);
$gqlPayload = [
'query' => $query,
'variables' => [
'databaseId' => $data['database']['_id'],
'tableId' => $data['table']['_id'],
'key' => 'role',
'elements' => [
'crew',
'actor',
'guest',
],
'required' => true,
]
];
$column = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $projectId,
], $this->getHeaders()), $gqlPayload);
$this->assertArrayNotHasKey('errors', $column['body']);
$this->assertIsArray($column['body']['data']);
$this->assertIsArray($column['body']['data']['tablesDBCreateEnumColumn']);
// Store for caching
$cacheKey = $this->getProject()['$id'] ?? 'default';
self::$cachedEnumColumnData[$cacheKey] = $data;
}
/**
* @throws Exception
*/
public function testUpdateEnumColumn(): void
{
$data = $this->setupEnumColumn();
$projectId = $this->getProject()['$id'];
$databaseId = $data['database']['_id'];
$tableId = $data['table']['_id'];
$this->assertEventually(function () use ($databaseId, $tableId) {
$response = $this->client->call(Client::METHOD_GET, '/tablesdb/' . $databaseId . '/tables/' . $tableId . '/columns/role', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
'x-appwrite-key' => $this->getProject()['apiKey'],
]));
$this->assertEquals('available', $response['body']['status']);
}, 240000, 500);
$query = $this->getQuery(self::UPDATE_ENUM_COLUMN);
$gqlPayload = [
'query' => $query,
'variables' => [
'databaseId' => $databaseId,
'tableId' => $tableId,
'key' => 'role',
'required' => false,
'elements' => [
'crew',
'tech',
'actor'
],
'default' => 'tech'
]
];
$column = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $projectId,
], $this->getHeaders()), $gqlPayload);
$this->assertIsArray($column['body']['data']);
$this->assertIsArray($column['body']['data']['tablesDBUpdateEnumColumn']);
$this->assertFalse($column['body']['data']['tablesDBUpdateEnumColumn']['required']);
$this->assertEquals('tech', $column['body']['data']['tablesDBUpdateEnumColumn']['default']);
$this->assertContains('tech', $column['body']['data']['tablesDBUpdateEnumColumn']['elements']);
$this->assertNotContains('guest', $column['body']['data']['tablesDBUpdateEnumColumn']['elements']);
$this->assertEquals(200, $column['headers']['status-code']);
}
/**
* @throws Exception
*/
public function testCreateDatetimeColumn(): void
{
$data = $this->setupTable();
$projectId = $this->getProject()['$id'];
$query = $this->getQuery(self::CREATE_DATETIME_COLUMN);
$gqlPayload = [
'query' => $query,
'variables' => [
'databaseId' => $data['database']['_id'],
'tableId' => $data['table']['_id'],
'key' => 'dob',
'required' => true,
]
];
$column = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $projectId,
], $this->getHeaders()), $gqlPayload);
$this->assertArrayNotHasKey('errors', $column['body']);
$this->assertIsArray($column['body']['data']);
$this->assertIsArray($column['body']['data']['tablesDBCreateDatetimeColumn']);
// Store for caching
$cacheKey = $this->getProject()['$id'] ?? 'default';
self::$cachedDatetimeColumnData[$cacheKey] = $data;
}
/**
* @throws Exception
*/
public function testUpdateDatetimeColumn(): void
{
$data = $this->setupDatetimeColumn();
$projectId = $this->getProject()['$id'];
$databaseId = $data['database']['_id'];
$tableId = $data['table']['_id'];
$this->assertEventually(function () use ($databaseId, $tableId) {
$response = $this->client->call(Client::METHOD_GET, '/tablesdb/' . $databaseId . '/tables/' . $tableId . '/columns/dob', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
'x-appwrite-key' => $this->getProject()['apiKey'],
]));
$this->assertEquals('available', $response['body']['status']);
}, 240000, 500);
$query = $this->getQuery(self::UPDATE_DATETIME_COLUMN);
$gqlPayload = [
'query' => $query,
'variables' => [
'databaseId' => $databaseId,
'tableId' => $tableId,
'key' => 'dob',
'required' => false,
'default' => '2000-01-01T00:00:00Z'
]
];
$column = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $projectId,
], $this->getHeaders()), $gqlPayload);
$this->assertIsArray($column['body']['data']);
$this->assertIsArray($column['body']['data']['tablesDBUpdateDatetimeColumn']);
$this->assertFalse($column['body']['data']['tablesDBUpdateDatetimeColumn']['required']);
$this->assertEquals('2000-01-01T00:00:00Z', $column['body']['data']['tablesDBUpdateDatetimeColumn']['default']);
$this->assertEquals(200, $column['headers']['status-code']);
}
public function testCreateRelationshipColumn(): void
{
$data = $this->setupTable();
$projectId = $this->getProject()['$id'];
$query = $this->getQuery(self::CREATE_RELATIONSHIP_COLUMN);
$gqlPayload = [
'query' => $query,
'variables' => [
'databaseId' => $data['database']['_id'],
'tableId' => $data['table2']['_id'], // Movies
'relatedTableId' => $data['table']['_id'], // Actors
'type' => Database::RELATION_ONE_TO_MANY,
'twoWay' => true,
'key' => 'actors',
'twoWayKey' => 'movie'
]
];
$column = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $projectId,
], $this->getHeaders()), $gqlPayload);
$this->assertArrayNotHasKey('errors', $column['body']);
$this->assertIsArray($column['body']['data']);
$this->assertIsArray($column['body']['data']['tablesDBCreateRelationshipColumn']);
// Store for caching
$cacheKey = $this->getProject()['$id'] ?? 'default';
self::$cachedRelationshipColumnData[$cacheKey] = $data;
}
public function testUpdateRelationshipColumn(): void
{
$data = $this->setupRelationshipColumn();
$databaseId = $data['database']['_id'];
$tableId = $data['table2']['_id'];
$this->assertEventually(function () use ($databaseId, $tableId) {
$response = $this->client->call(Client::METHOD_GET, '/tablesdb/' . $databaseId . '/tables/' . $tableId . '/columns/actors', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
'x-appwrite-key' => $this->getProject()['apiKey'],
]));
$this->assertEquals('available', $response['body']['status']);
}, 240000, 500);
$projectId = $this->getProject()['$id'];
$query = $this->getQuery(self::UPDATE_RELATIONSHIP_COLUMN);
$gqlPayload = [
'query' => $query,
'variables' => [
'databaseId' => $databaseId,
'tableId' => $tableId,
'key' => 'actors',
'onDelete' => Database::RELATION_MUTATE_CASCADE,
]
];
$column = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $projectId,
], $this->getHeaders()), $gqlPayload);
$this->assertArrayNotHasKey('errors', $column['body']);
$this->assertIsArray($column['body']['data']);
$this->assertIsArray($column['body']['data']['tablesDBUpdateRelationshipColumn']);
}
/**
* @throws Exception
*/
public function testCreateIPColumn(): void
{
$data = $this->setupTable();
$projectId = $this->getProject()['$id'];
$query = $this->getQuery(self::CREATE_IP_COLUMN);
$gqlPayload = [
'query' => $query,
'variables' => [
'databaseId' => $data['database']['_id'],
'tableId' => $data['table']['_id'],
'key' => 'ip',
'required' => false,
'default' => '::1',
]
];
$column = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $projectId,
], $this->getHeaders()), $gqlPayload);
$this->assertArrayNotHasKey('errors', $column['body']);
$this->assertIsArray($column['body']['data']);
$this->assertIsArray($column['body']['data']['tablesDBCreateIpColumn']);
// Store for caching
$cacheKey = $this->getProject()['$id'] ?? 'default';
self::$cachedIPColumnData[$cacheKey] = $data;
}
/**
* @throws Exception
*/
public function testUpdateIPColumn(): void
{
$data = $this->setupIPColumn();
$databaseId = $data['database']['_id'];
$tableId = $data['table']['_id'];
$this->assertEventually(function () use ($databaseId, $tableId) {
$response = $this->client->call(Client::METHOD_GET, '/tablesdb/' . $databaseId . '/tables/' . $tableId . '/columns/ip', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
'x-appwrite-key' => $this->getProject()['apiKey'],
]));
$this->assertEquals('available', $response['body']['status']);
}, 240000, 500);
$projectId = $this->getProject()['$id'];
$query = $this->getQuery(self::UPDATE_IP_COLUMN);
$gqlPayload = [
'query' => $query,
'variables' => [
'databaseId' => $databaseId,
'tableId' => $tableId,
'key' => 'ip',
'required' => false,
'default' => '127.0.0.1'
]
];
$column = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $projectId,
], $this->getHeaders()), $gqlPayload);
$this->assertIsArray($column['body']['data']);
$this->assertIsArray($column['body']['data']['tablesDBUpdateIpColumn']);
$this->assertFalse($column['body']['data']['tablesDBUpdateIpColumn']['required']);
$this->assertEquals('127.0.0.1', $column['body']['data']['tablesDBUpdateIpColumn']['default']);
$this->assertEquals(200, $column['headers']['status-code']);
}
/**
* @throws Exception
*/
public function testCreateURLColumn(): void
{
$data = $this->setupTable();
$projectId = $this->getProject()['$id'];
$query = $this->getQuery(self::CREATE_URL_COLUMN);
$gqlPayload = [
'query' => $query,
'variables' => [
'databaseId' => $data['database']['_id'],
'tableId' => $data['table']['_id'],
'key' => 'url',
'required' => false,
'default' => 'https://appwrite.io',
]
];
$column = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $projectId,
], $this->getHeaders()), $gqlPayload);
$this->assertArrayNotHasKey('errors', $column['body']);
$this->assertIsArray($column['body']['data']);
$this->assertIsArray($column['body']['data']['tablesDBCreateUrlColumn']);
// Store for caching
$cacheKey = $this->getProject()['$id'] ?? 'default';
self::$cachedURLColumnData[$cacheKey] = $data;
}
/**
* @throws Exception
*/
public function testUpdateURLColumn(): void
{
$data = $this->setupURLColumn();
$databaseId = $data['database']['_id'];
$tableId = $data['table']['_id'];
$this->assertEventually(function () use ($databaseId, $tableId) {
$response = $this->client->call(Client::METHOD_GET, '/tablesdb/' . $databaseId . '/tables/' . $tableId . '/columns/url', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
'x-appwrite-key' => $this->getProject()['apiKey'],
]));
$this->assertEquals('available', $response['body']['status']);
}, 240000, 500);
$projectId = $this->getProject()['$id'];
$query = $this->getQuery(self::UPDATE_URL_COLUMN);
$gqlPayload = [
'query' => $query,
'variables' => [
'databaseId' => $databaseId,
'tableId' => $tableId,
'key' => 'url',
'required' => false,
'default' => 'https://cloud.appwrite.io'
]
];
$column = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $projectId,
], $this->getHeaders()), $gqlPayload);
$this->assertIsArray($column['body']['data']);
$this->assertIsArray($column['body']['data']['tablesDBUpdateUrlColumn']);
$this->assertFalse($column['body']['data']['tablesDBUpdateUrlColumn']['required']);
$this->assertEquals('https://cloud.appwrite.io', $column['body']['data']['tablesDBUpdateUrlColumn']['default']);
$this->assertEquals(200, $column['headers']['status-code']);
}
/**
* @throws Exception
*/
public function testCreateIndex(): void
{
// Need updated string and integer columns first
$this->setupUpdatedStringColumn();
$data = $this->setupUpdatedIntegerColumn();
$projectId = $this->getProject()['$id'];
$query = $this->getQuery(self::CREATE_COLUMN_INDEX);
$gqlPayload = [
'query' => $query,
'variables' => [
'databaseId' => $data['database']['_id'],
'tableId' => $data['table']['_id'],
'key' => 'index',
'type' => 'key',
'columns' => [
'name',
'age',
],
]
];
$index = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $projectId,
], $this->getHeaders()), $gqlPayload);
$this->assertArrayNotHasKey('errors', $index['body']);
$this->assertIsArray($index['body']['data']);
$this->assertIsArray($index['body']['data']['tablesDBCreateIndex']);
// Store for caching
$cacheKey = $this->getProject()['$id'] ?? 'default';
self::$cachedIndexData[$cacheKey] = [
'database' => $data['database'],
'table' => $data['table'],
'index' => $index['body']['data']['tablesDBCreateIndex'],
];
}
/**
* @throws Exception
*/
public function testCreateRow(): void
{
// Need all columns that the row data references
$this->setupUpdatedStringColumn();
$this->setupUpdatedIntegerColumn();
$this->setupUpdatedBooleanColumn();
$this->setupUpdatedFloatColumn();
$this->setupUpdatedEmailColumn();
$this->setupUpdatedDatetimeColumn();
$data = $this->setupUpdatedEnumColumn();
$projectId = $this->getProject()['$id'];
$databaseId = $data['database']['_id'];
$tableId = $data['table']['_id'];
// Wait for all columns to be available
$columns = ['name', 'age', 'alive', 'salary', 'email', 'dob', 'role'];
foreach ($columns as $columnKey) {
$this->assertEventually(function () use ($databaseId, $tableId, $columnKey) {
$response = $this->client->call(Client::METHOD_GET, '/tablesdb/' . $databaseId . '/tables/' . $tableId . '/columns/' . $columnKey, array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
'x-appwrite-key' => $this->getProject()['apiKey'],
]));
$this->assertEquals('available', $response['body']['status']);
}, 240000, 500);
}
$query = $this->getQuery(self::CREATE_ROW);
$gqlPayload = [
'query' => $query,
'variables' => [
'databaseId' => $databaseId,
'tableId' => $tableId,
'rowId' => ID::unique(),
'data' => [
'name' => 'John Doe',
'email' => 'example@appwrite.io',
'age' => 30,
'alive' => true,
'salary' => 9999.9,
'role' => 'crew',
'dob' => '2000-01-01T00:00:00Z',
],
'permissions' => [
Permission::read(Role::any()),
Permission::update(Role::any()),
Permission::delete(Role::any()),
],
]
];
$row = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $projectId,
], $this->getHeaders()), $gqlPayload);
$this->assertArrayNotHasKey('errors', $row['body']);
$this->assertIsArray($row['body']['data']);
$row = $row['body']['data']['tablesDBCreateRow'];
$this->assertIsArray($row);
// Store for caching
$cacheKey = $this->getProject()['$id'] ?? 'default';
self::$cachedRowData[$cacheKey] = [
'database' => $data['database'],
'table' => $data['table'],
'row' => $row,
];
}
// /**
// * @depends testCreateStringColumn
// * @depends testCreateIntegerColumn
// * @depends testCreateBooleanColumn
// * @depends testCreateFloatColumn
// * @depends testCreateEmailColumn
// * @depends testCreateEnumColumn
// * @depends testCreateDatetimeColumn
// * @throws Exception
// */
// public function testCreateCustomEntity(): array
// {
// $projectId = $this->getProject()['$id'];
// $query = $this->getQuery(self::CREATE_CUSTOM_ENTITY);
// $gqlPayload = [
// 'query' => $query,
// 'variables' => [
// 'name' => 'John Doe',
// 'age' => 35,
// 'alive' => true,
// 'salary' => 9999.9,
// 'email' => 'johndoe@appwrite.io',
// 'role' => 'crew',
// 'dob' => '2000-01-01T00:00:00Z',
// ]
// ];
//
// $actor = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([
// 'content-type' => 'application/json',
// 'x-appwrite-project' => $projectId,
// ], $this->getHeaders()), $gqlPayload);
//
// $this->assertArrayNotHasKey('errors', $actor['body']);
// $this->assertIsArray($actor['body']['data']);
// $actor = $actor['body']['data']['actorsCreate'];
// $this->assertIsArray($actor);
//
// return $actor;
// }
public function testGetDatabases(): void
{
$projectId = $this->getProject()['$id'];
$query = $this->getQuery(self::TABLESDB_GET_DATABASES);
$gqlPayload = [
'query' => $query,
];
$databases = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $projectId,
], $this->getHeaders()), $gqlPayload);
$this->assertArrayNotHasKey('errors', $databases['body']);
$this->assertIsArray($databases['body']['data']);
$this->assertIsArray($databases['body']['data']['tablesDBList']);
}
/**
* @throws Exception
*/
public function testGetDatabase(): void
{
$database = $this->setupDatabase();
$projectId = $this->getProject()['$id'];
$query = $this->getQuery(self::TABLESDB_GET_DATABASE);
$gqlPayload = [
'query' => $query,
'variables' => [
'databaseId' => $database['_id'],
]
];
$database = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $projectId,
], $this->getHeaders()), $gqlPayload);
$this->assertArrayNotHasKey('errors', $database['body']);
$this->assertIsArray($database['body']['data']);
$this->assertIsArray($database['body']['data']['tablesDBGet']);
}
/**
* @throws Exception
*/
public function testGetTables(): void
{
$data = $this->setupTable();
$projectId = $this->getProject()['$id'];
$query = $this->getQuery(self::GET_TABLES);
$gqlPayload = [
'query' => $query,
'variables' => [
'databaseId' => $data['database']['_id'],
]
];
$tables = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $projectId,
], $this->getHeaders()), $gqlPayload);
$this->assertArrayNotHasKey('errors', $tables['body']);
$this->assertIsArray($tables['body']['data']);
$this->assertIsArray($tables['body']['data']['tablesDBListTables']);
}
/**
* @throws Exception
*/
public function testGetTable(): void
{
$data = $this->setupTable();
$projectId = $this->getProject()['$id'];
$query = $this->getQuery(self::GET_TABLE);
$gqlPayload = [
'query' => $query,
'variables' => [
'databaseId' => $data['database']['_id'],
'tableId' => $data['table']['_id'],
]
];
$table = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $projectId,
], $this->getHeaders()), $gqlPayload);
$this->assertArrayNotHasKey('errors', $table['body']);
$this->assertIsArray($table['body']['data']);
$this->assertIsArray($table['body']['data']['tablesDBGetTable']);
}
/**
* @throws Exception
*/
public function testGetColumns(): void
{
$this->setupUpdatedStringColumn();
$data = $this->setupUpdatedIntegerColumn();
$projectId = $this->getProject()['$id'];
$query = $this->getQuery(self::GET_COLUMNS);
$gqlPayload = [
'query' => $query,
'variables' => [
'databaseId' => $data['database']['_id'],
'tableId' => $data['table']['_id'],
]
];
$columns = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $projectId,
], $this->getHeaders()), $gqlPayload);
$this->assertArrayNotHasKey('errors', $columns['body']);
$this->assertIsArray($columns['body']['data']);
$this->assertIsArray($columns['body']['data']['tablesDBListColumns']);
}
/**
* @throws Exception
*/
public function testGetColumn(): void
{
$data = $this->setupStringColumn();
$projectId = $this->getProject()['$id'];
$query = $this->getQuery(self::GET_COLUMN);
$gqlPayload = [
'query' => $query,
'variables' => [
'databaseId' => $data['database']['_id'],
'tableId' => $data['table']['_id'],
'key' => 'name',
]
];
$column = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $projectId,
], $this->getHeaders()), $gqlPayload);
$this->assertArrayNotHasKey('errors', $column['body']);
$this->assertIsArray($column['body']['data']);
$this->assertIsArray($column['body']['data']['tablesDBGetColumn']);
}
/**
* @throws Exception
*/
public function testGetIndexes(): void
{
$data = $this->setupIndex();
$projectId = $this->getProject()['$id'];
$query = $this->getQuery(self::GET_COLUMN_INDEXES);
$gqlPayload = [
'query' => $query,
'variables' => [
'databaseId' => $data['database']['_id'],
'tableId' => $data['table']['_id'],
]
];
$indices = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $projectId,
], $this->getHeaders()), $gqlPayload);
$this->assertArrayNotHasKey('errors', $indices['body']);
$this->assertIsArray($indices['body']['data']);
$this->assertIsArray($indices['body']['data']['tablesDBListIndexes']);
}
/**
* @throws Exception
*/
public function testGetIndex(): void
{
$data = $this->setupIndex();
$projectId = $this->getProject()['$id'];
$query = $this->getQuery(self::GET_COLUMN_INDEX);
$gqlPayload = [
'query' => $query,
'variables' => [
'databaseId' => $data['database']['_id'],
'tableId' => $data['table']['_id'],
'key' => $data['index']['key'],
]
];
$index = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $projectId,
], $this->getHeaders()), $gqlPayload);
$this->assertArrayNotHasKey('errors', $index['body']);
$this->assertIsArray($index['body']['data']);
$this->assertIsArray($index['body']['data']['tablesDBGetIndex']);
}
/**
* @throws Exception
*/
public function testGetRows(): void
{
$data = $this->setupTable();
$projectId = $this->getProject()['$id'];
$query = $this->getQuery(self::GET_ROWS);
$gqlPayload = [
'query' => $query,
'variables' => [
'databaseId' => $data['database']['_id'],
'tableId' => $data['table']['_id'],
]
];
$rows = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $projectId,
], $this->getHeaders()), $gqlPayload);
$this->assertArrayNotHasKey('errors', $rows['body']);
$this->assertIsArray($rows['body']['data']);
$this->assertIsArray($rows['body']['data']['tablesDBListRows']);
}
/**
* @throws Exception
*/
public function testGetRow(): void
{
$data = $this->setupRow();
$projectId = $this->getProject()['$id'];
$query = $this->getQuery(self::GET_ROW);
$gqlPayload = [
'query' => $query,
'variables' => [
'databaseId' => $data['database']['_id'],
'tableId' => $data['table']['_id'],
'rowId' => $data['row']['_id'],
]
];
$row = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $projectId,
], $this->getHeaders()), $gqlPayload);
$this->assertArrayNotHasKey('errors', $row['body']);
$this->assertIsArray($row['body']['data']);
$this->assertIsArray($row['body']['data']['tablesDBGetRow']);
}
// /**
// * @depends testCreateCustomEntity
// * @throws Exception
// */
// public function testGetCustomEntities($data)
// {
// $projectId = $this->getProject()['$id'];
// $query = $this->getQuery(self::GET_CUSTOM_ENTITIES);
// $gqlPayload = [
// 'query' => $query,
// ];
//
// $customEntities = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([
// 'content-type' => 'application/json',
// 'x-appwrite-project' => $projectId,
// ], $this->getHeaders()), $gqlPayload);
//
// $this->assertArrayNotHasKey('errors', $customEntities['body']);
// $this->assertIsArray($customEntities['body']['data']);
// $this->assertIsArray($customEntities['body']['data']['actorsList']);
// }
//
// /**
// * @depends testCreateCustomEntity
// * @throws Exception
// */
// public function testGetCustomEntity($data)
// {
// $projectId = $this->getProject()['$id'];
// $query = $this->getQuery(self::GET_CUSTOM_ENTITY);
// $gqlPayload = [
// 'query' => $query,
// 'variables' => [
// 'id' => $data['id'],
// ]
// ];
//
// $entity = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([
// 'content-type' => 'application/json',
// 'x-appwrite-project' => $projectId,
// ], $this->getHeaders()), $gqlPayload);
//
// $this->assertArrayNotHasKey('errors', $entity['body']);
// $this->assertIsArray($entity['body']['data']);
// $this->assertIsArray($entity['body']['data']['actorsGet']);
// }
/**
* @throws Exception
*/
public function testUpdateDatabase(): void
{
$database = $this->setupDatabase();
$projectId = $this->getProject()['$id'];
$query = $this->getQuery(self::TABLESDB_UPDATE_DATABASE);
$gqlPayload = [
'query' => $query,
'variables' => [
'databaseId' => $database['_id'],
'name' => 'New Database Name',
]
];
$database = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $projectId,
], $this->getHeaders()), $gqlPayload);
$this->assertArrayNotHasKey('errors', $database['body']);
$this->assertIsArray($database['body']['data']);
$this->assertIsArray($database['body']['data']['tablesDBUpdate']);
}
/**
* @throws Exception
*/
public function testUpdateTable(): void
{
$data = $this->setupTable();
$projectId = $this->getProject()['$id'];
$query = $this->getQuery(self::UPDATE_TABLE);
$gqlPayload = [
'query' => $query,
'variables' => [
'databaseId' => $data['database']['_id'],
'tableId' => $data['table']['_id'],
'name' => 'New Table Name',
'rowSecurity' => false,
]
];
$table = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $projectId,
], $this->getHeaders()), $gqlPayload);
$this->assertArrayNotHasKey('errors', $table['body']);
$this->assertIsArray($table['body']['data']);
$this->assertIsArray($table['body']['data']['tablesDBUpdateTable']);
}
/**
* @throws Exception
*/
public function testUpdateRow(): void
{
$data = $this->setupRow();
$projectId = $this->getProject()['$id'];
$query = $this->getQuery(self::UPDATE_ROW);
$gqlPayload = [
'query' => $query,
'variables' => [
'databaseId' => $data['database']['_id'],
'tableId' => $data['table']['_id'],
'rowId' => $data['row']['_id'],
'data' => [
'name' => 'New Row Name',
],
]
];
$row = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $projectId,
], $this->getHeaders()), $gqlPayload);
$this->assertArrayNotHasKey('errors', $row['body']);
$this->assertIsArray($row['body']['data']);
$row = $row['body']['data']['tablesDBUpdateRow'];
$this->assertIsArray($row);
$this->assertStringContainsString('New Row Name', $row['data']);
}
// /**
// * @depends testCreateCustomEntity
// * @throws Exception
// */
// public function testUpdateCustomEntity(array $data)
// {
// $projectId = $this->getProject()['$id'];
// $query = $this->getQuery(self::UPDATE_CUSTOM_ENTITY);
// $gqlPayload = [
// 'query' => $query,
// 'variables' => [
// 'id' => $data['id'],
// 'name' => 'New Custom Entity Name',
// ]
// ];
//
// $entity = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([
// 'content-type' => 'application/json',
// 'x-appwrite-project' => $projectId,
// ], $this->getHeaders()), $gqlPayload);
//
// $this->assertArrayNotHasKey('errors', $entity['body']);
// $this->assertIsArray($entity['body']['data']);
// $entity = $entity['body']['data']['actorsUpdate'];
// $this->assertIsArray($entity);
// $this->assertStringContainsString('New Custom Entity Name', $entity['name']);
// }
/**
* @throws Exception
*/
public function testDeleteRow(): void
{
$data = $this->setupRow();
$projectId = $this->getProject()['$id'];
$query = $this->getQuery(self::DELETE_ROW);
$gqlPayload = [
'query' => $query,
'variables' => [
'databaseId' => $data['database']['_id'],
'tableId' => $data['table']['_id'],
'rowId' => $data['row']['_id'],
]
];
$row = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $projectId,
], $this->getHeaders()), $gqlPayload);
$this->assertIsNotArray($row['body']);
$this->assertEquals(204, $row['headers']['status-code']);
}
// /**
// * @depends testCreateCustomEntity
// * @throws Exception
// */
// public function testDeleteCustomEntity(array $data)
// {
// $projectId = $this->getProject()['$id'];
// $query = $this->getQuery(self::DELETE_CUSTOM_ENTITY);
// $gqlPayload = [
// 'query' => $query,
// 'variables' => [
// 'id' => $data['id'],
// ]
// ];
//
// $entity = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([
// 'content-type' => 'application/json',
// 'x-appwrite-project' => $projectId,
// ], $this->getHeaders()), $gqlPayload);
//
// $this->assertIsNotArray($entity['body']);
// $this->assertEquals(204, $entity['headers']['status-code']);
// }
/**
* @throws Exception
*/
public function testDeleteColumn(): void
{
$data = $this->setupUpdatedStringColumn();
$projectId = $this->getProject()['$id'];
$query = $this->getQuery(self::DELETE_COLUMN);
$gqlPayload = [
'query' => $query,
'variables' => [
'databaseId' => $data['database']['_id'],
'tableId' => $data['table']['_id'],
'key' => 'name',
]
];
$column = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $projectId,
], $this->getHeaders()), $gqlPayload);
$this->assertIsNotArray($column['body']);
$this->assertEquals(204, $column['headers']['status-code']);
}
/**
* @throws Exception
*/
public function testDeleteTable(): void
{
$data = $this->setupTable();
$projectId = $this->getProject()['$id'];
$query = $this->getQuery(self::DELETE_TABLE);
$gqlPayload = [
'query' => $query,
'variables' => [
'databaseId' => $data['database']['_id'],
'tableId' => $data['table']['_id'],
]
];
$table = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $projectId,
], $this->getHeaders()), $gqlPayload);
$this->assertIsNotArray($table['body']);
$this->assertEquals(204, $table['headers']['status-code']);
}
/**
* @throws Exception
*/
public function testDeleteDatabase(): void
{
$database = $this->setupDatabase();
$projectId = $this->getProject()['$id'];
$query = $this->getQuery(self::TABLESDB_DELETE_DATABASE);
$gqlPayload = [
'query' => $query,
'variables' => [
'databaseId' => $database['_id'],
]
];
$database = $this->client->call(Client::METHOD_POST, '/graphql', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $projectId,
], $this->getHeaders()), $gqlPayload);
$this->assertIsNotArray($database['body']);
$this->assertEquals(204, $database['headers']['status-code']);
}
/**
* @throws Exception
*/
public function testBulkCreate(): void
{
$data = $this->setupBulkData();
$this->assertNotEmpty($data['databaseId']);
$this->assertNotEmpty($data['tableId']);
$this->assertNotEmpty($data['projectId']);
}
public function testBulkUpdate(): void
{
$data = $this->setupBulkData();
$userId = $this->getUser()['$id'];
$permissions = [
Permission::read(Role::user($userId)),
Permission::update(Role::user($userId)),
Permission::delete(Role::user($userId)),
];
$headers = array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $data['projectId'],
], $this->getHeaders());
// Step 1: Bulk update rows
$query = $this->getQuery(self::UPDATE_ROWS);
$payload = [
'query' => $query,
'variables' => [
'databaseId' => $data['databaseId'],
'tableId' => $data['tableId'],
'data' => [
'name' => 'Rows Updated',
'$permissions' => $permissions,
],
],
];
$res = $this->client->call(Client::METHOD_POST, '/graphql', $headers, $payload);
$this->assertArrayNotHasKey('errors', $res['body']);
$this->assertCount(10, $res['body']['data']['tablesDBUpdateRows']['rows']);
// Step 2: Fetch and validate updated rows
$query = $this->getQuery(self::GET_ROWS);
$payload = [
'query' => $query,
'variables' => [
'databaseId' => $data['databaseId'],
'tableId' => $data['tableId'],
'queries' => [Query::equal('name', ['Rows Updated'])->toString()],
],
];
$res = $this->client->call(Client::METHOD_POST, '/graphql', $headers, $payload);
$this->assertEquals(200, $res['headers']['status-code']);
$fetched = $res['body']['data']['tablesDBListRows'];
$this->assertEquals(10, $fetched['total']);
foreach ($fetched['rows'] as $row) {
$this->assertEquals($permissions, $row['_permissions']);
$this->assertEquals($data['tableId'], $row['_tableId']);
$this->assertEquals($data['databaseId'], $row['_databaseId']);
$this->assertEquals('Rows Updated', json_decode($row['data'], true)['name']);
}
}
public function testBulkUpsert(): void
{
$data = $this->setupBulkData();
$userId = $this->getUser()['$id'];
$headers = array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $data['projectId'],
], $this->getHeaders());
$permissions = [
Permission::read(Role::user($userId)),
Permission::update(Role::user($userId)),
Permission::delete(Role::user($userId)),
];
// Step 1: Upsert two new rows
$query = $this->getQuery(self::UPSERT_ROWS);
$upsertPayload = [
'query' => $query,
'variables' => [
'databaseId' => $data['databaseId'],
'tableId' => $data['tableId'],
'rows' => [
[
'$id' => ID::unique(),
'name' => 'Row #1000',
],
[
'name' => 'Row #11',
],
],
],
];
$response = $this->client->call(Client::METHOD_POST, '/graphql', $headers, $upsertPayload);
$this->assertArrayNotHasKey('errors', $response['body']);
$rows = $response['body']['data']['tablesDBUpsertRows']['rows'];
$this->assertCount(2, $rows);
$rowMap = [];
foreach ($rows as $row) {
$decoded = json_decode($row['data'], true);
$rowMap[$decoded['name']] = $decoded;
}
$this->assertArrayHasKey('Row #1000', $rowMap);
$this->assertArrayHasKey('Row #11', $rowMap);
// Step 2: Fetch all rows and confirm count is now 12
$query = $this->getQuery(self::GET_ROWS);
$fetchPayload = [
'query' => $query,
'variables' => [
'databaseId' => $data['databaseId'],
'tableId' => $data['tableId'],
],
];
$res = $this->client->call(Client::METHOD_POST, '/graphql', $headers, $fetchPayload);
$this->assertEquals(200, $res['headers']['status-code']);
$fetched = $res['body']['data']['tablesDBListRows'];
$this->assertGreaterThanOrEqual(12, $fetched['total']);
// Step 3: Upsert row with new permissions using `tablesUpsertRow`
$upsertRowId = ID::unique();
$query = $this->getQuery(self::UPSERT_ROW);
$payload = [
'query' => $query,
'variables' => [
'databaseId' => $data['databaseId'],
'tableId' => $data['tableId'],
'rowId' => $upsertRowId,
'data' => ['name' => 'Row Upserted'],
'permissions' => $permissions,
],
];
$res = $this->client->call(Client::METHOD_POST, '/graphql', $headers, $payload);
$this->assertArrayNotHasKey('errors', $res['body']);
$updated = $res['body']['data']['tablesDBUpsertRow'];
$this->assertEquals('Row Upserted', json_decode($updated['data'], true)['name']);
$this->assertEquals($data['databaseId'], $updated['_databaseId']);
$this->assertEquals($data['tableId'], $updated['_tableId']);
}
public function testBulkDelete(): void
{
$data = $this->setupBulkData();
$headers = array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $data['projectId'],
], $this->getHeaders());
// Step 1: Perform bulk delete
$query = $this->getQuery(self::DELETE_ROWS);
$payload = [
'query' => $query,
'variables' => [
'databaseId' => $data['databaseId'],
'tableId' => $data['tableId'],
],
];
$res = $this->client->call(Client::METHOD_POST, '/graphql', $headers, $payload);
$this->assertArrayNotHasKey('errors', $res['body']);
$deleted = $res['body']['data']['tablesDBDeleteRows']['rows'];
$this->assertIsArray($deleted);
$this->assertGreaterThanOrEqual(10, count($deleted));
// Step 2: Confirm deletion via refetch
$query = $this->getQuery(self::GET_ROWS);
$payload = [
'query' => $query,
'variables' => [
'databaseId' => $data['databaseId'],
'tableId' => $data['tableId'],
],
];
$res = $this->client->call(Client::METHOD_POST, '/graphql', $headers, $payload);
$this->assertEquals(200, $res['headers']['status-code']);
$this->assertEquals(0, $res['body']['data']['tablesDBListRows']['total']);
}
}