cql 1.4.1 → 1.7.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 +5 -5
- data/lib/cql/dsl.rb +11 -1
- data/lib/cql/filters.rb +14 -1
- data/lib/cql/query.rb +5 -2
- data/lib/cql/repository.rb +1 -0
- data/lib/cql/version.rb +1 -1
- data/testing/cucumber/features/clauses/from_clause.feature +0 -8
- data/testing/cucumber/features/clauses/predefined_with_filters.feature +392 -0
- data/testing/cucumber/features/clauses/select_clause.feature +1 -5
- data/testing/cucumber/features/clauses/with_clause.feature +2 -164
- data/testing/cucumber/features/dsl.feature +0 -22
- data/testing/cucumber/step_definitions/verification_steps.rb +5 -6
- data/testing/gemfiles/cuke_modeler0.gemfile +9 -7
- data/testing/gemfiles/cuke_modeler1.gemfile +5 -7
- data/testing/gemfiles/cuke_modeler2.gemfile +33 -0
- data/testing/gemfiles/cuke_modeler3.gemfile +10 -0
- data/testing/helper_methods.rb +13 -0
- data/testing/model_helper.rb +28 -0
- data/testing/rspec/spec/clauses/as_clause_spec.rb +1 -0
- data/testing/rspec/spec/clauses/from_clause_spec.rb +146 -0
- data/testing/rspec/spec/clauses/select_clause_spec.rb +184 -0
- data/testing/rspec/spec/clauses/transform_clause_spec.rb +35 -0
- data/testing/rspec/spec/clauses/with_clause_spec.rb +84 -0
- data/testing/rspec/spec/clauses/without_clause_spec.rb +171 -0
- data/testing/rspec/spec/cql_spec.rb +31 -0
- data/testing/rspec/spec/dsl_spec.rb +3 -575
- data/testing/rspec/spec/filter_example_spec.rb +1 -1
- data/testing/rspec/spec/filter_feature_dsl_spec.rb +13 -13
- data/testing/rspec/spec/filter_sso_spec.rb +2 -2
- data/testing/rspec/spec/line_filterable_specs.rb +1 -1
- data/testing/rspec/spec/map_reduce_spec.rb +1 -1
- data/testing/rspec/spec/model_query_spec.rb +1 -1
- data/testing/rspec/spec/multiple_queries_spec.rb +1 -1
- data/testing/rspec/spec/name_filterable_specs.rb +1 -1
- data/testing/rspec/spec/predefined_filters_spec.rb +284 -0
- data/testing/rspec/spec/repository_spec.rb +3 -3
- data/testing/rspec/spec/select_feature_dsl_spec.rb +8 -8
- data/testing/rspec/spec/select_scen_outline_dsl_spec.rb +14 -14
- data/testing/rspec/spec/select_scenario_dsl_spec.rb +9 -9
- data/testing/rspec/spec/spec_helper.rb +7 -17
- metadata +67 -40
- data/testing/cucumber/support/transforms.rb +0 -3
@@ -0,0 +1,184 @@
|
|
1
|
+
require "#{File.dirname(__FILE__)}/../spec_helper"
|
2
|
+
|
3
|
+
|
4
|
+
describe 'an object that uses the DSL' do
|
5
|
+
|
6
|
+
|
7
|
+
let(:nodule) { CQL::Dsl }
|
8
|
+
let(:dsl_enabled_object) { Object.new.extend(nodule) }
|
9
|
+
|
10
|
+
describe "select" do
|
11
|
+
|
12
|
+
it 'knows how to select attributes' do
|
13
|
+
expect(dsl_enabled_object).to respond_to(:select)
|
14
|
+
end
|
15
|
+
|
16
|
+
it 'selects one or more attributes' do
|
17
|
+
expect(dsl_enabled_object.method(:select).arity).to eq(-1)
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'correctly selects a single attribute from a model' do
|
21
|
+
model = CukeModeler::CqlTestModel.new
|
22
|
+
model.attribute_1 = 'foo'
|
23
|
+
|
24
|
+
repo = CQL::Repository.new(model)
|
25
|
+
|
26
|
+
result = repo.query do
|
27
|
+
select attribute_1
|
28
|
+
from cql_test_model
|
29
|
+
end
|
30
|
+
|
31
|
+
|
32
|
+
expect(result).to eq([{'attribute_1' => 'foo'}])
|
33
|
+
end
|
34
|
+
|
35
|
+
it 'correctly selects multiple attributes from a model' do
|
36
|
+
model = CukeModeler::CqlTestModel.new
|
37
|
+
model.attribute_1 = 'foo'
|
38
|
+
model.attribute_2 = 'bar'
|
39
|
+
|
40
|
+
repo = CQL::Repository.new(model)
|
41
|
+
|
42
|
+
result = repo.query do
|
43
|
+
select attribute_1, attribute_2
|
44
|
+
from cql_test_model
|
45
|
+
end
|
46
|
+
|
47
|
+
|
48
|
+
expect(result).to eq([{'attribute_1' => 'foo',
|
49
|
+
'attribute_2' => 'bar'}])
|
50
|
+
end
|
51
|
+
|
52
|
+
|
53
|
+
describe 'special attributes' do
|
54
|
+
|
55
|
+
it 'understands the :model attribute' do
|
56
|
+
gs = CQL::Repository.new("#{CQL_FEATURE_FIXTURES_DIRECTORY}/scenario/simple")
|
57
|
+
|
58
|
+
expect { gs.query do
|
59
|
+
select :model
|
60
|
+
from features
|
61
|
+
end
|
62
|
+
}.to_not raise_error
|
63
|
+
end
|
64
|
+
|
65
|
+
it 'interprets :model in the same manner that it interprets :self' do
|
66
|
+
gs = CQL::Repository.new("#{CQL_FEATURE_FIXTURES_DIRECTORY}/scenario/simple")
|
67
|
+
|
68
|
+
self_result = gs.query do
|
69
|
+
select :self
|
70
|
+
from features
|
71
|
+
end
|
72
|
+
|
73
|
+
model_result = gs.query do
|
74
|
+
select :model
|
75
|
+
from features
|
76
|
+
end
|
77
|
+
|
78
|
+
# Only checking the values of the results because they will have different :model/:self keys
|
79
|
+
expect(model_result.collect { |result| result.values }).to eq(self_result.collect { |result| result.values })
|
80
|
+
end
|
81
|
+
|
82
|
+
it 'complains if an unknown special attribute is queried' do
|
83
|
+
gs = CQL::Repository.new("#{CQL_FEATURE_FIXTURES_DIRECTORY}/scenario/simple")
|
84
|
+
|
85
|
+
expect {
|
86
|
+
gs.query do
|
87
|
+
select :foo
|
88
|
+
from scenarios
|
89
|
+
end
|
90
|
+
}.to raise_error(ArgumentError, ":foo is not a valid attribute for selection.")
|
91
|
+
end
|
92
|
+
|
93
|
+
it 'uses the :self attribute by default' do
|
94
|
+
gs = CQL::Repository.new("#{CQL_FEATURE_FIXTURES_DIRECTORY}/scenario/simple")
|
95
|
+
|
96
|
+
default_result = gs.query do
|
97
|
+
select
|
98
|
+
from features
|
99
|
+
end
|
100
|
+
|
101
|
+
self_result = gs.query do
|
102
|
+
select :self
|
103
|
+
from features
|
104
|
+
end
|
105
|
+
|
106
|
+
expect(self_result).to eq(default_result)
|
107
|
+
end
|
108
|
+
|
109
|
+
end
|
110
|
+
|
111
|
+
|
112
|
+
it 'complains if an unknown normal attribute is queried' do
|
113
|
+
gs = CQL::Repository.new("#{CQL_FEATURE_FIXTURES_DIRECTORY}/scenario/simple")
|
114
|
+
|
115
|
+
expect {
|
116
|
+
gs.query do
|
117
|
+
select steps
|
118
|
+
from features
|
119
|
+
end
|
120
|
+
}.to raise_error(ArgumentError, "'steps' is not a valid attribute for selection from a 'CukeModeler::Feature'.")
|
121
|
+
end
|
122
|
+
|
123
|
+
|
124
|
+
describe "multiple selections" do
|
125
|
+
|
126
|
+
it 'can freely mix empty selections and attribute selections' do
|
127
|
+
gs = CQL::Repository.new("#{CQL_FEATURE_FIXTURES_DIRECTORY}/scenario/simple")
|
128
|
+
|
129
|
+
base_result = gs.query do
|
130
|
+
select :self
|
131
|
+
select name
|
132
|
+
select :self
|
133
|
+
as 'foo', 'bar', 'baz'
|
134
|
+
from scenarios
|
135
|
+
end
|
136
|
+
|
137
|
+
|
138
|
+
expect(
|
139
|
+
gs.query do
|
140
|
+
select
|
141
|
+
select name
|
142
|
+
select
|
143
|
+
as 'foo', 'bar', 'baz'
|
144
|
+
from scenarios
|
145
|
+
end
|
146
|
+
).to eq(base_result)
|
147
|
+
end
|
148
|
+
|
149
|
+
end
|
150
|
+
|
151
|
+
|
152
|
+
describe 'duplicate selections' do
|
153
|
+
|
154
|
+
let(:warning_message) { "Multiple selections made without using an 'as' clause\n" }
|
155
|
+
|
156
|
+
it "warns if the same attribute is selected more than once without an 'as' clause being used" do
|
157
|
+
gs = CQL::Repository.new("#{CQL_FEATURE_FIXTURES_DIRECTORY}/scenario/simple")
|
158
|
+
|
159
|
+
expect {
|
160
|
+
gs.query do
|
161
|
+
select :model, :model, :model
|
162
|
+
from :all
|
163
|
+
end
|
164
|
+
}.to output(warning_message).to_stderr
|
165
|
+
end
|
166
|
+
|
167
|
+
it "does not warn if the same attribute is selected more than once and an 'as' clause is used" do
|
168
|
+
gs = CQL::Repository.new("#{CQL_FEATURE_FIXTURES_DIRECTORY}/scenario/simple")
|
169
|
+
|
170
|
+
expect {
|
171
|
+
gs.query do
|
172
|
+
select :model, :model, :model
|
173
|
+
# Usage of the clause is sufficient. Not going to try and count the mappings or anything like that.
|
174
|
+
as foo
|
175
|
+
from :all
|
176
|
+
end
|
177
|
+
}.to_not output(warning_message).to_stderr
|
178
|
+
end
|
179
|
+
|
180
|
+
end
|
181
|
+
|
182
|
+
end
|
183
|
+
|
184
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require "#{File.dirname(__FILE__)}/../spec_helper"
|
2
|
+
|
3
|
+
|
4
|
+
describe 'an object that uses the DSL' do
|
5
|
+
|
6
|
+
|
7
|
+
let(:nodule) { CQL::Dsl }
|
8
|
+
let(:dsl_enabled_object) { Object.new.extend(nodule) }
|
9
|
+
|
10
|
+
|
11
|
+
describe "transform" do
|
12
|
+
|
13
|
+
describe "multiple targets" do
|
14
|
+
|
15
|
+
it 'does not apply more transforms than have been declared' do
|
16
|
+
gs = CQL::Repository.new("#{CQL_FEATURE_FIXTURES_DIRECTORY}/scenario/simple")
|
17
|
+
|
18
|
+
results = gs.query do
|
19
|
+
select :self, :self, :self
|
20
|
+
as thing1, thing2, thing3
|
21
|
+
from scenarios
|
22
|
+
transform :self => lambda { |thing1| 1 }
|
23
|
+
transform :self => lambda { |thing2| 2 }
|
24
|
+
end
|
25
|
+
|
26
|
+
expect(results.first).to include('thing1' => 1, 'thing2' => 2)
|
27
|
+
expect(results.first).to_not include('thing3' => 1)
|
28
|
+
expect(results.first).to_not include('thing3' => 2)
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
@@ -0,0 +1,84 @@
|
|
1
|
+
require "#{File.dirname(__FILE__)}/../spec_helper"
|
2
|
+
|
3
|
+
|
4
|
+
describe 'an object that uses the DSL' do
|
5
|
+
|
6
|
+
let(:nodule) { CQL::Dsl }
|
7
|
+
let(:dsl_enabled_object) { Object.new.extend(nodule) }
|
8
|
+
|
9
|
+
|
10
|
+
describe 'with' do
|
11
|
+
|
12
|
+
it 'knows how to filter selections with certain qualities' do
|
13
|
+
expect(dsl_enabled_object).to respond_to(:with)
|
14
|
+
end
|
15
|
+
|
16
|
+
|
17
|
+
describe 'targeted' do
|
18
|
+
|
19
|
+
it 'can handle predefined filters' do
|
20
|
+
gs = CQL::Repository.new(CQL_FEATURE_FIXTURES_DIRECTORY)
|
21
|
+
|
22
|
+
expect {
|
23
|
+
gs.query do
|
24
|
+
select name
|
25
|
+
from features, scenarios, outlines
|
26
|
+
with scenarios => name(/test/)
|
27
|
+
end
|
28
|
+
}.to_not raise_error
|
29
|
+
end
|
30
|
+
|
31
|
+
it 'can handle a block filter' do
|
32
|
+
gs = CQL::Repository.new(CQL_FEATURE_FIXTURES_DIRECTORY)
|
33
|
+
|
34
|
+
expect {
|
35
|
+
gs.query do
|
36
|
+
select name
|
37
|
+
from features, scenarios, outlines
|
38
|
+
with scenarios => lambda { |scenario| true }
|
39
|
+
end
|
40
|
+
}.to_not raise_error
|
41
|
+
end
|
42
|
+
|
43
|
+
it 'correctly filters with a targeted block' do
|
44
|
+
gs = CQL::Repository.new(CQL_FEATURE_FIXTURES_DIRECTORY)
|
45
|
+
|
46
|
+
result = gs.query do
|
47
|
+
select name
|
48
|
+
from scenarios
|
49
|
+
with scenarios => lambda { |scenario| scenario.name =~ /king of/ }
|
50
|
+
end
|
51
|
+
|
52
|
+
expect(result).to eq([{'name' => 'The king of kings'}])
|
53
|
+
end
|
54
|
+
|
55
|
+
it 'can handle shorthand targets' do
|
56
|
+
gs = CQL::Repository.new(CQL_FEATURE_FIXTURES_DIRECTORY)
|
57
|
+
|
58
|
+
expect {
|
59
|
+
gs.query do
|
60
|
+
select name
|
61
|
+
from features, scenarios, outlines
|
62
|
+
with scenarios => name(/test/)
|
63
|
+
end
|
64
|
+
}.to_not raise_error
|
65
|
+
end
|
66
|
+
|
67
|
+
it 'can handle multiple targets' do
|
68
|
+
gs = CQL::Repository.new(CQL_FEATURE_FIXTURES_DIRECTORY)
|
69
|
+
|
70
|
+
expect {
|
71
|
+
gs.query do
|
72
|
+
select name
|
73
|
+
from features, scenarios, outlines
|
74
|
+
with scenarios => lambda { |scenario| true },
|
75
|
+
outlines => lambda { |outline| true }
|
76
|
+
end
|
77
|
+
}.to_not raise_error
|
78
|
+
end
|
79
|
+
|
80
|
+
end
|
81
|
+
|
82
|
+
end
|
83
|
+
|
84
|
+
end
|
@@ -0,0 +1,171 @@
|
|
1
|
+
require "#{File.dirname(__FILE__)}/../spec_helper"
|
2
|
+
|
3
|
+
|
4
|
+
describe 'an object that uses the DSL' do
|
5
|
+
|
6
|
+
let(:nodule) { CQL::Dsl }
|
7
|
+
let(:dsl_enabled_object) { Object.new.extend(nodule) }
|
8
|
+
|
9
|
+
|
10
|
+
describe 'without' do
|
11
|
+
|
12
|
+
it 'knows how to filter selections without certain qualities' do
|
13
|
+
expect(dsl_enabled_object).to respond_to(:without)
|
14
|
+
end
|
15
|
+
|
16
|
+
it 'correctly negates a block filter' do
|
17
|
+
gs = CQL::Repository.new("#{CQL_FEATURE_FIXTURES_DIRECTORY}/scenario/simple")
|
18
|
+
|
19
|
+
negated_result = gs.query do
|
20
|
+
select name
|
21
|
+
from scenarios
|
22
|
+
with { |scenario| !(scenario.source_line == 3) }
|
23
|
+
end
|
24
|
+
|
25
|
+
without_result = gs.query do
|
26
|
+
select name
|
27
|
+
from scenarios
|
28
|
+
without { |scenario| scenario.source_line == 3 }
|
29
|
+
end
|
30
|
+
|
31
|
+
expect(without_result).to eq(negated_result)
|
32
|
+
end
|
33
|
+
|
34
|
+
it 'correctly negates a targeted filter' do
|
35
|
+
gs = CQL::Repository.new("#{CQL_FEATURE_FIXTURES_DIRECTORY}/scenario/simple")
|
36
|
+
|
37
|
+
negated_result = gs.query do
|
38
|
+
select :model
|
39
|
+
from features, scenarios
|
40
|
+
with scenarios => lambda { |scenario| false }
|
41
|
+
end
|
42
|
+
|
43
|
+
without_result = gs.query do
|
44
|
+
select :model
|
45
|
+
from features, scenarios
|
46
|
+
without scenarios => lambda { |scenario| true }
|
47
|
+
end
|
48
|
+
|
49
|
+
expect(without_result).to eq(negated_result)
|
50
|
+
end
|
51
|
+
|
52
|
+
|
53
|
+
describe 'negating predefined filters' do
|
54
|
+
|
55
|
+
it 'correctly negates a tag count filter' do
|
56
|
+
gs = CQL::Repository.new("#{CQL_FEATURE_FIXTURES_DIRECTORY}/scenario/tags2")
|
57
|
+
|
58
|
+
negated_result = gs.query do
|
59
|
+
select :model
|
60
|
+
from scenarios
|
61
|
+
with tc lt 2
|
62
|
+
end
|
63
|
+
|
64
|
+
without_result = gs.query do
|
65
|
+
select :model
|
66
|
+
from scenarios
|
67
|
+
without tc gt 1
|
68
|
+
end
|
69
|
+
|
70
|
+
expect(without_result).to eq(negated_result)
|
71
|
+
end
|
72
|
+
|
73
|
+
it 'correctly negates a name filter' do
|
74
|
+
gs = CQL::Repository.new("#{CQL_FEATURE_FIXTURES_DIRECTORY}/scenario/name_filter")
|
75
|
+
|
76
|
+
negated_result = gs.query do
|
77
|
+
select :model
|
78
|
+
from scenarios
|
79
|
+
with name /name[^1]/
|
80
|
+
end
|
81
|
+
|
82
|
+
without_result = gs.query do
|
83
|
+
select :model
|
84
|
+
from scenarios
|
85
|
+
without name /name1/
|
86
|
+
end
|
87
|
+
|
88
|
+
expect(without_result).to eq(negated_result)
|
89
|
+
end
|
90
|
+
|
91
|
+
it 'correctly negates a line filter' do
|
92
|
+
gs = CQL::Repository.new("#{CQL_FEATURE_FIXTURES_DIRECTORY}/scenario/line_filter")
|
93
|
+
|
94
|
+
negated_result = gs.query do
|
95
|
+
select name
|
96
|
+
from scenarios
|
97
|
+
with line 'green eggs and ham'
|
98
|
+
end
|
99
|
+
|
100
|
+
without_result = gs.query do
|
101
|
+
select name
|
102
|
+
from scenarios
|
103
|
+
without line 'some other phrase'
|
104
|
+
end
|
105
|
+
|
106
|
+
expect(without_result).to eq(negated_result)
|
107
|
+
end
|
108
|
+
|
109
|
+
it 'correctly negates a tag filter' do
|
110
|
+
gs = CQL::Repository.new("#{CQL_FEATURE_FIXTURES_DIRECTORY}/scenario/tags3")
|
111
|
+
|
112
|
+
negated_result = gs.query do
|
113
|
+
select :model
|
114
|
+
from scenarios
|
115
|
+
with tags '@one'
|
116
|
+
end
|
117
|
+
|
118
|
+
without_result = gs.query do
|
119
|
+
select :model
|
120
|
+
from scenarios
|
121
|
+
without tags '@two'
|
122
|
+
end
|
123
|
+
|
124
|
+
expect(without_result).to eq(negated_result)
|
125
|
+
end
|
126
|
+
|
127
|
+
end
|
128
|
+
|
129
|
+
it 'correctly negates a targeted, predefined filter' do
|
130
|
+
gs = CQL::Repository.new(CQL_FEATURE_FIXTURES_DIRECTORY)
|
131
|
+
|
132
|
+
negated_result = gs.query do
|
133
|
+
select :model
|
134
|
+
from :all
|
135
|
+
with scenarios => name(/(?!test)/)
|
136
|
+
end
|
137
|
+
|
138
|
+
without_result = gs.query do
|
139
|
+
select :model
|
140
|
+
from :all
|
141
|
+
without scenarios => name(/test/)
|
142
|
+
end
|
143
|
+
|
144
|
+
expect(without_result).to eq(negated_result)
|
145
|
+
end
|
146
|
+
|
147
|
+
it 'correctly negates multiple filters' do
|
148
|
+
gs = CQL::Repository.new(CQL_FEATURE_FIXTURES_DIRECTORY)
|
149
|
+
|
150
|
+
negated_result = gs.query do
|
151
|
+
select :model
|
152
|
+
from :all
|
153
|
+
with scenarios => lambda { |scenario| false },
|
154
|
+
outlines => lambda { |outline| false }
|
155
|
+
with { |model| !model.is_a?(CukeModeler::Example) }
|
156
|
+
end
|
157
|
+
|
158
|
+
without_result = gs.query do
|
159
|
+
select :model
|
160
|
+
from :all
|
161
|
+
without scenarios => lambda { |scenario| true },
|
162
|
+
outlines => lambda { |outline| true }
|
163
|
+
without { |model| model.is_a?(CukeModeler::Example) }
|
164
|
+
end
|
165
|
+
|
166
|
+
expect(without_result).to eq(negated_result)
|
167
|
+
end
|
168
|
+
|
169
|
+
end
|
170
|
+
|
171
|
+
end
|