site_prism.vcr 0.0.1 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (48) hide show
  1. checksums.yaml +5 -13
  2. data/.travis.yml +1 -0
  3. data/CHANGELOG.md +78 -0
  4. data/Gemfile +2 -0
  5. data/README.md +61 -24
  6. data/TODO.md +28 -40
  7. data/lib/site_prism_vcr/applier.rb +20 -6
  8. data/lib/site_prism_vcr/dsl/adjuster.rb +40 -19
  9. data/lib/site_prism_vcr/dsl/initial_adjuster.rb +1 -1
  10. data/lib/site_prism_vcr/element.rb +8 -5
  11. data/lib/site_prism_vcr/fixture.rb +0 -1
  12. data/lib/site_prism_vcr/options.rb +12 -1
  13. data/lib/site_prism_vcr/patches/element_container.rb +4 -0
  14. data/lib/site_prism_vcr/patches/page.rb +25 -27
  15. data/lib/site_prism_vcr/version.rb +1 -1
  16. data/site_prism.vcr.gemspec +2 -2
  17. data/spec/integration/elements/apply_spec.rb +100 -0
  18. data/spec/integration/elements/events/click_spec.rb +20 -0
  19. data/spec/integration/{immediate_http_interactions/page_load_on_click_spec.rb → pages/custom_event_spec.rb} +5 -3
  20. data/spec/integration/{immediate_http_interactions/page_load_spec.rb → pages/load_spec.rb} +13 -9
  21. data/spec/spec_helper.rb +3 -0
  22. data/spec/support/shared/integration/custom_fixtures.rb +17 -0
  23. data/spec/support/shared/integration/exchange.rb +1 -1
  24. data/spec/support/shared/integration/home_path.rb +1 -1
  25. data/spec/support/shared/integration/waiter.rb +37 -25
  26. data/spec/support/site_prism/pages/home.rb +7 -0
  27. data/spec/support/site_prism/pages/{immediate_http_interactions → page_load}/home_path.rb +1 -1
  28. data/spec/support/site_prism/pages/{immediate_http_interactions → page_load}/one_request.rb +1 -1
  29. data/spec/support/site_prism/pages/{immediate_http_interactions → page_load}/subpage.rb +1 -1
  30. data/spec/support/site_prism/pages/{immediate_http_interactions → page_load}/two_requests.rb +1 -1
  31. data/spec/support/site_prism/pages/{immediate_http_interactions → page_load}/waiter_without_fixtures_ejection.rb +1 -1
  32. data/spec/unit/applier_spec.rb +74 -56
  33. data/spec/unit/dsl/adjuster_spec.rb +58 -47
  34. data/spec/unit/dsl/initial_adjuster_spec.rb +18 -12
  35. data/spec/unit/element_spec.rb +11 -13
  36. data/spec/unit/fixtures/handler_spec.rb +7 -2
  37. data/spec/unit/fixtures/manager_spec.rb +20 -4
  38. data/spec/unit/fixtures/modifiers/home_path_spec.rb +14 -3
  39. data/spec/unit/fixtures/modifiers/path_spec.rb +9 -3
  40. data/spec/unit/fixtures/tmp_keeper_spec.rb +1 -1
  41. data/spec/unit/fixtures_spec.rb +5 -5
  42. data/spec/unit/options_spec.rb +35 -1
  43. data/spec/unit/patches/element_container_spec.rb +25 -12
  44. data/spec/unit/patches/page_spec.rb +23 -30
  45. data/spec/unit/waiter_spec.rb +16 -4
  46. metadata +30 -30
  47. data/spec/integration/http_interactions_on_even/click_spec.rb +0 -75
  48. data/spec/unit/element_container_spec.rb +0 -48
checksums.yaml CHANGED
@@ -1,15 +1,7 @@
1
1
  ---
2
- !binary "U0hBMQ==":
3
- metadata.gz: !binary |-
4
- Y2YwODQ0Y2JlYTZlMTI2YzIyMjA2Y2VhNmNiNDE5YTgwMmY4Y2E1ZQ==
5
- data.tar.gz: !binary |-
6
- YTU3ZWMxMGVkZWIyODA2MmQzZTcxZjZkMmZlNGQzMGI4MWVlNzhiZQ==
2
+ SHA1:
3
+ metadata.gz: bea07665857e88334694b2c69c3d0ded874626cf
4
+ data.tar.gz: 7320da925829386acea9991b1572e0f93a9d0dd4
7
5
  SHA512:
8
- metadata.gz: !binary |-
9
- N2FmY2YxNGYyMTUwZmUzZjg4NDVlNWJhYmZiOWE1OGQyYjgxZDljOGZjNWFh
10
- NTI2MDIyOGNkMjgyZjg1ZDJhODM2ZGMxNjA5M2RjMjc0NjVmNzQwOWNiY2Y0
11
- ZTI4NTA5OThkY2JmOTFhYzliM2IwOTRmYjAxNjJlODA1YjI3NWQ=
12
- data.tar.gz: !binary |-
13
- YjE4MTFlYjE2MmIwOGM5YzJmZGQxMTg5M2RlOTI2ZjQyYjZjYjAyMWNiMDYz
14
- OTlhM2ZhMDgwYzBkYzQ2NzQ3ZDY3YTA5YWI0YzkxOWQ0Njc3ZDU5OTljZDhm
15
- Mjk3MmNlMmY3Y2Q3ZmIyZWMxMTA5NTIxMWNlMWJkMjE4MzY2ZmQ=
6
+ metadata.gz: a7829ce24f5eab5d1a203712c9d38a362b0607af3f1cfd4c1d0c0b12d386f2c9b829ed1e06589940a9a471f7089094f15bf30fee9d8b19d4813d2fe10eb45a8e
7
+ data.tar.gz: 9ad8f2da29c6039106b5a7d03333c88b21cc87950926ab15806df271b1e044e8c6f03bfaf2afd9d042af250d218cf4100465692766f2380663a9450211e66d6d
data/.travis.yml CHANGED
@@ -2,6 +2,7 @@ language: ruby
2
2
  rvm:
3
3
  - 2.0.0
4
4
  - 1.9.3
5
+ - jruby-19mode
5
6
  matrix:
6
7
  allow_failures:
7
8
  - rvm: jruby-19mode
data/CHANGELOG.md ADDED
@@ -0,0 +1,78 @@
1
+ # Version 0.1.0
2
+
3
+ ## Changed
4
+
5
+ * dependencies. Now gem depends on Vcr 2.8.0 and SitePrism 2.5.
6
+ * re-factored the way how Vcr cassettes could be applying for any event of a page.
7
+ Before that change we had to use ugly way
8
+
9
+ ```ruby
10
+ @cars.apply_vcr(-> { page.find('#cars').click }) do
11
+ fixtures ['cars']
12
+ end
13
+ ```
14
+
15
+ now we use chainable way for this purpose
16
+
17
+ ```ruby
18
+ @cars = CarsPage.new
19
+
20
+ @cars.shift_event {
21
+ page.find('#cars').click
22
+ }.apply_vcr do
23
+ fixtures ['cars']
24
+ end
25
+ ```
26
+
27
+ ## Fixed
28
+
29
+ * the issue with defining an action to be done over cassettes in the adjusting block. Now even if an action is defined before a list of cassettes, the adjusting block will be performed properly
30
+
31
+ ```ruby
32
+ @products_page.cars_dropdown.click_and_apply_vcr do
33
+ replace
34
+ fixtures ['cars/ford/prices']
35
+ end
36
+ ```
37
+
38
+ ## Added
39
+
40
+ * possibility to apply Vcr cassettes for any event of an element. [Roman Rott and Dmitriy Nesteryuk]
41
+
42
+ ```ruby
43
+ @products_page.cars_dropdown.shift_event{
44
+ set 'Ford'
45
+ }.apply_vcr do
46
+ fixtures ['cars/ford/prices']
47
+ end
48
+ ```
49
+
50
+ * possibility to link Vcr with already defined elements, it will be helpful in case they are inherited
51
+
52
+ ```ruby
53
+ class CarsPage < TransportPage
54
+ link_vcr_with_element :transport_details_link do
55
+ fixtures ['cars/ford']
56
+ end
57
+ end
58
+
59
+ @page = CarsPage.new
60
+ @page.transport_details_link.click_and_apply_vcr
61
+ ```
62
+
63
+ * possibility to redefine default options for a default waiter
64
+
65
+ ```ruby
66
+ class ProductsPage < SitePrism::Page
67
+ link_vcr_with_element :details_link do
68
+ fixtures ['cars/ford']
69
+
70
+ waiter(eject_cassettes: false) { self.wait_until_loading_indicator_invisible } # default waiter with options
71
+ end
72
+ end
73
+
74
+ @page = ProductsPage.new
75
+ @page.details_link.click_and_apply_vcr do
76
+ waiter_options(eject_cassettes: true) # redefines default options
77
+ end
78
+ ```
data/Gemfile CHANGED
@@ -8,9 +8,11 @@ group :development do
8
8
  gem 'sinatra'
9
9
  gem 'httpi'
10
10
  gem 'capybara-firebug'
11
+ gem 'sandi_meter'
11
12
  end
12
13
 
13
14
  group :test do
15
+ gem 'rspec-fire'
14
16
  gem 'selenium-webdriver'
15
17
  gem 'coveralls', require: false
16
18
  end
data/README.md CHANGED
@@ -1,21 +1,21 @@
1
1
  # SitePrism.Vcr
2
2
 
3
3
  [![Code Climate](https://codeclimate.com/github/nestd/site_prism.vcr.png)](https://codeclimate.com/github/nestd/site_prism.vcr)
4
- [![Build Status](https://secure.travis-ci.org/nestd/site_prism.vcr.png?branch=master)](https://travis-ci.org/nestd/site_prism.vcr)
5
- [![Coverage Status](https://coveralls.io/repos/nestd/site_prism.vcr/badge.png)](https://coveralls.io/r/nestd/site_prism.vcr)
6
- [![Dependency Status](https://gemnasium.com/nestd/site_prism.vcr.png)](https://gemnasium.com/nestd/site_prism.vcr)
4
+ [![Build Status](https://secure.travis-ci.org/dnesteryuk/site_prism.vcr.png?branch=master)](https://travis-ci.org/dnesteryuk/site_prism.vcr)
5
+ [![Coverage Status](https://coveralls.io/repos/dnesteryuk/site_prism.vcr/badge.png)](https://coveralls.io/r/dnesteryuk/site_prism.vcr)
6
+ [![Dependency Status](https://gemnasium.com/dnesteryuk/site_prism.vcr.png)](https://gemnasium.com/dnesteryuk/site_prism.vcr)
7
7
 
8
8
  The purpose of this gem is to give an easy way for integrating [SitePrism](https://github.com/natritmeyer/site_prism) (it is Page Object Model DSL for Capybara) and [VCR](https://github.com/vcr/vcr) (it is a powerful tool for recording and stubbing HTTP interactions).
9
9
 
10
- Such integration allows you to write acceptance tests more easily since you receive handy tool for managing VCR cassettes. Those cassettes can be easily linked with SitePrism elements (in fact, Capybara elements since SitePrism doesn't have own elements). Afterwards those linked cassettes can be used for stubbing external API responses while clicking on an element that cassettes are defined for.
10
+ Such integration allows you to write acceptance tests more easily since you receive handy tool for managing VCR cassettes. Those cassettes can be easily linked with SitePrism elements (in fact, Capybara elements since SitePrism doesn't have own elements). Afterwards those linked cassettes can be used for stubbing external API responses while doing actions (click, change etc) over an element that cassettes are defined for.
11
11
 
12
12
  ## Features
13
13
 
14
14
  * Links VCR cassettes with SitePrism elements.
15
15
  * Links VCR cassettes with SitePrism pages.
16
- * Applies VCR cassettes while clicking on an element.
17
- * Applies VCR cassettes while loading a page.
18
- * Defines a waiter which will be used for waiting until an expected element is on a page or until an expected element has disappeared from a page (It is very helpful when a few external API requests are being executed after clicking on an element).
16
+ * Applies VCR cassettes on any event (click, change, blur etc).
17
+ * Applies VCR cassettes on page loading.
18
+ * Defines a waiter which will be used for waiting until an expected element is on a page or until an expected element has disappeared from a page (It is very helpful when a few external API requests are being executed after raising an event).
19
19
  * Allows to redefine default VCR cassettes (cassettes which were specified while describing a SitePrism element or a SitePrism page).
20
20
  * Allows to redefine a default waiter (a waiter which was specified while describing a SitePrism element or a SitePrism page).
21
21
 
@@ -51,6 +51,20 @@ end
51
51
 
52
52
  `fixtures` helper method is used for defining VCR cassettes. All cassettes are taken from a path which you have defined in `cassette_library_dir` configuration option of VCR. Please, refer to [documentation](https://relishapp.com/vcr/vcr/v/2-5-0/docs/configuration/cassette-library-dir) of VCR to get more info about configuration options.
53
53
 
54
+ You can specify cassettes for already defined elements, for example, your page inherits another one:
55
+
56
+ ```ruby
57
+ class TransportPage < SitePrism::Page
58
+ element :transport_details_link, '#car_details'
59
+ end
60
+
61
+ class CarsPage < TransportPage
62
+ link_vcr_with_element :transport_details_link do
63
+ fixtures ['cars/ford']
64
+ end
65
+ end
66
+ ```
67
+
54
68
  #### Path helper method
55
69
 
56
70
  In case you have a lot of cassettes which are stored in some subdirectory, there is more better way for defining cassettes:
@@ -66,7 +80,8 @@ class ProductsPage < SitePrism::Page
66
80
  end
67
81
  ```
68
82
 
69
- The `path` helper method can be used a few times in a block to define cassettes. The code above is identical to:
83
+ The `path` helper method can be used a few times in a block to define cassettes.
84
+ The code above is identical to:
70
85
 
71
86
  ```ruby
72
87
  class ProductsPage < SitePrism::Page
@@ -100,7 +115,7 @@ class ProductsPage < SitePrism::Page
100
115
  end
101
116
  ```
102
117
 
103
- If some fixture name begins with `~/`, it means that a defined home path will be applied to find such fixture. The previous example is identical to this one:
118
+ If some cassette name begins with `~/`, it means that a defined home path will be applied to find such cassette. The previous example is identical to this one:
104
119
 
105
120
  ```ruby
106
121
  class ProductsPage < SitePrism::Page
@@ -134,7 +149,7 @@ end
134
149
 
135
150
  ### Applying VCR cassettes on click
136
151
 
137
- Now cassettes can be applied only on a click event:
152
+ Cassettes can be applied on a click event:
138
153
 
139
154
  ```ruby
140
155
  @products_page.car_details_link.click_and_apply_vcr
@@ -229,7 +244,7 @@ end
229
244
 
230
245
  ### Waiters
231
246
 
232
- Waiters are very important part of this gem (actually, waiters are part of SitePrism gem, but they are used widely here). When we do some action and that action causes a few HTTP interactions we have to wait for a result of them, before expecting something on a page. The good approach is to wait for some visibility or invisibility of an element. For example, you have a list of products when you click on a button to show details of some product, you may wait until loading indicator which may be shown on a details page of a product disappears. Capybara already waits for an element to appear, but it hasn't any possibility to wait for invisibility of an element, SitePrism has this capability and it is very useful.
247
+ Waiters are very important part of this gem (actually, waiters are part of SitePrism gem, but they are used widely here). When we do some action and that action causes a few HTTP interactions we have to wait for a result of them before expecting something on a page. The good approach is to wait for some visibility or invisibility of an element. For example, you have a list of products when you click on a button to show details of some product, you may wait until loading indicator which may be shown on a details page of a product disappears. Capybara already waits for an element to appear, but it hasn't any possibility to wait for invisibility of an element, SitePrism has this capability and it is very useful.
233
248
 
234
249
  There is reason why you should use them when you use SitePrism.Vcr. If you specify a waiter while describing SitePrism elements or applying VCR cassettes, SitePrism.Vcr will know when the inserted cassettes should be ejected from Vcr to avoid a situation when some unexpected cassette is applied.
235
250
 
@@ -292,6 +307,36 @@ end
292
307
 
293
308
  The same thing can be defined for a default waiter.
294
309
 
310
+ In case you need to change only options defined for a default waiter, but you don't need to change a waiter, you can use `waiter_options` helper method:
311
+
312
+ ```ruby
313
+ @products_page.car_details_link.click_and_apply_vcr do
314
+ waiter_options(eject_cassettes: false)
315
+ end
316
+ ```
317
+
318
+ ### Applying VCR cassettes on any event
319
+
320
+ There may be a situation when you need to apply cassettes for some custom event rather than for a click event. It may be a change event for a select box or a drag-and-drop event for a list or a blur event for an input element. SitePrism.Vcr gem provides a way to archive such goal:
321
+
322
+ ```ruby
323
+ @products_page.cars_dropdown.shift_event{
324
+ set 'Ford'
325
+ }.apply_vcr # uses default fixtures defined for this element
326
+ ```
327
+
328
+ or if you need to use another cassettes:
329
+
330
+ ```ruby
331
+ @products_page.cars_dropdown.shift_event{
332
+ set 'Ford'
333
+ }.apply_vcr do
334
+ fixtures ['cars/ford/prices']
335
+ end
336
+ ```
337
+
338
+ The block which is passed to `shift_event` method is executed in a context of an element, it means any method of [Capybara::Node::Element](http://rubydoc.info/github/jnicklas/capybara/master/Capybara/Node/Element) object can be used there. Similar to `click_and_apply_vcr` method, you can override cassettes, add new cassettes, use `path` helper method while applying cassettes and `home_path` helper method specified while defining a SitePrism element.
339
+
295
340
  ### Linking and applying VCR cassettes with SitePrism pages
296
341
 
297
342
  External HTTP interactions may be done on page loading as well. This gem supports capability to apply Vcr cassettes on page loading. To define default cassettes you have to use `vcr_options_for_load` class method:
@@ -306,7 +351,7 @@ end
306
351
 
307
352
  Everything described above about defining cassettes for SitePrism elements is true for defining cassettes for pages.
308
353
 
309
- Applying cassettes is almost the same as we saw for a click event:
354
+ Applying cassettes is almost the same as you saw for a click event:
310
355
 
311
356
  ```ruby
312
357
  page.load_and_apply_vcr do
@@ -332,18 +377,6 @@ In this case, SitePrism will alter an url and it will look like:
332
377
  http://localhost/cats/tom
333
378
  ```
334
379
 
335
- There may be situation when we need to apply fixtures for page loading when an user clicks on a link (an user moves from one page to another one). In this case you can use `apply_vcr` method of a page object:
336
-
337
- ```ruby
338
- @cars = CarsPage.new
339
-
340
- @cars.apply_vcr(-> { page.find('#cars').click }) do
341
- fixtures ['cars']
342
- end
343
- ```
344
-
345
- The first argument passed to this method should be a proc object which will do an action. As you can see while applying fixtures without actual loading a page you can use everything what is described for `load_and_apply_vcr` method.
346
-
347
380
  ### Using Vcr options for cassettes
348
381
 
349
382
  Vcr provides number of options which can be used for cassettes. For example, you may [pass ERB into cassettes](https://relishapp.com/vcr/vcr/v/2-5-0/docs/cassettes/dynamic-erb-cassettes). This gem doesn't bother you use any options for Vcr cassettes. If you want to do so, you have to use a hash instead of a cassette name:
@@ -368,6 +401,10 @@ It works with any kind of helper methods where you list names of cassettes, even
368
401
  end
369
402
  ```
370
403
 
404
+ ## Examples
405
+
406
+ The simple example of using this gem you can find [here](https://github.com/dnesteryuk/site_prism.vcr_example)
407
+
371
408
  ## Contributing
372
409
 
373
410
  1. Fork it
data/TODO.md CHANGED
@@ -1,37 +1,30 @@
1
1
  # TODO
2
2
 
3
- ## Release 0.0.1
4
-
5
- 1. Add comments to code and review existing comments.
6
-
7
- ## Release 0.0.2
8
-
9
- 1. Think about adding more integration tests
10
- 2. Pages and elements should inherit fixtures defined for their parents
11
- 3. Add possibility to add fixtures for existing elements, it will be helpful in case they are inherited
12
- 4. Think about applying fixtures for any kind of events, for example, for a change event of select boxes
13
- 5. Think how to manage the situation when a method name and a block is passed to the `waiter` helper method
14
- 6. When we eject fixtures from Vcr we should eject only fixtures inserted into Vcr by one specific fixtures manager (See SPV#eject)
15
- 7. Make this gem working on JRuby
16
- 8. Give possibility to define options for a waiter instead of redefining a whole waiter in a subclass
17
- 9. Turn this code:
18
-
19
- ```ruby
20
- @cars.apply_vcr(-> { page.find('#cars').click }) do
21
- fixtures ['cars']
22
- end
23
- ```
24
-
25
- into
3
+ ## Release 0.1.1
4
+
5
+ 1. Change integration tests to use real data.
6
+ 2. Think how to avoid monkey patching to add stuffs to SitePrism
7
+ 3. SPV::Applier#apply_vcr should be refactored, it is too complex
8
+ 4. Think about renaming current integration tests on acceptance tests and create new integration tests which will test integration between classes without involving a browser. It will solve a lot of issues with shared tests to check the same things for pages and elements. In acceptance tests we will test very basic stuffs.
9
+ 5. We should freeze an instance of SPV::Fixtures to make sure it is not mutable, otherwise, there may be situation when default fixtures will be corrupted.
10
+ 6. We should disable double defining actions in the adjusting block:
11
+
12
+ ```ruby
13
+ self.some_link.click_and_apply_vcr do
14
+ fixtures ['test', 'test2']
15
+ union
16
+ fixtures ['test3']
17
+ replace
18
+ end
19
+ ```
20
+ It will lead to mess.
26
21
 
27
- ```ruby
28
- @cars.shift_event{ page.find('#cars').click }.apply_vcr do
29
- fixtures ['cars']
30
- end
31
- ```
22
+ ## Release 0.2.0
32
23
 
33
- 10. Think about creating set of fixtures which can be exchanged by a name of set. It will be very helpful when you have to exchange a set of fixtures.
34
- 11. Think how to avoid monkey patching to add stuffs to SitePrism
24
+ 1. Pages and elements should inherit fixtures defined for their parents
25
+ 2. When we eject fixtures from Vcr we should eject only fixtures inserted into Vcr by one specific fixtures manager (See SPV#eject)
26
+ 3. Make this gem working on JRuby (since we eject all VCR cassettes, it may be not thread safe)
27
+ 4. Think about creating set of fixtures which can be exchanged by a name of set. It will be very helpful when you have to exchange a set of fixtures.
35
28
 
36
29
  ## Should be implemented?
37
30
 
@@ -54,18 +47,13 @@ end
54
47
 
55
48
  will use previously defined fixtures
56
49
 
57
- 2. There should be possibility to change default fixtures:
58
-
59
- ```ruby
60
- self.confirm_btn.vcr do
61
- path 'products', ['tomato', 'fruit/apple']
62
- path 'goods', 'cars'
63
-
64
- force_replace
65
- end
66
- ```
67
50
 
68
51
  ## Things to think over
69
52
 
70
53
  1. Should we add the integration tests for page load to make sure 2 HTTP requests will be handled properly?
71
54
  2. Should we add own integration tests to test the path helper method?
55
+ 3. Should we add a test for testing to HTTP requests on page load?
56
+ 4. Should be Options class immutable?
57
+ 5. May be it makes sense to separately keep path from the name of a fixture? See SPV::Fixture class
58
+
59
+
@@ -2,6 +2,8 @@ module SPV
2
2
  # This class manages defining default fixtures
3
3
  # and applying them on an event.
4
4
  class Applier
5
+ class EventError < StandardError; end
6
+
5
7
  def initialize(node, &block)
6
8
  @node, @options = node, Options.new
7
9
  adjuster = DSL::InitialAdjuster.new(@options)
@@ -10,11 +12,17 @@ module SPV
10
12
  adjuster.instance_eval &block
11
13
  end
12
14
 
13
- @fixtures = adjuster.prepared_fixtures
15
+ @fixtures = adjuster.prepare_fixtures
14
16
 
15
17
  @fixtures_manager = Fixtures::Manager.new(@options)
16
18
  end
17
19
 
20
+ def shift_event(&block)
21
+ @event_action = block
22
+
23
+ self
24
+ end
25
+
18
26
  # Applies fixtures to be used for stubbing HTTP interactions
19
27
  # caused by an event (click on an element or page loading).
20
28
  #
@@ -26,7 +34,13 @@ module SPV
26
34
  # and @see SPV::DSL::Adjuster)
27
35
  #
28
36
  # @return [void]
29
- def apply(adjusting_block = nil)
37
+ def apply_vcr(&block)
38
+ if @event_action.nil?
39
+ raise EventError.new(
40
+ 'Event is not shifted, before applying Vcr you have to shift event with "shift_event" method'
41
+ )
42
+ end
43
+
30
44
  options = @options.clone_options
31
45
 
32
46
  adjuster = DSL::Adjuster.new(
@@ -34,13 +48,13 @@ module SPV
34
48
  @fixtures
35
49
  )
36
50
 
37
- if adjusting_block
38
- adjuster.instance_eval &adjusting_block
51
+ if block_given?
52
+ adjuster.instance_eval &block
39
53
  end
40
54
 
41
- @fixtures_manager.inject(adjuster.prepared_fixtures)
55
+ @fixtures_manager.inject(adjuster.prepare_fixtures)
42
56
 
43
- yield
57
+ @event_action.call
44
58
 
45
59
  @waiter = Waiter.new(
46
60
  @node,
@@ -7,26 +7,45 @@ module SPV
7
7
  super options
8
8
 
9
9
  @options, @fixtures = options, fixtures
10
+ @action = :replace
10
11
  end
11
12
 
12
- # Replaces default fixtures with a set of fixtures
13
- # defined in a block passed while applying fixtures.
13
+ # Defines the replace action as an action which
14
+ # will be performed over cassettes while adjusting cassettes.
15
+ #
16
+ # Example:
17
+ # @page.details_link.click_and_apply_vcr do
18
+ # fixtures ['no_found']
19
+ # replace
20
+ # end
21
+ #
22
+ # In this case 'no_found' cassette will be used instead
23
+ # of default cassettes defined for 'details_link'.
14
24
  #
15
25
  # @return [void]
16
26
  #
17
27
  # @api public
18
28
  def replace
19
- change_fixtures :replace
29
+ @action = :replace
20
30
  end
21
31
 
22
- # Joins default fixtures with a set of fixtures
23
- # defined in a block passed while applying fixtures.
32
+ # Defines the union action as an action which
33
+ # will be performed over cassettes while adjusting cassettes.
34
+ #
35
+ # Example:
36
+ # @page.details_link.click_and_apply_vcr do
37
+ # fixtures ['no_found']
38
+ # union
39
+ # end
40
+ #
41
+ # In this case 'no_found' cassette will be used a long with
42
+ # default cassettes.
24
43
  #
25
44
  # @return [void]
26
45
  #
27
46
  # @api public
28
47
  def union
29
- change_fixtures :union
48
+ @action = :union
30
49
  end
31
50
 
32
51
  # Exchanges certain default fixtures with another fixtures.
@@ -57,26 +76,28 @@ module SPV
57
76
  )
58
77
  end
59
78
 
79
+ # Redefines default waiter options or if default waiter options is not defined,
80
+ # it defines new options for a waiter. This method doesn't redefine all default options,
81
+ # it redefines only options passed in a hash.
82
+ #
83
+ # @param options [Hash] Options for a waiter
84
+ #
85
+ # @return [void]
86
+ #
87
+ # @api public
88
+ def waiter_options(options)
89
+ @options.merge_waiter_options!(options)
90
+ end
91
+
60
92
  # Performs the replace action when no explicit action is defined
61
93
  # in a block for manipulating fixtures before applying them.
62
94
  #
63
95
  # @return [SPV::Fixtures] A set of prepared fixtures.
64
96
  #
65
97
  # @api public
66
- def prepared_fixtures
67
- # If no action has been performed,
68
- # it should be performed manually, before allowing
69
- # to get prepared fixtures.
70
- replace unless @is_action_done # TODO: do something with this logic, it looks ugly
71
- @fixtures
98
+ def prepare_fixtures
99
+ @fixtures.public_send(@action, @tmp_keeper.fixtures)
72
100
  end
73
-
74
- private
75
- def change_fixtures(action)
76
- @fixtures = @fixtures.public_send(action, @tmp_keeper.fixtures)
77
- @tmp_keeper.clean_fixtures
78
- @is_action_done = true
79
- end
80
101
  end # class Adjuster
81
102
  end # module DSL
82
103
  end # module SPV
@@ -89,7 +89,7 @@ module SPV
89
89
  # @return [SPV::Fixtures] A set of prepared fixtures.
90
90
  #
91
91
  # @api public
92
- def prepared_fixtures
92
+ def prepare_fixtures
93
93
  Fixtures.new(@tmp_keeper.fixtures)
94
94
  end
95
95
  end # class InitialAdjuster
@@ -1,18 +1,21 @@
1
1
  require 'delegate'
2
+ require 'forwardable'
2
3
 
3
4
  module SPV
4
5
  # Extends a native Capybara element with new methods.
5
6
  class Element < SimpleDelegator
7
+ extend Forwardable
8
+
9
+ def_delegator :@applier, :shift_event
10
+
6
11
  def initialize(element, parent, &block)
7
12
  super element
8
13
 
9
14
  @applier = Applier.new(parent, &block)
10
15
  end
11
16
 
12
- def click_and_apply_vcr(&adjusting_block)
13
- @applier.apply(adjusting_block) do
14
- click
15
- end
17
+ def click_and_apply_vcr(&block)
18
+ shift_event { click }.apply_vcr(&block)
16
19
  end
17
20
  end
18
- end
21
+ end
@@ -4,7 +4,6 @@ module SPV
4
4
  class Fixture
5
5
  attr_accessor :name, :options
6
6
 
7
- # TODO: may be it makes sense to separately keep path from the name of a fixture?
8
7
  def initialize(name, vcr_options = {})
9
8
  @name, @options = name, vcr_options
10
9
  end
@@ -1,4 +1,3 @@
1
- # TODO: should be this class immutable?
2
1
  module SPV
3
2
  class Options
4
3
  attr_accessor :waiter, :waiter_options, :home_path
@@ -18,5 +17,17 @@ module SPV
18
17
  def clone_options
19
18
  dup
20
19
  end
20
+
21
+ def waiter_options
22
+ @waiter_options || {}
23
+ end
24
+
25
+ # Merges already defined waiter's options with a given hash.
26
+ #
27
+ # If waiter's options are not defined yet, it will define waiter options
28
+ # with a given hash.
29
+ def merge_waiter_options!(options)
30
+ self.waiter_options = self.waiter_options.merge(options)
31
+ end
21
32
  end
22
33
  end
@@ -2,6 +2,10 @@ module SitePrism::ElementContainer
2
2
  def element_with_vcr(element_name, *args, &block)
3
3
  element element_name, *args
4
4
 
5
+ link_vcr_with_element(element_name, &block)
6
+ end
7
+
8
+ def link_vcr_with_element(element_name, &block)
5
9
  origin_element_name = "origin_#{element_name}"
6
10
 
7
11
  alias_method origin_element_name, element_name
@@ -1,41 +1,39 @@
1
+ require 'forwardable'
2
+
1
3
  module SitePrism
2
4
  class Page
3
- # TODO: it should make sure this method does not a native method of SitePrism::Page class
4
- def self.inherited(subclass)
5
- # This code is required to allow subpages to inherit
6
- # a defined adjuster block. Otherwise, that block should be
7
- # duplicated in a subpage as well.
8
- subclass.instance_variable_set(:@vcr_adjuster, @vcr_adjuster)
9
- end
5
+ extend Forwardable
10
6
 
11
- def self.vcr_options_for_load(&block)
12
- @vcr_adjuster = block
13
- end
7
+ def_delegator :@applier, :shift_event
14
8
 
15
- def self.vcr_adjuster
16
- @vcr_adjuster
17
- end
9
+ class << self
10
+ def inherited(subclass)
11
+ # This code is required to allow subpages to inherit
12
+ # a defined adjuster block. Otherwise, that block should be
13
+ # duplicated in a subpage as well.
14
+ subclass.instance_variable_set(:@vcr_adjuster, @vcr_adjuster)
15
+ end
18
16
 
19
- def apply_vcr(*args, action_block, &adjusting_block)
20
- applier = SPV::Applier.new(
21
- self,
22
- &self.class.vcr_adjuster
23
- )
17
+ def vcr_options_for_load(&block)
18
+ @vcr_adjuster = block
19
+ end
24
20
 
25
- applier.apply(
26
- adjusting_block
27
- ) do
28
- action_block.call
21
+ def vcr_adjuster
22
+ @vcr_adjuster
29
23
  end
30
24
  end
31
25
 
32
- def load_and_apply_vcr(*args, &adjusting_block)
33
- action_block = proc { load(*args) }
26
+ def initialize(*args)
27
+ super
34
28
 
35
- apply_vcr(
36
- action_block,
37
- &adjusting_block
29
+ @applier = SPV::Applier.new(
30
+ self,
31
+ &self.class.vcr_adjuster
38
32
  )
39
33
  end
34
+
35
+ def load_and_apply_vcr(*args, &block)
36
+ shift_event { load(*args) }.apply_vcr(&block)
37
+ end
40
38
  end
41
39
  end