site_prism 0.9.9 → 1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +962 -0
- data/lib/site_prism/element_container.rb +0 -66
- data/lib/site_prism/exceptions.rb +0 -4
- data/lib/site_prism/page.rb +0 -51
- data/lib/site_prism/section.rb +0 -4
- data/lib/site_prism/version.rb +2 -1
- metadata +3 -2
data/README.md
ADDED
@@ -0,0 +1,962 @@
|
|
1
|
+
# SitePrism
|
2
|
+
_A Page Object Model DSL for Capybara_
|
3
|
+
|
4
|
+
SitePrism gives you a simple, clean and semantic DSL for describing your site using the Page Object Model pattern, for use with Capybara in automated acceptance testing.
|
5
|
+
|
6
|
+
Find the pretty documentation here: http://rdoc.info/gems/site_prism/frames
|
7
|
+
|
8
|
+
## Synopsis
|
9
|
+
|
10
|
+
Here's an overview of how SitePrism is designed to be used:
|
11
|
+
|
12
|
+
```ruby
|
13
|
+
# define our site's pages
|
14
|
+
|
15
|
+
class Home < SitePrism::Page
|
16
|
+
set_url "http://www.google.com"
|
17
|
+
set_url_matcher /google.com\/?/
|
18
|
+
|
19
|
+
element :search_field, "input[name='q']"
|
20
|
+
element :search_button, "button[name='btnK']"
|
21
|
+
elements :footer_links, "#footer a"
|
22
|
+
section :menu, MenuSection, "#gbx3"
|
23
|
+
end
|
24
|
+
|
25
|
+
class SearchResults < SitePrism::Page
|
26
|
+
set_url_matcher /google.com\/results\?.*/
|
27
|
+
|
28
|
+
section :menu, MenuSection, "#gbx3"
|
29
|
+
sections :search_results, SearchResultSection, "#results li"
|
30
|
+
end
|
31
|
+
|
32
|
+
# define sections used on multiple pages or multiple times on one page
|
33
|
+
|
34
|
+
class MenuSection < SitePrism::Section
|
35
|
+
element :search, "a.search"
|
36
|
+
element :images, "a.image-search"
|
37
|
+
element :maps, "a.map-search"
|
38
|
+
end
|
39
|
+
|
40
|
+
class SearchResultSection < SitePrism::Section
|
41
|
+
element :title, "a.title"
|
42
|
+
element :blurb, "span.result-decription"
|
43
|
+
end
|
44
|
+
|
45
|
+
# now for some tests
|
46
|
+
|
47
|
+
When /^I navigate to the google home page$/ do
|
48
|
+
@home = Home.new
|
49
|
+
@home.load
|
50
|
+
end
|
51
|
+
|
52
|
+
Then /^the home page should contain the menu and the search form$/ do
|
53
|
+
@home.wait_for_menu # menu loads after a second or 2, give it time to arrive
|
54
|
+
@home.should have_menu
|
55
|
+
@home.should have_search_field
|
56
|
+
@home.should have_search_button
|
57
|
+
end
|
58
|
+
|
59
|
+
When /^I search for Sausages$/ do
|
60
|
+
@home.search_field.set "Sausages"
|
61
|
+
@home.search_button.click
|
62
|
+
end
|
63
|
+
|
64
|
+
Then /^the search results page is displayed$/ do
|
65
|
+
@results_page = SearchResults.new
|
66
|
+
@results_page.should be_displayed
|
67
|
+
end
|
68
|
+
|
69
|
+
Then /^the search results page contains 10 individual search results$/ do
|
70
|
+
@results_page.wait_for_search_results
|
71
|
+
@results_page.should have_search_results
|
72
|
+
@results_page.search_results.size.should == 10
|
73
|
+
end
|
74
|
+
|
75
|
+
Then /^the search results contain a link to the wikipedia sausages page$/ do
|
76
|
+
@results_page.search_results.map {|sr| sr.title['href']}.should include "http://en.wikipedia.org/wiki/Sausage"
|
77
|
+
end
|
78
|
+
```
|
79
|
+
|
80
|
+
Now for the details...
|
81
|
+
|
82
|
+
## Setup
|
83
|
+
|
84
|
+
### Installation
|
85
|
+
|
86
|
+
To install SitePrism:
|
87
|
+
|
88
|
+
```bash
|
89
|
+
gem install site_prism
|
90
|
+
```
|
91
|
+
|
92
|
+
### Using SitePrism with Cucumber
|
93
|
+
|
94
|
+
If you are using cucumber, here's what needs requiring:
|
95
|
+
|
96
|
+
```ruby
|
97
|
+
require 'capybara'
|
98
|
+
require 'capybara/dsl'
|
99
|
+
require 'capybara/cucumber'
|
100
|
+
require 'selenium-webdriver'
|
101
|
+
require 'site_prism'
|
102
|
+
```
|
103
|
+
|
104
|
+
### Using SitePrism with RSpec
|
105
|
+
|
106
|
+
If you're using rspec instead, here's what needs requiring:
|
107
|
+
|
108
|
+
```ruby
|
109
|
+
require 'capybara'
|
110
|
+
require 'capybara/dsl'
|
111
|
+
require 'capybara/rspec'
|
112
|
+
require 'selenium-webdriver'
|
113
|
+
require 'site_prism'
|
114
|
+
```
|
115
|
+
|
116
|
+
## Introduction to the Page Object Model
|
117
|
+
|
118
|
+
The Page Object Model is a test automation pattern that aims to create
|
119
|
+
an abstraction of your site's user interface that can be used in tests.
|
120
|
+
The most common way to do this is to model each page as a class, and
|
121
|
+
to then use instances of those classes in your tests.
|
122
|
+
|
123
|
+
If a class represents a page then each element of the page is
|
124
|
+
represented by a method that, when called, returns a reference to that
|
125
|
+
element that can then be acted upon (clicked, set text value), or
|
126
|
+
queried (is it enabled? visible?).
|
127
|
+
|
128
|
+
SitePrism is based around this concept, but goes further as you'll see
|
129
|
+
below by also allowing modelling of repeated sections that appear on
|
130
|
+
muliple pages, or many times on a page using the concept of sections.
|
131
|
+
|
132
|
+
## Pages
|
133
|
+
|
134
|
+
As you might be able to guess from the name, pages are fairly central to
|
135
|
+
the Page Object Model. Here's how SitePrism models them:
|
136
|
+
|
137
|
+
### Creating a Page Model
|
138
|
+
|
139
|
+
The simplest page is one that has nothing defined in it. Here's an
|
140
|
+
example of how to begin modelling a home page:
|
141
|
+
|
142
|
+
```ruby
|
143
|
+
class Home < SitePrism::Page
|
144
|
+
end
|
145
|
+
```
|
146
|
+
|
147
|
+
The above has nothing useful defined, only the name.
|
148
|
+
|
149
|
+
### Adding a URL
|
150
|
+
|
151
|
+
A page usually has a URL. If you want to be able to navigate to a page,
|
152
|
+
you'll need to set its URL. Here's how:
|
153
|
+
|
154
|
+
```ruby
|
155
|
+
class Home < SitePrism::Page
|
156
|
+
set_url "http://www.google.com"
|
157
|
+
end
|
158
|
+
```
|
159
|
+
|
160
|
+
Note that setting a URL is optional - you only need to set a url if you want to be able to navigate
|
161
|
+
directly to that page. It makes sense to set the URL for a page model of a home
|
162
|
+
page or a login page, but probably not a search results page.
|
163
|
+
|
164
|
+
### Navigating to the Page
|
165
|
+
|
166
|
+
Once the URL has been set (using `set_url`), you can navigate directly
|
167
|
+
to the page using `#load`:
|
168
|
+
|
169
|
+
```ruby
|
170
|
+
@home_page = Home.new
|
171
|
+
@home_page.load
|
172
|
+
```
|
173
|
+
|
174
|
+
This will tell which ever capybara driver you have configured to
|
175
|
+
navigate to the URL set against that page's class.
|
176
|
+
|
177
|
+
### Verifying that a particular page is displayed
|
178
|
+
|
179
|
+
Automated tests often need to verify that a particular page is
|
180
|
+
displayed. Intuitively you'd think that simply checking that the URL
|
181
|
+
defined using `set_url` is the current page in the browser would be enough, but experience shows that it's
|
182
|
+
not. It is far more robust to check to see if the browser's current url
|
183
|
+
matches a regular expression. For example, though `account/1` and `account/2`
|
184
|
+
are the same page, their URLs are different. To deal with this,
|
185
|
+
SitePrism provides the ability to set a URL matcher.
|
186
|
+
|
187
|
+
```ruby
|
188
|
+
class Account < SitePrism::Page
|
189
|
+
set_url_matcher /\account\/\d+/
|
190
|
+
end
|
191
|
+
```
|
192
|
+
|
193
|
+
Once a URL matcher is set for a page, you can test to see if it is
|
194
|
+
displayed:
|
195
|
+
|
196
|
+
```ruby
|
197
|
+
@account_page = Account.new
|
198
|
+
#...
|
199
|
+
@account_page.displayed? #=> true or false
|
200
|
+
```
|
201
|
+
|
202
|
+
Calling `#displayed?` will return true if the browser's current URL
|
203
|
+
matches the regular expression for the page and false if it doesn't. So
|
204
|
+
in the above example (`account/1` and `account/2`), calling
|
205
|
+
`@account_page.displayed?` will return true for both examples.
|
206
|
+
|
207
|
+
#### Testing for Page display
|
208
|
+
|
209
|
+
SitePrism's `#displayed?` predicate method allows for semantic code in
|
210
|
+
your test:
|
211
|
+
|
212
|
+
```ruby
|
213
|
+
Then /^the account page is displayed$/ do
|
214
|
+
@account_page.should be_displayed
|
215
|
+
@some_other_page.should_not be_displayed
|
216
|
+
end
|
217
|
+
```
|
218
|
+
|
219
|
+
Another example that demonstrates why using regex instead of string
|
220
|
+
comparison for URL checking is when you want to be able to run your
|
221
|
+
tests across multiple environments.
|
222
|
+
|
223
|
+
```ruby
|
224
|
+
class Login < SitePrism::Page
|
225
|
+
set_url "#{$test_environment}.example.com/login" #=> global var used for demonstration purposes only!!!
|
226
|
+
set_url_matcher /(?:dev|test|www)\.example\.com\/login/
|
227
|
+
end
|
228
|
+
```
|
229
|
+
|
230
|
+
The above example would work for `dev.example.com/login`,
|
231
|
+
`test.example.com/login` and `www.example.com/login`; now your tests
|
232
|
+
aren't limited to one environment but can verify that they are on the
|
233
|
+
correct page regardless of the environment the tests are being executed
|
234
|
+
against.
|
235
|
+
|
236
|
+
#### Page Title
|
237
|
+
|
238
|
+
Getting a page's title isn't hard:
|
239
|
+
|
240
|
+
```ruby
|
241
|
+
class Account < SitePrism::Page
|
242
|
+
end
|
243
|
+
|
244
|
+
@account = Account.new
|
245
|
+
#...
|
246
|
+
@account.title #=> "Welcome to Your Account"
|
247
|
+
```
|
248
|
+
|
249
|
+
## Elements
|
250
|
+
|
251
|
+
Pages are made up of elements (text fields, buttons, combo boxes, etc),
|
252
|
+
either individual elements or groups of them. Examples of individual
|
253
|
+
elements would be a search field or a company logo image; examples of
|
254
|
+
element collections would be items in any sort of list, eg: menu items,
|
255
|
+
images in a carousel, etc.
|
256
|
+
|
257
|
+
### Individual Elements
|
258
|
+
|
259
|
+
To interact with individual elements, they need to be defined as part of
|
260
|
+
the relevant page. SitePrism makes this easy:
|
261
|
+
|
262
|
+
```ruby
|
263
|
+
class Home < SitePrism::Page
|
264
|
+
element :search_field, "input[name='q']"
|
265
|
+
end
|
266
|
+
```
|
267
|
+
|
268
|
+
Here we're adding a search field to the Home page. The `element` method
|
269
|
+
takes 2 arguments: the name of the element as a symbol, and a css selector
|
270
|
+
as a string.
|
271
|
+
|
272
|
+
#### Accessing the individual element
|
273
|
+
|
274
|
+
The `element` method will add a number of methods to instances of the
|
275
|
+
particular Page class. The first method to be added is the name of the
|
276
|
+
element. So using the following example:
|
277
|
+
|
278
|
+
```ruby
|
279
|
+
class Home < SitePrism::Page
|
280
|
+
set_url "http://www.google.com"
|
281
|
+
|
282
|
+
element :search_field, "input[name='q']"
|
283
|
+
end
|
284
|
+
```
|
285
|
+
|
286
|
+
... the following shows how to get hold of the search field:
|
287
|
+
|
288
|
+
```ruby
|
289
|
+
@home_page = Home.new
|
290
|
+
@home.load
|
291
|
+
|
292
|
+
@home.search_field #=> will return the capybara element found using the selector
|
293
|
+
@home.search_field.set "the search string" #=> since search_field returns a capybara element, you can use the capybara API to deal with it
|
294
|
+
@home.search_field.text #=> standard method on a capybara element; returns a string
|
295
|
+
```
|
296
|
+
|
297
|
+
#### Testing for the existence of the element
|
298
|
+
|
299
|
+
Another method added to the Page class by the `element` method is the
|
300
|
+
`has_<element name>?` method. Using the same example as above:
|
301
|
+
|
302
|
+
```ruby
|
303
|
+
class Home < SitePrism::Page
|
304
|
+
set_url "http://www.google.com"
|
305
|
+
|
306
|
+
element :search_field, "input[name='q']"
|
307
|
+
end
|
308
|
+
```
|
309
|
+
|
310
|
+
... you can test for the existence of the element on the page like this:
|
311
|
+
|
312
|
+
```ruby
|
313
|
+
@home_page = Home.new
|
314
|
+
@home.load
|
315
|
+
@home.has_search_field? #=> returns true if it exists, false if it doesn't
|
316
|
+
```
|
317
|
+
|
318
|
+
...which makes for nice test code:
|
319
|
+
|
320
|
+
```ruby
|
321
|
+
Then /^the search field exists$/ do
|
322
|
+
@home.should have_search_field
|
323
|
+
end
|
324
|
+
```
|
325
|
+
|
326
|
+
#### Waiting for an element to appear on a page
|
327
|
+
|
328
|
+
The final method added by calling `element` is the `wait_for_<element_name>` method.
|
329
|
+
Calling the method will cause the test to wait for the Capybara's
|
330
|
+
default wait time for the element to exist. It is also possible to use a
|
331
|
+
custom amount of time to wait. Using the same example as above:
|
332
|
+
|
333
|
+
```ruby
|
334
|
+
class Home < SitePrism::Page
|
335
|
+
set_url "http://www.google.com"
|
336
|
+
|
337
|
+
element :search_field, "input[name='q']"
|
338
|
+
end
|
339
|
+
```
|
340
|
+
|
341
|
+
... you can wait for the search field to exist like this:
|
342
|
+
|
343
|
+
```ruby
|
344
|
+
@home_page = Home.new
|
345
|
+
@home.load
|
346
|
+
@home.wait_for_search_field
|
347
|
+
# or...
|
348
|
+
@home.wait_for_search_field(10) #will wait for 10 seconds for the search field to appear
|
349
|
+
```
|
350
|
+
|
351
|
+
#### Summary of what the element method provides:
|
352
|
+
|
353
|
+
Given:
|
354
|
+
|
355
|
+
```ruby
|
356
|
+
class Home < SitePrism::Page
|
357
|
+
element :search_field, "input[name='q']"
|
358
|
+
end
|
359
|
+
```
|
360
|
+
|
361
|
+
...then the following methods are available:
|
362
|
+
|
363
|
+
```ruby
|
364
|
+
@home.search_field
|
365
|
+
@home.has_search_field?
|
366
|
+
@home.wait_for_search_field
|
367
|
+
@home.wait_for_search_field(10)
|
368
|
+
```
|
369
|
+
|
370
|
+
### Element Collections
|
371
|
+
|
372
|
+
Sometimes you don't want to deal with an individual element but rather
|
373
|
+
with a collection of similar elements, for example, a list of names. To
|
374
|
+
enable this, SitePrism provides the `elements` method on the Page class.
|
375
|
+
Here's how it works:
|
376
|
+
|
377
|
+
```ruby
|
378
|
+
class Friends < SitePrism::Page
|
379
|
+
elements :names, "ul#names li a"
|
380
|
+
end
|
381
|
+
```
|
382
|
+
|
383
|
+
Just like the `element` method, the `elements` method takes 2 arguments:
|
384
|
+
the first being the name of the elements as a symbol, the second is the
|
385
|
+
css selector that would return the array of capybara elements.
|
386
|
+
|
387
|
+
#### Accessing the elements
|
388
|
+
|
389
|
+
Just like the `element` method, the `elements` method adds a few methods
|
390
|
+
to the Page class. The first one is of the name of the element
|
391
|
+
collection which returns an array of capybara elements that match the
|
392
|
+
css selector. Using the example above:
|
393
|
+
|
394
|
+
```ruby
|
395
|
+
class Friends < SitePrism::Page
|
396
|
+
elements :names, "ul#names li a"
|
397
|
+
end
|
398
|
+
```
|
399
|
+
|
400
|
+
You can access the element collection like this:
|
401
|
+
|
402
|
+
```ruby
|
403
|
+
@friends_page = Friends.new
|
404
|
+
# ...
|
405
|
+
@friends_page.names #=> [<Capybara::Element>, <Capybara::Element>, <Capybara::Element>]
|
406
|
+
```
|
407
|
+
|
408
|
+
With that you can do all the normal things that are possible with
|
409
|
+
arrays:
|
410
|
+
|
411
|
+
|
412
|
+
```ruby
|
413
|
+
@friends_page.names.each {|name| puts name.text}
|
414
|
+
@friends_page.names.map {|name| name.text}.should == ["Alice", "Bob", "Fred"]
|
415
|
+
@friends_page.names.size.should == 3
|
416
|
+
```
|
417
|
+
|
418
|
+
#### Testing for the existence of the element collection
|
419
|
+
|
420
|
+
Just like the `element` method, the `elements` method adds a method to
|
421
|
+
the page that will allow you to check for the existence of the
|
422
|
+
collection, called `has_<element collection name>?`. As long as there is
|
423
|
+
at least 1 element in the array, the method will return true, otherwise
|
424
|
+
false. For example, with the following page:
|
425
|
+
|
426
|
+
```ruby
|
427
|
+
class Friends < SitePrism::Page
|
428
|
+
elements :names, "ul#names li a"
|
429
|
+
end
|
430
|
+
```
|
431
|
+
|
432
|
+
... the following method is available:
|
433
|
+
|
434
|
+
```ruby
|
435
|
+
@friends_page.has_names? #=> returns true if at least one element is found using the relevant selector
|
436
|
+
```
|
437
|
+
|
438
|
+
...which allows for pretty test code:
|
439
|
+
|
440
|
+
```ruby
|
441
|
+
Then /^there should be some names listed on the page$/ do
|
442
|
+
@friends_page.should have_names
|
443
|
+
end
|
444
|
+
```
|
445
|
+
|
446
|
+
#### Waiting for the element collection
|
447
|
+
|
448
|
+
Just like for an individual element, the tests can be told to wait for
|
449
|
+
the existence of the element collection. The `elements` method adds a
|
450
|
+
`wait_for_<element collection name>` method that will wait for
|
451
|
+
Capybara's default wait time until at least 1 element is found that
|
452
|
+
matches the selector. For example, with the following page:
|
453
|
+
|
454
|
+
```ruby
|
455
|
+
class Friends < SitePrism::Page
|
456
|
+
elements :names, "ul#names li a"
|
457
|
+
end
|
458
|
+
|
459
|
+
```
|
460
|
+
|
461
|
+
... you can wait for the existence of a list of names like this:
|
462
|
+
|
463
|
+
```ruby
|
464
|
+
@friends_page.wait_for_names
|
465
|
+
```
|
466
|
+
|
467
|
+
Again, you can customise the wait time by supplying a number of seconds
|
468
|
+
to wait for:
|
469
|
+
|
470
|
+
```ruby
|
471
|
+
@friends_page.wait_for_names(10)
|
472
|
+
```
|
473
|
+
|
474
|
+
### Checking that all mapped elements are present on the page
|
475
|
+
|
476
|
+
Throughout my time in test automation I keep getting asked to provide the
|
477
|
+
ability to check that all elements that should be on the page are on the
|
478
|
+
page. Why people would want to test this, I don't know. But if that's
|
479
|
+
what you want to do, SitePrism provides the `#all_there?` method that
|
480
|
+
will return true if all mapped elements (and sections... see below) are
|
481
|
+
present in the browser, false if they're not all there.
|
482
|
+
|
483
|
+
```ruby
|
484
|
+
@friends_page.all_there? #=> true/false
|
485
|
+
|
486
|
+
# and...
|
487
|
+
|
488
|
+
Then /^the friends page contains all the expected elements$/ do
|
489
|
+
@friends_page.should be_all_there
|
490
|
+
end
|
491
|
+
|
492
|
+
```
|
493
|
+
|
494
|
+
## Sections
|
495
|
+
|
496
|
+
SitePrism allows you to model sections of a page that appear on multiple
|
497
|
+
pages or that appear a number of times on a page separately from Pages.
|
498
|
+
SitePrism provides the Section class for this task.
|
499
|
+
|
500
|
+
### Individual Sections
|
501
|
+
|
502
|
+
In the same way that SitePrism provides `element` and `elements`, it
|
503
|
+
provides `section` and `sections`. The first returns an instance of a
|
504
|
+
page section, the secont returns an array of section instances, one for
|
505
|
+
each capybara element found by the supplied css selector. What follows
|
506
|
+
is an explanation of `section`.
|
507
|
+
|
508
|
+
|
509
|
+
#### Defining a Section
|
510
|
+
|
511
|
+
A section is similar to a page in that it inherits from a SitePrism
|
512
|
+
class:
|
513
|
+
|
514
|
+
```ruby
|
515
|
+
class MenuSection < SitePrism::Section
|
516
|
+
end
|
517
|
+
```
|
518
|
+
|
519
|
+
At the moment, this section does nothing.
|
520
|
+
|
521
|
+
#### Adding a section to a page
|
522
|
+
|
523
|
+
Pages include sections that's how SitePrism works. Here's a page that
|
524
|
+
includes the above `MenuSection` section:
|
525
|
+
|
526
|
+
```ruby
|
527
|
+
class Home < SitePrism::Page
|
528
|
+
section :menu, MenuSection, "#gbx3"
|
529
|
+
end
|
530
|
+
```
|
531
|
+
|
532
|
+
The way to add a section to a page (or another section -
|
533
|
+
SitePrism allows adding sections to sections) is to call the `section`
|
534
|
+
method. It takes 3 arguments: the first is the name of the section as
|
535
|
+
referred to on the page (sections that appear on multiple pages can be
|
536
|
+
named differently). The second argument is the class of which an
|
537
|
+
instance will be created to represent the page section, and the third
|
538
|
+
argument is a css selector that identifies the root node of the section
|
539
|
+
on this page (note that the css selector can be different for different
|
540
|
+
pages as the whole point of sections is that they can appear in
|
541
|
+
different places on different pages).
|
542
|
+
|
543
|
+
#### Accessing a page's section
|
544
|
+
|
545
|
+
The `section` method (like the `element` method) adds a few methods to
|
546
|
+
the page or section class it was called against. The first method that
|
547
|
+
is added is one that returns an instance of the section, the method name
|
548
|
+
being the first argument to the `section` method. Here's an example:
|
549
|
+
|
550
|
+
```ruby
|
551
|
+
# the section:
|
552
|
+
|
553
|
+
class MenuSection < SitePrism::Section
|
554
|
+
end
|
555
|
+
|
556
|
+
# the page that includes the section:
|
557
|
+
|
558
|
+
class Home < SitePrism::Page
|
559
|
+
section :menu, MenuSection, "#gbx3"
|
560
|
+
end
|
561
|
+
|
562
|
+
# the page and section in action:
|
563
|
+
|
564
|
+
@home = Home.new
|
565
|
+
@home.menu #=> <MenuSection...>
|
566
|
+
```
|
567
|
+
|
568
|
+
When the `menu` method is called against `@home`, an instance of
|
569
|
+
`MenuSection` (the second argument to the `section` method) is returned.
|
570
|
+
The third argument that is passed to the `section` method is the css
|
571
|
+
selector that will be used to find the root element of the section; this
|
572
|
+
root node becomes the 'scope' of the section.
|
573
|
+
|
574
|
+
The following shows that though the same section can appear on multiple
|
575
|
+
pages, it can take a different root node:
|
576
|
+
|
577
|
+
```ruby
|
578
|
+
# define the section that appears on both pages
|
579
|
+
|
580
|
+
class MenuSection < SitePrism::Section
|
581
|
+
end
|
582
|
+
|
583
|
+
# define 2 pages, each containing the same section
|
584
|
+
|
585
|
+
class Home < SitePrism::Page
|
586
|
+
section :menu, MenuSection, "#gbx3"
|
587
|
+
end
|
588
|
+
|
589
|
+
class SearchResults < SitePrism::Page
|
590
|
+
section :menu, MenuSection, "#gbx48"
|
591
|
+
end
|
592
|
+
```
|
593
|
+
|
594
|
+
You can see that the `MenuSection` is used in both the `Home` and
|
595
|
+
`SearchResults` pages, but each has slightly different root node. The
|
596
|
+
capybara element that is found by the css selector becomes the root node
|
597
|
+
for the relevant page's instance of the `MenuSection` section.
|
598
|
+
|
599
|
+
#### Adding elements to a section
|
600
|
+
|
601
|
+
This works just the same as adding elements to a page:
|
602
|
+
|
603
|
+
```ruby
|
604
|
+
class MenuSection < SitePrism::Section
|
605
|
+
element :search, "a.search"
|
606
|
+
element :images, "a.image-search"
|
607
|
+
element :maps, "a.map-search"
|
608
|
+
end
|
609
|
+
```
|
610
|
+
|
611
|
+
Note that the css selectors used to find elements are searched for
|
612
|
+
within the scope of the root element of that section. The search for the
|
613
|
+
element won't be page-wide but it will only look in the section.
|
614
|
+
|
615
|
+
When the section is added to a page...
|
616
|
+
|
617
|
+
```ruby
|
618
|
+
class Home < SitePrism::Page
|
619
|
+
section :menu, MenuSection, "#gbx3"
|
620
|
+
end
|
621
|
+
```
|
622
|
+
|
623
|
+
...then the section's elements can be accessed like this:
|
624
|
+
|
625
|
+
```ruby
|
626
|
+
@home = Home.new
|
627
|
+
@home.load
|
628
|
+
|
629
|
+
@home.menu.search #=> returns a capybara element representing the link to the search page
|
630
|
+
@home.menu.search.click #=> clicks the search link in the home page menu
|
631
|
+
@home.menu.search['href'] #=> returns the value for the href attribute of the capybara element representing the search link
|
632
|
+
@home.menu.has_images? #=> returns true or false based on whether the link is present in the section on the page
|
633
|
+
@home.menu.wait_for_images #=> waits for capybara's default wait time until the element appears in the page section
|
634
|
+
|
635
|
+
```
|
636
|
+
|
637
|
+
...which leads to some pretty test code:
|
638
|
+
|
639
|
+
```ruby
|
640
|
+
Then /^the home page menu contains a link to the various search functions$/ do
|
641
|
+
@home.menu.should have_search
|
642
|
+
@home.menu.search['href'].should include "google.com"
|
643
|
+
@home.menu.should have_images
|
644
|
+
@home.menu.should have_maps
|
645
|
+
end
|
646
|
+
```
|
647
|
+
|
648
|
+
#### Testing for the existence of a section
|
649
|
+
|
650
|
+
Just like elements, it is possible to test for the existence of a
|
651
|
+
section. The `section` method adds a method called `has_<section name>?`
|
652
|
+
to the page or section it's been added to - same idea as what the
|
653
|
+
`has_<element name>?` method. Given the following setup:
|
654
|
+
|
655
|
+
```ruby
|
656
|
+
class MenuSection < SitePrism::Section
|
657
|
+
element :search, "a.search"
|
658
|
+
element :images, "a.image-search"
|
659
|
+
element :maps, "a.map-search"
|
660
|
+
end
|
661
|
+
|
662
|
+
class Home < SitePrism::Page
|
663
|
+
section :menu, MenuSection, "#gbx3"
|
664
|
+
end
|
665
|
+
```
|
666
|
+
|
667
|
+
... you can check whether the section is present on the page or not:
|
668
|
+
|
669
|
+
```ruby
|
670
|
+
@home = Home.new
|
671
|
+
#...
|
672
|
+
#home.has_menu? #=> returns true or false
|
673
|
+
```
|
674
|
+
|
675
|
+
Again, this allows pretty test code:
|
676
|
+
|
677
|
+
```ruby
|
678
|
+
@home.should have_menu
|
679
|
+
@home.should_not have_menu
|
680
|
+
```
|
681
|
+
|
682
|
+
#### Waiting for a section to appear
|
683
|
+
|
684
|
+
The final method added to the page or section by the `section` method is
|
685
|
+
`wait_for_<section name>`. Similar to what `element` does, this method
|
686
|
+
waits for the section to appear - the test will wait up to capybara's
|
687
|
+
default wait time until the root node of the element exists on the
|
688
|
+
page/section that our section was added to. Given the following setup:
|
689
|
+
|
690
|
+
```ruby
|
691
|
+
class MenuSection < SitePrism::Section
|
692
|
+
element :search, "a.search"
|
693
|
+
element :images, "a.image-search"
|
694
|
+
element :maps, "a.map-search"
|
695
|
+
end
|
696
|
+
|
697
|
+
class Home < SitePrism::Page
|
698
|
+
section :menu, MenuSection, "#gbx3"
|
699
|
+
end
|
700
|
+
```
|
701
|
+
|
702
|
+
... we can wait for the menu section to appear on the page like this:
|
703
|
+
|
704
|
+
```ruby
|
705
|
+
@home.wait_for_menu
|
706
|
+
@home.wait_for_menu(10) # waits for 10 seconds instead of capybara's default timeout
|
707
|
+
```
|
708
|
+
|
709
|
+
#### Sections within sections
|
710
|
+
|
711
|
+
You are not limited to adding sections only to pages; you can nest
|
712
|
+
sections within sections within sections within sections!
|
713
|
+
|
714
|
+
```ruby
|
715
|
+
|
716
|
+
# define a page that contains an area that contains a section for both logging in and registration, then modelling each of the sub sections seperately
|
717
|
+
|
718
|
+
class Login < SitePrism::Section
|
719
|
+
element :username, "#username"
|
720
|
+
element :password, "#password"
|
721
|
+
element :sign_in, "button"
|
722
|
+
end
|
723
|
+
|
724
|
+
class Registration < SitePrism::Section
|
725
|
+
element :first_name, "#first_name"
|
726
|
+
element :last_name, "#last_name"
|
727
|
+
element :next_step, "button.next-reg-step"
|
728
|
+
end
|
729
|
+
|
730
|
+
class LoginRegistrationForm < SitePrism::Section
|
731
|
+
section :login, Login, "div.login-area"
|
732
|
+
section :registration, Registration, "div.reg-area"
|
733
|
+
end
|
734
|
+
|
735
|
+
class Home < SitePrism::Page
|
736
|
+
section :login_and_registration, LoginRegistrationForm, "div.login-registration"
|
737
|
+
end
|
738
|
+
|
739
|
+
# how to login (fatuous, but demonstrates the point):
|
740
|
+
|
741
|
+
Then /^I sign in$/ do
|
742
|
+
@home = Home.new
|
743
|
+
@home.load
|
744
|
+
@home.wait_for_login_and_registration
|
745
|
+
@home.should have_login_and_registration
|
746
|
+
@home.login_and_registration.should have_username
|
747
|
+
@home.login_and_registration.login.username.set "bob"
|
748
|
+
@home.login_and_registration.login.password.set "p4ssw0rd"
|
749
|
+
@home.login_and_registration.login.sign_in.click
|
750
|
+
end
|
751
|
+
|
752
|
+
# how to sign up:
|
753
|
+
|
754
|
+
When /^I enter my name into the home page's registration form$/ do
|
755
|
+
@home = Home.new
|
756
|
+
@home.load
|
757
|
+
@home.login_and_registration.should have_first_name
|
758
|
+
@home.login_and_registration.should have_last_name
|
759
|
+
@home.login_and_registration.first_name.set "Bob"
|
760
|
+
# ...
|
761
|
+
end
|
762
|
+
```
|
763
|
+
|
764
|
+
### Section Collections
|
765
|
+
|
766
|
+
An individual section represents a discrete section of a page, but often
|
767
|
+
sections are repeated on a page, an example is a search result listing -
|
768
|
+
each listing contains a title, a url and a description of the content.
|
769
|
+
It makes sense to model this only once and then to be able to access
|
770
|
+
each instance of a search result on a page as an array of SitePrism
|
771
|
+
sections. To achieve this, SitePrism provides the `sections` method that
|
772
|
+
can be called in a page or a section.
|
773
|
+
|
774
|
+
The only difference between `section` and `sections` is that whereas the
|
775
|
+
first returns an instance of the supplied section class, the second
|
776
|
+
returns an array containing as many instances of the section class as
|
777
|
+
there are capybara elements found by the supplied css selector. This is
|
778
|
+
better explained in code :)
|
779
|
+
|
780
|
+
#### Adding a Section collection to a page (or other section)
|
781
|
+
|
782
|
+
Given the following setup:
|
783
|
+
|
784
|
+
```ruby
|
785
|
+
class SearchResultSection < SitePrism::Section
|
786
|
+
element :title, "a.title"
|
787
|
+
element :blurb, "span.result-decription"
|
788
|
+
end
|
789
|
+
|
790
|
+
class SearchResults < SitePrism::Page
|
791
|
+
sections :search_results, SearchResultSection, "#results li"
|
792
|
+
end
|
793
|
+
```
|
794
|
+
|
795
|
+
... it is possible to access each of the search results:
|
796
|
+
|
797
|
+
```ruby
|
798
|
+
@results_page = SearchResults.new
|
799
|
+
# ...
|
800
|
+
@results_page.search_results.each do |search_result|
|
801
|
+
puts search_result.title.text
|
802
|
+
end
|
803
|
+
```
|
804
|
+
|
805
|
+
... which allows for pretty tests:
|
806
|
+
|
807
|
+
```ruby
|
808
|
+
Then /^there are lots of search_results$/ do
|
809
|
+
@results_page.search_results.size.should == 10
|
810
|
+
@results_page.search_results.each do |search_result|
|
811
|
+
search_result.should have_title
|
812
|
+
search_result.blurb.text.should_not be_nil
|
813
|
+
end
|
814
|
+
end
|
815
|
+
```
|
816
|
+
|
817
|
+
The css selector that is passed as the 3rd argument to the
|
818
|
+
`sections` method ("#results li") is used to find a number of capybara
|
819
|
+
elements. Each capybara element found using the css selector is used to
|
820
|
+
create a new instance of the `SearchResultSection` and becomes its root
|
821
|
+
element. So if the css selector finds 3 `li` elements, calling
|
822
|
+
`search_results` will return an array containing 3 instances of
|
823
|
+
`SearchResultSection`, each with one of the `li` elements as it's root
|
824
|
+
element.
|
825
|
+
|
826
|
+
#### Testing for existence of Sections
|
827
|
+
|
828
|
+
Using the example above, it is possible to test for the existence of the
|
829
|
+
sections. As long as there is at least one section in the array, the
|
830
|
+
sections exist. The `sections` method adds a `has_<sections name>?`
|
831
|
+
method to the page/section that our section has been added to. Given the
|
832
|
+
following example:
|
833
|
+
|
834
|
+
```ruby
|
835
|
+
class SearchResultSection < SitePrism::Section
|
836
|
+
element :title, "a.title"
|
837
|
+
element :blurb, "span.result-decription"
|
838
|
+
end
|
839
|
+
|
840
|
+
class SearchResults < SitePrism::Page
|
841
|
+
sections :search_results, SearchResultSection, "#results li"
|
842
|
+
end
|
843
|
+
```
|
844
|
+
|
845
|
+
... here's how to test for the existence of the section:
|
846
|
+
|
847
|
+
```ruby
|
848
|
+
@results_page = SearchResults.new
|
849
|
+
# ...
|
850
|
+
@results_page.has_search_results?
|
851
|
+
```
|
852
|
+
|
853
|
+
...which allows pretty tests:
|
854
|
+
|
855
|
+
```ruby
|
856
|
+
Then /^there are search results on the page$/ do
|
857
|
+
@results.page.should have_search_results
|
858
|
+
end
|
859
|
+
```
|
860
|
+
|
861
|
+
#### Waiting for sections to appear
|
862
|
+
|
863
|
+
The final method added by `sections` to the page/section we're adding
|
864
|
+
our sections to is `wait_for_<sections name>`. It will wait for
|
865
|
+
capybara's default wait time for there to be at least one instance of
|
866
|
+
the section in the array of sections. For example:
|
867
|
+
|
868
|
+
```ruby
|
869
|
+
class SearchResultSection < SitePrism::Section
|
870
|
+
element :title, "a.title"
|
871
|
+
element :blurb, "span.result-decription"
|
872
|
+
end
|
873
|
+
|
874
|
+
class SearchResults < SitePrism::Page
|
875
|
+
sections :search_results, SearchResultSection, "#results li"
|
876
|
+
end
|
877
|
+
```
|
878
|
+
|
879
|
+
... here's how to wait for the section:
|
880
|
+
|
881
|
+
```ruby
|
882
|
+
@results_page = SearchResults.new
|
883
|
+
# ...
|
884
|
+
@results_page.wait_for_search_results
|
885
|
+
@results_page.wait_for_search_results(10) #=> waits for 10 seconds instead of the default capybara timeout
|
886
|
+
```
|
887
|
+
|
888
|
+
|
889
|
+
# Epilogue
|
890
|
+
|
891
|
+
So, we've seen how to use SitePrism to put together page objects made up
|
892
|
+
of pages, elements and sections. But how to organise this stuff? There
|
893
|
+
are a few ways of saving yourself having to create instances of pages
|
894
|
+
all over the place. Here's an example of this common problem:
|
895
|
+
|
896
|
+
```ruby
|
897
|
+
@home = Home.new
|
898
|
+
@home.load
|
899
|
+
@home.search_field.set "Sausages"
|
900
|
+
@home.search_field.search_button.click
|
901
|
+
@results_page = SearchResults.new
|
902
|
+
@results_page.should have_search_result_items
|
903
|
+
```
|
904
|
+
|
905
|
+
The annoyance (and, later, maintenance nightmare) is having to create
|
906
|
+
`@home` and `@results_page`. It would be better to not have to create
|
907
|
+
instances of pages all over your tests.
|
908
|
+
|
909
|
+
The way I've dealt with this problem is to create a class containing
|
910
|
+
methods that return instances of the pages. Eg:
|
911
|
+
|
912
|
+
```ruby
|
913
|
+
# our pages
|
914
|
+
|
915
|
+
class Home < SitePrism::Page
|
916
|
+
#...
|
917
|
+
end
|
918
|
+
|
919
|
+
class SearchResults < SitePrism::Page
|
920
|
+
#...
|
921
|
+
end
|
922
|
+
|
923
|
+
class Maps < SitePrism::Page
|
924
|
+
#...
|
925
|
+
end
|
926
|
+
|
927
|
+
# here's the app class that represents our entire site:
|
928
|
+
|
929
|
+
class App
|
930
|
+
def home
|
931
|
+
Home.new
|
932
|
+
end
|
933
|
+
|
934
|
+
def results_page
|
935
|
+
SearchResults.new
|
936
|
+
end
|
937
|
+
|
938
|
+
def maps
|
939
|
+
Maps.new
|
940
|
+
end
|
941
|
+
end
|
942
|
+
|
943
|
+
# and here's how to use it:
|
944
|
+
|
945
|
+
#first line of the test...
|
946
|
+
Given /^I start on the home page$/ do
|
947
|
+
@app = App.new
|
948
|
+
@app.home.load
|
949
|
+
end
|
950
|
+
|
951
|
+
When /^I search for Sausages$/ do
|
952
|
+
@app.home.search_field.set "sausages"
|
953
|
+
@app.home.search_button.click
|
954
|
+
end
|
955
|
+
|
956
|
+
# etc...
|
957
|
+
```
|
958
|
+
|
959
|
+
The only thing that needs instantiating is the App class - from then on
|
960
|
+
pages don't need to be initialized, they are now returned by methods on
|
961
|
+
@app. Maintenance win!
|
962
|
+
|
@@ -1,26 +1,5 @@
|
|
1
|
-
# Contains methods applicable to both {SitePrism::Page}s and {SitePrism::Section}s. Note that they are mixed into the {SitePrism::Page}
|
2
|
-
# and {SitePrism::Section} classes so the methods below are used as class methods.
|
3
1
|
module SitePrism::ElementContainer
|
4
2
|
|
5
|
-
# Creates two methods; the first method has the same name as the element_name parameter and returns the capybara element
|
6
|
-
# located by the element_locator parameter when the method is called. The second method generated has a name with a format
|
7
|
-
# of: 'has_#\{element_name}?' which returns true if the element as located by the element_locator parameter exists, false
|
8
|
-
# if it doesn't
|
9
|
-
# @param [Symbol] element_name The name of the element
|
10
|
-
# @param [String] element_locator The CSS locator to find the element
|
11
|
-
# @example
|
12
|
-
# class HomePage < SitePrism::Page
|
13
|
-
# element :search_link, 'div.search > a'
|
14
|
-
# end
|
15
|
-
# home = HomePage.new
|
16
|
-
#
|
17
|
-
# #the element method created 2 methods...
|
18
|
-
# home.search_link #=> returns the capybara element located by the element_locator parameter
|
19
|
-
# home.has_search_link? #=> returns true if the capybara element as located by the element_locator exists, false if it doesn't
|
20
|
-
#
|
21
|
-
# #The has_search_link? method allows use of magic matchers in rspec/cucumber:
|
22
|
-
# home.should have_search_link
|
23
|
-
# home.should_not have_search_link
|
24
3
|
def element element_name, element_locator = nil
|
25
4
|
if element_locator.nil?
|
26
5
|
define_method element_name.to_s do
|
@@ -36,20 +15,6 @@ module SitePrism::ElementContainer
|
|
36
15
|
create_waiter element_name, element_locator
|
37
16
|
end
|
38
17
|
|
39
|
-
# Works in the same way as {SitePrism::Page.element} in that it will generate two methods; one to check existence of
|
40
|
-
# the element (in the format 'has_#\{element_name}?'), and another to return not a single element, but an array of elements
|
41
|
-
# found by the css locator
|
42
|
-
# @param [Symbol] collection_name The name of the collection
|
43
|
-
# @param [String] collection_locator The CSS locator that returns the list of elements in the collection
|
44
|
-
# @example
|
45
|
-
# class HomePage < SitePrism::Page
|
46
|
-
# elements :app_links, '.title-links > a'
|
47
|
-
# end
|
48
|
-
# home = HomePage.new
|
49
|
-
#
|
50
|
-
# home.should have_app_links
|
51
|
-
# home.app_links #=> [#<Capybara::Element tag="a">, #<Capybara::Element tag="a">, #<Capybara::Element tag="a">]
|
52
|
-
# home.app_links.map {|link| link.text}.should == ['Finance', 'Maps', 'Blogs']
|
53
18
|
def elements collection_name, collection_locator = nil
|
54
19
|
if collection_locator.nil?
|
55
20
|
define_method collection_name.to_s do
|
@@ -66,31 +31,6 @@ module SitePrism::ElementContainer
|
|
66
31
|
end
|
67
32
|
alias :collection :elements
|
68
33
|
|
69
|
-
# Creates a method that returns an instance of a {SitePrism::Section}. If a page contains a common section (eg: a search area) that
|
70
|
-
# appears on many pages, create a {SitePrism::Section} for it and then expose it in each {SitePrism::Page} that contains the section.
|
71
|
-
# Say a search engine website displays the search field and search button on each page and they always have the same IDs, they should
|
72
|
-
# be extracted into a {SitePrism::Section} that would look something like this:
|
73
|
-
#
|
74
|
-
# class SearchArea < SitePrism::Section
|
75
|
-
# element :search_field, '.q'
|
76
|
-
# element :search_button, '.btnK'
|
77
|
-
# end
|
78
|
-
#
|
79
|
-
# ...then that section could be added to any page as follows:
|
80
|
-
#
|
81
|
-
# class SearchPage < SitePrism::Page
|
82
|
-
# section :search_area, SearchArea, '.tsf-p'
|
83
|
-
# end
|
84
|
-
#
|
85
|
-
# class SearchResultsPage < SitePrism::Page
|
86
|
-
# section :search_again, SearchArea, '.tsf-p table'
|
87
|
-
# end
|
88
|
-
#
|
89
|
-
# The SearchArea section appears on both pages, but can be invoked by methods specific to the page (eg: 'search_area' and 'search_again')
|
90
|
-
# and the root element for the section can be different on the page (eg: '.tsf-p' and '.tsf-p table').
|
91
|
-
# @param [Symbol] the method name to be called against this page or section to return an instance of the {SitePrism::Section} class
|
92
|
-
# @param [Class] the class that models this area of the page
|
93
|
-
# @param [String] the CSS locator for the root element of the section on this page/section
|
94
34
|
def section section_name, section_class, section_locator
|
95
35
|
add_element_name section_name
|
96
36
|
create_existence_checker section_name, section_locator
|
@@ -100,7 +40,6 @@ module SitePrism::ElementContainer
|
|
100
40
|
end
|
101
41
|
end
|
102
42
|
|
103
|
-
# Works in the same way as {SitePrism::Page.section} but instead of it returning one section, it returns an array of them.
|
104
43
|
def sections section_collection_name, section_class, section_collection_locator
|
105
44
|
add_element_name section_collection_name
|
106
45
|
create_existence_checker section_collection_name, section_collection_locator
|
@@ -112,21 +51,17 @@ module SitePrism::ElementContainer
|
|
112
51
|
end
|
113
52
|
end
|
114
53
|
|
115
|
-
# Adds the element name to the list of known elements
|
116
54
|
def add_element_name element_name
|
117
55
|
@element_names ||= []
|
118
56
|
@element_names << element_name
|
119
57
|
end
|
120
58
|
|
121
|
-
# Returns list of known element names
|
122
59
|
def element_names
|
123
60
|
@element_names
|
124
61
|
end
|
125
62
|
|
126
63
|
private
|
127
64
|
|
128
|
-
# Creates a method used to check for the existence of the element whose details are passed to it
|
129
|
-
# @param
|
130
65
|
def create_existence_checker element_name, element_locator
|
131
66
|
method_name = "has_#{element_name.to_s}?"
|
132
67
|
if element_locator.nil?
|
@@ -142,7 +77,6 @@ module SitePrism::ElementContainer
|
|
142
77
|
end
|
143
78
|
end
|
144
79
|
|
145
|
-
# Creates a method used to wait for an element to appear - uses the default capybara wait time
|
146
80
|
def create_waiter element_name, element_locator
|
147
81
|
method_name = "wait_for_#{element_name.to_s}"
|
148
82
|
if element_locator.nil?
|
@@ -1,10 +1,6 @@
|
|
1
|
-
# SitePrism's exceptions...
|
2
1
|
module SitePrism
|
3
|
-
# Raised if you ask a page to load but it hasn't had its url set
|
4
2
|
class NoUrlForPage < StandardError; end
|
5
|
-
# Raised if you check to see if a page is displayed but it hasn't had its url matcher set
|
6
3
|
class NoUrlMatcherForPage < StandardError; end
|
7
|
-
# Raised if you ask for an element that hasn't got a locator (i.e. a pending element)
|
8
4
|
class NoLocatorForElement < StandardError; end
|
9
5
|
end
|
10
6
|
|
data/lib/site_prism/page.rb
CHANGED
@@ -1,90 +1,43 @@
|
|
1
1
|
module SitePrism
|
2
|
-
# Subclasses of {SitePrism::Page} represent pages in your app.
|
3
|
-
# class Home < SitePrism::Page
|
4
|
-
# end
|
5
|
-
#
|
6
|
-
# The above is an example of how to make a class representing the home page. There are a number of properties that can be
|
7
|
-
# set on a page - here is an example of a more fully spec'ed out page:
|
8
|
-
# class Home < SitePrism::Page
|
9
|
-
# set_url "/"
|
10
|
-
# set_url_matcher /\/home.htm$/
|
11
|
-
# end
|
12
2
|
class Page
|
13
3
|
include Capybara::DSL
|
14
4
|
include ElementChecker
|
15
5
|
extend ElementContainer
|
16
6
|
|
17
|
-
# Visits the url associated with this page
|
18
|
-
# @raise [SitePrism::NoUrlForPage] To load a page the url must be set using {.set_url}
|
19
7
|
def load
|
20
8
|
raise SitePrism::NoUrlForPage if url.nil?
|
21
9
|
visit url
|
22
10
|
end
|
23
11
|
|
24
|
-
# Checks to see if we're on this page or not
|
25
|
-
# @return true if the browser's current url matches the {.url_matcher} that has been set, false if it doesn't
|
26
|
-
# @raise [SitePrism::NoUrlMatcherForPage] To check whether we're on this page or not the url matcher must be set using {.set_url_matcher}
|
27
|
-
# @example
|
28
|
-
# class SearchPage < SitePrism::Page
|
29
|
-
# set_url_matcher /\/search.htm$/
|
30
|
-
# end
|
31
|
-
# search_page = SearchPage.new
|
32
|
-
# search_page.load
|
33
|
-
# puts "We're on the search page" if search_page.displayed?
|
34
|
-
# search_page.should be_displayed
|
35
12
|
def displayed?
|
36
13
|
raise SitePrism::NoUrlMatcherForPage if url_matcher.nil?
|
37
14
|
!(page.current_url =~ url_matcher).nil?
|
38
15
|
end
|
39
16
|
|
40
|
-
# Set the url associated with this page
|
41
|
-
# @param [String] page_url the portion of the url that identifies this page when appended onto Capybara's app_host. Calling {SitePrism::Page#load} causes Capybara to visit this page.
|
42
|
-
# @example
|
43
|
-
# class SearchPage < SitePrism::Page
|
44
|
-
# set_url "/search.htm"
|
45
|
-
# end
|
46
17
|
def self.set_url page_url
|
47
18
|
@url = page_url
|
48
19
|
end
|
49
20
|
|
50
|
-
# Set the url matcher associated with this page
|
51
|
-
# @param [Regexp] page_url_matcher a regular expression that when compared to the current browser url will match if we're on this page or not match if we're not on this page
|
52
|
-
# @example
|
53
|
-
# class SearchPage < SitePrism::Page
|
54
|
-
# set_url_matcher /\/search.htm$/
|
55
|
-
# end
|
56
21
|
def self.set_url_matcher page_url_matcher
|
57
22
|
@url_matcher = page_url_matcher
|
58
23
|
end
|
59
24
|
|
60
|
-
# Get the url associated with this page
|
61
|
-
# @see SitePrism::Page#url
|
62
|
-
# @return [String] the url originally set in {.set_url}
|
63
25
|
def self.url
|
64
26
|
@url
|
65
27
|
end
|
66
28
|
|
67
|
-
# Get the url matcher associated with this page
|
68
|
-
# @see SitePrism::Page#url_matcher
|
69
|
-
# @return [Regexp] the url matcher originally set in {.set_url_matcher}
|
70
29
|
def self.url_matcher
|
71
30
|
@url_matcher
|
72
31
|
end
|
73
32
|
|
74
|
-
# Get the url associated with this page
|
75
|
-
# @see SitePrism::Page.url
|
76
33
|
def url
|
77
34
|
self.class.url
|
78
35
|
end
|
79
36
|
|
80
|
-
# Get the url matcher associated with this page
|
81
|
-
# @see SitePrism::Page.url_matcher
|
82
37
|
def url_matcher
|
83
38
|
self.class.url_matcher
|
84
39
|
end
|
85
40
|
|
86
|
-
# Gets the title of the current page
|
87
|
-
# @return [String, nil] the text value of the title element within the page's head block
|
88
41
|
def title
|
89
42
|
title_selector = 'html > head > title'
|
90
43
|
using_wait_time(0) { page.find(title_selector).text if page.has_selector?(title_selector) }
|
@@ -92,22 +45,18 @@ module SitePrism
|
|
92
45
|
|
93
46
|
private
|
94
47
|
|
95
|
-
# Page specific element finder
|
96
48
|
def find_one locator
|
97
49
|
find locator
|
98
50
|
end
|
99
51
|
|
100
|
-
# Page specific elements finder
|
101
52
|
def find_all locator
|
102
53
|
all locator
|
103
54
|
end
|
104
55
|
|
105
|
-
# Page specific element existence check
|
106
56
|
def element_exists? locator
|
107
57
|
has_selector? locator
|
108
58
|
end
|
109
59
|
|
110
|
-
# Page specific element waiter
|
111
60
|
def element_waiter locator
|
112
61
|
wait_until { element_exists? locator }
|
113
62
|
end
|
data/lib/site_prism/section.rb
CHANGED
@@ -23,22 +23,18 @@ module SitePrism
|
|
23
23
|
|
24
24
|
private
|
25
25
|
|
26
|
-
# Section specific element finder
|
27
26
|
def find_one locator
|
28
27
|
@root_element.find locator
|
29
28
|
end
|
30
29
|
|
31
|
-
# Section specific elements finder
|
32
30
|
def find_all locator
|
33
31
|
@root_element.all locator
|
34
32
|
end
|
35
33
|
|
36
|
-
# Section specific element existence check
|
37
34
|
def element_exists? locator
|
38
35
|
@root_element.has_selector? locator
|
39
36
|
end
|
40
37
|
|
41
|
-
# Section specific element waiter
|
42
38
|
def element_waiter locator
|
43
39
|
Capybara.current_session.wait_until { element_exists? locator }
|
44
40
|
end
|
data/lib/site_prism/version.rb
CHANGED
metadata
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
name: site_prism
|
3
3
|
version: !ruby/object:Gem::Version
|
4
4
|
prerelease:
|
5
|
-
version: 0
|
5
|
+
version: "1.0"
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
8
|
- Nat Ritmeyer
|
@@ -10,7 +10,7 @@ autorequire:
|
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
12
|
|
13
|
-
date: 2012-
|
13
|
+
date: 2012-04-19 00:00:00 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: capybara
|
@@ -52,6 +52,7 @@ files:
|
|
52
52
|
- lib/site_prism/version.rb
|
53
53
|
- lib/site_prism.rb
|
54
54
|
- LICENSE
|
55
|
+
- README.md
|
55
56
|
homepage: http://github.com/natritmeyer/site_prism
|
56
57
|
licenses: []
|
57
58
|
|