cucumber-gherkin 29.0.0 → 30.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.
- checksums.yaml +4 -4
- data/bin/gherkin +12 -10
- data/bin/gherkin-ruby +2 -0
- data/lib/gherkin/ast_builder.rb +27 -19
- data/lib/gherkin/ast_node.rb +2 -0
- data/lib/gherkin/dialect.rb +4 -1
- data/lib/gherkin/errors.rb +5 -3
- data/lib/gherkin/gherkin_line.rb +7 -6
- data/lib/gherkin/parser.rb +532 -532
- data/lib/gherkin/pickles/compiler.rb +21 -14
- data/lib/gherkin/query.rb +6 -0
- data/lib/gherkin/stream/parser_message_stream.rb +16 -13
- data/lib/gherkin/token.rb +2 -0
- data/lib/gherkin/token_formatter_builder.rb +17 -11
- data/lib/gherkin/token_matcher.rb +20 -19
- data/lib/gherkin/token_scanner.rb +8 -5
- data/lib/gherkin.rb +11 -11
- metadata +6 -6
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'cucumber/messages'
|
2
4
|
|
3
5
|
module Gherkin
|
@@ -11,6 +13,7 @@ module Gherkin
|
|
11
13
|
pickles = []
|
12
14
|
|
13
15
|
return pickles unless gherkin_document.feature
|
16
|
+
|
14
17
|
feature = gherkin_document.feature
|
15
18
|
language = feature.language
|
16
19
|
tags = feature.tags
|
@@ -65,8 +68,11 @@ module Gherkin
|
|
65
68
|
unless scenario.steps.empty?
|
66
69
|
[].concat(background_steps).concat(scenario.steps).each do |step|
|
67
70
|
last_keyword_type =
|
68
|
-
step.keyword_type == Cucumber::Messages::StepKeywordType::CONJUNCTION
|
69
|
-
last_keyword_type
|
71
|
+
if step.keyword_type == Cucumber::Messages::StepKeywordType::CONJUNCTION
|
72
|
+
last_keyword_type
|
73
|
+
else
|
74
|
+
step.keyword_type
|
75
|
+
end
|
70
76
|
steps.push(Cucumber::Messages::PickleStep.new(**pickle_step_props(step, [], nil, last_keyword_type)))
|
71
77
|
end
|
72
78
|
end
|
@@ -95,15 +101,21 @@ module Gherkin
|
|
95
101
|
unless scenario.steps.empty?
|
96
102
|
background_steps.each do |step|
|
97
103
|
last_keyword_type =
|
98
|
-
step.keyword_type == Cucumber::Messages::StepKeywordType::CONJUNCTION
|
99
|
-
last_keyword_type
|
104
|
+
if step.keyword_type == Cucumber::Messages::StepKeywordType::CONJUNCTION
|
105
|
+
last_keyword_type
|
106
|
+
else
|
107
|
+
step.keyword_type
|
108
|
+
end
|
100
109
|
step_props = pickle_step_props(step, [], nil, last_keyword_type)
|
101
110
|
steps.push(Cucumber::Messages::PickleStep.new(**step_props))
|
102
111
|
end
|
103
112
|
scenario.steps.each do |step|
|
104
113
|
last_keyword_type =
|
105
|
-
step.keyword_type == Cucumber::Messages::StepKeywordType::CONJUNCTION
|
106
|
-
last_keyword_type
|
114
|
+
if step.keyword_type == Cucumber::Messages::StepKeywordType::CONJUNCTION
|
115
|
+
last_keyword_type
|
116
|
+
else
|
117
|
+
step.keyword_type
|
118
|
+
end
|
107
119
|
step_props = pickle_step_props(step, variable_cells, values_row, last_keyword_type)
|
108
120
|
steps.push(Cucumber::Messages::PickleStep.new(**step_props))
|
109
121
|
end
|
@@ -122,7 +134,6 @@ module Gherkin
|
|
122
134
|
]
|
123
135
|
)
|
124
136
|
pickles.push(pickle)
|
125
|
-
|
126
137
|
end
|
127
138
|
end
|
128
139
|
end
|
@@ -143,9 +154,7 @@ module Gherkin
|
|
143
154
|
type: keyword_type,
|
144
155
|
text: interpolate(step.text, variable_cells, value_cells),
|
145
156
|
}
|
146
|
-
if values_row
|
147
|
-
props[:ast_node_ids].push(values_row.id)
|
148
|
-
end
|
157
|
+
props[:ast_node_ids].push(values_row.id) if values_row
|
149
158
|
|
150
159
|
if step.data_table
|
151
160
|
data_table = Cucumber::Messages::PickleStepArgument.new(
|
@@ -180,14 +189,12 @@ module Gherkin
|
|
180
189
|
props = {
|
181
190
|
content: interpolate(doc_string.content, variable_cells, value_cells)
|
182
191
|
}
|
183
|
-
if doc_string.media_type
|
184
|
-
props[:media_type] = interpolate(doc_string.media_type, variable_cells, value_cells)
|
185
|
-
end
|
192
|
+
props[:media_type] = interpolate(doc_string.media_type, variable_cells, value_cells) if doc_string.media_type
|
186
193
|
Cucumber::Messages::PickleDocString.new(**props)
|
187
194
|
end
|
188
195
|
|
189
196
|
def pickle_tags(tags)
|
190
|
-
tags.map {|tag| pickle_tag(tag)}
|
197
|
+
tags.map { |tag| pickle_tag(tag) }
|
191
198
|
end
|
192
199
|
|
193
200
|
def pickle_tag(tag)
|
data/lib/gherkin/query.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Gherkin
|
2
4
|
class Query
|
3
5
|
def initialize
|
@@ -12,11 +14,13 @@ module Gherkin
|
|
12
14
|
|
13
15
|
def scenario_parent_locations(scenario_node_id)
|
14
16
|
return @scenario_parent_locations[scenario_node_id] if @scenario_parent_locations.has_key?(scenario_node_id)
|
17
|
+
|
15
18
|
raise AstNodeNotLocatedException, "No scenario parent locations found for #{scenario_node_id} }. Known: #{@scenario_parent_locations.keys}"
|
16
19
|
end
|
17
20
|
|
18
21
|
def location(ast_node_id)
|
19
22
|
return @ast_node_locations[ast_node_id] if @ast_node_locations.has_key?(ast_node_id)
|
23
|
+
|
20
24
|
raise AstNodeNotLocatedException, "No location found for #{ast_node_id} }. Known: #{@ast_node_locations.keys}"
|
21
25
|
end
|
22
26
|
|
@@ -24,6 +28,7 @@ module Gherkin
|
|
24
28
|
|
25
29
|
def update_feature(feature)
|
26
30
|
return if feature.nil?
|
31
|
+
|
27
32
|
store_nodes_location(feature.tags)
|
28
33
|
|
29
34
|
feature.children.each do |child|
|
@@ -35,6 +40,7 @@ module Gherkin
|
|
35
40
|
|
36
41
|
def update_rule(feature, rule)
|
37
42
|
return if rule.nil?
|
43
|
+
|
38
44
|
store_nodes_location(rule.tags)
|
39
45
|
rule.children.each do |child|
|
40
46
|
update_background(rule, child.background) if child.background
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'cucumber/messages'
|
2
4
|
require_relative '../parser'
|
3
5
|
require_relative '../token_matcher'
|
@@ -18,30 +20,31 @@ module Gherkin
|
|
18
20
|
|
19
21
|
def messages
|
20
22
|
enumerated = false
|
21
|
-
Enumerator.new do |
|
23
|
+
Enumerator.new do |yielder|
|
22
24
|
raise DoubleIterationException, "Messages have already been enumerated" if enumerated
|
25
|
+
|
23
26
|
enumerated = true
|
24
27
|
|
25
28
|
sources.each do |source|
|
26
|
-
|
29
|
+
yielder.yield(Cucumber::Messages::Envelope.new(source: source)) if @options[:include_source]
|
27
30
|
begin
|
28
31
|
gherkin_document = nil
|
29
32
|
|
30
33
|
if @options[:include_gherkin_document]
|
31
34
|
gherkin_document = build_gherkin_document(source)
|
32
|
-
|
35
|
+
yielder.yield(Cucumber::Messages::Envelope.new(gherkin_document: gherkin_document))
|
33
36
|
end
|
34
37
|
if @options[:include_pickles]
|
35
38
|
gherkin_document ||= build_gherkin_document(source)
|
36
39
|
pickles = @compiler.compile(gherkin_document, source)
|
37
40
|
pickles.each do |pickle|
|
38
|
-
|
41
|
+
yielder.yield(Cucumber::Messages::Envelope.new(pickle: pickle))
|
39
42
|
end
|
40
43
|
end
|
41
|
-
rescue CompositeParserException =>
|
42
|
-
yield_parse_errors(
|
43
|
-
rescue ParserException =>
|
44
|
-
yield_parse_errors(
|
44
|
+
rescue CompositeParserException => e
|
45
|
+
yield_parse_errors(yielder, e.errors, source.uri)
|
46
|
+
rescue ParserException => e
|
47
|
+
yield_parse_errors(yielder, [e], source.uri)
|
45
48
|
end
|
46
49
|
end
|
47
50
|
end
|
@@ -49,7 +52,7 @@ module Gherkin
|
|
49
52
|
|
50
53
|
private
|
51
54
|
|
52
|
-
def yield_parse_errors(
|
55
|
+
def yield_parse_errors(yielder, errors, uri)
|
53
56
|
errors.each do |err|
|
54
57
|
parse_error = Cucumber::Messages::ParseError.new(
|
55
58
|
source: Cucumber::Messages::SourceReference.new(
|
@@ -61,22 +64,22 @@ module Gherkin
|
|
61
64
|
),
|
62
65
|
message: err.message
|
63
66
|
)
|
64
|
-
|
67
|
+
yielder.yield(Cucumber::Messages::Envelope.new(parse_error: parse_error))
|
65
68
|
end
|
66
69
|
end
|
67
70
|
|
68
71
|
def sources
|
69
|
-
Enumerator.new do |
|
72
|
+
Enumerator.new do |yielder|
|
70
73
|
@paths.each do |path|
|
71
74
|
source = Cucumber::Messages::Source.new(
|
72
75
|
uri: path,
|
73
76
|
data: File.open(path, 'r:UTF-8', &:read),
|
74
77
|
media_type: 'text/x.cucumber.gherkin+plain'
|
75
78
|
)
|
76
|
-
|
79
|
+
yielder.yield(source)
|
77
80
|
end
|
78
81
|
@sources.each do |source|
|
79
|
-
|
82
|
+
yielder.yield(source)
|
80
83
|
end
|
81
84
|
end
|
82
85
|
end
|
data/lib/gherkin/token.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Gherkin
|
2
4
|
class TokenFormatterBuilder
|
3
5
|
def initialize
|
@@ -5,35 +7,39 @@ module Gherkin
|
|
5
7
|
end
|
6
8
|
|
7
9
|
def reset
|
8
|
-
@
|
10
|
+
@tokens = []
|
9
11
|
end
|
10
12
|
|
11
13
|
def build(token)
|
12
|
-
|
14
|
+
tokens << token
|
13
15
|
end
|
14
16
|
|
15
|
-
def start_rule(
|
16
|
-
end
|
17
|
+
def start_rule(_rule_type); end
|
17
18
|
|
18
|
-
def end_rule(
|
19
|
-
end
|
19
|
+
def end_rule(_rule_type); end
|
20
20
|
|
21
21
|
def get_result
|
22
|
-
|
22
|
+
tokens.map { |token| "#{format_token(token)}\n" }.join
|
23
23
|
end
|
24
24
|
|
25
25
|
private
|
26
|
+
|
27
|
+
def tokens
|
28
|
+
@tokens ||= []
|
29
|
+
end
|
30
|
+
|
26
31
|
def format_token(token)
|
27
|
-
return
|
32
|
+
return 'EOF' if token.eof?
|
28
33
|
|
29
|
-
sprintf
|
34
|
+
sprintf(
|
35
|
+
"(%s:%s)%s:%s/%s/%s",
|
30
36
|
token.location[:line],
|
31
37
|
token.location[:column],
|
32
38
|
token.matched_type,
|
33
39
|
token.matched_keyword ? sprintf("(%s)%s", token.matched_keyword_type, token.matched_keyword) : "",
|
34
40
|
token.matched_text,
|
35
|
-
Array(token.matched_items).map { |i| "#{i.column}:#{i.text}"}.join(',')
|
41
|
+
Array(token.matched_items).map { |i| "#{i.column}:#{i.text}" }.join(',')
|
42
|
+
)
|
36
43
|
end
|
37
|
-
|
38
44
|
end
|
39
45
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'cucumber/messages'
|
2
4
|
require_relative 'dialect'
|
3
5
|
require_relative 'errors'
|
@@ -35,7 +37,7 @@ module Gherkin
|
|
35
37
|
|
36
38
|
def match_ScenarioLine(token)
|
37
39
|
match_title_line(token, :ScenarioLine, @dialect.scenario_keywords) ||
|
38
|
-
|
40
|
+
match_title_line(token, :ScenarioLine, @dialect.scenario_outline_keywords)
|
39
41
|
end
|
40
42
|
|
41
43
|
def match_BackgroundLine(token)
|
@@ -48,21 +50,22 @@ module Gherkin
|
|
48
50
|
|
49
51
|
def match_TableRow(token)
|
50
52
|
return false unless token.line.start_with?('|')
|
51
|
-
|
52
|
-
set_token_matched(token, :TableRow, nil, nil, nil, nil,
|
53
|
-
token.line.table_cells)
|
53
|
+
|
54
|
+
set_token_matched(token, :TableRow, nil, nil, nil, nil, token.line.table_cells)
|
54
55
|
true
|
55
56
|
end
|
56
57
|
|
57
58
|
def match_Empty(token)
|
58
59
|
return false unless token.line.empty?
|
60
|
+
|
59
61
|
set_token_matched(token, :Empty, nil, nil, 0)
|
60
62
|
true
|
61
63
|
end
|
62
64
|
|
63
65
|
def match_Comment(token)
|
64
66
|
return false unless token.line.start_with?('#')
|
65
|
-
|
67
|
+
|
68
|
+
text = token.line.get_line_text(0) # take the entire line, including leading space
|
66
69
|
set_token_matched(token, :Comment, text, nil, 0)
|
67
70
|
true
|
68
71
|
end
|
@@ -70,7 +73,7 @@ module Gherkin
|
|
70
73
|
def match_Language(token)
|
71
74
|
return false unless token.line.trimmed_line_text =~ LANGUAGE_PATTERN
|
72
75
|
|
73
|
-
dialect_name =
|
76
|
+
dialect_name = Regexp.last_match(1)
|
74
77
|
set_token_matched(token, :Language, dialect_name)
|
75
78
|
|
76
79
|
change_dialect(dialect_name, token.location)
|
@@ -82,7 +85,7 @@ module Gherkin
|
|
82
85
|
if @active_doc_string_separator.nil?
|
83
86
|
# open
|
84
87
|
_match_DocStringSeparator(token, '"""', true) ||
|
85
|
-
|
88
|
+
_match_DocStringSeparator(token, '```', true)
|
86
89
|
else
|
87
90
|
# close
|
88
91
|
_match_DocStringSeparator(token, @active_doc_string_separator, false)
|
@@ -108,6 +111,7 @@ module Gherkin
|
|
108
111
|
|
109
112
|
def match_EOF(token)
|
110
113
|
return false unless token.eof?
|
114
|
+
|
111
115
|
set_token_matched(token, :EOF)
|
112
116
|
true
|
113
117
|
end
|
@@ -119,11 +123,12 @@ module Gherkin
|
|
119
123
|
end
|
120
124
|
|
121
125
|
def match_StepLine(token)
|
122
|
-
keywords =
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
126
|
+
keywords =
|
127
|
+
@dialect.given_keywords +
|
128
|
+
@dialect.when_keywords +
|
129
|
+
@dialect.then_keywords +
|
130
|
+
@dialect.and_keywords +
|
131
|
+
@dialect.but_keywords
|
127
132
|
|
128
133
|
keyword = keywords.detect { |k| token.line.start_with?(k) }
|
129
134
|
|
@@ -132,22 +137,18 @@ module Gherkin
|
|
132
137
|
title = token.line.get_rest_trimmed(keyword.length)
|
133
138
|
keyword_types = @keyword_types[keyword]
|
134
139
|
keyword_type = keyword_types[0]
|
135
|
-
if keyword_types.length
|
136
|
-
keyword_type = Cucumber::Messages::StepKeywordType::UNKNOWN
|
137
|
-
end
|
140
|
+
keyword_type = Cucumber::Messages::StepKeywordType::UNKNOWN if keyword_types.length > 1
|
138
141
|
|
139
142
|
set_token_matched(token,
|
140
143
|
:StepLine, title, keyword, nil, keyword_type)
|
141
|
-
|
144
|
+
true
|
142
145
|
end
|
143
146
|
|
144
147
|
private
|
145
148
|
|
146
149
|
def add_keyword_type_mappings(keywords, type)
|
147
150
|
keywords.each do |keyword|
|
148
|
-
|
149
|
-
@keyword_types[keyword] = []
|
150
|
-
end
|
151
|
+
@keyword_types[keyword] = [] unless @keyword_types.has_key?(keyword)
|
151
152
|
@keyword_types[keyword] += [type]
|
152
153
|
end
|
153
154
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'stringio'
|
2
4
|
require_relative 'token'
|
3
5
|
require_relative 'gherkin_line'
|
@@ -14,7 +16,7 @@ module Gherkin
|
|
14
16
|
def initialize(source_or_io)
|
15
17
|
@line_number = 0
|
16
18
|
|
17
|
-
case
|
19
|
+
case source_or_io
|
18
20
|
when String
|
19
21
|
@io = StringIO.new(source_or_io)
|
20
22
|
when StringIO, IO
|
@@ -25,9 +27,11 @@ module Gherkin
|
|
25
27
|
end
|
26
28
|
|
27
29
|
def read
|
28
|
-
location = {line: @line_number += 1}
|
29
|
-
if @io.nil?
|
30
|
-
|
30
|
+
location = { line: @line_number += 1 }
|
31
|
+
if @io.nil?
|
32
|
+
Token.new(nil, location)
|
33
|
+
elsif (line = @io.gets)
|
34
|
+
gherkin_line = GherkinLine.new(line, location[:line])
|
31
35
|
Token.new(gherkin_line, location)
|
32
36
|
else
|
33
37
|
@io.close unless @io.closed? # ARGF closes the last file after final gets
|
@@ -35,6 +39,5 @@ module Gherkin
|
|
35
39
|
Token.new(nil, location)
|
36
40
|
end
|
37
41
|
end
|
38
|
-
|
39
42
|
end
|
40
43
|
end
|
data/lib/gherkin.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require_relative 'gherkin/stream/parser_message_stream'
|
2
4
|
|
3
5
|
module Gherkin
|
@@ -7,28 +9,26 @@ module Gherkin
|
|
7
9
|
include_pickles: true
|
8
10
|
}.freeze
|
9
11
|
|
10
|
-
def self.from_paths(paths, options={})
|
12
|
+
def self.from_paths(paths, options = {})
|
11
13
|
Stream::ParserMessageStream.new(
|
12
|
-
|
13
|
-
|
14
|
-
|
14
|
+
paths,
|
15
|
+
[],
|
16
|
+
options
|
15
17
|
).messages
|
16
18
|
end
|
17
19
|
|
18
|
-
def self.from_sources(sources, options={})
|
20
|
+
def self.from_sources(sources, options = {})
|
19
21
|
Stream::ParserMessageStream.new(
|
20
|
-
|
21
|
-
|
22
|
-
|
22
|
+
[],
|
23
|
+
sources,
|
24
|
+
options
|
23
25
|
).messages
|
24
26
|
end
|
25
27
|
|
26
|
-
def self.from_source(uri, data, options={})
|
28
|
+
def self.from_source(uri, data, options = {})
|
27
29
|
from_sources([encode_source_message(uri, data)], options)
|
28
30
|
end
|
29
31
|
|
30
|
-
private
|
31
|
-
|
32
32
|
def self.encode_source_message(uri, data)
|
33
33
|
Cucumber::Messages::Source.new(
|
34
34
|
uri: uri,
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: cucumber-gherkin
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 30.0.1
|
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: 2024-
|
13
|
+
date: 2024-11-12 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: cucumber-messages
|
@@ -21,7 +21,7 @@ dependencies:
|
|
21
21
|
version: '25'
|
22
22
|
- - "<"
|
23
23
|
- !ruby/object:Gem::Version
|
24
|
-
version: '
|
24
|
+
version: '28'
|
25
25
|
type: :runtime
|
26
26
|
prerelease: false
|
27
27
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -31,7 +31,7 @@ dependencies:
|
|
31
31
|
version: '25'
|
32
32
|
- - "<"
|
33
33
|
- !ruby/object:Gem::Version
|
34
|
-
version: '
|
34
|
+
version: '28'
|
35
35
|
- !ruby/object:Gem::Dependency
|
36
36
|
name: rake
|
37
37
|
requirement: !ruby/object:Gem::Requirement
|
@@ -126,8 +126,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
126
126
|
- !ruby/object:Gem::Version
|
127
127
|
version: 3.2.8
|
128
128
|
requirements: []
|
129
|
-
rubygems_version: 3.5.
|
129
|
+
rubygems_version: 3.5.22
|
130
130
|
signing_key:
|
131
131
|
specification_version: 4
|
132
|
-
summary: cucumber-gherkin-
|
132
|
+
summary: cucumber-gherkin-30.0.1
|
133
133
|
test_files: []
|