cucumber 0.3.11 → 0.3.90

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.
Files changed (164) hide show
  1. data/History.txt +101 -0
  2. data/Manifest.txt +14 -5
  3. data/config/hoe.rb +1 -2
  4. data/cucumber.yml +1 -0
  5. data/examples/i18n/ar/Rakefile +1 -1
  6. data/examples/i18n/ar/features/addition.feature +1 -0
  7. data/examples/i18n/bg/Rakefile +1 -1
  8. data/examples/i18n/bg/features/addition.feature +1 -0
  9. data/examples/i18n/bg/features/consecutive_calculations.feature +1 -0
  10. data/examples/i18n/bg/features/division.feature +1 -0
  11. data/examples/i18n/cat/Rakefile +1 -1
  12. data/examples/i18n/cat/features/suma.feature +1 -0
  13. data/examples/i18n/da/Rakefile +1 -1
  14. data/examples/i18n/da/features/summering.feature +1 -0
  15. data/examples/i18n/de/Rakefile +1 -1
  16. data/examples/i18n/de/features/addition.feature +1 -0
  17. data/examples/i18n/de/features/division.feature +1 -0
  18. data/examples/i18n/en-lol/features/stuffing.feature +1 -1
  19. data/examples/i18n/en/Rakefile +1 -1
  20. data/examples/i18n/en/features/addition.feature +1 -0
  21. data/examples/i18n/en/features/division.feature +1 -0
  22. data/examples/i18n/es/Rakefile +1 -1
  23. data/examples/i18n/es/features/adicion.feature +1 -0
  24. data/examples/i18n/et/Rakefile +1 -1
  25. data/examples/i18n/et/features/jagamine.feature +1 -0
  26. data/examples/i18n/et/features/liitmine.feature +1 -0
  27. data/examples/i18n/fi/Rakefile +1 -1
  28. data/examples/i18n/fi/features/jakolasku.feature +1 -0
  29. data/examples/i18n/fr/Rakefile +1 -1
  30. data/examples/i18n/fr/features/addition.feature +2 -1
  31. data/examples/i18n/he/Rakefile +1 -1
  32. data/examples/i18n/he/features/addition.feature +1 -0
  33. data/examples/i18n/he/features/division.feature +1 -0
  34. data/examples/i18n/hu/Rakefile +1 -1
  35. data/examples/i18n/hu/features/addition.feature +1 -0
  36. data/examples/i18n/hu/features/division.feature +1 -0
  37. data/examples/i18n/id/Rakefile +1 -1
  38. data/examples/i18n/id/features/addition.feature +1 -0
  39. data/examples/i18n/id/features/division.feature +1 -0
  40. data/examples/i18n/it/Rakefile +1 -1
  41. data/examples/i18n/it/features/somma.feature +1 -0
  42. data/examples/i18n/ja/Rakefile +1 -1
  43. data/examples/i18n/ja/features/addition.feature +1 -0
  44. data/examples/i18n/ja/features/division.feature +1 -0
  45. data/examples/i18n/ko/Rakefile +1 -1
  46. data/examples/i18n/ko/features/addition.feature +6 -5
  47. data/examples/i18n/ko/features/division.feature +1 -0
  48. data/examples/i18n/ko/features/step_definitons/calculator_steps.rb +1 -1
  49. data/examples/i18n/lt/Rakefile +1 -1
  50. data/examples/i18n/lt/features/addition.feature +1 -0
  51. data/examples/i18n/lt/features/division.feature +1 -0
  52. data/examples/i18n/lv/Rakefile +1 -1
  53. data/examples/i18n/lv/features/addition.feature +1 -0
  54. data/examples/i18n/lv/features/division.feature +1 -0
  55. data/examples/i18n/no/Rakefile +1 -1
  56. data/examples/i18n/no/features/step_definitons/kalkulator_steps.rb +1 -1
  57. data/examples/i18n/no/features/summering.feature +1 -0
  58. data/examples/i18n/pl/Rakefile +1 -1
  59. data/examples/i18n/pl/features/addition.feature +1 -0
  60. data/examples/i18n/pl/features/division.feature +1 -0
  61. data/examples/i18n/pt/Rakefile +1 -1
  62. data/examples/i18n/pt/features/adicao.feature +1 -0
  63. data/examples/i18n/ro/Rakefile +1 -1
  64. data/examples/i18n/ro/features/suma.feature +1 -0
  65. data/examples/i18n/ru/Rakefile +1 -1
  66. data/examples/i18n/ru/features/addition.feature +1 -0
  67. data/examples/i18n/ru/features/consecutive_calculations.feature +1 -0
  68. data/examples/i18n/ru/features/division.feature +1 -0
  69. data/examples/i18n/se/Rakefile +1 -1
  70. data/examples/i18n/se/features/summering.feature +1 -0
  71. data/examples/i18n/sk/Rakefile +1 -1
  72. data/examples/i18n/sk/features/addition.feature +1 -0
  73. data/examples/i18n/sk/features/division.feature +1 -0
  74. data/examples/i18n/zh-CN/features/addition.feature +1 -0
  75. data/examples/i18n/zh-TW/features/addition.feature +1 -0
  76. data/examples/i18n/zh-TW/features/division.feature +1 -0
  77. data/examples/self_test/features/support/env.rb +2 -1
  78. data/examples/sinatra/features/step_definitions/add_steps.rb +1 -1
  79. data/examples/sinatra/features/support/env.rb +13 -5
  80. data/examples/steps_library/features/step_definitions/steps_lib1.rb +8 -0
  81. data/examples/steps_library/features/step_definitions/steps_lib2.rb +8 -0
  82. data/examples/tickets/features/step_definitons/tickets_steps.rb +15 -0
  83. data/examples/tickets/features/table_diffing.feature +13 -0
  84. data/features/after_block_exceptions.feature +4 -1
  85. data/features/after_step_block_exceptions.feature +4 -1
  86. data/features/background.feature +6 -0
  87. data/features/bug_371.feature +32 -0
  88. data/features/cucumber_cli.feature +11 -1
  89. data/features/cucumber_cli_diff_disabled.feature +9 -2
  90. data/features/drb_server_integration.feature +28 -5
  91. data/features/expand.feature +2 -1
  92. data/features/html_formatter/a.html +129 -1614
  93. data/features/junit_formatter.feature +4 -4
  94. data/features/language_from_header.feature +30 -0
  95. data/features/rake_task.feature +28 -0
  96. data/features/step_definitions/cucumber_steps.rb +2 -2
  97. data/features/steps_formatter.feature +25 -0
  98. data/features/support/env.rb +13 -5
  99. data/features/table_diffing.feature +45 -0
  100. data/features/unicode_table.feature +35 -0
  101. data/features/work_in_progress.feature +3 -0
  102. data/gem_tasks/sass.rake +4 -0
  103. data/lib/cucumber.rb +0 -57
  104. data/lib/cucumber/ast/comment.rb +1 -1
  105. data/lib/cucumber/ast/feature.rb +2 -2
  106. data/lib/cucumber/ast/feature_element.rb +4 -0
  107. data/lib/cucumber/ast/outline_table.rb +2 -1
  108. data/lib/cucumber/ast/py_string.rb +0 -1
  109. data/lib/cucumber/ast/scenario.rb +5 -3
  110. data/lib/cucumber/ast/scenario_outline.rb +6 -1
  111. data/lib/cucumber/ast/step.rb +8 -1
  112. data/lib/cucumber/ast/step_invocation.rb +6 -1
  113. data/lib/cucumber/ast/table.rb +287 -49
  114. data/lib/cucumber/ast/visitor.rb +2 -1
  115. data/lib/cucumber/cli/configuration.rb +45 -28
  116. data/lib/cucumber/cli/drb_client.rb +8 -9
  117. data/lib/cucumber/cli/language_help_formatter.rb +9 -7
  118. data/lib/cucumber/cli/main.rb +8 -9
  119. data/lib/cucumber/feature_file.rb +53 -0
  120. data/lib/cucumber/filter.rb +50 -0
  121. data/lib/cucumber/formatter/console.rb +12 -0
  122. data/lib/cucumber/formatter/cucumber.css +106 -48
  123. data/lib/cucumber/formatter/cucumber.sass +121 -31
  124. data/lib/cucumber/formatter/html.rb +6 -5
  125. data/lib/cucumber/formatter/junit.rb +3 -6
  126. data/lib/cucumber/formatter/pretty.rb +22 -9
  127. data/lib/cucumber/formatter/profile.rb +1 -1
  128. data/lib/cucumber/formatter/progress.rb +1 -1
  129. data/lib/cucumber/formatter/steps.rb +49 -0
  130. data/lib/cucumber/languages.yml +3 -3
  131. data/lib/cucumber/parser.rb +1 -33
  132. data/lib/cucumber/parser/feature.rb +39 -16
  133. data/lib/cucumber/parser/feature.tt +1 -3
  134. data/lib/cucumber/parser/i18n.tt +30 -23
  135. data/lib/cucumber/parser/i18n/language.rb +83 -0
  136. data/lib/cucumber/parser/treetop_ext.rb +12 -83
  137. data/lib/cucumber/platform.rb +6 -0
  138. data/lib/cucumber/rake/task.rb +6 -0
  139. data/lib/cucumber/step_definition.rb +6 -0
  140. data/lib/cucumber/step_match.rb +1 -1
  141. data/lib/cucumber/step_mother.rb +3 -3
  142. data/lib/cucumber/version.rb +1 -1
  143. data/lib/cucumber/webrat/table_locator.rb +66 -0
  144. data/rails_generators/cucumber/templates/cucumber.rake +4 -0
  145. data/rails_generators/cucumber/templates/env.rb +1 -0
  146. data/rails_generators/cucumber/templates/spork_env.rb +1 -1
  147. data/rails_generators/cucumber/templates/webrat_steps.rb +17 -0
  148. data/rails_generators/feature/templates/feature.erb +1 -1
  149. data/rails_generators/feature/templates/steps.erb +2 -8
  150. data/spec/cucumber/ast/step_collection_spec.rb +5 -4
  151. data/spec/cucumber/ast/table_spec.rb +145 -0
  152. data/spec/cucumber/cli/configuration_spec.rb +55 -9
  153. data/spec/cucumber/cli/drb_client_spec.rb +5 -4
  154. data/spec/cucumber/cli/main_spec.rb +9 -12
  155. data/spec/cucumber/formatter/progress_spec.rb +2 -2
  156. data/spec/cucumber/parser/feature_parser_spec.rb +11 -9
  157. data/spec/cucumber/parser/table_parser_spec.rb +1 -1
  158. data/spec/spec_helper.rb +2 -1
  159. metadata +21 -20
  160. data/spec/cucumber/formatter/html/cucumber.css +0 -37
  161. data/spec/cucumber/formatter/html/cucumber.js +0 -13
  162. data/spec/cucumber/formatter/html/index.html +0 -45
  163. data/spec/cucumber/formatter/html/jquery-1.3.min.js +0 -19
  164. data/spec/cucumber/formatter/html/jquery.uitableedit.js +0 -100
@@ -7,10 +7,8 @@ module Cucumber
7
7
  # Treetop will then generate the parser in-memory. When you're happy, just generate
8
8
  # the rb file with tt feature.tt
9
9
  grammar Feature
10
- include I18n
11
- include Table
12
10
 
13
- rule feature
11
+ rule feature_sub
14
12
  white
15
13
  comment
16
14
  white
@@ -1,35 +1,42 @@
1
1
  module Cucumber
2
2
  module Parser
3
- grammar I18n
3
+ module I18n
4
+ grammar <%= keywords('grammar_name', true) %>
5
+ include Feature
6
+ include Table
4
7
 
5
- rule background_keyword
6
- (<%= keywords('background') %>) ':'
7
- end
8
+ rule feature
9
+ feature_sub
10
+ end
8
11
 
9
- rule scenario_keyword
10
- (<%= keywords('scenario') %>) ':'
11
- end
12
+ rule background_keyword
13
+ (<%= keywords('background') %>) ':'
14
+ end
12
15
 
13
- rule scenario_outline_keyword
14
- (<%= keywords('scenario_outline') %>) ':'
15
- end
16
+ rule scenario_keyword
17
+ (<%= keywords('scenario') %>) ':'
18
+ end
16
19
 
17
- rule step_keyword
18
- (<%= keywords('given') %>) /
19
- (<%= keywords('when') %>) /
20
- (<%= keywords('then') %>) /
21
- (<%= keywords('and') %>) /
22
- (<%= keywords('but') %>)
23
- end
20
+ rule scenario_outline_keyword
21
+ (<%= keywords('scenario_outline') %>) ':'
22
+ end
24
23
 
25
- rule keyword_space
26
- <%= keywords('space_after_keyword', true) ? 'space+' : 'space*' %>
27
- end
24
+ rule step_keyword
25
+ (<%= keywords('given') %>) /
26
+ (<%= keywords('when') %>) /
27
+ (<%= keywords('then') %>) /
28
+ (<%= keywords('and') %>) /
29
+ (<%= keywords('but') %>)
30
+ end
28
31
 
29
- rule examples_keyword
30
- (<%= keywords('examples') %>) ':'?
31
- end
32
+ rule keyword_space
33
+ <%= keywords('space_after_keyword', true) ? 'space+' : 'space*' %>
34
+ end
32
35
 
36
+ rule examples_keyword
37
+ (<%= keywords('examples') %>) ':'?
38
+ end
39
+ end
33
40
  end
34
41
  end
35
42
  end
@@ -0,0 +1,83 @@
1
+ module Cucumber
2
+ module Parser
3
+ module I18n
4
+ class Language
5
+ KEYWORD_KEYS = %w{name native encoding feature background scenario scenario_outline examples given when then but}
6
+
7
+ class << self
8
+ LANGUAGES = Hash.new{|h,k| h[k] = Language.new(k)}
9
+
10
+ def [](key)
11
+ LANGUAGES[key]
12
+ end
13
+
14
+ def alias_step_definitions(keywords) #:nodoc:
15
+ all_keywords = %w{given when then and but}.map{|keyword| keywords[keyword].split('|')}.flatten
16
+ alias_steps(all_keywords)
17
+ end
18
+
19
+ # Sets up additional method aliases for Given, When and Then.
20
+ # This does *not* affect how feature files are parsed. If you
21
+ # want to create aliases in the parser, you have to do this in
22
+ # languages.yml. For example:
23
+ #
24
+ # and: And|With
25
+ def alias_steps(keywords)
26
+ keywords.each do |adverb|
27
+ StepMother.alias_adverb(adverb)
28
+ World.alias_adverb(adverb)
29
+ end
30
+ end
31
+ end
32
+
33
+ alias_step_definitions(Cucumber::LANGUAGES['en'])
34
+
35
+ def initialize(lang)
36
+ @keywords = Cucumber::LANGUAGES[lang]
37
+ raise "Language not supported: #{lang.inspect}" if @keywords.nil?
38
+ @keywords['grammar_name'] = @keywords['name'].gsub(/\s/, '')
39
+ end
40
+
41
+ def parser
42
+ return @parser if @parser
43
+ i18n_tt = File.expand_path(File.dirname(__FILE__) + '/../i18n.tt')
44
+ template = File.open(i18n_tt, Cucumber.file_mode('r')).read
45
+ erb = ERB.new(template)
46
+ grammar = erb.result(binding)
47
+ Treetop.load_from_string(grammar)
48
+ self.class.alias_step_definitions(@keywords)
49
+ @parser = Parser::I18n.const_get("#{@keywords['grammar_name']}Parser").new
50
+ end
51
+
52
+ def parse(source, path, filter)
53
+ feature = parser.parse_or_fail(source, path, filter)
54
+ feature.language = self if feature
55
+ feature
56
+ end
57
+
58
+ def keywords(key, raw=false)
59
+ return @keywords[key] if raw
60
+ return nil unless @keywords[key]
61
+ values = @keywords[key].split('|')
62
+ values.map{|value| "'#{value}'"}.join(" / ")
63
+ end
64
+
65
+ def incomplete?
66
+ KEYWORD_KEYS.detect{|key| @keywords[key].nil?}
67
+ end
68
+
69
+ def scenario_keyword
70
+ @keywords['scenario'].split('|')[0] + ':'
71
+ end
72
+
73
+ def but_keywords
74
+ @keywords['but'].split('|')
75
+ end
76
+
77
+ def and_keywords
78
+ @keywords['and'].split('|')
79
+ end
80
+ end
81
+ end
82
+ end
83
+ end
@@ -12,80 +12,19 @@ end
12
12
 
13
13
  module Cucumber
14
14
  module Parser
15
- class Filter
16
- def initialize(lines, options)
17
- @lines = lines
18
- @include_tags = options[:include_tags] || []
19
- @exclude_tags = options[:exclude_tags] || []
20
- @name_regexps = options[:name_regexps] || []
21
- end
22
-
23
- def accept?(syntax_node)
24
- at_line?(syntax_node) &&
25
- matches_tags?(syntax_node) &&
26
- matches_names?(syntax_node)
27
- end
28
-
29
- def accept_example?(syntax_node, outline)
30
- (at_line?(syntax_node) || outline_at_line?(outline)) &&
31
- (matches_names?(syntax_node) || outline_matches_names?(outline))
32
- end
33
-
34
- def at_line?(syntax_node)
35
- @lines.nil? || @lines.empty? || @lines.detect{|line| syntax_node.at_line?(line)}
36
- end
37
-
38
- def outline_at_line?(syntax_node)
39
- @lines.nil? || @lines.empty? || @lines.detect{|line| syntax_node.outline_at_line?(line)}
40
- end
41
-
42
- def matches_tags?(syntax_node)
43
- !excluded_by_tags?(syntax_node) &&
44
- included_by_tags?(syntax_node)
45
- end
46
-
47
- def included_by_tags?(syntax_node)
48
- @include_tags.empty? || syntax_node.has_tags?(@include_tags)
49
- end
50
-
51
- def excluded_by_tags?(syntax_node)
52
- @exclude_tags.any? && syntax_node.has_tags?(@exclude_tags)
53
- end
54
-
55
- def outline_matches_names?(syntax_node)
56
- @name_regexps.nil? || @name_regexps.empty? || @name_regexps.detect{|name_regexp| syntax_node.outline_matches_name?(name_regexp)}
57
- end
58
-
59
- def matches_names?(syntax_node)
60
- @name_regexps.nil? || @name_regexps.empty? || @name_regexps.detect{|name_regexp| syntax_node.matches_name?(name_regexp)}
15
+ class SyntaxError < StandardError
16
+ def initialize(parser, file, line_offset)
17
+ tf = parser.terminal_failures
18
+ expected = tf.size == 1 ? tf[0].expected_string.inspect : "one of #{tf.map{|f| f.expected_string.inspect}.uniq*', '}"
19
+ line = parser.failure_line + line_offset
20
+ message = "#{file}:#{line}:#{parser.failure_column}: Parse error, expected #{expected}."
21
+ super(message)
61
22
  end
62
23
  end
63
-
64
- module TreetopExt
65
- FILE_COLON_LINE_PATTERN = /^([\w\W]*?):([\d:]+)$/
66
-
67
- # Parses a file and returns a Cucumber::Ast
68
- def parse_file(file, options)
69
- _, path, lines = *FILE_COLON_LINE_PATTERN.match(file)
70
- if path
71
- lines = lines.split(':').map { |line| line.to_i }
72
- else
73
- path = file
74
- end
75
- filter = Filter.new(lines, options)
76
-
77
- loader = lambda { |io| parse_or_fail(io.read, filter, path) }
78
- feature = if path =~ /^http/
79
- require 'open-uri'
80
- open(path, &loader)
81
- else
82
- File.open(path, Cucumber.file_mode('r'), &loader)
83
- end
84
- feature
85
- end
86
-
87
- def parse_or_fail(string, filter=nil, file=nil, line_offset=0)
88
- parse_tree = parse(string)
24
+
25
+ module TreetopExt
26
+ def parse_or_fail(source, file=nil, filter=nil, line_offset=0)
27
+ parse_tree = parse(source)
89
28
  if parse_tree.nil?
90
29
  raise Cucumber::Parser::SyntaxError.new(self, file, line_offset)
91
30
  else
@@ -95,16 +34,6 @@ module Cucumber
95
34
  end
96
35
  end
97
36
  end
98
-
99
- class SyntaxError < StandardError
100
- def initialize(parser, file, line_offset)
101
- tf = parser.terminal_failures
102
- expected = tf.size == 1 ? tf[0].expected_string.inspect : "one of #{tf.map{|f| f.expected_string.inspect}.uniq*', '}"
103
- line = parser.failure_line + line_offset
104
- message = "#{file}:#{line}:#{parser.failure_column}: Parse error, expected #{expected}."
105
- super(message)
106
- end
107
- end
108
37
  end
109
38
  end
110
39
 
@@ -115,7 +44,7 @@ module Treetop
115
44
  input.line_of(interval.first)
116
45
  end
117
46
  end
118
-
47
+
119
48
  class CompiledParser
120
49
  include Cucumber::Parser::TreetopExt
121
50
  end
@@ -4,9 +4,11 @@ require 'rbconfig'
4
4
  require 'yaml'
5
5
 
6
6
  module Cucumber
7
+ # TODO: Move these constants and the file to Language. Update wiki
7
8
  LANGUAGE_FILE = File.expand_path(File.dirname(__FILE__) + '/languages.yml')
8
9
  LANGUAGES = YAML.load_file(LANGUAGE_FILE)
9
10
  BINARY = File.expand_path(File.dirname(__FILE__) + '/../../bin/cucumber')
11
+ LIBDIR = File.expand_path(File.dirname(__FILE__) + '/../../lib')
10
12
  JRUBY = defined?(JRUBY_VERSION)
11
13
  IRONRUBY = Config::CONFIG['sitedir'] =~ /IronRuby/
12
14
  WINDOWS = Config::CONFIG['host_os'] =~ /mswin|mingw/
@@ -14,4 +16,8 @@ module Cucumber
14
16
  RAILS = defined?(Rails)
15
17
  RUBY_BINARY = File.join(Config::CONFIG['bindir'], Config::CONFIG['ruby_install_name'])
16
18
  RUBY_1_9 = RUBY_VERSION =~ /^1\.9/
19
+
20
+ def self.file_mode(m)
21
+ RUBY_1_9 ? "#{m}:UTF-8" : m
22
+ end
17
23
  end
@@ -194,6 +194,7 @@ module Cucumber
194
194
  result = []
195
195
  result += feature_list.to_a if feature_list
196
196
  result += FileList[feature_pattern].to_a if feature_pattern
197
+ result = make_command_line_safe(result)
197
198
  FileList[result]
198
199
  end
199
200
  end
@@ -208,6 +209,11 @@ module Cucumber
208
209
  FileList[result]
209
210
  end
210
211
  end
212
+
213
+ private
214
+ def make_command_line_safe(list)
215
+ list.map{|string| string.gsub(' ', '\ ')}
216
+ end
211
217
  end
212
218
 
213
219
  class FeatureTask < Task
@@ -86,6 +86,8 @@ module Cucumber
86
86
 
87
87
  include StepDefinitionMethods
88
88
 
89
+ attr_reader :regexp, :proc
90
+
89
91
  def initialize(pattern, &proc)
90
92
  raise MissingProc if proc.nil?
91
93
  if String === pattern
@@ -112,5 +114,9 @@ module Cucumber
112
114
  def file_colon_line
113
115
  @proc.file_colon_line
114
116
  end
117
+
118
+ def file
119
+ @file ||= file_colon_line.split(':')[0]
120
+ end
115
121
  end
116
122
  end
@@ -34,7 +34,7 @@ module Cucumber
34
34
  end
35
35
 
36
36
  class NoStepMatch
37
- attr_reader :step_definition
37
+ attr_reader :step_definition, :name
38
38
 
39
39
  def initialize(step, name)
40
40
  @step = step
@@ -254,12 +254,12 @@ module Cucumber
254
254
  @snippet_generator.snippet_text(step_keyword, step_name, multiline_arg_class)
255
255
  end
256
256
 
257
- def before_and_after(scenario, skip=false)
258
- before(scenario) unless skip
257
+ def before_and_after(scenario, skip_hooks=false)
258
+ before(scenario) unless skip_hooks
259
259
  @current_scenario = scenario
260
260
  yield scenario
261
261
  @current_scenario = nil
262
- after(scenario) unless skip
262
+ after(scenario) unless skip_hooks
263
263
  scenario_visited(scenario)
264
264
  end
265
265
 
@@ -2,7 +2,7 @@ module Cucumber #:nodoc:
2
2
  class VERSION #:nodoc:
3
3
  MAJOR = 0
4
4
  MINOR = 3
5
- TINY = 11
5
+ TINY = 90
6
6
  PATCH = nil # Set to nil for official release
7
7
 
8
8
  STRING = [MAJOR, MINOR, TINY, PATCH].compact.join('.')
@@ -0,0 +1,66 @@
1
+ module Webrat
2
+ class Table < Element
3
+ def self.xpath_search
4
+ ".//table"
5
+ end
6
+
7
+ # Converts this Table element into a 2-dimensional array of String where each cell
8
+ # represents the inner_html of the <td> and <th> elements. The number of columns is
9
+ # determined by the number of cells in the first row.
10
+ def to_a
11
+ col_count = nil
12
+ Webrat::XML.css_search(@element, 'tr').map do |row|
13
+ cols = Webrat::XML.css_search(row, 'th,td')
14
+ col_count ||= cols.length
15
+ cols[0...col_count].map do |col|
16
+ col.inner_html
17
+ end
18
+ end
19
+ end
20
+ end
21
+
22
+ module Locators
23
+ class TableLocator < Locator
24
+ def locate
25
+ Table.load(@session, table_element)
26
+ end
27
+
28
+ def table_element
29
+ table_elements.detect do |table_element|
30
+ matches_id?(table_element) ||
31
+ matches_css_selector?(table_element)
32
+ end
33
+ end
34
+
35
+ def matches_id?(table_element)
36
+ Webrat::XML.attribute(table_element, "id") == @value.to_s
37
+ end
38
+
39
+ def matches_css_selector?(table_element)
40
+ Webrat::XML.css_at(@dom, @value)
41
+ end
42
+
43
+ def table_elements
44
+ Webrat::XML.xpath_search(@dom, *Table.xpath_search)
45
+ end
46
+
47
+ def error_message
48
+ "Could not find table matching '#{@value}'"
49
+ end
50
+ end
51
+
52
+ # Returns a Table element located by +id_or_selector+, which can
53
+ # be a DOM id or a CSS selector.
54
+ def table_at(id_or_selector)
55
+ TableLocator.new(@session, dom, id_or_selector).locate!
56
+ end
57
+ end
58
+
59
+ module Methods
60
+ delegate_to_session :table_at
61
+ end
62
+
63
+ class Session
64
+ def_delegators :current_scope, :table_at
65
+ end
66
+ end
@@ -1,5 +1,7 @@
1
1
  $LOAD_PATH.unshift(RAILS_ROOT + '/vendor/plugins/cucumber/lib') if File.directory?(RAILS_ROOT + '/vendor/plugins/cucumber/lib')
2
2
 
3
+ unless ARGV.any? {|a| a =~ /^gems/}
4
+
3
5
  begin
4
6
  require 'cucumber/rake/task'
5
7
 
@@ -14,3 +16,5 @@ rescue LoadError
14
16
  abort 'Cucumber rake task is not available. Be sure to install cucumber as a gem or plugin'
15
17
  end
16
18
  end
19
+
20
+ end