nimboids-capybara 1.1.2

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 (105) hide show
  1. data/History.txt +289 -0
  2. data/README.rdoc +722 -0
  3. data/lib/capybara.rb +252 -0
  4. data/lib/capybara/cucumber.rb +28 -0
  5. data/lib/capybara/driver/base.rb +64 -0
  6. data/lib/capybara/driver/node.rb +74 -0
  7. data/lib/capybara/dsl.rb +168 -0
  8. data/lib/capybara/node/actions.rb +162 -0
  9. data/lib/capybara/node/base.rb +63 -0
  10. data/lib/capybara/node/document.rb +25 -0
  11. data/lib/capybara/node/element.rb +201 -0
  12. data/lib/capybara/node/finders.rb +197 -0
  13. data/lib/capybara/node/matchers.rb +417 -0
  14. data/lib/capybara/node/simple.rb +132 -0
  15. data/lib/capybara/rack_test/browser.rb +121 -0
  16. data/lib/capybara/rack_test/driver.rb +80 -0
  17. data/lib/capybara/rack_test/form.rb +80 -0
  18. data/lib/capybara/rack_test/node.rb +105 -0
  19. data/lib/capybara/rails.rb +17 -0
  20. data/lib/capybara/rspec.rb +26 -0
  21. data/lib/capybara/rspec/features.rb +22 -0
  22. data/lib/capybara/rspec/matchers.rb +154 -0
  23. data/lib/capybara/selector.rb +89 -0
  24. data/lib/capybara/selenium/driver.rb +163 -0
  25. data/lib/capybara/selenium/node.rb +91 -0
  26. data/lib/capybara/server.rb +90 -0
  27. data/lib/capybara/session.rb +321 -0
  28. data/lib/capybara/spec/driver.rb +301 -0
  29. data/lib/capybara/spec/fixtures/capybara.jpg +3 -0
  30. data/lib/capybara/spec/fixtures/test_file.txt +1 -0
  31. data/lib/capybara/spec/public/test.js +43 -0
  32. data/lib/capybara/spec/session.rb +154 -0
  33. data/lib/capybara/spec/session/all_spec.rb +78 -0
  34. data/lib/capybara/spec/session/attach_file_spec.rb +73 -0
  35. data/lib/capybara/spec/session/check_spec.rb +65 -0
  36. data/lib/capybara/spec/session/choose_spec.rb +26 -0
  37. data/lib/capybara/spec/session/click_button_spec.rb +304 -0
  38. data/lib/capybara/spec/session/click_link_or_button_spec.rb +36 -0
  39. data/lib/capybara/spec/session/click_link_spec.rb +119 -0
  40. data/lib/capybara/spec/session/current_host_spec.rb +68 -0
  41. data/lib/capybara/spec/session/current_url_spec.rb +15 -0
  42. data/lib/capybara/spec/session/fill_in_spec.rb +125 -0
  43. data/lib/capybara/spec/session/find_button_spec.rb +18 -0
  44. data/lib/capybara/spec/session/find_by_id_spec.rb +18 -0
  45. data/lib/capybara/spec/session/find_field_spec.rb +26 -0
  46. data/lib/capybara/spec/session/find_link_spec.rb +19 -0
  47. data/lib/capybara/spec/session/find_spec.rb +149 -0
  48. data/lib/capybara/spec/session/first_spec.rb +105 -0
  49. data/lib/capybara/spec/session/has_button_spec.rb +32 -0
  50. data/lib/capybara/spec/session/has_content_spec.rb +106 -0
  51. data/lib/capybara/spec/session/has_css_spec.rb +243 -0
  52. data/lib/capybara/spec/session/has_field_spec.rb +192 -0
  53. data/lib/capybara/spec/session/has_link_spec.rb +37 -0
  54. data/lib/capybara/spec/session/has_select_spec.rb +129 -0
  55. data/lib/capybara/spec/session/has_selector_spec.rb +129 -0
  56. data/lib/capybara/spec/session/has_table_spec.rb +96 -0
  57. data/lib/capybara/spec/session/has_xpath_spec.rb +123 -0
  58. data/lib/capybara/spec/session/headers.rb +19 -0
  59. data/lib/capybara/spec/session/javascript.rb +289 -0
  60. data/lib/capybara/spec/session/response_code.rb +19 -0
  61. data/lib/capybara/spec/session/select_spec.rb +113 -0
  62. data/lib/capybara/spec/session/text_spec.rb +19 -0
  63. data/lib/capybara/spec/session/uncheck_spec.rb +21 -0
  64. data/lib/capybara/spec/session/unselect_spec.rb +61 -0
  65. data/lib/capybara/spec/session/within_spec.rb +178 -0
  66. data/lib/capybara/spec/test_app.rb +142 -0
  67. data/lib/capybara/spec/views/buttons.erb +4 -0
  68. data/lib/capybara/spec/views/fieldsets.erb +29 -0
  69. data/lib/capybara/spec/views/form.erb +365 -0
  70. data/lib/capybara/spec/views/frame_one.erb +8 -0
  71. data/lib/capybara/spec/views/frame_two.erb +8 -0
  72. data/lib/capybara/spec/views/header_links.erb +7 -0
  73. data/lib/capybara/spec/views/host_links.erb +12 -0
  74. data/lib/capybara/spec/views/popup_one.erb +8 -0
  75. data/lib/capybara/spec/views/popup_two.erb +8 -0
  76. data/lib/capybara/spec/views/postback.erb +13 -0
  77. data/lib/capybara/spec/views/tables.erb +122 -0
  78. data/lib/capybara/spec/views/with_html.erb +78 -0
  79. data/lib/capybara/spec/views/with_html_entities.erb +1 -0
  80. data/lib/capybara/spec/views/with_js.erb +48 -0
  81. data/lib/capybara/spec/views/with_scope.erb +36 -0
  82. data/lib/capybara/spec/views/with_simple_html.erb +1 -0
  83. data/lib/capybara/spec/views/within_frames.erb +10 -0
  84. data/lib/capybara/spec/views/within_popups.erb +25 -0
  85. data/lib/capybara/util/save_and_open_page.rb +44 -0
  86. data/lib/capybara/util/timeout.rb +27 -0
  87. data/lib/capybara/version.rb +3 -0
  88. data/spec/basic_node_spec.rb +77 -0
  89. data/spec/capybara_spec.rb +46 -0
  90. data/spec/driver/rack_test_driver_spec.rb +89 -0
  91. data/spec/driver/selenium_driver_spec.rb +50 -0
  92. data/spec/dsl_spec.rb +253 -0
  93. data/spec/fixtures/selenium_driver_rspec_failure.rb +8 -0
  94. data/spec/fixtures/selenium_driver_rspec_success.rb +8 -0
  95. data/spec/rspec/features_spec.rb +45 -0
  96. data/spec/rspec/matchers_spec.rb +495 -0
  97. data/spec/rspec_spec.rb +53 -0
  98. data/spec/save_and_open_page_spec.rb +155 -0
  99. data/spec/server_spec.rb +89 -0
  100. data/spec/session/rack_test_session_spec.rb +55 -0
  101. data/spec/session/selenium_session_spec.rb +26 -0
  102. data/spec/spec_helper.rb +30 -0
  103. data/spec/string_spec.rb +77 -0
  104. data/spec/timeout_spec.rb +28 -0
  105. metadata +346 -0
@@ -0,0 +1,162 @@
1
+ module Capybara
2
+ module Node
3
+ module Actions
4
+
5
+ ##
6
+ #
7
+ # Finds a button or link by id, text or value and clicks it. Also looks at image
8
+ # alt text inside the link.
9
+ #
10
+ # @param [String] locator Text, id or value of link or button
11
+ #
12
+ def click_link_or_button(locator)
13
+ msg = "no link or button '#{locator}' found"
14
+ find(:xpath, XPath::HTML.link_or_button(locator), :message => msg).click
15
+ end
16
+ alias_method :click_on, :click_link_or_button
17
+
18
+ ##
19
+ #
20
+ # Finds a link by id or text and clicks it. Also looks at image
21
+ # alt text inside the link.
22
+ #
23
+ # @param [String] locator Text, id or text of link
24
+ #
25
+ def click_link(locator)
26
+ msg = "no link with title, id or text '#{locator}' found"
27
+ find(:xpath, XPath::HTML.link(locator), :message => msg).click
28
+ end
29
+
30
+ ##
31
+ #
32
+ # Finds a button by id, text or value and clicks it.
33
+ #
34
+ # @param [String] locator Text, id or value of button
35
+ #
36
+ def click_button(locator)
37
+ msg = "no button with value or id or text '#{locator}' found"
38
+ find(:xpath, XPath::HTML.button(locator), :message => msg).click
39
+ end
40
+
41
+ ##
42
+ #
43
+ # Locate a text field or text area and fill it in with the given text
44
+ # The field can be found via its name, id or label text.
45
+ #
46
+ # page.fill_in 'Name', :with => 'Bob'
47
+ #
48
+ # @param [String] locator Which field to fill in
49
+ # @param [Hash{:with => String}] The value to fill in
50
+ #
51
+ def fill_in(locator, options={})
52
+ msg = "cannot fill in, no text field, text area or password field with id, name, or label '#{locator}' found"
53
+ raise "Must pass a hash containing 'with'" if not options.is_a?(Hash) or not options.has_key?(:with)
54
+ find(:xpath, XPath::HTML.fillable_field(locator), :message => msg).set(options[:with])
55
+ end
56
+
57
+ ##
58
+ #
59
+ # Find a radio button and mark it as checked. The radio button can be found
60
+ # via name, id or label text.
61
+ #
62
+ # page.choose('Male')
63
+ #
64
+ # @param [String] locator Which radio button to choose
65
+ #
66
+ def choose(locator)
67
+ msg = "cannot choose field, no radio button with id, name, or label '#{locator}' found"
68
+ find(:xpath, XPath::HTML.radio_button(locator), :message => msg).set(true)
69
+ end
70
+
71
+ ##
72
+ #
73
+ # Find a check box and mark it as checked. The check box can be found
74
+ # via name, id or label text.
75
+ #
76
+ # page.check('German')
77
+ #
78
+ # @param [String] locator Which check box to check
79
+ #
80
+ def check(locator)
81
+ msg = "cannot check field, no checkbox with id, name, or label '#{locator}' found"
82
+ find(:xpath, XPath::HTML.checkbox(locator), :message => msg).set(true)
83
+ end
84
+
85
+ ##
86
+ #
87
+ # Find a check box and mark uncheck it. The check box can be found
88
+ # via name, id or label text.
89
+ #
90
+ # page.uncheck('German')
91
+ #
92
+ # @param [String] locator Which check box to uncheck
93
+ #
94
+ def uncheck(locator)
95
+ msg = "cannot uncheck field, no checkbox with id, name, or label '#{locator}' found"
96
+ find(:xpath, XPath::HTML.checkbox(locator), :message => msg).set(false)
97
+ end
98
+
99
+ ##
100
+ #
101
+ # Find a select box on the page and select a particular option from it. If the select
102
+ # box is a multiple select, +select+ can be called multiple times to select more than
103
+ # one option. The select box can be found via its name, id or label text.
104
+ #
105
+ # page.select 'March', :from => 'Month'
106
+ #
107
+ # @param [String] value Which option to select
108
+ # @param [Hash{:from => String}] The id, name or label of the select box
109
+ #
110
+ def select(value, options={})
111
+ if options.has_key?(:from)
112
+ no_select_msg = "cannot select option, no select box with id, name, or label '#{options[:from]}' found"
113
+ no_option_msg = "cannot select option, no option with text '#{value}' in select box '#{options[:from]}'"
114
+ select = find(:xpath, XPath::HTML.select(options[:from]), :message => no_select_msg)
115
+ select.find(:xpath, XPath::HTML.option(value), :message => no_option_msg).select_option
116
+ else
117
+ no_option_msg = "cannot select option, no option with text '#{value}'"
118
+ find(:xpath, XPath::HTML.option(value), :message => no_option_msg).select_option
119
+ end
120
+ end
121
+
122
+ ##
123
+ #
124
+ # Find a select box on the page and unselect a particular option from it. If the select
125
+ # box is a multiple select, +unselect+ can be called multiple times to unselect more than
126
+ # one option. The select box can be found via its name, id or label text.
127
+ #
128
+ # page.unselect 'March', :from => 'Month'
129
+ #
130
+ # @param [String] value Which option to unselect
131
+ # @param [Hash{:from => String}] The id, name or label of the select box
132
+ #
133
+ def unselect(value, options={})
134
+ if options.has_key?(:from)
135
+ no_select_msg = "cannot unselect option, no select box with id, name, or label '#{options[:from]}' found"
136
+ no_option_msg = "cannot unselect option, no option with text '#{value}' in select box '#{options[:from]}'"
137
+ select = find(:xpath, XPath::HTML.select(options[:from]), :message => no_select_msg)
138
+ select.find(:xpath, XPath::HTML.option(value), :message => no_option_msg).unselect_option
139
+ else
140
+ no_option_msg = "cannot unselect option, no option with text '#{value}'"
141
+ find(:xpath, XPath::HTML.option(value), :message => no_option_msg).unselect_option
142
+ end
143
+ end
144
+
145
+ ##
146
+ #
147
+ # Find a file field on the page and attach a file given its path. The file field can
148
+ # be found via its name, id or label text.
149
+ #
150
+ # page.attach_file(locator, '/path/to/file.png')
151
+ #
152
+ # @param [String] locator Which field to attach the file to
153
+ # @param [String] path The path of the file that will be attached
154
+ #
155
+ def attach_file(locator, path)
156
+ raise Capybara::FileNotFound, "cannot attach file, #{path} does not exist" unless File.exist?(path.to_s)
157
+ msg = "cannot attach file, no file field with id, name, or label '#{locator}' found"
158
+ find(:xpath, XPath::HTML.file_field(locator), :message => msg).set(path)
159
+ end
160
+ end
161
+ end
162
+ end
@@ -0,0 +1,63 @@
1
+ module Capybara
2
+ module Node
3
+
4
+ ##
5
+ #
6
+ # A {Capybara::Node::Base} represents either an element on a page through the subclass
7
+ # {Capybara::Node::Element} or a document through {Capybara::Node::Document}.
8
+ #
9
+ # Both types of Node share the same methods, used for interacting with the
10
+ # elements on the page. These methods are divided into three categories,
11
+ # finders, actions and matchers. These are found in the modules
12
+ # {Capybara::Node::Finders}, {Capybara::Node::Actions} and {Capybara::Node::Matchers}
13
+ # respectively.
14
+ #
15
+ # A {Capybara::Session} exposes all methods from {Capybara::Node::Document} directly:
16
+ #
17
+ # session = Capybara::Session.new(:rack_test, my_app)
18
+ # session.visit('/')
19
+ # session.fill_in('Foo', :with => 'Bar') # from Capybara::Node::Actions
20
+ # bar = session.find('#bar') # from Capybara::Node::Finders
21
+ # bar.select('Baz', :from => 'Quox') # from Capybara::Node::Actions
22
+ # session.has_css?('#foobar') # from Capybara::Node::Matchers
23
+ #
24
+ class Base
25
+ attr_reader :session, :base, :parent
26
+
27
+ include Capybara::Node::Finders
28
+ include Capybara::Node::Actions
29
+ include Capybara::Node::Matchers
30
+
31
+ def initialize(session, base)
32
+ @session = session
33
+ @base = base
34
+ end
35
+
36
+ def reload
37
+ self
38
+ end
39
+
40
+ protected
41
+
42
+ def wait_until(seconds=Capybara.default_wait_time)
43
+ start_time = Time.now
44
+
45
+ begin
46
+ yield
47
+ rescue => e
48
+ raise e unless driver.wait?
49
+ raise e unless (driver.respond_to?(:invalid_element_errors) and driver.invalid_element_errors.include?(e.class)) or e.is_a?(Capybara::ElementNotFound)
50
+ raise e if (Time.now - start_time) >= seconds
51
+ sleep(0.05)
52
+ raise Capybara::FrozenInTime, "time appears to be frozen, Capybara does not work with libraries which freeze time, consider using time travelling instead" if Time.now == start_time
53
+ reload if Capybara.automatic_reload
54
+ retry
55
+ end
56
+ end
57
+
58
+ def driver
59
+ session.driver
60
+ end
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,25 @@
1
+ module Capybara
2
+ module Node
3
+
4
+ ##
5
+ #
6
+ # A {Capybara::Document} represents an HTML document. Any operation
7
+ # performed on it will be performed on the entire document.
8
+ #
9
+ # @see Capybara::Node
10
+ #
11
+ class Document < Base
12
+ def inspect
13
+ %(#<Capybara::Document>)
14
+ end
15
+
16
+ ##
17
+ #
18
+ # @return [String] The text of the document
19
+ #
20
+ def text
21
+ find(:xpath, '/html').text
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,201 @@
1
+ module Capybara
2
+ module Node
3
+
4
+ ##
5
+ #
6
+ # A {Capybara::Element} represents a single element on the page. It is possible
7
+ # to interact with the contents of this element the same as with a document:
8
+ #
9
+ # session = Capybara::Session.new(:rack_test, my_app)
10
+ #
11
+ # bar = session.find('#bar') # from Capybara::Node::Finders
12
+ # bar.select('Baz', :from => 'Quox') # from Capybara::Node::Actions
13
+ #
14
+ # {Capybara::Element} also has access to HTML attributes and other properties of the
15
+ # element:
16
+ #
17
+ # bar.value
18
+ # bar.text
19
+ # bar[:title]
20
+ #
21
+ # @see Capybara::Node
22
+ #
23
+ class Element < Base
24
+
25
+ def initialize(session, base, parent, selector)
26
+ super(session, base)
27
+ @parent = parent
28
+ @selector = selector
29
+ end
30
+
31
+ ##
32
+ #
33
+ # @return [Object] The native element from the driver, this allows access to driver specific methods
34
+ #
35
+ def native
36
+ wait_until { base.native }
37
+ end
38
+
39
+ ##
40
+ #
41
+ # @return [String] The text of the element
42
+ #
43
+ def text
44
+ wait_until { base.text }
45
+ end
46
+
47
+ ##
48
+ #
49
+ # Retrieve the given attribute
50
+ #
51
+ # element[:title] # => HTML title attribute
52
+ #
53
+ # @param [Symbol] attribute The attribute to retrieve
54
+ # @return [String] The value of the attribute
55
+ #
56
+ def [](attribute)
57
+ wait_until { base[attribute] }
58
+ end
59
+
60
+ ##
61
+ #
62
+ # @return [String] The value of the form element
63
+ #
64
+ def value
65
+ wait_until { base.value }
66
+ end
67
+
68
+ ##
69
+ #
70
+ # Set the value of the form element to the given value.
71
+ #
72
+ # @param [String] value The new value
73
+ #
74
+ def set(value)
75
+ wait_until { base.set(value) }
76
+ end
77
+
78
+ ##
79
+ #
80
+ # Select this node if is an option element inside a select tag
81
+ #
82
+ def select_option
83
+ wait_until { base.select_option }
84
+ end
85
+
86
+ ##
87
+ #
88
+ # Unselect this node if is an option element inside a multiple select tag
89
+ #
90
+ def unselect_option
91
+ wait_until { base.unselect_option }
92
+ end
93
+
94
+ ##
95
+ #
96
+ # Click the Element
97
+ #
98
+ def click
99
+ wait_until { base.click }
100
+ end
101
+
102
+ ##
103
+ #
104
+ # @return [String] The tag name of the element
105
+ #
106
+ def tag_name
107
+ wait_until { base.tag_name }
108
+ end
109
+
110
+ ##
111
+ #
112
+ # Whether or not the element is visible. Not all drivers support CSS, so
113
+ # the result may be inaccurate.
114
+ #
115
+ # @return [Boolean] Whether the element is visible
116
+ #
117
+ def visible?
118
+ wait_until { base.visible? }
119
+ end
120
+
121
+ ##
122
+ #
123
+ # Whether or not the element is checked.
124
+ #
125
+ # @return [Boolean] Whether the element is checked
126
+ #
127
+ def checked?
128
+ wait_until { base.checked? }
129
+ end
130
+
131
+ ##
132
+ #
133
+ # Whether or not the element is selected.
134
+ #
135
+ # @return [Boolean] Whether the element is selected
136
+ #
137
+ def selected?
138
+ wait_until { base.selected? }
139
+ end
140
+
141
+ ##
142
+ #
143
+ # An XPath expression describing where on the page the element can be found
144
+ #
145
+ # @return [String] An XPath expression
146
+ #
147
+ def path
148
+ wait_until { base.path }
149
+ end
150
+
151
+ ##
152
+ #
153
+ # Trigger any event on the current element, for example mouseover or focus
154
+ # events. Does not work in Selenium.
155
+ #
156
+ # @param [String] event The name of the event to trigger
157
+ #
158
+ def trigger(event)
159
+ wait_until { base.trigger(event) }
160
+ end
161
+
162
+ ##
163
+ #
164
+ # Drag the element to the given other element.
165
+ #
166
+ # source = page.find('#foo')
167
+ # target = page.find('#bar')
168
+ # source.drag_to(target)
169
+ #
170
+ # @param [Capybara::Element] node The element to drag to
171
+ #
172
+ def drag_to(node)
173
+ wait_until { base.drag_to(node.base) }
174
+ end
175
+
176
+ def find(*args)
177
+ wait_until { super }
178
+ end
179
+
180
+ def first(*args)
181
+ wait_until { super }
182
+ end
183
+
184
+ def all(*args)
185
+ wait_until { super }
186
+ end
187
+
188
+ def reload
189
+ reloaded = parent.reload.first(@selector.name, @selector.locator, @selector.options)
190
+ @base = reloaded.base if reloaded
191
+ self
192
+ end
193
+
194
+ def inspect
195
+ %(#<Capybara::Element tag="#{tag_name}" path="#{path}">)
196
+ rescue NotSupportedByDriverError
197
+ %(#<Capybara::Element tag="#{tag_name}">)
198
+ end
199
+ end
200
+ end
201
+ end