aslakhellesoy-cucumber 0.3.0 → 0.3.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (49) hide show
  1. data/History.txt +18 -1
  2. data/Manifest.txt +15 -1
  3. data/config/hoe.rb +5 -4
  4. data/examples/i18n/hu/Rakefile +6 -0
  5. data/examples/i18n/hu/features/addition.feature +16 -0
  6. data/examples/i18n/hu/features/division.feature +9 -0
  7. data/examples/i18n/hu/features/step_definitons/calculator_steps.rb +25 -0
  8. data/examples/i18n/hu/lib/calculator.rb +14 -0
  9. data/examples/i18n/lv/Rakefile +6 -0
  10. data/examples/i18n/lv/features/addition.feature +16 -0
  11. data/examples/i18n/lv/features/division.feature +9 -0
  12. data/examples/i18n/lv/features/step_definitons/calculator_steps.rb +24 -0
  13. data/examples/i18n/lv/lib/calculator.rb +14 -0
  14. data/examples/self_test/features/multiline_name.feature +27 -0
  15. data/examples/tickets/Rakefile +3 -3
  16. data/examples/tickets/features/272/hooks.feature +26 -0
  17. data/examples/tickets/features/272/hooks_steps.rb +53 -0
  18. data/features/cucumber_cli.feature +32 -2
  19. data/features/multiline_names.feature +43 -0
  20. data/features/report_called_undefined_steps.feature +1 -1
  21. data/features/usage.feature +4 -0
  22. data/lib/cucumber/ast/background.rb +3 -6
  23. data/lib/cucumber/ast/feature_element.rb +18 -9
  24. data/lib/cucumber/ast/outline_table.rb +10 -0
  25. data/lib/cucumber/ast/scenario.rb +16 -1
  26. data/lib/cucumber/ast/scenario_outline.rb +1 -1
  27. data/lib/cucumber/ast/step.rb +4 -2
  28. data/lib/cucumber/ast/step_collection.rb +9 -1
  29. data/lib/cucumber/ast/table.rb +4 -0
  30. data/lib/cucumber/formatter/console.rb +1 -1
  31. data/lib/cucumber/formatter/html.rb +1 -1
  32. data/lib/cucumber/formatter/pretty.rb +7 -8
  33. data/lib/cucumber/languages.yml +30 -0
  34. data/lib/cucumber/parser/feature.rb +196 -10
  35. data/lib/cucumber/parser/feature.tt +26 -10
  36. data/lib/cucumber/rails/world.rb +6 -0
  37. data/lib/cucumber/step_mother.rb +2 -1
  38. data/lib/cucumber/version.rb +1 -1
  39. data/lib/cucumber/world.rb +2 -2
  40. data/rails_generators/cucumber/templates/paths.rb +11 -13
  41. data/rails_generators/feature/feature_generator.rb +1 -1
  42. data/spec/cucumber/ast/feature_element_spec.rb +35 -0
  43. data/spec/cucumber/ast/table_spec.rb +6 -2
  44. data/spec/cucumber/cli/configuration_spec.rb +0 -9
  45. data/spec/cucumber/cli/main_spec.rb +55 -153
  46. data/spec/cucumber/parser/feature_parser_spec.rb +79 -0
  47. data/spec/cucumber/step_mother_spec.rb +12 -5
  48. metadata +17 -13
  49. data/spec/cucumber/formatters/profile_formatter_spec.rb +0 -198
@@ -23,7 +23,7 @@ Feature: Cucumber command line
23
23
  2 scenarios
24
24
  2 undefined steps
25
25
 
26
- You can implement step definitions for missing steps with these snippets:
26
+ You can implement step definitions for undefined steps with these snippets:
27
27
 
28
28
  Given /^this does not exist$/ do
29
29
  pending
@@ -9,6 +9,10 @@ Feature: Cucumber command line
9
9
  """
10
10
  /^passing without a table$/ # features/step_definitions/sample_steps.rb:12
11
11
  Given passing without a table # features/background/failing_background_after_success.feature:4
12
+ Given passing without a table # features/multiline_name.feature:6
13
+ Given passing without a table # features/multiline_name.feature:11
14
+ Given <state> without a table # features/multiline_name.feature:16
15
+ Given <state> without a table # features/multiline_name.feature:22
12
16
  Given <state> without a table # features/outline_sample.feature:6
13
17
  Given <other_state> without a table # features/outline_sample.feature:7
14
18
  /^failing without a table$/ # features/step_definitions/sample_steps.rb:15
@@ -23,7 +23,7 @@ module Cucumber
23
23
 
24
24
  def accept(visitor)
25
25
  visitor.visit_comment(@comment)
26
- visitor.visit_background_name(@keyword, @name, file_colon_line(@line), source_indent(text_length))
26
+ visitor.visit_background_name(@keyword, @name, file_colon_line(@line), source_indent(first_line_length))
27
27
  visitor.step_mother.before(self)
28
28
  visitor.visit_steps(@step_invocations)
29
29
  @failed = @step_invocations.detect{|step_invocation| step_invocation.exception}
@@ -43,12 +43,9 @@ module Cucumber
43
43
  @failed
44
44
  end
45
45
 
46
- def text_length
47
- @keyword.jlength
48
- end
49
-
50
46
  def to_sexp
51
47
  sexp = [:background, @line, @keyword]
48
+ sexp += [@name] unless @name.empty?
52
49
  comment = @comment.to_sexp
53
50
  sexp += [comment] if comment
54
51
  steps = @steps.to_sexp
@@ -57,4 +54,4 @@ module Cucumber
57
54
  end
58
55
  end
59
56
  end
60
- end
57
+ end
@@ -1,3 +1,5 @@
1
+ require 'enumerator'
2
+
1
3
  module Cucumber
2
4
  module FeatureElement
3
5
  def attach_steps(steps)
@@ -9,7 +11,21 @@ module Cucumber
9
11
  end
10
12
 
11
13
  def text_length
12
- @keyword.jlength + @name.jlength
14
+ name_line_lengths.max
15
+ end
16
+
17
+ def first_line_length
18
+ name_line_lengths[0]
19
+ end
20
+
21
+ def name_line_lengths
22
+ if @name.empty?
23
+ [@keyword.jlength]
24
+ else
25
+ @name.split("\n").enum_for(:each_with_index).map do |line, line_number|
26
+ line_number == 0 ? @keyword.jlength + line.jlength : line.jlength + Ast::Step::INDENT - 1 # We -1 as names which are not keyword lines are missing a space between keyword and name
27
+ end
28
+ end
13
29
  end
14
30
 
15
31
  def matches_scenario_names?(scenario_names)
@@ -31,12 +47,5 @@ module Cucumber
31
47
  def accept_hook?(hook)
32
48
  @tags.accept_hook?(hook)
33
49
  end
34
-
35
- # TODO: Remove when we use StepCollection everywhere
36
- def previous_step(step)
37
- i = @steps.index(step) || -1
38
- @steps[i-1]
39
- end
40
-
41
50
  end
42
- end
51
+ end
@@ -70,6 +70,16 @@ module Cucumber
70
70
  @table.accept_hook?(hook)
71
71
  end
72
72
 
73
+ # Returns true if one or more steps failed
74
+ def failed?
75
+ @step_invocations.failed?
76
+ end
77
+
78
+ # Returns true if all steps passed
79
+ def passed?
80
+ @step_invocations.passed?
81
+ end
82
+
73
83
  private
74
84
 
75
85
  def header?
@@ -25,7 +25,7 @@ module Cucumber
25
25
  def accept(visitor)
26
26
  visitor.visit_comment(@comment)
27
27
  visitor.visit_tags(@tags)
28
- visitor.visit_scenario_name(@keyword, @name, file_colon_line(@line), source_indent(text_length))
28
+ visitor.visit_scenario_name(@keyword, @name, file_colon_line(@line), source_indent(first_line_length))
29
29
 
30
30
  skip = @background && @background.failed?
31
31
  skip_invoke! if skip
@@ -34,6 +34,21 @@ module Cucumber
34
34
  end
35
35
  end
36
36
 
37
+ # Returns true if one or more steps failed
38
+ def failed?
39
+ @steps.failed?
40
+ end
41
+
42
+ # Returns true if all steps passed
43
+ def passed?
44
+ @steps.passed?
45
+ end
46
+
47
+ # Returns the first exception (if any)
48
+ def exception
49
+ @steps.exception
50
+ end
51
+
37
52
  def skip_invoke!
38
53
  @steps.each{|step_invocation| step_invocation.skip_invoke!}
39
54
  @feature.next_feature_element(self) do |next_one|
@@ -33,7 +33,7 @@ module Cucumber
33
33
  def accept(visitor)
34
34
  visitor.visit_comment(@comment)
35
35
  visitor.visit_tags(@tags)
36
- visitor.visit_scenario_name(@keyword, @name, file_colon_line(@line), source_indent(text_length))
36
+ visitor.visit_scenario_name(@keyword, @name, file_colon_line(@line), source_indent(first_line_length))
37
37
  visitor.visit_steps(@steps)
38
38
 
39
39
  skip_invoke! if @background && @background.failed?
@@ -8,6 +8,8 @@ module Cucumber
8
8
  attr_writer :step_collection, :options
9
9
  attr_accessor :feature_element, :exception
10
10
 
11
+ INDENT = 2
12
+
11
13
  def initialize(line, keyword, name, multiline_arg=nil)
12
14
  @line, @keyword, @name, @multiline_arg = line, keyword, name, multiline_arg
13
15
  end
@@ -32,7 +34,7 @@ module Cucumber
32
34
 
33
35
  def accept(visitor)
34
36
  # The only time a Step is visited is when it is in a ScenarioOutline.
35
- # Otherwise it's always StepInvocation that gest visited instead.
37
+ # Otherwise it's always StepInvocation that gets visited instead.
36
38
  visit_step_result(visitor, first_match(visitor), @multiline_arg, :skipped, nil, nil)
37
39
  end
38
40
 
@@ -61,7 +63,7 @@ module Cucumber
61
63
  end
62
64
 
63
65
  def text_length
64
- @keyword.jlength + @name.jlength + 2 # Add 2 because steps get indented 2 more than scenarios
66
+ @keyword.jlength + @name.jlength + INDENT # Add indent as steps get indented more than scenarios
65
67
  end
66
68
 
67
69
  def backtrace_line
@@ -54,9 +54,17 @@ module Cucumber
54
54
  @exception ||= ((failed = @steps.detect {|step| step.exception}) && failed.exception)
55
55
  end
56
56
 
57
+ def failed?
58
+ @steps.detect{|step_invocation| step_invocation.status == :failed}
59
+ end
60
+
61
+ def passed?
62
+ @steps.detect{|step_invocation| step_invocation.status != :passed}.nil?
63
+ end
64
+
57
65
  def to_sexp
58
66
  @steps.map{|step| step.to_sexp}
59
67
  end
60
68
  end
61
69
  end
62
- end
70
+ end
@@ -197,6 +197,10 @@ module Cucumber
197
197
  end
198
198
  end
199
199
 
200
+ def headers
201
+ @raw.first
202
+ end
203
+
200
204
  def header_cell(col)
201
205
  cells_rows[0][col]
202
206
  end
@@ -79,7 +79,7 @@ module Cucumber
79
79
  snippet
80
80
  end.compact.uniq
81
81
 
82
- text = "\nYou can implement step definitions for missing steps with these snippets:\n\n"
82
+ text = "\nYou can implement step definitions for undefined steps with these snippets:\n\n"
83
83
  text += snippets.join("\n\n")
84
84
 
85
85
  @io.puts format_string(text, :undefined)
@@ -114,7 +114,7 @@ module Cucumber
114
114
  unless @skip_step
115
115
  step_name = step_match.format_args(lambda{|param| "<span>#{param}</span>"})
116
116
  @builder.div do |div|
117
- div << h("#{keyword} #{step_name}")
117
+ div << h("#{keyword} #{step_name}").gsub(/&lt;span&gt;/, '<span>').gsub(/&lt;\/span&gt;/, '</span>')
118
118
  end
119
119
  end
120
120
  end
@@ -95,7 +95,9 @@ module Cucumber
95
95
  end
96
96
 
97
97
  def visit_examples_name(keyword, name)
98
- @io.puts("\n #{keyword} #{name}")
98
+ names = name.empty? ? [name] : name.split("\n")
99
+ @io.puts("\n #{keyword} #{names[0]}")
100
+ names[1..-1].each {|s| @io.puts " #{s}" }
99
101
  @io.flush
100
102
  @indent = 4
101
103
  end
@@ -105,13 +107,15 @@ module Cucumber
105
107
  end
106
108
 
107
109
  def visit_feature_element_name(keyword, name, file_colon_line, source_indent)
108
- line = " #{keyword} #{name}"
110
+ names = name.empty? ? [name] : name.split("\n")
111
+ line = " #{keyword} #{names[0]}"
109
112
  @io.print(line)
110
113
  if @options[:source]
111
114
  line_comment = " # #{file_colon_line}".indent(source_indent)
112
115
  @io.print(format_string(line_comment, :comment))
113
116
  end
114
117
  @io.puts
118
+ names[1..-1].each {|s| @io.puts " #{s}"}
115
119
  @io.flush
116
120
  end
117
121
 
@@ -126,11 +130,6 @@ module Cucumber
126
130
  @exceptions << exception
127
131
  end
128
132
  return if status != :failed && @in_background ^ background
129
-
130
- # @step_matches ||= []
131
- # return if @step_matches.index(step_match)
132
- # @step_matches << step_match
133
-
134
133
  @status = status
135
134
  super
136
135
  end
@@ -169,7 +168,7 @@ module Cucumber
169
168
 
170
169
  def visit_table_cell_value(value, width, status)
171
170
  status ||= @status || :passed
172
- @io.print(' ' + format_string((value.to_s || '').ljust(width), status) + " #{@delim}")
171
+ @io.print(' ' + format_string((value.to_s || '').ljust(width), status) + ::Term::ANSIColor.reset(" #{@delim}"))
173
172
  @io.flush
174
173
  end
175
174
 
@@ -206,6 +206,21 @@
206
206
  and: Et
207
207
  but: Mais
208
208
  space_after_keyword: true
209
+ "hu":
210
+ name: Hungarian
211
+ native: magyar
212
+ encoding: UTF-8
213
+ feature: Jellemző
214
+ background: Háttér
215
+ scenario: Forgatókönyv
216
+ scenario_outline: Forgatókönyv vázlat
217
+ examples: Példák
218
+ given: Ha
219
+ when: Majd
220
+ then: Akkor
221
+ and: És
222
+ but: De
223
+ space_after_keyword: true
209
224
  "id":
210
225
  name: Indonesian
211
226
  native: Bahasa Indonesia
@@ -264,6 +279,21 @@
264
279
  and: Ir
265
280
  but: Bet
266
281
  space_after_keyword: true
282
+ "lv":
283
+ name: Latvian
284
+ native: latviešu
285
+ encoding: UTF-8
286
+ feature: Funkcionalitāte|Fīča
287
+ background: Konteksts|Situācija
288
+ scenario: Scenārijs
289
+ scenario_outline: Scenārijs pēc parauga
290
+ examples: Piemēri|Paraugs
291
+ given: Kad
292
+ when: Ja
293
+ then: Tad
294
+ and: Un
295
+ but: Bet
296
+ space_after_keyword: true
267
297
  "nl":
268
298
  name: Dutch
269
299
  native: Nederlands
@@ -486,7 +486,7 @@ module Cucumber
486
486
  comment.build,
487
487
  background_keyword.line,
488
488
  background_keyword.text_value,
489
- name.text_value,
489
+ name.build,
490
490
  steps.build
491
491
  )
492
492
  end
@@ -522,7 +522,7 @@ module Cucumber
522
522
  r4 = instantiate_node(SyntaxNode,input, i4...index, s4)
523
523
  s0 << r4
524
524
  if r4
525
- r7 = _nt_line_to_eol
525
+ r7 = _nt_lines_to_keyword
526
526
  if r7
527
527
  r6 = r7
528
528
  else
@@ -679,7 +679,7 @@ module Cucumber
679
679
  end
680
680
 
681
681
  def matches_name?(name_to_match)
682
- name.text_value == name_to_match
682
+ name.build == name_to_match
683
683
  end
684
684
 
685
685
  def build(background, filter)
@@ -689,7 +689,7 @@ module Cucumber
689
689
  tags.build,
690
690
  scenario_keyword.line,
691
691
  scenario_keyword.text_value,
692
- name.text_value,
692
+ name.build,
693
693
  steps.build
694
694
  )
695
695
  end
@@ -728,7 +728,7 @@ module Cucumber
728
728
  r5 = instantiate_node(SyntaxNode,input, i5...index, s5)
729
729
  s0 << r5
730
730
  if r5
731
- r7 = _nt_line_to_eol
731
+ r7 = _nt_lines_to_keyword
732
732
  s0 << r7
733
733
  if r7
734
734
  r8 = _nt_white
@@ -817,7 +817,7 @@ module Cucumber
817
817
  end
818
818
 
819
819
  def matches_name?(name_to_match)
820
- name.text_value == name_to_match
820
+ name.build == name_to_match
821
821
  end
822
822
 
823
823
  def build(background, filter)
@@ -827,7 +827,7 @@ module Cucumber
827
827
  tags.build,
828
828
  scenario_outline_keyword.line,
829
829
  scenario_outline_keyword.text_value,
830
- name.text_value,
830
+ name.build,
831
831
  steps.build,
832
832
  examples_sections.build(filter, self)
833
833
  )
@@ -867,7 +867,7 @@ module Cucumber
867
867
  r5 = instantiate_node(SyntaxNode,input, i5...index, s5)
868
868
  s0 << r5
869
869
  if r5
870
- r7 = _nt_line_to_eol
870
+ r7 = _nt_lines_to_keyword
871
871
  s0 << r7
872
872
  if r7
873
873
  r8 = _nt_white
@@ -1149,7 +1149,7 @@ module Cucumber
1149
1149
  end
1150
1150
 
1151
1151
  def build(filter, scenario_outline)
1152
- [examples_keyword.line, examples_keyword.text_value, name.text_value, table.raw(filter, scenario_outline)]
1152
+ [examples_keyword.line, examples_keyword.text_value, name.build, table.raw(filter, scenario_outline)]
1153
1153
  end
1154
1154
  end
1155
1155
 
@@ -1189,7 +1189,7 @@ module Cucumber
1189
1189
  r4 = instantiate_node(SyntaxNode,input, i4...index, s4)
1190
1190
  s0 << r4
1191
1191
  if r4
1192
- r7 = _nt_line_to_eol
1192
+ r7 = _nt_lines_to_keyword
1193
1193
  if r7
1194
1194
  r6 = r7
1195
1195
  else
@@ -1305,6 +1305,192 @@ module Cucumber
1305
1305
  return r0
1306
1306
  end
1307
1307
 
1308
+ module LineToKeyword0
1309
+ end
1310
+
1311
+ module LineToKeyword1
1312
+ def white
1313
+ elements[0]
1314
+ end
1315
+
1316
+ def text
1317
+ elements[1]
1318
+ end
1319
+ end
1320
+
1321
+ module LineToKeyword2
1322
+ def build
1323
+ text.text_value.strip
1324
+ end
1325
+ end
1326
+
1327
+ def _nt_line_to_keyword
1328
+ start_index = index
1329
+ if node_cache[:line_to_keyword].has_key?(index)
1330
+ cached = node_cache[:line_to_keyword][index]
1331
+ @index = cached.interval.end if cached
1332
+ return cached
1333
+ end
1334
+
1335
+ i0, s0 = index, []
1336
+ r1 = _nt_white
1337
+ s0 << r1
1338
+ if r1
1339
+ s2, i2 = [], index
1340
+ loop do
1341
+ i3, s3 = index, []
1342
+ i4 = index
1343
+ r5 = _nt_step_keyword
1344
+ if r5
1345
+ r4 = nil
1346
+ else
1347
+ self.index = i4
1348
+ r4 = instantiate_node(SyntaxNode,input, index...index)
1349
+ end
1350
+ s3 << r4
1351
+ if r4
1352
+ i6 = index
1353
+ r7 = _nt_scenario_keyword
1354
+ if r7
1355
+ r6 = nil
1356
+ else
1357
+ self.index = i6
1358
+ r6 = instantiate_node(SyntaxNode,input, index...index)
1359
+ end
1360
+ s3 << r6
1361
+ if r6
1362
+ i8 = index
1363
+ r9 = _nt_scenario_outline_keyword
1364
+ if r9
1365
+ r8 = nil
1366
+ else
1367
+ self.index = i8
1368
+ r8 = instantiate_node(SyntaxNode,input, index...index)
1369
+ end
1370
+ s3 << r8
1371
+ if r8
1372
+ i10 = index
1373
+ r11 = _nt_table
1374
+ if r11
1375
+ r10 = nil
1376
+ else
1377
+ self.index = i10
1378
+ r10 = instantiate_node(SyntaxNode,input, index...index)
1379
+ end
1380
+ s3 << r10
1381
+ if r10
1382
+ i12 = index
1383
+ r13 = _nt_tag
1384
+ if r13
1385
+ r12 = nil
1386
+ else
1387
+ self.index = i12
1388
+ r12 = instantiate_node(SyntaxNode,input, index...index)
1389
+ end
1390
+ s3 << r12
1391
+ if r12
1392
+ i14 = index
1393
+ r15 = _nt_comment_line
1394
+ if r15
1395
+ r14 = nil
1396
+ else
1397
+ self.index = i14
1398
+ r14 = instantiate_node(SyntaxNode,input, index...index)
1399
+ end
1400
+ s3 << r14
1401
+ if r14
1402
+ i16 = index
1403
+ r17 = _nt_eol
1404
+ if r17
1405
+ r16 = nil
1406
+ else
1407
+ self.index = i16
1408
+ r16 = instantiate_node(SyntaxNode,input, index...index)
1409
+ end
1410
+ s3 << r16
1411
+ if r16
1412
+ if index < input_length
1413
+ r18 = instantiate_node(SyntaxNode,input, index...(index + 1))
1414
+ @index += 1
1415
+ else
1416
+ terminal_parse_failure("any character")
1417
+ r18 = nil
1418
+ end
1419
+ s3 << r18
1420
+ end
1421
+ end
1422
+ end
1423
+ end
1424
+ end
1425
+ end
1426
+ end
1427
+ if s3.last
1428
+ r3 = instantiate_node(SyntaxNode,input, i3...index, s3)
1429
+ r3.extend(LineToKeyword0)
1430
+ else
1431
+ self.index = i3
1432
+ r3 = nil
1433
+ end
1434
+ if r3
1435
+ s2 << r3
1436
+ else
1437
+ break
1438
+ end
1439
+ end
1440
+ if s2.empty?
1441
+ self.index = i2
1442
+ r2 = nil
1443
+ else
1444
+ r2 = instantiate_node(SyntaxNode,input, i2...index, s2)
1445
+ end
1446
+ s0 << r2
1447
+ end
1448
+ if s0.last
1449
+ r0 = instantiate_node(SyntaxNode,input, i0...index, s0)
1450
+ r0.extend(LineToKeyword1)
1451
+ r0.extend(LineToKeyword2)
1452
+ else
1453
+ self.index = i0
1454
+ r0 = nil
1455
+ end
1456
+
1457
+ node_cache[:line_to_keyword][start_index] = r0
1458
+
1459
+ return r0
1460
+ end
1461
+
1462
+ module LinesToKeyword0
1463
+
1464
+ def build
1465
+ elements.map{|s| s.build}.join("\n")
1466
+ end
1467
+ end
1468
+
1469
+ def _nt_lines_to_keyword
1470
+ start_index = index
1471
+ if node_cache[:lines_to_keyword].has_key?(index)
1472
+ cached = node_cache[:lines_to_keyword][index]
1473
+ @index = cached.interval.end if cached
1474
+ return cached
1475
+ end
1476
+
1477
+ s0, i0 = [], index
1478
+ loop do
1479
+ r1 = _nt_line_to_keyword
1480
+ if r1
1481
+ s0 << r1
1482
+ else
1483
+ break
1484
+ end
1485
+ end
1486
+ r0 = instantiate_node(SyntaxNode,input, i0...index, s0)
1487
+ r0.extend(LinesToKeyword0)
1488
+
1489
+ node_cache[:lines_to_keyword][start_index] = r0
1490
+
1491
+ return r0
1492
+ end
1493
+
1308
1494
  module PyString0
1309
1495
  end
1310
1496