site_prism 3.4.1 → 3.7.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: d5d3515d35ccf73d1d9678c9f299ddfbe224783c0d324fbb8151d2e7dbac8afa
4
- data.tar.gz: cd63c3947bee0fce01954e7156fcf67dda5c774307910c10afc8fdfb2fc3dd0b
3
+ metadata.gz: c5deda0d9df9e83e2a66663a217cf5c434fd3ed25abae0d14778d99cd5db1c0f
4
+ data.tar.gz: 6c86aff27c00c5e91b01667f7da1f9ee6e2d33d4f95d18fbb0cfdd9fd44779c5
5
5
  SHA512:
6
- metadata.gz: 3a7906d90c8f83154f15c84422712638c547b855774dea30abc8b2bc229abf965352cbb32ac76bee9033909d321ada772e581ab9aa866738cfde23eaa1af2e08
7
- data.tar.gz: 86f98bed36557c418ca65f681c88c1461a4d52518f0b264e87844fd643711da7902068f5836755a2f7126165a05a0ace87863d3af4a93f45e294b28b32b74c08
6
+ metadata.gz: 254398e151d390326bf085d0746391aedd247d1ed8bf47909d8fb87752b6cedd056ff32c14f324d5b33f4b922734ed01ec2467f64be59a8d97a07cf8aa002eea
7
+ data.tar.gz: 652781ebe825ed5f943ca0f8480a9b5fbd511e81e6c12d9ce95de7c3239073d4499f4165044c8c58888aeabf0cf2d9bc76e4ca6f2ae6baa6996093117577005a
data/LICENSE.md CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2011-2019, The SitePrism team
1
+ Copyright (c) 2011-2021, The SitePrism team
2
2
 
3
3
  All rights reserved.
4
4
 
data/README.md CHANGED
@@ -7,23 +7,34 @@ _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: http://rdoc.info/gems/site_prism/frames
10
+ Find the pretty documentation here: https://rdoc.info/gems/site_prism/frames
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
 
14
+ ## Support
15
+
16
+ Support us with a monthly donation and help us continue our activities by supporting us as a [backer](https://opencollective.com/site-prism#backer)
17
+
18
+ Become a sponsor and get your logo on our README on Github with a link to your site. [How to Sponsor SitePrism?](https://opencollective.com/site-prism#sponsor)
19
+
20
+ Free Open Source software can only be maintained with the support of you. If you and/or your company find
21
+ value in SitePrism and would like to contribute financially to its ongoing maintenance and development,
22
+ then please do so. Visit the OpenCollective links above for more details.
23
+
14
24
  ## Developing / Contributing to SitePrism
15
25
 
16
26
  We love it when people want to get involved with our Open Source Project.
17
27
 
18
- We have a brief set of setup docs [HERE](https://github.com/site-prism/site_prism/blob/master/development_setup.md)
28
+ We have a brief set of setup docs [HERE](https://github.com/site-prism/site_prism/blob/main/HACKING.md)
19
29
 
20
30
  ## Supported Rubies / Browsers
21
31
 
22
- SitePrism is built and tested to work on Ruby 2.4 - 2.6. Ruby 2.3 (Now EOL), is supported but not tested against.
23
- If you are using SitePrism with Ruby 2.3 it is highly advisable to upgrade to a more modern Ruby
24
- such as 2.5 or 2.6, if for any other reason, to get a noticeable speed boost!
32
+ SitePrism is built and tested to work on Ruby 2.4 - 2.7. Ruby 2.4 (Now EOL), is supported but
33
+ this version will be removed from the Support Matrix in the coming months.
34
+ If you are using SitePrism with Ruby 2.4 it is highly advisable to upgrade to a more modern Ruby
35
+ such as 2.7, if for any other reason, to get a noticeable speed boost!
25
36
 
26
- SitePrism should run on all major browsers. The gem's integration tests are ran on Chrome and Firefox.
37
+ SitePrism should run on all major browsers. The gem's integration tests are run on Chrome and Firefox.
27
38
 
28
39
  If you find you cannot integrate nicely with SitePrism, please open an
29
40
  [issue request](https://github.com/site-prism/site_prism/issues/new)
@@ -124,6 +135,7 @@ require 'capybara'
124
135
  require 'capybara/cucumber'
125
136
  require 'selenium-webdriver'
126
137
  require 'site_prism'
138
+ require 'site_prism/all_there' # Optional but needed to perform more complex matching
127
139
  ```
128
140
 
129
141
  The driver creation is identical to how you would normally create a Capybara driver,
@@ -135,6 +147,7 @@ Capybara.register_driver :site_prism do |app|
135
147
  Capybara::Selenium::Driver.new(app, browser: browser, desired_capabilities: capabilities)
136
148
  end
137
149
 
150
+ # Then tell Capybara to use the Driver you've just defined as its default driver
138
151
  Capybara.configure do |config|
139
152
  config.default_driver = :site_prism
140
153
  end
@@ -149,6 +162,7 @@ require 'capybara'
149
162
  require 'capybara/rspec'
150
163
  require 'selenium-webdriver'
151
164
  require 'site_prism'
165
+ require 'site_prism/all_there' # Optional but needed to perform more complex matching
152
166
  ```
153
167
 
154
168
  And again, as above, a sample driver is no different to a normal driver instantiation in Capybara.
@@ -295,7 +309,13 @@ expect(@account_page).to be_displayed
295
309
  ```
296
310
 
297
311
  Calling `#displayed?` will return true if the browser's current URL
298
- matches the page's template and false if it doesn't.
312
+ matches the page's template and false if it doesn't. It will wait for
313
+ `Capybara.default_max_wait_time` seconds or you can pass an explicit
314
+ wait time in seconds as the first argument like this:
315
+
316
+ ```ruby
317
+ @account_page.displayed?(10) # wait up to 10 seconds for display
318
+ ```
299
319
 
300
320
  #### Specifying parameter values for templated URLs
301
321
 
@@ -422,8 +442,11 @@ as a string.
422
442
  #### Accessing the individual element
423
443
 
424
444
  The `element` method will add a number of methods to instances of the
425
- particular Page class. The first method to be added is the name of the
426
- element. So using the following example:
445
+ particular Page class. The first method added is the name of the
446
+ element. It finds the element using [Capybara::Node::Finders#find](https://www.rubydoc.info/github/teamcapybara/capybara/master/Capybara/Node/Finders#find-instance_method)
447
+ returning a [Capybara::Node::Element](https://www.rubydoc.info/github/teamcapybara/capybara/master/Capybara/Node/Element) or
448
+ raising [Capybara::ElementNotFound](https://www.rubydoc.info/github/teamcapybara/capybara/master/Capybara/ElementNotFound)
449
+ if the element can not be found.
427
450
 
428
451
  ```ruby
429
452
  class Home < SitePrism::Page
@@ -447,7 +470,9 @@ end
447
470
  #### Testing for the existence of the element
448
471
 
449
472
  Another method added to the Page class by the `element` method is the
450
- `has_<element_name>?` method. Using the same example as above:
473
+ `has_<element_name>?` method.
474
+ This method delegates to [Capybara::Node::Matchers#has_selector?](https://www.rubydoc.info/github/teamcapybara/capybara/master/Capybara/Node/Matchers#has_selector%3F-instance_method).
475
+ Using the same example as above:
451
476
 
452
477
  ```ruby
453
478
  class Home < SitePrism::Page
@@ -477,7 +502,9 @@ end
477
502
 
478
503
  To test that an element does not exist on the page, it is not possible to just call
479
504
  `#not_to have_search_field`. SitePrism supplies the `#has_no_<element>?` method
480
- that should be used to test for non-existence. Using the above example:
505
+ that should be used to test for non-existence.
506
+ 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)
507
+ Using the above example:
481
508
 
482
509
  ```ruby
483
510
  @home = Home.new
@@ -495,9 +522,10 @@ end
495
522
 
496
523
  #### Waiting for an element to become visible
497
524
 
498
- A method that gets added by calling `element` is the
499
- `wait_until_<element_name>_visible` method. Calling this method will
500
- cause the test to wait for Capybara's default wait time for the element
525
+ A method that gets added by calling `element` is the
526
+ `wait_until_<element_name>_visible` method.
527
+ This method delegates to [Capybara::Node::Matchers#has_selector?](https://www.rubydoc.info/github/teamcapybara/capybara/master/Capybara/Node/Matchers#has_selector%3F-instance_method).
528
+ Calling this method will cause the test to wait for Capybara's default wait time for the element
501
529
  to become visible. You can customise the wait time by supplying a number
502
530
  of seconds to wait in-line or configuring the default wait time.
503
531
 
@@ -510,10 +538,11 @@ of seconds to wait in-line or configuring the default wait time.
510
538
  #### Waiting for an element to become invisible
511
539
 
512
540
  Another method added by calling `element` is the
513
- `wait_until_<element_name>_invisible` method. Calling this method will
514
- cause the test to wait for Capybara's default wait time for the element
515
- to become invisible. You can as with the visibility waiter, customise
516
- the wait time in the same way.
541
+ `wait_until_<element_name>_invisible` method.
542
+ 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).
543
+ Calling this method will cause the test to wait for Capybara's default
544
+ wait time for the element to become invisible. You can as with the visibility
545
+ waiter, customise the wait time in the same way.
517
546
 
518
547
  ```ruby
519
548
  @home.wait_until_search_field_invisible
@@ -717,8 +746,8 @@ through them to find out if all of your items are present then you can also do t
717
746
  Simply pass a recursion parameter to the `#all_there?` check. Note that the only valid values
718
747
  for this at the moment are `:none` and `:one`
719
748
 
720
- Passing `:none` in (default), will not change the functionality. However passing in `:one` will cause
721
- site_prism to recurse through all section / sections items defined in your current scope.
749
+ Passing `:none` (default), will not change the functionality. However passing in `:one` will cause
750
+ `site_prism` to recurse through all `section` / `sections` items defined in your present scope.
722
751
 
723
752
  Work alongside developing this functionality further is being continued in the
724
753
  [site_prism-all_there](http://www.github.com/site-prism/site_prism-all_there) repo. So head on over
@@ -727,11 +756,33 @@ there if you're interested in how this feature will work going forwards
727
756
  NB: At the moment a "primitive" but working copy of this is hosted inside this gem. But if you wish to
728
757
  use the bleeding edge version of the logic. Then simply set the following configuration parameter
729
758
 
730
- ```rb
759
+ ```ruby
760
+ `require 'site_prism/all_there'`
761
+
731
762
  SitePrism.use_all_there_gem = true
732
763
  ```
733
764
 
734
- Make sure as well to require the gem code by doing `require 'site_prism/all_there'`
765
+ ### Getting the list of missing elements
766
+
767
+ If `#all_there?` returns false and you wish to get the list of missing elements for debugging purposes
768
+ you may want to use `#elements_missing` method. It will return all missing elements from the expected_elements list
769
+
770
+ If you do not provide a list of `expected_elements` this method will return all elements that are missing on the page;
771
+ from those which are defined.
772
+
773
+ ```ruby
774
+ class Home < SitePrism::Page
775
+ element :name, '#name'
776
+ element :address, '#address'
777
+ element :success_message, 'span.alert-success'
778
+
779
+ expected_elements :name, :address
780
+ end
781
+
782
+ # and... Only `address` is on the page
783
+
784
+ @test_page.elements_missing #=> [:name]
785
+ ```
735
786
 
736
787
  ## Sections
737
788
 
@@ -918,14 +969,13 @@ end
918
969
 
919
970
  ##### Accessing section elements using a block
920
971
 
921
- A Section can be scoped so it is only accessible inside a block. This is
972
+ You can execute a block within the context of a Section. This is
922
973
  similar to Capybara's `within` method and allows for shorter test code
923
- particularly with nested sections. Some of this test code can be
924
- made a little prettier by simply passing a block in.
974
+ particularly with nested sections. Test code that might have to repeat the block name can be shortened up this way.
925
975
 
926
976
  ```ruby
927
977
  Then(/^the home page menu contains a link to the various search functions$/) do
928
- @home.menu do |menu|
978
+ @home.menu.within do |menu|
929
979
  expect(menu).to have_search
930
980
  expect(menu.search['href']).to include('google.com')
931
981
  expect(menu).to have_images
@@ -934,6 +984,16 @@ Then(/^the home page menu contains a link to the various search functions$/) do
934
984
  end
935
985
  ```
936
986
 
987
+ 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.
988
+
989
+ ```ruby
990
+ Then(/^the home page menu contains a link to the various search functions$/) do
991
+ @home.menu do |menu| # possible, but prefer: `@home.menu.within`
992
+ expect(menu).to have_search
993
+ end
994
+ end
995
+ ```
996
+
937
997
  #### Getting a section's parent
938
998
 
939
999
  It is possible to ask a section for its parent (page, or section if this
@@ -1172,7 +1232,7 @@ This allows for pretty tests ...
1172
1232
  ```ruby
1173
1233
  Then(/^there are lots of search_results$/) do
1174
1234
  expect(@results_page.search_results.size).to eq(10)
1175
-
1235
+
1176
1236
  @home.search_results.each do |result|
1177
1237
  expect(result).to have_title
1178
1238
  expect(result.blurb.text).not_to be_empty
@@ -1188,6 +1248,26 @@ element. So if the css selector finds 3 `li` elements, calling
1188
1248
  `search_results` will return an array containing 3 instances of
1189
1249
  `SearchResults`, each with one of the `li` elements as it's root element.
1190
1250
 
1251
+ ##### Accessing Within a Collection of Sections
1252
+
1253
+ 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:
1254
+
1255
+ ```rb
1256
+ @home.search_results.first do |result|
1257
+ # This block is silently ignored.
1258
+ expect(result).to have_title
1259
+ end
1260
+ ```
1261
+ Instead use `within` to access the inner-context of the Section.
1262
+
1263
+ ```rb
1264
+ @home.search_results.first.within do |result|
1265
+ # This block is run within the context of the Section.
1266
+ expect(result).to have_title
1267
+ end
1268
+ ```
1269
+
1270
+
1191
1271
  #### Anonymous Section Collections
1192
1272
 
1193
1273
  You can define collections of anonymous sections the same way you would
@@ -1384,7 +1464,7 @@ instance of the class when created.
1384
1464
 
1385
1465
  ### Skipping load Validations
1386
1466
 
1387
- Defined load validations can be skipped for one `load` call by
1467
+ Defined load validations can be skipped for one `load` call by
1388
1468
  passing in `with_validations: false`.
1389
1469
 
1390
1470
  ```ruby
@@ -1435,7 +1515,7 @@ the validations will be performed in the following order:
1435
1515
  **NB:** `SitePrism::Page` **used to** include a default load validation on
1436
1516
  `page.displayed?` however for v3 this has been removed. It is therefore
1437
1517
  necessary to re-define this if you want to retain the behaviour
1438
- from site_prism v2. See [UPGRADING.md](https://github.com/site-prism/site_prism/blob/master/UPGRADING.md#default-load-validations)
1518
+ from site_prism v2. See [UPGRADING.md](https://github.com/site-prism/site_prism/blob/main/UPGRADING.md#default-load-validations)
1439
1519
  for more info on this.
1440
1520
 
1441
1521
  ## Using Capybara Query Options
@@ -1651,12 +1731,12 @@ as per the code below
1651
1731
  Capybara.configure do |config|
1652
1732
  config.default_max_wait_time = 11 #=> Wait up to 11 seconds for all queries to fail
1653
1733
  # or if you don't want to ever wait
1654
- config.default_max_wait_time = 0 #=> Don't ever wait!
1734
+ config.default_max_wait_time = 0 #=> Don't ever wait!
1655
1735
  end
1656
1736
  ```
1657
1737
 
1658
1738
  Note that even with implicit waits on you can dynamically modify the wait times
1659
- in any SitePrism method to help work-around special circumstances.
1739
+ in any SitePrism method to help work-around special circumstances.
1660
1740
 
1661
1741
  ```ruby
1662
1742
  # Option 1: using wait key assignment
data/lib/site_prism.rb CHANGED
@@ -3,15 +3,20 @@
3
3
  require 'site_prism/error'
4
4
  require 'addressable/template'
5
5
 
6
+ # [SitePrism] namespace
7
+ # We autoload our files underneath here to provide a slightly more optimal load solution
6
8
  module SitePrism
7
9
  autoload :AddressableUrlMatcher, 'site_prism/addressable_url_matcher'
8
- autoload :Deprecator, 'site_prism/deprecator'
9
10
  autoload :DSL, 'site_prism/dsl'
11
+ autoload :Deprecator, 'site_prism/deprecator'
10
12
  autoload :ElementChecker, 'site_prism/element_checker'
11
- autoload :RecursionChecker, 'site_prism/recursion_checker'
13
+ autoload :Loadable, 'site_prism/loadable'
12
14
  autoload :Logger, 'site_prism/logger'
13
15
  autoload :Page, 'site_prism/page'
16
+ autoload :RecursionChecker, 'site_prism/recursion_checker'
17
+ autoload :RspecMatchers, 'site_prism/rspec_matchers'
14
18
  autoload :Section, 'site_prism/section'
19
+ autoload :Timer, 'site_prism/timer'
15
20
  autoload :Waiter, 'site_prism/waiter'
16
21
 
17
22
  class << self
@@ -4,6 +4,10 @@ require 'digest'
4
4
  require 'base64'
5
5
 
6
6
  module SitePrism
7
+ # [SitePrism::AddressableUrlMatcher]
8
+ # Used in a couple of places to allow users to ...
9
+ # Specify patterns for loading webpages
10
+ # Pass in hashable args or query parameters for loading dynamic pages
7
11
  class AddressableUrlMatcher
8
12
  attr_reader :pattern
9
13
 
@@ -43,12 +47,10 @@ module SitePrism
43
47
  def all_expected_mappings_match?(expected_mappings, actual_mappings)
44
48
  expected_mappings.all? do |key, expected_value|
45
49
  actual_value = actual_mappings[key.to_s]
46
- if expected_value.is_a?(Numeric)
47
- actual_value == expected_value.to_s
48
- elsif expected_value.is_a?(Regexp)
49
- actual_value.match(expected_value)
50
- else
51
- expected_value == actual_value
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
52
54
  end
53
55
  end
54
56
  end
@@ -1,8 +1,12 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module SitePrism
4
+ # [SitePrism::Deprecator]
4
5
  class Deprecator
5
6
  class << self
7
+ # @return SitePrism.logger.warn(msg)
8
+ # Tells the user that they are using old functionality, which needs removing in the
9
+ # next major version
6
10
  def deprecate(old, new = nil)
7
11
  if new
8
12
  warn("#{old} is being deprecated and should no longer be used. Use #{new} instead.")
@@ -13,6 +17,13 @@ module SitePrism
13
17
  warn("#{old} will be removed in SitePrism v4. You have been warned!")
14
18
  end
15
19
 
20
+ # @return SitePrism.logger.debug(msg)
21
+ # Tells the user that they are using functionality which is non-optimal
22
+ # The functionality should usually provide a reason for it being poor, as well as an
23
+ # optional way of upgrading to something different
24
+ #
25
+ # NB: As this is bubbled up at debug level, often users will not see this. So it will
26
+ # never be a candidate for removal directly
16
27
  def soft_deprecate(old, reason, new = nil)
17
28
  debug("The #{old} method is changing, as is SitePrism, and is now configurable.")
18
29
  debug("REASON: #{reason}.")
@@ -1,6 +1,13 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module SitePrism
4
+ # [SitePrism::DSL]
5
+ #
6
+ # This is the core Module Namespace for all of the public-facing DSL methods
7
+ # such as `element`. The code here is designed to be used through the defining
8
+ # of said items, and not to be instantiated directly.
9
+ #
10
+ # The whole package here can be thought of as [@api private]
4
11
  module DSL
5
12
  def self.included(klass)
6
13
  klass.extend ClassMethods
@@ -8,9 +15,28 @@ module SitePrism
8
15
 
9
16
  private
10
17
 
11
- # The default waiting time set by Capybara's configuration settings.
12
- def wait_time
13
- Capybara.default_max_wait_time
18
+ # Call `find` inside context set on page/section
19
+ def _find(*find_args)
20
+ kwargs = find_args.pop
21
+ page.find(*find_args, **kwargs)
22
+ end
23
+
24
+ # Call `all` inside context set on page/section
25
+ def _all(*find_args)
26
+ kwargs = find_args.pop
27
+ page.all(*find_args, **kwargs)
28
+ end
29
+
30
+ # Call `has_selector?` inside context set on page/section
31
+ def element_exists?(*find_args)
32
+ kwargs = find_args.pop
33
+ page.has_selector?(*find_args, **kwargs)
34
+ end
35
+
36
+ # Call `has_no_selector?` inside context set on page/section
37
+ def element_does_not_exist?(*find_args)
38
+ kwargs = find_args.pop
39
+ page.has_no_selector?(*find_args, **kwargs)
14
40
  end
15
41
 
16
42
  # Prevent users from calling methods with blocks when they shouldn't be.
@@ -36,6 +62,14 @@ module SitePrism
36
62
  raise SitePrism::UnsupportedBlockError
37
63
  end
38
64
 
65
+ # Warn users from naming the elements starting with no_
66
+ def warn_if_dsl_collision(obj, name)
67
+ return unless name.to_s.start_with?('no_')
68
+
69
+ SitePrism.logger.warn("#{obj.class}##{name} should not start with no_")
70
+ SitePrism::Deprecator.deprecate('Using no_ prefix in DSL definition')
71
+ end
72
+
39
73
  # Sanitize method called before calling any SitePrism DSL method or
40
74
  # meta-programmed method. This ensures that the Capybara query is correct.
41
75
  #
@@ -49,7 +83,7 @@ module SitePrism
49
83
 
50
84
  recombine_args(find_args, runtime_args, options)
51
85
 
52
- return [*find_args, *runtime_args] if options.empty?
86
+ return [*find_args, *runtime_args, {}] if options.empty?
53
87
 
54
88
  [*find_args, *runtime_args, options]
55
89
  end
@@ -60,55 +94,84 @@ module SitePrism
60
94
  #
61
95
  # If the hash is empty, then the hash is omitted from the payload sent
62
96
  # to Capybara, and the find / runtime arguments are sent alone.
97
+ #
98
+ # NB: If the +wait+ key is present in the options hash, even as false or 0, It will
99
+ # be set as the user-supplied value (So user error can be the cause for issues).
63
100
  def recombine_args(find_args, runtime_args, options)
64
101
  options.merge!(find_args.pop) if find_args.last.is_a? Hash
65
102
  options.merge!(runtime_args.pop) if runtime_args.last.is_a? Hash
66
- options[:wait] = wait_time unless wait_key_present?(options)
67
- end
68
-
69
- # Detect if the +wait+ key is present in the options hash.
70
- # Note that setting it to to false or 0, still will return true here.
71
- def wait_key_present?(options)
72
- options.key?(:wait)
103
+ options[:wait] = Capybara.default_max_wait_time unless options.key?(:wait)
73
104
  end
74
105
 
106
+ # SitePrism::DSL::ClassMethods
107
+ # This exposes all of the DSL definitions users will use when generating
108
+ # their POM classes.
109
+ #
110
+ # Many of these methods will be used in-line to allow users to generate a multitude of
111
+ # methods and locators for finding elements / sections on a page or section of a page
75
112
  module ClassMethods
76
113
  attr_reader :expected_items
77
114
 
115
+ # Creates an instance of a SitePrism Element - This will create several methods designed to
116
+ # Locate the element -> @return [Capybara::Node::Element]
117
+ # Check the elements presence or non-presence -> @return [Boolean]
118
+ # Wait for the elements to be present or not -> @return [TrueClass, SitePrism::Error]
119
+ # Validate certain properties about the element
78
120
  def element(name, *find_args)
79
121
  SitePrism::Deprecator.deprecate('Passing a block to :element') if block_given?
80
122
  build(:element, name, *find_args) do
81
123
  define_method(name) do |*runtime_args, &element_block|
124
+ warn_if_dsl_collision(self, name)
82
125
  raise_if_block(self, name, !element_block.nil?, :element)
83
126
  _find(*merge_args(find_args, runtime_args))
84
127
  end
85
128
  end
86
129
  end
87
130
 
131
+ # Creates a enumerable instance of a SitePrism Element - This will create several methods designed to
132
+ # Locate the enumerable element -> @return [Capybara::Result]
133
+ # Check the elements presence or non-presence -> @return [Boolean]
134
+ # Wait for the elements to be present or not -> @return [TrueClass, SitePrism::Error]
135
+ # Validate certain properties about the elements
88
136
  def elements(name, *find_args)
89
137
  SitePrism::Deprecator.deprecate('Passing a block to :elements') if block_given?
90
138
  build(:elements, name, *find_args) do
91
139
  define_method(name) do |*runtime_args, &element_block|
140
+ warn_if_dsl_collision(self, name)
92
141
  raise_if_block(self, name, !element_block.nil?, :elements)
93
142
  _all(*merge_args(find_args, runtime_args))
94
143
  end
95
144
  end
96
145
  end
97
146
 
147
+ # Sets the `expected_items` iVar on a class. This property is used in conjunction with
148
+ # `all_there?` to provide a way of granularising the check made to only interrogate a sub-set
149
+ # of DSL defined items
98
150
  def expected_elements(*elements)
99
151
  @expected_items = elements
100
152
  end
101
153
 
154
+ # Creates an instance of a SitePrism Section - This will create several methods designed to
155
+ # Locate the section -> @return [SitePrism::Section]
156
+ # Check the section presence or non-presence -> @return [Boolean]
157
+ # Wait for the section to be present or not -> @return [TrueClass, SitePrism::Error]
158
+ # Validate certain properties about the section
102
159
  def section(name, *args, &block)
103
160
  section_class, find_args = extract_section_options(args, &block)
104
161
  build(:section, name, *find_args) do
105
162
  define_method(name) do |*runtime_args, &runtime_block|
163
+ warn_if_dsl_collision(self, name)
106
164
  section_element = _find(*merge_args(find_args, runtime_args))
107
165
  section_class.new(self, section_element, &runtime_block)
108
166
  end
109
167
  end
110
168
  end
111
169
 
170
+ # Creates an enumerable instance of a SitePrism Section - This will create several methods designed to
171
+ # Locate the sections -> @return [Array]
172
+ # Check the sections presence or non-presence -> @return [Boolean]
173
+ # Wait for the sections to be present or not -> @return [TrueClass, SitePrism::Error]
174
+ # Validate certain properties about the section
112
175
  def sections(name, *args, &block)
113
176
  section_class, find_args = extract_section_options(args, &block)
114
177
  build(:sections, name, *find_args) do
@@ -135,11 +198,9 @@ module SitePrism
135
198
  end
136
199
 
137
200
  def mapped_items(legacy: true)
138
- if legacy
139
- old_mapped_items
140
- else
141
- new_mapped_items
142
- end
201
+ return old_mapped_items if legacy
202
+
203
+ new_mapped_items
143
204
  end
144
205
 
145
206
  private
@@ -154,13 +215,7 @@ module SitePrism
154
215
  end
155
216
 
156
217
  def new_mapped_items
157
- @new_mapped_items ||= {
158
- element: [],
159
- elements: [],
160
- section: [],
161
- sections: [],
162
- iframe: [],
163
- }
218
+ @new_mapped_items ||= { element: [], elements: [], section: [], sections: [], iframe: [] }
164
219
  end
165
220
 
166
221
  def build(type, name, *find_args)
@@ -181,27 +236,15 @@ module SitePrism
181
236
  def add_helper_methods(name, *find_args)
182
237
  create_existence_checker(name, *find_args)
183
238
  create_nonexistence_checker(name, *find_args)
184
- create_rspec_existence_matchers(name) if defined?(RSpec)
239
+ SitePrism::RspecMatchers.new(name)._create_rspec_existence_matchers if defined?(RSpec)
185
240
  create_visibility_waiter(name, *find_args)
186
241
  create_invisibility_waiter(name, *find_args)
187
242
  end
188
243
 
189
244
  def create_helper_method(proposed_method_name, *find_args)
190
- if find_args.empty?
191
- create_error_method(proposed_method_name)
192
- else
193
- yield
194
- end
195
- end
245
+ return create_error_method(proposed_method_name) if find_args.empty?
196
246
 
197
- def create_rspec_existence_matchers(element_name)
198
- matcher = "has_#{element_name}?"
199
- negated_matcher = "has_no_#{element_name}?"
200
-
201
- RSpec::Matchers.define "have_#{element_name}" do |*args|
202
- match { |actual| actual.public_send(matcher, *args) }
203
- match_when_negated { |actual| actual.public_send(negated_matcher, *args) }
204
- end
247
+ yield
205
248
  end
206
249
 
207
250
  def create_existence_checker(element_name, *find_args)
@@ -250,6 +293,10 @@ module SitePrism
250
293
 
251
294
  def create_error_method(name)
252
295
  SitePrism.logger.error("#{name} has come from an item with no locators.")
296
+ SitePrism::Deprecator.soft_deprecate(
297
+ 'DSL definition with no find_args',
298
+ 'All DSL elements should have find_args'
299
+ )
253
300
  define_method(name) { raise SitePrism::InvalidElementError }
254
301
  end
255
302
 
@@ -285,7 +332,7 @@ module SitePrism
285
332
  def extract_section_options(args, &block)
286
333
  if args.first.is_a?(Class)
287
334
  klass = args.shift
288
- section_class = klass if klass.ancestors.include?(SitePrism::Section)
335
+ section_class = klass if klass <= SitePrism::Section
289
336
  end
290
337
 
291
338
  section_class = deduce_section_class(section_class, &block)
@@ -298,20 +345,23 @@ module SitePrism
298
345
  klass = Class.new(klass || SitePrism::Section, &block) if block_given?
299
346
  return klass if klass
300
347
 
301
- raise ArgumentError, "You should provide descendant of \
302
- SitePrism::Section class or/and a block as the second argument."
348
+ raise ArgumentError, 'You should provide descendant of SitePrism::Section class or/and a block as the second argument.'
303
349
  end
304
350
 
305
351
  def deduce_search_arguments(section_class, args)
306
352
  extract_search_arguments(args) ||
307
353
  extract_search_arguments(section_class.default_search_arguments) ||
308
- raise(ArgumentError, "You should provide search arguments \
309
- in section creation or set_default_search_arguments within section class")
354
+ invalidate_search_arguments!
310
355
  end
311
356
 
312
357
  def extract_search_arguments(args)
313
358
  args if args && !args.empty?
314
359
  end
360
+
361
+ def invalidate_search_arguments!
362
+ SitePrism.logger.error('Could not deduce search_arguments')
363
+ raise(ArgumentError, 'search arguments are needed in `section` definition or alternatively use `set_default_search_arguments`')
364
+ end
315
365
  end
316
366
  end
317
367
  end