vcr-log_unmatched_cassettes 0.0.1 → 0.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5715a8e1d849e98faea2e124290b2fa5d4b74a3e75f7feced17ad4b64457e115
4
- data.tar.gz: 7a51740f8bcae35c1ddb986e143a21b5182a9e7b9c38e17a4257428958b18269
3
+ metadata.gz: 6d72754d5764e97b62b6ea59ee4a147d4a9534dc8aafd00d22d57c461ebc1a71
4
+ data.tar.gz: 1811f85b5fd64fdfbc75d6f4c5baf1e609b57d0864cf5c883c1bd7ee7904b0b9
5
5
  SHA512:
6
- metadata.gz: e2cd3c15a2d8a73d93e6a9d78d64cf09436c43191a8dad13064f2f4b13287920e276ac397d41b2b438f9c0a5c413d146deb34df4f1731ab7ad062f8caad213eb
7
- data.tar.gz: 67c3705c67566b056274f65fa397b82c95692c8fc5ee2db8de5f6233010be4251d11b719d005dd08f9699fb0f4aceb7fa313b923ae7ed07f49f93ca7d462f51b
6
+ metadata.gz: 38e933db7f083f77c926580f00c75fbb058fb8c175769d6f7852427384272a947f2af3a0ae3b33b5884bc3ebfba6192436a0b8730257789e5700ffe06ddeb973
7
+ data.tar.gz: f164ffa88ca3f56c519d2b1fb08774e428e44be35ee811ef1936ac58911e38dda155debb876e6248579df72358314eb962ad060dcc7ef78d15d14f2b603e6594
data/README.md CHANGED
@@ -1,5 +1,7 @@
1
1
  # VCR::LogUnmatchedCassettes
2
2
 
3
+ [![Ruby](https://github.com/sshaw/vcr-log_unmatched_cassettes/actions/workflows/main.yml/badge.svg?branch=master)](https://github.com/sshaw/vcr-log_unmatched_cassettes/actions/workflows/main.yml)
4
+
3
5
  Make finding and re-recording unmatched [VCR cassettes](https://github.com/vcr/vcr) (test that fail due to `VCR::Errors::UnhandledHTTPRequestError`)
4
6
  easier by logging the test and unmatched cassette paths to a CSV.
5
7
 
@@ -8,7 +10,8 @@ easier by logging the test and unmatched cassette paths to a CSV.
8
10
  In your `Gemfile`
9
11
 
10
12
  ```rb
11
- gem "vcr-log_unmatched_cassettes", :group => "test"
13
+ # development for Rake task access
14
+ gem "vcr-log_unmatched_cassettes", :group => %w[test development]
12
15
  ```
13
16
 
14
17
  In your spec configuration, after loading VCR, call:
@@ -16,9 +19,26 @@ In your spec configuration, after loading VCR, call:
16
19
  VCR::LogUnmatchedCassettes.install
17
20
  ```
18
21
 
19
- Now tests that fails due to VCR being able to unmatch the request (`VCR::Errors::UnhandledHTTPRequestError`) will be output to the system's temp directory in a CSV.
22
+ Now tests that fail due to VCR being able to unmatch the request (`VCR::Errors::UnhandledHTTPRequestError`) will be output to the system's temp directory in a CSV.
20
23
  If you're using Rails it will be output to `./tmp`.
21
24
 
25
+ ## Deleting Cassettes
26
+
27
+ Load the Rake task to delete cassettes listed in the `cassette` column of the latest report:
28
+
29
+ ```rb
30
+ # Rakefile
31
+ require "vcr/log_unmatched_cassettes/rake"
32
+ ```
33
+
34
+ Then run:
35
+
36
+ ```
37
+ rake vcr:log_unmatched_cassettes:delete_cassettes
38
+ ```
39
+
40
+ Under Rails it is loaded automatically via a Railtie.
41
+
22
42
  ## Why?
23
43
 
24
44
  When tests fail due to unmatched HTTP requests the path is output within a large blob of text. This may be fine for a couple of tests but
@@ -28,7 +48,11 @@ Often one needs the path solely to delete the cassette and re-record it. This is
28
48
 
29
49
  `record: :all` can be applied per test, but this requires modifying the test so that it can be scoped to `:all`.
30
50
 
31
- Remove all cassettes is an option but this can clutter your git history with needless and _very_ bloated diffs.
51
+ Removing all cassettes is an option but this can clutter your git history with needless and _very_ bloated diffs.
52
+
53
+ ## See Also
54
+
55
+ [vcr-unused_cassettes](https://github.com/jbockler/vcr-unused_cassettes) - Find unused VCR cassettes
32
56
 
33
57
  ## License
34
58
 
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ module VCR
4
+ module LogUnmatchedCassettes
5
+ class Railtie < ::Rails::Railtie
6
+ rake_tasks do
7
+ load File.expand_path("rake.rb", __dir__)
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,77 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "rake"
4
+ require "csv"
5
+ require "fileutils"
6
+ require "vcr/log_unmatched_cassettes"
7
+
8
+ module VCR
9
+ module LogUnmatchedCassettes
10
+ module Rake
11
+ class << self
12
+ # Deletes the files listed in the +cassette+ column of the latest
13
+ # report and returns the paths that were removed.
14
+ def delete_cassettes(report = latest_report_file)
15
+ return [] unless report && File.file?(report)
16
+
17
+ report_path = File.expand_path(report)
18
+ deleted = []
19
+
20
+ CSV.foreach(report, headers: true) do |row|
21
+ path = row["cassette"]
22
+ next if path.nil? || path.strip.empty?
23
+
24
+ path = File.expand_path(path)
25
+ next if path == report_path || deleted.include?(path) || !File.file?(path)
26
+
27
+ FileUtils.rm(path)
28
+ deleted << path
29
+ end
30
+
31
+ deleted
32
+ end
33
+
34
+ private
35
+
36
+ # The most recently written report. Reports from previous runs are
37
+ # ignored, as their cassettes have presumably been dealt with already.
38
+ def latest_report_file
39
+ Dir[File.join(report_dir, "#{REPORT_PREFIX}.*.csv")]
40
+ .select { |path| File.file?(path) }
41
+ .max_by { |path| [File.mtime(path), File.basename(path)] }
42
+ end
43
+
44
+ def report_dir
45
+ LogUnmatchedCassettes.output_dir || LogUnmatchedCassettes.default_output_dir
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
51
+
52
+ namespace :vcr do
53
+ namespace :log_unmatched_cassettes do
54
+ desc "Delete the cassettes listed in the latest vcr-unmatched-cassettes report"
55
+ task :delete_cassettes do
56
+ log = VCR::LogUnmatchedCassettes
57
+ tasks = VCR::LogUnmatchedCassettes::Rake
58
+
59
+ if log.enabled == false
60
+ warn "[VCR::LogUnmatchedCassettes] Disabled, not deleting anything."
61
+ next
62
+ end
63
+
64
+ dir = log.output_dir || log.default_output_dir
65
+ deleted = tasks.delete_cassettes
66
+
67
+ if deleted.empty?
68
+ warn "[VCR::LogUnmatchedCassettes] Nothing to delete from the latest report in #{dir}."
69
+ next
70
+ end
71
+
72
+ warn "[VCR::LogUnmatchedCassettes] Deleted #{deleted.size} cassette(s) from the latest report in #{dir}:"
73
+
74
+ deleted.each { |path| warn " #{path}" }
75
+ end
76
+ end
77
+ end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module VCR
4
4
  module LogUnmatchedCassettes
5
- VERSION = "0.0.1"
5
+ VERSION = "0.0.2"
6
6
  end
7
7
  end
@@ -7,6 +7,13 @@ require "csv"
7
7
 
8
8
  module VCR
9
9
  module LogUnmatchedCassettes
10
+ REPORT_PREFIX = "vcr-unmatched-cassettes"
11
+
12
+ # Sentinels from VCR's UnhandledHTTPRequestError message. Used as a fallback
13
+ # when the exception class itself can no longer be reached (see
14
+ # `find_vcr_error`).
15
+ UNHANDLED_REQUEST_MESSAGE = "An HTTP request has been made that VCR does not know how to handle"
16
+
10
17
  module MinitestHook # :nodoc:
11
18
  # Minitest stores the test's exception by running it through
12
19
  # `sanitize_exception` in `capture_exceptions`. A marshable exception is
@@ -41,7 +48,7 @@ module VCR
41
48
 
42
49
  def install
43
50
  self.enabled = true if enabled.nil?
44
- self.output_dir = defined?(Rails) && Rails.respond_to?(:root) ? Rails.root.join("tmp").to_s : Dir.tmpdir
51
+ self.output_dir = default_output_dir
45
52
 
46
53
  @failures = []
47
54
 
@@ -54,6 +61,14 @@ module VCR
54
61
  end
55
62
  end
56
63
 
64
+ def default_output_dir
65
+ if defined?(Rails) && Rails.respond_to?(:root) && Rails.root
66
+ Rails.root.join("tmp").to_s
67
+ else
68
+ Dir.tmpdir
69
+ end
70
+ end
71
+
57
72
  def record(location, cassette_path)
58
73
  return if !enabled || cassette_path.nil? || cassette_path.empty?
59
74
 
@@ -66,7 +81,7 @@ module VCR
66
81
  FileUtils.mkdir_p(output_dir)
67
82
 
68
83
  timestamp = Time.now.strftime("%Y%m%d%H%M%S")
69
- filename = File.join(output_dir, "vcr-unmatched-cassettes.#{timestamp}.csv")
84
+ filename = File.join(output_dir, "#{REPORT_PREFIX}.#{timestamp}.csv")
70
85
 
71
86
  CSV.open(filename, "w") do |csv|
72
87
  csv << %w[test cassette]
@@ -79,12 +94,20 @@ module VCR
79
94
  warn "\n[VCR::LogUnmatchedCassettes] Wrote #{@failures.size} failed cassette(s) to: #{filename}"
80
95
  end
81
96
 
82
- # Walks the exception + cause chain looking for UnhandledHTTPRequestError
97
+ # Walks the exception + cause chain looking for UnhandledHTTPRequestError.
98
+ #
99
+ # Some frameworks re-raise VCR's error as a different class after it has
100
+ # crossed a thread boundary (e.g. Capybara's app server). Re-raising a
101
+ # fresh exception object replaces the cause chain, so the VCR error is no
102
+ # longer reachable via `cause`. In that case the only thing left is its
103
+ # message, which VCR's wrapper embeds into its own message. Match on the
104
+ # message as a fallback.
83
105
  def find_vcr_error(exception)
84
106
  current = exception
85
107
 
86
108
  while current
87
109
  return current if current.is_a?(VCR::Errors::UnhandledHTTPRequestError)
110
+ return current if current.message.to_s.include?(UNHANDLED_REQUEST_MESSAGE)
88
111
  current = current.cause
89
112
  end
90
113
 
@@ -120,3 +143,5 @@ module VCR
120
143
  end
121
144
  end
122
145
  end
146
+
147
+ require "vcr/log_unmatched_cassettes/railtie" if defined?(::Rails::Railtie)
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: vcr-log_unmatched_cassettes
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Skye Shaw
8
8
  bindir: bin
9
9
  cert_chain: []
10
- date: 2026-10-22 00:00:00.000000000 Z
10
+ date: 2026-10-23 00:00:00.000000000 Z
11
11
  dependencies:
12
12
  - !ruby/object:Gem::Dependency
13
13
  name: vcr
@@ -117,6 +117,8 @@ files:
117
117
  - README.md
118
118
  - Rakefile
119
119
  - lib/vcr/log_unmatched_cassettes.rb
120
+ - lib/vcr/log_unmatched_cassettes/railtie.rb
121
+ - lib/vcr/log_unmatched_cassettes/rake.rb
120
122
  - lib/vcr/log_unmatched_cassettes/version.rb
121
123
  homepage: https://github.com/sshaw/vcr-log_unmatched_cassettes
122
124
  licenses: