celerity 0.0.6 → 0.0.7

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 (75) hide show
  1. data/History.txt +36 -0
  2. data/Manifest.txt +82 -0
  3. data/README.rdoc +78 -0
  4. data/Rakefile +25 -10
  5. data/celerity.gemspec +40 -0
  6. data/lib/celerity.rb +36 -20
  7. data/lib/celerity/browser.rb +396 -189
  8. data/lib/celerity/clickable_element.rb +25 -5
  9. data/lib/celerity/collections.rb +2 -2
  10. data/lib/celerity/container.rb +74 -61
  11. data/lib/celerity/default_viewer.rb +8 -4
  12. data/lib/celerity/disabled_element.rb +5 -5
  13. data/lib/celerity/element.rb +57 -35
  14. data/lib/celerity/element_collection.rb +22 -21
  15. data/lib/celerity/element_locator.rb +25 -18
  16. data/lib/celerity/elements/button.rb +13 -11
  17. data/lib/celerity/elements/file_field.rb +8 -4
  18. data/lib/celerity/elements/form.rb +7 -5
  19. data/lib/celerity/elements/frame.rb +6 -4
  20. data/lib/celerity/elements/image.rb +4 -4
  21. data/lib/celerity/elements/label.rb +1 -1
  22. data/lib/celerity/elements/link.rb +5 -5
  23. data/lib/celerity/elements/meta.rb +2 -1
  24. data/lib/celerity/elements/non_control_elements.rb +3 -3
  25. data/lib/celerity/elements/option.rb +7 -7
  26. data/lib/celerity/elements/radio_check.rb +18 -18
  27. data/lib/celerity/elements/select_list.rb +55 -25
  28. data/lib/celerity/elements/table.rb +21 -18
  29. data/lib/celerity/elements/table_cell.rb +1 -1
  30. data/lib/celerity/elements/table_elements.rb +1 -1
  31. data/lib/celerity/elements/table_row.rb +5 -5
  32. data/lib/celerity/elements/text_field.rb +33 -28
  33. data/lib/celerity/exception.rb +11 -5
  34. data/lib/celerity/htmlunit.rb +24 -8
  35. data/lib/celerity/htmlunit/commons-codec-1.4.jar +0 -0
  36. data/lib/celerity/htmlunit/htmlunit-2.6.jar +0 -0
  37. data/lib/celerity/htmlunit/htmlunit-core-js-2.6.jar +0 -0
  38. data/lib/celerity/htmlunit/nekohtml-1.9.13.jar +0 -0
  39. data/lib/celerity/htmlunit/{xercesImpl-2.8.1.jar → xercesImpl-2.9.1.jar} +0 -0
  40. data/lib/celerity/ignoring_web_connection.rb +15 -0
  41. data/lib/celerity/input_element.rb +1 -1
  42. data/lib/celerity/listener.rb +23 -17
  43. data/lib/celerity/short_inspect.rb +20 -0
  44. data/lib/celerity/util.rb +5 -2
  45. data/lib/celerity/version.rb +3 -10
  46. data/lib/celerity/viewer_connection.rb +89 -0
  47. data/lib/celerity/watir_compatibility.rb +2 -5
  48. data/lib/celerity/xpath_support.rb +48 -0
  49. data/spec/browser_authentication_spec.rb +16 -0
  50. data/spec/browser_spec.rb +300 -0
  51. data/spec/clickable_element_spec.rb +39 -0
  52. data/spec/default_viewer_spec.rb +23 -0
  53. data/spec/element_spec.rb +51 -0
  54. data/spec/filefield_spec.rb +18 -0
  55. data/spec/htmlunit_spec.rb +56 -0
  56. data/spec/index_offset_spec.rb +24 -0
  57. data/spec/listener_spec.rb +142 -0
  58. data/spec/spec_helper.rb +8 -0
  59. data/tasks/benchmark.rake +4 -0
  60. data/tasks/deployment.rake +43 -0
  61. data/tasks/environment.rake +7 -0
  62. data/tasks/fix.rake +25 -0
  63. data/tasks/jar.rake +4 -6
  64. data/tasks/rspec.rake +43 -0
  65. data/tasks/simple_ci.rake +94 -0
  66. data/tasks/snapshot.rake +22 -0
  67. data/tasks/website.rake +17 -0
  68. data/tasks/yard.rake +9 -0
  69. metadata +59 -26
  70. data/README.txt +0 -69
  71. data/lib/celerity/extra/method_generator.rb +0 -170
  72. data/lib/celerity/htmlunit/commons-codec-1.3.jar +0 -0
  73. data/lib/celerity/htmlunit/htmlunit-2.5-SNAPSHOT.jar +0 -0
  74. data/lib/celerity/htmlunit/htmlunit-core-js-2.5-SNAPSHOT.jar +0 -0
  75. data/lib/celerity/htmlunit/nekohtml-1.9.12-20090308.130127-11.jar +0 -0
@@ -0,0 +1,15 @@
1
+ module Celerity
2
+ class IgnoringWebConnection < HtmlUnit::Util::FalsifyingWebConnection
3
+
4
+ def initialize(web_client, pattern)
5
+ super(web_client)
6
+ @pattern = pattern
7
+ end
8
+
9
+ def getResponse(request_settings)
10
+ return super unless request_settings.getUrl.toString =~ @pattern
11
+ createWebResponse(request_settings, "", "text/html")
12
+ end
13
+
14
+ end
15
+ end
@@ -9,7 +9,7 @@ module Celerity
9
9
 
10
10
  def readonly?
11
11
  assert_exists
12
- @object.isAttributeDefined('readonly')
12
+ @object.hasAttribute 'readonly'
13
13
  end
14
14
 
15
15
  private
@@ -3,7 +3,7 @@ module Celerity
3
3
  #
4
4
  # This class is used to wrap some of the listeners available from HtmlUnit's WebClient.
5
5
  #
6
-
6
+
7
7
  class Listener
8
8
  include com.gargoylesoftware.htmlunit.AlertHandler
9
9
  include com.gargoylesoftware.htmlunit.ConfirmHandler
@@ -18,12 +18,12 @@ module Celerity
18
18
  @webclient = webclient
19
19
  @procs = Hash.new { |h, k| h[k] = [] }
20
20
  end
21
-
21
+
22
22
  #
23
23
  # Add a listener block for one of the available types.
24
24
  # @see Celerity::Browser#add_listener
25
25
  #
26
-
26
+
27
27
  def add_listener(type, &block)
28
28
  case type
29
29
  when :status
@@ -63,51 +63,57 @@ module Celerity
63
63
  raise TypeError, "must give proc or index"
64
64
  end
65
65
  end
66
-
66
+
67
67
  #
68
68
  # interface StatusHandler
69
69
  #
70
-
70
+
71
71
  def statusMessageChanged(page, message)
72
72
  @procs[:status].each { |h| h.call(page, message) }
73
73
  end
74
-
74
+
75
75
  #
76
76
  # interface AlertHandler
77
77
  #
78
-
78
+
79
79
  def handleAlert(page, message)
80
80
  @procs[:alert].each { |h| h.call(page, message) }
81
81
  end
82
-
82
+
83
83
  #
84
84
  # interface ConfirmHandler
85
85
  #
86
-
86
+ # The returned value is determined by the last registered :confirm listener proc.
87
+ # If it is nil, return true, otherwise return that value as a boolean.
88
+ #
89
+ # @see Browser#confirm
90
+ #
91
+
87
92
  def handleConfirm(page, message)
88
- @procs[:confirm].each { |h| h.call(page, message) }
93
+ val = @procs[:confirm].map { |h| h.call(page, message) }.last
94
+ val.nil? || !!val
89
95
  end
90
96
 
91
97
  #
92
98
  # interface AttachmentHandler
93
99
  #
94
-
100
+
95
101
  def handleAttachment(page)
96
102
  @procs[:attachment].each { |h| h.call(page) }
97
103
  end
98
-
104
+
99
105
  #
100
106
  # interface PromptHandler
101
107
  #
102
-
108
+
103
109
  def handlePrompt(page, message)
104
110
  @procs[:prompt].each { |h| h.call(page, message) }
105
111
  end
106
-
112
+
107
113
  #
108
114
  # interface WebWindowListener
109
115
  #
110
-
116
+
111
117
  def webWindowClosed(web_window_event)
112
118
  @procs[:web_window_event].each { |h| h.call(web_window_event) }
113
119
  end
@@ -117,7 +123,7 @@ module Celerity
117
123
  #
118
124
  # interface HTMLParserListener
119
125
  #
120
-
126
+
121
127
  def error(message, url, line, column, key)
122
128
  @procs[:html_parser].each { |h| h.call(message, url, line, column, key) }
123
129
  end
@@ -126,7 +132,7 @@ module Celerity
126
132
  #
127
133
  # interface IncorrectnessListener
128
134
  #
129
-
135
+
130
136
  def notify(message, origin)
131
137
  @procs[:incorrectness].each { |h| h.call(message, origin) }
132
138
  end
@@ -0,0 +1,20 @@
1
+ module Celerity
2
+ module ShortInspect
3
+
4
+ def short_inspect(opts)
5
+ if excluded_ivars = opts[:exclude]
6
+ ivars = (instance_variables - excluded_ivars)
7
+ elsif included_ivars = opts[:include]
8
+ ivars = included_ivars
9
+ else
10
+ raise ArgumentError, "unknown arg: #{opts.inspect}"
11
+ end
12
+
13
+ ivars.map! { |ivar| "#{ivar}=#{instance_variable_get(ivar).inspect}" }
14
+ '#<%s:0x%s %s>' % [self.class.name, self.hash.to_s(16), ivars.join(" ")]
15
+ end
16
+
17
+
18
+
19
+ end
20
+ end
data/lib/celerity/util.rb CHANGED
@@ -28,7 +28,6 @@ module Celerity
28
28
  HtmlUnit::Html::HtmlHiddenInput => Celerity::Hidden,
29
29
  HtmlUnit::Html::HtmlImage => Celerity::Image,
30
30
  HtmlUnit::Html::HtmlLabel => Celerity::Label,
31
- HtmlUnit::Html::HtmlLink => Celerity::Link,
32
31
  HtmlUnit::Html::HtmlListItem => Celerity::Li,
33
32
  HtmlUnit::Html::HtmlMap => Celerity::Map,
34
33
  HtmlUnit::Html::HtmlOption => Celerity::Option,
@@ -58,7 +57,7 @@ module Celerity
58
57
  # HtmlUnit will recognize most common file types, but custom ones can be added here.
59
58
  # Used for FileField uploads.
60
59
  #
61
-
60
+
62
61
  ContentTypes = {
63
62
  ".bmp" => "image/x-ms-bmp",
64
63
  ".doc" => "application/msword",
@@ -84,5 +83,9 @@ module Celerity
84
83
  strip
85
84
  end
86
85
 
86
+ def logger_for(package_string)
87
+ java.util.logging.Logger.getLogger(package_string)
88
+ end
89
+
87
90
  end
88
91
  end
@@ -1,10 +1,3 @@
1
- module Celerity #:nodoc:
2
- module VERSION #:nodoc:
3
- MAJOR = 0
4
- MINOR = 0
5
- TINY = 6
6
- PATCH = nil # Set to nil for official release
7
-
8
- STRING = [MAJOR, MINOR, TINY, PATCH].compact.join('.')
9
- end
10
- end
1
+ module Celerity
2
+ VERSION = "0.0.7"
3
+ end
@@ -0,0 +1,89 @@
1
+ module Celerity
2
+ class ViewerConnection
3
+
4
+ #
5
+ # Create a new connection to the given host/port
6
+ #
7
+
8
+ def self.create(host, port)
9
+ # if the connection fails, we won't spend time loading json
10
+ socket = TCPSocket.new(host, port)
11
+ require "json"
12
+ new(socket)
13
+ end
14
+
15
+ def initialize(socket)
16
+ @socket = socket
17
+ end
18
+
19
+ #
20
+ # Tells the viewer to render the given HTML, with the given URL as base url.
21
+ #
22
+
23
+ def render_html(html, url)
24
+ send_data('method' => 'page_changed', 'html' => html, 'url' => url)
25
+ end
26
+
27
+ #
28
+ # Tells the viewer to save a screenshot of the current page to the given path.
29
+ # May not be available on all viewers.
30
+ #
31
+
32
+ def save(path)
33
+ send_data('method' => 'save', 'path' => path)
34
+ end
35
+
36
+
37
+ #
38
+ # Tells the viewer to dump the render tree to the given path.
39
+ # Only available in the Qt viewer.
40
+ #
41
+
42
+ def save_render_tree(path)
43
+ send_data('method' => 'save_render_tree', 'path' => path)
44
+ end
45
+
46
+ #
47
+ # Get the currently rendered page as a Base64-encoded PNG image.
48
+ # Only available in the Qt viewer.
49
+ #
50
+
51
+ def image_data
52
+ send_data('method' => 'image_data')
53
+ data = read_data
54
+ data['image'] || data['error']
55
+ end
56
+
57
+ #
58
+ # Close the connection.
59
+ #
60
+
61
+ def close
62
+ @socket.close rescue nil
63
+ end
64
+
65
+ private
66
+
67
+ def send_data(msg)
68
+ json = msg.to_json
69
+ data = "Content-Length: #{json.size}\n\n#{json}"
70
+ @socket.write data
71
+ @socket.flush
72
+
73
+ nil
74
+ end
75
+
76
+ def read_data
77
+ buf = ''
78
+ until buf =~ /\n\n\z/ || @socket.eof? || @socket.closed?
79
+ buf << @socket.read(1).to_s
80
+ end
81
+
82
+ return if buf.empty?
83
+
84
+ length = buf[/Content-Length: (\d+)/, 1].to_i
85
+ JSON.parse @socket.read(length)
86
+ end
87
+
88
+ end
89
+ end
@@ -1,7 +1,7 @@
1
1
  module Celerity
2
2
  class Browser
3
3
  class << self
4
-
4
+
5
5
  # Added for Watir compatibility - not in use by Celerity
6
6
  attr_accessor :speed, :attach_timeout, :visible
7
7
  # Added for Watir compatibility - not in use by Celerity
@@ -25,8 +25,6 @@ module Celerity
25
25
  def bring_to_front; true; end
26
26
  # Added for Watir compatibility - not in use by Celerity
27
27
  def speed=(s); s end
28
- # Added for Watir compatibility - not in use by Celerity
29
- def status; '' end
30
28
  end
31
29
 
32
30
 
@@ -70,7 +68,6 @@ module Celerity
70
68
  alias_method :getAllContents, :options
71
69
  alias_method :clearSelection, :clear
72
70
  alias_method :clear_selection, :clear
73
- alias_method :select_value, :select
74
71
  alias_method :includes?, :include?
75
72
  end
76
73
 
@@ -78,7 +75,7 @@ module Celerity
78
75
  alias_method :dragContentsTo, :drag_contents_to
79
76
  alias_method :getContents, :value
80
77
  alias_method :get_contents, :value
81
-
78
+
82
79
  def requires_typing; end
83
80
  end
84
81
  end
@@ -0,0 +1,48 @@
1
+ module Celerity
2
+
3
+ #
4
+ # Module to search by xpath
5
+ #
6
+
7
+ module XpathSupport
8
+
9
+ #
10
+ # Get the first element found matching the given XPath.
11
+ #
12
+ # @param [String] xpath
13
+ # @return [Celerity::Element] An element subclass (or Element if none is found)
14
+ #
15
+
16
+ def element_by_xpath(xpath)
17
+ assert_exists
18
+ obj = @page.getFirstByXPath(xpath)
19
+ element_from_dom_node(obj)
20
+ end
21
+
22
+ #
23
+ # Get all the elements matching the given XPath.
24
+ #
25
+ # @param [String] xpath
26
+ # @return [Array<Celerity::Element>] array of elements
27
+ #
28
+
29
+ def elements_by_xpath(xpath)
30
+ assert_exists
31
+ objects = @page.getByXPath(xpath)
32
+ # should use an ElementCollection here?
33
+ objects.map { |o| element_from_dom_node(o) }.compact
34
+ end
35
+
36
+ #
37
+ # Convert the given HtmlUnit DomNode to a Celerity object
38
+ #
39
+
40
+ def element_from_dom_node(obj)
41
+ element_class = Util.htmlunit2celerity(obj.class) || Element
42
+ element_class.new(self, :object, obj)
43
+ end
44
+
45
+
46
+ end
47
+
48
+ end
@@ -0,0 +1,16 @@
1
+ require File.dirname(__FILE__) + '/watirspec/spec_helper'
2
+
3
+ describe "Browser" do
4
+
5
+ describe "#credentials=" do
6
+ it "sets the basic authentication credentials" do
7
+ browser.goto(WatirSpec.host + "/authentication")
8
+ browser.text.should_not include("ok")
9
+
10
+ browser.credentials = "foo:bar"
11
+
12
+ browser.goto(WatirSpec.host + "/authentication")
13
+ browser.text.should include("ok")
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,300 @@
1
+ require File.dirname(__FILE__) + '/watirspec/spec_helper'
2
+
3
+ describe "Browser" do
4
+ describe "#new" do
5
+ it "raises TypeError if argument is not a Hash" do
6
+ lambda { Browser.new(:foo) }.should raise_error(TypeError)
7
+ end
8
+
9
+ it "raises ArgumentError if given bad arguments for :render key" do
10
+ lambda { Browser.new(:render => :foo) }.should raise_error(ArgumentError)
11
+ end
12
+
13
+ it "raises ArgumentError if given bad arguments for :browser key" do
14
+ lambda { Browser.new(:browser => 'foo') }.should raise_error(ArgumentError)
15
+ end
16
+
17
+ it "raises ArgumentError if given an unknown option" do
18
+ lambda { Browser.new(:foo => 1) }.should raise_error(ArgumentError)
19
+ end
20
+
21
+ it "should hold the init options" do
22
+ browser.options.should == WatirSpec.browser_args.first
23
+ end
24
+
25
+ it "should use the specified proxy" do
26
+ # TODO: find a better way to test this with rack
27
+ require 'webrick/httpproxy'
28
+
29
+ received = false
30
+ blk = lambda { received = true }
31
+ s = WEBrick::HTTPProxyServer.new(:Port => 2001, :ProxyContentHandler => blk)
32
+ Thread.new { s.start }
33
+
34
+ b = Browser.new(WatirSpec.browser_args.first.merge(:proxy => "localhost:2001"))
35
+ b.goto(WatirSpec.host)
36
+ s.shutdown
37
+
38
+ received.should be_true
39
+ end
40
+
41
+ it "should use the specified user agent" do
42
+ b = Browser.new(WatirSpec.browser_args.first.merge(:user_agent => "Celerity"))
43
+ b.goto(WatirSpec.host + "/header_echo")
44
+ b.text.should include('"HTTP_USER_AGENT"=>"Celerity"')
45
+ b.close
46
+ end
47
+
48
+ it "does not try to find a viewer if created with :viewer => false" do
49
+ ViewerConnection.should_not_receive(:create)
50
+
51
+ b = Browser.new(:viewer => false)
52
+ b.close
53
+ end
54
+
55
+ it "tries to find a viewer if created with :viewer => nil" do
56
+ ViewerConnection.should_receive(:create).with("127.0.0.1", 6429)
57
+
58
+ b = Browser.new(:viewer => nil)
59
+ b.close
60
+ end
61
+
62
+ it "tries to find a viewer on the specified host/port with :viewer => String" do
63
+ ViewerConnection.should_receive(:create).with("localhost", 1234)
64
+
65
+ b = Browser.new(:viewer => "localhost:1234")
66
+ b.close
67
+ end
68
+ end
69
+
70
+ describe "#html" do
71
+ %w(shift_jis iso-2022-jp euc-jp).each do |charset|
72
+ it "returns decoded #{charset.upcase} when :charset specified" do
73
+ browser = Browser.new(WatirSpec.browser_args.first.merge(:charset => charset.upcase))
74
+ browser.goto(WatirSpec.files + "/#{charset}_text.html")
75
+ # Browser#text is automagically transcoded into the right charset, but Browser#html isn't.
76
+ browser.html.should =~ /本日は晴天なり。/
77
+ browser.close
78
+ end
79
+ end
80
+ end
81
+
82
+ describe "#response_headers" do
83
+ it "returns the response headers (as a hash)" do
84
+ browser.goto(WatirSpec.host + "/non_control_elements.html")
85
+ browser.response_headers.should be_kind_of(Hash)
86
+ browser.response_headers['Date'].should be_kind_of(String)
87
+ browser.response_headers['Content-Type'].should be_kind_of(String)
88
+ end
89
+ end
90
+
91
+ describe "#content_type" do
92
+ it "returns the content type" do
93
+ browser.goto(WatirSpec.host + "/non_control_elements.html")
94
+ browser.content_type.should =~ /\w+\/\w+/
95
+ end
96
+ end
97
+
98
+ describe "#io" do
99
+ it "returns the io object of the content" do
100
+ browser.goto(WatirSpec.files + "/non_control_elements.html")
101
+ browser.io.should be_kind_of(IO)
102
+ browser.io.read.should == File.read("#{WatirSpec.html}/non_control_elements.html")
103
+ end
104
+ end
105
+
106
+ describe "#goto" do
107
+ it "raises UnexpectedPageException if the content type is not understood" do
108
+ lambda { browser.goto(WatirSpec.host + "/octet_stream") }.should raise_error(UnexpectedPageException)
109
+ end
110
+ end
111
+
112
+ describe "#cookies" do
113
+ it "returns set cookies as a Ruby hash" do
114
+ cookies = browser.cookies
115
+ cookies.should be_instance_of(Hash)
116
+ cookies.should be_empty
117
+
118
+ browser.goto(WatirSpec.host + "/set_cookie")
119
+
120
+ cookies = browser.cookies
121
+ cookies.size.should == 1
122
+ cookies[WatirSpec::Server.host]['monster'].should == "/"
123
+ end
124
+ end
125
+
126
+ describe "#clear_cookies" do
127
+ it "clears all cookies" do
128
+ b = WatirSpec.new_browser
129
+ b.cookies.should be_empty
130
+
131
+ b.goto(WatirSpec.host + "/set_cookie")
132
+ b.cookies.size.should == 1
133
+ b.clear_cookies
134
+ b.cookies.should be_empty
135
+
136
+ b.close
137
+ end
138
+ end
139
+
140
+ describe "add_cookie" do
141
+ it "adds a cookie with the given domain, name and value" do
142
+ browser.add_cookie("example.com", "foo", "bar")
143
+ cookies = browser.cookies
144
+ cookies.should be_instance_of(Hash)
145
+ cookies.should have_key('example.com')
146
+ cookies['example.com']['foo'].should == 'bar'
147
+
148
+ browser.clear_cookies
149
+ end
150
+
151
+ it "adds a cookie with the specified options" do
152
+ browser.add_cookie("example.com", "foo", "bar", :path => "/foobar", :max_age => 1000)
153
+ cookies = browser.cookies
154
+ cookies.should be_instance_of(Hash)
155
+ cookies['example.com']['foo'].should == 'bar'
156
+ end
157
+ end
158
+
159
+ describe "remove_cookie" do
160
+ it "removes the cookie for the given domain and name" do
161
+ b = WatirSpec.new_browser
162
+ b.goto(WatirSpec.host + "/set_cookie")
163
+
164
+ b.remove_cookie(WatirSpec::Server.host, "monster")
165
+ b.cookies.should be_empty
166
+
167
+ b.close
168
+ end
169
+
170
+ it "raises an error if no such cookie exists" do
171
+ lambda { browser.remove_cookie("bogus.com", "bar") }.should raise_error(CookieNotFoundError)
172
+ end
173
+ end
174
+
175
+ describe "#wait" do
176
+ it "should wait for javascript timers to finish" do
177
+ alerts = 0
178
+ browser.add_listener(:alert) { alerts += 1 }
179
+ browser.goto(WatirSpec.files + "/timeout.html")
180
+ browser.div(:id, 'alert').click
181
+ browser.wait.should be_true
182
+ alerts.should == 1
183
+ end
184
+ end
185
+
186
+ describe "#wait_while" do
187
+ it "waits until the specified condition becomes false" do
188
+ browser.goto(WatirSpec.files + "/timeout.html")
189
+ browser.div(:id, "change").click
190
+ browser.wait_while { browser.contains_text("Trigger change") }
191
+ browser.div(:id, "change").text.should == "all done"
192
+ end
193
+
194
+ it "returns the value returned from the block" do
195
+ browser.wait_while { false }.should == false
196
+ end
197
+ end
198
+
199
+ describe "#wait_until" do
200
+ it "waits until the condition becomes true" do
201
+ browser.goto(WatirSpec.files + "/timeout.html")
202
+ browser.div(:id, "change").click
203
+ browser.wait_until { browser.contains_text("all done") }
204
+ end
205
+
206
+ it "returns the value returned from the block" do
207
+ browser.wait_until { true }.should == true
208
+ end
209
+ end
210
+
211
+ describe "#element_by_xpath" do
212
+ it "returns usable elements even though they're not supported" do
213
+ browser.goto(WatirSpec.files + "/forms_with_input_elements.html")
214
+
215
+ el = browser.element_by_xpath("//link")
216
+ el.should be_instance_of(Celerity::Element)
217
+ el.rel.should == "stylesheet"
218
+ end
219
+ end
220
+
221
+ describe "#focused_element" do
222
+ it "returns the element that currently has the focus" do
223
+ b = WatirSpec.new_browser
224
+ b.goto(WatirSpec.files + "/forms_with_input_elements.html")
225
+ b.focused_element.id.should == "new_user_first_name"
226
+
227
+ b.close
228
+ end
229
+ end
230
+
231
+ describe "#status_code" do
232
+ it "returns the status code of the last request" do
233
+ browser.goto(WatirSpec.files + "/forms_with_input_elements.html")
234
+ browser.status_code.should == 200
235
+
236
+ browser.goto(WatirSpec.host + "/doesnt_exist")
237
+ browser.status_code.should == 404
238
+ end
239
+ end
240
+
241
+ describe "#status_code_exceptions" do
242
+ it "raises status code exceptions if set to true" do
243
+ browser.status_code_exceptions = true
244
+ lambda do
245
+ browser.goto(WatirSpec.host + "/doesnt_exist")
246
+ end.should raise_error(NavigationException)
247
+ end
248
+ end
249
+
250
+ describe "#javascript_exceptions" do
251
+ it "raises javascript exceptions if set to true" do
252
+ browser.goto(WatirSpec.files + "/forms_with_input_elements.html")
253
+ browser.javascript_exceptions = true
254
+ lambda do
255
+ browser.execute_script("no_such_function()")
256
+ end.should raise_error
257
+ end
258
+ end
259
+
260
+ describe "#add_listener" do
261
+ it "should click OK for confirm() calls" do
262
+ browser.goto(WatirSpec.files + "/forms_with_input_elements.html")
263
+ browser.add_listener(:confirm) { }
264
+ browser.execute_script("confirm()").should == true
265
+ end
266
+ end
267
+
268
+ describe "#add_checker" do
269
+
270
+ # watir only supports a lambda instance as argument, celerity supports both
271
+ it "runs the given block on each page load" do
272
+ output = ''
273
+
274
+ browser.add_checker { |browser| output << browser.text }
275
+ browser.goto(WatirSpec.files + "/non_control_elements.html")
276
+
277
+ output.should include('Dubito, ergo cogito, ergo sum')
278
+ end
279
+ end
280
+
281
+
282
+ describe "#confirm" do
283
+ it "clicks 'OK' for a confirm() call" do
284
+ browser.goto(WatirSpec.files + "/forms_with_input_elements.html")
285
+
286
+ browser.confirm(true) do
287
+ browser.execute_script('confirm()').should be_true
288
+ end
289
+ end
290
+
291
+ it "clicks 'cancel' for a confirm() call" do
292
+ browser.goto(WatirSpec.files + "/forms_with_input_elements.html")
293
+
294
+ browser.confirm(false) do
295
+ browser.execute_script('confirm()').should be_false
296
+ end
297
+ end
298
+ end
299
+
300
+ end