angular_webdriver 1.0.3 → 1.0.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/angular_webdriver.rb +5 -2
- data/lib/angular_webdriver/protractor/protractor.rb +32 -4
- data/lib/angular_webdriver/protractor/watir_patch.rb +185 -169
- data/lib/angular_webdriver/version.rb +1 -1
- data/release_notes.md +8 -0
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: bddebdc5e0805f1a225634f2472d982f3e29d7f5
|
4
|
+
data.tar.gz: 4725e12aef7fc193b367dc393d397b46149befb2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 881b3dac4df7917e4dd36dccc99349148ec86d90abf80d204fc76bfe5af181c42f02e32cfb6a80c71852b9e685ac0b56f3104eea682456ce1df8fbc2fb8fe940
|
7
|
+
data.tar.gz: 0d4ccf98664fe02f9708bae8b3f2556968c5b0b594a4141594cf4b7d8cba5c0ea064a51a31895a55bc285027e043af1411bdd1e79c3213154e7c2b233321a323
|
data/lib/angular_webdriver.rb
CHANGED
@@ -2,7 +2,12 @@ require_relative 'angular_webdriver/version'
|
|
2
2
|
|
3
3
|
require 'rubygems'
|
4
4
|
require 'selenium-webdriver'
|
5
|
+
require_relative 'angular_webdriver/protractor/webdriver_patch'
|
6
|
+
|
7
|
+
require_relative 'angular_webdriver/protractor/watir_patch'
|
8
|
+
AngularWebdriver.patch_watir # (1/2) before
|
5
9
|
require 'watir-webdriver'
|
10
|
+
AngularWebdriver.patch_watir # (2/2) after
|
6
11
|
|
7
12
|
require_relative 'angular_webdriver/protractor/by'
|
8
13
|
require_relative 'angular_webdriver/protractor/by_repeater_inner'
|
@@ -10,5 +15,3 @@ require_relative 'angular_webdriver/protractor/client_side_scripts'
|
|
10
15
|
require_relative 'angular_webdriver/protractor/protractor'
|
11
16
|
require_relative 'angular_webdriver/protractor/protractor_element'
|
12
17
|
require_relative 'angular_webdriver/protractor/rspec_helpers'
|
13
|
-
require_relative 'angular_webdriver/protractor/webdriver_patch'
|
14
|
-
require_relative 'angular_webdriver/protractor/watir_patch'
|
@@ -122,7 +122,7 @@ class Protractor
|
|
122
122
|
|
123
123
|
# data urls must be preserved and not have http:// prepended.
|
124
124
|
# data:<blah>
|
125
|
-
data_url
|
125
|
+
data_url = destination.start_with?('data:')
|
126
126
|
|
127
127
|
unless about_url || data_url
|
128
128
|
# URI.join doesn't allow for http://localhost:8081/#/ as a base_url
|
@@ -283,20 +283,48 @@ class Protractor
|
|
283
283
|
|
284
284
|
# must be local var for use with define element below.
|
285
285
|
protractor_element = AngularWebdriver::ProtractorElement.new @watir
|
286
|
+
driver = @driver
|
286
287
|
|
287
288
|
# Top level element method to enable protractor syntax.
|
288
289
|
# redefine element to point to the new protractor element instance.
|
289
290
|
#
|
290
291
|
# toplevel self enables by/element from within pry. rspec helpers enables
|
291
292
|
# by/element within rspec tests when used with install_rspec_helpers.
|
292
|
-
|
293
|
-
|
293
|
+
toplevel_main = eval('self', TOPLEVEL_BINDING)
|
294
|
+
[toplevel_main, AngularWebdriver::RSpecHelpers].each do |obj|
|
295
|
+
# define singleton on toplevel main, otherwise use regular define method
|
296
|
+
# if we use define singleton on the rspec helpers, then rspec won't
|
297
|
+
# be able to handle block parameters.
|
298
|
+
#
|
299
|
+
# Also rspec requires config.include AngularWebdriver::RSpecHelpers
|
300
|
+
# for the no_wait helper to accept the block parameter.
|
301
|
+
method_type = obj == toplevel_main ? :define_singleton_method : :define_method
|
302
|
+
|
303
|
+
obj.send method_type, :element do |*args|
|
294
304
|
protractor_element.element *args
|
295
305
|
end
|
296
306
|
|
297
|
-
obj.send
|
307
|
+
obj.send method_type, :by do
|
298
308
|
AngularWebdriver::By
|
299
309
|
end
|
310
|
+
|
311
|
+
obj.send method_type, :no_wait do |&block|
|
312
|
+
max_wait = driver.max_wait_seconds
|
313
|
+
max_page_wait = driver.max_page_wait_seconds
|
314
|
+
|
315
|
+
driver.set_max_wait 0
|
316
|
+
driver.set_max_page_wait 0
|
317
|
+
|
318
|
+
begin
|
319
|
+
raise ArgumentError, 'Tried to use no_wait without a block' unless block
|
320
|
+
result = block.call
|
321
|
+
ensure
|
322
|
+
driver.set_max_wait max_wait
|
323
|
+
driver.set_max_page_wait max_page_wait
|
324
|
+
end
|
325
|
+
|
326
|
+
result
|
327
|
+
end
|
300
328
|
end
|
301
329
|
|
302
330
|
self
|
@@ -1,209 +1,225 @@
|
|
1
|
-
require 'watir-webdriver/elements/element'
|
2
|
-
|
3
1
|
# match protractor semantics
|
4
2
|
# unfortunately setting always locate doesn't always locate.
|
5
|
-
Watir.always_locate = true
|
6
|
-
|
7
|
-
#
|
8
|
-
# This patch serves a few purposes. The first is matching Protractor semantics
|
9
|
-
# of lazy finding elements and always relocating elements (ex: element.text)
|
10
|
-
#
|
11
|
-
# The second is removing unnecessary bloatware from Watir which has a number
|
12
|
-
# of checks that don't make sense for angular.js testing. The specifics
|
13
|
-
# of this patch will change in the next Watir release. Currently version
|
14
|
-
# 0.7.0 is targeted.
|
15
|
-
#
|
16
|
-
# The third is teaching Watir about angular specific locators
|
17
|
-
#
|
18
|
-
# Design goal: element.all(by.binding('slowHttpStatus'))
|
19
|
-
# should not make any server requests
|
20
|
-
#
|
21
|
-
|
22
3
|
module Watir
|
4
|
+
@always_locate = true
|
5
|
+
end
|
23
6
|
|
24
|
-
|
25
|
-
# Return original selector.
|
26
|
-
# Method added for protractor compatibility
|
27
|
-
def locator
|
28
|
-
@selector
|
29
|
-
end
|
30
|
-
end
|
7
|
+
module AngularWebdriver
|
31
8
|
|
32
|
-
|
9
|
+
# Patch watir must be invoked before watir-webdriver is required to
|
10
|
+
# ensure the methods are defined before inheritance occurs.
|
11
|
+
# Then patch_watir must be invoked after requiring watir-webdriver to
|
12
|
+
# restore the methods that were overridden.
|
13
|
+
#
|
14
|
+
def self.patch_watir
|
33
15
|
#
|
34
|
-
#
|
16
|
+
# This patch serves a few purposes. The first is matching Protractor semantics
|
17
|
+
# of lazy finding elements and always relocating elements (ex: element.text)
|
18
|
+
#
|
19
|
+
# The second is removing unnecessary bloatware from Watir which has a number
|
20
|
+
# of checks that don't make sense for angular.js testing. The specifics
|
21
|
+
# of this patch will change in the next Watir release. Currently version
|
22
|
+
# 0.7.0 is targeted.
|
23
|
+
#
|
24
|
+
# The third is teaching Watir about angular specific locators
|
25
|
+
#
|
26
|
+
# Design goal: element.all(by.binding('slowHttpStatus'))
|
27
|
+
# should not make any server requests
|
35
28
|
#
|
36
29
|
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
define_method(:extract_selector) do |selectors|
|
44
|
-
selectors = AngularWebdriver::ByRepeaterInner.wrap_repeater selectors
|
45
|
-
|
46
|
-
upstream_extract_selector.bind(self).call selectors
|
30
|
+
::Watir::HTMLElementCollection.class_eval do
|
31
|
+
# Return original selector.
|
32
|
+
# Method added for protractor compatibility
|
33
|
+
def locator
|
34
|
+
@selector
|
35
|
+
end
|
47
36
|
end
|
48
37
|
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
#
|
38
|
+
::Watir::Container.module_eval do
|
39
|
+
#
|
40
|
+
# Alias of elements for Protractor
|
41
|
+
#
|
54
42
|
|
55
|
-
|
43
|
+
def all(*args)
|
44
|
+
elements(*args)
|
45
|
+
end
|
56
46
|
|
57
|
-
|
47
|
+
# Redefine extract_selector to wrap find by repeater
|
48
|
+
upstream_extract_selector = instance_method(:extract_selector)
|
49
|
+
define_method(:extract_selector) do |selectors|
|
50
|
+
selectors = AngularWebdriver::ByRepeaterInner.wrap_repeater selectors
|
58
51
|
|
59
|
-
|
60
|
-
|
61
|
-
yield
|
62
|
-
rescue Selenium::WebDriver::Error::StaleElementReferenceError
|
63
|
-
raise
|
64
|
-
end
|
52
|
+
upstream_extract_selector.bind(self).call selectors
|
53
|
+
end
|
65
54
|
|
66
|
-
|
67
|
-
assert_exists
|
68
|
-
element_call { @element.selected? }
|
69
|
-
end
|
55
|
+
end # ::Watir::Container.module_eval
|
70
56
|
|
71
|
-
# required for watir otherwise execute_script will fail
|
72
|
-
#
|
73
|
-
# e = browser.element(tag_name: 'div')
|
74
|
-
# driver.execute_script 'return arguments[0].tagName', e
|
75
|
-
# {"script":"return arguments[0].tagName","args":[{"ELEMENT":"0"}]}
|
76
57
|
#
|
77
|
-
#
|
78
|
-
# @see https://github.com/SeleniumHQ/selenium/wiki/JsonWireProtocol#basic-terms-and-concepts
|
58
|
+
# Base class for HTML elements.
|
79
59
|
#
|
80
|
-
# @api private
|
81
|
-
#
|
82
|
-
def to_json(*args)
|
83
|
-
assert_exists
|
84
|
-
{ ELEMENT: @element.ref }.to_json
|
85
|
-
end
|
86
60
|
|
87
|
-
#
|
88
|
-
# Required to trigger waitForAngular. Caching the element here will
|
89
|
-
# break the Protractor sync feature so this must be @element = locate.
|
90
|
-
def assert_exists
|
91
|
-
@element = locate
|
92
|
-
end
|
61
|
+
# Note the element class is different on master.
|
93
62
|
|
94
|
-
|
95
|
-
|
96
|
-
|
63
|
+
::Watir::Element.class_eval do
|
64
|
+
# Always raise on stale element ref error. Prevents infinite retry loop.
|
65
|
+
def element_call
|
66
|
+
yield
|
67
|
+
rescue Selenium::WebDriver::Error::StaleElementReferenceError
|
68
|
+
raise
|
69
|
+
end
|
97
70
|
|
98
|
-
|
99
|
-
|
100
|
-
|
71
|
+
# Rescue all exceptions. Guarantee that we'll return true or false.
|
72
|
+
#
|
73
|
+
# Returns true if element exists and false otherwise.
|
74
|
+
def exists?
|
75
|
+
assert_exists
|
76
|
+
true
|
77
|
+
rescue Exception
|
78
|
+
false
|
79
|
+
end
|
101
80
|
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
end
|
81
|
+
def selected?
|
82
|
+
assert_exists
|
83
|
+
element_call { @element.selected? }
|
84
|
+
end
|
107
85
|
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
86
|
+
# required for watir otherwise execute_script will fail
|
87
|
+
#
|
88
|
+
# e = browser.element(tag_name: 'div')
|
89
|
+
# driver.execute_script 'return arguments[0].tagName', e
|
90
|
+
# {"script":"return arguments[0].tagName","args":[{"ELEMENT":"0"}]}
|
91
|
+
#
|
92
|
+
# Convert to a WebElement JSON Object for transmission over the wire.
|
93
|
+
# @see https://github.com/SeleniumHQ/selenium/wiki/JsonWireProtocol#basic-terms-and-concepts
|
94
|
+
#
|
95
|
+
# @api private
|
96
|
+
#
|
97
|
+
def to_json(*args)
|
98
|
+
assert_exists
|
99
|
+
{ ELEMENT: @element.ref }.to_json
|
100
|
+
end
|
112
101
|
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
assert_exists
|
117
|
-
|
118
|
-
|
102
|
+
# Ensure that the element exists by always relocating it
|
103
|
+
# Required to trigger waitForAngular. Caching the element here will
|
104
|
+
# break the Protractor sync feature so this must be @element = locate.
|
105
|
+
def assert_exists
|
106
|
+
@element = locate
|
107
|
+
end
|
119
108
|
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
element_call { @element.clear }
|
124
|
-
end
|
109
|
+
def assert_not_stale
|
110
|
+
nil
|
111
|
+
end
|
125
112
|
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
# @param expression <String> The expression to evaluate.
|
130
|
-
#
|
131
|
-
# @return <Object> The result of the evaluation.
|
132
|
-
def evaluate expression
|
133
|
-
assert_exists
|
134
|
-
driver.protractor.evaluate @element, expression
|
135
|
-
end
|
113
|
+
def assert_enabled
|
114
|
+
nil
|
115
|
+
end
|
136
116
|
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
#
|
143
|
-
#
|
144
|
-
# rescue element not found
|
145
|
-
def present?
|
146
|
-
exists? && visible?
|
147
|
-
rescue Selenium::WebDriver::Error::NoSuchElementError, Selenium::WebDriver::Error::StaleElementReferenceError, UnknownObjectException
|
148
|
-
# if the element disappears between the exists? and visible? calls,
|
149
|
-
# consider it not present.
|
150
|
-
false
|
151
|
-
end
|
152
|
-
end
|
117
|
+
# Return original selector.
|
118
|
+
# Method added for protractor compatibility
|
119
|
+
def locator
|
120
|
+
@selector
|
121
|
+
end
|
153
122
|
|
123
|
+
# avoid context lookup
|
124
|
+
def locate
|
125
|
+
locator_class.new(@parent.wd, @selector, self.class.attribute_list).locate
|
126
|
+
end
|
154
127
|
|
155
|
-
|
156
|
-
|
157
|
-
|
128
|
+
# Invoke protractor.allowAnimations with freshly located element and
|
129
|
+
# optional value.
|
130
|
+
def allowAnimations value=nil
|
131
|
+
assert_exists
|
132
|
+
driver.protractor.allowAnimations @element, value
|
133
|
+
end
|
158
134
|
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
135
|
+
# Watir doesn't define a clear method on element so we have to provide one.
|
136
|
+
def clear
|
137
|
+
assert_exists
|
138
|
+
element_call { @element.clear }
|
139
|
+
end
|
164
140
|
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
141
|
+
# Evaluate an Angular expression as if it were on the scope
|
142
|
+
# of the current element.
|
143
|
+
#
|
144
|
+
# @param expression <String> The expression to evaluate.
|
145
|
+
#
|
146
|
+
# @return <Object> The result of the evaluation.
|
147
|
+
def evaluate expression
|
148
|
+
assert_exists
|
149
|
+
driver.protractor.evaluate @element, expression
|
150
|
+
end
|
169
151
|
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
152
|
+
#
|
153
|
+
# Returns true if the element exists and is visible on the page.
|
154
|
+
# Returns false if the element doesn't exist or isn't visible.
|
155
|
+
#
|
156
|
+
# @return [Boolean]
|
157
|
+
# @see Watir::Wait
|
158
|
+
#
|
159
|
+
#
|
160
|
+
# rescue element not found
|
161
|
+
def present?
|
162
|
+
exists? && visible?
|
163
|
+
rescue Exception
|
164
|
+
# if the element disappears between the exists? and visible? calls,
|
165
|
+
# consider it not present.
|
166
|
+
false
|
167
|
+
end
|
168
|
+
end # ::Watir::Element.class_eval
|
175
169
|
|
176
|
-
|
170
|
+
#
|
171
|
+
# The main class through which you control the browser.
|
172
|
+
#
|
177
173
|
|
178
|
-
|
179
|
-
|
174
|
+
::Watir::Browser.class_eval do
|
175
|
+
def assert_exists
|
176
|
+
# remove expensive window check
|
177
|
+
raise Exception::Error, 'browser was closed' if @closed
|
180
178
|
end
|
181
179
|
|
182
|
-
|
183
|
-
|
180
|
+
def inspect
|
181
|
+
nil # avoid expensive browser url and title lookup
|
182
|
+
end
|
183
|
+
end # ::Watir::Browser.class_eval
|
184
184
|
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
#
|
191
|
-
# see 'should find multiple buttons containing "text"' in locators_spec.rb
|
192
|
-
return @selector[:element] if @selector.is_a?(Hash) && @selector[:element].is_a?(Selenium::WebDriver::Element)
|
185
|
+
::Watir::ElementLocator.class_eval do
|
186
|
+
def validate_element(element)
|
187
|
+
tn = @selector[:tag_name]
|
188
|
+
return element unless tn # don't validate nil tag names
|
189
|
+
element_tag_name = element.tag_name.downcase
|
193
190
|
|
194
|
-
|
191
|
+
return if tn && !tag_name_matches?(element_tag_name, tn)
|
195
192
|
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
193
|
+
if element_tag_name == 'input'
|
194
|
+
return if @selector[:type] && @selector[:type] != element.attribute(:type)
|
195
|
+
end
|
196
|
+
|
197
|
+
element
|
200
198
|
end
|
201
199
|
|
202
|
-
#
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
200
|
+
# always raise element not found / stale reference error
|
201
|
+
def locate
|
202
|
+
# element.all(by.partialButtonText('text')).to_a[0].value creates the
|
203
|
+
# selector {:element=>#<Selenium::WebDriver::Element ...>}
|
204
|
+
# in that case we've already located the element.
|
205
|
+
#
|
206
|
+
# see 'should find multiple buttons containing "text"' in locators_spec.rb
|
207
|
+
return @selector[:element] if @selector.is_a?(Hash) && @selector[:element].is_a?(Selenium::WebDriver::Element)
|
208
|
+
|
209
|
+
e = by_id and return e # short-circuit if :id is given
|
210
|
+
|
211
|
+
if @selector.size == 1
|
212
|
+
element = find_first_by_one
|
213
|
+
else
|
214
|
+
element = find_first_by_multiple
|
215
|
+
end
|
216
|
+
|
217
|
+
# This actually only applies when finding by xpath/css - browser.text_field(:xpath, "//input[@type='radio']")
|
218
|
+
# We don't need to validate the element if we built the xpath ourselves.
|
219
|
+
# It is also used to alter behavior of methods locating more than one type of element
|
220
|
+
# (e.g. text_field locates both input and textarea)
|
221
|
+
validate_element(element) if element
|
222
|
+
end
|
223
|
+
end # ::Watir::ElementLocator.class_eval
|
224
|
+
end # def patch_watir
|
225
|
+
end # module AngularWebdriver
|
data/release_notes.md
CHANGED
@@ -1,3 +1,11 @@
|
|
1
|
+
#### v1.0.4 2015-06-07
|
2
|
+
|
3
|
+
- [a7965d7](https://github.com/bootstraponline/angular_webdriver/commit/a7965d7d1103bb802eabbdf11a37c9be8f9f3547) Release 1.0.4
|
4
|
+
- [bf94300](https://github.com/bootstraponline/angular_webdriver/commit/bf9430076da4a89a85050b92289b1fda34afe3f8) Fix and test rspec helpers
|
5
|
+
- [1d11610](https://github.com/bootstraponline/angular_webdriver/commit/1d11610441ed56addabc5be60fe35125151a7a75) Move no_wait into top level singleton
|
6
|
+
- [10f7ff9](https://github.com/bootstraponline/angular_webdriver/commit/10f7ff9ecbbdf0751752c751cebef4119eb86f94) Fix watir patch. Fix exists?
|
7
|
+
|
8
|
+
|
1
9
|
#### v1.0.3 2015-06-07
|
2
10
|
|
3
11
|
- [97d5f18](https://github.com/bootstraponline/angular_webdriver/commit/97d5f18e187d56bc8616fb65ec1e5b9bafa8c289) Release 1.0.3
|