vcr 1.3.1 → 1.3.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (72) hide show
  1. data/CHANGELOG.md +14 -2
  2. data/Gemfile +3 -0
  3. data/Gemfile.lock +20 -2
  4. data/README.md +6 -1
  5. data/Rakefile +6 -44
  6. data/benchmarks/http_stubbing_libraries.rb +4 -4
  7. data/cucumber.yml +14 -0
  8. data/features/README.md +21 -0
  9. data/features/cassettes/automatic_re_recording.feature +68 -0
  10. data/features/cassettes/dynamic_erb.feature +90 -0
  11. data/features/cassettes/format.feature +81 -0
  12. data/features/cassettes/no_cassette.feature +38 -0
  13. data/features/cassettes/record_modes/all.feature +78 -0
  14. data/features/cassettes/record_modes/new_episodes.feature +71 -0
  15. data/features/cassettes/record_modes/none.feature +65 -0
  16. data/features/cassettes/request_matching.feature +379 -0
  17. data/features/configuration/cassette_library_dir.feature +28 -0
  18. data/features/configuration/default_cassette_options.feature +80 -0
  19. data/features/configuration/ignore_localhost.feature +103 -0
  20. data/features/configuration/stub_with.feature +164 -0
  21. data/features/http_libraries/net_http.feature +137 -0
  22. data/features/step_definitions/cli_steps.rb +82 -0
  23. data/features/support/aruba_workaround/aruba_patches.rb +36 -0
  24. data/features/support/aruba_workaround/background_process.rb +4 -0
  25. data/features/support/env.rb +16 -102
  26. data/features/support/http_lib_filters.rb +37 -0
  27. data/features/support/vcr_cucumber_helpers.rb +34 -0
  28. data/features/test_frameworks/cucumber.feature +109 -0
  29. data/features/test_frameworks/rspec.feature +110 -0
  30. data/features/test_frameworks/shoulda.feature +64 -0
  31. data/features/test_frameworks/test_unit.feature +46 -0
  32. data/lib/vcr/cassette.rb +1 -1
  33. data/lib/vcr/structs.rb +64 -13
  34. data/lib/vcr/version.rb +1 -1
  35. data/{FullBuildRakeFile → script/FullBuildRakeFile} +0 -0
  36. data/script/full_build +1 -0
  37. data/spec/extensions/net_http_spec.rb +1 -1
  38. data/spec/spec_helper.rb +1 -1
  39. data/spec/structs_spec.rb +47 -16
  40. data/spec/support/vcr_localhost_server.rb +11 -5
  41. data/vcr.gemspec +2 -1
  42. metadata +82 -77
  43. data/features/fixtures/vcr_cassettes/1.9.1/cucumber_tags/regex_cassette.yml +0 -43
  44. data/features/fixtures/vcr_cassettes/1.9.1/cucumber_tags/replay_cassette1.yml +0 -43
  45. data/features/fixtures/vcr_cassettes/1.9.1/cucumber_tags/replay_cassette2.yml +0 -63
  46. data/features/fixtures/vcr_cassettes/1.9.1/cucumber_tags/replay_cassette3.yml +0 -85
  47. data/features/fixtures/vcr_cassettes/1.9.1/erb_cassette.yml +0 -36
  48. data/features/fixtures/vcr_cassettes/1.9.1/match_requests_on.yml +0 -35
  49. data/features/fixtures/vcr_cassettes/1.9.1/nested_replay_cassette.yml +0 -32
  50. data/features/fixtures/vcr_cassettes/1.9.1/not_the_real_response.yml +0 -43
  51. data/features/fixtures/vcr_cassettes/1.9.1/record_all.yml +0 -62
  52. data/features/fixtures/vcr_cassettes/1.9.1/replay_localhost_cassette.yml +0 -32
  53. data/features/fixtures/vcr_cassettes/not_1.9.1/cucumber_tags/regex_cassette.yml +0 -43
  54. data/features/fixtures/vcr_cassettes/not_1.9.1/cucumber_tags/replay_cassette1.yml +0 -43
  55. data/features/fixtures/vcr_cassettes/not_1.9.1/cucumber_tags/replay_cassette2.yml +0 -47
  56. data/features/fixtures/vcr_cassettes/not_1.9.1/cucumber_tags/replay_cassette3.yml +0 -85
  57. data/features/fixtures/vcr_cassettes/not_1.9.1/erb_cassette.yml +0 -36
  58. data/features/fixtures/vcr_cassettes/not_1.9.1/match_requests_on.yml +0 -35
  59. data/features/fixtures/vcr_cassettes/not_1.9.1/nested_replay_cassette.yml +0 -24
  60. data/features/fixtures/vcr_cassettes/not_1.9.1/not_the_real_response.yml +0 -43
  61. data/features/fixtures/vcr_cassettes/not_1.9.1/record_all.yml +0 -61
  62. data/features/fixtures/vcr_cassettes/not_1.9.1/replay_localhost_cassette.yml +0 -32
  63. data/features/http_client.feature +0 -16
  64. data/features/net_http.feature +0 -38
  65. data/features/record_response.feature +0 -95
  66. data/features/replay_recorded_response.feature +0 -96
  67. data/features/rspec.feature +0 -100
  68. data/features/step_definitions/http_client_steps.rb +0 -7
  69. data/features/step_definitions/net_http_steps.rb +0 -49
  70. data/features/step_definitions/vcr_steps.rb +0 -252
  71. data/features/webmock.feature +0 -26
  72. data/full_build +0 -1
@@ -1,32 +0,0 @@
1
- ---
2
- - !ruby/struct:VCR::HTTPInteraction
3
- request: !ruby/struct:VCR::Request
4
- method: :get
5
- uri: http://localhost/
6
- body:
7
- headers:
8
- response: !ruby/struct:VCR::Response
9
- status: !ruby/struct:VCR::ResponseStatus
10
- code: 200
11
- message: OK
12
- headers:
13
- etag:
14
- - "\"24ec5-1b6-4059a80bfd280\""
15
- last-modified:
16
- - Tue, 15 Nov 2005 13:24:10 GMT
17
- connection:
18
- - Keep-Alive
19
- content-type:
20
- - text/html; charset=UTF-8
21
- date:
22
- - Thu, 25 Feb 2010 15:22:32 GMT
23
- server:
24
- - Apache/2.2.3 (CentOS)
25
- content-length:
26
- - "438"
27
- age:
28
- - "2643"
29
- accept-ranges:
30
- - bytes
31
- body: This is a fake response.
32
- http_version: "1.1"
@@ -1,16 +0,0 @@
1
- @httpclient
2
- Feature: HTTPClient
3
- In order to have deterministic, fast tests that do not depend on an internet connection
4
- As a TDD/BDD developer
5
- I want VCR to work with asynchronous HTTPClient requests
6
-
7
- Scenario: Record an asynchronous request
8
- Given we do not have a "temp/asynchronous" cassette
9
- When I make an asynchronous HTTPClient get request to "http://example.com" while using the "temp/asynchronous" cassette
10
- Then the "temp/asynchronous" library file should have a response for "http://example.com" that matches /You have reached this web page by typing.*example\.com/
11
-
12
- @copy_not_the_real_response_to_temp
13
- Scenario: Replay a response for an asynchronous request
14
- Given the "temp/not_the_real_response" library file has a response for "http://example.com" that matches /This is not the real response from example\.com/
15
- When I make an asynchronous HTTPClient get request to "http://example.com" while using the "temp/not_the_real_response" cassette
16
- Then the response for "http://example.com" should match /This is not the real response from example\.com/
@@ -1,38 +0,0 @@
1
- @net_http
2
- Feature: Net::HTTP
3
- In order to have deterministic, fast tests that do not depend on an internet connection
4
- As a TDD/BDD developer
5
- I want to use VCR with Net::HTTP
6
-
7
- Scenario: Record an asynchronous request (such as for mechanize)
8
- Given we do not have a "temp/asynchronous" cassette
9
- When I make an asynchronous Net::HTTP get request to "http://example.com" while using the "temp/asynchronous" cassette
10
- Then the "temp/asynchronous" library file should have a response for "http://example.com" that matches /You have reached this web page by typing.*example\.com/
11
-
12
- @copy_not_the_real_response_to_temp
13
- Scenario: Replay a response for an asynchronous request (such as for mechanize)
14
- Given the "temp/not_the_real_response" library file has a response for "http://example.com" that matches /This is not the real response from example\.com/
15
- When I make a replayed asynchronous Net::HTTP get request to "http://example.com" while using the "temp/not_the_real_response" cassette
16
- Then the response for "http://example.com" should match /This is not the real response from example\.com/
17
-
18
- Scenario: Record a recursive post request
19
- Given we do not have a "temp/recursive_post" cassette
20
- When I make a recursive Net::HTTP post request to "http://example.com" while using the "temp/recursive_post" cassette
21
- Then the "temp/recursive_post" library file should have a response for "http://example.com" that matches /You have reached this web page by typing.*example\.com/
22
- And the "temp/recursive_post" library file should have exactly 1 response
23
-
24
- Scenario: Record a request with a block with a return statement
25
- Given we do not have a "temp/block_with_a_return" cassette
26
- When I make a returning block Net::HTTP get request to "http://example.com" while using the "temp/block_with_a_return" cassette
27
- Then the "temp/block_with_a_return" library file should have a response for "http://example.com" that matches /You have reached this web page by typing.*example\.com/
28
-
29
- Scenario: Record a request made with open uri
30
- Given we do not have a "temp/open_uri" cassette
31
- When I make an open uri Net::HTTP get request to "http://example.com" while using the "temp/open_uri" cassette
32
- Then the "temp/open_uri" library file should have a response for "http://example.com" that matches /You have reached this web page by typing.*example\.com/
33
-
34
- @copy_not_the_real_response_to_temp
35
- Scenario: Replay a response for an open uri request
36
- Given the "temp/not_the_real_response" library file has a response for "http://example.com" that matches /This is not the real response from example\.com/
37
- When I make an open uri Net::HTTP get request to "http://example.com" while using the "temp/not_the_real_response" cassette
38
- Then the response for "http://example.com" should match /This is not the real response from example\.com/
@@ -1,95 +0,0 @@
1
- @all_http_libs
2
- Feature: Record response
3
- In order to have deterministic, fast tests that do not depend on an internet connection
4
- As a TDD/BDD developer
5
- I want to record responses for new requests so I can replay them in future test runs
6
-
7
- Scenario: Record a response using VCR.use_cassette
8
- Given we do not have a "temp/cassette" cassette
9
- When I make an HTTP get request to "http://example.com/" while using the "temp/cassette" cassette
10
- Then the "temp/cassette" library file should have a response for "http://example.com/" that matches /You have reached this web page by typing.*example\.com/
11
- And the "temp/cassette" library file should have normalized headers for all recorded interactions
12
-
13
- @record_cassette1
14
- Scenario: Record a response using a tagged scenario
15
- Given we do not have a "cucumber_tags/record_cassette1" cassette
16
- And this scenario is tagged with the vcr cassette tag: "@record_cassette1"
17
- When I make an HTTP get request to "http://example.com/"
18
- Then I can test the scenario cassette's recorded responses in the next scenario, after the cassette has been ejected
19
-
20
- Scenario: Check the recorded response for the previous scenario
21
- Given the previous scenario was tagged with the vcr cassette tag: "@record_cassette1"
22
- Then the "cucumber_tags/record_cassette1" library file should have a response for "http://example.com/" that matches /You have reached this web page by typing.*example\.com/
23
-
24
- @record_cassette2
25
- Scenario: Use both a tagged scenario cassette and a nested cassette within a single step definition
26
- Given we do not have a "cucumber_tags/record_cassette2" cassette
27
- And we do not have a "temp/nested" cassette
28
- And this scenario is tagged with the vcr cassette tag: "@record_cassette2"
29
- When I make an HTTP get request to "http://example.com/before_nested"
30
- And I make an HTTP get request to "http://example.com/nested" while using the "temp/nested" cassette
31
- And I make an HTTP get request to "http://example.com/after_nested"
32
- Then I can test the scenario cassette's recorded responses in the next scenario, after the cassette has been ejected
33
- And the "temp/nested" library file should have a response for "http://example.com/nested" that matches /The requested URL \/nested was not found/
34
-
35
- Scenario: Check the recorded response for the previous scenario
36
- Given the previous scenario was tagged with the vcr cassette tag: "@record_cassette2"
37
- Then the "cucumber_tags/record_cassette2" library file should have a response for "http://example.com/before_nested" that matches /The requested URL \/before_nested was not found/
38
- And the "cucumber_tags/record_cassette2" library file should have a response for "http://example.com/after_nested" that matches /The requested URL \/after_nested was not found/
39
-
40
- Scenario: Make an HTTP request in a cassette with record mode set to :all when the cassette does not already exist
41
- Given we do not have a "temp/record_all_cassette" cassette
42
- When I make an HTTP get request to "http://example.com/" while using the "temp/record_all_cassette" cassette using cassette options: { :record => :all }
43
- Then the "temp/record_all_cassette" library file should have a response for "http://example.com/" that matches /You have reached this web page by typing.*example\.com/
44
-
45
- @copy_record_all_to_temp
46
- Scenario: Make an HTTP request in a cassette with record mode set to :all when the cassette already exists
47
- Given the "temp/record_all" library file has a response for "http://example.com/a" that matches /a response 1/
48
- And the "temp/record_all" library file has a response for "http://example.com/a" that matches /a response 2/
49
- And the "temp/record_all" library file has a response for "http://example.com/b" that matches /b response 1/
50
- And the "temp/record_all" library file has a response for "http://example.com/b" that matches /b response 2/
51
- When I make an HTTP get request to "http://example.com/a" while using the "temp/record_all" cassette using cassette options: { :record => :all }
52
- Then the "temp/record_all" library file should have a response for "http://example.com/a" that matches /The requested URL \/a was not found/
53
- And the "temp/record_all" library file should not have a response for "http://example.com/a" that matches /a response 1/
54
- And the "temp/record_all" library file should not have a response for "http://example.com/a" that matches /a response 2/
55
- And the "temp/record_all" library file should have a response for "http://example.com/b" that matches /b response 1/
56
- And the "temp/record_all" library file should have a response for "http://example.com/b" that matches /b response 2/
57
-
58
- Scenario: Make an HTTP request in a cassette with record mode set to :none
59
- Given we do not have a "temp/record_none_cassette" cassette
60
- When I make an HTTP get request to "http://example.com/" while using the "temp/record_none_cassette" cassette using cassette options: { :record => :none }
61
- Then the HTTP get request to "http://example.com/" should result in an error that mentions VCR
62
- And there should not be a "temp/record_none_cassette" library file
63
-
64
- @copy_not_the_real_response_to_temp
65
- Scenario: Make an HTTP request in a cassette with record mode set to :new_episodes
66
- Given we have a "temp/not_the_real_response" library file with a previously recorded response for "http://example.com/"
67
- And we have a "temp/not_the_real_response" library file with no previously recorded response for "http://example.com/foo"
68
- When I make HTTP get requests to "http://example.com/" and "http://example.com/foo" while using the "temp/not_the_real_response" cassette
69
- Then the "temp/not_the_real_response" library file should have a response for "http://example.com/" that matches /This is not the real response from example\.com/
70
- And the "temp/not_the_real_response" library file should have a response for "http://example.com/foo" that matches /The requested URL \/foo was not found/
71
-
72
- @spawns_localhost_server
73
- Scenario: Ignore localhost setting allows localhost requests and does not record them
74
- Given we do not have a "temp/localhost" cassette
75
- And the ignore_localhost config setting is set to true
76
- And a rack app is running on localhost that returns "hello world" for all requests
77
- When I make an HTTP get request to the localhost rack app while using the "temp/localhost" cassette
78
- Then the response for the localhost rack app should match /hello world/
79
- And there should not be a "temp/localhost" library file
80
-
81
- @copy_not_the_real_response_to_temp
82
- Scenario: The response is not automatically recorded when not enough time has passed
83
- Given the "temp/not_the_real_response" library file has a response for "http://example.com/" that matches /This is not the real response from example.com/
84
- And 6 days have passed since the "temp/not_the_real_response" library file last changed
85
- When I make an HTTP get request to "http://example.com/" while using the "temp/not_the_real_response" cassette using cassette options: { :record => :none, :re_record_interval => 7.days }
86
- Then the response for "http://example.com/" should match /This is not the real response from example.com/
87
- And the "temp/not_the_real_response" library file should have a response for "http://example.com/" that matches /This is not the real response from example.com/
88
-
89
- @copy_not_the_real_response_to_temp
90
- Scenario: The response is automatically recorded when enough time has passed
91
- Given the "temp/not_the_real_response" library file has a response for "http://example.com/" that matches /This is not the real response from example.com/
92
- And 8 days have passed since the "temp/not_the_real_response" library file last changed
93
- When I make an HTTP get request to "http://example.com/" while using the "temp/not_the_real_response" cassette using cassette options: { :record => :none, :re_record_interval => 7.days }
94
- Then the response for "http://example.com/" should match /You have reached this web page by typing.*example\.com/
95
- And the "temp/not_the_real_response" library file should have a response for "http://example.com/" that matches /You have reached this web page by typing.*example\.com/
@@ -1,96 +0,0 @@
1
- @all_http_libs
2
- Feature: Replay recorded response
3
- In order to have deterministic, fast tests that do not depend on an internet connection
4
- As a TDD/BDD developer
5
- I want to replay responses for requests I have previously recorded
6
-
7
- Scenario: Replay recorded response for a request in a VCR.use_cassette block
8
- Given the "not_the_real_response" library file has a response for "http://example.com/" that matches /This is not the real response from example\.com/
9
- When I make an HTTP get request to "http://example.com/" while using the "not_the_real_response" cassette
10
- Then the response for "http://example.com/" should match /This is not the real response from example\.com/
11
-
12
- @replay_cassette1
13
- Scenario: Replay recorded response for a request within a tagged scenario
14
- Given this scenario is tagged with the vcr cassette tag: "@replay_cassette1"
15
- And the "cucumber_tags/replay_cassette1" library file has a response for "http://example.com/" that matches /This is not the real response from example\.com/
16
- When I make an HTTP get request to "http://example.com/"
17
- Then the response for "http://example.com/" should match /This is not the real response from example\.com/
18
-
19
- @replay_cassette2
20
- Scenario: Use both a tagged scenario cassette and a nested cassette within a single step definition
21
- Given this scenario is tagged with the vcr cassette tag: "@replay_cassette2"
22
- And the "cucumber_tags/replay_cassette2" library file has a response for "http://example.com/before_nested" that matches /The before_nested response/
23
- And the "nested_replay_cassette" library file has a response for "http://example.com/nested" that matches /The nested response/
24
- And the "cucumber_tags/replay_cassette2" library file has a response for "http://example.com/after_nested" that matches /The after_nested response/
25
- When I make an HTTP get request to "http://example.com/before_nested"
26
- And I make an HTTP get request to "http://example.com/nested" while using the "nested_replay_cassette" cassette
27
- And I make an HTTP get request to "http://example.com/after_nested"
28
- Then the response for "http://example.com/before_nested" should match /The before_nested response/
29
- And the response for "http://example.com/nested" should match /The nested response/
30
- And the response for "http://example.com/after_nested" should match /The after_nested response/
31
-
32
- @copy_not_the_real_response_to_temp
33
- Scenario: Make an HTTP request in a cassette with record mode set to :all
34
- Given we have a "temp/not_the_real_response" library file with a previously recorded response for "http://example.com/"
35
- And we have a "temp/not_the_real_response" library file with no previously recorded response for "http://example.com/foo"
36
- When I make HTTP get requests to "http://example.com/" and "http://example.com/foo" while using the "temp/not_the_real_response" cassette using cassette options: { :record => :all }
37
- Then the response for "http://example.com/" should match /You have reached this web page by typing.*example\.com/
38
- And the response for "http://example.com/foo" should match /The requested URL \/foo was not found/
39
-
40
- @copy_not_the_real_response_to_temp
41
- Scenario: Make an HTTP request in a cassette with record mode set to :none
42
- Given we have a "temp/not_the_real_response" library file with a previously recorded response for "http://example.com/"
43
- And we have a "temp/not_the_real_response" library file with no previously recorded response for "http://example.com/foo"
44
- When I make HTTP get requests to "http://example.com/" and "http://example.com/foo" while using the "temp/not_the_real_response" cassette using cassette options: { :record => :none }
45
- Then the response for "http://example.com/" should match /This is not the real response from example\.com/
46
- And the HTTP get request to "http://example.com/foo" should result in an error that mentions VCR
47
-
48
- @copy_not_the_real_response_to_temp
49
- Scenario: Make an HTTP request in a cassette with record mode set to :new_episodes
50
- Given we have a "temp/not_the_real_response" library file with a previously recorded response for "http://example.com/"
51
- And we have a "temp/not_the_real_response" library file with no previously recorded response for "http://example.com/foo"
52
- When I make HTTP get requests to "http://example.com/" and "http://example.com/foo" while using the "temp/not_the_real_response" cassette
53
- Then the response for "http://example.com/" should match /This is not the real response from example\.com/
54
- And the response for "http://example.com/foo" should match /The requested URL \/foo was not found/
55
-
56
- @replay_cassette3
57
- Scenario: Replay multiple different recorded responses for requests to the same URL
58
- Given this scenario is tagged with the vcr cassette tag: "@replay_cassette3"
59
- And the "cucumber_tags/replay_cassette3" library file has a response for "http://example.com/" that matches /This is not the real response from example\.com/
60
- And the "cucumber_tags/replay_cassette3" library file has a response for "http://example.com/" that matches /This is another fake response from example\.com/
61
- When I make an HTTP get request to "http://example.com/"
62
- And I make an HTTP get request to "http://example.com/"
63
- Then response 1 for "http://example.com/" should match /This is not the real response from example\.com/
64
- And response 2 for "http://example.com/" should match /This is another fake response from example\.com/
65
-
66
- @regex_cassette
67
- Scenario: Replay a cassette with a regex URI
68
- Given this scenario is tagged with the vcr cassette tag: "@regex_cassette"
69
- And the "cucumber_tags/regex_cassette" library file has a response for /example\.com\/reg/ that matches /This is the response from the regex cassette/
70
- When I make an HTTP get request to "http://example.com/regex1"
71
- And I make an HTTP get request to "http://example.com/regex2"
72
- And I make an HTTP get request to "http://example.com/something_else"
73
- Then the response for "http://example.com/regex1" should match /This is the response from the regex cassette/
74
- And the response for "http://example.com/regex2" should match /This is the response from the regex cassette/
75
- And the HTTP get request to "http://example.com/something_else" should result in an error that mentions VCR
76
-
77
- Scenario: Replay recorded erb response
78
- Given the "erb_cassette" library file has a response for "http://example.com/embedded_ruby_code" that matches /Some embedded ruby code[\S\s]*The value of some_variable is/
79
- When I make an HTTP get request to "http://example.com/embedded_ruby_code" while using the "erb_cassette" cassette using cassette options: { :record => :none, :erb => { :some_variable => 'foo-bar' } }
80
- Then the response for "http://example.com/embedded_ruby_code" should match /Some embedded ruby code: 7[\S\s]*The value of some_variable is: foo-bar/
81
-
82
- @create_replay_localhost_cassette @spawns_localhost_server
83
- Scenario: Replay recorded localhost response with ignore_localhost = false
84
- Given the ignore_localhost config setting is set to false
85
- And the "temp/replay_localhost_cassette" library file has a response for localhost that matches /This is a fake response/
86
- And a rack app is running on localhost that returns "localhost response" for all requests
87
- When I make an HTTP get request to the localhost rack app while using the "temp/replay_localhost_cassette" cassette
88
- Then the response for the localhost rack app should match /This is a fake response/
89
-
90
- @create_replay_localhost_cassette @spawns_localhost_server
91
- Scenario: Replay recorded localhost response with ignore_localhost = true
92
- Given the ignore_localhost config setting is set to true
93
- And the "temp/replay_localhost_cassette" library file has a response for localhost that matches /This is a fake response/
94
- And a rack app is running on localhost that returns "localhost response" for all requests
95
- When I make an HTTP get request to the localhost rack app while using the "temp/replay_localhost_cassette" cassette
96
- Then the response for the localhost rack app should match /localhost response/
@@ -1,100 +0,0 @@
1
- @fakeweb
2
- Feature: RSpec integration
3
- In order to easily use VCR with RSpec
4
- As a user of both VCR and RSpec
5
- I want a simple macro that uses a cassette for an example group
6
-
7
- Scenario: `use_vcr_cassette` macro for RSpec 2
8
- Given the following files do not exist:
9
- | cassettes/VCR-RSpec_integration/without_an_explicit_cassette_name.yml |
10
- | cassettes/net_http_example.yml |
11
- And a file named "use_vcr_cassette_for_rspec_2_spec.rb" with:
12
- """
13
- require 'vcr'
14
-
15
- VCR.config do |c|
16
- c.cassette_library_dir = 'cassettes'
17
- c.http_stubbing_library = :fakeweb
18
- c.default_cassette_options = { :record => :new_episodes }
19
- end
20
-
21
- RSpec.configure do |c|
22
- c.extend VCR::RSpec::Macros
23
- end
24
-
25
- describe "VCR-RSpec integration" do
26
- def make_http_request
27
- Net::HTTP.get_response('example.com', '/').body
28
- end
29
-
30
- context "without an explicit cassette name" do
31
- use_vcr_cassette
32
-
33
- it 'records an http request' do
34
- make_http_request.should =~ /You have reached this web page by typing.*example\.com/
35
- end
36
- end
37
-
38
- context "with an explicit cassette name" do
39
- use_vcr_cassette "net_http_example"
40
-
41
- it 'records an http request' do
42
- make_http_request.should =~ /You have reached this web page by typing.*example\.com/
43
- end
44
- end
45
- end
46
- """
47
- When I run "rspec ./use_vcr_cassette_for_rspec_2_spec.rb"
48
- Then the output should contain "2 examples, 0 failures"
49
- And the file "cassettes/VCR-RSpec_integration/without_an_explicit_cassette_name.yml" should contain "You have reached this web page by typing"
50
- And the file "cassettes/net_http_example.yml" should contain "You have reached this web page by typing"
51
-
52
- Scenario: `use_vcr_cassette` macro for RSpec 1
53
- Given the following files do not exist:
54
- | cassettes/VCR-RSpec_integration/without_an_explicit_cassette_name.yml |
55
- | cassettes/net_http_example.yml |
56
- And a file named "use_vcr_cassette_for_rspec_1_spec.rb" with:
57
- """
58
- $LOAD_PATH.unshift(File.join(%w[ .. .. vendor rspec-1 lib ]))
59
-
60
- require 'spec'
61
- require 'spec/autorun'
62
-
63
- require 'vcr'
64
-
65
- VCR.config do |c|
66
- c.cassette_library_dir = 'cassettes'
67
- c.http_stubbing_library = :fakeweb
68
- c.default_cassette_options = { :record => :new_episodes }
69
- end
70
-
71
- Spec::Runner.configure do |c|
72
- c.extend VCR::RSpec::Macros
73
- end
74
-
75
- describe "VCR-RSpec integration" do
76
- def make_http_request
77
- Net::HTTP.get_response('example.com', '/').body
78
- end
79
-
80
- context "without an explicit cassette name" do
81
- use_vcr_cassette
82
-
83
- it 'records an http request' do
84
- make_http_request.should =~ /You have reached this web page by typing.*example\.com/
85
- end
86
- end
87
-
88
- context "with an explicit cassette name" do
89
- use_vcr_cassette "net_http_example"
90
-
91
- it 'records an http request' do
92
- make_http_request.should =~ /You have reached this web page by typing.*example\.com/
93
- end
94
- end
95
- end
96
- """
97
- When I run "ruby -I'../../lib' ./use_vcr_cassette_for_rspec_1_spec.rb"
98
- Then the output should contain "2 examples, 0 failures"
99
- And the file "cassettes/VCR-RSpec_integration/without_an_explicit_cassette_name.yml" should contain "You have reached this web page by typing"
100
- And the file "cassettes/net_http_example.yml" should contain "You have reached this web page by typing"
@@ -1,7 +0,0 @@
1
- When /^I make an asynchronous HTTPClient get request to "([^\"]*)"$/ do |url|
2
- capture_response(url) do |uri, path|
3
- connection = HTTPClient.new.get_async(uri)
4
- connection.join
5
- connection.pop
6
- end
7
- end
@@ -1,49 +0,0 @@
1
- require 'open-uri'
2
-
3
- module NetHTTPHelpers
4
- def perform_net_http_get_with_returning_block(uri, path)
5
- Net::HTTP.new(uri.host, uri.port).request(Net::HTTP::Get.new(path, {})) do |response|
6
- return response
7
- end
8
- end
9
- end
10
- World(NetHTTPHelpers)
11
-
12
- When /^I make an asynchronous Net::HTTP get request to "([^\"]*)"$/ do |url|
13
- capture_response(url) do |uri, path|
14
- result = Net::HTTP.new(uri.host, uri.port).request_get(path) { |r| r.read_body { } }
15
- result.body.should be_a(Net::ReadAdapter)
16
- result
17
- end
18
- end
19
-
20
- When /^I make a replayed asynchronous Net::HTTP get request to "([^\"]*)"$/ do |url|
21
- capture_response(url) do |uri, path|
22
- result_body = ''
23
- result = Net::HTTP.new(uri.host, uri.port).request_get(path) { |r| r.read_body { |fragment| result_body << fragment } }
24
- def result_body.body; self; end # make the string a fake response (so response.body can be called on it)
25
- result_body
26
- end
27
- end
28
-
29
- When /^I make a recursive Net::HTTP post request to "([^\"]*)"$/ do |url|
30
- capture_response(url) do |uri, path|
31
- Net::HTTP.new(uri.host, uri.port).post(path, nil)
32
- end
33
- end
34
-
35
- When /^I make a returning block Net::HTTP get request to "([^\"]*)"$/ do |url|
36
- capture_response(url) do |uri, path|
37
- perform_net_http_get_with_returning_block(uri, path)
38
- end
39
- end
40
-
41
- When /^I make an open uri Net::HTTP get request to "([^"]*)"$/ do |url|
42
- capture_response(url) do |uri, path|
43
- result = open(url)
44
- # #open returns a StringIO rather than a Net::HTTPResponse, so we add #body to make it conform to the same interface
45
- def result.body; read; end
46
- result
47
- end
48
- end
49
-
@@ -1,252 +0,0 @@
1
- require 'tmpdir'
2
-
3
- RSpec::Matchers.define :have_expected_response do |regex_str, request_attributes|
4
- def matched_responses(responses, request_attributes)
5
- url, request_body, request_headers = request_attributes[:url], request_attributes[:request_body], request_attributes[:request_headers]
6
-
7
- selector = case url
8
- when String then lambda { |r| URI.parse(r.uri) == URI.parse(url) }
9
- when Regexp then lambda { |r| r.uri == url }
10
- else raise ArgumentError.new("Unexpected url: #{url.class.to_s}: #{url.inspect}")
11
- end
12
-
13
- matched = responses.select(&selector)
14
-
15
- if request_body
16
- matched = matched.select { |r| r.request.body == request_body }
17
- end
18
-
19
- (request_headers || {}).each do |r_key, r_val|
20
- matched = matched.select do |r|
21
- r.request.headers.any? { |k, v| k.downcase == r_key.downcase && v == [r_val] }
22
- end
23
- end
24
-
25
- matched
26
- end
27
-
28
- match do |responses|
29
- regex = /#{regex_str}/i
30
- matched_responses(responses, request_attributes).detect { |r| r.response.body =~ regex }
31
- end
32
-
33
- failure_message_for_should do |responses|
34
- url = request_attributes[:url]
35
- responses = matched_responses(responses, request_attributes)
36
- response_bodies = responses.map { |r| r.response.body }
37
- "expected a response for #{url.inspect} to match /#{regex_str}/. Responses for #{url.inspect}:\n\n #{response_bodies.join("\n\n")}"
38
- end
39
- end
40
-
41
- RSpec::Matchers.define :be_tagged_with do |tag|
42
- match do |scenario|
43
- scenario.source_tag_names.include?(tag)
44
- end
45
-
46
- failure_message_for_should do |scenario|
47
- "expected scenario to be tagged with #{tag}. Tags: #{scenario.source_tag_names.inspect}"
48
- end
49
- end
50
-
51
- RSpec::Matchers.define :have_normalized_headers do
52
- match do |object|
53
- headers = object.headers
54
- headers.is_a?(Hash) &&
55
- headers.keys.map { |k| k.downcase } == headers.keys &&
56
- headers.values.all? { |val| val.is_a?(Array) }
57
- end
58
-
59
- failure_message_for_should do |object|
60
- "expected headers to be normalized to have lower cased keys and arrays as values. Actual headers: #{object.headers.inspect}"
61
- end
62
- end
63
-
64
- module VCRHelpers
65
- def static_rack_server(response_string)
66
- orig_ignore_localhost = VCR.http_stubbing_adapter.ignore_localhost?
67
- VCR.http_stubbing_adapter.ignore_localhost = true
68
-
69
- begin
70
- VCR::LocalhostServer::STATIC_SERVERS[response_string]
71
- ensure
72
- VCR.http_stubbing_adapter.ignore_localhost = orig_ignore_localhost
73
- end
74
- end
75
-
76
- def recorded_interactions_for(cassette_name)
77
- interactions = YAML.load(File.read(file_name(cassette_name)))
78
- end
79
-
80
- def file_name(cassette_name)
81
- File.join(VCR::Config.cassette_library_dir, "#{cassette_name}.yml")
82
- end
83
-
84
- def capture_response(url)
85
- @http_requests ||= Hash.new([])
86
- uri = URI.parse(url)
87
- path = uri.path.to_s == '' ? '/' : uri.path
88
- begin
89
- result = yield uri, path
90
- rescue => e
91
- result = e
92
- end
93
- @http_requests[url] += [result]
94
- end
95
-
96
- end
97
- World(VCRHelpers)
98
-
99
- Given /^we do not have a "([^\"]*)" cassette$/ do |cassette_name|
100
- File.exist?(file_name(cassette_name)).should be_false
101
- end
102
-
103
- Given /^we have a "([^\"]*)" library file with (a|no) previously recorded response for "([^\"]*)"$/ do |cassette_name, a_or_no, url|
104
- fixture_file = file_name(cassette_name)
105
- File.exist?(fixture_file).should be_true
106
- responses = File.open(fixture_file, 'r') { |f| YAML.load(f.read) }
107
- should_method = a_or_no == 'a' ? :should : :should_not
108
- responses.map{ |r| URI.parse(r.uri) }.send(should_method, include(URI.parse(url)))
109
- end
110
-
111
- Given /^the "([^\"]*)" library file has a response for "([^\"]*)" that matches \/(.+)\/$/ do |cassette_name, url, regex_str|
112
- Given %{we have a "#{cassette_name}" library file with a previously recorded response for "#{url}"}
113
- Then %{the "#{cassette_name}" library file should have a response for "#{url}" that matches /#{regex_str}/}
114
- end
115
-
116
- Given /^the "([^\"]*)" library file has a response for \/(\S+)\/ that matches \/(.+)\/$/ do |cassette_name, url_regex, body_regex|
117
- recorded_interactions_for(cassette_name).should have_expected_response(body_regex, :url => /#{url_regex}/)
118
- end
119
-
120
- Given /^the "([^"]*)" library file has a response for "([^"]*)" with the request body "([^"]*)" that matches \/(.+)\/$/ do |cassette_name, url, request_body, response_regex|
121
- recorded_interactions_for(cassette_name).should have_expected_response(response_regex, :url => url, :request_body => request_body)
122
- end
123
-
124
- Given /^the "([^"]*)" library file has a response for "([^"]*)" with the request header "([^"]*)=([^"]*)" that matches \/(.+)\/$/ do |cassette_name, url, header_key, header_value, response_regex|
125
- recorded_interactions_for(cassette_name).should have_expected_response(response_regex, :url => url, :request_headers => { header_key => header_value })
126
- end
127
-
128
- Given /^this scenario is tagged with the vcr cassette tag: "([^\"]+)"$/ do |tag|
129
- VCR.current_cucumber_scenario.should be_tagged_with(tag)
130
- VCR::CucumberTags.tags.should include(tag)
131
- end
132
-
133
- Given /^the previous scenario was tagged with the vcr cassette tag: "([^\"]*)"$/ do |tag|
134
- last_scenario = VCR.completed_cucumber_scenarios.last
135
- last_scenario.should_not be_nil
136
- last_scenario.should be_tagged_with(tag)
137
- VCR::CucumberTags.tags.should include(tag)
138
- end
139
-
140
- When /^I make (?:an )?HTTP get request to "([^\"]*)"$/ do |url|
141
- capture_response(url) do |uri, path|
142
- make_http_request(:get, url)
143
- end
144
- end
145
-
146
- When /^I make an HTTP post request to "([^"]*)" with request body "([^"]*)"$/ do |url, request_body|
147
- capture_response(url) do |uri, path|
148
- make_http_request(:post, url, request_body)
149
- end
150
- end
151
-
152
- When /^I make an HTTP post request to "([^"]*)" with request header "([^"]*)=([^"]*)"$/ do |url, header_key, header_val|
153
- capture_response(url) do |uri, path|
154
- make_http_request(:post, url, '', { header_key => header_val })
155
- end
156
- end
157
-
158
- When /^I make (.*) requests? to "([^\"]*)"(?: and "([^\"]*)")? while using the "([^\"]*)" cassette(?: using cassette options: (.*))?$/ do |http_request_type, url1, url2, cassette_name, options|
159
- options = options.to_s == '' ? { :record => :new_episodes } : eval(options)
160
- urls = [url1, url2].select { |u| u.to_s.size > 0 }
161
- VCR.use_cassette(cassette_name, options) do
162
- urls.each do |url|
163
- When %{I make #{http_request_type} request to "#{url}"}
164
- end
165
- end
166
- end
167
-
168
- When /^I make an HTTP post request to "([^"]*)" with request body "([^"]*)" while using the "([^"]*)" cassette(?: using cassette options: (.*))?$/ do |url, request_body, cassette_name, options|
169
- options = options.to_s == '' ? { :record => :new_episodes } : eval(options)
170
- VCR.use_cassette(cassette_name, options) do
171
- When %{I make an HTTP post request to "#{url}" with request body "#{request_body}"}
172
- end
173
- end
174
-
175
- When /^I make an HTTP post request to "([^"]*)" with request header "([^"]*)=([^"]*)" while using the "([^"]*)" cassette(?: using cassette options: (.*))?$/ do |url, header_key, header_value, cassette_name, options|
176
- options = options.to_s == '' ? { :record => :new_episodes } : eval(options)
177
- VCR.use_cassette(cassette_name, options) do
178
- When %{I make an HTTP post request to "#{url}" with request header "#{header_key}=#{header_value}"}
179
- end
180
- end
181
-
182
- Then /^the "([^\"]*)" library file (should(?: not)?) have a response for "([^\"]*)" that matches \/(.+)\/$/ do |cassette_name, expectation, url, regex_str|
183
- expectation = expectation.gsub(' ', '_')
184
- interactions = recorded_interactions_for(cassette_name)
185
- interactions.send(expectation, have_expected_response(regex_str, :url => url))
186
- end
187
-
188
- Then /^the "([^\"]*)" library file should have exactly (\d+) response$/ do |cassette_name, response_count|
189
- interactions = recorded_interactions_for(cassette_name)
190
- interactions.should have(response_count.to_i).responses
191
- end
192
-
193
- Then /^the "([^"]*)" library file should have normalized headers for all recorded interactions$/ do |cassette_name|
194
- interactions = recorded_interactions_for(cassette_name)
195
- interactions.each do |i|
196
- i.request.should have_normalized_headers
197
- i.response.should have_normalized_headers
198
- end
199
- end
200
-
201
- Then /^I can test the scenario cassette's recorded responses in the next scenario, after the cassette has been ejected$/ do
202
- # do nothing...
203
- end
204
-
205
- Then /^the HTTP get request to "([^\"]*)" should result in an error that mentions VCR$/ do |url|
206
- result = @http_requests[url][0]
207
- result.should be_a(StandardError)
208
- result.message.should =~ /VCR/
209
- end
210
-
211
- Then /^(?:the )?response(?: (\d+))? for "([^\"]*)" should match \/(.+)\/$/ do |response_num, url, regex_str|
212
- response_num = response_num.to_i || 0
213
- response_num -= 1 if response_num > 0 # translate to 0-based array index.
214
- regex = /#{regex_str}/i
215
- response = @http_requests[url][response_num]
216
- raise response if response.is_a?(Exception)
217
- get_body_string(response).should =~ regex
218
- end
219
-
220
- Then /^there should not be a "([^\"]*)" library file$/ do |cassette_name|
221
- File.exist?(file_name(cassette_name)).should be_false
222
- end
223
-
224
- Given /^the ignore_localhost config setting is set to (true|false)$/ do |value|
225
- VCR::Config.ignore_localhost = eval(value)
226
- end
227
-
228
- Given /^a rack app is running on localhost that returns "([^"]+)" for all requests$/ do |response_string|
229
- @rack_server = static_rack_server(response_string)
230
- end
231
-
232
- When /^I make an HTTP get request to the localhost rack app while using the "([^\"]*)" cassette$/ do |cassette|
233
- When %{I make an HTTP get request to "http://localhost:#{@rack_server.port}/" while using the "#{cassette}" cassette}
234
- end
235
-
236
- Then /^the response for the localhost rack app should match \/(.*)\/$/ do |regex|
237
- Then %{the response for "http://localhost:#{@rack_server.port}/" should match /#{regex}/}
238
- end
239
-
240
- Given /^the "([^\"]*)" library file has a response for localhost that matches \/(.*)\/$/ do |cassette, regex|
241
- port = static_rack_server('localhost response').port
242
- Given %{the "#{cassette}" library file has a response for "http://localhost:#{port}/" that matches /#{regex}/}
243
- end
244
-
245
- Given /^(\d+) days have passed since the "([^"]*)" library file last changed$/ do |day_count, file|
246
- last_changed_at = File.new(file_name(file)).mtime
247
- Timecop.travel(last_changed_at + day_count.to_i.days)
248
- end
249
-
250
- Given /the following files do not exist:/ do |files|
251
- check_file_presence(files.raw.map{|file_row| file_row[0]}, false)
252
- end