Skip to content

Commit 0c8951d

Browse files
committed
Update the tests to cache locally if possible. Add the \!\! operator, and clean up using truthy in all boolean ops.
1 parent 9073dcc commit 0c8951d

File tree

4 files changed

+71
-43
lines changed

4 files changed

+71
-43
lines changed

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
node_modules
2+
tests/tests.json
23

README.md

+8-8
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ The same format can also be executed in PHP by the library [json-logic-php](http
1010

1111
### Simple
1212
```js
13-
jsonLogic( { "==" : [1, 1] } );
13+
jsonLogic.apply( { "==" : [1, 1] } );
1414
// true
1515
```
1616

@@ -24,7 +24,7 @@ This is a simple test, equivalent to `1 == 1`. A few things about the format:
2424
Here we're beginning to nest rules.
2525

2626
```js
27-
jsonLogic(
27+
jsonLogic.apply(
2828
{"and" : [
2929
{ ">" : [3,1] },
3030
{ "<" : [1,3] }
@@ -44,7 +44,7 @@ In an infix language (like JavaScript) this could be written as:
4444
Obviously these rules aren't very interesting if they can only take static literal data. Typically `jsonLogic` will be called with a rule object and a data object. You can use the `var` operator to get attributes of the data object:
4545

4646
```js
47-
jsonLogic(
47+
jsonLogic.apply(
4848
{ "var" : ["a"] }, // Rule
4949
{ a : 1, b : 2 } // Data
5050
);
@@ -54,7 +54,7 @@ jsonLogic(
5454
If you like, we support [syntactic sugar](https://en.wikipedia.org/wiki/Syntactic_sugar) on unary operators to skip the array around values:
5555

5656
```js
57-
jsonLogic(
57+
jsonLogic.apply(
5858
{ "var" : "a" },
5959
{ a : 1, b : 2 }
6060
);
@@ -64,7 +64,7 @@ jsonLogic(
6464
You can also use the `var` operator to access an array by numeric index:
6565

6666
```js
67-
jsonLogic(
67+
jsonLogic.apply(
6868
{"var" : 1 },
6969
[ "apple", "banana", "carrot" ]
7070
);
@@ -81,7 +81,7 @@ var rules = { "and" : [
8181

8282
var data = { "temp" : 100, "pie" : { "filling" : "apple" } };
8383

84-
jsonLogic(rules, data);
84+
jsonLogic.apply(rules, data);
8585
// true
8686
```
8787

@@ -90,11 +90,11 @@ Sometimes the rule you want to process is "Always" or "Never." If the first par
9090

9191
```js
9292
//Always
93-
jsonLogic(true, data_will_be_ignored);
93+
jsonLogic.apply(true, data_will_be_ignored);
9494
// true
9595

9696
//Never
97-
jsonLogic(false, i_wasnt_even_supposed_to_be_here);
97+
jsonLogic.apply(false, i_wasnt_even_supposed_to_be_here);
9898
// false
9999
```
100100

logic.js

+12-8
Original file line numberDiff line numberDiff line change
@@ -48,13 +48,16 @@ var jsonLogic = {},
4848
"<=" : function(a,b,c){
4949
return (c === undefined) ? a <= b : (a <= b) && (b <= c);
5050
},
51-
"!" : function(a){ return !a; },
51+
"!!" : function(a){ return jsonLogic.truthy(a); },
52+
"!" : function(a){ return !jsonLogic.truthy(a); },
5253
"%" : function(a,b){ return a % b; },
53-
"and" : function(){
54-
return Array.prototype.reduce.call(arguments, function(a,b){ return a && b; });
54+
"and" : function(){ //Return first falsy, or last
55+
for(var i in arguments){ if( ! jsonLogic.truthy(arguments[i])){ return arguments[i]; } }
56+
return arguments[i];
5557
},
56-
"or" : function(){
57-
return Array.prototype.reduce.call(arguments, function(a,b){ return a || b; });
58+
"or" : function(){ //Return first truthy, or last
59+
for(var i in arguments){ if(jsonLogic.truthy(arguments[i])){ return arguments[i]; } }
60+
return arguments[i];
5861
},
5962
"log" : function(a){ console.log(a); return a; },
6063
"in" : function(a, b){
@@ -111,7 +114,8 @@ jsonLogic.apply = function(logic, data){
111114
data = data || {};
112115

113116
var op = Object.keys(logic)[0],
114-
values = logic[op];
117+
values = logic[op],
118+
i;
115119

116120
//easy syntax for unary operators, like {"var" : "x"} instead of strict {"var" : ["x"]}
117121
if( ! Array.isArray(values)){ values = [values]; }
@@ -131,7 +135,7 @@ jsonLogic.apply = function(logic, data){
131135
given one parameter, evaluate and return it. (it's an Else and all the If/ElseIf were false)
132136
given 0 parameters, return NULL (not great practice, but there was no Else)
133137
*/
134-
for(var i = 0 ; i < values.length - 1 ; i += 2){
138+
for(i = 0 ; i < values.length - 1 ; i += 2){
135139
if( jsonLogic.truthy( jsonLogic.apply(values[i], data) ) ){
136140
return jsonLogic.apply(values[i+1], data);
137141
}
@@ -148,7 +152,7 @@ jsonLogic.apply = function(logic, data){
148152
if(op === "var"){
149153
var not_found = values[1] || null,
150154
sub_props = String(values[0]).split(".");
151-
for(var i = 0 ; i < sub_props.length ; i++){
155+
for(i = 0 ; i < sub_props.length ; i++){
152156
//Descending into data
153157
data = data[ sub_props[i] ];
154158
if(data === undefined){ return not_found; }

tests/tests.js

+50-27
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,22 @@
1-
var jsonLogic = require('../logic.js');
2-
3-
var real_console = console.log, last_console;
4-
console.log = function(logged){ last_console = logged; real_console.apply(this, arguments); };
5-
6-
QUnit.test( "Bad operator", function( assert ) {
7-
assert.throws(
8-
function(){ jsonLogic.apply({"fubar": []}); },
9-
/Unrecognized operation/
10-
);
11-
});
1+
var jsonLogic = require('../logic.js'),
2+
http = require('http'),
3+
fs = require('fs');
124

5+
var download = function(url, dest, cb) {
6+
var file = fs.createWriteStream(dest);
7+
var request = http.get(url, function(response) {
8+
response.pipe(file);
9+
file.on('finish', function() {
10+
file.close(cb); // close() is async, call cb after close completes.
11+
});
12+
}).on('error', function(err) { // Handle errors
13+
fs.unlink(dest); // Delete the file async. (But we don't check the result)
14+
if (cb) cb(err.message);
15+
});
16+
};
1317

14-
15-
QUnit.test( "Shared JsonLogic.com tests ", function( assert ){
16-
//Only waiting on the request() is async
17-
stop();
18-
19-
/*
20-
var fs = require('fs');
21-
fs.readFile('tests.json', 'utf8', function (error, body) {
22-
*/
23-
var request = require('request');
24-
request('http://jsonlogic.com/tests.json', function (error, response, body) {
25-
if (error || response.statusCode != 200) {
26-
console.log("Failed to load tests from JsonLogic.com:", error, response.statusCode);
27-
start();
28-
return;
29-
}
18+
var process_test_file = function (filename){
19+
fs.readFile(filename, 'utf8', function (error, body) {
3020
try{
3121
tests = JSON.parse(body);
3222
}catch(e){
@@ -52,6 +42,39 @@ QUnit.test( "Shared JsonLogic.com tests ", function( assert ){
5242

5343
start();
5444
});
45+
};
46+
47+
var real_console = console.log, last_console;
48+
console.log = function(logged){ last_console = logged; real_console.apply(this, arguments); };
49+
50+
QUnit.test( "Bad operator", function( assert ) {
51+
assert.throws(
52+
function(){ jsonLogic.apply({"fubar": []}); },
53+
/Unrecognized operation/
54+
);
55+
});
56+
57+
58+
59+
QUnit.test( "Shared JsonLogic.com tests ", function( assert ){
60+
//Only waiting on the request() is async
61+
stop();
62+
63+
var local_file = 'tests.json';
64+
65+
fs.stat(local_file, function(err, stats){
66+
if(err){
67+
console.log("Downloading shared tests from JsonLogic.com");
68+
download('http://jsonlogic.com/tests.json', local_file, function(){
69+
process_test_file(local_file);
70+
});
71+
}else{
72+
console.log("Using cached tests");
73+
process_test_file(local_file);
74+
}
75+
});
76+
77+
5578
});
5679

5780
QUnit.test( "logging", function( assert ) {

0 commit comments

Comments
 (0)