# frozen_string_literal: true require 'spec_helper' describe Geoblacklight::Download do subject(:download) { described_class.new(document, options) } let(:faraday_connection) { instance_double(Faraday::Connection) } let(:faraday_response) { instance_double(Faraday::Response) } let(:references_field) { Settings.FIELDS.REFERENCES } let(:document) { SolrDocument.new("#{Settings.FIELDS.ID}": 'test', references_field => { 'http://www.opengis.net/def/serviceType/ogc/wms' => 'http://www.example.com/wms' }.to_json) } let(:options) { { type: 'shapefile', extension: 'zip', service_type: 'wms', content_type: 'application/zip' } } describe '#initialize' do it 'initializes as a Download object' do expect(download).to be_a described_class end end describe '#downloadable?' do before do allow(document).to receive(:downloadable?).and_return(true) end it 'determines whether or not the resource can be downloaded' do expect(download.downloadable?).to be true end end describe '#file_name' do it 'gives the file name with path and extension' do expect(download.file_name).to eq 'test-shapefile.zip' end end describe '#file_path' do it 'returns the path with name and extension' do expect(download.class.file_path).to eq Rails.root.join('tmp', 'cache', 'downloads') end it 'is configurable' do expect(Settings).to receive(:DOWNLOAD_PATH).and_return('configured/path') expect(download.class.file_path).to eq 'configured/path' end end describe '#download_exists?' do it 'returns false if file does not exist' do expect(File).to receive(:file?).and_return(false) expect(download.download_exists?).to be_falsey end it 'returns true if file does not exist' do expect(File).to receive(:file?).and_return(true) expect(download.download_exists?).to be_truthy end end describe '#get' do before do allow(File).to receive(:file?).and_return(true) end it 'returns filename if download exists' do expect(download.get).to eq download.file_name end context 'when the file has not already been downloaded' do let(:connection) { instance_double(Faraday::Connection) } let(:response) { instance_double(Faraday::Response) } before do allow(File).to receive(:file?).and_return(false) allow(connection).to receive(:get).and_return(object: 'file') allow(Faraday).to receive(:new).and_return(connection) end it 'calls create_download_file if it does not exist' do allow(File).to receive(:open).with("#{download.file_path_and_name}.tmp", 'wb').and_return('') allow(File).to receive(:rename) expect(download.get).to eq 'test-shapefile.zip' end end end describe '#create_download_file' do let(:file) { instance_double(File) } let(:shapefile) { OpenStruct.new(headers: { 'content-type' => 'application/zip' }) } let(:connection) { instance_double(Faraday::Connection) } let(:response) { instance_double(Faraday::Response) } before do allow(file).to receive(:write) allow(Faraday).to receive(:new).and_return(connection) allow(connection).to receive(:get).and_return(shapefile) end it 'creates the file, write it, and then rename from tmp if everything is ok' do allow(File).to receive(:open).with("#{download.file_path_and_name}.tmp", 'wb').and_yield(file).and_return('') allow(File).to receive(:rename) expect(download.create_download_file).to eq download.file_name end context 'when the file received is not of the type requested' do let(:bad_file) { OpenStruct.new(headers: { 'content-type' => 'bad/file' }) } before do allow(connection).to receive(:get).and_return(bad_file) end it 'creates the file in fs and delete it if the content headers are not correct' do allow(File).to receive(:delete).with("#{download.file_path_and_name}.tmp").and_return(nil) expect { download.create_download_file }.to raise_error(Geoblacklight::Exceptions::ExternalDownloadFailed, 'Wrong download type') end end context 'when the MIME type has more information encoded' do let(:geojson) { OpenStruct.new(headers: { 'content-type' => 'application/json;charset=utf-8' }) } before do allow(connection).to receive(:get).and_return(geojson) end it 'accepts response MIME type that is more complex than requested' do allow(File).to receive(:open).with("#{download.file_path_and_name}.tmp", 'wb').and_return('') allow(File).to receive(:rename) expect(download.create_download_file).to eq download.file_name end end end describe '#initiate_download' do let(:faraday_request) { instance_double(Faraday::Request) } let(:faraday_request_options) { OpenStruct.new(timeout: nil, open_timeout: nil) } before do allow(faraday_request).to receive(:params=) allow(faraday_request).to receive(:options).and_return(faraday_request_options) end it 'request download from server' do allow(faraday_connection).to receive(:get).and_yield(faraday_request).and_return(faraday_response) allow(Faraday).to receive(:new).with(url: 'http://www.example.com/wms').and_return(faraday_connection) expect(download.initiate_download).to eq faraday_response end it 'raises Geoblacklight::Exceptions::ExternalDownloadFailed with a connection failure' do expect(faraday_connection).to receive(:url_prefix).and_return 'http://www.example.com/wms' expect(faraday_connection).to receive(:get).and_raise(Faraday::ConnectionFailed.new('Failed')) expect(Faraday).to receive(:new).with(url: 'http://www.example.com/wms').and_return(faraday_connection) expect { download.initiate_download }.to raise_error(Geoblacklight::Exceptions::ExternalDownloadFailed) end it 'raises Geoblacklight::Exceptions::ExternalDownloadFailed with a connection timout' do expect(faraday_connection).to receive(:url_prefix).and_return 'http://www.example.com/wms' expect(faraday_connection).to receive(:get).and_raise(Faraday::TimeoutError) expect(Faraday).to receive(:new).with(url: 'http://www.example.com/wms').and_return(faraday_connection) expect { download.initiate_download }.to raise_error(Geoblacklight::Exceptions::ExternalDownloadFailed) end end describe '#url_with_params' do let(:options) do { service_type: 'wms', request_params: { service: 'wfs', version: '2.0.0', request: 'GetFeature', srsName: 'EPSG:4326', outputformat: 'SHAPE-ZIP', typeName: '' } } end it 'creates a download url with params' do expect(download.url_with_params).to eq 'http://www.example.com/wms/?ser' \ 'vice=wfs&version=2.0.0&request=GetFeature&srsName=EPSG%3A4326&output' \ 'format=SHAPE-ZIP&typeName=' end end end