cucumber-gherkin 9.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,40 @@
1
+ require 'stringio'
2
+ require 'gherkin/token'
3
+ require 'gherkin/gherkin_line'
4
+
5
+ module Gherkin
6
+ # The scanner reads a gherkin doc (typically read from a .feature file) and
7
+ # creates a token for line. The tokens are passed to the parser, which outputs
8
+ # an AST (Abstract Syntax Tree).
9
+ #
10
+ # If the scanner sees a # language header, it will reconfigure itself dynamically
11
+ # to look for Gherkin keywords for the associated language. The keywords are defined
12
+ # in gherkin-languages.json.
13
+ class TokenScanner
14
+ def initialize(source_or_io)
15
+ @line_number = 0
16
+
17
+ case(source_or_io)
18
+ when String
19
+ @io = StringIO.new(source_or_io)
20
+ when StringIO, IO
21
+ @io = source_or_io
22
+ else
23
+ fail ArgumentError, "Please a pass String, StringIO or IO. I got a #{source_or_io.class}"
24
+ end
25
+ end
26
+
27
+ def read
28
+ location = {line: @line_number += 1, column: 0}
29
+ if @io.nil? || line = @io.gets
30
+ gherkin_line = line ? GherkinLine.new(line, location[:line]) : nil
31
+ Token.new(gherkin_line, location)
32
+ else
33
+ @io.close unless @io.closed? # ARGF closes the last file after final gets
34
+ @io = nil
35
+ Token.new(nil, location)
36
+ end
37
+ end
38
+
39
+ end
40
+ end
@@ -0,0 +1,74 @@
1
+ # frozen_string_literal: true
2
+ # With thanks to @myronmarston
3
+ # https://github.com/vcr/vcr/blob/master/spec/capture_warnings.rb
4
+
5
+ module CaptureWarnings
6
+ def report_warnings(&block)
7
+ current_dir = Dir.pwd
8
+ warnings, errors = capture_error(&block).partition { |line| line.include?('warning') }
9
+ project_warnings, other_warnings = warnings.uniq.partition { |line| line.include?(current_dir) }
10
+
11
+ if errors.any?
12
+ puts errors.join("\n")
13
+ end
14
+
15
+ if other_warnings.any?
16
+ puts "#{ other_warnings.count } warnings detected, set VIEW_OTHER_WARNINGS=true to see them."
17
+ print_warnings('other', other_warnings) if ENV['VIEW_OTHER_WARNINGS']
18
+ end
19
+
20
+ # Until they fix https://bugs.ruby-lang.org/issues/10661
21
+ if RUBY_VERSION == "2.2.0"
22
+ project_warnings = project_warnings.reject { |w| w =~ /warning: possible reference to past scope/ }
23
+ end
24
+
25
+ if project_warnings.any?
26
+ puts "#{ project_warnings.count } warnings detected"
27
+ print_warnings('cucumber-expressions', project_warnings)
28
+ fail "Please remove all cucumber-expressions warnings."
29
+ end
30
+
31
+ ensure_system_exit_if_required
32
+ end
33
+
34
+ def capture_error(&block)
35
+ old_stderr = STDERR.clone
36
+ pipe_r, pipe_w = IO.pipe
37
+ pipe_r.sync = true
38
+ error = String.new
39
+ reader = Thread.new do
40
+ begin
41
+ loop do
42
+ error << pipe_r.readpartial(1024)
43
+ end
44
+ rescue EOFError
45
+ end
46
+ end
47
+ STDERR.reopen(pipe_w)
48
+ block.call
49
+ ensure
50
+ capture_system_exit
51
+ STDERR.reopen(old_stderr)
52
+ pipe_w.close
53
+ reader.join
54
+ return error.split("\n")
55
+ end
56
+
57
+ def print_warnings(type, warnings)
58
+ puts
59
+ puts "-" * 30 + " #{type} warnings: " + "-" * 30
60
+ puts
61
+ puts warnings.join("\n")
62
+ puts
63
+ puts "-" * 75
64
+ puts
65
+ end
66
+
67
+ def ensure_system_exit_if_required
68
+ raise @system_exit if @system_exit
69
+ end
70
+
71
+ def capture_system_exit
72
+ @system_exit = $!
73
+ end
74
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+ require 'simplecov'
3
+ formatters = [ SimpleCov::Formatter::HTMLFormatter ]
4
+
5
+ SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter.new(*formatters)
6
+ SimpleCov.add_filter 'spec/'
7
+ SimpleCov.start
@@ -0,0 +1,13 @@
1
+ # coding: utf-8
2
+ require 'rspec'
3
+ require 'gherkin/dialect'
4
+
5
+ module Gherkin
6
+ describe Dialect do
7
+ it 'provides an interface to the keywords of a dialect' do
8
+ dialect_en = Dialect.for('en')
9
+
10
+ expect(dialect_en.feature_keywords).to eq(['Feature', 'Business Need', 'Ability'])
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,45 @@
1
+ require 'rspec'
2
+ require 'gherkin'
3
+
4
+ describe Gherkin do
5
+ it "can process feature file paths" do
6
+ messages = Gherkin.from_paths(
7
+ ["testdata/good/minimal.feature"],
8
+ {include_source: true,
9
+ include_gherkin_document: true,
10
+ include_pickles: true}
11
+ ).to_a
12
+
13
+ expect(messages.length).to eq(3)
14
+ end
15
+
16
+ it "can process feature file content" do
17
+ data = File.open("testdata/good/minimal.feature", 'r:UTF-8', &:read)
18
+
19
+ messages = Gherkin.from_source(
20
+ "uri",
21
+ data,
22
+ {include_source: true,
23
+ include_gherkin_document: true,
24
+ include_pickles: true}
25
+ ).to_a
26
+
27
+ expect(messages.length).to eq(3)
28
+ end
29
+
30
+ it "can set the default dialect for the feature file content" do
31
+ data = File.open("testdata/good/i18n_no.feature", 'r:UTF-8', &:read)
32
+ data_without_language_header = data.split("\n")[1..-1].join("\n")
33
+
34
+ messages = Gherkin.from_source(
35
+ "uri",
36
+ data,
37
+ {include_source: true,
38
+ include_gherkin_document: true,
39
+ include_pickles: true,
40
+ default_dialect: "no"}
41
+ ).to_a
42
+
43
+ expect(messages.length).to eq(3)
44
+ end
45
+ end
@@ -0,0 +1,142 @@
1
+ require 'rspec'
2
+ require 'gherkin'
3
+ require 'gherkin/query'
4
+
5
+ describe Gherkin::Query do
6
+ let(:subject) { Gherkin::Query.new() }
7
+
8
+ def filter_messages_by_attribute(messages, attribute)
9
+ messages.map do |message|
10
+ return unless message.respond_to?(attribute)
11
+ message.send(attribute)
12
+ end.compact
13
+ end
14
+
15
+ def find_message_by_attribute(messages, attribute)
16
+ filter_messages_by_attribute(messages, attribute).first
17
+ end
18
+
19
+ let(:gherkin_document) { find_message_by_attribute(messages, :gherkin_document) }
20
+
21
+ let(:messages) {
22
+ Gherkin.from_source(
23
+ "some/path",
24
+ feature_content,
25
+ {
26
+ include_gherkin_document: true
27
+ }
28
+ ).to_a
29
+ }
30
+
31
+ let(:feature_content) {
32
+ """
33
+ @feature-tag
34
+ Feature: my feature
35
+
36
+ Background:
37
+ Given a passed background step
38
+
39
+ @scenario-tag
40
+ Scenario: my scenario
41
+ Given a passed step
42
+
43
+ Scenario Outline: with examples
44
+ Given a <Status> step
45
+
46
+ @example-tag
47
+ Examples:
48
+ | Status |
49
+ | passed |
50
+
51
+
52
+ Rule: this is a rule
53
+ Background:
54
+ Given the passed step in the rule background
55
+
56
+ @ruled-scenario-tag
57
+ Scenario: a ruled scenario
58
+ Given a step in the ruled scenario
59
+ """
60
+ }
61
+
62
+ before do
63
+ messages.each { |message|
64
+ subject.update(message)
65
+ }
66
+ end
67
+
68
+ context '#location' do
69
+ let(:background) { find_message_by_attribute(gherkin_document.feature.children, :background) }
70
+ let(:scenarios) { filter_messages_by_attribute(gherkin_document.feature.children, :scenario) }
71
+ let(:scenario) { scenarios.first }
72
+
73
+ it 'raises an exception when the AST node ID is unknown' do
74
+ expect { subject.location("this-id-may-not-exist-for-real") }.to raise_exception(Gherkin::AstNodeNotLocatedException)
75
+ end
76
+
77
+ it 'provides the location of a scenario' do
78
+ expect(subject.location(scenario.id)).to eq(scenario.location)
79
+ end
80
+
81
+ it 'provides the location of an examples table row' do
82
+ node = scenarios.last.examples.first.table_body.first
83
+ expect(subject.location(node.id)).to eq(node.location)
84
+ end
85
+
86
+ context 'when querying steps' do
87
+ let(:background_step) { background.steps.first }
88
+ let(:scenario_step) { scenario.steps.first }
89
+
90
+ it 'provides the location of a background step' do
91
+ expect(subject.location(background_step.id)).to eq(background_step.location)
92
+ end
93
+
94
+ it 'provides the location of a scenario step' do
95
+ expect(subject.location(scenario_step.id)).to eq(scenario_step.location)
96
+ end
97
+ end
98
+
99
+ context 'when querying tags' do
100
+ let(:feature_tag) { gherkin_document.feature.tags.first }
101
+ let(:scenario_tag) { scenario.tags.first }
102
+ let(:example_tag) { scenarios.last.examples.first.tags.first }
103
+
104
+ it 'provides the location of a feature tags' do
105
+ expect(subject.location(feature_tag.id)).to eq(feature_tag.location)
106
+ end
107
+
108
+ it 'provides the location of a scenario tags' do
109
+ expect(subject.location(scenario_tag.id)).to eq(scenario_tag.location)
110
+ end
111
+
112
+ it 'provides the location of a scenario example tags' do
113
+ expect(subject.location(example_tag.id)).to eq(example_tag.location)
114
+ end
115
+ end
116
+
117
+ context 'when children are scoped in a Rule' do
118
+ let(:rule) { find_message_by_attribute(gherkin_document.feature.children, :rule) }
119
+ let(:rule_background) { find_message_by_attribute(rule.children, :background) }
120
+ let(:rule_background_step) { rule_background.steps.first }
121
+ let(:rule_scenario) { find_message_by_attribute(rule.children, :scenario) }
122
+ let(:rule_scenario_step) { rule_scenario.steps.first }
123
+ let(:rule_scenario_tag) { rule_scenario.tags.first }
124
+
125
+ it 'provides the location of a background step' do
126
+ expect(subject.location(rule_background_step.id)).to eq(rule_background_step.location)
127
+ end
128
+
129
+ it 'provides the location of a scenario' do
130
+ expect(subject.location(rule_scenario.id)).to eq(rule_scenario.location)
131
+ end
132
+
133
+ it 'provides the location of a scenario tag' do
134
+ expect(subject.location(rule_scenario_tag.id)).to eq(rule_scenario_tag.location)
135
+ end
136
+
137
+ it 'provides the location of a scenario step' do
138
+ expect(subject.location(rule_scenario_step.id)).to eq(rule_scenario_step.location)
139
+ end
140
+ end
141
+ end
142
+ end
@@ -0,0 +1,67 @@
1
+ require 'rspec'
2
+ require 'gherkin/stream/parser_message_stream'
3
+
4
+ module Gherkin
5
+ module Stream
6
+ describe ParserMessageStream do
7
+ let(:feature_content) {
8
+ "Feature: my feature\n" \
9
+ " Scenario: a scenario\n" \
10
+ " Given some context"
11
+ }
12
+
13
+ let(:source_feature) {
14
+ Cucumber::Messages::Source.new({
15
+ uri: '//whatever/uri',
16
+ data: feature_content,
17
+ media_type: 'text/x.cucumber.gherkin+plain'
18
+ })
19
+ }
20
+
21
+ let(:options) {
22
+ {
23
+ include_gherkin_document: true,
24
+ }
25
+ }
26
+
27
+ let(:gherkin_document) {
28
+ ParserMessageStream.new([], [source_feature], options).messages.first.gherkin_document
29
+ }
30
+
31
+ let(:scenario_id) { gherkin_document.feature.children.first.scenario.id }
32
+
33
+ context '#messages' do
34
+ it "raises an exception on second iteration" do
35
+ messages = ParserMessageStream.new([], [source_feature], options).messages
36
+
37
+ expect { messages.map(&:to_s) }.not_to raise_exception
38
+ expect { messages.map(&:to_s) }.to raise_exception(Gherkin::DoubleIterationException)
39
+ end
40
+ end
41
+
42
+ context 'options.id_generator' do
43
+ context 'when not set' do
44
+ it 'generates random UUIDs' do
45
+ expect(scenario_id).to match(/[0-9a-fA-F]{8}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{12}/)
46
+ end
47
+ end
48
+
49
+
50
+ context 'when set' do
51
+ let(:id_generator) { double }
52
+ let(:options) {
53
+ {
54
+ include_gherkin_document: true,
55
+ id_generator: id_generator
56
+ }
57
+ }
58
+
59
+ it 'uses the generator instance to produce the IDs' do
60
+ allow(id_generator).to receive(:new_id).and_return('some-random-id')
61
+ expect(scenario_id).to eq('some-random-id')
62
+ end
63
+ end
64
+ end
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,18 @@
1
+ require 'rspec'
2
+ require 'gherkin/stream/subprocess_message_stream'
3
+
4
+ module Gherkin
5
+ module Stream
6
+ describe SubprocessMessageStream do
7
+ it "works" do
8
+ cucumber_messages = SubprocessMessageStream.new(
9
+ "./bin/gherkin",
10
+ ["testdata/good/minimal.feature"],
11
+ true, true, true
12
+ )
13
+ messages = cucumber_messages.messages.to_a
14
+ expect(messages.length).to eq(3)
15
+ end
16
+ end
17
+ end
18
+ end
metadata ADDED
@@ -0,0 +1,167 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: cucumber-gherkin
3
+ version: !ruby/object:Gem::Version
4
+ version: 9.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Gáspár Nagy
8
+ - Aslak Hellesøy
9
+ - Steve Tooke
10
+ autorequire:
11
+ bindir: bin
12
+ cert_chain: []
13
+ date: 2020-01-10 00:00:00.000000000 Z
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: cucumber-messages
17
+ requirement: !ruby/object:Gem::Requirement
18
+ requirements:
19
+ - - "~>"
20
+ - !ruby/object:Gem::Version
21
+ version: '9.0'
22
+ - - ">="
23
+ - !ruby/object:Gem::Version
24
+ version: 9.0.3
25
+ type: :runtime
26
+ prerelease: false
27
+ version_requirements: !ruby/object:Gem::Requirement
28
+ requirements:
29
+ - - "~>"
30
+ - !ruby/object:Gem::Version
31
+ version: '9.0'
32
+ - - ">="
33
+ - !ruby/object:Gem::Version
34
+ version: 9.0.3
35
+ - !ruby/object:Gem::Dependency
36
+ name: rake
37
+ requirement: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - "~>"
40
+ - !ruby/object:Gem::Version
41
+ version: '13.0'
42
+ - - ">="
43
+ - !ruby/object:Gem::Version
44
+ version: 13.0.1
45
+ type: :development
46
+ prerelease: false
47
+ version_requirements: !ruby/object:Gem::Requirement
48
+ requirements:
49
+ - - "~>"
50
+ - !ruby/object:Gem::Version
51
+ version: '13.0'
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: 13.0.1
55
+ - !ruby/object:Gem::Dependency
56
+ name: rspec
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '3.9'
62
+ - - ">="
63
+ - !ruby/object:Gem::Version
64
+ version: 3.9.0
65
+ type: :development
66
+ prerelease: false
67
+ version_requirements: !ruby/object:Gem::Requirement
68
+ requirements:
69
+ - - "~>"
70
+ - !ruby/object:Gem::Version
71
+ version: '3.9'
72
+ - - ">="
73
+ - !ruby/object:Gem::Version
74
+ version: 3.9.0
75
+ - !ruby/object:Gem::Dependency
76
+ name: coveralls
77
+ requirement: !ruby/object:Gem::Requirement
78
+ requirements:
79
+ - - "~>"
80
+ - !ruby/object:Gem::Version
81
+ version: '0.8'
82
+ - - ">="
83
+ - !ruby/object:Gem::Version
84
+ version: 0.8.23
85
+ type: :development
86
+ prerelease: false
87
+ version_requirements: !ruby/object:Gem::Requirement
88
+ requirements:
89
+ - - "~>"
90
+ - !ruby/object:Gem::Version
91
+ version: '0.8'
92
+ - - ">="
93
+ - !ruby/object:Gem::Version
94
+ version: 0.8.23
95
+ description: Gherkin parser
96
+ email: cukes@googlegroups.com
97
+ executables:
98
+ - gherkin-ruby
99
+ - gherkin
100
+ extensions: []
101
+ extra_rdoc_files: []
102
+ files:
103
+ - LICENSE
104
+ - README.md
105
+ - bin/gherkin
106
+ - bin/gherkin-ruby
107
+ - lib/gherkin.rb
108
+ - lib/gherkin/ast_builder.rb
109
+ - lib/gherkin/ast_node.rb
110
+ - lib/gherkin/dialect.rb
111
+ - lib/gherkin/errors.rb
112
+ - lib/gherkin/gherkin-languages.json
113
+ - lib/gherkin/gherkin_line.rb
114
+ - lib/gherkin/parser.rb
115
+ - lib/gherkin/pickles/compiler.rb
116
+ - lib/gherkin/query.rb
117
+ - lib/gherkin/stream/parser_message_stream.rb
118
+ - lib/gherkin/stream/subprocess_message_stream.rb
119
+ - lib/gherkin/token.rb
120
+ - lib/gherkin/token_formatter_builder.rb
121
+ - lib/gherkin/token_matcher.rb
122
+ - lib/gherkin/token_scanner.rb
123
+ - spec/capture_warnings.rb
124
+ - spec/coverage.rb
125
+ - spec/gherkin/dialect_spec.rb
126
+ - spec/gherkin/gherkin_spec.rb
127
+ - spec/gherkin/query_spec.rb
128
+ - spec/gherkin/stream/parser_message_stream_spec.rb
129
+ - spec/gherkin/stream/subprocess_message_stream_spec.rb
130
+ homepage: https://github.com/cucumber/gherkin-ruby
131
+ licenses:
132
+ - MIT
133
+ metadata:
134
+ bug_tracker_uri: https://github.com/cucumber/cucumber/issues
135
+ changelog_uri: https://github.com/cucumber/cucumber/blob/master/gherkin/CHANGELOG.md
136
+ documentation_uri: https://cucumber.io/docs/gherkin/
137
+ mailing_list_uri: https://groups.google.com/forum/#!forum/cukes
138
+ source_code_uri: https://github.com/cucumber/cucumber/blob/master/gherkin/ruby
139
+ post_install_message:
140
+ rdoc_options:
141
+ - "--charset=UTF-8"
142
+ require_paths:
143
+ - lib
144
+ required_ruby_version: !ruby/object:Gem::Requirement
145
+ requirements:
146
+ - - ">="
147
+ - !ruby/object:Gem::Version
148
+ version: '2.3'
149
+ required_rubygems_version: !ruby/object:Gem::Requirement
150
+ requirements:
151
+ - - ">="
152
+ - !ruby/object:Gem::Version
153
+ version: '0'
154
+ requirements: []
155
+ rubyforge_project:
156
+ rubygems_version: 2.7.6.2
157
+ signing_key:
158
+ specification_version: 4
159
+ summary: cucumber-gherkin-9.1.0
160
+ test_files:
161
+ - spec/gherkin/dialect_spec.rb
162
+ - spec/gherkin/stream/parser_message_stream_spec.rb
163
+ - spec/gherkin/stream/subprocess_message_stream_spec.rb
164
+ - spec/gherkin/gherkin_spec.rb
165
+ - spec/gherkin/query_spec.rb
166
+ - spec/capture_warnings.rb
167
+ - spec/coverage.rb