cql 0.1.9 → 0.2.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.
- data/lib/cql.rb +63 -62
- data/lib/dsl.rb +110 -110
- data/lib/feature_filters.rb +72 -72
- data/lib/map_reduce.rb +40 -39
- data/lib/sso_filters.rb +72 -72
- data/spec/filter_feature_dsl_spec.rb +485 -485
- data/spec/filter_sso_spec.rb +287 -287
- data/spec/map_reduce_spec.rb +131 -131
- data/spec/multiple_queries_spec.rb +28 -0
- data/spec/select_feature_dsl_spec.rb +49 -49
- data/spec/select_scen_outline_dsl_spec.rb +125 -125
- data/spec/select_scenario_dsl_spec.rb +72 -72
- metadata +9 -20
- data/spec/unit_spec.rb +0 -22
data/lib/cql.rb
CHANGED
@@ -1,63 +1,64 @@
|
|
1
|
-
require 'gherkin/parser/parser'
|
2
|
-
require 'gherkin/formatter/json_formatter'
|
3
|
-
require 'stringio'
|
4
|
-
require
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
@data =
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
1
|
+
require 'gherkin/parser/parser'
|
2
|
+
require 'gherkin/formatter/json_formatter'
|
3
|
+
require 'stringio'
|
4
|
+
require 'deep_clone'
|
5
|
+
require File.dirname(__FILE__) + "/dsl"
|
6
|
+
|
7
|
+
module CQL
|
8
|
+
|
9
|
+
class Query
|
10
|
+
include Dsl
|
11
|
+
attr_reader :data, :what
|
12
|
+
|
13
|
+
def format_to_ary_of_hsh data
|
14
|
+
result = Array.new(data.size).map { |e| {} }
|
15
|
+
@what.each do |w|
|
16
|
+
CQL::MapReduce.send(w, data).each_with_index { |e, i| result[i][w]=e }
|
17
|
+
end
|
18
|
+
result
|
19
|
+
end
|
20
|
+
|
21
|
+
def initialize features, &block
|
22
|
+
@data = features
|
23
|
+
@data = self.instance_eval(&block)
|
24
|
+
|
25
|
+
#getting the children of features
|
26
|
+
@data= CQL::MapReduce.feature_children(@data, 'what'=>@from[0, @from.size-1]) if @from != "features"
|
27
|
+
|
28
|
+
@data= format_to_ary_of_hsh(@data)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
|
33
|
+
class Repository
|
34
|
+
attr_reader :parsed_feature_files
|
35
|
+
|
36
|
+
def initialize features_home_dir
|
37
|
+
@parsed_feature_files = load_features list_features features_home_dir
|
38
|
+
end
|
39
|
+
|
40
|
+
def query &block
|
41
|
+
Query.new(parsed_feature_files.__deep_clone__, &block).data
|
42
|
+
end
|
43
|
+
|
44
|
+
private
|
45
|
+
def list_features base_dir
|
46
|
+
require 'find'
|
47
|
+
res = []
|
48
|
+
Find.find(base_dir) do |f|
|
49
|
+
res << f if f.match(/\.feature\Z/)
|
50
|
+
end
|
51
|
+
res
|
52
|
+
end
|
53
|
+
|
54
|
+
def load_features sources
|
55
|
+
io = StringIO.new
|
56
|
+
formatter = Gherkin::Formatter::JSONFormatter.new(io)
|
57
|
+
parser = Gherkin::Parser::Parser.new(formatter)
|
58
|
+
sources.each { |s| parser.parse(IO.read(s), s, 0) }
|
59
|
+
formatter.done
|
60
|
+
JSON.parse(io.string)
|
61
|
+
end
|
62
|
+
|
63
|
+
end
|
63
64
|
end
|
data/lib/dsl.rb
CHANGED
@@ -1,111 +1,111 @@
|
|
1
|
-
require File.dirname(__FILE__) + "/map_reduce"
|
2
|
-
module CQL
|
3
|
-
module Dsl
|
4
|
-
#Select clause
|
5
|
-
def select *what
|
6
|
-
@what = what
|
7
|
-
end
|
8
|
-
|
9
|
-
(CQL::QUERY_VALUES + %w(all step_lines examples)).each do |method_name|
|
10
|
-
define_method(method_name) { |*args|
|
11
|
-
return method_name if args.size == 0
|
12
|
-
{method_name=>args}
|
13
|
-
}
|
14
|
-
end
|
15
|
-
|
16
|
-
alias :everything :all
|
17
|
-
alias :complete :all
|
18
|
-
|
19
|
-
def name *args
|
20
|
-
return 'name' if args.size == 0
|
21
|
-
CQL::NameFilter.new args[0]
|
22
|
-
end
|
23
|
-
|
24
|
-
def line *args
|
25
|
-
return 'line' if args.size == 0
|
26
|
-
CQL::LineFilter.new args.first
|
27
|
-
end
|
28
|
-
|
29
|
-
#from clause
|
30
|
-
def from where
|
31
|
-
@from = where
|
32
|
-
@data
|
33
|
-
end
|
34
|
-
|
35
|
-
%w(features scenario_outlines scenarios).each do |method_name|
|
36
|
-
define_method(method_name) { |*args|
|
37
|
-
return method_name if args.size == 0
|
38
|
-
{method_name=>args}
|
39
|
-
}
|
40
|
-
end
|
41
|
-
|
42
|
-
#with clause
|
43
|
-
def with filter
|
44
|
-
@data = filter.execute(@data)
|
45
|
-
end
|
46
|
-
|
47
|
-
class Comparison
|
48
|
-
attr_accessor :op, :amount
|
49
|
-
|
50
|
-
def initialize op, amount
|
51
|
-
@op = op
|
52
|
-
@amount = amount
|
53
|
-
end
|
54
|
-
|
55
|
-
def operator
|
56
|
-
{"lt"=>'<', 'lte'=>'<=', 'gt'=>'>', 'gte'=>'>='}[@op]
|
57
|
-
end
|
58
|
-
|
59
|
-
end
|
60
|
-
|
61
|
-
def tc comparison
|
62
|
-
if @from == 'features'
|
63
|
-
FeatureTagCountFilter.new('tc', comparison)
|
64
|
-
else
|
65
|
-
SsoTagCountFilter.new 'tc', comparison
|
66
|
-
end
|
67
|
-
end
|
68
|
-
|
69
|
-
def lc comparison
|
70
|
-
CQL::SsoLineCountFilter.new('lc', comparison)
|
71
|
-
end
|
72
|
-
|
73
|
-
def ssoc comparison
|
74
|
-
Filter.new('ssoc', comparison)
|
75
|
-
end
|
76
|
-
|
77
|
-
def sc comparison
|
78
|
-
Filter.new('sc', comparison)
|
79
|
-
end
|
80
|
-
|
81
|
-
def soc comparison
|
82
|
-
Filter.new('soc', comparison)
|
83
|
-
end
|
84
|
-
|
85
|
-
def gt amount
|
86
|
-
Comparison.new 'gt', amount
|
87
|
-
end
|
88
|
-
|
89
|
-
def gte amount
|
90
|
-
Comparison.new 'gte', amount
|
91
|
-
end
|
92
|
-
|
93
|
-
def lt amount
|
94
|
-
Comparison.new 'lt', amount
|
95
|
-
end
|
96
|
-
|
97
|
-
def lte amount
|
98
|
-
Comparison.new 'lte', amount
|
99
|
-
end
|
100
|
-
|
101
|
-
def tags *tags
|
102
|
-
return "tags" if tags.size == 0
|
103
|
-
if @from == 'features'
|
104
|
-
FeatureTagFilter.new tags
|
105
|
-
else
|
106
|
-
CQL::SsoTagFilter.new tags
|
107
|
-
end
|
108
|
-
end
|
109
|
-
|
110
|
-
end
|
1
|
+
require File.dirname(__FILE__) + "/map_reduce"
|
2
|
+
module CQL
|
3
|
+
module Dsl
|
4
|
+
#Select clause
|
5
|
+
def select *what
|
6
|
+
@what = what
|
7
|
+
end
|
8
|
+
|
9
|
+
(CQL::QUERY_VALUES + %w(all step_lines examples)).each do |method_name|
|
10
|
+
define_method(method_name) { |*args|
|
11
|
+
return method_name if args.size == 0
|
12
|
+
{method_name=>args}
|
13
|
+
}
|
14
|
+
end
|
15
|
+
|
16
|
+
alias :everything :all
|
17
|
+
alias :complete :all
|
18
|
+
|
19
|
+
def name *args
|
20
|
+
return 'name' if args.size == 0
|
21
|
+
CQL::NameFilter.new args[0]
|
22
|
+
end
|
23
|
+
|
24
|
+
def line *args
|
25
|
+
return 'line' if args.size == 0
|
26
|
+
CQL::LineFilter.new args.first
|
27
|
+
end
|
28
|
+
|
29
|
+
#from clause
|
30
|
+
def from where
|
31
|
+
@from = where
|
32
|
+
@data
|
33
|
+
end
|
34
|
+
|
35
|
+
%w(features scenario_outlines scenarios).each do |method_name|
|
36
|
+
define_method(method_name) { |*args|
|
37
|
+
return method_name if args.size == 0
|
38
|
+
{method_name=>args}
|
39
|
+
}
|
40
|
+
end
|
41
|
+
|
42
|
+
#with clause
|
43
|
+
def with filter
|
44
|
+
@data = filter.execute(@data)
|
45
|
+
end
|
46
|
+
|
47
|
+
class Comparison
|
48
|
+
attr_accessor :op, :amount
|
49
|
+
|
50
|
+
def initialize op, amount
|
51
|
+
@op = op
|
52
|
+
@amount = amount
|
53
|
+
end
|
54
|
+
|
55
|
+
def operator
|
56
|
+
{"lt"=>'<', 'lte'=>'<=', 'gt'=>'>', 'gte'=>'>='}[@op]
|
57
|
+
end
|
58
|
+
|
59
|
+
end
|
60
|
+
|
61
|
+
def tc comparison
|
62
|
+
if @from == 'features'
|
63
|
+
FeatureTagCountFilter.new('tc', comparison)
|
64
|
+
else
|
65
|
+
SsoTagCountFilter.new 'tc', comparison
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def lc comparison
|
70
|
+
CQL::SsoLineCountFilter.new('lc', comparison)
|
71
|
+
end
|
72
|
+
|
73
|
+
def ssoc comparison
|
74
|
+
Filter.new('ssoc', comparison)
|
75
|
+
end
|
76
|
+
|
77
|
+
def sc comparison
|
78
|
+
Filter.new('sc', comparison)
|
79
|
+
end
|
80
|
+
|
81
|
+
def soc comparison
|
82
|
+
Filter.new('soc', comparison)
|
83
|
+
end
|
84
|
+
|
85
|
+
def gt amount
|
86
|
+
Comparison.new 'gt', amount
|
87
|
+
end
|
88
|
+
|
89
|
+
def gte amount
|
90
|
+
Comparison.new 'gte', amount
|
91
|
+
end
|
92
|
+
|
93
|
+
def lt amount
|
94
|
+
Comparison.new 'lt', amount
|
95
|
+
end
|
96
|
+
|
97
|
+
def lte amount
|
98
|
+
Comparison.new 'lte', amount
|
99
|
+
end
|
100
|
+
|
101
|
+
def tags *tags
|
102
|
+
return "tags" if tags.size == 0
|
103
|
+
if @from == 'features'
|
104
|
+
FeatureTagFilter.new tags
|
105
|
+
else
|
106
|
+
CQL::SsoTagFilter.new tags
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
end
|
111
111
|
end
|
data/lib/feature_filters.rb
CHANGED
@@ -1,73 +1,73 @@
|
|
1
|
-
module CQL
|
2
|
-
class NameFilter
|
3
|
-
attr_reader :name
|
4
|
-
|
5
|
-
def initialize name
|
6
|
-
@name = name
|
7
|
-
end
|
8
|
-
|
9
|
-
def execute input
|
10
|
-
if name.class == String
|
11
|
-
input = input.find_all { |feature| feature['name'] == name }
|
12
|
-
elsif name.class == Regexp
|
13
|
-
input = input.find_all { |feature| feature['name'] =~ name }
|
14
|
-
end
|
15
|
-
input
|
16
|
-
end
|
17
|
-
end
|
18
|
-
|
19
|
-
class Filter
|
20
|
-
attr_reader :type, :comparison
|
21
|
-
|
22
|
-
def initialize type, comparison
|
23
|
-
@type = type
|
24
|
-
@comparison = comparison
|
25
|
-
end
|
26
|
-
|
27
|
-
def full_type
|
28
|
-
{"sc"=>["Scenario"], "soc"=>["Scenario Outline"], "ssoc"=>["Scenario", "Scenario Outline"]}[@type]
|
29
|
-
end
|
30
|
-
|
31
|
-
def execute input
|
32
|
-
input.find_all do |feature|
|
33
|
-
size = feature['elements'].find_all { |e| full_type.include? e['keyword'] }.size
|
34
|
-
size.send(comparison.operator, comparison.amount)
|
35
|
-
end
|
36
|
-
end
|
37
|
-
|
38
|
-
end
|
39
|
-
|
40
|
-
class FeatureTagCountFilter < Filter
|
41
|
-
def execute input
|
42
|
-
input.find_all do |feature|
|
43
|
-
feature['tags'] && feature['tags'].size.send(comparison.operator, comparison.amount)
|
44
|
-
end
|
45
|
-
end
|
46
|
-
end
|
47
|
-
|
48
|
-
class TagFilter
|
49
|
-
attr_reader :tags
|
50
|
-
|
51
|
-
def initialize tags
|
52
|
-
@tags = tags
|
53
|
-
end
|
54
|
-
|
55
|
-
def has_tags given, search
|
56
|
-
return false if given == nil
|
57
|
-
search.count do |tag_for_search|
|
58
|
-
given.map { |t| t["name"] }.include?(tag_for_search)
|
59
|
-
end ==search.size
|
60
|
-
end
|
61
|
-
end
|
62
|
-
|
63
|
-
class FeatureTagFilter < TagFilter
|
64
|
-
def initialize tags
|
65
|
-
super tags
|
66
|
-
end
|
67
|
-
|
68
|
-
def execute input
|
69
|
-
input.find_all { |feature| has_tags feature['tags'], tags }
|
70
|
-
end
|
71
|
-
end
|
72
|
-
|
1
|
+
module CQL
|
2
|
+
class NameFilter
|
3
|
+
attr_reader :name
|
4
|
+
|
5
|
+
def initialize name
|
6
|
+
@name = name
|
7
|
+
end
|
8
|
+
|
9
|
+
def execute input
|
10
|
+
if name.class == String
|
11
|
+
input = input.find_all { |feature| feature['name'] == name }
|
12
|
+
elsif name.class == Regexp
|
13
|
+
input = input.find_all { |feature| feature['name'] =~ name }
|
14
|
+
end
|
15
|
+
input
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
class Filter
|
20
|
+
attr_reader :type, :comparison
|
21
|
+
|
22
|
+
def initialize type, comparison
|
23
|
+
@type = type
|
24
|
+
@comparison = comparison
|
25
|
+
end
|
26
|
+
|
27
|
+
def full_type
|
28
|
+
{"sc"=>["Scenario"], "soc"=>["Scenario Outline"], "ssoc"=>["Scenario", "Scenario Outline"]}[@type]
|
29
|
+
end
|
30
|
+
|
31
|
+
def execute input
|
32
|
+
input.find_all do |feature|
|
33
|
+
size = feature['elements'].find_all { |e| full_type.include? e['keyword'] }.size
|
34
|
+
size.send(comparison.operator, comparison.amount)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
39
|
+
|
40
|
+
class FeatureTagCountFilter < Filter
|
41
|
+
def execute input
|
42
|
+
input.find_all do |feature|
|
43
|
+
feature['tags'] && feature['tags'].size.send(comparison.operator, comparison.amount)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
class TagFilter
|
49
|
+
attr_reader :tags
|
50
|
+
|
51
|
+
def initialize tags
|
52
|
+
@tags = tags
|
53
|
+
end
|
54
|
+
|
55
|
+
def has_tags given, search
|
56
|
+
return false if given == nil
|
57
|
+
search.count do |tag_for_search|
|
58
|
+
given.map { |t| t["name"] }.include?(tag_for_search)
|
59
|
+
end ==search.size
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
class FeatureTagFilter < TagFilter
|
64
|
+
def initialize tags
|
65
|
+
super tags
|
66
|
+
end
|
67
|
+
|
68
|
+
def execute input
|
69
|
+
input.find_all { |feature| has_tags feature['tags'], tags }
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
73
|
end
|