gherkin 8.1.1 → 8.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8b980738a33c8315a4c75f6a40d9c64c8db4e73090a0e3994b5faf630cfcd57d
4
- data.tar.gz: b747a6767dea475e580d3ba1ee2a8abe19a1f3a23bfefa58d3ddf639ea77e91a
3
+ metadata.gz: c425e6ebae052b06f2464f7c5a53d744013a51538cd063d8894c922460aaa85b
4
+ data.tar.gz: 60a4f31c0b53f7995f75f258a25773043eabc82116565706a5789ede5eaacd78
5
5
  SHA512:
6
- metadata.gz: e9f680f17ea1eef814cb66bff79122bcf7e0b73cdd0e310a7ae740b8a493f319cc864b6bbefcba4af7ab17b200e0f23f7efa19c215f93c61462412b9f097fc35
7
- data.tar.gz: a5c01fb1dc5f2f56f86e39598ac110fe37d38f4e1e47a83f4a54a1597fb02f84022753c58b157e8f4b19fbe7eddc31fadd30167cd9d82d0c192fe55db6b7513f
6
+ metadata.gz: db8446162a263304c961c2fd79ff808c47a2c71c69c34c1300b412fa17c924df7a54becffd84e6608babab7441a968790e299a9360d4f2123c377ced30bbeb89
7
+ data.tar.gz: fcb986c6d9abb4c3a388d783cb0f51e2187a152830d9a207692bf0bf02b5a76c442d813cff62c3106c1279380c3023fc637c5cecf8a9223252ac009838d71384
data/bin/gherkin CHANGED
@@ -12,7 +12,8 @@ options = {
12
12
  include_source: true,
13
13
  include_gherkin_document: true,
14
14
  include_pickles: true,
15
- json: false
15
+ json: false,
16
+ predictable_ids: false
16
17
  }
17
18
 
18
19
  OptionParser.new do |opts|
@@ -28,6 +29,9 @@ OptionParser.new do |opts|
28
29
  opts.on("--json", "Print messages as JSON") do |v|
29
30
  options[:json] = v
30
31
  end
32
+ opts.on("--predictable-ids", "Generate incrementing ids rather than UUIDs") do |v|
33
+ options[:predictable_ids] = v
34
+ end
31
35
  end.parse!
32
36
 
33
37
  def process_messages(messages, options)
@@ -1,9 +1,11 @@
1
1
  require 'cucumber/messages'
2
2
  require 'gherkin/ast_node'
3
+ require 'gherkin/id_generator'
3
4
 
4
5
  module Gherkin
5
6
  class AstBuilder
6
- def initialize
7
+ def initialize(id_generator = Gherkin::IdGenerator::UUID.new)
8
+ @id_generator = id_generator
7
9
  reset
8
10
  end
9
11
 
@@ -57,7 +59,8 @@ module Gherkin
57
59
  token.matched_items.each do |tag_item|
58
60
  tags.push(Cucumber::Messages::GherkinDocument::Feature::Tag.new(
59
61
  location: get_location(token, tag_item.column),
60
- name: tag_item.text
62
+ name: tag_item.text,
63
+ id: @id_generator.new_id
61
64
  ))
62
65
  end
63
66
  end
@@ -68,6 +71,7 @@ module Gherkin
68
71
  def get_table_rows(node)
69
72
  rows = node.get_tokens(:TableRow).map do |token|
70
73
  Cucumber::Messages::GherkinDocument::Feature::TableRow.new(
74
+ id: @id_generator.new_id,
71
75
  location: get_location(token, 0),
72
76
  cells: get_cells(token)
73
77
  )
@@ -111,28 +115,26 @@ module Gherkin
111
115
  data_table = node.get_single(:DataTable)
112
116
  doc_string = node.get_single(:DocString)
113
117
 
114
- props = {
118
+ Cucumber::Messages::GherkinDocument::Feature::Step.new(
115
119
  location: get_location(step_line, 0),
116
120
  keyword: step_line.matched_keyword,
117
- text: step_line.matched_text
118
- }
119
- props[:data_table] = data_table if data_table
120
- props[:doc_string] = doc_string if doc_string
121
-
122
- Cucumber::Messages::GherkinDocument::Feature::Step.new(props)
121
+ text: step_line.matched_text,
122
+ data_table: data_table,
123
+ doc_string: doc_string,
124
+ id: @id_generator.new_id
125
+ )
123
126
  when :DocString
124
127
  separator_token = node.get_tokens(:DocStringSeparator)[0]
125
128
  content_type = separator_token.matched_text == '' ? nil : separator_token.matched_text
126
129
  line_tokens = node.get_tokens(:Other)
127
130
  content = line_tokens.map { |t| t.matched_text }.join("\n")
128
131
 
129
- props = {
132
+ Cucumber::Messages::GherkinDocument::Feature::Step::DocString.new(
130
133
  location: get_location(separator_token, 0),
131
134
  content: content,
132
- delimiter: separator_token.matched_keyword
133
- }
134
- props[:content_type] = content_type if content_type
135
- Cucumber::Messages::GherkinDocument::Feature::Step::DocString.new(props)
135
+ delimiter: separator_token.matched_keyword,
136
+ content_type: content_type,
137
+ )
136
138
  when :DataTable
137
139
  rows = get_table_rows(node)
138
140
  Cucumber::Messages::GherkinDocument::Feature::Step::DataTable.new(
@@ -144,14 +146,13 @@ module Gherkin
144
146
  description = get_description(node)
145
147
  steps = get_steps(node)
146
148
 
147
- props = {
149
+ Cucumber::Messages::GherkinDocument::Feature::Background.new(
148
150
  location: get_location(background_line, 0),
149
151
  keyword: background_line.matched_keyword,
150
152
  name: background_line.matched_text,
153
+ description: description,
151
154
  steps: steps
152
- }
153
- props[:description] = description if description
154
- Cucumber::Messages::GherkinDocument::Feature::Background.new(props)
155
+ )
155
156
  when :ScenarioDefinition
156
157
  tags = get_tags(node)
157
158
  scenario_node = node.get_single(:Scenario)
@@ -159,16 +160,16 @@ module Gherkin
159
160
  description = get_description(scenario_node)
160
161
  steps = get_steps(scenario_node)
161
162
  examples = scenario_node.get_items(:ExamplesDefinition)
162
- props = {
163
+ Cucumber::Messages::GherkinDocument::Feature::Scenario.new(
164
+ id: @id_generator.new_id,
163
165
  tags: tags,
164
166
  location: get_location(scenario_line, 0),
165
167
  keyword: scenario_line.matched_keyword,
166
168
  name: scenario_line.matched_text,
169
+ description: description,
167
170
  steps: steps,
168
171
  examples: examples
169
- }
170
- props[:description] = description if description
171
- Cucumber::Messages::GherkinDocument::Feature::Scenario.new(props)
172
+ )
172
173
  when :ExamplesDefinition
173
174
  tags = get_tags(node)
174
175
  examples_node = node.get_single(:Examples)
@@ -179,16 +180,15 @@ module Gherkin
179
180
  table_header = rows.nil? ? nil : rows.first
180
181
  table_body = rows.nil? ? nil : rows[1..-1]
181
182
 
182
- props = {
183
+ Cucumber::Messages::GherkinDocument::Feature::Scenario::Examples.new(
183
184
  tags: tags,
184
185
  location: get_location(examples_line, 0),
185
186
  keyword: examples_line.matched_keyword,
186
187
  name: examples_line.matched_text,
187
- }
188
- props[:table_header] = table_header if table_header
189
- props[:table_body] = table_body if table_body
190
- props[:description] = description if description
191
- Cucumber::Messages::GherkinDocument::Feature::Scenario::Examples.new(props)
188
+ description: description,
189
+ table_header: table_header,
190
+ table_body: table_body,
191
+ )
192
192
  when :ExamplesTable
193
193
  get_table_rows(node)
194
194
  when :Description
@@ -215,17 +215,15 @@ module Gherkin
215
215
  description = get_description(header)
216
216
  language = feature_line.matched_gherkin_dialect
217
217
 
218
- props = {
218
+ Cucumber::Messages::GherkinDocument::Feature.new(
219
219
  tags: tags,
220
220
  location: get_location(feature_line, 0),
221
221
  language: language,
222
222
  keyword: feature_line.matched_keyword,
223
223
  name: feature_line.matched_text,
224
+ description: description,
224
225
  children: children,
225
- }
226
- props[:description] = description if description
227
-
228
- Cucumber::Messages::GherkinDocument::Feature.new(props)
226
+ )
229
227
  when :Rule
230
228
  header = node.get_single(:RuleHeader)
231
229
  return unless header
@@ -0,0 +1,22 @@
1
+ require 'securerandom'
2
+
3
+ module Gherkin
4
+ module IdGenerator
5
+ class Incrementing
6
+ def initialize
7
+ @index = -1
8
+ end
9
+
10
+ def new_id
11
+ @index += 1
12
+ @index.to_s
13
+ end
14
+ end
15
+
16
+ class UUID
17
+ def new_id
18
+ SecureRandom.uuid
19
+ end
20
+ end
21
+ end
22
+ end
@@ -56,7 +56,7 @@ module Gherkin
56
56
  class Parser
57
57
  attr_accessor :stop_at_first_error
58
58
 
59
- def initialize(ast_builder=AstBuilder.new)
59
+ def initialize(ast_builder = AstBuilder.new)
60
60
  @ast_builder = ast_builder
61
61
  end
62
62
 
@@ -1,9 +1,13 @@
1
1
  require 'cucumber/messages'
2
- require 'digest'
2
+ require 'gherkin/id_generator'
3
3
 
4
4
  module Gherkin
5
5
  module Pickles
6
6
  class Compiler
7
+ def initialize(id_generator = Gherkin::IdGenerator::UUID.new)
8
+ @id_generator = id_generator
9
+ end
10
+
7
11
  def compile(gherkin_document, source)
8
12
  pickles = []
9
13
 
@@ -63,11 +67,11 @@ module Gherkin
63
67
 
64
68
  pickle = Cucumber::Messages::Pickle.new(
65
69
  uri: source.uri,
66
- id: calculate_id(source.data, [scenario.location]),
70
+ id: @id_generator.new_id,
67
71
  tags: pickle_tags(tags),
68
72
  name: scenario.name,
69
73
  language: language,
70
- locations: [scenario.location],
74
+ sourceIds: [scenario.id],
71
75
  steps: steps
72
76
  )
73
77
  pickles.push(pickle)
@@ -76,67 +80,34 @@ module Gherkin
76
80
  def compile_scenario_outline(feature_tags, background_steps, scenario, language, pickles, source)
77
81
  scenario.examples.reject { |examples| examples.table_header.nil? }.each do |examples|
78
82
  variable_cells = examples.table_header.cells
79
- examples.table_body.each do |values|
80
- value_cells = values.cells
83
+ examples.table_body.each do |values_row|
84
+ value_cells = values_row.cells
81
85
  steps = scenario.steps.empty? ? [] : [].concat(background_steps)
82
86
  tags = [].concat(feature_tags).concat(scenario.tags).concat(examples.tags)
83
87
 
84
88
  scenario.steps.each do |scenario_outline_step|
85
- step_props = pickle_step_props(scenario_outline_step, variable_cells, value_cells)
86
- step_props[:locations].push(values.location)
89
+ step_props = pickle_step_props(scenario_outline_step, variable_cells, values_row)
87
90
  steps.push(Cucumber::Messages::Pickle::PickleStep.new(step_props))
88
91
  end
89
92
 
90
93
  pickle = Cucumber::Messages::Pickle.new(
91
94
  uri: source.uri,
92
- id: calculate_id(source.data, [scenario.location, values.location]),
95
+ id: @id_generator.new_id,
93
96
  name: interpolate(scenario.name, variable_cells, value_cells),
94
97
  language: language,
95
98
  steps: steps,
96
99
  tags: pickle_tags(tags),
97
- locations: [
98
- scenario.location,
99
- values.location
100
- ]
100
+ sourceIds: [
101
+ scenario.id,
102
+ values_row.id
103
+ ],
101
104
  )
102
- pickles.push(pickle);
105
+ pickles.push(pickle)
103
106
 
104
107
  end
105
108
  end
106
109
  end
107
110
 
108
- def create_pickle_arguments(argument, variable_cells, value_cells)
109
- result = []
110
- return result if argument.nil?
111
- if (argument[:type] == :DataTable)
112
- table = {
113
- rows: argument[:rows].map do |row|
114
- {
115
- cells: row[:cells].map do |cell|
116
- {
117
- location: cell.location,
118
- value: interpolate(cell.value, variable_cells, value_cells)
119
- }
120
- end
121
- }
122
- end
123
- }
124
- result.push(table)
125
- elsif (argument[:type] == :DocString)
126
- doc_string = {
127
- location: pickle_location(argument.location),
128
- content: interpolate(argument[:content], variable_cells, value_cells)
129
- }
130
- if argument.key?(:contentType)
131
- doc_string[:contentType] = interpolate(argument[:contentType], variable_cells, value_cells)
132
- end
133
- result.push(doc_string)
134
- else
135
- raise 'Internal error'
136
- end
137
- result
138
- end
139
-
140
111
  def interpolate(name, variable_cells, value_cells)
141
112
  variable_cells.each_with_index do |variable_cell, n|
142
113
  value_cell = value_cells[n]
@@ -145,15 +116,6 @@ module Gherkin
145
116
  name
146
117
  end
147
118
 
148
- def calculate_id(source_data, locations)
149
- sha1 = Digest::SHA1.new
150
- sha1 << source_data
151
- locations.each do |location|
152
- sha1 << [location.line, location.column].pack('V*')
153
- end
154
- sha1.hexdigest
155
- end
156
-
157
119
  def pickle_steps(steps)
158
120
  steps.map do |step|
159
121
  pickle_step(step)
@@ -161,14 +123,19 @@ module Gherkin
161
123
  end
162
124
 
163
125
  def pickle_step(step)
164
- Cucumber::Messages::Pickle::PickleStep.new(pickle_step_props(step, [], []))
126
+ Cucumber::Messages::Pickle::PickleStep.new(pickle_step_props(step, [], nil))
165
127
  end
166
128
 
167
- def pickle_step_props(step, variable_cells, value_cells)
129
+ def pickle_step_props(step, variable_cells, values_row)
130
+ value_cells = values_row ? values_row.cells : []
168
131
  props = {
132
+ id: @id_generator.new_id,
133
+ sourceIds: [step.id],
169
134
  text: interpolate(step.text, variable_cells, value_cells),
170
- locations: [pickle_step_location(step)]
171
135
  }
136
+ if values_row
137
+ props[:sourceIds].push(values_row.id)
138
+ end
172
139
 
173
140
  if step.data_table
174
141
  data_table = Cucumber::Messages::PickleStepArgument.new(
@@ -191,7 +158,6 @@ module Gherkin
191
158
  Cucumber::Messages::PickleStepArgument::PickleTable::PickleTableRow.new(
192
159
  cells: row.cells.map do |cell|
193
160
  Cucumber::Messages::PickleStepArgument::PickleTable::PickleTableRow::PickleTableCell.new(
194
- location: cell.location,
195
161
  value: interpolate(cell.value, variable_cells, value_cells)
196
162
  )
197
163
  end
@@ -202,7 +168,6 @@ module Gherkin
202
168
 
203
169
  def pickle_doc_string(doc_string, variable_cells, value_cells)
204
170
  props = {
205
- location: doc_string.location,
206
171
  content: interpolate(doc_string.content, variable_cells, value_cells)
207
172
  }
208
173
  if doc_string.content_type
@@ -211,13 +176,6 @@ module Gherkin
211
176
  Cucumber::Messages::PickleStepArgument::PickleDocString.new(props)
212
177
  end
213
178
 
214
- def pickle_step_location(step)
215
- Cucumber::Messages::Location.new(
216
- line: step.location.line,
217
- column: step.location.column + (step.keyword ? step.keyword.length : 0)
218
- )
219
- end
220
-
221
179
  def pickle_tags(tags)
222
180
  tags.map {|tag| pickle_tag(tag)}
223
181
  end
@@ -225,7 +183,7 @@ module Gherkin
225
183
  def pickle_tag(tag)
226
184
  Cucumber::Messages::Pickle::PickleTag.new(
227
185
  name: tag.name,
228
- location: tag.location
186
+ sourceId: tag.id
229
187
  )
230
188
  end
231
189
  end
@@ -2,6 +2,7 @@ require 'cucumber/messages'
2
2
  require 'gherkin/parser'
3
3
  require 'gherkin/token_matcher'
4
4
  require 'gherkin/pickles/compiler'
5
+ require 'gherkin/id_generator'
5
6
 
6
7
  module Gherkin
7
8
  module Stream
@@ -10,8 +11,14 @@ module Gherkin
10
11
  @paths = paths
11
12
  @sources = sources
12
13
  @options = options
13
- @parser = Parser.new
14
- @compiler = Pickles::Compiler.new
14
+
15
+ id_generator = id_generator_class.new
16
+ @parser = Parser.new(AstBuilder.new(id_generator))
17
+ @compiler = Pickles::Compiler.new(id_generator)
18
+ end
19
+
20
+ def id_generator_class
21
+ @options[:predictable_ids] ? Gherkin::IdGenerator::Incrementing : Gherkin::IdGenerator::UUID
15
22
  end
16
23
 
17
24
  def messages
@@ -0,0 +1,29 @@
1
+ require 'rspec'
2
+ require 'gherkin/id_generator'
3
+
4
+ describe Gherkin::IdGenerator::Incrementing do
5
+ subject { Gherkin::IdGenerator::Incrementing.new }
6
+
7
+ context '#new_id' do
8
+ it 'returns 0 the first time' do
9
+ expect(subject.new_id).to eq("0")
10
+ end
11
+
12
+ it 'increments on every call' do
13
+ expect(subject.new_id).to eq("0")
14
+ expect(subject.new_id).to eq("1")
15
+ expect(subject.new_id).to eq("2")
16
+ end
17
+ end
18
+ end
19
+
20
+ describe Gherkin::IdGenerator::UUID do
21
+ subject { Gherkin::IdGenerator::UUID.new }
22
+
23
+ context '#new_id' do
24
+ it 'generates a UUID' do
25
+ allowed_characters = "[0-9a-fA-F]"
26
+ expect(subject.new_id).to match(/#{allowed_characters}{8}\-#{allowed_characters}{4}\-#{allowed_characters}{4}\-#{allowed_characters}{4}\-#{allowed_characters}{12}/)
27
+ end
28
+ end
29
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: gherkin
3
3
  version: !ruby/object:Gem::Version
4
- version: 8.1.1
4
+ version: 8.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Gáspár Nagy
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2019-10-17 00:00:00.000000000 Z
13
+ date: 2019-11-14 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: cucumber-messages
@@ -18,20 +18,20 @@ dependencies:
18
18
  requirements:
19
19
  - - "~>"
20
20
  - !ruby/object:Gem::Version
21
- version: '6.0'
21
+ version: '7.0'
22
22
  - - ">="
23
23
  - !ruby/object:Gem::Version
24
- version: 6.0.2
24
+ version: 7.0.0
25
25
  type: :runtime
26
26
  prerelease: false
27
27
  version_requirements: !ruby/object:Gem::Requirement
28
28
  requirements:
29
29
  - - "~>"
30
30
  - !ruby/object:Gem::Version
31
- version: '6.0'
31
+ version: '7.0'
32
32
  - - ">="
33
33
  - !ruby/object:Gem::Version
34
- version: 6.0.2
34
+ version: 7.0.0
35
35
  - !ruby/object:Gem::Dependency
36
36
  name: rake
37
37
  requirement: !ruby/object:Gem::Requirement
@@ -41,7 +41,7 @@ dependencies:
41
41
  version: '13.0'
42
42
  - - ">="
43
43
  - !ruby/object:Gem::Version
44
- version: 13.0.0
44
+ version: 13.0.1
45
45
  type: :development
46
46
  prerelease: false
47
47
  version_requirements: !ruby/object:Gem::Requirement
@@ -51,7 +51,7 @@ dependencies:
51
51
  version: '13.0'
52
52
  - - ">="
53
53
  - !ruby/object:Gem::Version
54
- version: 13.0.0
54
+ version: 13.0.1
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: rspec
57
57
  requirement: !ruby/object:Gem::Requirement
@@ -111,6 +111,7 @@ files:
111
111
  - lib/gherkin/errors.rb
112
112
  - lib/gherkin/gherkin-languages.json
113
113
  - lib/gherkin/gherkin_line.rb
114
+ - lib/gherkin/id_generator.rb
114
115
  - lib/gherkin/parser.rb
115
116
  - lib/gherkin/pickles/compiler.rb
116
117
  - lib/gherkin/stream/parser_message_stream.rb
@@ -123,6 +124,7 @@ files:
123
124
  - spec/coverage.rb
124
125
  - spec/gherkin/dialect_spec.rb
125
126
  - spec/gherkin/gherkin_spec.rb
127
+ - spec/gherkin/id_generator_spec.rb
126
128
  - spec/gherkin/stream/subprocess_message_stream_spec.rb
127
129
  homepage: https://github.com/cucumber/gherkin-ruby
128
130
  licenses:
@@ -153,10 +155,11 @@ rubyforge_project:
153
155
  rubygems_version: 2.7.6.2
154
156
  signing_key:
155
157
  specification_version: 4
156
- summary: gherkin-8.1.1
158
+ summary: gherkin-8.2.0
157
159
  test_files:
158
160
  - spec/gherkin/dialect_spec.rb
159
161
  - spec/gherkin/stream/subprocess_message_stream_spec.rb
162
+ - spec/gherkin/id_generator_spec.rb
160
163
  - spec/gherkin/gherkin_spec.rb
161
164
  - spec/capture_warnings.rb
162
165
  - spec/coverage.rb