bbc-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 (107) hide show
  1. data/History.txt +325 -0
  2. data/License.txt +22 -0
  3. data/README.md +815 -0
  4. data/lib/capybara.rb +368 -0
  5. data/lib/capybara/cucumber.rb +25 -0
  6. data/lib/capybara/driver/base.rb +64 -0
  7. data/lib/capybara/driver/node.rb +74 -0
  8. data/lib/capybara/dsl.rb +50 -0
  9. data/lib/capybara/node/actions.rb +146 -0
  10. data/lib/capybara/node/base.rb +63 -0
  11. data/lib/capybara/node/document.rb +25 -0
  12. data/lib/capybara/node/element.rb +201 -0
  13. data/lib/capybara/node/finders.rb +154 -0
  14. data/lib/capybara/node/matchers.rb +442 -0
  15. data/lib/capybara/node/simple.rb +132 -0
  16. data/lib/capybara/query.rb +63 -0
  17. data/lib/capybara/rack_test/browser.rb +126 -0
  18. data/lib/capybara/rack_test/driver.rb +80 -0
  19. data/lib/capybara/rack_test/form.rb +80 -0
  20. data/lib/capybara/rack_test/node.rb +121 -0
  21. data/lib/capybara/rails.rb +17 -0
  22. data/lib/capybara/rspec.rb +26 -0
  23. data/lib/capybara/rspec/features.rb +22 -0
  24. data/lib/capybara/rspec/matchers.rb +152 -0
  25. data/lib/capybara/selector.rb +156 -0
  26. data/lib/capybara/selenium/driver.rb +169 -0
  27. data/lib/capybara/selenium/node.rb +91 -0
  28. data/lib/capybara/server.rb +87 -0
  29. data/lib/capybara/session.rb +322 -0
  30. data/lib/capybara/spec/driver.rb +329 -0
  31. data/lib/capybara/spec/fixtures/capybara.jpg +3 -0
  32. data/lib/capybara/spec/fixtures/test_file.txt +1 -0
  33. data/lib/capybara/spec/public/jquery-ui.js +791 -0
  34. data/lib/capybara/spec/public/jquery.js +9046 -0
  35. data/lib/capybara/spec/public/test.js +43 -0
  36. data/lib/capybara/spec/session.rb +148 -0
  37. data/lib/capybara/spec/session/all_spec.rb +78 -0
  38. data/lib/capybara/spec/session/attach_file_spec.rb +76 -0
  39. data/lib/capybara/spec/session/check_spec.rb +68 -0
  40. data/lib/capybara/spec/session/choose_spec.rb +29 -0
  41. data/lib/capybara/spec/session/click_button_spec.rb +305 -0
  42. data/lib/capybara/spec/session/click_link_or_button_spec.rb +37 -0
  43. data/lib/capybara/spec/session/click_link_spec.rb +120 -0
  44. data/lib/capybara/spec/session/current_url_spec.rb +83 -0
  45. data/lib/capybara/spec/session/fill_in_spec.rb +127 -0
  46. data/lib/capybara/spec/session/find_button_spec.rb +18 -0
  47. data/lib/capybara/spec/session/find_by_id_spec.rb +18 -0
  48. data/lib/capybara/spec/session/find_field_spec.rb +26 -0
  49. data/lib/capybara/spec/session/find_link_spec.rb +19 -0
  50. data/lib/capybara/spec/session/find_spec.rb +168 -0
  51. data/lib/capybara/spec/session/first_spec.rb +105 -0
  52. data/lib/capybara/spec/session/has_button_spec.rb +32 -0
  53. data/lib/capybara/spec/session/has_css_spec.rb +243 -0
  54. data/lib/capybara/spec/session/has_field_spec.rb +192 -0
  55. data/lib/capybara/spec/session/has_link_spec.rb +37 -0
  56. data/lib/capybara/spec/session/has_select_spec.rb +129 -0
  57. data/lib/capybara/spec/session/has_selector_spec.rb +129 -0
  58. data/lib/capybara/spec/session/has_table_spec.rb +34 -0
  59. data/lib/capybara/spec/session/has_text_spec.rb +138 -0
  60. data/lib/capybara/spec/session/has_xpath_spec.rb +123 -0
  61. data/lib/capybara/spec/session/headers.rb +19 -0
  62. data/lib/capybara/spec/session/javascript.rb +312 -0
  63. data/lib/capybara/spec/session/response_code.rb +19 -0
  64. data/lib/capybara/spec/session/select_spec.rb +119 -0
  65. data/lib/capybara/spec/session/text_spec.rb +24 -0
  66. data/lib/capybara/spec/session/uncheck_spec.rb +21 -0
  67. data/lib/capybara/spec/session/unselect_spec.rb +67 -0
  68. data/lib/capybara/spec/session/within_spec.rb +178 -0
  69. data/lib/capybara/spec/test_app.rb +156 -0
  70. data/lib/capybara/spec/views/buttons.erb +4 -0
  71. data/lib/capybara/spec/views/fieldsets.erb +29 -0
  72. data/lib/capybara/spec/views/form.erb +366 -0
  73. data/lib/capybara/spec/views/frame_one.erb +8 -0
  74. data/lib/capybara/spec/views/frame_two.erb +8 -0
  75. data/lib/capybara/spec/views/header_links.erb +7 -0
  76. data/lib/capybara/spec/views/host_links.erb +12 -0
  77. data/lib/capybara/spec/views/popup_one.erb +8 -0
  78. data/lib/capybara/spec/views/popup_two.erb +8 -0
  79. data/lib/capybara/spec/views/postback.erb +13 -0
  80. data/lib/capybara/spec/views/tables.erb +62 -0
  81. data/lib/capybara/spec/views/with_html.erb +75 -0
  82. data/lib/capybara/spec/views/with_html_entities.erb +1 -0
  83. data/lib/capybara/spec/views/with_js.erb +53 -0
  84. data/lib/capybara/spec/views/with_scope.erb +36 -0
  85. data/lib/capybara/spec/views/with_simple_html.erb +1 -0
  86. data/lib/capybara/spec/views/within_frames.erb +10 -0
  87. data/lib/capybara/spec/views/within_popups.erb +25 -0
  88. data/lib/capybara/util/save_and_open_page.rb +45 -0
  89. data/lib/capybara/util/timeout.rb +27 -0
  90. data/lib/capybara/version.rb +3 -0
  91. data/spec/basic_node_spec.rb +89 -0
  92. data/spec/capybara_spec.rb +46 -0
  93. data/spec/driver/rack_test_driver_spec.rb +90 -0
  94. data/spec/driver/selenium_driver_spec.rb +55 -0
  95. data/spec/dsl_spec.rb +255 -0
  96. data/spec/fixtures/selenium_driver_rspec_failure.rb +8 -0
  97. data/spec/fixtures/selenium_driver_rspec_success.rb +8 -0
  98. data/spec/rspec/features_spec.rb +43 -0
  99. data/spec/rspec/matchers_spec.rb +564 -0
  100. data/spec/rspec_spec.rb +51 -0
  101. data/spec/save_and_open_page_spec.rb +155 -0
  102. data/spec/server_spec.rb +74 -0
  103. data/spec/session/rack_test_session_spec.rb +61 -0
  104. data/spec/session/selenium_session_spec.rb +26 -0
  105. data/spec/spec_helper.rb +31 -0
  106. data/spec/timeout_spec.rb +28 -0
  107. metadata +297 -0
@@ -0,0 +1,74 @@
1
+ module Capybara
2
+ module Driver
3
+ class Node
4
+ attr_reader :driver, :native
5
+
6
+ def initialize(driver, native)
7
+ @driver = driver
8
+ @native = native
9
+ end
10
+
11
+ def text
12
+ raise NotImplementedError
13
+ end
14
+
15
+ def [](name)
16
+ raise NotImplementedError
17
+ end
18
+
19
+ def value
20
+ raise NotImplementedError
21
+ end
22
+
23
+ def set(value)
24
+ raise NotImplementedError
25
+ end
26
+
27
+ def select_option
28
+ raise NotImplementedError
29
+ end
30
+
31
+ def unselect_option
32
+ raise NotImplementedError
33
+ end
34
+
35
+ def click
36
+ raise NotImplementedError
37
+ end
38
+
39
+ def drag_to(element)
40
+ raise NotImplementedError
41
+ end
42
+
43
+ def tag_name
44
+ raise NotImplementedError
45
+ end
46
+
47
+ def visible?
48
+ raise NotImplementedError
49
+ end
50
+
51
+ def checked?
52
+ raise NotImplementedError
53
+ end
54
+
55
+ def selected?
56
+ raise NotImplementedError
57
+ end
58
+
59
+ def path
60
+ raise NotSupportedByDriverError
61
+ end
62
+
63
+ def trigger(event)
64
+ raise NotSupportedByDriverError
65
+ end
66
+
67
+ def inspect
68
+ %(#<Capybara::Driver::Node tag="#{tag_name}" path="#{path}">)
69
+ rescue NotSupportedByDriverError
70
+ %(#<Capybara::Driver::Node tag="#{tag_name}">)
71
+ end
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,50 @@
1
+ require 'capybara'
2
+
3
+ module Capybara
4
+ module DSL
5
+
6
+ ##
7
+ #
8
+ # Shortcut to working in a different session.
9
+ #
10
+ def using_session(name, &block)
11
+ Capybara.using_session(name, &block)
12
+ end
13
+
14
+ ##
15
+ #
16
+ # Shortcut to using a different wait time.
17
+ #
18
+ def using_wait_time(seconds, &block)
19
+ Capybara.using_wait_time(seconds, &block)
20
+ end
21
+
22
+ ##
23
+ #
24
+ # Shortcut to accessing the current session.
25
+ #
26
+ # class MyClass
27
+ # include Capybara::DSL
28
+ #
29
+ # def has_header?
30
+ # page.has_css?('h1')
31
+ # end
32
+ # end
33
+ #
34
+ # @return [Capybara::Session] The current session object
35
+ #
36
+ def page
37
+ Capybara.current_session
38
+ end
39
+
40
+ Session::DSL_METHODS.each do |method|
41
+ class_eval <<-RUBY, __FILE__, __LINE__+1
42
+ def #{method}(*args, &block)
43
+ page.#{method}(*args, &block)
44
+ end
45
+ RUBY
46
+ end
47
+ end
48
+
49
+ extend(Capybara::DSL)
50
+ end
@@ -0,0 +1,146 @@
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
+ find(:link_or_button, locator).click
14
+ end
15
+ alias_method :click_on, :click_link_or_button
16
+
17
+ ##
18
+ #
19
+ # Finds a link by id or text and clicks it. Also looks at image
20
+ # alt text inside the link.
21
+ #
22
+ # @param [String] locator Text, id or text of link
23
+ #
24
+ def click_link(locator)
25
+ find(:link, locator).click
26
+ end
27
+
28
+ ##
29
+ #
30
+ # Finds a button by id, text or value and clicks it.
31
+ #
32
+ # @param [String] locator Text, id or value of button
33
+ #
34
+ def click_button(locator)
35
+ find(:button, locator).click
36
+ end
37
+
38
+ ##
39
+ #
40
+ # Locate a text field or text area and fill it in with the given text
41
+ # The field can be found via its name, id or label text.
42
+ #
43
+ # page.fill_in 'Name', :with => 'Bob'
44
+ #
45
+ # @param [String] locator Which field to fill in
46
+ # @param [Hash{:with => String}] The value to fill in
47
+ #
48
+ def fill_in(locator, options={})
49
+ raise "Must pass a hash containing 'with'" if not options.is_a?(Hash) or not options.has_key?(:with)
50
+ find(:fillable_field, locator).set(options[:with])
51
+ end
52
+
53
+ ##
54
+ #
55
+ # Find a radio button and mark it as checked. The radio button can be found
56
+ # via name, id or label text.
57
+ #
58
+ # page.choose('Male')
59
+ #
60
+ # @param [String] locator Which radio button to choose
61
+ #
62
+ def choose(locator)
63
+ find(:radio_button, locator).set(true)
64
+ end
65
+
66
+ ##
67
+ #
68
+ # Find a check box and mark it as checked. The check box can be found
69
+ # via name, id or label text.
70
+ #
71
+ # page.check('German')
72
+ #
73
+ # @param [String] locator Which check box to check
74
+ #
75
+ def check(locator)
76
+ find(:checkbox, locator).set(true)
77
+ end
78
+
79
+ ##
80
+ #
81
+ # Find a check box and mark uncheck it. The check box can be found
82
+ # via name, id or label text.
83
+ #
84
+ # page.uncheck('German')
85
+ #
86
+ # @param [String] locator Which check box to uncheck
87
+ #
88
+ def uncheck(locator)
89
+ find(:checkbox, locator).set(false)
90
+ end
91
+
92
+ ##
93
+ #
94
+ # Find a select box on the page and select a particular option from it. If the select
95
+ # box is a multiple select, +select+ can be called multiple times to select more than
96
+ # one option. The select box can be found via its name, id or label text.
97
+ #
98
+ # page.select 'March', :from => 'Month'
99
+ #
100
+ # @param [String] value Which option to select
101
+ # @param [Hash{:from => String}] The id, name or label of the select box
102
+ #
103
+ def select(value, options={})
104
+ if options.has_key?(:from)
105
+ find(:select, options[:from]).find(:option, value).select_option
106
+ else
107
+ find(:option, value).select_option
108
+ end
109
+ end
110
+
111
+ ##
112
+ #
113
+ # Find a select box on the page and unselect a particular option from it. If the select
114
+ # box is a multiple select, +unselect+ can be called multiple times to unselect more than
115
+ # one option. The select box can be found via its name, id or label text.
116
+ #
117
+ # page.unselect 'March', :from => 'Month'
118
+ #
119
+ # @param [String] value Which option to unselect
120
+ # @param [Hash{:from => String}] The id, name or label of the select box
121
+ #
122
+ def unselect(value, options={})
123
+ if options.has_key?(:from)
124
+ find(:select, options[:from]).find(:option, value).unselect_option
125
+ else
126
+ find(:option, value).unselect_option
127
+ end
128
+ end
129
+
130
+ ##
131
+ #
132
+ # Find a file field on the page and attach a file given its path. The file field can
133
+ # be found via its name, id or label text.
134
+ #
135
+ # page.attach_file(locator, '/path/to/file.png')
136
+ #
137
+ # @param [String] locator Which field to attach the file to
138
+ # @param [String] path The path of the file that will be attached
139
+ #
140
+ def attach_file(locator, path)
141
+ raise Capybara::FileNotFound, "cannot attach file, #{path} does not exist" unless File.exist?(path.to_s)
142
+ find(:file_field, locator).set(path)
143
+ end
144
+ end
145
+ end
146
+ 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