site_prism 2.10 → 2.11
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/README.md +107 -87
- data/lib/site_prism/addressable_url_matcher.rb +21 -18
- data/lib/site_prism/element_checker.rb +9 -1
- data/lib/site_prism/element_container.rb +7 -3
- data/lib/site_prism/exceptions.rb +7 -1
- data/lib/site_prism/version.rb +1 -1
- metadata +30 -40
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e194be3ee7349ee99bb8704a35acca0d4bf963d9
|
4
|
+
data.tar.gz: 584fc98753ee4abfd4bbd1e220b537dfd2a10280
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4a6eb96791b4c5be970baa67ed782a14744066284ca8053fd0832ddf78325dc95aaedf5c97a488ef1e041b999d28e91b048c5be226d89a2c6308de15ec561d66
|
7
|
+
data.tar.gz: bad1b3076a2ca4a4b40430228d806dfc1e22a127f23451c46f2976c89fed03e8f9a804357dc6cb2244e4d158022edd3687b1efef180542317c631145f556f264
|
data/README.md
CHANGED
@@ -9,6 +9,14 @@ Find the pretty documentation here: http://rdoc.info/gems/site_prism/frames
|
|
9
9
|
|
10
10
|
Make sure to add your project/company to https://github.com/natritmeyer/site_prism/wiki/Who-is-using-SitePrism
|
11
11
|
|
12
|
+
## Supported Rubies / Browsers
|
13
|
+
|
14
|
+
SitePrism is built and tested to work on Ruby 2.0 - 2.4. There is also some limited support for the Ruby 1.9 series.
|
15
|
+
|
16
|
+
SitePrism should run on all major browsers. The gem's integration tests are ran on the latest version of Firefox.
|
17
|
+
|
18
|
+
If you find your browser isn't working correctly with SitePrism, please open an [issue request](https://github.com/natritmeyer/site_prism/issues/new)
|
19
|
+
|
12
20
|
## Synopsis
|
13
21
|
|
14
22
|
Here's an overview of how SitePrism is designed to be used:
|
@@ -17,20 +25,20 @@ Here's an overview of how SitePrism is designed to be used:
|
|
17
25
|
# define our site's pages
|
18
26
|
|
19
27
|
class Home < SitePrism::Page
|
20
|
-
set_url
|
28
|
+
set_url '/index.htm'
|
21
29
|
set_url_matcher /google.com\/?/
|
22
30
|
|
23
|
-
element :search_field,
|
31
|
+
element :search_field, 'input[name="q"]'
|
24
32
|
element :search_button, "button[name='btnK']"
|
25
|
-
elements :footer_links,
|
26
|
-
section :menu, MenuSection,
|
33
|
+
elements :footer_links, '#footer a'
|
34
|
+
section :menu, MenuSection, '#gbx3'
|
27
35
|
end
|
28
36
|
|
29
37
|
class SearchResults < SitePrism::Page
|
30
38
|
set_url_matcher /google.com\/results\?.*/
|
31
39
|
|
32
|
-
section :menu, MenuSection,
|
33
|
-
sections :search_results, SearchResultSection,
|
40
|
+
section :menu, MenuSection, '#gbx3'
|
41
|
+
sections :search_results, SearchResultSection, '#results li'
|
34
42
|
|
35
43
|
def search_result_links
|
36
44
|
search_results.map {|sr| sr.title['href']}
|
@@ -40,14 +48,14 @@ end
|
|
40
48
|
# define sections used on multiple pages or multiple times on one page
|
41
49
|
|
42
50
|
class MenuSection < SitePrism::Section
|
43
|
-
element :search,
|
44
|
-
element :images,
|
45
|
-
element :maps,
|
51
|
+
element :search, 'a.search'
|
52
|
+
element :images, 'a.image-search'
|
53
|
+
element :maps, 'a.map-search'
|
46
54
|
end
|
47
55
|
|
48
56
|
class SearchResultSection < SitePrism::Section
|
49
|
-
element :title,
|
50
|
-
element :blurb,
|
57
|
+
element :title, 'a.title'
|
58
|
+
element :blurb, 'span.result-description'
|
51
59
|
end
|
52
60
|
|
53
61
|
# now for some tests
|
@@ -174,7 +182,7 @@ Note that setting a URL is optional - you only need to set a url if you want to
|
|
174
182
|
directly to that page. It makes sense to set the URL for a page model of a home
|
175
183
|
page or a login page, but probably not a search results page.
|
176
184
|
|
177
|
-
####
|
185
|
+
#### Parametrized URLs
|
178
186
|
|
179
187
|
SitePrism uses the Addressable gem and therefore allows for parameterized URLs. Here is
|
180
188
|
a simple example:
|
@@ -333,7 +341,7 @@ end
|
|
333
341
|
@account = Account.new
|
334
342
|
#...
|
335
343
|
@account.current_url #=> "http://www.example.com/account/123"
|
336
|
-
expect(@account.current_url).to include
|
344
|
+
expect(@account.current_url).to include 'example.com/account/'
|
337
345
|
```
|
338
346
|
|
339
347
|
### Page Title
|
@@ -381,7 +389,7 @@ the relevant page. SitePrism makes this easy:
|
|
381
389
|
|
382
390
|
```ruby
|
383
391
|
class Home < SitePrism::Page
|
384
|
-
element :search_field,
|
392
|
+
element :search_field, 'input[name="q"]'
|
385
393
|
end
|
386
394
|
```
|
387
395
|
|
@@ -397,9 +405,9 @@ element. So using the following example:
|
|
397
405
|
|
398
406
|
```ruby
|
399
407
|
class Home < SitePrism::Page
|
400
|
-
set_url
|
408
|
+
set_url 'http://www.google.com'
|
401
409
|
|
402
|
-
element :search_field,
|
410
|
+
element :search_field, 'input[name="q"]'
|
403
411
|
end
|
404
412
|
```
|
405
413
|
|
@@ -410,7 +418,7 @@ end
|
|
410
418
|
@home.load
|
411
419
|
|
412
420
|
@home.search_field #=> will return the capybara element found using the selector
|
413
|
-
@home.search_field.set
|
421
|
+
@home.search_field.set 'the search string' #=> since search_field returns a capybara element, you can use the capybara API to deal with it
|
414
422
|
@home.search_field.text #=> standard method on a capybara element; returns a string
|
415
423
|
```
|
416
424
|
|
@@ -421,9 +429,9 @@ Another method added to the Page class by the `element` method is the
|
|
421
429
|
|
422
430
|
```ruby
|
423
431
|
class Home < SitePrism::Page
|
424
|
-
set_url
|
432
|
+
set_url 'http://www.google.com'
|
425
433
|
|
426
|
-
element :search_field,
|
434
|
+
element :search_field, 'input[name="q"]'
|
427
435
|
end
|
428
436
|
```
|
429
437
|
|
@@ -472,9 +480,9 @@ custom amount of time to wait. Using the same example as above:
|
|
472
480
|
|
473
481
|
```ruby
|
474
482
|
class Home < SitePrism::Page
|
475
|
-
set_url
|
483
|
+
set_url 'http://www.google.com'
|
476
484
|
|
477
|
-
element :search_field,
|
485
|
+
element :search_field, 'input[name="q"]'
|
478
486
|
end
|
479
487
|
```
|
480
488
|
|
@@ -526,10 +534,10 @@ can use a CSS selector, you can use an XPath expression. An example:
|
|
526
534
|
```ruby
|
527
535
|
class Home < SitePrism::Page
|
528
536
|
# CSS Selector:
|
529
|
-
element :first_name,
|
537
|
+
element :first_name, 'div#signup input[name="first-name"]'
|
530
538
|
|
531
539
|
#same thing as an XPath expression:
|
532
|
-
element :first_name, :xpath,
|
540
|
+
element :first_name, :xpath, '//div[@id="signup"]//input[@name="first-name"]'
|
533
541
|
end
|
534
542
|
```
|
535
543
|
|
@@ -539,7 +547,7 @@ Given:
|
|
539
547
|
|
540
548
|
```ruby
|
541
549
|
class Home < SitePrism::Page
|
542
|
-
element :search_field,
|
550
|
+
element :search_field, 'input[name="q"]'
|
543
551
|
end
|
544
552
|
```
|
545
553
|
|
@@ -567,7 +575,7 @@ Here's how it works:
|
|
567
575
|
|
568
576
|
```ruby
|
569
577
|
class Friends < SitePrism::Page
|
570
|
-
elements :names,
|
578
|
+
elements :names, 'ul#names li a'
|
571
579
|
end
|
572
580
|
```
|
573
581
|
|
@@ -584,7 +592,7 @@ css selector. Using the example above:
|
|
584
592
|
|
585
593
|
```ruby
|
586
594
|
class Friends < SitePrism::Page
|
587
|
-
elements :names,
|
595
|
+
elements :names, 'ul#names li a'
|
588
596
|
end
|
589
597
|
```
|
590
598
|
|
@@ -607,7 +615,7 @@ arrays:
|
|
607
615
|
Or even run some tests...
|
608
616
|
|
609
617
|
```ruby
|
610
|
-
expect(@friends_page.names.map { |name| name.text }).to eq([
|
618
|
+
expect(@friends_page.names.map { |name| name.text }).to eq(['Alice', 'Bob', 'Fred'])
|
611
619
|
expect(@friends_page.names.size).to eq(3)
|
612
620
|
expect(@friends_page).to have(3).names
|
613
621
|
```
|
@@ -650,7 +658,7 @@ matches the selector. For example, with the following page:
|
|
650
658
|
|
651
659
|
```ruby
|
652
660
|
class Friends < SitePrism::Page
|
653
|
-
elements :names,
|
661
|
+
elements :names, 'ul#names li a'
|
654
662
|
end
|
655
663
|
|
656
664
|
```
|
@@ -711,6 +719,18 @@ end
|
|
711
719
|
|
712
720
|
```
|
713
721
|
|
722
|
+
You may wish to have elements declared in a page object class that are not always guaranteed to be present (success or error messages, etc.). If you'd still like to test such a page with `all_there?` you can declare `expected_elements` on your page object class that narrows the elements included in `all_there?` check to those that definitely should be present.
|
723
|
+
|
724
|
+
```ruby
|
725
|
+
class TestPage < SitePrism::Page
|
726
|
+
element :name_field, '#name'
|
727
|
+
element :address_field, '#address'
|
728
|
+
element :success_msg, 'span.alert-success'
|
729
|
+
|
730
|
+
expected_elements :name_field, :address_field
|
731
|
+
end
|
732
|
+
```
|
733
|
+
|
714
734
|
## Sections
|
715
735
|
|
716
736
|
SitePrism allows you to model sections of a page that appear on multiple
|
@@ -745,7 +765,7 @@ includes the above `MenuSection` section:
|
|
745
765
|
|
746
766
|
```ruby
|
747
767
|
class Home < SitePrism::Page
|
748
|
-
section :menu, MenuSection,
|
768
|
+
section :menu, MenuSection, '#gbx3'
|
749
769
|
end
|
750
770
|
```
|
751
771
|
|
@@ -776,7 +796,7 @@ end
|
|
776
796
|
# the page that includes the section:
|
777
797
|
|
778
798
|
class Home < SitePrism::Page
|
779
|
-
section :menu, MenuSection,
|
799
|
+
section :menu, MenuSection, '#gbx3'
|
780
800
|
end
|
781
801
|
|
782
802
|
# the page and section in action:
|
@@ -803,11 +823,11 @@ end
|
|
803
823
|
# define 2 pages, each containing the same section
|
804
824
|
|
805
825
|
class Home < SitePrism::Page
|
806
|
-
section :menu, MenuSection,
|
826
|
+
section :menu, MenuSection, '#gbx3'
|
807
827
|
end
|
808
828
|
|
809
829
|
class SearchResults < SitePrism::Page
|
810
|
-
section :menu, MenuSection,
|
830
|
+
section :menu, MenuSection, '#gbx48'
|
811
831
|
end
|
812
832
|
```
|
813
833
|
|
@@ -822,9 +842,9 @@ This works just the same as adding elements to a page:
|
|
822
842
|
|
823
843
|
```ruby
|
824
844
|
class MenuSection < SitePrism::Section
|
825
|
-
element :search,
|
826
|
-
element :images,
|
827
|
-
element :maps,
|
845
|
+
element :search, 'a.search'
|
846
|
+
element :images, 'a.image-search'
|
847
|
+
element :maps, 'a.map-search'
|
828
848
|
end
|
829
849
|
```
|
830
850
|
|
@@ -836,7 +856,7 @@ When the section is added to a page...
|
|
836
856
|
|
837
857
|
```ruby
|
838
858
|
class Home < SitePrism::Page
|
839
|
-
section :menu, MenuSection,
|
859
|
+
section :menu, MenuSection, '#gbx3'
|
840
860
|
end
|
841
861
|
```
|
842
862
|
|
@@ -888,15 +908,15 @@ section is a subsection). For example, given the following setup:
|
|
888
908
|
|
889
909
|
```ruby
|
890
910
|
class MySubSection < SitePrism::Section
|
891
|
-
element :some_element,
|
911
|
+
element :some_element, 'abc'
|
892
912
|
end
|
893
913
|
|
894
914
|
class MySection < SitePrism::Section
|
895
|
-
section :my_subsection, MySubSection,
|
915
|
+
section :my_subsection, MySubSection, 'def'
|
896
916
|
end
|
897
917
|
|
898
918
|
class MyPage < SitePrism::Page
|
899
|
-
section :my_section, MySection,
|
919
|
+
section :my_section, MySection, 'ghi'
|
900
920
|
end
|
901
921
|
```
|
902
922
|
|
@@ -917,13 +937,13 @@ given the following setup:
|
|
917
937
|
|
918
938
|
```ruby
|
919
939
|
class MenuSection < SitePrism::Section
|
920
|
-
element :search,
|
921
|
-
element :images,
|
922
|
-
element :maps,
|
940
|
+
element :search, 'a.search'
|
941
|
+
element :images, 'a.image-search'
|
942
|
+
element :maps, 'a.map-search'
|
923
943
|
end
|
924
944
|
|
925
945
|
class Home < SitePrism::Page
|
926
|
-
section :menu, MenuSection,
|
946
|
+
section :menu, MenuSection, '#gbx3'
|
927
947
|
end
|
928
948
|
```
|
929
949
|
|
@@ -944,13 +964,13 @@ to the page or section it's been added to - same idea as what the
|
|
944
964
|
|
945
965
|
```ruby
|
946
966
|
class MenuSection < SitePrism::Section
|
947
|
-
element :search,
|
948
|
-
element :images,
|
949
|
-
element :maps,
|
967
|
+
element :search, 'a.search'
|
968
|
+
element :images, 'a.image-search'
|
969
|
+
element :maps, 'a.map-search'
|
950
970
|
end
|
951
971
|
|
952
972
|
class Home < SitePrism::Page
|
953
|
-
section :menu, MenuSection,
|
973
|
+
section :menu, MenuSection, '#gbx3'
|
954
974
|
end
|
955
975
|
```
|
956
976
|
|
@@ -979,13 +999,13 @@ page/section that our section was added to. Given the following setup:
|
|
979
999
|
|
980
1000
|
```ruby
|
981
1001
|
class MenuSection < SitePrism::Section
|
982
|
-
element :search,
|
983
|
-
element :images,
|
984
|
-
element :maps,
|
1002
|
+
element :search, 'a.search'
|
1003
|
+
element :images, 'a.image-search'
|
1004
|
+
element :maps, 'a.map-search'
|
985
1005
|
end
|
986
1006
|
|
987
1007
|
class Home < SitePrism::Page
|
988
|
-
section :menu, MenuSection,
|
1008
|
+
section :menu, MenuSection, '#gbx3'
|
989
1009
|
end
|
990
1010
|
```
|
991
1011
|
|
@@ -1032,24 +1052,24 @@ sections within sections within sections within sections!
|
|
1032
1052
|
# define a page that contains an area that contains a section for both logging in and registration, then modelling each of the sub sections separately
|
1033
1053
|
|
1034
1054
|
class Login < SitePrism::Section
|
1035
|
-
element :username,
|
1036
|
-
element :password,
|
1037
|
-
element :sign_in,
|
1055
|
+
element :username, '#username'
|
1056
|
+
element :password, '#password'
|
1057
|
+
element :sign_in, 'button'
|
1038
1058
|
end
|
1039
1059
|
|
1040
1060
|
class Registration < SitePrism::Section
|
1041
|
-
element :first_name,
|
1042
|
-
element :last_name,
|
1043
|
-
element :next_step,
|
1061
|
+
element :first_name, '#first_name'
|
1062
|
+
element :last_name, '#last_name'
|
1063
|
+
element :next_step, 'button.next-reg-step'
|
1044
1064
|
end
|
1045
1065
|
|
1046
1066
|
class LoginRegistrationForm < SitePrism::Section
|
1047
|
-
section :login, Login,
|
1048
|
-
section :registration, Registration,
|
1067
|
+
section :login, Login, 'div.login-area'
|
1068
|
+
section :registration, Registration, 'div.reg-area'
|
1049
1069
|
end
|
1050
1070
|
|
1051
1071
|
class Home < SitePrism::Page
|
1052
|
-
section :login_and_registration, LoginRegistrationForm,
|
1072
|
+
section :login_and_registration, LoginRegistrationForm, 'div.login-registration'
|
1053
1073
|
end
|
1054
1074
|
|
1055
1075
|
# how to login (fatuous, but demonstrates the point):
|
@@ -1122,12 +1142,12 @@ Given the following setup:
|
|
1122
1142
|
|
1123
1143
|
```ruby
|
1124
1144
|
class SearchResultSection < SitePrism::Section
|
1125
|
-
element :title,
|
1126
|
-
element :blurb,
|
1145
|
+
element :title, 'a.title'
|
1146
|
+
element :blurb, 'span.result-decription'
|
1127
1147
|
end
|
1128
1148
|
|
1129
1149
|
class SearchResults < SitePrism::Page
|
1130
|
-
sections :search_results, SearchResultSection,
|
1150
|
+
sections :search_results, SearchResultSection, '#results li'
|
1131
1151
|
end
|
1132
1152
|
```
|
1133
1153
|
|
@@ -1169,9 +1189,9 @@ define a single anonymous section:
|
|
1169
1189
|
|
1170
1190
|
```ruby
|
1171
1191
|
class SearchResults < SitePrism::Page
|
1172
|
-
sections :search_results,
|
1173
|
-
element :title,
|
1174
|
-
element :blurb,
|
1192
|
+
sections :search_results, '#results li' do
|
1193
|
+
element :title, 'a.title'
|
1194
|
+
element :blurb, 'span.result-decription'
|
1175
1195
|
end
|
1176
1196
|
end
|
1177
1197
|
```
|
@@ -1186,12 +1206,12 @@ following example:
|
|
1186
1206
|
|
1187
1207
|
```ruby
|
1188
1208
|
class SearchResultSection < SitePrism::Section
|
1189
|
-
element :title,
|
1190
|
-
element :blurb,
|
1209
|
+
element :title, 'a.title'
|
1210
|
+
element :blurb, 'span.result-decription'
|
1191
1211
|
end
|
1192
1212
|
|
1193
1213
|
class SearchResults < SitePrism::Page
|
1194
|
-
sections :search_results, SearchResultSection,
|
1214
|
+
sections :search_results, SearchResultSection, '#results li'
|
1195
1215
|
end
|
1196
1216
|
```
|
1197
1217
|
|
@@ -1220,12 +1240,12 @@ the section in the array of sections. For example:
|
|
1220
1240
|
|
1221
1241
|
```ruby
|
1222
1242
|
class SearchResultSection < SitePrism::Section
|
1223
|
-
element :title,
|
1224
|
-
element :blurb,
|
1243
|
+
element :title, 'a.title'
|
1244
|
+
element :blurb, 'span.result-decription'
|
1225
1245
|
end
|
1226
1246
|
|
1227
1247
|
class SearchResults < SitePrism::Page
|
1228
|
-
sections :search_results, SearchResultSection,
|
1248
|
+
sections :search_results, SearchResultSection, '#results li'
|
1229
1249
|
end
|
1230
1250
|
```
|
1231
1251
|
|
@@ -1386,13 +1406,13 @@ Given the following sample page and elements:
|
|
1386
1406
|
|
1387
1407
|
```ruby
|
1388
1408
|
class SearchResultSection < SitePrism::Section
|
1389
|
-
element :title,
|
1390
|
-
element :blurb,
|
1409
|
+
element :title, 'a.title'
|
1410
|
+
element :blurb, 'span.result-decription'
|
1391
1411
|
end
|
1392
1412
|
|
1393
1413
|
class SearchResults < SitePrism::Page
|
1394
|
-
element :footer,
|
1395
|
-
sections :search_results, SearchResultSection,
|
1414
|
+
element :footer, '.footer'
|
1415
|
+
sections :search_results, SearchResultSection, '#results li'
|
1396
1416
|
end
|
1397
1417
|
```
|
1398
1418
|
|
@@ -1433,9 +1453,9 @@ This is supported for all of the Capybara options including, but not limited to
|
|
1433
1453
|
|
1434
1454
|
```ruby
|
1435
1455
|
class SearchResults < SitePrism::Page
|
1436
|
-
element :footer,
|
1437
|
-
element :view_more,
|
1438
|
-
sections :search_results, SearchResultSection,
|
1456
|
+
element :footer, '.footer'
|
1457
|
+
element :view_more, 'li', text: 'View More'
|
1458
|
+
sections :search_results, SearchResultSection, '#results li'
|
1439
1459
|
end
|
1440
1460
|
```
|
1441
1461
|
|
@@ -1490,7 +1510,7 @@ An iframe is declared in the same way as a Page:
|
|
1490
1510
|
|
1491
1511
|
```ruby
|
1492
1512
|
class MyIframe < SitePrism::Page
|
1493
|
-
element :some_text_field,
|
1513
|
+
element :some_text_field, 'input.username'
|
1494
1514
|
end
|
1495
1515
|
```
|
1496
1516
|
|
@@ -1501,7 +1521,7 @@ iframe, and an ID or class by which you can locate the iframe. For example:
|
|
1501
1521
|
|
1502
1522
|
```ruby
|
1503
1523
|
class PageContainingIframe < SitePrism::Page
|
1504
|
-
iframe :my_iframe, MyIframe,
|
1524
|
+
iframe :my_iframe, MyIframe, '#my_iframe_id'
|
1505
1525
|
end
|
1506
1526
|
```
|
1507
1527
|
|
@@ -1543,15 +1563,15 @@ SitePrism::Page that represents the iframe's contents. For example:
|
|
1543
1563
|
```ruby
|
1544
1564
|
# SitePrism::Page representing the iframe
|
1545
1565
|
class Login < SitePrism::Page
|
1546
|
-
element :username,
|
1547
|
-
element :password,
|
1566
|
+
element :username, 'input.username'
|
1567
|
+
element :password, 'input.password'
|
1548
1568
|
end
|
1549
1569
|
|
1550
1570
|
# SitePrism::Page representing the page that contains the iframe
|
1551
1571
|
class Home < SitePrism::Page
|
1552
|
-
set_url
|
1572
|
+
set_url 'http://www.example.com'
|
1553
1573
|
|
1554
|
-
iframe :login_area, Login,
|
1574
|
+
iframe :login_area, Login, '#login_and_registration'
|
1555
1575
|
end
|
1556
1576
|
|
1557
1577
|
# cucumber step that performs login
|
@@ -1561,8 +1581,8 @@ When /^I log in$/ do
|
|
1561
1581
|
|
1562
1582
|
@home.login_area do |frame|
|
1563
1583
|
#`frame` is an instance of the `Login` class
|
1564
|
-
frame.username.set
|
1565
|
-
frame.password.set
|
1584
|
+
frame.username.set 'admin'
|
1585
|
+
frame.password.set 'p4ssword'
|
1566
1586
|
end
|
1567
1587
|
end
|
1568
1588
|
```
|
@@ -5,7 +5,7 @@ require 'base64'
|
|
5
5
|
|
6
6
|
module SitePrism
|
7
7
|
class AddressableUrlMatcher
|
8
|
-
COMPONENT_NAMES = %
|
8
|
+
COMPONENT_NAMES = %i[scheme user password host port path query fragment].freeze
|
9
9
|
COMPONENT_PREFIXES = {
|
10
10
|
query: '?',
|
11
11
|
fragment: '#'
|
@@ -24,8 +24,9 @@ module SitePrism
|
|
24
24
|
result = {}
|
25
25
|
COMPONENT_NAMES.each do |component|
|
26
26
|
component_result = component_matches(component, uri)
|
27
|
-
|
28
|
-
|
27
|
+
return nil unless component_result
|
28
|
+
|
29
|
+
result.merge!(component_result)
|
29
30
|
end
|
30
31
|
result
|
31
32
|
end
|
@@ -35,7 +36,7 @@ module SitePrism
|
|
35
36
|
def matches?(url, expected_mappings = {})
|
36
37
|
actual_mappings = mappings(url)
|
37
38
|
if actual_mappings
|
38
|
-
expected_mappings.empty?
|
39
|
+
expected_mappings.empty? || all_expected_mappings_match?(expected_mappings, actual_mappings)
|
39
40
|
else
|
40
41
|
false
|
41
42
|
end
|
@@ -57,7 +58,6 @@ module SitePrism
|
|
57
58
|
end
|
58
59
|
end
|
59
60
|
|
60
|
-
# Memoizes the extracted component templates
|
61
61
|
def component_templates
|
62
62
|
@component_templates ||= extract_component_templates
|
63
63
|
end
|
@@ -66,14 +66,14 @@ module SitePrism
|
|
66
66
|
COMPONENT_NAMES.each_with_object({}) do |component, component_templates|
|
67
67
|
component_url = to_substituted_uri.public_send(component).to_s
|
68
68
|
|
69
|
-
next unless component_url && component_url
|
69
|
+
next unless component_url && !component_url.empty?
|
70
70
|
|
71
71
|
reverse_substitutions.each_pair do |substituted_value, template_value|
|
72
72
|
component_url = component_url.sub(substituted_value, template_value)
|
73
73
|
end
|
74
74
|
|
75
75
|
component_templates[component] = Addressable::Template.new(component_url.to_s)
|
76
|
-
end
|
76
|
+
end
|
77
77
|
end
|
78
78
|
|
79
79
|
# Returns empty hash if the template omits the component, a set of substitutions if the
|
@@ -83,7 +83,8 @@ module SitePrism
|
|
83
83
|
component_template = component_templates[component]
|
84
84
|
if component_template
|
85
85
|
component_url = uri.public_send(component).to_s
|
86
|
-
|
86
|
+
extracted_mappings = component_template.extract(component_url)
|
87
|
+
unless extracted_mappings
|
87
88
|
# to support Addressable's expansion of queries, ensure it's parsing the fragment as appropriate (e.g. {?params*})
|
88
89
|
prefix = COMPONENT_PREFIXES[component]
|
89
90
|
return nil unless prefix && (extracted_mappings = component_template.extract(prefix + component_url))
|
@@ -101,36 +102,38 @@ module SitePrism
|
|
101
102
|
begin
|
102
103
|
Addressable::URI.parse(url)
|
103
104
|
rescue Addressable::URI::InvalidURIError
|
104
|
-
raise SitePrism::InvalidUrlMatcher
|
105
|
+
raise SitePrism::InvalidUrlMatcher
|
105
106
|
end
|
106
107
|
end
|
107
108
|
|
108
109
|
def substitutions
|
109
|
-
@substitutions ||= slugs.each_with_index.reduce({}) do |memo,
|
110
|
-
slug, index =
|
110
|
+
@substitutions ||= slugs.each_with_index.reduce({}) do |memo, slug_index|
|
111
|
+
slug, index = slug_index
|
111
112
|
memo.merge(slug => slug_prefix(slug) + substitution_value(index))
|
112
113
|
end
|
113
114
|
end
|
114
115
|
|
115
116
|
def reverse_substitutions
|
116
|
-
@reverse_substitutions ||= slugs.each_with_index.reduce({}) do |memo,
|
117
|
-
slug, index =
|
117
|
+
@reverse_substitutions ||= slugs.each_with_index.reduce({}) do |memo, slug_index|
|
118
|
+
slug, index = slug_index
|
118
119
|
memo.merge(slug_prefix(slug) + substitution_value(index) => slug, substitution_value(index) => slug)
|
119
120
|
end
|
120
121
|
end
|
121
122
|
|
122
123
|
def slugs
|
123
|
-
pattern.scan(
|
124
|
+
pattern.scan(/{[^}]+}/)
|
124
125
|
end
|
125
126
|
|
126
|
-
# If a slug begins with non-alpha characters, it may denote the start of a new component
|
127
|
-
# We emit this prefix as part of the substituted slug
|
127
|
+
# If a slug begins with non-alpha characters, it may denote the start of a new component
|
128
|
+
# (e.g. query or fragment). We emit this prefix as part of the substituted slug
|
129
|
+
# so that Addressable's URI parser can see it as such.
|
128
130
|
def slug_prefix(slug)
|
129
|
-
matches = slug.match(/\A
|
131
|
+
matches = slug.match(/\A{([^A-Za-z]+)/)
|
130
132
|
matches && matches[1] || ''
|
131
133
|
end
|
132
134
|
|
133
|
-
# Generate a repeatable 5 character uniform alphabetical nonsense string
|
135
|
+
# Generate a repeatable 5 character uniform alphabetical nonsense string
|
136
|
+
# to allow parsing as a URI
|
134
137
|
def substitution_value(index)
|
135
138
|
Base64.urlsafe_encode64(Digest::SHA1.digest(index.to_s)).gsub(/[^A-Za-z]/, '')[0..5]
|
136
139
|
end
|
@@ -3,7 +3,15 @@
|
|
3
3
|
module SitePrism
|
4
4
|
module ElementChecker
|
5
5
|
def all_there?
|
6
|
-
|
6
|
+
elements_to_check.all? { |element| send "has_#{element}?" }
|
7
|
+
end
|
8
|
+
|
9
|
+
private
|
10
|
+
|
11
|
+
def elements_to_check
|
12
|
+
elements = self.class.mapped_items
|
13
|
+
elements = elements.select { |el| self.class.expected_items.include?(el) } if self.class.expected_items
|
14
|
+
elements
|
7
15
|
end
|
8
16
|
end
|
9
17
|
end
|
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
module SitePrism
|
4
4
|
module ElementContainer
|
5
|
-
attr_reader :mapped_items
|
5
|
+
attr_reader :mapped_items, :expected_items
|
6
6
|
|
7
7
|
def element(element_name, *find_args)
|
8
8
|
build element_name, *find_args do
|
@@ -23,6 +23,10 @@ module SitePrism
|
|
23
23
|
end
|
24
24
|
alias collection elements
|
25
25
|
|
26
|
+
def expected_elements(*elements)
|
27
|
+
@expected_items = elements
|
28
|
+
end
|
29
|
+
|
26
30
|
def section(section_name, *args, &block)
|
27
31
|
section_class, find_args = extract_section_options args, &block
|
28
32
|
build section_name, *find_args do
|
@@ -60,7 +64,7 @@ module SitePrism
|
|
60
64
|
|
61
65
|
def add_to_mapped_items(item)
|
62
66
|
@mapped_items ||= []
|
63
|
-
@mapped_items << item
|
67
|
+
@mapped_items << item
|
64
68
|
end
|
65
69
|
|
66
70
|
def raise_if_block(obj, name, has_block)
|
@@ -178,7 +182,7 @@ module SitePrism
|
|
178
182
|
elsif block_given?
|
179
183
|
section_class = Class.new SitePrism::Section, &block
|
180
184
|
else
|
181
|
-
raise ArgumentError, 'You should provide section class either as a block, or as the second argument'
|
185
|
+
raise ArgumentError, 'You should provide section class either as a block, or as the second argument.'
|
182
186
|
end
|
183
187
|
return section_class, args
|
184
188
|
end
|
@@ -3,7 +3,13 @@
|
|
3
3
|
module SitePrism
|
4
4
|
class NoUrlForPage < StandardError; end
|
5
5
|
class NoUrlMatcherForPage < StandardError; end
|
6
|
-
|
6
|
+
|
7
|
+
class InvalidUrlMatcher < StandardError
|
8
|
+
def message
|
9
|
+
'Could not automatically match your URL. Templated port numbers are unsupported.'
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
7
13
|
class NoSelectorForElement < StandardError; end
|
8
14
|
class TimeoutException < StandardError; end
|
9
15
|
class TimeOutWaitingForElementVisibility < StandardError; end
|
data/lib/site_prism/version.rb
CHANGED
metadata
CHANGED
@@ -1,43 +1,44 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: site_prism
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: '2.
|
4
|
+
version: '2.11'
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Nat Ritmeyer
|
8
|
+
- Luke Hill
|
8
9
|
autorequire:
|
9
10
|
bindir: bin
|
10
11
|
cert_chain: []
|
11
|
-
date: 2018-
|
12
|
+
date: 2018-03-12 00:00:00.000000000 Z
|
12
13
|
dependencies:
|
13
14
|
- !ruby/object:Gem::Dependency
|
14
15
|
name: addressable
|
15
16
|
requirement: !ruby/object:Gem::Requirement
|
16
17
|
requirements:
|
17
|
-
- - ~>
|
18
|
+
- - "~>"
|
18
19
|
- !ruby/object:Gem::Version
|
19
20
|
version: '2.4'
|
20
21
|
type: :runtime
|
21
22
|
prerelease: false
|
22
23
|
version_requirements: !ruby/object:Gem::Requirement
|
23
24
|
requirements:
|
24
|
-
- - ~>
|
25
|
+
- - "~>"
|
25
26
|
- !ruby/object:Gem::Version
|
26
27
|
version: '2.4'
|
27
28
|
- !ruby/object:Gem::Dependency
|
28
29
|
name: capybara
|
29
30
|
requirement: !ruby/object:Gem::Requirement
|
30
31
|
requirements:
|
31
|
-
- - ~>
|
32
|
+
- - "~>"
|
32
33
|
- !ruby/object:Gem::Version
|
33
|
-
version: '2.
|
34
|
+
version: '2.7'
|
34
35
|
type: :runtime
|
35
36
|
prerelease: false
|
36
37
|
version_requirements: !ruby/object:Gem::Requirement
|
37
38
|
requirements:
|
38
|
-
- - ~>
|
39
|
+
- - "~>"
|
39
40
|
- !ruby/object:Gem::Version
|
40
|
-
version: '2.
|
41
|
+
version: '2.7'
|
41
42
|
- !ruby/object:Gem::Dependency
|
42
43
|
name: cucumber
|
43
44
|
requirement: !ruby/object:Gem::Requirement
|
@@ -56,42 +57,42 @@ dependencies:
|
|
56
57
|
name: rake
|
57
58
|
requirement: !ruby/object:Gem::Requirement
|
58
59
|
requirements:
|
59
|
-
- -
|
60
|
+
- - ">="
|
60
61
|
- !ruby/object:Gem::Version
|
61
62
|
version: '11.0'
|
62
63
|
type: :development
|
63
64
|
prerelease: false
|
64
65
|
version_requirements: !ruby/object:Gem::Requirement
|
65
66
|
requirements:
|
66
|
-
- -
|
67
|
+
- - ">="
|
67
68
|
- !ruby/object:Gem::Version
|
68
69
|
version: '11.0'
|
69
70
|
- !ruby/object:Gem::Dependency
|
70
71
|
name: redcarpet
|
71
72
|
requirement: !ruby/object:Gem::Requirement
|
72
73
|
requirements:
|
73
|
-
- - ~>
|
74
|
+
- - "~>"
|
74
75
|
- !ruby/object:Gem::Version
|
75
76
|
version: '3.0'
|
76
77
|
type: :development
|
77
78
|
prerelease: false
|
78
79
|
version_requirements: !ruby/object:Gem::Requirement
|
79
80
|
requirements:
|
80
|
-
- - ~>
|
81
|
+
- - "~>"
|
81
82
|
- !ruby/object:Gem::Version
|
82
83
|
version: '3.0'
|
83
84
|
- !ruby/object:Gem::Dependency
|
84
85
|
name: rspec
|
85
86
|
requirement: !ruby/object:Gem::Requirement
|
86
87
|
requirements:
|
87
|
-
- - ~>
|
88
|
+
- - "~>"
|
88
89
|
- !ruby/object:Gem::Version
|
89
90
|
version: '3.2'
|
90
91
|
type: :development
|
91
92
|
prerelease: false
|
92
93
|
version_requirements: !ruby/object:Gem::Requirement
|
93
94
|
requirements:
|
94
|
-
- - ~>
|
95
|
+
- - "~>"
|
95
96
|
- !ruby/object:Gem::Version
|
96
97
|
version: '3.2'
|
97
98
|
- !ruby/object:Gem::Dependency
|
@@ -112,47 +113,36 @@ dependencies:
|
|
112
113
|
name: selenium-webdriver
|
113
114
|
requirement: !ruby/object:Gem::Requirement
|
114
115
|
requirements:
|
115
|
-
- - ~>
|
116
|
+
- - "~>"
|
116
117
|
- !ruby/object:Gem::Version
|
117
118
|
version: 3.4.0
|
118
119
|
type: :development
|
119
120
|
prerelease: false
|
120
121
|
version_requirements: !ruby/object:Gem::Requirement
|
121
122
|
requirements:
|
122
|
-
- - ~>
|
123
|
+
- - "~>"
|
123
124
|
- !ruby/object:Gem::Version
|
124
125
|
version: 3.4.0
|
125
126
|
- !ruby/object:Gem::Dependency
|
126
127
|
name: simplecov
|
127
128
|
requirement: !ruby/object:Gem::Requirement
|
128
129
|
requirements:
|
129
|
-
- -
|
130
|
+
- - ">="
|
130
131
|
- !ruby/object:Gem::Version
|
131
|
-
version: '0.
|
132
|
+
version: '0.11'
|
132
133
|
type: :development
|
133
134
|
prerelease: false
|
134
135
|
version_requirements: !ruby/object:Gem::Requirement
|
135
136
|
requirements:
|
136
|
-
- -
|
137
|
+
- - ">="
|
137
138
|
- !ruby/object:Gem::Version
|
138
|
-
version: '0.
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
version: '0.8'
|
146
|
-
type: :development
|
147
|
-
prerelease: false
|
148
|
-
version_requirements: !ruby/object:Gem::Requirement
|
149
|
-
requirements:
|
150
|
-
- - ~>
|
151
|
-
- !ruby/object:Gem::Version
|
152
|
-
version: '0.8'
|
153
|
-
description: SitePrism gives you a simple, clean and semantic DSL for describing your
|
154
|
-
site using the Page Object Model pattern, for use with Capybara
|
155
|
-
email: nat@natontesting.com
|
139
|
+
version: '0.11'
|
140
|
+
description: |-
|
141
|
+
SitePrism gives you a simple, clean and semantic DSL for describing your site.
|
142
|
+
SitePrism implements the Page Object Model pattern on top of Capybara.
|
143
|
+
email:
|
144
|
+
- nat@natontesting.com
|
145
|
+
- lukehill_uk@hotmail.com
|
156
146
|
executables: []
|
157
147
|
extensions: []
|
158
148
|
extra_rdoc_files: []
|
@@ -179,17 +169,17 @@ require_paths:
|
|
179
169
|
- lib
|
180
170
|
required_ruby_version: !ruby/object:Gem::Requirement
|
181
171
|
requirements:
|
182
|
-
- -
|
172
|
+
- - ">="
|
183
173
|
- !ruby/object:Gem::Version
|
184
174
|
version: '2.0'
|
185
175
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
186
176
|
requirements:
|
187
|
-
- -
|
177
|
+
- - ">="
|
188
178
|
- !ruby/object:Gem::Version
|
189
179
|
version: '0'
|
190
180
|
requirements: []
|
191
181
|
rubyforge_project:
|
192
|
-
rubygems_version: 2.
|
182
|
+
rubygems_version: 2.6.13
|
193
183
|
signing_key:
|
194
184
|
specification_version: 4
|
195
185
|
summary: A Page Object Model DSL for Capybara
|