Skip to content

Commit c33f9e9

Browse files
authored
Merge pull request #16 from RadiusNetworks/common-vcr-setup
Add common VCR configuration
2 parents b042748 + c8faddb commit c33f9e9

File tree

11 files changed

+431
-0
lines changed

11 files changed

+431
-0
lines changed

CHANGELOG.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,17 @@
44

55
### Enhancements
66

7+
- Add common VCR configuration (Aaron Kromer, #16)
8+
- Filters out `Authorization` headers
9+
- Filters out the following sensitive/environment varying `ENV` values, as
10+
well as their URL and form encoded variants:
11+
- `AWS_ACCESS_KEY_ID`
12+
- `AWS_SECRET_ACCESS_KEY`
13+
- `GOOGLE_CLIENT_ID`
14+
- `GOOGLE_CLIENT_SECRET`
15+
- `RADIUS_OAUTH_PROVIDER_APP_ID`
16+
- `RADIUS_OAUTH_PROVIDER_APP_SECRET`
17+
- `RADIUS_OAUTH_PROVIDER_URL`
718
- Add "temp file" helpers for working with file stubs (Aaron Kromer, #15)
819
- Upgrade to Rubocop 0.59.x (Aaron Kromer, #14)
920
- Adjust common Rubocop configuration (Aaron Kromer, #14)

README.md

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -719,6 +719,61 @@ There are a few additional behaviors to note:
719719
end
720720
```
721721

722+
### Common VCR Configuration
723+
724+
A project must include both [`vcr`](https://rubygems.org/gems/vcr) and
725+
[`webmock`](https://rubygems.org/gems/webmock) to use this configuration.
726+
Neither of those gems will be installed as dependencies of this gem. This is
727+
intended to give projects more flexibility in choosing which additional features
728+
they will use.
729+
730+
The main `radius/spec/rspec` setup will load the common VCR configuration
731+
automatically when a spec is tagged with the `:vcr` metadata. This will
732+
configure VCR to:
733+
734+
- save specs to `/spec/cassettes`
735+
736+
- use record mode `once` when a single spec or spec file is run
737+
738+
This helps ease the development of new specs without requiring any
739+
configuration / setting changes.
740+
741+
- uses record mode `none` otherwise, along setting VCR to fail when unused
742+
interactions remain in a cassette
743+
744+
This is intended to better alert developers to unexpected side effects of
745+
changes as any addition or removal of a request will cause a failure.
746+
747+
- all `Authorization` HTTP headers are filtered by default
748+
749+
This is a common oversight when recording specs. Often token based
750+
authentication is picked up by the other filtered environment settings, but
751+
basic authentication is not. Additionally, certain types of digest
752+
authentication may cause specs to leak state. This filtering guards all of
753+
these cases from accidental credential leak.
754+
755+
- the following common sensitive, or often environment variable, settings are
756+
filtered
757+
758+
Those settings which often change between developer machines, and even the
759+
CI server, can cause for flaky specs. It may also be frustrating for
760+
developers to have to adjust their local systems to match others just to
761+
get a few specs to pass. This is intended to help mitigate those issues:
762+
763+
- `AWS_ACCESS_KEY_ID`
764+
- `AWS_SECRET_ACCESS_KEY`
765+
- `GOOGLE_CLIENT_ID`
766+
- `GOOGLE_CLIENT_SECRET`
767+
- `RADIUS_OAUTH_PROVIDER_APP_ID`
768+
- `RADIUS_OAUTH_PROVIDER_APP_SECRET`
769+
- `RADIUS_OAUTH_PROVIDER_URL`
770+
771+
- a project's local `support/vcr.rb` file will be loaded after the common
772+
VCR configuration loads; if it's available
773+
774+
This allows projects to overwrite common settings if they need to, as well,
775+
as add on addition settings or filtering of data.
776+
722777
## Development
723778

724779
After checking out the repo, run `bin/setup` to install dependencies. Then, run

common_rubocop.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,10 @@ Metrics/BlockLength:
106106
- 'spec/spec_helper.rb'
107107
- 'spec/**/*_spec.rb'
108108
- 'spec/support/model_factories.rb'
109+
ExcludedMethods:
110+
- 'refine'
111+
- 'RSpec.configure'
112+
- 'VCR.configure'
109113

110114
# We generally prefer to use the default line length of 80. Though sometimes
111115
# we just need a little extra space because it makes it easier to read.

lib/radius/spec/rspec.rb

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,14 @@
148148
require 'radius/spec/model_factory'
149149
config.include Radius::Spec::ModelFactory, type: :system
150150
end
151+
152+
config.when_first_matching_example_defined(:webmock) do
153+
require 'webmock/rspec'
154+
end
155+
156+
config.when_first_matching_example_defined(:vcr, :vcr_record, :vcr_record_new) do
157+
require 'radius/spec/vcr'
158+
end
151159
end
152160

153161
require 'radius/spec/rspec/negated_matchers'

lib/radius/spec/vcr.rb

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
# frozen_string_literal: true
2+
3+
require 'webmock/rspec'
4+
require 'vcr'
5+
6+
VCR.configure do |config|
7+
config.cassette_library_dir = "spec/cassettes"
8+
config.hook_into :webmock
9+
config.configure_rspec_metadata!
10+
config.ignore_localhost = true
11+
12+
record_mode = case
13+
when RSpec.configuration.files_to_run.one?
14+
# When developing new features we often run new specs in
15+
# isolation as we write the code. This is the time to allow
16+
# creating the cassettes.
17+
:once
18+
when ENV['CI']
19+
# Never let CI record
20+
:none
21+
else
22+
# Default to blocking new requests to catch issues
23+
:none
24+
end
25+
config.default_cassette_options = {
26+
record: record_mode,
27+
28+
# Required for working proxy
29+
update_content_length_header: true,
30+
31+
# Raise errors when recorded cassettes no longer match interactions
32+
allow_unused_http_interactions: false,
33+
}
34+
35+
# Filter out common sensitive or environment specific data
36+
%w[
37+
AWS_ACCESS_KEY_ID
38+
AWS_SECRET_ACCESS_KEY
39+
GOOGLE_CLIENT_ID
40+
GOOGLE_CLIENT_SECRET
41+
RADIUS_OAUTH_PROVIDER_APP_ID
42+
RADIUS_OAUTH_PROVIDER_APP_SECRET
43+
RADIUS_OAUTH_PROVIDER_URL
44+
].each do |secret|
45+
config.filter_sensitive_data("<#{secret}>") { ENV[secret] }
46+
47+
config.filter_sensitive_data("<#{secret}_FORM>") {
48+
URI.encode_www_form_component(ENV[secret]) if ENV[secret]
49+
}
50+
51+
config.filter_sensitive_data("<#{secret}_URI>") {
52+
ERB::Util.url_encode(ENV[secret]) if ENV[secret]
53+
}
54+
55+
config.filter_sensitive_data('<AUTHORIZATION_HEADER>') { |interaction|
56+
interaction.request.headers['Authorization']&.first
57+
}
58+
end
59+
end
60+
61+
RSpec.configure do |config|
62+
{
63+
vcr_record: :once,
64+
vcr_record_new: :new_episodes,
65+
}.each do |tag, record_mode|
66+
config.define_derived_metadata(tag) do |metadata|
67+
case metadata[:vcr]
68+
when nil, true
69+
metadata[:vcr] = { record: record_mode }
70+
when Hash
71+
metadata[:vcr][:record] = record_mode
72+
else
73+
raise "Unknown VCR metadata value: #{metadata[:vcr].inspect}"
74+
end
75+
end
76+
end
77+
78+
config.define_derived_metadata(:focus) do |metadata|
79+
# VCR is flagged as falsey
80+
next if metadata.key?(:vcr) && !metadata[:vcr]
81+
82+
case metadata[:vcr]
83+
when nil, true
84+
metadata[:vcr] = { record: :once }
85+
when Hash
86+
metadata[:vcr][:record] ||= :once
87+
else
88+
raise "Unknown VCR metadata value: #{metadata[:vcr].inspect}"
89+
end
90+
end
91+
end
92+
93+
# Try to any custom VCR config for the app
94+
# rubocop:disable Lint/HandleExceptions
95+
begin
96+
require 'support/vcr'
97+
rescue LoadError
98+
# Ignore as this is an optional convenience feature
99+
end
100+
# rubocop:enable Lint/HandleExceptions

spec/cassettes/Radius_Spec_VCR/configures_VCR_to_filter_authorization_headers.yml

Lines changed: 67 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

spec/cassettes/Radius_Spec_VCR/configures_VCR_to_filter_common_data_even_when_encoded.yml

Lines changed: 34 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

spec/cassettes/Radius_Spec_VCR/configures_VCR_to_filter_common_secret_and_environment_data.yml

Lines changed: 32 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

spec/cassettes/unused_interactions.yml

Lines changed: 32 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)