fix(spec): pin SafeFetch error classes to described_class to survive Zeitwerk reload (#14139)
This commit is contained in:
+18
-18
@@ -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,<x>') { 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
|
||||
|
||||
Reference in New Issue
Block a user