gherkin 1.0.30-i386-mingw32 → 2.0.0-i386-mingw32
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/.rspec +1 -0
- data/History.txt +19 -0
- data/Rakefile +4 -4
- data/VERSION.yml +2 -2
- data/features/feature_parser.feature +11 -0
- data/features/json_formatter.feature +238 -0
- data/features/pretty_formatter.feature +9 -0
- data/features/step_definitions/gherkin_steps.rb +1 -1
- data/features/step_definitions/json_formatter_steps.rb +32 -0
- data/features/step_definitions/pretty_formatter_steps.rb +24 -23
- data/features/support/env.rb +3 -3
- data/lib/gherkin/formatter/json_formatter.rb +82 -0
- data/lib/gherkin/formatter/pretty_formatter.rb +73 -78
- data/lib/gherkin/i18n.rb +22 -18
- data/lib/gherkin/i18n.yml +9 -9
- data/lib/gherkin/i18n_lexer.rb +2 -2
- data/lib/gherkin/parser/event.rb +6 -6
- data/lib/gherkin/parser/filter_listener.rb +5 -1
- data/lib/gherkin/parser/formatter_listener.rb +113 -0
- data/lib/gherkin/parser/json_parser.rb +102 -0
- data/lib/gherkin/parser/parser.rb +10 -2
- data/lib/gherkin/parser/row.rb +15 -0
- data/lib/gherkin/rubify.rb +2 -0
- data/lib/gherkin/tools/files.rb +1 -1
- data/lib/gherkin/tools/reformat.rb +1 -2
- data/lib/gherkin/tools/stats.rb +1 -1
- data/lib/gherkin/tools/stats_listener.rb +5 -5
- data/ragel/lexer.c.rl.erb +41 -12
- data/ragel/lexer.java.rl.erb +26 -17
- data/ragel/lexer.rb.rl.erb +10 -5
- data/ragel/lexer_common.rl.erb +6 -6
- data/spec/gherkin/c_lexer_spec.rb +2 -2
- data/spec/gherkin/fixtures/complex.js +105 -0
- data/spec/gherkin/formatter/argument_spec.rb +3 -3
- data/spec/gherkin/formatter/colors_spec.rb +3 -4
- data/spec/gherkin/formatter/pretty_formatter_spec.rb +21 -50
- data/spec/gherkin/i18n_lexer_spec.rb +6 -6
- data/spec/gherkin/i18n_spec.rb +16 -9
- data/spec/gherkin/java_lexer_spec.rb +1 -2
- data/spec/gherkin/output_stream_string_io.rb +24 -0
- data/spec/gherkin/parser/filter_listener_spec.rb +16 -9
- data/spec/gherkin/parser/formatter_listener_spec.rb +134 -0
- data/spec/gherkin/parser/json_parser_spec.rb +129 -0
- data/spec/gherkin/parser/parser_spec.rb +9 -9
- data/spec/gherkin/parser/tag_expression_spec.rb +8 -8
- data/spec/gherkin/rb_lexer_spec.rb +1 -1
- data/spec/gherkin/sexp_recorder.rb +21 -1
- data/spec/gherkin/shared/{lexer_spec.rb → lexer_group.rb} +172 -102
- data/spec/gherkin/shared/{py_string_spec.rb → py_string_group.rb} +21 -17
- data/spec/gherkin/shared/{row_spec.rb → row_group.rb} +36 -19
- data/spec/gherkin/shared/{tags_spec.rb → tags_group.rb} +13 -9
- data/spec/spec_helper.rb +18 -38
- data/tasks/bench.rake +3 -3
- data/tasks/compile.rake +13 -14
- data/tasks/rspec.rake +6 -11
- metadata +42 -28
- data/features/pretty_printer.feature +0 -14
- data/spec/gherkin/csharp_lexer_spec.rb +0 -20
@@ -0,0 +1,82 @@
|
|
1
|
+
require 'json'
|
2
|
+
require 'json/pure' # Needed to make JSON.generate work.
|
3
|
+
require 'gherkin/rubify'
|
4
|
+
|
5
|
+
module Gherkin
|
6
|
+
module Formatter
|
7
|
+
class JSONFormatter
|
8
|
+
include Rubify
|
9
|
+
|
10
|
+
def initialize(io)
|
11
|
+
@io = io
|
12
|
+
end
|
13
|
+
|
14
|
+
def feature(comments, tags, keyword, name, description, uri)
|
15
|
+
@json_hash = {
|
16
|
+
'comments' => comments.to_a,
|
17
|
+
'tags' => tags.to_a,
|
18
|
+
'keyword' => keyword,
|
19
|
+
'name' => name,
|
20
|
+
'description' => description,
|
21
|
+
'uri' => uri
|
22
|
+
}
|
23
|
+
end
|
24
|
+
|
25
|
+
def scenario(comments, tags, keyword, name, description, line)
|
26
|
+
add_step_container(comments, tags, keyword, name, description, line)
|
27
|
+
end
|
28
|
+
|
29
|
+
def scenario_outline(comments, tags, keyword, name, description, line)
|
30
|
+
add_step_container(comments, tags, keyword, name, description, line)
|
31
|
+
end
|
32
|
+
|
33
|
+
def examples(comments, tags, keyword, name, description, line, table)
|
34
|
+
@table_container = add_element(comments, tags, keyword, name, description, line)
|
35
|
+
@table_container['examples_table'] = to_hash_array(table)
|
36
|
+
end
|
37
|
+
|
38
|
+
def step(comments, keyword, name, line, multiline_arg, status, exception, arguments, stepdef_location)
|
39
|
+
multiline_arg = rubify(multiline_arg)
|
40
|
+
multiline_arg = to_hash_array(multiline_arg) if Array === multiline_arg
|
41
|
+
@table_container = {'comments' => comments.to_a, 'keyword' => keyword, 'name' => name, 'line' => line, 'multiline_arg' => multiline_arg}
|
42
|
+
last_element['steps'] ||= []
|
43
|
+
last_element['steps'] << @table_container
|
44
|
+
end
|
45
|
+
|
46
|
+
def eof
|
47
|
+
@io.write(@json_hash.to_json)
|
48
|
+
end
|
49
|
+
|
50
|
+
private
|
51
|
+
|
52
|
+
def add_element(comments, tags, keyword, name, description, line)
|
53
|
+
element = {
|
54
|
+
'comments' => comments.to_a,
|
55
|
+
'tags' => tags.to_a,
|
56
|
+
'keyword' => keyword,
|
57
|
+
'name' => name,
|
58
|
+
'description' => description,
|
59
|
+
'line' => line
|
60
|
+
}
|
61
|
+
@json_hash['elements'] ||= []
|
62
|
+
@json_hash['elements'] << element
|
63
|
+
element
|
64
|
+
end
|
65
|
+
|
66
|
+
def add_step_container(comments, tags, keyword, name, description, line)
|
67
|
+
add_element(comments, tags, keyword, name, description, line)
|
68
|
+
last_element['steps'] = []
|
69
|
+
end
|
70
|
+
|
71
|
+
def last_element
|
72
|
+
@json_hash['elements'][-1]
|
73
|
+
end
|
74
|
+
|
75
|
+
def to_hash_array(rows)
|
76
|
+
rows.map do |row|
|
77
|
+
{"cells" => row.cells.to_a, "comments" => row.comments.to_a, "line" => row.line}
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
@@ -13,66 +13,66 @@ module Gherkin
|
|
13
13
|
include Colors
|
14
14
|
include Escaping
|
15
15
|
|
16
|
-
def initialize(io, monochrome
|
16
|
+
def initialize(io, monochrome)
|
17
17
|
@io = io
|
18
18
|
@monochrome = monochrome
|
19
19
|
@format = MonochromeFormat.new #@monochrome ? MonochromeFormat.new : AnsiColorFormat.new
|
20
|
-
@tags = nil
|
21
|
-
@comments = nil
|
22
20
|
end
|
23
21
|
|
24
|
-
def
|
25
|
-
@
|
26
|
-
|
22
|
+
def feature(comments, tags, keyword, name, description, uri)
|
23
|
+
@uri = uri
|
24
|
+
print_comments(comments, '')
|
25
|
+
print_tags(tags, '')
|
26
|
+
@io.puts "#{keyword}: #{name}"
|
27
|
+
@io.puts indent(description, ' ') unless description == ""
|
27
28
|
end
|
28
29
|
|
29
|
-
def
|
30
|
-
@
|
31
|
-
|
30
|
+
def background(comments, keyword, name, description, line)
|
31
|
+
@io.puts
|
32
|
+
print_comments(comments, ' ')
|
33
|
+
@io.puts " #{keyword}: #{name}#{indented_element_uri!(keyword, name, line)}"
|
34
|
+
@io.puts indent(description, ' ') unless description == ""
|
32
35
|
end
|
33
36
|
|
34
|
-
def
|
35
|
-
@io.puts
|
37
|
+
def scenario(comments, tags, keyword, name, description, line)
|
38
|
+
@io.puts
|
39
|
+
print_comments(comments, ' ')
|
40
|
+
print_tags(tags, ' ')
|
41
|
+
@io.puts " #{keyword}: #{name}#{indented_element_uri!(keyword, name, line)}"
|
42
|
+
@io.puts indent(description, ' ') unless description == ""
|
36
43
|
end
|
37
44
|
|
38
|
-
def
|
39
|
-
|
45
|
+
def scenario_outline(comments, tags, keyword, name, description, line)
|
46
|
+
scenario(comments, tags, keyword, name, description, line)
|
40
47
|
end
|
41
48
|
|
42
|
-
def
|
43
|
-
|
44
|
-
|
49
|
+
def examples(comments, tags, keyword, name, description, line, examples_table)
|
50
|
+
@io.puts
|
51
|
+
print_comments(comments, ' ')
|
52
|
+
print_tags(tags, ' ')
|
53
|
+
@io.puts " #{keyword}: #{name}"
|
54
|
+
@io.puts indent(description, ' ') unless description == ""
|
55
|
+
table(examples_table)
|
45
56
|
end
|
46
57
|
|
47
|
-
def
|
48
|
-
flush_table
|
49
|
-
@io.puts "\n#{grab_comments!(' ')}#{grab_tags!(' ')} #{keyword}: #{indent(name, ' ')}"
|
50
|
-
end
|
51
|
-
|
52
|
-
def examples(keyword, name, line)
|
53
|
-
flush_table
|
54
|
-
@io.puts "\n#{grab_comments!(' ')}#{grab_tags!(' ')} #{keyword}: #{indent(name, ' ')}"
|
55
|
-
end
|
56
|
-
|
57
|
-
def step(keyword, name, line, status=nil, exception=nil, arguments=nil, location=nil)
|
58
|
-
flush_table
|
58
|
+
def step(comments, keyword, name, line, multiline_arg, status, exception, arguments, stepdef_location)
|
59
59
|
status_param = "#{status}_param" if status
|
60
60
|
name = Gherkin::Formatter::Argument.format(name, @format, (arguments || []))
|
61
|
-
#{|arg| status_param ? self.__send__(status_param, arg, @monochrome) : arg} if arguments
|
62
61
|
|
63
|
-
step = "#{keyword}#{
|
62
|
+
step = "#{keyword}#{name}"
|
64
63
|
step = self.__send__(status, step, @monochrome) if status
|
65
64
|
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
65
|
+
print_comments(comments, ' ')
|
66
|
+
@io.puts(" #{step}#{indented_step_location!(stepdef_location)}")
|
67
|
+
case multiline_arg
|
68
|
+
when String
|
69
|
+
py_string(multiline_arg)
|
70
|
+
when Array
|
71
|
+
table(multiline_arg)
|
72
|
+
when NilClass
|
73
|
+
else
|
74
|
+
raise "Bad multiline_arg: #{multiline_arg.inspect}"
|
75
|
+
end
|
76
76
|
end
|
77
77
|
|
78
78
|
def syntax_error(state, event, legal_events, line)
|
@@ -80,7 +80,6 @@ module Gherkin
|
|
80
80
|
end
|
81
81
|
|
82
82
|
def eof
|
83
|
-
flush_table
|
84
83
|
end
|
85
84
|
|
86
85
|
# This method can be invoked before a #scenario, to ensure location arguments are aligned
|
@@ -90,79 +89,75 @@ module Gherkin
|
|
90
89
|
@step_index = -1
|
91
90
|
end
|
92
91
|
|
93
|
-
def
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
return if @rows.nil?
|
100
|
-
cell_lengths = @rows.map { |col| col.map { |cell| cell.unpack("U*").length }}
|
92
|
+
def table(rows)
|
93
|
+
cell_lengths = rows.map do |row|
|
94
|
+
row.cells.map do |cell|
|
95
|
+
escape_cell(cell).unpack("U*").length
|
96
|
+
end
|
97
|
+
end
|
101
98
|
max_lengths = cell_lengths.transpose.map { |col_lengths| col_lengths.max }.flatten
|
102
99
|
|
103
|
-
|
100
|
+
rows.each_with_index do |row, i|
|
104
101
|
j = -1
|
105
|
-
@io.puts ' | ' + row.zip(max_lengths).map { |cell, max_length|
|
102
|
+
@io.puts ' | ' + row.cells.zip(max_lengths).map { |cell, max_length|
|
106
103
|
j += 1
|
107
|
-
color(cell,
|
104
|
+
color(cell, nil, j) + ' ' * (max_length - cell_lengths[i][j])
|
108
105
|
}.join(' | ') + ' |'
|
109
|
-
exception(exception) if exception
|
110
106
|
end
|
111
|
-
@rows = nil
|
112
107
|
end
|
113
108
|
|
114
|
-
|
109
|
+
private
|
110
|
+
|
111
|
+
def py_string(string)
|
112
|
+
@io.puts " \"\"\"\n" + string.gsub(START, ' ').gsub(/"""/,'\"\"\"') + "\n \"\"\""
|
113
|
+
end
|
114
|
+
|
115
|
+
def exception(exception)
|
116
|
+
exception_text = "#{exception.message} (#{exception.class})\n#{(exception.backtrace || []).join("\n")}".gsub(/^/, ' ')
|
117
|
+
@io.puts(failed(exception_text, @monochrome))
|
118
|
+
end
|
115
119
|
|
116
120
|
def color(cell, statuses, col)
|
117
121
|
if statuses
|
118
|
-
self.__send__(statuses[col], cell, @monochrome) + (@monochrome ? '' : reset)
|
122
|
+
self.__send__(statuses[col], escape_cell(cell), @monochrome) + (@monochrome ? '' : reset)
|
119
123
|
else
|
120
|
-
cell
|
124
|
+
escape_cell(cell)
|
121
125
|
end
|
122
126
|
end
|
123
127
|
|
124
128
|
if(RUBY_VERSION =~ /^1\.9/)
|
125
129
|
START = /#{"^".encode('UTF-8')}/
|
126
|
-
|
130
|
+
CRLF = Regexp.new("\r\n".encode('UTF-8'))
|
127
131
|
else
|
128
132
|
START = /^/
|
129
|
-
|
133
|
+
CRLF = /\r\n/n
|
130
134
|
end
|
131
135
|
|
132
136
|
def indent(string, indentation)
|
133
|
-
|
134
|
-
string.split(NL).map do |l|
|
135
|
-
s = "#{indent}#{l}"
|
136
|
-
indent = indentation
|
137
|
-
s
|
138
|
-
end.join("\n")
|
137
|
+
string.gsub(/^/, indentation)
|
139
138
|
end
|
140
139
|
|
141
|
-
def
|
142
|
-
|
143
|
-
@tags = nil
|
144
|
-
tags
|
140
|
+
def print_tags(tags, indent)
|
141
|
+
@io.write(tags.empty? ? '' : indent + tags.join(' ') + "\n")
|
145
142
|
end
|
146
143
|
|
147
|
-
def
|
148
|
-
|
149
|
-
@comments = nil
|
150
|
-
comments
|
144
|
+
def print_comments(comments, indent)
|
145
|
+
@io.write(comments.empty? ? '' : indent + comments.join("\n#{indent}") + "\n")
|
151
146
|
end
|
152
147
|
|
153
|
-
def
|
154
|
-
return
|
148
|
+
def indented_element_uri!(keyword, name, line)
|
149
|
+
return '' if @max_step_length.nil?
|
155
150
|
l = (keyword+name).unpack("U*").length
|
156
151
|
@max_step_length = [@max_step_length, l].max
|
157
152
|
indent = @max_step_length - l
|
158
|
-
' ' * indent + ' ' + comments("# #{
|
153
|
+
' ' * indent + ' ' + comments("# #{@uri}:#{line}", @monochrome)
|
159
154
|
end
|
160
155
|
|
161
156
|
def indented_step_location!(location)
|
162
|
-
return
|
157
|
+
return '' if location.nil?
|
163
158
|
indent = @max_step_length - @step_lengths[@step_index+=1]
|
164
159
|
' ' * indent + ' ' + comments("# #{location}", @monochrome)
|
165
160
|
end
|
166
161
|
end
|
167
162
|
end
|
168
|
-
end
|
163
|
+
end
|
data/lib/gherkin/i18n.rb
CHANGED
@@ -34,14 +34,14 @@ module Gherkin
|
|
34
34
|
unique_keywords = all.map do |i18n|
|
35
35
|
keywords.map do |keyword|
|
36
36
|
if keyword.to_s == 'step'
|
37
|
-
i18n.step_keywords
|
37
|
+
i18n.step_keywords.to_a
|
38
38
|
else
|
39
|
-
i18n.keywords(keyword)
|
39
|
+
i18n.keywords(keyword).to_a
|
40
40
|
end
|
41
41
|
end
|
42
42
|
end
|
43
43
|
|
44
|
-
unique_keywords.flatten.compact.sort.reverse.uniq.join('|').gsub(/\*/, '\*')
|
44
|
+
unique_keywords.flatten.compact.map{|kw| kw.to_s}.sort.reverse.uniq.join('|').gsub(/\*/, '\*')
|
45
45
|
end
|
46
46
|
|
47
47
|
def code_keywords
|
@@ -55,15 +55,17 @@ module Gherkin
|
|
55
55
|
def language_table
|
56
56
|
require 'stringio'
|
57
57
|
require 'gherkin/formatter/pretty_formatter'
|
58
|
+
require 'gherkin/parser/row'
|
58
59
|
io = defined?(JRUBY_VERSION) ? Java.java.io.StringWriter.new : StringIO.new
|
59
60
|
pf = Gherkin::Formatter::PrettyFormatter.new(io, true)
|
60
|
-
all.
|
61
|
-
|
61
|
+
table = all.map do |i18n|
|
62
|
+
Parser::Row.new([i18n.iso_code, i18n.keywords('name')[0], i18n.keywords('native')[0]], [], nil)
|
63
|
+
end
|
64
|
+
pf.table(table)
|
62
65
|
if defined?(JRUBY_VERSION)
|
63
66
|
io.getBuffer.toString
|
64
67
|
else
|
65
|
-
io.
|
66
|
-
io.read
|
68
|
+
io.string
|
67
69
|
end
|
68
70
|
end
|
69
71
|
|
@@ -136,37 +138,39 @@ module Gherkin
|
|
136
138
|
result
|
137
139
|
end
|
138
140
|
|
139
|
-
def keywords(
|
140
|
-
|
141
|
-
raise "No #{
|
142
|
-
@keywords[
|
141
|
+
def keywords(key)
|
142
|
+
key = key.to_s
|
143
|
+
raise "No #{key.inspect} in #{@keywords.inspect}" if @keywords[key].nil?
|
144
|
+
@keywords[key].split('|').map{|keyword| real_keyword(key, keyword)}
|
143
145
|
end
|
144
146
|
|
145
147
|
def keyword_table
|
146
148
|
require 'stringio'
|
147
149
|
require 'gherkin/formatter/pretty_formatter'
|
150
|
+
require 'gherkin/parser/row'
|
148
151
|
io = StringIO.new
|
149
152
|
pf = Gherkin::Formatter::PrettyFormatter.new(io, true)
|
150
153
|
|
151
|
-
KEYWORD_KEYS.
|
152
|
-
|
154
|
+
gherkin_keyword_table = KEYWORD_KEYS.map do |key|
|
155
|
+
Parser::Row.new([key, keywords(key).map{|keyword| %{"#{keyword}"}}.join(', ')], [], nil)
|
153
156
|
end
|
154
|
-
|
157
|
+
|
158
|
+
code_keyword_table = STEP_KEYWORD_KEYS.map do |key|
|
155
159
|
code_keywords = keywords(key).reject{|keyword| keyword == '* '}.map do |keyword|
|
156
160
|
%{"#{self.class.code_keyword_for(keyword)}"}
|
157
161
|
end.join(', ')
|
158
|
-
|
162
|
+
Parser::Row.new(["#{key} (code)", code_keywords], [], nil)
|
159
163
|
end
|
160
164
|
|
161
|
-
pf.
|
165
|
+
pf.table(gherkin_keyword_table + code_keyword_table)
|
162
166
|
io.rewind
|
163
167
|
io.read
|
164
168
|
end
|
165
169
|
|
166
170
|
private
|
167
171
|
|
168
|
-
def real_keyword(
|
169
|
-
if(STEP_KEYWORD_KEYS.index(
|
172
|
+
def real_keyword(key, keyword)
|
173
|
+
if(STEP_KEYWORD_KEYS.index(key))
|
170
174
|
(keyword + ' ').sub(/< $/, '')
|
171
175
|
else
|
172
176
|
keyword
|
data/lib/gherkin/i18n.yml
CHANGED
@@ -269,8 +269,8 @@
|
|
269
269
|
scenario: Forgatókönyv
|
270
270
|
scenario_outline: Forgatókönyv vázlat
|
271
271
|
examples: Példák
|
272
|
-
given: "*|
|
273
|
-
when: "*|Majd"
|
272
|
+
given: "*|Amennyiben|Adott"
|
273
|
+
when: "*|Majd|Ha|Amikor"
|
274
274
|
then: "*|Akkor"
|
275
275
|
and: "*|És"
|
276
276
|
but: "*|De"
|
@@ -451,9 +451,9 @@
|
|
451
451
|
scenario: Сценарий
|
452
452
|
scenario_outline: Структура сценария
|
453
453
|
examples: Значения
|
454
|
-
given: "
|
455
|
-
when: "
|
456
|
-
then: "
|
454
|
+
given: "*|Допустим|Дано|Пусть"
|
455
|
+
when: "*|Если|Когда"
|
456
|
+
then: "*|То|Тогда"
|
457
457
|
and: "*|И|К тому же"
|
458
458
|
but: "*|Но|А"
|
459
459
|
"sv":
|
@@ -529,10 +529,10 @@
|
|
529
529
|
scenario: Сценарій
|
530
530
|
scenario_outline: Структура сценарію
|
531
531
|
examples: Приклади
|
532
|
-
given: "*|Припустимо|Припустимо,
|
533
|
-
when: "
|
534
|
-
then: "
|
535
|
-
and: "
|
532
|
+
given: "*|Припустимо|Припустимо, що|Нехай|Дано"
|
533
|
+
when: "*|Якщо|Коли"
|
534
|
+
then: "*|То|Тоді"
|
535
|
+
and: "*|І|А також|Та"
|
536
536
|
but: "*|Але"
|
537
537
|
"uz":
|
538
538
|
name: Uzbek
|
data/lib/gherkin/i18n_lexer.rb
CHANGED