From 3e0ee3042879ad67e996f2e2c686fd1a5d52c7ec Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Thu, 26 Feb 2026 18:31:52 +1300 Subject: [PATCH] Add tests for collection bust --- .../e2e/Services/Databases/DatabasesBase.php | 186 +++++++++++------- 1 file changed, 117 insertions(+), 69 deletions(-) diff --git a/tests/e2e/Services/Databases/DatabasesBase.php b/tests/e2e/Services/Databases/DatabasesBase.php index aa3c5024f6..34e759b51d 100644 --- a/tests/e2e/Services/Databases/DatabasesBase.php +++ b/tests/e2e/Services/Databases/DatabasesBase.php @@ -3267,13 +3267,13 @@ trait DatabasesBase ], $this->getHeaders())); } - #[Depends('testCreateDocument')] - public function testListDocumentsWithCache(array $data): void + public function testListDocumentsWithCache(): void { + $data = $this->setupDocuments(); $databaseId = $data['databaseId']; - // 1. Using cache with select queries , first request should miss cache. - $documents1 = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/documents', array_merge([ + // 1. Using cache with select queries, first request should miss cache. + $documents1 = $this->client->call(Client::METHOD_GET, $this->getRecordUrl($databaseId, $data['moviesId']), array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -3285,20 +3285,18 @@ trait DatabasesBase ]); $this->assertEquals(200, $documents1['headers']['status-code']); - $this->assertCount(3, $documents1['body']['documents']); - $this->assertEquals(1944, $documents1['body']['documents'][0]['releaseYear']); - $this->assertEquals(2017, $documents1['body']['documents'][1]['releaseYear']); - $this->assertEquals(2019, $documents1['body']['documents'][2]['releaseYear']); - $this->assertArrayHasKey('title', $documents1['body']['documents'][0]); - $this->assertArrayHasKey('releaseYear', $documents1['body']['documents'][0]); - $this->assertArrayHasKey('$id', $documents1['body']['documents'][0]); - $this->assertArrayHasKey('x-appwrite-cache-documents', $documents1['headers']); - $this->assertEquals('miss', $documents1['headers']['x-appwrite-cache-documents']); - $this->assertArrayHasKey('x-appwrite-cache-documents-total', $documents1['headers']); - $this->assertEquals('miss', $documents1['headers']['x-appwrite-cache-documents-total']); + $this->assertCount(3, $documents1['body'][$this->getRecordResource()]); + $this->assertEquals(1944, $documents1['body'][$this->getRecordResource()][0]['releaseYear']); + $this->assertEquals(2017, $documents1['body'][$this->getRecordResource()][1]['releaseYear']); + $this->assertEquals(2019, $documents1['body'][$this->getRecordResource()][2]['releaseYear']); + $this->assertArrayHasKey('title', $documents1['body'][$this->getRecordResource()][0]); + $this->assertArrayHasKey('releaseYear', $documents1['body'][$this->getRecordResource()][0]); + $this->assertArrayHasKey('$id', $documents1['body'][$this->getRecordResource()][0]); + $this->assertArrayHasKey('x-appwrite-cache', $documents1['headers']); + $this->assertEquals('miss', $documents1['headers']['x-appwrite-cache']); - // 2. Using cache with same select queries , should return cached results. - $documents2 = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/documents', array_merge([ + // 2. Using cache with same select queries, should return cached results. + $documents2 = $this->client->call(Client::METHOD_GET, $this->getRecordUrl($databaseId, $data['moviesId']), array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -3309,19 +3307,16 @@ trait DatabasesBase 'ttl' => 30, ]); - $this->assertEquals(200, $documents1['headers']['status-code']); - $this->assertCount(3, $documents1['body']['documents']); - $this->assertEquals($documents1['body']['documents'][0]['$id'], $documents2['body']['documents'][0]['$id']); - $this->assertEquals($documents1['body']['documents'][0]['title'], $documents2['body']['documents'][0]['title']); - $this->assertEquals($documents1['body']['documents'][0]['releaseYear'], $documents2['body']['documents'][0]['releaseYear']); - $this->assertArrayHasKey('x-appwrite-cache-documents', $documents2['headers']); - $this->assertEquals('hit', $documents2['headers']['x-appwrite-cache-documents']); - $this->assertArrayHasKey('x-appwrite-cache-documents-total', $documents2['headers']); - $this->assertEquals('hit', $documents2['headers']['x-appwrite-cache-documents-total']); + $this->assertEquals(200, $documents2['headers']['status-code']); + $this->assertCount(3, $documents2['body'][$this->getRecordResource()]); + $this->assertEquals($documents1['body'][$this->getRecordResource()][0]['$id'], $documents2['body'][$this->getRecordResource()][0]['$id']); + $this->assertEquals($documents1['body'][$this->getRecordResource()][0]['title'], $documents2['body'][$this->getRecordResource()][0]['title']); + $this->assertEquals($documents1['body'][$this->getRecordResource()][0]['releaseYear'], $documents2['body'][$this->getRecordResource()][0]['releaseYear']); + $this->assertArrayHasKey('x-appwrite-cache', $documents2['headers']); + $this->assertEquals('hit', $documents2['headers']['x-appwrite-cache']); - - // 3. Using cache with same select queries but total is false,Should return cached results just for documents. - $documents3 = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/documents', array_merge([ + // 3. Using cache with same select queries but total is false, should return cached results just for documents. + $documents3 = $this->client->call(Client::METHOD_GET, $this->getRecordUrl($databaseId, $data['moviesId']), array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -3334,20 +3329,16 @@ trait DatabasesBase ]); $this->assertEquals(200, $documents3['headers']['status-code']); - $this->assertCount(3, $documents3['body']['documents']); - $this->assertEquals($documents3['body']['documents'][0]['$id'], $documents1['body']['documents'][0]['$id']); - $this->assertEquals($documents3['body']['documents'][0]['title'], $documents1['body']['documents'][0]['title']); - $this->assertEquals($documents3['body']['documents'][0]['releaseYear'], $documents1['body']['documents'][0]['releaseYear']); + $this->assertCount(3, $documents3['body'][$this->getRecordResource()]); + $this->assertEquals($documents3['body'][$this->getRecordResource()][0]['$id'], $documents1['body'][$this->getRecordResource()][0]['$id']); + $this->assertEquals($documents3['body'][$this->getRecordResource()][0]['title'], $documents1['body'][$this->getRecordResource()][0]['title']); + $this->assertEquals($documents3['body'][$this->getRecordResource()][0]['releaseYear'], $documents1['body'][$this->getRecordResource()][0]['releaseYear']); $this->assertEquals(0, $documents3['body']['total']); - $this->assertCount(3, $documents3['body']['documents']); - $this->assertArrayHasKey('x-appwrite-cache-documents', $documents3['headers']); - $this->assertEquals('hit', $documents3['headers']['x-appwrite-cache-documents']); - $this->assertArrayHasKey('x-appwrite-cache-documents-total', $documents3['headers']); - $this->assertEquals('miss', $documents3['headers']['x-appwrite-cache-documents-total']); + $this->assertArrayHasKey('x-appwrite-cache', $documents3['headers']); + $this->assertEquals('hit', $documents3['headers']['x-appwrite-cache']); - - // 3. Using cache with diffrent select queries ,Should miss cache. - $documents4 = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/documents', array_merge([ + // 4. Using cache with different select queries, should miss cache. + $documents4 = $this->client->call(Client::METHOD_GET, $this->getRecordUrl($databaseId, $data['moviesId']), array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -3360,18 +3351,15 @@ trait DatabasesBase $this->assertEquals(200, $documents4['headers']['status-code']); $this->assertEquals(3, $documents4['body']['total']); - $this->assertCount(3, $documents4['body']['documents']); - $this->assertEquals($documents4['body']['documents'][0]['title'], $documents1['body']['documents'][0]['title']); - $this->assertEquals($documents4['body']['documents'][1]['title'], $documents1['body']['documents'][1]['title']); - $this->assertEquals($documents4['body']['documents'][2]['title'], $documents1['body']['documents'][2]['title']); - $this->assertArrayHasKey('x-appwrite-cache-documents', $documents3['headers']); - $this->assertEquals('miss', $documents4['headers']['x-appwrite-cache-documents']); - $this->assertArrayHasKey('x-appwrite-cache-documents-total', $documents3['headers']); - $this->assertEquals('miss', $documents4['headers']['x-appwrite-cache-documents-total']); + $this->assertCount(3, $documents4['body'][$this->getRecordResource()]); + $this->assertEquals($documents4['body'][$this->getRecordResource()][0]['title'], $documents1['body'][$this->getRecordResource()][0]['title']); + $this->assertEquals($documents4['body'][$this->getRecordResource()][1]['title'], $documents1['body'][$this->getRecordResource()][1]['title']); + $this->assertEquals($documents4['body'][$this->getRecordResource()][2]['title'], $documents1['body'][$this->getRecordResource()][2]['title']); + $this->assertArrayHasKey('x-appwrite-cache', $documents4['headers']); + $this->assertEquals('miss', $documents4['headers']['x-appwrite-cache']); - - // 4. Not using cache at all - $documents5 = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/documents', array_merge([ + // 5. Not using cache at all + $documents5 = $this->client->call(Client::METHOD_GET, $this->getRecordUrl($databaseId, $data['moviesId']), array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -3382,15 +3370,14 @@ trait DatabasesBase ]); $this->assertEquals(200, $documents5['headers']['status-code']); - $this->assertCount(3, $documents5['body']['documents']); - $this->assertEquals(1944, $documents5['body']['documents'][0]['releaseYear']); - $this->assertArrayNotHasKey('x-appwrite-cache-documents', $documents5['headers']); - $this->assertArrayNotHasKey('x-appwrite-cache-documents-total', $documents5['headers']); + $this->assertCount(3, $documents5['body'][$this->getRecordResource()]); + $this->assertEquals(1944, $documents5['body'][$this->getRecordResource()][0]['releaseYear']); + $this->assertArrayNotHasKey('x-appwrite-cache', $documents5['headers']); sleep(10); - // Using cache with same select queries but passed ttl time, should miss cache. - $documents6 = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/documents', array_merge([ + // 6. Using cache with same select queries but passed ttl time, should miss cache. + $documents6 = $this->client->call(Client::METHOD_GET, $this->getRecordUrl($databaseId, $data['moviesId']), array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -3402,17 +3389,78 @@ trait DatabasesBase ]); $this->assertEquals(200, $documents6['headers']['status-code']); - $this->assertCount(3, $documents6['body']['documents']); - $this->assertArrayHasKey('title', $documents6['body']['documents'][0]); - $this->assertArrayHasKey('releaseYear', $documents6['body']['documents'][0]); - $this->assertArrayHasKey('$id', $documents6['body']['documents'][0]); - $this->assertEquals($documents4['body']['documents'][0]['$id'], $documents1['body']['documents'][0]['$id']); - $this->assertEquals($documents4['body']['documents'][1]['$id'], $documents1['body']['documents'][1]['$id']); - $this->assertEquals($documents4['body']['documents'][2]['$id'], $documents1['body']['documents'][2]['$id']); - $this->assertArrayHasKey('x-appwrite-cache-documents', $documents6['headers']); - $this->assertEquals('miss', $documents6['headers']['x-appwrite-cache-documents']); - $this->assertArrayHasKey('x-appwrite-cache-documents-total', $documents6['headers']); - $this->assertEquals('miss', $documents6['headers']['x-appwrite-cache-documents-total']); + $this->assertCount(3, $documents6['body'][$this->getRecordResource()]); + $this->assertArrayHasKey('title', $documents6['body'][$this->getRecordResource()][0]); + $this->assertArrayHasKey('releaseYear', $documents6['body'][$this->getRecordResource()][0]); + $this->assertArrayHasKey('$id', $documents6['body'][$this->getRecordResource()][0]); + $this->assertArrayHasKey('x-appwrite-cache', $documents6['headers']); + $this->assertEquals('miss', $documents6['headers']['x-appwrite-cache']); + } + + public function testListDocumentsCacheBustedByAttributeChange(): void + { + $data = $this->setupDocuments(); + $databaseId = $data['databaseId']; + + $queries = [ + Query::select(['title', 'releaseYear', '$id'])->toString(), + Query::orderAsc('releaseYear')->toString(), + ]; + + // 1. First request should miss cache. + $documents1 = $this->client->call(Client::METHOD_GET, $this->getRecordUrl($databaseId, $data['moviesId']), array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'queries' => $queries, + 'ttl' => 300, + ]); + + $this->assertEquals(200, $documents1['headers']['status-code']); + $this->assertArrayHasKey('x-appwrite-cache', $documents1['headers']); + $this->assertEquals('miss', $documents1['headers']['x-appwrite-cache']); + + // 2. Same request should hit cache. + $documents2 = $this->client->call(Client::METHOD_GET, $this->getRecordUrl($databaseId, $data['moviesId']), array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'queries' => $queries, + 'ttl' => 300, + ]); + + $this->assertEquals(200, $documents2['headers']['status-code']); + $this->assertArrayHasKey('x-appwrite-cache', $documents2['headers']); + $this->assertEquals('hit', $documents2['headers']['x-appwrite-cache']); + + // 3. Add a new attribute to the collection, which updates the collection's $updatedAt. + $attribute = $this->client->call(Client::METHOD_POST, $this->getSchemaUrl($databaseId, $data['moviesId']) . '/string', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'cacheTestAttr', + 'size' => 64, + 'required' => false, + ]); + + $this->assertEquals(202, $attribute['headers']['status-code']); + + // Wait for the attribute to be ready + $this->waitForAttribute($databaseId, $data['moviesId'], 'cacheTestAttr'); + + // 4. Same request should now miss cache because collection $updatedAt changed. + $documents3 = $this->client->call(Client::METHOD_GET, $this->getRecordUrl($databaseId, $data['moviesId']), array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'queries' => $queries, + 'ttl' => 300, + ]); + + $this->assertEquals(200, $documents3['headers']['status-code']); + $this->assertArrayHasKey('x-appwrite-cache', $documents3['headers']); + $this->assertEquals('miss', $documents3['headers']['x-appwrite-cache']); } public function testGetDocument(): void