vcr.rb 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. VCR.configure do |config|
  2. config.cassette_library_dir = 'test/data/vcr_cassettes'
  3. config.hook_into :webmock
  4. config.allow_http_connections_when_no_cassette = false
  5. config.ignore_localhost = true
  6. config.ignore_request do |request|
  7. uri = URI(request.uri)
  8. ['zammad.com', 'google.com', 'elasticsearch', 'selenium'].any? do |site|
  9. uri.host.include?(site)
  10. end
  11. end
  12. config.register_request_matcher(:oauth_headers) do |r1, r2|
  13. without_onetime_oauth_params = ->(params) { params.gsub(/oauth_(nonce|signature|timestamp)="[^"]+", /, '') }
  14. r1.headers.except('Authorization') == r2.headers.except('Authorization') &&
  15. r1.headers['Authorization']&.map(&without_onetime_oauth_params) ==
  16. r2.headers['Authorization']&.map(&without_onetime_oauth_params)
  17. end
  18. end
  19. module VCRHelper
  20. def self.auto_record(example)
  21. spec_path = Pathname.new(example.file_path).realpath
  22. cassette_path = spec_path.relative_path_from(Rails.root.join('spec')).sub(/_spec\.rb$/, '')
  23. cassette_name = "#{example.example_group.description} #{example.description}".gsub(/[^0-9A-Za-z.\-]+/, '_').downcase
  24. request_profile = case example.metadata[:use_vcr]
  25. when true
  26. %i[method uri]
  27. when :with_oauth_headers
  28. %i[method uri oauth_headers]
  29. end
  30. VCR.use_cassette(cassette_path.join(cassette_name), match_requests_on: request_profile) do
  31. example.run
  32. end
  33. end
  34. end
  35. module RSpec
  36. VCR_ADVISORY = <<~MSG.freeze
  37. If this test is failing unexpectedly, the VCR cassette may be to blame.
  38. This can happen when changing `describe`/`context` labels on some specs;
  39. see commit message 1ebddff95 for details.
  40. Check `git status` to see if a new VCR cassette has been generated.
  41. If so, rename the old cassette to replace the new one and try again.
  42. MSG
  43. module Support
  44. module VCRHelper
  45. def self.inject_advisory(example)
  46. # block argument is an #<RSpec::Expectations::ExpectationNotMetError>
  47. define_method(:notify_failure) do |e|
  48. super(e.exception(VCR_ADVISORY + e.message))
  49. end
  50. example.run
  51. ensure
  52. remove_method(:notify_failure)
  53. end
  54. end
  55. singleton_class.send(:prepend, VCRHelper)
  56. end
  57. module Expectations
  58. module VCRHelper
  59. def self.inject_advisory(example)
  60. define_method(:handle_matcher) do |*args|
  61. super(*args)
  62. rescue => e
  63. raise e.exception(VCR_ADVISORY + e.message)
  64. end
  65. example.run
  66. ensure
  67. remove_method(:handle_matcher)
  68. end
  69. end
  70. PositiveExpectationHandler.singleton_class.send(:prepend, VCRHelper)
  71. NegativeExpectationHandler.singleton_class.send(:prepend, VCRHelper)
  72. end
  73. end
  74. RSpec.configure do |config|
  75. config.around(:each, use_vcr: true, &VCRHelper.method(:auto_record))
  76. config.around(:each, use_vcr: true, &RSpec::Support::VCRHelper.method(:inject_advisory))
  77. config.around(:each, use_vcr: true, &RSpec::Expectations::VCRHelper.method(:inject_advisory))
  78. end