cql 1.4.0 → 1.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.
Files changed (52) hide show
  1. checksums.yaml +5 -5
  2. data/lib/cql.rb +4 -169
  3. data/lib/cql/dsl.rb +39 -5
  4. data/lib/cql/feature_filters.rb +2 -0
  5. data/lib/cql/filters.rb +25 -1
  6. data/lib/cql/map_reduce.rb +3 -0
  7. data/lib/cql/model_dsl.rb +7 -1
  8. data/lib/cql/queriable.rb +6 -1
  9. data/lib/cql/query.rb +157 -0
  10. data/lib/cql/repository.rb +25 -0
  11. data/lib/cql/sso_filters.rb +4 -0
  12. data/lib/cql/version.rb +2 -1
  13. data/testing/cucumber/features/clauses/as_clause.feature +10 -9
  14. data/testing/cucumber/features/clauses/from_clause.feature +15 -20
  15. data/testing/cucumber/features/clauses/predefined_with_filters.feature +392 -0
  16. data/testing/cucumber/features/clauses/select_clause.feature +11 -14
  17. data/testing/cucumber/features/clauses/transform_clause.feature +10 -9
  18. data/testing/cucumber/features/clauses/with_clause.feature +10 -170
  19. data/testing/cucumber/features/dsl.feature +15 -34
  20. data/testing/cucumber/step_definitions/setup_steps.rb +1 -13
  21. data/testing/cucumber/step_definitions/verification_steps.rb +6 -7
  22. data/testing/cucumber/support/env.rb +9 -9
  23. data/testing/gemfiles/cuke_modeler0.gemfile +10 -7
  24. data/testing/gemfiles/cuke_modeler1.gemfile +6 -7
  25. data/testing/gemfiles/cuke_modeler2.gemfile +33 -0
  26. data/testing/gemfiles/cuke_modeler3.gemfile +10 -0
  27. data/testing/helper_methods.rb +13 -0
  28. data/testing/model_helper.rb +28 -0
  29. data/testing/rspec/spec/clauses/as_clause_spec.rb +1 -0
  30. data/testing/rspec/spec/clauses/from_clause_spec.rb +146 -0
  31. data/testing/rspec/spec/clauses/select_clause_spec.rb +184 -0
  32. data/testing/rspec/spec/clauses/transform_clause_spec.rb +35 -0
  33. data/testing/rspec/spec/clauses/with_clause_spec.rb +84 -0
  34. data/testing/rspec/spec/clauses/without_clause_spec.rb +171 -0
  35. data/testing/rspec/spec/cql_spec.rb +25 -0
  36. data/testing/rspec/spec/dsl_spec.rb +3 -575
  37. data/testing/rspec/spec/filter_example_spec.rb +1 -1
  38. data/testing/rspec/spec/filter_feature_dsl_spec.rb +13 -13
  39. data/testing/rspec/spec/filter_sso_spec.rb +2 -2
  40. data/testing/rspec/spec/line_filterable_specs.rb +1 -1
  41. data/testing/rspec/spec/map_reduce_spec.rb +1 -1
  42. data/testing/rspec/spec/model_query_spec.rb +1 -1
  43. data/testing/rspec/spec/multiple_queries_spec.rb +1 -1
  44. data/testing/rspec/spec/name_filterable_specs.rb +1 -1
  45. data/testing/rspec/spec/predefined_filters_spec.rb +284 -0
  46. data/testing/rspec/spec/repository_spec.rb +3 -3
  47. data/testing/rspec/spec/select_feature_dsl_spec.rb +8 -8
  48. data/testing/rspec/spec/select_scen_outline_dsl_spec.rb +14 -14
  49. data/testing/rspec/spec/select_scenario_dsl_spec.rb +9 -9
  50. data/testing/rspec/spec/spec_helper.rb +7 -17
  51. metadata +52 -23
  52. data/testing/cucumber/support/transforms.rb +0 -3
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: fe541449ce515566bd3a3483b42f2260829a03e1
4
- data.tar.gz: 846f80e853bef0ba8d441187370ce948e6cca50b
2
+ SHA256:
3
+ metadata.gz: 2cef04f054cecd8e489f46daa063be8ac02360c53f5d7d8fe8e551ce337e5d34
4
+ data.tar.gz: 6714fecd35d662a966cb82f9bda4a43e308b38597834a53d03c337fe9ad1d75d
5
5
  SHA512:
6
- metadata.gz: 5f5bb7cb738155ad68f98b877d4889be5f57b69adec5c37804307aa47d29bde11c7819e3a883994e85ff3b903f636a542a575668b1cac9b299068244e3b08df6
7
- data.tar.gz: ee4e8bf2dee1d7aeb0128c65fe3001c1d21c97290b6668384d044de2066880de687a2398040616f8f000eefb6d4aed1ff269a975ae2c8f51e6769ac7364063f6
6
+ metadata.gz: 5779cca5eef6d487d88fc9089bc4374b03ccea619443f333490217fbf2b747288b7f297078d8c148969bc53c50c00ea5fa4d0f876473cb9e22afe70bbfbbe795
7
+ data.tar.gz: 4def191c2d3dd5ee166980dde04f3f05599614797d015ca242574a467dcdb1a6bab05c3b6648e70c50d5a66f8b960da6f1790cd44117ec699ee7902b040a3909
data/lib/cql.rb CHANGED
@@ -1,176 +1,11 @@
1
1
  require 'cuke_modeler'
2
2
  require 'cql/map_reduce'
3
3
  require 'cql/queriable'
4
+ require 'cql/query'
5
+ require 'cql/repository'
4
6
 
5
- module CQL
6
-
7
- class Query
8
- include Dsl
9
- attr_reader :data, :what
10
-
11
- def format_data data
12
- space_data
13
-
14
- Array.new.tap do |result_array|
15
- data.each do |element|
16
- result_array << Hash.new.tap do |result|
17
- @what.each_with_index do |attribute, index|
18
- key = determine_key(attribute, index)
19
- value = determine_value(element, attribute, index)
20
-
21
- result[key] = value
22
- end
23
- end
24
- end
25
- end
26
-
27
- end
28
-
29
- def initialize(directory, &block)
30
- # Set root object
31
- @data = directory
32
-
33
- # Populate configurables from DSL block
34
- self.instance_eval(&block)
35
-
36
-
37
- raise(ArgumentError, "A query must specify a 'select' clause") unless @what
38
- raise(ArgumentError, "A query must specify a 'from' clause") unless @from
39
-
40
- warn("Multiple selections made without using an 'as' clause") unless @name_transforms || (@what.count == @what.uniq.count)
41
-
42
- # Gather relevant objects from root object and filters
43
- @data = CQL::MapReduce.gather_objects(@data, @from, @filters)
44
-
45
- # Extract properties from gathered objects
46
- @data = format_output(@data)
47
- end
48
-
49
-
50
- private
51
-
52
-
53
- def format_output(data)
54
- format_data(data)
55
- end
56
-
57
- def determine_key(attribute, index)
58
- key = mapped_attribute(@name_transforms, attribute, index) if @name_transforms
59
-
60
- key || attribute
61
- end
62
-
63
- def determine_value(element, attribute, index)
64
- original_value = attribute.is_a?(Symbol) ? determine_special_value(element, attribute) : determine_normal_value(element, attribute)
65
-
66
- if @value_transforms
67
- value = mapped_attribute(@value_transforms, attribute, index)
68
- value = value.call(original_value) if value.is_a?(Proc)
69
- end
70
-
71
- value || original_value
72
- end
73
7
 
74
- def determine_special_value(element, attribute)
75
- # todo - Not sure what other special values to have but this could be expanded upon later.
76
- case attribute
77
- when :self, :model
78
- val = element
79
- else
80
- raise(ArgumentError, ":#{attribute} is not a valid attribute for selection.")
81
- end
8
+ # The top level namespace for CQL related code.
82
9
 
83
- val
84
- end
85
-
86
- def determine_normal_value(element, attribute)
87
- if element.respond_to?(attribute)
88
- element.send(attribute)
89
- else
90
- raise(ArgumentError, "'#{attribute}' is not a valid attribute for selection from a '#{element.class}'.")
91
- end
92
- end
93
-
94
- def mapped_attribute(mappings, attribute, location)
95
- case
96
- when mappings.is_a?(Array)
97
- value = mappings[location]
98
- when mappings.is_a?(Hash)
99
- if mappings[attribute]
100
- value = mappings[attribute][location]
101
- end
102
- else
103
- # todo - add error message
104
- end
105
-
106
- value
107
- end
108
-
109
- def space_data
110
- space_renamings
111
- space_transforms
112
- end
113
-
114
- def space_renamings
115
- if @name_transforms.is_a?(Hash)
116
- new_names = {}
117
-
118
- @name_transforms.each_pair do |key, value|
119
- new_names[key] = []
120
-
121
- @what.each do |attribute|
122
- if attribute == key
123
- new_names[key] << value.shift
124
- else
125
- new_names[key] << nil
126
- end
127
- end
128
- end
129
-
130
- @name_transforms = new_names
131
- end
132
- end
133
-
134
- def space_transforms
135
- if @value_transforms.is_a?(Hash)
136
- new_values = {}
137
-
138
- @value_transforms.each_pair do |key, value|
139
- new_values[key] = []
140
-
141
- @what.each do |attribute|
142
- if attribute == key
143
- new_values[key] << value.shift
144
- else
145
- new_values[key] << nil
146
- end
147
- end
148
- end
149
-
150
- @value_transforms = new_values
151
- end
152
- end
153
-
154
- end
155
-
156
-
157
- class Repository
158
-
159
- include Queriable
160
-
161
-
162
- def initialize(repository_root)
163
- case
164
- when repository_root.is_a?(String)
165
- root = CukeModeler::Directory.new(repository_root)
166
- when repository_root.class.to_s =~ /CukeModeler/
167
- root = repository_root
168
- else
169
- raise(ArgumentError, "Don't know how to make a repository from a #{repository_root.class}")
170
- end
171
-
172
- @query_root = root
173
- end
174
-
175
- end
10
+ module CQL
176
11
  end
@@ -1,10 +1,16 @@
1
1
  module CQL
2
+
3
+ # The Domain Specific Language used for performing queries.
4
+
2
5
  module Dsl
3
6
 
7
+
8
+ # Any undefined method is assumed to mean its String equivalent, thus allowing a more convenient query syntax.
4
9
  def method_missing(method_name)
5
10
  method_name.to_s
6
11
  end
7
12
 
13
+ # Adds a *transform* clause to the query. See the corresponding Cucumber documentation for details.
8
14
  def transform(*attribute_transforms, &block)
9
15
  # todo - Still feels like some as/transform code duplication but I think that it would get too meta if I
10
16
  # reduced it any further. Perhaps change how the transforms are handled so that there doesn't have to be
@@ -16,13 +22,14 @@ module CQL
16
22
  add_transforms(attribute_transforms, @value_transforms)
17
23
  end
18
24
 
25
+ # Adds an *as* clause to the query. See the corresponding Cucumber documentation for details.
19
26
  def as(*name_transforms)
20
27
  prep_variable('name_transforms', name_transforms) unless @name_transforms
21
28
 
22
29
  add_transforms(name_transforms, @name_transforms)
23
30
  end
24
31
 
25
- #Select clause
32
+ # Adds a *select* clause to the query. See the corresponding Cucumber documentation for details.
26
33
  def select *what
27
34
  what = [:self] if what.empty?
28
35
 
@@ -30,17 +37,19 @@ module CQL
30
37
  @what.concat(what)
31
38
  end
32
39
 
40
+ # Adds a *name* filter to the query. See the corresponding Cucumber documentation for details.
33
41
  def name *args
34
42
  return 'name' if args.size == 0
35
43
  CQL::NameFilter.new args[0]
36
44
  end
37
45
 
46
+ # Adds a *line* filter to the query. See the corresponding Cucumber documentation for details.
38
47
  def line *args
39
48
  return 'line' if args.size == 0
40
49
  CQL::LineFilter.new args.first
41
50
  end
42
51
 
43
- #from clause
52
+ # Adds a *from* clause to the query. See the corresponding Cucumber documentation for details.
44
53
  def from(*targets)
45
54
  @from ||= []
46
55
 
@@ -49,7 +58,7 @@ module CQL
49
58
  @from.concat(targets)
50
59
  end
51
60
 
52
- #with clause
61
+ # Adds a *with* clause to the query. See the corresponding Cucumber documentation for details.
53
62
  def with(*conditions, &block)
54
63
  @filters ||= []
55
64
 
@@ -59,7 +68,7 @@ module CQL
59
68
  end
60
69
  end
61
70
 
62
- #without clause
71
+ # Adds a *without* clause to the query. See the corresponding Cucumber documentation for details.
63
72
  def without(*conditions, &block)
64
73
  @filters ||= []
65
74
 
@@ -69,9 +78,15 @@ module CQL
69
78
  end
70
79
  end
71
80
 
81
+ # Not a part of the public API. Subject to change at any time.
72
82
  class Comparison
73
- attr_accessor :operator, :amount
74
83
 
84
+ # the operator used for comparison
85
+ attr_accessor :operator,
86
+ # value that will be compared against
87
+ :amount
88
+
89
+ # Creates a new comparison object
75
90
  def initialize operator, amount
76
91
  @operator = operator
77
92
  @amount = amount
@@ -79,48 +94,67 @@ module CQL
79
94
 
80
95
  end
81
96
 
97
+ # Adds a *tc* filter to the query. See the corresponding Cucumber documentation for details.
82
98
  def tc comparison
83
99
  TagCountFilter.new 'tc', comparison
84
100
  end
85
101
 
102
+ # Adds a *lc* filter to the query. See the corresponding Cucumber documentation for details.
86
103
  def lc comparison
87
104
  CQL::SsoLineCountFilter.new('lc', comparison)
88
105
  end
89
106
 
107
+ # Adds an *ssoc* filter to the query. See the corresponding Cucumber documentation for details.
90
108
  def ssoc comparison
91
109
  TestCountFilter.new([CukeModeler::Scenario, CukeModeler::Outline], comparison)
92
110
  end
93
111
 
112
+ # Adds an *sc* filter to the query. See the corresponding Cucumber documentation for details.
94
113
  def sc comparison
95
114
  TestCountFilter.new([CukeModeler::Scenario], comparison)
96
115
  end
97
116
 
117
+ # Adds an *soc* filter to the query. See the corresponding Cucumber documentation for details.
98
118
  def soc comparison
99
119
  TestCountFilter.new([CukeModeler::Outline], comparison)
100
120
  end
101
121
 
122
+ # Adds a *gt* filter operator to the query. See the corresponding Cucumber documentation for details.
102
123
  def gt amount
103
124
  Comparison.new '>', amount
104
125
  end
105
126
 
127
+ # Adds a *gte* filter operator to the query. See the corresponding Cucumber documentation for details.
106
128
  def gte amount
107
129
  Comparison.new '>=', amount
108
130
  end
109
131
 
132
+ # Adds an *lt* filter operator to the query. See the corresponding Cucumber documentation for details.
110
133
  def lt amount
111
134
  Comparison.new '<', amount
112
135
  end
113
136
 
137
+ # Adds an *lte* filter operator to the query. See the corresponding Cucumber documentation for details.
114
138
  def lte amount
115
139
  Comparison.new '<=', amount
116
140
  end
117
141
 
142
+ # Adds an *eq* filter operator to the query. See the corresponding Cucumber documentation for details.
143
+ def eq amount
144
+ Comparison.new '==', amount
145
+ end
146
+
147
+ # Adds a *tags* filter to the query. See the corresponding Cucumber documentation for details.
118
148
  def tags *tags
119
149
  return "tags" if tags.size == 0
120
150
 
121
151
  TagFilter.new tags
122
152
  end
123
153
 
154
+
155
+ private
156
+
157
+
124
158
  def translate_shorthand(where)
125
159
  where.split('_').map(&:capitalize).join
126
160
  end
@@ -3,8 +3,10 @@ require 'cql/filters'
3
3
 
4
4
  module CQL
5
5
 
6
+ # Not a part of the public API. Subject to change at any time.
6
7
  class TestCountFilter < TypeCountFilter
7
8
 
9
+ # Counts the numbers of tests of a certain type
8
10
  def type_count(feature)
9
11
  feature.tests.find_all { |test| types.include?(test.class) }.size
10
12
  end
@@ -1,12 +1,17 @@
1
1
  module CQL
2
2
 
3
+ # Not a part of the public API. Subject to change at any time.
3
4
  class TagFilter
5
+
6
+ # Tags to match
4
7
  attr_reader :tags
5
8
 
9
+ # Creates a new filter
6
10
  def initialize tags
7
11
  @tags = tags
8
12
  end
9
13
 
14
+ # Returns whether or not the object has the target tags
10
15
  def has_tags?(object, target_tags)
11
16
  target_tags.all? { |target_tag|
12
17
  tags = object.tags
@@ -15,6 +20,7 @@ module CQL
15
20
  }
16
21
  end
17
22
 
23
+ # Filters the input models so that only the desired ones are returned
18
24
  def execute(objects, negate)
19
25
  method = negate ? :reject : :select
20
26
 
@@ -23,15 +29,20 @@ module CQL
23
29
 
24
30
  end
25
31
 
32
+ # Not a part of the public API. Subject to change at any time.
26
33
  class ContentMatchFilter
34
+
35
+ # Pattern to match
27
36
  attr_reader :pattern
28
37
 
38
+ # Creates a new filter
29
39
  def initialize(pattern)
30
40
  raise(ArgumentError, "Can only match a String or Regexp. Got #{pattern.class}.") unless pattern.is_a?(String) || pattern.is_a?(Regexp)
31
41
 
32
42
  @pattern = pattern
33
43
  end
34
44
 
45
+ # Returns whether or not the content matches the pattern
35
46
  def content_match?(content)
36
47
  if pattern.is_a?(String)
37
48
  content.any? { |thing| thing == pattern }
@@ -42,14 +53,22 @@ module CQL
42
53
 
43
54
  end
44
55
 
56
+ # Not a part of the public API. Subject to change at any time.
45
57
  class TypeCountFilter
46
- attr_reader :types, :comparison
47
58
 
59
+ # the types of object that will be filtered against
60
+ attr_reader :types,
61
+ # the comparison that will be made between the objects
62
+ :comparison
63
+
64
+ # Creates a new filter
48
65
  def initialize types, comparison
49
66
  @types = types
50
67
  @comparison = comparison
51
68
  end
52
69
 
70
+ # Not a part of the public API. Subject to change at any time.
71
+ # Filters the input models so that only the desired ones are returned
53
72
  def execute(input, negate)
54
73
  method = negate ? :reject : :select
55
74
 
@@ -60,8 +79,10 @@ module CQL
60
79
 
61
80
  end
62
81
 
82
+ # Not a part of the public API. Subject to change at any time.
63
83
  class NameFilter < ContentMatchFilter
64
84
 
85
+ # Filters the input models so that only the desired ones are returned
65
86
  def execute(input, negate)
66
87
  method = negate ? :reject : :select
67
88
 
@@ -72,8 +93,11 @@ module CQL
72
93
 
73
94
  end
74
95
 
96
+
97
+ # Not a part of the public API. Subject to change at any time.
75
98
  class TagCountFilter < TypeCountFilter
76
99
 
100
+ # Counts the numbers of tags on a test
77
101
  def type_count(test)
78
102
  test.tags.size
79
103
  end