<?php 
 
/** 
 * JSONPath implementation for PHP. 
 * 
 * @license https://github.com/SoftCreatR/JSONPath/blob/main/LICENSE  MIT License 
 */ 
 
declare(strict_types=1); 
 
namespace Flow\JSONPath\Test; 
 
use Flow\JSONPath\{JSONPathException, JSONPathLexer, JSONPathToken}; 
use PHPUnit\Framework\TestCase; 
 
class JSONPathLexerTest extends TestCase 
{ 
    /** 
     * @throws JSONPathException 
     */ 
    public function testIndexWildcard(): void 
    { 
        $tokens = (new JSONPathLexer('.*')) 
            ->parseExpression(); 
 
        self::assertEquals(JSONPathToken::T_INDEX, $tokens[0]->type); 
        self::assertEquals("*", $tokens[0]->value); 
    } 
 
    /** 
     * @throws JSONPathException 
     */ 
    public function testIndexSimple(): void 
    { 
        $tokens = (new JSONPathLexer('.foo')) 
            ->parseExpression(); 
 
        self::assertEquals(JSONPathToken::T_INDEX, $tokens[0]->type); 
        self::assertEquals("foo", $tokens[0]->value); 
    } 
 
    /** 
     * @throws JSONPathException 
     */ 
    public function testIndexRecursive(): void 
    { 
        $tokens = (new JSONPathLexer('..teams.*')) 
            ->parseExpression(); 
 
        self::assertCount(3, $tokens); 
        self::assertEquals(JSONPathToken::T_RECURSIVE, $tokens[0]->type); 
        self::assertEquals(null, $tokens[0]->value); 
        self::assertEquals(JSONPathToken::T_INDEX, $tokens[1]->type); 
        self::assertEquals('teams', $tokens[1]->value); 
        self::assertEquals(JSONPathToken::T_INDEX, $tokens[2]->type); 
        self::assertEquals('*', $tokens[2]->value); 
    } 
 
    /** 
     * @throws JSONPathException 
     */ 
    public function testIndexComplex(): void 
    { 
        $tokens = (new JSONPathLexer('["\'b.^*_"]')) 
            ->parseExpression(); 
 
        self::assertEquals(JSONPathToken::T_INDEX, $tokens[0]->type); 
        self::assertEquals("'b.^*_", $tokens[0]->value); 
    } 
 
    /** 
     * @throws JSONPathException 
     */ 
    public function testIndexBadlyFormed(): void 
    { 
        $this->expectException(JSONPathException::class); 
        $this->expectExceptionMessage('Unable to parse token hello* in expression: .hello*'); 
 
        (new JSONPathLexer('.hello*')) 
            ->parseExpression(); 
    } 
 
    /** 
     * @throws JSONPathException 
     */ 
    public function testIndexInteger(): void 
    { 
        $tokens = (new JSONPathLexer('[0]')) 
            ->parseExpression(); 
 
        self::assertEquals(JSONPathToken::T_INDEX, $tokens[0]->type); 
        self::assertEquals("0", $tokens[0]->value); 
    } 
 
    /** 
     * @throws JSONPathException 
     */ 
    public function testIndexIntegerAfterDotNotation(): void 
    { 
        $tokens = (new JSONPathLexer('.books[0]')) 
            ->parseExpression(); 
 
        self::assertEquals(JSONPathToken::T_INDEX, $tokens[0]->type); 
        self::assertEquals(JSONPathToken::T_INDEX, $tokens[1]->type); 
        self::assertEquals("books", $tokens[0]->value); 
        self::assertEquals("0", $tokens[1]->value); 
    } 
 
    /** 
     * @throws JSONPathException 
     */ 
    public function testIndexWord(): void 
    { 
        $tokens = (new JSONPathLexer('["foo$-/\'"]')) 
            ->parseExpression(); 
 
        self::assertEquals(JSONPathToken::T_INDEX, $tokens[0]->type); 
        self::assertEquals("foo$-/'", $tokens[0]->value); 
    } 
 
    /** 
     * @throws JSONPathException 
     */ 
    public function testIndexWordWithWhitespace(): void 
    { 
        $tokens = (new JSONPathLexer('[   "foo$-/\'"     ]')) 
            ->parseExpression(); 
 
        self::assertEquals(JSONPathToken::T_INDEX, $tokens[0]->type); 
        self::assertEquals("foo$-/'", $tokens[0]->value); 
    } 
 
    /** 
     * @throws JSONPathException 
     */ 
    public function testSliceSimple(): void 
    { 
        $tokens = (new JSONPathLexer('[0:1:2]')) 
            ->parseExpression(); 
 
        self::assertEquals(JSONPathToken::T_SLICE, $tokens[0]->type); 
        self::assertEquals(['start' => 0, 'end' => 1, 'step' => 2], $tokens[0]->value); 
    } 
 
    /** 
     * @throws JSONPathException 
     */ 
    public function testIndexNegativeIndex(): void 
    { 
        $tokens = (new JSONPathLexer('[-1]')) 
            ->parseExpression(); 
 
        self::assertEquals(JSONPathToken::T_SLICE, $tokens[0]->type); 
        self::assertEquals(['start' => -1, 'end' => null, 'step' => null], $tokens[0]->value); 
    } 
 
    /** 
     * @throws JSONPathException 
     */ 
    public function testSliceAllNull(): void 
    { 
        $tokens = (new JSONPathLexer('[:]')) 
            ->parseExpression(); 
 
        self::assertEquals(JSONPathToken::T_SLICE, $tokens[0]->type); 
        self::assertEquals(['start' => null, 'end' => null, 'step' => null], $tokens[0]->value); 
    } 
 
    /** 
     * @throws JSONPathException 
     */ 
    public function testQueryResultSimple(): void 
    { 
        $tokens = (new JSONPathLexer('[(@.foo + 2)]')) 
            ->parseExpression(); 
 
        self::assertEquals(JSONPathToken::T_QUERY_RESULT, $tokens[0]->type); 
        self::assertEquals('@.foo + 2', $tokens[0]->value); 
    } 
 
    /** 
     * @throws JSONPathException 
     */ 
    public function testQueryMatchSimple(): void 
    { 
        $tokens = (new JSONPathLexer('[?(@.foo < \'bar\')]')) 
            ->parseExpression(); 
 
        self::assertEquals(JSONPathToken::T_QUERY_MATCH, $tokens[0]->type); 
        self::assertEquals('@.foo < \'bar\'', $tokens[0]->value); 
    } 
 
    /** 
     * @throws JSONPathException 
     */ 
    public function testQueryMatchNotEqualTO(): void 
    { 
        $tokens = (new JSONPathLexer('[?(@.foo != \'bar\')]')) 
            ->parseExpression(); 
 
        self::assertEquals(JSONPathToken::T_QUERY_MATCH, $tokens[0]->type); 
        self::assertEquals('@.foo != \'bar\'', $tokens[0]->value); 
    } 
 
    /** 
     * @throws JSONPathException 
     */ 
    public function testQueryMatchBrackets(): void 
    { 
        $tokens = (new JSONPathLexer("[?(@['@language']='en')]")) 
            ->parseExpression(); 
 
        self::assertEquals(JSONPathToken::T_QUERY_MATCH, $tokens[0]->type); 
        self::assertEquals("@['@language']='en'", $tokens[0]->value); 
    } 
 
    /** 
     * @throws JSONPathException 
     */ 
    public function testRecursiveSimple(): void 
    { 
        $tokens = (new JSONPathLexer('..foo')) 
            ->parseExpression(); 
 
        self::assertEquals(JSONPathToken::T_RECURSIVE, $tokens[0]->type); 
        self::assertEquals(JSONPathToken::T_INDEX, $tokens[1]->type); 
        self::assertEquals(null, $tokens[0]->value); 
        self::assertEquals('foo', $tokens[1]->value); 
    } 
 
    /** 
     * @throws JSONPathException 
     */ 
    public function testRecursiveWildcard(): void 
    { 
        $tokens = (new JSONPathLexer('..*')) 
            ->parseExpression(); 
 
        self::assertEquals(JSONPathToken::T_RECURSIVE, $tokens[0]->type); 
        self::assertEquals(JSONPathToken::T_INDEX, $tokens[1]->type); 
        self::assertEquals(null, $tokens[0]->value); 
        self::assertEquals('*', $tokens[1]->value); 
    } 
 
    /** 
     * @throws JSONPathException 
     */ 
    public function testRecursiveBadlyFormed(): void 
    { 
        $this->expectException(JSONPathException::class); 
        $this->expectExceptionMessage('Unable to parse token ba^r in expression: ..ba^r'); 
 
        (new JSONPathLexer('..ba^r')) 
            ->parseExpression(); 
    } 
 
    /** 
     * @throws JSONPathException 
     */ 
    public function testIndexesSimple(): void 
    { 
        $tokens = (new JSONPathLexer('[1,2,3]')) 
            ->parseExpression(); 
 
        self::assertEquals(JSONPathToken::T_INDEXES, $tokens[0]->type); 
        self::assertEquals([1, 2, 3], $tokens[0]->value); 
    } 
 
    /** 
     * @throws JSONPathException 
     */ 
    public function testIndexesWhitespace(): void 
    { 
        $tokens = (new JSONPathLexer('[ 1,2 , 3]')) 
            ->parseExpression(); 
 
        self::assertEquals(JSONPathToken::T_INDEXES, $tokens[0]->type); 
        self::assertEquals([1, 2, 3], $tokens[0]->value); 
    } 
} 
 
 |