site_prism 4.0.beta → 4.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4ebb39462fdc078aff996d358cfadeb4feddbb443cb0655340efa51f4d4af80d
4
- data.tar.gz: 2913da09df5462bcf924d3598d8d9f6f4e996c65951acb31694d0dea67990b4d
3
+ metadata.gz: de1db2cfa8b40510768bbea0bee96e548ae949149428d669e1a038c83e2b7f8d
4
+ data.tar.gz: 3862848b777a9fbafb8c1640df914313b6deac6da942a3859ff2dfe6dbafb214
5
5
  SHA512:
6
- metadata.gz: '080072c82a3df37666dd079600cd75db84be14b2f73e2f06227bdf48e45f8ff2783a64d122c05e12c8eda54462491a6c0f3d3e935b48fad54278dcf4eab0d841'
7
- data.tar.gz: 79157445566537187b9578113b3a3100aa13dbf4cbb615f9e8563dc6d1264177eaab62d9caa2fa79f152118aa1c919a5607477492fa33b1d2b23c6f2bf162b49
6
+ metadata.gz: 8deff2edc00b2b4c0fab86c96e10bc184ed2afc8276b7daf9f69b97a9f7ab4b105ece138f6901456d76e57d508f546971f0262e6cec90787e64ea89bac904047
7
+ data.tar.gz: 505eb15872469490ab314497737e04eda896f14e7b98c631efae658d42eedb09d8a8aefa53fd5d845fa0a11936951aaf5cd9e6bc99563b4f454251eb212126d9
data/README.md CHANGED
@@ -7,7 +7,7 @@ _A Page Object Model DSL for Capybara_
7
7
  SitePrism gives you a simple, clean and semantic DSL for describing your site using the Page Object Model pattern,
8
8
  for use with Capybara in automated acceptance testing.
9
9
 
10
- Find the pretty documentation here: https://rdoc.info/gems/site_prism/frames
10
+ Find the pretty documentation here: https://www.rubydoc.info/github/site-prism/site_prism
11
11
 
12
12
  Make sure to add your project/company to https://github.com/site-prism/site_prism/wiki/Who-is-using-SitePrism
13
13
 
@@ -81,34 +81,34 @@ end
81
81
 
82
82
  # now for some tests
83
83
 
84
- When(/^I navigate to the google home page$/) do
84
+ When('I navigate to the google home page') do
85
85
  @home = Home.new
86
86
  @home.load
87
87
  end
88
88
 
89
- Then(/^the home page should contain the menu and the search form$/) do
90
- @home.wait_until_menu_visible # menu loads after a second or 2, give it time to arrive
89
+ Then('the home page should contain the menu and the search form') do
90
+ @home.wait_until_menu_visible(wait: 5)
91
91
  expect(@home).to have_menu
92
92
  expect(@home).to have_search_field
93
93
  expect(@home).to have_search_button
94
94
  end
95
95
 
96
- When(/^I search for Sausages$/) do
97
- @home.search_field.set 'Sausages'
96
+ When('I search for Sausages') do
97
+ @home.search_field.send_keys('Sausages')
98
98
  @home.search_button.click
99
99
  end
100
100
 
101
- Then(/^the search results page is displayed$/) do
101
+ Then('the search results page is displayed') do
102
102
  @results_page = SearchResults.new
103
103
  expect(@results_page).to be_displayed
104
104
  end
105
105
 
106
- Then(/^the search results page contains 10 individual search results$/) do
107
- @results_page.wait_until_search_results_visible
106
+ Then('the search results page contains 10 individual search results') do
107
+ @results_page.wait_until_search_results_visible(wait: 5)
108
108
  expect(@results_page).to have_search_results(count: 10)
109
109
  end
110
110
 
111
- Then(/^the search results contain a link to the wikipedia sausages page$/) do
111
+ Then('the search results contain a link to the wikipedia sausages page') do
112
112
  expect(@results_page.search_result_links).to include('http://en.wikipedia.org/wiki/Sausage')
113
113
  end
114
114
  ```
@@ -134,7 +134,6 @@ require 'capybara'
134
134
  require 'capybara/cucumber'
135
135
  require 'selenium-webdriver'
136
136
  require 'site_prism'
137
- require 'site_prism/all_there' # Optional but needed to perform more complex matching
138
137
  ```
139
138
 
140
139
  The driver creation is identical to how you would normally create a Capybara driver,
@@ -143,7 +142,7 @@ a sample Selenium one could look something like this...
143
142
  ```ruby
144
143
  Capybara.register_driver :site_prism do |app|
145
144
  browser = ENV.fetch('browser', 'firefox').to_sym
146
- Capybara::Selenium::Driver.new(app, browser: browser, desired_capabilities: capabilities)
145
+ Capybara::Selenium::Driver.new(app, browser: browser, options: options)
147
146
  end
148
147
 
149
148
  # Then tell Capybara to use the Driver you've just defined as its default driver
@@ -161,7 +160,6 @@ require 'capybara'
161
160
  require 'capybara/rspec'
162
161
  require 'selenium-webdriver'
163
162
  require 'site_prism'
164
- require 'site_prism/all_there' # Optional but needed to perform more complex matching
165
163
  ```
166
164
 
167
165
  And again, as above, a sample driver is no different to a normal driver instantiation in Capybara.
@@ -175,7 +173,7 @@ to then use instances of those classes in your tests.
175
173
 
176
174
  If a class represents a page then each element of the page is
177
175
  represented by a method that, when called, returns a reference to that
178
- element that can then be acted upon (clicked, set text value), or
176
+ element that can then be acted upon (clicked, type in some text), or
179
177
  queried (is it enabled? / visible?).
180
178
 
181
179
  SitePrism is based around this concept, but goes further as you'll see
@@ -218,7 +216,7 @@ class Home < SitePrism::Page
218
216
  end
219
217
  ```
220
218
 
221
- Note that setting a URL is optional - you only need to set a url if you want to be able to
219
+ Note that setting a URL is **optional** - you only need to set a url if you want to be able to
222
220
  navigate directly to that page. It makes sense to set the URL for a page model of a
223
221
  home page or a login page, but probably not a search results page.
224
222
 
@@ -245,8 +243,7 @@ See https://github.com/sporkmonger/addressable for more details on parameterized
245
243
 
246
244
  ### Navigating to the Page
247
245
 
248
- Once the URL has been set (using `set_url`), you can navigate directly
249
- to the page using `#load`:
246
+ Once the URL has been set (using `set_url`), you can navigate directly to the page using `#load`:
250
247
 
251
248
  ```ruby
252
249
  @home_page = Home.new
@@ -282,8 +279,6 @@ end
282
279
  This will tell whichever capybara driver you have configured to
283
280
  navigate to the URL set against that page's class.
284
281
 
285
- See https://github.com/sporkmonger/addressable for more details on parameterized URLs.
286
-
287
282
  ### Verifying that a particular page is displayed
288
283
 
289
284
  Automated tests often need to verify that a particular page is
@@ -319,8 +314,7 @@ wait time in seconds as the first argument like this:
319
314
  #### Specifying parameter values for templated URLs
320
315
 
321
316
  Sometimes you want to verify not just that the current URL matches the
322
- template, but that you're looking at a specific page matching that
323
- template.
317
+ template, but that you're looking at a specific page matching that template.
324
318
 
325
319
  Given the previous example, if you wanted to ensure that the browser had loaded
326
320
  account number 22, you could assert the following:
@@ -347,7 +341,7 @@ when comparing your page's URL template to the current_url:
347
341
  @account_page.load(id: 22, query: { token: 'ca2786616a4285bc', color: 'irrelevant' })
348
342
 
349
343
  expect(@account_page).to be_displayed(id: 22)
350
- expect(@account_page.url_matches['query']['token']).to eq('ca2786616a4285bc')
344
+ expect(@account_page.url_matches.dig('query', 'token')).to eq('ca2786616a4285bc')
351
345
  ```
352
346
 
353
347
  #### Falling back to basic regexp matchers
@@ -367,7 +361,7 @@ end
367
361
  SitePrism's `#displayed?` predicate method allows for semantic code in your tests:
368
362
 
369
363
  ```ruby
370
- Then(/^the account page is displayed$/) do
364
+ Then('the account page is displayed') do
371
365
  expect(@account_page).to be_displayed
372
366
  expect(@some_other_page).not_to be_displayed
373
367
  end
@@ -375,8 +369,7 @@ end
375
369
 
376
370
  ### Getting the Current Page's URL
377
371
 
378
- SitePrism allows you to get the current page's URL. Here's how it's
379
- done:
372
+ SitePrism allows you to get the current page's URL. Here's how it's done:
380
373
 
381
374
  ```ruby
382
375
  class Account < SitePrism::Page
@@ -462,8 +455,8 @@ end
462
455
  @home.load
463
456
 
464
457
  @home.search_field #=> will return the capybara element found using the selector
465
- @home.search_field.set 'the search string' #=> `search_field` returns a capybara element, so use the capybara API to deal with it
466
- @home.search_field.text #=> standard method on a capybara element; returns a string
458
+ @home.search_field.send_keys('the search string')
459
+ @home.search_field['value'] #=> standard method on a capybara element (field); returns the string value
467
460
  ```
468
461
 
469
462
  #### Testing for the existence of the element
@@ -492,16 +485,16 @@ end
492
485
  ...which makes for nice test code:
493
486
 
494
487
  ```ruby
495
- Then(/^the search field exists$/) do
488
+ Then('the search field exists') do
496
489
  expect(@home).to have_search_field
497
490
  end
498
491
  ```
499
492
 
500
493
  #### Testing that an element does not exist
501
494
 
502
- To test that an element does not exist on the page, it is not possible to just call
495
+ To test that an element does not exist on the page, you should not call
503
496
  `#not_to have_search_field`. SitePrism supplies the `#has_no_<element>?` method
504
- that should be used to test for non-existence.
497
+ that should be used instead to test for non-existence.
505
498
  This method delegates to [Capybara::Node::Matchers#has_no_selector?](https://www.rubydoc.info/github/teamcapybara/capybara/master/Capybara/Node/Matchers#has_no_selector%3F-instance_method)
506
499
  Using the above example:
507
500
 
@@ -514,7 +507,7 @@ Using the above example:
514
507
  ...which makes for nice test code:
515
508
 
516
509
  ```ruby
517
- Then(/^the search field exists$/)do
510
+ Then('the search field exists')do
518
511
  expect(@home).to have_no_search_field #NB: NOT => expect(@home).not_to have_search_field
519
512
  end
520
513
  ```
@@ -529,7 +522,7 @@ to become visible. You can customise the wait time by supplying a number
529
522
  of seconds to wait in-line or configuring the default wait time.
530
523
 
531
524
  ```ruby
532
- @home.wait_until_search_field_visible
525
+ @home.wait_until_search_field_visible # using the default wait time set
533
526
  # or...
534
527
  @home.wait_until_search_field_visible(wait: 10)
535
528
  ```
@@ -544,7 +537,7 @@ wait time for the element to become invisible. You can as with the visibility
544
537
  waiter, customise the wait time in the same way.
545
538
 
546
539
  ```ruby
547
- @home.wait_until_search_field_invisible
540
+ @home.wait_until_search_field_invisible # using the default wait time set
548
541
  # or...
549
542
  @home.wait_until_search_field_invisible(wait: 10)
550
543
  ```
@@ -663,7 +656,7 @@ Then the following method is available:
663
656
  This in turn allows the following nice test code
664
657
 
665
658
  ```ruby
666
- Then(/^there should be some names listed on the page$/) do
659
+ Then('there should be some names listed on the page') do
667
660
  expect(@friends_page).to have_names #=> This only passes if there is at least one `name`
668
661
  end
669
662
  ```
@@ -704,16 +697,16 @@ are present in the browser and `false` if they're not all there.
704
697
 
705
698
  # and...
706
699
 
707
- Then(/^the friends page contains all the expected elements$/) do
700
+ Then('the friends page contains all the expected elements') do
708
701
  expect(@friends_page).to be_all_there
709
702
  end
710
703
  ```
711
704
 
712
705
  You may wish to have elements declared in a page object class that are not
713
706
  always guaranteed to be present (success or error messages, etc.).
714
- If you'd still like to test such a page with `all_there?` you can declare
715
- `expected_elements` on your page object class that narrows the elements
716
- included in `all_there?` check to those that definitely should be present.
707
+ If you'd still like to test such a page with `#all_there?` you can declare
708
+ `.expected_elements` on your page class that narrows the elements
709
+ included in `#all_there?` check to those that definitely should be present.
717
710
 
718
711
  ```ruby
719
712
  class TestPage < SitePrism::Page
@@ -748,9 +741,9 @@ for this at the moment are `:none` and `:one`
748
741
  Passing `:none` (default), will not change the functionality. However passing in `:one` will cause
749
742
  `site_prism` to recurse through all `section` / `sections` items defined in your present scope.
750
743
 
751
- Work alongside developing this functionality further is being continued in the
744
+ Work to develop this is contained in the
752
745
  [site_prism-all_there](http://www.github.com/site-prism/site_prism-all_there) repo. So head on over
753
- there if you're interested in how this feature will work going forwards
746
+ there if you're interested in this area more
754
747
 
755
748
  ### Getting the list of missing elements
756
749
 
@@ -830,15 +823,14 @@ class People < SitePrism::Section
830
823
  end
831
824
 
832
825
  class Home < SitePrism::Page
833
- # section people_with_block will have `headline` and
834
- # `footer` elements in it
826
+ # section people_with_block will have `headline` and `footer` elements in it
835
827
  section :people_with_block, People do
836
828
  element :headline, 'h2'
837
829
  end
838
830
  end
839
831
  ```
840
832
 
841
- The 3rd argument (Locators), can be omitted if you are re-using the same
833
+ The 3rd argument (Locator), can be omitted if you are re-using the same
842
834
  locator for all references to the section Class. In order to do this,
843
835
  simply tell SitePrism that you want to use default search arguments.
844
836
 
@@ -874,7 +866,7 @@ end
874
866
  # the page and section in action
875
867
 
876
868
  @home = Home.new
877
- @home.menu #=> <MenuSection...>
869
+ @home.menu #=> <Menu...>
878
870
  ```
879
871
 
880
872
  When the `menu` method is called against `@home`, an instance of `Menu`
@@ -949,7 +941,7 @@ end
949
941
  This then leads to some pretty test code ...
950
942
 
951
943
  ```ruby
952
- Then(/^the home page menu contains a link to the various search functions$/) do
944
+ Then('the home page menu contains a link to the various search functions') do
953
945
  expect(@home.menu).to have_search
954
946
  expect(@home.menu.search['href']).to include('google.com')
955
947
  expect(@home.menu).to have_images
@@ -964,7 +956,7 @@ similar to Capybara's `within` method and allows for shorter test code
964
956
  particularly with nested sections. Test code that might have to repeat the block name can be shortened up this way.
965
957
 
966
958
  ```ruby
967
- Then(/^the home page menu contains a link to the various search functions$/) do
959
+ Then('the home page menu contains a link to the various search functions') do
968
960
  @home.menu.within do |menu|
969
961
  expect(menu).to have_search
970
962
  expect(menu.search['href']).to include('google.com')
@@ -974,10 +966,12 @@ Then(/^the home page menu contains a link to the various search functions$/) do
974
966
  end
975
967
  ```
976
968
 
977
- Note that on an individual section it's possible to pass a block directly to the section without using `within`. Because the block is executed only during `Section` initialization this won't work when accessing a single Section from an array of Sections. For that reason we recommend using `within` which works in either case.
969
+ Note that on an individual section it's possible to pass a block directly to the section without using `within`.
970
+ Because the block is executed only during `Section` initialization this won't work when accessing a single
971
+ Section from an array of Sections. For that reason we recommend using `within` which works in either case.
978
972
 
979
973
  ```ruby
980
- Then(/^the home page menu contains a link to the various search functions$/) do
974
+ Then('the home page menu contains a link to the various search functions') do
981
975
  @home.menu do |menu| # possible, but prefer: `@home.menu.within`
982
976
  expect(menu).to have_search
983
977
  end
@@ -1129,26 +1123,22 @@ class Home < SitePrism::Page
1129
1123
  section :login_and_registration, LoginRegistrationForm, 'div.login-registration'
1130
1124
  end
1131
1125
 
1132
- # how to login (fatuous, but demonstrates the point):
1126
+ # Then you could log in like so ...
1133
1127
 
1134
- Then(/^I sign in$/) do
1128
+ Then('I sign in') do
1135
1129
  @home = Home.new
1136
1130
  @home.load
1137
- expect(@home).to have_login_and_registration
1138
- expect(@home.login_and_registration).to have_username
1139
- @home.login_and_registration.login.username.set 'bob'
1140
- @home.login_and_registration.login.password.set 'p4ssw0rd'
1131
+ @home.login_and_registration.login.username.send_keys('bob')
1132
+ @home.login_and_registration.login.password.send_keys('p4ssw0rd')
1141
1133
  @home.login_and_registration.login.sign_in.click
1142
1134
  end
1143
1135
 
1144
- # how to sign up:
1136
+ # And you could sign up like so ...
1145
1137
 
1146
- When(/^I enter my name into the home page's registration form$/) do
1138
+ When('I sign up') do
1147
1139
  @home = Home.new
1148
1140
  @home.load
1149
- expect(@home.login_and_registration).to have_first_name
1150
- expect(@home.login_and_registration).to have_last_name
1151
- @home.login_and_registration.first_name.set 'Bob'
1141
+ @home.login_and_registration.first_name.send_keys('Bob')
1152
1142
  # ...
1153
1143
  end
1154
1144
  ```
@@ -1188,7 +1178,7 @@ can be called in a page or a section.
1188
1178
 
1189
1179
  The only difference between `section` and `sections` is that whereas the
1190
1180
  first returns an instance of the supplied section class, the second
1191
- returns an array containing as many instances of the section class as
1181
+ returns a `Capybara::Result` containing as many instances of the section class as
1192
1182
  there are capybara elements found by the supplied css selector. This is
1193
1183
  better explained in the following example ...
1194
1184
 
@@ -1220,7 +1210,7 @@ end
1220
1210
  This allows for pretty tests ...
1221
1211
 
1222
1212
  ```ruby
1223
- Then(/^there are lots of search_results$/) do
1213
+ Then('there are lots of search_results') do
1224
1214
  expect(@results_page.search_results.size).to eq(10)
1225
1215
 
1226
1216
  @home.search_results.each do |result|
@@ -1235,12 +1225,14 @@ The css selector that is passed as the 3rd argument to the
1235
1225
  elements. Each capybara element found using the css selector is used to
1236
1226
  create a new instance of `SearchResults` and becomes its root
1237
1227
  element. So if the css selector finds 3 `li` elements, calling
1238
- `search_results` will return an array containing 3 instances of
1228
+ `search_results` will return a `Capybara::Result` containing 3 instances of
1239
1229
  `SearchResults`, each with one of the `li` elements as it's root element.
1240
1230
 
1241
1231
  ##### Accessing Within a Collection of Sections
1242
1232
 
1243
- When using an iterator such as `each` to pass a block through to a collection of sections it is possible to skip using `within`. However some caution is warranted when accessing the Sections directly from an array, as the block can only be executed when the section is being initialized. The following does not work:
1233
+ When using an iterator such as `each` to pass a block through to a collection of sections it is
1234
+ possible to skip using `within`. However some caution is warranted when accessing the
1235
+ Sections directly from an array, as the block can only be executed when the section is being initialized. The following does not work:
1244
1236
 
1245
1237
  ```rb
1246
1238
  @home.search_results.first do |result|
@@ -1304,7 +1296,7 @@ Here's how to test for the existence of the section:
1304
1296
  This allows for some pretty tests ...
1305
1297
 
1306
1298
  ```ruby
1307
- Then(/^there are search results on the page$/) do
1299
+ Then('there are search results on the page') do
1308
1300
  expect(@home).to have_search_results
1309
1301
  end
1310
1302
  ```
@@ -1443,8 +1435,8 @@ The error message is ignored unless the boolean value is evaluated as falsey.
1443
1435
 
1444
1436
  ```ruby
1445
1437
  class SomePage < SitePrism::Page
1446
- element :foo_element, '.foo'
1447
- load_validation { [has_foo_element?, 'did not have foo element!'] }
1438
+ element :foo, '.foo'
1439
+ load_validation { [has_foo?, 'did not have foo element!'] }
1448
1440
  end
1449
1441
  ```
1450
1442
 
@@ -1490,8 +1482,8 @@ class FooPage < BasePage
1490
1482
  section :form, '#form'
1491
1483
  element :some_other_element, '.myelement'
1492
1484
 
1493
- load_validation { [has_form?, 'form did not appear'] }
1494
- load_validation { [has_some_other_element?, 'some other element did not appear'] }
1485
+ load_validation { [has_form?(wait: 5), 'form did not appear'] }
1486
+ load_validation { [has_some_other_element?(wait: 5), 'some other element did not appear'] }
1495
1487
  end
1496
1488
  ```
1497
1489
 
@@ -1502,12 +1494,6 @@ the validations will be performed in the following order:
1502
1494
  2. The `FooPage` validation will wait for the `form` element to be present.
1503
1495
  3. The `FooPage` validation will wait for the `some_other_element` element to be present.
1504
1496
 
1505
- **NB:** `SitePrism::Page` **used to** include a default load validation on
1506
- `page.displayed?` however for v3 this has been removed. It is therefore
1507
- necessary to re-define this if you want to retain the behaviour
1508
- from site_prism v2. See [UPGRADING.md](https://github.com/site-prism/site_prism/blob/main/UPGRADING.md#default-load-validations)
1509
- for more info on this.
1510
-
1511
1497
  ## Using Capybara Query Options
1512
1498
 
1513
1499
  When querying an element, section or a collection of elements or sections,
@@ -1535,7 +1521,7 @@ fail if the page has not finished loading the section(s):
1535
1521
  ```ruby
1536
1522
  @home = Home.new
1537
1523
  # ...
1538
- expect(@home.search_results.size).to == 25 # This may fail!
1524
+ expect(@home.search_results.size).to eq(25) # This may fail!
1539
1525
  ```
1540
1526
 
1541
1527
  The above query can be rewritten to utilize the Capybara `:count` option
@@ -1546,16 +1532,16 @@ the page within the timeout:
1546
1532
 
1547
1533
  ```ruby
1548
1534
  @home = Home.new
1549
- @home.has_search_results?(count: 25)
1535
+ @home.has_search_results?(count: 25) # will wait default wait time
1550
1536
  # OR
1551
- @home.search_results(count: 25)
1537
+ @home.search_results(count: 25, wait: 5) # will wait 5 seconds
1552
1538
  ```
1553
1539
 
1554
1540
  Now we can write pretty, non-failing tests without hard coding these options
1555
1541
  into our page and section classes:
1556
1542
 
1557
1543
  ```ruby
1558
- Then(/^there are search results on the page$/) do
1544
+ Then('there are search results on the page') do
1559
1545
  expect(@results_page).to have_search_results(count: 25)
1560
1546
  end
1561
1547
  ```
@@ -1586,7 +1572,7 @@ The following element methods allow Capybara options to be passed as arguments t
1586
1572
  ## Test views with Page objects
1587
1573
 
1588
1574
  It's possible to use the same page objects of integration tests for view tests, too,
1589
- just pass the rendered HTML to the ```load``` method:
1575
+ just pass the rendered HTML to the `load` method:
1590
1576
 
1591
1577
  ```ruby
1592
1578
  require 'spec_helper'
@@ -1688,14 +1674,14 @@ class Home < SitePrism::Page
1688
1674
  end
1689
1675
 
1690
1676
  # cucumber step that performs login
1691
- When(/^I log in$/) do
1677
+ When('I log in') do
1692
1678
  @home = Home.new
1693
1679
  @home.load
1694
1680
 
1695
1681
  @home.login_frame do |frame|
1696
1682
  #`frame` is an instance of the `LoginFrame` class
1697
- frame.username.set 'admin'
1698
- frame.password.set 'p4ssword'
1683
+ frame.username.send_keys('admin')
1684
+ frame.password.send_keys('p4ssword')
1699
1685
  end
1700
1686
  end
1701
1687
  ```
@@ -1738,14 +1724,6 @@ Capybara.using_wait_time(20) do
1738
1724
  end
1739
1725
  ```
1740
1726
 
1741
- ## Using SitePrism with VCR
1742
-
1743
- There's a SitePrism plugin called `site_prism.vcr` that lets you use
1744
- SitePrism with the VCR gem. Check it out [HERE](https://github.com/dnesteryuk/site_prism.vcr)
1745
-
1746
- Note that as of 2016 this plugin doesn't appear to have been under active development. Also it is
1747
- still pinned to the `2.x` series of site_prism so use it of your own accord.
1748
-
1749
1727
  # Epilogue
1750
1728
 
1751
1729
  So, we've seen how to use SitePrism to put together page objects made up
@@ -1756,7 +1734,7 @@ all over the place. Here's an example of this common problem:
1756
1734
  ```ruby
1757
1735
  @home = Home.new # <-- noise
1758
1736
  @home.load
1759
- @home.search_field.set 'Sausages'
1737
+ @home.search_field.send_keys('Sausages')
1760
1738
  @home.search_field.search_button.click
1761
1739
  @results_page = SearchResults.new # <-- noise
1762
1740
  expect(@results_page).to have_search_result_items
@@ -1766,7 +1744,7 @@ The annoyance (and, later, maintenance nightmare) is having to create
1766
1744
  `@home` and `@results_page`. It would be better to not have to create
1767
1745
  instances of pages all over your tests.
1768
1746
 
1769
- The way I've dealt with this problem is to create a class containing
1747
+ One way you can deal with this problem is to create a class containing
1770
1748
  methods that return instances of the pages. Eg:
1771
1749
 
1772
1750
  ```ruby
@@ -1803,17 +1781,17 @@ end
1803
1781
  # and here's how to use it
1804
1782
 
1805
1783
  #first line of the test...
1806
- Given(/^I start on the home page$/) do
1784
+ Given('I start on the home page') do
1807
1785
  @app = App.new
1808
1786
  @app.home.load
1809
1787
  end
1810
1788
 
1811
- When(/^I search for Sausages$/) do
1789
+ When('I search for Sausages') do
1812
1790
  @app.home.search_field.set 'Sausages'
1813
1791
  @app.home.search_button.click
1814
1792
  end
1815
1793
 
1816
- Then(/^I am on the results page$/) do
1794
+ Then('I am on the results page') do
1817
1795
  expect(@app.results_page).to be_displayed
1818
1796
  end
1819
1797
 
@@ -1823,8 +1801,8 @@ end
1823
1801
  The only thing that needs instantiating is the `App` class - from then on
1824
1802
  pages don't need to be initialized, they are now returned by methods on `@app`.
1825
1803
 
1826
- It is possible to further optimise this, by using Cucumber/RSpec hooks, amongst
1827
- other things. However the investigation and optimisation of this (and other
1804
+ It is possible to further optimise this, by using Cucumber/RSpec hooks, memoization as well
1805
+ as many other things. However the investigation and optimisation of this (and other
1828
1806
  aspects of SitePrism), is left as an exercise to the Reader.
1829
1807
 
1830
1808
  Happy testing from all of the SitePrism team!
@@ -15,7 +15,8 @@ module SitePrism
15
15
  @pattern = pattern
16
16
  end
17
17
 
18
- # @return the hash of extracted mappings from
18
+ # @return Hash
19
+ #
19
20
  # parsing the provided URL according to our pattern,
20
21
  # or nil if the URL doesn't conform to the matcher template.
21
22
  def mappings(url)
@@ -30,6 +31,8 @@ module SitePrism
30
31
  result
31
32
  end
32
33
 
34
+ # @return Boolean
35
+ #
33
36
  # Determine whether URL matches our pattern, and
34
37
  # optionally whether the extracted mappings match
35
38
  # a hash of expected values. You can specify values
@@ -38,21 +41,24 @@ module SitePrism
38
41
  actual_mappings = mappings(url)
39
42
  return false unless actual_mappings
40
43
 
41
- expected_mappings.empty? ||
42
- all_expected_mappings_match?(expected_mappings, actual_mappings)
44
+ expected_mappings.empty? || all_expected_mappings_match?(expected_mappings, actual_mappings)
43
45
  end
44
46
 
45
47
  private
46
48
 
47
- def all_expected_mappings_match?(expected_mappings, actual_mappings)
48
- expected_mappings.all? do |key, expected_value|
49
- actual_value = actual_mappings[key.to_s]
50
- case expected_value
51
- when Numeric; then actual_value == expected_value.to_s
52
- when Regexp; then actual_value.match(expected_value)
53
- else expected_value == actual_value
54
- end
55
- end
49
+ def component_matches(component, uri)
50
+ component_template = component_templates[component]
51
+ return {} unless component_template
52
+
53
+ component_url = uri.public_send(component).to_s
54
+ mappings = component_template.extract(component_url)
55
+ return mappings if mappings
56
+
57
+ # To support Addressable's expansion of queries - ensure it's parsing the fragment as appropriate (e.g. {?params*})
58
+ prefix = component_prefixes[component]
59
+ return nil unless prefix
60
+
61
+ component_template.extract(prefix + component_url)
56
62
  end
57
63
 
58
64
  def component_templates
@@ -73,27 +79,6 @@ module SitePrism
73
79
  end
74
80
  end
75
81
 
76
- # Returns empty hash if the template omits the component or a set of
77
- # substitutions if the provided URI component matches the template
78
- # component or nil if the match fails.
79
- def component_matches(component, uri)
80
- component_template = component_templates[component]
81
- return {} unless component_template
82
-
83
- component_url = uri.public_send(component).to_s
84
- mappings = component_template.extract(component_url)
85
- return mappings if mappings
86
-
87
- # to support Addressable's expansion of queries
88
- # ensure it's parsing the fragment as appropriate (e.g. {?params*})
89
- prefix = component_prefixes[component]
90
- return nil unless prefix
91
-
92
- component_template.extract(prefix + component_url)
93
- end
94
-
95
- # Convert the pattern into an Addressable URI by substituting
96
- # the template slugs with nonsense strings.
97
82
  def to_substituted_uri
98
83
  url = pattern
99
84
  substitutions.each_pair { |slug, value| url = url.sub(slug, value) }
@@ -105,13 +90,6 @@ module SitePrism
105
90
  end
106
91
  end
107
92
 
108
- def substitutions
109
- @substitutions ||= slugs.each_with_index.reduce({}) do |memo, slug_index|
110
- slug, index = slug_index
111
- memo.merge(slug => slug_prefix(slug) + substitution_value(index))
112
- end
113
- end
114
-
115
93
  def reverse_substitutions
116
94
  @reverse_substitutions ||=
117
95
  slugs.each_with_index.reduce({}) do |memo, slug_index|
@@ -127,6 +105,24 @@ module SitePrism
127
105
  pattern.scan(/{[^}]+}/)
128
106
  end
129
107
 
108
+ def all_expected_mappings_match?(expected_mappings, actual_mappings)
109
+ expected_mappings.all? do |key, expected_value|
110
+ actual_value = actual_mappings[key.to_s]
111
+ case expected_value
112
+ when Numeric; then actual_value == expected_value.to_s
113
+ when Regexp; then actual_value.match(expected_value)
114
+ else expected_value == actual_value
115
+ end
116
+ end
117
+ end
118
+
119
+ def substitutions
120
+ @substitutions ||= slugs.each_with_index.reduce({}) do |memo, slug_index|
121
+ slug, index = slug_index
122
+ memo.merge(slug => slug_prefix(slug) + substitution_value(index))
123
+ end
124
+ end
125
+
130
126
  # If a slug begins with non-alpha characters, it may denote the start of
131
127
  # a new component (e.g. query or fragment). We emit this prefix as part of
132
128
  # the substituted slug so that Addressable's URI parser can see it as such.
@@ -135,8 +131,7 @@ module SitePrism
135
131
  (prefix && prefix[1]) || ''
136
132
  end
137
133
 
138
- # Generate a repeatable 5 character uniform alphabetical nonsense string
139
- # to allow parsing as a URI
134
+ # Generate a repeatable 5 character uniform alphabetical nonsense string to allow parsing as a URI
140
135
  def substitution_value(index)
141
136
  sha = Digest::SHA1.digest(index.to_s)
142
137
  Base64.urlsafe_encode64(sha).gsub(/[^A-Za-z]/, '')[0..5]