bbc-capybara 1.1.2

Sign up to get free protection for your applications and to get access to all the features.
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