Add comprehensive tests for Query::select with users endpoint

Co-authored-by: jakeb994 <jakeb994@gmail.com>
This commit is contained in:
Cursor Agent
2025-08-12 13:05:31 +00:00
co-authored by jakeb994
parent 3ad1bcbb25
commit c07ede1fc5
+348
View File
@@ -1861,4 +1861,352 @@ trait UsersBase
// TODO add test for session delete
// TODO add test for all sessions delete
/**
* @depends testCreateUser
*/
public function testListUsersWithSelect(array $data): void
{
/**
* Test Query::select with regular attributes
*/
$response = $this->client->call(Client::METHOD_GET, '/users', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()), [
'queries' => [
Query::select(['$id', 'name', 'email'])->toString()
]
]);
$this->assertEquals($response['headers']['status-code'], 200);
$this->assertNotEmpty($response['body']);
$this->assertNotEmpty($response['body']['users']);
// Verify only selected attributes are present
$user = $response['body']['users'][0];
$this->assertArrayHasKey('$id', $user);
$this->assertArrayHasKey('name', $user);
$this->assertArrayHasKey('email', $user);
// Verify other attributes are not present
$this->assertArrayNotHasKey('status', $user);
$this->assertArrayNotHasKey('registration', $user);
$this->assertArrayNotHasKey('passwordUpdate', $user);
$this->assertArrayNotHasKey('phone', $user);
/**
* Test Query::select with subQuery attributes (sessions, tokens)
*/
$response = $this->client->call(Client::METHOD_GET, '/users', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()), [
'queries' => [
Query::select(['$id', 'name', 'sessions', 'tokens'])->toString()
]
]);
$this->assertEquals($response['headers']['status-code'], 200);
$this->assertNotEmpty($response['body']);
$this->assertNotEmpty($response['body']['users']);
$user = $response['body']['users'][0];
$this->assertArrayHasKey('$id', $user);
$this->assertArrayHasKey('name', $user);
// SubQuery attributes should not be directly present in select but data should be available
// The implementation removes subQuery attributes from select and handles them via skipFilters
$this->assertArrayNotHasKey('sessions', $user);
$this->assertArrayNotHasKey('tokens', $user);
// Verify other attributes are not present
$this->assertArrayNotHasKey('email', $user);
$this->assertArrayNotHasKey('status', $user);
/**
* Test Query::select with mixed attributes (regular + subQuery)
*/
$response = $this->client->call(Client::METHOD_GET, '/users', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()), [
'queries' => [
Query::select(['name', 'email', 'memberships', 'targets'])->toString()
]
]);
$this->assertEquals($response['headers']['status-code'], 200);
$this->assertNotEmpty($response['body']);
$this->assertNotEmpty($response['body']['users']);
$user = $response['body']['users'][0];
$this->assertArrayHasKey('name', $user);
$this->assertArrayHasKey('email', $user);
// SubQuery attributes (memberships) should not be in select result
$this->assertArrayNotHasKey('memberships', $user);
// targets should be available since subQueryTargets is not skipped by default
$this->assertArrayHasKey('targets', $user);
/**
* Test Query::select with only subQuery attributes
*/
$response = $this->client->call(Client::METHOD_GET, '/users', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()), [
'queries' => [
Query::select(['sessions', 'challenges', 'authenticators'])->toString()
]
]);
$this->assertEquals($response['headers']['status-code'], 200);
$this->assertNotEmpty($response['body']);
$this->assertNotEmpty($response['body']['users']);
// When only subQuery attributes are selected, all attributes should be returned
// since no select query is passed to database
$user = $response['body']['users'][0];
$this->assertArrayHasKey('$id', $user);
$this->assertArrayHasKey('name', $user);
$this->assertArrayHasKey('email', $user);
/**
* Test Query::select with system attributes
*/
$response = $this->client->call(Client::METHOD_GET, '/users', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()), [
'queries' => [
Query::select(['$id', '$createdAt', '$updatedAt', 'name'])->toString()
]
]);
$this->assertEquals($response['headers']['status-code'], 200);
$this->assertNotEmpty($response['body']);
$this->assertNotEmpty($response['body']['users']);
$user = $response['body']['users'][0];
$this->assertArrayHasKey('$id', $user);
$this->assertArrayHasKey('$createdAt', $user);
$this->assertArrayHasKey('$updatedAt', $user);
$this->assertArrayHasKey('name', $user);
$this->assertArrayNotHasKey('email', $user);
/**
* Test Query::select with multiple select queries (should be consolidated)
*/
$response = $this->client->call(Client::METHOD_GET, '/users', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()), [
'queries' => [
Query::select(['$id', 'name'])->toString(),
Query::select(['email', 'status'])->toString()
]
]);
$this->assertEquals($response['headers']['status-code'], 200);
$this->assertNotEmpty($response['body']);
$this->assertNotEmpty($response['body']['users']);
$user = $response['body']['users'][0];
// All attributes from both select queries should be present
$this->assertArrayHasKey('$id', $user);
$this->assertArrayHasKey('name', $user);
$this->assertArrayHasKey('email', $user);
$this->assertArrayHasKey('status', $user);
$this->assertArrayNotHasKey('registration', $user);
/**
* Test Query::select with targets (should not be skipped by default)
*/
$response = $this->client->call(Client::METHOD_GET, '/users', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()), [
'queries' => [
Query::select(['$id', 'name', 'targets'])->toString()
]
]);
$this->assertEquals($response['headers']['status-code'], 200);
$this->assertNotEmpty($response['body']);
$this->assertNotEmpty($response['body']['users']);
$user = $response['body']['users'][0];
$this->assertArrayHasKey('$id', $user);
$this->assertArrayHasKey('name', $user);
$this->assertArrayHasKey('targets', $user); // targets should be available
/**
* Test invalid select attributes
*/
$response = $this->client->call(Client::METHOD_GET, '/users', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()), [
'queries' => [
Query::select(['nonExistentAttribute'])->toString()
]
]);
$this->assertEquals($response['headers']['status-code'], 400);
$this->assertStringContainsString('not found', $response['body']['message']);
/**
* Test Query::select with mixed valid and invalid attributes
*/
$response = $this->client->call(Client::METHOD_GET, '/users', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()), [
'queries' => [
Query::select(['$id', 'name', 'invalidAttribute'])->toString()
]
]);
$this->assertEquals($response['headers']['status-code'], 400);
$this->assertStringContainsString('not found', $response['body']['message']);
/**
* Test Query::select combined with other queries
*/
$response = $this->client->call(Client::METHOD_GET, '/users', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()), [
'queries' => [
Query::select(['$id', 'name', 'email'])->toString(),
Query::equal('status', [true])->toString(),
Query::limit(5)->toString()
]
]);
$this->assertEquals($response['headers']['status-code'], 200);
$this->assertNotEmpty($response['body']);
$this->assertNotEmpty($response['body']['users']);
$this->assertLessThanOrEqual(5, count($response['body']['users']));
$user = $response['body']['users'][0];
$this->assertArrayHasKey('$id', $user);
$this->assertArrayHasKey('name', $user);
$this->assertArrayHasKey('email', $user);
$this->assertArrayNotHasKey('status', $user);
$this->assertArrayNotHasKey('registration', $user);
}
/**
* @depends testCreateUser
*/
public function testListUsersSelectEdgeCases(array $data): void
{
/**
* Test empty select query - should return all attributes
*/
$response = $this->client->call(Client::METHOD_GET, '/users', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()), [
'queries' => [
Query::select([])->toString()
]
]);
$this->assertEquals($response['headers']['status-code'], 200);
$this->assertNotEmpty($response['body']);
$this->assertNotEmpty($response['body']['users']);
$user = $response['body']['users'][0];
$this->assertArrayHasKey('$id', $user);
$this->assertArrayHasKey('name', $user);
$this->assertArrayHasKey('email', $user);
$this->assertArrayHasKey('status', $user);
/**
* Test select with duplicate attributes - should deduplicate
*/
$response = $this->client->call(Client::METHOD_GET, '/users', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()), [
'queries' => [
Query::select(['$id', 'name', 'name', '$id', 'email'])->toString()
]
]);
$this->assertEquals($response['headers']['status-code'], 200);
$this->assertNotEmpty($response['body']);
$this->assertNotEmpty($response['body']['users']);
$user = $response['body']['users'][0];
$this->assertArrayHasKey('$id', $user);
$this->assertArrayHasKey('name', $user);
$this->assertArrayHasKey('email', $user);
$this->assertArrayNotHasKey('status', $user);
/**
* Test select with only targets (should be available since subQueryTargets not skipped by default)
*/
$response = $this->client->call(Client::METHOD_GET, '/users', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()), [
'queries' => [
Query::select(['targets'])->toString()
]
]);
$this->assertEquals($response['headers']['status-code'], 200);
$this->assertNotEmpty($response['body']);
$this->assertNotEmpty($response['body']['users']);
// Since targets is the only selected attribute and it's a subQuery attribute,
// but subQueryTargets is not skipped by default, all attributes should be returned
$user = $response['body']['users'][0];
$this->assertArrayHasKey('$id', $user);
$this->assertArrayHasKey('targets', $user);
/**
* Core functionality test: verify subQuery attributes handling
* This test specifically validates the PR requirements
*/
// Test that sessions/tokens are handled correctly (removed from select, added to skipFilters)
$response = $this->client->call(Client::METHOD_GET, '/users', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()), [
'queries' => [
Query::select(['$id', 'name', 'sessions'])->toString()
]
]);
$this->assertEquals($response['headers']['status-code'], 200);
$user = $response['body']['users'][0];
$this->assertArrayHasKey('$id', $user);
$this->assertArrayHasKey('name', $user);
// sessions should not be present as it's removed from select and handled via skipFilters
$this->assertArrayNotHasKey('sessions', $user);
$this->assertArrayNotHasKey('email', $user); // Not selected
// Test that targets are NOT removed (since subQueryTargets is not skipped by default)
$response = $this->client->call(Client::METHOD_GET, '/users', array_merge([
'content-type' => 'application/json',
'x-appwrite-project' => $this->getProject()['$id'],
], $this->getHeaders()), [
'queries' => [
Query::select(['$id', 'name', 'targets'])->toString()
]
]);
$this->assertEquals($response['headers']['status-code'], 200);
$user = $response['body']['users'][0];
$this->assertArrayHasKey('$id', $user);
$this->assertArrayHasKey('name', $user);
$this->assertArrayHasKey('targets', $user); // Should be present
}
}