page_magic 1.0.0.alpha21 → 1.0.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.
- checksums.yaml +4 -4
- data/.rubocop.yml +4 -1
- data/Gemfile +1 -1
- data/Gemfile.lock +9 -7
- data/README.md +181 -78
- data/VERSION +1 -1
- data/lib/page_magic/class_methods.rb +8 -7
- data/lib/page_magic/driver.rb +7 -7
- data/lib/page_magic/drivers.rb +6 -6
- data/lib/page_magic/element/locators.rb +24 -0
- data/lib/page_magic/element/query.rb +1 -0
- data/lib/page_magic/element/selector.rb +11 -9
- data/lib/page_magic/element.rb +47 -85
- data/lib/page_magic/element_context.rb +25 -5
- data/lib/page_magic/element_definition_builder.rb +39 -0
- data/lib/page_magic/elements.rb +24 -27
- data/lib/page_magic/exceptions.rb +11 -8
- data/lib/page_magic/instance_methods.rb +23 -21
- data/lib/page_magic/session.rb +43 -44
- data/lib/page_magic/session_methods.rb +28 -0
- data/lib/page_magic/wait_methods.rb +18 -0
- data/lib/page_magic/watcher.rb +41 -0
- data/lib/page_magic/watchers.rb +43 -0
- data/lib/page_magic.rb +13 -9
- data/spec/element_spec.rb +58 -160
- data/spec/page_magic/class_methods_spec.rb +7 -6
- data/spec/page_magic/driver_spec.rb +14 -13
- data/spec/page_magic/drivers_spec.rb +7 -6
- data/spec/page_magic/element/locators_spec.rb +33 -0
- data/spec/page_magic/element/query_spec.rb +44 -19
- data/spec/page_magic/element/selector_spec.rb +45 -3
- data/spec/page_magic/element_context_spec.rb +41 -11
- data/spec/page_magic/element_definition_builder_spec.rb +76 -0
- data/spec/page_magic/elements_spec.rb +94 -141
- data/spec/page_magic/instance_methods_spec.rb +15 -10
- data/spec/page_magic/session_methods_spec.rb +36 -0
- data/spec/page_magic/session_spec.rb +78 -79
- data/spec/page_magic/wait_methods_spec.rb +41 -0
- data/spec/page_magic/watchers_spec.rb +74 -0
- data/spec/page_magic_spec.rb +9 -9
- data/spec/spec_helper.rb +1 -0
- data/spec/support/shared_contexts/nested_elements_html_context.rb +16 -0
- data/spec/support/shared_contexts/{webapp_context.rb → webapp_fixture_context.rb} +0 -0
- data/spec/support/shared_examples.rb +25 -0
- data/spec/watcher_spec.rb +49 -0
- metadata +23 -11
- data/lib/page_magic/element/method_observer.rb +0 -20
- data/spec/member_methods_spec.rb +0 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 72362e511bc0f363179017fa7363ce20995b28b1
|
4
|
+
data.tar.gz: a7c4b1ba4c85213592217702bedcb0f76080da8e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6c5646258cadec859bfa0923db62334d055ba0ede606d6f62c05e73b21524832a0b4da4be9be2f6dc20f5be47e2c041cf3a1224693b7549ec6db91e45fa9041d
|
7
|
+
data.tar.gz: 6a82e9164bdb65b49cb892ea83f67334ae512b91305974329fa041bf884c63d0145dfde2ac503de133d12c51a8504b85e82d3ce06d851764763bda6631a5d6b5
|
data/.rubocop.yml
CHANGED
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
@@ -12,7 +12,7 @@ GEM
|
|
12
12
|
astrolabe (1.3.1)
|
13
13
|
parser (~> 2.2)
|
14
14
|
builder (3.2.2)
|
15
|
-
capybara (2.
|
15
|
+
capybara (2.5.0)
|
16
16
|
mime-types (>= 1.16)
|
17
17
|
nokogiri (>= 1.3.3)
|
18
18
|
rack (>= 1.0.0)
|
@@ -21,7 +21,7 @@ GEM
|
|
21
21
|
certifi (2015.08.10)
|
22
22
|
childprocess (0.3.9)
|
23
23
|
ffi (~> 1.0, >= 1.0.11)
|
24
|
-
cliver (0.
|
24
|
+
cliver (0.3.2)
|
25
25
|
codeclimate-test-reporter (0.4.8)
|
26
26
|
simplecov (>= 0.7.1, < 1.0.0)
|
27
27
|
diff-lcs (1.2.5)
|
@@ -69,9 +69,9 @@ GEM
|
|
69
69
|
rack (~> 1.2)
|
70
70
|
parser (2.2.3.0)
|
71
71
|
ast (>= 1.1, < 3.0)
|
72
|
-
poltergeist (1.
|
73
|
-
capybara (~> 2.1
|
74
|
-
cliver (~> 0.
|
72
|
+
poltergeist (1.7.0)
|
73
|
+
capybara (~> 2.1)
|
74
|
+
cliver (~> 0.3.1)
|
75
75
|
multi_json (~> 1.0)
|
76
76
|
websocket-driver (>= 0.2.0)
|
77
77
|
powerpack (0.1.1)
|
@@ -131,7 +131,9 @@ GEM
|
|
131
131
|
watir-webdriver (0.6.4)
|
132
132
|
selenium-webdriver (>= 2.18.0)
|
133
133
|
websocket (1.0.7)
|
134
|
-
websocket-driver (0.3
|
134
|
+
websocket-driver (0.6.3)
|
135
|
+
websocket-extensions (>= 0.1.0)
|
136
|
+
websocket-extensions (0.1.2)
|
135
137
|
xpath (2.0.0)
|
136
138
|
nokogiri (~> 1.3)
|
137
139
|
yard (0.8.7.6)
|
@@ -141,7 +143,7 @@ PLATFORMS
|
|
141
143
|
|
142
144
|
DEPENDENCIES
|
143
145
|
activesupport (~> 4)
|
144
|
-
capybara (
|
146
|
+
capybara (= 2.5.0)
|
145
147
|
codeclimate-test-reporter
|
146
148
|
github-markup (~> 1.4)
|
147
149
|
jeweler (~> 2.0)
|
data/README.md
CHANGED
@@ -5,51 +5,40 @@ PageMagic is an API for testing web applications.
|
|
5
5
|
It has a simple but powerful DSL which makes modelling and interacting with your pages easy.
|
6
6
|
|
7
7
|
Wouldn't it be great if there was a framework that could:
|
8
|
-
- [Model your pages](#
|
9
|
-
- [Fluently define
|
8
|
+
- [Model your pages](#defining-pages)
|
9
|
+
- [Fluently define event hooks / waiters on page elements](#hooks)
|
10
10
|
- [Map paths to pages so that the correct page object is loaded as you navigate](#page-mapping)
|
11
11
|
- [Be super dynamic](#dynamic-selectors)
|
12
12
|
|
13
13
|
Well PageMagic might just be the answer!
|
14
14
|
|
15
15
|
Give it a try and let us know what you think! There will undoubtedly be things that can be improved and issues that we are not aware of so your feedback/pull requests are greatly appreciated!
|
16
|
+
# Contents
|
17
|
+
- [Installation](#installation)
|
18
|
+
- [Starting a session](#starting-a-session)
|
19
|
+
- [Defining Pages](#defining-pages)
|
20
|
+
- [Elements](#elements)
|
21
|
+
- [Interacting with elements](#interacting-with-elements)
|
22
|
+
- [Multple Results](#multiple-results)
|
23
|
+
- [Sub elements](#sub-elements)
|
24
|
+
- [Custom elements](#custom-elements)
|
25
|
+
- [Hooks](#hooks)
|
26
|
+
- [Element event hooks](#element-event-hooks)
|
27
|
+
- [On load hook](#on-load-hook)
|
28
|
+
- [Helper Methods](#helper-methods)
|
29
|
+
- [Dynamic Selectors](#dynamic-selectors)
|
30
|
+
- [Watchers](#watchers)
|
31
|
+
- [Method watchers](#method-watchers)
|
32
|
+
- [Simple watchers](#simple-watchers)
|
33
|
+
- [Custom watchers](#custom-watchers)
|
34
|
+
- [Page mapping](#page-mapping)
|
35
|
+
- [Drivers](#drivers)
|
36
|
+
- [Pulling it all together](#pulling-it-all-together)
|
16
37
|
|
17
38
|
# Installation
|
18
39
|
`gem install page_magic --pre`
|
19
40
|
|
20
|
-
#
|
21
|
-
Imagine the scene. You've written a web based mail client and now you want to test it...
|
22
|
-
You have a scenario in mind that goes something along the lines of:
|
23
|
-
- Send yourself an email with a unique subject
|
24
|
-
- Go to the Login page and login
|
25
|
-
- Find the message using it's unique subject and read it
|
26
|
-
- delete the message
|
27
|
-
|
28
|
-
You're mail client is total 21st century so there is loads of lovely ajax etc...
|
29
|
-
|
30
|
-
Writing robust, nice looking code for this could be a real pain...
|
31
|
-
Here's how you might do it with PageMagic (note that the following code would work if we you had a compatible mail web app but in this case is purely illustrative)
|
32
|
-
|
33
|
-
What we really want to write is something like
|
34
|
-
```ruby
|
35
|
-
test_subject = send_test_mail('test@21st-century-mail.com')
|
36
|
-
#Visit your site using a PageMagic session we prepared earlier
|
37
|
-
session.visit(LoginPage)
|
38
|
-
|
39
|
-
#Login using some handy helper method on our page object
|
40
|
-
session.login('username', 'password')
|
41
|
-
|
42
|
-
#Find the message amongst all the other messages that are on screen and read it
|
43
|
-
session.message(subject: test_subject).read.click
|
44
|
-
|
45
|
-
#Now we are on the message screen lets delete it without having to worry about the ajax.
|
46
|
-
session.delete_message
|
47
|
-
|
48
|
-
fail "message is still there!" if session.message(subject: test_subject).exists?
|
49
|
-
|
50
|
-
# Sweet :)
|
51
|
-
```
|
52
|
-
## Starting a session
|
41
|
+
# Starting a session
|
53
42
|
To start a PageMagic session simply decide what browser you want to use and pass it to PageMagic's `.session` method
|
54
43
|
```ruby
|
55
44
|
session = PageMagic.session(browser: :chrome, url: 'https://21st-century-mail.com')
|
@@ -63,8 +52,15 @@ Under the hood, PageMagic is using [Capybara](https://github.com/jnicklas/capyba
|
|
63
52
|
|
64
53
|
**Note:** We don't want to impose particular driver versions so PageMagic does not list any as dependencies. Therefore you will need add the requiste gem to your Gemfile.
|
65
54
|
|
66
|
-
|
67
|
-
To define something that PageMagic can work with, simply include PageMagic in to a class.
|
55
|
+
# Defining Pages
|
56
|
+
To define something that PageMagic can work with, simply include PageMagic in to a class.
|
57
|
+
```ruby
|
58
|
+
class LoginPage
|
59
|
+
include PageMagic
|
60
|
+
end
|
61
|
+
```
|
62
|
+
## Elements
|
63
|
+
Defining elements is easy see the example below.
|
68
64
|
|
69
65
|
```ruby
|
70
66
|
class LoginPage
|
@@ -74,10 +70,9 @@ class LoginPage
|
|
74
70
|
button(:login_button, text: 'login')
|
75
71
|
end
|
76
72
|
```
|
77
|
-
In the case of the Login page, it's easy to imagine that it will have text fields for a username and password and a button to login in with.
|
78
73
|
|
79
|
-
|
80
|
-
Elements are defined with
|
74
|
+
### Interacting with elements
|
75
|
+
Elements are defined with an id which is the name of the method you will use to reference it. In the above example, the textfields and button were defined with the id's, `:username`, `:password`, and `:login_button`
|
81
76
|
|
82
77
|
After visiting a page with a PageMagic session, you can access all of the elements of that page through the session itself.
|
83
78
|
```ruby
|
@@ -85,24 +80,67 @@ session.username.set 'joe@blogs.com'
|
|
85
80
|
session.password.set 'passw0rd'
|
86
81
|
session.login_button.click
|
87
82
|
```
|
88
|
-
|
89
|
-
|
90
|
-
|
83
|
+
#### Multple Results
|
84
|
+
Where an element has been scoped to return multple results, these will be returned in an array. These elements can be defined
|
85
|
+
using all of the same features as described in this readme and behave in exactly the same way.
|
91
86
|
```ruby
|
92
87
|
class LoginPage
|
93
|
-
|
88
|
+
element :links, css: 'a'
|
94
89
|
end
|
95
90
|
|
91
|
+
session.link => Array<Element>
|
92
|
+
```
|
93
|
+
|
94
|
+
### Sub Elements
|
95
|
+
If your pages are complex you can use PageMagic to compose pages, their elements and subelements to as many levels as you need to.
|
96
|
+
|
97
|
+
```ruby
|
96
98
|
class MailBox
|
97
99
|
include PageMagic
|
100
|
+
|
101
|
+
element :message, id: 'message_id' do
|
102
|
+
link(:read, text: 'read')
|
103
|
+
end
|
104
|
+
end
|
105
|
+
```
|
106
|
+
Sub elements can be accessed through their parent elements e.g:
|
107
|
+
```
|
108
|
+
session.message.read.click
|
109
|
+
```
|
110
|
+
|
111
|
+
### Custom elements
|
112
|
+
PageMagic allows you to define your own custom elements.
|
113
|
+
```ruby
|
114
|
+
class Nav < PageMagic::Element
|
115
|
+
selector css: '.nav
|
116
|
+
|
117
|
+
element :options, css: '.options' do
|
118
|
+
link(:link1, id: 'link1')
|
119
|
+
link(:link2, id: 'link2')
|
120
|
+
link(:link3, id: 'link3')
|
121
|
+
end
|
98
122
|
end
|
99
123
|
|
100
|
-
class
|
124
|
+
class MyPage
|
101
125
|
include PageMagic
|
126
|
+
element Nav
|
102
127
|
end
|
103
128
|
```
|
104
|
-
|
105
|
-
|
129
|
+
If an id is not specified then the name of the element class will be used. The selector for the element can be specified on the class itself or overiden when defining the element on the page. The custom element can also be extended as with other elements.
|
130
|
+
```ruby
|
131
|
+
class MyPage
|
132
|
+
include PageMagic
|
133
|
+
element Nav, :navigation, selector: '.custom' do
|
134
|
+
link(:extr_link, id: 'extra-link')
|
135
|
+
do
|
136
|
+
end
|
137
|
+
```
|
138
|
+
|
139
|
+
## Hooks
|
140
|
+
PageMagic provides hooks to allow you to interact at the right moments with your pages
|
141
|
+
|
142
|
+
### On load hook
|
143
|
+
PageMagic lets you define an on_load hook for your pages. This lets you write any custom wait logic you might need
|
106
144
|
before letting execution continue.
|
107
145
|
```ruby
|
108
146
|
class LoginPage
|
@@ -114,10 +152,25 @@ class LoginPage
|
|
114
152
|
end
|
115
153
|
```
|
116
154
|
|
117
|
-
###
|
155
|
+
### Element event hooks
|
156
|
+
Frequently, you are going to have to work with pages that make heavy use of ajax. This means that just because you've clicked something, it doesn't mean that the action is finished. For these occasions PageMagic provides `before_events` and `after_events` hooks that you use to perform custom actions and wait for things to happen.
|
157
|
+
|
158
|
+
```ruby
|
159
|
+
class MessagePage
|
160
|
+
include PageMagic
|
161
|
+
## code defining other elements, such as subject and body
|
162
|
+
|
163
|
+
link(:delete id: 'delete-message') do
|
164
|
+
after_events do
|
165
|
+
wait_until{fancy_animation_has_disappeared?}
|
166
|
+
end
|
167
|
+
end
|
168
|
+
end
|
169
|
+
```
|
170
|
+
|
171
|
+
## Helper methods
|
118
172
|
Using elements that are defined on a page is great, but if you are enacting a procedure through interacting with a few of them then your code could end up with some pretty repetitive code. In this case you can define helper methods instead.
|
119
173
|
|
120
|
-
In the above [example](#an example) we used a helper called `login`.
|
121
174
|
```ruby
|
122
175
|
class LoginPage
|
123
176
|
# ... code defining elements as shown above
|
@@ -134,25 +187,9 @@ We can interact with helper in the same way as we did page elements.
|
|
134
187
|
```ruby
|
135
188
|
session.login('joe', 'blogs')
|
136
189
|
```
|
137
|
-
##Defining sub elements
|
138
|
-
If your pages are complex you can use PageMagic to compose pages, their elements and subelements to as many levels as you need to.
|
139
190
|
|
140
|
-
In the example we accessed a read link that resided with a particular message
|
141
|
-
```ruby
|
142
|
-
class MailBox
|
143
|
-
include PageMagic
|
144
|
-
|
145
|
-
element :message, id: 'message_id' do
|
146
|
-
link(:read, text: 'read')
|
147
|
-
end
|
148
|
-
end
|
149
|
-
```
|
150
|
-
Sub elements can be accessed through their parent elements e.g:
|
151
|
-
```
|
152
|
-
session.message.read.click
|
153
|
-
```
|
154
191
|
## Dynamic Selectors
|
155
|
-
In
|
192
|
+
In some cases you will able to specify the selector for an element until runtime. PageMagic allows you to handle such situations with support for dynamic selectors.
|
156
193
|
|
157
194
|
```ruby
|
158
195
|
class MailBox
|
@@ -168,23 +205,60 @@ Here we have defined the 'message' element using a block that takes subject argu
|
|
168
205
|
```ruby
|
169
206
|
session.message(subject: 'test message')
|
170
207
|
```
|
171
|
-
## Interaction hooks
|
172
|
-
Frequently, you are going to have to work with pages that make heavy use of ajax. This means that just because you've clicked something, it doesn't mean that the action is finished. For these occasions PageMagic provides `before_events` and `after_events` hooks that you use to perform custom actions and wait for things to happen. In the case of our web based mail client, we could imagine that when deleting the email, a fancy spinner is displayed whilst the application sends an ajax request to have the message deleted. In this case we wouldn't want to proceed until this has disappeared.
|
173
208
|
|
209
|
+
# Watchers
|
210
|
+
PageMagic lets you set a watcher on any of the elements that you have defined on your pages. Use watchers to decide when
|
211
|
+
things have changed.
|
212
|
+
|
213
|
+
**Note**: Watchers are not inherited
|
214
|
+
|
215
|
+
## Method watchers
|
216
|
+
Method watchers watch the output of the given method name.
|
174
217
|
```ruby
|
175
|
-
|
176
|
-
|
177
|
-
|
218
|
+
button :javascript_button, css: '.fancy_button' do
|
219
|
+
before_events do
|
220
|
+
watch(:url)
|
221
|
+
end
|
178
222
|
|
179
|
-
|
180
|
-
|
181
|
-
|
223
|
+
after_events do
|
224
|
+
wait_until{changed?(:url)}
|
225
|
+
end
|
226
|
+
end
|
227
|
+
```
|
228
|
+
|
229
|
+
## Simple watchers
|
230
|
+
Simple watchers use the `watch` method passing two parameters, the first is the name of the element you want to keep an
|
231
|
+
eye and the second is the method that needs to be called to get the value that should be observed.
|
232
|
+
```ruby
|
233
|
+
element :product_row, css '.cta' do
|
234
|
+
before_events do
|
235
|
+
element(:total, css: '.total')
|
236
|
+
end
|
237
|
+
|
238
|
+
after_events do
|
239
|
+
wait_until{changed?(:total)}
|
240
|
+
end
|
241
|
+
end
|
242
|
+
```
|
243
|
+
## Custom watchers
|
244
|
+
Custom watchers are defined by passing a name and block parameter to the `watch` method. The block returns the value
|
245
|
+
that needs to be observed. Use watch in this way if you need to do something non standard to obtain a value or to
|
246
|
+
access an element not located within the current element but elsewhere within the page.
|
247
|
+
```ruby
|
248
|
+
element :product_row, css '.cta' do
|
249
|
+
before_events do
|
250
|
+
element(:total) do
|
251
|
+
session.nav.total.text
|
182
252
|
end
|
183
253
|
end
|
254
|
+
|
255
|
+
after_events do
|
256
|
+
wait_until{changed?(:total)}
|
257
|
+
end
|
184
258
|
end
|
185
259
|
```
|
186
|
-
|
187
|
-
|
260
|
+
# Page mapping
|
261
|
+
With PageMagic you can map which pages should be used to handle which URL paths. This is a pretty killer feature that will remove a lot of the juggling and bring back fluency to your code!
|
188
262
|
```ruby
|
189
263
|
# define what pages map to what
|
190
264
|
browser.define_page_mappings %r{/messages/\d+} => MessagePage,
|
@@ -193,6 +267,7 @@ browser.define_page_mappings %r{/messages/\d+} => MessagePage,
|
|
193
267
|
```
|
194
268
|
You can use even use regular expressions to map multiple paths to the same page. In the above example we are mapping paths that that starts with '/messages/' and are followed by one ore more digits to the `MessagePage` class.
|
195
269
|
|
270
|
+
# Drivers
|
196
271
|
## Registering a custom driver
|
197
272
|
You can register any Capybara compliant driver as follows
|
198
273
|
|
@@ -211,6 +286,34 @@ PageMagic.drivers.register Webkit
|
|
211
286
|
#3. Use registered driver
|
212
287
|
session = PageMagic.session(browser: webkit, url: 'https://21st-century-mail.com')
|
213
288
|
```
|
214
|
-
##What else can you do with PageMagic?
|
215
|
-
PageMagic has lots of other useful features. I'm writing up the documentation so check back here soon!
|
216
289
|
|
290
|
+
# Pulling it all together
|
291
|
+
Imagine the scene. You've written a web based mail client and now you want to test it...
|
292
|
+
You have a scenario in mind that goes something along the lines of:
|
293
|
+
- Send yourself an email with a unique subject
|
294
|
+
- Go to the Login page and login
|
295
|
+
- Find the message using it's unique subject and read it
|
296
|
+
- delete the message
|
297
|
+
|
298
|
+
You're mail client is totally 21st century so there is loads of lovely ajax etc...
|
299
|
+
|
300
|
+
Using the PageMagic you can implement an API that might look something like the following to use:
|
301
|
+
|
302
|
+
```ruby
|
303
|
+
test_subject = send_test_mail('test@21st-century-mail.com')
|
304
|
+
#Visit your site using a PageMagic session we prepared earlier
|
305
|
+
session.visit(LoginPage)
|
306
|
+
|
307
|
+
#Login using some handy helper method on our page object
|
308
|
+
session.login('username', 'password')
|
309
|
+
|
310
|
+
#Find the message amongst all the other messages that are on screen and read it
|
311
|
+
session.message(subject: test_subject).read.click
|
312
|
+
|
313
|
+
#Now we are on the message screen lets delete it without having to worry about the ajax.
|
314
|
+
session.delete_message
|
315
|
+
|
316
|
+
fail "message is still there!" if session.message(subject: test_subject).exists?
|
317
|
+
|
318
|
+
# Sweet :)
|
319
|
+
```
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
1.0.0
|
1
|
+
1.0.0
|
@@ -1,15 +1,9 @@
|
|
1
1
|
module PageMagic
|
2
2
|
# module ClassMethods - contains class level methods for PageObjects
|
3
3
|
module ClassMethods
|
4
|
+
# Default block to be run when a page is loaded. This is used if a specific handler is not registered
|
4
5
|
DEFAULT_ON_LOAD = proc {}
|
5
6
|
|
6
|
-
# getter setter for storing the page url
|
7
|
-
# @param [String] url the url of the page
|
8
|
-
def url(url = nil)
|
9
|
-
@url = url if url
|
10
|
-
@url
|
11
|
-
end
|
12
|
-
|
13
7
|
# sets block to run when page has loaded
|
14
8
|
# if one has not been set on the page object class it will return a default block that does nothing
|
15
9
|
def on_load(&block)
|
@@ -17,6 +11,13 @@ module PageMagic
|
|
17
11
|
@on_load = block
|
18
12
|
end
|
19
13
|
|
14
|
+
# getter setter for storing the page url
|
15
|
+
# @param [String] url the url of the page
|
16
|
+
def url(url = nil)
|
17
|
+
@url = url if url
|
18
|
+
@url
|
19
|
+
end
|
20
|
+
|
20
21
|
# Visit this page based on the class level registered url
|
21
22
|
# @param [Object] application rack application (optional)
|
22
23
|
# @param [Symbol] browser name of browser
|
data/lib/page_magic/driver.rb
CHANGED
@@ -20,13 +20,6 @@ module PageMagic
|
|
20
20
|
@supported_browsers = supported_browsers
|
21
21
|
end
|
22
22
|
|
23
|
-
# Determines if the given browser name is supported by this driver definition
|
24
|
-
# @param [Symbol] browser name of browser
|
25
|
-
# @return [Boolean] true if definition supports the given driver name
|
26
|
-
def support?(browser)
|
27
|
-
supported_browsers.include?(browser)
|
28
|
-
end
|
29
|
-
|
30
23
|
# Build a new driver instance based on this definition
|
31
24
|
# @param [Object] app - rack compatible application
|
32
25
|
# @param [Symbol] browser name of required browser
|
@@ -35,5 +28,12 @@ module PageMagic
|
|
35
28
|
def build(app, browser:, options:{})
|
36
29
|
handler.call(app, options, browser)
|
37
30
|
end
|
31
|
+
|
32
|
+
# Determines if the given browser name is supported by this driver definition
|
33
|
+
# @param [Symbol] browser name of browser
|
34
|
+
# @return [Boolean] true if definition supports the given driver name
|
35
|
+
def support?(browser)
|
36
|
+
supported_browsers.include?(browser)
|
37
|
+
end
|
38
38
|
end
|
39
39
|
end
|
data/lib/page_magic/drivers.rb
CHANGED
@@ -7,12 +7,6 @@ module PageMagic
|
|
7
7
|
@all ||= []
|
8
8
|
end
|
9
9
|
|
10
|
-
# Make a driver available for selection when creating calling {PageMagic.session}
|
11
|
-
# @param [Driver] driver driver definition
|
12
|
-
def register(driver)
|
13
|
-
all << driver
|
14
|
-
end
|
15
|
-
|
16
10
|
# Find a driver definition based on its registered name
|
17
11
|
# @param [Symbol] browser registered name of the required browser
|
18
12
|
def find(browser)
|
@@ -31,6 +25,12 @@ module PageMagic
|
|
31
25
|
end
|
32
26
|
end
|
33
27
|
|
28
|
+
# Make a driver available for selection when creating calling {PageMagic.session}
|
29
|
+
# @param [Driver] driver driver definition
|
30
|
+
def register(driver)
|
31
|
+
all << driver
|
32
|
+
end
|
33
|
+
|
34
34
|
# returns true if this driver instance is equal to the supplied object
|
35
35
|
# @param [Object] other subject of equality check
|
36
36
|
# @return [Boolean] true if the object is a match
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module PageMagic
|
2
|
+
class Element
|
3
|
+
# contains method for finding element definitions
|
4
|
+
module Locators
|
5
|
+
# message used when raising {ElementMissingException} from methods within this module
|
6
|
+
ELEMENT_NOT_DEFINED_MSG = 'Element not defined: %s'
|
7
|
+
|
8
|
+
# find an element definition based on its name
|
9
|
+
# @param [Symbol] name name of the element
|
10
|
+
# @return [Element] element definition with the given name
|
11
|
+
# @raise [ElementMissingException] raised when element with the given name is not found
|
12
|
+
def element_by_name(name, *args)
|
13
|
+
defintion = element_definitions[name]
|
14
|
+
fail ElementMissingException, (ELEMENT_NOT_DEFINED_MSG % name) unless defintion
|
15
|
+
defintion.call(*args.append(self))
|
16
|
+
end
|
17
|
+
|
18
|
+
# @return [Array] class level defined element definitions
|
19
|
+
def element_definitions
|
20
|
+
self.class.element_definitions
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -14,6 +14,15 @@ module PageMagic
|
|
14
14
|
end
|
15
15
|
end
|
16
16
|
|
17
|
+
attr_reader :name, :formatter, :exact, :supports_type
|
18
|
+
|
19
|
+
def initialize(selector = nil, supports_type: false, exact: false, &formatter)
|
20
|
+
@name = selector
|
21
|
+
@formatter = formatter || proc { |arg| arg }
|
22
|
+
@supports_type = supports_type
|
23
|
+
@exact = exact
|
24
|
+
end
|
25
|
+
|
17
26
|
# Build selector query parameters for Capybara's find method
|
18
27
|
# @param [Symbol] element_type the type of browser element being found. e.g :link
|
19
28
|
# @param [Hash] locator the selection method and its parameter. E.g. text: 'click me'
|
@@ -22,20 +31,13 @@ module PageMagic
|
|
22
31
|
array << element_type if supports_type
|
23
32
|
array << name if name
|
24
33
|
array << formatter.call(locator)
|
34
|
+
array << { exact: true } if exact
|
25
35
|
end
|
26
36
|
end
|
27
37
|
|
28
|
-
attr_reader :name, :formatter, :supports_type
|
29
|
-
|
30
|
-
def initialize(selector = nil, supports_type: false, &formatter)
|
31
|
-
@name = selector
|
32
|
-
@formatter = formatter || proc { |arg| arg }
|
33
|
-
@supports_type = supports_type
|
34
|
-
end
|
35
|
-
|
36
38
|
XPATH = Selector.new(:xpath, supports_type: false)
|
37
39
|
ID = Selector.new(:id, supports_type: false)
|
38
|
-
LABEL = Selector.new(:field, supports_type: false)
|
40
|
+
LABEL = Selector.new(:field, supports_type: false, exact: true)
|
39
41
|
|
40
42
|
CSS = Selector.new(supports_type: false)
|
41
43
|
TEXT = Selector.new(supports_type: true)
|