From ecdeb891ff14845697ec6b887d0b4d607fa1cd38 Mon Sep 17 00:00:00 2001 From: Vishnu Narayanan Date: Thu, 23 Apr 2026 19:48:05 +0530 Subject: [PATCH] fix(spec): pin SafeFetch error classes to described_class to survive Zeitwerk reload (#14139) --- spec/lib/safe_fetch_spec.rb | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/spec/lib/safe_fetch_spec.rb b/spec/lib/safe_fetch_spec.rb index 70f9b05de..d8d37115a 100644 --- a/spec/lib/safe_fetch_spec.rb +++ b/spec/lib/safe_fetch_spec.rb @@ -68,55 +68,55 @@ RSpec.describe SafeFetch do context 'with URL validation' do it 'raises InvalidUrlError for javascript: URLs' do expect { described_class.fetch('javascript:alert(1)') { nil } } - .to raise_error(SafeFetch::InvalidUrlError) + .to raise_error(described_class::InvalidUrlError) end it 'raises InvalidUrlError for mailto: URLs' do expect { described_class.fetch('mailto:test@example.com') { nil } } - .to raise_error(SafeFetch::InvalidUrlError) + .to raise_error(described_class::InvalidUrlError) end it 'raises InvalidUrlError for data: URLs' do expect { described_class.fetch('data:text/html,') { nil } } - .to raise_error(SafeFetch::InvalidUrlError) + .to raise_error(described_class::InvalidUrlError) end it 'raises InvalidUrlError for ftp: URLs' do expect { described_class.fetch('ftp://example.com/file') { nil } } - .to raise_error(SafeFetch::InvalidUrlError) + .to raise_error(described_class::InvalidUrlError) end it 'raises InvalidUrlError for malformed URLs' do expect { described_class.fetch('not_a_url') { nil } } - .to raise_error(SafeFetch::InvalidUrlError) + .to raise_error(described_class::InvalidUrlError) end it 'raises InvalidUrlError when host is missing' do expect { described_class.fetch('http:///path') { nil } } - .to raise_error(SafeFetch::InvalidUrlError, /missing host/) + .to raise_error(described_class::InvalidUrlError, /missing host/) end end context 'with SSRF protection (integration with ssrf_filter)' do it 'raises UnsafeUrlError for private IP literals (10.x.x.x)' do expect { described_class.fetch('http://10.0.0.1/secret') { nil } } - .to raise_error(SafeFetch::UnsafeUrlError) + .to raise_error(described_class::UnsafeUrlError) end it 'raises UnsafeUrlError for loopback addresses' do expect { described_class.fetch('http://127.0.0.1/secret') { nil } } - .to raise_error(SafeFetch::UnsafeUrlError) + .to raise_error(described_class::UnsafeUrlError) end it 'raises UnsafeUrlError for AWS metadata IP (169.254.169.254)' do expect { described_class.fetch('http://169.254.169.254/latest/meta-data/') { nil } } - .to raise_error(SafeFetch::UnsafeUrlError) + .to raise_error(described_class::UnsafeUrlError) end it 'raises UnsafeUrlError when hostname resolves to a private IP (DNS rebinding)' do allow(Resolv).to receive(:getaddresses).with('evil.example.com').and_return(['10.0.0.1']) expect { described_class.fetch('http://evil.example.com/secret') { nil } } - .to raise_error(SafeFetch::UnsafeUrlError) + .to raise_error(described_class::UnsafeUrlError) end end @@ -129,7 +129,7 @@ RSpec.describe SafeFetch do ) expect { described_class.fetch(url) { nil } } - .to raise_error(SafeFetch::UnsupportedContentTypeError) + .to raise_error(described_class::UnsupportedContentTypeError) end it 'rejects application/octet-stream responses' do @@ -140,7 +140,7 @@ RSpec.describe SafeFetch do ) expect { described_class.fetch(url) { nil } } - .to raise_error(SafeFetch::UnsupportedContentTypeError) + .to raise_error(described_class::UnsupportedContentTypeError) end it 'allows video/mp4 responses' do @@ -167,7 +167,7 @@ RSpec.describe SafeFetch do stub_request(:get, url).to_return(status: 200, body: 'x', headers: {}) expect { described_class.fetch(url) { nil } } - .to raise_error(SafeFetch::UnsupportedContentTypeError) + .to raise_error(described_class::UnsupportedContentTypeError) end end @@ -180,7 +180,7 @@ RSpec.describe SafeFetch do ) expect { described_class.fetch(url, max_bytes: 2) { nil } } - .to raise_error(SafeFetch::FileTooLargeError) + .to raise_error(described_class::FileTooLargeError) end it 'reads the default cap from GlobalConfigService MAXIMUM_FILE_UPLOAD_SIZE (matching Attachment#validate_file_size)' do @@ -195,7 +195,7 @@ RSpec.describe SafeFetch do ) expect { described_class.fetch(url) { nil } } - .to raise_error(SafeFetch::FileTooLargeError) + .to raise_error(described_class::FileTooLargeError) end it 'falls back to 40 MB when GlobalConfigService returns a non-positive value' do @@ -234,14 +234,14 @@ RSpec.describe SafeFetch do stub_request(:get, url).to_raise(Net::ReadTimeout) expect { described_class.fetch(url) { nil } } - .to raise_error(SafeFetch::FetchError) + .to raise_error(described_class::FetchError) end it 'maps SocketError to FetchError' do stub_request(:get, url).to_raise(SocketError.new('connection refused')) expect { described_class.fetch(url) { nil } } - .to raise_error(SafeFetch::FetchError) + .to raise_error(described_class::FetchError) end end @@ -250,7 +250,7 @@ RSpec.describe SafeFetch do stub_request(:get, url).to_return(status: 404, body: '', headers: {}) expect { described_class.fetch(url) { nil } } - .to raise_error(SafeFetch::HttpError, /404/) + .to raise_error(described_class::HttpError, /404/) end end end