mirror of
https://github.com/appwrite/appwrite.git
synced 2026-05-26 13:51:13 +00:00
added spatial query testing
This commit is contained in:
@@ -5763,4 +5763,980 @@ trait DatabasesBase
|
||||
]);
|
||||
$this->assertEquals(400, $inc3['headers']['status-code']);
|
||||
}
|
||||
|
||||
public function testSpatialPointAttributes(): void
|
||||
{
|
||||
$database = $this->client->call(Client::METHOD_POST, '/databases', [
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
], [
|
||||
'databaseId' => ID::unique(),
|
||||
'name' => 'Spatial Point Test Database'
|
||||
]);
|
||||
|
||||
$databaseId = $database['body']['$id'];
|
||||
|
||||
// Create collection with spatial and non-spatial attributes
|
||||
$collection = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]), [
|
||||
'collectionId' => ID::unique(),
|
||||
'name' => 'Spatial Point Collection',
|
||||
'documentSecurity' => true,
|
||||
'permissions' => [
|
||||
Permission::create(Role::user($this->getUser()['$id'])),
|
||||
Permission::read(Role::user($this->getUser()['$id'])),
|
||||
Permission::update(Role::user($this->getUser()['$id'])),
|
||||
Permission::delete(Role::user($this->getUser()['$id'])),
|
||||
],
|
||||
]);
|
||||
|
||||
$collectionId = $collection['body']['$id'];
|
||||
|
||||
// Create string attribute
|
||||
$this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/string', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]), [
|
||||
'key' => 'name',
|
||||
'size' => 256,
|
||||
'required' => true,
|
||||
]);
|
||||
|
||||
// Create point attribute - handle both 201 (created) and 200 (already exists)
|
||||
$response = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/point', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]), [
|
||||
'key' => 'location',
|
||||
'required' => true,
|
||||
]);
|
||||
|
||||
$this->assertEquals(202, $response['headers']['status-code']);
|
||||
|
||||
sleep(2);
|
||||
|
||||
// Test 1: Create document with point attribute
|
||||
$response = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'documentId' => ID::unique(),
|
||||
'data' => [
|
||||
'name' => 'Test Location',
|
||||
'location' => [40.7128, -74.0060] // New York coordinates
|
||||
]
|
||||
]);
|
||||
|
||||
$this->assertEquals(201, $response['headers']['status-code']);
|
||||
$this->assertEquals([40.7128, -74.0060], $response['body']['location']);
|
||||
$documentId = $response['body']['$id'];
|
||||
|
||||
// Test 2: Read document with point attribute
|
||||
$response = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents/' . $documentId, array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()));
|
||||
|
||||
$this->assertEquals(200, $response['headers']['status-code']);
|
||||
$this->assertEquals([40.7128, -74.0060], $response['body']['location']);
|
||||
|
||||
// Test 3: Update document with new point coordinates
|
||||
$response = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents/' . $documentId, array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'data' => [
|
||||
'location' => [40.7589, -73.9851] // Times Square coordinates
|
||||
]
|
||||
]);
|
||||
|
||||
$this->assertEquals(200, $response['headers']['status-code']);
|
||||
$this->assertEquals([40.7589, -73.9851], $response['body']['location']);
|
||||
|
||||
// Test 4: Upsert document with point attribute
|
||||
$response = $this->client->call(Client::METHOD_PUT, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents/' . ID::unique(), array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'documentId' => ID::unique(),
|
||||
'data' => [
|
||||
'name' => 'Upserted Location',
|
||||
'location' => [34.0522, -118.2437] // Los Angeles coordinates
|
||||
]
|
||||
]);
|
||||
|
||||
$this->assertEquals(200, $response['headers']['status-code']);
|
||||
$this->assertEquals([34.0522, -118.2437], $response['body']['location']);
|
||||
|
||||
// Test 5: Create document without permissions (should fail)
|
||||
$response = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents', [
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], [
|
||||
'documentId' => ID::unique(),
|
||||
'data' => [
|
||||
'name' => 'Unauthorized Location',
|
||||
'location' => [0, 0]
|
||||
]
|
||||
]);
|
||||
|
||||
$this->assertEquals(401, $response['headers']['status-code']);
|
||||
|
||||
// Cleanup
|
||||
$this->client->call(Client::METHOD_DELETE, '/databases/' . $databaseId . '/collections/' . $collectionId, array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]));
|
||||
|
||||
$this->client->call(Client::METHOD_DELETE, '/databases/' . $databaseId, array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]));
|
||||
}
|
||||
|
||||
public function testSpatialLineAttributes(): void
|
||||
{
|
||||
$database = $this->client->call(Client::METHOD_POST, '/databases', [
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
], [
|
||||
'databaseId' => ID::unique(),
|
||||
'name' => 'Spatial Line Test Database'
|
||||
]);
|
||||
|
||||
$databaseId = $database['body']['$id'];
|
||||
|
||||
// Create collection with spatial and non-spatial attributes
|
||||
$collection = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]), [
|
||||
'collectionId' => ID::unique(),
|
||||
'name' => 'Spatial Line Collection',
|
||||
'documentSecurity' => true,
|
||||
'permissions' => [
|
||||
Permission::create(Role::user($this->getUser()['$id'])),
|
||||
Permission::read(Role::user($this->getUser()['$id'])),
|
||||
Permission::update(Role::user($this->getUser()['$id'])),
|
||||
Permission::delete(Role::user($this->getUser()['$id'])),
|
||||
],
|
||||
]);
|
||||
|
||||
$collectionId = $collection['body']['$id'];
|
||||
|
||||
// Create integer attribute
|
||||
$this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/integer', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]), [
|
||||
'key' => 'distance',
|
||||
'required' => true,
|
||||
]);
|
||||
|
||||
// Create line attribute
|
||||
$this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/line', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]), [
|
||||
'key' => 'route',
|
||||
'required' => true,
|
||||
]);
|
||||
|
||||
sleep(2);
|
||||
|
||||
// Test 1: Create document with line attribute
|
||||
$response = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'documentId' => ID::unique(),
|
||||
'data' => [
|
||||
'distance' => 100,
|
||||
'route' => [[40.7128, -74.0060], [40.7589, -73.9851]] // Line from Downtown to Times Square
|
||||
]
|
||||
]);
|
||||
|
||||
$this->assertEquals(201, $response['headers']['status-code']);
|
||||
$this->assertEquals([[40.7128, -74.0060], [40.7589, -73.9851]], $response['body']['route']);
|
||||
$documentId = $response['body']['$id'];
|
||||
|
||||
// Test 2: Read document with line attribute
|
||||
$response = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents/' . $documentId, array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()));
|
||||
|
||||
$this->assertEquals(200, $response['headers']['status-code']);
|
||||
$this->assertEquals([[40.7128, -74.0060], [40.7589, -73.9851]], $response['body']['route']);
|
||||
|
||||
// Test 3: Update document with new line coordinates
|
||||
$response = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents/' . $documentId, array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'data' => [
|
||||
'route' => [[40.7128, -74.0060], [40.7589, -73.9851], [40.7505, -73.9934]] // Extended route
|
||||
]
|
||||
]);
|
||||
|
||||
$this->assertEquals(200, $response['headers']['status-code']);
|
||||
$this->assertEquals([[40.7128, -74.0060], [40.7589, -73.9851], [40.7505, -73.9934]], $response['body']['route']);
|
||||
|
||||
// Test 4: Upsert document with line attribute
|
||||
$response = $this->client->call(Client::METHOD_PUT, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents/' . ID::unique(), array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'documentId' => ID::unique(),
|
||||
'data' => [
|
||||
'distance' => 200,
|
||||
'route' => [[34.0522, -118.2437], [34.0736, -118.2400]] // LA route
|
||||
]
|
||||
]);
|
||||
|
||||
$this->assertEquals(200, $response['headers']['status-code']);
|
||||
$this->assertEquals([[34.0522, -118.2437], [34.0736, -118.2400]], $response['body']['route']);
|
||||
|
||||
// Test 5: Delete document
|
||||
$response = $this->client->call(Client::METHOD_DELETE, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents/' . $documentId, array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()));
|
||||
|
||||
$this->assertEquals(204, $response['headers']['status-code']);
|
||||
|
||||
// Test 6: Verify document is deleted
|
||||
$response = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents/' . $documentId, array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()));
|
||||
|
||||
$this->assertEquals(404, $response['headers']['status-code']);
|
||||
|
||||
// Cleanup
|
||||
$this->client->call(Client::METHOD_DELETE, '/databases/' . $databaseId . '/collections/' . $collectionId, array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]));
|
||||
|
||||
$this->client->call(Client::METHOD_DELETE, '/databases/' . $databaseId, array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]));
|
||||
}
|
||||
|
||||
public function testSpatialPolygonAttributes(): void
|
||||
{
|
||||
$database = $this->client->call(Client::METHOD_POST, '/databases', [
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
], [
|
||||
'databaseId' => ID::unique(),
|
||||
'name' => 'Spatial Polygon Test Database'
|
||||
]);
|
||||
|
||||
$databaseId = $database['body']['$id'];
|
||||
|
||||
// Create collection with spatial and non-spatial attributes
|
||||
$collection = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]), [
|
||||
'collectionId' => ID::unique(),
|
||||
'name' => 'Spatial Polygon Collection',
|
||||
'documentSecurity' => true,
|
||||
'permissions' => [
|
||||
Permission::create(Role::user($this->getUser()['$id'])),
|
||||
Permission::read(Role::user($this->getUser()['$id'])),
|
||||
Permission::update(Role::user($this->getUser()['$id'])),
|
||||
Permission::delete(Role::user($this->getUser()['$id'])),
|
||||
],
|
||||
]);
|
||||
|
||||
$collectionId = $collection['body']['$id'];
|
||||
|
||||
// Create boolean attribute
|
||||
$this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/boolean', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]), [
|
||||
'key' => 'active',
|
||||
'required' => true,
|
||||
]);
|
||||
|
||||
// Create polygon attribute
|
||||
$this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/polygon', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]), [
|
||||
'key' => 'area',
|
||||
'required' => true,
|
||||
]);
|
||||
|
||||
sleep(2);
|
||||
|
||||
// Test 1: Create document with polygon attribute
|
||||
$response = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'documentId' => ID::unique(),
|
||||
'data' => [
|
||||
'active' => true,
|
||||
'area' => [[[40.7128, -74.0060], [40.7589, -74.0060], [40.7589, -73.9851], [40.7128, -73.9851], [40.7128, -74.0060]]] // Manhattan area
|
||||
]
|
||||
]);
|
||||
|
||||
$this->assertEquals(201, $response['headers']['status-code']);
|
||||
$this->assertEquals([[[40.7128, -74.0060], [40.7589, -74.0060], [40.7589, -73.9851], [40.7128, -73.9851], [40.7128, -74.0060]]], $response['body']['area']);
|
||||
$documentId = $response['body']['$id'];
|
||||
|
||||
// Test 2: Read document with polygon attribute
|
||||
$response = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents/' . $documentId, array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()));
|
||||
|
||||
$this->assertEquals(200, $response['headers']['status-code']);
|
||||
$this->assertEquals([[[40.7128, -74.0060], [40.7589, -74.0060], [40.7589, -73.9851], [40.7128, -73.9851], [40.7128, -74.0060]]], $response['body']['area']);
|
||||
|
||||
// Test 3: Update document with new polygon coordinates
|
||||
$response = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents/' . $documentId, array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'data' => [
|
||||
'area' => [[[40.7128, -74.0060], [40.7589, -74.0060], [40.7589, -73.9851], [40.7128, -73.9851], [40.7505, -73.9934], [40.7128, -74.0060]]] // Extended area
|
||||
]
|
||||
]);
|
||||
|
||||
$this->assertEquals(200, $response['headers']['status-code']);
|
||||
$this->assertEquals([[[40.7128, -74.0060], [40.7589, -74.0060], [40.7589, -73.9851], [40.7128, -73.9851], [40.7505, -73.9934], [40.7128, -74.0060]]], $response['body']['area']);
|
||||
|
||||
// Test 4: Upsert document with polygon attribute
|
||||
$response = $this->client->call(Client::METHOD_PUT, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents/' . ID::unique(), array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'documentId' => ID::unique(),
|
||||
'data' => [
|
||||
'active' => false,
|
||||
'area' => [[[34.0522, -118.2437], [34.0736, -118.2437], [34.0736, -118.2400], [34.0522, -118.2400], [34.0522, -118.2437]]] // LA area
|
||||
]
|
||||
]);
|
||||
|
||||
$this->assertEquals(200, $response['headers']['status-code']);
|
||||
$this->assertEquals([[[34.0522, -118.2437], [34.0736, -118.2437], [34.0736, -118.2400], [34.0522, -118.2400], [34.0522, -118.2437]]], $response['body']['area']);
|
||||
|
||||
// Test 5: Create document without required polygon attribute (should fail)
|
||||
$response = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'documentId' => ID::unique(),
|
||||
'data' => [
|
||||
'active' => true
|
||||
// Missing required 'area' attribute
|
||||
]
|
||||
]);
|
||||
|
||||
$this->assertEquals(400, $response['headers']['status-code']);
|
||||
|
||||
// Cleanup
|
||||
$this->client->call(Client::METHOD_DELETE, '/databases/' . $databaseId . '/collections/' . $collectionId, array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]));
|
||||
|
||||
$this->client->call(Client::METHOD_DELETE, '/databases/' . $databaseId, array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]));
|
||||
}
|
||||
|
||||
public function testSpatialAttributesMixedCollection(): void
|
||||
{
|
||||
$database = $this->client->call(Client::METHOD_POST, '/databases', [
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
], [
|
||||
'databaseId' => ID::unique(),
|
||||
'name' => 'Mixed Spatial Test Database'
|
||||
]);
|
||||
|
||||
$databaseId = $database['body']['$id'];
|
||||
|
||||
// Create collection with multiple spatial and non-spatial attributes
|
||||
$collection = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]), [
|
||||
'collectionId' => ID::unique(),
|
||||
'name' => 'Mixed Spatial Collection',
|
||||
'documentSecurity' => true,
|
||||
'permissions' => [
|
||||
Permission::create(Role::user($this->getUser()['$id'])),
|
||||
Permission::read(Role::user($this->getUser()['$id'])),
|
||||
Permission::update(Role::user($this->getUser()['$id'])),
|
||||
Permission::delete(Role::user($this->getUser()['$id'])),
|
||||
],
|
||||
]);
|
||||
|
||||
$collectionId = $collection['body']['$id'];
|
||||
|
||||
// Create multiple attributes
|
||||
$this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/string', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]), [
|
||||
'key' => 'name',
|
||||
'size' => 256,
|
||||
'required' => true,
|
||||
]);
|
||||
|
||||
$this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/point', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]), [
|
||||
'key' => 'center',
|
||||
'required' => true,
|
||||
]);
|
||||
|
||||
$this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/line', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]), [
|
||||
'key' => 'boundary',
|
||||
'required' => false,
|
||||
]);
|
||||
|
||||
$this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/polygon', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]), [
|
||||
'key' => 'coverage',
|
||||
'required' => true,
|
||||
]);
|
||||
|
||||
sleep(3);
|
||||
|
||||
// Test 1: Create document with all spatial attributes
|
||||
$response = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'documentId' => ID::unique(),
|
||||
'data' => [
|
||||
'name' => 'Central Park',
|
||||
'center' => [40.7829, -73.9654],
|
||||
'boundary' => [[40.7649, -73.9814], [40.8009, -73.9494]],
|
||||
'coverage' => [[[40.7649, -73.9814], [40.8009, -73.9814], [40.8009, -73.9494], [40.7649, -73.9494], [40.7649, -73.9814]]]
|
||||
]
|
||||
]);
|
||||
|
||||
$this->assertEquals(201, $response['headers']['status-code']);
|
||||
$this->assertEquals([40.7829, -73.9654], $response['body']['center']);
|
||||
$this->assertEquals([[40.7649, -73.9814], [40.8009, -73.9494]], $response['body']['boundary']);
|
||||
$this->assertEquals([[[40.7649, -73.9814], [40.8009, -73.9814], [40.8009, -73.9494], [40.7649, -73.9494], [40.7649, -73.9814]]], $response['body']['coverage']);
|
||||
$documentId = $response['body']['$id'];
|
||||
|
||||
// Test 2: Update document with new spatial data
|
||||
$response = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents/' . $documentId, array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'data' => [
|
||||
'center' => [40.7505, -73.9934],
|
||||
'boundary' => [[40.7305, -74.0134], [40.7705, -73.9734]],
|
||||
'coverage' => [[[40.7305, -74.0134], [40.7705, -74.0134], [40.7705, -73.9734], [40.7305, -73.9734], [40.7305, -74.0134]]]
|
||||
]
|
||||
]);
|
||||
|
||||
$this->assertEquals(200, $response['headers']['status-code']);
|
||||
$this->assertEquals([40.7505, -73.9934], $response['body']['center']);
|
||||
$this->assertEquals([[40.7305, -74.0134], [40.7705, -73.9734]], $response['body']['boundary']);
|
||||
$this->assertEquals([[[40.7305, -74.0134], [40.7705, -74.0134], [40.7705, -73.9734], [40.7305, -73.9734], [40.7305, -74.0134]]], $response['body']['coverage']);
|
||||
|
||||
// Test 3: Create document with minimal required attributes
|
||||
$response = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'documentId' => ID::unique(),
|
||||
'data' => [
|
||||
'name' => 'Minimal Location',
|
||||
'center' => [0, 0],
|
||||
'coverage' => [[[0, 0], [1, 0], [1, 1], [0, 1], [0, 0]]]
|
||||
]
|
||||
]);
|
||||
|
||||
$this->assertEquals(201, $response['headers']['status-code']);
|
||||
$this->assertEquals([0, 0], $response['body']['center']);
|
||||
|
||||
// Test 4: Test permission validation - create without user context
|
||||
$response = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents', [
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], [
|
||||
'documentId' => ID::unique(),
|
||||
'data' => [
|
||||
'name' => 'Unauthorized Location',
|
||||
'center' => [0, 0],
|
||||
'coverage' => [[[0, 0], [1, 0], [1, 1], [0, 1], [0, 0]]]
|
||||
]
|
||||
]);
|
||||
|
||||
$this->assertEquals(401, $response['headers']['status-code']);
|
||||
|
||||
// Cleanup
|
||||
$this->client->call(Client::METHOD_DELETE, '/databases/' . $databaseId . '/collections/' . $collectionId, array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]));
|
||||
|
||||
$this->client->call(Client::METHOD_DELETE, '/databases/' . $databaseId, array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]));
|
||||
}
|
||||
|
||||
public function testSpatialQuery(): void
|
||||
{
|
||||
$database = $this->client->call(Client::METHOD_POST, '/databases', [
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
], [
|
||||
'databaseId' => ID::unique(),
|
||||
'name' => 'Spatial Query Test Database'
|
||||
]);
|
||||
|
||||
$this->assertNotEmpty($database['body']['$id']);
|
||||
$databaseId = $database['body']['$id'];
|
||||
|
||||
// Create collection with spatial attributes
|
||||
$collection = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]), [
|
||||
'collectionId' => ID::unique(),
|
||||
'name' => 'Spatial Query Collection',
|
||||
'documentSecurity' => true,
|
||||
'permissions' => [
|
||||
Permission::create(Role::any()),
|
||||
Permission::read(Role::any()),
|
||||
Permission::delete(Role::any()),
|
||||
Permission::update(Role::any()),
|
||||
],
|
||||
]);
|
||||
|
||||
$this->assertEquals(201, $collection['headers']['status-code']);
|
||||
$collectionId = $collection['body']['$id'];
|
||||
|
||||
// Create string attribute
|
||||
$nameAttribute = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/string', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]), [
|
||||
'key' => 'name',
|
||||
'size' => 256,
|
||||
'required' => true,
|
||||
]);
|
||||
|
||||
$this->assertEquals(202, $nameAttribute['headers']['status-code']);
|
||||
|
||||
// Create point attribute
|
||||
$pointAttribute = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/point', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]), [
|
||||
'key' => 'pointAttr',
|
||||
'required' => true,
|
||||
]);
|
||||
|
||||
$this->assertEquals(202, $pointAttribute['headers']['status-code']);
|
||||
|
||||
// Create line attribute
|
||||
$lineAttribute = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/line', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]), [
|
||||
'key' => 'lineAttr',
|
||||
'required' => true,
|
||||
]);
|
||||
|
||||
$this->assertEquals(202, $lineAttribute['headers']['status-code']);
|
||||
|
||||
// Create polygon attribute
|
||||
$polygonAttribute = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/polygon', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]), [
|
||||
'key' => 'polyAttr',
|
||||
'required' => true,
|
||||
]);
|
||||
|
||||
$this->assertEquals(202, $polygonAttribute['headers']['status-code']);
|
||||
|
||||
// Wait for attributes to be created
|
||||
sleep(2);
|
||||
|
||||
// Create test documents with spatial data
|
||||
$documents = [
|
||||
[
|
||||
'$id' => 'doc1',
|
||||
'name' => 'Test Document 1',
|
||||
'pointAttr' => [6.0, 6.0],
|
||||
'lineAttr' => [[1.0, 1.0], [2.0, 2.0]],
|
||||
'polyAttr' => [[[0.0, 0.0], [10.0, 0.0], [10.0, 10.0], [0.0, 10.0], [0.0, 0.0]]]
|
||||
],
|
||||
[
|
||||
'$id' => 'doc2',
|
||||
'name' => 'Test Document 2',
|
||||
'pointAttr' => [7.0, 6.0],
|
||||
'lineAttr' => [[10.0, 10.0], [20.0, 20.0]],
|
||||
'polyAttr' => [[[20.0, 20.0], [30.0, 20.0], [30.0, 30.0], [20.0, 30.0], [20.0, 20.0]]]
|
||||
],
|
||||
[
|
||||
'$id' => 'doc3',
|
||||
'name' => 'Test Document 3',
|
||||
'pointAttr' => [25.0, 25.0],
|
||||
'lineAttr' => [[25.0, 25.0], [35.0, 35.0]],
|
||||
'polyAttr' => [[[40.0, 40.0], [50.0, 40.0], [50.0, 50.0], [40.0, 50.0], [40.0, 40.0]]]
|
||||
]
|
||||
];
|
||||
|
||||
foreach ($documents as $doc) {
|
||||
$response = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'documentId' => $doc['$id'],
|
||||
'data' => [
|
||||
'name' => $doc['name'],
|
||||
'pointAttr' => $doc['pointAttr'],
|
||||
'lineAttr' => $doc['lineAttr'],
|
||||
'polyAttr' => $doc['polyAttr']
|
||||
]
|
||||
]);
|
||||
|
||||
$this->assertEquals(201, $response['headers']['status-code']);
|
||||
}
|
||||
|
||||
// Test 1: Equality on non-spatial attribute (name)
|
||||
$response = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'queries' => [Query::equal('name', ['Test Document 1'])->toString()]
|
||||
]);
|
||||
|
||||
$this->assertEquals(200, $response['headers']['status-code']);
|
||||
$this->assertCount(1, $response['body']['documents']);
|
||||
$this->assertEquals('doc1', $response['body']['documents'][0]['$id']);
|
||||
|
||||
|
||||
|
||||
// Test 3: Polygon attribute queries
|
||||
$response = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'queries' => [Query::equal('polyAttr', [[[[0.0, 0.0], [10.0, 0.0], [10.0, 10.0], [0.0, 10.0], [0.0, 0.0]]]])->toString()]
|
||||
]);
|
||||
|
||||
$this->assertEquals(200, $response['headers']['status-code']);
|
||||
$this->assertCount(1, $response['body']['documents']);
|
||||
$this->assertEquals('doc1', $response['body']['documents'][0]['$id']);
|
||||
|
||||
// Test 4: Not equal queries
|
||||
$response = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'queries' => [Query::notEqual('pointAttr', [[6.0, 6.0]])->toString()]
|
||||
]);
|
||||
|
||||
$this->assertEquals(200, $response['headers']['status-code']);
|
||||
$this->assertCount(2, $response['body']['documents']);
|
||||
|
||||
// Test 4.1: contains on line (point on line)
|
||||
$response = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'queries' => [Query::contains('lineAttr', [[1.0, 1.0]])->toString()]
|
||||
]);
|
||||
$this->assertEquals(200, $response['headers']['status-code']);
|
||||
$this->assertCount(1, $response['body']['documents']);
|
||||
$this->assertEquals('doc1', $response['body']['documents'][0]['$id']);
|
||||
|
||||
// Test 4.2: notContains on polygon (point outside all polygons)
|
||||
$response = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'queries' => [Query::notContains('polyAttr', [[15.0, 15.0]])->toString()]
|
||||
]);
|
||||
$this->assertEquals(200, $response['headers']['status-code']);
|
||||
$this->assertEquals(3, $response['body']['total']);
|
||||
|
||||
// Test 4.3: intersects on polygon (point inside doc1 polygon)
|
||||
$response = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'queries' => [Query::intersects('polyAttr', [[5.0, 5.0]])->toString()]
|
||||
]);
|
||||
$this->assertEquals(200, $response['headers']['status-code']);
|
||||
$this->assertEquals(1, $response['body']['total']);
|
||||
$this->assertEquals('doc1', $response['body']['documents'][0]['$id']);
|
||||
|
||||
// Test 4.4: notIntersects on polygon (point outside all polygons)
|
||||
$response = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'queries' => [Query::notIntersects('polyAttr', [[60.0, 60.0]])->toString()]
|
||||
]);
|
||||
$this->assertEquals(200, $response['headers']['status-code']);
|
||||
$this->assertEquals(3, $response['body']['total']);
|
||||
|
||||
// Test 4.5: overlaps on polygon (polygon overlapping doc1)
|
||||
$overlapPoly = [[[5.0, 5.0], [12.0, 5.0], [12.0, 12.0], [5.0, 12.0], [5.0, 5.0]]];
|
||||
$response = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'queries' => [Query::overlaps('polyAttr', [$overlapPoly])->toString()]
|
||||
]);
|
||||
$this->assertEquals(200, $response['headers']['status-code']);
|
||||
$this->assertEquals(1, $response['body']['total']);
|
||||
$this->assertEquals('doc1', $response['body']['documents'][0]['$id']);
|
||||
|
||||
// Test 4.6: notOverlaps on polygon (polygon that overlaps none)
|
||||
$noOverlapPoly = [[[60.0, 60.0], [70.0, 60.0], [70.0, 70.0], [60.0, 70.0], [60.0, 60.0]]];
|
||||
$response = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'queries' => [Query::notOverlaps('polyAttr', [$noOverlapPoly])->toString()]
|
||||
]);
|
||||
$this->assertEquals(200, $response['headers']['status-code']);
|
||||
$this->assertEquals(3, $response['body']['total']);
|
||||
|
||||
// Test 4.7: distance (equals) on point
|
||||
$response = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'queries' => [Query::distance('pointAttr', [[[6.0, 6.0], 1.0]])->toString()]
|
||||
]);
|
||||
$this->assertEquals(200, $response['headers']['status-code']);
|
||||
$this->assertEquals(1, $response['body']['total']);
|
||||
$this->assertEquals('doc2', $response['body']['documents'][0]['$id']);
|
||||
|
||||
// Test 4.8: notDistance (outside radius) on point
|
||||
$response = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'queries' => [Query::notDistance('pointAttr', [[[6.0, 6.0], 1.0]])->toString()]
|
||||
]);
|
||||
$this->assertEquals(200, $response['headers']['status-code']);
|
||||
$this->assertEquals(2, $response['body']['total']);
|
||||
|
||||
// Test 4.9: distanceGreaterThan
|
||||
$response = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'queries' => [Query::distanceGreaterThan('pointAttr', [[[6.0, 6.0], 5.0]])->toString()]
|
||||
]);
|
||||
$this->assertEquals(200, $response['headers']['status-code']);
|
||||
$this->assertEquals(1, $response['body']['total']);
|
||||
|
||||
// Test 4.10: distanceLessThan
|
||||
$response = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'queries' => [Query::distanceLessThan('pointAttr', [[[6.0, 6.0], 0.5]])->toString()]
|
||||
]);
|
||||
$this->assertEquals(200, $response['headers']['status-code']);
|
||||
$this->assertEquals(1, $response['body']['total']);
|
||||
|
||||
// Test 4.11: crosses on line (query line crosses doc1 line)
|
||||
$crossLine = [[1.0, 2.0], [2.0, 1.0]];
|
||||
$response = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'queries' => [Query::crosses('lineAttr', [$crossLine])->toString()]
|
||||
]);
|
||||
$this->assertEquals(200, $response['headers']['status-code']);
|
||||
$this->assertEquals(1, $response['body']['total']);
|
||||
$this->assertEquals('doc1', $response['body']['documents'][0]['$id']);
|
||||
|
||||
// Test 4.12: notCrosses on line (query line does not cross any stored lines)
|
||||
$nonCrossLine = [[0.0, 1.0], [0.0, 2.0]];
|
||||
$response = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'queries' => [Query::notCrosses('lineAttr', [$nonCrossLine])->toString()]
|
||||
]);
|
||||
$this->assertEquals(200, $response['headers']['status-code']);
|
||||
$this->assertEquals(3, $response['body']['total']);
|
||||
|
||||
// Test 4.13: touches on polygon (query polygon touches doc1 polygon at corner)
|
||||
$touchPoly = [[[10.0, 10.0], [20.0, 10.0], [20.0, 20.0], [10.0, 20.0], [10.0, 10.0]]];
|
||||
$response = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'queries' => [Query::touches('polyAttr', [$touchPoly])->toString()]
|
||||
]);
|
||||
$this->assertEquals(200, $response['headers']['status-code']);
|
||||
$this->assertEquals(2, $response['body']['total']);
|
||||
$this->assertEquals('doc1', $response['body']['documents'][0]['$id']);
|
||||
|
||||
// Test 4.14: notTouches on polygon (polygon far away should not touch)
|
||||
$farPoly = [[[60.0, 60.0], [70.0, 60.0], [70.0, 70.0], [60.0, 70.0], [60.0, 60.0]]];
|
||||
$response = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'queries' => [Query::notTouches('polyAttr', [$farPoly])->toString()]
|
||||
]);
|
||||
$this->assertEquals(200, $response['headers']['status-code']);
|
||||
$this->assertEquals(3, $response['body']['total']);
|
||||
|
||||
// Test 5: Select specific attributes
|
||||
$response = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'queries' => [Query::select(['name', 'pointAttr'])->toString()]
|
||||
]);
|
||||
|
||||
$this->assertEquals(200, $response['headers']['status-code']);
|
||||
$this->assertCount(3, $response['body']['documents']);
|
||||
|
||||
foreach ($response['body']['documents'] as $doc) {
|
||||
$this->assertArrayHasKey('name', $doc);
|
||||
$this->assertArrayHasKey('pointAttr', $doc);
|
||||
$this->assertArrayNotHasKey('lineAttr', $doc);
|
||||
$this->assertArrayNotHasKey('polyAttr', $doc);
|
||||
}
|
||||
|
||||
// Test 6: Order by name
|
||||
$response = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'queries' => [Query::orderAsc('name')->toString()]
|
||||
]);
|
||||
|
||||
$this->assertEquals(200, $response['headers']['status-code']);
|
||||
$this->assertCount(3, $response['body']['documents']);
|
||||
$this->assertEquals('Test Document 1', $response['body']['documents'][0]['name']);
|
||||
$this->assertEquals('Test Document 2', $response['body']['documents'][1]['name']);
|
||||
$this->assertEquals('Test Document 3', $response['body']['documents'][2]['name']);
|
||||
|
||||
// Test 7: Limit results
|
||||
$response = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'queries' => [Query::limit(2)->toString()]
|
||||
]);
|
||||
|
||||
$this->assertEquals(200, $response['headers']['status-code']);
|
||||
$this->assertCount(2, $response['body']['documents']);
|
||||
|
||||
// Test 8: Offset results
|
||||
$response = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'queries' => [Query::offset(1)->toString(), Query::limit(2)->toString()]
|
||||
]);
|
||||
|
||||
$this->assertEquals(200, $response['headers']['status-code']);
|
||||
$this->assertCount(2, $response['body']['documents']);
|
||||
|
||||
// Test 9: Complex query with multiple conditions
|
||||
$response = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'queries' => [
|
||||
Query::select(['name', 'pointAttr'])->toString(),
|
||||
Query::orderAsc('name')->toString(),
|
||||
Query::limit(1)->toString()
|
||||
]
|
||||
]);
|
||||
|
||||
$this->assertEquals(200, $response['headers']['status-code']);
|
||||
$this->assertCount(1, $response['body']['documents']);
|
||||
$this->assertEquals('Test Document 1', $response['body']['documents'][0]['name']);
|
||||
|
||||
// Test 11: Query with no results
|
||||
$response = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'queries' => [Query::equal('name', ['Non-existent Document'])->toString()]
|
||||
]);
|
||||
|
||||
$this->assertEquals(200, $response['headers']['status-code']);
|
||||
$this->assertCount(0, $response['body']['documents']);
|
||||
|
||||
// Cleanup
|
||||
$this->client->call(Client::METHOD_DELETE, '/databases/' . $databaseId . '/collections/' . $collectionId, array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]));
|
||||
|
||||
$this->client->call(Client::METHOD_DELETE, '/databases/' . $databaseId, array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1036,567 +1036,4 @@ class DatabasesCustomClientTest extends Scope
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]));
|
||||
}
|
||||
public function testSpatialPointAttributes(): void
|
||||
{
|
||||
$database = $this->client->call(Client::METHOD_POST, '/databases', [
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
], [
|
||||
'databaseId' => ID::unique(),
|
||||
'name' => 'Spatial Point Test Database'
|
||||
]);
|
||||
|
||||
$databaseId = $database['body']['$id'];
|
||||
|
||||
// Create collection with spatial and non-spatial attributes
|
||||
$collection = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]), [
|
||||
'collectionId' => ID::unique(),
|
||||
'name' => 'Spatial Point Collection',
|
||||
'documentSecurity' => true,
|
||||
'permissions' => [
|
||||
Permission::create(Role::user($this->getUser()['$id'])),
|
||||
Permission::read(Role::user($this->getUser()['$id'])),
|
||||
Permission::update(Role::user($this->getUser()['$id'])),
|
||||
Permission::delete(Role::user($this->getUser()['$id'])),
|
||||
],
|
||||
]);
|
||||
|
||||
$collectionId = $collection['body']['$id'];
|
||||
|
||||
// Create string attribute
|
||||
$this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/string', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]), [
|
||||
'key' => 'name',
|
||||
'size' => 256,
|
||||
'required' => true,
|
||||
]);
|
||||
|
||||
// Create point attribute - handle both 201 (created) and 200 (already exists)
|
||||
$response = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/point', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]), [
|
||||
'key' => 'location',
|
||||
'required' => true,
|
||||
]);
|
||||
|
||||
$this->assertEquals(202, $response['headers']['status-code']);
|
||||
|
||||
sleep(2);
|
||||
|
||||
// Test 1: Create document with point attribute
|
||||
$response = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'documentId' => ID::unique(),
|
||||
'data' => [
|
||||
'name' => 'Test Location',
|
||||
'location' => [40.7128, -74.0060] // New York coordinates
|
||||
]
|
||||
]);
|
||||
|
||||
$this->assertEquals(201, $response['headers']['status-code']);
|
||||
$this->assertEquals([40.7128, -74.0060], $response['body']['location']);
|
||||
$documentId = $response['body']['$id'];
|
||||
|
||||
// Test 2: Read document with point attribute
|
||||
$response = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents/' . $documentId, array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()));
|
||||
|
||||
$this->assertEquals(200, $response['headers']['status-code']);
|
||||
$this->assertEquals([40.7128, -74.0060], $response['body']['location']);
|
||||
|
||||
// Test 3: Update document with new point coordinates
|
||||
$response = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents/' . $documentId, array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'data' => [
|
||||
'location' => [40.7589, -73.9851] // Times Square coordinates
|
||||
]
|
||||
]);
|
||||
|
||||
$this->assertEquals(200, $response['headers']['status-code']);
|
||||
$this->assertEquals([40.7589, -73.9851], $response['body']['location']);
|
||||
|
||||
// Test 4: Upsert document with point attribute
|
||||
$response = $this->client->call(Client::METHOD_PUT, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents/' . ID::unique(), array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'documentId' => ID::unique(),
|
||||
'data' => [
|
||||
'name' => 'Upserted Location',
|
||||
'location' => [34.0522, -118.2437] // Los Angeles coordinates
|
||||
]
|
||||
]);
|
||||
|
||||
$this->assertEquals(200, $response['headers']['status-code']);
|
||||
$this->assertEquals([34.0522, -118.2437], $response['body']['location']);
|
||||
|
||||
// Test 5: Create document without permissions (should fail)
|
||||
$response = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents', [
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], [
|
||||
'documentId' => ID::unique(),
|
||||
'data' => [
|
||||
'name' => 'Unauthorized Location',
|
||||
'location' => [0, 0]
|
||||
]
|
||||
]);
|
||||
|
||||
$this->assertEquals(401, $response['headers']['status-code']);
|
||||
|
||||
// Cleanup
|
||||
$this->client->call(Client::METHOD_DELETE, '/databases/' . $databaseId . '/collections/' . $collectionId, array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]));
|
||||
|
||||
$this->client->call(Client::METHOD_DELETE, '/databases/' . $databaseId, array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]));
|
||||
}
|
||||
|
||||
public function testSpatialLineAttributes(): void
|
||||
{
|
||||
$database = $this->client->call(Client::METHOD_POST, '/databases', [
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
], [
|
||||
'databaseId' => ID::unique(),
|
||||
'name' => 'Spatial Line Test Database'
|
||||
]);
|
||||
|
||||
$databaseId = $database['body']['$id'];
|
||||
|
||||
// Create collection with spatial and non-spatial attributes
|
||||
$collection = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]), [
|
||||
'collectionId' => ID::unique(),
|
||||
'name' => 'Spatial Line Collection',
|
||||
'documentSecurity' => true,
|
||||
'permissions' => [
|
||||
Permission::create(Role::user($this->getUser()['$id'])),
|
||||
Permission::read(Role::user($this->getUser()['$id'])),
|
||||
Permission::update(Role::user($this->getUser()['$id'])),
|
||||
Permission::delete(Role::user($this->getUser()['$id'])),
|
||||
],
|
||||
]);
|
||||
|
||||
$collectionId = $collection['body']['$id'];
|
||||
|
||||
// Create integer attribute
|
||||
$this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/integer', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]), [
|
||||
'key' => 'distance',
|
||||
'required' => true,
|
||||
]);
|
||||
|
||||
// Create line attribute
|
||||
$this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/line', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]), [
|
||||
'key' => 'route',
|
||||
'required' => true,
|
||||
]);
|
||||
|
||||
sleep(2);
|
||||
|
||||
// Test 1: Create document with line attribute
|
||||
$response = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'documentId' => ID::unique(),
|
||||
'data' => [
|
||||
'distance' => 100,
|
||||
'route' => [[40.7128, -74.0060], [40.7589, -73.9851]] // Line from Downtown to Times Square
|
||||
]
|
||||
]);
|
||||
|
||||
$this->assertEquals(201, $response['headers']['status-code']);
|
||||
$this->assertEquals([[40.7128, -74.0060], [40.7589, -73.9851]], $response['body']['route']);
|
||||
$documentId = $response['body']['$id'];
|
||||
|
||||
// Test 2: Read document with line attribute
|
||||
$response = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents/' . $documentId, array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()));
|
||||
|
||||
$this->assertEquals(200, $response['headers']['status-code']);
|
||||
$this->assertEquals([[40.7128, -74.0060], [40.7589, -73.9851]], $response['body']['route']);
|
||||
|
||||
// Test 3: Update document with new line coordinates
|
||||
$response = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents/' . $documentId, array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'data' => [
|
||||
'route' => [[40.7128, -74.0060], [40.7589, -73.9851], [40.7505, -73.9934]] // Extended route
|
||||
]
|
||||
]);
|
||||
|
||||
$this->assertEquals(200, $response['headers']['status-code']);
|
||||
$this->assertEquals([[40.7128, -74.0060], [40.7589, -73.9851], [40.7505, -73.9934]], $response['body']['route']);
|
||||
|
||||
// Test 4: Upsert document with line attribute
|
||||
$response = $this->client->call(Client::METHOD_PUT, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents/' . ID::unique(), array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'documentId' => ID::unique(),
|
||||
'data' => [
|
||||
'distance' => 200,
|
||||
'route' => [[34.0522, -118.2437], [34.0736, -118.2400]] // LA route
|
||||
]
|
||||
]);
|
||||
|
||||
$this->assertEquals(200, $response['headers']['status-code']);
|
||||
$this->assertEquals([[34.0522, -118.2437], [34.0736, -118.2400]], $response['body']['route']);
|
||||
|
||||
// Test 5: Delete document
|
||||
$response = $this->client->call(Client::METHOD_DELETE, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents/' . $documentId, array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()));
|
||||
|
||||
$this->assertEquals(204, $response['headers']['status-code']);
|
||||
|
||||
// Test 6: Verify document is deleted
|
||||
$response = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents/' . $documentId, array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()));
|
||||
|
||||
$this->assertEquals(404, $response['headers']['status-code']);
|
||||
|
||||
// Cleanup
|
||||
$this->client->call(Client::METHOD_DELETE, '/databases/' . $databaseId . '/collections/' . $collectionId, array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]));
|
||||
|
||||
$this->client->call(Client::METHOD_DELETE, '/databases/' . $databaseId, array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]));
|
||||
}
|
||||
|
||||
public function testSpatialPolygonAttributes(): void
|
||||
{
|
||||
$database = $this->client->call(Client::METHOD_POST, '/databases', [
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
], [
|
||||
'databaseId' => ID::unique(),
|
||||
'name' => 'Spatial Polygon Test Database'
|
||||
]);
|
||||
|
||||
$databaseId = $database['body']['$id'];
|
||||
|
||||
// Create collection with spatial and non-spatial attributes
|
||||
$collection = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]), [
|
||||
'collectionId' => ID::unique(),
|
||||
'name' => 'Spatial Polygon Collection',
|
||||
'documentSecurity' => true,
|
||||
'permissions' => [
|
||||
Permission::create(Role::user($this->getUser()['$id'])),
|
||||
Permission::read(Role::user($this->getUser()['$id'])),
|
||||
Permission::update(Role::user($this->getUser()['$id'])),
|
||||
Permission::delete(Role::user($this->getUser()['$id'])),
|
||||
],
|
||||
]);
|
||||
|
||||
$collectionId = $collection['body']['$id'];
|
||||
|
||||
// Create boolean attribute
|
||||
$this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/boolean', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]), [
|
||||
'key' => 'active',
|
||||
'required' => true,
|
||||
]);
|
||||
|
||||
// Create polygon attribute
|
||||
$this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/polygon', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]), [
|
||||
'key' => 'area',
|
||||
'required' => true,
|
||||
]);
|
||||
|
||||
sleep(2);
|
||||
|
||||
// Test 1: Create document with polygon attribute
|
||||
$response = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'documentId' => ID::unique(),
|
||||
'data' => [
|
||||
'active' => true,
|
||||
'area' => [[[40.7128, -74.0060], [40.7589, -74.0060], [40.7589, -73.9851], [40.7128, -73.9851], [40.7128, -74.0060]]] // Manhattan area
|
||||
]
|
||||
]);
|
||||
|
||||
$this->assertEquals(201, $response['headers']['status-code']);
|
||||
$this->assertEquals([[[40.7128, -74.0060], [40.7589, -74.0060], [40.7589, -73.9851], [40.7128, -73.9851], [40.7128, -74.0060]]], $response['body']['area']);
|
||||
$documentId = $response['body']['$id'];
|
||||
|
||||
// Test 2: Read document with polygon attribute
|
||||
$response = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents/' . $documentId, array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()));
|
||||
|
||||
$this->assertEquals(200, $response['headers']['status-code']);
|
||||
$this->assertEquals([[[40.7128, -74.0060], [40.7589, -74.0060], [40.7589, -73.9851], [40.7128, -73.9851], [40.7128, -74.0060]]], $response['body']['area']);
|
||||
|
||||
// Test 3: Update document with new polygon coordinates
|
||||
$response = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents/' . $documentId, array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'data' => [
|
||||
'area' => [[[40.7128, -74.0060], [40.7589, -74.0060], [40.7589, -73.9851], [40.7128, -73.9851], [40.7505, -73.9934], [40.7128, -74.0060]]] // Extended area
|
||||
]
|
||||
]);
|
||||
|
||||
$this->assertEquals(200, $response['headers']['status-code']);
|
||||
$this->assertEquals([[[40.7128, -74.0060], [40.7589, -74.0060], [40.7589, -73.9851], [40.7128, -73.9851], [40.7505, -73.9934], [40.7128, -74.0060]]], $response['body']['area']);
|
||||
|
||||
// Test 4: Upsert document with polygon attribute
|
||||
$response = $this->client->call(Client::METHOD_PUT, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents/' . ID::unique(), array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'documentId' => ID::unique(),
|
||||
'data' => [
|
||||
'active' => false,
|
||||
'area' => [[[34.0522, -118.2437], [34.0736, -118.2437], [34.0736, -118.2400], [34.0522, -118.2400], [34.0522, -118.2437]]] // LA area
|
||||
]
|
||||
]);
|
||||
|
||||
$this->assertEquals(200, $response['headers']['status-code']);
|
||||
$this->assertEquals([[[34.0522, -118.2437], [34.0736, -118.2437], [34.0736, -118.2400], [34.0522, -118.2400], [34.0522, -118.2437]]], $response['body']['area']);
|
||||
|
||||
// Test 5: Create document without required polygon attribute (should fail)
|
||||
$response = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'documentId' => ID::unique(),
|
||||
'data' => [
|
||||
'active' => true
|
||||
// Missing required 'area' attribute
|
||||
]
|
||||
]);
|
||||
|
||||
$this->assertEquals(400, $response['headers']['status-code']);
|
||||
|
||||
// Cleanup
|
||||
$this->client->call(Client::METHOD_DELETE, '/databases/' . $databaseId . '/collections/' . $collectionId, array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]));
|
||||
|
||||
$this->client->call(Client::METHOD_DELETE, '/databases/' . $databaseId, array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]));
|
||||
}
|
||||
|
||||
public function testSpatialAttributesMixedCollection(): void
|
||||
{
|
||||
$database = $this->client->call(Client::METHOD_POST, '/databases', [
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
], [
|
||||
'databaseId' => ID::unique(),
|
||||
'name' => 'Mixed Spatial Test Database'
|
||||
]);
|
||||
|
||||
$databaseId = $database['body']['$id'];
|
||||
|
||||
// Create collection with multiple spatial and non-spatial attributes
|
||||
$collection = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]), [
|
||||
'collectionId' => ID::unique(),
|
||||
'name' => 'Mixed Spatial Collection',
|
||||
'documentSecurity' => true,
|
||||
'permissions' => [
|
||||
Permission::create(Role::user($this->getUser()['$id'])),
|
||||
Permission::read(Role::user($this->getUser()['$id'])),
|
||||
Permission::update(Role::user($this->getUser()['$id'])),
|
||||
Permission::delete(Role::user($this->getUser()['$id'])),
|
||||
],
|
||||
]);
|
||||
|
||||
$collectionId = $collection['body']['$id'];
|
||||
|
||||
// Create multiple attributes
|
||||
$this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/string', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]), [
|
||||
'key' => 'name',
|
||||
'size' => 256,
|
||||
'required' => true,
|
||||
]);
|
||||
|
||||
$this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/point', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]), [
|
||||
'key' => 'center',
|
||||
'required' => true,
|
||||
]);
|
||||
|
||||
$this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/line', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]), [
|
||||
'key' => 'boundary',
|
||||
'required' => false,
|
||||
]);
|
||||
|
||||
$this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/polygon', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]), [
|
||||
'key' => 'coverage',
|
||||
'required' => true,
|
||||
]);
|
||||
|
||||
sleep(3);
|
||||
|
||||
// Test 1: Create document with all spatial attributes
|
||||
$response = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'documentId' => ID::unique(),
|
||||
'data' => [
|
||||
'name' => 'Central Park',
|
||||
'center' => [40.7829, -73.9654],
|
||||
'boundary' => [[40.7649, -73.9814], [40.8009, -73.9494]],
|
||||
'coverage' => [[[40.7649, -73.9814], [40.8009, -73.9814], [40.8009, -73.9494], [40.7649, -73.9494], [40.7649, -73.9814]]]
|
||||
]
|
||||
]);
|
||||
|
||||
$this->assertEquals(201, $response['headers']['status-code']);
|
||||
$this->assertEquals([40.7829, -73.9654], $response['body']['center']);
|
||||
$this->assertEquals([[40.7649, -73.9814], [40.8009, -73.9494]], $response['body']['boundary']);
|
||||
$this->assertEquals([[[40.7649, -73.9814], [40.8009, -73.9814], [40.8009, -73.9494], [40.7649, -73.9494], [40.7649, -73.9814]]], $response['body']['coverage']);
|
||||
$documentId = $response['body']['$id'];
|
||||
|
||||
// Test 2: Update document with new spatial data
|
||||
$response = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents/' . $documentId, array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'data' => [
|
||||
'center' => [40.7505, -73.9934],
|
||||
'boundary' => [[40.7305, -74.0134], [40.7705, -73.9734]],
|
||||
'coverage' => [[[40.7305, -74.0134], [40.7705, -74.0134], [40.7705, -73.9734], [40.7305, -73.9734], [40.7305, -74.0134]]]
|
||||
]
|
||||
]);
|
||||
|
||||
$this->assertEquals(200, $response['headers']['status-code']);
|
||||
$this->assertEquals([40.7505, -73.9934], $response['body']['center']);
|
||||
$this->assertEquals([[40.7305, -74.0134], [40.7705, -73.9734]], $response['body']['boundary']);
|
||||
$this->assertEquals([[[40.7305, -74.0134], [40.7705, -74.0134], [40.7705, -73.9734], [40.7305, -73.9734], [40.7305, -74.0134]]], $response['body']['coverage']);
|
||||
|
||||
// Test 3: Create document with minimal required attributes
|
||||
$response = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents', array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], $this->getHeaders()), [
|
||||
'documentId' => ID::unique(),
|
||||
'data' => [
|
||||
'name' => 'Minimal Location',
|
||||
'center' => [0, 0],
|
||||
'coverage' => [[[0, 0], [1, 0], [1, 1], [0, 1], [0, 0]]]
|
||||
]
|
||||
]);
|
||||
|
||||
$this->assertEquals(201, $response['headers']['status-code']);
|
||||
$this->assertEquals([0, 0], $response['body']['center']);
|
||||
|
||||
// Test 4: Test permission validation - create without user context
|
||||
$response = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents', [
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
], [
|
||||
'documentId' => ID::unique(),
|
||||
'data' => [
|
||||
'name' => 'Unauthorized Location',
|
||||
'center' => [0, 0],
|
||||
'coverage' => [[[0, 0], [1, 0], [1, 1], [0, 1], [0, 0]]]
|
||||
]
|
||||
]);
|
||||
|
||||
$this->assertEquals(401, $response['headers']['status-code']);
|
||||
|
||||
// Cleanup
|
||||
$this->client->call(Client::METHOD_DELETE, '/databases/' . $databaseId . '/collections/' . $collectionId, array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]));
|
||||
|
||||
$this->client->call(Client::METHOD_DELETE, '/databases/' . $databaseId, array_merge([
|
||||
'content-type' => 'application/json',
|
||||
'x-appwrite-project' => $this->getProject()['$id'],
|
||||
'x-appwrite-key' => $this->getProject()['apiKey']
|
||||
]));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user