123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230 |
- # frozen_string_literal: true
- require 'rails_helper'
- RSpec.describe Remotable do
- class Foo
- def initialize
- @attrs = {}
- end
- def [](arg)
- @attrs[arg]
- end
- def []=(arg1, arg2)
- @attrs[arg1] = arg2
- end
- def hoge=(arg); end
- def hoge_file_name; end
- def hoge_file_name=(arg); end
- def has_attribute?(arg); end
- def self.attachment_definitions
- { hoge: nil }
- end
- end
- context 'Remotable module is included' do
- before do
- class Foo
- include Remotable
- remotable_attachment :hoge, 1.kilobyte
- end
- end
- let(:attribute_name) { "#{hoge}_remote_url".to_sym }
- let(:code) { 200 }
- let(:file) { 'filename="foo.txt"' }
- let(:foo) { Foo.new }
- let(:headers) { { 'content-disposition' => file } }
- let(:hoge) { :hoge }
- let(:url) { 'https://google.com' }
- let(:request) do
- stub_request(:get, url)
- .to_return(status: code, headers: headers)
- end
- it 'defines a method #hoge_remote_url=' do
- expect(foo).to respond_to(:hoge_remote_url=)
- end
- it 'defines a method #reset_hoge!' do
- expect(foo).to respond_to(:reset_hoge!)
- end
- describe '#hoge_remote_url' do
- before do
- request
- end
- it 'always returns arg' do
- [nil, '', [], {}].each do |arg|
- expect(foo.hoge_remote_url = arg).to be arg
- end
- end
- context 'Addressable::URI::InvalidURIError raised' do
- it 'makes no request' do
- allow(Addressable::URI).to receive_message_chain(:parse, :normalize)
- .with(url).with(no_args).and_raise(Addressable::URI::InvalidURIError)
- foo.hoge_remote_url = url
- expect(request).not_to have_been_requested
- end
- end
- context 'scheme is neither http nor https' do
- let(:url) { 'ftp://google.com' }
- it 'makes no request' do
- foo.hoge_remote_url = url
- expect(request).not_to have_been_requested
- end
- end
- context 'parsed_url.host is empty' do
- it 'makes no request' do
- parsed_url = double(scheme: 'https', host: double(blank?: true))
- allow(Addressable::URI).to receive_message_chain(:parse, :normalize)
- .with(url).with(no_args).and_return(parsed_url)
- foo.hoge_remote_url = url
- expect(request).not_to have_been_requested
- end
- end
- context 'parsed_url.host is nil' do
- it 'makes no request' do
- parsed_url = Addressable::URI.parse('https:https://example.com/path/file.png')
- allow(Addressable::URI).to receive_message_chain(:parse, :normalize)
- .with(url).with(no_args).and_return(parsed_url)
- foo.hoge_remote_url = url
- expect(request).not_to have_been_requested
- end
- end
- context 'foo[attribute_name] == url' do
- it 'makes no request if file is saved' do
- allow(foo).to receive(:[]).with(attribute_name).and_return(url)
- allow(foo).to receive(:hoge_file_name).and_return('foo.jpg')
- foo.hoge_remote_url = url
- expect(request).not_to have_been_requested
- end
- it 'makes request if file is not saved' do
- allow(foo).to receive(:[]).with(attribute_name).and_return(url)
- allow(foo).to receive(:hoge_file_name).and_return(nil)
- foo.hoge_remote_url = url
- expect(request).to have_been_requested
- end
- end
- context "scheme is https, parsed_url.host isn't empty, and foo[attribute_name] != url" do
- it 'makes a request' do
- foo.hoge_remote_url = url
- expect(request).to have_been_requested
- end
- context 'response.code != 200' do
- let(:code) { 500 }
- it 'calls not send' do
- expect(foo).not_to receive(:send).with("#{hoge}=", any_args)
- expect(foo).not_to receive(:send).with("#{hoge}_file_name=", any_args)
- foo.hoge_remote_url = url
- end
- end
- context 'response.code == 200' do
- let(:code) { 200 }
- context 'response contains headers["content-disposition"]' do
- let(:file) { 'filename="foo.txt"' }
- let(:headers) { { 'content-disposition' => file } }
- it 'calls send' do
- string_io = StringIO.new('')
- extname = '.txt'
- basename = '0123456789abcdef'
- allow(SecureRandom).to receive(:hex).and_return(basename)
- allow(StringIO).to receive(:new).with(anything).and_return(string_io)
- expect(foo).to receive(:send).with("#{hoge}=", string_io)
- expect(foo).to receive(:send).with("#{hoge}_file_name=", basename + extname)
- foo.hoge_remote_url = url
- end
- end
- context 'if has_attribute?' do
- it 'calls foo[attribute_name] = url' do
- allow(foo).to receive(:has_attribute?).with(attribute_name).and_return(true)
- expect(foo).to receive('[]=').with(attribute_name, url)
- foo.hoge_remote_url = url
- end
- end
- context 'unless has_attribute?' do
- it 'calls not foo[attribute_name] = url' do
- allow(foo).to receive(:has_attribute?)
- .with(attribute_name).and_return(false)
- expect(foo).not_to receive('[]=').with(attribute_name, url)
- foo.hoge_remote_url = url
- end
- end
- end
- context 'an error raised during the request' do
- let(:request) { stub_request(:get, url).to_raise(error_class) }
- error_classes = [
- HTTP::TimeoutError,
- HTTP::ConnectionError,
- OpenSSL::SSL::SSLError,
- Paperclip::Errors::NotIdentifiedByImageMagickError,
- Addressable::URI::InvalidURIError,
- ]
- error_classes.each do |error_class|
- let(:error_class) { error_class }
- it 'calls Rails.logger.debug' do
- expect(Rails.logger).to receive(:debug).with(/^Error fetching remote #{hoge}: /)
- foo.hoge_remote_url = url
- end
- end
- end
- end
- end
- describe '#reset_hoge!' do
- context 'if url.blank?' do
- it 'returns nil, without clearing foo[attribute_name] and calling #hoge_remote_url=' do
- url = nil
- expect(foo).not_to receive(:send).with(:hoge_remote_url=, url)
- foo[attribute_name] = url
- expect(foo.reset_hoge!).to be_nil
- expect(foo[attribute_name]).to be_nil
- end
- end
- context 'unless url.blank?' do
- it 'clears foo[attribute_name] and calls #hoge_remote_url=' do
- foo[attribute_name] = url
- expect(foo).to receive(:send).with(:hoge_remote_url=, url)
- foo.reset_hoge!
- expect(foo[attribute_name]).to be ''
- end
- end
- end
- end
- end
|