jmespath.js
  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  });