You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

205 lines
6.0 KiB

  1. # frozen_string_literal: true
  2. require 'rails_helper'
  3. RSpec.describe Remotable do
  4. class Foo
  5. def initialize
  6. @attrs = {}
  7. end
  8. def [](arg)
  9. @attrs[arg]
  10. end
  11. def []=(arg1, arg2)
  12. @attrs[arg1] = arg2
  13. end
  14. def hoge=(arg); end
  15. def hoge_file_name=(arg); end
  16. def has_attribute?(arg); end
  17. def self.attachment_definitions
  18. { hoge: nil }
  19. end
  20. end
  21. context 'Remotable module is included' do
  22. before do
  23. class Foo; include Remotable; end
  24. end
  25. let(:attribute_name) { "#{hoge}_remote_url".to_sym }
  26. let(:code) { 200 }
  27. let(:file) { 'filename="foo.txt"' }
  28. let(:foo) { Foo.new }
  29. let(:headers) { { 'content-disposition' => file } }
  30. let(:hoge) { :hoge }
  31. let(:url) { 'https://google.com' }
  32. let(:request) do
  33. stub_request(:get, url)
  34. .to_return(status: code, headers: headers)
  35. end
  36. it 'defines a method #hoge_remote_url=' do
  37. expect(foo).to respond_to(:hoge_remote_url=)
  38. end
  39. it 'defines a method #reset_hoge!' do
  40. expect(foo).to respond_to(:reset_hoge!)
  41. end
  42. describe '#hoge_remote_url' do
  43. before do
  44. request
  45. end
  46. it 'always returns arg' do
  47. [nil, '', [], {}].each do |arg|
  48. expect(foo.hoge_remote_url = arg).to be arg
  49. end
  50. end
  51. context 'Addressable::URI::InvalidURIError raised' do
  52. it 'makes no request' do
  53. allow(Addressable::URI).to receive_message_chain(:parse, :normalize)
  54. .with(url).with(no_args).and_raise(Addressable::URI::InvalidURIError)
  55. foo.hoge_remote_url = url
  56. expect(request).not_to have_been_requested
  57. end
  58. end
  59. context 'scheme is neither http nor https' do
  60. let(:url) { 'ftp://google.com' }
  61. it 'makes no request' do
  62. foo.hoge_remote_url = url
  63. expect(request).not_to have_been_requested
  64. end
  65. end
  66. context 'parsed_url.host is empty' do
  67. it 'makes no request' do
  68. parsed_url = double(scheme: 'https', host: double(empty?: true))
  69. allow(Addressable::URI).to receive_message_chain(:parse, :normalize)
  70. .with(url).with(no_args).and_return(parsed_url)
  71. foo.hoge_remote_url = url
  72. expect(request).not_to have_been_requested
  73. end
  74. end
  75. context 'foo[attribute_name] == url' do
  76. it 'makes no request' do
  77. allow(foo).to receive(:[]).with(attribute_name).and_return(url)
  78. foo.hoge_remote_url = url
  79. expect(request).not_to have_been_requested
  80. end
  81. end
  82. context "scheme is https, parsed_url.host isn't empty, and foo[attribute_name] != url" do
  83. it 'makes a request' do
  84. foo.hoge_remote_url = url
  85. expect(request).to have_been_requested
  86. end
  87. context 'response.code != 200' do
  88. let(:code) { 500 }
  89. it 'calls not send' do
  90. expect(foo).not_to receive(:send).with("#{hoge}=", any_args)
  91. expect(foo).not_to receive(:send).with("#{hoge}_file_name=", any_args)
  92. foo.hoge_remote_url = url
  93. end
  94. end
  95. context 'response.code == 200' do
  96. let(:code) { 200 }
  97. context 'response contains headers["content-disposition"]' do
  98. let(:file) { 'filename="foo.txt"' }
  99. let(:headers) { { 'content-disposition' => file } }
  100. it 'calls send' do
  101. string_io = StringIO.new('')
  102. extname = '.txt'
  103. basename = '0123456789abcdef'
  104. allow(SecureRandom).to receive(:hex).and_return(basename)
  105. allow(StringIO).to receive(:new).with(anything).and_return(string_io)
  106. expect(foo).to receive(:send).with("#{hoge}=", string_io)
  107. expect(foo).to receive(:send).with("#{hoge}_file_name=", basename + extname)
  108. foo.hoge_remote_url = url
  109. end
  110. end
  111. context 'if has_attribute?' do
  112. it 'calls foo[attribute_name] = url' do
  113. allow(foo).to receive(:has_attribute?).with(attribute_name).and_return(true)
  114. expect(foo).to receive('[]=').with(attribute_name, url)
  115. foo.hoge_remote_url = url
  116. end
  117. end
  118. context 'unless has_attribute?' do
  119. it 'calls not foo[attribute_name] = url' do
  120. allow(foo).to receive(:has_attribute?)
  121. .with(attribute_name).and_return(false)
  122. expect(foo).not_to receive('[]=').with(attribute_name, url)
  123. foo.hoge_remote_url = url
  124. end
  125. end
  126. end
  127. context 'an error raised during the request' do
  128. let(:request) { stub_request(:get, url).to_raise(error_class) }
  129. error_classes = [
  130. HTTP::TimeoutError,
  131. HTTP::ConnectionError,
  132. OpenSSL::SSL::SSLError,
  133. Paperclip::Errors::NotIdentifiedByImageMagickError,
  134. Addressable::URI::InvalidURIError,
  135. ]
  136. error_classes.each do |error_class|
  137. let(:error_class) { error_class }
  138. it 'calls Rails.logger.debug' do
  139. expect(Rails.logger).to receive(:debug).with(/^Error fetching remote #{hoge}: /)
  140. foo.hoge_remote_url = url
  141. end
  142. end
  143. end
  144. end
  145. end
  146. describe '#reset_hoge!' do
  147. context 'if url.blank?' do
  148. it 'returns nil, without clearing foo[attribute_name] and calling #hoge_remote_url=' do
  149. url = nil
  150. expect(foo).not_to receive(:send).with(:hoge_remote_url=, url)
  151. foo[attribute_name] = url
  152. expect(foo.reset_hoge!).to be_nil
  153. expect(foo[attribute_name]).to be_nil
  154. end
  155. end
  156. context 'unless url.blank?' do
  157. it 'clears foo[attribute_name] and calls #hoge_remote_url=' do
  158. foo[attribute_name] = url
  159. expect(foo).to receive(:send).with(:hoge_remote_url=, url)
  160. foo.reset_hoge!
  161. expect(foo[attribute_name]).to be ''
  162. end
  163. end
  164. end
  165. end
  166. end