mirror of
https://github.com/firefly-iii/firefly-iii.git
synced 2025-09-20 03:08:11 +00:00
Auto commit for release 'develop' on 2025-01-05
This commit is contained in:
@@ -15,128 +15,128 @@ abstract class AbstractQueryParserInterfaceParseQueryTest extends TestCase
|
||||
{
|
||||
abstract protected function createParser(): QueryParserInterface;
|
||||
|
||||
public static function queryDataProvider(): array
|
||||
public static function queryDataProvider(): iterable
|
||||
{
|
||||
return [
|
||||
'empty query' => [
|
||||
'query' => '',
|
||||
'expected' => new NodeGroup([])
|
||||
'empty query' => [
|
||||
'query' => '',
|
||||
'expected' => new NodeGroup([]),
|
||||
],
|
||||
'simple word' => [
|
||||
'query' => 'groceries',
|
||||
'expected' => new NodeGroup([new StringNode('groceries')])
|
||||
'simple word' => [
|
||||
'query' => 'groceries',
|
||||
'expected' => new NodeGroup([new StringNode('groceries')]),
|
||||
],
|
||||
'prohibited word' => [
|
||||
'query' => '-groceries',
|
||||
'expected' => new NodeGroup([new StringNode('groceries', true)])
|
||||
'prohibited word' => [
|
||||
'query' => '-groceries',
|
||||
'expected' => new NodeGroup([new StringNode('groceries', true)]),
|
||||
],
|
||||
'prohibited field' => [
|
||||
'query' => '-amount:100',
|
||||
'expected' => new NodeGroup([new FieldNode('amount', '100', true)])
|
||||
'prohibited field' => [
|
||||
'query' => '-amount:100',
|
||||
'expected' => new NodeGroup([new FieldNode('amount', '100', true)]),
|
||||
],
|
||||
'quoted word' => [
|
||||
'query' => '"test phrase"',
|
||||
'expected' => new NodeGroup([new StringNode('test phrase')])
|
||||
'quoted word' => [
|
||||
'query' => '"test phrase"',
|
||||
'expected' => new NodeGroup([new StringNode('test phrase')]),
|
||||
],
|
||||
'prohibited quoted word' => [
|
||||
'query' => '-"test phrase"',
|
||||
'expected' => new NodeGroup([new StringNode('test phrase', true)])
|
||||
'prohibited quoted word' => [
|
||||
'query' => '-"test phrase"',
|
||||
'expected' => new NodeGroup([new StringNode('test phrase', true)]),
|
||||
],
|
||||
'multiple words' => [
|
||||
'query' => 'groceries shopping market',
|
||||
'multiple words' => [
|
||||
'query' => 'groceries shopping market',
|
||||
'expected' => new NodeGroup([
|
||||
new StringNode('groceries'),
|
||||
new StringNode('shopping'),
|
||||
new StringNode('market')
|
||||
])
|
||||
new StringNode('market'),
|
||||
]),
|
||||
],
|
||||
'field operator' => [
|
||||
'query' => 'amount:100',
|
||||
'expected' => new NodeGroup([new FieldNode('amount', '100')])
|
||||
'field operator' => [
|
||||
'query' => 'amount:100',
|
||||
'expected' => new NodeGroup([new FieldNode('amount', '100')]),
|
||||
],
|
||||
'quoted field value with single space' => [
|
||||
'query' => 'description:"test phrase"',
|
||||
'expected' => new NodeGroup([new FieldNode('description', 'test phrase')])
|
||||
'quoted field value with single space' => [
|
||||
'query' => 'description:"test phrase"',
|
||||
'expected' => new NodeGroup([new FieldNode('description', 'test phrase')]),
|
||||
],
|
||||
'multiple fields' => [
|
||||
'query' => 'amount:100 category:food',
|
||||
'multiple fields' => [
|
||||
'query' => 'amount:100 category:food',
|
||||
'expected' => new NodeGroup([
|
||||
new FieldNode('amount', '100'),
|
||||
new FieldNode('category', 'food')
|
||||
])
|
||||
new FieldNode('category', 'food'),
|
||||
]),
|
||||
],
|
||||
'simple subquery' => [
|
||||
'query' => '(amount:100 category:food)',
|
||||
'simple subquery' => [
|
||||
'query' => '(amount:100 category:food)',
|
||||
'expected' => new NodeGroup([
|
||||
new NodeGroup([
|
||||
new FieldNode('amount', '100'),
|
||||
new FieldNode('category', 'food')
|
||||
])
|
||||
])
|
||||
new FieldNode('category', 'food'),
|
||||
]),
|
||||
]),
|
||||
],
|
||||
'prohibited subquery' => [
|
||||
'query' => '-(amount:100 category:food)',
|
||||
'prohibited subquery' => [
|
||||
'query' => '-(amount:100 category:food)',
|
||||
'expected' => new NodeGroup([
|
||||
new NodeGroup([
|
||||
new FieldNode('amount', '100'),
|
||||
new FieldNode('category', 'food')
|
||||
], true)
|
||||
])
|
||||
new FieldNode('category', 'food'),
|
||||
], true),
|
||||
]),
|
||||
],
|
||||
'nested subquery' => [
|
||||
'query' => '(amount:100 (description:"test" category:food))',
|
||||
'nested subquery' => [
|
||||
'query' => '(amount:100 (description:"test" category:food))',
|
||||
'expected' => new NodeGroup([
|
||||
new NodeGroup([
|
||||
new FieldNode('amount', '100'),
|
||||
new NodeGroup([
|
||||
new FieldNode('description', 'test'),
|
||||
new FieldNode('category', 'food')
|
||||
])
|
||||
])
|
||||
])
|
||||
new FieldNode('category', 'food'),
|
||||
]),
|
||||
]),
|
||||
]),
|
||||
],
|
||||
'mixed words and operators' => [
|
||||
'query' => 'groceries amount:50 shopping',
|
||||
'mixed words and operators' => [
|
||||
'query' => 'groceries amount:50 shopping',
|
||||
'expected' => new NodeGroup([
|
||||
new StringNode('groceries'),
|
||||
new FieldNode('amount', '50'),
|
||||
new StringNode('shopping')
|
||||
])
|
||||
new StringNode('shopping'),
|
||||
]),
|
||||
],
|
||||
'subquery after field value' => [
|
||||
'query' => 'amount:100 (description:"market" category:food)',
|
||||
'subquery after field value' => [
|
||||
'query' => 'amount:100 (description:"market" category:food)',
|
||||
'expected' => new NodeGroup([
|
||||
new FieldNode('amount', '100'),
|
||||
new NodeGroup([
|
||||
new FieldNode('description', 'market'),
|
||||
new FieldNode('category', 'food')
|
||||
])
|
||||
])
|
||||
new FieldNode('category', 'food'),
|
||||
]),
|
||||
]),
|
||||
],
|
||||
'word followed by subquery' => [
|
||||
'query' => 'groceries (amount:100 description_contains:"test")',
|
||||
'word followed by subquery' => [
|
||||
'query' => 'groceries (amount:100 description_contains:"test")',
|
||||
'expected' => new NodeGroup([
|
||||
new StringNode('groceries'),
|
||||
new NodeGroup([
|
||||
new FieldNode('amount', '100'),
|
||||
new FieldNode('description_contains', 'test')
|
||||
])
|
||||
])
|
||||
new FieldNode('description_contains', 'test'),
|
||||
]),
|
||||
]),
|
||||
],
|
||||
'nested subquery with prohibited field' => [
|
||||
'query' => '(amount:100 (description_contains:"test payment" -has_attachments:true))',
|
||||
'query' => '(amount:100 (description_contains:"test payment" -has_attachments:true))',
|
||||
'expected' => new NodeGroup([
|
||||
new NodeGroup([
|
||||
new FieldNode('amount', '100'),
|
||||
new NodeGroup([
|
||||
new FieldNode('description_contains', 'test payment'),
|
||||
new FieldNode('has_attachments', 'true', true)
|
||||
])
|
||||
])
|
||||
])
|
||||
new FieldNode('has_attachments', 'true', true),
|
||||
]),
|
||||
]),
|
||||
]),
|
||||
],
|
||||
'complex nested subqueries' => [
|
||||
'query' => 'shopping (amount:50 market (-category:food word description:"test phrase" (has_notes:true)))',
|
||||
'complex nested subqueries' => [
|
||||
'query' => 'shopping (amount:50 market (-category:food word description:"test phrase" (has_notes:true)))',
|
||||
'expected' => new NodeGroup([
|
||||
new StringNode('shopping'),
|
||||
new NodeGroup([
|
||||
@@ -147,51 +147,52 @@ abstract class AbstractQueryParserInterfaceParseQueryTest extends TestCase
|
||||
new StringNode('word'),
|
||||
new FieldNode('description', 'test phrase'),
|
||||
new NodeGroup([
|
||||
new FieldNode('has_notes', 'true')
|
||||
])
|
||||
])
|
||||
])
|
||||
])
|
||||
new FieldNode('has_notes', 'true'),
|
||||
]),
|
||||
]),
|
||||
]),
|
||||
]),
|
||||
],
|
||||
'word with multiple spaces' => [
|
||||
'query' => '"multiple spaces"',
|
||||
'expected' => new NodeGroup([new StringNode('multiple spaces')])
|
||||
'word with multiple spaces' => [
|
||||
'query' => '"multiple spaces"',
|
||||
'expected' => new NodeGroup([new StringNode('multiple spaces')]),
|
||||
],
|
||||
'field with multiple spaces in value' => [
|
||||
'query' => 'description:"multiple spaces here"',
|
||||
'expected' => new NodeGroup([new FieldNode('description', 'multiple spaces here')])
|
||||
'field with multiple spaces in value' => [
|
||||
'query' => 'description:"multiple spaces here"',
|
||||
'expected' => new NodeGroup([new FieldNode('description', 'multiple spaces here')]),
|
||||
],
|
||||
'unmatched right parenthesis in word' => [
|
||||
'query' => 'test)word',
|
||||
'expected' => new NodeGroup([new StringNode('test)word')])
|
||||
'unmatched right parenthesis in word' => [
|
||||
'query' => 'test)word',
|
||||
'expected' => new NodeGroup([new StringNode('test)word')]),
|
||||
],
|
||||
'unmatched right parenthesis in field' => [
|
||||
'query' => 'description:test)phrase',
|
||||
'expected' => new NodeGroup([new FieldNode('description', 'test)phrase')])
|
||||
'unmatched right parenthesis in field' => [
|
||||
'query' => 'description:test)phrase',
|
||||
'expected' => new NodeGroup([new FieldNode('description', 'test)phrase')]),
|
||||
],
|
||||
'subquery followed by word' => [
|
||||
'query' => '(amount:100 category:food) shopping',
|
||||
'subquery followed by word' => [
|
||||
'query' => '(amount:100 category:food) shopping',
|
||||
'expected' => new NodeGroup([
|
||||
new NodeGroup([
|
||||
new FieldNode('amount', '100'),
|
||||
new FieldNode('category', 'food')
|
||||
new FieldNode('category', 'food'),
|
||||
]),
|
||||
new StringNode('shopping')
|
||||
])
|
||||
]
|
||||
new StringNode('shopping'),
|
||||
]),
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider queryDataProvider
|
||||
* @param string $query The query string to parse
|
||||
* @param Node $expected The expected parse result
|
||||
*
|
||||
* @param string $query The query string to parse
|
||||
* @param Node $expected The expected parse result
|
||||
*/
|
||||
public function testQueryParsing(string $query, Node $expected): void
|
||||
{
|
||||
$actual = $this->createParser()->parse($query);
|
||||
|
||||
$this->assertEquals($expected, $actual);
|
||||
self::assertSame($expected, $actual);
|
||||
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user