site_prism.vcr 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +15 -0
- data/.gitignore +17 -0
- data/.rspec +2 -0
- data/.travis.yml +12 -0
- data/Gemfile +17 -0
- data/LICENSE.txt +22 -0
- data/README.md +381 -0
- data/Rakefile +1 -0
- data/TODO.md +71 -0
- data/lib/site_prism.vcr.rb +1 -0
- data/lib/site_prism_vcr/applier.rb +54 -0
- data/lib/site_prism_vcr/dsl/adjuster.rb +82 -0
- data/lib/site_prism_vcr/dsl/initial_adjuster.rb +97 -0
- data/lib/site_prism_vcr/element.rb +18 -0
- data/lib/site_prism_vcr/fixture.rb +29 -0
- data/lib/site_prism_vcr/fixtures/converter.rb +17 -0
- data/lib/site_prism_vcr/fixtures/handler.rb +31 -0
- data/lib/site_prism_vcr/fixtures/manager.rb +38 -0
- data/lib/site_prism_vcr/fixtures/modifiers/home_path.rb +27 -0
- data/lib/site_prism_vcr/fixtures/modifiers/path.rb +30 -0
- data/lib/site_prism_vcr/fixtures/tmp_keeper.rb +21 -0
- data/lib/site_prism_vcr/fixtures.rb +41 -0
- data/lib/site_prism_vcr/options.rb +22 -0
- data/lib/site_prism_vcr/options_with_path.rb +7 -0
- data/lib/site_prism_vcr/patches/element_container.rb +15 -0
- data/lib/site_prism_vcr/patches/page.rb +41 -0
- data/lib/site_prism_vcr/vcr_helpers.rb +18 -0
- data/lib/site_prism_vcr/version.rb +3 -0
- data/lib/site_prism_vcr/waiter.rb +23 -0
- data/lib/site_prism_vcr.rb +24 -0
- data/site_prism.vcr.gemspec +24 -0
- data/spec/fixtures/arya_stark.yml +44 -0
- data/spec/fixtures/custom/blank.yml +44 -0
- data/spec/fixtures/custom/bran_stark.yml +44 -0
- data/spec/fixtures/custom/daenerys_targaryen.yml +44 -0
- data/spec/fixtures/jon_snow.yml +44 -0
- data/spec/fixtures/ned_stark.yml +44 -0
- data/spec/fixtures/robb_stark.yml +44 -0
- data/spec/integration/http_interactions_on_even/click_spec.rb +75 -0
- data/spec/integration/immediate_http_interactions/page_load_on_click_spec.rb +18 -0
- data/spec/integration/immediate_http_interactions/page_load_spec.rb +56 -0
- data/spec/spec_helper.rb +18 -0
- data/spec/spec_integration_helper.rb +27 -0
- data/spec/support/shared/integration/custom_fixtures.rb +32 -0
- data/spec/support/shared/integration/exchange.rb +42 -0
- data/spec/support/shared/integration/home_path.rb +49 -0
- data/spec/support/shared/integration/waiter.rb +75 -0
- data/spec/support/site_prism/pages/base.rb +18 -0
- data/spec/support/site_prism/pages/home.rb +44 -0
- data/spec/support/site_prism/pages/immediate_http_interactions/home_path.rb +15 -0
- data/spec/support/site_prism/pages/immediate_http_interactions/one_request.rb +13 -0
- data/spec/support/site_prism/pages/immediate_http_interactions/subpage.rb +7 -0
- data/spec/support/site_prism/pages/immediate_http_interactions/two_requests.rb +12 -0
- data/spec/support/site_prism/pages/immediate_http_interactions/waiter_without_fixtures_ejection.rb +12 -0
- data/spec/support/site_prism/sections/console_block.rb +8 -0
- data/spec/support/test_app/public/jquery.min.js +5 -0
- data/spec/support/test_app/public/test.js +44 -0
- data/spec/support/test_app/test_app.rb +46 -0
- data/spec/support/test_app/views/index.erb +26 -0
- data/spec/unit/applier_spec.rb +134 -0
- data/spec/unit/dsl/adjuster_spec.rb +141 -0
- data/spec/unit/dsl/initial_adjuster_spec.rb +166 -0
- data/spec/unit/element_container_spec.rb +48 -0
- data/spec/unit/element_spec.rb +47 -0
- data/spec/unit/fixture_spec.rb +45 -0
- data/spec/unit/fixtures/converter_spec.rb +36 -0
- data/spec/unit/fixtures/handler_spec.rb +72 -0
- data/spec/unit/fixtures/manager_spec.rb +58 -0
- data/spec/unit/fixtures/modifiers/home_path_spec.rb +47 -0
- data/spec/unit/fixtures/modifiers/path_spec.rb +45 -0
- data/spec/unit/fixtures/tmp_keeper_spec.rb +17 -0
- data/spec/unit/fixtures_spec.rb +76 -0
- data/spec/unit/options_spec.rb +41 -0
- data/spec/unit/patches/element_container_spec.rb +48 -0
- data/spec/unit/patches/page_spec.rb +57 -0
- data/spec/unit/vcr_helpers_spec.rb +18 -0
- data/spec/unit/waiter_spec.rb +67 -0
- metadata +213 -0
checksums.yaml
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
---
|
2
|
+
!binary "U0hBMQ==":
|
3
|
+
metadata.gz: !binary |-
|
4
|
+
Y2YwODQ0Y2JlYTZlMTI2YzIyMjA2Y2VhNmNiNDE5YTgwMmY4Y2E1ZQ==
|
5
|
+
data.tar.gz: !binary |-
|
6
|
+
YTU3ZWMxMGVkZWIyODA2MmQzZTcxZjZkMmZlNGQzMGI4MWVlNzhiZQ==
|
7
|
+
SHA512:
|
8
|
+
metadata.gz: !binary |-
|
9
|
+
N2FmY2YxNGYyMTUwZmUzZjg4NDVlNWJhYmZiOWE1OGQyYjgxZDljOGZjNWFh
|
10
|
+
NTI2MDIyOGNkMjgyZjg1ZDJhODM2ZGMxNjA5M2RjMjc0NjVmNzQwOWNiY2Y0
|
11
|
+
ZTI4NTA5OThkY2JmOTFhYzliM2IwOTRmYjAxNjJlODA1YjI3NWQ=
|
12
|
+
data.tar.gz: !binary |-
|
13
|
+
YjE4MTFlYjE2MmIwOGM5YzJmZGQxMTg5M2RlOTI2ZjQyYjZjYjAyMWNiMDYz
|
14
|
+
OTlhM2ZhMDgwYzBkYzQ2NzQ3ZDY3YTA5YWI0YzkxOWQ0Njc3ZDU5OTljZDhm
|
15
|
+
Mjk3MmNlMmY3Y2Q3ZmIyZWMxMTA5NTIxMWNlMWJkMjE4MzY2ZmQ=
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/.travis.yml
ADDED
data/Gemfile
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
source 'https://rubygems.org'
|
2
|
+
|
3
|
+
# Specify your gem's dependencies in site_prism.vcr.gemspec
|
4
|
+
gemspec
|
5
|
+
|
6
|
+
group :development do
|
7
|
+
gem 'rspec', '~> 2.14.1'
|
8
|
+
gem 'sinatra'
|
9
|
+
gem 'httpi'
|
10
|
+
gem 'capybara-firebug'
|
11
|
+
end
|
12
|
+
|
13
|
+
group :test do
|
14
|
+
gem 'selenium-webdriver'
|
15
|
+
gem 'coveralls', require: false
|
16
|
+
end
|
17
|
+
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2013 Dmitriy Nesteryuk
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,381 @@
|
|
1
|
+
# SitePrism.Vcr
|
2
|
+
|
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)
|
7
|
+
|
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
|
+
|
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.
|
11
|
+
|
12
|
+
## Features
|
13
|
+
|
14
|
+
* Links VCR cassettes with SitePrism elements.
|
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).
|
19
|
+
* Allows to redefine default VCR cassettes (cassettes which were specified while describing a SitePrism element or a SitePrism page).
|
20
|
+
* Allows to redefine a default waiter (a waiter which was specified while describing a SitePrism element or a SitePrism page).
|
21
|
+
|
22
|
+
## Installation
|
23
|
+
|
24
|
+
Add this line to your application's Gemfile:
|
25
|
+
|
26
|
+
gem 'site_prism.vcr'
|
27
|
+
|
28
|
+
And then execute:
|
29
|
+
|
30
|
+
$ bundle install
|
31
|
+
|
32
|
+
Or install it yourself as:
|
33
|
+
|
34
|
+
$ gem install site_prism.vcr
|
35
|
+
|
36
|
+
## Usage
|
37
|
+
|
38
|
+
### Linking VCR cassettes with SitePrism elements
|
39
|
+
|
40
|
+
To link VCR cassettes with SitePrism elements, you have to use `element_with_vcr` instead of `element` method of SitePrism for specifying elements:
|
41
|
+
|
42
|
+
```ruby
|
43
|
+
class ProductsPage < SitePrism::Page
|
44
|
+
element_with_vcr \
|
45
|
+
:car_details_link,
|
46
|
+
'#car_details' do
|
47
|
+
fixtures ['ford', 'cars/ford_features']
|
48
|
+
end
|
49
|
+
end
|
50
|
+
```
|
51
|
+
|
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
|
+
|
54
|
+
#### Path helper method
|
55
|
+
|
56
|
+
In case you have a lot of cassettes which are stored in some subdirectory, there is more better way for defining cassettes:
|
57
|
+
|
58
|
+
```ruby
|
59
|
+
class ProductsPage < SitePrism::Page
|
60
|
+
element_with_vcr \
|
61
|
+
:car_details_link,
|
62
|
+
'#car_details' do
|
63
|
+
path 'cars/small', ['ford', 'ford_features', 'prices']
|
64
|
+
path 'offerings', ['used_cars', 'new_cars']
|
65
|
+
end
|
66
|
+
end
|
67
|
+
```
|
68
|
+
|
69
|
+
The `path` helper method can be used a few times in a block to define cassettes. The code above is identical to:
|
70
|
+
|
71
|
+
```ruby
|
72
|
+
class ProductsPage < SitePrism::Page
|
73
|
+
element_with_vcr \
|
74
|
+
:car_details_link,
|
75
|
+
'#car_details' do
|
76
|
+
fixtures [
|
77
|
+
'cars/small/ford',
|
78
|
+
'cars/small/ford_features',
|
79
|
+
'cars/small/prices',
|
80
|
+
'offerings/used_cars',
|
81
|
+
'offerings/new_cars'
|
82
|
+
]
|
83
|
+
end
|
84
|
+
end
|
85
|
+
```
|
86
|
+
|
87
|
+
#### Home path helper method
|
88
|
+
|
89
|
+
There is a possibility to define a home path to cassettes which are applied for a particular element:
|
90
|
+
|
91
|
+
```ruby
|
92
|
+
class ProductsPage < SitePrism::Page
|
93
|
+
element_with_vcr \
|
94
|
+
:car_details_link,
|
95
|
+
'#car_details' do
|
96
|
+
home_path 'cars/small'
|
97
|
+
|
98
|
+
fixtures ['~/ford', '~/ford_features', '~/prices']
|
99
|
+
end
|
100
|
+
end
|
101
|
+
```
|
102
|
+
|
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:
|
104
|
+
|
105
|
+
```ruby
|
106
|
+
class ProductsPage < SitePrism::Page
|
107
|
+
element_with_vcr \
|
108
|
+
:car_details_link,
|
109
|
+
'#car_details' do
|
110
|
+
fixtures [
|
111
|
+
'cars/small/ford',
|
112
|
+
'cars/small/ford_features',
|
113
|
+
'cars/small/prices'
|
114
|
+
]
|
115
|
+
end
|
116
|
+
end
|
117
|
+
```
|
118
|
+
|
119
|
+
Home path is a very useful while redefining default cassettes (It is described below).
|
120
|
+
|
121
|
+
Also, you can use a defined home path with the `path` helper method:
|
122
|
+
|
123
|
+
```ruby
|
124
|
+
class ProductsPage < SitePrism::Page
|
125
|
+
element_with_vcr \
|
126
|
+
:car_details_link,
|
127
|
+
'#car_details' do
|
128
|
+
home_path 'cars/small'
|
129
|
+
|
130
|
+
path '~/', ['ford', 'ford_features', 'prices']
|
131
|
+
end
|
132
|
+
end
|
133
|
+
```
|
134
|
+
|
135
|
+
### Applying VCR cassettes on click
|
136
|
+
|
137
|
+
Now cassettes can be applied only on a click event:
|
138
|
+
|
139
|
+
```ruby
|
140
|
+
@products_page.car_details_link.click_and_apply_vcr
|
141
|
+
```
|
142
|
+
|
143
|
+
This code applies VCR cassettes which were specified while defining a SitePrism element. But, there is also possibility to override them:
|
144
|
+
|
145
|
+
```ruby
|
146
|
+
@products_page.car_details_link.click_and_apply_vcr do
|
147
|
+
fixtures ['cars/volvo']
|
148
|
+
end
|
149
|
+
```
|
150
|
+
|
151
|
+
This code completely overrides default cassettes, but only for this one particular click action. If you want to apply default cassettes again after this code, just use code without specifying custom cassettes:
|
152
|
+
|
153
|
+
```ruby
|
154
|
+
@products_page.car_details_link.click_and_apply_vcr do # overrides all default cassettes
|
155
|
+
fixtures ['cars/volvo']
|
156
|
+
end
|
157
|
+
|
158
|
+
@products_page.car_details_link.click_and_apply_vcr # uses default cassettes again
|
159
|
+
```
|
160
|
+
|
161
|
+
Also, there is possibility to add new cassettes instead of overriding default one:
|
162
|
+
|
163
|
+
```ruby
|
164
|
+
@products_page.car_details_link.click_and_apply_vcr do
|
165
|
+
fixtures ['cars/volvo']
|
166
|
+
union # makes this library add new cassettes to a list with default cassettes
|
167
|
+
end
|
168
|
+
```
|
169
|
+
|
170
|
+
Similar to defining SitePrism elements with VCR cassettes, you can use `path` helper method while applying fixtures:
|
171
|
+
|
172
|
+
```ruby
|
173
|
+
@products_page.car_details_link.click_and_apply_vcr do
|
174
|
+
path 'cars/small', ['volvo', 'volvo_features', 'prices']
|
175
|
+
end
|
176
|
+
```
|
177
|
+
|
178
|
+
Also, if you have specified a home path while defining a SitePrism element, you can use it here:
|
179
|
+
|
180
|
+
```ruby
|
181
|
+
@products_page.car_details_link.click_and_apply_vcr do
|
182
|
+
fixtures ['~/volvo', '~/volvo_features', '~/prices']
|
183
|
+
end
|
184
|
+
```
|
185
|
+
|
186
|
+
or
|
187
|
+
|
188
|
+
```ruby
|
189
|
+
@products_page.car_details_link.click_and_apply_vcr do
|
190
|
+
path '~/', ['volvo', 'volvo_features', 'prices']
|
191
|
+
end
|
192
|
+
```
|
193
|
+
|
194
|
+
Home path can be defined while applying Vcr:
|
195
|
+
|
196
|
+
```ruby
|
197
|
+
@products_page.car_details_link.click_and_apply_vcr do
|
198
|
+
home_path 'cars/volvo'
|
199
|
+
|
200
|
+
path '~/', ['volvo', 'volvo_features', 'prices']
|
201
|
+
end
|
202
|
+
```
|
203
|
+
|
204
|
+
#### Exchange default fixtures
|
205
|
+
|
206
|
+
There may be a situation when you need to exchange some default cassette for one specific test. It is a very easy to do:
|
207
|
+
|
208
|
+
```ruby
|
209
|
+
@products_page.car_details_link.click_and_apply_vcr do
|
210
|
+
exchange 'volvo', 'ford'
|
211
|
+
end
|
212
|
+
```
|
213
|
+
|
214
|
+
When you use a home path:
|
215
|
+
|
216
|
+
```ruby
|
217
|
+
@products_page.car_details_link.click_and_apply_vcr do
|
218
|
+
exchange '~/volvo', '~/ford'
|
219
|
+
end
|
220
|
+
```
|
221
|
+
|
222
|
+
Also, multiple cassettes can be exchanged:
|
223
|
+
|
224
|
+
```ruby
|
225
|
+
@products_page.car_details_link.click_and_apply_vcr do
|
226
|
+
exchange ['~/volvo', '~/ford'], ['~/mazda', '~/toyota']
|
227
|
+
end
|
228
|
+
```
|
229
|
+
|
230
|
+
### Waiters
|
231
|
+
|
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.
|
233
|
+
|
234
|
+
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
|
+
|
236
|
+
There are 2 ways for defining a waiter. When you define SitePrism elements:
|
237
|
+
|
238
|
+
```ruby
|
239
|
+
class ProductsPage < SitePrism::Page
|
240
|
+
element_with_vcr \
|
241
|
+
:car_details_link,
|
242
|
+
'#car_details' do
|
243
|
+
fixtures ['ford', 'cars/ford_features']
|
244
|
+
waiter &:wait_until_loading_indicator_invisible # our code will wait until the loading indicator has disappeared from a page
|
245
|
+
end
|
246
|
+
end
|
247
|
+
```
|
248
|
+
|
249
|
+
The second way is to set it while applying Vcr cassettes:
|
250
|
+
|
251
|
+
```ruby
|
252
|
+
@products_page.car_details_link.click_and_apply_vcr do
|
253
|
+
fixtures ['cars/volvo']
|
254
|
+
waiter &:wait_until_loading_indicator_invisible
|
255
|
+
end
|
256
|
+
```
|
257
|
+
|
258
|
+
*Note:* Using the second way, you can override a default waiter which was specified while defining SitePrism element.
|
259
|
+
|
260
|
+
In this case once we meet an expectation defined in a waiter, Vcr cassettes will be ejected and you will avoid issues with mixing unexpected cassettes. If you don't specify a waiter, you have to eject them manually:
|
261
|
+
|
262
|
+
```ruby
|
263
|
+
after do
|
264
|
+
SPV::Helpers.eject_all_cassettes
|
265
|
+
end
|
266
|
+
```
|
267
|
+
|
268
|
+
or directly in the test:
|
269
|
+
|
270
|
+
```ruby
|
271
|
+
it 'displays details of a product' do
|
272
|
+
products_page.products.first.show_details_btn.click_and_apply_vcr
|
273
|
+
products_page.details.should have_content('Volvo')
|
274
|
+
|
275
|
+
SPV::Helpers.eject_all_cassettes
|
276
|
+
|
277
|
+
products_page.products.second.show_details_btn.click_and_apply_vcr
|
278
|
+
products_page.details.should have_content('Ford')
|
279
|
+
end
|
280
|
+
```
|
281
|
+
|
282
|
+
*Note:* Waiters must be defined in a block. In a block you have access to an instance of class where you define elements.
|
283
|
+
|
284
|
+
There may be situation when you don't need a waiter to eject all cassettes. In this case you can pass an additional option to a waiter to disable ejecting all cassettes:
|
285
|
+
|
286
|
+
```ruby
|
287
|
+
@products_page.car_details_link.click_and_apply_vcr do
|
288
|
+
fixtures ['cars/volvo']
|
289
|
+
waiter(eject_cassettes: false) { self.wait_until_loading_indicator_invisible }
|
290
|
+
end
|
291
|
+
```
|
292
|
+
|
293
|
+
The same thing can be defined for a default waiter.
|
294
|
+
|
295
|
+
### Linking and applying VCR cassettes with SitePrism pages
|
296
|
+
|
297
|
+
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:
|
298
|
+
|
299
|
+
```ruby
|
300
|
+
class ProductsPage < SitePrism::Page
|
301
|
+
vcr_options_for_load do
|
302
|
+
fixtures ['max']
|
303
|
+
end
|
304
|
+
end
|
305
|
+
```
|
306
|
+
|
307
|
+
Everything described above about defining cassettes for SitePrism elements is true for defining cassettes for pages.
|
308
|
+
|
309
|
+
Applying cassettes is almost the same as we saw for a click event:
|
310
|
+
|
311
|
+
```ruby
|
312
|
+
page.load_and_apply_vcr do
|
313
|
+
fixtures ['max', 'felix']
|
314
|
+
|
315
|
+
waiter &:wait_for_max_and_felix
|
316
|
+
end
|
317
|
+
```
|
318
|
+
|
319
|
+
All arguments passed to `load_and_apply_vcr` method will be passed to `load` method of SitePrism. It allows you to change an url of the being loaded page.
|
320
|
+
|
321
|
+
```ruby
|
322
|
+
page.load_and_apply_vcr(cat: 'tom') do
|
323
|
+
fixtures ['max', 'felix']
|
324
|
+
|
325
|
+
waiter &:wait_for_max_and_felix
|
326
|
+
end
|
327
|
+
```
|
328
|
+
|
329
|
+
In this case, SitePrism will alter an url and it will look like:
|
330
|
+
|
331
|
+
```ruby
|
332
|
+
http://localhost/cats/tom
|
333
|
+
```
|
334
|
+
|
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
|
+
### Using Vcr options for cassettes
|
348
|
+
|
349
|
+
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:
|
350
|
+
|
351
|
+
```ruby
|
352
|
+
class ProductsPage < SitePrism::Page
|
353
|
+
element_with_vcr \
|
354
|
+
:car_details_link,
|
355
|
+
'#car_details' do
|
356
|
+
home_path 'cars/small'
|
357
|
+
|
358
|
+
path '~/', [{fixture: 'ford', options: {erb: {amount: 109} } }, 'ford_features', 'prices']
|
359
|
+
end
|
360
|
+
end
|
361
|
+
```
|
362
|
+
|
363
|
+
It works with any kind of helper methods where you list names of cassettes, even with the `exchange` helper method:
|
364
|
+
|
365
|
+
```ruby
|
366
|
+
@products_page.car_details_link.click_and_apply_vcr do
|
367
|
+
exchange '~/volvo', {fixture: '~/toyota', options: {erb: {amount: 1000} } }
|
368
|
+
end
|
369
|
+
```
|
370
|
+
|
371
|
+
## Contributing
|
372
|
+
|
373
|
+
1. Fork it
|
374
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
375
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
376
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
377
|
+
5. Create new Pull Request
|
378
|
+
|
379
|
+
|
380
|
+
[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/nestd/site_prism.vcr/trend.png)](https://bitdeli.com/free "Bitdeli Badge")
|
381
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
data/TODO.md
ADDED
@@ -0,0 +1,71 @@
|
|
1
|
+
# TODO
|
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
|
26
|
+
|
27
|
+
```ruby
|
28
|
+
@cars.shift_event{ page.find('#cars').click }.apply_vcr do
|
29
|
+
fixtures ['cars']
|
30
|
+
end
|
31
|
+
```
|
32
|
+
|
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
|
35
|
+
|
36
|
+
## Should be implemented?
|
37
|
+
|
38
|
+
1. Create possibility to define fixtures without the click action:
|
39
|
+
|
40
|
+
```ruby
|
41
|
+
self.confirm_btn.vcr do
|
42
|
+
path 'products', ['tomato', 'fruit/apple']
|
43
|
+
path 'goods', 'cars'
|
44
|
+
|
45
|
+
replace
|
46
|
+
end
|
47
|
+
```
|
48
|
+
|
49
|
+
and then
|
50
|
+
|
51
|
+
```ruby
|
52
|
+
self.confirm_btn.click_and_apply_vcr
|
53
|
+
```
|
54
|
+
|
55
|
+
will use previously defined fixtures
|
56
|
+
|
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
|
+
|
68
|
+
## Things to think over
|
69
|
+
|
70
|
+
1. Should we add the integration tests for page load to make sure 2 HTTP requests will be handled properly?
|
71
|
+
2. Should we add own integration tests to test the path helper method?
|
@@ -0,0 +1 @@
|
|
1
|
+
require 'site_prism_vcr'
|
@@ -0,0 +1,54 @@
|
|
1
|
+
module SPV
|
2
|
+
# This class manages defining default fixtures
|
3
|
+
# and applying them on an event.
|
4
|
+
class Applier
|
5
|
+
def initialize(node, &block)
|
6
|
+
@node, @options = node, Options.new
|
7
|
+
adjuster = DSL::InitialAdjuster.new(@options)
|
8
|
+
|
9
|
+
if block_given?
|
10
|
+
adjuster.instance_eval &block
|
11
|
+
end
|
12
|
+
|
13
|
+
@fixtures = adjuster.prepared_fixtures
|
14
|
+
|
15
|
+
@fixtures_manager = Fixtures::Manager.new(@options)
|
16
|
+
end
|
17
|
+
|
18
|
+
# Applies fixtures to be used for stubbing HTTP interactions
|
19
|
+
# caused by an event (click on an element or page loading).
|
20
|
+
#
|
21
|
+
# Makes a defined waiter to meet expectation before ejecting
|
22
|
+
# fixtures from VCR.
|
23
|
+
#
|
24
|
+
# @param adjusting_block [nil, Proc] If an adjusting block is given,
|
25
|
+
# it allows to change fixtures through DSL (@see SPV::DSL::InitialAdjuster
|
26
|
+
# and @see SPV::DSL::Adjuster)
|
27
|
+
#
|
28
|
+
# @return [void]
|
29
|
+
def apply(adjusting_block = nil)
|
30
|
+
options = @options.clone_options
|
31
|
+
|
32
|
+
adjuster = DSL::Adjuster.new(
|
33
|
+
options,
|
34
|
+
@fixtures
|
35
|
+
)
|
36
|
+
|
37
|
+
if adjusting_block
|
38
|
+
adjuster.instance_eval &adjusting_block
|
39
|
+
end
|
40
|
+
|
41
|
+
@fixtures_manager.inject(adjuster.prepared_fixtures)
|
42
|
+
|
43
|
+
yield
|
44
|
+
|
45
|
+
@waiter = Waiter.new(
|
46
|
+
@node,
|
47
|
+
@fixtures_manager,
|
48
|
+
options
|
49
|
+
)
|
50
|
+
|
51
|
+
@waiter.wait
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,82 @@
|
|
1
|
+
module SPV
|
2
|
+
module DSL
|
3
|
+
# This class extends SPV::DSL::InitialAdjuster with new methods
|
4
|
+
# which can be used in a block for manipulating fixtures before applying them.
|
5
|
+
class Adjuster < InitialAdjuster
|
6
|
+
def initialize(options, fixtures)
|
7
|
+
super options
|
8
|
+
|
9
|
+
@options, @fixtures = options, fixtures
|
10
|
+
end
|
11
|
+
|
12
|
+
# Replaces default fixtures with a set of fixtures
|
13
|
+
# defined in a block passed while applying fixtures.
|
14
|
+
#
|
15
|
+
# @return [void]
|
16
|
+
#
|
17
|
+
# @api public
|
18
|
+
def replace
|
19
|
+
change_fixtures :replace
|
20
|
+
end
|
21
|
+
|
22
|
+
# Joins default fixtures with a set of fixtures
|
23
|
+
# defined in a block passed while applying fixtures.
|
24
|
+
#
|
25
|
+
# @return [void]
|
26
|
+
#
|
27
|
+
# @api public
|
28
|
+
def union
|
29
|
+
change_fixtures :union
|
30
|
+
end
|
31
|
+
|
32
|
+
# Exchanges certain default fixtures with another fixtures.
|
33
|
+
#
|
34
|
+
# @param old_fixtures [String, Array<String>] List of fixtures which should be removed.
|
35
|
+
# If string is passed instead of an array, it will be converted to an array.
|
36
|
+
# @param new_fixtures [String, Array<String>] List of fixtures which should added.
|
37
|
+
# If string is passed instead of an array, it will be converted to an array.
|
38
|
+
#
|
39
|
+
# @return [void]
|
40
|
+
#
|
41
|
+
# @api public
|
42
|
+
def exchange(old_fixtures, new_fixtures)
|
43
|
+
home_path_modifier = Fixtures::Modifiers::HomePath.new(@options)
|
44
|
+
|
45
|
+
old_fixtures = [old_fixtures] unless old_fixtures.is_a?(Array)
|
46
|
+
new_fixtures = [new_fixtures] unless new_fixtures.is_a?(Array)
|
47
|
+
|
48
|
+
old_fixtures, new_fixtures = @fixtures_handler.handle_set_raws(
|
49
|
+
old_fixtures,
|
50
|
+
new_fixtures,
|
51
|
+
[home_path_modifier]
|
52
|
+
)
|
53
|
+
|
54
|
+
@fixtures = @fixtures.exchange(
|
55
|
+
old_fixtures,
|
56
|
+
new_fixtures
|
57
|
+
)
|
58
|
+
end
|
59
|
+
|
60
|
+
# Performs the replace action when no explicit action is defined
|
61
|
+
# in a block for manipulating fixtures before applying them.
|
62
|
+
#
|
63
|
+
# @return [SPV::Fixtures] A set of prepared fixtures.
|
64
|
+
#
|
65
|
+
# @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
|
72
|
+
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
|
+
end # class Adjuster
|
81
|
+
end # module DSL
|
82
|
+
end # module SPV
|