watirsome 0.1.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.
- data/.coveralls.yml +1 -0
- data/.travis.yml +4 -0
- data/Gemfile +3 -0
- data/LICENSE.md +20 -0
- data/README.md +330 -0
- data/Rakefile +12 -0
- data/lib/watirsome/accessors.rb +228 -0
- data/lib/watirsome/initializers.rb +42 -0
- data/lib/watirsome/version.rb +3 -0
- data/lib/watirsome.rb +155 -0
- data/spec/lib/watirsome/accessors_spec.rb +12 -0
- data/spec/lib/watirsome/initializers_spec.rb +47 -0
- data/spec/lib/watirsome_spec.rb +98 -0
- data/spec/spec_helper.rb +31 -0
- data/spec/support/page.rb +49 -0
- data/spec/support/shared_examples/click_accessor.rb +52 -0
- data/spec/support/shared_examples/element_accessor.rb +47 -0
- data/spec/support/shared_examples/read_accessor.rb +67 -0
- data/spec/support/shared_examples/select_accessor.rb +46 -0
- data/spec/support/shared_examples/set_accessor.rb +53 -0
- data/watirsome.gemspec +26 -0
- metadata +177 -0
data/.coveralls.yml
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
service_name: 'travis-ci'
|
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/LICENSE.md
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2013 Alex Rodionov
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,330 @@
|
|
1
|
+
## watirsome
|
2
|
+
|
3
|
+
Pure dynamic Watir-based page object DSL.
|
4
|
+
|
5
|
+
[](http://badge.fury.io/rb/watirsome)
|
6
|
+
[](http://travis-ci.org/p0deje/watirsome)
|
7
|
+
[](https://coveralls.io/r/p0deje/watirsome)
|
8
|
+
|
9
|
+
Inspired by [page-object](https://github.com/cheezy/page-object) and [watir-page-helper](https://github.com/alisterscott/watir-page-helper).
|
10
|
+
|
11
|
+
### Installation
|
12
|
+
|
13
|
+
Just like any other gem:
|
14
|
+
|
15
|
+
```shell
|
16
|
+
➜ gem install watirsome
|
17
|
+
```
|
18
|
+
|
19
|
+
Or using bundler:
|
20
|
+
|
21
|
+
```ruby
|
22
|
+
# Gemfile
|
23
|
+
gem 'watirsome'
|
24
|
+
```
|
25
|
+
|
26
|
+
### Examples
|
27
|
+
|
28
|
+
```ruby
|
29
|
+
class Page
|
30
|
+
include Watirsome
|
31
|
+
|
32
|
+
text_field :username, label: 'Username'
|
33
|
+
text_field :password, label: 'Password'
|
34
|
+
button :login, text: 'Login'
|
35
|
+
|
36
|
+
def login(username, password)
|
37
|
+
self.username = username
|
38
|
+
self.password = password
|
39
|
+
login
|
40
|
+
end
|
41
|
+
end
|
42
|
+
```
|
43
|
+
|
44
|
+
### Accessors
|
45
|
+
|
46
|
+
Watirsome provides you with accessors DSL to isolate elements from your methods.
|
47
|
+
|
48
|
+
All accessors are just proxied to Watir, thus you free to use all its power in your page objects.
|
49
|
+
|
50
|
+
```ruby
|
51
|
+
class Page
|
52
|
+
include Watirsome
|
53
|
+
|
54
|
+
# any method defined in Watir::Container are accessible
|
55
|
+
body :body
|
56
|
+
section :section, id: 'section_one'
|
57
|
+
element :svg, tag_name: 'svg'
|
58
|
+
end
|
59
|
+
```
|
60
|
+
|
61
|
+
#### Locators
|
62
|
+
|
63
|
+
You can use any kind of locators you use with Watir.
|
64
|
+
|
65
|
+
```ruby
|
66
|
+
class Page
|
67
|
+
include Watirsome
|
68
|
+
|
69
|
+
body :body
|
70
|
+
section :one, id: 'section_one'
|
71
|
+
element :svg, tag_name: 'svg'
|
72
|
+
button :login, class: 'submit', index: 1
|
73
|
+
end
|
74
|
+
|
75
|
+
page = Page.new(@browser)
|
76
|
+
page.body_element # equals to @browser.body
|
77
|
+
page.section_one # equals to @browser.section(id: 'section')
|
78
|
+
page.svg_element # equals to @browser.element(tag_name: 'svg')
|
79
|
+
page.login_button # equals to @browser.button(class: 'submit', index: 1)
|
80
|
+
```
|
81
|
+
|
82
|
+
Watirsome also provides you with opportunity to locate elements by using any boolean method Watir element supports.
|
83
|
+
|
84
|
+
```ruby
|
85
|
+
class Page
|
86
|
+
include Watirsome
|
87
|
+
|
88
|
+
div :layer, class: 'layer', visible: true
|
89
|
+
span :wrapper, class: 'span', exists: false
|
90
|
+
end
|
91
|
+
|
92
|
+
page = Page.new(@browser)
|
93
|
+
page.layer_div # equals to @browser.divs(class: 'layer').find { |e| e.visible? == true }
|
94
|
+
page.wrapper_span # equals to @browser.divs(class: 'layer').find { |e| e.exists? == false }
|
95
|
+
```
|
96
|
+
|
97
|
+
You can also use proc/lambda/block to locate element. Block is executed in the context of initalized page, so other accessors can be used.
|
98
|
+
|
99
|
+
```ruby
|
100
|
+
class Page
|
101
|
+
include Watirsome
|
102
|
+
|
103
|
+
div :layer, class: 'layer'
|
104
|
+
span :wrapper, -> { layer_div.span(class: 'span') }
|
105
|
+
end
|
106
|
+
|
107
|
+
page = Page.new(@browser)
|
108
|
+
page.wrapper_span # equals to @browser.div(class: 'layer').span(class: 'span')
|
109
|
+
```
|
110
|
+
|
111
|
+
Moreover, you can pass arguments to blocks!
|
112
|
+
|
113
|
+
```ruby
|
114
|
+
class Page
|
115
|
+
include Watirsome
|
116
|
+
|
117
|
+
div :layer, class: 'layer'
|
118
|
+
a :link, do |text|
|
119
|
+
layer_div.a(text: text)
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
page = Page.new(@browser)
|
124
|
+
page.link_a('Login') # equals to @browser.div(class: 'layer').a(text: 'Login')
|
125
|
+
```
|
126
|
+
|
127
|
+
#### Element accessors
|
128
|
+
|
129
|
+
For each element, accessor method is defined which returns instance of `Watir::Element` (or subtype when applicable).
|
130
|
+
|
131
|
+
Element accessor method name is `#{element_name}_#{tag_name}`.
|
132
|
+
|
133
|
+
```ruby
|
134
|
+
class Page
|
135
|
+
include Watirsome
|
136
|
+
|
137
|
+
section :section_one, id: 'section_one'
|
138
|
+
element :svg, tag_name: 'svg'
|
139
|
+
end
|
140
|
+
|
141
|
+
page = Page.new(@browser)
|
142
|
+
page.section_one_section #=> #<Watir::HTMLElement:0x201b2f994f32c922 selector={:tag_name=>"section"}>
|
143
|
+
page.svg_element #=> #<Watir::HTMLElement:0x15288276ab771162 selector={:tag_name=>"svg"}>
|
144
|
+
```
|
145
|
+
|
146
|
+
#### Readable accessors
|
147
|
+
|
148
|
+
For each redable element, accessor method is defined which returns text of that element.
|
149
|
+
|
150
|
+
Read accessor method name is `element_name`.
|
151
|
+
|
152
|
+
Default redable methods are: `[:div, :span, :p, :h1, :h2, :h3, :h4, :h5, :h6, :select_list, :text_field, :textarea]`.
|
153
|
+
|
154
|
+
You can make other elements redable by adding tag names to `Watirsome.redable`.
|
155
|
+
|
156
|
+
```ruby
|
157
|
+
# make section redable
|
158
|
+
Watirsome.redable << :section
|
159
|
+
|
160
|
+
class Page
|
161
|
+
include Watirsome
|
162
|
+
|
163
|
+
div :main, id: 'main_div'
|
164
|
+
section :date, id: 'date'
|
165
|
+
end
|
166
|
+
|
167
|
+
page = Page.new(@browser)
|
168
|
+
page.main # returns text of main div
|
169
|
+
page.date # returns text of date section
|
170
|
+
```
|
171
|
+
|
172
|
+
There is a bit of logic behind text retrieval:
|
173
|
+
|
174
|
+
1. If element is a text field or textarea, return value
|
175
|
+
2. If element is a select list, return text of first selected option
|
176
|
+
3. Otherwise, return text
|
177
|
+
|
178
|
+
#### Clickable accessors
|
179
|
+
|
180
|
+
For each clickable element, accessor method is defined which performs click on that element.
|
181
|
+
|
182
|
+
Click accessor method name is `element_name`.
|
183
|
+
|
184
|
+
Default clickable methods are: `[:a, :link, :button]`.
|
185
|
+
|
186
|
+
You can make other elements clickable by adding tag names to `Watirsome.clickable`.
|
187
|
+
|
188
|
+
```ruby
|
189
|
+
# make input clickable
|
190
|
+
Watirsome.clickable << :input
|
191
|
+
|
192
|
+
class Page
|
193
|
+
include Watirsome
|
194
|
+
|
195
|
+
a :login, text: 'Login'
|
196
|
+
input :submit, ->(type) { @browser.input(type: type) }
|
197
|
+
end
|
198
|
+
|
199
|
+
page = Page.new(@browser)
|
200
|
+
page.login # clicks on link
|
201
|
+
page.submit('submit') # clicks on submit input
|
202
|
+
```
|
203
|
+
|
204
|
+
#### Settable accessors
|
205
|
+
|
206
|
+
For each settable element, accessor method is defined which sets value to that element.
|
207
|
+
|
208
|
+
Click accessor method name is `#{element_name}=`.
|
209
|
+
|
210
|
+
Default settable methods are: `[:text_field, :file_field, :textarea, :checkbox]`.
|
211
|
+
|
212
|
+
You can make other elements settable by adding tag names to `Watirsome.settable`.
|
213
|
+
|
214
|
+
```ruby
|
215
|
+
# make input settable
|
216
|
+
Watirsome.settable << :input
|
217
|
+
|
218
|
+
class Page
|
219
|
+
include Watirsome
|
220
|
+
|
221
|
+
text_field :username, label: 'Username'
|
222
|
+
input :date, type: 'date'
|
223
|
+
end
|
224
|
+
|
225
|
+
page = Page.new(@browser)
|
226
|
+
page.username = 'Username' # sets value of username text field
|
227
|
+
page.date = '2013-01-01', :return # sends text to element and hits "Enter"
|
228
|
+
```
|
229
|
+
|
230
|
+
If found element responds to `#set`, accessor calls it. Otherwise, `#send_keys` is used.
|
231
|
+
|
232
|
+
#### Selectable accessors
|
233
|
+
|
234
|
+
For each selectable element, accessor method is defined which selects opton of that element.
|
235
|
+
|
236
|
+
Click accessor method name is `#{element_name}=`.
|
237
|
+
|
238
|
+
Default selectable methods are: `[:select_list]`.
|
239
|
+
|
240
|
+
You can make other elements selectable by adding tag names to `Watirsome.selectable`. Though, why would you want?
|
241
|
+
|
242
|
+
```ruby
|
243
|
+
class Page
|
244
|
+
include Watirsome
|
245
|
+
|
246
|
+
select_list :country, label: 'Country'
|
247
|
+
end
|
248
|
+
|
249
|
+
page = Page.new(@browser)
|
250
|
+
page.country = 'Russia' #=> selects option with "Russia" text
|
251
|
+
```
|
252
|
+
|
253
|
+
### Initializers
|
254
|
+
|
255
|
+
Watirsome provides you with initializers DSL to dynamically modify your pages/regions behavior.
|
256
|
+
|
257
|
+
#### Page initializer
|
258
|
+
|
259
|
+
Each page may define `#initialize_page` method which will be used as page constructor.
|
260
|
+
|
261
|
+
```ruby
|
262
|
+
class Page
|
263
|
+
include Watirsome
|
264
|
+
|
265
|
+
def initialize_page
|
266
|
+
puts 'Initialized!'
|
267
|
+
end
|
268
|
+
end
|
269
|
+
|
270
|
+
Page.new(@browser)
|
271
|
+
#=> 'Initialized!'
|
272
|
+
```
|
273
|
+
|
274
|
+
#### Region initializer
|
275
|
+
|
276
|
+
Each region you include/extend may define `#initialize_region` method which will be called after page constructor.
|
277
|
+
|
278
|
+
|
279
|
+
```ruby
|
280
|
+
module HeaderRegion
|
281
|
+
def initialize_region
|
282
|
+
puts 'Initialzed header!'
|
283
|
+
end
|
284
|
+
end
|
285
|
+
|
286
|
+
module FooterRegion
|
287
|
+
def initialize_region
|
288
|
+
puts 'Initialzed footer!'
|
289
|
+
end
|
290
|
+
end
|
291
|
+
|
292
|
+
class Page
|
293
|
+
include Watirsome
|
294
|
+
include HeaderRegion
|
295
|
+
|
296
|
+
def initialize_page
|
297
|
+
extend FooterRegion
|
298
|
+
end
|
299
|
+
end
|
300
|
+
|
301
|
+
Page.new(@browser)
|
302
|
+
#=> 'Initialized header!'
|
303
|
+
#=> 'Initialized footer!'
|
304
|
+
```
|
305
|
+
|
306
|
+
Regions are being cached, so, once initialzed, they won't be executed if you call `Page#initialize_regions` again.
|
307
|
+
|
308
|
+
Each module is first checked if its name matches the regular expression of region (to make sure we don't touch unrelated included modules). By default, regexp is `/^.+(Region)$/`, but you can change it by altering `Watirsome.region_matcher`.
|
309
|
+
|
310
|
+
```ruby
|
311
|
+
Watirsome.region_matcher = /^.+(Region|Helper)$/
|
312
|
+
```
|
313
|
+
|
314
|
+
### Limitations
|
315
|
+
|
316
|
+
1. Currently tested to work only with `watir-webdriver`. Let me know if it works using `watir-classic`.
|
317
|
+
2. You cannot use `Watir::Browser#select` method as it's overriden by `Kernel#select`. Use `Watir::Browser#select_list` instead.
|
318
|
+
3. You cannot use block arguments to locate elements for settable/selectable accessors (it makes no sense). However, you can use block arguments for all other accessors.
|
319
|
+
|
320
|
+
### Contribute
|
321
|
+
|
322
|
+
* Fork the project.
|
323
|
+
* Make your feature addition or bug fix.
|
324
|
+
* Add tests for it. This is important so I don't break it in a future version unintentionally.
|
325
|
+
* Commit, do not mess with rakefile, version, or history.
|
326
|
+
* Send me a pull request. Bonus points for topic branches.
|
327
|
+
|
328
|
+
### Copyright
|
329
|
+
|
330
|
+
Copyright (c) 2013 Alex Rodionov. See LICENSE.md for details.
|
data/Rakefile
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
$LOAD_PATH.unshift File.expand_path('../lib', __FILE__)
|
2
|
+
|
3
|
+
require 'bundler'
|
4
|
+
Bundler::GemHelper.install_tasks
|
5
|
+
|
6
|
+
require 'rspec/core/rake_task'
|
7
|
+
RSpec::Core::RakeTask.new do |spec|
|
8
|
+
spec.rspec_opts = %w(--color --require fuubar --format Fuubar)
|
9
|
+
spec.pattern = 'spec/**/*_spec.rb'
|
10
|
+
end
|
11
|
+
|
12
|
+
task default: :spec
|
@@ -0,0 +1,228 @@
|
|
1
|
+
module Watirsome
|
2
|
+
module Accessors
|
3
|
+
module ClassMethods
|
4
|
+
|
5
|
+
#
|
6
|
+
# Iterate thorugh Watir continer methods and define all necessary
|
7
|
+
# class methods of element accessors.
|
8
|
+
#
|
9
|
+
Watirsome.watir_methods.each do |method|
|
10
|
+
define_method method do |*args, &blk|
|
11
|
+
name, args = parse_args(args)
|
12
|
+
block = proc_from_args(args, &blk)
|
13
|
+
define_element_accessor(name, method, args, &block)
|
14
|
+
define_click_accessor(name, method, args, &block) if Watirsome.clickable?(method)
|
15
|
+
define_read_accessor(name, method, args, &block) if Watirsome.readable?(method)
|
16
|
+
define_set_accessor(name, method, args, &block) if Watirsome.settable?(method)
|
17
|
+
define_select_accessor(name, method, args, &block) if Watirsome.selectable?(method)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
#
|
24
|
+
# Returns name and locators.
|
25
|
+
# @api private
|
26
|
+
#
|
27
|
+
def parse_args(args)
|
28
|
+
return args.shift, args.shift
|
29
|
+
end
|
30
|
+
|
31
|
+
#
|
32
|
+
# Returns block retreived from locators.
|
33
|
+
# @api private
|
34
|
+
#
|
35
|
+
def proc_from_args(*args, &blk)
|
36
|
+
if block_given?
|
37
|
+
blk
|
38
|
+
else
|
39
|
+
block = args.shift
|
40
|
+
block.is_a?(Proc) && args.empty? ? block : nil
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
#
|
45
|
+
# Defines accessor which returns Watir element instance.
|
46
|
+
# Method name is element name + tag.
|
47
|
+
#
|
48
|
+
# @param [Symbol] name Element name
|
49
|
+
# @param [Symbol] method Watir method
|
50
|
+
# @param [Array] args Splat of locators
|
51
|
+
# @param [Proc] block Block as element retriever
|
52
|
+
# @api private
|
53
|
+
#
|
54
|
+
def define_element_accessor(name, method, *args, &block)
|
55
|
+
watir_args, custom_args = extract_custom_args(args)
|
56
|
+
define_method :"#{name}_#{method}" do |*opts|
|
57
|
+
if block_given?
|
58
|
+
instance_exec(*opts, &block)
|
59
|
+
else
|
60
|
+
grab_elements(method, watir_args, custom_args)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
#
|
66
|
+
# Defines accessor which clicks Watir element instance.
|
67
|
+
# Method name is element name.
|
68
|
+
#
|
69
|
+
# @param [Symbol] name Element name
|
70
|
+
# @param [Symbol] method Watir method
|
71
|
+
# @param [Array] args Splat of locators
|
72
|
+
# @param [Proc] block Block as element retriever
|
73
|
+
# @api private
|
74
|
+
#
|
75
|
+
def define_click_accessor(name, method, *args, &block)
|
76
|
+
watir_args, custom_args = extract_custom_args(args)
|
77
|
+
define_method name do |*opts|
|
78
|
+
if block_given?
|
79
|
+
instance_exec(*opts, &block).click
|
80
|
+
else
|
81
|
+
grab_elements(method, watir_args, custom_args).click
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
#
|
87
|
+
# Defines accessor which returns text of Watir element instance.
|
88
|
+
# Method name is element name.
|
89
|
+
#
|
90
|
+
# For textfield and textarea, value is returned.
|
91
|
+
# For select list, selected option text is returned.
|
92
|
+
# For other elements, text is returned.
|
93
|
+
#
|
94
|
+
# @param [Symbol] name Element name
|
95
|
+
# @param [Symbol] method Watir method
|
96
|
+
# @param [Array] args Splat of locators
|
97
|
+
# @param [Proc] block Block as element retriever
|
98
|
+
# @api private
|
99
|
+
#
|
100
|
+
def define_read_accessor(name, method, *args, &block)
|
101
|
+
watir_args, custom_args = extract_custom_args(args)
|
102
|
+
define_method name do |*opts|
|
103
|
+
element = if block_given?
|
104
|
+
instance_exec(*opts, &block)
|
105
|
+
else
|
106
|
+
grab_elements(method, watir_args, custom_args)
|
107
|
+
end
|
108
|
+
case method
|
109
|
+
when :text_field, :textarea
|
110
|
+
element.value
|
111
|
+
when :select_list
|
112
|
+
element.options.detect(&:selected?).text
|
113
|
+
else
|
114
|
+
element.text
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
#
|
120
|
+
# Defines accessor which sets value of Watir element instance.
|
121
|
+
# Method name is element name + "=".
|
122
|
+
#
|
123
|
+
# Note that custom block arguments are not used here.
|
124
|
+
#
|
125
|
+
# @param [Symbol] name Element name
|
126
|
+
# @param [Symbol] method Watir method
|
127
|
+
# @param [Array] args Splat of locators
|
128
|
+
# @param [Proc] block Block as element retriever
|
129
|
+
# @api private
|
130
|
+
#
|
131
|
+
def define_set_accessor(name, method, *args, &block)
|
132
|
+
watir_args, custom_args = extract_custom_args(args)
|
133
|
+
define_method :"#{name}=" do |*opts|
|
134
|
+
element = if block_given?
|
135
|
+
instance_exec(&block)
|
136
|
+
else
|
137
|
+
grab_elements(method, watir_args, custom_args)
|
138
|
+
end
|
139
|
+
if element.respond_to?(:set)
|
140
|
+
element.set *opts
|
141
|
+
else
|
142
|
+
element.send_keys *opts
|
143
|
+
end
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
#
|
148
|
+
# Defines accessor which selects option Watir element instance.
|
149
|
+
# Method name is element name + "=".
|
150
|
+
#
|
151
|
+
# Note that custom block arguments are not used here.
|
152
|
+
#
|
153
|
+
# @param [Symbol] name Element name
|
154
|
+
# @param [Symbol] method Watir method
|
155
|
+
# @param [Array] args Splat of locators
|
156
|
+
# @param [Proc] block Block as element retriever
|
157
|
+
# @api private
|
158
|
+
#
|
159
|
+
def define_select_accessor(name, method, *args, &block)
|
160
|
+
watir_args, custom_args = extract_custom_args(args)
|
161
|
+
define_method :"#{name}=" do |*opts|
|
162
|
+
if block_given?
|
163
|
+
instance_exec(&block).select *opts
|
164
|
+
else
|
165
|
+
grab_elements(method, watir_args, custom_args).select *opts
|
166
|
+
end
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
170
|
+
#
|
171
|
+
# Extracts custom arguments which Watirsome gracefully handles from
|
172
|
+
# mixed array with Watir locators.
|
173
|
+
#
|
174
|
+
# @param [Array] args
|
175
|
+
# @return Two arrays: Watir locators and custom locators
|
176
|
+
# @api private
|
177
|
+
#
|
178
|
+
def extract_custom_args(*args)
|
179
|
+
identifier = args.shift
|
180
|
+
watir_args, custom_args = [], []
|
181
|
+
identifier.each_with_index do |hashes, index|
|
182
|
+
watir_arg, custom_arg = {}, {}
|
183
|
+
if hashes && !hashes.is_a?(Proc)
|
184
|
+
hashes.each do |k, v|
|
185
|
+
if Watir::Element.instance_methods.include? :"#{k}?"
|
186
|
+
custom_arg[k] = identifier[index][k]
|
187
|
+
else
|
188
|
+
watir_arg[k] = v
|
189
|
+
end
|
190
|
+
end
|
191
|
+
end
|
192
|
+
watir_args << watir_arg unless watir_arg.empty?
|
193
|
+
custom_args << custom_arg unless custom_arg.empty?
|
194
|
+
end
|
195
|
+
|
196
|
+
return watir_args, custom_args
|
197
|
+
end
|
198
|
+
|
199
|
+
end # ClassMethods
|
200
|
+
|
201
|
+
|
202
|
+
module InstanceMethods
|
203
|
+
|
204
|
+
private
|
205
|
+
|
206
|
+
#
|
207
|
+
# Calls Watir browser instance to find element.
|
208
|
+
#
|
209
|
+
# @param [Symbol] method Watir method
|
210
|
+
# @param [Array] watir_args Watir locators
|
211
|
+
# @param [Array] custom_args Custom locators
|
212
|
+
# @api private
|
213
|
+
#
|
214
|
+
def grab_elements(method, watir_args, custom_args)
|
215
|
+
if custom_args.empty?
|
216
|
+
@browser.send(method, *watir_args)
|
217
|
+
else
|
218
|
+
plural = Watirsome.plural?(method)
|
219
|
+
method = :"#{method}s" unless plural
|
220
|
+
elements = @browser.send(method, *watir_args)
|
221
|
+
custom_args.first.each { |k, v| elements.to_a.select! { |e| e.send(:"#{k}?") == v } }
|
222
|
+
plural ? elements : elements.first
|
223
|
+
end
|
224
|
+
end
|
225
|
+
|
226
|
+
end # InstanceMethods
|
227
|
+
end # Accessors
|
228
|
+
end # Watirsome
|
@@ -0,0 +1,42 @@
|
|
1
|
+
module Watirsome
|
2
|
+
module Initializers
|
3
|
+
|
4
|
+
#
|
5
|
+
# Initializes page class.
|
6
|
+
# Allows to define "#initialize_page" which will be called as page constructor.
|
7
|
+
# After page is initialized, iterates through region and initialize each of them.
|
8
|
+
#
|
9
|
+
def initialize(browser)
|
10
|
+
@browser = browser
|
11
|
+
initialize_page if respond_to?(:initialize_page)
|
12
|
+
initialize_regions
|
13
|
+
end
|
14
|
+
|
15
|
+
#
|
16
|
+
# Iterates through definitions of "#initialize_region", thus implementing
|
17
|
+
# polymorphic Ruby modules (i.e. page regions).
|
18
|
+
#
|
19
|
+
# Only works with modules matching "Watirsome.region_matcher" regexp.
|
20
|
+
# @see Watirsome.region_matcher
|
21
|
+
#
|
22
|
+
def initialize_regions
|
23
|
+
# regions cacher
|
24
|
+
@initialized_regions ||= []
|
25
|
+
# get included and extended modules
|
26
|
+
modules = self.class.included_modules + (class << self; self end).included_modules
|
27
|
+
modules.uniq!
|
28
|
+
# make sure only necessary modules are being called
|
29
|
+
regexp = Watirsome.region_matcher
|
30
|
+
modules.select! { |m| regexp === m.to_s }
|
31
|
+
modules.each do |m|
|
32
|
+
# check that constructor is defined and we haven't called it before
|
33
|
+
if m.instance_methods.include?(:initialize_region) && !@initialized_regions.include?(m)
|
34
|
+
m.instance_method(:initialize_region).bind(self).call
|
35
|
+
# cache region
|
36
|
+
@initialized_regions << m
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
end # Initializers
|
42
|
+
end # Watirsome
|