capybara 0.1.4 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,7 +1,7 @@
1
1
  require 'nokogiri'
2
2
 
3
3
  module Capybara
4
- VERSION = '0.1.4'
4
+ VERSION = '0.2.0'
5
5
 
6
6
  class CapybaraError < StandardError; end
7
7
  class DriverNotFoundError < CapybaraError; end
@@ -55,7 +55,6 @@ class Capybara::Driver::Culerity < Capybara::Driver::Base
55
55
  def initialize(app)
56
56
  @app = app
57
57
  @rack_server = Capybara::Server.new(@app)
58
- @rack_server.boot
59
58
  end
60
59
 
61
60
  def visit(path)
@@ -66,7 +66,6 @@ class Capybara::Driver::Selenium < Capybara::Driver::Base
66
66
  def initialize(app)
67
67
  @app = app
68
68
  @rack_server = Capybara::Server.new(@app)
69
- @rack_server.boot
70
69
  end
71
70
 
72
71
  def visit(path)
@@ -50,7 +50,7 @@ module Capybara
50
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
52
  :within_table, :save_and_open_page, :find, :find_field, :find_link, :find_button,
53
- :field_labeled, :all, :wait_for, :evaluate_script
53
+ :field_labeled, :all, :wait_for, :evaluate_script, :click
54
54
  ]
55
55
  SESSION_METHODS.each do |method|
56
56
  class_eval <<-RUBY, __FILE__, __LINE__+1
@@ -4,14 +4,27 @@ require 'rack'
4
4
  require 'rack/handler/mongrel'
5
5
 
6
6
  class Capybara::Server
7
- attr_reader :app
8
-
7
+ class Identify
8
+ def initialize(app)
9
+ @app = app
10
+ end
11
+
12
+ def call(env)
13
+ if env["REQUEST_PATH"] == "/__identify__"
14
+ [200, {}, @app.object_id.to_s]
15
+ else
16
+ @app.call(env)
17
+ end
18
+ end
19
+ end
20
+
21
+
22
+ attr_reader :app, :port
23
+
9
24
  def initialize(app)
10
25
  @app = app
11
- end
12
-
13
- def port
14
- 8080
26
+ find_available_port
27
+ boot
15
28
  end
16
29
 
17
30
  def host
@@ -22,34 +35,59 @@ class Capybara::Server
22
35
  path = URI.parse(path).request_uri if path =~ /^http/
23
36
  "http://#{host}:#{port}#{path}"
24
37
  end
25
-
38
+
39
+ def responsive?
40
+ is_running_on_port?(port)
41
+ end
42
+
43
+ private
44
+
26
45
  def boot
27
46
  Capybara.log "application has already booted" and return if responsive?
28
47
  Capybara.log "booting Rack applicartion on port #{port}"
29
- start_time = Time.now
30
- Thread.new do
31
- Rack::Handler::Mongrel.run @app, :Port => port
32
- end
33
- Capybara.log "checking if application has booted"
34
- loop do
35
- Capybara.log("application has booted") and break if responsive?
36
- if Time.now - start_time > 10
37
- Capybara.log "Rack application timed out during boot"
38
- exit
48
+
49
+ Timeout.timeout(10) do
50
+ Thread.new do
51
+ Rack::Handler::Mongrel.run Identify.new(@app), :Port => port
52
+ end
53
+ Capybara.log "checking if application has booted"
54
+
55
+ loop do
56
+ Capybara.log("application has booted") and break if responsive?
57
+ sleep 0.5
39
58
  end
40
-
41
- Capybara.log '.'
42
- sleep 1
43
59
  end
60
+ rescue Timeout::Error
61
+ Capybara.log "Rack application timed out during boot"
62
+ exit
44
63
  end
45
64
 
46
- def responsive?
47
- res = Net::HTTP.start(host, port) { |http| http.get('/') }
65
+ def find_available_port
66
+ @port = 9887
67
+ @port += 1 while is_port_open?(@port) and not is_running_on_port?(@port)
68
+ end
69
+
70
+ def is_running_on_port?(tested_port)
71
+ res = Net::HTTP.start(host, tested_port) { |http| http.get('/__identify__') }
48
72
 
49
73
  if res.is_a?(Net::HTTPSuccess) or res.is_a?(Net::HTTPRedirection)
50
- return true
74
+ return res.body == @app.object_id.to_s
75
+ end
76
+ rescue Errno::ECONNREFUSED
77
+ return false
78
+ end
79
+
80
+ def is_port_open?(tested_port)
81
+ Timeout::timeout(1) do
82
+ begin
83
+ s = TCPSocket.new(host, tested_port)
84
+ s.close
85
+ return true
86
+ rescue Errno::ECONNREFUSED, Errno::EHOSTUNREACH
87
+ return false
88
+ end
51
89
  end
52
- rescue Errno::ECONNREFUSED
90
+ rescue Timeout::Error
53
91
  return false
54
92
  end
55
93
 
@@ -25,6 +25,12 @@ module Capybara
25
25
  driver.visit(path)
26
26
  end
27
27
 
28
+ def click(locator)
29
+ link = wait_for(XPath.link(locator).button(locator))
30
+ raise Capybara::ElementNotFound, "no link or button '#{locator}' found" unless link
31
+ link.click
32
+ end
33
+
28
34
  def click_link(locator)
29
35
  link = wait_for(XPath.link(locator))
30
36
  raise Capybara::ElementNotFound, "no link with title, id or text '#{locator}' found" unless link
@@ -91,6 +91,14 @@ module Capybara
91
91
  def to_s
92
92
  @paths.join(' | ')
93
93
  end
94
+
95
+ def append(path)
96
+ XPath.new(*[@paths, XPath.wrap(path).paths].flatten)
97
+ end
98
+
99
+ def prepend(path)
100
+ XPath.new(*[XPath.wrap(path).paths, @paths].flatten)
101
+ end
94
102
 
95
103
  protected
96
104
 
@@ -111,14 +119,6 @@ module Capybara
111
119
  "'#{string}'"
112
120
  end
113
121
  end
114
-
115
- def prepend(path)
116
- XPath.new(*[path, @paths].flatten)
117
- end
118
-
119
- def append(path)
120
- XPath.new(*[@paths, path].flatten)
121
- end
122
122
 
123
123
  end
124
124
  end
@@ -21,6 +21,29 @@ shared_examples_for "session" do
21
21
  @session.body.should include('Another World')
22
22
  end
23
23
  end
24
+
25
+ describe '#click' do
26
+ it "should click on a link" do
27
+ @session.visit('/with_html')
28
+ @session.click('labore')
29
+ @session.body.should include('<h1>Bar</h1>')
30
+ end
31
+
32
+ it "should click on a button" do
33
+ @session.visit('/form')
34
+ @session.click('awe123')
35
+ extract_results(@session)['first_name'].should == 'John'
36
+ end
37
+
38
+ context "with a locator that doesn't exist" do
39
+ it "should raise an error" do
40
+ @session.visit('/with_html')
41
+ running do
42
+ @session.click('does not exist')
43
+ end.should raise_error(Capybara::ElementNotFound)
44
+ end
45
+ end
46
+ end
24
47
 
25
48
  describe '#click_link' do
26
49
  before do
@@ -538,6 +561,7 @@ shared_examples_for "session" do
538
561
 
539
562
  it "should not break if no file is submitted" do
540
563
  @session.click_button('Upload')
564
+ @session.body.should include('No file uploaded')
541
565
  end
542
566
  end
543
567
 
@@ -871,6 +895,14 @@ shared_examples_for "session with javascript support" do
871
895
  end
872
896
  end
873
897
 
898
+ describe '#click' do
899
+ it "should wait for asynchronous load" do
900
+ @session.visit('/with_js')
901
+ @session.click_link('Click me')
902
+ @session.click('Has been clicked')
903
+ end
904
+ end
905
+
874
906
  describe '#click_link' do
875
907
  it "should wait for asynchronous load" do
876
908
  @session.visit('/with_js')
@@ -50,7 +50,7 @@ class TestApp < Sinatra::Base
50
50
  end
51
51
 
52
52
  post '/upload' do
53
- params[:form][:document][:tempfile].read rescue ''
53
+ params[:form][:document][:tempfile].read rescue 'No file uploaded'
54
54
  end
55
55
  end
56
56
 
@@ -29,6 +29,34 @@ describe Capybara::XPath do
29
29
  end
30
30
  end
31
31
 
32
+ describe '#append' do
33
+ it "should append an XPath's paths" do
34
+ @xpath = Capybara::XPath.wrap('//test')
35
+ @xpath = @xpath.append(Capybara::XPath.wrap('//foo/bar'))
36
+ @xpath.paths.should == ['//test', '//foo/bar']
37
+ end
38
+
39
+ it "should append an String as a new path" do
40
+ @xpath = Capybara::XPath.wrap('//test')
41
+ @xpath = @xpath.append('//foo/bar')
42
+ @xpath.paths.should == ['//test', '//foo/bar']
43
+ end
44
+ end
45
+
46
+ describe '#prepend' do
47
+ it "should prepend an XPath's paths" do
48
+ @xpath = Capybara::XPath.wrap('//test')
49
+ @xpath = @xpath.prepend(Capybara::XPath.wrap('//foo/bar'))
50
+ @xpath.paths.should == ['//foo/bar', '//test']
51
+ end
52
+
53
+ it "should prepend an String as a new path" do
54
+ @xpath = Capybara::XPath.wrap('//test')
55
+ @xpath = @xpath.prepend('//foo/bar')
56
+ @xpath.paths.should == ['//foo/bar', '//test']
57
+ end
58
+ end
59
+
32
60
  describe '#scope' do
33
61
  it "should prepend the given scope to all paths" do
34
62
  @xpath = Capybara::XPath.new('//foo/bar', '//test[@blah=foo]').scope('//quox')
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: capybara
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.4
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jonas Nicklas
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-12-12 00:00:00 +01:00
12
+ date: 2009-12-13 00:00:00 +01:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency