cucumber-gherkin 19.0.1 → 20.0.1

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.
@@ -8,10 +8,10 @@ module Gherkin
8
8
  def compile(gherkin_document, source)
9
9
  pickles = []
10
10
 
11
- return pickles unless gherkin_document[:feature]
12
- feature = gherkin_document[:feature]
13
- language = feature[:language]
14
- tags = feature[:tags]
11
+ return pickles unless gherkin_document.feature
12
+ feature = gherkin_document.feature
13
+ language = feature.language
14
+ tags = feature.tags
15
15
 
16
16
  compile_feature(pickles, language, tags, feature, source)
17
17
  pickles
@@ -21,14 +21,14 @@ module Gherkin
21
21
 
22
22
  def compile_feature(pickles, language, tags, feature, source)
23
23
  feature_background_steps = []
24
- feature[:children].each do |child|
25
- if child[:background]
26
- feature_background_steps.concat(child[:background][:steps])
27
- elsif child[:rule]
28
- compile_rule(pickles, language, tags, feature_background_steps, child[:rule], source)
24
+ feature.children.each do |child|
25
+ if child.background
26
+ feature_background_steps.concat(child.background.steps)
27
+ elsif child.rule
28
+ compile_rule(pickles, language, tags, feature_background_steps, child.rule, source)
29
29
  else
30
- scenario = child[:scenario]
31
- if scenario[:examples].empty?
30
+ scenario = child.scenario
31
+ if scenario.examples.empty?
32
32
  compile_scenario(tags, feature_background_steps, scenario, language, pickles, source)
33
33
  else
34
34
  compile_scenario_outline(tags, feature_background_steps, scenario, language, pickles, source)
@@ -38,15 +38,15 @@ module Gherkin
38
38
  end
39
39
 
40
40
  def compile_rule(pickles, language, feature_tags, feature_background_steps, rule, source)
41
- tags = [].concat(feature_tags).concat(rule[:tags])
41
+ tags = [].concat(feature_tags).concat(rule.tags)
42
42
 
43
43
  rule_background_steps = feature_background_steps.dup
44
- rule[:children].each do |child|
45
- if child[:background]
46
- rule_background_steps.concat(child[:background][:steps])
44
+ rule.children.each do |child|
45
+ if child.background
46
+ rule_background_steps.concat(child.background.steps)
47
47
  else
48
- scenario = child[:scenario]
49
- if scenario[:examples].empty?
48
+ scenario = child.scenario
49
+ if scenario.examples.empty?
50
50
  compile_scenario(tags, rule_background_steps, scenario, language, pickles, source)
51
51
  else
52
52
  compile_scenario_outline(tags, rule_background_steps, scenario, language, pickles, source)
@@ -56,51 +56,51 @@ module Gherkin
56
56
  end
57
57
 
58
58
  def compile_scenario(inherited_tags, background_steps, scenario, language, pickles, source)
59
- steps = scenario[:steps].empty? ? [] : [].concat(pickle_steps(background_steps))
59
+ steps = scenario.steps.empty? ? [] : [].concat(pickle_steps(background_steps))
60
60
 
61
- tags = [].concat(inherited_tags).concat(scenario[:tags])
61
+ tags = [].concat(inherited_tags).concat(scenario.tags)
62
62
 
63
- scenario[:steps].each do |step|
63
+ scenario.steps.each do |step|
64
64
  steps.push(pickle_step(step))
65
65
  end
66
66
 
67
- pickle = {
68
- uri: source[:uri],
67
+ pickle = Cucumber::Messages::Pickle.new(
68
+ uri: source.uri,
69
69
  id: @id_generator.new_id,
70
70
  tags: pickle_tags(tags),
71
- name: scenario[:name],
71
+ name: scenario.name,
72
72
  language: language,
73
- astNodeIds: [scenario[:id]],
73
+ ast_node_ids: [scenario.id],
74
74
  steps: steps
75
- }
75
+ )
76
76
  pickles.push(pickle)
77
77
  end
78
78
 
79
79
  def compile_scenario_outline(inherited_tags, background_steps, scenario, language, pickles, source)
80
- scenario[:examples].reject { |examples| examples[:tableHeader].nil? }.each do |examples|
81
- variable_cells = examples[:tableHeader][:cells]
82
- examples[:tableBody].each do |values_row|
83
- value_cells = values_row[:cells]
84
- steps = scenario[:steps].empty? ? [] : [].concat(pickle_steps(background_steps))
85
- tags = [].concat(inherited_tags).concat(scenario[:tags]).concat(examples[:tags])
86
-
87
- scenario[:steps].each do |scenario_step|
88
- step = pickle_step_props(scenario_step, variable_cells, values_row)
89
- steps.push(step)
80
+ scenario.examples.reject { |examples| examples.table_header.nil? }.each do |examples|
81
+ variable_cells = examples.table_header.cells
82
+ examples.table_body.each do |values_row|
83
+ value_cells = values_row.cells
84
+ steps = scenario.steps.empty? ? [] : [].concat(pickle_steps(background_steps))
85
+ tags = [].concat(inherited_tags).concat(scenario.tags).concat(examples.tags)
86
+
87
+ scenario.steps.each do |scenario_step|
88
+ step_props = pickle_step_props(scenario_step, variable_cells, values_row)
89
+ steps.push(Cucumber::Messages::PickleStep.new(**step_props))
90
90
  end
91
91
 
92
- pickle = {
93
- uri: source[:uri],
92
+ pickle = Cucumber::Messages::Pickle.new(
93
+ uri: source.uri,
94
94
  id: @id_generator.new_id,
95
- name: interpolate(scenario[:name], variable_cells, value_cells),
95
+ name: interpolate(scenario.name, variable_cells, value_cells),
96
96
  language: language,
97
97
  steps: steps,
98
98
  tags: pickle_tags(tags),
99
- astNodeIds: [
100
- scenario[:id],
101
- values_row[:id]
102
- ],
103
- }
99
+ ast_node_ids: [
100
+ scenario.id,
101
+ values_row.id
102
+ ]
103
+ )
104
104
  pickles.push(pickle)
105
105
 
106
106
  end
@@ -110,7 +110,7 @@ module Gherkin
110
110
  def interpolate(name, variable_cells, value_cells)
111
111
  variable_cells.each_with_index do |variable_cell, n|
112
112
  value_cell = value_cells[n]
113
- name = name.gsub('<' + variable_cell[:value] + '>', value_cell[:value])
113
+ name = name.gsub('<' + variable_cell.value + '>', value_cell.value)
114
114
  end
115
115
  name
116
116
  end
@@ -122,57 +122,57 @@ module Gherkin
122
122
  end
123
123
 
124
124
  def pickle_step(step)
125
- pickle_step_props(step, [], nil)
125
+ Cucumber::Messages::PickleStep.new(**pickle_step_props(step, [], nil))
126
126
  end
127
127
 
128
128
  def pickle_step_props(step, variable_cells, values_row)
129
- value_cells = values_row ? values_row[:cells] : []
129
+ value_cells = values_row ? values_row.cells : []
130
130
  props = {
131
131
  id: @id_generator.new_id,
132
- astNodeIds: [step[:id]],
133
- text: interpolate(step[:text], variable_cells, value_cells),
132
+ ast_node_ids: [step.id],
133
+ text: interpolate(step.text, variable_cells, value_cells),
134
134
  }
135
135
  if values_row
136
- props[:astNodeIds].push(values_row[:id])
136
+ props[:ast_node_ids].push(values_row.id)
137
137
  end
138
138
 
139
- if step[:dataTable]
140
- data_table = {
141
- dataTable: pickle_data_table(step[:dataTable], variable_cells, value_cells)
142
- }
139
+ if step.data_table
140
+ data_table = Cucumber::Messages::PickleStepArgument.new(
141
+ data_table: pickle_data_table(step.data_table, variable_cells, value_cells)
142
+ )
143
143
  props[:argument] = data_table
144
144
  end
145
- if step[:docString]
146
- doc_string = {
147
- docString: pickle_doc_string(step[:docString], variable_cells, value_cells)
148
- }
145
+ if step.doc_string
146
+ doc_string = Cucumber::Messages::PickleStepArgument.new(
147
+ doc_string: pickle_doc_string(step.doc_string, variable_cells, value_cells)
148
+ )
149
149
  props[:argument] = doc_string
150
150
  end
151
151
  props
152
152
  end
153
153
 
154
154
  def pickle_data_table(data_table, variable_cells, value_cells)
155
- {
156
- rows: data_table[:rows].map do |row|
157
- {
158
- cells: row[:cells].map do |cell|
159
- {
160
- value: interpolate(cell[:value], variable_cells, value_cells)
161
- }
155
+ Cucumber::Messages::PickleTable.new(
156
+ rows: data_table.rows.map do |row|
157
+ Cucumber::Messages::PickleTableRow.new(
158
+ cells: row.cells.map do |cell|
159
+ Cucumber::Messages::PickleTableCell.new(
160
+ value: interpolate(cell.value, variable_cells, value_cells)
161
+ )
162
162
  end
163
- }
163
+ )
164
164
  end
165
- }
165
+ )
166
166
  end
167
167
 
168
168
  def pickle_doc_string(doc_string, variable_cells, value_cells)
169
169
  props = {
170
- content: interpolate(doc_string[:content], variable_cells, value_cells)
170
+ content: interpolate(doc_string.content, variable_cells, value_cells)
171
171
  }
172
- if doc_string[:mediaType]
173
- props[:mediaType] = interpolate(doc_string[:mediaType], variable_cells, value_cells)
172
+ if doc_string.media_type
173
+ props[:media_type] = interpolate(doc_string.media_type, variable_cells, value_cells)
174
174
  end
175
- props
175
+ Cucumber::Messages::PickleDocString.new(**props)
176
176
  end
177
177
 
178
178
  def pickle_tags(tags)
@@ -180,10 +180,10 @@ module Gherkin
180
180
  end
181
181
 
182
182
  def pickle_tag(tag)
183
- {
184
- name: tag[:name],
185
- astNodeId: tag[:id]
186
- }
183
+ Cucumber::Messages::PickleTag.new(
184
+ name: tag.name,
185
+ ast_node_id: tag.id
186
+ )
187
187
  end
188
188
  end
189
189
  end
data/lib/gherkin/query.rb CHANGED
@@ -5,7 +5,7 @@ module Gherkin
5
5
  end
6
6
 
7
7
  def update(message)
8
- update_feature(message[:gherkinDocument][:feature]) if message[:gherkinDocument]
8
+ update_feature(message.gherkin_document.feature) if message.gherkin_document
9
9
  end
10
10
 
11
11
  def location(ast_node_id)
@@ -17,33 +17,36 @@ module Gherkin
17
17
 
18
18
  def update_feature(feature)
19
19
  return if feature.nil?
20
- store_nodes_location(feature[:tags])
20
+ store_nodes_location(feature.tags)
21
21
 
22
- feature[:children].each do |child|
23
- update_rule(child[:rule]) if child[:rule]
24
- update_background(child[:background]) if child[:background]
25
- update_scenario(child[:scenario]) if child[:scenario]
22
+ feature.children.each do |child|
23
+ update_rule(child.rule) if child.rule
24
+ update_background(child.background) if child.background
25
+ update_scenario(child.scenario) if child.scenario
26
26
  end
27
27
  end
28
28
 
29
29
  def update_rule(rule)
30
- rule[:children].each do |child|
31
- update_background(child[:background]) if child[:background]
32
- update_scenario(child[:scenario]) if child[:scenario]
30
+ return if rule.nil?
31
+ store_nodes_location(rule.tags)
32
+
33
+ rule.children.each do |child|
34
+ update_background(child.background) if child.background
35
+ update_scenario(child.scenario) if child.scenario
33
36
  end
34
37
  end
35
38
 
36
39
  def update_background(background)
37
- update_steps(background[:steps])
40
+ update_steps(background.steps)
38
41
  end
39
42
 
40
43
  def update_scenario(scenario)
41
44
  store_node_location(scenario)
42
- store_nodes_location(scenario[:tags])
43
- update_steps(scenario[:steps])
44
- scenario[:examples].each do |examples|
45
- store_nodes_location(examples[:tags] || [])
46
- store_nodes_location(examples[:tableBody] || [])
45
+ store_nodes_location(scenario.tags)
46
+ update_steps(scenario.steps)
47
+ scenario.examples.each do |examples|
48
+ store_nodes_location(examples.tags || [])
49
+ store_nodes_location(examples.table_body || [])
47
50
  end
48
51
  end
49
52
 
@@ -56,7 +59,7 @@ module Gherkin
56
59
  end
57
60
 
58
61
  def store_node_location(node)
59
- @ast_node_locations[node[:id]] = node[:location]
62
+ @ast_node_locations[node.id] = node.location
60
63
  end
61
64
  end
62
65
  end
@@ -23,25 +23,25 @@ module Gherkin
23
23
  enumerated = true
24
24
 
25
25
  sources.each do |source|
26
- y.yield({source: source}) if @options[:include_source]
26
+ y.yield(Cucumber::Messages::Envelope.new(source: source)) if @options[:include_source]
27
27
  begin
28
28
  gherkin_document = nil
29
29
 
30
30
  if @options[:include_gherkin_document]
31
31
  gherkin_document = build_gherkin_document(source)
32
- y.yield({gherkinDocument: gherkin_document})
32
+ y.yield(Cucumber::Messages::Envelope.new(gherkin_document: gherkin_document))
33
33
  end
34
34
  if @options[:include_pickles]
35
35
  gherkin_document ||= build_gherkin_document(source)
36
36
  pickles = @compiler.compile(gherkin_document, source)
37
37
  pickles.each do |pickle|
38
- y.yield({pickle: pickle})
38
+ y.yield(Cucumber::Messages::Envelope.new(pickle: pickle))
39
39
  end
40
40
  end
41
41
  rescue CompositeParserException => err
42
- yield_parse_errors(y, err.errors, source[:uri])
42
+ yield_parse_errors(y, err.errors, source.uri)
43
43
  rescue ParserException => err
44
- yield_parse_errors(y, [err], source[:uri])
44
+ yield_parse_errors(y, [err], source.uri)
45
45
  end
46
46
  end
47
47
  end
@@ -51,28 +51,28 @@ module Gherkin
51
51
 
52
52
  def yield_parse_errors(y, errors, uri)
53
53
  errors.each do |err|
54
- parse_error = {
55
- source: {
54
+ parse_error = Cucumber::Messages::ParseError.new(
55
+ source: Cucumber::Messages::SourceReference.new(
56
56
  uri: uri,
57
- location: {
57
+ location: Cucumber::Messages::Location.new(
58
58
  line: err.location[:line],
59
59
  column: err.location[:column]
60
- }.delete_if {|k,v| v.nil?}
61
- },
60
+ )
61
+ ),
62
62
  message: err.message
63
- }
64
- y.yield({parseError: parse_error})
63
+ )
64
+ y.yield(Cucumber::Messages::Envelope.new(parse_error: parse_error))
65
65
  end
66
66
  end
67
67
 
68
68
  def sources
69
69
  Enumerator.new do |y|
70
70
  @paths.each do |path|
71
- source = {
71
+ source = Cucumber::Messages::Source.new(
72
72
  uri: path,
73
73
  data: File.open(path, 'r:UTF-8', &:read),
74
- mediaType: 'text/x.cucumber.gherkin+plain'
75
- }
74
+ media_type: 'text/x.cucumber.gherkin+plain'
75
+ )
76
76
  y.yield(source)
77
77
  end
78
78
  @sources.each do |source|
@@ -84,12 +84,15 @@ module Gherkin
84
84
  def build_gherkin_document(source)
85
85
  if @options[:default_dialect]
86
86
  token_matcher = TokenMatcher.new(@options[:default_dialect])
87
- gd = @parser.parse(source[:data], token_matcher)
87
+ gd = @parser.parse(source.data, token_matcher)
88
88
  else
89
- gd = @parser.parse(source[:data])
89
+ gd = @parser.parse(source.data)
90
90
  end
91
- gd[:uri] = source[:uri]
92
- gd
91
+ Cucumber::Messages::GherkinDocument.new(
92
+ uri: source.uri,
93
+ feature: gd.feature,
94
+ comments: gd.comments
95
+ )
93
96
  end
94
97
  end
95
98
  end
@@ -6,16 +6,19 @@ describe Gherkin::Query do
6
6
  let(:subject) { Gherkin::Query.new }
7
7
 
8
8
  def filter_messages_by_attribute(messages, attribute)
9
- messages.select { |message| message.has_key?(attribute) }.map { |message| message[attribute] }
9
+ messages.map do |message|
10
+ return unless message.respond_to?(attribute)
11
+ message.send(attribute)
12
+ end.compact
10
13
  end
11
14
 
12
15
  def find_message_by_attribute(messages, attribute)
13
16
  filter_messages_by_attribute(messages, attribute).first
14
17
  end
15
18
 
16
- let(:gherkin_document) { find_message_by_attribute(messages, :gherkinDocument) }
19
+ let(:gherkin_document) { find_message_by_attribute(messages, :gherkin_document) }
17
20
 
18
- let(:messages) {
21
+ let(:messages) do
19
22
  Gherkin.from_source(
20
23
  "some/path",
21
24
  feature_content,
@@ -23,9 +26,9 @@ describe Gherkin::Query do
23
26
  include_gherkin_document: true
24
27
  }
25
28
  ).to_a
26
- }
29
+ end
27
30
 
28
- let(:feature_content) {
31
+ let(:feature_content) do
29
32
  """
30
33
  @feature-tag
31
34
  Feature: my feature
@@ -40,12 +43,12 @@ describe Gherkin::Query do
40
43
  Scenario Outline: with examples
41
44
  Given a <Status> step
42
45
 
43
- @example-tag
46
+ @examples-tag
44
47
  Examples:
45
48
  | Status |
46
49
  | passed |
47
50
 
48
-
51
+ @rule-tag
49
52
  Rule: this is a rule
50
53
  Background:
51
54
  Given the passed step in the rule background
@@ -53,32 +56,29 @@ describe Gherkin::Query do
53
56
  @ruled-scenario-tag
54
57
  Scenario: a ruled scenario
55
58
  Given a step in the ruled scenario
56
- """
57
- }
59
+ """
60
+ end
58
61
 
59
- context '#update' do
62
+ describe '#update' do
60
63
  context 'when the feature file is empty' do
61
64
  let(:feature_content) { '' }
62
65
 
63
66
  it 'does not fail' do
64
- expect {
65
- messages.each { |message|
66
- subject.update(message)
67
- }
68
- }.not_to raise_exception
67
+ expect do
68
+ messages.each { |message| subject.update(message) }
69
+ end.not_to raise_exception
69
70
  end
70
71
  end
71
72
  end
72
73
 
73
- context '#location' do
74
+ describe '#location' do
74
75
  before do
75
- messages.each { |message|
76
- subject.update(message)
77
- }
76
+ messages.each { |message| subject.update(message) }
78
77
  end
79
78
 
80
- let(:background) { find_message_by_attribute(gherkin_document[:feature][:children], :background) }
81
- let(:scenarios) { filter_messages_by_attribute(gherkin_document[:feature][:children], :scenario) }
79
+ let(:background) { find_message_by_attribute(gherkin_document.feature.children, :background) }
80
+ let(:rule) { find_message_by_attribute(gherkin_document.feature.children, :rule) }
81
+ let(:scenarios) { filter_messages_by_attribute(gherkin_document.feature.children, :scenario) }
82
82
  let(:scenario) { scenarios.first }
83
83
 
84
84
  it 'raises an exception when the AST node ID is unknown' do
@@ -86,67 +86,71 @@ describe Gherkin::Query do
86
86
  end
87
87
 
88
88
  it 'provides the location of a scenario' do
89
- expect(subject.location(scenario[:id])).to eq(scenario[:location])
89
+ expect(subject.location(scenario.id)).to eq(scenario.location)
90
90
  end
91
91
 
92
92
  it 'provides the location of an examples table row' do
93
- node = scenarios.last[:examples].first[:tableBody].first
94
- expect(subject.location(node[:id])).to eq(node[:location])
93
+ node = scenarios.last.examples.first.table_body.first
94
+ expect(subject.location(node.id)).to eq(node.location)
95
95
  end
96
96
 
97
97
  context 'when querying steps' do
98
- let(:background_step) { background[:steps].first }
99
- let(:scenario_step) { scenario[:steps].first }
98
+ let(:background_step) { background.steps.first }
99
+ let(:scenario_step) { scenario.steps.first }
100
100
 
101
101
  it 'provides the location of a background step' do
102
- expect(subject.location(background_step[:id])).to eq(background_step[:location])
102
+ expect(subject.location(background_step.id)).to eq(background_step.location)
103
103
  end
104
104
 
105
105
  it 'provides the location of a scenario step' do
106
- expect(subject.location(scenario_step[:id])).to eq(scenario_step[:location])
106
+ expect(subject.location(scenario_step.id)).to eq(scenario_step.location)
107
107
  end
108
108
  end
109
109
 
110
110
  context 'when querying tags' do
111
- let(:feature_tag) { gherkin_document[:feature][:tags].first }
112
- let(:scenario_tag) { scenario[:tags].first }
113
- let(:example_tag) { scenarios.last[:examples].first[:tags].first }
111
+ let(:feature_tag) { gherkin_document.feature.tags.first }
112
+ let(:rule_tag) { rule.tags.first }
113
+ let(:scenario_tag) { scenario.tags.first }
114
+ let(:examples_tag) { scenarios.last.examples.first.tags.first }
114
115
 
115
116
  it 'provides the location of a feature tags' do
116
- expect(subject.location(feature_tag[:id])).to eq(feature_tag[:location])
117
+ expect(subject.location(feature_tag.id)).to eq(feature_tag.location)
117
118
  end
118
119
 
119
120
  it 'provides the location of a scenario tags' do
120
- expect(subject.location(scenario_tag[:id])).to eq(scenario_tag[:location])
121
+ expect(subject.location(scenario_tag.id)).to eq(scenario_tag.location)
122
+ end
123
+
124
+ it 'provides the location of scenario examples tags' do
125
+ expect(subject.location(examples_tag.id)).to eq(examples_tag.location)
121
126
  end
122
127
 
123
- it 'provides the location of a scenario example tags' do
124
- expect(subject.location(example_tag[:id])).to eq(example_tag[:location])
128
+ it 'provides the location of a rule tag' do
129
+ expect(subject.location(rule_tag.id)).to eq(rule_tag.location)
125
130
  end
126
131
  end
127
132
 
128
133
  context 'when children are scoped in a Rule' do
129
- let(:rule) { find_message_by_attribute(gherkin_document[:feature][:children], :rule) }
130
- let(:rule_background) { find_message_by_attribute(rule[:children], :background) }
131
- let(:rule_background_step) { rule_background[:steps].first }
132
- let(:rule_scenario) { find_message_by_attribute(rule[:children], :scenario) }
133
- let(:rule_scenario_step) { rule_scenario[:steps].first }
134
- let(:rule_scenario_tag) { rule_scenario[:tags].first }
134
+ let(:rule_background) { find_message_by_attribute(rule.children, :background) }
135
+ let(:rule_background_step) { rule_background.steps.first }
136
+ let(:rule_scenario) { find_message_by_attribute(rule.children, :scenario) }
137
+ let(:rule_scenario_step) { rule_scenario.steps.first }
138
+ let(:rule_scenario_tag) { rule_scenario.tags.first }
135
139
 
136
140
  it 'provides the location of a background step' do
137
- expect(subject.location(rule_background_step[:id])).to eq(rule_background_step[:location])
141
+ expect(subject.location(rule_background_step.id)).to eq(rule_background_step.location)
138
142
  end
139
143
 
140
144
  it 'provides the location of a scenario' do
141
- expect(subject.location(rule_scenario[:id])).to eq(rule_scenario[:location])
145
+ expect(subject.location(rule_scenario.id)).to eq(rule_scenario.location)
142
146
  end
143
147
 
144
148
  it 'provides the location of a scenario tag' do
145
- expect(subject.location(rule_scenario_tag[:id])).to eq(rule_scenario_tag[:location])
149
+ expect(subject.location(rule_scenario_tag.id)).to eq(rule_scenario_tag.location)
146
150
  end
147
151
 
148
152
  it 'provides the location of a scenario step' do
149
- expect(subject.location(rule_scenario_step[:id])).to eq(rule_scenario_step[:location])
153
+ expect(subject.location(rule_scenario_step.id)).to eq(rule_scenario_step.location)
150
154
  end
151
155
  end
152
156
  end