From 1f70077f73d176ab577a50033b6762b7a6d70772 Mon Sep 17 00:00:00 2001 From: Alex Taylor Date: Fri, 20 Mar 2020 13:38:30 -0700 Subject: [PATCH] Add option to downcase cassette names before saving (#802) * Add option to downcase cassette names before saving * Update debugging feature spec to include new option * Document the downcase_cassette_names persister option Co-Authored-By: Alex Taylor Co-authored-by: Olle Jonsson --- features/configuration/debug_logging.feature | 4 ++-- lib/vcr.rb | 6 ++++++ lib/vcr/cassette.rb | 2 +- lib/vcr/cassette/persisters/file_system.rb | 10 +++++++++- lib/vcr/configuration.rb | 3 ++- spec/lib/vcr/cassette/persisters/file_system_spec.rb | 12 ++++++++++++ spec/lib/vcr/configuration_spec.rb | 3 ++- 7 files changed, 34 insertions(+), 6 deletions(-) diff --git a/features/configuration/debug_logging.feature b/features/configuration/debug_logging.feature index 8b833b3d..80bdc053 100644 --- a/features/configuration/debug_logging.feature +++ b/features/configuration/debug_logging.feature @@ -34,7 +34,7 @@ Feature: Debug Logging Given that port numbers in "record.log" are normalized to "7777" Then the file "record.log" should contain exactly: """ - [Cassette: 'example'] Initialized with options: {:record=>:once, :record_on_error=>true, :match_requests_on=>[:method, :host, :path], :allow_unused_http_interactions=>true, :serialize_with=>:yaml, :persist_with=>:file_system} + [Cassette: 'example'] Initialized with options: {:record=>:once, :record_on_error=>true, :match_requests_on=>[:method, :host, :path], :allow_unused_http_interactions=>true, :serialize_with=>:yaml, :persist_with=>:file_system, :persister_options=>{}} [webmock] Handling request: [get http://localhost:7777/] (disabled: false) [Cassette: 'example'] Initialized HTTPInteractionList with request matchers [:method, :host, :path] and 0 interaction(s): { } [webmock] Identified request type (recordable) for [get http://localhost:7777/] @@ -44,7 +44,7 @@ Feature: Debug Logging Given that port numbers in "playback.log" are normalized to "7777" Then the file "playback.log" should contain exactly: """ - [Cassette: 'example'] Initialized with options: {:record=>:once, :record_on_error=>true, :match_requests_on=>[:method, :host, :path], :allow_unused_http_interactions=>true, :serialize_with=>:yaml, :persist_with=>:file_system} + [Cassette: 'example'] Initialized with options: {:record=>:once, :record_on_error=>true, :match_requests_on=>[:method, :host, :path], :allow_unused_http_interactions=>true, :serialize_with=>:yaml, :persist_with=>:file_system, :persister_options=>{}} [webmock] Handling request: [get http://localhost:7777/] (disabled: false) [Cassette: 'example'] Initialized HTTPInteractionList with request matchers [:method, :host, :path] and 1 interaction(s): { [get http://localhost:7777/] => [200 "Hello World"] } [Cassette: 'example'] Checking if [get http://localhost:7777/] matches [get http://localhost:7777/] using [:method, :host, :path] diff --git a/lib/vcr.rb b/lib/vcr.rb index 99abb050..00d2e7c1 100644 --- a/lib/vcr.rb +++ b/lib/vcr.rb @@ -107,6 +107,12 @@ def current_cassette # @option options :persist_with [Symbol] Which cassette persister to # use. Defaults to :file_system. You can also register and use a # custom persister. + # @option options :persister_options [Hash] Pass options to the + # persister specified in `persist_with`. Currently available options for the file_system persister: + # - `:downcase_cassette_names`: when `true`, names of cassettes will be + # normalized in lowercase before reading and writing, which can avoid + # confusion when using both case-sensitive and case-insensitive file + # systems. # @option options :preserve_exact_body_bytes [Boolean] Whether or not # to base64 encode the bytes of the requests and responses for this cassette # when serializing it. See also `VCR::Configuration#preserve_exact_body_bytes`. diff --git a/lib/vcr/cassette.rb b/lib/vcr/cassette.rb index e9050767..d9272908 100644 --- a/lib/vcr/cassette.rb +++ b/lib/vcr/cassette.rb @@ -176,7 +176,7 @@ def assert_valid_options! :record, :record_on_error, :erb, :match_requests_on, :re_record_interval, :tag, :tags, :update_content_length_header, :allow_playback_repeats, :allow_unused_http_interactions, :exclusive, :serialize_with, :preserve_exact_body_bytes, :decode_compressed_response, - :recompress_response, :persist_with, :clean_outdated_http_interactions + :recompress_response, :persist_with, :persister_options, :clean_outdated_http_interactions ] if invalid_options.size > 0 diff --git a/lib/vcr/cassette/persisters/file_system.rb b/lib/vcr/cassette/persisters/file_system.rb index f0a25c16..21547168 100644 --- a/lib/vcr/cassette/persisters/file_system.rb +++ b/lib/vcr/cassette/persisters/file_system.rb @@ -55,7 +55,15 @@ def sanitized_file_name_from(file_name) file_extension = '.' + parts.pop end - parts.join('.').gsub(/[^[:word:]\-\/]+/, '_') + file_extension.to_s + file_name = parts.join('.').gsub(/[^[:word:]\-\/]+/, '_') + file_extension.to_s + file_name.downcase! if downcase_cassette_names? + file_name + end + + def downcase_cassette_names? + !!VCR.configuration + .default_cassette_options + .dig(:persister_options, :downcase_cassette_names) end end end diff --git a/lib/vcr/configuration.rb b/lib/vcr/configuration.rb index adbc79ac..d02ca650 100644 --- a/lib/vcr/configuration.rb +++ b/lib/vcr/configuration.rb @@ -496,7 +496,8 @@ def initialize :match_requests_on => RequestMatcherRegistry::DEFAULT_MATCHERS, :allow_unused_http_interactions => true, :serialize_with => :yaml, - :persist_with => :file_system + :persist_with => :file_system, + :persister_options => {} } self.uri_parser = URI diff --git a/spec/lib/vcr/cassette/persisters/file_system_spec.rb b/spec/lib/vcr/cassette/persisters/file_system_spec.rb index e1dfe460..18ae3bd2 100644 --- a/spec/lib/vcr/cassette/persisters/file_system_spec.rb +++ b/spec/lib/vcr/cassette/persisters/file_system_spec.rb @@ -64,12 +64,24 @@ class Persisters expected = File.join(FileSystem.storage_location, "\u842c\u570b\u78bc") expect(FileSystem.absolute_path_to_file("\u842c\u570b\u78bc")).to eq(expected) + + expected = File.join(FileSystem.storage_location, "Uppercase_Cassette.yml") + expect(FileSystem.absolute_path_to_file("Uppercase_Cassette.yml")).to eq(expected) end it 'handles files with no extensions (even when there is a dot in the path)' do expected = File.join(FileSystem.storage_location, "/foo_bar/baz_qux") expect(FileSystem.absolute_path_to_file("/foo.bar/baz qux")).to eq(expected) end + + it 'downcases cassette names if the option is passed' do + VCR.configuration.default_cassette_options.merge!( + { :persister_options => { :downcase_cassette_names => true } } + ) + + expected = File.join(FileSystem.storage_location, "/path/to/cassette") + expect(FileSystem.absolute_path_to_file("/pAtH/tO/CaSsEtTe")).to eq(expected) + end end end end diff --git a/spec/lib/vcr/configuration_spec.rb b/spec/lib/vcr/configuration_spec.rb index 182bf4fc..1aca6ec2 100644 --- a/spec/lib/vcr/configuration_spec.rb +++ b/spec/lib/vcr/configuration_spec.rb @@ -29,7 +29,8 @@ :record => :once, :record_on_error => true, :serialize_with => :yaml, - :persist_with => :file_system + :persist_with => :file_system, + :persister_options => {} }) end