tao-test/app/vendor/flow/jsonpath/tests/JSONPathTest.php

631 lines
20 KiB
PHP

<?php
namespace Flow\JSONPath\Test;
require_once __DIR__ . "/../vendor/autoload.php";
use Flow\JSONPath\JSONPath;
use PHPUnit\Framework\TestCase;
class JSONPathTest extends TestCase
{
/**
* $.store.books[0].title
*/
public function testChildOperators()
{
$result = (new JSONPath($this->exampleData(rand(0, 1))))->find('$.store.books[0].title');
$this->assertEquals('Sayings of the Century', $result[0]);
}
/**
* $['store']['books'][0]['title']
*/
public function testChildOperatorsAlt()
{
$result = (new JSONPath($this->exampleData(rand(0, 1))))->find("$['store']['books'][0]['title']");
$this->assertEquals('Sayings of the Century', $result[0]);
}
/**
* $.array[start:end:step]
*/
public function testFilterSliceA()
{
// Copy all items... similar to a wildcard
$result = (new JSONPath($this->exampleData(rand(0, 1))))->find("$['store']['books'][:].title");
$this->assertEquals(['Sayings of the Century', 'Sword of Honour', 'Moby Dick', 'The Lord of the Rings'], $result->data());
}
/**
* Positive end indexes
* $[0:2]
*/
public function testFilterSlice_PositiveEndIndexes()
{
$result = (new JSONPath(["first", "second", "third", "fourth", "fifth"]))->find("$[0:0]");
$this->assertEquals([], $result->data());
$result = (new JSONPath(["first", "second", "third", "fourth", "fifth"]))->find("$[0:1]");
$this->assertEquals(["first"], $result->data());
$result = (new JSONPath(["first", "second", "third", "fourth", "fifth"]))->find("$[0:2]");
$this->assertEquals(["first", "second"], $result->data());
$result = (new JSONPath(["first", "second", "third", "fourth", "fifth"]))->find("$[:2]");
$this->assertEquals(["first", "second"], $result->data());
$result = (new JSONPath(["first", "second", "third", "fourth", "fifth"]))->find("$[1:2]");
$this->assertEquals(["second"], $result->data());
$result = (new JSONPath(["first", "second", "third", "fourth", "fifth"]))->find("$[0:3:1]");
$this->assertEquals(["first", "second","third"], $result->data());
$result = (new JSONPath(["first", "second", "third", "fourth", "fifth"]))->find("$[0:3:0]");
$this->assertEquals(["first", "second","third"], $result->data());
}
public function testFilterSlice_NegativeStartIndexes()
{
$result = (new JSONPath(["first", "second", "third", "fourth", "fifth"]))->find("$[-2:]");
$this->assertEquals(["fourth", "fifth"], $result->data());
$result = (new JSONPath(["first", "second", "third", "fourth", "fifth"]))->find("$[-1:]");
$this->assertEquals(["fifth"], $result->data());
}
/**
* Negative end indexes
* $[:-2]
*/
public function testFilterSlice_NegativeEndIndexes()
{
$result = (new JSONPath(["first", "second", "third", "fourth", "fifth"]))->find("$[:-2]");
$this->assertEquals(["first", "second", "third"], $result->data());
$result = (new JSONPath(["first", "second", "third", "fourth", "fifth"]))->find("$[0:-2]");
$this->assertEquals(["first", "second", "third"], $result->data());
}
/**
* Negative end indexes
* $[:-2]
*/
public function testFilterSlice_NegativeStartAndEndIndexes()
{
$result = (new JSONPath(["first", "second", "third", "fourth", "fifth"]))->find("$[-2:-1]");
$this->assertEquals(["fourth"], $result->data());
$result = (new JSONPath(["first", "second", "third", "fourth", "fifth"]))->find("$[-4:-2]");
$this->assertEquals(["second", "third"], $result->data());
}
/**
* Negative end indexes
* $[:-2]
*/
public function testFilterSlice_NegativeStartAndPositiveEnd()
{
$result = (new JSONPath(["first", "second", "third", "fourth", "fifth"]))->find("$[-2:2]");
$this->assertEquals([], $result->data());
}
public function testFilterSlice_StepBy2()
{
$result = (new JSONPath(["first", "second", "third", "fourth", "fifth"]))->find("$[0:4:2]");
$this->assertEquals(["first", "third"], $result->data());
}
/**
* The Last item
* $[-1]
*/
public function testFilterLastIndex()
{
$result = (new JSONPath(["first", "second", "third", "fourth", "fifth"]))->find("$[-1]");
$this->assertEquals(["fifth"], $result->data());
}
/**
* Array index slice only end
* $[:2]
*/
public function testFilterSliceG()
{
// Fetch up to the second index
$result = (new JSONPath(["first", "second", "third", "fourth", "fifth"]))->find("$[:2]");
$this->assertEquals(["first", "second"], $result->data());
}
/**
* $.store.books[(@.length-1)].title
*
* This notation is only partially implemented eg. hacked in
*/
public function testChildQuery()
{
$result = (new JSONPath($this->exampleData(rand(0, 1))))->find("$.store.books[(@.length-1)].title");
$this->assertEquals(['The Lord of the Rings'], $result->data());
}
/**
* $.store.books[?(@.price < 10)].title
* Filter books that have a price less than 10
*/
public function testQueryMatchLessThan()
{
$result = (new JSONPath($this->exampleData(rand(0, 1))))->find("$.store.books[?(@.price < 10)].title");
$this->assertEquals(['Sayings of the Century', 'Moby Dick'], $result->data());
}
/**
* $..books[?(@.author == "J. R. R. Tolkien")]
* Filter books that have a title equal to "..."
*/
public function testQueryMatchEquals()
{
$results = (new JSONPath($this->exampleData(rand(0, 1))))->find('$..books[?(@.author == "J. R. R. Tolkien")].title');
$this->assertEquals($results[0], 'The Lord of the Rings');
}
/**
* $..books[?(@.author = 1)]
* Filter books that have a title equal to "..."
*/
public function testQueryMatchEqualsWithUnquotedInteger()
{
$results = (new JSONPath($this->exampleDataWithSimpleIntegers(rand(0, 1))))->find('$..features[?(@.value = 1)]');
$this->assertEquals($results[0]->name, "foo");
$this->assertEquals($results[1]->name, "baz");
}
/**
* $..books[?(@.author != "J. R. R. Tolkien")]
* Filter books that have a title not equal to "..."
*/
public function testQueryMatchNotEqualsTo()
{
$results = (new JSONPath($this->exampleData(rand(0, 1))))->find('$..books[?(@.author != "J. R. R. Tolkien")].title');
$this->assertcount(3, $results);
$this->assertEquals(['Sayings of the Century', 'Sword of Honour', 'Moby Dick'], [$results[0], $results[1], $results[2]]);
$results = (new JSONPath($this->exampleData(rand(0, 1))))->find('$..books[?(@.author !== "J. R. R. Tolkien")].title');
$this->assertcount(3, $results);
$this->assertEquals(['Sayings of the Century', 'Sword of Honour', 'Moby Dick'], [$results[0], $results[1], $results[2]]);
$results = (new JSONPath($this->exampleData(rand(0, 1))))->find('$..books[?(@.author <> "J. R. R. Tolkien")].title');
$this->assertcount(3, $results);
$this->assertEquals(['Sayings of the Century', 'Sword of Honour', 'Moby Dick'], [$results[0], $results[1], $results[2]]);
}
/**
* $.store.books[*].author
*/
public function testWildcardAltNotation()
{
$result = (new JSONPath($this->exampleData(rand(0, 1))))->find("$.store.books[*].author");
$this->assertEquals(['Nigel Rees', 'Evelyn Waugh', 'Herman Melville', 'J. R. R. Tolkien'], $result->data());
}
/**
* $..author
*/
public function testRecursiveChildSearch()
{
$result = (new JSONPath($this->exampleData(rand(0, 1))))->find("$..author");
$this->assertEquals(['Nigel Rees', 'Evelyn Waugh', 'Herman Melville', 'J. R. R. Tolkien'], $result->data());
}
/**
* $.store.*
* all things in store
* the structure of the example data makes this test look weird
*/
public function testWildCard()
{
$result = (new JSONPath($this->exampleData(rand(0, 1))))->find("$.store.*");
if (is_object($result[0][0])) {
$this->assertEquals('Sayings of the Century', $result[0][0]->title);
} else {
$this->assertEquals('Sayings of the Century', $result[0][0]['title']);
}
if (is_object($result[1])) {
$this->assertEquals('red', $result[1]->color);
} else {
$this->assertEquals('red', $result[1]['color']);
}
}
/**
* $.store..price
* the price of everything in the store.
*/
public function testRecursiveChildSearchAlt()
{
$result = (new JSONPath($this->exampleData(rand(0, 1))))->find("$.store..price");
$this->assertEquals([8.95, 12.99, 8.99, 22.99, 19.95], $result->data());
}
/**
* $..books[2]
* the third book
*/
public function testRecursiveChildSearchWithChildIndex()
{
$result = (new JSONPath($this->exampleData(rand(0, 1))))->find("$..books[2].title");
$this->assertEquals(["Moby Dick"], $result->data());
}
/**
* $..books[(@.length-1)]
*/
public function testRecursiveChildSearchWithChildQuery()
{
$result = (new JSONPath($this->exampleData(rand(0, 1))))->find("$..books[(@.length-1)].title");
$this->assertEquals(["The Lord of the Rings"], $result->data());
}
/**
* $..books[-1:]
* Resturn the last results
*/
public function testRecursiveChildSearchWithSliceFilter()
{
$result = (new JSONPath($this->exampleData(rand(0, 1))))->find("$..books[-1:].title");
$this->assertEquals(["The Lord of the Rings"], $result->data());
}
/**
* $..books[?(@.isbn)]
* filter all books with isbn number
*/
public function testRecursiveWithQueryMatch()
{
$result = (new JSONPath($this->exampleData(rand(0, 1))))->find("$..books[?(@.isbn)].isbn");
$this->assertEquals(['0-553-21311-3', '0-395-19395-8'], $result->data());
}
/**
* $..*
* All members of JSON structure
*/
public function testRecursiveWithWildcard()
{
$result = (new JSONPath($this->exampleData(rand(0, 1))))->find("$..*");
$result = json_decode(json_encode($result), true);
$this->assertEquals('Sayings of the Century', $result[0]['books'][0]['title']);
$this->assertEquals(19.95, $result[26]);
}
/**
* Tests direct key access.
*/
public function testSimpleArrayAccess()
{
$result = (new JSONPath(['title' => 'test title']))->find('title');
$this->assertEquals(['test title'], $result->data());
}
public function testFilteringOnNoneArrays()
{
$data = ['foo' => 'asdf'];
$result = (new JSONPath($data))->find("$.foo.bar");
$this->assertEquals([], $result->data());
}
public function testMagicMethods()
{
$fooClass = new JSONPathTestClass();
$results = (new JSONPath($fooClass, JSONPath::ALLOW_MAGIC))->find('$.foo');
$this->assertEquals(['bar'], $results->data());
}
public function testMatchWithComplexSquareBrackets()
{
$result = (new JSONPath($this->exampleDataExtra()))->find("$['http://www.w3.org/2000/01/rdf-schema#label'][?(@['@language']='en')]['@language']");
$this->assertEquals(["en"], $result->data());
}
public function testQueryMatchWithRecursive()
{
$locations = $this->exampleDataLocations();
$result = (new JSONPath($locations))->find("..[?(@.type == 'suburb')].name");
$this->assertEquals(["Rosebank"], $result->data());
}
public function testFirst()
{
$result = (new JSONPath($this->exampleDataExtra()))->find("$['http://www.w3.org/2000/01/rdf-schema#label'].*");
$this->assertEquals(["@language" => "en"], $result->first()->data());
}
public function testLast()
{
$result = (new JSONPath($this->exampleDataExtra()))->find("$['http://www.w3.org/2000/01/rdf-schema#label'].*");
$this->assertEquals(["@language" => "de"], $result->last()->data());
}
public function testSlashesInIndex()
{
$result = (new JSONPath($this->exampleDataWithSlashes()))->find("$['mediatypes']['image/png']");
$this->assertEquals(
[
"/core/img/filetypes/image.png",
],
$result->data()
);
}
public function testCyrillicText()
{
$result = (new JSONPath(["трололо" => 1]))->find("$['трололо']");
$this->assertEquals([1], $result->data());
$result = (new JSONPath(["трололо" => 1]))->find("$.трололо");
$this->assertEquals([1], $result->data());
}
public function testOffsetUnset()
{
$data = [
"route" => [
["name" => "A", "type" => "type of A"],
["name" => "B", "type" => "type of B"],
],
];
$data = json_encode($data);
$jsonIterator = new JSONPath(json_decode($data));
/** @var JSONPath $route */
$route = $jsonIterator->offsetGet('route');
$route->offsetUnset(0);
$first = $route->first();
$this->assertEquals("B", $first['name']);
}
public function testFirstKey()
{
// Array test for array
$jsonPath = new JSONPath(['a' => 'A', 'b', 'B']);
$firstKey = $jsonPath->firstKey();
$this->assertEquals('a', $firstKey);
// Array test for object
$jsonPath = new JSONPath((object)['a' => 'A', 'b', 'B']);
$firstKey = $jsonPath->firstKey();
$this->assertEquals('a', $firstKey);
}
public function testLastKey()
{
// Array test for array
$jsonPath = new JSONPath(['a' => 'A', 'b' => 'B', 'c' => 'C']);
$lastKey = $jsonPath->lastKey();
$this->assertEquals('c', $lastKey);
// Array test for object
$jsonPath = new JSONPath((object)['a' => 'A', 'b' => 'B', 'c' => 'C']);
$lastKey = $jsonPath->lastKey();
$this->assertEquals('c', $lastKey);
}
/**
* Test: ensure trailing comma is stripped during parsing
*/
public function testTrailingComma()
{
$jsonPath = new JSONPath(json_decode('{"store":{"book":[{"category":"reference","author":"Nigel Rees","title":"Sayings of the Century","price":8.95},{"category":"fiction","author":"Evelyn Waugh","title":"Sword of Honour","price":12.99},{"category":"fiction","author":"Herman Melville","title":"Moby Dick","isbn":"0-553-21311-3","price":8.99},{"category":"fiction","author":"J. R. R. Tolkien","title":"The Lord of the Rings","isbn":"0-395-19395-8","price":22.99}],"bicycle":{"color":"red","price":19.95}},"expensive":10}'));
$result = $jsonPath->find("$..book[0,1,2,]");
$this->assertCount(3, $result);
}
/**
* Test: ensure negative indexes return -n from last index
*/
public function testNegativeIndex()
{
$jsonPath = new JSONPath(json_decode('{"store":{"book":[{"category":"reference","author":"Nigel Rees","title":"Sayings of the Century","price":8.95},{"category":"fiction","author":"Evelyn Waugh","title":"Sword of Honour","price":12.99},{"category":"fiction","author":"Herman Melville","title":"Moby Dick","isbn":"0-553-21311-3","price":8.99},{"category":"fiction","author":"J. R. R. Tolkien","title":"The Lord of the Rings","isbn":"0-395-19395-8","price":22.99}],"bicycle":{"color":"red","price":19.95}},"expensive":10}'));
$result = $jsonPath->find("$..book[-2]");
$this->assertEquals("Herman Melville", $result[0]['author']);
}
public function testQueryAccessWithNumericalIndexes()
{
$jsonPath = new JSONPath(json_decode('{
"result": {
"list": [
{
"time": 1477526400,
"o": "11.51000"
},
{
"time": 1477612800,
"o": "11.49870"
}
]
}
}'));
$result = $jsonPath->find("$.result.list[?(@.o == \"11.51000\")]");
$this->assertEquals("11.51000", $result[0]->o);
$jsonPath = new JSONPath(json_decode('{
"result": {
"list": [
[
1477526400,
"11.51000"
],
[
1477612800,
"11.49870"
]
]
}
}'));
$result = $jsonPath->find("$.result.list[?(@[1] == \"11.51000\")]");
$this->assertEquals("11.51000", $result[0][1]);
}
public function exampleData($asArray = true)
{
$json = '
{
"store":{
"books":[
{
"category":"reference",
"author":"Nigel Rees",
"title":"Sayings of the Century",
"price":8.95
},
{
"category":"fiction",
"author":"Evelyn Waugh",
"title":"Sword of Honour",
"price":12.99
},
{
"category":"fiction",
"author":"Herman Melville",
"title":"Moby Dick",
"isbn":"0-553-21311-3",
"price":8.99
},
{
"category":"fiction",
"author":"J. R. R. Tolkien",
"title":"The Lord of the Rings",
"isbn":"0-395-19395-8",
"price":22.99
}
],
"bicycle":{
"color":"red",
"price":19.95
}
}
}';
return json_decode($json, $asArray);
}
public function exampleDataExtra($asArray = true)
{
$json = '
{
"http://www.w3.org/2000/01/rdf-schema#label":[
{
"@language":"en"
},
{
"@language":"de"
}
]
}
';
return json_decode($json, $asArray);
}
public function exampleDataLocations($asArray = true)
{
$json = '
{
"name": "Gauteng",
"type": "province",
"child": {
"name": "Johannesburg",
"type": "city",
"child": {
"name": "Rosebank",
"type": "suburb"
}
}
}
';
return json_decode($json, $asArray);
}
public function exampleDataWithSlashes($asArray = true)
{
$json = '
{
"features": [],
"mediatypes": {
"image/png": "/core/img/filetypes/image.png",
"image/jpeg": "/core/img/filetypes/image.png",
"image/gif": "/core/img/filetypes/image.png",
"application/postscript": "/core/img/filetypes/image-vector.png"
}
}
';
return json_decode($json, $asArray);
}
public function exampleDataWithSimpleIntegers($asArray = true)
{
$json = '
{
"features": [{"name": "foo", "value": 1},{"name": "bar", "value": 2},{"name": "baz", "value": 1}]
}
';
return json_decode($json, $asArray);
}
}
class JSONPathTestClass
{
protected $attributes = [
'foo' => 'bar',
];
public function __get($key)
{
return isset($this->attributes[$key]) ? $this->attributes[$key] : null;
}
}