1 | var assert = require('assert');
|
2 | var jmespath = require('../jmespath');
|
3 | var tokenize = jmespath.tokenize;
|
4 | var compile = jmespath.compile;
|
5 | var strictDeepEqual = jmespath.strictDeepEqual;
|
6 |
|
7 |
|
8 | describe('tokenize', function() {
|
9 | it('should tokenize unquoted identifier', function() {
|
10 | assert.deepEqual(tokenize('foo'),
|
11 | [{type: "UnquotedIdentifier",
|
12 | value: "foo",
|
13 | start: 0}]);
|
14 | });
|
15 | it('should tokenize unquoted identifier with underscore', function() {
|
16 | assert.deepEqual(tokenize('_underscore'),
|
17 | [{type: "UnquotedIdentifier",
|
18 | value: "_underscore",
|
19 | start: 0}]);
|
20 | });
|
21 | it('should tokenize unquoted identifier with numbers', function() {
|
22 | assert.deepEqual(tokenize('foo123'),
|
23 | [{type: "UnquotedIdentifier",
|
24 | value: "foo123",
|
25 | start: 0}]);
|
26 | });
|
27 | it('should tokenize dotted lookups', function() {
|
28 | assert.deepEqual(
|
29 | tokenize('foo.bar'),
|
30 | [{type: "UnquotedIdentifier", value: "foo", start: 0},
|
31 | {type: "Dot", value: ".", start: 3},
|
32 | {type: "UnquotedIdentifier", value: "bar", start: 4},
|
33 | ]);
|
34 | });
|
35 | it('should tokenize numbers', function() {
|
36 | assert.deepEqual(
|
37 | tokenize('foo[0]'),
|
38 | [{type: "UnquotedIdentifier", value: "foo", start: 0},
|
39 | {type: "Lbracket", value: "[", start: 3},
|
40 | {type: "Number", value: 0, start: 4},
|
41 | {type: "Rbracket", value: "]", start: 5},
|
42 | ]);
|
43 | });
|
44 | it('should tokenize numbers with multiple digits', function() {
|
45 | assert.deepEqual(
|
46 | tokenize("12345"),
|
47 | [{type: "Number", value: 12345, start: 0}]);
|
48 | });
|
49 | it('should tokenize negative numbers', function() {
|
50 | assert.deepEqual(
|
51 | tokenize("-12345"),
|
52 | [{type: "Number", value: -12345, start: 0}]);
|
53 | });
|
54 | it('should tokenize quoted identifier', function() {
|
55 | assert.deepEqual(tokenize('"foo"'),
|
56 | [{type: "QuotedIdentifier",
|
57 | value: "foo",
|
58 | start: 0}]);
|
59 | });
|
60 | it('should tokenize quoted identifier with unicode escape', function() {
|
61 | assert.deepEqual(tokenize('"\\u2713"'),
|
62 | [{type: "QuotedIdentifier",
|
63 | value: "✓",
|
64 | start: 0}]);
|
65 | });
|
66 | it('should tokenize literal lists', function() {
|
67 | assert.deepEqual(tokenize("`[0, 1]`"),
|
68 | [{type: "Literal",
|
69 | value: [0, 1],
|
70 | start: 0}]);
|
71 | });
|
72 | it('should tokenize literal dict', function() {
|
73 | assert.deepEqual(tokenize("`{\"foo\": \"bar\"}`"),
|
74 | [{type: "Literal",
|
75 | value: {"foo": "bar"},
|
76 | start: 0}]);
|
77 | });
|
78 | it('should tokenize literal strings', function() {
|
79 | assert.deepEqual(tokenize("`\"foo\"`"),
|
80 | [{type: "Literal",
|
81 | value: "foo",
|
82 | start: 0}]);
|
83 | });
|
84 | it('should tokenize json literals', function() {
|
85 | assert.deepEqual(tokenize("`true`"),
|
86 | [{type: "Literal",
|
87 | value: true,
|
88 | start: 0}]);
|
89 | });
|
90 | it('should not requiring surrounding quotes for strings', function() {
|
91 | assert.deepEqual(tokenize("`foo`"),
|
92 | [{type: "Literal",
|
93 | value: "foo",
|
94 | start: 0}]);
|
95 | });
|
96 | it('should not requiring surrounding quotes for numbers', function() {
|
97 | assert.deepEqual(tokenize("`20`"),
|
98 | [{type: "Literal",
|
99 | value: 20,
|
100 | start: 0}]);
|
101 | });
|
102 | it('should tokenize literal lists with chars afterwards', function() {
|
103 | assert.deepEqual(
|
104 | tokenize("`[0, 1]`[0]"), [
|
105 | {type: "Literal", value: [0, 1], start: 0},
|
106 | {type: "Lbracket", value: "[", start: 8},
|
107 | {type: "Number", value: 0, start: 9},
|
108 | {type: "Rbracket", value: "]", start: 10}
|
109 | ]);
|
110 | });
|
111 | it('should tokenize two char tokens with shared prefix', function() {
|
112 | assert.deepEqual(
|
113 | tokenize("[?foo]"),
|
114 | [{type: "Filter", value: "[?", start: 0},
|
115 | {type: "UnquotedIdentifier", value: "foo", start: 2},
|
116 | {type: "Rbracket", value: "]", start: 5}]
|
117 | );
|
118 | });
|
119 | it('should tokenize flatten operator', function() {
|
120 | assert.deepEqual(
|
121 | tokenize("[]"),
|
122 | [{type: "Flatten", value: "[]", start: 0}]);
|
123 | });
|
124 | it('should tokenize comparators', function() {
|
125 | assert.deepEqual(tokenize("<"),
|
126 | [{type: "LT",
|
127 | value: "<",
|
128 | start: 0}]);
|
129 | });
|
130 | it('should tokenize two char tokens without shared prefix', function() {
|
131 | assert.deepEqual(
|
132 | tokenize("=="),
|
133 | [{type: "EQ", value: "==", start: 0}]
|
134 | );
|
135 | });
|
136 | it('should tokenize not equals', function() {
|
137 | assert.deepEqual(
|
138 | tokenize("!="),
|
139 | [{type: "NE", value: "!=", start: 0}]
|
140 | );
|
141 | });
|
142 | it('should tokenize the OR token', function() {
|
143 | assert.deepEqual(
|
144 | tokenize("a||b"),
|
145 | [
|
146 | {type: "UnquotedIdentifier", value: "a", start: 0},
|
147 | {type: "Or", value: "||", start: 1},
|
148 | {type: "UnquotedIdentifier", value: "b", start: 3}
|
149 | ]
|
150 | );
|
151 | });
|
152 | it('should tokenize function calls', function() {
|
153 | assert.deepEqual(
|
154 | tokenize("abs(@)"),
|
155 | [
|
156 | {type: "UnquotedIdentifier", value: "abs", start: 0},
|
157 | {type: "Lparen", value: "(", start: 3},
|
158 | {type: "Current", value: "@", start: 4},
|
159 | {type: "Rparen", value: ")", start: 5}
|
160 | ]
|
161 | );
|
162 | });
|
163 | });
|
164 |
|
165 |
|
166 | describe('parsing', function() {
|
167 | it('should parse field node', function() {
|
168 | assert.deepEqual(compile('foo'),
|
169 | {type: 'Field', name: 'foo'});
|
170 | });
|
171 | });
|
172 |
|
173 | describe('strictDeepEqual', function() {
|
174 | it('should compare scalars', function() {
|
175 | assert.strictEqual(strictDeepEqual('a', 'a'), true);
|
176 | });
|
177 | it('should be false for different types', function() {
|
178 | assert.strictEqual(strictDeepEqual('a', 2), false);
|
179 | });
|
180 | it('should be false for arrays of different lengths', function() {
|
181 | assert.strictEqual(strictDeepEqual([0, 1], [1, 2, 3]), false);
|
182 | });
|
183 | it('should be true for identical arrays', function() {
|
184 | assert.strictEqual(strictDeepEqual([0, 1], [0, 1]), true);
|
185 | });
|
186 | it('should be true for nested arrays', function() {
|
187 | assert.strictEqual(
|
188 | strictDeepEqual([[0, 1], [2, 3]], [[0, 1], [2, 3]]), true);
|
189 | });
|
190 | it('should be true for nested arrays of strings', function() {
|
191 | assert.strictEqual(
|
192 | strictDeepEqual([["a", "b"], ["c", "d"]],
|
193 | [["a", "b"], ["c", "d"]]), true);
|
194 | });
|
195 | it('should be false for different arrays of the same length', function() {
|
196 | assert.strictEqual(strictDeepEqual([0, 1], [1, 2]), false);
|
197 | });
|
198 | it('should handle object literals', function() {
|
199 | assert.strictEqual(strictDeepEqual({a: 1, b: 2}, {a: 1, b: 2}), true);
|
200 | });
|
201 | it('should handle keys in first not in second', function() {
|
202 | assert.strictEqual(strictDeepEqual({a: 1, b: 2}, {a: 1}), false);
|
203 | });
|
204 | it('should handle keys in second not in first', function() {
|
205 | assert.strictEqual(strictDeepEqual({a: 1}, {a: 1, b: 2}), false);
|
206 | });
|
207 | it('should handle nested objects', function() {
|
208 | assert.strictEqual(
|
209 | strictDeepEqual({a: {b: [1, 2]}},
|
210 | {a: {b: [1, 2]}}), true);
|
211 | });
|
212 | it('should handle nested objects that are not equal', function() {
|
213 | assert.strictEqual(
|
214 | strictDeepEqual({a: {b: [1, 2]}},
|
215 | {a: {b: [1, 4]}}), false);
|
216 | });
|
217 | });
|