cuke_modeler 3.2.0 → 3.7.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +48 -3
- data/LICENSE.txt +1 -1
- data/README.md +7 -7
- data/cuke_modeler.gemspec +35 -16
- data/lib/cuke_modeler.rb +1 -2
- 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 +13 -0
- data/lib/cuke_modeler/adapters/gherkin_16_adapter.rb +13 -0
- data/lib/cuke_modeler/adapters/gherkin_17_adapter.rb +13 -0
- data/lib/cuke_modeler/adapters/gherkin_9_adapter.rb +261 -243
- data/lib/cuke_modeler/containing.rb +47 -90
- data/lib/cuke_modeler/described.rb +40 -2
- data/lib/cuke_modeler/models/background.rb +11 -12
- data/lib/cuke_modeler/models/cell.rb +13 -8
- data/lib/cuke_modeler/models/comment.rb +5 -6
- data/lib/cuke_modeler/models/directory.rb +13 -18
- data/lib/cuke_modeler/models/doc_string.rb +10 -8
- data/lib/cuke_modeler/models/example.rb +63 -46
- data/lib/cuke_modeler/models/feature.rb +23 -17
- data/lib/cuke_modeler/models/feature_file.rb +5 -8
- data/lib/cuke_modeler/models/model.rb +2 -3
- data/lib/cuke_modeler/models/outline.rb +19 -15
- data/lib/cuke_modeler/models/row.rb +15 -8
- data/lib/cuke_modeler/models/rule.rb +11 -10
- data/lib/cuke_modeler/models/scenario.rb +17 -13
- data/lib/cuke_modeler/models/step.rb +40 -19
- data/lib/cuke_modeler/models/table.rb +9 -7
- data/lib/cuke_modeler/models/tag.rb +9 -6
- data/lib/cuke_modeler/named.rb +5 -2
- data/lib/cuke_modeler/nested.rb +22 -19
- data/lib/cuke_modeler/parsed.rb +8 -1
- data/lib/cuke_modeler/parsing.rb +38 -29
- data/lib/cuke_modeler/sourceable.rb +8 -1
- data/lib/cuke_modeler/stepped.rb +8 -1
- data/lib/cuke_modeler/taggable.rb +9 -2
- data/lib/cuke_modeler/version.rb +1 -1
- metadata +91 -36
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: abf3eb894f4814405982ec3e2e664b9b6b0ede9b4c3f41ac99148680e251fdf0
|
4
|
+
data.tar.gz: 31e87cc947478d94ad6e5316315698b2af7a7280ecc062a670f9c70e399038fe
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: cc973033937d9bad34a2a47da77901850e6ce2e9de6cf875a0d51f6fe634e64f48cf42d4a4ca154e308982dff0e945bd002df98a48e725c8a5705e2f78720522
|
7
|
+
data.tar.gz: 73b177f6e22947a5301fbfae5a90fde84394e50adf5d7790f783d8fdea7f2b46c2b7025c0a483f80ce31f3707970051d8b7b3717299fd60adbbf6ab736e4cac6
|
data/CHANGELOG.md
CHANGED
@@ -6,7 +6,47 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
6
6
|
|
7
7
|
## [Unreleased]
|
8
8
|
|
9
|
-
|
9
|
+
Noting yet...
|
10
|
+
|
11
|
+
|
12
|
+
## [3.7.0] - 2021-02-18
|
13
|
+
|
14
|
+
### Added
|
15
|
+
- Support added for more versions of the `cucumber-gherkin` gem
|
16
|
+
- 17.x
|
17
|
+
|
18
|
+
|
19
|
+
## [3.6.0] - 2021-01-05
|
20
|
+
|
21
|
+
### Added
|
22
|
+
- Ruby 3.x is now supported
|
23
|
+
- All models are now `Enumerable`. However, some methods such as `Enumerable#max` and `Enumerable#sort` do not work
|
24
|
+
because models do not meaningfully compare to each other.
|
25
|
+
|
26
|
+
### Deprecated
|
27
|
+
- `Model#each_descendant` and `Model#each_model` will be removed on the next major release. `Model#each` and methods in
|
28
|
+
the `Enumerable` module now provide this kind of functionality.
|
29
|
+
|
30
|
+
### Fixed
|
31
|
+
- `Row#children` now returns the row's `Cell` models instead of returning an empty array
|
32
|
+
|
33
|
+
|
34
|
+
## [3.5.0] - 2020-12-19
|
35
|
+
|
36
|
+
### Added
|
37
|
+
- Support added for more versions of the `cucumber-gherkin` gem
|
38
|
+
- 16.x
|
39
|
+
|
40
|
+
## [3.4.0] - 2020-09-02
|
41
|
+
|
42
|
+
### Added
|
43
|
+
- `Feature#has_background?` and `Rule#has_background?` now both have a more conventional name via the alias `#background?`
|
44
|
+
|
45
|
+
## [3.3.0] - 2020-08-15
|
46
|
+
|
47
|
+
### Added
|
48
|
+
- Support added for more versions of the `cucumber-gherkin` gem
|
49
|
+
- 15.x
|
10
50
|
|
11
51
|
## [3.2.0] - 2020-07-27
|
12
52
|
|
@@ -312,7 +352,7 @@ Nothing yet...
|
|
312
352
|
|
313
353
|
### Fixed
|
314
354
|
|
315
|
-
- Fixed a bug that was causing object comparison using
|
355
|
+
- Fixed a bug that was causing object comparison using `#==` to not
|
316
356
|
work when comparing some models to other types of objects.
|
317
357
|
|
318
358
|
|
@@ -323,7 +363,12 @@ Nothing yet...
|
|
323
363
|
- Initial release
|
324
364
|
|
325
365
|
|
326
|
-
[Unreleased]: https://github.com/enkessler/cuke_modeler/compare/v3.
|
366
|
+
[Unreleased]: https://github.com/enkessler/cuke_modeler/compare/v3.7.0...HEAD
|
367
|
+
[3.7.0]: https://github.com/enkessler/cuke_modeler/compare/v3.6.0...v3.7.0
|
368
|
+
[3.6.0]: https://github.com/enkessler/cuke_modeler/compare/v3.5.0...v3.6.0
|
369
|
+
[3.5.0]: https://github.com/enkessler/cuke_modeler/compare/v3.4.0...v3.5.0
|
370
|
+
[3.4.0]: https://github.com/enkessler/cuke_modeler/compare/v3.3.0...v3.4.0
|
371
|
+
[3.3.0]: https://github.com/enkessler/cuke_modeler/compare/v3.2.0...v3.3.0
|
327
372
|
[3.2.0]: https://github.com/enkessler/cuke_modeler/compare/v3.1.0...v3.2.0
|
328
373
|
[3.1.0]: https://github.com/enkessler/cuke_modeler/compare/v3.0.0...v3.1.0
|
329
374
|
[3.0.0]: https://github.com/enkessler/cuke_modeler/compare/v2.1.0...v3.0.0
|
data/LICENSE.txt
CHANGED
data/README.md
CHANGED
@@ -4,15 +4,15 @@ Basic stuff:
|
|
4
4
|
[![Downloads](https://img.shields.io/gem/dt/cuke_modeler.svg)](https://rubygems.org/gems/cuke_modeler)
|
5
5
|
|
6
6
|
User stuff:
|
7
|
-
[![Cucumber Docs](http://img.shields.io/badge/Documentation-Features-green.svg)](https://
|
7
|
+
[![Cucumber Docs](http://img.shields.io/badge/Documentation-Features-green.svg)](https://github.com/enkessler/cuke_modeler/tree/master/testing/cucumber/features)
|
8
8
|
[![Yard Docs](http://img.shields.io/badge/Documentation-API-blue.svg)](https://www.rubydoc.info/gems/cuke_modeler)
|
9
9
|
|
10
10
|
Developer stuff:
|
11
|
-
[![Build Status](https://travis-ci.org/enkessler/cuke_modeler.svg)](https://travis-ci.org/enkessler/cuke_modeler)
|
12
|
-
[![Build status](https://ci.appveyor.com/api/projects/status/is8xqvoqn3pjh9l0?svg=true)](https://ci.appveyor.com/project/enkessler/cuke-modeler)
|
13
|
-
[![Coverage Status](https://coveralls.io/repos/github/enkessler/cuke_modeler/badge.svg)](https://coveralls.io/github/enkessler/cuke_modeler)
|
11
|
+
[![Build Status](https://travis-ci.org/enkessler/cuke_modeler.svg?branch=master)](https://travis-ci.org/enkessler/cuke_modeler)
|
12
|
+
[![Build status](https://ci.appveyor.com/api/projects/status/is8xqvoqn3pjh9l0/branch/master?svg=true)](https://ci.appveyor.com/project/enkessler/cuke-modeler)
|
13
|
+
[![Coverage Status](https://coveralls.io/repos/github/enkessler/cuke_modeler/badge.svg?branch=master)](https://coveralls.io/github/enkessler/cuke_modeler?branch=master)
|
14
14
|
[![Maintainability](https://api.codeclimate.com/v1/badges/83986d8f7a918fed9707/maintainability)](https://codeclimate.com/github/enkessler/cuke_modeler/maintainability)
|
15
|
-
[![Inline docs](http://inch-ci.org/github/enkessler/cuke_modeler.svg)](https://inch-ci.org/github/enkessler/cuke_modeler)
|
15
|
+
[![Inline docs](http://inch-ci.org/github/enkessler/cuke_modeler.svg?branch=master)](https://inch-ci.org/github/enkessler/cuke_modeler)
|
16
16
|
|
17
17
|
---
|
18
18
|
|
@@ -84,12 +84,12 @@ an entire test suite!
|
|
84
84
|
|
85
85
|
For more information on the different models (which more or less have the same relation
|
86
86
|
to each other as described in the AST [here](https://github.com/cucumber/cucumber/tree/master/gherkin#ast)) and how to use them, see the
|
87
|
-
[documentation](https://
|
87
|
+
[documentation](https://github.com/enkessler/cuke_modeler/tree/master/testing/cucumber/features).
|
88
88
|
|
89
89
|
## Modeling dialects other than English
|
90
90
|
|
91
91
|
The modeling functionality provided by this gem will work with any dialect that
|
92
|
-
is supported by the **gherkin** gem. For modeling at the feature level or higher,
|
92
|
+
is supported by the **cucumber-gherkin** gem. For modeling at the feature level or higher,
|
93
93
|
no additional effort is needed because the `# language` header at the top of a
|
94
94
|
feature already indicates that a non-default dialect is being used.
|
95
95
|
|
data/cuke_modeler.gemspec
CHANGED
@@ -1,17 +1,29 @@
|
|
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
|
13
17
|
spec.homepage = 'https://github.com/enkessler/cuke_modeler'
|
14
|
-
spec.license =
|
18
|
+
spec.license = 'MIT'
|
19
|
+
|
20
|
+
spec.metadata = {
|
21
|
+
'bug_tracker_uri' => 'https://github.com/enkessler/cuke_modeler/issues',
|
22
|
+
'changelog_uri' => 'https://github.com/enkessler/cuke_modeler/blob/master/CHANGELOG.md',
|
23
|
+
'documentation_uri' => 'https://www.rubydoc.info/gems/cuke_modeler',
|
24
|
+
'homepage_uri' => 'https://github.com/enkessler/cuke_modeler',
|
25
|
+
'source_code_uri' => 'https://github.com/enkessler/cuke_modeler'
|
26
|
+
}
|
15
27
|
|
16
28
|
# Specify which files should be added to the gem when it is released.
|
17
29
|
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
@@ -20,19 +32,26 @@ Gem::Specification.new do |spec|
|
|
20
32
|
source_controlled_files.keep_if { |file| file =~ %r{^(lib|testing/cucumber/features)} }
|
21
33
|
source_controlled_files + ['README.md', 'LICENSE.txt', 'CHANGELOG.md', 'cuke_modeler.gemspec']
|
22
34
|
end
|
23
|
-
spec.require_paths = [
|
35
|
+
spec.require_paths = ['lib']
|
24
36
|
|
25
|
-
spec.required_ruby_version = '>= 2.3', '<
|
37
|
+
spec.required_ruby_version = '>= 2.3', '< 4.0'
|
26
38
|
|
27
|
-
spec.add_runtime_dependency 'cucumber-gherkin', '<
|
39
|
+
spec.add_runtime_dependency 'cucumber-gherkin', '< 18.0'
|
28
40
|
|
29
41
|
spec.add_development_dependency 'bundler', '< 3.0'
|
30
|
-
spec.add_development_dependency
|
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'
|
42
|
+
spec.add_development_dependency 'childprocess', '< 5.0'
|
35
43
|
spec.add_development_dependency 'coveralls', '< 1.0.0'
|
44
|
+
spec.add_development_dependency 'ffi', '< 2.0' # This is an invisible dependency for the `childprocess` gem on Windows
|
45
|
+
# Cucumber 4.x is the earliest version to use cucumber-gherkin
|
46
|
+
spec.add_development_dependency 'cucumber', '>= 4.0.0', '< 6.0.0'
|
36
47
|
spec.add_development_dependency 'rainbow', '< 4.0.0'
|
48
|
+
spec.add_development_dependency 'rake', '< 14.0.0'
|
49
|
+
spec.add_development_dependency 'rspec', '~> 3.0'
|
50
|
+
# RuboCop drops Ruby 2.3 support after this version and we need to maintain Ruby 2.3 compatibility when writing code
|
51
|
+
# for this gem
|
52
|
+
spec.add_development_dependency 'rubocop', '< 0.82.0'
|
53
|
+
# Coveralls gem does not support any newer version than this
|
54
|
+
spec.add_development_dependency 'simplecov', '<= 0.16.1'
|
37
55
|
spec.add_development_dependency 'test-unit', '< 4.0.0'
|
56
|
+
spec.add_development_dependency 'yard', '< 1.0'
|
38
57
|
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
|
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require_relative 'gherkin_9_adapter'
|
2
|
+
|
3
|
+
|
4
|
+
module CukeModeler
|
5
|
+
|
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
|
8
|
+
# by this gem.
|
9
|
+
|
10
|
+
class Gherkin15Adapter < Gherkin9Adapter
|
11
|
+
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require_relative 'gherkin_9_adapter'
|
2
|
+
|
3
|
+
|
4
|
+
module CukeModeler
|
5
|
+
|
6
|
+
# NOT A PART OF THE PUBLIC API
|
7
|
+
# An adapter that can convert the output of version 16.x of the *cucumber-gherkin* gem into input that is consumable
|
8
|
+
# by this gem.
|
9
|
+
|
10
|
+
class Gherkin16Adapter < Gherkin9Adapter
|
11
|
+
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require_relative 'gherkin_9_adapter'
|
2
|
+
|
3
|
+
|
4
|
+
module CukeModeler
|
5
|
+
|
6
|
+
# NOT A PART OF THE PUBLIC API
|
7
|
+
# An adapter that can convert the output of version 17.x of the *cucumber-gherkin* gem into input that is consumable
|
8
|
+
# by this gem.
|
9
|
+
|
10
|
+
class Gherkin17Adapter < Gherkin9Adapter
|
11
|
+
|
12
|
+
end
|
13
|
+
end
|
@@ -1,345 +1,363 @@
|
|
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
|
5
|
-
|
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.
|
6
9
|
class Gherkin9Adapter
|
7
10
|
|
8
11
|
# 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
|
+
def adapt(ast)
|
13
|
+
adapted_ast = {}
|
12
14
|
|
13
|
-
#
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
parsed_ast['comments'] = []
|
18
|
-
if parsed_ast[:comments]
|
19
|
-
parsed_ast[:comments].each do |comment|
|
20
|
-
adapt_comment!(comment)
|
21
|
-
end
|
22
|
-
parsed_ast['comments'].concat(parsed_ast.delete(:comments))
|
23
|
-
end
|
15
|
+
# Saving off the original data and removing parsed data for child elements in order to avoid duplicating data
|
16
|
+
save_original_data(adapted_ast, ast)
|
17
|
+
clear_child_elements(adapted_ast, [[:feature],
|
18
|
+
[:comments]])
|
24
19
|
|
25
|
-
|
26
|
-
|
20
|
+
adapted_ast['comments'] = adapt_comments(ast)
|
21
|
+
adapted_ast['feature'] = adapt_feature(ast[:feature])
|
27
22
|
|
28
|
-
|
23
|
+
adapted_ast
|
29
24
|
end
|
30
25
|
|
31
26
|
# 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))
|
27
|
+
def adapt_feature(feature_ast)
|
28
|
+
return nil unless feature_ast
|
35
29
|
|
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]
|
30
|
+
adapted_feature = {}
|
39
31
|
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
32
|
+
# Saving off the original data and removing parsed data for child elements in order to avoid duplicating data
|
33
|
+
save_original_data(adapted_feature, feature_ast)
|
34
|
+
clear_child_elements(adapted_feature, [[:tags],
|
35
|
+
[:children]])
|
44
36
|
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
end
|
37
|
+
adapted_feature['keyword'] = feature_ast[:keyword]
|
38
|
+
adapted_feature['name'] = feature_ast[:name]
|
39
|
+
adapted_feature['description'] = feature_ast[:description] || ''
|
40
|
+
adapted_feature['line'] = feature_ast[:location][:line]
|
50
41
|
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
end
|
56
|
-
parsed_feature['tags'].concat(parsed_feature.delete(:tags))
|
57
|
-
end
|
42
|
+
adapted_feature['elements'] = adapt_child_elements(feature_ast)
|
43
|
+
adapted_feature['tags'] = adapt_tags(feature_ast)
|
44
|
+
|
45
|
+
adapted_feature
|
58
46
|
end
|
59
47
|
|
60
48
|
# 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))
|
49
|
+
def adapt_background(background_ast)
|
50
|
+
adapted_background = {}
|
64
51
|
|
65
|
-
#
|
66
|
-
|
52
|
+
# Saving off the original data and removing parsed data for child elements in order to avoid duplicating data
|
53
|
+
save_original_data(adapted_background, background_ast)
|
54
|
+
clear_child_elements(adapted_background, [[:background, :steps]])
|
67
55
|
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
56
|
+
adapted_background['type'] = 'Background'
|
57
|
+
adapted_background['keyword'] = background_ast[:background][:keyword]
|
58
|
+
adapted_background['name'] = background_ast[:background][:name]
|
59
|
+
adapted_background['description'] = background_ast[:background][:description] || ''
|
60
|
+
adapted_background['line'] = background_ast[:background][:location][:line]
|
73
61
|
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
adapt_step!(step)
|
78
|
-
end
|
79
|
-
parsed_background['steps'].concat(parsed_background[:background].delete(:steps))
|
80
|
-
end
|
62
|
+
adapted_background['steps'] = adapt_steps(background_ast[:background])
|
63
|
+
|
64
|
+
adapted_background
|
81
65
|
end
|
82
66
|
|
83
67
|
# 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))
|
68
|
+
def adapt_rule(rule_ast)
|
69
|
+
adapted_rule = {}
|
87
70
|
|
88
|
-
#
|
89
|
-
|
71
|
+
# Saving off the original data and removing parsed data for child elements in order to avoid duplicating data
|
72
|
+
save_original_data(adapted_rule, rule_ast)
|
73
|
+
clear_child_elements(adapted_rule, [[:rule, :children]])
|
90
74
|
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
75
|
+
adapted_rule['type'] = 'Rule'
|
76
|
+
adapted_rule['keyword'] = rule_ast[:rule][:keyword]
|
77
|
+
adapted_rule['name'] = rule_ast[:rule][:name]
|
78
|
+
adapted_rule['description'] = rule_ast[:rule][:description] || ''
|
79
|
+
adapted_rule['line'] = rule_ast[:rule][:location][:line]
|
96
80
|
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
parsed_rule['elements'].concat(parsed_rule[:rule].delete(:children))
|
101
|
-
end
|
81
|
+
adapted_rule['elements'] = adapt_child_elements(rule_ast[:rule])
|
82
|
+
|
83
|
+
adapted_rule
|
102
84
|
end
|
103
85
|
|
104
86
|
# 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
|
87
|
+
def adapt_scenario(test_ast)
|
88
|
+
adapted_scenario = {}
|
123
89
|
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
end
|
129
|
-
parsed_test['steps'].concat(parsed_test[:scenario].delete(:steps))
|
130
|
-
end
|
131
|
-
end
|
90
|
+
# Saving off the original data and removing parsed data for child elements in order to avoid duplicating data
|
91
|
+
save_original_data(adapted_scenario, test_ast)
|
92
|
+
clear_child_elements(adapted_scenario, [[:scenario, :tags],
|
93
|
+
[:scenario, :steps]])
|
132
94
|
|
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
|
95
|
+
adapted_scenario['type'] = 'Scenario'
|
96
|
+
adapted_scenario['keyword'] = test_ast[:scenario][:keyword]
|
97
|
+
adapted_scenario['name'] = test_ast[:scenario][:name]
|
98
|
+
adapted_scenario['description'] = test_ast[:scenario][:description] || ''
|
99
|
+
adapted_scenario['line'] = test_ast[:scenario][:location][:line]
|
153
100
|
|
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
|
101
|
+
adapted_scenario['tags'] = adapt_tags(test_ast[:scenario])
|
102
|
+
adapted_scenario['steps'] = adapt_steps(test_ast[:scenario])
|
161
103
|
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
104
|
+
adapted_scenario
|
105
|
+
end
|
106
|
+
|
107
|
+
# Adapts the AST sub-tree that is rooted at the given outline node.
|
108
|
+
def adapt_outline(test_ast)
|
109
|
+
adapted_outline = {}
|
110
|
+
|
111
|
+
# Saving off the original data and removing parsed data for child elements in order to avoid duplicating data
|
112
|
+
save_original_data(adapted_outline, test_ast)
|
113
|
+
clear_child_elements(adapted_outline, [[:scenario, :tags],
|
114
|
+
[:scenario, :steps],
|
115
|
+
[:scenario, :examples]])
|
116
|
+
|
117
|
+
adapted_outline['type'] = 'ScenarioOutline'
|
118
|
+
adapted_outline['keyword'] = test_ast[:scenario][:keyword]
|
119
|
+
adapted_outline['name'] = test_ast[:scenario][:name]
|
120
|
+
adapted_outline['description'] = test_ast[:scenario][:description] || ''
|
121
|
+
adapted_outline['line'] = test_ast[:scenario][:location][:line]
|
122
|
+
|
123
|
+
adapted_outline['tags'] = adapt_tags(test_ast[:scenario])
|
124
|
+
adapted_outline['steps'] = adapt_steps(test_ast[:scenario])
|
125
|
+
adapted_outline['examples'] = adapt_examples(test_ast[:scenario])
|
126
|
+
|
127
|
+
adapted_outline
|
169
128
|
end
|
170
129
|
|
171
130
|
# 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))
|
131
|
+
def adapt_example(example_ast)
|
132
|
+
adapted_example = {}
|
175
133
|
|
176
|
-
#
|
177
|
-
|
178
|
-
|
179
|
-
|
134
|
+
# Saving off the original data and removing parsed data for child elements in order to avoid duplicating data
|
135
|
+
save_original_data(adapted_example, example_ast)
|
136
|
+
clear_child_elements(adapted_example, [[:tags],
|
137
|
+
[:table_header],
|
138
|
+
[:table_body]])
|
180
139
|
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
140
|
+
adapted_example['keyword'] = example_ast[:keyword]
|
141
|
+
adapted_example['name'] = example_ast[:name]
|
142
|
+
adapted_example['line'] = example_ast[:location][:line]
|
143
|
+
adapted_example['description'] = example_ast[:description] || ''
|
185
144
|
|
186
|
-
|
145
|
+
adapted_example['rows'] = []
|
146
|
+
adapted_example['rows'] << adapt_table_row(example_ast[:table_header]) if example_ast[:table_header]
|
187
147
|
|
188
|
-
|
189
|
-
adapt_table_row
|
190
|
-
parsed_example['rows'] << parsed_example.delete(:table_header)
|
148
|
+
example_ast[:table_body]&.each do |row|
|
149
|
+
adapted_example['rows'] << adapt_table_row(row)
|
191
150
|
end
|
192
151
|
|
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
|
152
|
+
adapted_example['tags'] = adapt_tags(example_ast)
|
199
153
|
|
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
|
154
|
+
adapted_example
|
207
155
|
end
|
208
156
|
|
209
157
|
# Adapts the AST sub-tree that is rooted at the given tag node.
|
210
|
-
def adapt_tag
|
158
|
+
def adapt_tag(tag_ast)
|
159
|
+
adapted_tag = {}
|
160
|
+
|
211
161
|
# Saving off the original data
|
212
|
-
|
162
|
+
save_original_data(adapted_tag, tag_ast)
|
213
163
|
|
214
|
-
|
215
|
-
|
164
|
+
adapted_tag['name'] = tag_ast[:name]
|
165
|
+
adapted_tag['line'] = tag_ast[:location][:line]
|
166
|
+
|
167
|
+
adapted_tag
|
216
168
|
end
|
217
169
|
|
218
170
|
# Adapts the AST sub-tree that is rooted at the given comment node.
|
219
|
-
def adapt_comment
|
171
|
+
def adapt_comment(comment_ast)
|
172
|
+
adapted_comment = {}
|
173
|
+
|
220
174
|
# Saving off the original data
|
221
|
-
|
175
|
+
save_original_data(adapted_comment, comment_ast)
|
222
176
|
|
223
|
-
|
224
|
-
|
177
|
+
adapted_comment['text'] = comment_ast[:text]
|
178
|
+
adapted_comment['line'] = comment_ast[:location][:line]
|
179
|
+
|
180
|
+
adapted_comment
|
225
181
|
end
|
226
182
|
|
227
183
|
# 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
|
184
|
+
def adapt_step(step_ast)
|
185
|
+
adapted_step = {}
|
186
|
+
|
187
|
+
# Saving off the original data and removing parsed data for child elements in order to avoid duplicating data
|
188
|
+
save_original_data(adapted_step, step_ast)
|
189
|
+
clear_child_elements(adapted_step, [[:data_table],
|
190
|
+
[:doc_string]])
|
191
|
+
|
192
|
+
adapted_step['keyword'] = step_ast[:keyword]
|
193
|
+
adapted_step['name'] = step_ast[:text]
|
194
|
+
adapted_step['line'] = step_ast[:location][:line]
|
195
|
+
|
196
|
+
if step_ast[:doc_string]
|
197
|
+
adapted_step['doc_string'] = adapt_doc_string(step_ast[:doc_string])
|
198
|
+
elsif step_ast[:data_table]
|
199
|
+
adapted_step['table'] = adapt_step_table(step_ast[:data_table])
|
249
200
|
end
|
201
|
+
|
202
|
+
adapted_step
|
250
203
|
end
|
251
204
|
|
252
205
|
# Adapts the AST sub-tree that is rooted at the given doc string node.
|
253
|
-
def adapt_doc_string
|
206
|
+
def adapt_doc_string(doc_string_ast)
|
207
|
+
adapted_doc_string = {}
|
208
|
+
|
254
209
|
# Saving off the original data
|
255
|
-
|
210
|
+
save_original_data(adapted_doc_string, doc_string_ast)
|
211
|
+
|
212
|
+
adapted_doc_string['value'] = doc_string_ast[:content]
|
213
|
+
adapted_doc_string['content_type'] = doc_string_ast[:media_type]
|
214
|
+
adapted_doc_string['line'] = doc_string_ast[:location][:line]
|
256
215
|
|
257
|
-
|
258
|
-
parsed_doc_string['content_type'] = parsed_doc_string.delete(:media_type)
|
259
|
-
parsed_doc_string['line'] = parsed_doc_string.delete(:location)[:line]
|
216
|
+
adapted_doc_string
|
260
217
|
end
|
261
218
|
|
262
219
|
# 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))
|
220
|
+
def adapt_step_table(step_table_ast)
|
221
|
+
adapted_step_table = {}
|
266
222
|
|
267
|
-
#
|
268
|
-
|
223
|
+
# Saving off the original data and removing parsed data for child elements in order to avoid duplicating data
|
224
|
+
save_original_data(adapted_step_table, step_table_ast)
|
225
|
+
clear_child_elements(adapted_step_table, [[:rows]])
|
269
226
|
|
270
|
-
|
271
|
-
|
272
|
-
adapt_table_row
|
227
|
+
adapted_step_table['rows'] = []
|
228
|
+
step_table_ast[:rows].each do |row|
|
229
|
+
adapted_step_table['rows'] << adapt_table_row(row)
|
273
230
|
end
|
274
|
-
|
275
|
-
|
231
|
+
adapted_step_table['line'] = step_table_ast[:location][:line]
|
232
|
+
|
233
|
+
adapted_step_table
|
276
234
|
end
|
277
235
|
|
278
236
|
# 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))
|
237
|
+
def adapt_table_row(table_row_ast)
|
238
|
+
adapted_table_row = {}
|
282
239
|
|
283
|
-
#
|
284
|
-
|
240
|
+
# Saving off the original data and removing parsed data for child elements in order to avoid duplicating data
|
241
|
+
save_original_data(adapted_table_row, table_row_ast)
|
242
|
+
clear_child_elements(adapted_table_row, [[:cells]])
|
285
243
|
|
286
|
-
|
244
|
+
adapted_table_row['line'] = table_row_ast[:location][:line]
|
287
245
|
|
288
|
-
|
289
|
-
|
290
|
-
adapt_table_cell
|
246
|
+
adapted_table_row['cells'] = []
|
247
|
+
table_row_ast[:cells].each do |row|
|
248
|
+
adapted_table_row['cells'] << adapt_table_cell(row)
|
291
249
|
end
|
292
|
-
|
250
|
+
|
251
|
+
adapted_table_row
|
293
252
|
end
|
294
253
|
|
295
254
|
# Adapts the AST sub-tree that is rooted at the given cell node.
|
296
|
-
def adapt_table_cell
|
255
|
+
def adapt_table_cell(cell_ast)
|
256
|
+
adapted_cell = {}
|
257
|
+
|
297
258
|
# Saving off the original data
|
298
|
-
|
259
|
+
save_original_data(adapted_cell, cell_ast)
|
299
260
|
|
300
|
-
|
301
|
-
|
261
|
+
adapted_cell['value'] = cell_ast[:value]
|
262
|
+
adapted_cell['line'] = cell_ast[:location][:line]
|
263
|
+
|
264
|
+
adapted_cell
|
302
265
|
end
|
303
266
|
|
304
267
|
|
305
268
|
private
|
306
269
|
|
307
270
|
|
308
|
-
def
|
309
|
-
|
310
|
-
|
311
|
-
|
271
|
+
def adapt_comments(file_ast)
|
272
|
+
return [] unless file_ast[:comments]
|
273
|
+
|
274
|
+
file_ast[:comments].map { |comment| adapt_comment(comment) }
|
275
|
+
end
|
276
|
+
|
277
|
+
def adapt_tags(element_ast)
|
278
|
+
return [] unless element_ast[:tags]
|
279
|
+
|
280
|
+
element_ast[:tags].map { |tag| adapt_tag(tag) }
|
281
|
+
end
|
282
|
+
|
283
|
+
def adapt_steps(element_ast)
|
284
|
+
return [] unless element_ast[:steps]
|
285
|
+
|
286
|
+
element_ast[:steps].map { |step| adapt_step(step) }
|
287
|
+
end
|
288
|
+
|
289
|
+
def adapt_examples(element_ast)
|
290
|
+
return [] unless element_ast[:examples]
|
291
|
+
|
292
|
+
element_ast[:examples].map { |example| adapt_example(example) }
|
293
|
+
end
|
294
|
+
|
295
|
+
def adapt_child_elements(element_ast)
|
296
|
+
return [] unless element_ast[:children]
|
297
|
+
|
298
|
+
adapted_children = []
|
299
|
+
|
300
|
+
element_ast[:children].each do |child_element|
|
301
|
+
adapted_children << if child_element[:background]
|
302
|
+
adapt_background(child_element)
|
303
|
+
elsif child_element[:rule]
|
304
|
+
adapt_rule(child_element)
|
305
|
+
else
|
306
|
+
adapt_test(child_element)
|
307
|
+
end
|
308
|
+
end
|
312
309
|
|
313
|
-
|
314
|
-
adapt_rules!(rule_children)
|
315
|
-
adapt_tests!(remaining_children)
|
310
|
+
adapted_children
|
316
311
|
end
|
317
312
|
|
318
|
-
def
|
319
|
-
|
320
|
-
|
313
|
+
def adapt_test(test_ast)
|
314
|
+
if (test_node?(test_ast) && test_has_examples?(test_ast)) ||
|
315
|
+
(test_node?(test_ast) && test_uses_outline_keyword?(test_ast))
|
316
|
+
|
317
|
+
adapt_outline(test_ast)
|
318
|
+
elsif test_node?(test_ast)
|
319
|
+
adapt_scenario(test_ast)
|
320
|
+
else
|
321
|
+
raise(ArgumentError, "Unknown test type with keys: #{test_ast.keys}")
|
321
322
|
end
|
322
323
|
end
|
323
324
|
|
324
|
-
def
|
325
|
-
|
326
|
-
|
325
|
+
def save_original_data(adapted_ast, raw_ast)
|
326
|
+
adapted_ast['cuke_modeler_parsing_data'] = Marshal.load(Marshal.dump(raw_ast))
|
327
|
+
end
|
328
|
+
|
329
|
+
def clear_child_elements(ast, child_paths)
|
330
|
+
child_paths.each do |traversal_path|
|
331
|
+
if ast['cuke_modeler_parsing_data'].dig(*traversal_path)
|
332
|
+
bury(ast['cuke_modeler_parsing_data'], traversal_path, nil)
|
333
|
+
end
|
327
334
|
end
|
328
335
|
end
|
329
336
|
|
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}")
|
337
|
+
def bury(hash, traversal_path, value)
|
338
|
+
keys = *traversal_path
|
339
|
+
|
340
|
+
current = hash
|
341
|
+
(keys.count - 1).times do |index|
|
342
|
+
current = hash[keys[index]]
|
341
343
|
end
|
344
|
+
|
345
|
+
current[keys.last] = value
|
346
|
+
end
|
347
|
+
|
348
|
+
def test_node?(ast_node)
|
349
|
+
ast_node[:scenario]
|
350
|
+
end
|
351
|
+
|
352
|
+
def test_has_examples?(ast_node)
|
353
|
+
ast_node[:scenario][:examples]
|
354
|
+
end
|
355
|
+
|
356
|
+
def test_uses_outline_keyword?(test_ast)
|
357
|
+
Parsing.dialects[Parsing.dialect]['scenarioOutline'].include?(test_ast[:scenario][:keyword])
|
342
358
|
end
|
343
359
|
|
344
360
|
end
|
345
361
|
end
|
362
|
+
|
363
|
+
# rubocop:enable Metrics/ClassLength, Metrics/AbcSize, Metrics/MethodLength
|