cuke_modeler 3.3.0 → 3.4.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/CHANGELOG.md +7 -1
- data/cuke_modeler.gemspec +23 -14
- data/lib/cuke_modeler.rb +1 -1
- data/lib/cuke_modeler/adapters/gherkin_10_adapter.rb +2 -1
- data/lib/cuke_modeler/adapters/gherkin_11_adapter.rb +2 -1
- data/lib/cuke_modeler/adapters/gherkin_12_adapter.rb +2 -1
- data/lib/cuke_modeler/adapters/gherkin_13_adapter.rb +2 -1
- data/lib/cuke_modeler/adapters/gherkin_14_adapter.rb +2 -1
- data/lib/cuke_modeler/adapters/gherkin_15_adapter.rb +2 -1
- data/lib/cuke_modeler/adapters/gherkin_9_adapter.rb +261 -242
- data/lib/cuke_modeler/containing.rb +31 -89
- data/lib/cuke_modeler/described.rb +40 -1
- data/lib/cuke_modeler/models/background.rb +11 -11
- data/lib/cuke_modeler/models/cell.rb +13 -7
- data/lib/cuke_modeler/models/comment.rb +5 -5
- data/lib/cuke_modeler/models/directory.rb +13 -17
- data/lib/cuke_modeler/models/doc_string.rb +10 -7
- data/lib/cuke_modeler/models/example.rb +63 -45
- data/lib/cuke_modeler/models/feature.rb +23 -16
- data/lib/cuke_modeler/models/feature_file.rb +5 -7
- data/lib/cuke_modeler/models/model.rb +2 -1
- data/lib/cuke_modeler/models/outline.rb +19 -14
- data/lib/cuke_modeler/models/row.rb +10 -7
- data/lib/cuke_modeler/models/rule.rb +11 -9
- data/lib/cuke_modeler/models/scenario.rb +17 -12
- data/lib/cuke_modeler/models/step.rb +40 -18
- data/lib/cuke_modeler/models/table.rb +9 -6
- data/lib/cuke_modeler/models/tag.rb +9 -5
- data/lib/cuke_modeler/named.rb +5 -1
- data/lib/cuke_modeler/nested.rb +22 -18
- data/lib/cuke_modeler/parsed.rb +8 -0
- data/lib/cuke_modeler/parsing.rb +36 -26
- data/lib/cuke_modeler/sourceable.rb +8 -0
- data/lib/cuke_modeler/stepped.rb +8 -0
- data/lib/cuke_modeler/taggable.rb +9 -1
- data/lib/cuke_modeler/version.rb +1 -1
- metadata +53 -33
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ab8068e33b09b4e508b0cd53f77c954052796fbbd33686070cbf6e65cd616378
|
4
|
+
data.tar.gz: 57849a93b03a7d6d0cc56548e4e6482eb61557c4b42a68950c82e3b43542e482
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3077bf8a1a1defacc92d371db01044c2ea5c7ef44dc7a194079a1e8721b4e8dad598eb4705acc4882d04a5934c27a70103a7eca2795f45ea9f5bebad37d24e7d
|
7
|
+
data.tar.gz: 0a9e2fbae81285bad22f59ef8626fd020be7516a824292fd08387eb38f34d1bc185f41d71084c1be84f331574c7d65145fa3e37ae28d8585ab5369f25adfffa5
|
data/CHANGELOG.md
CHANGED
@@ -8,6 +8,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
8
8
|
|
9
9
|
Nothing yet...
|
10
10
|
|
11
|
+
## [3.4.0] - 2020-09-02
|
12
|
+
|
13
|
+
### Added
|
14
|
+
- `Feature#has_background?` and `Rule#has_background?` now both have a more conventional name via the alias `#background?`
|
15
|
+
|
11
16
|
## [3.3.0] - 2020-08-15
|
12
17
|
|
13
18
|
### Added
|
@@ -329,7 +334,8 @@ Nothing yet...
|
|
329
334
|
- Initial release
|
330
335
|
|
331
336
|
|
332
|
-
[Unreleased]: https://github.com/enkessler/cuke_modeler/compare/v3.
|
337
|
+
[Unreleased]: https://github.com/enkessler/cuke_modeler/compare/v3.4.0...HEAD
|
338
|
+
[3.4.0]: https://github.com/enkessler/cuke_modeler/compare/v3.3.0...v3.4.0
|
333
339
|
[3.3.0]: https://github.com/enkessler/cuke_modeler/compare/v3.2.0...v3.3.0
|
334
340
|
[3.2.0]: https://github.com/enkessler/cuke_modeler/compare/v3.1.0...v3.2.0
|
335
341
|
[3.1.0]: https://github.com/enkessler/cuke_modeler/compare/v3.0.0...v3.1.0
|
data/cuke_modeler.gemspec
CHANGED
@@ -1,17 +1,21 @@
|
|
1
|
-
|
2
|
-
lib = File.expand_path('../lib', __FILE__)
|
1
|
+
lib = File.expand_path('lib', __dir__)
|
3
2
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
3
|
require 'cuke_modeler/version'
|
5
4
|
|
6
5
|
Gem::Specification.new do |spec|
|
7
|
-
spec.name =
|
6
|
+
spec.name = 'cuke_modeler'
|
8
7
|
spec.version = CukeModeler::VERSION
|
9
|
-
spec.authors = [
|
10
|
-
spec.email = [
|
11
|
-
spec.summary =
|
12
|
-
spec.description =
|
8
|
+
spec.authors = ['Eric Kessler']
|
9
|
+
spec.email = ['morrow748@gmail.com']
|
10
|
+
spec.summary = 'A gem providing functionality to model Gherkin based test suites.'
|
11
|
+
spec.description = ['This gem facilitates modeling a test suite that is written in Gherkin (e.g. Cucumber, ',
|
12
|
+
'SpecFlow, Lettuce, etc.). It does this by providing an abstraction layer on top of the ',
|
13
|
+
"Abstract Syntax Tree that the 'cucumber-gherkin' gem generates when parsing features, ",
|
14
|
+
'as well as providing models for feature files and directories in order to be able to ',
|
15
|
+
"have a fully traversable model tree of a test suite's structure. These models can then ",
|
16
|
+
'be analyzed or manipulated more easily than the underlying AST layer.'].join("\n")
|
13
17
|
spec.homepage = 'https://github.com/enkessler/cuke_modeler'
|
14
|
-
spec.license =
|
18
|
+
spec.license = 'MIT'
|
15
19
|
|
16
20
|
# Specify which files should be added to the gem when it is released.
|
17
21
|
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
@@ -20,19 +24,24 @@ Gem::Specification.new do |spec|
|
|
20
24
|
source_controlled_files.keep_if { |file| file =~ %r{^(lib|testing/cucumber/features)} }
|
21
25
|
source_controlled_files + ['README.md', 'LICENSE.txt', 'CHANGELOG.md', 'cuke_modeler.gemspec']
|
22
26
|
end
|
23
|
-
spec.require_paths = [
|
27
|
+
spec.require_paths = ['lib']
|
24
28
|
|
25
29
|
spec.required_ruby_version = '>= 2.3', '< 3.0'
|
26
30
|
|
27
31
|
spec.add_runtime_dependency 'cucumber-gherkin', '< 16.0'
|
28
32
|
|
29
33
|
spec.add_development_dependency 'bundler', '< 3.0'
|
30
|
-
spec.add_development_dependency "rake", '< 13.0.0'
|
31
|
-
spec.add_development_dependency 'cucumber', '< 5.0.0'
|
32
|
-
spec.add_development_dependency 'rspec', '~> 3.0'
|
33
|
-
spec.add_development_dependency 'simplecov', '<= 0.16.1'
|
34
|
-
spec.add_development_dependency 'racatt', '~> 1.0'
|
35
34
|
spec.add_development_dependency 'coveralls', '< 1.0.0'
|
35
|
+
# Cucumber 4.x is the earliest version to use cucumber-gherkin
|
36
|
+
spec.add_development_dependency 'cucumber', '>= 4.0.0', '< 6.0.0'
|
37
|
+
spec.add_development_dependency 'racatt', '~> 1.0'
|
36
38
|
spec.add_development_dependency 'rainbow', '< 4.0.0'
|
39
|
+
spec.add_development_dependency 'rake', '< 14.0.0'
|
40
|
+
spec.add_development_dependency 'rspec', '~> 3.0'
|
41
|
+
# RuboCop drops Ruby 2.3 support after this version and we need to maintain Ruby 2.3 compatibility when writing code
|
42
|
+
# for this gem
|
43
|
+
spec.add_development_dependency 'rubocop', '< 0.82.0'
|
44
|
+
# Coveralls gem does not support any newer version than this
|
45
|
+
spec.add_development_dependency 'simplecov', '<= 0.16.1'
|
37
46
|
spec.add_development_dependency 'test-unit', '< 4.0.0'
|
38
47
|
end
|
data/lib/cuke_modeler.rb
CHANGED
@@ -4,7 +4,8 @@ require_relative 'gherkin_9_adapter'
|
|
4
4
|
module CukeModeler
|
5
5
|
|
6
6
|
# NOT A PART OF THE PUBLIC API
|
7
|
-
# An adapter that can convert the output of version 10.x of the *cucumber-gherkin* gem into input that is consumable
|
7
|
+
# An adapter that can convert the output of version 10.x of the *cucumber-gherkin* gem into input that is consumable
|
8
|
+
# by this gem.
|
8
9
|
|
9
10
|
class Gherkin10Adapter < Gherkin9Adapter
|
10
11
|
|
@@ -4,7 +4,8 @@ require_relative 'gherkin_9_adapter'
|
|
4
4
|
module CukeModeler
|
5
5
|
|
6
6
|
# NOT A PART OF THE PUBLIC API
|
7
|
-
# An adapter that can convert the output of version 11.x of the *cucumber-gherkin* gem into input that is consumable
|
7
|
+
# An adapter that can convert the output of version 11.x of the *cucumber-gherkin* gem into input that is consumable
|
8
|
+
# by this gem.
|
8
9
|
|
9
10
|
class Gherkin11Adapter < Gherkin9Adapter
|
10
11
|
|
@@ -4,7 +4,8 @@ require_relative 'gherkin_9_adapter'
|
|
4
4
|
module CukeModeler
|
5
5
|
|
6
6
|
# NOT A PART OF THE PUBLIC API
|
7
|
-
# An adapter that can convert the output of version 12.x of the *cucumber-gherkin* gem into input that is consumable
|
7
|
+
# An adapter that can convert the output of version 12.x of the *cucumber-gherkin* gem into input that is consumable
|
8
|
+
# by this gem.
|
8
9
|
|
9
10
|
class Gherkin12Adapter < Gherkin9Adapter
|
10
11
|
|
@@ -4,7 +4,8 @@ require_relative 'gherkin_9_adapter'
|
|
4
4
|
module CukeModeler
|
5
5
|
|
6
6
|
# NOT A PART OF THE PUBLIC API
|
7
|
-
# An adapter that can convert the output of version 13.x of the *cucumber-gherkin* gem into input that is consumable
|
7
|
+
# An adapter that can convert the output of version 13.x of the *cucumber-gherkin* gem into input that is consumable
|
8
|
+
# by this gem.
|
8
9
|
|
9
10
|
class Gherkin13Adapter < Gherkin9Adapter
|
10
11
|
|
@@ -4,7 +4,8 @@ require_relative 'gherkin_9_adapter'
|
|
4
4
|
module CukeModeler
|
5
5
|
|
6
6
|
# NOT A PART OF THE PUBLIC API
|
7
|
-
# An adapter that can convert the output of version 14.x of the *cucumber-gherkin* gem into input that is consumable
|
7
|
+
# An adapter that can convert the output of version 14.x of the *cucumber-gherkin* gem into input that is consumable
|
8
|
+
# by this gem.
|
8
9
|
|
9
10
|
class Gherkin14Adapter < Gherkin9Adapter
|
10
11
|
|
@@ -4,7 +4,8 @@ require_relative 'gherkin_9_adapter'
|
|
4
4
|
module CukeModeler
|
5
5
|
|
6
6
|
# NOT A PART OF THE PUBLIC API
|
7
|
-
# An adapter that can convert the output of version 15.x of the *cucumber-gherkin* gem into input that is consumable
|
7
|
+
# An adapter that can convert the output of version 15.x of the *cucumber-gherkin* gem into input that is consumable
|
8
|
+
# by this gem.
|
8
9
|
|
9
10
|
class Gherkin15Adapter < Gherkin9Adapter
|
10
11
|
|
@@ -1,345 +1,364 @@
|
|
1
|
+
# Some things just aren't going to get better due to the inherent complexity of the AST
|
2
|
+
# rubocop:disable Metrics/ClassLength, Metrics/AbcSize, Metrics/MethodLength
|
3
|
+
|
1
4
|
module CukeModeler
|
2
5
|
|
3
6
|
# NOT A PART OF THE PUBLIC API
|
4
|
-
# An adapter that can convert the output of version 9.x of the *cucumber-gherkin* gem into input that is consumable
|
7
|
+
# An adapter that can convert the output of version 9.x of the *cucumber-gherkin* gem into input that is consumable
|
8
|
+
# by this gem.
|
5
9
|
|
6
10
|
class Gherkin9Adapter
|
7
11
|
|
8
12
|
# Adapts the given AST into the shape that this gem expects
|
9
|
-
def adapt(
|
10
|
-
|
11
|
-
parsed_ast['cuke_modeler_parsing_data'] = Marshal::load(Marshal.dump(parsed_ast))
|
12
|
-
|
13
|
-
# Removing parsed data for child elements in order to avoid duplicating data
|
14
|
-
parsed_ast['cuke_modeler_parsing_data'][:feature] = nil if parsed_ast['cuke_modeler_parsing_data'][:feature]
|
15
|
-
parsed_ast['cuke_modeler_parsing_data'][:comments] = nil if parsed_ast['cuke_modeler_parsing_data'][:comments]
|
13
|
+
def adapt(ast)
|
14
|
+
adapted_ast = {}
|
16
15
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
end
|
22
|
-
parsed_ast['comments'].concat(parsed_ast.delete(:comments))
|
23
|
-
end
|
16
|
+
# Saving off the original data and removing parsed data for child elements in order to avoid duplicating data
|
17
|
+
save_original_data(adapted_ast, ast)
|
18
|
+
clear_child_elements(adapted_ast, [[:feature],
|
19
|
+
[:comments]])
|
24
20
|
|
25
|
-
|
26
|
-
|
21
|
+
adapted_ast['comments'] = adapt_comments(ast)
|
22
|
+
adapted_ast['feature'] = adapt_feature(ast[:feature])
|
27
23
|
|
28
|
-
|
24
|
+
adapted_ast
|
29
25
|
end
|
30
26
|
|
31
27
|
# Adapts the AST sub-tree that is rooted at the given feature node.
|
32
|
-
def adapt_feature
|
33
|
-
|
34
|
-
parsed_feature['cuke_modeler_parsing_data'] = Marshal::load(Marshal.dump(parsed_feature))
|
28
|
+
def adapt_feature(feature_ast)
|
29
|
+
return nil unless feature_ast
|
35
30
|
|
36
|
-
|
37
|
-
parsed_feature['cuke_modeler_parsing_data'][:tags] = nil if parsed_feature['cuke_modeler_parsing_data'][:tags]
|
38
|
-
parsed_feature['cuke_modeler_parsing_data'][:children] = nil if parsed_feature['cuke_modeler_parsing_data'][:children]
|
31
|
+
adapted_feature = {}
|
39
32
|
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
33
|
+
# Saving off the original data and removing parsed data for child elements in order to avoid duplicating data
|
34
|
+
save_original_data(adapted_feature, feature_ast)
|
35
|
+
clear_child_elements(adapted_feature, [[:tags],
|
36
|
+
[:children]])
|
44
37
|
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
end
|
38
|
+
adapted_feature['keyword'] = feature_ast[:keyword]
|
39
|
+
adapted_feature['name'] = feature_ast[:name]
|
40
|
+
adapted_feature['description'] = feature_ast[:description] || ''
|
41
|
+
adapted_feature['line'] = feature_ast[:location][:line]
|
50
42
|
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
end
|
56
|
-
parsed_feature['tags'].concat(parsed_feature.delete(:tags))
|
57
|
-
end
|
43
|
+
adapted_feature['elements'] = adapt_child_elements(feature_ast)
|
44
|
+
adapted_feature['tags'] = adapt_tags(feature_ast)
|
45
|
+
|
46
|
+
adapted_feature
|
58
47
|
end
|
59
48
|
|
60
49
|
# Adapts the AST sub-tree that is rooted at the given background node.
|
61
|
-
def adapt_background
|
62
|
-
|
63
|
-
parsed_background['cuke_modeler_parsing_data'] = Marshal::load(Marshal.dump(parsed_background))
|
50
|
+
def adapt_background(background_ast)
|
51
|
+
adapted_background = {}
|
64
52
|
|
65
|
-
#
|
66
|
-
|
53
|
+
# Saving off the original data and removing parsed data for child elements in order to avoid duplicating data
|
54
|
+
save_original_data(adapted_background, background_ast)
|
55
|
+
clear_child_elements(adapted_background, [[:background, :steps]])
|
67
56
|
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
57
|
+
adapted_background['type'] = 'Background'
|
58
|
+
adapted_background['keyword'] = background_ast[:background][:keyword]
|
59
|
+
adapted_background['name'] = background_ast[:background][:name]
|
60
|
+
adapted_background['description'] = background_ast[:background][:description] || ''
|
61
|
+
adapted_background['line'] = background_ast[:background][:location][:line]
|
73
62
|
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
adapt_step!(step)
|
78
|
-
end
|
79
|
-
parsed_background['steps'].concat(parsed_background[:background].delete(:steps))
|
80
|
-
end
|
63
|
+
adapted_background['steps'] = adapt_steps(background_ast[:background])
|
64
|
+
|
65
|
+
adapted_background
|
81
66
|
end
|
82
67
|
|
83
68
|
# Adapts the AST sub-tree that is rooted at the given rule node.
|
84
|
-
def adapt_rule
|
85
|
-
|
86
|
-
parsed_rule['cuke_modeler_parsing_data'] = Marshal::load(Marshal.dump(parsed_rule))
|
69
|
+
def adapt_rule(rule_ast)
|
70
|
+
adapted_rule = {}
|
87
71
|
|
88
|
-
#
|
89
|
-
|
72
|
+
# Saving off the original data and removing parsed data for child elements in order to avoid duplicating data
|
73
|
+
save_original_data(adapted_rule, rule_ast)
|
74
|
+
clear_child_elements(adapted_rule, [[:rule, :children]])
|
90
75
|
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
76
|
+
adapted_rule['type'] = 'Rule'
|
77
|
+
adapted_rule['keyword'] = rule_ast[:rule][:keyword]
|
78
|
+
adapted_rule['name'] = rule_ast[:rule][:name]
|
79
|
+
adapted_rule['description'] = rule_ast[:rule][:description] || ''
|
80
|
+
adapted_rule['line'] = rule_ast[:rule][:location][:line]
|
96
81
|
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
parsed_rule['elements'].concat(parsed_rule[:rule].delete(:children))
|
101
|
-
end
|
82
|
+
adapted_rule['elements'] = adapt_child_elements(rule_ast[:rule])
|
83
|
+
|
84
|
+
adapted_rule
|
102
85
|
end
|
103
86
|
|
104
87
|
# Adapts the AST sub-tree that is rooted at the given scenario node.
|
105
|
-
def adapt_scenario
|
106
|
-
|
107
|
-
parsed_test['cuke_modeler_parsing_data'][:scenario][:tags] = nil if parsed_test['cuke_modeler_parsing_data'][:scenario][:tags]
|
108
|
-
parsed_test['cuke_modeler_parsing_data'][:scenario][:steps] = nil if parsed_test['cuke_modeler_parsing_data'][:scenario][:steps]
|
109
|
-
|
110
|
-
parsed_test['type'] = 'Scenario'
|
111
|
-
parsed_test['keyword'] = parsed_test[:scenario].delete(:keyword)
|
112
|
-
parsed_test['name'] = parsed_test[:scenario].delete(:name)
|
113
|
-
parsed_test['description'] = parsed_test[:scenario].delete(:description) || ''
|
114
|
-
parsed_test['line'] = parsed_test[:scenario].delete(:location)[:line]
|
115
|
-
|
116
|
-
parsed_test['tags'] = []
|
117
|
-
if parsed_test[:scenario][:tags]
|
118
|
-
parsed_test[:scenario][:tags].each do |tag|
|
119
|
-
adapt_tag!(tag)
|
120
|
-
end
|
121
|
-
parsed_test['tags'].concat(parsed_test[:scenario].delete(:tags))
|
122
|
-
end
|
88
|
+
def adapt_scenario(test_ast)
|
89
|
+
adapted_scenario = {}
|
123
90
|
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
end
|
129
|
-
parsed_test['steps'].concat(parsed_test[:scenario].delete(:steps))
|
130
|
-
end
|
131
|
-
end
|
91
|
+
# Saving off the original data and removing parsed data for child elements in order to avoid duplicating data
|
92
|
+
save_original_data(adapted_scenario, test_ast)
|
93
|
+
clear_child_elements(adapted_scenario, [[:scenario, :tags],
|
94
|
+
[:scenario, :steps]])
|
132
95
|
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
parsed_test['cuke_modeler_parsing_data'][:scenario][:examples] = nil if parsed_test['cuke_modeler_parsing_data'][:scenario][:examples]
|
139
|
-
|
140
|
-
parsed_test['type'] = 'ScenarioOutline'
|
141
|
-
parsed_test['keyword'] = parsed_test[:scenario].delete(:keyword)
|
142
|
-
parsed_test['name'] = parsed_test[:scenario].delete(:name)
|
143
|
-
parsed_test['description'] = parsed_test[:scenario].delete(:description) || ''
|
144
|
-
parsed_test['line'] = parsed_test[:scenario].delete(:location)[:line]
|
145
|
-
|
146
|
-
parsed_test['tags'] = []
|
147
|
-
if parsed_test[:scenario][:tags]
|
148
|
-
parsed_test[:scenario][:tags].each do |tag|
|
149
|
-
adapt_tag!(tag)
|
150
|
-
end
|
151
|
-
parsed_test['tags'].concat(parsed_test[:scenario].delete(:tags))
|
152
|
-
end
|
96
|
+
adapted_scenario['type'] = 'Scenario'
|
97
|
+
adapted_scenario['keyword'] = test_ast[:scenario][:keyword]
|
98
|
+
adapted_scenario['name'] = test_ast[:scenario][:name]
|
99
|
+
adapted_scenario['description'] = test_ast[:scenario][:description] || ''
|
100
|
+
adapted_scenario['line'] = test_ast[:scenario][:location][:line]
|
153
101
|
|
154
|
-
|
155
|
-
|
156
|
-
parsed_test[:scenario][:steps].each do |step|
|
157
|
-
adapt_step!(step)
|
158
|
-
end
|
159
|
-
parsed_test['steps'].concat(parsed_test[:scenario].delete(:steps))
|
160
|
-
end
|
102
|
+
adapted_scenario['tags'] = adapt_tags(test_ast[:scenario])
|
103
|
+
adapted_scenario['steps'] = adapt_steps(test_ast[:scenario])
|
161
104
|
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
105
|
+
adapted_scenario
|
106
|
+
end
|
107
|
+
|
108
|
+
# Adapts the AST sub-tree that is rooted at the given outline node.
|
109
|
+
def adapt_outline(test_ast)
|
110
|
+
adapted_outline = {}
|
111
|
+
|
112
|
+
# Saving off the original data and removing parsed data for child elements in order to avoid duplicating data
|
113
|
+
save_original_data(adapted_outline, test_ast)
|
114
|
+
clear_child_elements(adapted_outline, [[:scenario, :tags],
|
115
|
+
[:scenario, :steps],
|
116
|
+
[:scenario, :examples]])
|
117
|
+
|
118
|
+
adapted_outline['type'] = 'ScenarioOutline'
|
119
|
+
adapted_outline['keyword'] = test_ast[:scenario][:keyword]
|
120
|
+
adapted_outline['name'] = test_ast[:scenario][:name]
|
121
|
+
adapted_outline['description'] = test_ast[:scenario][:description] || ''
|
122
|
+
adapted_outline['line'] = test_ast[:scenario][:location][:line]
|
123
|
+
|
124
|
+
adapted_outline['tags'] = adapt_tags(test_ast[:scenario])
|
125
|
+
adapted_outline['steps'] = adapt_steps(test_ast[:scenario])
|
126
|
+
adapted_outline['examples'] = adapt_examples(test_ast[:scenario])
|
127
|
+
|
128
|
+
adapted_outline
|
169
129
|
end
|
170
130
|
|
171
131
|
# Adapts the AST sub-tree that is rooted at the given example node.
|
172
|
-
def adapt_example
|
173
|
-
|
174
|
-
parsed_example['cuke_modeler_parsing_data'] = Marshal::load(Marshal.dump(parsed_example))
|
132
|
+
def adapt_example(example_ast)
|
133
|
+
adapted_example = {}
|
175
134
|
|
176
|
-
#
|
177
|
-
|
178
|
-
|
179
|
-
|
135
|
+
# Saving off the original data and removing parsed data for child elements in order to avoid duplicating data
|
136
|
+
save_original_data(adapted_example, example_ast)
|
137
|
+
clear_child_elements(adapted_example, [[:tags],
|
138
|
+
[:table_header],
|
139
|
+
[:table_body]])
|
180
140
|
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
141
|
+
adapted_example['keyword'] = example_ast[:keyword]
|
142
|
+
adapted_example['name'] = example_ast[:name]
|
143
|
+
adapted_example['line'] = example_ast[:location][:line]
|
144
|
+
adapted_example['description'] = example_ast[:description] || ''
|
185
145
|
|
186
|
-
|
146
|
+
adapted_example['rows'] = []
|
147
|
+
adapted_example['rows'] << adapt_table_row(example_ast[:table_header]) if example_ast[:table_header]
|
187
148
|
|
188
|
-
|
189
|
-
adapt_table_row
|
190
|
-
parsed_example['rows'] << parsed_example.delete(:table_header)
|
149
|
+
example_ast[:table_body]&.each do |row|
|
150
|
+
adapted_example['rows'] << adapt_table_row(row)
|
191
151
|
end
|
192
152
|
|
193
|
-
|
194
|
-
parsed_example[:table_body].each do |row|
|
195
|
-
adapt_table_row!(row)
|
196
|
-
end
|
197
|
-
parsed_example['rows'].concat(parsed_example.delete(:table_body))
|
198
|
-
end
|
153
|
+
adapted_example['tags'] = adapt_tags(example_ast)
|
199
154
|
|
200
|
-
|
201
|
-
if parsed_example[:tags]
|
202
|
-
parsed_example[:tags].each do |tag|
|
203
|
-
adapt_tag!(tag)
|
204
|
-
end
|
205
|
-
parsed_example['tags'].concat(parsed_example.delete(:tags))
|
206
|
-
end
|
155
|
+
adapted_example
|
207
156
|
end
|
208
157
|
|
209
158
|
# Adapts the AST sub-tree that is rooted at the given tag node.
|
210
|
-
def adapt_tag
|
159
|
+
def adapt_tag(tag_ast)
|
160
|
+
adapted_tag = {}
|
161
|
+
|
211
162
|
# Saving off the original data
|
212
|
-
|
163
|
+
save_original_data(adapted_tag, tag_ast)
|
213
164
|
|
214
|
-
|
215
|
-
|
165
|
+
adapted_tag['name'] = tag_ast[:name]
|
166
|
+
adapted_tag['line'] = tag_ast[:location][:line]
|
167
|
+
|
168
|
+
adapted_tag
|
216
169
|
end
|
217
170
|
|
218
171
|
# Adapts the AST sub-tree that is rooted at the given comment node.
|
219
|
-
def adapt_comment
|
172
|
+
def adapt_comment(comment_ast)
|
173
|
+
adapted_comment = {}
|
174
|
+
|
220
175
|
# Saving off the original data
|
221
|
-
|
176
|
+
save_original_data(adapted_comment, comment_ast)
|
222
177
|
|
223
|
-
|
224
|
-
|
178
|
+
adapted_comment['text'] = comment_ast[:text]
|
179
|
+
adapted_comment['line'] = comment_ast[:location][:line]
|
180
|
+
|
181
|
+
adapted_comment
|
225
182
|
end
|
226
183
|
|
227
184
|
# Adapts the AST sub-tree that is rooted at the given step node.
|
228
|
-
def adapt_step
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
when parsed_step[:data_table]
|
245
|
-
adapt_step_table!(parsed_step[:data_table])
|
246
|
-
parsed_step['table'] = parsed_step.delete(:data_table)
|
247
|
-
else
|
248
|
-
# Step has no extra argument
|
185
|
+
def adapt_step(step_ast)
|
186
|
+
adapted_step = {}
|
187
|
+
|
188
|
+
# Saving off the original data and removing parsed data for child elements in order to avoid duplicating data
|
189
|
+
save_original_data(adapted_step, step_ast)
|
190
|
+
clear_child_elements(adapted_step, [[:data_table],
|
191
|
+
[:doc_string]])
|
192
|
+
|
193
|
+
adapted_step['keyword'] = step_ast[:keyword]
|
194
|
+
adapted_step['name'] = step_ast[:text]
|
195
|
+
adapted_step['line'] = step_ast[:location][:line]
|
196
|
+
|
197
|
+
if step_ast[:doc_string]
|
198
|
+
adapted_step['doc_string'] = adapt_doc_string(step_ast[:doc_string])
|
199
|
+
elsif step_ast[:data_table]
|
200
|
+
adapted_step['table'] = adapt_step_table(step_ast[:data_table])
|
249
201
|
end
|
202
|
+
|
203
|
+
adapted_step
|
250
204
|
end
|
251
205
|
|
252
206
|
# Adapts the AST sub-tree that is rooted at the given doc string node.
|
253
|
-
def adapt_doc_string
|
207
|
+
def adapt_doc_string(doc_string_ast)
|
208
|
+
adapted_doc_string = {}
|
209
|
+
|
254
210
|
# Saving off the original data
|
255
|
-
|
211
|
+
save_original_data(adapted_doc_string, doc_string_ast)
|
212
|
+
|
213
|
+
adapted_doc_string['value'] = doc_string_ast[:content]
|
214
|
+
adapted_doc_string['content_type'] = doc_string_ast[:media_type]
|
215
|
+
adapted_doc_string['line'] = doc_string_ast[:location][:line]
|
256
216
|
|
257
|
-
|
258
|
-
parsed_doc_string['content_type'] = parsed_doc_string.delete(:media_type)
|
259
|
-
parsed_doc_string['line'] = parsed_doc_string.delete(:location)[:line]
|
217
|
+
adapted_doc_string
|
260
218
|
end
|
261
219
|
|
262
220
|
# Adapts the AST sub-tree that is rooted at the given table node.
|
263
|
-
def adapt_step_table
|
264
|
-
|
265
|
-
parsed_step_table['cuke_modeler_parsing_data'] = Marshal::load(Marshal.dump(parsed_step_table))
|
221
|
+
def adapt_step_table(step_table_ast)
|
222
|
+
adapted_step_table = {}
|
266
223
|
|
267
|
-
#
|
268
|
-
|
224
|
+
# Saving off the original data and removing parsed data for child elements in order to avoid duplicating data
|
225
|
+
save_original_data(adapted_step_table, step_table_ast)
|
226
|
+
clear_child_elements(adapted_step_table, [[:rows]])
|
269
227
|
|
270
|
-
|
271
|
-
|
272
|
-
adapt_table_row
|
228
|
+
adapted_step_table['rows'] = []
|
229
|
+
step_table_ast[:rows].each do |row|
|
230
|
+
adapted_step_table['rows'] << adapt_table_row(row)
|
273
231
|
end
|
274
|
-
|
275
|
-
|
232
|
+
adapted_step_table['line'] = step_table_ast[:location][:line]
|
233
|
+
|
234
|
+
adapted_step_table
|
276
235
|
end
|
277
236
|
|
278
237
|
# Adapts the AST sub-tree that is rooted at the given row node.
|
279
|
-
def adapt_table_row
|
280
|
-
|
281
|
-
parsed_table_row['cuke_modeler_parsing_data'] = Marshal::load(Marshal.dump(parsed_table_row))
|
238
|
+
def adapt_table_row(table_row_ast)
|
239
|
+
adapted_table_row = {}
|
282
240
|
|
283
|
-
#
|
284
|
-
|
241
|
+
# Saving off the original data and removing parsed data for child elements in order to avoid duplicating data
|
242
|
+
save_original_data(adapted_table_row, table_row_ast)
|
243
|
+
clear_child_elements(adapted_table_row, [[:cells]])
|
285
244
|
|
286
|
-
|
245
|
+
adapted_table_row['line'] = table_row_ast[:location][:line]
|
287
246
|
|
288
|
-
|
289
|
-
|
290
|
-
adapt_table_cell
|
247
|
+
adapted_table_row['cells'] = []
|
248
|
+
table_row_ast[:cells].each do |row|
|
249
|
+
adapted_table_row['cells'] << adapt_table_cell(row)
|
291
250
|
end
|
292
|
-
|
251
|
+
|
252
|
+
adapted_table_row
|
293
253
|
end
|
294
254
|
|
295
255
|
# Adapts the AST sub-tree that is rooted at the given cell node.
|
296
|
-
def adapt_table_cell
|
256
|
+
def adapt_table_cell(cell_ast)
|
257
|
+
adapted_cell = {}
|
258
|
+
|
297
259
|
# Saving off the original data
|
298
|
-
|
260
|
+
save_original_data(adapted_cell, cell_ast)
|
299
261
|
|
300
|
-
|
301
|
-
|
262
|
+
adapted_cell['value'] = cell_ast[:value]
|
263
|
+
adapted_cell['line'] = cell_ast[:location][:line]
|
264
|
+
|
265
|
+
adapted_cell
|
302
266
|
end
|
303
267
|
|
304
268
|
|
305
269
|
private
|
306
270
|
|
307
271
|
|
308
|
-
def
|
309
|
-
|
310
|
-
|
311
|
-
|
272
|
+
def adapt_comments(file_ast)
|
273
|
+
return [] unless file_ast[:comments]
|
274
|
+
|
275
|
+
file_ast[:comments].map { |comment| adapt_comment(comment) }
|
276
|
+
end
|
277
|
+
|
278
|
+
def adapt_tags(element_ast)
|
279
|
+
return [] unless element_ast[:tags]
|
280
|
+
|
281
|
+
element_ast[:tags].map { |tag| adapt_tag(tag) }
|
282
|
+
end
|
283
|
+
|
284
|
+
def adapt_steps(element_ast)
|
285
|
+
return [] unless element_ast[:steps]
|
286
|
+
|
287
|
+
element_ast[:steps].map { |step| adapt_step(step) }
|
288
|
+
end
|
289
|
+
|
290
|
+
def adapt_examples(element_ast)
|
291
|
+
return [] unless element_ast[:examples]
|
292
|
+
|
293
|
+
element_ast[:examples].map { |example| adapt_example(example) }
|
294
|
+
end
|
295
|
+
|
296
|
+
def adapt_child_elements(element_ast)
|
297
|
+
return [] unless element_ast[:children]
|
298
|
+
|
299
|
+
adapted_children = []
|
300
|
+
|
301
|
+
element_ast[:children].each do |child_element|
|
302
|
+
adapted_children << if child_element[:background]
|
303
|
+
adapt_background(child_element)
|
304
|
+
elsif child_element[:rule]
|
305
|
+
adapt_rule(child_element)
|
306
|
+
else
|
307
|
+
adapt_test(child_element)
|
308
|
+
end
|
309
|
+
end
|
312
310
|
|
313
|
-
|
314
|
-
adapt_rules!(rule_children)
|
315
|
-
adapt_tests!(remaining_children)
|
311
|
+
adapted_children
|
316
312
|
end
|
317
313
|
|
318
|
-
def
|
319
|
-
|
320
|
-
|
314
|
+
def adapt_test(test_ast)
|
315
|
+
if (test_node?(test_ast) && test_has_examples?(test_ast)) ||
|
316
|
+
(test_node?(test_ast) && test_uses_outline_keyword?(test_ast))
|
317
|
+
|
318
|
+
adapt_outline(test_ast)
|
319
|
+
elsif test_node?(test_ast)
|
320
|
+
adapt_scenario(test_ast)
|
321
|
+
else
|
322
|
+
raise(ArgumentError, "Unknown test type with keys: #{test_ast.keys}")
|
321
323
|
end
|
322
324
|
end
|
323
325
|
|
324
|
-
def
|
325
|
-
|
326
|
-
|
326
|
+
def save_original_data(adapted_ast, raw_ast)
|
327
|
+
adapted_ast['cuke_modeler_parsing_data'] = Marshal.load(Marshal.dump(raw_ast))
|
328
|
+
end
|
329
|
+
|
330
|
+
def clear_child_elements(ast, child_paths)
|
331
|
+
child_paths.each do |traversal_path|
|
332
|
+
if ast['cuke_modeler_parsing_data'].dig(*traversal_path)
|
333
|
+
bury(ast['cuke_modeler_parsing_data'], traversal_path, nil)
|
334
|
+
end
|
327
335
|
end
|
328
336
|
end
|
329
337
|
|
330
|
-
def
|
331
|
-
|
332
|
-
|
333
|
-
|
334
|
-
|
335
|
-
|
336
|
-
adapt_outline!(parsed_test)
|
337
|
-
when parsed_test[:scenario]
|
338
|
-
adapt_scenario!(parsed_test)
|
339
|
-
else
|
340
|
-
raise(ArgumentError, "Unknown test type with keys: #{parsed_test.keys}")
|
338
|
+
def bury(hash, traversal_path, value)
|
339
|
+
keys = *traversal_path
|
340
|
+
|
341
|
+
current = hash
|
342
|
+
(keys.count - 1).times do |index|
|
343
|
+
current = hash[keys[index]]
|
341
344
|
end
|
345
|
+
|
346
|
+
current[keys.last] = value
|
347
|
+
end
|
348
|
+
|
349
|
+
def test_node?(ast_node)
|
350
|
+
ast_node[:scenario]
|
351
|
+
end
|
352
|
+
|
353
|
+
def test_has_examples?(ast_node)
|
354
|
+
ast_node[:scenario][:examples]
|
355
|
+
end
|
356
|
+
|
357
|
+
def test_uses_outline_keyword?(test_ast)
|
358
|
+
Parsing.dialects[Parsing.dialect]['scenarioOutline'].include?(test_ast[:scenario][:keyword])
|
342
359
|
end
|
343
360
|
|
344
361
|
end
|
345
362
|
end
|
363
|
+
|
364
|
+
# rubocop:enable Metrics/ClassLength, Metrics/AbcSize, Metrics/MethodLength
|