cuke_modeler 3.20.0 → 3.20.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (51) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +12 -1
  3. data/README.md +5 -6
  4. data/lib/cuke_modeler/adapters/gherkin_10_adapter.rb +5 -5
  5. data/lib/cuke_modeler/adapters/gherkin_11_adapter.rb +5 -5
  6. data/lib/cuke_modeler/adapters/gherkin_12_adapter.rb +5 -5
  7. data/lib/cuke_modeler/adapters/gherkin_13_adapter.rb +5 -5
  8. data/lib/cuke_modeler/adapters/gherkin_14_adapter.rb +5 -5
  9. data/lib/cuke_modeler/adapters/gherkin_15_adapter.rb +5 -5
  10. data/lib/cuke_modeler/adapters/gherkin_16_adapter.rb +5 -5
  11. data/lib/cuke_modeler/adapters/gherkin_17_adapter.rb +5 -5
  12. data/lib/cuke_modeler/adapters/gherkin_18_adapter.rb +5 -2
  13. data/lib/cuke_modeler/adapters/gherkin_19_adapter.rb +5 -2
  14. data/lib/cuke_modeler/adapters/gherkin_20_adapter.rb +5 -2
  15. data/lib/cuke_modeler/adapters/gherkin_21_adapter.rb +5 -5
  16. data/lib/cuke_modeler/adapters/gherkin_22_adapter.rb +5 -5
  17. data/lib/cuke_modeler/adapters/gherkin_23_adapter.rb +5 -5
  18. data/lib/cuke_modeler/adapters/gherkin_24_adapter.rb +5 -5
  19. data/lib/cuke_modeler/adapters/gherkin_25_adapter.rb +5 -5
  20. data/lib/cuke_modeler/adapters/gherkin_26_adapter.rb +5 -5
  21. data/lib/cuke_modeler/adapters/gherkin_27_adapter.rb +5 -5
  22. data/lib/cuke_modeler/adapters/gherkin_9_adapter.rb +5 -2
  23. data/lib/cuke_modeler/adapters/gherkin_base_adapter.rb +5 -2
  24. data/lib/cuke_modeler/containing.rb +43 -210
  25. data/lib/cuke_modeler/described.rb +8 -4
  26. data/lib/cuke_modeler/models/background.rb +53 -11
  27. data/lib/cuke_modeler/models/cell.rb +36 -8
  28. data/lib/cuke_modeler/models/comment.rb +35 -8
  29. data/lib/cuke_modeler/models/directory.rb +58 -10
  30. data/lib/cuke_modeler/models/doc_string.rb +41 -9
  31. data/lib/cuke_modeler/models/example.rb +94 -17
  32. data/lib/cuke_modeler/models/feature.rb +73 -11
  33. data/lib/cuke_modeler/models/feature_file.rb +56 -12
  34. data/lib/cuke_modeler/models/model.rb +50 -7
  35. data/lib/cuke_modeler/models/outline.rb +59 -10
  36. data/lib/cuke_modeler/models/row.rb +45 -9
  37. data/lib/cuke_modeler/models/rule.rb +59 -9
  38. data/lib/cuke_modeler/models/scenario.rb +51 -10
  39. data/lib/cuke_modeler/models/step.rb +61 -11
  40. data/lib/cuke_modeler/models/table.rb +45 -9
  41. data/lib/cuke_modeler/models/tag.rb +30 -14
  42. data/lib/cuke_modeler/named.rb +7 -4
  43. data/lib/cuke_modeler/nested.rb +19 -4
  44. data/lib/cuke_modeler/parsed.rb +10 -5
  45. data/lib/cuke_modeler/parsing.rb +25 -13
  46. data/lib/cuke_modeler/sourceable.rb +11 -5
  47. data/lib/cuke_modeler/stepped.rb +7 -5
  48. data/lib/cuke_modeler/taggable.rb +22 -4
  49. data/lib/cuke_modeler/version.rb +1 -1
  50. data/testing/cucumber/features/modeling/base_model.feature +3 -0
  51. metadata +3 -2
@@ -14,31 +14,55 @@ module CukeModeler
14
14
 
15
15
  # Creates a new Table object and, if *source_text* is provided, populates
16
16
  # the object.
17
+ #
18
+ # @example
19
+ # Table.new
20
+ # Table.new("|value_1|value_2|\n|value_3|value_4|")
21
+ #
22
+ # @param source_text [String] The Gherkin text that will be used to populate the model
23
+ # @raise [ArgumentError] If *source_text* is not a String
24
+ # @return [Table] A new Table instance
17
25
  def initialize(source_text = nil)
18
26
  @rows = []
19
27
 
20
28
  super(source_text)
21
-
22
- return unless source_text
23
-
24
- parsed_table_data = parse_source(source_text)
25
- populate_table(self, parsed_table_data)
26
29
  end
27
30
 
28
- # Returns the model objects that belong to this model.
31
+ # Returns the model objects that are children of this model. For a
32
+ # Table model, these would be any associated Row models.
33
+ #
34
+ # @example
35
+ # table.children
36
+ #
37
+ # @return [Array<Row>] A collection of child models
29
38
  def children
30
39
  rows
31
40
  end
32
41
 
33
- # Returns a string representation of this model. For a table model,
42
+ # Returns a string representation of this model. For a Table model,
34
43
  # this will be Gherkin text that is equivalent to the table being modeled.
44
+ #
45
+ # @example
46
+ # table.to_s
47
+ #
48
+ # @return [String] A string representation of this model
35
49
  def to_s
36
50
  rows.empty? ? '' : rows.collect { |row| row_output_string(row) }.join("\n")
37
51
  end
38
52
 
39
53
  # See `Object#inspect`. Returns some basic information about the
40
54
  # object, including its class, object ID, and its most meaningful
41
- # attribute. For a table model, this will be the rows of the table.
55
+ # attribute. For a Table model, this will be the rows of the table.
56
+ # If *verbose* is true, provides default Ruby inspection behavior
57
+ # instead.
58
+ #
59
+ # @example
60
+ # table.inspect
61
+ # table.inspect(verbose: true)
62
+ #
63
+ # @param verbose [Boolean] Whether or not to return the full details of
64
+ # the object. Defaults to false.
65
+ # @return [String] A string representation of this model
42
66
  def inspect(verbose: false)
43
67
  return super(verbose: verbose) if verbose
44
68
 
@@ -51,7 +75,7 @@ module CukeModeler
51
75
  private
52
76
 
53
77
 
54
- def parse_source(source_text)
78
+ def process_source(source_text)
55
79
  base_file_string = "# language: #{Parsing.dialect}
56
80
  #{dialect_feature_keyword}:
57
81
  #{dialect_scenario_keyword}:
@@ -63,6 +87,18 @@ module CukeModeler
63
87
  parsed_file['feature']['elements'].first['steps'].first['table']
64
88
  end
65
89
 
90
+ def populate_model(parsed_table_data)
91
+ populate_row_models(parsed_table_data)
92
+ populate_parsing_data(parsed_table_data)
93
+ populate_source_location(parsed_table_data)
94
+ end
95
+
96
+ def populate_row_models(parsed_table_data)
97
+ parsed_table_data['rows'].each do |row_data|
98
+ @rows << build_child_model(Row, row_data)
99
+ end
100
+ end
101
+
66
102
  def row_output_string(row)
67
103
  row_text = '|'
68
104
 
@@ -6,32 +6,46 @@ module CukeModeler
6
6
  include Parsing
7
7
  include Parsed
8
8
  include Sourceable
9
-
10
-
11
- # The name of the tag
12
- attr_accessor :name
9
+ include Named
13
10
 
14
11
 
15
12
  # Creates a new Tag object and, if *source_text* is provided, populates the
16
13
  # object.
14
+ #
15
+ # @example
16
+ # Tag.new
17
+ # Tag.new('@a_tag')
18
+ #
19
+ # @param source_text [String] The Gherkin text that will be used to populate the model
20
+ # @raise [ArgumentError] If *source_text* is not a String
21
+ # @return [Tag] A new Tag instance
17
22
  def initialize(source_text = nil)
18
23
  super(source_text)
19
-
20
- return unless source_text
21
-
22
- parsed_tag_data = parse_source(source_text)
23
- populate_tag(self, parsed_tag_data)
24
24
  end
25
25
 
26
- # Returns a string representation of this model. For a tag model,
26
+ # Returns a string representation of this model. For a Tag model,
27
27
  # this will be Gherkin text that is equivalent to the tag being modeled.
28
+ #
29
+ # @example
30
+ # tag.to_s
31
+ #
32
+ # @return [String] A string representation of this model
28
33
  def to_s
29
34
  name || ''
30
35
  end
31
36
 
32
37
  # See `Object#inspect`. Returns some basic information about the
33
38
  # object, including its class, object ID, and its most meaningful
34
- # attribute. For a tag model, this will be the name of the tag.
39
+ # attribute. For a Tag model, this will be the name of the tag. If
40
+ # *verbose* is true, provides default Ruby inspection behavior instead.
41
+ #
42
+ # @example
43
+ # tag.inspect
44
+ # tag.inspect(verbose: true)
45
+ #
46
+ # @param verbose [Boolean] Whether or not to return the full details of
47
+ # the object. Defaults to false.
48
+ # @return [String] A string representation of this model
35
49
  def inspect(verbose: false)
36
50
  return super(verbose: verbose) if verbose
37
51
 
@@ -42,7 +56,7 @@ module CukeModeler
42
56
  private
43
57
 
44
58
 
45
- def parse_source(source_text)
59
+ def process_source(source_text)
46
60
  base_file_string = "\n#{dialect_feature_keyword}: Fake feature to parse"
47
61
  source_text = "# language: #{Parsing.dialect}\n" + source_text + base_file_string
48
62
 
@@ -51,8 +65,10 @@ module CukeModeler
51
65
  parsed_file['feature']['tags'].first
52
66
  end
53
67
 
54
- def populate_name(model, parsed_model_data)
55
- model.name = parsed_model_data['name']
68
+ def populate_model(processed_tag_data)
69
+ populate_name(processed_tag_data)
70
+ populate_parsing_data(processed_tag_data)
71
+ populate_source_location(processed_tag_data)
56
72
  end
57
73
 
58
74
  end
@@ -1,9 +1,12 @@
1
1
  module CukeModeler
2
2
 
3
- # NOT A PART OF THE PUBLIC API
4
- # A mix-in module containing methods used by models that represent an element that has a name.
3
+ # @api private
4
+ #
5
+ # A mix-in module containing methods used by models that represent an element that has a name. Internal helper class.
5
6
  module Named
6
7
 
8
+ # @api
9
+ #
7
10
  # The name of the element
8
11
  attr_accessor :name
9
12
 
@@ -15,8 +18,8 @@ module CukeModeler
15
18
  name.nil? || name.empty? ? '' : " #{name}"
16
19
  end
17
20
 
18
- def populate_name(model, parsed_model_data)
19
- model.name = parsed_model_data['name']
21
+ def populate_name(parsed_model_data)
22
+ @name = parsed_model_data['name']
20
23
  end
21
24
 
22
25
  end
@@ -1,15 +1,30 @@
1
1
  module CukeModeler
2
2
 
3
- # NOT A PART OF THE PUBLIC API
3
+ # @api private
4
+ #
4
5
  # A mix-in module containing methods used by models that are nested inside
5
- # of other models.
6
+ # of other models. Internal helper class.
6
7
  module Nested
7
8
 
9
+ # @api
10
+ #
8
11
  # The parent model that contains this model
9
12
  attr_accessor :parent_model
10
13
 
11
-
12
- # Returns the ancestor model of this model that matches the given type.
14
+ # TODO: Use an Enum type instead of symbols as arguments?
15
+
16
+ # @api
17
+ #
18
+ # Returns the ancestor model of this model that matches the given type. Available
19
+ # types are simply snake_case versions of the model Class names. Additionally, a
20
+ # special type *:test* will return either a Scenario or an Outline model.
21
+ #
22
+ # @example
23
+ # model.get_ancestor(:directory)
24
+ #
25
+ # @param ancestor_type [Symbol] The ancestor type to get
26
+ # @raise [ArgumentError] If the passed type is not a valid model type
27
+ # @return [Model, nil] The ancestor model, if one is found
13
28
  def get_ancestor(ancestor_type)
14
29
  target_classes = classes_for_type(ancestor_type)
15
30
 
@@ -1,18 +1,23 @@
1
1
  module CukeModeler
2
2
 
3
- # NOT A PART OF THE PUBLIC API
4
- # A mix-in module containing methods used by models that are parsed from source text.
3
+ # @api private
4
+ #
5
+ # A mix-in module containing methods used by models that are parsed from
6
+ # source text. Internal helper class.
5
7
  module Parsed
6
8
 
7
- # The parsing data for this element that was generated by the parsing engine (i.e. the *gherkin* gem)
9
+ # @api
10
+ #
11
+ # The parsing data for this element that was generated by
12
+ # the parsing engine (i.e. the *cucumber-gherkin* gem)
8
13
  attr_accessor :parsing_data
9
14
 
10
15
 
11
16
  private
12
17
 
13
18
 
14
- def populate_parsing_data(model, parsed_model_data)
15
- model.parsing_data = parsed_model_data['cuke_modeler_parsing_data']
19
+ def populate_parsing_data(parsed_model_data)
20
+ @parsing_data = parsed_model_data['cuke_modeler_parsing_data']
16
21
  end
17
22
 
18
23
  end
@@ -28,18 +28,38 @@ module CukeModeler
28
28
 
29
29
 
30
30
  # The dialect that will be used to parse snippets of Gherkin text
31
+ #
32
+ # @example
33
+ # Parsing.dialect
34
+ #
35
+ # @return [String] The current dialect. Defaults to 'en'.
31
36
  def dialect
32
37
  @dialect || 'en'
33
38
  end
34
39
 
35
- # The dialects currently known by the gherkin gem
40
+ # The dialects currently known by the cucumber-gherkin gem. See *Gherkin::DIALECTS*.
41
+ #
42
+ # @example
43
+ # Parsing.dialects
44
+ #
45
+ # @return [Hash] The dialect data
36
46
  def dialects
37
47
  Gherkin::DIALECTS
38
48
  end
39
49
 
40
- # Parses the Cucumber feature given in *source_text* and returns a hash representation of
50
+ # Parses the Cucumber feature given in *source_text* and returns a Hash representation of
41
51
  # its logical structure. This is a standardized AST that should remain consistent across
42
52
  # different versions of `cucumber-gherkin`
53
+ #
54
+ # @example
55
+ # Parsing.parse_text('Feature: Some feature')
56
+ # Parsing.parse_text('Feature: Some feature', 'my.feature')
57
+ #
58
+ # @param source_text [String] The Gherkin text to parse
59
+ # @param filename [String] The file name associated with the parsed text. Used for error messages.
60
+ # @raise [ArgumentError] If *source_text* is not a String
61
+ # @raise [ArgumentError] If *source_text* does not parse cleanly
62
+ # @return [Hash] An AST of the text
43
63
  def parse_text(source_text, filename = 'cuke_modeler_fake_file.feature')
44
64
  unless source_text.is_a?(String)
45
65
  raise(ArgumentError, "Text to parse must be a String but got #{source_text.class}")
@@ -55,6 +75,9 @@ module CukeModeler
55
75
  end
56
76
 
57
77
 
78
+ private
79
+
80
+
58
81
  gherkin_version = Gem.loaded_specs['cucumber-gherkin'].version.version
59
82
  gherkin_major_version = gherkin_version.match(/^(\d+)\./)[1].to_i
60
83
 
@@ -64,8 +87,6 @@ module CukeModeler
64
87
  # rubocop:disable Lint/DuplicateMethods
65
88
  case gherkin_major_version
66
89
  when 20, 21, 22, 23, 24, 25, 26, 27
67
- # TODO: make these methods private?
68
- # NOT A PART OF THE PUBLIC API
69
90
  # The method to use for parsing Gherkin text
70
91
  def parsing_method(source_text, filename)
71
92
  messages = Gherkin.from_source(filename,
@@ -81,8 +102,6 @@ module CukeModeler
81
102
  gherkin_ast_message.gherkin_document
82
103
  end
83
104
  when 19
84
- # TODO: make these methods private?
85
- # NOT A PART OF THE PUBLIC API
86
105
  # The method to use for parsing Gherkin text
87
106
  def parsing_method(source_text, filename)
88
107
  messages = Gherkin.from_source(filename,
@@ -98,8 +117,6 @@ module CukeModeler
98
117
  gherkin_ast_message[:gherkinDocument]
99
118
  end
100
119
  when 13, 14, 15, 16, 17, 18
101
- # TODO: make these methods private?
102
- # NOT A PART OF THE PUBLIC API
103
120
  # The method to use for parsing Gherkin text
104
121
  def parsing_method(source_text, filename)
105
122
  messages = Gherkin.from_source(filename,
@@ -115,8 +132,6 @@ module CukeModeler
115
132
  gherkin_ast_message[:gherkin_document]
116
133
  end
117
134
  when 12
118
- # TODO: make these methods private?
119
- # NOT A PART OF THE PUBLIC API
120
135
  # The method to use for parsing Gherkin text
121
136
  def parsing_method(source_text, filename)
122
137
  messages = Gherkin.from_source(filename,
@@ -134,8 +149,6 @@ module CukeModeler
134
149
  gherkin_ast_message[:gherkin_document]
135
150
  end
136
151
  when 9, 10, 11
137
- # TODO: make these methods private?
138
- # NOT A PART OF THE PUBLIC API
139
152
  # The method to use for parsing Gherkin text
140
153
  def parsing_method(source_text, filename)
141
154
  messages = Gherkin.from_source(filename,
@@ -155,7 +168,6 @@ module CukeModeler
155
168
  end
156
169
  # rubocop:enable Lint/DuplicateMethods
157
170
 
158
- # NOT A PART OF THE PUBLIC API
159
171
  # The adapter to use when converting an AST to a standard internal shape
160
172
  define_method('adapter_class') do
161
173
  CukeModeler.const_get("Gherkin#{gherkin_major_version}Adapter")
@@ -1,22 +1,28 @@
1
1
  module CukeModeler
2
2
 
3
- # NOT A PART OF THE PUBLIC API
3
+ # @api private
4
+ #
4
5
  # A mix-in module containing methods used by models that know from which line of
5
- # source code they originate.
6
+ # source code they originate. Internal helper class.
6
7
  module Sourceable
7
8
 
9
+ # @api
10
+ #
8
11
  # The line number where the element began in the source code
9
12
  attr_accessor :source_line
10
13
 
14
+ # @api
15
+ #
11
16
  # The column number where the element began in the source code
12
17
  attr_accessor :source_column
13
18
 
19
+
14
20
  private
15
21
 
16
22
 
17
- def populate_source_location(model, parsed_model_data)
18
- model.source_line = parsed_model_data['line']
19
- model.source_column = parsed_model_data['column']
23
+ def populate_source_location(parsed_model_data)
24
+ @source_line = parsed_model_data['line']
25
+ @source_column = parsed_model_data['column']
20
26
  end
21
27
 
22
28
  end
@@ -1,10 +1,12 @@
1
1
  module CukeModeler
2
2
 
3
- # NOT A PART OF THE PUBLIC API
4
- # A mix-in module containing methods used by models that represent an element that has steps.
3
+ # @api private
4
+ #
5
+ # A mix-in module containing methods used by models that represent an element that has steps. Internal helper class.
5
6
  module Stepped
6
7
 
7
-
8
+ # @api
9
+ #
8
10
  # The step models contained by this model
9
11
  attr_accessor :steps
10
12
 
@@ -20,11 +22,11 @@ module CukeModeler
20
22
  step.to_s.split("\n").collect { |line| " #{line}" }.join("\n")
21
23
  end
22
24
 
23
- def populate_steps(model, parsed_model_data)
25
+ def populate_steps(parsed_model_data)
24
26
  return unless parsed_model_data['steps']
25
27
 
26
28
  parsed_model_data['steps'].each do |step_data|
27
- model.steps << build_child_model(Step, step_data)
29
+ @steps << build_child_model(Step, step_data)
28
30
  end
29
31
  end
30
32
 
@@ -1,20 +1,38 @@
1
1
  module CukeModeler
2
2
 
3
- # NOT A PART OF THE PUBLIC API
4
- # A mix-in module containing methods used by models that represent an element that can be tagged.
3
+ # @api private
4
+ #
5
+ # A mix-in module containing methods used by models that represent an element that can be
6
+ # tagged. Internal helper class.
5
7
  module Taggable
6
8
 
9
+ # @api
10
+ #
7
11
  # The models for tags which are directly assigned to the element
8
12
  attr_accessor :tags
9
13
 
10
14
 
15
+ # @api
16
+ #
11
17
  # Returns the models for tags which are indirectly assigned to the element (i.e. they
12
18
  # have been inherited from a parent element).
19
+ #
20
+ # @example
21
+ # model.applied_tags
22
+ #
23
+ # @return [Array<Tag>] Applied tag models
13
24
  def applied_tags
14
25
  parent_model.respond_to?(:all_tags) ? parent_model.all_tags : []
15
26
  end
16
27
 
28
+ # @api
29
+ #
17
30
  # Returns models for all of the tags which are applicable to the element.
31
+ #
32
+ # @example
33
+ # model.all_tags
34
+ #
35
+ # @return [Array<Tag>] All tag models
18
36
  def all_tags
19
37
  applied_tags + @tags
20
38
  end
@@ -27,11 +45,11 @@ module CukeModeler
27
45
  tags.map(&:name).join(' ')
28
46
  end
29
47
 
30
- def populate_tags(model, parsed_model_data)
48
+ def populate_tags(parsed_model_data)
31
49
  return unless parsed_model_data['tags']
32
50
 
33
51
  parsed_model_data['tags'].each do |tag|
34
- model.tags << build_child_model(Tag, tag)
52
+ @tags << build_child_model(Tag, tag)
35
53
  end
36
54
  end
37
55
 
@@ -1,4 +1,4 @@
1
1
  module CukeModeler
2
2
  # The gem version
3
- VERSION = '3.20.0'.freeze
3
+ VERSION = '3.20.1'.freeze
4
4
  end
@@ -0,0 +1,3 @@
1
+ # TODO: demo the base model class and generic model usage (it's not abstract, just situationally useful)
2
+ @wip
3
+ Feature:
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cuke_modeler
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.20.0
4
+ version: 3.20.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Eric Kessler
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-09-22 00:00:00.000000000 Z
11
+ date: 2023-10-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: cucumber-gherkin
@@ -266,6 +266,7 @@ files:
266
266
  - testing/cucumber/features/analysis/test_comparison.feature
267
267
  - testing/cucumber/features/modeling/background_modeling.feature
268
268
  - testing/cucumber/features/modeling/background_output.feature
269
+ - testing/cucumber/features/modeling/base_model.feature
269
270
  - testing/cucumber/features/modeling/cell_modeling.feature
270
271
  - testing/cucumber/features/modeling/cell_output.feature
271
272
  - testing/cucumber/features/modeling/comment_modeling.feature