kelp 0.1.1 → 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (56) hide show
  1. data/.gitignore +2 -0
  2. data/.yardopts +6 -0
  3. data/Gemfile +4 -9
  4. data/Gemfile.lock +8 -0
  5. data/History.md +22 -0
  6. data/README.md +154 -7
  7. data/kelp.gemspec +1 -1
  8. data/lib/kelp.rb +8 -1
  9. data/lib/kelp/attribute.rb +31 -0
  10. data/lib/kelp/checkbox.rb +31 -0
  11. data/lib/kelp/dropdown.rb +109 -0
  12. data/lib/kelp/field.rb +159 -0
  13. data/lib/kelp/helper.rb +14 -0
  14. data/lib/kelp/navigation.rb +63 -0
  15. data/lib/kelp/scoping.rb +45 -0
  16. data/lib/kelp/visibility.rb +176 -0
  17. data/lib/kelp/xpath.rb +14 -0
  18. data/spec/attribute_spec.rb +56 -0
  19. data/spec/checkbox_spec.rb +69 -0
  20. data/spec/dropdown_spec.rb +176 -0
  21. data/spec/field_spec.rb +290 -0
  22. data/spec/navigation_spec.rb +89 -0
  23. data/spec/scoping_spec.rb +0 -0
  24. data/spec/{capybara/spec_helper.rb → spec_helper.rb} +9 -5
  25. data/spec/test_app/views/form.erb +24 -0
  26. data/spec/visibility_spec.rb +315 -0
  27. data/spec/xpath_spec.rb +0 -0
  28. data/step_definitions/capybara_steps.rb +132 -0
  29. metadata +25 -32
  30. data/docs/Makefile +0 -130
  31. data/docs/_static/custom.css +0 -9
  32. data/docs/conf.py +0 -217
  33. data/docs/development.rst +0 -27
  34. data/docs/future.rst +0 -9
  35. data/docs/index.rst +0 -33
  36. data/docs/make.bat +0 -155
  37. data/docs/testing.rst +0 -15
  38. data/docs/usage.rst +0 -85
  39. data/lib/kelp/capybara.rb +0 -2
  40. data/lib/kelp/capybara/capybara_steps.rb +0 -225
  41. data/lib/kelp/capybara/form_helper.rb +0 -131
  42. data/lib/kelp/capybara/web_helper.rb +0 -148
  43. data/spec/capybara/click_link_in_row_spec.rb +0 -24
  44. data/spec/capybara/dropdown_spec.rb +0 -112
  45. data/spec/capybara/field_should_be_empty_spec.rb +0 -44
  46. data/spec/capybara/field_should_contain_spec.rb +0 -143
  47. data/spec/capybara/fill_in_fields_spec.rb +0 -67
  48. data/spec/capybara/follow_spec.rb +0 -35
  49. data/spec/capybara/page_should_have_spec.rb +0 -48
  50. data/spec/capybara/page_should_not_have_spec.rb +0 -53
  51. data/spec/capybara/press_spec.rb +0 -33
  52. data/spec/capybara/should_be_disabled_spec.rb +0 -28
  53. data/spec/capybara/should_be_enabled_spec.rb +0 -29
  54. data/spec/capybara/should_not_see_spec.rb +0 -97
  55. data/spec/capybara/should_see_in_same_row_spec.rb +0 -41
  56. data/spec/capybara/should_see_spec.rb +0 -80
data/.gitignore CHANGED
@@ -3,3 +3,5 @@
3
3
  coverage
4
4
  docs/_build
5
5
  .rvmrc
6
+ doc
7
+ .yardoc
data/.yardopts ADDED
@@ -0,0 +1,6 @@
1
+ --readme README.md
2
+ --markup markdown
3
+ lib/**/*.rb
4
+ -
5
+ History.md
6
+
data/Gemfile CHANGED
@@ -1,12 +1,7 @@
1
1
  source :rubygems
2
2
 
3
- group :capybara do
4
- gem 'capybara', '>= 0.4.0'
5
- end
3
+ gem 'bundler', '~> 1.0'
4
+
5
+ # Get all other dependencies from the gemspec
6
+ gemspec
6
7
 
7
- group :test do
8
- gem 'sinatra'
9
- gem 'rspec', '>= 2.2.0' # Rails 3
10
- gem 'rspec-rails'
11
- gem 'rcov'
12
- end
data/Gemfile.lock CHANGED
@@ -1,3 +1,9 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ kelp (0.1.2)
5
+ capybara (>= 0.4.0)
6
+
1
7
  GEM
2
8
  remote: http://rubygems.org/
3
9
  specs:
@@ -84,7 +90,9 @@ PLATFORMS
84
90
  ruby
85
91
 
86
92
  DEPENDENCIES
93
+ bundler (~> 1.0)
87
94
  capybara (>= 0.4.0)
95
+ kelp!
88
96
  rcov
89
97
  rspec (>= 2.2.0)
90
98
  rspec-rails
data/History.md ADDED
@@ -0,0 +1,22 @@
1
+ Kelp History
2
+ ============
3
+
4
+ 0.1.2
5
+ -----
6
+
7
+ - Improved namespacing for submodules, so you can be more specific about
8
+ requiring the helpers you need.
9
+ - Improved documentation and formatting, and converted all docs to YARD format.
10
+ - Added new methods fill_in_field, added scoping to field_should(_not)_contain
11
+ - Modified scope_within to use cucumber-rails' selector_for if it's defined
12
+
13
+
14
+ 0.1.1
15
+ -----
16
+
17
+ Initial public release. Includes basic helpers for checking element visibility
18
+ (should_see, should_not_see etc.) as well as navigation (press, follow,
19
+ click_link_in_row), form filling and verification (fill_in_fields,
20
+ fields_should_contain, dropdown_should_equal, etc.), with many of these
21
+ methods supporting a :within scope.
22
+
data/README.md CHANGED
@@ -1,16 +1,163 @@
1
1
  Kelp
2
2
  ====
3
3
 
4
- This project aims to package a collection of useful helper methods for
5
- Cucumber. Currently, the provided methods depend on Capybara, though support
6
- may eventually be added for Webrat, email-spec, or related tools.
4
+ This is the documentation for [Kelp](http://github.com/wapcaplet/kelp), a
5
+ collection of helpers that makes it easier to write step definitions for
6
+ [Cucumber](http://cukes.info). The Kelp gem is hosted on
7
+ [Rubygems](http://rubygems.org/gems/kelp), so you can install it with:
8
+
9
+ $ gem install kelp
10
+
11
+ The name "Kelp" is a contraction of "Cuke Helpers". It was chosen because it's
12
+ short, easy to remember, and is in keeping with the theme of greenish plants.
13
+ Kelp is licensed under the
14
+ [MIT License](http://www.opensource.org/licenses/mit-license.php).
15
+
16
+ Please use the [issue tracker](http://github.com/wapcaplet/kelp/issues)
17
+ to report any bugs or feature requests. Visit the `#kelp` channel on
18
+ `irc.freenode.net` to chat.
19
+
20
+
21
+ Usage
22
+ -----
23
+
24
+ To use Kelp's helpers in your Cucumber step definitions, simply `require` the
25
+ helper module you're interested in:
26
+
27
+ require 'kelp/visibility'
28
+
29
+ Then add the relevant modules to Cucumber's `World`:
30
+
31
+ World(Kelp::Visibility)
32
+
33
+ Many of the provided helpers are designed to make it easier to do things you
34
+ might otherwise be tempted to do with nested step definitions. For example, if
35
+ you need to verify the presence of several text strings on a webpage, you might
36
+ have a step definition like this:
37
+
38
+ Then /^I should see the login page$/ do
39
+ Then %{I should see "Welcome"}
40
+ And %{I should see "Thanks for visiting"}
41
+ And %{I should see "Login"}
42
+ end
43
+
44
+ Using the provided helper method `should_see`, you can do this instead:
45
+
46
+ Then /^I should see the login page$/ do
47
+ should_see "Welcome"
48
+ should_see "Thanks for visiting"
49
+ should_see "Login"
50
+ end
51
+
52
+ Or even this:
53
+
54
+ Then /^I should see the login page$/ do
55
+ should_see [
56
+ "Welcome",
57
+ "Thanks for visiting",
58
+ "Login"
59
+ ]
60
+ end
61
+
62
+ Many of the provided methods are similar to their counterparts in the
63
+ Cucumber-Rails generated step definitions. Following links, filling in fields,
64
+ and pressing buttons can all be easily done with Ruby code instead of nested
65
+ steps. Thus this:
66
+
67
+ When %{I follow "Login"}
68
+ And %{I fill in "Username" with "skroob"}
69
+ And %{I fill in "Password" with "12345"}
70
+ And %{I press "Log me in"}
71
+
72
+ translates to this:
73
+
74
+ follow "Login"
75
+ fill_in_fields \
76
+ "Username" => "skroob",
77
+ "Password" => "12345"
78
+ press "Log me in"
79
+
80
+ Several methods also accept keywords to define the scope of an action. For
81
+ instance, if you want to look within an element with id="greeting"`, do:
82
+
83
+ should_see "Welcome", :within => "#greeting"
84
+
85
+ At the moment, the `:within` keyword is the only accepted scope; the locator
86
+ you pass to this should be in whatever format your `Capybara.default_selector`
87
+ is set to. Other keywords like `:before` or `:after` may be supported in future
88
+ revisions.
89
+
90
+
91
+ Development
92
+ -----------
93
+
94
+ If you'd like to hack on Kelp, first fork the {http://github.com/wapcaplet/kelp
95
+ repository}, then clone your fork:
96
+
97
+ $ git clone git://github.com/your_username/kelp.git
98
+
99
+ Install [bundler](http://gembundler.com/):
100
+
101
+ $ gem install bundler
102
+
103
+ Then install Kelp's dependencies (specified in `Gemfile`):
104
+
105
+ $ cd /path/to/kelp
106
+ $ bundle install
107
+
108
+ It's a good idea to use [RVM](http://rvm.beginrescueend.com/)
109
+ with a new gemset to keep things tidy.
110
+
111
+ If you make changes that you'd like to share, push them into your Kelp fork,
112
+ then [submit a pull request](http://github.com/wapcaplet/kelp/pulls).
113
+
114
+
115
+ Testing
116
+ -------
117
+
118
+ Kelp comes with a `Rakefile`, so you can run the RSpec tests like so:
119
+
120
+ $ rake spec
121
+
122
+ You can also generate an [rcov](http://eigenclass.org/hiki.rb?rcov)
123
+ coverage report via:
124
+
125
+ $ rake rcov
126
+
127
+ This will write an HTML report to `coverage/index.html`.
128
+
129
+
130
+ Future plans
131
+ ------------
132
+
133
+ * Write Cucumber integration tests
134
+ * Support other stuff besides Capybara
135
+ * Turn the project into a proper Rails plugin, with generators
7
136
 
8
- [Read the docs](http://kelp.rtfd.org/) online or view the raw documentation in
9
- the `docs` folder.
10
137
 
11
138
  Copyright
12
139
  ---------
13
140
 
14
- Copyright (c) 2010 Eric Pierce, released under the MIT license.
15
- See MIT-LICENSE for details.
141
+ The MIT License
142
+
143
+ Copyright (c) 2010 Eric Pierce
144
+
145
+ Permission is hereby granted, free of charge, to any person obtaining
146
+ a copy of this software and associated documentation files (the
147
+ "Software"), to deal in the Software without restriction, including
148
+ without limitation the rights to use, copy, modify, merge, publish,
149
+ distribute, sublicense, and/or sell copies of the Software, and to
150
+ permit persons to whom the Software is furnished to do so, subject to
151
+ the following conditions:
152
+
153
+ The above copyright notice and this permission notice shall be
154
+ included in all copies or substantial portions of the Software.
155
+
156
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
157
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
158
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
159
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
160
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
161
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
162
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
16
163
 
data/kelp.gemspec CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  Gem::Specification.new do |s|
4
4
  s.name = "kelp"
5
- s.version = "0.1.1"
5
+ s.version = "0.1.2"
6
6
  s.summary = "Cucumber helper methods"
7
7
  s.description = <<-EOS
8
8
  Kelp is a collection of helper methods for Cucumber to ease the process of
data/lib/kelp.rb CHANGED
@@ -1 +1,8 @@
1
- require 'kelp/capybara'
1
+ require 'kelp/attribute'
2
+ require 'kelp/checkbox'
3
+ require 'kelp/dropdown'
4
+ require 'kelp/field'
5
+ require 'kelp/navigation'
6
+ require 'kelp/scoping'
7
+ require 'kelp/visibility'
8
+
@@ -0,0 +1,31 @@
1
+ module Kelp
2
+ # This module defines helper methods for verifying attributes of HTML
3
+ # elements on a web page.
4
+ #
5
+ module Attribute
6
+ # Verify that the HTML element with the given ID exists, and is disabled (has
7
+ # the `disabled` attribute).
8
+ #
9
+ # @param [String] element_id
10
+ # HTML `id` attribute of the element that should be disabled
11
+ #
12
+ def should_be_disabled(element_id)
13
+ page.should have_xpath("//*[@id='#{element_id}']")
14
+ page.should have_xpath("//*[@id='#{element_id}' and @disabled]")
15
+ end
16
+
17
+
18
+ # Verify that the HTML element with the given ID exists, and is enabled (does
19
+ # not have the `disabled` attribute).
20
+ #
21
+ # @param [String] element_id
22
+ # HTML `id` attribute of the element that should be enabled
23
+ #
24
+ def should_be_enabled(element_id)
25
+ page.should have_xpath("//*[@id='#{element_id}']")
26
+ page.should have_no_xpath("//*[@id='#{element_id}' and @disabled]")
27
+ end
28
+
29
+ end
30
+
31
+ end
@@ -0,0 +1,31 @@
1
+ require 'kelp/helper'
2
+ require 'kelp/scoping'
3
+
4
+ module Kelp
5
+ module Checkbox
6
+ include Scoping
7
+ include Helper
8
+
9
+ def checkbox_should_be_checked(checkbox, scope={})
10
+ in_scope(scope) do
11
+ field_checked = find_field(checkbox)['checked']
12
+ if field_checked.respond_to? :should
13
+ field_checked.should be_true
14
+ else
15
+ assert field_checked
16
+ end
17
+ end
18
+ end
19
+
20
+ def checkbox_should_not_be_checked(checkbox, scope={})
21
+ in_scope(scope) do
22
+ field_checked = find_field(checkbox)['checked']
23
+ if field_checked.respond_to? :should
24
+ field_checked.should be_false
25
+ else
26
+ assert !field_checked
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,109 @@
1
+ require 'kelp/scoping'
2
+ require 'kelp/helper'
3
+
4
+ module Kelp
5
+ # This module defines methods for working with dropdown fields in a web form,
6
+ # including verifying their visible content as well as the `value` attribute
7
+ # of selected options.
8
+ #
9
+ module Dropdown
10
+ include Scoping
11
+ include Helper
12
+
13
+ # Verify that the selected option in a dropdown has the given
14
+ # value. Note that this is the *visible* content of the dropdown
15
+ # (the content of the <option> element), rather than the
16
+ # 'value' attribute of the option.
17
+ #
18
+ # @param [String] dropdown
19
+ # Capybara locator for the dropdown (the `select` element)
20
+ # @param [String] value
21
+ # Value you expect to see as the currently-selected option
22
+ #
23
+ def dropdown_should_equal(dropdown, value)
24
+ field = nice_find_field(dropdown)
25
+ # See if there's a 'selected' option
26
+ begin
27
+ selected = field.find(:xpath, ".//option[@selected='selected']")
28
+ # If not, find the option matching the first field value
29
+ rescue Capybara::ElementNotFound
30
+ selected = field.find(:xpath, ".//option[@value='#{field.value.first}']")
31
+ end
32
+ selected.text.should =~ /#{value}/
33
+ end
34
+
35
+
36
+ # Verify that a given dropdown includes all of the given strings.
37
+ # This looks for the visible values in the dropdown, *not* the 'value'
38
+ # attribute of each option.
39
+ #
40
+ # @example
41
+ # dropdown_should_include "Weekday", "Monday"
42
+ # dropdown_should_include "Size", ["Small", "Medium", "Large"]
43
+ #
44
+ # @param [String] dropdown
45
+ # Capybara locator for the dropdown (the `select` element)
46
+ # @param [Array] values
47
+ # Visible contents you expect to be able to select from the dropdown
48
+ # @param [Hash] scope
49
+ # Scoping keywords as understood by {#in_scope}
50
+ #
51
+ def dropdown_should_include(dropdown, values, scope={})
52
+ in_scope(scope) do
53
+ # If values is a String, convert it to an Array
54
+ values = [values] if values.class == String
55
+
56
+ field = nice_find_field(dropdown)
57
+ # Look for each value
58
+ values.each do |value|
59
+ page.should have_xpath(".//option[text()='#{value}']")
60
+ end
61
+ end
62
+ end
63
+
64
+
65
+ # Verify that a given dropdown does not include any of the given strings.
66
+ # This looks for the visible values in the dropdown, *not* the 'value'
67
+ # attribute of each option.
68
+ #
69
+ # @param [String] dropdown
70
+ # Capybara locator for the dropdown (the `select` element)
71
+ # @param [Array] values
72
+ # Visible contents you do not want to see in the dropdown
73
+ # @param [Hash] scope
74
+ # Scoping keywords as understood by {#in_scope}
75
+ #
76
+ # @since 0.1.2
77
+ #
78
+ def dropdown_should_not_include(dropdown, values, scope={})
79
+ in_scope(scope) do
80
+ # If values is a String, convert it to an Array
81
+ values = [values] if values.class == String
82
+
83
+ field = nice_find_field(dropdown)
84
+ # Look for each value
85
+ values.each do |value|
86
+ page.should have_no_xpath(".//option[text()='#{value}']")
87
+ end
88
+ end
89
+ end
90
+
91
+
92
+ # Verify that a dropdown currently has the option with the given `value`
93
+ # attribute selected. Note that this differs from {#dropdown_should_equal},
94
+ # in that it looks at the actual `value` attribute of the selected option,
95
+ # rather than its visible contents.
96
+ #
97
+ # @param [String] dropdown
98
+ # Capybara locator for the dropdown (the `select` element)
99
+ # @param [String] value
100
+ # Expected `value` attribute of the selected `option`
101
+ #
102
+ def dropdown_value_should_equal(dropdown, value)
103
+ # FIXME: When this returns False, does that fail the step?
104
+ field = find_field(dropdown)
105
+ field.value.should include(value)
106
+ end
107
+
108
+ end
109
+ end
data/lib/kelp/field.rb ADDED
@@ -0,0 +1,159 @@
1
+ require 'kelp/helper'
2
+ require 'kelp/scoping'
3
+
4
+ module Kelp
5
+ # This module defines helper methods for filling in and verifying the content
6
+ # of fields in a web form.
7
+ #
8
+ module Field
9
+ include Scoping
10
+ include Helper
11
+
12
+ # Fill in multiple fields according to values in a `Hash`.
13
+ #
14
+ # @example
15
+ # fill_in_fields "First name" => "Otto", "Last name" => "Scratchansniff"
16
+ # fill_in_fields "phone" => "303-224-7428", :within => "#home"
17
+ #
18
+ # @param [Hash] fields
19
+ # "field" => "value" for each field to fill in
20
+ # @param [Hash] scope
21
+ # Scoping keywords as understood by {#in_scope}
22
+ #
23
+ def fill_in_fields(fields, scope={})
24
+ in_scope(scope) do
25
+ fields.each do |name, value|
26
+ fill_in name, :with => value
27
+ end
28
+ end
29
+ end
30
+
31
+
32
+ # Fill in a single field within the scope of a given selector.
33
+ def fill_in_field(field, value, scope={})
34
+ fields = {field => value}
35
+ fill_in_fields fields, scope
36
+ end
37
+
38
+
39
+ # Fill in multiple fields within the scope of a given selector.
40
+ # Alias for:
41
+ #
42
+ # fill_in_fields fields, :within => selector
43
+ #
44
+ def fill_in_fields_within(selector, fields)
45
+ fill_in_fields fields, :within => selector
46
+ end
47
+
48
+
49
+ # Fill in a single fields within the scope of a given selector.
50
+ # Alias for:
51
+ #
52
+ # fill_in_field field, value, :within => selector
53
+ #
54
+ def fill_in_field_within(selector, field, value)
55
+ fill_in_field field, value, :within => selector
56
+ end
57
+
58
+
59
+ # Verify that the given field is empty or nil.
60
+ def field_should_be_empty(field)
61
+ _field = nice_find_field(field)
62
+ if _field.nil? || _field.value.nil?
63
+ return true
64
+ else
65
+ raise RuntimeError, "Expected field '#{field}' to be empty, but value is '#{_field.value}'"
66
+ end
67
+ end
68
+
69
+
70
+ # Verify that the given field contains the given value.
71
+ #
72
+ # @param [String] field
73
+ # Capybara locator for the field (name, id, or label text)
74
+ # @param [String] value
75
+ # Value you expect to see in the text field
76
+ #
77
+ def field_should_contain(field, value, scope={})
78
+ in_scope(scope) do
79
+ # TODO: Make this work equally well with any kind of field
80
+ # (text, single-select, multi-select)
81
+ field = find_field(field)
82
+ field_value = (field.tag_name == 'textarea') ? field.text : field.value
83
+ # If field value is an Array, take the first item
84
+ if field_value.class == Array
85
+ field_value = field_value.first
86
+ end
87
+ # Escape any problematic characters in the expected value
88
+ value = Regexp.escape(value)
89
+ # Match actual to expected
90
+ if field_value.respond_to? :should
91
+ field_value.should =~ /#{value}/
92
+ else
93
+ assert_match(/#{value}/, field_value)
94
+ end
95
+ end
96
+ end
97
+
98
+
99
+ def field_should_not_contain(field, value, scope={})
100
+ raise "Not implemented yet"
101
+ #with_scope(parent) do
102
+ #field = find_field(field)
103
+ #field_value = (field.tag_name == 'textarea') ? field.text : field.value
104
+ #if field_value.respond_to? :should_not
105
+ #field_value.should_not =~ /#{value}/
106
+ #else
107
+ #assert_no_match(/#{value}/, field_value)
108
+ #end
109
+ #end
110
+ end
111
+
112
+
113
+ # Verify the values of multiple fields given as a Hash.
114
+ #
115
+ # @param [Hash] field_values
116
+ # "field" => "value" for each field you want to verify
117
+ # @param [Hash] scope
118
+ # Scoping keywords as understood by {#in_scope}
119
+ #
120
+ def fields_should_contain(field_values, scope={})
121
+ in_scope(scope) do
122
+ field_values.each do |field, value|
123
+ _field = find_field(field)
124
+ # For nil/empty, check for nil field or nil value
125
+ if value.nil? or value.empty?
126
+ field_should_be_empty(field)
127
+ # If field is a dropdown
128
+ elsif _field.tag_name == 'select'
129
+ dropdown_should_equal(field, value)
130
+ # Otherwise treat as a text field
131
+ else
132
+ field_should_contain(field, value)
133
+ end
134
+ end
135
+ end
136
+ end
137
+
138
+
139
+ # Verify a single field within the scope of a given selector.
140
+ # Alias for:
141
+ #
142
+ # field_should_contain field, value, :within => selector
143
+ #
144
+ def field_should_contain_within(selector, field, value)
145
+ field_should_contain field, value, :within => selector
146
+ end
147
+
148
+
149
+ # Verify fields within the scope of a given selector.
150
+ # Alias for:
151
+ #
152
+ # fields_should_contain field_values, :within => selector
153
+ #
154
+ def fields_should_contain_within(selector, field_values)
155
+ fields_should_contain field_values, :within => selector
156
+ end
157
+
158
+ end
159
+ end