capybara 0.1.3 → 0.1.4

Sign up to get free protection for your applications and to get access to all the features.
@@ -4,10 +4,9 @@ README.rdoc
4
4
  Rakefile
5
5
  lib/capybara.rb
6
6
  lib/capybara/cucumber.rb
7
+ lib/capybara/driver/base.rb
7
8
  lib/capybara/driver/culerity_driver.rb
8
- lib/capybara/driver/firewatir_driver.rb
9
9
  lib/capybara/driver/rack_test_driver.rb
10
- lib/capybara/driver/safariwatir_driver.rb
11
10
  lib/capybara/driver/selenium_driver.rb
12
11
  lib/capybara/dsl.rb
13
12
  lib/capybara/node.rb
@@ -15,17 +14,17 @@ lib/capybara/rails.rb
15
14
  lib/capybara/save_and_open_page.rb
16
15
  lib/capybara/server.rb
17
16
  lib/capybara/session.rb
17
+ lib/capybara/xpath.rb
18
18
  script/console
19
19
  script/destroy
20
20
  script/generate
21
21
  spec/driver/culerity_driver_spec.rb
22
- spec/driver/firewatir_driver_spec.rb
23
22
  spec/driver/rack_test_driver_spec.rb
24
- spec/driver/safariwarit_driver_spec.rb
25
23
  spec/driver/selenium_driver_spec.rb
26
24
  spec/drivers_spec.rb
27
25
  spec/dsl_spec.rb
28
26
  spec/fixtures/test_file.txt
27
+ spec/public/jquery-ui.js
29
28
  spec/public/jquery.js
30
29
  spec/save_and_open_page_spec.rb
31
30
  spec/session/culerity_session_spec.rb
@@ -42,3 +41,4 @@ spec/views/with_html.erb
42
41
  spec/views/with_js.erb
43
42
  spec/views/with_scope.erb
44
43
  spec/views/with_simple_html.erb
44
+ spec/xpath_spec.rb
@@ -119,6 +119,10 @@ Querying:
119
119
  find_button
120
120
  field_labeled
121
121
 
122
+ Scripting:
123
+
124
+ evaluate_script – Returns the value of the executed javascript (only works on javascript supported drivers)
125
+
122
126
  Debugging:
123
127
 
124
128
  save_and_open_page
@@ -158,7 +162,7 @@ For ultimate control, you can instantiate and use a session manually.
158
162
  Capybara does not try to guess what kind of selector you are going to give it,
159
163
  if you want to use CSS with your 'within' declarations for example, you'll need
160
164
  to do:
161
-
165
+
162
166
  within(:css, 'ul li') { ... }
163
167
 
164
168
  Alternatively you can set the default selector to CSS, which may help if you are
@@ -207,6 +211,9 @@ The following people have dedicated their time and effort to Capybara:
207
211
  * Jonas Nicklas
208
212
  * Dennis Rogenius
209
213
  * Rob Holland
214
+ * Wincent Colaiuta
215
+ * Andrea Fazzi
216
+ * Aslak Hellesøy
210
217
 
211
218
  == License:
212
219
 
@@ -231,4 +238,4 @@ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
231
238
  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
232
239
  CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
233
240
  TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
234
- SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
241
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -1,30 +1,36 @@
1
1
  require 'nokogiri'
2
2
 
3
3
  module Capybara
4
- VERSION = '0.1.3'
4
+ VERSION = '0.1.4'
5
5
 
6
6
  class CapybaraError < StandardError; end
7
7
  class DriverNotFoundError < CapybaraError; end
8
8
  class ElementNotFound < CapybaraError; end
9
+ class NotSupportedByDriverError < CapybaraError; end
9
10
 
10
11
  class << self
11
12
  attr_accessor :debug, :asset_root
12
-
13
+ attr_writer :default_selector
14
+
15
+ def default_selector
16
+ @default_selector ||= :xpath
17
+ end
18
+
13
19
  def log(message)
14
20
  puts "[capybara] #{message}" if debug
15
21
  true
16
22
  end
17
23
  end
18
24
 
19
- autoload :Server, 'capybara/server'
25
+ autoload :Server, 'capybara/server'
20
26
  autoload :Session, 'capybara/session'
21
- autoload :Node, 'capybara/node'
27
+ autoload :Node, 'capybara/node'
28
+ autoload :XPath, 'capybara/xpath'
22
29
 
23
30
  module Driver
31
+ autoload :Base, 'capybara/driver/base'
24
32
  autoload :RackTest, 'capybara/driver/rack_test_driver'
25
33
  autoload :Culerity, 'capybara/driver/culerity_driver'
26
- autoload :SafariWatir, 'capybara/driver/safariwatir_driver'
27
- autoload :FireWatir, 'capybara/driver/firewatir_driver'
28
34
  autoload :Selenium, 'capybara/driver/selenium_driver'
29
35
  end
30
36
  end
@@ -0,0 +1,17 @@
1
+ class Capybara::Driver::Base
2
+ def visit(path)
3
+ raise "Not implemented"
4
+ end
5
+
6
+ def find(query)
7
+ raise "Not implemented"
8
+ end
9
+
10
+ def body
11
+ raise "Not implemented"
12
+ end
13
+
14
+ def wait?
15
+ false
16
+ end
17
+ end
@@ -1,11 +1,11 @@
1
1
  require 'culerity'
2
2
 
3
- class Capybara::Driver::Culerity
3
+ class Capybara::Driver::Culerity < Capybara::Driver::Base
4
4
  class Node < Capybara::Node
5
5
  def text
6
6
  node.text
7
7
  end
8
-
8
+
9
9
  def [](name)
10
10
  value = if name.to_sym == :class
11
11
  node.class_name
@@ -18,22 +18,28 @@ class Capybara::Driver::Culerity
18
18
  def set(value)
19
19
  node.set(value)
20
20
  end
21
-
21
+
22
22
  def select(option)
23
23
  node.select(option)
24
24
  end
25
-
25
+
26
26
  def click
27
27
  node.click
28
28
  end
29
-
29
+
30
+ def drag_to(element)
31
+ node.fire_event('mousedown')
32
+ element.node.fire_event('mousemove')
33
+ element.node.fire_event('mouseup')
34
+ end
35
+
30
36
  def tag_name
31
37
  # FIXME: this might be the dumbest way ever of getting the tag name
32
38
  # there has to be something better...
33
39
  node.to_xml[/^\s*<([a-z0-9\-\:]+)/, 1]
34
40
  end
35
41
  end
36
-
42
+
37
43
  attr_reader :app, :rack_server
38
44
 
39
45
  def self.server
@@ -51,25 +57,31 @@ class Capybara::Driver::Culerity
51
57
  @rack_server = Capybara::Server.new(@app)
52
58
  @rack_server.boot
53
59
  end
54
-
60
+
55
61
  def visit(path)
56
62
  browser.goto(url(path))
57
63
  end
58
-
64
+
59
65
  def body
60
66
  browser.html
61
67
  end
62
-
68
+
63
69
  def find(selector)
64
70
  browser.elements_by_xpath(selector).map { |node| Node.new(self, node) }
65
71
  end
72
+
73
+ def wait?; true; end
74
+
75
+ def evaluate_script(script)
76
+ browser.execute_script "#{script}"
77
+ end
66
78
 
67
79
  private
68
80
 
69
81
  def url(path)
70
82
  rack_server.url(path)
71
83
  end
72
-
84
+
73
85
  def browser
74
86
  unless @_browser
75
87
  @_browser = ::Culerity::RemoteBrowserProxy.new self.class.server, {:browser => :firefox, :log_level => :off}
@@ -1,7 +1,8 @@
1
1
  require 'rack/test'
2
2
  require 'nokogiri'
3
+ require 'cgi'
3
4
 
4
- class Capybara::Driver::RackTest
5
+ class Capybara::Driver::RackTest < Capybara::Driver::Base
5
6
  class Node < Capybara::Node
6
7
  def text
7
8
  node.text
@@ -59,50 +60,39 @@ class Capybara::Driver::RackTest
59
60
 
60
61
  class Form < Node
61
62
  def params(button)
62
- params = []
63
- params += node.xpath(".//input[@type='text']", ".//input[@type='hidden']", ".//input[@type='password']").inject([]) do |agg, input|
64
- agg << [input['name'].to_s, input['value'].to_s]
65
- agg
63
+ params = {}
64
+ node.xpath(".//input[@type='text' or @type='hidden' or @type='password']").map do |input|
65
+ merge_param!(params, input['name'].to_s, input['value'].to_s)
66
66
  end
67
- params += node.xpath(".//textarea").inject([]) do |agg, textarea|
68
- agg << [textarea['name'].to_s, textarea.text.to_s]
69
- agg
67
+ node.xpath(".//textarea").map do |textarea|
68
+ merge_param!(params, textarea['name'].to_s, textarea.text.to_s)
70
69
  end
71
- params += node.xpath(".//input[@type='radio']").inject([]) do |agg, input|
72
- agg << [input['name'].to_s, input['value'].to_s] if input['checked']
73
- agg
70
+ node.xpath(".//input[@type='radio' or @type='checkbox']").map do |input|
71
+ merge_param!(params, input['name'].to_s, input['value'].to_s) if input['checked']
74
72
  end
75
- params += node.xpath(".//input[@type='checkbox']").inject([]) do |agg, input|
76
- agg << [input['name'].to_s, input['value'].to_s] if input['checked']
77
- agg
78
- end
79
- params += node.xpath(".//select").inject([]) do |agg, select|
73
+ node.xpath(".//select").map do |select|
80
74
  option = select.xpath(".//option[@selected]").first
81
75
  option ||= select.xpath('.//option').first
82
- agg << [select['name'].to_s, (option['value'] || option.text).to_s] if option
83
- agg
76
+ merge_param!(params, select['name'].to_s, (option['value'] || option.text).to_s) if option
84
77
  end
85
- params += node.xpath(".//input[@type='file']").inject([]) do |agg, input|
86
- if multipart?
87
- agg << [input['name'].to_s, Rack::Test::UploadedFile.new(input['value'].to_s)]
88
- else
89
- agg << [input['name'].to_s, File.basename(input['value'].to_s)]
78
+ node.xpath(".//input[@type='file']").map do |input|
79
+ if input['value'].to_s.any?
80
+ if multipart?
81
+ merge_param!(params, input['name'].to_s, Rack::Test::UploadedFile.new(input['value'].to_s))
82
+ else
83
+ merge_param!(params, input['name'].to_s, File.basename(input['value'].to_s))
84
+ end
90
85
  end
91
- agg
92
- end
93
- params.push [button[:name], button[:value]] if button[:name]
94
- if multipart?
95
- params.inject({}) { |agg, (key, value)| agg[key] = value; agg }
96
- else
97
- params.map { |key, value| "#{key}=#{value}" }.join('&')
98
86
  end
87
+ merge_param!(params, button[:name], button[:value]) if button[:name]
88
+ params
99
89
  end
100
90
 
101
91
  def submit(button)
102
92
  if post?
103
- driver.submit(node['action'].to_s, params(button))
93
+ driver.submit(node['action'].to_s, params(button))
104
94
  else
105
- driver.visit(node['action'].to_s.split('?').first + '?' + params(button))
95
+ driver.visit(node['action'].to_s, params(button))
106
96
  end
107
97
  end
108
98
 
@@ -113,6 +103,21 @@ class Capybara::Driver::RackTest
113
103
  def post?
114
104
  self[:method] =~ /post/i
115
105
  end
106
+
107
+ private
108
+
109
+ def merge_param!(params, key, value)
110
+ collection = key.sub!(/\[\]$/, '')
111
+ if collection
112
+ if params[key]
113
+ params[key] << value
114
+ else
115
+ params[key] = [value]
116
+ end
117
+ else
118
+ params[key] = value
119
+ end
120
+ end
116
121
  end
117
122
 
118
123
  include ::Rack::Test::Methods
@@ -125,8 +130,8 @@ class Capybara::Driver::RackTest
125
130
  @app = app
126
131
  end
127
132
 
128
- def visit(path)
129
- get(path)
133
+ def visit(path, attributes = {})
134
+ get(path, attributes)
130
135
  follow_redirect! while response.redirect?
131
136
  cache_body
132
137
  end
@@ -134,9 +139,9 @@ class Capybara::Driver::RackTest
134
139
  def submit(path, attributes)
135
140
  post(path, attributes)
136
141
  follow_redirect! while response.redirect?
137
- cache_body
142
+ cache_body
138
143
  end
139
-
144
+
140
145
  def find(selector)
141
146
  html.xpath(selector).map { |node| Node.new(self, node) }
142
147
  end
@@ -1,6 +1,6 @@
1
1
  require 'selenium-webdriver'
2
2
 
3
- class Capybara::Driver::Selenium
3
+ class Capybara::Driver::Selenium < Capybara::Driver::Base
4
4
  class Node < Capybara::Node
5
5
  def text
6
6
  node.text
@@ -17,16 +17,13 @@ class Capybara::Driver::Selenium
17
17
  end
18
18
 
19
19
  def set(value)
20
- if tag_name == 'input' and %w(text password hidden file).include?(type)
20
+ if tag_name == 'textarea' or (tag_name == 'input' and %w(text password hidden file).include?(type))
21
21
  node.clear
22
22
  node.send_keys(value.to_s)
23
23
  elsif tag_name == 'input' and type == 'radio'
24
24
  node.select
25
25
  elsif tag_name == 'input' and type == 'checkbox'
26
26
  node.toggle
27
- elsif tag_name == "textarea"
28
- node.clear
29
- node.send_keys(value.to_s)
30
27
  end
31
28
  end
32
29
 
@@ -38,6 +35,10 @@ class Capybara::Driver::Selenium
38
35
  node.click
39
36
  end
40
37
 
38
+ def drag_to(element)
39
+ node.drag_and_drop_on(element.node)
40
+ end
41
+
41
42
  def tag_name
42
43
  node.tag_name
43
44
  end
@@ -80,6 +81,12 @@ class Capybara::Driver::Selenium
80
81
  driver.find_elements(:xpath, selector).map { |node| Node.new(self, node) }
81
82
  end
82
83
 
84
+ def wait?; true; end
85
+
86
+ def evaluate_script(script)
87
+ driver.execute_script "return #{script}"
88
+ end
89
+
83
90
  private
84
91
 
85
92
  def url(path)
@@ -12,7 +12,7 @@ module Capybara
12
12
  @current_driver || default_driver
13
13
  end
14
14
  alias_method :mode, :current_driver
15
-
15
+
16
16
  def javascript_driver
17
17
  @javascript_driver || :selenium
18
18
  end
@@ -24,11 +24,11 @@ module Capybara
24
24
  def current_session
25
25
  session_pool["#{current_driver}#{app.object_id}"] ||= Capybara::Session.new(current_driver, app)
26
26
  end
27
-
27
+
28
28
  def current_session?
29
29
  session_pool.has_key?("#{current_driver}#{app.object_id}")
30
30
  end
31
-
31
+
32
32
  def reset_sessions!
33
33
  @session_pool = nil
34
34
  end
@@ -47,10 +47,10 @@ module Capybara
47
47
  end
48
48
 
49
49
  SESSION_METHODS = [
50
- :visit, :body, :click_link, :click_button, :fill_in, :choose, :has_xpath?, :has_css?,
50
+ :visit, :body, :click_link, :click_button, :drag, :fill_in, :choose, :has_xpath?, :has_css?,
51
51
  :check, :uncheck, :attach_file, :select, :has_content?, :within, :within_fieldset,
52
- :within_table, :save_and_open_page, :find_field, :find_link, :find_button,
53
- :field_labeled
52
+ :within_table, :save_and_open_page, :find, :find_field, :find_link, :find_button,
53
+ :field_labeled, :all, :wait_for, :evaluate_script
54
54
  ]
55
55
  SESSION_METHODS.each do |method|
56
56
  class_eval <<-RUBY, __FILE__, __LINE__+1
@@ -9,11 +9,11 @@ class Capybara::Node
9
9
  def text
10
10
  raise "Not implemented"
11
11
  end
12
-
12
+
13
13
  def [](name)
14
14
  raise "Not implemented"
15
15
  end
16
-
16
+
17
17
  def value
18
18
  self[:value]
19
19
  end
@@ -21,7 +21,7 @@ class Capybara::Node
21
21
  def set(value)
22
22
  raise "Not implemented"
23
23
  end
24
-
24
+
25
25
  def select(option)
26
26
  raise "Not implemented"
27
27
  end
@@ -29,8 +29,12 @@ class Capybara::Node
29
29
  def click
30
30
  raise "Not implemented"
31
31
  end
32
-
32
+
33
+ def drag_to(element)
34
+ raise "Not implemented"
35
+ end
36
+
33
37
  def tag_name
34
38
  raise "Not implemented"
35
39
  end
36
- end
40
+ end