predicate 2.3.2 → 2.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/Gemfile +4 -0
- data/LICENSE.md +17 -19
- data/README.md +435 -0
- data/bin/g +2 -0
- data/lib/predicate/dsl.rb +138 -0
- data/lib/predicate/factory.rb +142 -37
- data/lib/predicate/grammar.rb +11 -2
- data/lib/predicate/grammar.sexp.yml +29 -0
- data/lib/predicate/nodes/${op_name}.rb.jeny +12 -0
- data/lib/predicate/nodes/and.rb +9 -0
- data/lib/predicate/nodes/binary_func.rb +20 -0
- data/lib/predicate/nodes/contradiction.rb +2 -7
- data/lib/predicate/nodes/dyadic_comp.rb +1 -3
- data/lib/predicate/nodes/empty.rb +14 -0
- data/lib/predicate/nodes/eq.rb +11 -3
- data/lib/predicate/nodes/expr.rb +9 -3
- data/lib/predicate/nodes/has_size.rb +14 -0
- data/lib/predicate/nodes/identifier.rb +1 -3
- data/lib/predicate/nodes/in.rb +7 -6
- data/lib/predicate/nodes/intersect.rb +3 -23
- data/lib/predicate/nodes/literal.rb +1 -3
- data/lib/predicate/nodes/match.rb +1 -21
- data/lib/predicate/nodes/nadic_bool.rb +1 -3
- data/lib/predicate/nodes/native.rb +1 -3
- data/lib/predicate/nodes/not.rb +1 -3
- data/lib/predicate/nodes/opaque.rb +1 -3
- data/lib/predicate/nodes/qualified_identifier.rb +1 -3
- data/lib/predicate/nodes/set_op.rb +26 -0
- data/lib/predicate/nodes/subset.rb +11 -0
- data/lib/predicate/nodes/superset.rb +11 -0
- data/lib/predicate/nodes/tautology.rb +6 -7
- data/lib/predicate/nodes/unary_func.rb +16 -0
- data/lib/predicate/nodes/var.rb +46 -0
- data/lib/predicate/processors/qualifier.rb +4 -0
- data/lib/predicate/processors/renamer.rb +4 -0
- data/lib/predicate/processors/to_s.rb +28 -0
- data/lib/predicate/processors/unqualifier.rb +21 -0
- data/lib/predicate/processors.rb +1 -0
- data/lib/predicate/sequel/to_sequel.rb +4 -1
- data/lib/predicate/sugar.rb +47 -0
- data/lib/predicate/version.rb +2 -2
- data/lib/predicate.rb +26 -2
- data/spec/dsl/test_dsl.rb +204 -0
- data/spec/dsl/test_evaluate.rb +65 -0
- data/spec/dsl/test_respond_to_missing.rb +35 -0
- data/spec/dsl/test_to_skake_case.rb +38 -0
- data/spec/factory/shared/a_comparison_factory_method.rb +1 -0
- data/spec/factory/test_${op_name}.rb.jeny +12 -0
- data/spec/factory/test_comp.rb +28 -5
- data/spec/factory/test_empty.rb +11 -0
- data/spec/factory/test_has_size.rb +11 -0
- data/spec/factory/test_match.rb +1 -0
- data/spec/factory/test_set_ops.rb +18 -0
- data/spec/factory/test_var.rb +22 -0
- data/spec/factory/test_vars.rb +27 -0
- data/spec/nodes/${op_name}.jeny/test_evaluate.rb.jeny +19 -0
- data/spec/nodes/empty/test_evaluate.rb +42 -0
- data/spec/nodes/has_size/test_evaluate.rb +44 -0
- data/spec/predicate/test_and_split.rb +18 -0
- data/spec/predicate/test_attr_split.rb +18 -0
- data/spec/predicate/test_constant_variables.rb +24 -2
- data/spec/predicate/test_constants.rb +24 -0
- data/spec/predicate/test_evaluate.rb +205 -3
- data/spec/predicate/test_free_variables.rb +1 -1
- data/spec/predicate/test_to_hash.rb +40 -0
- data/spec/predicate/test_to_s.rb +37 -0
- data/spec/predicate/test_unqualify.rb +18 -0
- data/spec/sequel/test_to_sequel.rb +25 -0
- data/spec/shared/a_predicate.rb +30 -0
- data/spec/spec_helper.rb +1 -0
- data/spec/test_predicate.rb +78 -33
- data/spec/test_readme.rb +80 -0
- data/spec/test_sugar.rb +48 -0
- data/tasks/test.rake +3 -3
- metadata +45 -14
- data/spec/factory/test_between.rb +0 -12
- data/spec/factory/test_intersect.rb +0 -12
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
class Predicate
|
4
|
+
describe Dsl, "to_snake_case" do
|
5
|
+
|
6
|
+
def snake(str)
|
7
|
+
Dsl.new.__send__(:to_snake_case, str)
|
8
|
+
end
|
9
|
+
|
10
|
+
it 'works on snake case already' do
|
11
|
+
{
|
12
|
+
"snake" => "snake",
|
13
|
+
"snake_case" => "snake_case"
|
14
|
+
}.each_pair do |k,v|
|
15
|
+
expect(snake(k)).to eq(v)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'works on camelCase already' do
|
20
|
+
{
|
21
|
+
"camelCase" => "camel_case",
|
22
|
+
"theCamelCase" => "the_camel_case"
|
23
|
+
}.each_pair do |k,v|
|
24
|
+
expect(snake(k)).to eq(v)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
it 'works on PascalCase already' do
|
29
|
+
{
|
30
|
+
"PascalCase" => "pascal_case",
|
31
|
+
"ThePascalCase" => "the_pascal_case"
|
32
|
+
}.each_pair do |k,v|
|
33
|
+
expect(snake(k)).to eq(v)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
#jeny(predicate)
|
2
|
+
require_relative 'shared/a_predicate_ast_node'
|
3
|
+
class Predicate
|
4
|
+
describe Factory, '${op_name}' do
|
5
|
+
include Factory
|
6
|
+
subject{ ${op_name}(TODO) }
|
7
|
+
|
8
|
+
it_should_behave_like "a predicate AST node"
|
9
|
+
|
10
|
+
it{ should be_a(${OpName}) }
|
11
|
+
end
|
12
|
+
end
|
data/spec/factory/test_comp.rb
CHANGED
@@ -10,7 +10,15 @@ class Predicate
|
|
10
10
|
it{ should eq(Factory.tautology) }
|
11
11
|
end
|
12
12
|
|
13
|
-
context "when the hash is
|
13
|
+
context "when the hash is a singelton" do
|
14
|
+
let(:h){ {:x => 12} }
|
15
|
+
|
16
|
+
it_should_behave_like "a predicate AST node"
|
17
|
+
it{ should be_a(Eq) }
|
18
|
+
it{ should eq([:eq, [:identifier, :x], [:literal, 12]]) }
|
19
|
+
end
|
20
|
+
|
21
|
+
context "when the hash is not singleton" do
|
14
22
|
let(:h){ {:x => 12, :y => :z} }
|
15
23
|
let(:expected){
|
16
24
|
[:and,
|
@@ -23,12 +31,27 @@ class Predicate
|
|
23
31
|
it{ should eq(expected) }
|
24
32
|
end
|
25
33
|
|
26
|
-
context "when the
|
27
|
-
let(:
|
34
|
+
context "when the value is a Regexp" do
|
35
|
+
let(:rx){ /[a-z]+/ }
|
36
|
+
let(:h){ {:x => /[a-z]+/} }
|
28
37
|
|
29
38
|
it_should_behave_like "a predicate AST node"
|
30
|
-
it{ should be_a(
|
31
|
-
it{ should eq([:
|
39
|
+
it{ should be_a(Match) }
|
40
|
+
it{ should eq([:match, [:identifier, :x], [:literal, rx]]) }
|
41
|
+
end
|
42
|
+
|
43
|
+
context "when the hash mixes value types" do
|
44
|
+
let(:rx){ /[a-z]+/ }
|
45
|
+
let(:h){ {:x => 12, :y => rx} }
|
46
|
+
let(:expected){
|
47
|
+
[:and,
|
48
|
+
[:eq, [:identifier, :x], [:literal, 12]],
|
49
|
+
[:match, [:identifier, :y], [:literal, rx]]]
|
50
|
+
}
|
51
|
+
|
52
|
+
it_should_behave_like "a predicate AST node"
|
53
|
+
it{ should be_a(And) }
|
54
|
+
it{ should eq(expected) }
|
32
55
|
end
|
33
56
|
|
34
57
|
end
|
data/spec/factory/test_match.rb
CHANGED
@@ -0,0 +1,18 @@
|
|
1
|
+
require_relative "shared/a_comparison_factory_method"
|
2
|
+
class Predicate
|
3
|
+
[
|
4
|
+
[ :intersect, Intersect ],
|
5
|
+
[ :subset, Subset ],
|
6
|
+
[ :superset, Superset ],
|
7
|
+
].each do |op_name, op_class|
|
8
|
+
describe Factory, op_name do
|
9
|
+
|
10
|
+
subject{ Factory.send(op_name, :x, [2, 3]) }
|
11
|
+
|
12
|
+
it{ should be_a(op_class) }
|
13
|
+
|
14
|
+
it{ should eq([op_name, [:identifier, :x], [:literal, [2, 3]]]) }
|
15
|
+
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require_relative 'shared/a_predicate_ast_node'
|
2
|
+
class Predicate
|
3
|
+
describe Factory, 'var' do
|
4
|
+
include Factory
|
5
|
+
|
6
|
+
context 'when used with a string' do
|
7
|
+
subject{ var("a.b.c", :dig) }
|
8
|
+
|
9
|
+
it_should_behave_like "a predicate AST node"
|
10
|
+
it{ should be_a(Var) }
|
11
|
+
it{ should eql([:var, "a.b.c", :dig]) }
|
12
|
+
end
|
13
|
+
|
14
|
+
context 'when used with an array' do
|
15
|
+
subject{ var([:a, :b, :c], :dig) }
|
16
|
+
|
17
|
+
it_should_behave_like "a predicate AST node"
|
18
|
+
it{ should be_a(Var) }
|
19
|
+
it{ should eql([:var, [:a, :b, :c], :dig]) }
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require_relative 'shared/a_predicate_ast_node'
|
2
|
+
class Predicate
|
3
|
+
describe Factory, 'vars' do
|
4
|
+
include Factory
|
5
|
+
|
6
|
+
context 'when used without semantics' do
|
7
|
+
subject{ vars("a.b.c", "d.e.f") }
|
8
|
+
|
9
|
+
it 'works as expected' do
|
10
|
+
expect(subject).to be_a(Array)
|
11
|
+
expect(subject.size).to eql(2)
|
12
|
+
expect(subject.all?{|p| p.is_a?(Var) && p.semantics == :dig })
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
context 'when used with semantics' do
|
17
|
+
subject{ vars("a.b.c", "d.e.f", :jsonpath) }
|
18
|
+
|
19
|
+
it 'works as expected' do
|
20
|
+
expect(subject).to be_a(Array)
|
21
|
+
expect(subject.size).to eql(2)
|
22
|
+
expect(subject.all?{|p| p.is_a?(Var) && p.semantics == :jsonpath })
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
#jeny(predicate)
|
2
|
+
require 'spec_helper'
|
3
|
+
class Predicate
|
4
|
+
describe ${OpName}, "evaluate" do
|
5
|
+
|
6
|
+
let(:predicate){ Factory.${op_name}(TODO) }
|
7
|
+
|
8
|
+
subject{ predicate.evaluate(context) }
|
9
|
+
|
10
|
+
context "on TODO" do
|
11
|
+
let(:context){ TODO }
|
12
|
+
|
13
|
+
it 'works as expected' do
|
14
|
+
TODO
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
class Predicate
|
3
|
+
describe Empty, "evaluate" do
|
4
|
+
|
5
|
+
let(:predicate){ Factory.empty(:x) }
|
6
|
+
|
7
|
+
subject{ predicate.evaluate(context) }
|
8
|
+
|
9
|
+
context "on an empty array" do
|
10
|
+
let(:context){ { x: [] } }
|
11
|
+
|
12
|
+
it{ expect(subject).to eq(true) }
|
13
|
+
end
|
14
|
+
|
15
|
+
context "on a non empty array" do
|
16
|
+
let(:context){ { x: [1, 2, 3] } }
|
17
|
+
|
18
|
+
it{ expect(subject).to eq(false) }
|
19
|
+
end
|
20
|
+
|
21
|
+
context "on a empty string" do
|
22
|
+
let(:context){ { x: "" } }
|
23
|
+
|
24
|
+
it{ expect(subject).to eq(true) }
|
25
|
+
end
|
26
|
+
|
27
|
+
context "on a non empty string" do
|
28
|
+
let(:context){ { x: "1233" } }
|
29
|
+
|
30
|
+
it{ expect(subject).to eq(false) }
|
31
|
+
end
|
32
|
+
|
33
|
+
context "on an object that does not respond to empty?" do
|
34
|
+
let(:context){ { x: 14567 } }
|
35
|
+
|
36
|
+
it{
|
37
|
+
expect{ subject }.to raise_error(TypeError, "Expected 14567 to respond to empty?")
|
38
|
+
}
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
class Predicate
|
3
|
+
describe HasSize, "evaluate" do
|
4
|
+
|
5
|
+
let(:predicate){
|
6
|
+
Factory.has_size(:x, y)
|
7
|
+
}
|
8
|
+
|
9
|
+
subject{ predicate.evaluate(context) }
|
10
|
+
|
11
|
+
context 'against a Range' do
|
12
|
+
let(:y){ 1..10 }
|
13
|
+
|
14
|
+
context "on a match x" do
|
15
|
+
let(:context){ { x: "1234567" } }
|
16
|
+
|
17
|
+
it{ expect(subject).to eq(true) }
|
18
|
+
end
|
19
|
+
|
20
|
+
context "on a non matching x" do
|
21
|
+
let(:context){ { x: "1234567891011" } }
|
22
|
+
|
23
|
+
it{ expect(subject).to eq(false) }
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
context 'against an Integer' do
|
28
|
+
let(:y){ 10 }
|
29
|
+
|
30
|
+
context "on a match x" do
|
31
|
+
let(:context){ { x: "0123456789" } }
|
32
|
+
|
33
|
+
it{ expect(subject).to eq(true) }
|
34
|
+
end
|
35
|
+
|
36
|
+
context "on a non matching x" do
|
37
|
+
let(:context){ { x: "1234567891011" } }
|
38
|
+
|
39
|
+
it{ expect(subject).to eq(false) }
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
44
|
+
end
|
@@ -83,5 +83,23 @@ class Predicate
|
|
83
83
|
it{ should eq([ pred, p.tautology ]) }
|
84
84
|
end
|
85
85
|
|
86
|
+
context "on intersect" do
|
87
|
+
let(:pred){ p.intersect(:x, [1, 2]) }
|
88
|
+
|
89
|
+
it{ should eq([ pred, p.tautology ]) }
|
90
|
+
end
|
91
|
+
|
92
|
+
context "on subset" do
|
93
|
+
let(:pred){ p.subset(:x, [1, 2]) }
|
94
|
+
|
95
|
+
it{ should eq([ pred, p.tautology ]) }
|
96
|
+
end
|
97
|
+
|
98
|
+
context "on superset" do
|
99
|
+
let(:pred){ p.superset(:x, [1, 2]) }
|
100
|
+
|
101
|
+
it{ should eq([ pred, p.tautology ]) }
|
102
|
+
end
|
103
|
+
|
86
104
|
end
|
87
105
|
end
|
@@ -47,6 +47,24 @@ class Predicate
|
|
47
47
|
it{ should eq({ x: pred }) }
|
48
48
|
end
|
49
49
|
|
50
|
+
context "on intersect" do
|
51
|
+
let(:pred){ p.intersect(:x, [2]) }
|
52
|
+
|
53
|
+
it{ should eq({ x: pred }) }
|
54
|
+
end
|
55
|
+
|
56
|
+
context "on subset" do
|
57
|
+
let(:pred){ p.subset(:x, [2]) }
|
58
|
+
|
59
|
+
it{ should eq({ x: pred }) }
|
60
|
+
end
|
61
|
+
|
62
|
+
context "on superset" do
|
63
|
+
let(:pred){ p.superset(:x, [2]) }
|
64
|
+
|
65
|
+
it{ should eq({ x: pred }) }
|
66
|
+
end
|
67
|
+
|
50
68
|
context "on match" do
|
51
69
|
let(:pred){ p.match(:x, "London") }
|
52
70
|
|
@@ -37,14 +37,36 @@ class Predicate
|
|
37
37
|
describe "on an intersect with one value" do
|
38
38
|
let(:p){ Predicate.intersect(:x, [2]) }
|
39
39
|
|
40
|
-
# TODO: is that correct?
|
41
40
|
it{ expect(subject).to eql([]) }
|
42
41
|
end
|
43
42
|
|
44
43
|
describe "on an intersect with a placeholder" do
|
45
44
|
let(:p){ Predicate.intersect(:x, Predicate.placeholder) }
|
46
45
|
|
47
|
-
|
46
|
+
it{ expect(subject).to eql([]) }
|
47
|
+
end
|
48
|
+
|
49
|
+
describe "on an subset with one value" do
|
50
|
+
let(:p){ Predicate.subset(:x, [2]) }
|
51
|
+
|
52
|
+
it{ expect(subject).to eql([]) }
|
53
|
+
end
|
54
|
+
|
55
|
+
describe "on an subset with a placeholder" do
|
56
|
+
let(:p){ Predicate.subset(:x, Predicate.placeholder) }
|
57
|
+
|
58
|
+
it{ expect(subject).to eql([]) }
|
59
|
+
end
|
60
|
+
|
61
|
+
describe "on an superset with one value" do
|
62
|
+
let(:p){ Predicate.superset(:x, [2]) }
|
63
|
+
|
64
|
+
it{ expect(subject).to eql([]) }
|
65
|
+
end
|
66
|
+
|
67
|
+
describe "on an superset with a placeholder" do
|
68
|
+
let(:p){ Predicate.superset(:x, Predicate.placeholder) }
|
69
|
+
|
48
70
|
it{ expect(subject).to eql([]) }
|
49
71
|
end
|
50
72
|
|
@@ -119,6 +119,30 @@ class Predicate
|
|
119
119
|
it{ should eq({}) }
|
120
120
|
end
|
121
121
|
|
122
|
+
context "on subset" do
|
123
|
+
let(:pred){ p.subset(:x, [4,8]) }
|
124
|
+
|
125
|
+
it{ should eq({}) }
|
126
|
+
end
|
127
|
+
|
128
|
+
context "on subset with placeholder" do
|
129
|
+
let(:pred){ p.subset(:x, p.placeholder) }
|
130
|
+
|
131
|
+
it{ should eq({}) }
|
132
|
+
end
|
133
|
+
|
134
|
+
context "on superset" do
|
135
|
+
let(:pred){ p.superset(:x, [4,8]) }
|
136
|
+
|
137
|
+
it{ should eq({}) }
|
138
|
+
end
|
139
|
+
|
140
|
+
context "on superset with placeholder" do
|
141
|
+
let(:pred){ p.superset(:x, p.placeholder) }
|
142
|
+
|
143
|
+
it{ should eq({}) }
|
144
|
+
end
|
145
|
+
|
122
146
|
context "on or (two eqs)" do
|
123
147
|
let(:pred){ p.eq(:x, 2) | p.eq(:y, 4) }
|
124
148
|
|
@@ -40,7 +40,7 @@ class Predicate
|
|
40
40
|
|
41
41
|
context 'on a factored predicate' do
|
42
42
|
let(:predicate){
|
43
|
-
Predicate.
|
43
|
+
Predicate.lte(:x => 2)
|
44
44
|
}
|
45
45
|
|
46
46
|
describe "on x == 2" do
|
@@ -80,7 +80,7 @@ class Predicate
|
|
80
80
|
end
|
81
81
|
end
|
82
82
|
|
83
|
-
context 'on an intersect predicate' do
|
83
|
+
context 'on an intersect predicate, with array literal' do
|
84
84
|
let(:predicate){
|
85
85
|
Predicate.intersect(:x, [8,9])
|
86
86
|
}
|
@@ -98,6 +98,168 @@ class Predicate
|
|
98
98
|
end
|
99
99
|
end
|
100
100
|
|
101
|
+
context 'on an intersect predicate, with two variables' do
|
102
|
+
let(:predicate){
|
103
|
+
Predicate.intersect(:x, :y)
|
104
|
+
}
|
105
|
+
|
106
|
+
describe "on x == [2]" do
|
107
|
+
let(:scope){ { :x => [2], :y => [8,9] } }
|
108
|
+
|
109
|
+
it{ expect(predicate.evaluate(scope)).to be_falsy }
|
110
|
+
end
|
111
|
+
|
112
|
+
describe "on x == [9,12]" do
|
113
|
+
let(:scope){ { :x => [9,12], :y => [8,9] } }
|
114
|
+
|
115
|
+
it{ expect(predicate.evaluate(scope)).to be_truthy }
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
context 'on an subset predicate, with an array literal' do
|
120
|
+
let(:predicate){
|
121
|
+
Predicate.subset(:x, [8,9])
|
122
|
+
}
|
123
|
+
|
124
|
+
describe "on x == [2]" do
|
125
|
+
let(:scope){ { :x => [2] } }
|
126
|
+
|
127
|
+
it{ expect(predicate.evaluate(scope)).to be_falsy }
|
128
|
+
end
|
129
|
+
|
130
|
+
describe "on x == []" do
|
131
|
+
let(:scope){ { :x => [] } }
|
132
|
+
|
133
|
+
it{ expect(predicate.evaluate(scope)).to be_truthy }
|
134
|
+
end
|
135
|
+
|
136
|
+
describe "on x == [9]" do
|
137
|
+
let(:scope){ { :x => [9] } }
|
138
|
+
|
139
|
+
it{ expect(predicate.evaluate(scope)).to be_truthy }
|
140
|
+
end
|
141
|
+
|
142
|
+
describe "on x == [8, 9]" do
|
143
|
+
let(:scope){ { :x => [8, 9] } }
|
144
|
+
|
145
|
+
it{ expect(predicate.evaluate(scope)).to be_truthy }
|
146
|
+
end
|
147
|
+
|
148
|
+
describe "on x == [8, 9, 10]" do
|
149
|
+
let(:scope){ { :x => [8, 9, 19] } }
|
150
|
+
|
151
|
+
it{ expect(predicate.evaluate(scope)).to be_falsy }
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
context 'on an subset predicate, with two variables' do
|
156
|
+
let(:predicate){
|
157
|
+
Predicate.subset(:x, :y)
|
158
|
+
}
|
159
|
+
|
160
|
+
describe "on x == [2]" do
|
161
|
+
let(:scope){ { :x => [2], :y => [8,9] } }
|
162
|
+
|
163
|
+
it{ expect(predicate.evaluate(scope)).to be_falsy }
|
164
|
+
end
|
165
|
+
|
166
|
+
describe "on x == []" do
|
167
|
+
let(:scope){ { :x => [], :y => [8,9] } }
|
168
|
+
|
169
|
+
it{ expect(predicate.evaluate(scope)).to be_truthy }
|
170
|
+
end
|
171
|
+
|
172
|
+
describe "on x == [9]" do
|
173
|
+
let(:scope){ { :x => [9], :y => [8,9] } }
|
174
|
+
|
175
|
+
it{ expect(predicate.evaluate(scope)).to be_truthy }
|
176
|
+
end
|
177
|
+
|
178
|
+
describe "on x == [8, 9]" do
|
179
|
+
let(:scope){ { :x => [8, 9], :y => [8,9] } }
|
180
|
+
|
181
|
+
it{ expect(predicate.evaluate(scope)).to be_truthy }
|
182
|
+
end
|
183
|
+
|
184
|
+
describe "on x == [8, 9, 10]" do
|
185
|
+
let(:scope){ { :x => [8, 9, 19], :y => [8,9] } }
|
186
|
+
|
187
|
+
it{ expect(predicate.evaluate(scope)).to be_falsy }
|
188
|
+
end
|
189
|
+
end
|
190
|
+
|
191
|
+
context 'on an superset predicate, with an array literal' do
|
192
|
+
let(:predicate){
|
193
|
+
Predicate.superset(:x, [8,9])
|
194
|
+
}
|
195
|
+
|
196
|
+
describe "on x == [2]" do
|
197
|
+
let(:scope){ { :x => [2] } }
|
198
|
+
|
199
|
+
it{ expect(predicate.evaluate(scope)).to be_falsy }
|
200
|
+
end
|
201
|
+
|
202
|
+
describe "on x == []" do
|
203
|
+
let(:scope){ { :x => [] } }
|
204
|
+
|
205
|
+
it{ expect(predicate.evaluate(scope)).to be_falsy }
|
206
|
+
end
|
207
|
+
|
208
|
+
describe "on x == [9]" do
|
209
|
+
let(:scope){ { :x => [9] } }
|
210
|
+
|
211
|
+
it{ expect(predicate.evaluate(scope)).to be_falsy }
|
212
|
+
end
|
213
|
+
|
214
|
+
describe "on x == [8, 9]" do
|
215
|
+
let(:scope){ { :x => [8, 9] } }
|
216
|
+
|
217
|
+
it{ expect(predicate.evaluate(scope)).to be_truthy }
|
218
|
+
end
|
219
|
+
|
220
|
+
describe "on x == [8, 9, 10]" do
|
221
|
+
let(:scope){ { :x => [8, 9, 19] } }
|
222
|
+
|
223
|
+
it{ expect(predicate.evaluate(scope)).to be_truthy }
|
224
|
+
end
|
225
|
+
end
|
226
|
+
|
227
|
+
context 'on an superset predicate, with two variables' do
|
228
|
+
let(:predicate){
|
229
|
+
Predicate.superset(:x, :y)
|
230
|
+
}
|
231
|
+
|
232
|
+
describe "on x == [2]" do
|
233
|
+
let(:scope){ { :x => [2], :y => [8,9] } }
|
234
|
+
|
235
|
+
it{ expect(predicate.evaluate(scope)).to be_falsy }
|
236
|
+
end
|
237
|
+
|
238
|
+
describe "on x == []" do
|
239
|
+
let(:scope){ { :x => [], :y => [8,9] } }
|
240
|
+
|
241
|
+
it{ expect(predicate.evaluate(scope)).to be_falsy }
|
242
|
+
end
|
243
|
+
|
244
|
+
describe "on x == [9]" do
|
245
|
+
let(:scope){ { :x => [9], :y => [8,9] } }
|
246
|
+
|
247
|
+
it{ expect(predicate.evaluate(scope)).to be_falsy }
|
248
|
+
end
|
249
|
+
|
250
|
+
describe "on x == [8, 9]" do
|
251
|
+
let(:scope){ { :x => [8, 9], :y => [8,9] } }
|
252
|
+
|
253
|
+
it{ expect(predicate.evaluate(scope)).to be_truthy }
|
254
|
+
end
|
255
|
+
|
256
|
+
describe "on x == [8, 9, 10]" do
|
257
|
+
let(:scope){ { :x => [8, 9, 19], :y => [8,9] } }
|
258
|
+
|
259
|
+
it{ expect(predicate.evaluate(scope)).to be_truthy }
|
260
|
+
end
|
261
|
+
end
|
262
|
+
|
101
263
|
context 'on a match against a string' do
|
102
264
|
let(:predicate){
|
103
265
|
Predicate.match(:x, "12")
|
@@ -228,12 +390,52 @@ class Predicate
|
|
228
390
|
|
229
391
|
context 'has a call alias' do
|
230
392
|
let(:predicate){
|
231
|
-
Predicate.
|
393
|
+
Predicate.gte(:x => 0)
|
232
394
|
}
|
233
395
|
|
234
396
|
let(:scope){ { x: 2 } }
|
235
397
|
|
236
398
|
it{ expect(predicate.call(scope)).to be(true) }
|
237
399
|
end
|
400
|
+
|
401
|
+
context "on a var, build with a dotted string" do
|
402
|
+
let(:predicate){
|
403
|
+
Predicate.var("x.0.y")
|
404
|
+
}
|
405
|
+
|
406
|
+
let(:scope){ { x: [{ y: 2 }] } }
|
407
|
+
|
408
|
+
it{ expect(predicate.call(scope)).to eql(2) }
|
409
|
+
end
|
410
|
+
|
411
|
+
context "on a var, build with a . string" do
|
412
|
+
let(:predicate){
|
413
|
+
Predicate.var(".")
|
414
|
+
}
|
415
|
+
|
416
|
+
let(:scope){ { x: [{ y: 2 }] } }
|
417
|
+
|
418
|
+
it{ expect(predicate.call(scope)).to be(scope) }
|
419
|
+
end
|
420
|
+
|
421
|
+
context "on a var, build with an array for terms" do
|
422
|
+
let(:predicate){
|
423
|
+
Predicate.var([:x, 0, :y])
|
424
|
+
}
|
425
|
+
|
426
|
+
let(:scope){ { x: [{ y: 2 }] } }
|
427
|
+
|
428
|
+
it{ expect(predicate.call(scope)).to eql(2) }
|
429
|
+
end
|
430
|
+
|
431
|
+
context "on a var, build with an empty array" do
|
432
|
+
let(:predicate){
|
433
|
+
Predicate.var([])
|
434
|
+
}
|
435
|
+
|
436
|
+
let(:scope){ { x: [{ y: 2 }] } }
|
437
|
+
|
438
|
+
it{ expect(predicate.call(scope)).to be(scope) }
|
439
|
+
end
|
238
440
|
end
|
239
441
|
end
|