cucumber 0.3.94 → 0.3.95
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/History.txt +26 -1
- data/Manifest.txt +2 -0
- data/examples/cs/features/step_definitons/calculator_steps.rb +1 -1
- data/features/drb_server_integration.feature +5 -0
- data/features/support/env.rb +3 -4
- data/features/work_in_progress.feature +6 -0
- data/lib/cucumber/cli/configuration.rb +28 -28
- data/lib/cucumber/cli/main.rb +38 -15
- data/lib/cucumber/cli/options.rb +13 -12
- data/lib/cucumber/cli/profile_loader.rb +0 -2
- data/lib/cucumber/cli/rb_step_def_loader.rb +14 -0
- data/lib/cucumber/formatter/ansicolor.rb +0 -1
- data/lib/cucumber/formatter/console.rb +3 -1
- data/lib/cucumber/step_mother.rb +5 -1
- data/lib/cucumber/version.rb +1 -1
- data/lib/cucumber/webrat/element_locator.rb +87 -0
- data/lib/cucumber/webrat/table_locator.rb +1 -66
- data/lib/cucumber/world.rb +16 -0
- data/rails_generators/cucumber/templates/cucumber.rake +3 -1
- data/rails_generators/cucumber/templates/env.rb +1 -1
- data/rails_generators/cucumber/templates/spork_env.rb +1 -1
- data/rails_generators/cucumber/templates/webrat_steps.rb +4 -0
- data/spec/cucumber/cli/configuration_spec.rb +20 -80
- data/spec/cucumber/cli/main_spec.rb +1 -9
- data/spec/cucumber/cli/options_spec.rb +18 -4
- data/spec/cucumber/step_mother_spec.rb +11 -3
- metadata +4 -2
data/History.txt
CHANGED
@@ -1,3 +1,28 @@
|
|
1
|
+
== 0.3.95 2009-08-13
|
2
|
+
|
3
|
+
This release improves Webrat support for table-like HTML markup. Now you can easily turn the HTML
|
4
|
+
elements table, dl, ol and ul elements into a 2D array. This is particularly useful for comparing
|
5
|
+
data in your HTML with a Cucumber table using Cucumber::Ast::Table#diff!
|
6
|
+
|
7
|
+
This release also fixes several bugs related to --drb (Spork) and profiles (cucumber.yml)
|
8
|
+
|
9
|
+
=== Bug Fixes
|
10
|
+
* --guess will always prefer the longest regexp with no groups if they exist.
|
11
|
+
* Prevent delays if a NoMethodError is raise in a step definition. Define a light #inspect in World. (#374 Aslak Hellesøy)
|
12
|
+
* Restore 'features' as the default feature running path. (#412 Ben Mabey)
|
13
|
+
* --drb degrades gracefully when no drb server is running and no formatter is provided. (#410 Ben Mabey)
|
14
|
+
* --language picked up from profiles again. (#409 Ben Mabey)
|
15
|
+
* Resolved infinite loop problem when --drb was defined in a profile. (#408 Ben Mabey)
|
16
|
+
|
17
|
+
=== New Features
|
18
|
+
* The object returned by element_at (Webrat::Element) has a #to_table that works for table, dl, ol and ul. (Aslak Hellesøy)
|
19
|
+
* An explanation of why failures are ok is printed when --wip is used. (Aslak Hellesøy)
|
20
|
+
* Added cucumber alias for cucumber:ok in Rails Rake tasks. (Aslak Hellesøy)
|
21
|
+
|
22
|
+
=== Changed features
|
23
|
+
* element_at('table').to_table should be used instead of table_at('table').to_a. The old way is deprecated but still works. (Aslak Hellesøy)
|
24
|
+
* element_at (and the depracated table_at) no longer takes a DOM id, only CSS selectors. Change "my_id" to "#my_id". (Aslak Hellesøy)
|
25
|
+
|
1
26
|
== 0.3.94 2009-08-06
|
2
27
|
|
3
28
|
Kanban take II.
|
@@ -40,7 +65,7 @@ Highlights in this release: Improved profile handling (cucumber.yml) and a fix f
|
|
40
65
|
|
41
66
|
=== Bugfixes
|
42
67
|
* script/cucumber correctly loads the gem's binary if the plugin isn't installed.
|
43
|
-
* Cucumber hangs waiting for Ctrl+C if an Error is raised (#374 Aslak Hellesøy)
|
68
|
+
* Cucumber hangs waiting for Ctrl+C if an Error is raised. (#374 Aslak Hellesøy)
|
44
69
|
|
45
70
|
== 0.3.92 2009-07-29
|
46
71
|
|
data/Manifest.txt
CHANGED
@@ -321,6 +321,7 @@ lib/cucumber/cli/language_help_formatter.rb
|
|
321
321
|
lib/cucumber/cli/main.rb
|
322
322
|
lib/cucumber/cli/options.rb
|
323
323
|
lib/cucumber/cli/profile_loader.rb
|
324
|
+
lib/cucumber/cli/rb_step_def_loader.rb
|
324
325
|
lib/cucumber/core_ext/exception.rb
|
325
326
|
lib/cucumber/core_ext/instance_exec.rb
|
326
327
|
lib/cucumber/core_ext/proc.rb
|
@@ -363,6 +364,7 @@ lib/cucumber/step_definition.rb
|
|
363
364
|
lib/cucumber/step_match.rb
|
364
365
|
lib/cucumber/step_mother.rb
|
365
366
|
lib/cucumber/version.rb
|
367
|
+
lib/cucumber/webrat/element_locator.rb
|
366
368
|
lib/cucumber/webrat/table_locator.rb
|
367
369
|
lib/cucumber/world.rb
|
368
370
|
rails_generators/cucumber/USAGE
|
@@ -1,5 +1,5 @@
|
|
1
1
|
require 'spec/expectations'
|
2
|
-
$:.unshift(File.dirname(__FILE__) + '/../../
|
2
|
+
$:.unshift(File.dirname(__FILE__) + '/../../') # This line is not needed in your own project
|
3
3
|
require 'Calculator' # Calculator.dll
|
4
4
|
|
5
5
|
Before do
|
@@ -93,6 +93,11 @@ Feature: DRb Server Integration
|
|
93
93
|
I'm loading all the heavy stuff...
|
94
94
|
I'm loading the stuff just for this run...
|
95
95
|
"""
|
96
|
+
And the output should contain
|
97
|
+
"""
|
98
|
+
1 step (1 passed)
|
99
|
+
"""
|
100
|
+
|
96
101
|
|
97
102
|
Scenario: Feature Run with --drb flag *defined in a profile* with no DRb server running
|
98
103
|
|
data/features/support/env.rb
CHANGED
@@ -4,9 +4,9 @@ require 'spec/expectations'
|
|
4
4
|
require 'fileutils'
|
5
5
|
require 'forwardable'
|
6
6
|
begin
|
7
|
-
|
7
|
+
require 'spork'
|
8
8
|
rescue Gem::LoadError => ex
|
9
|
-
|
9
|
+
gem 'spork', '>= 0.5.7' # Ensure correct spork version number to avoid false-negatives.
|
10
10
|
end
|
11
11
|
|
12
12
|
class CucumberWorld
|
@@ -92,8 +92,7 @@ class CucumberWorld
|
|
92
92
|
else
|
93
93
|
# STDOUT.close
|
94
94
|
# STDERR.close
|
95
|
-
|
96
|
-
cmd = "#{Cucumber::RUBY_BINARY} -I #{Cucumber::LIBDIR} #{spork} cuc"
|
95
|
+
cmd = "#{Cucumber::RUBY_BINARY} -I #{Cucumber::LIBDIR} #{Spork::BINARY} cuc"
|
97
96
|
exec cmd
|
98
97
|
end
|
99
98
|
end
|
@@ -70,6 +70,8 @@ Feature: Cucumber --work-in-progress switch
|
|
70
70
|
1 scenario (1 failed)
|
71
71
|
1 step (1 failed)
|
72
72
|
|
73
|
+
The --wip switch was used, so the failures were expected. All is good.
|
74
|
+
|
73
75
|
"""
|
74
76
|
|
75
77
|
Scenario: Pass with Undefined Scenarios
|
@@ -85,6 +87,8 @@ Feature: Cucumber --work-in-progress switch
|
|
85
87
|
1 scenario (1 undefined)
|
86
88
|
1 step (1 undefined)
|
87
89
|
|
90
|
+
The --wip switch was used, so the failures were expected. All is good.
|
91
|
+
|
88
92
|
"""
|
89
93
|
|
90
94
|
@mri186
|
@@ -104,6 +108,8 @@ Feature: Cucumber --work-in-progress switch
|
|
104
108
|
1 scenario (1 pending)
|
105
109
|
1 step (1 pending)
|
106
110
|
|
111
|
+
The --wip switch was used, so the failures were expected. All is good.
|
112
|
+
|
107
113
|
"""
|
108
114
|
|
109
115
|
Scenario: Fail with Passing Scenarios
|
@@ -18,12 +18,12 @@ module Cucumber
|
|
18
18
|
def parse!(args)
|
19
19
|
@args = args
|
20
20
|
@options.parse!(args)
|
21
|
+
arrange_formats
|
21
22
|
raise("You can't use both --strict and --wip") if strict? && wip?
|
22
23
|
|
23
24
|
return @args.replace(@options.expanded_args_without_drb) if drb?
|
24
25
|
|
25
26
|
set_environment_variables
|
26
|
-
arrange_formats
|
27
27
|
end
|
28
28
|
|
29
29
|
def verbose?
|
@@ -50,10 +50,6 @@ module Cucumber
|
|
50
50
|
@options[:drb]
|
51
51
|
end
|
52
52
|
|
53
|
-
def paths
|
54
|
-
@options[:paths]
|
55
|
-
end
|
56
|
-
|
57
53
|
def build_formatter_broadcaster(step_mother)
|
58
54
|
return Formatter::Pretty.new(step_mother, nil, @options) if @options[:autoformat]
|
59
55
|
formatters = @options[:formats].map do |format_and_out|
|
@@ -91,23 +87,23 @@ module Cucumber
|
|
91
87
|
end
|
92
88
|
end
|
93
89
|
|
94
|
-
def
|
90
|
+
def step_defs_to_load
|
95
91
|
requires = @options[:require].empty? ? require_dirs : @options[:require]
|
96
92
|
files = requires.map do |path|
|
97
93
|
path = path.gsub(/\\/, '/') # In case we're on windows. Globs don't work with backslashes.
|
98
94
|
path = path.gsub(/\/$/, '') # Strip trailing slash.
|
99
|
-
File.directory?(path) ? Dir["#{path}
|
95
|
+
File.directory?(path) ? Dir["#{path}/**/*"] : path
|
100
96
|
end.flatten.uniq
|
101
|
-
sorted_files = files.sort { |a,b| (b =~ %r{/support/} || -1) <=>
|
102
|
-
env_files = sorted_files.select {|f| f =~ %r{/support/env
|
103
|
-
files = env_files + sorted_files.reject {|f| f =~ %r{/support/env
|
97
|
+
sorted_files = files.sort { |a,b| (b =~ %r{/support/} || -1) <=> (a =~ %r{/support/} || -1) }.reject{|f| f =~ /^http/}
|
98
|
+
env_files = sorted_files.select {|f| f =~ %r{/support/env\..*} }
|
99
|
+
files = env_files + sorted_files.reject {|f| f =~ %r{/support/env\..*} }
|
104
100
|
remove_excluded_files_from(files)
|
105
|
-
files.reject! {|f| f =~ %r{/support/env
|
101
|
+
files.reject! {|f| f =~ %r{/support/env\..*} } if @options[:dry_run]
|
106
102
|
files
|
107
103
|
end
|
108
104
|
|
109
105
|
def feature_files
|
110
|
-
potential_feature_files =
|
106
|
+
potential_feature_files = paths.map do |path|
|
111
107
|
path = path.gsub(/\\/, '/') # In case we're on windows. Globs don't work with backslashes.
|
112
108
|
path = path.chomp('/')
|
113
109
|
File.directory?(path) ? Dir["#{path}/**/*.feature"] : path
|
@@ -116,8 +112,28 @@ module Cucumber
|
|
116
112
|
potential_feature_files
|
117
113
|
end
|
118
114
|
|
115
|
+
def constantize(camel_cased_word)
|
116
|
+
begin
|
117
|
+
names = camel_cased_word.split('::')
|
118
|
+
names.shift if names.empty? || names.first.empty?
|
119
|
+
|
120
|
+
constant = Object
|
121
|
+
names.each do |name|
|
122
|
+
constant = constant.const_defined?(name) ? constant.const_get(name) : constant.const_missing(name)
|
123
|
+
end
|
124
|
+
constant
|
125
|
+
rescue NameError
|
126
|
+
require underscore(camel_cased_word)
|
127
|
+
retry
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
119
131
|
private
|
120
132
|
|
133
|
+
def paths
|
134
|
+
@options[:paths].empty? ? ['features'] : @options[:paths]
|
135
|
+
end
|
136
|
+
|
121
137
|
def set_environment_variables
|
122
138
|
@options[:env_vars].each do |var, value|
|
123
139
|
ENV[var] = value
|
@@ -144,22 +160,6 @@ module Cucumber
|
|
144
160
|
feature_dirs + Dir['vendor/{gems,plugins}/*/cucumber']
|
145
161
|
end
|
146
162
|
|
147
|
-
def constantize(camel_cased_word)
|
148
|
-
begin
|
149
|
-
names = camel_cased_word.split('::')
|
150
|
-
names.shift if names.empty? || names.first.empty?
|
151
|
-
|
152
|
-
constant = Object
|
153
|
-
names.each do |name|
|
154
|
-
constant = constant.const_defined?(name) ? constant.const_get(name) : constant.const_missing(name)
|
155
|
-
end
|
156
|
-
constant
|
157
|
-
rescue NameError
|
158
|
-
require underscore(camel_cased_word)
|
159
|
-
retry
|
160
|
-
end
|
161
|
-
end
|
162
|
-
|
163
163
|
# Snagged from active_support
|
164
164
|
def underscore(camel_cased_word)
|
165
165
|
camel_cased_word.to_s.gsub(/::/, '/').
|
data/lib/cucumber/cli/main.rb
CHANGED
@@ -51,7 +51,7 @@ module Cucumber
|
|
51
51
|
# features are loaded. If we swap the order, the requires
|
52
52
|
# will fail.
|
53
53
|
features = load_plain_text_features
|
54
|
-
|
54
|
+
load_step_defs
|
55
55
|
enable_diffing
|
56
56
|
|
57
57
|
visitor = configuration.build_formatter_broadcaster(step_mother)
|
@@ -108,33 +108,56 @@ module Cucumber
|
|
108
108
|
@configuration
|
109
109
|
end
|
110
110
|
|
111
|
-
def
|
112
|
-
|
111
|
+
def verbose_log(string)
|
112
|
+
@out_stream.puts(string) if configuration.verbose?
|
113
113
|
end
|
114
114
|
|
115
115
|
private
|
116
116
|
|
117
|
-
def
|
118
|
-
|
117
|
+
def load_step_defs
|
118
|
+
step_def_files = configuration.step_defs_to_load
|
119
|
+
verbose_log("Step Definitions Files:")
|
120
|
+
step_def_files.each do |step_def_file|
|
121
|
+
load_step_def(step_def_file)
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
def load_step_def(step_def_file)
|
126
|
+
if loader = step_def_loader_for(step_def_file)
|
127
|
+
verbose_log(" * #{step_def_file}")
|
128
|
+
loader.load_step_def_file(self, step_def_file)
|
129
|
+
end
|
119
130
|
end
|
120
131
|
|
121
|
-
def
|
122
|
-
|
123
|
-
|
124
|
-
|
132
|
+
def step_def_loader_for(step_def_file)
|
133
|
+
@sted_def_loaders ||= {}
|
134
|
+
if ext = File.extname(step_def_file)[1..-1]
|
135
|
+
loader = @sted_def_loaders[ext]
|
136
|
+
return nil if loader == :missing
|
137
|
+
return loader if loader
|
138
|
+
begin
|
139
|
+
loader_class = configuration.constantize("Cucumber::Cli::#{ext.capitalize}StepDefLoader")
|
140
|
+
return @sted_def_loaders[ext] = loader_class.new
|
141
|
+
rescue LoadError
|
142
|
+
@sted_def_loaders[ext] = :missing
|
143
|
+
nil
|
144
|
+
end
|
145
|
+
end
|
146
|
+
nil
|
147
|
+
end
|
148
|
+
|
149
|
+
def step_def_files
|
150
|
+
main.verbose_log("Ruby files required:")
|
151
|
+
main.verbose_log(requires.map{|lib| " * #{lib}"}.join("\n"))
|
125
152
|
requires.each do |lib|
|
126
153
|
begin
|
127
|
-
|
154
|
+
require lib
|
128
155
|
rescue LoadError => e
|
129
156
|
e.message << "\nFailed to load #{lib}"
|
130
157
|
raise e
|
131
158
|
end
|
132
159
|
end
|
133
|
-
verbose_log("\n")
|
134
|
-
end
|
135
|
-
|
136
|
-
def verbose_log(string)
|
137
|
-
@out_stream.puts(string) if configuration.verbose?
|
160
|
+
main.verbose_log("\n")
|
138
161
|
end
|
139
162
|
|
140
163
|
def enable_diffing
|
data/lib/cucumber/cli/options.rb
CHANGED
@@ -28,9 +28,10 @@ module Cucumber
|
|
28
28
|
]
|
29
29
|
DRB_FLAG = '--drb'
|
30
30
|
PROFILE_SHORT_FLAG = '-p'
|
31
|
+
NO_PROFILE_SHORT_FLAG = '-P'
|
31
32
|
PROFILE_LONG_FLAG = '--profile'
|
33
|
+
NO_PROFILE_LONG_FLAG = '--no-profile'
|
32
34
|
|
33
|
-
attr_reader :paths
|
34
35
|
|
35
36
|
def self.parse(args, out_stream, error_stream, options = {})
|
36
37
|
new(out_stream, error_stream, options).parse!(args)
|
@@ -56,7 +57,8 @@ module Cucumber
|
|
56
57
|
end
|
57
58
|
|
58
59
|
def expanded_args_without_drb
|
59
|
-
@expanded_args_without_drb
|
60
|
+
return @expanded_args_without_drb if @expanded_args_without_drb
|
61
|
+
@expanded_args_without_drb = (
|
60
62
|
previous_flag_was_profile = false
|
61
63
|
@expanded_args.reject do |arg|
|
62
64
|
if previous_flag_was_profile
|
@@ -70,6 +72,9 @@ module Cucumber
|
|
70
72
|
arg == DRB_FLAG || @overridden_paths.include?(arg)
|
71
73
|
end
|
72
74
|
)
|
75
|
+
|
76
|
+
@expanded_args_without_drb.push("--no-profile") unless @expanded_args_without_drb.include?(NO_PROFILE_LONG_FLAG) || @expanded_args_without_drb.include?(NO_PROFILE_SHORT_FLAG)
|
77
|
+
@expanded_args_without_drb
|
73
78
|
end
|
74
79
|
|
75
80
|
def parse!(args)
|
@@ -151,7 +156,7 @@ module Cucumber
|
|
151
156
|
"then only the ones from the command line are used.") do |v|
|
152
157
|
@profiles << v
|
153
158
|
end
|
154
|
-
opts.on(
|
159
|
+
opts.on(NO_PROFILE_SHORT_FLAG, NO_PROFILE_LONG_FLAG,
|
155
160
|
"Disables all profile laoding to avoid using the 'default' profile.") do |v|
|
156
161
|
@disable_profile_loading = true
|
157
162
|
end
|
@@ -230,7 +235,6 @@ module Cucumber
|
|
230
235
|
@options[:source] = true if @options[:source].nil?
|
231
236
|
end
|
232
237
|
|
233
|
-
|
234
238
|
extract_environment_variables
|
235
239
|
@options[:paths] = @args.dup #whatver is left over
|
236
240
|
|
@@ -240,8 +244,6 @@ module Cucumber
|
|
240
244
|
self
|
241
245
|
end
|
242
246
|
|
243
|
-
|
244
|
-
|
245
247
|
protected
|
246
248
|
|
247
249
|
attr_reader :options, :profiles, :expanded_args
|
@@ -354,19 +356,18 @@ module Cucumber
|
|
354
356
|
end
|
355
357
|
|
356
358
|
def print_profile_information
|
357
|
-
|
358
|
-
|
359
|
-
|
360
|
-
|
359
|
+
return if @skip_profile_information || @profiles.empty?
|
360
|
+
profiles_sentence = ''
|
361
|
+
profiles_sentence = @profiles.size == 1 ? @profiles.first :
|
362
|
+
"#{@profiles[0...-1].join(', ')} and #{@profiles.last}"
|
361
363
|
|
362
|
-
|
364
|
+
@out_stream.puts "Using the #{profiles_sentence} profile#{'s' if @profiles.size> 1}..."
|
363
365
|
end
|
364
366
|
|
365
367
|
def default_options
|
366
368
|
{
|
367
369
|
:strict => false,
|
368
370
|
:require => [],
|
369
|
-
:lang => nil,
|
370
371
|
:dry_run => false,
|
371
372
|
:formats => [],
|
372
373
|
:excludes => [],
|
@@ -109,8 +109,10 @@ module Cucumber
|
|
109
109
|
return unless options[:wip]
|
110
110
|
passed = step_mother.scenarios(:passed)
|
111
111
|
if passed.any?
|
112
|
-
@io.puts "\nThe --wip switch was used, so I didn't expect anything to pass. These scenarios passed:"
|
112
|
+
@io.puts format_string("\nThe --wip switch was used, so I didn't expect anything to pass. These scenarios passed:", :failed)
|
113
113
|
print_elements(passed, :passed, "scenarios")
|
114
|
+
else
|
115
|
+
@io.puts format_string("\nThe --wip switch was used, so the failures were expected. All is good.\n", :passed)
|
114
116
|
end
|
115
117
|
end
|
116
118
|
|
data/lib/cucumber/step_mother.rb
CHANGED
@@ -230,10 +230,14 @@ module Cucumber
|
|
230
230
|
end
|
231
231
|
|
232
232
|
def best_matches(step_name, step_matches)
|
233
|
+
no_groups = step_matches.select {|step_match| step_match.args.length == 0}
|
233
234
|
max_arg_length = step_matches.map {|step_match| step_match.args.length }.max
|
234
235
|
top_groups = step_matches.select {|step_match| step_match.args.length == max_arg_length }
|
235
236
|
|
236
|
-
if
|
237
|
+
if no_groups.any?
|
238
|
+
longest_regexp_length = no_groups.map {|step_match| step_match.text_length }.max
|
239
|
+
no_groups.select {|step_match| step_match.text_length == longest_regexp_length }
|
240
|
+
elsif top_groups.any?
|
237
241
|
shortest_capture_length = top_groups.map {|step_match| step_match.args.inject(0) {|sum, c| sum + c.length } }.min
|
238
242
|
top_groups.select {|step_match| step_match.args.inject(0) {|sum, c| sum + c.length } == shortest_capture_length }
|
239
243
|
else
|
data/lib/cucumber/version.rb
CHANGED
@@ -0,0 +1,87 @@
|
|
1
|
+
module Webrat
|
2
|
+
class Element
|
3
|
+
# Returns an Array of Array of String where each String is the
|
4
|
+
# a "cell" in the table-like structure represented by this Element.
|
5
|
+
#
|
6
|
+
# Supported elements are table, dl, ol and ul. The return value depends
|
7
|
+
# on the type of the element:
|
8
|
+
#
|
9
|
+
# * table : Each tr is a row. The innerHTML of each tr or th becomes cells. The number
|
10
|
+
# of columns is determined by the number of cells in the first row.
|
11
|
+
# * dl : Each dt creates a row with 2 cells. The innerHTML of the dt itself and the next dd become cells.
|
12
|
+
# * ul or ol : Each ul creates a row with one cell, the innerHTML of the ul.
|
13
|
+
#
|
14
|
+
def to_table
|
15
|
+
case element.name
|
16
|
+
when 'table'
|
17
|
+
table_from_table
|
18
|
+
when 'dl'
|
19
|
+
table_from_dl
|
20
|
+
when /ul|ol/
|
21
|
+
table_from_list
|
22
|
+
else
|
23
|
+
raise "#to_table not supported for #{element.name} elements"
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def table_from_table #:nodoc:
|
28
|
+
col_count = nil
|
29
|
+
Webrat::XML.css_search(element, 'tr').map do |row|
|
30
|
+
cols = Webrat::XML.css_search(row, 'th,td')
|
31
|
+
col_count ||= cols.length
|
32
|
+
cols[0...col_count].map do |col|
|
33
|
+
col.inner_html
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def table_from_dl #:nodoc:
|
39
|
+
Webrat::XML.css_search(@element, 'dt').map do |dt|
|
40
|
+
next_node = dt.next_sibling
|
41
|
+
while next_node.name != 'dd'
|
42
|
+
next_node = next_node.next_sibling
|
43
|
+
end
|
44
|
+
[dt.inner_html, next_node.inner_html]
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def table_from_list #:nodoc:
|
49
|
+
Webrat::XML.css_search(@element, 'li').map do |li|
|
50
|
+
[li.inner_html]
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
alias to_a to_table # Backwards compatibility with Cucumber
|
55
|
+
end
|
56
|
+
|
57
|
+
module Locators
|
58
|
+
class ElementLocator < Locator
|
59
|
+
def locate
|
60
|
+
Element.load(@session, table_element)
|
61
|
+
end
|
62
|
+
|
63
|
+
def table_element
|
64
|
+
Webrat::XML.css_search(@dom, @value)[0]
|
65
|
+
end
|
66
|
+
|
67
|
+
def error_message
|
68
|
+
"Could not find anything matching '#{@value}'"
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
# Returns a Webrat DOM element located by +css_selector+.
|
73
|
+
def element_at(css_selector)
|
74
|
+
ElementLocator.new(@session, dom, css_selector).locate!
|
75
|
+
end
|
76
|
+
|
77
|
+
alias table_at element_at # Backwards compatibility with Cucumber
|
78
|
+
end
|
79
|
+
|
80
|
+
module Methods
|
81
|
+
delegate_to_session :element_at, :table_at
|
82
|
+
end
|
83
|
+
|
84
|
+
class Session
|
85
|
+
def_delegators :current_scope, :element_at, :table_at
|
86
|
+
end
|
87
|
+
end
|
@@ -1,66 +1 @@
|
|
1
|
-
|
2
|
-
class Table < Element
|
3
|
-
def self.xpath_search
|
4
|
-
".//table"
|
5
|
-
end
|
6
|
-
|
7
|
-
# Converts this Table element into an Array of 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
|
+
require 'cucumber/webrat/element_locator'
|
data/lib/cucumber/world.rb
CHANGED
@@ -49,5 +49,21 @@ module Cucumber
|
|
49
49
|
raise Pending.new(message)
|
50
50
|
end
|
51
51
|
end
|
52
|
+
|
53
|
+
# The default implementation of Object#inspect recursively
|
54
|
+
# traverses all instance variables and invokes inspect.
|
55
|
+
# This can be time consuming if the object graph is large.
|
56
|
+
#
|
57
|
+
# This can cause unnecessary delays when certain exceptions
|
58
|
+
# occur. For example, MRI internally invokes #inspect on an
|
59
|
+
# object that raises a NoMethodError. (JRuby does not do this).
|
60
|
+
#
|
61
|
+
# A World object can have many references created by the user
|
62
|
+
# or frameworks (Rails), so to avoid long waiting times on
|
63
|
+
# such errors in World we define it to just return a simple String.
|
64
|
+
#
|
65
|
+
def inspect
|
66
|
+
sprintf("#<%s:0x%x>", self.class, self.object_id)
|
67
|
+
end
|
52
68
|
end
|
53
69
|
end
|
@@ -18,8 +18,10 @@ begin
|
|
18
18
|
desc 'Run all features'
|
19
19
|
task :all => [:ok, :wip]
|
20
20
|
end
|
21
|
+
desc 'Alias for cucumber:ok'
|
22
|
+
task :cucumber => 'cucumber:ok'
|
21
23
|
|
22
|
-
task :features =>
|
24
|
+
task :features => :cucumber do
|
23
25
|
STDERR.puts "*** The 'features' task is deprecated. See rake -T cucumber ***"
|
24
26
|
end
|
25
27
|
rescue LoadError
|
@@ -15,7 +15,7 @@ Cucumber::Rails.use_transactional_fixtures
|
|
15
15
|
Cucumber::Rails.bypass_rescue
|
16
16
|
|
17
17
|
require 'webrat'
|
18
|
-
require 'cucumber/webrat/
|
18
|
+
require 'cucumber/webrat/element_locator' # Lets you do table.diff!(element_at('#my_table_or_dl_or_ul_or_ol').to_table)
|
19
19
|
|
20
20
|
Webrat.configure do |config|
|
21
21
|
config.mode = :rails
|
@@ -7,7 +7,7 @@ Spork.prefork do
|
|
7
7
|
require File.expand_path(File.dirname(__FILE__) + '/../../config/environment')
|
8
8
|
|
9
9
|
require 'webrat'
|
10
|
-
require 'cucumber/webrat/
|
10
|
+
require 'cucumber/webrat/element_locator' # Lets you do table.diff!(element_at('#my_table_or_dl_or_ul_or_ol').to_table)
|
11
11
|
|
12
12
|
Webrat.configure do |config|
|
13
13
|
config.mode = :rails
|
@@ -38,7 +38,7 @@ module Cli
|
|
38
38
|
|
39
39
|
config.parse!(%w{--require /features})
|
40
40
|
|
41
|
-
config.
|
41
|
+
config.step_defs_to_load.should == [
|
42
42
|
"/features/support/bar.rb",
|
43
43
|
"/features/step_definitions/foo.rb"
|
44
44
|
]
|
@@ -49,7 +49,7 @@ module Cli
|
|
49
49
|
|
50
50
|
config.parse!(%w{--require /features})
|
51
51
|
|
52
|
-
config.
|
52
|
+
config.step_defs_to_load.should == [
|
53
53
|
"/features/support/env.rb",
|
54
54
|
"/features/support/a_file.rb"
|
55
55
|
]
|
@@ -60,7 +60,7 @@ module Cli
|
|
60
60
|
|
61
61
|
config.parse!(%w{--require /features --dry-run})
|
62
62
|
|
63
|
-
config.
|
63
|
+
config.step_defs_to_load.should == [
|
64
64
|
"/features/support/a_file.rb"
|
65
65
|
]
|
66
66
|
end
|
@@ -71,7 +71,7 @@ module Cli
|
|
71
71
|
|
72
72
|
config.parse!(%w{--require /features})
|
73
73
|
|
74
|
-
config.
|
74
|
+
config.step_defs_to_load.should == [
|
75
75
|
"/vendor/plugins/plugin_a/cucumber/foo.rb",
|
76
76
|
"/vendor/gems/gem_a/cucumber/bar.rb"
|
77
77
|
]
|
@@ -84,7 +84,7 @@ module Cli
|
|
84
84
|
|
85
85
|
config.parse!(%w{--require /features --exclude a_file.rb})
|
86
86
|
|
87
|
-
config.
|
87
|
+
config.step_defs_to_load.should == [
|
88
88
|
"/features/support/env.rb"
|
89
89
|
]
|
90
90
|
end
|
@@ -96,7 +96,7 @@ module Cli
|
|
96
96
|
|
97
97
|
config.parse!(%w{--require /features --exclude foo[df] --exclude blah})
|
98
98
|
|
99
|
-
config.
|
99
|
+
config.step_defs_to_load.should == [
|
100
100
|
"/features/support/bar.rb",
|
101
101
|
"/features/support/fooz.rb"
|
102
102
|
]
|
@@ -114,50 +114,6 @@ module Cli
|
|
114
114
|
end
|
115
115
|
end
|
116
116
|
|
117
|
-
context '--drb' do
|
118
|
-
it "removes the --drb flag from the args" do
|
119
|
-
args = %w{features --drb}
|
120
|
-
config.parse!(args)
|
121
|
-
args.should == %w{features}
|
122
|
-
end
|
123
|
-
|
124
|
-
it "keeps all other flags intact" do
|
125
|
-
args = %w{features --drb --format profile}
|
126
|
-
config.parse!(args)
|
127
|
-
args.should == %w{features --format profile}
|
128
|
-
end
|
129
|
-
|
130
|
-
end
|
131
|
-
|
132
|
-
context '--drb in a profile' do
|
133
|
-
it "removes the --drb flag from the args" do
|
134
|
-
given_cucumber_yml_defined_as({'server' => '--drb features'})
|
135
|
-
|
136
|
-
args = %w{--profile server}
|
137
|
-
config.parse!(args)
|
138
|
-
args.should == %w{features}
|
139
|
-
end
|
140
|
-
|
141
|
-
it "keeps all other flags intact from all profiles involved" do
|
142
|
-
given_cucumber_yml_defined_as({'server' => '--drb features --profile nested',
|
143
|
-
'nested' => '--verbose'})
|
144
|
-
|
145
|
-
args = %w{--profile server --format profile}
|
146
|
-
config.parse!(args)
|
147
|
-
args.should == %w{--format profile features --verbose}
|
148
|
-
end
|
149
|
-
|
150
|
-
end
|
151
|
-
|
152
|
-
context '--drb in the default profile and no arguments specified' do
|
153
|
-
it "expands the profile's arguments into the args excpet for --drb" do
|
154
|
-
given_cucumber_yml_defined_as({'default' => '--drb features --format pretty'})
|
155
|
-
args = []
|
156
|
-
config.parse!(args)
|
157
|
-
args.should == %w{features --format pretty}
|
158
|
-
end
|
159
|
-
end
|
160
|
-
|
161
117
|
it "uses the default profile when no profile is defined" do
|
162
118
|
given_cucumber_yml_defined_as({'default' => '--require some_file'})
|
163
119
|
|
@@ -197,36 +153,10 @@ END_OF_MESSAGE
|
|
197
153
|
end
|
198
154
|
|
199
155
|
it "allows profiles to be defined in arrays" do
|
200
|
-
given_cucumber_yml_defined_as({'foo' => [
|
156
|
+
given_cucumber_yml_defined_as({'foo' => ['-f','progress']})
|
201
157
|
|
202
158
|
config.parse!(%w{--profile foo})
|
203
|
-
config.
|
204
|
-
end
|
205
|
-
|
206
|
-
it "notifies the user that an individual profile is being used" do
|
207
|
-
given_cucumber_yml_defined_as({'foo' => [1,2,3]})
|
208
|
-
|
209
|
-
config.parse!(%w{--profile foo})
|
210
|
-
out.string.should =~ /Using the foo profile...\n/
|
211
|
-
end
|
212
|
-
|
213
|
-
it "notifies the user when multiple profiles are being used" do
|
214
|
-
given_cucumber_yml_defined_as({'foo' => [1,2,3], 'bar' => ['v'], 'dog' => ['v']})
|
215
|
-
|
216
|
-
config.parse!(%w{--profile foo --profile bar})
|
217
|
-
out.string.should =~ /Using the foo and bar profiles...\n/
|
218
|
-
|
219
|
-
reset_config
|
220
|
-
|
221
|
-
config.parse!(%w{--profile foo --profile bar --profile dog})
|
222
|
-
out.string.should =~ /Using the foo, bar and dog profiles...\n/
|
223
|
-
end
|
224
|
-
|
225
|
-
it "disregards paths in profiles when other paths are passed in (via cmd line)" do
|
226
|
-
given_cucumber_yml_defined_as({'foo' => %w[-v features]})
|
227
|
-
|
228
|
-
config.parse!(%w{--profile foo features/specific.feature --format pretty})
|
229
|
-
config.paths.should == ['features/specific.feature']
|
159
|
+
config.options[:formats].should == [['progress', out]]
|
230
160
|
end
|
231
161
|
|
232
162
|
it "disregards default STDOUT formatter defined in profile when another is passed in (via cmd line)" do
|
@@ -422,17 +352,27 @@ END_OF_MESSAGE
|
|
422
352
|
config.feature_files.should == ["cucumber.feature"]
|
423
353
|
end
|
424
354
|
|
355
|
+
it "defaults to the features directory when no feature file are provided" do
|
356
|
+
File.stub!(:directory?).and_return(true)
|
357
|
+
Dir.should_receive(:[]).with("features/**/*.feature").
|
358
|
+
any_number_of_times.and_return(["cucumber.feature"])
|
359
|
+
|
360
|
+
config.parse!(%w{})
|
361
|
+
|
362
|
+
config.feature_files.should == ["cucumber.feature"]
|
363
|
+
end
|
364
|
+
|
425
365
|
it "should allow specifying environment variables on the command line" do
|
426
366
|
config.parse!(["foo=bar"])
|
427
367
|
ENV["foo"].should == "bar"
|
428
|
-
config.feature_files.
|
368
|
+
config.feature_files.should_not include('foo=bar')
|
429
369
|
end
|
430
370
|
|
431
371
|
it "should allow specifying environment variables in profiles" do
|
432
372
|
given_cucumber_yml_defined_as({'selenium' => 'RAILS_ENV=selenium'})
|
433
373
|
config.parse!(["--profile", "selenium"])
|
434
374
|
ENV["RAILS_ENV"].should == "selenium"
|
435
|
-
config.feature_files.
|
375
|
+
config.feature_files.should_not include('RAILS_ENV=selenium')
|
436
376
|
end
|
437
377
|
|
438
378
|
end
|
@@ -14,6 +14,7 @@ module Cucumber
|
|
14
14
|
@err = StringIO.new
|
15
15
|
Kernel.stub!(:exit).and_return(nil)
|
16
16
|
File.stub!(:exist?).and_return(false) # When Configuration checks for cucumber.yml
|
17
|
+
Dir.stub!(:[]).and_return([]) # to prevent cucumber's features dir to being laoded
|
17
18
|
end
|
18
19
|
|
19
20
|
describe "verbose mode" do
|
@@ -22,15 +23,6 @@ module Cucumber
|
|
22
23
|
@empty_feature = Ast::Feature.new(nil, Ast::Comment.new(''), Ast::Tags.new(2, []), "Feature", [])
|
23
24
|
end
|
24
25
|
|
25
|
-
it "should show ruby files required" do
|
26
|
-
@cli = Main.new(%w{--verbose --require example.rb}, @out)
|
27
|
-
@cli.stub!(:require)
|
28
|
-
|
29
|
-
@cli.execute!(Object.new.extend(StepMother))
|
30
|
-
|
31
|
-
@out.string.should include('example.rb')
|
32
|
-
end
|
33
|
-
|
34
26
|
it "should show feature files parsed" do
|
35
27
|
@cli = Main.new(%w{--verbose example.feature}, @out)
|
36
28
|
@cli.stub!(:require)
|
@@ -209,6 +209,10 @@ module Cli
|
|
209
209
|
options[:source].should be_false
|
210
210
|
end
|
211
211
|
|
212
|
+
it "uses the language from profile when none is specified on the command line" do
|
213
|
+
given_cucumber_yml_defined_as({'foo' => '--language fr'})
|
214
|
+
after_parsing('-p foo') {options[:lang].should == 'fr'}
|
215
|
+
end
|
212
216
|
end
|
213
217
|
|
214
218
|
context '-P or --no-profile' do
|
@@ -278,28 +282,38 @@ module Cli
|
|
278
282
|
'baz' => '-r some_file.rb')
|
279
283
|
options.parse!(%w[features -p foo --profile bar])
|
280
284
|
|
281
|
-
options.expanded_args_without_drb.should == %w[features -v --wip -r some_file.rb]
|
285
|
+
options.expanded_args_without_drb.should == %w[features -v --wip -r some_file.rb --no-profile]
|
282
286
|
end
|
283
287
|
|
284
288
|
it "removes the --drb flag so that the args can be safely passed to the drb server" do
|
285
289
|
given_cucumber_yml_defined_as('default' => 'features -f pretty --drb')
|
286
290
|
options.parse!(%w[--profile default])
|
287
291
|
|
288
|
-
options.expanded_args_without_drb.should == %w[features -f pretty]
|
292
|
+
options.expanded_args_without_drb.should == %w[features -f pretty --no-profile]
|
289
293
|
end
|
290
294
|
|
291
295
|
it "contains the environment variables" do
|
292
296
|
options.parse!(%w[features FOO=bar])
|
293
|
-
options.expanded_args_without_drb.should == %w[features FOO=bar]
|
297
|
+
options.expanded_args_without_drb.should == %w[features FOO=bar --no-profile]
|
294
298
|
end
|
295
299
|
|
296
300
|
it "ignores the paths from the profiles if one was specified on the command line" do
|
297
301
|
given_cucumber_yml_defined_as('foo' => 'features --drb')
|
298
302
|
options.parse!(%w[some_feature.feature -p foo])
|
299
|
-
options.expanded_args_without_drb.should == %w[some_feature.feature]
|
303
|
+
options.expanded_args_without_drb.should == %w[some_feature.feature --no-profile]
|
300
304
|
end
|
301
305
|
|
302
306
|
|
307
|
+
it "appends the --no-profile flag so that the DRb server doesn't reload the profiles" do
|
308
|
+
given_cucumber_yml_defined_as('foo' => 'features --drb')
|
309
|
+
options.parse!(%w[some_feature.feature -p foo])
|
310
|
+
options.expanded_args_without_drb.should == %w[some_feature.feature --no-profile]
|
311
|
+
end
|
312
|
+
|
313
|
+
it "does not append --no-profile if already present" do
|
314
|
+
options.parse!(%w[some_feature.feature -P])
|
315
|
+
options.expanded_args_without_drb.should == %w[some_feature.feature -P]
|
316
|
+
end
|
303
317
|
|
304
318
|
|
305
319
|
end
|
@@ -72,6 +72,14 @@ spec/cucumber/step_mother_spec.rb:40:in `/Three cute (.*)/'
|
|
72
72
|
wrong = @step_mother.Given(/Three (.*)/) {|animal|}
|
73
73
|
@step_mother.step_match("Three blind mice ran far").step_definition.should == right
|
74
74
|
end
|
75
|
+
|
76
|
+
it "should pick most specific step definition when --guess is enabled and unequal number of capture groups" do
|
77
|
+
@step_mother.options = {:guess => true}
|
78
|
+
general = @step_mother.Given(/Three (.*) mice ran (.*)/) {|disability|}
|
79
|
+
specific = @step_mother.Given(/Three blind mice ran far/) {}
|
80
|
+
more_specific = @step_mother.Given(/^Three blind mice ran far$/) {}
|
81
|
+
@step_mother.step_match("Three blind mice ran far").step_definition.should == more_specific
|
82
|
+
end
|
75
83
|
|
76
84
|
it "should raise Undefined error when no step definitions match" do
|
77
85
|
lambda do
|
@@ -101,7 +109,7 @@ spec/cucumber/step_mother_spec.rb:40:in `/Three cute (.*)/'
|
|
101
109
|
raise "Should fail"
|
102
110
|
rescue NilWorld => e
|
103
111
|
e.message.should == "World procs should never return nil"
|
104
|
-
e.backtrace.should == ["spec/cucumber/step_mother_spec.rb:
|
112
|
+
e.backtrace.should == ["spec/cucumber/step_mother_spec.rb:104:in `World'"]
|
105
113
|
end
|
106
114
|
end
|
107
115
|
|
@@ -132,8 +140,8 @@ spec/cucumber/step_mother_spec.rb:40:in `/Three cute (.*)/'
|
|
132
140
|
end.should raise_error(MultipleWorld, %{You can only pass a proc to #World once, but it's happening
|
133
141
|
in 2 places:
|
134
142
|
|
135
|
-
spec/cucumber/step_mother_spec.rb:
|
136
|
-
spec/cucumber/step_mother_spec.rb:
|
143
|
+
spec/cucumber/step_mother_spec.rb:137:in `World'
|
144
|
+
spec/cucumber/step_mother_spec.rb:139:in `World'
|
137
145
|
|
138
146
|
Use Ruby modules instead to extend your worlds. See the Cucumber::StepMother#World RDoc
|
139
147
|
or http://wiki.github.com/aslakhellesoy/cucumber/a-whole-new-world.
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: cucumber
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.3.
|
4
|
+
version: 0.3.95
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- "Aslak Helles\xC3\xB8y"
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-08-
|
12
|
+
date: 2009-08-13 00:00:00 +02:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
@@ -388,6 +388,7 @@ files:
|
|
388
388
|
- lib/cucumber/cli/main.rb
|
389
389
|
- lib/cucumber/cli/options.rb
|
390
390
|
- lib/cucumber/cli/profile_loader.rb
|
391
|
+
- lib/cucumber/cli/rb_step_def_loader.rb
|
391
392
|
- lib/cucumber/core_ext/exception.rb
|
392
393
|
- lib/cucumber/core_ext/instance_exec.rb
|
393
394
|
- lib/cucumber/core_ext/proc.rb
|
@@ -430,6 +431,7 @@ files:
|
|
430
431
|
- lib/cucumber/step_match.rb
|
431
432
|
- lib/cucumber/step_mother.rb
|
432
433
|
- lib/cucumber/version.rb
|
434
|
+
- lib/cucumber/webrat/element_locator.rb
|
433
435
|
- lib/cucumber/webrat/table_locator.rb
|
434
436
|
- lib/cucumber/world.rb
|
435
437
|
- rails_generators/cucumber/USAGE
|