cql 1.4.0 → 1.6.0

Sign up to get free protection for your applications and to get access to all the features.
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