mirror of
https://github.com/appwrite/appwrite
synced 2026-05-02 02:47:17 +00:00
RuntimeQuery::filter() now returns null when the query doesn't match, instead of an empty array. This distinguishes between "no match" and "match with empty payload", fixing the issue where subscriptions with empty payloads weren't being delivered. Updated Realtime::getSubscribers() to check for null instead of using !empty(), and updated all tests to expect null for non-matches. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
703 lines
22 KiB
PHP
703 lines
22 KiB
PHP
<?php
|
|
|
|
namespace Tests\Unit\Utopia\Database\Query;
|
|
|
|
use Appwrite\Utopia\Database\RuntimeQuery;
|
|
use PHPUnit\Framework\TestCase;
|
|
use Utopia\Database\Query;
|
|
|
|
class RuntimeQueryTest extends TestCase
|
|
{
|
|
public function setUp(): void
|
|
{
|
|
}
|
|
|
|
public function tearDown(): void
|
|
{
|
|
}
|
|
|
|
/**
|
|
* Helper to compile and filter queries in one step for tests.
|
|
*/
|
|
private function compileAndFilter(array $queries, array $payload): array
|
|
{
|
|
$compiled = RuntimeQuery::compile($queries);
|
|
return RuntimeQuery::filter($compiled, $payload);
|
|
}
|
|
|
|
public function testFilterEmptyQueries(): void
|
|
{
|
|
$payload = ['name' => 'John', 'age' => 30];
|
|
$result = $this->compileAndFilter([], $payload);
|
|
$this->assertEquals($payload, $result);
|
|
}
|
|
|
|
public function testFilterWithNoMatchingQuery(): void
|
|
{
|
|
$queries = [Query::equal('name', ['Jane'])];
|
|
$payload = ['name' => 'John', 'age' => 30];
|
|
$result = $this->compileAndFilter($queries, $payload);
|
|
$this->assertNull($result);
|
|
}
|
|
|
|
public function testFilterWithMatchingQuery(): void
|
|
{
|
|
$queries = [Query::equal('name', ['John'])];
|
|
$payload = ['name' => 'John', 'age' => 30];
|
|
$result = $this->compileAndFilter($queries, $payload);
|
|
$this->assertEquals($payload, $result);
|
|
}
|
|
|
|
// TYPE_EQUAL tests
|
|
public function testEqualMatch(): void
|
|
{
|
|
$query = Query::equal('name', ['John']);
|
|
$payload = ['name' => 'John'];
|
|
$result = $this->compileAndFilter([$query], $payload);
|
|
$this->assertEquals($payload, $result);
|
|
}
|
|
|
|
public function testEqualNoMatch(): void
|
|
{
|
|
$query = Query::equal('name', ['Jane']);
|
|
$payload = ['name' => 'John'];
|
|
$result = $this->compileAndFilter([$query], $payload);
|
|
$this->assertNull($result);
|
|
}
|
|
|
|
public function testEqualMultipleValuesMatch(): void
|
|
{
|
|
$query = Query::equal('status', ['active', 'pending', 'approved']);
|
|
$payload = ['status' => 'active'];
|
|
$result = $this->compileAndFilter([$query], $payload);
|
|
$this->assertEquals($payload, $result);
|
|
}
|
|
|
|
public function testEqualMultipleValuesNoMatch(): void
|
|
{
|
|
$query = Query::equal('status', ['active', 'pending', 'approved']);
|
|
$payload = ['status' => 'rejected'];
|
|
$result = $this->compileAndFilter([$query], $payload);
|
|
$this->assertNull($result);
|
|
}
|
|
|
|
public function testEqualNumericValues(): void
|
|
{
|
|
$query = Query::equal('age', [30, 25, 35]);
|
|
$payload = ['age' => 30];
|
|
$result = $this->compileAndFilter([$query], $payload);
|
|
$this->assertEquals($payload, $result);
|
|
}
|
|
|
|
public function testEqualBooleanValues(): void
|
|
{
|
|
$query = Query::equal('active', [true]);
|
|
$payload = ['active' => true];
|
|
$result = $this->compileAndFilter([$query], $payload);
|
|
$this->assertEquals($payload, $result);
|
|
}
|
|
|
|
public function testEqualMissingAttribute(): void
|
|
{
|
|
$query = Query::equal('missing', ['value']);
|
|
$payload = ['name' => 'John'];
|
|
$result = $this->compileAndFilter([$query], $payload);
|
|
$this->assertNull($result);
|
|
}
|
|
|
|
// TYPE_NOT_EQUAL tests
|
|
public function testNotEqualMatch(): void
|
|
{
|
|
$query = Query::notEqual('name', ['Jane']);
|
|
$payload = ['name' => 'John'];
|
|
$result = $this->compileAndFilter([$query], $payload);
|
|
$this->assertEquals($payload, $result);
|
|
}
|
|
|
|
public function testNotEqualNoMatch(): void
|
|
{
|
|
$query = Query::notEqual('name', ['John']);
|
|
$payload = ['name' => 'John'];
|
|
$result = $this->compileAndFilter([$query], $payload);
|
|
$this->assertNull($result);
|
|
}
|
|
|
|
public function testNotEqualMultipleValues(): void
|
|
{
|
|
// generally from the client side they will pass query strings via the realtime
|
|
// and Query::parse will be done first and parse doesn't allow multiple notEqual values
|
|
$query = Query::notEqual('status', ['rejected', 'cancelled']);
|
|
$payload = ['status' => 'active'];
|
|
$result = $this->compileAndFilter([$query], $payload);
|
|
$this->assertEquals($payload, $result);
|
|
|
|
$query = Query::notEqual('status', ['active', 'pending']);
|
|
$payload = ['status' => 'active'];
|
|
$result = $this->compileAndFilter([$query], $payload);
|
|
$this->assertNull($result);
|
|
}
|
|
|
|
// TYPE_LESSER tests
|
|
public function testLesserMatch(): void
|
|
{
|
|
$query = Query::lessThan('age', 30);
|
|
$payload = ['age' => 25];
|
|
$result = $this->compileAndFilter([$query], $payload);
|
|
$this->assertEquals($payload, $result);
|
|
}
|
|
|
|
public function testLesserNoMatch(): void
|
|
{
|
|
$query = Query::lessThan('age', 30);
|
|
$payload = ['age' => 35];
|
|
$result = $this->compileAndFilter([$query], $payload);
|
|
$this->assertNull($result);
|
|
}
|
|
|
|
public function testLesserEqualValue(): void
|
|
{
|
|
$query = Query::lessThan('age', 30);
|
|
$payload = ['age' => 30];
|
|
$result = $this->compileAndFilter([$query], $payload);
|
|
$this->assertNull($result);
|
|
}
|
|
|
|
public function testLesserMultipleValues(): void
|
|
{
|
|
// Note: Query::lessThan only accepts single value, but RuntimeQuery's anyMatch supports arrays
|
|
// This test uses a single value as Query class requires
|
|
$query = Query::lessThan('age', 30);
|
|
$payload = ['age' => 25];
|
|
$result = $this->compileAndFilter([$query], $payload);
|
|
$this->assertEquals($payload, $result);
|
|
}
|
|
|
|
public function testLesserStringComparison(): void
|
|
{
|
|
$query = Query::lessThan('name', 'M');
|
|
$payload = ['name' => 'A'];
|
|
$result = $this->compileAndFilter([$query], $payload);
|
|
$this->assertEquals($payload, $result);
|
|
}
|
|
|
|
// TYPE_LESSER_EQUAL tests
|
|
public function testLesserEqualMatch(): void
|
|
{
|
|
$query = Query::lessThanEqual('age', 30);
|
|
$payload = ['age' => 25];
|
|
$result = $this->compileAndFilter([$query], $payload);
|
|
$this->assertEquals($payload, $result);
|
|
}
|
|
|
|
public function testLesserEqualExactMatch(): void
|
|
{
|
|
$query = Query::lessThanEqual('age', 30);
|
|
$payload = ['age' => 30];
|
|
$result = $this->compileAndFilter([$query], $payload);
|
|
$this->assertEquals($payload, $result);
|
|
}
|
|
|
|
public function testLesserEqualNoMatch(): void
|
|
{
|
|
$query = Query::lessThanEqual('age', 30);
|
|
$payload = ['age' => 35];
|
|
$result = $this->compileAndFilter([$query], $payload);
|
|
$this->assertNull($result);
|
|
}
|
|
|
|
public function testLesserEqualMultipleValues(): void
|
|
{
|
|
// Note: Query::lessThanEqual only accepts single value
|
|
$query = Query::lessThanEqual('age', 30);
|
|
$payload = ['age' => 30];
|
|
$result = $this->compileAndFilter([$query], $payload);
|
|
$this->assertEquals($payload, $result);
|
|
}
|
|
|
|
// TYPE_GREATER tests
|
|
public function testGreaterMatch(): void
|
|
{
|
|
$query = Query::greaterThan('age', 30);
|
|
$payload = ['age' => 35];
|
|
$result = $this->compileAndFilter([$query], $payload);
|
|
$this->assertEquals($payload, $result);
|
|
}
|
|
|
|
public function testGreaterNoMatch(): void
|
|
{
|
|
$query = Query::greaterThan('age', 30);
|
|
$payload = ['age' => 25];
|
|
$result = $this->compileAndFilter([$query], $payload);
|
|
$this->assertNull($result);
|
|
}
|
|
|
|
public function testGreaterEqualValue(): void
|
|
{
|
|
$query = Query::greaterThan('age', 30);
|
|
$payload = ['age' => 30];
|
|
$result = $this->compileAndFilter([$query], $payload);
|
|
$this->assertNull($result);
|
|
}
|
|
|
|
public function testGreaterMultipleValues(): void
|
|
{
|
|
// Note: Query::greaterThan only accepts single value
|
|
$query = Query::greaterThan('age', 20);
|
|
$payload = ['age' => 35];
|
|
$result = $this->compileAndFilter([$query], $payload);
|
|
$this->assertEquals($payload, $result);
|
|
}
|
|
|
|
// TYPE_GREATER_EQUAL tests
|
|
public function testGreaterEqualMatch(): void
|
|
{
|
|
$query = Query::greaterThanEqual('age', 30);
|
|
$payload = ['age' => 35];
|
|
$result = $this->compileAndFilter([$query], $payload);
|
|
$this->assertEquals($payload, $result);
|
|
}
|
|
|
|
public function testGreaterEqualExactMatch(): void
|
|
{
|
|
$query = Query::greaterThanEqual('age', 30);
|
|
$payload = ['age' => 30];
|
|
$result = $this->compileAndFilter([$query], $payload);
|
|
$this->assertEquals($payload, $result);
|
|
}
|
|
|
|
public function testGreaterEqualNoMatch(): void
|
|
{
|
|
$query = Query::greaterThanEqual('age', 30);
|
|
$payload = ['age' => 25];
|
|
$result = $this->compileAndFilter([$query], $payload);
|
|
$this->assertNull($result);
|
|
}
|
|
|
|
public function testGreaterEqualMultipleValues(): void
|
|
{
|
|
// Note: Query::greaterThanEqual only accepts single value
|
|
$query = Query::greaterThanEqual('age', 20);
|
|
$payload = ['age' => 30];
|
|
$result = $this->compileAndFilter([$query], $payload);
|
|
$this->assertEquals($payload, $result);
|
|
}
|
|
|
|
// TYPE_IS_NULL tests
|
|
public function testIsNullMatch(): void
|
|
{
|
|
$query = Query::isNull('description');
|
|
$payload = ['description' => null];
|
|
$result = $this->compileAndFilter([$query], $payload);
|
|
$this->assertEquals($payload, $result);
|
|
}
|
|
|
|
public function testIsNullNoMatch(): void
|
|
{
|
|
$query = Query::isNull('description');
|
|
$payload = ['description' => 'Some text'];
|
|
$result = $this->compileAndFilter([$query], $payload);
|
|
$this->assertNull($result);
|
|
}
|
|
|
|
public function testIsNullMissingAttribute(): void
|
|
{
|
|
$query = Query::isNull('missing');
|
|
$payload = ['name' => 'John'];
|
|
$result = $this->compileAndFilter([$query], $payload);
|
|
$this->assertNull($result);
|
|
}
|
|
|
|
// TYPE_IS_NOT_NULL tests
|
|
public function testIsNotNullMatch(): void
|
|
{
|
|
$query = Query::isNotNull('description');
|
|
$payload = ['description' => 'Some text'];
|
|
$result = $this->compileAndFilter([$query], $payload);
|
|
$this->assertEquals($payload, $result);
|
|
}
|
|
|
|
public function testIsNotNullNoMatch(): void
|
|
{
|
|
$query = Query::isNotNull('description');
|
|
$payload = ['description' => null];
|
|
$result = $this->compileAndFilter([$query], $payload);
|
|
$this->assertNull($result);
|
|
}
|
|
|
|
public function testIsNotNullMissingAttribute(): void
|
|
{
|
|
$query = Query::isNotNull('missing');
|
|
$payload = ['name' => 'John'];
|
|
$result = $this->compileAndFilter([$query], $payload);
|
|
$this->assertNull($result);
|
|
}
|
|
|
|
// TYPE_AND tests
|
|
public function testAndAllMatch(): void
|
|
{
|
|
$query = Query::and([
|
|
Query::equal('name', ['John']),
|
|
Query::equal('age', [30])
|
|
]);
|
|
$payload = ['name' => 'John', 'age' => 30];
|
|
$result = $this->compileAndFilter([$query], $payload);
|
|
$this->assertEquals($payload, $result);
|
|
}
|
|
|
|
public function testAndOneFails(): void
|
|
{
|
|
$query = Query::and([
|
|
Query::equal('name', ['John']),
|
|
Query::equal('age', [25])
|
|
]);
|
|
$payload = ['name' => 'John', 'age' => 30];
|
|
$result = $this->compileAndFilter([$query], $payload);
|
|
$this->assertNull($result);
|
|
}
|
|
|
|
public function testAndAllFail(): void
|
|
{
|
|
$query = Query::and([
|
|
Query::equal('name', ['Jane']),
|
|
Query::equal('age', [25])
|
|
]);
|
|
$payload = ['name' => 'John', 'age' => 30];
|
|
$result = $this->compileAndFilter([$query], $payload);
|
|
$this->assertNull($result);
|
|
}
|
|
|
|
public function testAndMultipleConditions(): void
|
|
{
|
|
$query = Query::and([
|
|
Query::equal('status', ['active']),
|
|
Query::greaterThan('age', 18),
|
|
Query::isNotNull('email')
|
|
]);
|
|
$payload = ['status' => 'active', 'age' => 25, 'email' => 'test@example.com'];
|
|
$result = $this->compileAndFilter([$query], $payload);
|
|
$this->assertEquals($payload, $result);
|
|
}
|
|
|
|
public function testAndNestedAnd(): void
|
|
{
|
|
$query = Query::and([
|
|
Query::equal('name', ['John']),
|
|
Query::and([
|
|
Query::equal('age', [30]),
|
|
Query::equal('status', ['active'])
|
|
])
|
|
]);
|
|
$payload = ['name' => 'John', 'age' => 30, 'status' => 'active'];
|
|
$result = $this->compileAndFilter([$query], $payload);
|
|
$this->assertEquals($payload, $result);
|
|
}
|
|
|
|
// TYPE_OR tests
|
|
public function testOrOneMatch(): void
|
|
{
|
|
$query = Query::or([
|
|
Query::equal('name', ['John']),
|
|
Query::equal('name', ['Jane'])
|
|
]);
|
|
$payload = ['name' => 'John'];
|
|
$result = $this->compileAndFilter([$query], $payload);
|
|
$this->assertEquals($payload, $result);
|
|
}
|
|
|
|
public function testOrAllMatch(): void
|
|
{
|
|
$query = Query::or([
|
|
Query::equal('status', ['active']),
|
|
Query::equal('status', ['pending'])
|
|
]);
|
|
$payload = ['status' => 'active'];
|
|
$result = $this->compileAndFilter([$query], $payload);
|
|
$this->assertEquals($payload, $result);
|
|
}
|
|
|
|
public function testOrAllFail(): void
|
|
{
|
|
$query = Query::or([
|
|
Query::equal('name', ['Jane']),
|
|
Query::equal('age', [25])
|
|
]);
|
|
$payload = ['name' => 'John', 'age' => 30];
|
|
$result = $this->compileAndFilter([$query], $payload);
|
|
$this->assertNull($result);
|
|
}
|
|
|
|
public function testOrMultipleConditions(): void
|
|
{
|
|
$query = Query::or([
|
|
Query::equal('status', ['active']),
|
|
Query::equal('status', ['pending']),
|
|
Query::equal('status', ['approved'])
|
|
]);
|
|
$payload = ['status' => 'pending'];
|
|
$result = $this->compileAndFilter([$query], $payload);
|
|
$this->assertEquals($payload, $result);
|
|
}
|
|
|
|
public function testOrNestedOr(): void
|
|
{
|
|
$query = Query::or([
|
|
Query::equal('name', ['John']),
|
|
Query::or([
|
|
Query::equal('name', ['Jane']),
|
|
Query::equal('name', ['Bob'])
|
|
])
|
|
]);
|
|
$payload = ['name' => 'Bob'];
|
|
$result = $this->compileAndFilter([$query], $payload);
|
|
$this->assertEquals($payload, $result);
|
|
}
|
|
|
|
public function testOrWithDifferentAttributes(): void
|
|
{
|
|
$query = Query::or([
|
|
Query::equal('name', ['John']),
|
|
Query::equal('email', ['john@example.com'])
|
|
]);
|
|
$payload = ['name' => 'Jane', 'email' => 'john@example.com'];
|
|
$result = $this->compileAndFilter([$query], $payload);
|
|
$this->assertEquals($payload, $result);
|
|
}
|
|
|
|
// Complex combinations
|
|
public function testAndOrCombination(): void
|
|
{
|
|
$query = Query::and([
|
|
Query::equal('type', ['user']),
|
|
Query::or([
|
|
Query::equal('status', ['active']),
|
|
Query::equal('status', ['pending'])
|
|
])
|
|
]);
|
|
$payload = ['type' => 'user', 'status' => 'active'];
|
|
$result = $this->compileAndFilter([$query], $payload);
|
|
$this->assertEquals($payload, $result);
|
|
}
|
|
|
|
public function testOrAndCombination(): void
|
|
{
|
|
$query = Query::or([
|
|
Query::and([
|
|
Query::equal('name', ['John']),
|
|
Query::equal('age', [30])
|
|
]),
|
|
Query::and([
|
|
Query::equal('name', ['Jane']),
|
|
Query::equal('age', [25])
|
|
])
|
|
]);
|
|
$payload = ['name' => 'John', 'age' => 30];
|
|
$result = $this->compileAndFilter([$query], $payload);
|
|
$this->assertEquals($payload, $result);
|
|
}
|
|
|
|
// Edge cases
|
|
public function testMultipleQueriesAllMatch(): void
|
|
{
|
|
$queries = [
|
|
Query::equal('name', ['John']),
|
|
Query::equal('age', [30])
|
|
];
|
|
$payload = ['name' => 'John', 'age' => 30];
|
|
$result = $this->compileAndFilter($queries, $payload);
|
|
$this->assertEquals($payload, $result);
|
|
}
|
|
|
|
public function testMultipleQueriesFirstMatches(): void
|
|
{
|
|
$queries = [
|
|
Query::equal('name', ['John']),
|
|
Query::equal('age', [25])
|
|
];
|
|
$payload = ['name' => 'John', 'age' => 30];
|
|
$result = $this->compileAndFilter($queries, $payload);
|
|
// With AND logic, if first matches but second doesn't, should return empty
|
|
$this->assertNull($result);
|
|
}
|
|
|
|
public function testMultipleQueriesSecondMatches(): void
|
|
{
|
|
$queries = [
|
|
Query::equal('name', ['Jane']),
|
|
Query::equal('age', [30])
|
|
];
|
|
$payload = ['name' => 'John', 'age' => 30];
|
|
$result = $this->compileAndFilter($queries, $payload);
|
|
// With AND logic, if second matches but first doesn't, should return empty
|
|
$this->assertNull($result);
|
|
}
|
|
|
|
public function testMultipleQueriesNoneMatch(): void
|
|
{
|
|
$queries = [
|
|
Query::equal('name', ['Jane']),
|
|
Query::equal('age', [25])
|
|
];
|
|
$payload = ['name' => 'John', 'age' => 30];
|
|
$result = $this->compileAndFilter($queries, $payload);
|
|
$this->assertNull($result);
|
|
}
|
|
|
|
public function testEmptyPayload(): void
|
|
{
|
|
$query = Query::equal('name', ['John']);
|
|
$payload = [];
|
|
$result = $this->compileAndFilter([$query], $payload);
|
|
$this->assertNull($result);
|
|
}
|
|
|
|
public function testEmptyAndQuery(): void
|
|
{
|
|
$query = Query::and([]);
|
|
$payload = ['name' => 'John'];
|
|
$result = $this->compileAndFilter([$query], $payload);
|
|
// Empty AND should return true (all conditions pass vacuously)
|
|
$this->assertEquals($payload, $result);
|
|
}
|
|
|
|
public function testEmptyOrQuery(): void
|
|
{
|
|
$query = Query::or([]);
|
|
$payload = ['name' => 'John'];
|
|
$result = $this->compileAndFilter([$query], $payload);
|
|
// Empty OR should return false (no conditions match)
|
|
$this->assertNull($result);
|
|
}
|
|
|
|
// Type-specific edge cases
|
|
public function testEqualWithZero(): void
|
|
{
|
|
$query = Query::equal('count', [0]);
|
|
$payload = ['count' => 0];
|
|
$result = $this->compileAndFilter([$query], $payload);
|
|
$this->assertEquals($payload, $result);
|
|
}
|
|
|
|
public function testEqualWithEmptyString(): void
|
|
{
|
|
$query = Query::equal('name', ['']);
|
|
$payload = ['name' => ''];
|
|
$result = $this->compileAndFilter([$query], $payload);
|
|
$this->assertEquals($payload, $result);
|
|
}
|
|
|
|
public function testEqualWithFalse(): void
|
|
{
|
|
$query = Query::equal('active', [false]);
|
|
$payload = ['active' => false];
|
|
$result = $this->compileAndFilter([$query], $payload);
|
|
$this->assertEquals($payload, $result);
|
|
}
|
|
|
|
public function testComparisonWithFloat(): void
|
|
{
|
|
$query = Query::greaterThan('score', 8.5);
|
|
$payload = ['score' => 9.2];
|
|
$result = $this->compileAndFilter([$query], $payload);
|
|
$this->assertEquals($payload, $result);
|
|
}
|
|
|
|
public function testComparisonWithStringNumbers(): void
|
|
{
|
|
$query = Query::lessThan('version', '10');
|
|
$payload = ['version' => '9'];
|
|
$result = $this->compileAndFilter([$query], $payload);
|
|
$this->assertEquals($payload, $result);
|
|
}
|
|
|
|
// TYPE_SELECT tests - select("*") means "listen to all events"
|
|
public function testSelectAllIsAllowed(): void
|
|
{
|
|
$query = Query::select(['*']);
|
|
$this->assertTrue(RuntimeQuery::isSelectAll($query));
|
|
}
|
|
|
|
public function testSelectSpecificFieldsNotAllowed(): void
|
|
{
|
|
$query = Query::select(['name', 'age']);
|
|
$this->assertFalse(RuntimeQuery::isSelectAll($query));
|
|
}
|
|
|
|
public function testSelectSingleFieldNotAllowed(): void
|
|
{
|
|
$query = Query::select(['name']);
|
|
$this->assertFalse(RuntimeQuery::isSelectAll($query));
|
|
}
|
|
|
|
public function testValidateSelectQueryWithWildcard(): void
|
|
{
|
|
$query = Query::select(['*']);
|
|
// Should not throw
|
|
RuntimeQuery::validateSelectQuery($query);
|
|
$this->assertTrue(true);
|
|
}
|
|
|
|
public function testValidateSelectQueryWithSpecificFields(): void
|
|
{
|
|
$query = Query::select(['name', 'age']);
|
|
$this->expectException(\InvalidArgumentException::class);
|
|
$this->expectExceptionMessage('Only select("*") is allowed in Realtime queries');
|
|
RuntimeQuery::validateSelectQuery($query);
|
|
}
|
|
|
|
public function testValidateSelectQueryWithSingleField(): void
|
|
{
|
|
$query = Query::select(['name']);
|
|
$this->expectException(\InvalidArgumentException::class);
|
|
$this->expectExceptionMessage('Only select("*") is allowed in Realtime queries');
|
|
RuntimeQuery::validateSelectQuery($query);
|
|
}
|
|
|
|
public function testSelectInAllowedQueries(): void
|
|
{
|
|
$this->assertContains(Query::TYPE_SELECT, RuntimeQuery::ALLOWED_QUERIES);
|
|
}
|
|
|
|
public function testIsSelectAllWithNonSelectQuery(): void
|
|
{
|
|
$query = Query::equal('name', ['John']);
|
|
$this->assertFalse(RuntimeQuery::isSelectAll($query));
|
|
}
|
|
|
|
public function testValidateSelectQueryWithNonSelectQuery(): void
|
|
{
|
|
$query = Query::equal('name', ['John']);
|
|
// Should not throw for non-select queries
|
|
RuntimeQuery::validateSelectQuery($query);
|
|
$this->assertTrue(true);
|
|
}
|
|
|
|
// Filter tests with select("*")
|
|
public function testFilterWithSelectAllReturnsPayload(): void
|
|
{
|
|
$query = Query::select(['*']);
|
|
$payload = ['name' => 'John', 'age' => 30];
|
|
$result = $this->compileAndFilter([$query], $payload);
|
|
$this->assertEquals($payload, $result);
|
|
}
|
|
|
|
public function testFilterWithSelectAllAndOtherQueriesReturnsPayload(): void
|
|
{
|
|
// If select("*") is present, it should return payload regardless of other queries
|
|
$queries = [
|
|
Query::select(['*']),
|
|
Query::equal('name', ['Jane']), // This would normally fail
|
|
];
|
|
$payload = ['name' => 'John', 'age' => 30];
|
|
$result = $this->compileAndFilter($queries, $payload);
|
|
// select("*") takes precedence - returns payload
|
|
$this->assertEquals($payload, $result);
|
|
}
|
|
|
|
public function testFilterWithSelectAllOnEmptyPayload(): void
|
|
{
|
|
$query = Query::select(['*']);
|
|
$payload = [];
|
|
$result = $this->compileAndFilter([$query], $payload);
|
|
$this->assertEquals($payload, $result);
|
|
}
|
|
}
|