packages/ztd-query-core/tests/Unit/Sql/SqlKeywordSequenceTest.php

1<?php
2
3declare(strict_types=1);
4
5namespace Tests\Unit\Sql;
6
7use PHPUnit\Framework\Attributes\CoversClass;
8use PHPUnit\Framework\Attributes\UsesClass;
9use PHPUnit\Framework\TestCase;
10use Tests\Fake\FakeSqlLexerProfiles;
11use ZtdQuery\Sql\Profile\SqlCommentProfile;
12use ZtdQuery\Sql\Profile\SqlParameterProfile;
13use ZtdQuery\Sql\Profile\SqlQuoteProfile;
14use ZtdQuery\Sql\Profile\SqlSymbolProfile;
15use ZtdQuery\Sql\Reader\SqlBlockCommentReader;
16use ZtdQuery\Sql\Reader\SqlDelimitedReader;
17use ZtdQuery\Sql\Reader\SqlLexeme;
18use ZtdQuery\Sql\Reader\SqlParameterReader;
19use ZtdQuery\Sql\Reader\SqlTriviaReader;
20use ZtdQuery\Sql\Reader\SqlWordReader;
21use ZtdQuery\Sql\SqlKeywordSequence;
22use ZtdQuery\Sql\SqlLexerProfile;
23use ZtdQuery\Sql\SqlToken;
24use ZtdQuery\Sql\SqlTokenScanner;
25use ZtdQuery\Sql\SqlTokenStream;
26
27#[CoversClass(SqlKeywordSequence::class)]
28#[UsesClass(SqlToken::class)]
29#[UsesClass(SqlTokenStream::class)]
30#[UsesClass(SqlTokenScanner::class)]
31#[UsesClass(SqlLexerProfile::class)]
32#[UsesClass(\ZtdQuery\Sql\LexicalDelimiters::class)]
33#[UsesClass(\ZtdQuery\Sql\LexicalPattern::class)]
34#[UsesClass(SqlCommentProfile::class)]
35#[UsesClass(SqlParameterProfile::class)]
36#[UsesClass(SqlQuoteProfile::class)]
37#[UsesClass(SqlSymbolProfile::class)]
38#[UsesClass(SqlBlockCommentReader::class)]
39#[UsesClass(SqlDelimitedReader::class)]
40#[UsesClass(SqlLexeme::class)]
41#[UsesClass(SqlParameterReader::class)]
42#[UsesClass(SqlTriviaReader::class)]
43#[UsesClass(SqlWordReader::class)]
44final class SqlKeywordSequenceTest extends TestCase
45{
46    public function testPositionInAnswersWhereTheRunOfKeywordsBegins(): void
47    {
48        $tokens = SqlTokenStream::tokenize(
49            'SELECT a FROM t ORDER BY a',
50            FakeSqlLexerProfiles::standard(),
51        )->significantTokens();
52
53        self::assertSame(4, (new SqlKeywordSequence())->positionIn($tokens, ['ORDER', 'BY'], 0));
54    }
55
56    public function testPositionInIgnoresTheSameWordsWrittenInsideParentheses(): void
57    {
58        $tokens = SqlTokenStream::tokenize(
59            'SELECT (SELECT a FROM t ORDER BY a) FROM u',
60            FakeSqlLexerProfiles::standard(),
61        )->significantTokens();
62
63        self::assertNull((new SqlKeywordSequence())->positionIn($tokens, ['ORDER', 'BY'], 0));
64    }
65
66    public function testPositionInIsNothingWhereTheRunIsNotWrittenAtAll(): void
67    {
68        $tokens = SqlTokenStream::tokenize('SELECT a FROM t', FakeSqlLexerProfiles::standard())
69            ->significantTokens();
70
71        self::assertNull((new SqlKeywordSequence())->positionIn($tokens, ['GROUP', 'BY'], 0));
72    }
73
74    public function testPositionInLooksNoEarlierThanItWasToldTo(): void
75    {
76        $tokens = SqlTokenStream::tokenize(
77            'SELECT a FROM t WHERE a = 1',
78            FakeSqlLexerProfiles::standard(),
79        )->significantTokens();
80
81        self::assertNull((new SqlKeywordSequence())->positionIn($tokens, ['SELECT'], 1));
82    }
83
84    public function testPositionInIsNothingWhereOnlyPartOfTheRunIsWritten(): void
85    {
86        $tokens = SqlTokenStream::tokenize('SELECT a FROM t ORDER', FakeSqlLexerProfiles::standard())
87            ->significantTokens();
88
89        self::assertNull((new SqlKeywordSequence())->positionIn($tokens, ['ORDER', 'BY'], 0));
90    }
91}
92