bryanl-gherkin 2.11.1.1-java
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.
- data/.gitattributes +2 -0
- data/.mailmap +2 -0
- data/.rbenv-gemsets +1 -0
- data/.rspec +1 -0
- data/.rvmrc +1 -0
- data/.travis.yml +16 -0
- data/.yardopts +5 -0
- data/Gemfile +5 -0
- data/History.md +788 -0
- data/LICENSE +20 -0
- data/README.md +272 -0
- data/Rakefile +26 -0
- data/build_native_gems.sh +7 -0
- data/cucumber.yml +4 -0
- data/examples/parse_and_output_json.rb +19 -0
- data/features/.cucumber/stepdefs.json +244 -0
- data/features/escaped_pipes.feature +8 -0
- data/features/feature_parser.feature +237 -0
- data/features/json_formatter.feature +498 -0
- data/features/json_parser.feature +331 -0
- data/features/native_lexer.feature +19 -0
- data/features/parser_with_native_lexer.feature +205 -0
- data/features/pretty_formatter.feature +16 -0
- data/features/step_definitions/eyeball_steps.rb +3 -0
- data/features/step_definitions/gherkin_steps.rb +29 -0
- data/features/step_definitions/json_formatter_steps.rb +30 -0
- data/features/step_definitions/json_parser_steps.rb +20 -0
- data/features/step_definitions/pretty_formatter_steps.rb +85 -0
- data/features/steps_parser.feature +46 -0
- data/features/support/env.rb +42 -0
- data/gherkin.gemspec +77 -0
- data/install_mingw_os_x.sh +7 -0
- data/js/.npmignore +1 -0
- data/js/lib/gherkin/lexer/.npmignore +0 -0
- data/lib/gherkin/c_lexer.rb +17 -0
- data/lib/gherkin/formatter/ansi_escapes.rb +97 -0
- data/lib/gherkin/formatter/argument.rb +16 -0
- data/lib/gherkin/formatter/escaping.rb +15 -0
- data/lib/gherkin/formatter/filter_formatter.rb +146 -0
- data/lib/gherkin/formatter/hashable.rb +19 -0
- data/lib/gherkin/formatter/json_formatter.rb +122 -0
- data/lib/gherkin/formatter/line_filter.rb +26 -0
- data/lib/gherkin/formatter/model.rb +281 -0
- data/lib/gherkin/formatter/pretty_formatter.rb +244 -0
- data/lib/gherkin/formatter/regexp_filter.rb +21 -0
- data/lib/gherkin/formatter/step_printer.rb +21 -0
- data/lib/gherkin/formatter/tag_count_formatter.rb +47 -0
- data/lib/gherkin/formatter/tag_filter.rb +19 -0
- data/lib/gherkin/i18n.rb +180 -0
- data/lib/gherkin/i18n.yml +613 -0
- data/lib/gherkin/js_lexer.rb +20 -0
- data/lib/gherkin/json_parser.rb +177 -0
- data/lib/gherkin/lexer/i18n_lexer.rb +46 -0
- data/lib/gherkin/listener/event.rb +45 -0
- data/lib/gherkin/listener/formatter_listener.rb +143 -0
- data/lib/gherkin/native/java.rb +72 -0
- data/lib/gherkin/native/null.rb +5 -0
- data/lib/gherkin/native/therubyracer.rb +39 -0
- data/lib/gherkin/native.rb +7 -0
- data/lib/gherkin/parser/meta.txt +5 -0
- data/lib/gherkin/parser/parser.rb +164 -0
- data/lib/gherkin/parser/root.txt +11 -0
- data/lib/gherkin/parser/steps.txt +4 -0
- data/lib/gherkin/rb_lexer/README.rdoc +8 -0
- data/lib/gherkin/rb_lexer.rb +8 -0
- data/lib/gherkin/rubify.rb +24 -0
- data/lib/gherkin/tag_expression.rb +62 -0
- data/lib/gherkin.jar +0 -0
- data/lib/gherkin.rb +2 -0
- data/ragel/lexer.c.rl.erb +454 -0
- data/ragel/lexer.java.rl.erb +219 -0
- data/ragel/lexer.js.rl.erb +227 -0
- data/ragel/lexer.rb.rl.erb +174 -0
- data/ragel/lexer_common.rl.erb +50 -0
- data/spec/gherkin/c_lexer_spec.rb +22 -0
- data/spec/gherkin/fixtures/1.feature +8 -0
- data/spec/gherkin/fixtures/comments_in_table.feature +9 -0
- data/spec/gherkin/fixtures/complex.feature +45 -0
- data/spec/gherkin/fixtures/complex.json +139 -0
- data/spec/gherkin/fixtures/complex_for_filtering.feature +60 -0
- data/spec/gherkin/fixtures/complex_with_tags.feature +61 -0
- data/spec/gherkin/fixtures/dos_line_endings.feature +45 -0
- data/spec/gherkin/fixtures/examples_with_only_header.feature +14 -0
- data/spec/gherkin/fixtures/hantu_pisang.feature +35 -0
- data/spec/gherkin/fixtures/i18n_fr.feature +14 -0
- data/spec/gherkin/fixtures/i18n_fr2.feature +8 -0
- data/spec/gherkin/fixtures/i18n_no.feature +7 -0
- data/spec/gherkin/fixtures/i18n_pt1.feature +44 -0
- data/spec/gherkin/fixtures/i18n_pt2.feature +4 -0
- data/spec/gherkin/fixtures/i18n_pt3.feature +4 -0
- data/spec/gherkin/fixtures/i18n_pt4.feature +4 -0
- data/spec/gherkin/fixtures/i18n_zh-CN.feature +9 -0
- data/spec/gherkin/fixtures/issue_145.feature +22 -0
- data/spec/gherkin/fixtures/scenario_outline_with_tags.feature +13 -0
- data/spec/gherkin/fixtures/scenario_without_steps.feature +5 -0
- data/spec/gherkin/fixtures/simple_with_comments.feature +7 -0
- data/spec/gherkin/fixtures/simple_with_tags.feature +11 -0
- data/spec/gherkin/fixtures/with_bom.feature +3 -0
- data/spec/gherkin/formatter/ansi_escapes_spec.rb +32 -0
- data/spec/gherkin/formatter/filter_formatter_spec.rb +204 -0
- data/spec/gherkin/formatter/json_formatter_spec.rb +92 -0
- data/spec/gherkin/formatter/model_spec.rb +28 -0
- data/spec/gherkin/formatter/pretty_formatter_spec.rb +177 -0
- data/spec/gherkin/formatter/spaces.feature +9 -0
- data/spec/gherkin/formatter/step_printer_spec.rb +55 -0
- data/spec/gherkin/formatter/tabs.feature +9 -0
- data/spec/gherkin/formatter/tag_count_formatter_spec.rb +30 -0
- data/spec/gherkin/i18n_spec.rb +241 -0
- data/spec/gherkin/java_lexer_spec.rb +20 -0
- data/spec/gherkin/js_lexer_spec.rb +23 -0
- data/spec/gherkin/json_parser_spec.rb +176 -0
- data/spec/gherkin/lexer/i18n_lexer_spec.rb +43 -0
- data/spec/gherkin/output_stream_string_io.rb +20 -0
- data/spec/gherkin/parser/parser_spec.rb +16 -0
- data/spec/gherkin/rb_lexer_spec.rb +20 -0
- data/spec/gherkin/sexp_recorder.rb +59 -0
- data/spec/gherkin/shared/bom_group.rb +20 -0
- data/spec/gherkin/shared/doc_string_group.rb +163 -0
- data/spec/gherkin/shared/lexer_group.rb +591 -0
- data/spec/gherkin/shared/row_group.rb +125 -0
- data/spec/gherkin/shared/tags_group.rb +54 -0
- data/spec/gherkin/tag_expression_spec.rb +142 -0
- data/spec/spec_helper.rb +75 -0
- data/tasks/bench/feature_builder.rb +49 -0
- data/tasks/bench/null_listener.rb +4 -0
- data/tasks/bench.rake +184 -0
- data/tasks/compile.rake +120 -0
- data/tasks/cucumber.rake +22 -0
- data/tasks/gems.rake +31 -0
- data/tasks/ikvm.rake +124 -0
- data/tasks/ragel_task.rb +100 -0
- data/tasks/release.rake +49 -0
- data/tasks/rspec.rake +8 -0
- data/tasks/yard/default/layout/html/bubble_32x32.png +0 -0
- data/tasks/yard/default/layout/html/bubble_48x48.png +0 -0
- data/tasks/yard/default/layout/html/footer.erb +5 -0
- data/tasks/yard/default/layout/html/index.erb +1 -0
- data/tasks/yard/default/layout/html/layout.erb +25 -0
- data/tasks/yard/default/layout/html/logo.erb +1 -0
- data/tasks/yard/default/layout/html/setup.rb +4 -0
- data/tasks/yard.rake +7 -0
- metadata +412 -0
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
require 'json'
|
|
2
|
+
require 'gherkin/formatter/model'
|
|
3
|
+
require 'gherkin/native'
|
|
4
|
+
require 'base64'
|
|
5
|
+
|
|
6
|
+
module Gherkin
|
|
7
|
+
module Formatter
|
|
8
|
+
# This class doesn't really generate JSON - instead it populates an Array that can easily
|
|
9
|
+
# be turned into JSON.
|
|
10
|
+
class JSONFormatter
|
|
11
|
+
native_impl('gherkin')
|
|
12
|
+
|
|
13
|
+
include Base64
|
|
14
|
+
|
|
15
|
+
def initialize(io)
|
|
16
|
+
raise "Must be writeable" unless io.respond_to?(:write)
|
|
17
|
+
@io = io
|
|
18
|
+
@feature_hashes = []
|
|
19
|
+
@current_step_or_hook = nil
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def done
|
|
23
|
+
@io.write(@feature_hashes.to_json)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def uri(uri)
|
|
27
|
+
@uri = uri
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def feature(feature)
|
|
31
|
+
@feature_hash = feature.to_hash
|
|
32
|
+
@feature_hash['uri'] = @uri
|
|
33
|
+
@feature_hashes << @feature_hash
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def background(background)
|
|
37
|
+
feature_elements << background.to_hash
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def scenario(scenario)
|
|
41
|
+
feature_elements << scenario.to_hash
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def scenario_outline(scenario_outline)
|
|
45
|
+
feature_elements << scenario_outline.to_hash
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def examples(examples)
|
|
49
|
+
all_examples << examples.to_hash
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def step(step)
|
|
53
|
+
@current_step_or_hook = step.to_hash
|
|
54
|
+
steps << @current_step_or_hook
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def match(match)
|
|
58
|
+
@current_step_or_hook['match'] = match.to_hash
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def result(result)
|
|
62
|
+
@current_step_or_hook['result'] = result.to_hash
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def before(match, result)
|
|
66
|
+
add_hook(match, result, "before")
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def after(match, result)
|
|
70
|
+
add_hook(match, result, "after")
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def embedding(mime_type, data)
|
|
74
|
+
embeddings << {'mime_type' => mime_type, 'data' => encode64s(data)}
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def write(text)
|
|
78
|
+
output << text
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def eof
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
private
|
|
85
|
+
|
|
86
|
+
def add_hook(match, result, hook)
|
|
87
|
+
hooks = feature_element[hook] ||= []
|
|
88
|
+
hooks << {'match' => match.to_hash, 'result' => result.to_hash}
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
def feature_elements
|
|
92
|
+
@feature_hash['elements'] ||= []
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
def feature_element
|
|
96
|
+
feature_elements[-1]
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
def all_examples
|
|
100
|
+
feature_element['examples'] ||= []
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
def steps
|
|
104
|
+
feature_element['steps'] ||= []
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
def embeddings
|
|
108
|
+
@current_step_or_hook['embeddings'] ||= []
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
def output
|
|
112
|
+
@current_step_or_hook['output'] ||= []
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
def encode64s(data)
|
|
116
|
+
# Strip newlines
|
|
117
|
+
Base64.encode64(data).gsub(/\n/, '')
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
end
|
|
122
|
+
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
module Gherkin
|
|
2
|
+
module Formatter
|
|
3
|
+
class LineFilter
|
|
4
|
+
def initialize(lines)
|
|
5
|
+
@lines = lines
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
def eval(tags, names, ranges)
|
|
9
|
+
ranges.detect do |range|
|
|
10
|
+
@lines.detect do |line|
|
|
11
|
+
range.include?(line)
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def filter_table_body_rows(rows)
|
|
17
|
+
body = rows.to_a[1..-1].select do |row|
|
|
18
|
+
@lines.detect do |line|
|
|
19
|
+
row.line == line
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
[rows[0]] + body
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
@@ -0,0 +1,281 @@
|
|
|
1
|
+
require 'gherkin/native'
|
|
2
|
+
require 'gherkin/formatter/hashable'
|
|
3
|
+
|
|
4
|
+
module Gherkin
|
|
5
|
+
module Formatter
|
|
6
|
+
module Model
|
|
7
|
+
class BasicStatement < Hashable
|
|
8
|
+
attr_reader :comments, :keyword, :name, :line
|
|
9
|
+
|
|
10
|
+
def initialize(comments, keyword, name, line)
|
|
11
|
+
@comments, @keyword, @name, @line = comments, keyword, name, line
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def line_range
|
|
15
|
+
first = @comments.any? ? @comments[0].line : first_non_comment_line
|
|
16
|
+
first..line
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def first_non_comment_line
|
|
20
|
+
@line
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
class DescribedStatement < BasicStatement
|
|
25
|
+
attr_reader :description
|
|
26
|
+
|
|
27
|
+
def initialize(comments, keyword, name, description, line)
|
|
28
|
+
super(comments, keyword, name, line)
|
|
29
|
+
@description = description
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
class TagStatement < DescribedStatement
|
|
34
|
+
attr_reader :tags, :id
|
|
35
|
+
|
|
36
|
+
def initialize(comments, tags, keyword, name, description, line, id)
|
|
37
|
+
super(comments, keyword, name, description, line)
|
|
38
|
+
@tags = tags
|
|
39
|
+
@id = id
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def first_non_comment_line
|
|
43
|
+
@tags.any? ? @tags[0].line : @line
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
class Feature < TagStatement
|
|
48
|
+
native_impl('gherkin')
|
|
49
|
+
|
|
50
|
+
def replay(formatter)
|
|
51
|
+
formatter.feature(self)
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
class Background < DescribedStatement
|
|
56
|
+
native_impl('gherkin')
|
|
57
|
+
|
|
58
|
+
def initialize(comments, keyword, name, description, line)
|
|
59
|
+
super(comments, keyword, name, description, line)
|
|
60
|
+
@type = "background"
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def replay(formatter)
|
|
64
|
+
formatter.background(self)
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
class Scenario < TagStatement
|
|
69
|
+
native_impl('gherkin')
|
|
70
|
+
|
|
71
|
+
def initialize(comments, tags, keyword, name, description, line, id)
|
|
72
|
+
super(comments, tags, keyword, name, description, line, id)
|
|
73
|
+
@type = "scenario"
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def replay(formatter)
|
|
77
|
+
formatter.scenario(self)
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
class ScenarioOutline < TagStatement
|
|
82
|
+
native_impl('gherkin')
|
|
83
|
+
|
|
84
|
+
def initialize(comments, tags, keyword, name, description, line, id)
|
|
85
|
+
super(comments, tags, keyword, name, description, line, id)
|
|
86
|
+
@type = "scenario_outline"
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
def replay(formatter)
|
|
90
|
+
formatter.scenario_outline(self)
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
class Examples < TagStatement
|
|
95
|
+
native_impl('gherkin')
|
|
96
|
+
|
|
97
|
+
attr_accessor :rows # needs to remain mutable for filters
|
|
98
|
+
|
|
99
|
+
def initialize(comments, tags, keyword, name, description, line, id, rows)
|
|
100
|
+
super(comments, tags, keyword, name, description, line, id)
|
|
101
|
+
@rows = rows
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
def replay(formatter)
|
|
105
|
+
formatter.examples(self)
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
class Builder
|
|
109
|
+
def initialize(*args)
|
|
110
|
+
@args = *args
|
|
111
|
+
@rows = nil
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
def row(comments, cells, line, id)
|
|
115
|
+
@rows ||= []
|
|
116
|
+
@rows << ExamplesTableRow.new(comments, cells, line, id)
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
def replay(formatter)
|
|
120
|
+
build.replay(formatter)
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
def build
|
|
124
|
+
Examples.new(*(@args << @rows))
|
|
125
|
+
end
|
|
126
|
+
end
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
class Step < BasicStatement
|
|
130
|
+
native_impl('gherkin')
|
|
131
|
+
|
|
132
|
+
attr_reader :rows, :doc_string
|
|
133
|
+
|
|
134
|
+
def initialize(comments, keyword, name, line, rows, doc_string)
|
|
135
|
+
super(comments, keyword, name, line)
|
|
136
|
+
@rows, @doc_string = rows, doc_string
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
def line_range
|
|
140
|
+
range = super
|
|
141
|
+
if(rows)
|
|
142
|
+
range = range.first..rows[-1].line
|
|
143
|
+
elsif(doc_string)
|
|
144
|
+
range = range.first..doc_string.line_range.last
|
|
145
|
+
end
|
|
146
|
+
range
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
def replay(formatter)
|
|
150
|
+
formatter.step(self)
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
def outline_args
|
|
154
|
+
offset = 0
|
|
155
|
+
name.scan(/<[^<]*>/).map do |val|
|
|
156
|
+
offset = name.index(val, offset)
|
|
157
|
+
Argument.new(offset, val)
|
|
158
|
+
end
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
class Builder
|
|
162
|
+
def initialize(*args)
|
|
163
|
+
@args = *args
|
|
164
|
+
@rows = nil
|
|
165
|
+
@doc_string = nil
|
|
166
|
+
end
|
|
167
|
+
|
|
168
|
+
def row(comments, cells, line, id)
|
|
169
|
+
@rows ||= []
|
|
170
|
+
@rows << DataTableRow.new(comments, cells, line)
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
def doc_string(string, content_type, line)
|
|
174
|
+
@doc_string = Formatter::Model::DocString.new(string, content_type, line)
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
def replay(formatter)
|
|
178
|
+
build.replay(formatter)
|
|
179
|
+
end
|
|
180
|
+
|
|
181
|
+
def build
|
|
182
|
+
Step.new(*(@args << @rows << @doc_string))
|
|
183
|
+
end
|
|
184
|
+
end
|
|
185
|
+
end
|
|
186
|
+
|
|
187
|
+
class Comment < Hashable
|
|
188
|
+
native_impl('gherkin')
|
|
189
|
+
|
|
190
|
+
attr_reader :value, :line
|
|
191
|
+
|
|
192
|
+
def initialize(value, line)
|
|
193
|
+
@value, @line = value, line
|
|
194
|
+
end
|
|
195
|
+
end
|
|
196
|
+
|
|
197
|
+
class Tag < Hashable
|
|
198
|
+
native_impl('gherkin')
|
|
199
|
+
|
|
200
|
+
attr_reader :name, :line
|
|
201
|
+
|
|
202
|
+
def initialize(name, line)
|
|
203
|
+
@name, @line = name, line
|
|
204
|
+
end
|
|
205
|
+
|
|
206
|
+
def eql?(tag)
|
|
207
|
+
@name.eql?(tag.name)
|
|
208
|
+
end
|
|
209
|
+
|
|
210
|
+
def hash
|
|
211
|
+
@name.hash
|
|
212
|
+
end
|
|
213
|
+
end
|
|
214
|
+
|
|
215
|
+
class DocString < Hashable
|
|
216
|
+
native_impl('gherkin')
|
|
217
|
+
|
|
218
|
+
attr_reader :value, :content_type, :line
|
|
219
|
+
|
|
220
|
+
def initialize(value, content_type, line)
|
|
221
|
+
@value, @content_type, @line = value, content_type, line
|
|
222
|
+
end
|
|
223
|
+
|
|
224
|
+
def line_range
|
|
225
|
+
line_count = value.split(/\r?\n/).length
|
|
226
|
+
line..(line+line_count+1)
|
|
227
|
+
end
|
|
228
|
+
end
|
|
229
|
+
|
|
230
|
+
class Row < Hashable
|
|
231
|
+
attr_reader :comments, :cells, :line
|
|
232
|
+
|
|
233
|
+
def initialize(comments, cells, line)
|
|
234
|
+
@comments, @cells, @line = comments, cells, line
|
|
235
|
+
end
|
|
236
|
+
end
|
|
237
|
+
|
|
238
|
+
class DataTableRow < Row
|
|
239
|
+
native_impl('gherkin')
|
|
240
|
+
end
|
|
241
|
+
|
|
242
|
+
class ExamplesTableRow < Row
|
|
243
|
+
native_impl('gherkin')
|
|
244
|
+
attr_reader :id
|
|
245
|
+
|
|
246
|
+
def initialize(comments, cells, line, id)
|
|
247
|
+
super(comments, cells, line)
|
|
248
|
+
@id = id
|
|
249
|
+
end
|
|
250
|
+
end
|
|
251
|
+
|
|
252
|
+
class Match < Hashable
|
|
253
|
+
native_impl('gherkin')
|
|
254
|
+
|
|
255
|
+
attr_reader :arguments, :location
|
|
256
|
+
|
|
257
|
+
def initialize(arguments, location)
|
|
258
|
+
@arguments, @location = arguments, location
|
|
259
|
+
end
|
|
260
|
+
|
|
261
|
+
def replay(formatter)
|
|
262
|
+
formatter.match(self)
|
|
263
|
+
end
|
|
264
|
+
end
|
|
265
|
+
|
|
266
|
+
class Result < Hashable
|
|
267
|
+
native_impl('gherkin')
|
|
268
|
+
|
|
269
|
+
attr_reader :status, :duration, :error_message
|
|
270
|
+
|
|
271
|
+
def initialize(status, duration, error_message)
|
|
272
|
+
@status, @duration, @error_message = status, duration, error_message
|
|
273
|
+
end
|
|
274
|
+
|
|
275
|
+
def replay(formatter)
|
|
276
|
+
formatter.result(self)
|
|
277
|
+
end
|
|
278
|
+
end
|
|
279
|
+
end
|
|
280
|
+
end
|
|
281
|
+
end
|
|
@@ -0,0 +1,244 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
require 'gherkin/formatter/ansi_escapes'
|
|
3
|
+
require 'gherkin/formatter/step_printer'
|
|
4
|
+
require 'gherkin/formatter/argument'
|
|
5
|
+
require 'gherkin/formatter/escaping'
|
|
6
|
+
require 'gherkin/formatter/model'
|
|
7
|
+
require 'gherkin/native'
|
|
8
|
+
|
|
9
|
+
module Gherkin
|
|
10
|
+
module Formatter
|
|
11
|
+
class PrettyFormatter
|
|
12
|
+
native_impl('gherkin')
|
|
13
|
+
|
|
14
|
+
include AnsiEscapes
|
|
15
|
+
include Escaping
|
|
16
|
+
|
|
17
|
+
def initialize(io, monochrome, executing)
|
|
18
|
+
@io = io
|
|
19
|
+
@step_printer = StepPrinter.new
|
|
20
|
+
@monochrome = monochrome
|
|
21
|
+
@executing = executing
|
|
22
|
+
@background = nil
|
|
23
|
+
@tag_statement = nil
|
|
24
|
+
@steps = []
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def uri(uri)
|
|
28
|
+
@uri = uri
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def feature(feature)
|
|
32
|
+
print_comments(feature.comments, '')
|
|
33
|
+
print_tags(feature.tags, '')
|
|
34
|
+
@io.puts "#{feature.keyword}: #{feature.name}"
|
|
35
|
+
print_description(feature.description, ' ', false)
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def background(background)
|
|
39
|
+
replay
|
|
40
|
+
@statement = background
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def scenario(scenario)
|
|
44
|
+
replay
|
|
45
|
+
@statement = scenario
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def scenario_outline(scenario_outline)
|
|
49
|
+
replay
|
|
50
|
+
@statement = scenario_outline
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def replay
|
|
54
|
+
print_statement
|
|
55
|
+
print_steps
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def print_statement
|
|
59
|
+
return if @statement.nil?
|
|
60
|
+
calculate_location_indentations
|
|
61
|
+
@io.puts
|
|
62
|
+
print_comments(@statement.comments, ' ')
|
|
63
|
+
print_tags(@statement.tags, ' ') if @statement.respond_to?(:tags) # Background doesn't
|
|
64
|
+
@io.write " #{@statement.keyword}: #{@statement.name}"
|
|
65
|
+
location = @executing ? "#{@uri}:#{@statement.line}" : nil
|
|
66
|
+
@io.puts indented_location(location, true)
|
|
67
|
+
print_description(@statement.description, ' ')
|
|
68
|
+
@statement = nil
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def print_steps
|
|
72
|
+
while(@steps.any?)
|
|
73
|
+
print_step('skipped', [], nil, true)
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def examples(examples)
|
|
78
|
+
replay
|
|
79
|
+
@io.puts
|
|
80
|
+
print_comments(examples.comments, ' ')
|
|
81
|
+
print_tags(examples.tags, ' ')
|
|
82
|
+
@io.puts " #{examples.keyword}: #{examples.name}"
|
|
83
|
+
print_description(examples.description, ' ')
|
|
84
|
+
table(examples.rows)
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
def step(step)
|
|
88
|
+
@steps << step
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
def match(match)
|
|
92
|
+
@match = match
|
|
93
|
+
print_statement
|
|
94
|
+
print_step('executing', @match.arguments, @match.location, false)
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
def result(result)
|
|
98
|
+
@io.write(up(1))
|
|
99
|
+
print_step(result.status, @match.arguments, @match.location, true)
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
def print_step(status, arguments, location, proceed)
|
|
103
|
+
step = proceed ? @steps.shift : @steps[0]
|
|
104
|
+
|
|
105
|
+
text_format = format(status)
|
|
106
|
+
arg_format = arg_format(status)
|
|
107
|
+
|
|
108
|
+
print_comments(step.comments, ' ')
|
|
109
|
+
@io.write(' ')
|
|
110
|
+
@io.write(text_format.text(step.keyword))
|
|
111
|
+
@step_printer.write_step(@io, text_format, arg_format, step.name, arguments)
|
|
112
|
+
@io.puts(indented_location(location, proceed))
|
|
113
|
+
|
|
114
|
+
doc_string(step.doc_string) if step.doc_string
|
|
115
|
+
table(step.rows) if step.rows
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
class MonochromeFormat
|
|
119
|
+
def text(text)
|
|
120
|
+
text
|
|
121
|
+
end
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
class ColorFormat
|
|
125
|
+
include AnsiEscapes
|
|
126
|
+
|
|
127
|
+
def initialize(status)
|
|
128
|
+
@status = status
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
def text(text)
|
|
132
|
+
self.__send__(@status) + text + reset
|
|
133
|
+
end
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
def arg_format(key)
|
|
137
|
+
format("#{key}_arg")
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
def format(key)
|
|
141
|
+
if @formats.nil?
|
|
142
|
+
if @monochrome
|
|
143
|
+
@formats = Hash.new(MonochromeFormat.new)
|
|
144
|
+
else
|
|
145
|
+
@formats = Hash.new do |formats, status|
|
|
146
|
+
formats[status] = ColorFormat.new(status)
|
|
147
|
+
end
|
|
148
|
+
end
|
|
149
|
+
end
|
|
150
|
+
@formats[key]
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
def eof
|
|
154
|
+
replay
|
|
155
|
+
# NO-OP
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
def done
|
|
159
|
+
# NO-OP
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
def table(rows)
|
|
163
|
+
cell_lengths = rows.map do |row|
|
|
164
|
+
row.cells.map do |cell|
|
|
165
|
+
escape_cell(cell).unpack("U*").length
|
|
166
|
+
end
|
|
167
|
+
end
|
|
168
|
+
max_lengths = cell_lengths.transpose.map { |col_lengths| col_lengths.max }.flatten
|
|
169
|
+
|
|
170
|
+
rows.each_with_index do |row, i|
|
|
171
|
+
row.comments.each do |comment|
|
|
172
|
+
@io.puts " #{comment.value}"
|
|
173
|
+
end
|
|
174
|
+
j = -1
|
|
175
|
+
@io.puts ' | ' + row.cells.zip(max_lengths).map { |cell, max_length|
|
|
176
|
+
j += 1
|
|
177
|
+
color(cell, nil, j) + ' ' * (max_length - cell_lengths[i][j])
|
|
178
|
+
}.join(' | ') + ' |'
|
|
179
|
+
end
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
private
|
|
183
|
+
|
|
184
|
+
def doc_string(doc_string)
|
|
185
|
+
@io.puts " \"\"\"" + doc_string.content_type + "\n" + escape_triple_quotes(indent(doc_string.value, ' ')) + "\n \"\"\""
|
|
186
|
+
end
|
|
187
|
+
|
|
188
|
+
def exception(exception)
|
|
189
|
+
exception_text = "#{exception.message} (#{exception.class})\n#{(exception.backtrace || []).join("\n")}".gsub(/^/, ' ')
|
|
190
|
+
@io.puts(failed(exception_text))
|
|
191
|
+
end
|
|
192
|
+
|
|
193
|
+
def color(cell, statuses, col)
|
|
194
|
+
if statuses
|
|
195
|
+
self.__send__(statuses[col], escape_cell(cell)) + reset
|
|
196
|
+
else
|
|
197
|
+
escape_cell(cell)
|
|
198
|
+
end
|
|
199
|
+
end
|
|
200
|
+
|
|
201
|
+
if(RUBY_VERSION =~ /^1\.9/)
|
|
202
|
+
START = /#{'^'.encode('UTF-8')}/
|
|
203
|
+
TRIPLE_QUOTES = /#{'"""'.encode('UTF-8')}/
|
|
204
|
+
else
|
|
205
|
+
START = /^/
|
|
206
|
+
TRIPLE_QUOTES = /"""/
|
|
207
|
+
end
|
|
208
|
+
|
|
209
|
+
def indent(string, indentation)
|
|
210
|
+
string.gsub(START, indentation)
|
|
211
|
+
end
|
|
212
|
+
|
|
213
|
+
def escape_triple_quotes(s)
|
|
214
|
+
s.gsub(TRIPLE_QUOTES, '\"\"\"')
|
|
215
|
+
end
|
|
216
|
+
|
|
217
|
+
def print_tags(tags, indent)
|
|
218
|
+
@io.write(tags.empty? ? '' : indent + tags.map{|tag| tag.name}.join(' ') + "\n")
|
|
219
|
+
end
|
|
220
|
+
|
|
221
|
+
def print_comments(comments, indent)
|
|
222
|
+
@io.write(comments.empty? ? '' : indent + comments.map{|comment| comment.value}.join("\n#{indent}") + "\n")
|
|
223
|
+
end
|
|
224
|
+
|
|
225
|
+
def print_description(description, indent, newline=true)
|
|
226
|
+
if description != ""
|
|
227
|
+
@io.puts indent(description, indent)
|
|
228
|
+
@io.puts if newline
|
|
229
|
+
end
|
|
230
|
+
end
|
|
231
|
+
|
|
232
|
+
def indented_location(location, proceed)
|
|
233
|
+
indentation = proceed ? @indentations.shift : @indentations[0]
|
|
234
|
+
location ? (' ' * indentation + ' ' + comments + "# #{location}" + reset) : ''
|
|
235
|
+
end
|
|
236
|
+
|
|
237
|
+
def calculate_location_indentations
|
|
238
|
+
line_widths = ([@statement] + @steps).map {|step| (step.keyword+step.name).unpack("U*").length}
|
|
239
|
+
max_line_width = line_widths.max
|
|
240
|
+
@indentations = line_widths.map{|w| max_line_width - w}
|
|
241
|
+
end
|
|
242
|
+
end
|
|
243
|
+
end
|
|
244
|
+
end
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
module Gherkin
|
|
2
|
+
module Formatter
|
|
3
|
+
class RegexpFilter
|
|
4
|
+
def initialize(regexen)
|
|
5
|
+
@regexen = regexen
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
def eval(tags, names, ranges)
|
|
9
|
+
@regexen.detect do |regexp|
|
|
10
|
+
names.detect do |name|
|
|
11
|
+
name =~ regexp
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def filter_table_body_rows(rows)
|
|
17
|
+
rows
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
module Gherkin
|
|
2
|
+
module Formatter
|
|
3
|
+
class StepPrinter
|
|
4
|
+
def write_step(io, text_format, arg_format, step_name, arguments)
|
|
5
|
+
unpacked_step_name = step_name.unpack("U*")
|
|
6
|
+
|
|
7
|
+
text_start = 0
|
|
8
|
+
arguments.each do |arg|
|
|
9
|
+
if(arg.offset != 0 && !arg.offset.nil?)
|
|
10
|
+
io.write(text_format.text(unpacked_step_name[text_start..arg.offset-1].pack("U*")))
|
|
11
|
+
end
|
|
12
|
+
if(!arg.val.nil?)
|
|
13
|
+
io.write(arg_format.text(arg.val))
|
|
14
|
+
text_start = arg.offset + arg.val.unpack("U*").length
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
io.write(text_format.text(unpacked_step_name[text_start..-1].pack("U*"))) unless text_start == unpacked_step_name.length
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|