jsonpath-faster
Version:
Query JavaScript objects with JSONPath expressions. Compiles and caches JSONpath to JS
453 lines (452 loc) • 10 kB
JavaScript
// automatically translated from node_modules/jsonpath/test/parse.js
const tap = require("tap");
var assert = require("assert");
var jp = require("../../").strict;
var util = require("util");
tap.test("parse", async function () {
tap.test("should parse root-only", async function () {
var path = jp.parse("$");
tap.same(path, [
{
expression: {
type: "root",
value: "$",
},
},
]);
});
tap.test("parse path for store", async function () {
var path = jp.parse("$.store");
tap.same(path, [
{
expression: {
type: "root",
value: "$",
},
},
{
operation: "member",
scope: "child",
expression: {
type: "identifier",
value: "store",
},
},
]);
});
tap.test(
"parse path for the authors of all books in the store",
async function () {
var path = jp.parse("$.store.book[*].author");
tap.same(path, [
{
expression: {
type: "root",
value: "$",
},
},
{
operation: "member",
scope: "child",
expression: {
type: "identifier",
value: "store",
},
},
{
operation: "member",
scope: "child",
expression: {
type: "identifier",
value: "book",
},
},
{
operation: "subscript",
scope: "child",
expression: {
type: "wildcard",
value: "*",
},
},
{
operation: "member",
scope: "child",
expression: {
type: "identifier",
value: "author",
},
},
]);
}
);
tap.test("parse path for all authors", async function () {
var path = jp.parse("$..author");
tap.same(path, [
{
expression: {
type: "root",
value: "$",
},
},
{
operation: "member",
scope: "descendant",
expression: {
type: "identifier",
value: "author",
},
},
]);
});
tap.test(
"parse path for all authors via subscript descendant string literal",
async function () {
var path = jp.parse("$..['author']");
tap.same(path, [
{
expression: {
type: "root",
value: "$",
},
},
{
operation: "subscript",
scope: "descendant",
expression: {
type: "string_literal",
value: "author",
},
},
]);
}
);
tap.test("parse path for all things in store", async function () {
var path = jp.parse("$.store.*");
tap.same(path, [
{
expression: {
type: "root",
value: "$",
},
},
{
operation: "member",
scope: "child",
expression: {
type: "identifier",
value: "store",
},
},
{
operation: "member",
scope: "child",
expression: {
type: "wildcard",
value: "*",
},
},
]);
});
tap.test(
"parse path for price of everything in the store",
async function () {
var path = jp.parse("$.store..price");
tap.same(path, [
{
expression: {
type: "root",
value: "$",
},
},
{
operation: "member",
scope: "child",
expression: {
type: "identifier",
value: "store",
},
},
{
operation: "member",
scope: "descendant",
expression: {
type: "identifier",
value: "price",
},
},
]);
}
);
tap.test(
"parse path for the last book in order via expression",
async function () {
var path = jp.parse("$..book[(@.length-1)]");
tap.same(path, [
{
expression: {
type: "root",
value: "$",
},
},
{
operation: "member",
scope: "descendant",
expression: {
type: "identifier",
value: "book",
},
},
{
operation: "subscript",
scope: "child",
expression: {
type: "script_expression",
value: "(@.length-1)",
},
},
]);
}
);
tap.test("parse path for the first two books via union", async function () {
var path = jp.parse("$..book[0,1]");
tap.same(path, [
{
expression: {
type: "root",
value: "$",
},
},
{
operation: "member",
scope: "descendant",
expression: {
type: "identifier",
value: "book",
},
},
{
operation: "subscript",
scope: "child",
expression: {
type: "union",
value: [
{
expression: {
type: "numeric_literal",
value: "0",
},
},
{
expression: {
type: "numeric_literal",
value: "1",
},
},
],
},
},
]);
});
tap.test("parse path for the first two books via slice", async function () {
var path = jp.parse("$..book[0:2]");
tap.same(path, [
{
expression: {
type: "root",
value: "$",
},
},
{
operation: "member",
scope: "descendant",
expression: {
type: "identifier",
value: "book",
},
},
{
operation: "subscript",
scope: "child",
expression: {
type: "slice",
value: "0:2",
},
},
]);
});
tap.test(
"parse path to filter all books with isbn number",
async function () {
var path = jp.parse("$..book[?(@.isbn)]");
tap.same(path, [
{
expression: {
type: "root",
value: "$",
},
},
{
operation: "member",
scope: "descendant",
expression: {
type: "identifier",
value: "book",
},
},
{
operation: "subscript",
scope: "child",
expression: {
type: "filter_expression",
value: "?(@.isbn)",
},
},
]);
}
);
tap.test(
"parse path to filter all books with a price less than 10",
async function () {
var path = jp.parse("$..book[?(@.price<10)]");
tap.same(path, [
{
expression: {
type: "root",
value: "$",
},
},
{
operation: "member",
scope: "descendant",
expression: {
type: "identifier",
value: "book",
},
},
{
operation: "subscript",
scope: "child",
expression: {
type: "filter_expression",
value: "?(@.price<10)",
},
},
]);
}
);
tap.test("parse path to match all elements", async function () {
var path = jp.parse("$..*");
tap.same(path, [
{
expression: {
type: "root",
value: "$",
},
},
{
operation: "member",
scope: "descendant",
expression: {
type: "wildcard",
value: "*",
},
},
]);
});
tap.test("parse path with leading member", async function () {
var path = jp.parse("store");
tap.same(path, [
{
operation: "member",
scope: "child",
expression: {
type: "identifier",
value: "store",
},
},
]);
});
tap.test("parse path with leading member and followers", async function () {
var path = jp.parse("Request.prototype.end");
tap.same(path, [
{
operation: "member",
scope: "child",
expression: {
type: "identifier",
value: "Request",
},
},
{
operation: "member",
scope: "child",
expression: {
type: "identifier",
value: "prototype",
},
},
{
operation: "member",
scope: "child",
expression: {
type: "identifier",
value: "end",
},
},
]);
});
tap.test(
"parser ast is reinitialized after parse() throws",
async function () {
tap.throws(function () {
var path = jp.parse("store.book...");
});
var path = jp.parse("$..price");
tap.same(path, [
{
expression: {
type: "root",
value: "$",
},
},
{
expression: {
type: "identifier",
value: "price",
},
operation: "member",
scope: "descendant",
},
]);
}
);
});
tap.test("parse-negative", async function () {
tap.test(
"parse path with leading member component throws",
async function () {
tap.throws(function (e) {
var path = jp.parse(".store");
}, /Expecting 'DOLLAR'/);
}
);
tap.test(
"parse path with leading descendant member throws",
async function () {
tap.throws(function () {
var path = jp.parse("..store");
}, /Expecting 'DOLLAR'/);
}
);
tap.test("leading script throws", async function () {
tap.throws(function () {
var path = jp.parse("()");
}, /Unrecognized text/);
});
tap.test("first time friendly error", async function () {
tap.throws(function () {
new jp.JSONPath().parse("$...");
}, /Expecting 'STAR'/);
});
});