gherkin 8.1.1 → 8.2.0

Sign up to get free protection for your applications and to get access to all the features.
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