ayanko-watir-webdriver 0.1.1.1

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 (74) hide show
  1. data/.document +5 -0
  2. data/.gitignore +5 -0
  3. data/.gitmodules +3 -0
  4. data/Gemfile +4 -0
  5. data/LICENSE +20 -0
  6. data/README.rdoc +55 -0
  7. data/Rakefile +139 -0
  8. data/VERSION +1 -0
  9. data/lib/watir-webdriver.rb +71 -0
  10. data/lib/watir-webdriver/attribute_helper.rb +128 -0
  11. data/lib/watir-webdriver/browser.rb +164 -0
  12. data/lib/watir-webdriver/browserbot.js +49 -0
  13. data/lib/watir-webdriver/cell_container.rb +19 -0
  14. data/lib/watir-webdriver/container.rb +40 -0
  15. data/lib/watir-webdriver/core_ext/string.rb +22 -0
  16. data/lib/watir-webdriver/element_collection.rb +96 -0
  17. data/lib/watir-webdriver/elements/button.rb +75 -0
  18. data/lib/watir-webdriver/elements/checkbox.rb +73 -0
  19. data/lib/watir-webdriver/elements/element.rb +265 -0
  20. data/lib/watir-webdriver/elements/file_field.rb +69 -0
  21. data/lib/watir-webdriver/elements/font.rb +11 -0
  22. data/lib/watir-webdriver/elements/form.rb +17 -0
  23. data/lib/watir-webdriver/elements/frame.rb +110 -0
  24. data/lib/watir-webdriver/elements/generated.rb +2541 -0
  25. data/lib/watir-webdriver/elements/hidden.rb +24 -0
  26. data/lib/watir-webdriver/elements/image.rb +51 -0
  27. data/lib/watir-webdriver/elements/input.rb +42 -0
  28. data/lib/watir-webdriver/elements/link.rb +7 -0
  29. data/lib/watir-webdriver/elements/option.rb +55 -0
  30. data/lib/watir-webdriver/elements/radio.rb +49 -0
  31. data/lib/watir-webdriver/elements/select.rb +216 -0
  32. data/lib/watir-webdriver/elements/table.rb +37 -0
  33. data/lib/watir-webdriver/elements/table_cell.rb +36 -0
  34. data/lib/watir-webdriver/elements/table_row.rb +45 -0
  35. data/lib/watir-webdriver/elements/table_section.rb +9 -0
  36. data/lib/watir-webdriver/elements/text_field.rb +97 -0
  37. data/lib/watir-webdriver/exception.rb +21 -0
  38. data/lib/watir-webdriver/extensions/alerts.rb +69 -0
  39. data/lib/watir-webdriver/extensions/cookies.rb +39 -0
  40. data/lib/watir-webdriver/extensions/firefox/webdriver.xpi +0 -0
  41. data/lib/watir-webdriver/extensions/nokogiri.rb +14 -0
  42. data/lib/watir-webdriver/extensions/performance.rb +54 -0
  43. data/lib/watir-webdriver/extensions/wait.rb +141 -0
  44. data/lib/watir-webdriver/html.rb +19 -0
  45. data/lib/watir-webdriver/html/generator.rb +112 -0
  46. data/lib/watir-webdriver/html/idl_sorter.rb +49 -0
  47. data/lib/watir-webdriver/html/spec_extractor.rb +111 -0
  48. data/lib/watir-webdriver/html/util.rb +22 -0
  49. data/lib/watir-webdriver/html/visitor.rb +174 -0
  50. data/lib/watir-webdriver/locators/button_locator.rb +74 -0
  51. data/lib/watir-webdriver/locators/child_cell_locator.rb +32 -0
  52. data/lib/watir-webdriver/locators/child_row_locator.rb +37 -0
  53. data/lib/watir-webdriver/locators/element_locator.rb +352 -0
  54. data/lib/watir-webdriver/locators/text_field_locator.rb +65 -0
  55. data/lib/watir-webdriver/row_container.rb +34 -0
  56. data/lib/watir-webdriver/window_switching.rb +105 -0
  57. data/lib/watir-webdriver/xpath_support.rb +28 -0
  58. data/lib/yard/handlers/watir.rb +57 -0
  59. data/spec/alert_spec.rb +49 -0
  60. data/spec/browser_spec.rb +42 -0
  61. data/spec/container_spec.rb +42 -0
  62. data/spec/element_locator_spec.rb +304 -0
  63. data/spec/element_spec.rb +13 -0
  64. data/spec/html/alerts.html +11 -0
  65. data/spec/html/keylogger.html +15 -0
  66. data/spec/html/wait.html +27 -0
  67. data/spec/implementation.rb +17 -0
  68. data/spec/input_spec.rb +39 -0
  69. data/spec/locator_spec_helper.rb +51 -0
  70. data/spec/spec_helper.rb +14 -0
  71. data/spec/wait_spec.rb +98 -0
  72. data/support/html5.html +90243 -0
  73. data/watir-webdriver.gemspec +59 -0
  74. metadata +238 -0
@@ -0,0 +1,37 @@
1
+ # encoding: utf-8
2
+
3
+ module Watir
4
+ class Table < HTMLElement
5
+ include RowContainer
6
+
7
+ def hashes
8
+ all_rows = rows.to_a
9
+ header_row = all_rows.shift or raise Exception::Error, "no rows in table"
10
+
11
+ headers = header_row.ths.map { |header_cell| header_cell.text }
12
+ result = []
13
+
14
+ all_rows.each_with_index do |row, idx|
15
+ cells = row.cells.to_a
16
+ if cells.length != headers.length
17
+ raise Exception::Error, "row at index #{idx} has #{cells.length} cells, expected #{headers.length}"
18
+ end
19
+
20
+ result << headers.inject({}) { |res, header| res.merge(header => cells.shift.text) }
21
+ end
22
+
23
+ result
24
+ end
25
+
26
+ #
27
+ # Get the n'th row of this table.
28
+ #
29
+ # @return Watir::TableRow
30
+ #
31
+
32
+ def [](idx)
33
+ row(:index, idx)
34
+ end
35
+
36
+ end # Table
37
+ end # Watir
@@ -0,0 +1,36 @@
1
+ module Watir
2
+ class TableCell < HTMLElement
3
+ # @private
4
+ attr_writer :locator_class
5
+
6
+ def locator_class
7
+ @locator_class || super
8
+ end
9
+
10
+ def colspan
11
+ value = attribute_value :colspan
12
+ value ? Integer(value) : 1
13
+ end
14
+ end
15
+
16
+ class TableCellCollection < ElementCollection
17
+ attr_writer :locator_class
18
+
19
+ def locator_class
20
+ @locator_class || super
21
+ end
22
+
23
+ def elements
24
+ # we do this craziness since the xpath used will find direct child rows
25
+ # before any rows inside thead/tbody/tfoot...
26
+ elements = super
27
+
28
+ if locator_class == ChildCellLocator
29
+ elements = elements.sort_by { |row| row.attribute(:cellIndex).to_i }
30
+ end
31
+
32
+ elements
33
+ end
34
+
35
+ end
36
+ end
@@ -0,0 +1,45 @@
1
+ module Watir
2
+ class TableRow < HTMLElement
3
+ include CellContainer
4
+
5
+ # @private
6
+ attr_writer :locator_class
7
+
8
+ #
9
+ # Get the n'th cell (<th> or <td>) of this row
10
+ #
11
+ # @return Watir::TableCell
12
+ #
13
+
14
+ def [](idx)
15
+ cell(:index, idx)
16
+ end
17
+
18
+ private
19
+
20
+ def locator_class
21
+ @locator_class || super
22
+ end
23
+ end # TableRow
24
+
25
+
26
+ class TableRowCollection < ElementCollection
27
+ attr_writer :locator_class
28
+
29
+ def elements
30
+ # we do this craziness since the xpath used will find direct child rows
31
+ # before any rows inside thead/tbody/tfoot...
32
+ elements = super
33
+
34
+ if locator_class == ChildRowLocator and @parent.kind_of? Table
35
+ elements = elements.sort_by { |row| row.attribute(:rowIndex).to_i }
36
+ end
37
+
38
+ elements
39
+ end
40
+
41
+ def locator_class
42
+ @locator_class || super
43
+ end
44
+ end # TableRowCollection
45
+ end # Watir
@@ -0,0 +1,9 @@
1
+ module Watir
2
+ class TableSection < HTMLElement
3
+ include RowContainer
4
+
5
+ def [](idx)
6
+ row(:index => idx)
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,97 @@
1
+ # encoding: utf-8
2
+ module Watir
3
+ class TextField < Input
4
+
5
+ attributes Watir::TextArea.typed_attributes
6
+ remove_method :type # we want Input#type here, which was overriden by TextArea's attributes
7
+
8
+ def self.from(parent, element)
9
+ type = element.attribute(:type)
10
+
11
+ if TextFieldLocator::NON_TEXT_TYPES.include?(type)
12
+ raise TypeError, "expected type != #{type} for #{element.inspect}"
13
+ end
14
+
15
+ super
16
+ end
17
+
18
+ #
19
+ # Clear the element, the type in the given value.
20
+ #
21
+
22
+ def set(*args)
23
+ assert_exists
24
+ assert_writable
25
+
26
+ @element.clear
27
+ @element.send_keys(*args)
28
+ end
29
+ alias_method :value=, :set
30
+
31
+ #
32
+ # Append the given value to the text in the text field.
33
+ #
34
+
35
+ def append(*args)
36
+ assert_exists
37
+ assert_writable
38
+
39
+ @element.send_keys(*args)
40
+ end
41
+
42
+ #
43
+ # Clear the text field.
44
+ #
45
+
46
+ def clear
47
+ assert_exists
48
+ @element.clear
49
+ end
50
+
51
+ #
52
+ # Returns the text in the text field.
53
+ #
54
+
55
+ def value
56
+ # since 'value' is an attribute on input fields, we override this here
57
+ assert_exists
58
+ @element.value
59
+ end
60
+
61
+ private
62
+
63
+ def locate
64
+ @parent.assert_exists
65
+ TextFieldLocator.new(@parent.wd, @selector, self.class.attribute_list).locate
66
+ end
67
+
68
+ def selector_string
69
+ selector = @selector.dup
70
+ selector[:type] = '(any text type)'
71
+ selector[:tag_name] = "input or textarea"
72
+ selector.inspect
73
+ end
74
+ end
75
+
76
+ module Container
77
+ def text_field(*args)
78
+ TextField.new(self, extract_selector(args).merge(:tag_name => "input"))
79
+ end
80
+
81
+ def text_fields(*args)
82
+ TextFieldCollection.new(self, extract_selector(args).merge(:tag_name => "input"))
83
+ end
84
+ end # Container
85
+
86
+ class TextFieldCollection < InputCollection
87
+ private
88
+
89
+ def locator_class
90
+ TextFieldLocator
91
+ end
92
+
93
+ def element_class
94
+ TextField
95
+ end
96
+ end # TextFieldCollection
97
+ end
@@ -0,0 +1,21 @@
1
+ # encoding: utf-8
2
+
3
+ module Watir
4
+ module Exception
5
+ class Error < StandardError; end
6
+
7
+ # TODO: rename Object -> Element?
8
+ class UnknownObjectException < Error; end
9
+ class ObjectDisabledException < Error; end
10
+ class ObjectReadOnlyException < Error; end
11
+ class NoValueFoundException < Error; end
12
+ class MissingWayOfFindingObjectException < Error; end
13
+ class UnknownCellException < Error; end
14
+ class NoMatchingWindowFoundException < Error; end
15
+ class NoStatusBarException < Error; end
16
+ class NavigationException < Error; end
17
+ class UnknownFrameException < Error; end
18
+ class UnknownRowException < Error; end
19
+
20
+ end # Exception
21
+ end # Watir
@@ -0,0 +1,69 @@
1
+ module Watir
2
+
3
+ #
4
+ # Module provided by optional require:
5
+ #
6
+ # require "watir-webdriver/extensions/alerts"
7
+ #
8
+
9
+ module AlertHelper
10
+
11
+ #
12
+ # Overwrite window.alert()
13
+ #
14
+ # This method is provided by an optional require - API is subject to change.
15
+ #
16
+ # @example
17
+ # browser.alert do
18
+ # browser.button(:value => "Alert").click
19
+ # end #=> "the alert message"
20
+ #
21
+
22
+ def alert(&blk)
23
+ execute_script "window.alert = function(msg) { window.__lastWatirAlert = msg; }"
24
+ yield
25
+ execute_script "return window.__lastWatirAlert"
26
+ end
27
+
28
+ #
29
+ # Overwrite window.confirm()
30
+ #
31
+ # This method is provided by an optional require - API is subject to change.
32
+ #
33
+ # @example
34
+ # browser.confirm(true) do
35
+ # browser.button(:value => "Confirm").click
36
+ # end #=> "the confirm message"
37
+
38
+ def confirm(bool, &blk)
39
+ execute_script "window.confirm = function(msg) { window.__lastWatirConfirm = msg; return #{!!bool} }"
40
+ yield
41
+ execute_script "return window.__lastWatirConfirm"
42
+ end
43
+
44
+ #
45
+ # Overwrite window.prompt()
46
+ #
47
+ # This method is provided by an optional require - API is subject to change.
48
+ #
49
+ # @example
50
+ # browser.prompt("hello") do
51
+ # browser.button(:value => "Prompt").click
52
+ # end #=> { :message => "foo", :default => "bar" }
53
+ #
54
+
55
+ def prompt(answer, &blk)
56
+ execute_script "window.prompt = function(text, value) { window.__lastWatirPrompt = { message: text, default: value }; return #{answer.to_json}; }"
57
+ yield
58
+ result = execute_script "return window.__lastWatirPrompt"
59
+
60
+ result && result.dup.each_key { |k| result[k.to_sym] = result.delete(k)}
61
+ result
62
+ end
63
+ end
64
+
65
+ class Browser
66
+ include AlertHelper
67
+ end
68
+
69
+ end
@@ -0,0 +1,39 @@
1
+ module Watir
2
+ class Browser
3
+
4
+ def clear_all_cookies
5
+ @driver.manage.clear_cookies
6
+ end
7
+
8
+ end
9
+ end
10
+
11
+
12
+ module Selenium
13
+ module WebDriver
14
+
15
+ class Options
16
+ def clear_cookies
17
+ @bridge.clearCookies
18
+ end
19
+ end
20
+
21
+ module Remote
22
+ class Bridge
23
+ def clearCookies
24
+ execute :clearCookies
25
+ end
26
+
27
+ command :clearCookies, :delete, "session/:session_id/cookies"
28
+ end
29
+ end
30
+
31
+ module Firefox
32
+ class Profile
33
+ remove_const :WEBDRIVER_EXTENSION_PATH
34
+ WEBDRIVER_EXTENSION_PATH = File.expand_path('../firefox/webdriver.xpi', __FILE__)
35
+ end
36
+ end
37
+
38
+ end
39
+ end
@@ -0,0 +1,14 @@
1
+ require "nokogiri"
2
+
3
+ module Watir
4
+ class Browser
5
+
6
+ def text
7
+ doc = Nokogiri::HTML(body(:index => 0).html)
8
+ doc.css("script").remove # encoding bug in older libxml?
9
+
10
+ doc.inner_text
11
+ end
12
+
13
+ end
14
+ end
@@ -0,0 +1,54 @@
1
+ require "ostruct"
2
+
3
+ module Watir
4
+
5
+ # Adds helper for window.performance to Watir::Browser.
6
+ #
7
+ # This module is provided by an optional require:
8
+ #
9
+ # require "watir-webdriver/extensions/performance"
10
+ #
11
+ # @see http://dev.w3.org/2006/webapi/WebTiming/
12
+ #
13
+
14
+ module PerformanceHelper
15
+
16
+ def performance
17
+ data = driver.execute_script("return window.performance || window.webkitPerformance || window.mozPerformance || window.msPerformance;")
18
+ data && Performance.new(data)
19
+ end
20
+
21
+ class Performance
22
+ attr_reader :timing, :navigation, :memory
23
+
24
+ def initialize(data)
25
+ @timing = rubify data['timing'] || {}
26
+ @navigation = rubify data['navigation'] || {}
27
+ @memory = rubify data['memory'] || {}
28
+ end
29
+
30
+ private
31
+
32
+ def rubify(hash)
33
+ result = {}
34
+
35
+ hash.each do |k, v|
36
+ if k =~ /^[A-Z_]+$/
37
+ k = k.downcase
38
+ elsif k =~ /(start|end)$/i && Fixnum === v
39
+ v = ::Time.at(v / 1000)
40
+ end
41
+
42
+ result[k.snake_case] = v
43
+ end
44
+
45
+ OpenStruct.new(result)
46
+ end
47
+
48
+ end # Performance
49
+ end # PerformanceHelper
50
+
51
+ class Browser
52
+ include PerformanceHelper
53
+ end
54
+ end # Watir
@@ -0,0 +1,141 @@
1
+ # encoding: utf-8
2
+ module Watir
3
+
4
+ #
5
+ # Module provided by optional require:
6
+ #
7
+ # require "watir-webdriver/extensions/wait"
8
+ #
9
+
10
+ module Wait
11
+ module_function
12
+
13
+ class TimeoutError < StandardError
14
+ end
15
+
16
+ #
17
+ # Wait until the block evaluates to true or times out.
18
+ #
19
+
20
+ def until(timeout = 30, &block)
21
+ end_time = ::Time.now + timeout
22
+
23
+ until ::Time.now > end_time
24
+ result = yield(self)
25
+ return result if result
26
+ sleep 0.5
27
+ end
28
+
29
+ raise TimeoutError, "timed out after #{timeout} seconds"
30
+ end
31
+
32
+ #
33
+ # Wait while the block evaluates to true or times out.
34
+ #
35
+
36
+ def while(timeout = 30, &block)
37
+ end_time = ::Time.now + timeout
38
+
39
+ until ::Time.now > end_time
40
+ return unless yield(self)
41
+ sleep 0.5
42
+ end
43
+
44
+ raise TimeoutError, "timed out after #{timeout} seconds"
45
+ end
46
+
47
+ end # Wait
48
+
49
+ #
50
+ # Wraps an Element so that any subsequent method calls are
51
+ # put on hold until the element is present (exists and is visible) on the page.
52
+ #
53
+
54
+ class WhenPresentDecorator
55
+ def initialize(element, timeout)
56
+ @element = element
57
+ @timeout = timeout
58
+ end
59
+
60
+ def method_missing(m, *args, &block)
61
+ unless @element.respond_to?(m)
62
+ raise NoMethodError, "undefined method `#{m}' for #{@element.inspect}:#{@element.class}"
63
+ end
64
+
65
+ Watir::Wait.until(@timeout) { @element.present? }
66
+
67
+ @element.__send__(m, *args, &block)
68
+ end
69
+ end # WhenPresentDecorator
70
+
71
+ class Element
72
+
73
+ #
74
+ # Returns true if the element exists and is visible on the page
75
+ #
76
+ # This method is provided by an optional require.
77
+ # @see Watir::Wait
78
+ #
79
+
80
+ def present?
81
+ exists? && visible?
82
+ end
83
+
84
+ #
85
+ # Waits until the element is present.
86
+ #
87
+ # This method is provided by an optional require.
88
+ # @see Watir::Wait
89
+ #
90
+ # Example:
91
+ # browser.button(:id, 'foo').when_present.click
92
+ # browser.div(:id, 'bar').when_present { |div| ... }
93
+ # browser.p(:id, 'baz').when_present(60).text
94
+ #
95
+ # @param [Integer] timeout seconds to wait before timing out
96
+ #
97
+
98
+ def when_present(timeout = 30)
99
+ if block_given?
100
+ Watir::Wait.until(timeout) { self.present? }
101
+ yield self
102
+ else
103
+ WhenPresentDecorator.new(self, timeout)
104
+ end
105
+ end
106
+
107
+ #
108
+ # Waits until the element is present.
109
+ #
110
+ # This method is provided by an optional require.
111
+ #
112
+ # @param [Integer] timeout seconds to wait before timing out
113
+ #
114
+ # @see Watir::Wait
115
+ # @see Watir::Element#present?
116
+ #
117
+
118
+ def wait_until_present(timeout = 30)
119
+ Watir::Wait.until(timeout) { self.present? }
120
+ end
121
+
122
+ #
123
+ # Waits while the element is present.
124
+ #
125
+ # This method is provided by an optional require.
126
+ #
127
+ # @param [Integer] timeout seconds to wait before timing out
128
+ #
129
+ # @see Watir::Wait
130
+ # @see Watir::Element#present?
131
+ #
132
+
133
+ def wait_while_present(timeout = 30)
134
+ Watir::Wait.while(timeout) { self.present? }
135
+ rescue Selenium::WebDriver::Error::ObsoleteElementError
136
+ # it's not present
137
+ end
138
+ end # Element
139
+
140
+
141
+ end # Watir