no-click-exception-celerity 0.9.0

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 (114) hide show
  1. data/.document +5 -0
  2. data/.gitignore +9 -0
  3. data/.gitmodules +3 -0
  4. data/.travis.yml +4 -0
  5. data/Gemfile +3 -0
  6. data/LICENSE +621 -0
  7. data/README.rdoc +83 -0
  8. data/Rakefile +15 -0
  9. data/benchmark/bm_2000_spans.rb +48 -0
  10. data/benchmark/bm_digg.rb +26 -0
  11. data/benchmark/bm_google_images.rb +36 -0
  12. data/benchmark/bm_input_locator.rb +69 -0
  13. data/benchmark/bm_text_input.rb +19 -0
  14. data/benchmark/loader.rb +14 -0
  15. data/celerity.gemspec +26 -0
  16. data/lib/celerity.rb +75 -0
  17. data/lib/celerity/browser.rb +924 -0
  18. data/lib/celerity/clickable_element.rb +87 -0
  19. data/lib/celerity/collections.rb +164 -0
  20. data/lib/celerity/container.rb +802 -0
  21. data/lib/celerity/default_viewer.rb +14 -0
  22. data/lib/celerity/disabled_element.rb +40 -0
  23. data/lib/celerity/element.rb +314 -0
  24. data/lib/celerity/element_collection.rb +115 -0
  25. data/lib/celerity/element_locator.rb +164 -0
  26. data/lib/celerity/elements/button.rb +54 -0
  27. data/lib/celerity/elements/file_field.rb +29 -0
  28. data/lib/celerity/elements/form.rb +22 -0
  29. data/lib/celerity/elements/frame.rb +86 -0
  30. data/lib/celerity/elements/image.rb +89 -0
  31. data/lib/celerity/elements/label.rb +16 -0
  32. data/lib/celerity/elements/link.rb +43 -0
  33. data/lib/celerity/elements/meta.rb +14 -0
  34. data/lib/celerity/elements/non_control_elements.rb +124 -0
  35. data/lib/celerity/elements/option.rb +38 -0
  36. data/lib/celerity/elements/radio_check.rb +114 -0
  37. data/lib/celerity/elements/select_list.rb +146 -0
  38. data/lib/celerity/elements/table.rb +154 -0
  39. data/lib/celerity/elements/table_cell.rb +36 -0
  40. data/lib/celerity/elements/table_elements.rb +42 -0
  41. data/lib/celerity/elements/table_row.rb +54 -0
  42. data/lib/celerity/elements/text_field.rb +168 -0
  43. data/lib/celerity/exception.rb +83 -0
  44. data/lib/celerity/htmlunit.rb +64 -0
  45. data/lib/celerity/htmlunit/commons-codec-1.4.jar +0 -0
  46. data/lib/celerity/htmlunit/commons-collections-3.2.1.jar +0 -0
  47. data/lib/celerity/htmlunit/commons-io-2.0.1.jar +0 -0
  48. data/lib/celerity/htmlunit/commons-lang3-3.0.1.jar +0 -0
  49. data/lib/celerity/htmlunit/commons-logging-1.1.1.jar +0 -0
  50. data/lib/celerity/htmlunit/cssparser-0.9.6-20110829.205617-3.jar +0 -0
  51. data/lib/celerity/htmlunit/htmlunit-2.10-SNAPSHOT.jar +0 -0
  52. data/lib/celerity/htmlunit/htmlunit-core-js-2.9.jar +0 -0
  53. data/lib/celerity/htmlunit/httpclient-4.1.2.jar +0 -0
  54. data/lib/celerity/htmlunit/httpcore-4.1.2.jar +0 -0
  55. data/lib/celerity/htmlunit/httpmime-4.1.2.jar +0 -0
  56. data/lib/celerity/htmlunit/nekohtml-1.9.15.jar +0 -0
  57. data/lib/celerity/htmlunit/sac-1.3.jar +0 -0
  58. data/lib/celerity/htmlunit/serializer-2.7.1.jar +0 -0
  59. data/lib/celerity/htmlunit/xalan-2.7.1.jar +0 -0
  60. data/lib/celerity/htmlunit/xercesImpl-2.9.1.jar +0 -0
  61. data/lib/celerity/htmlunit/xml-apis-1.3.04.jar +0 -0
  62. data/lib/celerity/identifier.rb +28 -0
  63. data/lib/celerity/ignoring_web_connection.rb +15 -0
  64. data/lib/celerity/input_element.rb +25 -0
  65. data/lib/celerity/javascript_debugger.rb +32 -0
  66. data/lib/celerity/listener.rb +143 -0
  67. data/lib/celerity/resources/no_viewer.png +0 -0
  68. data/lib/celerity/short_inspect.rb +20 -0
  69. data/lib/celerity/util.rb +129 -0
  70. data/lib/celerity/version.rb +3 -0
  71. data/lib/celerity/viewer_connection.rb +89 -0
  72. data/lib/celerity/watir_compatibility.rb +70 -0
  73. data/lib/celerity/xpath_support.rb +50 -0
  74. data/spec/browser_authentication_spec.rb +16 -0
  75. data/spec/browser_spec.rb +428 -0
  76. data/spec/button_spec.rb +24 -0
  77. data/spec/clickable_element_spec.rb +39 -0
  78. data/spec/default_viewer_spec.rb +23 -0
  79. data/spec/element_spec.rb +77 -0
  80. data/spec/filefield_spec.rb +18 -0
  81. data/spec/htmlunit_spec.rb +63 -0
  82. data/spec/implementation.rb +7 -0
  83. data/spec/index_offset_spec.rb +24 -0
  84. data/spec/link_spec.rb +16 -0
  85. data/spec/listener_spec.rb +142 -0
  86. data/spec/spec_helper.rb +6 -0
  87. data/spec/table_spec.rb +41 -0
  88. data/spec/watir_compatibility_spec.rb +32 -0
  89. data/tasks/benchmark.rake +4 -0
  90. data/tasks/check.rake +24 -0
  91. data/tasks/clean.rake +3 -0
  92. data/tasks/fix.rake +25 -0
  93. data/tasks/jar.rake +55 -0
  94. data/tasks/rdoc.rake +4 -0
  95. data/tasks/snapshot.rake +25 -0
  96. data/tasks/spec.rake +27 -0
  97. data/tasks/website.rake +10 -0
  98. data/tasks/yard.rake +16 -0
  99. data/website/benchmarks.html +237 -0
  100. data/website/css/color.css +153 -0
  101. data/website/css/hacks.css +3 -0
  102. data/website/css/layout.css +179 -0
  103. data/website/css/screen.css +5 -0
  104. data/website/css/textmate.css +226 -0
  105. data/website/css/typography.css +72 -0
  106. data/website/gfx/body_bg.gif +0 -0
  107. data/website/gfx/button_bg.jpg +0 -0
  108. data/website/gfx/header_bg.jpg +0 -0
  109. data/website/gfx/header_left.jpg +0 -0
  110. data/website/gfx/header_right.jpg +0 -0
  111. data/website/gfx/nav_bg.jpg +0 -0
  112. data/website/index.html +125 -0
  113. data/website/yard/index.html +1 -0
  114. metadata +224 -0
@@ -0,0 +1,129 @@
1
+ module Celerity
2
+ module Util
3
+ module_function
4
+
5
+ HtmlUnit2CelerityElement = {
6
+ HtmlUnit::Html::HtmlAnchor => Celerity::Link,
7
+ HtmlUnit::Html::HtmlArea => Celerity::Area,
8
+ HtmlUnit::Html::HtmlButton => Celerity::Button,
9
+ HtmlUnit::Html::HtmlSubmitInput => Celerity::Button,
10
+ HtmlUnit::Html::HtmlResetInput => Celerity::Button,
11
+ HtmlUnit::Html::HtmlImageInput => Celerity::Button,
12
+ HtmlUnit::Html::HtmlButtonInput => Celerity::Button,
13
+ HtmlUnit::Html::HtmlCaption => Celerity::Button, # ?
14
+ HtmlUnit::Html::HtmlCheckBoxInput => Celerity::CheckBox,
15
+ HtmlUnit::Html::HtmlDefinitionDescription => Celerity::Dd,
16
+ HtmlUnit::Html::HtmlDefinitionList => Celerity::Dl,
17
+ HtmlUnit::Html::HtmlDefinitionTerm => Celerity::Dt,
18
+ HtmlUnit::Html::HtmlDeletedText => Celerity::Del,
19
+ HtmlUnit::Html::HtmlDivision => Celerity::Div,
20
+ HtmlUnit::Html::HtmlFileInput => Celerity::FileField,
21
+ HtmlUnit::Html::HtmlForm => Celerity::Form,
22
+ HtmlUnit::Html::HtmlFrame => Celerity::Frame,
23
+ HtmlUnit::Html::HtmlHeading1 => Celerity::H1,
24
+ HtmlUnit::Html::HtmlHeading2 => Celerity::H2,
25
+ HtmlUnit::Html::HtmlHeading3 => Celerity::H3,
26
+ HtmlUnit::Html::HtmlHeading4 => Celerity::H4,
27
+ HtmlUnit::Html::HtmlHeading5 => Celerity::H5,
28
+ HtmlUnit::Html::HtmlHeading6 => Celerity::H6,
29
+ HtmlUnit::Html::HtmlHiddenInput => Celerity::Hidden,
30
+ HtmlUnit::Html::HtmlImage => Celerity::Image,
31
+ HtmlUnit::Html::HtmlLabel => Celerity::Label,
32
+ HtmlUnit::Html::HtmlListItem => Celerity::Li,
33
+ HtmlUnit::Html::HtmlMap => Celerity::Map,
34
+ HtmlUnit::Html::HtmlOption => Celerity::Option,
35
+ HtmlUnit::Html::HtmlOrderedList => Celerity::Ol,
36
+ HtmlUnit::Html::HtmlParagraph => Celerity::P,
37
+ HtmlUnit::Html::HtmlPasswordInput => Celerity::TextField,
38
+ HtmlUnit::Html::HtmlPreformattedText => Celerity::Pre,
39
+ HtmlUnit::Html::HtmlRadioButtonInput => Celerity::Radio,
40
+ HtmlUnit::Html::HtmlSelect => Celerity::SelectList,
41
+ HtmlUnit::Html::HtmlSpan => Celerity::Span,
42
+ HtmlUnit::Html::HtmlTable => Celerity::Table,
43
+ HtmlUnit::Html::HtmlTableBody => Celerity::TableBody,
44
+ HtmlUnit::Html::HtmlTableCell => Celerity::TableCell,
45
+ HtmlUnit::Html::HtmlTableDataCell => Celerity::TableCell,
46
+ HtmlUnit::Html::HtmlTableFooter => Celerity::TableFooter,
47
+ HtmlUnit::Html::HtmlTableHeader => Celerity::TableHeader,
48
+ HtmlUnit::Html::HtmlTableRow => Celerity::TableRow,
49
+ HtmlUnit::Html::HtmlTextArea => Celerity::TextField,
50
+ HtmlUnit::Html::HtmlTextInput => Celerity::TextField,
51
+ HtmlUnit::Html::HtmlUnorderedList => Celerity::Ul,
52
+ HtmlUnit::Html::HtmlInsertedText => Celerity::Ins
53
+ }
54
+
55
+ def htmlunit2celerity(klass)
56
+ HtmlUnit2CelerityElement[klass]
57
+ end
58
+
59
+ #
60
+ # HtmlUnit will recognize most common file types, but custom ones can be added here.
61
+ # Used for FileField uploads.
62
+ #
63
+
64
+ ContentTypes = {
65
+ ".bmp" => "image/x-ms-bmp",
66
+ ".doc" => "application/msword",
67
+ ".odg" => "application/vnd.oasis.opendocument.graphics",
68
+ ".odp" => "application/vnd.oasis.opendocument.presentation",
69
+ ".ods" => "application/vnd.oasis.opendocument.spreadsheet",
70
+ ".odt" => "application/vnd.oasis.opendocument.text",
71
+ ".ppt" => "application/vnd.ms-powerpoint",
72
+ ".xls" => "application/vnd.ms-excel",
73
+ }
74
+
75
+ def content_type_for(path)
76
+ if ct = java.net.URLConnection.getFileNameMap.getContentTypeFor(path)
77
+ return ct
78
+ else
79
+ ContentTypes[File.extname(path).downcase]
80
+ end
81
+ end
82
+
83
+ def normalize_text(string)
84
+ string.gsub("\302\240", ' '). # non-breaking space 00A0
85
+ gsub(/\n|\t/, ''). # get rid of newlines/tabs
86
+ strip
87
+ end
88
+
89
+ def logger_for(package_string)
90
+ java.util.logging.Logger.getLogger(package_string)
91
+ end
92
+
93
+ # number of spaces that separate the property from the value in the create_string method
94
+ TO_S_SIZE = 14
95
+
96
+ def create_string(element)
97
+ ret = []
98
+
99
+ unless (tag = element.getTagName).empty?
100
+ ret << "tag:".ljust(TO_S_SIZE) + tag
101
+ end
102
+
103
+ element.getAttributes.each do |_, attribute|
104
+ ret << " #{attribute.getName}:".ljust(TO_S_SIZE + 2) + attribute.getValue.to_s
105
+ end
106
+
107
+ unless (text = element.asText).empty?
108
+ ret << " text:".ljust(TO_S_SIZE + 2) + element.asText
109
+ end
110
+
111
+ ret.join("\n")
112
+ end
113
+
114
+ #
115
+ # Used internally.
116
+ #
117
+ # @param [String] string The string to match against.
118
+ # @param [Regexp, String, #to_s] what The match we're looking for.
119
+ # @return [Fixnum, true, false, nil]
120
+ #
121
+ # @api private
122
+ #
123
+
124
+ def matches?(string, what)
125
+ Regexp === what ? string.strip =~ what : string == what.to_s
126
+ end
127
+
128
+ end
129
+ end
@@ -0,0 +1,3 @@
1
+ module Celerity
2
+ VERSION = "0.9.0"
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
@@ -0,0 +1,70 @@
1
+ module Celerity
2
+ class Browser
3
+ class << self
4
+
5
+ # Added for Watir compatibility - not in use by Celerity
6
+ attr_accessor :speed, :attach_timeout, :visible
7
+ # Added for Watir compatibility - not in use by Celerity
8
+ alias_method :start_window, :start
9
+ # Added for Watir compatibility - not in use by Celerity
10
+ def each; end
11
+ end
12
+
13
+ # Added for Watir compatibility - not in use by Celerity
14
+ attr_accessor :visible
15
+
16
+ # Added for Watir compatibility - not in use by Celerity
17
+ def bring_to_front; true; end
18
+ # Added for Watir compatibility - not in use by Celerity
19
+ def speed=(s); s end
20
+ end
21
+
22
+
23
+ module ClickableElement
24
+ alias_method :click_no_wait, :click
25
+ end
26
+
27
+ module Container
28
+ alias_method :checkbox, :check_box
29
+ alias_method :checkBox, :check_box
30
+ alias_method :body, :tbody
31
+ alias_method :bodies, :tbodies
32
+ end
33
+
34
+ class Element
35
+ alias_method :exists, :exists?
36
+ alias_method :innerText, :text
37
+ alias_method :inner_text, :text
38
+ end
39
+
40
+ class Image
41
+ alias_method :hasLoaded?, :loaded?
42
+ alias_method :fileSize, :file_size
43
+ alias_method :fileCreatedDate, :file_created_date
44
+ end
45
+
46
+ class Link
47
+ alias_method :click_no_wait, :click
48
+ end
49
+
50
+ class RadioCheckCommon
51
+ alias_method :isSet?, :set?
52
+ alias_method :getState, :set?
53
+ end
54
+
55
+ class SelectList
56
+ alias_method :getSelectedItems, :selected_options
57
+ alias_method :getAllContents, :options
58
+ alias_method :clearSelection, :clear
59
+ alias_method :includes?, :include?
60
+ end
61
+
62
+ class TextField
63
+ alias_method :dragContentsTo, :drag_contents_to
64
+ alias_method :getContents, :value
65
+
66
+ def requires_typing; end
67
+ end
68
+ end
69
+
70
+ Celerity::IE = Celerity::Browser
@@ -0,0 +1,50 @@
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, ":xpath and #{xpath.inspect}")
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) }
34
+ end
35
+
36
+ #
37
+ # Convert the given HtmlUnit DomNode to a Celerity object
38
+ #
39
+
40
+ def element_from_dom_node(obj, identifier_string = nil)
41
+ element_class = Util.htmlunit2celerity(obj.class) || Element
42
+ element = element_class.new(self, :object, obj)
43
+
44
+ element.identifier_string = identifier_string
45
+ element.extend(ClickableElement) unless element.is_a?(ClickableElement)
46
+
47
+ element
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,16 @@
1
+ require File.expand_path("../watirspec/spec_helper", __FILE__)
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,428 @@
1
+ require File.expand_path("../watirspec/spec_helper", __FILE__)
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.implementation.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
+ port = WatirSpec::Server.find_free_port_above(2001)
32
+
33
+ s = WEBrick::HTTPProxyServer.new(:Port => port,
34
+ :ProxyContentHandler => blk)
35
+ Thread.new { s.start }
36
+
37
+ opts = WatirSpec.implementation.browser_args.first.merge(:proxy => "localhost:#{port}")
38
+
39
+ begin
40
+ b = Browser.new(opts)
41
+ b.goto(WatirSpec.host)
42
+ ensure
43
+ s.shutdown
44
+ b.close if b
45
+ end
46
+
47
+ received.should be_true
48
+ end
49
+
50
+ it "should use the specified user agent" do
51
+ opts = WatirSpec.implementation.browser_args.first.merge(:user_agent => "Celerity")
52
+
53
+ b = Browser.new(opts)
54
+
55
+ begin
56
+ b.goto(WatirSpec.host + "/header_echo")
57
+ b.text.should include('"HTTP_USER_AGENT"=>"Celerity"')
58
+ ensure
59
+ b.close
60
+ end
61
+ end
62
+
63
+ it "does not try to find a viewer if created with :viewer => false" do
64
+ ViewerConnection.should_not_receive(:create)
65
+
66
+ Browser.new(:viewer => false).close
67
+ end
68
+
69
+ it "tries to find a viewer if created with :viewer => nil" do
70
+ ViewerConnection.should_receive(:create).with("127.0.0.1", 6429)
71
+
72
+ Browser.new(:viewer => nil).close
73
+ end
74
+
75
+ it "tries to find a viewer on the specified host/port with :viewer => String" do
76
+ ViewerConnection.should_receive(:create).with("localhost", 1234)
77
+
78
+ Browser.new(:viewer => "localhost:1234").close
79
+ end
80
+
81
+ it "should use the specified cache limit" do
82
+ opts = WatirSpec.implementation.browser_args.first.merge(:cache_limit => 100)
83
+ b = Browser.new(opts)
84
+
85
+ begin
86
+ b.cache_limit.should == 100
87
+ ensure
88
+ b.close
89
+ end
90
+ end
91
+
92
+ it "should use the Firefox 3 browser version when specified" do
93
+ Browser.new(:browser => :firefox).webclient.browser_version.nickname.should == "FF3"
94
+ Browser.new(:browser => :firefox3).webclient.browser_version.nickname.should == "FF3"
95
+ end
96
+
97
+ it "should use the Firefox 3.6 browser version when specified" do
98
+ Browser.new(:browser => :firefox_3_6).webclient.browser_version.nickname.should == "FF3.6"
99
+ Browser.new(:browser => :ff36).webclient.browser_version.nickname.should == "FF3.6"
100
+ end
101
+
102
+ it "should use the Internet Explorer 7 browser version when specified" do
103
+ Browser.new(:browser => :internet_explorer).webclient.browser_version.nickname.should == "IE7"
104
+ Browser.new(:browser => :internet_explorer7).webclient.browser_version.nickname.should == "IE7"
105
+ Browser.new(:browser => :internet_explorer_7).webclient.browser_version.nickname.should == "IE7"
106
+ Browser.new(:browser => :ie).webclient.browser_version.nickname.should == "IE7"
107
+ end
108
+
109
+ it "should use the Internet Explorer 8 browser version when specified" do
110
+ Browser.new(:browser => :internet_explorer_8).webclient.browser_version.nickname.should == "IE8"
111
+ Browser.new(:browser => :ie8).webclient.browser_version.nickname.should == "IE8"
112
+ end
113
+
114
+ it "should turn off CSS" do
115
+ b = Browser.new(:css => false)
116
+ b.css.should be_false
117
+ end
118
+
119
+ end
120
+
121
+ describe "#html" do
122
+ %w(shift_jis iso-2022-jp euc-jp).each do |charset|
123
+ it "returns decoded #{charset.upcase} when :charset specified" do
124
+ opts = WatirSpec.implementation.browser_args.first.merge(:charset => charset.upcase)
125
+ browser = Browser.new(opts)
126
+
127
+ begin
128
+ browser.goto(WatirSpec.files + "/#{charset}_text.html")
129
+ # Browser#text is automagically transcoded into the right charset, but Browser#html isn't.
130
+ browser.html.should =~ /本日は晴天なり。/
131
+ ensure
132
+ browser.close
133
+ end
134
+ end
135
+ end
136
+
137
+ it "does not fail for huge pages" do
138
+ browser.goto WatirSpec.host + "/big"
139
+ browser.html.should include("hello</body>")
140
+ end
141
+ end
142
+
143
+ describe "#text" do
144
+ it "does not fail for huge pages" do
145
+ browser.goto WatirSpec.host + "/big"
146
+ browser.text.should include("hello")
147
+ end
148
+ end
149
+
150
+ describe "#response_headers" do
151
+ it "returns the response headers (as a hash)" do
152
+ browser.goto(WatirSpec.host + "/non_control_elements.html")
153
+ browser.response_headers.should be_kind_of(Hash)
154
+ browser.response_headers['Date'].should be_kind_of(String)
155
+ browser.response_headers['Content-Type'].should be_kind_of(String)
156
+ end
157
+ end
158
+
159
+ describe "#content_type" do
160
+ it "returns the content type" do
161
+ browser.goto(WatirSpec.host + "/non_control_elements.html")
162
+ browser.content_type.should =~ /\w+\/\w+/
163
+ end
164
+ end
165
+
166
+ describe "#io" do
167
+ it "returns the io object of the content" do
168
+ browser.goto(WatirSpec.files + "/non_control_elements.html")
169
+ browser.io.should be_kind_of(IO)
170
+ browser.io.read.should == File.read("#{WatirSpec.html}/non_control_elements.html")
171
+ end
172
+ end
173
+
174
+ describe "#goto" do
175
+ it "raises UnexpectedPageException if the content type is not understood" do
176
+ lambda { browser.goto(WatirSpec.host + "/octet_stream") }.should raise_error(UnexpectedPageException)
177
+ end
178
+
179
+ it "takes a 2nd argument of headers" do
180
+ browser.goto(WatirSpec.host + "/header_echo", {'Accept-Language'=>'fr','Accept'=>'application/json'})
181
+ browser.text.should include('"HTTP_ACCEPT"=>"application/json"')
182
+ browser.text.should include('"HTTP_ACCEPT_LANGUAGE"=>"fr"')
183
+ end
184
+ end
185
+
186
+ describe "#cookies" do
187
+ it "returns set cookies as a Ruby hash" do
188
+ browser = WatirSpec.new_browser
189
+ begin
190
+ browser.cookies.should == {}
191
+
192
+ browser.goto(WatirSpec.host + "/set_cookie")
193
+
194
+ cookies = browser.cookies
195
+ cookies.size.should == 1
196
+ cookies[WatirSpec::Server.bind]['monster'].should == "/"
197
+ ensure
198
+ browser.close
199
+ end
200
+ end
201
+ end
202
+
203
+ describe "#clear_cookies" do
204
+ it "clears all cookies" do
205
+ b = WatirSpec.new_browser
206
+
207
+ begin
208
+ b.cookies.should be_empty
209
+
210
+ b.goto(WatirSpec.host + "/set_cookie")
211
+ b.cookies.size.should == 1
212
+ b.clear_cookies
213
+ b.cookies.should be_empty
214
+ ensure
215
+ b.close
216
+ end
217
+ end
218
+ end
219
+
220
+ describe "add_cookie" do
221
+ it "adds a cookie with the given domain, name and value" do
222
+ begin
223
+ browser.add_cookie("example.com", "foo", "bar")
224
+ cookies = browser.cookies
225
+ cookies.should be_instance_of(Hash)
226
+ cookies.should have_key('example.com')
227
+ cookies['example.com']['foo'].should == 'bar'
228
+ ensure
229
+ browser.clear_cookies
230
+ end
231
+ end
232
+
233
+ it "adds a cookie with the specified options" do
234
+ begin
235
+ browser.add_cookie("example.com", "foo", "bar", :path => "/foobar", :expires => Time.now + 100000)
236
+ cookies = browser.cookies
237
+ cookies.should be_instance_of(Hash)
238
+ cookies['example.com']['foo'].should == 'bar'
239
+ ensure
240
+ browser.clear_cookies
241
+ end
242
+ end
243
+ end
244
+
245
+ describe "remove_cookie" do
246
+ it "removes the cookie for the given domain and name" do
247
+ b = WatirSpec.new_browser
248
+ begin
249
+ b.goto(WatirSpec.host + "/set_cookie")
250
+
251
+ b.remove_cookie(WatirSpec::Server.bind, "monster")
252
+ b.cookies.should be_empty
253
+ ensure
254
+ b.close
255
+ end
256
+ end
257
+
258
+ it "raises an error if no such cookie exists" do
259
+ lambda { browser.remove_cookie("bogus.com", "bar") }.should raise_error(CookieNotFoundError)
260
+ end
261
+ end
262
+
263
+ describe "#wait" do
264
+ it "should wait for javascript timers to finish" do
265
+ alerts = 0
266
+ browser.add_listener(:alert) { alerts += 1 }
267
+ browser.goto(WatirSpec.files + "/timeout.html")
268
+ browser.div(:id, 'alert').click
269
+ browser.wait.should be_true
270
+ alerts.should == 1
271
+ end
272
+
273
+ it "should pass the correct args to webclient" do
274
+ browser.webclient.should_receive(:waitForBackgroundJavaScript).with(10000)
275
+ browser.wait
276
+
277
+ browser.webclient.should_receive(:waitForBackgroundJavaScript).with(3000)
278
+ browser.wait(3)
279
+ end
280
+
281
+ end
282
+
283
+ describe "#wait_while" do
284
+ it "waits until the specified condition becomes false" do
285
+ browser.goto(WatirSpec.files + "/timeout.html")
286
+ browser.div(:id, "change").click
287
+ browser.wait_while { browser.contains_text("Trigger change") }
288
+ browser.div(:id, "change").text.should == "all done"
289
+ end
290
+
291
+ it "returns the value returned from the block" do
292
+ browser.wait_while { false }.should == false
293
+ end
294
+ end
295
+
296
+ describe "#wait_until" do
297
+ it "waits until the condition becomes true" do
298
+ browser.goto(WatirSpec.files + "/timeout.html")
299
+ browser.div(:id, "change").click
300
+ browser.wait_until { browser.contains_text("all done") }
301
+ end
302
+
303
+ it "returns the value returned from the block" do
304
+ browser.wait_until { true }.should == true
305
+ end
306
+ end
307
+
308
+ describe "#element_by_xpath" do
309
+ it "returns usable elements even though they're not supported" do
310
+ browser.goto(WatirSpec.files + "/forms_with_input_elements.html")
311
+
312
+ el = browser.element_by_xpath("//link")
313
+ el.should be_instance_of(Celerity::Element)
314
+ el.should be_kind_of(Celerity::ClickableElement)
315
+ el.rel.should == "stylesheet"
316
+ end
317
+
318
+ it "includes the xpath in an exception message" do
319
+ browser.goto(WatirSpec.files + "/forms_with_input_elements.html")
320
+
321
+ the_xpath = "//div[contains(@class, 'this does not exist')]"
322
+ el = browser.element_by_xpath(the_xpath)
323
+
324
+ lambda { el.visible? }.should raise_error(
325
+ Celerity::Exception::UnknownObjectException, Regexp.new(Regexp.escape(the_xpath)))
326
+ end
327
+ end
328
+
329
+ describe "#focused_element" do
330
+ it "returns the element that currently has the focus" do
331
+ b = WatirSpec.new_browser
332
+ b.goto(WatirSpec.files + "/forms_with_input_elements.html")
333
+ b.focused_element.id.should == "new_user_first_name"
334
+
335
+ b.close
336
+ end
337
+ end
338
+
339
+ describe "#status_code" do
340
+ it "returns the status code of the last request" do
341
+ browser.goto(WatirSpec.files + "/forms_with_input_elements.html")
342
+ browser.status_code.should == 200
343
+
344
+ browser.goto(WatirSpec.host + "/doesnt_exist")
345
+ browser.status_code.should == 404
346
+ end
347
+ end
348
+
349
+ describe "#status_code_exceptions" do
350
+ it "raises status code exceptions if set to true" do
351
+ browser.status_code_exceptions = true
352
+ lambda do
353
+ browser.goto(WatirSpec.host + "/doesnt_exist")
354
+ end.should raise_error(NavigationException)
355
+ end
356
+ end
357
+
358
+ describe "#javascript_exceptions" do
359
+ it "raises javascript exceptions if set to true" do
360
+ browser.goto(WatirSpec.files + "/forms_with_input_elements.html")
361
+ browser.javascript_exceptions = true
362
+ lambda do
363
+ browser.execute_script("no_such_function()")
364
+ end.should raise_error
365
+ end
366
+ end
367
+
368
+ describe "#add_listener" do
369
+ it "should click OK for confirm() calls" do
370
+ browser.goto(WatirSpec.files + "/forms_with_input_elements.html")
371
+ browser.add_listener(:confirm) { }
372
+ browser.execute_script("confirm()").should == true
373
+ end
374
+ end
375
+
376
+ describe "#remove_listener" do
377
+ it "should remove the given listener Proc" do
378
+ browser.goto(WatirSpec.files + "/forms_with_input_elements.html")
379
+
380
+ called = false
381
+ listener = lambda { called = true }
382
+
383
+ browser.add_listener(:alert, &listener)
384
+ browser.execute_script("alert('foo')")
385
+ called.should be_true
386
+
387
+ called = false
388
+ browser.remove_listener(:alert, listener)
389
+ browser.execute_script("alert('foo')")
390
+ called.should be_false
391
+ end
392
+ end
393
+
394
+ describe "#add_checker" do
395
+
396
+ # watir only supports a lambda instance as argument, celerity supports both
397
+ it "runs the given block on each page load" do
398
+ output = ''
399
+
400
+ browser.add_checker { |browser| output << browser.text }
401
+ browser.goto(WatirSpec.files + "/non_control_elements.html")
402
+
403
+ output.should include('Dubito, ergo cogito, ergo sum')
404
+ end
405
+ end
406
+
407
+
408
+ describe "#confirm" do
409
+ it "clicks 'OK' for a confirm() call" do
410
+ browser.goto(WatirSpec.files + "/forms_with_input_elements.html")
411
+
412
+ browser.confirm(true) do
413
+ browser.execute_script('confirm()').should be_true
414
+ end
415
+ end
416
+
417
+ it "clicks 'cancel' for a confirm() call" do
418
+ browser.goto(WatirSpec.files + "/forms_with_input_elements.html")
419
+
420
+ browser.confirm(false) do
421
+ browser.execute_script('confirm()').should be_false
422
+ end
423
+ end
424
+ end
425
+
426
+
427
+
428
+ end