feat: Add Be and tbd skill, also added Roadmap file

This commit is contained in:
2026-05-10 16:32:12 -04:00
parent 3500ade13f
commit 0bb8885802
29587 changed files with 10611695 additions and 0 deletions

10
Skills/@be/node_modules/jmespath/.eslintrc generated vendored Normal file
View File

@@ -0,0 +1,10 @@
{
"env": {
"browser": true,
"node": true
},
"globals": {
"toString": true,
"hasOwnProperty": true
}
}

1
Skills/@be/node_modules/jmespath/.npmignore generated vendored Normal file
View File

@@ -0,0 +1 @@
node_modules

6
Skills/@be/node_modules/jmespath/.travis.yml generated vendored Normal file
View File

@@ -0,0 +1,6 @@
language: node_js
node_js:
- "0.12"
- "0.11"
- "0.10"
- "iojs"

15
Skills/@be/node_modules/jmespath/BASELINE generated vendored Normal file
View File

@@ -0,0 +1,15 @@
master:
Mean time: 0.002530msec Parser#single_expr x 395,306 ops/sec ±1.89% (79 runs sampled)
Mean time: 0.005492msec Parser#single_subexpr x 182,084 ops/sec ±1.99% (84 runs sampled)
Mean time: 0.126803msec Parser#deeply_nested_50 x 7,886 ops/sec ±2.44% (80 runs sampled)
Mean time: 0.166790msec Parser#deeply_nested_50_index x 5,996 ops/sec ±5.08% (75 runs sampled)
Mean time: 0.008347msec Parser#basic_list_projection x 119,798 ops/sec ±2.33% (79 runs sampled)
Mean time: 0.002779msec Parser#single_expr x 359,839 ops/sec ±4.15% (80 runs sampled)
Mean time: 0.005235msec Parser#single_subexpr x 191,026 ops/sec ±2.62% (78 runs sampled)
Mean time: 0.104357msec Parser#deeply_nested_50 x 9,582 ops/sec ±4.34% (72 runs sampled)
Mean time: 0.178837msec Parser#deeply_nested_50_index x 5,592 ops/sec ±3.35% (77 runs sampled)
Mean time: 0.009614msec Parser#basic_list_projection x 104,012 ops/sec ±2.97% (79 runs sampled)

36
Skills/@be/node_modules/jmespath/Gruntfile.js generated vendored Normal file
View File

@@ -0,0 +1,36 @@
module.exports = function(grunt) {
// Project configuration.
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
uglify: {
options: {
banner: '/*! <%= pkg.name %> <%= grunt.template.today("yyyy-mm-dd") %> */\n',
mangleProperties: {regex: /^_/}
},
build: {
src: '<%= pkg.name %>.js',
dest: 'artifacts/<%= pkg.name %>.min.js'
}
},
jshint: {
ignore_warning: {
options: {
'-W083': true
},
src: ['jmespath.js', 'test/*.js', 'Gruntfile.js']
}
},
eslint: {
target: ['jmespath.js']
}
});
grunt.loadNpmTasks('grunt-contrib-uglify');
grunt.loadNpmTasks('grunt-contrib-jshint');
grunt.loadNpmTasks('grunt-eslint');
// Default task(s).
grunt.registerTask('default', ['uglify', 'jshint', 'eslint']);
};

13
Skills/@be/node_modules/jmespath/LICENSE generated vendored Normal file
View File

@@ -0,0 +1,13 @@
Copyright 2014 James Saryerwinnie
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

57
Skills/@be/node_modules/jmespath/README.md generated vendored Normal file
View File

@@ -0,0 +1,57 @@
# jmespath.js
[![Build Status](https://travis-ci.org/jmespath/jmespath.js.png?branch=master)](https://travis-ci.org/jmespath/jmespath.js)
jmespath.js is a javascript implementation of JMESPath,
which is a query language for JSON. It will take a JSON
document and transform it into another JSON document
through a JMESPath expression.
Using jmespath.js is really easy. There's a single function
you use, `jmespath.search`:
```
> var jmespath = require('jmespath');
> jmespath.search({foo: {bar: {baz: [0, 1, 2, 3, 4]}}}, "foo.bar.baz[2]")
2
```
In the example we gave the ``search`` function input data of
`{foo: {bar: {baz: [0, 1, 2, 3, 4]}}}` as well as the JMESPath
expression `foo.bar.baz[2]`, and the `search` function evaluated
the expression against the input data to produce the result ``2``.
The JMESPath language can do a lot more than select an element
from a list. Here are a few more examples:
```
> jmespath.search({foo: {bar: {baz: [0, 1, 2, 3, 4]}}}, "foo.bar")
{ baz: [ 0, 1, 2, 3, 4 ] }
> jmespath.search({"foo": [{"first": "a", "last": "b"},
{"first": "c", "last": "d"}]},
"foo[*].first")
[ 'a', 'c' ]
> jmespath.search({"foo": [{"age": 20}, {"age": 25},
{"age": 30}, {"age": 35},
{"age": 40}]},
"foo[?age > `30`]")
[ { age: 35 }, { age: 40 } ]
```
## More Resources
The example above only show a small amount of what
a JMESPath expression can do. If you want to take a
tour of the language, the *best* place to go is the
[JMESPath Tutorial](http://jmespath.org/tutorial.html).
One of the best things about JMESPath is that it is
implemented in many different programming languages including
python, ruby, php, lua, etc. To see a complete list of libraries,
check out the [JMESPath libraries page](http://jmespath.org/libraries.html).
And finally, the full JMESPath specification can be found
on the [JMESPath site](http://jmespath.org/specification.html).

File diff suppressed because one or more lines are too long

24
Skills/@be/node_modules/jmespath/bower.json generated vendored Normal file
View File

@@ -0,0 +1,24 @@
{
"name": "jmespath.js",
"main": "jmespath.js",
"version": "0.11.0",
"homepage": "https://github.com/jmespath/jmespath.js",
"authors": [
"James Saryerwinnie <js@jamesls.com>"
],
"description": "JMESPath implementation in javascript",
"moduleType": [
"node"
],
"keywords": [
"jmespath"
],
"license": "MIT",
"ignore": [
"**/.*",
"node_modules",
"bower_components",
"test",
"tests"
]
}

5
Skills/@be/node_modules/jmespath/g.sh generated vendored Normal file
View File

@@ -0,0 +1,5 @@
#!/bin/bash
grunt
uglifyjs artifacts/jmespath.min.js -b -o /tmp/jmespath.min.js
uglifyjs artifacts/jmespath.min.js -b -o ~/Source/jmespath.site/docs/_build/html/_static/js/jmespath.min.js
#cp artifacts/jmespath.min.js ~/Source/jmespath.site/docs/_build/html/_static/js/

93
Skills/@be/node_modules/jmespath/index.html generated vendored Normal file
View File

@@ -0,0 +1,93 @@
<!doctype html>
<!--[if lt IE 7]> <html class="no-js lt-ie9 lt-ie8 lt-ie7" lang="en"> <![endif]-->
<!--[if IE 7]> <html class="no-js lt-ie9 lt-ie8" lang="en"> <![endif]-->
<!--[if IE 8]> <html class="no-js lt-ie9" lang="en"> <![endif]-->
<!--[if gt IE 8]><!--> <html class="no-js" lang="en"> <!--<![endif]-->
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title>JMESPath Demo</title>
<meta name="description" content="JMESPath Demo">
<!--
<link rel="stylesheet" href="css/bootstrap.min.css">
<link rel="stylesheet" href="css/style.css">
-->
<script src="artifacts/jmespath.min.js"></script>
</head>
<body>
<div class="container-fluid">
<div class="hero-unit">
<h1>JSONPath Online Evaluator</h1>
<div id="info">
<p>Author: <a href="http://ashphy.com/">Kazuki Hamasaki</a> [ashphy@ashphy.com]</p>
<p>This evaluator uses <a href="http://goessner.net/articles/JsonPath/">JSONPath - XPath for JSON</a></p>
</div>
</div>
<div class="row-fluid">
<div class="span6">
<h2>Inputs</h2>
<form>
<label>JSONPath Syntax</label>
<input type="text" placeholder="Put JSONPath syntax" value="$.phoneNumbers[:1].type" />
<span class="help-block">Example '$.phoneNumbers[*].type' See also <a href="http://goessner.net/articles/JsonPath/index.html#e2">JSONPath expressions</a></span>
<label>JSON</label>
<textarea rows="30" cols="80">
{
"firstName": "John",
"lastName" : "doe",
"age" : 26,
"address" :
{
"streetAddress": "naist street",
"city" : "Nara",
"postalCode" : "630-0192"
},
"phoneNumbers":
[
{
"type" : "iPhone",
"number": "0123-4567-8888"
},
{
"type" : "home",
"number": "0123-4567-8910"
}
]
}
</textarea>
</form>
</div>
<div class="span6 ">
<h2>Evaluation Results</h2>
<pre class="result">false</pre>
</div>
</div>
</div>
<!-- JavaScript at the bottom for fast page loading: http://developer.yahoo.com/performance/rules.html#js_bottom -->
<!-- Grab Google CDN's jQuery, with a protocol relative URL; fall back to local if offline -->
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
<script>window.jQuery || document.write('<script src="js/vendor/jquery-1.7.2.min.js"><\/script>')</script>
<script src="js/vendor/jquery.textchange.min.js"></script>
<script>
var evaluate = function(event, previousText){
var query = $("input").val();
var json = JSON.parse($("textarea").val().replace(/(\r\n|\n|\r)/gm,""));
var result = jsonPath(json, query);
$(".result").empty();
if(result) {
$(".result").append(dump(result));
}
}
$(document).ready(function(){
$('input').bind('textchange', evaluate);
$('textarea').bind('textchange', evaluate);
evaluate();
});
</script>
</body>
</html>

7
Skills/@be/node_modules/jmespath/james.html generated vendored Normal file
View File

@@ -0,0 +1,7 @@
<html>
<head>
<script src="artifacts/jmespath.min.js"></script>
</head>
<body>
</body>
</html>

1667
Skills/@be/node_modules/jmespath/jmespath.js generated vendored Normal file

File diff suppressed because it is too large Load Diff

23
Skills/@be/node_modules/jmespath/jp.js generated vendored Normal file
View File

@@ -0,0 +1,23 @@
#!/usr/bin/env node
jmespath = require('./jmespath');
process.stdin.setEncoding('utf-8');
if (process.argv.length < 2) {
console.log("Must provide a jmespath expression.");
process.exit(1);
}
var inputJSON = "";
process.stdin.on('readable', function() {
var chunk = process.stdin.read();
if (chunk !== null) {
inputJSON += chunk;
}
});
process.stdin.on('end', function() {
var parsedInput = JSON.parse(inputJSON);
console.log(JSON.stringify(jmespath.search(parsedInput, process.argv[2])));
});

189
Skills/@be/node_modules/jmespath/l.js generated vendored Normal file
View File

@@ -0,0 +1,189 @@
'use strict';
var Lexer = exports.Lexer = function() {
this.pos = 0;
this.buf = null;
this.buflen = 0;
// Operator table, mapping operator -> token name
this.optable = {
'+': 'PLUS',
'-': 'MINUS',
'*': 'MULTIPLY',
'.': 'PERIOD',
'\\': 'BACKSLASH',
':': 'COLON',
'%': 'PERCENT',
'|': 'PIPE',
'!': 'EXCLAMATION',
'?': 'QUESTION',
'#': 'POUND',
'&': 'AMPERSAND',
';': 'SEMI',
',': 'COMMA',
'(': 'L_PAREN',
')': 'R_PAREN',
'<': 'L_ANG',
'>': 'R_ANG',
'{': 'L_BRACE',
'}': 'R_BRACE',
'[': 'L_BRACKET',
']': 'R_BRACKET',
'=': 'EQUALS'
};
}
// Initialize the Lexer's buffer. This resets the lexer's internal
// state and subsequent tokens will be returned starting with the
// beginning of the new buffer.
Lexer.prototype.input = function(buf) {
this.pos = 0;
this.buf = buf;
this.buflen = buf.length;
}
// Get the next token from the current buffer. A token is an object with
// the following properties:
// - name: name of the pattern that this token matched (taken from rules).
// - value: actual string value of the token.
// - pos: offset in the current buffer where the token starts.
//
// If there are no more tokens in the buffer, returns null. In case of
// an error throws Error.
Lexer.prototype.token = function() {
this._skipnontokens();
if (this.pos >= this.buflen) {
return null;
}
// The char at this.pos is part of a real token. Figure out which.
var c = this.buf.charAt(this.pos);
// '/' is treated specially, because it starts a comment if followed by
// another '/'. If not followed by another '/', it's the DIVIDE
// operator.
if (c === '/') {
var next_c = this.buf.charAt(this.pos + 1);
if (next_c === '/') {
return this._process_comment();
} else {
return {name: 'DIVIDE', value: '/', pos: this.pos++};
}
} else {
// Look it up in the table of operators
var op = this.optable[c];
if (op !== undefined) {
return {name: op, value: c, pos: this.pos++};
} else {
// Not an operator - so it's the beginning of another token.
if (Lexer._isalpha(c)) {
return this._process_identifier();
} else if (Lexer._isdigit(c)) {
return this._process_number();
} else if (c === '"') {
return this._process_quote();
} else {
throw Error('Token error at ' + this.pos);
}
}
}
}
Lexer._isnewline = function(c) {
return c === '\r' || c === '\n';
}
Lexer._isdigit = function(c) {
return c >= '0' && c <= '9';
}
Lexer._isalpha = function(c) {
return (c >= 'a' && c <= 'z') ||
(c >= 'A' && c <= 'Z') ||
c === '_' || c === '$';
}
Lexer._isalphanum = function(c) {
return (c >= 'a' && c <= 'z') ||
(c >= 'A' && c <= 'Z') ||
(c >= '0' && c <= '9') ||
c === '_' || c === '$';
}
Lexer.prototype._process_number = function() {
var endpos = this.pos + 1;
while (endpos < this.buflen &&
Lexer._isdigit(this.buf.charAt(endpos))) {
endpos++;
}
var tok = {
name: 'NUMBER',
value: this.buf.substring(this.pos, endpos),
pos: this.pos
};
this.pos = endpos;
return tok;
}
Lexer.prototype._process_comment = function() {
var endpos = this.pos + 2;
// Skip until the end of the line
var c = this.buf.charAt(this.pos + 2);
while (endpos < this.buflen &&
!Lexer._isnewline(this.buf.charAt(endpos))) {
endpos++;
}
var tok = {
name: 'COMMENT',
value: this.buf.substring(this.pos, endpos),
pos: this.pos
};
this.pos = endpos + 1;
return tok;
}
Lexer.prototype._process_identifier = function() {
var endpos = this.pos + 1;
while (endpos < this.buflen &&
Lexer._isalphanum(this.buf.charAt(endpos))) {
endpos++;
}
var tok = {
name: 'IDENTIFIER',
value: this.buf.substring(this.pos, endpos),
pos: this.pos
};
this.pos = endpos;
return tok;
}
Lexer.prototype._process_quote = function() {
// this.pos points at the opening quote. Find the ending quote.
var end_index = this.buf.indexOf('"', this.pos + 1);
if (end_index === -1) {
throw Error('Unterminated quote at ' + this.pos);
} else {
var tok = {
name: 'QUOTE',
value: this.buf.substring(this.pos, end_index + 1),
pos: this.pos
};
this.pos = end_index + 1;
return tok;
}
}
Lexer.prototype._skipnontokens = function() {
while (this.pos < this.buflen) {
var c = this.buf.charAt(this.pos);
if (c == ' ' || c == '\t' || c == '\r' || c == '\n') {
this.pos++;
} else {
break;
}
}
}

50
Skills/@be/node_modules/jmespath/package.json generated vendored Normal file
View File

@@ -0,0 +1,50 @@
{
"name": "jmespath",
"description": "JMESPath implementation in javascript",
"version": "0.15.0",
"author": {
"name": "James Saryerwinnie",
"email": "js@jamesls.com",
"url": "http://jamesls.com/"
},
"homepage": "https://github.com/jmespath/jmespath.js",
"contributors": [],
"devDependencies": {
"grunt": "^0.4.5",
"grunt-contrib-jshint": "^0.11.0",
"grunt-contrib-uglify": "^0.11.1",
"grunt-eslint": "^17.3.1",
"mocha": "^2.1.0"
},
"dependencies": {},
"main": "jmespath.js",
"directories": {
"test": "test"
},
"engines": {
"node": ">= 0.6.0"
},
"repository": {
"type": "git",
"url": "git://github.com/jmespath/jmespath.js"
},
"bugs": {
"url": "http://github.com/jmespath/jmespath.js/issues",
"mail": ""
},
"licenses": [
{
"type": "Apache 2.0",
"url": "http://github.com/jmespath/jmespath.js/raw/master/LICENSE"
}
],
"keywords": [
"jmespath",
"jsonpath",
"json",
"xpath"
],
"scripts": {
"test": "mocha test/"
}
}

33
Skills/@be/node_modules/jmespath/perf.js generated vendored Normal file
View File

@@ -0,0 +1,33 @@
var jmespath = require('./jmespath')
var Benchmark = require('benchmark');
var suite = new Benchmark.Suite;
// add tests
suite.add('Parser#single_expr', function() {
jmespath.compile("foo");
})
.add('Parser#single_subexpr', function() {
jmespath.compile("foo.bar");
})
.add('Parser#deeply_nested_50', function() {
jmespath.compile("j49.j48.j47.j46.j45.j44.j43.j42.j41.j40.j39.j38.j37.j36.j35.j34.j33.j32.j31.j30.j29.j28.j27.j26.j25.j24.j23.j22.j21.j20.j19.j18.j17.j16.j15.j14.j13.j12.j11.j10.j9.j8.j7.j6.j5.j4.j3.j2.j1.j0");
})
.add('Parser#deeply_nested_50_index', function() {
jmespath.compile("[49][48][47][46][45][44][43][42][41][40][39][38][37][36][35][34][33][32][31][30][29][28][27][26][25][24][23][22][21][20][19][18][17][16][15][14][13][12][11][10][9][8][7][6][5][4][3][2][1][0]");
})
.add('Parser#basic_list_projection', function() {
jmespath.compile("foo[*].bar");
})
.on('cycle', function(event) {
var bench = event.target;
var mean = bench.stats.mean * 1000;
var variance = bench.stats.variance * 1000000;
var result = 'Mean time: ' + mean.toFixed(6) + 'msec ';
result += event.target.toString();
console.log(result);
})
.on('complete', function() {
})
// run async
.run({ 'async': false });

4
Skills/@be/node_modules/jmespath/reservedWords.json generated vendored Normal file
View File

@@ -0,0 +1,4 @@
{
"vars": [ "define", "require", "exports"],
"props": ["compile", "search", "tokenize", "jmespath", "parse", "stringify", "prototype", "length"]
}

56
Skills/@be/node_modules/jmespath/test/compliance.js generated vendored Normal file
View File

@@ -0,0 +1,56 @@
var fs = require('fs');
var path = require('path');
var assert = require('assert');
var jmespath = require('../jmespath');
var search = jmespath.search;
// Compliance tests that aren't supported yet.
var notImplementedYet = [];
function endsWith(str, suffix) {
return str.indexOf(suffix, str.length - suffix.length) !== -1;
}
var listing = fs.readdirSync('test/compliance');
for (var i = 0; i < listing.length; i++) {
var filename = 'test/compliance/' + listing[i];
if (fs.statSync(filename).isFile() && endsWith(filename, '.json') &&
notImplementedYet.indexOf(path.basename(filename)) === -1) {
addTestSuitesFromFile(filename);
}
}
function addTestSuitesFromFile(filename) {
describe(filename, function() {
var spec = JSON.parse(fs.readFileSync(filename, 'utf-8'));
var errorMsg;
for (var i = 0; i < spec.length; i++) {
var msg = "suite " + i + " for filename " + filename;
describe(msg, function() {
var given = spec[i].given;
var cases = spec[i].cases;
for (var j = 0; j < cases.length; j++) {
var testcase = cases[j];
if (testcase.error !== undefined) {
// For now just verify that an error is thrown
// for error tests.
(function(testcase, given) {
it('should throw error for test ' + j, function() {
assert.throws(
function() {
search(given, testcase.expression);
}, Error, testcase.expression);
});
})(testcase, given);
} else {
(function(testcase, given) {
it('should pass test ' + j + " expression: " + testcase.expression, function() {
assert.deepEqual(search(given, testcase.expression),
testcase.result);
});
})(testcase, given);
}
}
});
}
});
}

View File

@@ -0,0 +1,96 @@
[{
"given":
{"foo": {"bar": {"baz": "correct"}}},
"cases": [
{
"expression": "foo",
"result": {"bar": {"baz": "correct"}}
},
{
"expression": "foo.bar",
"result": {"baz": "correct"}
},
{
"expression": "foo.bar.baz",
"result": "correct"
},
{
"expression": "foo\n.\nbar\n.baz",
"result": "correct"
},
{
"expression": "foo.bar.baz.bad",
"result": null
},
{
"expression": "foo.bar.bad",
"result": null
},
{
"expression": "foo.bad",
"result": null
},
{
"expression": "bad",
"result": null
},
{
"expression": "bad.morebad.morebad",
"result": null
}
]
},
{
"given":
{"foo": {"bar": ["one", "two", "three"]}},
"cases": [
{
"expression": "foo",
"result": {"bar": ["one", "two", "three"]}
},
{
"expression": "foo.bar",
"result": ["one", "two", "three"]
}
]
},
{
"given": ["one", "two", "three"],
"cases": [
{
"expression": "one",
"result": null
},
{
"expression": "two",
"result": null
},
{
"expression": "three",
"result": null
},
{
"expression": "one.two",
"result": null
}
]
},
{
"given":
{"foo": {"1": ["one", "two", "three"], "-1": "bar"}},
"cases": [
{
"expression": "foo.\"1\"",
"result": ["one", "two", "three"]
},
{
"expression": "foo.\"1\"[0]",
"result": "one"
},
{
"expression": "foo.\"-1\"",
"result": "bar"
}
]
}
]

View File

@@ -0,0 +1,257 @@
[
{
"given": {
"outer": {
"foo": "foo",
"bar": "bar",
"baz": "baz"
}
},
"cases": [
{
"expression": "outer.foo || outer.bar",
"result": "foo"
},
{
"expression": "outer.foo||outer.bar",
"result": "foo"
},
{
"expression": "outer.bar || outer.baz",
"result": "bar"
},
{
"expression": "outer.bar||outer.baz",
"result": "bar"
},
{
"expression": "outer.bad || outer.foo",
"result": "foo"
},
{
"expression": "outer.bad||outer.foo",
"result": "foo"
},
{
"expression": "outer.foo || outer.bad",
"result": "foo"
},
{
"expression": "outer.foo||outer.bad",
"result": "foo"
},
{
"expression": "outer.bad || outer.alsobad",
"result": null
},
{
"expression": "outer.bad||outer.alsobad",
"result": null
}
]
},
{
"given": {
"outer": {
"foo": "foo",
"bool": false,
"empty_list": [],
"empty_string": ""
}
},
"cases": [
{
"expression": "outer.empty_string || outer.foo",
"result": "foo"
},
{
"expression": "outer.nokey || outer.bool || outer.empty_list || outer.empty_string || outer.foo",
"result": "foo"
}
]
},
{
"given": {
"True": true,
"False": false,
"Number": 5,
"EmptyList": [],
"Zero": 0
},
"cases": [
{
"expression": "True && False",
"result": false
},
{
"expression": "False && True",
"result": false
},
{
"expression": "True && True",
"result": true
},
{
"expression": "False && False",
"result": false
},
{
"expression": "True && Number",
"result": 5
},
{
"expression": "Number && True",
"result": true
},
{
"expression": "Number && False",
"result": false
},
{
"expression": "Number && EmptyList",
"result": []
},
{
"expression": "Number && True",
"result": true
},
{
"expression": "EmptyList && True",
"result": []
},
{
"expression": "EmptyList && False",
"result": []
},
{
"expression": "True || False",
"result": true
},
{
"expression": "True || True",
"result": true
},
{
"expression": "False || True",
"result": true
},
{
"expression": "False || False",
"result": false
},
{
"expression": "Number || EmptyList",
"result": 5
},
{
"expression": "Number || True",
"result": 5
},
{
"expression": "Number || True && False",
"result": 5
},
{
"expression": "(Number || True) && False",
"result": false
},
{
"expression": "Number || (True && False)",
"result": 5
},
{
"expression": "!True",
"result": false
},
{
"expression": "!False",
"result": true
},
{
"expression": "!Number",
"result": false
},
{
"expression": "!EmptyList",
"result": true
},
{
"expression": "True && !False",
"result": true
},
{
"expression": "True && !EmptyList",
"result": true
},
{
"expression": "!False && !EmptyList",
"result": true
},
{
"expression": "!(True && False)",
"result": true
},
{
"expression": "!Zero",
"result": false
},
{
"expression": "!!Zero",
"result": true
}
]
},
{
"given": {
"one": 1,
"two": 2,
"three": 3
},
"cases": [
{
"expression": "one < two",
"result": true
},
{
"expression": "one <= two",
"result": true
},
{
"expression": "one == one",
"result": true
},
{
"expression": "one == two",
"result": false
},
{
"expression": "one > two",
"result": false
},
{
"expression": "one >= two",
"result": false
},
{
"expression": "one != two",
"result": true
},
{
"expression": "one < two && three > one",
"result": true
},
{
"expression": "one < two || three > one",
"result": true
},
{
"expression": "one < two || three < one",
"result": true
},
{
"expression": "two < one || three < one",
"result": false
}
]
}
]

View File

@@ -0,0 +1,25 @@
[
{
"given": {
"foo": [{"name": "a"}, {"name": "b"}],
"bar": {"baz": "qux"}
},
"cases": [
{
"expression": "@",
"result": {
"foo": [{"name": "a"}, {"name": "b"}],
"bar": {"baz": "qux"}
}
},
{
"expression": "@.bar",
"result": {"baz": "qux"}
},
{
"expression": "@.foo[0]",
"result": {"name": "a"}
}
]
}
]

View File

@@ -0,0 +1,46 @@
[{
"given": {
"foo.bar": "dot",
"foo bar": "space",
"foo\nbar": "newline",
"foo\"bar": "doublequote",
"c:\\\\windows\\path": "windows",
"/unix/path": "unix",
"\"\"\"": "threequotes",
"bar": {"baz": "qux"}
},
"cases": [
{
"expression": "\"foo.bar\"",
"result": "dot"
},
{
"expression": "\"foo bar\"",
"result": "space"
},
{
"expression": "\"foo\\nbar\"",
"result": "newline"
},
{
"expression": "\"foo\\\"bar\"",
"result": "doublequote"
},
{
"expression": "\"c:\\\\\\\\windows\\\\path\"",
"result": "windows"
},
{
"expression": "\"/unix/path\"",
"result": "unix"
},
{
"expression": "\"\\\"\\\"\\\"\"",
"result": "threequotes"
},
{
"expression": "\"bar\".\"baz\"",
"result": "qux"
}
]
}]

View File

@@ -0,0 +1,468 @@
[
{
"given": {"foo": [{"name": "a"}, {"name": "b"}]},
"cases": [
{
"comment": "Matching a literal",
"expression": "foo[?name == 'a']",
"result": [{"name": "a"}]
}
]
},
{
"given": {"foo": [0, 1], "bar": [2, 3]},
"cases": [
{
"comment": "Matching a literal",
"expression": "*[?[0] == `0`]",
"result": [[], []]
}
]
},
{
"given": {"foo": [{"first": "foo", "last": "bar"},
{"first": "foo", "last": "foo"},
{"first": "foo", "last": "baz"}]},
"cases": [
{
"comment": "Matching an expression",
"expression": "foo[?first == last]",
"result": [{"first": "foo", "last": "foo"}]
},
{
"comment": "Verify projection created from filter",
"expression": "foo[?first == last].first",
"result": ["foo"]
}
]
},
{
"given": {"foo": [{"age": 20},
{"age": 25},
{"age": 30}]},
"cases": [
{
"comment": "Greater than with a number",
"expression": "foo[?age > `25`]",
"result": [{"age": 30}]
},
{
"expression": "foo[?age >= `25`]",
"result": [{"age": 25}, {"age": 30}]
},
{
"comment": "Greater than with a number",
"expression": "foo[?age > `30`]",
"result": []
},
{
"comment": "Greater than with a number",
"expression": "foo[?age < `25`]",
"result": [{"age": 20}]
},
{
"comment": "Greater than with a number",
"expression": "foo[?age <= `25`]",
"result": [{"age": 20}, {"age": 25}]
},
{
"comment": "Greater than with a number",
"expression": "foo[?age < `20`]",
"result": []
},
{
"expression": "foo[?age == `20`]",
"result": [{"age": 20}]
},
{
"expression": "foo[?age != `20`]",
"result": [{"age": 25}, {"age": 30}]
}
]
},
{
"given": {"foo": [{"top": {"name": "a"}},
{"top": {"name": "b"}}]},
"cases": [
{
"comment": "Filter with subexpression",
"expression": "foo[?top.name == 'a']",
"result": [{"top": {"name": "a"}}]
}
]
},
{
"given": {"foo": [{"top": {"first": "foo", "last": "bar"}},
{"top": {"first": "foo", "last": "foo"}},
{"top": {"first": "foo", "last": "baz"}}]},
"cases": [
{
"comment": "Matching an expression",
"expression": "foo[?top.first == top.last]",
"result": [{"top": {"first": "foo", "last": "foo"}}]
},
{
"comment": "Matching a JSON array",
"expression": "foo[?top == `{\"first\": \"foo\", \"last\": \"bar\"}`]",
"result": [{"top": {"first": "foo", "last": "bar"}}]
}
]
},
{
"given": {"foo": [
{"key": true},
{"key": false},
{"key": 0},
{"key": 1},
{"key": [0]},
{"key": {"bar": [0]}},
{"key": null},
{"key": [1]},
{"key": {"a":2}}
]},
"cases": [
{
"expression": "foo[?key == `true`]",
"result": [{"key": true}]
},
{
"expression": "foo[?key == `false`]",
"result": [{"key": false}]
},
{
"expression": "foo[?key == `0`]",
"result": [{"key": 0}]
},
{
"expression": "foo[?key == `1`]",
"result": [{"key": 1}]
},
{
"expression": "foo[?key == `[0]`]",
"result": [{"key": [0]}]
},
{
"expression": "foo[?key == `{\"bar\": [0]}`]",
"result": [{"key": {"bar": [0]}}]
},
{
"expression": "foo[?key == `null`]",
"result": [{"key": null}]
},
{
"expression": "foo[?key == `[1]`]",
"result": [{"key": [1]}]
},
{
"expression": "foo[?key == `{\"a\":2}`]",
"result": [{"key": {"a":2}}]
},
{
"expression": "foo[?`true` == key]",
"result": [{"key": true}]
},
{
"expression": "foo[?`false` == key]",
"result": [{"key": false}]
},
{
"expression": "foo[?`0` == key]",
"result": [{"key": 0}]
},
{
"expression": "foo[?`1` == key]",
"result": [{"key": 1}]
},
{
"expression": "foo[?`[0]` == key]",
"result": [{"key": [0]}]
},
{
"expression": "foo[?`{\"bar\": [0]}` == key]",
"result": [{"key": {"bar": [0]}}]
},
{
"expression": "foo[?`null` == key]",
"result": [{"key": null}]
},
{
"expression": "foo[?`[1]` == key]",
"result": [{"key": [1]}]
},
{
"expression": "foo[?`{\"a\":2}` == key]",
"result": [{"key": {"a":2}}]
},
{
"expression": "foo[?key != `true`]",
"result": [{"key": false}, {"key": 0}, {"key": 1}, {"key": [0]},
{"key": {"bar": [0]}}, {"key": null}, {"key": [1]}, {"key": {"a":2}}]
},
{
"expression": "foo[?key != `false`]",
"result": [{"key": true}, {"key": 0}, {"key": 1}, {"key": [0]},
{"key": {"bar": [0]}}, {"key": null}, {"key": [1]}, {"key": {"a":2}}]
},
{
"expression": "foo[?key != `0`]",
"result": [{"key": true}, {"key": false}, {"key": 1}, {"key": [0]},
{"key": {"bar": [0]}}, {"key": null}, {"key": [1]}, {"key": {"a":2}}]
},
{
"expression": "foo[?key != `1`]",
"result": [{"key": true}, {"key": false}, {"key": 0}, {"key": [0]},
{"key": {"bar": [0]}}, {"key": null}, {"key": [1]}, {"key": {"a":2}}]
},
{
"expression": "foo[?key != `null`]",
"result": [{"key": true}, {"key": false}, {"key": 0}, {"key": 1}, {"key": [0]},
{"key": {"bar": [0]}}, {"key": [1]}, {"key": {"a":2}}]
},
{
"expression": "foo[?key != `[1]`]",
"result": [{"key": true}, {"key": false}, {"key": 0}, {"key": 1}, {"key": [0]},
{"key": {"bar": [0]}}, {"key": null}, {"key": {"a":2}}]
},
{
"expression": "foo[?key != `{\"a\":2}`]",
"result": [{"key": true}, {"key": false}, {"key": 0}, {"key": 1}, {"key": [0]},
{"key": {"bar": [0]}}, {"key": null}, {"key": [1]}]
},
{
"expression": "foo[?`true` != key]",
"result": [{"key": false}, {"key": 0}, {"key": 1}, {"key": [0]},
{"key": {"bar": [0]}}, {"key": null}, {"key": [1]}, {"key": {"a":2}}]
},
{
"expression": "foo[?`false` != key]",
"result": [{"key": true}, {"key": 0}, {"key": 1}, {"key": [0]},
{"key": {"bar": [0]}}, {"key": null}, {"key": [1]}, {"key": {"a":2}}]
},
{
"expression": "foo[?`0` != key]",
"result": [{"key": true}, {"key": false}, {"key": 1}, {"key": [0]},
{"key": {"bar": [0]}}, {"key": null}, {"key": [1]}, {"key": {"a":2}}]
},
{
"expression": "foo[?`1` != key]",
"result": [{"key": true}, {"key": false}, {"key": 0}, {"key": [0]},
{"key": {"bar": [0]}}, {"key": null}, {"key": [1]}, {"key": {"a":2}}]
},
{
"expression": "foo[?`null` != key]",
"result": [{"key": true}, {"key": false}, {"key": 0}, {"key": 1}, {"key": [0]},
{"key": {"bar": [0]}}, {"key": [1]}, {"key": {"a":2}}]
},
{
"expression": "foo[?`[1]` != key]",
"result": [{"key": true}, {"key": false}, {"key": 0}, {"key": 1}, {"key": [0]},
{"key": {"bar": [0]}}, {"key": null}, {"key": {"a":2}}]
},
{
"expression": "foo[?`{\"a\":2}` != key]",
"result": [{"key": true}, {"key": false}, {"key": 0}, {"key": 1}, {"key": [0]},
{"key": {"bar": [0]}}, {"key": null}, {"key": [1]}]
}
]
},
{
"given": {"reservations": [
{"instances": [
{"foo": 1, "bar": 2}, {"foo": 1, "bar": 3},
{"foo": 1, "bar": 2}, {"foo": 2, "bar": 1}]}]},
"cases": [
{
"expression": "reservations[].instances[?bar==`1`]",
"result": [[{"foo": 2, "bar": 1}]]
},
{
"expression": "reservations[*].instances[?bar==`1`]",
"result": [[{"foo": 2, "bar": 1}]]
},
{
"expression": "reservations[].instances[?bar==`1`][]",
"result": [{"foo": 2, "bar": 1}]
}
]
},
{
"given": {
"baz": "other",
"foo": [
{"bar": 1}, {"bar": 2}, {"bar": 3}, {"bar": 4}, {"bar": 1, "baz": 2}
]
},
"cases": [
{
"expression": "foo[?bar==`1`].bar[0]",
"result": []
}
]
},
{
"given": {
"foo": [
{"a": 1, "b": {"c": "x"}},
{"a": 1, "b": {"c": "y"}},
{"a": 1, "b": {"c": "z"}},
{"a": 2, "b": {"c": "z"}},
{"a": 1, "baz": 2}
]
},
"cases": [
{
"expression": "foo[?a==`1`].b.c",
"result": ["x", "y", "z"]
}
]
},
{
"given": {"foo": [{"name": "a"}, {"name": "b"}, {"name": "c"}]},
"cases": [
{
"comment": "Filter with or expression",
"expression": "foo[?name == 'a' || name == 'b']",
"result": [{"name": "a"}, {"name": "b"}]
},
{
"expression": "foo[?name == 'a' || name == 'e']",
"result": [{"name": "a"}]
},
{
"expression": "foo[?name == 'a' || name == 'b' || name == 'c']",
"result": [{"name": "a"}, {"name": "b"}, {"name": "c"}]
}
]
},
{
"given": {"foo": [{"a": 1, "b": 2}, {"a": 1, "b": 3}]},
"cases": [
{
"comment": "Filter with and expression",
"expression": "foo[?a == `1` && b == `2`]",
"result": [{"a": 1, "b": 2}]
},
{
"expression": "foo[?a == `1` && b == `4`]",
"result": []
}
]
},
{
"given": {"foo": [{"a": 1, "b": 2, "c": 3}, {"a": 3, "b": 4}]},
"cases": [
{
"comment": "Filter with Or and And expressions",
"expression": "foo[?c == `3` || a == `1` && b == `4`]",
"result": [{"a": 1, "b": 2, "c": 3}]
},
{
"expression": "foo[?b == `2` || a == `3` && b == `4`]",
"result": [{"a": 1, "b": 2, "c": 3}, {"a": 3, "b": 4}]
},
{
"expression": "foo[?a == `3` && b == `4` || b == `2`]",
"result": [{"a": 1, "b": 2, "c": 3}, {"a": 3, "b": 4}]
},
{
"expression": "foo[?(a == `3` && b == `4`) || b == `2`]",
"result": [{"a": 1, "b": 2, "c": 3}, {"a": 3, "b": 4}]
},
{
"expression": "foo[?((a == `3` && b == `4`)) || b == `2`]",
"result": [{"a": 1, "b": 2, "c": 3}, {"a": 3, "b": 4}]
},
{
"expression": "foo[?a == `3` && (b == `4` || b == `2`)]",
"result": [{"a": 3, "b": 4}]
},
{
"expression": "foo[?a == `3` && ((b == `4` || b == `2`))]",
"result": [{"a": 3, "b": 4}]
}
]
},
{
"given": {"foo": [{"a": 1, "b": 2, "c": 3}, {"a": 3, "b": 4}]},
"cases": [
{
"comment": "Verify precedence of or/and expressions",
"expression": "foo[?a == `1` || b ==`2` && c == `5`]",
"result": [{"a": 1, "b": 2, "c": 3}]
},
{
"comment": "Parentheses can alter precedence",
"expression": "foo[?(a == `1` || b ==`2`) && c == `5`]",
"result": []
},
{
"comment": "Not expressions combined with and/or",
"expression": "foo[?!(a == `1` || b ==`2`)]",
"result": [{"a": 3, "b": 4}]
}
]
},
{
"given": {
"foo": [
{"key": true},
{"key": false},
{"key": []},
{"key": {}},
{"key": [0]},
{"key": {"a": "b"}},
{"key": 0},
{"key": 1},
{"key": null},
{"notkey": true}
]
},
"cases": [
{
"comment": "Unary filter expression",
"expression": "foo[?key]",
"result": [
{"key": true}, {"key": [0]}, {"key": {"a": "b"}},
{"key": 0}, {"key": 1}
]
},
{
"comment": "Unary not filter expression",
"expression": "foo[?!key]",
"result": [
{"key": false}, {"key": []}, {"key": {}},
{"key": null}, {"notkey": true}
]
},
{
"comment": "Equality with null RHS",
"expression": "foo[?key == `null`]",
"result": [
{"key": null}, {"notkey": true}
]
}
]
},
{
"given": {
"foo": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
},
"cases": [
{
"comment": "Using @ in a filter expression",
"expression": "foo[?@ < `5`]",
"result": [0, 1, 2, 3, 4]
},
{
"comment": "Using @ in a filter expression",
"expression": "foo[?`5` > @]",
"result": [0, 1, 2, 3, 4]
},
{
"comment": "Using @ in a filter expression",
"expression": "foo[?@ == @]",
"result": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
}
]
}
]

View File

@@ -0,0 +1,825 @@
[{
"given":
{
"foo": -1,
"zero": 0,
"numbers": [-1, 3, 4, 5],
"array": [-1, 3, 4, 5, "a", "100"],
"strings": ["a", "b", "c"],
"decimals": [1.01, 1.2, -1.5],
"str": "Str",
"false": false,
"empty_list": [],
"empty_hash": {},
"objects": {"foo": "bar", "bar": "baz"},
"null_key": null
},
"cases": [
{
"expression": "abs(foo)",
"result": 1
},
{
"expression": "abs(foo)",
"result": 1
},
{
"expression": "abs(str)",
"error": "invalid-type"
},
{
"expression": "abs(array[1])",
"result": 3
},
{
"expression": "abs(array[1])",
"result": 3
},
{
"expression": "abs(`false`)",
"error": "invalid-type"
},
{
"expression": "abs(`-24`)",
"result": 24
},
{
"expression": "abs(`-24`)",
"result": 24
},
{
"expression": "abs(`1`, `2`)",
"error": "invalid-arity"
},
{
"expression": "abs()",
"error": "invalid-arity"
},
{
"expression": "unknown_function(`1`, `2`)",
"error": "unknown-function"
},
{
"expression": "avg(numbers)",
"result": 2.75
},
{
"expression": "avg(array)",
"error": "invalid-type"
},
{
"expression": "avg('abc')",
"error": "invalid-type"
},
{
"expression": "avg(foo)",
"error": "invalid-type"
},
{
"expression": "avg(@)",
"error": "invalid-type"
},
{
"expression": "avg(strings)",
"error": "invalid-type"
},
{
"expression": "ceil(`1.2`)",
"result": 2
},
{
"expression": "ceil(decimals[0])",
"result": 2
},
{
"expression": "ceil(decimals[1])",
"result": 2
},
{
"expression": "ceil(decimals[2])",
"result": -1
},
{
"expression": "ceil('string')",
"error": "invalid-type"
},
{
"expression": "contains('abc', 'a')",
"result": true
},
{
"expression": "contains('abc', 'd')",
"result": false
},
{
"expression": "contains(`false`, 'd')",
"error": "invalid-type"
},
{
"expression": "contains(strings, 'a')",
"result": true
},
{
"expression": "contains(decimals, `1.2`)",
"result": true
},
{
"expression": "contains(decimals, `false`)",
"result": false
},
{
"expression": "ends_with(str, 'r')",
"result": true
},
{
"expression": "ends_with(str, 'tr')",
"result": true
},
{
"expression": "ends_with(str, 'Str')",
"result": true
},
{
"expression": "ends_with(str, 'SStr')",
"result": false
},
{
"expression": "ends_with(str, 'foo')",
"result": false
},
{
"expression": "ends_with(str, `0`)",
"error": "invalid-type"
},
{
"expression": "floor(`1.2`)",
"result": 1
},
{
"expression": "floor('string')",
"error": "invalid-type"
},
{
"expression": "floor(decimals[0])",
"result": 1
},
{
"expression": "floor(foo)",
"result": -1
},
{
"expression": "floor(str)",
"error": "invalid-type"
},
{
"expression": "length('abc')",
"result": 3
},
{
"expression": "length('✓foo')",
"result": 4
},
{
"expression": "length('')",
"result": 0
},
{
"expression": "length(@)",
"result": 12
},
{
"expression": "length(strings[0])",
"result": 1
},
{
"expression": "length(str)",
"result": 3
},
{
"expression": "length(array)",
"result": 6
},
{
"expression": "length(objects)",
"result": 2
},
{
"expression": "length(`false`)",
"error": "invalid-type"
},
{
"expression": "length(foo)",
"error": "invalid-type"
},
{
"expression": "length(strings[0])",
"result": 1
},
{
"expression": "max(numbers)",
"result": 5
},
{
"expression": "max(decimals)",
"result": 1.2
},
{
"expression": "max(strings)",
"result": "c"
},
{
"expression": "max(abc)",
"error": "invalid-type"
},
{
"expression": "max(array)",
"error": "invalid-type"
},
{
"expression": "max(decimals)",
"result": 1.2
},
{
"expression": "max(empty_list)",
"result": null
},
{
"expression": "merge(`{}`)",
"result": {}
},
{
"expression": "merge(`{}`, `{}`)",
"result": {}
},
{
"expression": "merge(`{\"a\": 1}`, `{\"b\": 2}`)",
"result": {"a": 1, "b": 2}
},
{
"expression": "merge(`{\"a\": 1}`, `{\"a\": 2}`)",
"result": {"a": 2}
},
{
"expression": "merge(`{\"a\": 1, \"b\": 2}`, `{\"a\": 2, \"c\": 3}`, `{\"d\": 4}`)",
"result": {"a": 2, "b": 2, "c": 3, "d": 4}
},
{
"expression": "min(numbers)",
"result": -1
},
{
"expression": "min(decimals)",
"result": -1.5
},
{
"expression": "min(abc)",
"error": "invalid-type"
},
{
"expression": "min(array)",
"error": "invalid-type"
},
{
"expression": "min(empty_list)",
"result": null
},
{
"expression": "min(decimals)",
"result": -1.5
},
{
"expression": "min(strings)",
"result": "a"
},
{
"expression": "type('abc')",
"result": "string"
},
{
"expression": "type(`1.0`)",
"result": "number"
},
{
"expression": "type(`2`)",
"result": "number"
},
{
"expression": "type(`true`)",
"result": "boolean"
},
{
"expression": "type(`false`)",
"result": "boolean"
},
{
"expression": "type(`null`)",
"result": "null"
},
{
"expression": "type(`[0]`)",
"result": "array"
},
{
"expression": "type(`{\"a\": \"b\"}`)",
"result": "object"
},
{
"expression": "type(@)",
"result": "object"
},
{
"expression": "sort(keys(objects))",
"result": ["bar", "foo"]
},
{
"expression": "keys(foo)",
"error": "invalid-type"
},
{
"expression": "keys(strings)",
"error": "invalid-type"
},
{
"expression": "keys(`false`)",
"error": "invalid-type"
},
{
"expression": "sort(values(objects))",
"result": ["bar", "baz"]
},
{
"expression": "keys(empty_hash)",
"result": []
},
{
"expression": "values(foo)",
"error": "invalid-type"
},
{
"expression": "join(', ', strings)",
"result": "a, b, c"
},
{
"expression": "join(', ', strings)",
"result": "a, b, c"
},
{
"expression": "join(',', `[\"a\", \"b\"]`)",
"result": "a,b"
},
{
"expression": "join(',', `[\"a\", 0]`)",
"error": "invalid-type"
},
{
"expression": "join(', ', str)",
"error": "invalid-type"
},
{
"expression": "join('|', strings)",
"result": "a|b|c"
},
{
"expression": "join(`2`, strings)",
"error": "invalid-type"
},
{
"expression": "join('|', decimals)",
"error": "invalid-type"
},
{
"expression": "join('|', decimals[].to_string(@))",
"result": "1.01|1.2|-1.5"
},
{
"expression": "join('|', empty_list)",
"result": ""
},
{
"expression": "reverse(numbers)",
"result": [5, 4, 3, -1]
},
{
"expression": "reverse(array)",
"result": ["100", "a", 5, 4, 3, -1]
},
{
"expression": "reverse(`[]`)",
"result": []
},
{
"expression": "reverse('')",
"result": ""
},
{
"expression": "reverse('hello world')",
"result": "dlrow olleh"
},
{
"expression": "starts_with(str, 'S')",
"result": true
},
{
"expression": "starts_with(str, 'St')",
"result": true
},
{
"expression": "starts_with(str, 'Str')",
"result": true
},
{
"expression": "starts_with(str, 'String')",
"result": false
},
{
"expression": "starts_with(str, `0`)",
"error": "invalid-type"
},
{
"expression": "sum(numbers)",
"result": 11
},
{
"expression": "sum(decimals)",
"result": 0.71
},
{
"expression": "sum(array)",
"error": "invalid-type"
},
{
"expression": "sum(array[].to_number(@))",
"result": 111
},
{
"expression": "sum(`[]`)",
"result": 0
},
{
"expression": "to_array('foo')",
"result": ["foo"]
},
{
"expression": "to_array(`0`)",
"result": [0]
},
{
"expression": "to_array(objects)",
"result": [{"foo": "bar", "bar": "baz"}]
},
{
"expression": "to_array(`[1, 2, 3]`)",
"result": [1, 2, 3]
},
{
"expression": "to_array(false)",
"result": [false]
},
{
"expression": "to_string('foo')",
"result": "foo"
},
{
"expression": "to_string(`1.2`)",
"result": "1.2"
},
{
"expression": "to_string(`[0, 1]`)",
"result": "[0,1]"
},
{
"expression": "to_number('1.0')",
"result": 1.0
},
{
"expression": "to_number('1.1')",
"result": 1.1
},
{
"expression": "to_number('4')",
"result": 4
},
{
"expression": "to_number('notanumber')",
"result": null
},
{
"expression": "to_number(`false`)",
"result": null
},
{
"expression": "to_number(`null`)",
"result": null
},
{
"expression": "to_number(`[0]`)",
"result": null
},
{
"expression": "to_number(`{\"foo\": 0}`)",
"result": null
},
{
"expression": "\"to_string\"(`1.0`)",
"error": "syntax"
},
{
"expression": "sort(numbers)",
"result": [-1, 3, 4, 5]
},
{
"expression": "sort(strings)",
"result": ["a", "b", "c"]
},
{
"expression": "sort(decimals)",
"result": [-1.5, 1.01, 1.2]
},
{
"expression": "sort(array)",
"error": "invalid-type"
},
{
"expression": "sort(abc)",
"error": "invalid-type"
},
{
"expression": "sort(empty_list)",
"result": []
},
{
"expression": "sort(@)",
"error": "invalid-type"
},
{
"expression": "not_null(unknown_key, str)",
"result": "Str"
},
{
"expression": "not_null(unknown_key, foo.bar, empty_list, str)",
"result": []
},
{
"expression": "not_null(unknown_key, null_key, empty_list, str)",
"result": []
},
{
"expression": "not_null(all, expressions, are_null)",
"result": null
},
{
"expression": "not_null()",
"error": "invalid-arity"
},
{
"description": "function projection on single arg function",
"expression": "numbers[].to_string(@)",
"result": ["-1", "3", "4", "5"]
},
{
"description": "function projection on single arg function",
"expression": "array[].to_number(@)",
"result": [-1, 3, 4, 5, 100]
}
]
}, {
"given":
{
"foo": [
{"b": "b", "a": "a"},
{"c": "c", "b": "b"},
{"d": "d", "c": "c"},
{"e": "e", "d": "d"},
{"f": "f", "e": "e"}
]
},
"cases": [
{
"description": "function projection on variadic function",
"expression": "foo[].not_null(f, e, d, c, b, a)",
"result": ["b", "c", "d", "e", "f"]
}
]
}, {
"given":
{
"people": [
{"age": 20, "age_str": "20", "bool": true, "name": "a", "extra": "foo"},
{"age": 40, "age_str": "40", "bool": false, "name": "b", "extra": "bar"},
{"age": 30, "age_str": "30", "bool": true, "name": "c"},
{"age": 50, "age_str": "50", "bool": false, "name": "d"},
{"age": 10, "age_str": "10", "bool": true, "name": 3}
]
},
"cases": [
{
"description": "sort by field expression",
"expression": "sort_by(people, &age)",
"result": [
{"age": 10, "age_str": "10", "bool": true, "name": 3},
{"age": 20, "age_str": "20", "bool": true, "name": "a", "extra": "foo"},
{"age": 30, "age_str": "30", "bool": true, "name": "c"},
{"age": 40, "age_str": "40", "bool": false, "name": "b", "extra": "bar"},
{"age": 50, "age_str": "50", "bool": false, "name": "d"}
]
},
{
"expression": "sort_by(people, &age_str)",
"result": [
{"age": 10, "age_str": "10", "bool": true, "name": 3},
{"age": 20, "age_str": "20", "bool": true, "name": "a", "extra": "foo"},
{"age": 30, "age_str": "30", "bool": true, "name": "c"},
{"age": 40, "age_str": "40", "bool": false, "name": "b", "extra": "bar"},
{"age": 50, "age_str": "50", "bool": false, "name": "d"}
]
},
{
"description": "sort by function expression",
"expression": "sort_by(people, &to_number(age_str))",
"result": [
{"age": 10, "age_str": "10", "bool": true, "name": 3},
{"age": 20, "age_str": "20", "bool": true, "name": "a", "extra": "foo"},
{"age": 30, "age_str": "30", "bool": true, "name": "c"},
{"age": 40, "age_str": "40", "bool": false, "name": "b", "extra": "bar"},
{"age": 50, "age_str": "50", "bool": false, "name": "d"}
]
},
{
"description": "function projection on sort_by function",
"expression": "sort_by(people, &age)[].name",
"result": [3, "a", "c", "b", "d"]
},
{
"expression": "sort_by(people, &extra)",
"error": "invalid-type"
},
{
"expression": "sort_by(people, &bool)",
"error": "invalid-type"
},
{
"expression": "sort_by(people, &name)",
"error": "invalid-type"
},
{
"expression": "sort_by(people, name)",
"error": "invalid-type"
},
{
"expression": "sort_by(people, &age)[].extra",
"result": ["foo", "bar"]
},
{
"expression": "sort_by(`[]`, &age)",
"result": []
},
{
"expression": "max_by(people, &age)",
"result": {"age": 50, "age_str": "50", "bool": false, "name": "d"}
},
{
"expression": "max_by(people, &age_str)",
"result": {"age": 50, "age_str": "50", "bool": false, "name": "d"}
},
{
"expression": "max_by(people, &bool)",
"error": "invalid-type"
},
{
"expression": "max_by(people, &extra)",
"error": "invalid-type"
},
{
"expression": "max_by(people, &to_number(age_str))",
"result": {"age": 50, "age_str": "50", "bool": false, "name": "d"}
},
{
"expression": "min_by(people, &age)",
"result": {"age": 10, "age_str": "10", "bool": true, "name": 3}
},
{
"expression": "min_by(people, &age_str)",
"result": {"age": 10, "age_str": "10", "bool": true, "name": 3}
},
{
"expression": "min_by(people, &bool)",
"error": "invalid-type"
},
{
"expression": "min_by(people, &extra)",
"error": "invalid-type"
},
{
"expression": "min_by(people, &to_number(age_str))",
"result": {"age": 10, "age_str": "10", "bool": true, "name": 3}
}
]
}, {
"given":
{
"people": [
{"age": 10, "order": "1"},
{"age": 10, "order": "2"},
{"age": 10, "order": "3"},
{"age": 10, "order": "4"},
{"age": 10, "order": "5"},
{"age": 10, "order": "6"},
{"age": 10, "order": "7"},
{"age": 10, "order": "8"},
{"age": 10, "order": "9"},
{"age": 10, "order": "10"},
{"age": 10, "order": "11"}
]
},
"cases": [
{
"description": "stable sort order",
"expression": "sort_by(people, &age)",
"result": [
{"age": 10, "order": "1"},
{"age": 10, "order": "2"},
{"age": 10, "order": "3"},
{"age": 10, "order": "4"},
{"age": 10, "order": "5"},
{"age": 10, "order": "6"},
{"age": 10, "order": "7"},
{"age": 10, "order": "8"},
{"age": 10, "order": "9"},
{"age": 10, "order": "10"},
{"age": 10, "order": "11"}
]
}
]
}, {
"given":
{
"people": [
{"a": 10, "b": 1, "c": "z"},
{"a": 10, "b": 2, "c": null},
{"a": 10, "b": 3},
{"a": 10, "b": 4, "c": "z"},
{"a": 10, "b": 5, "c": null},
{"a": 10, "b": 6},
{"a": 10, "b": 7, "c": "z"},
{"a": 10, "b": 8, "c": null},
{"a": 10, "b": 9}
],
"empty": []
},
"cases": [
{
"expression": "map(&a, people)",
"result": [10, 10, 10, 10, 10, 10, 10, 10, 10]
},
{
"expression": "map(&c, people)",
"result": ["z", null, null, "z", null, null, "z", null, null]
},
{
"expression": "map(&a, badkey)",
"error": "invalid-type"
},
{
"expression": "map(&foo, empty)",
"result": []
}
]
}, {
"given": {
"array": [
{
"foo": {"bar": "yes1"}
},
{
"foo": {"bar": "yes2"}
},
{
"foo1": {"bar": "no"}
}
]},
"cases": [
{
"expression": "map(&foo.bar, array)",
"result": ["yes1", "yes2", null]
},
{
"expression": "map(&foo1.bar, array)",
"result": [null, null, "no"]
},
{
"expression": "map(&foo.bar.baz, array)",
"result": [null, null, null]
}
]
}, {
"given": {
"array": [[1, 2, 3, [4]], [5, 6, 7, [8, 9]]]
},
"cases": [
{
"expression": "map(&[], array)",
"result": [[1, 2, 3, 4], [5, 6, 7, 8, 9]]
}
]
}
]

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,346 @@
[{
"given":
{"foo": {"bar": ["zero", "one", "two"]}},
"cases": [
{
"expression": "foo.bar[0]",
"result": "zero"
},
{
"expression": "foo.bar[1]",
"result": "one"
},
{
"expression": "foo.bar[2]",
"result": "two"
},
{
"expression": "foo.bar[3]",
"result": null
},
{
"expression": "foo.bar[-1]",
"result": "two"
},
{
"expression": "foo.bar[-2]",
"result": "one"
},
{
"expression": "foo.bar[-3]",
"result": "zero"
},
{
"expression": "foo.bar[-4]",
"result": null
}
]
},
{
"given":
{"foo": [{"bar": "one"}, {"bar": "two"}, {"bar": "three"}, {"notbar": "four"}]},
"cases": [
{
"expression": "foo.bar",
"result": null
},
{
"expression": "foo[0].bar",
"result": "one"
},
{
"expression": "foo[1].bar",
"result": "two"
},
{
"expression": "foo[2].bar",
"result": "three"
},
{
"expression": "foo[3].notbar",
"result": "four"
},
{
"expression": "foo[3].bar",
"result": null
},
{
"expression": "foo[0]",
"result": {"bar": "one"}
},
{
"expression": "foo[1]",
"result": {"bar": "two"}
},
{
"expression": "foo[2]",
"result": {"bar": "three"}
},
{
"expression": "foo[3]",
"result": {"notbar": "four"}
},
{
"expression": "foo[4]",
"result": null
}
]
},
{
"given": [
"one", "two", "three"
],
"cases": [
{
"expression": "[0]",
"result": "one"
},
{
"expression": "[1]",
"result": "two"
},
{
"expression": "[2]",
"result": "three"
},
{
"expression": "[-1]",
"result": "three"
},
{
"expression": "[-2]",
"result": "two"
},
{
"expression": "[-3]",
"result": "one"
}
]
},
{
"given": {"reservations": [
{"instances": [{"foo": 1}, {"foo": 2}]}
]},
"cases": [
{
"expression": "reservations[].instances[].foo",
"result": [1, 2]
},
{
"expression": "reservations[].instances[].bar",
"result": []
},
{
"expression": "reservations[].notinstances[].foo",
"result": []
},
{
"expression": "reservations[].notinstances[].foo",
"result": []
}
]
},
{
"given": {"reservations": [{
"instances": [
{"foo": [{"bar": 1}, {"bar": 2}, {"notbar": 3}, {"bar": 4}]},
{"foo": [{"bar": 5}, {"bar": 6}, {"notbar": [7]}, {"bar": 8}]},
{"foo": "bar"},
{"notfoo": [{"bar": 20}, {"bar": 21}, {"notbar": [7]}, {"bar": 22}]},
{"bar": [{"baz": [1]}, {"baz": [2]}, {"baz": [3]}, {"baz": [4]}]},
{"baz": [{"baz": [1, 2]}, {"baz": []}, {"baz": []}, {"baz": [3, 4]}]},
{"qux": [{"baz": []}, {"baz": [1, 2, 3]}, {"baz": [4]}, {"baz": []}]}
],
"otherkey": {"foo": [{"bar": 1}, {"bar": 2}, {"notbar": 3}, {"bar": 4}]}
}, {
"instances": [
{"a": [{"bar": 1}, {"bar": 2}, {"notbar": 3}, {"bar": 4}]},
{"b": [{"bar": 5}, {"bar": 6}, {"notbar": [7]}, {"bar": 8}]},
{"c": "bar"},
{"notfoo": [{"bar": 23}, {"bar": 24}, {"notbar": [7]}, {"bar": 25}]},
{"qux": [{"baz": []}, {"baz": [1, 2, 3]}, {"baz": [4]}, {"baz": []}]}
],
"otherkey": {"foo": [{"bar": 1}, {"bar": 2}, {"notbar": 3}, {"bar": 4}]}
}
]},
"cases": [
{
"expression": "reservations[].instances[].foo[].bar",
"result": [1, 2, 4, 5, 6, 8]
},
{
"expression": "reservations[].instances[].foo[].baz",
"result": []
},
{
"expression": "reservations[].instances[].notfoo[].bar",
"result": [20, 21, 22, 23, 24, 25]
},
{
"expression": "reservations[].instances[].notfoo[].notbar",
"result": [[7], [7]]
},
{
"expression": "reservations[].notinstances[].foo",
"result": []
},
{
"expression": "reservations[].instances[].foo[].notbar",
"result": [3, [7]]
},
{
"expression": "reservations[].instances[].bar[].baz",
"result": [[1], [2], [3], [4]]
},
{
"expression": "reservations[].instances[].baz[].baz",
"result": [[1, 2], [], [], [3, 4]]
},
{
"expression": "reservations[].instances[].qux[].baz",
"result": [[], [1, 2, 3], [4], [], [], [1, 2, 3], [4], []]
},
{
"expression": "reservations[].instances[].qux[].baz[]",
"result": [1, 2, 3, 4, 1, 2, 3, 4]
}
]
},
{
"given": {
"foo": [
[["one", "two"], ["three", "four"]],
[["five", "six"], ["seven", "eight"]],
[["nine"], ["ten"]]
]
},
"cases": [
{
"expression": "foo[]",
"result": [["one", "two"], ["three", "four"], ["five", "six"],
["seven", "eight"], ["nine"], ["ten"]]
},
{
"expression": "foo[][0]",
"result": ["one", "three", "five", "seven", "nine", "ten"]
},
{
"expression": "foo[][1]",
"result": ["two", "four", "six", "eight"]
},
{
"expression": "foo[][0][0]",
"result": []
},
{
"expression": "foo[][2][2]",
"result": []
},
{
"expression": "foo[][0][0][100]",
"result": []
}
]
},
{
"given": {
"foo": [{
"bar": [
{
"qux": 2,
"baz": 1
},
{
"qux": 4,
"baz": 3
}
]
},
{
"bar": [
{
"qux": 6,
"baz": 5
},
{
"qux": 8,
"baz": 7
}
]
}
]
},
"cases": [
{
"expression": "foo",
"result": [{"bar": [{"qux": 2, "baz": 1}, {"qux": 4, "baz": 3}]},
{"bar": [{"qux": 6, "baz": 5}, {"qux": 8, "baz": 7}]}]
},
{
"expression": "foo[]",
"result": [{"bar": [{"qux": 2, "baz": 1}, {"qux": 4, "baz": 3}]},
{"bar": [{"qux": 6, "baz": 5}, {"qux": 8, "baz": 7}]}]
},
{
"expression": "foo[].bar",
"result": [[{"qux": 2, "baz": 1}, {"qux": 4, "baz": 3}],
[{"qux": 6, "baz": 5}, {"qux": 8, "baz": 7}]]
},
{
"expression": "foo[].bar[]",
"result": [{"qux": 2, "baz": 1}, {"qux": 4, "baz": 3},
{"qux": 6, "baz": 5}, {"qux": 8, "baz": 7}]
},
{
"expression": "foo[].bar[].baz",
"result": [1, 3, 5, 7]
}
]
},
{
"given": {
"string": "string",
"hash": {"foo": "bar", "bar": "baz"},
"number": 23,
"nullvalue": null
},
"cases": [
{
"expression": "string[]",
"result": null
},
{
"expression": "hash[]",
"result": null
},
{
"expression": "number[]",
"result": null
},
{
"expression": "nullvalue[]",
"result": null
},
{
"expression": "string[].foo",
"result": null
},
{
"expression": "hash[].foo",
"result": null
},
{
"expression": "number[].foo",
"result": null
},
{
"expression": "nullvalue[].foo",
"result": null
},
{
"expression": "nullvalue[].foo[].bar",
"result": null
}
]
}
]

View File

@@ -0,0 +1,190 @@
[
{
"given": {
"foo": [{"name": "a"}, {"name": "b"}],
"bar": {"baz": "qux"}
},
"cases": [
{
"expression": "`\"foo\"`",
"result": "foo"
},
{
"comment": "Interpret escaped unicode.",
"expression": "`\"\\u03a6\"`",
"result": "Φ"
},
{
"expression": "`\"✓\"`",
"result": "✓"
},
{
"expression": "`[1, 2, 3]`",
"result": [1, 2, 3]
},
{
"expression": "`{\"a\": \"b\"}`",
"result": {"a": "b"}
},
{
"expression": "`true`",
"result": true
},
{
"expression": "`false`",
"result": false
},
{
"expression": "`null`",
"result": null
},
{
"expression": "`0`",
"result": 0
},
{
"expression": "`1`",
"result": 1
},
{
"expression": "`2`",
"result": 2
},
{
"expression": "`3`",
"result": 3
},
{
"expression": "`4`",
"result": 4
},
{
"expression": "`5`",
"result": 5
},
{
"expression": "`6`",
"result": 6
},
{
"expression": "`7`",
"result": 7
},
{
"expression": "`8`",
"result": 8
},
{
"expression": "`9`",
"result": 9
},
{
"comment": "Escaping a backtick in quotes",
"expression": "`\"foo\\`bar\"`",
"result": "foo`bar"
},
{
"comment": "Double quote in literal",
"expression": "`\"foo\\\"bar\"`",
"result": "foo\"bar"
},
{
"expression": "`\"1\\`\"`",
"result": "1`"
},
{
"comment": "Multiple literal expressions with escapes",
"expression": "`\"\\\\\"`.{a:`\"b\"`}",
"result": {"a": "b"}
},
{
"comment": "literal . identifier",
"expression": "`{\"a\": \"b\"}`.a",
"result": "b"
},
{
"comment": "literal . identifier . identifier",
"expression": "`{\"a\": {\"b\": \"c\"}}`.a.b",
"result": "c"
},
{
"comment": "literal . identifier bracket-expr",
"expression": "`[0, 1, 2]`[1]",
"result": 1
}
]
},
{
"comment": "Literals",
"given": {"type": "object"},
"cases": [
{
"comment": "Literal with leading whitespace",
"expression": "` {\"foo\": true}`",
"result": {"foo": true}
},
{
"comment": "Literal with trailing whitespace",
"expression": "`{\"foo\": true} `",
"result": {"foo": true}
},
{
"comment": "Literal on RHS of subexpr not allowed",
"expression": "foo.`\"bar\"`",
"error": "syntax"
}
]
},
{
"comment": "Raw String Literals",
"given": {},
"cases": [
{
"expression": "'foo'",
"result": "foo"
},
{
"expression": "' foo '",
"result": " foo "
},
{
"expression": "'0'",
"result": "0"
},
{
"expression": "'newline\n'",
"result": "newline\n"
},
{
"expression": "'\n'",
"result": "\n"
},
{
"expression": "'✓'",
"result": "✓"
},
{
"expression": "'𝄞'",
"result": "𝄞"
},
{
"expression": "' [foo] '",
"result": " [foo] "
},
{
"expression": "'[foo]'",
"result": "[foo]"
},
{
"comment": "Do not interpret escaped unicode.",
"expression": "'\\u03a6'",
"result": "\\u03a6"
},
{
"comment": "Can escape the single quote",
"expression": "'foo\\'bar'",
"result": "foo'bar"
}
]
}
]

View File

@@ -0,0 +1,393 @@
[{
"given": {
"foo": {
"bar": "bar",
"baz": "baz",
"qux": "qux",
"nested": {
"one": {
"a": "first",
"b": "second",
"c": "third"
},
"two": {
"a": "first",
"b": "second",
"c": "third"
},
"three": {
"a": "first",
"b": "second",
"c": {"inner": "third"}
}
}
},
"bar": 1,
"baz": 2,
"qux\"": 3
},
"cases": [
{
"expression": "foo.{bar: bar}",
"result": {"bar": "bar"}
},
{
"expression": "foo.{\"bar\": bar}",
"result": {"bar": "bar"}
},
{
"expression": "foo.{\"foo.bar\": bar}",
"result": {"foo.bar": "bar"}
},
{
"expression": "foo.{bar: bar, baz: baz}",
"result": {"bar": "bar", "baz": "baz"}
},
{
"expression": "foo.{\"bar\": bar, \"baz\": baz}",
"result": {"bar": "bar", "baz": "baz"}
},
{
"expression": "{\"baz\": baz, \"qux\\\"\": \"qux\\\"\"}",
"result": {"baz": 2, "qux\"": 3}
},
{
"expression": "foo.{bar:bar,baz:baz}",
"result": {"bar": "bar", "baz": "baz"}
},
{
"expression": "foo.{bar: bar,qux: qux}",
"result": {"bar": "bar", "qux": "qux"}
},
{
"expression": "foo.{bar: bar, noexist: noexist}",
"result": {"bar": "bar", "noexist": null}
},
{
"expression": "foo.{noexist: noexist, alsonoexist: alsonoexist}",
"result": {"noexist": null, "alsonoexist": null}
},
{
"expression": "foo.badkey.{nokey: nokey, alsonokey: alsonokey}",
"result": null
},
{
"expression": "foo.nested.*.{a: a,b: b}",
"result": [{"a": "first", "b": "second"},
{"a": "first", "b": "second"},
{"a": "first", "b": "second"}]
},
{
"expression": "foo.nested.three.{a: a, cinner: c.inner}",
"result": {"a": "first", "cinner": "third"}
},
{
"expression": "foo.nested.three.{a: a, c: c.inner.bad.key}",
"result": {"a": "first", "c": null}
},
{
"expression": "foo.{a: nested.one.a, b: nested.two.b}",
"result": {"a": "first", "b": "second"}
},
{
"expression": "{bar: bar, baz: baz}",
"result": {"bar": 1, "baz": 2}
},
{
"expression": "{bar: bar}",
"result": {"bar": 1}
},
{
"expression": "{otherkey: bar}",
"result": {"otherkey": 1}
},
{
"expression": "{no: no, exist: exist}",
"result": {"no": null, "exist": null}
},
{
"expression": "foo.[bar]",
"result": ["bar"]
},
{
"expression": "foo.[bar,baz]",
"result": ["bar", "baz"]
},
{
"expression": "foo.[bar,qux]",
"result": ["bar", "qux"]
},
{
"expression": "foo.[bar,noexist]",
"result": ["bar", null]
},
{
"expression": "foo.[noexist,alsonoexist]",
"result": [null, null]
}
]
}, {
"given": {
"foo": {"bar": 1, "baz": [2, 3, 4]}
},
"cases": [
{
"expression": "foo.{bar:bar,baz:baz}",
"result": {"bar": 1, "baz": [2, 3, 4]}
},
{
"expression": "foo.[bar,baz[0]]",
"result": [1, 2]
},
{
"expression": "foo.[bar,baz[1]]",
"result": [1, 3]
},
{
"expression": "foo.[bar,baz[2]]",
"result": [1, 4]
},
{
"expression": "foo.[bar,baz[3]]",
"result": [1, null]
},
{
"expression": "foo.[bar[0],baz[3]]",
"result": [null, null]
}
]
}, {
"given": {
"foo": {"bar": 1, "baz": 2}
},
"cases": [
{
"expression": "foo.{bar: bar, baz: baz}",
"result": {"bar": 1, "baz": 2}
},
{
"expression": "foo.[bar,baz]",
"result": [1, 2]
}
]
}, {
"given": {
"foo": {
"bar": {"baz": [{"common": "first", "one": 1},
{"common": "second", "two": 2}]},
"ignoreme": 1,
"includeme": true
}
},
"cases": [
{
"expression": "foo.{bar: bar.baz[1],includeme: includeme}",
"result": {"bar": {"common": "second", "two": 2}, "includeme": true}
},
{
"expression": "foo.{\"bar.baz.two\": bar.baz[1].two, includeme: includeme}",
"result": {"bar.baz.two": 2, "includeme": true}
},
{
"expression": "foo.[includeme, bar.baz[*].common]",
"result": [true, ["first", "second"]]
},
{
"expression": "foo.[includeme, bar.baz[*].none]",
"result": [true, []]
},
{
"expression": "foo.[includeme, bar.baz[].common]",
"result": [true, ["first", "second"]]
}
]
}, {
"given": {
"reservations": [{
"instances": [
{"id": "id1",
"name": "first"},
{"id": "id2",
"name": "second"}
]}, {
"instances": [
{"id": "id3",
"name": "third"},
{"id": "id4",
"name": "fourth"}
]}
]},
"cases": [
{
"expression": "reservations[*].instances[*].{id: id, name: name}",
"result": [[{"id": "id1", "name": "first"}, {"id": "id2", "name": "second"}],
[{"id": "id3", "name": "third"}, {"id": "id4", "name": "fourth"}]]
},
{
"expression": "reservations[].instances[].{id: id, name: name}",
"result": [{"id": "id1", "name": "first"},
{"id": "id2", "name": "second"},
{"id": "id3", "name": "third"},
{"id": "id4", "name": "fourth"}]
},
{
"expression": "reservations[].instances[].[id, name]",
"result": [["id1", "first"],
["id2", "second"],
["id3", "third"],
["id4", "fourth"]]
}
]
},
{
"given": {
"foo": [{
"bar": [
{
"qux": 2,
"baz": 1
},
{
"qux": 4,
"baz": 3
}
]
},
{
"bar": [
{
"qux": 6,
"baz": 5
},
{
"qux": 8,
"baz": 7
}
]
}
]
},
"cases": [
{
"expression": "foo",
"result": [{"bar": [{"qux": 2, "baz": 1}, {"qux": 4, "baz": 3}]},
{"bar": [{"qux": 6, "baz": 5}, {"qux": 8, "baz": 7}]}]
},
{
"expression": "foo[]",
"result": [{"bar": [{"qux": 2, "baz": 1}, {"qux": 4, "baz": 3}]},
{"bar": [{"qux": 6, "baz": 5}, {"qux": 8, "baz": 7}]}]
},
{
"expression": "foo[].bar",
"result": [[{"qux": 2, "baz": 1}, {"qux": 4, "baz": 3}],
[{"qux": 6, "baz": 5}, {"qux": 8, "baz": 7}]]
},
{
"expression": "foo[].bar[]",
"result": [{"qux": 2, "baz": 1}, {"qux": 4, "baz": 3},
{"qux": 6, "baz": 5}, {"qux": 8, "baz": 7}]
},
{
"expression": "foo[].bar[].[baz, qux]",
"result": [[1, 2], [3, 4], [5, 6], [7, 8]]
},
{
"expression": "foo[].bar[].[baz]",
"result": [[1], [3], [5], [7]]
},
{
"expression": "foo[].bar[].[baz, qux][]",
"result": [1, 2, 3, 4, 5, 6, 7, 8]
}
]
},
{
"given": {
"foo": {
"baz": [
{
"bar": "abc"
}, {
"bar": "def"
}
],
"qux": ["zero"]
}
},
"cases": [
{
"expression": "foo.[baz[*].bar, qux[0]]",
"result": [["abc", "def"], "zero"]
}
]
},
{
"given": {
"foo": {
"baz": [
{
"bar": "a",
"bam": "b",
"boo": "c"
}, {
"bar": "d",
"bam": "e",
"boo": "f"
}
],
"qux": ["zero"]
}
},
"cases": [
{
"expression": "foo.[baz[*].[bar, boo], qux[0]]",
"result": [[["a", "c" ], ["d", "f" ]], "zero"]
}
]
},
{
"given": {
"foo": {
"baz": [
{
"bar": "a",
"bam": "b",
"boo": "c"
}, {
"bar": "d",
"bam": "e",
"boo": "f"
}
],
"qux": ["zero"]
}
},
"cases": [
{
"expression": "foo.[baz[*].not_there || baz[*].bar, qux[0]]",
"result": [["a", "d"], "zero"]
}
]
},
{
"given": {"type": "object"},
"cases": [
{
"comment": "Nested multiselect",
"expression": "[[*],*]",
"result": [null, ["object"]]
}
]
},
{
"given": [],
"cases": [
{
"comment": "Nested multiselect",
"expression": "[[*]]",
"result": [[]]
}
]
}
]

View File

@@ -0,0 +1,131 @@
[{
"given": {
"foo": {
"bar": {
"baz": "subkey"
},
"other": {
"baz": "subkey"
},
"other2": {
"baz": "subkey"
},
"other3": {
"notbaz": ["a", "b", "c"]
},
"other4": {
"notbaz": ["a", "b", "c"]
}
}
},
"cases": [
{
"expression": "foo.*.baz | [0]",
"result": "subkey"
},
{
"expression": "foo.*.baz | [1]",
"result": "subkey"
},
{
"expression": "foo.*.baz | [2]",
"result": "subkey"
},
{
"expression": "foo.bar.* | [0]",
"result": "subkey"
},
{
"expression": "foo.*.notbaz | [*]",
"result": [["a", "b", "c"], ["a", "b", "c"]]
},
{
"expression": "{\"a\": foo.bar, \"b\": foo.other} | *.baz",
"result": ["subkey", "subkey"]
}
]
}, {
"given": {
"foo": {
"bar": {
"baz": "one"
},
"other": {
"baz": "two"
},
"other2": {
"baz": "three"
},
"other3": {
"notbaz": ["a", "b", "c"]
},
"other4": {
"notbaz": ["d", "e", "f"]
}
}
},
"cases": [
{
"expression": "foo | bar",
"result": {"baz": "one"}
},
{
"expression": "foo | bar | baz",
"result": "one"
},
{
"expression": "foo|bar| baz",
"result": "one"
},
{
"expression": "not_there | [0]",
"result": null
},
{
"expression": "not_there | [0]",
"result": null
},
{
"expression": "[foo.bar, foo.other] | [0]",
"result": {"baz": "one"}
},
{
"expression": "{\"a\": foo.bar, \"b\": foo.other} | a",
"result": {"baz": "one"}
},
{
"expression": "{\"a\": foo.bar, \"b\": foo.other} | b",
"result": {"baz": "two"}
},
{
"expression": "foo.bam || foo.bar | baz",
"result": "one"
},
{
"expression": "foo | not_there || bar",
"result": {"baz": "one"}
}
]
}, {
"given": {
"foo": [{
"bar": [{
"baz": "one"
}, {
"baz": "two"
}]
}, {
"bar": [{
"baz": "three"
}, {
"baz": "four"
}]
}]
},
"cases": [
{
"expression": "foo[*].bar[*] | [0][0]",
"result": {"baz": "one"}
}
]
}]

View File

@@ -0,0 +1,187 @@
[{
"given": {
"foo": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
"bar": {
"baz": 1
}
},
"cases": [
{
"expression": "bar[0:10]",
"result": null
},
{
"expression": "foo[0:10:1]",
"result": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
},
{
"expression": "foo[0:10]",
"result": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
},
{
"expression": "foo[0:10:]",
"result": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
},
{
"expression": "foo[0::1]",
"result": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
},
{
"expression": "foo[0::]",
"result": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
},
{
"expression": "foo[0:]",
"result": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
},
{
"expression": "foo[:10:1]",
"result": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
},
{
"expression": "foo[::1]",
"result": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
},
{
"expression": "foo[:10:]",
"result": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
},
{
"expression": "foo[::]",
"result": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
},
{
"expression": "foo[:]",
"result": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
},
{
"expression": "foo[1:9]",
"result": [1, 2, 3, 4, 5, 6, 7, 8]
},
{
"expression": "foo[0:10:2]",
"result": [0, 2, 4, 6, 8]
},
{
"expression": "foo[5:]",
"result": [5, 6, 7, 8, 9]
},
{
"expression": "foo[5::2]",
"result": [5, 7, 9]
},
{
"expression": "foo[::2]",
"result": [0, 2, 4, 6, 8]
},
{
"expression": "foo[::-1]",
"result": [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
},
{
"expression": "foo[1::2]",
"result": [1, 3, 5, 7, 9]
},
{
"expression": "foo[10:0:-1]",
"result": [9, 8, 7, 6, 5, 4, 3, 2, 1]
},
{
"expression": "foo[10:5:-1]",
"result": [9, 8, 7, 6]
},
{
"expression": "foo[8:2:-2]",
"result": [8, 6, 4]
},
{
"expression": "foo[0:20]",
"result": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
},
{
"expression": "foo[10:-20:-1]",
"result": [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
},
{
"expression": "foo[10:-20]",
"result": []
},
{
"expression": "foo[-4:-1]",
"result": [6, 7, 8]
},
{
"expression": "foo[:-5:-1]",
"result": [9, 8, 7, 6]
},
{
"expression": "foo[8:2:0]",
"error": "invalid-value"
},
{
"expression": "foo[8:2:0:1]",
"error": "syntax"
},
{
"expression": "foo[8:2&]",
"error": "syntax"
},
{
"expression": "foo[2:a:3]",
"error": "syntax"
}
]
}, {
"given": {
"foo": [{"a": 1}, {"a": 2}, {"a": 3}],
"bar": [{"a": {"b": 1}}, {"a": {"b": 2}},
{"a": {"b": 3}}],
"baz": 50
},
"cases": [
{
"expression": "foo[:2].a",
"result": [1, 2]
},
{
"expression": "foo[:2].b",
"result": []
},
{
"expression": "foo[:2].a.b",
"result": []
},
{
"expression": "bar[::-1].a.b",
"result": [3, 2, 1]
},
{
"expression": "bar[:2].a.b",
"result": [1, 2]
},
{
"expression": "baz[:2].a",
"result": null
}
]
}, {
"given": [{"a": 1}, {"a": 2}, {"a": 3}],
"cases": [
{
"expression": "[:]",
"result": [{"a": 1}, {"a": 2}, {"a": 3}]
},
{
"expression": "[:2].a",
"result": [1, 2]
},
{
"expression": "[::-1].a",
"result": [3, 2, 1]
},
{
"expression": "[:2].b",
"result": []
}
]
}]

View File

@@ -0,0 +1,616 @@
[{
"comment": "Dot syntax",
"given": {"type": "object"},
"cases": [
{
"expression": "foo.bar",
"result": null
},
{
"expression": "foo.1",
"error": "syntax"
},
{
"expression": "foo.-11",
"error": "syntax"
},
{
"expression": "foo",
"result": null
},
{
"expression": "foo.",
"error": "syntax"
},
{
"expression": "foo.",
"error": "syntax"
},
{
"expression": ".foo",
"error": "syntax"
},
{
"expression": "foo..bar",
"error": "syntax"
},
{
"expression": "foo.bar.",
"error": "syntax"
},
{
"expression": "foo[.]",
"error": "syntax"
}
]
},
{
"comment": "Simple token errors",
"given": {"type": "object"},
"cases": [
{
"expression": ".",
"error": "syntax"
},
{
"expression": ":",
"error": "syntax"
},
{
"expression": ",",
"error": "syntax"
},
{
"expression": "]",
"error": "syntax"
},
{
"expression": "[",
"error": "syntax"
},
{
"expression": "}",
"error": "syntax"
},
{
"expression": "{",
"error": "syntax"
},
{
"expression": ")",
"error": "syntax"
},
{
"expression": "(",
"error": "syntax"
},
{
"expression": "((&",
"error": "syntax"
},
{
"expression": "a[",
"error": "syntax"
},
{
"expression": "a]",
"error": "syntax"
},
{
"expression": "a][",
"error": "syntax"
},
{
"expression": "!",
"error": "syntax"
}
]
},
{
"comment": "Boolean syntax errors",
"given": {"type": "object"},
"cases": [
{
"expression": "![!(!",
"error": "syntax"
}
]
},
{
"comment": "Wildcard syntax",
"given": {"type": "object"},
"cases": [
{
"expression": "*",
"result": ["object"]
},
{
"expression": "*.*",
"result": []
},
{
"expression": "*.foo",
"result": []
},
{
"expression": "*[0]",
"result": []
},
{
"expression": ".*",
"error": "syntax"
},
{
"expression": "*foo",
"error": "syntax"
},
{
"expression": "*0",
"error": "syntax"
},
{
"expression": "foo[*]bar",
"error": "syntax"
},
{
"expression": "foo[*]*",
"error": "syntax"
}
]
},
{
"comment": "Flatten syntax",
"given": {"type": "object"},
"cases": [
{
"expression": "[]",
"result": null
}
]
},
{
"comment": "Simple bracket syntax",
"given": {"type": "object"},
"cases": [
{
"expression": "[0]",
"result": null
},
{
"expression": "[*]",
"result": null
},
{
"expression": "*.[0]",
"error": "syntax"
},
{
"expression": "*.[\"0\"]",
"result": [[null]]
},
{
"expression": "[*].bar",
"result": null
},
{
"expression": "[*][0]",
"result": null
},
{
"expression": "foo[#]",
"error": "syntax"
}
]
},
{
"comment": "Multi-select list syntax",
"given": {"type": "object"},
"cases": [
{
"expression": "foo[0]",
"result": null
},
{
"comment": "Valid multi-select of a list",
"expression": "foo[0, 1]",
"error": "syntax"
},
{
"expression": "foo.[0]",
"error": "syntax"
},
{
"expression": "foo.[*]",
"result": null
},
{
"comment": "Multi-select of a list with trailing comma",
"expression": "foo[0, ]",
"error": "syntax"
},
{
"comment": "Multi-select of a list with trailing comma and no close",
"expression": "foo[0,",
"error": "syntax"
},
{
"comment": "Multi-select of a list with trailing comma and no close",
"expression": "foo.[a",
"error": "syntax"
},
{
"comment": "Multi-select of a list with extra comma",
"expression": "foo[0,, 1]",
"error": "syntax"
},
{
"comment": "Multi-select of a list using an identifier index",
"expression": "foo[abc]",
"error": "syntax"
},
{
"comment": "Multi-select of a list using identifier indices",
"expression": "foo[abc, def]",
"error": "syntax"
},
{
"comment": "Multi-select of a list using an identifier index",
"expression": "foo[abc, 1]",
"error": "syntax"
},
{
"comment": "Multi-select of a list using an identifier index with trailing comma",
"expression": "foo[abc, ]",
"error": "syntax"
},
{
"comment": "Valid multi-select of a hash using an identifier index",
"expression": "foo.[abc]",
"result": null
},
{
"comment": "Valid multi-select of a hash",
"expression": "foo.[abc, def]",
"result": null
},
{
"comment": "Multi-select of a hash using a numeric index",
"expression": "foo.[abc, 1]",
"error": "syntax"
},
{
"comment": "Multi-select of a hash with a trailing comma",
"expression": "foo.[abc, ]",
"error": "syntax"
},
{
"comment": "Multi-select of a hash with extra commas",
"expression": "foo.[abc,, def]",
"error": "syntax"
},
{
"comment": "Multi-select of a hash using number indices",
"expression": "foo.[0, 1]",
"error": "syntax"
}
]
},
{
"comment": "Multi-select hash syntax",
"given": {"type": "object"},
"cases": [
{
"comment": "No key or value",
"expression": "a{}",
"error": "syntax"
},
{
"comment": "No closing token",
"expression": "a{",
"error": "syntax"
},
{
"comment": "Not a key value pair",
"expression": "a{foo}",
"error": "syntax"
},
{
"comment": "Missing value and closing character",
"expression": "a{foo:",
"error": "syntax"
},
{
"comment": "Missing closing character",
"expression": "a{foo: 0",
"error": "syntax"
},
{
"comment": "Missing value",
"expression": "a{foo:}",
"error": "syntax"
},
{
"comment": "Trailing comma and no closing character",
"expression": "a{foo: 0, ",
"error": "syntax"
},
{
"comment": "Missing value with trailing comma",
"expression": "a{foo: ,}",
"error": "syntax"
},
{
"comment": "Accessing Array using an identifier",
"expression": "a{foo: bar}",
"error": "syntax"
},
{
"expression": "a{foo: 0}",
"error": "syntax"
},
{
"comment": "Missing key-value pair",
"expression": "a.{}",
"error": "syntax"
},
{
"comment": "Not a key-value pair",
"expression": "a.{foo}",
"error": "syntax"
},
{
"comment": "Missing value",
"expression": "a.{foo:}",
"error": "syntax"
},
{
"comment": "Missing value with trailing comma",
"expression": "a.{foo: ,}",
"error": "syntax"
},
{
"comment": "Valid multi-select hash extraction",
"expression": "a.{foo: bar}",
"result": null
},
{
"comment": "Valid multi-select hash extraction",
"expression": "a.{foo: bar, baz: bam}",
"result": null
},
{
"comment": "Trailing comma",
"expression": "a.{foo: bar, }",
"error": "syntax"
},
{
"comment": "Missing key in second key-value pair",
"expression": "a.{foo: bar, baz}",
"error": "syntax"
},
{
"comment": "Missing value in second key-value pair",
"expression": "a.{foo: bar, baz:}",
"error": "syntax"
},
{
"comment": "Trailing comma",
"expression": "a.{foo: bar, baz: bam, }",
"error": "syntax"
},
{
"comment": "Nested multi select",
"expression": "{\"\\\\\":{\" \":*}}",
"result": {"\\": {" ": ["object"]}}
}
]
},
{
"comment": "Or expressions",
"given": {"type": "object"},
"cases": [
{
"expression": "foo || bar",
"result": null
},
{
"expression": "foo ||",
"error": "syntax"
},
{
"expression": "foo.|| bar",
"error": "syntax"
},
{
"expression": " || foo",
"error": "syntax"
},
{
"expression": "foo || || foo",
"error": "syntax"
},
{
"expression": "foo.[a || b]",
"result": null
},
{
"expression": "foo.[a ||]",
"error": "syntax"
},
{
"expression": "\"foo",
"error": "syntax"
}
]
},
{
"comment": "Filter expressions",
"given": {"type": "object"},
"cases": [
{
"expression": "foo[?bar==`\"baz\"`]",
"result": null
},
{
"expression": "foo[? bar == `\"baz\"` ]",
"result": null
},
{
"expression": "foo[ ?bar==`\"baz\"`]",
"error": "syntax"
},
{
"expression": "foo[?bar==]",
"error": "syntax"
},
{
"expression": "foo[?==]",
"error": "syntax"
},
{
"expression": "foo[?==bar]",
"error": "syntax"
},
{
"expression": "foo[?bar==baz?]",
"error": "syntax"
},
{
"expression": "foo[?a.b.c==d.e.f]",
"result": null
},
{
"expression": "foo[?bar==`[0, 1, 2]`]",
"result": null
},
{
"expression": "foo[?bar==`[\"a\", \"b\", \"c\"]`]",
"result": null
},
{
"comment": "Literal char not escaped",
"expression": "foo[?bar==`[\"foo`bar\"]`]",
"error": "syntax"
},
{
"comment": "Literal char escaped",
"expression": "foo[?bar==`[\"foo\\`bar\"]`]",
"result": null
},
{
"comment": "Unknown comparator",
"expression": "foo[?bar<>baz]",
"error": "syntax"
},
{
"comment": "Unknown comparator",
"expression": "foo[?bar^baz]",
"error": "syntax"
},
{
"expression": "foo[bar==baz]",
"error": "syntax"
},
{
"comment": "Quoted identifier in filter expression no spaces",
"expression": "[?\"\\\\\">`\"foo\"`]",
"result": null
},
{
"comment": "Quoted identifier in filter expression with spaces",
"expression": "[?\"\\\\\" > `\"foo\"`]",
"result": null
}
]
},
{
"comment": "Filter expression errors",
"given": {"type": "object"},
"cases": [
{
"expression": "bar.`\"anything\"`",
"error": "syntax"
},
{
"expression": "bar.baz.noexists.`\"literal\"`",
"error": "syntax"
},
{
"comment": "Literal wildcard projection",
"expression": "foo[*].`\"literal\"`",
"error": "syntax"
},
{
"expression": "foo[*].name.`\"literal\"`",
"error": "syntax"
},
{
"expression": "foo[].name.`\"literal\"`",
"error": "syntax"
},
{
"expression": "foo[].name.`\"literal\"`.`\"subliteral\"`",
"error": "syntax"
},
{
"comment": "Projecting a literal onto an empty list",
"expression": "foo[*].name.noexist.`\"literal\"`",
"error": "syntax"
},
{
"expression": "foo[].name.noexist.`\"literal\"`",
"error": "syntax"
},
{
"expression": "twolen[*].`\"foo\"`",
"error": "syntax"
},
{
"comment": "Two level projection of a literal",
"expression": "twolen[*].threelen[*].`\"bar\"`",
"error": "syntax"
},
{
"comment": "Two level flattened projection of a literal",
"expression": "twolen[].threelen[].`\"bar\"`",
"error": "syntax"
}
]
},
{
"comment": "Identifiers",
"given": {"type": "object"},
"cases": [
{
"expression": "foo",
"result": null
},
{
"expression": "\"foo\"",
"result": null
},
{
"expression": "\"\\\\\"",
"result": null
}
]
},
{
"comment": "Combined syntax",
"given": [],
"cases": [
{
"expression": "*||*|*|*",
"result": null
},
{
"expression": "*[]||[*]",
"result": []
},
{
"expression": "[*.*]",
"result": [null]
}
]
}
]

View File

@@ -0,0 +1,38 @@
[
{
"given": {"foo": [{"✓": "✓"}, {"✓": "✗"}]},
"cases": [
{
"expression": "foo[].\"✓\"",
"result": ["✓", "✗"]
}
]
},
{
"given": {"☯": true},
"cases": [
{
"expression": "\"☯\"",
"result": true
}
]
},
{
"given": {"♪♫•*¨*•.¸¸❤¸¸.•*¨*•♫♪": true},
"cases": [
{
"expression": "\"♪♫•*¨*•.¸¸❤¸¸.•*¨*•♫♪\"",
"result": true
}
]
},
{
"given": {"☃": true},
"cases": [
{
"expression": "\"☃\"",
"result": true
}
]
}
]

View File

@@ -0,0 +1,460 @@
[{
"given": {
"foo": {
"bar": {
"baz": "val"
},
"other": {
"baz": "val"
},
"other2": {
"baz": "val"
},
"other3": {
"notbaz": ["a", "b", "c"]
},
"other4": {
"notbaz": ["a", "b", "c"]
},
"other5": {
"other": {
"a": 1,
"b": 1,
"c": 1
}
}
}
},
"cases": [
{
"expression": "foo.*.baz",
"result": ["val", "val", "val"]
},
{
"expression": "foo.bar.*",
"result": ["val"]
},
{
"expression": "foo.*.notbaz",
"result": [["a", "b", "c"], ["a", "b", "c"]]
},
{
"expression": "foo.*.notbaz[0]",
"result": ["a", "a"]
},
{
"expression": "foo.*.notbaz[-1]",
"result": ["c", "c"]
}
]
}, {
"given": {
"foo": {
"first-1": {
"second-1": "val"
},
"first-2": {
"second-1": "val"
},
"first-3": {
"second-1": "val"
}
}
},
"cases": [
{
"expression": "foo.*",
"result": [{"second-1": "val"}, {"second-1": "val"},
{"second-1": "val"}]
},
{
"expression": "foo.*.*",
"result": [["val"], ["val"], ["val"]]
},
{
"expression": "foo.*.*.*",
"result": [[], [], []]
},
{
"expression": "foo.*.*.*.*",
"result": [[], [], []]
}
]
}, {
"given": {
"foo": {
"bar": "one"
},
"other": {
"bar": "one"
},
"nomatch": {
"notbar": "three"
}
},
"cases": [
{
"expression": "*.bar",
"result": ["one", "one"]
}
]
}, {
"given": {
"top1": {
"sub1": {"foo": "one"}
},
"top2": {
"sub1": {"foo": "one"}
}
},
"cases": [
{
"expression": "*",
"result": [{"sub1": {"foo": "one"}},
{"sub1": {"foo": "one"}}]
},
{
"expression": "*.sub1",
"result": [{"foo": "one"},
{"foo": "one"}]
},
{
"expression": "*.*",
"result": [[{"foo": "one"}],
[{"foo": "one"}]]
},
{
"expression": "*.*.foo[]",
"result": ["one", "one"]
},
{
"expression": "*.sub1.foo",
"result": ["one", "one"]
}
]
},
{
"given":
{"foo": [{"bar": "one"}, {"bar": "two"}, {"bar": "three"}, {"notbar": "four"}]},
"cases": [
{
"expression": "foo[*].bar",
"result": ["one", "two", "three"]
},
{
"expression": "foo[*].notbar",
"result": ["four"]
}
]
},
{
"given":
[{"bar": "one"}, {"bar": "two"}, {"bar": "three"}, {"notbar": "four"}],
"cases": [
{
"expression": "[*]",
"result": [{"bar": "one"}, {"bar": "two"}, {"bar": "three"}, {"notbar": "four"}]
},
{
"expression": "[*].bar",
"result": ["one", "two", "three"]
},
{
"expression": "[*].notbar",
"result": ["four"]
}
]
},
{
"given": {
"foo": {
"bar": [
{"baz": ["one", "two", "three"]},
{"baz": ["four", "five", "six"]},
{"baz": ["seven", "eight", "nine"]}
]
}
},
"cases": [
{
"expression": "foo.bar[*].baz",
"result": [["one", "two", "three"], ["four", "five", "six"], ["seven", "eight", "nine"]]
},
{
"expression": "foo.bar[*].baz[0]",
"result": ["one", "four", "seven"]
},
{
"expression": "foo.bar[*].baz[1]",
"result": ["two", "five", "eight"]
},
{
"expression": "foo.bar[*].baz[2]",
"result": ["three", "six", "nine"]
},
{
"expression": "foo.bar[*].baz[3]",
"result": []
}
]
},
{
"given": {
"foo": {
"bar": [["one", "two"], ["three", "four"]]
}
},
"cases": [
{
"expression": "foo.bar[*]",
"result": [["one", "two"], ["three", "four"]]
},
{
"expression": "foo.bar[0]",
"result": ["one", "two"]
},
{
"expression": "foo.bar[0][0]",
"result": "one"
},
{
"expression": "foo.bar[0][0][0]",
"result": null
},
{
"expression": "foo.bar[0][0][0][0]",
"result": null
},
{
"expression": "foo[0][0]",
"result": null
}
]
},
{
"given": {
"foo": [
{"bar": [{"kind": "basic"}, {"kind": "intermediate"}]},
{"bar": [{"kind": "advanced"}, {"kind": "expert"}]},
{"bar": "string"}
]
},
"cases": [
{
"expression": "foo[*].bar[*].kind",
"result": [["basic", "intermediate"], ["advanced", "expert"]]
},
{
"expression": "foo[*].bar[0].kind",
"result": ["basic", "advanced"]
}
]
},
{
"given": {
"foo": [
{"bar": {"kind": "basic"}},
{"bar": {"kind": "intermediate"}},
{"bar": {"kind": "advanced"}},
{"bar": {"kind": "expert"}},
{"bar": "string"}
]
},
"cases": [
{
"expression": "foo[*].bar.kind",
"result": ["basic", "intermediate", "advanced", "expert"]
}
]
},
{
"given": {
"foo": [{"bar": ["one", "two"]}, {"bar": ["three", "four"]}, {"bar": ["five"]}]
},
"cases": [
{
"expression": "foo[*].bar[0]",
"result": ["one", "three", "five"]
},
{
"expression": "foo[*].bar[1]",
"result": ["two", "four"]
},
{
"expression": "foo[*].bar[2]",
"result": []
}
]
},
{
"given": {
"foo": [{"bar": []}, {"bar": []}, {"bar": []}]
},
"cases": [
{
"expression": "foo[*].bar[0]",
"result": []
}
]
},
{
"given": {
"foo": [["one", "two"], ["three", "four"], ["five"]]
},
"cases": [
{
"expression": "foo[*][0]",
"result": ["one", "three", "five"]
},
{
"expression": "foo[*][1]",
"result": ["two", "four"]
}
]
},
{
"given": {
"foo": [
[
["one", "two"], ["three", "four"]
], [
["five", "six"], ["seven", "eight"]
], [
["nine"], ["ten"]
]
]
},
"cases": [
{
"expression": "foo[*][0]",
"result": [["one", "two"], ["five", "six"], ["nine"]]
},
{
"expression": "foo[*][1]",
"result": [["three", "four"], ["seven", "eight"], ["ten"]]
},
{
"expression": "foo[*][0][0]",
"result": ["one", "five", "nine"]
},
{
"expression": "foo[*][1][0]",
"result": ["three", "seven", "ten"]
},
{
"expression": "foo[*][0][1]",
"result": ["two", "six"]
},
{
"expression": "foo[*][1][1]",
"result": ["four", "eight"]
},
{
"expression": "foo[*][2]",
"result": []
},
{
"expression": "foo[*][2][2]",
"result": []
},
{
"expression": "bar[*]",
"result": null
},
{
"expression": "bar[*].baz[*]",
"result": null
}
]
},
{
"given": {
"string": "string",
"hash": {"foo": "bar", "bar": "baz"},
"number": 23,
"nullvalue": null
},
"cases": [
{
"expression": "string[*]",
"result": null
},
{
"expression": "hash[*]",
"result": null
},
{
"expression": "number[*]",
"result": null
},
{
"expression": "nullvalue[*]",
"result": null
},
{
"expression": "string[*].foo",
"result": null
},
{
"expression": "hash[*].foo",
"result": null
},
{
"expression": "number[*].foo",
"result": null
},
{
"expression": "nullvalue[*].foo",
"result": null
},
{
"expression": "nullvalue[*].foo[*].bar",
"result": null
}
]
},
{
"given": {
"string": "string",
"hash": {"foo": "val", "bar": "val"},
"number": 23,
"array": [1, 2, 3],
"nullvalue": null
},
"cases": [
{
"expression": "string.*",
"result": null
},
{
"expression": "hash.*",
"result": ["val", "val"]
},
{
"expression": "number.*",
"result": null
},
{
"expression": "array.*",
"result": null
},
{
"expression": "nullvalue.*",
"result": null
}
]
},
{
"given": {
"a": [0, 1, 2],
"b": [0, 1, 2]
},
"cases": [
{
"expression": "*[0]",
"result": [0, 0]
}
]
}
]

217
Skills/@be/node_modules/jmespath/test/jmespath.js generated vendored Normal file
View File

@@ -0,0 +1,217 @@
var assert = require('assert');
var jmespath = require('../jmespath');
var tokenize = jmespath.tokenize;
var compile = jmespath.compile;
var strictDeepEqual = jmespath.strictDeepEqual;
describe('tokenize', function() {
it('should tokenize unquoted identifier', function() {
assert.deepEqual(tokenize('foo'),
[{type: "UnquotedIdentifier",
value: "foo",
start: 0}]);
});
it('should tokenize unquoted identifier with underscore', function() {
assert.deepEqual(tokenize('_underscore'),
[{type: "UnquotedIdentifier",
value: "_underscore",
start: 0}]);
});
it('should tokenize unquoted identifier with numbers', function() {
assert.deepEqual(tokenize('foo123'),
[{type: "UnquotedIdentifier",
value: "foo123",
start: 0}]);
});
it('should tokenize dotted lookups', function() {
assert.deepEqual(
tokenize('foo.bar'),
[{type: "UnquotedIdentifier", value: "foo", start: 0},
{type: "Dot", value: ".", start: 3},
{type: "UnquotedIdentifier", value: "bar", start: 4},
]);
});
it('should tokenize numbers', function() {
assert.deepEqual(
tokenize('foo[0]'),
[{type: "UnquotedIdentifier", value: "foo", start: 0},
{type: "Lbracket", value: "[", start: 3},
{type: "Number", value: 0, start: 4},
{type: "Rbracket", value: "]", start: 5},
]);
});
it('should tokenize numbers with multiple digits', function() {
assert.deepEqual(
tokenize("12345"),
[{type: "Number", value: 12345, start: 0}]);
});
it('should tokenize negative numbers', function() {
assert.deepEqual(
tokenize("-12345"),
[{type: "Number", value: -12345, start: 0}]);
});
it('should tokenize quoted identifier', function() {
assert.deepEqual(tokenize('"foo"'),
[{type: "QuotedIdentifier",
value: "foo",
start: 0}]);
});
it('should tokenize quoted identifier with unicode escape', function() {
assert.deepEqual(tokenize('"\\u2713"'),
[{type: "QuotedIdentifier",
value: "✓",
start: 0}]);
});
it('should tokenize literal lists', function() {
assert.deepEqual(tokenize("`[0, 1]`"),
[{type: "Literal",
value: [0, 1],
start: 0}]);
});
it('should tokenize literal dict', function() {
assert.deepEqual(tokenize("`{\"foo\": \"bar\"}`"),
[{type: "Literal",
value: {"foo": "bar"},
start: 0}]);
});
it('should tokenize literal strings', function() {
assert.deepEqual(tokenize("`\"foo\"`"),
[{type: "Literal",
value: "foo",
start: 0}]);
});
it('should tokenize json literals', function() {
assert.deepEqual(tokenize("`true`"),
[{type: "Literal",
value: true,
start: 0}]);
});
it('should not requiring surrounding quotes for strings', function() {
assert.deepEqual(tokenize("`foo`"),
[{type: "Literal",
value: "foo",
start: 0}]);
});
it('should not requiring surrounding quotes for numbers', function() {
assert.deepEqual(tokenize("`20`"),
[{type: "Literal",
value: 20,
start: 0}]);
});
it('should tokenize literal lists with chars afterwards', function() {
assert.deepEqual(
tokenize("`[0, 1]`[0]"), [
{type: "Literal", value: [0, 1], start: 0},
{type: "Lbracket", value: "[", start: 8},
{type: "Number", value: 0, start: 9},
{type: "Rbracket", value: "]", start: 10}
]);
});
it('should tokenize two char tokens with shared prefix', function() {
assert.deepEqual(
tokenize("[?foo]"),
[{type: "Filter", value: "[?", start: 0},
{type: "UnquotedIdentifier", value: "foo", start: 2},
{type: "Rbracket", value: "]", start: 5}]
);
});
it('should tokenize flatten operator', function() {
assert.deepEqual(
tokenize("[]"),
[{type: "Flatten", value: "[]", start: 0}]);
});
it('should tokenize comparators', function() {
assert.deepEqual(tokenize("<"),
[{type: "LT",
value: "<",
start: 0}]);
});
it('should tokenize two char tokens without shared prefix', function() {
assert.deepEqual(
tokenize("=="),
[{type: "EQ", value: "==", start: 0}]
);
});
it('should tokenize not equals', function() {
assert.deepEqual(
tokenize("!="),
[{type: "NE", value: "!=", start: 0}]
);
});
it('should tokenize the OR token', function() {
assert.deepEqual(
tokenize("a||b"),
[
{type: "UnquotedIdentifier", value: "a", start: 0},
{type: "Or", value: "||", start: 1},
{type: "UnquotedIdentifier", value: "b", start: 3}
]
);
});
it('should tokenize function calls', function() {
assert.deepEqual(
tokenize("abs(@)"),
[
{type: "UnquotedIdentifier", value: "abs", start: 0},
{type: "Lparen", value: "(", start: 3},
{type: "Current", value: "@", start: 4},
{type: "Rparen", value: ")", start: 5}
]
);
});
});
describe('parsing', function() {
it('should parse field node', function() {
assert.deepEqual(compile('foo'),
{type: 'Field', name: 'foo'});
});
});
describe('strictDeepEqual', function() {
it('should compare scalars', function() {
assert.strictEqual(strictDeepEqual('a', 'a'), true);
});
it('should be false for different types', function() {
assert.strictEqual(strictDeepEqual('a', 2), false);
});
it('should be false for arrays of different lengths', function() {
assert.strictEqual(strictDeepEqual([0, 1], [1, 2, 3]), false);
});
it('should be true for identical arrays', function() {
assert.strictEqual(strictDeepEqual([0, 1], [0, 1]), true);
});
it('should be true for nested arrays', function() {
assert.strictEqual(
strictDeepEqual([[0, 1], [2, 3]], [[0, 1], [2, 3]]), true);
});
it('should be true for nested arrays of strings', function() {
assert.strictEqual(
strictDeepEqual([["a", "b"], ["c", "d"]],
[["a", "b"], ["c", "d"]]), true);
});
it('should be false for different arrays of the same length', function() {
assert.strictEqual(strictDeepEqual([0, 1], [1, 2]), false);
});
it('should handle object literals', function() {
assert.strictEqual(strictDeepEqual({a: 1, b: 2}, {a: 1, b: 2}), true);
});
it('should handle keys in first not in second', function() {
assert.strictEqual(strictDeepEqual({a: 1, b: 2}, {a: 1}), false);
});
it('should handle keys in second not in first', function() {
assert.strictEqual(strictDeepEqual({a: 1}, {a: 1, b: 2}), false);
});
it('should handle nested objects', function() {
assert.strictEqual(
strictDeepEqual({a: {b: [1, 2]}},
{a: {b: [1, 2]}}), true);
});
it('should handle nested objects that are not equal', function() {
assert.strictEqual(
strictDeepEqual({a: {b: [1, 2]}},
{a: {b: [1, 4]}}), false);
});
});