JSONSelect JS parser tests

## Tests of the JSONSelect parser

Selectors

    $ JSONSelect._parse(".foo");
    [{id: "foo"}]
    $ JSONSelect._parse('." foo "');
    [{id: " foo "}]
    $ JSONSelect._parse("string.foo:last-child");
    [{a: 0, b: 1, id: "foo", pf: ":nth-last-child", type: "string"}]
    $ JSONSelect._parse("string.foo.bar");
    Error: multiple ids not allowed
    $ JSONSelect._parse("string.foo:first-child.bar");
    Error: multiple ids not allowed
    $ JSONSelect._parse("string:last-child.foo:first-child.bar");
    Error: multiple pseudo classes (:xxx) not allowed
    $ JSONSelect._parse("string.");
    Error: string required after '.'
    $ JSONSelect._parse("string:bogus");
    Error: unrecognized pseudo class
    $ JSONSelect._parse("string.xxx\\@yyy");
    [{id: "xxx@yyy", type: "string"}]
    $ JSONSelect._parse(" ");
    Error: selector expected
    $ JSONSelect._parse("");
    Error: selector expected

Combinators

    $ JSONSelect._parse(".foo .bar");
    [{id: "foo"}, {id: "bar"}]
    $ JSONSelect._parse("string.foo , number.foo");
    [",", [{id: "foo", type: "string"}], [{id: "foo", type: "number"}]]
    $ JSONSelect._parse("string > .foo number.bar");
    [{type: "string"}, ">", {id: "foo"}, {id: "bar", type: "number"}]
    $ JSONSelect._parse("string > .foo number.bar, object");
    [",", [{type: "string"}, ">", {id: "foo"}, {id: "bar", type: "number"}], [{type: "object"}]]
    $ JSONSelect._parse("string > .foo number.bar, object, string, .\"baz bing\", :root");
    [
      ",",
      [{type: "string"}, ">", {id: "foo"}, {id: "bar", type: "number"}],
      [{type: "object"}],
      [{type: "string"}],
      [{id: "baz bing"}],
      [{pc: ":root"}]
    ]

Expressions

    $ JSONSelect._parse(":nth-child(1)");
    [{a: 0, b: 1, pf: ":nth-child"}]
    $ JSONSelect._parse(":nth-child(2n+1)");
    [{a: 2, b: 1, pf: ":nth-child"}]
    $ JSONSelect._parse(":nth-child ( 2n + 1 )");
    [{a: 2, b: 1, pf: ":nth-child"}]
    $ JSONSelect._parse(":nth-child(odd)");
    [{a: 2, b: 1, pf: ":nth-child"}]
    $ JSONSelect._parse(":nth-child(even)");
    [{a: 2, b: 0, pf: ":nth-child"}]
    $ JSONSelect._parse(":nth-child(-n+6)");
    [{a: -1, b: 6, pf: ":nth-child"}]
    $ JSONSelect._parse(":nth-child(2n)");
    [{a: 2, b: 0, pf: ":nth-child"}]
    $ JSONSelect._parse(":nth-last-child(-3n - 3)");
    [{a: -3, b: -3, pf: ":nth-last-child"}]
    $ JSONSelect._parse(":first-child");
    [{a: 0, b: 1, pf: ":nth-child"}]
    $ JSONSelect._parse(":last-child");
    [{a: 0, b: 1, pf: ":nth-last-child"}]