UNPKG

17.2 kBJavaScriptView Raw
1var assert = require('assert');
2var jp = require('../');
3
4var data = require('./data/store.json');
5
6suite('query', function() {
7
8 test('first-level member', function() {
9 var results = jp.nodes(data, '$.store');
10 assert.deepEqual(results, [ { path: ['$', 'store'], value: data.store } ]);
11 });
12
13 test('authors of all books in the store', function() {
14 var results = jp.nodes(data, '$.store.book[*].author');
15 assert.deepEqual(results, [
16 { path: ['$', 'store', 'book', 0, 'author'], value: 'Nigel Rees' },
17 { path: ['$', 'store', 'book', 1, 'author'], value: 'Evelyn Waugh' },
18 { path: ['$', 'store', 'book', 2, 'author'], value: 'Herman Melville' },
19 { path: ['$', 'store', 'book', 3, 'author'], value: 'J. R. R. Tolkien' }
20 ]);
21 });
22
23 test('all authors', function() {
24 var results = jp.nodes(data, '$..author');
25 assert.deepEqual(results, [
26 { path: ['$', 'store', 'book', 0, 'author'], value: 'Nigel Rees' },
27 { path: ['$', 'store', 'book', 1, 'author'], value: 'Evelyn Waugh' },
28 { path: ['$', 'store', 'book', 2, 'author'], value: 'Herman Melville' },
29 { path: ['$', 'store', 'book', 3, 'author'], value: 'J. R. R. Tolkien' }
30 ]);
31 });
32
33 test('all authors via subscript descendant string literal', function() {
34 var results = jp.nodes(data, "$..['author']");
35 assert.deepEqual(results, [
36 { path: ['$', 'store', 'book', 0, 'author'], value: 'Nigel Rees' },
37 { path: ['$', 'store', 'book', 1, 'author'], value: 'Evelyn Waugh' },
38 { path: ['$', 'store', 'book', 2, 'author'], value: 'Herman Melville' },
39 { path: ['$', 'store', 'book', 3, 'author'], value: 'J. R. R. Tolkien' }
40 ]);
41 });
42
43 test('all things in store', function() {
44 var results = jp.nodes(data, '$.store.*');
45 assert.deepEqual(results, [
46 { path: ['$', 'store', 'book'], value: data.store.book },
47 { path: ['$', 'store', 'bicycle'], value: data.store.bicycle }
48 ]);
49 });
50
51 test('price of everything in the store', function() {
52 var results = jp.nodes(data, '$.store..price');
53 assert.deepEqual(results, [
54 { path: ['$', 'store', 'book', 0, 'price'], value: 8.95 },
55 { path: ['$', 'store', 'book', 1, 'price'], value: 12.99 },
56 { path: ['$', 'store', 'book', 2, 'price'], value: 8.99 },
57 { path: ['$', 'store', 'book', 3, 'price'], value: 22.99 },
58 { path: ['$', 'store', 'bicycle', 'price'], value: 19.95 }
59 ]);
60 });
61
62 test('last book in order via expression', function() {
63 var results = jp.nodes(data, '$..book[(@.length-1)]');
64 assert.deepEqual(results, [ { path: ['$', 'store', 'book', 3], value: data.store.book[3] }]);
65 });
66
67 test('first two books via union', function() {
68 var results = jp.nodes(data, '$..book[0,1]');
69 assert.deepEqual(results, [
70 { path: ['$', 'store', 'book', 0], value: data.store.book[0] },
71 { path: ['$', 'store', 'book', 1], value: data.store.book[1] }
72 ]);
73 });
74
75 test('first two books via slice', function() {
76 var results = jp.nodes(data, '$..book[0:2]');
77 assert.deepEqual(results, [
78 { path: ['$', 'store', 'book', 0], value: data.store.book[0] },
79 { path: ['$', 'store', 'book', 1], value: data.store.book[1] }
80 ]);
81 });
82
83 test('filter all books with isbn number', function() {
84 var results = jp.nodes(data, '$..book[?(@.isbn)]');
85 assert.deepEqual(results, [
86 { path: ['$', 'store', 'book', 2], value: data.store.book[2] },
87 { path: ['$', 'store', 'book', 3], value: data.store.book[3] }
88 ]);
89 });
90
91 test('filter all books with a price less than 10', function() {
92 var results = jp.nodes(data, '$..book[?(@.price<10)]');
93 assert.deepEqual(results, [
94 { path: ['$', 'store', 'book', 0], value: data.store.book[0] },
95 { path: ['$', 'store', 'book', 2], value: data.store.book[2] }
96 ]);
97 });
98
99 test('first ten of all elements', function() {
100 var results = jp.nodes(data, '$..*', 10);
101 assert.deepEqual(results, [
102 { path: [ '$', 'store' ], value: data.store },
103 { path: [ '$', 'store', 'book' ], value: data.store.book },
104 { path: [ '$', 'store', 'bicycle' ], value: data.store.bicycle },
105 { path: [ '$', 'store', 'book', 0 ], value: data.store.book[0] },
106 { path: [ '$', 'store', 'book', 1 ], value: data.store.book[1] },
107 { path: [ '$', 'store', 'book', 2 ], value: data.store.book[2] },
108 { path: [ '$', 'store', 'book', 3 ], value: data.store.book[3] },
109 { path: [ '$', 'store', 'book', 0, 'category' ], value: 'reference' },
110 { path: [ '$', 'store', 'book', 0, 'author' ], value: 'Nigel Rees' },
111 { path: [ '$', 'store', 'book', 0, 'title' ], value: 'Sayings of the Century' }
112 ])
113 });
114
115 test('all elements', function() {
116 var results = jp.nodes(data, '$..*');
117
118 assert.deepEqual(results, [
119 { path: [ '$', 'store' ], value: data.store },
120 { path: [ '$', 'store', 'book' ], value: data.store.book },
121 { path: [ '$', 'store', 'bicycle' ], value: data.store.bicycle },
122 { path: [ '$', 'store', 'book', 0 ], value: data.store.book[0] },
123 { path: [ '$', 'store', 'book', 1 ], value: data.store.book[1] },
124 { path: [ '$', 'store', 'book', 2 ], value: data.store.book[2] },
125 { path: [ '$', 'store', 'book', 3 ], value: data.store.book[3] },
126 { path: [ '$', 'store', 'book', 0, 'category' ], value: 'reference' },
127 { path: [ '$', 'store', 'book', 0, 'author' ], value: 'Nigel Rees' },
128 { path: [ '$', 'store', 'book', 0, 'title' ], value: 'Sayings of the Century' },
129 { path: [ '$', 'store', 'book', 0, 'price' ], value: 8.95 },
130 { path: [ '$', 'store', 'book', 1, 'category' ], value: 'fiction' },
131 { path: [ '$', 'store', 'book', 1, 'author' ], value: 'Evelyn Waugh' },
132 { path: [ '$', 'store', 'book', 1, 'title' ], value: 'Sword of Honour' },
133 { path: [ '$', 'store', 'book', 1, 'price' ], value: 12.99 },
134 { path: [ '$', 'store', 'book', 2, 'category' ], value: 'fiction' },
135 { path: [ '$', 'store', 'book', 2, 'author' ], value: 'Herman Melville' },
136 { path: [ '$', 'store', 'book', 2, 'title' ], value: 'Moby Dick' },
137 { path: [ '$', 'store', 'book', 2, 'isbn' ], value: '0-553-21311-3' },
138 { path: [ '$', 'store', 'book', 2, 'price' ], value: 8.99 },
139 { path: [ '$', 'store', 'book', 3, 'category' ], value: 'fiction' },
140 { path: [ '$', 'store', 'book', 3, 'author' ], value: 'J. R. R. Tolkien' },
141 { path: [ '$', 'store', 'book', 3, 'title' ], value: 'The Lord of the Rings' },
142 { path: [ '$', 'store', 'book', 3, 'isbn' ], value: '0-395-19395-8' },
143 { path: [ '$', 'store', 'book', 3, 'price' ], value: 22.99 },
144 { path: [ '$', 'store', 'bicycle', 'color' ], value: 'red' },
145 { path: [ '$', 'store', 'bicycle', 'price' ], value: 19.95 }
146 ]);
147 });
148
149 test('all elements via subscript wildcard', function() {
150 var results = jp.nodes(data, '$..*');
151 assert.deepEqual(jp.nodes(data, '$..[*]'), jp.nodes(data, '$..*'));
152 });
153
154 test('object subscript wildcard', function() {
155 var results = jp.query(data, '$.store[*]');
156 assert.deepEqual(results, [ data.store.book, data.store.bicycle ]);
157 });
158
159 test('no match returns empty array', function() {
160 var results = jp.nodes(data, '$..bookz');
161 assert.deepEqual(results, []);
162 });
163
164 test('member numeric literal gets first element', function() {
165 var results = jp.nodes(data, '$.store.book.0');
166 assert.deepEqual(results, [ { path: [ '$', 'store', 'book', 0 ], value: data.store.book[0] } ]);
167 });
168
169 test('member numeric literal matches string-numeric key', function() {
170 var data = { authors: { '1': 'Herman Melville', '2': 'J. R. R. Tolkien' } };
171 var results = jp.nodes(data, '$.authors.1');
172 assert.deepEqual(results, [ { path: [ '$', 'authors', 1 ], value: 'Herman Melville' } ]);
173 });
174
175 test('descendant numeric literal gets first element', function() {
176 var results = jp.nodes(data, '$.store.book..0');
177 assert.deepEqual(results, [ { path: [ '$', 'store', 'book', 0 ], value: data.store.book[0] } ]);
178 });
179
180 test('root element gets us original obj', function() {
181 var results = jp.nodes(data, '$');
182 assert.deepEqual(results, [ { path: ['$'], value: data } ]);
183 });
184
185 test('subscript double-quoted string', function() {
186 var results = jp.nodes(data, '$["store"]');
187 assert.deepEqual(results, [ { path: ['$', 'store'], value: data.store} ]);
188 });
189
190 test('subscript single-quoted string', function() {
191 var results = jp.nodes(data, "$['store']");
192 assert.deepEqual(results, [ { path: ['$', 'store'], value: data.store} ]);
193 });
194
195 test('leading member component', function() {
196 var results = jp.nodes(data, "store");
197 assert.deepEqual(results, [ { path: ['$', 'store'], value: data.store} ]);
198 });
199
200 test('union of three array slices', function() {
201 var results = jp.query(data, "$.store.book[0:1,1:2,2:3]");
202 assert.deepEqual(results, data.store.book.slice(0,3));
203 });
204
205 test('slice with step > 1', function() {
206 var results = jp.query(data, "$.store.book[0:4:2]");
207 assert.deepEqual(results, [ data.store.book[0], data.store.book[2]]);
208 });
209
210 test('union of subscript string literal keys', function() {
211 var results = jp.nodes(data, "$.store['book','bicycle']");
212 assert.deepEqual(results, [
213 { path: ['$', 'store', 'book'], value: data.store.book },
214 { path: ['$', 'store', 'bicycle'], value: data.store.bicycle },
215 ]);
216 });
217
218 test('union of subscript string literal three keys', function() {
219 var results = jp.nodes(data, "$.store.book[0]['title','author','price']");
220 assert.deepEqual(results, [
221 { path: ['$', 'store', 'book', 0, 'title'], value: data.store.book[0].title },
222 { path: ['$', 'store', 'book', 0, 'author'], value: data.store.book[0].author },
223 { path: ['$', 'store', 'book', 0, 'price'], value: data.store.book[0].price }
224 ]);
225 });
226
227 test('union of subscript integer three keys followed by member-child-identifier', function() {
228 var results = jp.nodes(data, "$.store.book[1,2,3]['title']");
229 assert.deepEqual(results, [
230 { path: ['$', 'store', 'book', 1, 'title'], value: data.store.book[1].title },
231 { path: ['$', 'store', 'book', 2, 'title'], value: data.store.book[2].title },
232 { path: ['$', 'store', 'book', 3, 'title'], value: data.store.book[3].title }
233 ]);
234 });
235
236 test('union of subscript integer three keys followed by union of subscript string literal three keys', function() {
237 var results = jp.nodes(data, "$.store.book[0,1,2,3]['title','author','price']");
238 assert.deepEqual(results, [
239 { path: ['$', 'store', 'book', 0, 'title'], value: data.store.book[0].title },
240 { path: ['$', 'store', 'book', 0, 'author'], value: data.store.book[0].author },
241 { path: ['$', 'store', 'book', 0, 'price'], value: data.store.book[0].price },
242 { path: ['$', 'store', 'book', 1, 'title'], value: data.store.book[1].title },
243 { path: ['$', 'store', 'book', 1, 'author'], value: data.store.book[1].author },
244 { path: ['$', 'store', 'book', 1, 'price'], value: data.store.book[1].price },
245 { path: ['$', 'store', 'book', 2, 'title'], value: data.store.book[2].title },
246 { path: ['$', 'store', 'book', 2, 'author'], value: data.store.book[2].author },
247 { path: ['$', 'store', 'book', 2, 'price'], value: data.store.book[2].price },
248 { path: ['$', 'store', 'book', 3, 'title'], value: data.store.book[3].title },
249 { path: ['$', 'store', 'book', 3, 'author'], value: data.store.book[3].author },
250 { path: ['$', 'store', 'book', 3, 'price'], value: data.store.book[3].price }
251 ]);
252 });
253
254 test('union of subscript integer four keys, including an inexistent one, followed by union of subscript string literal three keys', function() {
255 var results = jp.nodes(data, "$.store.book[0,1,2,3,151]['title','author','price']");
256 assert.deepEqual(results, [
257 { path: ['$', 'store', 'book', 0, 'title'], value: data.store.book[0].title },
258 { path: ['$', 'store', 'book', 0, 'author'], value: data.store.book[0].author },
259 { path: ['$', 'store', 'book', 0, 'price'], value: data.store.book[0].price },
260 { path: ['$', 'store', 'book', 1, 'title'], value: data.store.book[1].title },
261 { path: ['$', 'store', 'book', 1, 'author'], value: data.store.book[1].author },
262 { path: ['$', 'store', 'book', 1, 'price'], value: data.store.book[1].price },
263 { path: ['$', 'store', 'book', 2, 'title'], value: data.store.book[2].title },
264 { path: ['$', 'store', 'book', 2, 'author'], value: data.store.book[2].author },
265 { path: ['$', 'store', 'book', 2, 'price'], value: data.store.book[2].price },
266 { path: ['$', 'store', 'book', 3, 'title'], value: data.store.book[3].title },
267 { path: ['$', 'store', 'book', 3, 'author'], value: data.store.book[3].author },
268 { path: ['$', 'store', 'book', 3, 'price'], value: data.store.book[3].price }
269 ]);
270 });
271
272 test('union of subscript integer three keys followed by union of subscript string literal three keys, followed by inexistent literal key', function() {
273 var results = jp.nodes(data, "$.store.book[0,1,2,3]['title','author','price','fruit']");
274 assert.deepEqual(results, [
275 { path: ['$', 'store', 'book', 0, 'title'], value: data.store.book[0].title },
276 { path: ['$', 'store', 'book', 0, 'author'], value: data.store.book[0].author },
277 { path: ['$', 'store', 'book', 0, 'price'], value: data.store.book[0].price },
278 { path: ['$', 'store', 'book', 1, 'title'], value: data.store.book[1].title },
279 { path: ['$', 'store', 'book', 1, 'author'], value: data.store.book[1].author },
280 { path: ['$', 'store', 'book', 1, 'price'], value: data.store.book[1].price },
281 { path: ['$', 'store', 'book', 2, 'title'], value: data.store.book[2].title },
282 { path: ['$', 'store', 'book', 2, 'author'], value: data.store.book[2].author },
283 { path: ['$', 'store', 'book', 2, 'price'], value: data.store.book[2].price },
284 { path: ['$', 'store', 'book', 3, 'title'], value: data.store.book[3].title },
285 { path: ['$', 'store', 'book', 3, 'author'], value: data.store.book[3].author },
286 { path: ['$', 'store', 'book', 3, 'price'], value: data.store.book[3].price }
287 ]);
288 });
289
290 test('union of subscript 4 array slices followed by union of subscript string literal three keys', function() {
291 var results = jp.nodes(data, "$.store.book[0:1,1:2,2:3,3:4]['title','author','price']");
292 assert.deepEqual(results, [
293 { path: ['$', 'store', 'book', 0, 'title'], value: data.store.book[0].title },
294 { path: ['$', 'store', 'book', 0, 'author'], value: data.store.book[0].author },
295 { path: ['$', 'store', 'book', 0, 'price'], value: data.store.book[0].price },
296 { path: ['$', 'store', 'book', 1, 'title'], value: data.store.book[1].title },
297 { path: ['$', 'store', 'book', 1, 'author'], value: data.store.book[1].author },
298 { path: ['$', 'store', 'book', 1, 'price'], value: data.store.book[1].price },
299 { path: ['$', 'store', 'book', 2, 'title'], value: data.store.book[2].title },
300 { path: ['$', 'store', 'book', 2, 'author'], value: data.store.book[2].author },
301 { path: ['$', 'store', 'book', 2, 'price'], value: data.store.book[2].price },
302 { path: ['$', 'store', 'book', 3, 'title'], value: data.store.book[3].title },
303 { path: ['$', 'store', 'book', 3, 'author'], value: data.store.book[3].author },
304 { path: ['$', 'store', 'book', 3, 'price'], value: data.store.book[3].price }
305 ]);
306 });
307
308
309 test('nested parentheses eval', function() {
310 var pathExpression = '$..book[?( @.price && (@.price + 20 || false) )]'
311 var results = jp.query(data, pathExpression);
312 assert.deepEqual(results, data.store.book);
313 });
314
315 test('array indexes from 0 to 100', function() {
316 var data = [];
317 for (var i = 0; i <= 100; ++i)
318 data[i] = Math.random();
319
320 for (var i = 0; i <= 100; ++i) {
321 var results = jp.query(data, '$[' + i.toString() + ']');
322 assert.deepEqual(results, [data[i]]);
323 }
324 });
325
326 test('descendant subscript numeric literal', function() {
327 var data = [ 0, [ 1, 2, 3 ], [ 4, 5, 6 ] ];
328 var results = jp.query(data, '$..[0]');
329 assert.deepEqual(results, [ 0, 1, 4 ]);
330 });
331
332 test('descendant subscript numeric literal', function() {
333 var data = [ 0, 1, [ 2, 3, 4 ], [ 5, 6, 7, [ 8, 9 , 10 ] ] ];
334 var results = jp.query(data, '$..[0,1]');
335 assert.deepEqual(results, [ 0, 1, 2, 3, 5, 6, 8, 9 ]);
336 });
337
338 test('throws for no input', function() {
339 assert.throws(function() { jp.query() }, /needs to be an object/);
340 });
341
342 test('throws for bad input', function() {
343 assert.throws(function() { jp.query("string", "string") }, /needs to be an object/);
344 });
345
346 test('throws for bad input', function() {
347 assert.throws(function() { jp.query({}, null) }, /we need a path/);
348 });
349
350 test('throws for bad input', function() {
351 assert.throws(function() { jp.query({}, 42) }, /we need a path/);
352 });
353
354 test('union on objects', function() {
355 assert.deepEqual(jp.query({a: 1, b: 2, c: null}, '$..["a","b","c","d"]'), [1, 2, null]);
356 });
357
358});
359