UNPKG

6.82 kBJavaScriptView Raw
1var assert = require('assert');
2var jp = require('../');
3var util = require('util');
4
5suite('parse', function() {
6
7 test('should parse root-only', function() {
8 var path = jp.parse('$');
9 assert.deepEqual(path, [ { expression: { type: 'root', value: '$' } } ]);
10 });
11
12 test('parse path for store', function() {
13 var path = jp.parse('$.store');
14 assert.deepEqual(path, [
15 { expression: { type: 'root', value: '$' } },
16 { operation: 'member', scope: 'child', expression: { type: 'identifier', value: 'store' } }
17 ])
18 });
19
20 test('parse path for the authors of all books in the store', function() {
21 var path = jp.parse('$.store.book[*].author');
22 assert.deepEqual(path, [
23 { expression: { type: 'root', value: '$' } },
24 { operation: 'member', scope: 'child', expression: { type: 'identifier', value: 'store' } },
25 { operation: 'member', scope: 'child', expression: { type: 'identifier', value: 'book' } },
26 { operation: 'subscript', scope: 'child', expression: { type: 'wildcard', value: '*' } },
27 { operation: 'member', scope: 'child', expression: { type: 'identifier', value: 'author' } }
28 ])
29 });
30
31 test('parse path for all authors', function() {
32 var path = jp.parse('$..author');
33 assert.deepEqual(path, [
34 { expression: { type: 'root', value: '$' } },
35 { operation: 'member', scope: 'descendant', expression: { type: 'identifier', value: 'author' } }
36 ])
37 });
38
39 test('parse path for all authors via subscript descendant string literal', function() {
40 var path = jp.parse("$..['author']");
41 assert.deepEqual(path, [
42 { expression: { type: 'root', value: '$' } },
43 { operation: 'subscript', scope: 'descendant', expression: { type: 'string_literal', value: 'author' } }
44 ])
45 });
46
47 test('parse path for all things in store', function() {
48 var path = jp.parse('$.store.*');
49 assert.deepEqual(path, [
50 { expression: { type: 'root', value: '$' } },
51 { operation: 'member', scope: 'child', expression: { type: 'identifier', value: 'store' } },
52 { operation: 'member', scope: 'child', expression: { type: 'wildcard', value: '*' } }
53 ])
54 });
55
56 test('parse path for price of everything in the store', function() {
57 var path = jp.parse('$.store..price');
58 assert.deepEqual(path, [
59 { expression: { type: 'root', value: '$' } },
60 { operation: 'member', scope: 'child', expression: { type: 'identifier', value: 'store' } },
61 { operation: 'member', scope: 'descendant', expression: { type: 'identifier', value: 'price' } }
62 ])
63 });
64
65 test('parse path for the last book in order via expression', function() {
66 var path = jp.parse('$..book[(@.length-1)]');
67 assert.deepEqual(path, [
68 { expression: { type: 'root', value: '$' } },
69 { operation: 'member', scope: 'descendant', expression: { type: 'identifier', value: 'book' } },
70 { operation: 'subscript', scope: 'child', expression: { type: 'script_expression', value: '(@.length-1)' } }
71 ])
72 });
73
74 test('parse path for the first two books via union', function() {
75 var path = jp.parse('$..book[0,1]');
76
77 assert.deepEqual(path, [
78 { expression: { type: 'root', value: '$' } },
79 { operation: 'member', scope: 'descendant', expression: { type: 'identifier', value: 'book' } },
80 { operation: 'subscript', scope: 'child', expression: { type: 'union', value: [ { expression: { type: 'numeric_literal', value: '0' } }, { expression: { type: 'numeric_literal', value: '1' } } ] } }
81 ])
82 });
83
84 test('parse path for the first two books via slice', function() {
85 var path = jp.parse('$..book[0:2]');
86 assert.deepEqual(path, [
87 { expression: { type: 'root', value: '$' } },
88 { operation: 'member', scope: 'descendant', expression: { type: 'identifier', value: 'book' } },
89 { operation: 'subscript', scope: 'child', expression: { type: 'slice', value: '0:2' } }
90 ])
91 });
92
93 test('parse path to filter all books with isbn number', function() {
94 var path = jp.parse('$..book[?(@.isbn)]');
95 assert.deepEqual(path, [
96 { expression: { type: 'root', value: '$' } },
97 { operation: 'member', scope: 'descendant', expression: { type: 'identifier', value: 'book' } },
98 { operation: 'subscript', scope: 'child', expression: { type: 'filter_expression', value: '?(@.isbn)' } }
99 ])
100 });
101
102 test('parse path to filter all books with a price less than 10', function() {
103 var path = jp.parse('$..book[?(@.price<10)]');
104 assert.deepEqual(path, [
105 { expression: { type: 'root', value: '$' } },
106 { operation: 'member', scope: 'descendant', expression: { type: 'identifier', value: 'book' } },
107 { operation: 'subscript', scope: 'child', expression: { type: 'filter_expression', value: '?(@.price<10)' } }
108 ])
109 });
110
111 test('parse path to match all elements', function() {
112 var path = jp.parse('$..*');
113 assert.deepEqual(path, [
114 { expression: { type: 'root', value: '$' } },
115 { operation: 'member', scope: 'descendant', expression: { type: 'wildcard', value: '*' } }
116 ])
117 });
118
119 test('parse path with leading member', function() {
120 var path = jp.parse('store');
121 assert.deepEqual(path, [
122 { operation: 'member', scope: 'child', expression: { type: 'identifier', value: 'store' } }
123 ])
124 });
125
126 test('parse path with leading member and followers', function() {
127 var path = jp.parse('Request.prototype.end');
128 assert.deepEqual(path, [
129 { operation: 'member', scope: 'child', expression: { type: 'identifier', value: 'Request' } },
130 { operation: 'member', scope: 'child', expression: { type: 'identifier', value: 'prototype' } },
131 { operation: 'member', scope: 'child', expression: { type: 'identifier', value: 'end' } }
132 ])
133 });
134
135 test('parser ast is reinitialized after parse() throws', function() {
136 assert.throws(function() { var path = jp.parse('store.book...') })
137 var path = jp.parse('$..price');
138 assert.deepEqual(path, [
139 { "expression": { "type": "root", "value": "$" } },
140 { "expression": { "type": "identifier", "value": "price" }, "operation": "member", "scope": "descendant"}
141 ])
142 });
143
144});
145
146suite('parse-negative', function() {
147
148 test('parse path with leading member component throws', function() {
149 assert.throws(function(e) { var path = jp.parse('.store') }, /Expecting 'DOLLAR'/)
150 });
151
152 test('parse path with leading descendant member throws', function() {
153 assert.throws(function() { var path = jp.parse('..store') }, /Expecting 'DOLLAR'/)
154 });
155
156 test('leading script throws', function() {
157 assert.throws(function() { var path = jp.parse('()') }, /Unrecognized text/)
158 });
159
160 test('first time friendly error', function() {
161 assert.throws(function() { (new jp.JSONPath).parse('$...') }, /Expecting 'STAR'/)
162 });
163
164});