kelp 0.1.5 → 0.1.6
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/.gitignore +2 -0
- data/Gemfile.lock +1 -1
- data/History.md +8 -0
- data/README.md +23 -7
- data/Rakefile +32 -9
- data/examples/sinatra_app/features/checkbox.feature +12 -0
- data/examples/sinatra_app/features/dropdown.feature +6 -0
- data/examples/sinatra_app/features/field.feature +18 -0
- data/examples/sinatra_app/features/visibility.feature +7 -0
- data/examples/sinatra_app/views/form.erb +18 -8
- data/features/kelp_step_definitions.feature +31 -5
- data/features/step_definitions/app_steps.rb +14 -6
- data/kelp.gemspec +1 -1
- data/lib/kelp/field.rb +6 -6
- data/lib/kelp/scoping.rb +8 -4
- data/rails_generators/kelp/templates/kelp_steps.rb +140 -32
- data/spec/field_spec.rb +2 -0
- data/spec/visibility_spec.rb +36 -5
- metadata +6 -4
data/.gitignore
CHANGED
data/Gemfile.lock
CHANGED
data/History.md
CHANGED
@@ -1,6 +1,14 @@
|
|
1
1
|
Kelp History
|
2
2
|
============
|
3
3
|
|
4
|
+
0.1.6
|
5
|
+
-----
|
6
|
+
|
7
|
+
- Improved generated step definitions in kelp_steps.rb, fixed some bugs therein
|
8
|
+
- Expanded cucumber self-tests for generated step definitions
|
9
|
+
- Fixed bug with field_should_be_empty; now works with textarea
|
10
|
+
|
11
|
+
|
4
12
|
0.1.5
|
5
13
|
-----
|
6
14
|
|
data/README.md
CHANGED
@@ -94,6 +94,20 @@ See the
|
|
94
94
|
for more information.
|
95
95
|
|
96
96
|
|
97
|
+
Rails generator
|
98
|
+
---------------
|
99
|
+
|
100
|
+
Kelp provides a generator for Rails 2.x projects, to quickly add some generic
|
101
|
+
step definitions. Simply run:
|
102
|
+
|
103
|
+
$ script/generate kelp
|
104
|
+
|
105
|
+
This will create `features/step_definitions/kelp_steps.rb` with some example
|
106
|
+
step definitions using Kelp's helper methods.
|
107
|
+
|
108
|
+
A Rails 3.x generator is not currently provided. Contributions are welcome!
|
109
|
+
|
110
|
+
|
97
111
|
Development
|
98
112
|
-----------
|
99
113
|
|
@@ -122,24 +136,26 @@ then [submit a pull request](http://github.com/wapcaplet/kelp/pulls).
|
|
122
136
|
Testing
|
123
137
|
-------
|
124
138
|
|
125
|
-
Kelp comes with a `Rakefile`, so you can run the RSpec tests
|
139
|
+
Kelp comes with a `Rakefile`, so you can run the RSpec tests and generate an
|
140
|
+
[rcov](http://eigenclass.org/hiki.rb?rcov) coverage report via:
|
126
141
|
|
127
142
|
$ rake spec
|
128
143
|
|
129
|
-
|
130
|
-
|
144
|
+
This will write an HTML report to `coverage/index.html`. Finally, there are
|
145
|
+
some Cucumber self-tests included, mainly for testing the `kelp_steps.rb`
|
146
|
+
file used by the Rails generator. Run via:
|
131
147
|
|
132
|
-
$ rake
|
148
|
+
$ rake cucumber
|
133
149
|
|
134
|
-
This
|
150
|
+
This self-test is a single scenario that exercises scenarios in
|
151
|
+
`examples/sinatra_app/features`, and ensures that they perform as expected.
|
135
152
|
|
136
153
|
|
137
154
|
Future plans
|
138
155
|
------------
|
139
156
|
|
140
|
-
*
|
157
|
+
* Generator for Rails 3
|
141
158
|
* Support other stuff besides Capybara
|
142
|
-
* Turn the project into a proper Rails plugin, with generators
|
143
159
|
|
144
160
|
|
145
161
|
Copyright
|
data/Rakefile
CHANGED
@@ -1,16 +1,39 @@
|
|
1
1
|
require 'rubygems'
|
2
2
|
require 'rspec/core/rake_task'
|
3
|
+
require 'cucumber/rake/task'
|
3
4
|
|
4
|
-
RSpec
|
5
|
-
|
6
|
-
|
5
|
+
desc "Run RSpec tests with coverage analysis"
|
6
|
+
RSpec::Core::RakeTask.new(:spec) do |t|
|
7
|
+
t.pattern = 'spec/**/*_spec.rb'
|
8
|
+
t.rspec_opts = ['--color', '--format doc']
|
9
|
+
t.rcov = true
|
10
|
+
t.rcov_opts = [
|
11
|
+
'--exclude /.gem/,/gems/,spec,features,examples',
|
12
|
+
'--include lib/**/*.rb',
|
13
|
+
'--aggregate coverage.data',
|
14
|
+
]
|
7
15
|
end
|
8
16
|
|
9
|
-
desc "
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
17
|
+
desc "Run Cucumber tests with coverage analysis"
|
18
|
+
Cucumber::Rake::Task.new(:cucumber) do |t|
|
19
|
+
t.cucumber_opts = [
|
20
|
+
"--format pretty",
|
21
|
+
"--tags ~@wip",
|
22
|
+
]
|
23
|
+
t.rcov = true
|
24
|
+
t.rcov_opts = [
|
25
|
+
'--exclude /.gem/,/gems/,spec,features,examples',
|
26
|
+
'--include lib/**/*.rb',
|
27
|
+
'--aggregate coverage.data',
|
28
|
+
]
|
15
29
|
end
|
16
30
|
|
31
|
+
desc "Run RSpec and Cucumber tests with coverage analysis"
|
32
|
+
task :all do |t|
|
33
|
+
rm 'coverage.data' if File.exist?('coverage.data')
|
34
|
+
Rake::Task['rcov:spec'].invoke
|
35
|
+
Rake::Task['rcov:cucumber'].invoke
|
36
|
+
end
|
37
|
+
|
38
|
+
task :default => ['all']
|
39
|
+
|
@@ -0,0 +1,12 @@
|
|
1
|
+
Feature: Checkboxes
|
2
|
+
|
3
|
+
Background:
|
4
|
+
Given I visit "/form"
|
5
|
+
|
6
|
+
Scenario: Checkbox should be checked
|
7
|
+
Then the "Like" checkbox next to "Apple" should be checked
|
8
|
+
And the "Like" checkbox next to "Apple" should not be unchecked
|
9
|
+
|
10
|
+
Scenario: Checkbox should not be checked
|
11
|
+
Then the "Like" checkbox next to "Banana" should be unchecked
|
12
|
+
And the "Like" checkbox next to "Banana" should not be checked
|
@@ -17,6 +17,12 @@ Feature: Dropdowns
|
|
17
17
|
| Single 'quotes' |
|
18
18
|
| "Double" quotes |
|
19
19
|
| 'Single' and "Double" quotes |
|
20
|
+
And the "Favorite Colors" dropdown should include:
|
21
|
+
"""
|
22
|
+
Red
|
23
|
+
Green
|
24
|
+
Blue
|
25
|
+
"""
|
20
26
|
|
21
27
|
Scenario: Dropdown should not include
|
22
28
|
Then the "Height" dropdown should not include "Midget"
|
@@ -0,0 +1,18 @@
|
|
1
|
+
Feature: Fields
|
2
|
+
|
3
|
+
Background:
|
4
|
+
Given I visit "/form"
|
5
|
+
|
6
|
+
Scenario: Field should be empty
|
7
|
+
Then the "First name" field should be empty
|
8
|
+
And the "First name" field within "#person_form" should be empty
|
9
|
+
And the "Last name" field should be empty
|
10
|
+
And the "Last name" field within "#person_form" should be empty
|
11
|
+
|
12
|
+
Scenario: Fields should contain
|
13
|
+
Then the fields should contain:
|
14
|
+
| First name | |
|
15
|
+
| Last name | |
|
16
|
+
| Weight | Light |
|
17
|
+
| Height | Average |
|
18
|
+
| Message | Your message goes here |
|
@@ -11,6 +11,7 @@ Feature: Visibility
|
|
11
11
|
And I should not see the following:
|
12
12
|
| Goodbye cruel world |
|
13
13
|
|
14
|
+
|
14
15
|
Scenario: Should or shouldn't see in same row
|
15
16
|
Then I should see a table row containing:
|
16
17
|
| Eric | Edit |
|
@@ -26,3 +27,9 @@ Feature: Visibility
|
|
26
27
|
| John | Delete |
|
27
28
|
| Terry | Delete |
|
28
29
|
|
30
|
+
|
31
|
+
Scenario: Should or shouldn't see next to
|
32
|
+
Then I should see "Edit" next to "John"
|
33
|
+
And I should not see "Delete" next to "John"
|
34
|
+
|
35
|
+
|
@@ -13,6 +13,10 @@
|
|
13
13
|
<label for="last_name">Last name</label>
|
14
14
|
<input id="last_name" type="text" />
|
15
15
|
</p>
|
16
|
+
<p>
|
17
|
+
<label for="biography">Life story</label>
|
18
|
+
<textarea id="biography" cols="80" rows="10" />
|
19
|
+
</p>
|
16
20
|
<p>
|
17
21
|
<label for="height">Height</label>
|
18
22
|
<select id="height">
|
@@ -53,6 +57,10 @@
|
|
53
57
|
<label for="like_salami">I like salami</label>
|
54
58
|
<input id="like_salami" type="checkbox" />
|
55
59
|
</p>
|
60
|
+
<p>
|
61
|
+
<label for="message">Message</label>
|
62
|
+
<input id="message" type="text" value="Your message goes here" />
|
63
|
+
</p>
|
56
64
|
<p><input type="submit" value="Submit" /></p>
|
57
65
|
</form>
|
58
66
|
</div>
|
@@ -68,16 +76,18 @@
|
|
68
76
|
<form action="/thanks" method="get">
|
69
77
|
<table>
|
70
78
|
<tr>
|
71
|
-
<
|
72
|
-
<td
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
<td><input id="check_b" type="checkbox"/></td>
|
79
|
+
<th>Apple</th>
|
80
|
+
<td>
|
81
|
+
<label for="like_apple">Like</label>
|
82
|
+
<input id="like_apple" type="checkbox" checked="checked"/>
|
83
|
+
</td>
|
77
84
|
</tr>
|
78
85
|
<tr>
|
79
|
-
<
|
80
|
-
<td
|
86
|
+
<th>Banana</th>
|
87
|
+
<td>
|
88
|
+
<label for="like_banana">Like</label>
|
89
|
+
<input id="like_banana" type="checkbox"/>
|
90
|
+
</td>
|
81
91
|
</tr>
|
82
92
|
</table>
|
83
93
|
</form>
|
@@ -3,12 +3,38 @@ Feature: Kelp Step Definitions
|
|
3
3
|
As a Kelp developer
|
4
4
|
I want to be sure the step definitions Kelp provides work correctly
|
5
5
|
|
6
|
-
|
7
|
-
Given
|
8
|
-
|
6
|
+
Background:
|
7
|
+
Given the latest Kelp step definitions
|
8
|
+
|
9
|
+
Scenario: Checkbox test
|
10
|
+
When I run cucumber on "checkbox.feature"
|
11
|
+
Then the results should be:
|
12
|
+
"""
|
13
|
+
2 scenarios (2 passed)
|
14
|
+
6 steps (6 passed)
|
15
|
+
"""
|
16
|
+
|
17
|
+
Scenario: Dropdown test
|
18
|
+
When I run cucumber on "dropdown.feature"
|
19
|
+
Then the results should be:
|
20
|
+
"""
|
21
|
+
3 scenarios (3 passed)
|
22
|
+
11 steps (11 passed)
|
23
|
+
"""
|
24
|
+
|
25
|
+
Scenario: Field test
|
26
|
+
When I run cucumber on "field.feature"
|
27
|
+
Then the results should be:
|
28
|
+
"""
|
29
|
+
2 scenarios (2 passed)
|
30
|
+
7 steps (7 passed)
|
31
|
+
"""
|
32
|
+
|
33
|
+
Scenario: Visibility test
|
34
|
+
When I run cucumber on "visibility.feature"
|
9
35
|
Then the results should be:
|
10
36
|
"""
|
11
|
-
|
12
|
-
|
37
|
+
3 scenarios (3 passed)
|
38
|
+
11 steps (11 passed)
|
13
39
|
"""
|
14
40
|
|
@@ -2,8 +2,8 @@
|
|
2
2
|
|
3
3
|
require 'fileutils'
|
4
4
|
|
5
|
-
Given /^
|
6
|
-
app_dir = File.join(root_dir, 'examples', "
|
5
|
+
Given /^the latest Kelp step definitions$/ do
|
6
|
+
app_dir = File.join(root_dir, 'examples', "sinatra_app")
|
7
7
|
installed_steps = File.join(app_dir, 'features', 'step_definitions', 'kelp_steps.rb')
|
8
8
|
latest_steps = File.join(root_dir, 'rails_generators', 'kelp', 'templates', 'kelp_steps.rb')
|
9
9
|
# Remove the installed kelp_steps.rb, if any, then install the latest one
|
@@ -12,15 +12,23 @@ Given /^a (\w+) application with the latest Kelp step definitions$/ do |platform
|
|
12
12
|
FileUtils.cp_r(latest_steps, installed_steps)
|
13
13
|
end
|
14
14
|
|
15
|
-
|
16
|
-
|
17
|
-
|
15
|
+
|
16
|
+
When /^I run cucumber on "(.+)"$/ do |feature|
|
17
|
+
cucumber = "#{Cucumber::RUBY_BINARY} #{Cucumber::BINARY}"
|
18
|
+
opts = "-q --no-color"
|
19
|
+
command = "#{cucumber} #{opts} features/#{feature}"
|
20
|
+
app_dir = File.join(root_dir, 'examples', "sinatra_app")
|
18
21
|
Dir.chdir(app_dir) do
|
19
22
|
@output = `#{command}`
|
20
23
|
end
|
21
24
|
end
|
22
25
|
|
26
|
+
|
23
27
|
Then /^the results should be:$/ do |expected_results|
|
24
|
-
|
28
|
+
if !@output.include?(expected_results)
|
29
|
+
got = @output.collect {|line| " #{line}"}.join
|
30
|
+
want = expected_results.collect {|line| " #{line}"}.join
|
31
|
+
raise("Expected:\n#{want}\nGot:\n#{got}")
|
32
|
+
end
|
25
33
|
end
|
26
34
|
|
data/kelp.gemspec
CHANGED
data/lib/kelp/field.rb
CHANGED
@@ -57,12 +57,12 @@ module Kelp
|
|
57
57
|
|
58
58
|
|
59
59
|
# Verify that the given field is empty or nil.
|
60
|
-
def field_should_be_empty(field)
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
60
|
+
def field_should_be_empty(field, scope={})
|
61
|
+
in_scope(scope) do
|
62
|
+
_field = nice_find_field(field)
|
63
|
+
if !(_field.nil? || _field.value.nil? || _field.value == '')
|
64
|
+
raise RuntimeError, "Expected field '#{field}' to be empty, but value is '#{_field.value}'"
|
65
|
+
end
|
66
66
|
end
|
67
67
|
end
|
68
68
|
|
data/lib/kelp/scoping.rb
CHANGED
@@ -3,9 +3,9 @@ module Kelp
|
|
3
3
|
# verifications on a webpage.
|
4
4
|
#
|
5
5
|
module Scoping
|
6
|
-
# Execute a block of code within a given scope.
|
7
|
-
#
|
8
|
-
#
|
6
|
+
# Execute a block of code within a given scope. If `locator` begins with
|
7
|
+
# `/` or `./`, then it's assumed to be an XPath selector; otherwise, it's
|
8
|
+
# assumed to be a CSS selector.
|
9
9
|
def scope_within(locator)
|
10
10
|
if locator
|
11
11
|
# Use the selector_for method if it's defined
|
@@ -15,7 +15,11 @@ module Kelp
|
|
15
15
|
# and fall back on the Capybara locator syntax (CSS or XPath)
|
16
16
|
else
|
17
17
|
locator.gsub!(/^"(.*?)"$/, '\1')
|
18
|
-
|
18
|
+
if locator =~ /\.?\//
|
19
|
+
within(:xpath, locator) { yield }
|
20
|
+
else
|
21
|
+
within(:css, locator) { yield }
|
22
|
+
end
|
19
23
|
end
|
20
24
|
else
|
21
25
|
yield
|
@@ -14,11 +14,30 @@
|
|
14
14
|
#
|
15
15
|
|
16
16
|
require 'kelp'
|
17
|
-
World(Kelp::
|
17
|
+
World(Kelp::Attribute)
|
18
|
+
World(Kelp::Checkbox)
|
18
19
|
World(Kelp::Dropdown)
|
20
|
+
World(Kelp::Field)
|
21
|
+
World(Kelp::Navigation)
|
22
|
+
World(Kelp::Scoping)
|
23
|
+
World(Kelp::Visibility)
|
24
|
+
|
25
|
+
module KelpStepHelper
|
26
|
+
# Convert a Cucumber::Ast::Table or multiline string into
|
27
|
+
# a list of strings
|
28
|
+
def listify(items)
|
29
|
+
if items.class == Cucumber::Ast::Table
|
30
|
+
strings = items.raw.flatten
|
31
|
+
else
|
32
|
+
strings = items.split(/[\r\n]+/)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
World(KelpStepHelper)
|
19
37
|
|
20
38
|
SHOULD_OR_NOT = /(should|should not)/
|
21
39
|
WITHIN = /(?: within "([^\"]+)")?/
|
40
|
+
ELEMENT = /(?:field|checkbox|dropdown|button)/
|
22
41
|
STR = /([^\"]+)/
|
23
42
|
|
24
43
|
# Verify the presence or absence of multiple text strings in the page,
|
@@ -30,23 +49,19 @@ STR = /([^\"]+)/
|
|
30
49
|
# `items` may be a Cucumber table, or a multi-line string. Examples:
|
31
50
|
#
|
32
51
|
# Then I should see the following:
|
33
|
-
# |
|
34
|
-
# |
|
35
|
-
# |
|
52
|
+
# | Apple crumble |
|
53
|
+
# | Banana cream pie |
|
54
|
+
# | Cherry tart |
|
36
55
|
#
|
37
56
|
# Then I should see the following:
|
38
57
|
# """
|
39
|
-
#
|
40
|
-
#
|
41
|
-
#
|
58
|
+
# Bacon & Eggs
|
59
|
+
# Biscuits & Gravy
|
60
|
+
# Hash Browns
|
42
61
|
# """
|
43
62
|
#
|
44
63
|
Then /^I #{SHOULD_OR_NOT} see the following#{WITHIN}:$/ do |expect, selector, items|
|
45
|
-
|
46
|
-
strings = items.raw.flatten
|
47
|
-
else
|
48
|
-
strings = items.split("\n")
|
49
|
-
end
|
64
|
+
strings = listify(items)
|
50
65
|
if expect == 'should'
|
51
66
|
should_see strings, :within => selector
|
52
67
|
else
|
@@ -58,6 +73,15 @@ end
|
|
58
73
|
# Verify that one or more table rows containing the correct values exist (or do
|
59
74
|
# not exist). Rows do not need to match exactly, and fields do not need to be
|
60
75
|
# in the same order.
|
76
|
+
#
|
77
|
+
# Examples:
|
78
|
+
#
|
79
|
+
# Then I should see table rows containing:
|
80
|
+
# | Eric | Edit |
|
81
|
+
# | John | Edit |
|
82
|
+
# And I should not see a table row containing:
|
83
|
+
# | Eric | Delete |
|
84
|
+
#
|
61
85
|
Then /^I #{SHOULD_OR_NOT} see (?:a table row|table rows)#{WITHIN} containing:$/ do |expect, selector, rows|
|
62
86
|
rows.raw.each do |fields|
|
63
87
|
if expect == 'should'
|
@@ -72,12 +96,22 @@ end
|
|
72
96
|
# Verify that a dropdown has a given value selected. This verifies the visible
|
73
97
|
# value shown to the user, rather than the value attribute of the selected
|
74
98
|
# option element.
|
99
|
+
#
|
100
|
+
# Examples:
|
101
|
+
#
|
102
|
+
# Then the "Height" dropdown should equal "Average"
|
103
|
+
#
|
75
104
|
Then /^the "#{STR}" dropdown#{WITHIN} should equal "#{STR}"$/ do |dropdown, selector, value|
|
76
105
|
dropdown_should_equal(dropdown, value, :within => selector)
|
77
106
|
end
|
78
107
|
|
79
108
|
|
80
109
|
# Verify that a dropdown includes or doesn't include the given value.
|
110
|
+
#
|
111
|
+
# Examples:
|
112
|
+
#
|
113
|
+
# Then the "Height" dropdown should include "Tall"
|
114
|
+
#
|
81
115
|
Then /^the "#{STR}" dropdown#{WITHIN} #{SHOULD_OR_NOT} include "#{STR}"$/ do |dropdown, selector, expect, value|
|
82
116
|
if expect == 'should'
|
83
117
|
dropdown_should_include(dropdown, value, :within => selector)
|
@@ -87,9 +121,25 @@ Then /^the "#{STR}" dropdown#{WITHIN} #{SHOULD_OR_NOT} include "#{STR}"$/ do |dr
|
|
87
121
|
end
|
88
122
|
|
89
123
|
|
90
|
-
# Verify that a dropdown includes or doesn't include all values in the given
|
124
|
+
# Verify that a dropdown includes or doesn't include all values in the given
|
125
|
+
# table or multiline string.
|
126
|
+
#
|
127
|
+
# Examples:
|
128
|
+
#
|
129
|
+
# Then the "Height" dropdown should include:
|
130
|
+
# | Short |
|
131
|
+
# | Average |
|
132
|
+
# | Tall |
|
133
|
+
#
|
134
|
+
# Then the "Favorite Colors" dropdown should include:
|
135
|
+
# """
|
136
|
+
# Red
|
137
|
+
# Green
|
138
|
+
# Blue
|
139
|
+
# """
|
140
|
+
#
|
91
141
|
Then /^the "#{STR}" dropdown#{WITHIN} #{SHOULD_OR_NOT} include:$/ do |dropdown, selector, expect, values|
|
92
|
-
values.
|
142
|
+
listify(values).each do |value|
|
93
143
|
if expect == 'should'
|
94
144
|
dropdown_should_include(dropdown, value, :within => selector)
|
95
145
|
else
|
@@ -99,30 +149,73 @@ Then /^the "#{STR}" dropdown#{WITHIN} #{SHOULD_OR_NOT} include:$/ do |dropdown,
|
|
99
149
|
end
|
100
150
|
|
101
151
|
|
102
|
-
# Verify that a given field is empty or nil
|
152
|
+
# Verify that a given field is empty or nil.
|
153
|
+
#
|
154
|
+
# Examples:
|
155
|
+
#
|
156
|
+
# Then the "First name" field should be empty
|
157
|
+
#
|
103
158
|
Then /^the "#{STR}" field#{WITHIN} should be empty$/ do |field, selector|
|
104
|
-
|
105
|
-
field_should_be_empty field
|
106
|
-
end
|
159
|
+
field_should_be_empty(field, :within => selector)
|
107
160
|
end
|
108
161
|
|
109
162
|
|
110
163
|
# Verify multiple fields in a form, optionally restricted to a given selector.
|
111
|
-
# Fields may be text inputs or dropdowns
|
164
|
+
# Fields may be text inputs or dropdowns.
|
165
|
+
#
|
166
|
+
# Examples:
|
167
|
+
#
|
168
|
+
# Then the fields should contain:
|
169
|
+
# | First name | Eric |
|
170
|
+
# | Last name | Pierce |
|
171
|
+
#
|
112
172
|
Then /^the fields#{WITHIN} should contain:$/ do |selector, fields|
|
113
173
|
fields_should_contain_within(selector, fields.rows_hash)
|
114
174
|
end
|
115
175
|
|
116
176
|
|
117
177
|
# Verify that expected text exists or does not exist in the same row as
|
118
|
-
#
|
178
|
+
# some text. This can be used to ensure the presence or absence of "Edit"
|
119
179
|
# or "Delete" links, or specific data associated with a row in a table.
|
120
|
-
|
121
|
-
|
180
|
+
#
|
181
|
+
# Examples:
|
182
|
+
#
|
183
|
+
# Then I should see "Edit" next to "John"
|
184
|
+
# And I should not see "Delete" next to "John"
|
185
|
+
#
|
186
|
+
Then /^I #{SHOULD_OR_NOT} see "#{STR}" next to "#{STR}"#{WITHIN}$/ do |expect, text, next_to, selector|
|
187
|
+
if expect == 'should'
|
188
|
+
should_see_in_same_row([text, next_to], :within => selector)
|
189
|
+
else
|
190
|
+
should_not_see_in_same_row([text, next_to], :within => selector)
|
191
|
+
end
|
192
|
+
end
|
193
|
+
|
194
|
+
|
195
|
+
# Verify that several expected text strings exist or do not exist in the same
|
196
|
+
# row as some text. Prevents multiple "should see X next to Y" calls. Similar
|
197
|
+
# to "should see a row containing", but targeted toward a specific row.
|
198
|
+
#
|
199
|
+
# Examples:
|
200
|
+
#
|
201
|
+
# Then I should see the following next to "Terry":
|
202
|
+
# | Copy |
|
203
|
+
# | Edit |
|
204
|
+
# | Delete |
|
205
|
+
#
|
206
|
+
# Then I should see the following next to "John":
|
207
|
+
# """
|
208
|
+
# Copy
|
209
|
+
# Edit
|
210
|
+
# Delete
|
211
|
+
# """
|
212
|
+
#
|
213
|
+
Then /^I #{SHOULD_OR_NOT} see the following next to "#{STR}"#{WITHIN}:$/ do |expect, next_to, selector, items|
|
214
|
+
listify(items).each do |text|
|
122
215
|
if expect == 'should'
|
123
|
-
should_see_in_same_row
|
216
|
+
should_see_in_same_row([text, next_to], :within => selector)
|
124
217
|
else
|
125
|
-
should_not_see_in_same_row
|
218
|
+
should_not_see_in_same_row([text, next_to], :within => selector)
|
126
219
|
end
|
127
220
|
end
|
128
221
|
end
|
@@ -130,19 +223,34 @@ end
|
|
130
223
|
|
131
224
|
# Click a link in a table row that contains the given text.
|
132
225
|
# This can be used to click the "Edit" link for a specific record.
|
133
|
-
|
134
|
-
|
226
|
+
#
|
227
|
+
# Examples:
|
228
|
+
#
|
229
|
+
# When I follow "Edit" next to "John"
|
230
|
+
#
|
231
|
+
When /^I follow "#{STR}" next to "#{STR}"$/ do |link, next_to|
|
232
|
+
click_link_in_row(link, next_to)
|
135
233
|
end
|
136
234
|
|
137
235
|
|
138
|
-
# Verify that a checkbox in a certain table row is checked or unchecked
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
236
|
+
# Verify that a checkbox in a certain table row is checked or unchecked.
|
237
|
+
# "should not be checked" and "should be unchecked" are equivalent, and
|
238
|
+
# "should be checked" and "should not be unchecked" are equivalent.
|
239
|
+
#
|
240
|
+
# Examples:
|
241
|
+
#
|
242
|
+
# Then the "Like" checkbox next to "Apple" should be checked
|
243
|
+
# And the "Like" checkbox next to "Banana" should be unchecked
|
244
|
+
#
|
245
|
+
Then /^the "#{STR}" checkbox next to "#{STR}"#{WITHIN} #{SHOULD_OR_NOT} be (checked|unchecked)$/ do |checkbox, next_to, selector, expect, state|
|
246
|
+
|
247
|
+
within(:xpath, xpath_row_containing(next_to)) do
|
248
|
+
if (expect == 'should' && state == 'checked') || (expect == 'should not' && state == 'unchecked')
|
249
|
+
checkbox_should_be_checked(checkbox, :within => selector)
|
143
250
|
else
|
144
|
-
checkbox_should_not_be_checked(checkbox,
|
251
|
+
checkbox_should_not_be_checked(checkbox, :within => selector)
|
145
252
|
end
|
146
253
|
end
|
147
254
|
end
|
148
255
|
|
256
|
+
|
data/spec/field_spec.rb
CHANGED
@@ -10,6 +10,7 @@ describe Kelp::Field, "field_should_be_empty" do
|
|
10
10
|
it "is empty" do
|
11
11
|
field_should_be_empty "first_name"
|
12
12
|
field_should_be_empty "last_name"
|
13
|
+
field_should_be_empty "biography"
|
13
14
|
end
|
14
15
|
end
|
15
16
|
|
@@ -17,6 +18,7 @@ describe Kelp::Field, "field_should_be_empty" do
|
|
17
18
|
it "is empty" do
|
18
19
|
field_should_be_empty "First name"
|
19
20
|
field_should_be_empty "Last name"
|
21
|
+
field_should_be_empty "Life story"
|
20
22
|
end
|
21
23
|
end
|
22
24
|
end
|
data/spec/visibility_spec.rb
CHANGED
@@ -19,9 +19,13 @@ describe Kelp::Visibility, "should_see" do
|
|
19
19
|
]
|
20
20
|
end
|
21
21
|
|
22
|
-
it "is within
|
22
|
+
it "is within a CSS scope" do
|
23
23
|
should_see "Hello world", :within => "#greeting"
|
24
24
|
end
|
25
|
+
|
26
|
+
it "is within an XPath scope" do
|
27
|
+
should_see "Hello world", :within => "//div[@id='greeting']"
|
28
|
+
end
|
25
29
|
end
|
26
30
|
|
27
31
|
context "Regexp" do
|
@@ -29,10 +33,15 @@ describe Kelp::Visibility, "should_see" do
|
|
29
33
|
should_see /(Hello|Goodbye) world/
|
30
34
|
end
|
31
35
|
|
32
|
-
it "matches within
|
36
|
+
it "matches within a CSS scope" do
|
33
37
|
should_see /(Hello|Goodbye) world/, :within => "#greeting"
|
34
38
|
should_see /(Hello|Goodbye) world/, :within => "#farewell"
|
35
39
|
end
|
40
|
+
|
41
|
+
it "matches within an XPath scope" do
|
42
|
+
should_see /(Hello|Goodbye) world/, :within => "//div[@id='greeting']"
|
43
|
+
should_see /(Hello|Goodbye) world/, :within => "//div[@id='farewell']"
|
44
|
+
end
|
36
45
|
end
|
37
46
|
end
|
38
47
|
|
@@ -54,11 +63,23 @@ describe Kelp::Visibility, "should_see" do
|
|
54
63
|
end.should raise_error(RSpec::Expectations::ExpectationNotMetError)
|
55
64
|
end
|
56
65
|
|
57
|
-
it "is not within
|
66
|
+
it "is not within a given CSS scope" do
|
58
67
|
lambda do
|
59
68
|
should_see "Goodbye world", :within => "#greeting"
|
60
69
|
end.should raise_error(RSpec::Expectations::ExpectationNotMetError)
|
61
70
|
end
|
71
|
+
|
72
|
+
it "is not within a given XPath scope" do
|
73
|
+
lambda do
|
74
|
+
should_see "Goodbye world", :within => "//div[@id='greeting']"
|
75
|
+
end.should raise_error(RSpec::Expectations::ExpectationNotMetError)
|
76
|
+
end
|
77
|
+
|
78
|
+
it "is given a nonexistent XPath scope" do
|
79
|
+
lambda do
|
80
|
+
should_see "Goodbye world", :within => "//div[@id='nonexistent']"
|
81
|
+
end.should raise_error(Capybara::ElementNotFound)
|
82
|
+
end
|
62
83
|
end
|
63
84
|
|
64
85
|
context "Regexp" do
|
@@ -97,9 +118,13 @@ describe Kelp::Visibility, "should_not_see" do
|
|
97
118
|
]
|
98
119
|
end
|
99
120
|
|
100
|
-
it "exists but is not within the scope" do
|
121
|
+
it "exists but is not within the given CSS scope" do
|
101
122
|
should_not_see "Goodbye world", :within => "#greeting"
|
102
123
|
end
|
124
|
+
|
125
|
+
it "exists but is not within the given XPath scope" do
|
126
|
+
should_not_see "Goodbye world", :within => "//div[@id='greeting']"
|
127
|
+
end
|
103
128
|
end
|
104
129
|
|
105
130
|
context "Regexp" do
|
@@ -139,11 +164,17 @@ describe Kelp::Visibility, "should_not_see" do
|
|
139
164
|
end.should raise_error(RSpec::Expectations::ExpectationNotMetError)
|
140
165
|
end
|
141
166
|
|
142
|
-
it "exists within the scope" do
|
167
|
+
it "exists within the given CSS scope" do
|
143
168
|
lambda do
|
144
169
|
should_not_see "Hello world", :within => "#greeting"
|
145
170
|
end.should raise_error(RSpec::Expectations::ExpectationNotMetError)
|
146
171
|
end
|
172
|
+
|
173
|
+
it "exists within the given XPath scope" do
|
174
|
+
lambda do
|
175
|
+
should_not_see "Hello world", :within => "//div[@id='greeting']"
|
176
|
+
end.should raise_error(RSpec::Expectations::ExpectationNotMetError)
|
177
|
+
end
|
147
178
|
end
|
148
179
|
|
149
180
|
context "Regexp" do
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: kelp
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 23
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 1
|
9
|
-
-
|
10
|
-
version: 0.1.
|
9
|
+
- 6
|
10
|
+
version: 0.1.6
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Eric Pierce
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2011-04-
|
18
|
+
date: 2011-04-20 00:00:00 -06:00
|
19
19
|
default_executable:
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|
@@ -139,7 +139,9 @@ files:
|
|
139
139
|
- Rakefile
|
140
140
|
- examples/sinatra_app/app.rb
|
141
141
|
- examples/sinatra_app/config.ru
|
142
|
+
- examples/sinatra_app/features/checkbox.feature
|
142
143
|
- examples/sinatra_app/features/dropdown.feature
|
144
|
+
- examples/sinatra_app/features/field.feature
|
143
145
|
- examples/sinatra_app/features/support/env.rb
|
144
146
|
- examples/sinatra_app/features/visibility.feature
|
145
147
|
- examples/sinatra_app/features/web_steps.rb
|