aboutsummaryrefslogtreecommitdiffstats
path: root/spec
diff options
context:
space:
mode:
authorteddywing2017-08-01 17:39:10 +0200
committerGitHub2017-08-01 17:39:10 +0200
commit1f09ead58c9c603e9d767781ceb82859b2393f49 (patch)
treeaec7d66e003ef9768156976750e27c38fd22cc0a /spec
parent60ae8866d6d4c55bc064a2a83c1a1ffa87894202 (diff)
parentee75bd1e579ab366eb6cac938f50e7786536472b (diff)
downloadchouette-core-1f09ead58c9c603e9d767781ceb82859b2393f49.tar.bz2
Merge pull request #46 from af83/3507_1726_impl_workbench_import
3507 1726 impl workbench import
Diffstat (limited to 'spec')
-rw-r--r--spec/concerns/configurable_spec.rb35
-rw-r--r--spec/controllers/imports_controller_spec.rb1
-rw-r--r--spec/factories/api_keys.rb6
-rw-r--r--spec/factories/import_tasks.rb10
-rw-r--r--spec/factories/imports.rb3
-rw-r--r--spec/fixtures/multiple_references_import.zipbin0 -> 1086 bytes
-rw-r--r--spec/fixtures/neptune.zipbin4904 -> 0 bytes
-rw-r--r--spec/fixtures/nozip.zip1
-rw-r--r--spec/fixtures/ref1.zipbin0 -> 554 bytes
-rw-r--r--spec/fixtures/ref2.zipbin0 -> 554 bytes
-rw-r--r--spec/fixtures/single_reference_import.zipbin0 -> 220 bytes
-rw-r--r--spec/lib/result_spec.rb20
-rw-r--r--spec/models/api/v1/api_key_spec.rb31
-rw-r--r--spec/models/import_spec.rb7
-rw-r--r--spec/models/organisation_spec.rb4
-rw-r--r--spec/models/user_spec.rb2
-rw-r--r--spec/requests/api/v1/netex_import_spec.rb5
-rw-r--r--spec/services/file_service_spec.rb17
-rw-r--r--spec/services/http_service_spec.rb74
-rw-r--r--spec/services/retry_service_spec.rb137
-rw-r--r--spec/services/zip_service/zip_entry_data_spec.rb32
-rw-r--r--spec/services/zip_service/zip_entry_dirs_spec.rb33
-rw-r--r--spec/services/zip_service/zip_output_streams_spec.rb21
-rw-r--r--spec/support/fixtures_helper.rb18
-rw-r--r--spec/support/webmock/helpers.rb18
-rw-r--r--spec/tasks/reflex_rake_spec.rb4
-rw-r--r--spec/workers/stop_area_referential_sync_worker_spec.rb1
-rw-r--r--spec/workers/workbench_import_worker_spec.rb119
28 files changed, 573 insertions, 26 deletions
diff --git a/spec/concerns/configurable_spec.rb b/spec/concerns/configurable_spec.rb
new file mode 100644
index 000000000..330241b72
--- /dev/null
+++ b/spec/concerns/configurable_spec.rb
@@ -0,0 +1,35 @@
+RSpec.describe Configurable do
+
+ subject do
+ Class.new do
+ include Configurable
+ end
+ end
+
+ let( :something ){ double('something') }
+
+ it 'can be configured' do
+ expect{ subject.config.anything }.to raise_error(NoMethodError)
+
+ subject.config.something = something
+
+ expect( subject.config.something ).to eq(something)
+ # Instances delegate to the class
+ expect( subject.new.send(:config).something ).to eq(something)
+ # **All** instances delegate to the class
+ expect( subject.new.send(:config).something ).to eq(something)
+ end
+
+ it 'can be configured with a block' do
+
+ subject.config do | c |
+ c.something = something
+ end
+
+ expect( subject.config.something ).to eq(something)
+ # Instances delegate to the class
+ expect( subject.new.send(:config).something ).to eq(something)
+ # **All** instances delegate to the class
+ expect( subject.new.send(:config).something ).to eq(something)
+ end
+end
diff --git a/spec/controllers/imports_controller_spec.rb b/spec/controllers/imports_controller_spec.rb
index 7b575ab61..f07190496 100644
--- a/spec/controllers/imports_controller_spec.rb
+++ b/spec/controllers/imports_controller_spec.rb
@@ -15,6 +15,7 @@ RSpec.describe ImportsController, :type => :controller do
it 'should be successful' do
get :download, workbench_id: workbench.id, id: import.id, token: import.token_download
expect(response).to be_success
+ expect( response.body ).to eq(import.file.read)
end
end
end
diff --git a/spec/factories/api_keys.rb b/spec/factories/api_keys.rb
new file mode 100644
index 000000000..bd31edecc
--- /dev/null
+++ b/spec/factories/api_keys.rb
@@ -0,0 +1,6 @@
+FactoryGirl.define do
+ factory :api_key, class: Api::V1::ApiKey do
+ token { "#{referential.id}-#{SecureRandom.hex}" }
+ referential
+ end
+end
diff --git a/spec/factories/import_tasks.rb b/spec/factories/import_tasks.rb
deleted file mode 100644
index 9ca6db899..000000000
--- a/spec/factories/import_tasks.rb
+++ /dev/null
@@ -1,10 +0,0 @@
-FactoryGirl.define do
- factory :import_task do |f|
- user_name "dummy"
- user_id 123
- no_save false
- format "Neptune"
- resources { Rack::Test::UploadedFile.new 'spec/fixtures/neptune.zip', 'application/zip', false }
- referential { Referential.find_by_slug("first") }
- end
-end
diff --git a/spec/factories/imports.rb b/spec/factories/imports.rb
index e19fe92bb..aa9288fe9 100644
--- a/spec/factories/imports.rb
+++ b/spec/factories/imports.rb
@@ -13,5 +13,8 @@ FactoryGirl.define do
factory :netex_import, class: NetexImport do
file {File.open(Rails.root.join('spec', 'fixtures', 'terminated_job.json'))}
end
+ factory :workbench_import, class: WorkbenchImport do
+ file {File.open(Rails.root.join('spec', 'fixtures', 'terminated_job.json'))}
+ end
end
end
diff --git a/spec/fixtures/multiple_references_import.zip b/spec/fixtures/multiple_references_import.zip
new file mode 100644
index 000000000..28ddff198
--- /dev/null
+++ b/spec/fixtures/multiple_references_import.zip
Binary files differ
diff --git a/spec/fixtures/neptune.zip b/spec/fixtures/neptune.zip
deleted file mode 100644
index 86b688b51..000000000
--- a/spec/fixtures/neptune.zip
+++ /dev/null
Binary files differ
diff --git a/spec/fixtures/nozip.zip b/spec/fixtures/nozip.zip
new file mode 100644
index 000000000..505bd213a
--- /dev/null
+++ b/spec/fixtures/nozip.zip
@@ -0,0 +1 @@
+no zip file
diff --git a/spec/fixtures/ref1.zip b/spec/fixtures/ref1.zip
new file mode 100644
index 000000000..1cbd0268e
--- /dev/null
+++ b/spec/fixtures/ref1.zip
Binary files differ
diff --git a/spec/fixtures/ref2.zip b/spec/fixtures/ref2.zip
new file mode 100644
index 000000000..342353b07
--- /dev/null
+++ b/spec/fixtures/ref2.zip
Binary files differ
diff --git a/spec/fixtures/single_reference_import.zip b/spec/fixtures/single_reference_import.zip
new file mode 100644
index 000000000..4aee23614
--- /dev/null
+++ b/spec/fixtures/single_reference_import.zip
Binary files differ
diff --git a/spec/lib/result_spec.rb b/spec/lib/result_spec.rb
new file mode 100644
index 000000000..949de163c
--- /dev/null
+++ b/spec/lib/result_spec.rb
@@ -0,0 +1,20 @@
+RSpec.describe Result do
+
+ context 'is a wrapper of a value' do
+ it { expect( described_class.ok('hello').value ).to eq('hello') }
+ it { expect( described_class.error('hello').value ).to eq('hello') }
+ end
+
+ context 'it has status information' do
+ it { expect( described_class.ok('hello') ).to be_ok }
+ it { expect( described_class.ok('hello').status ).to eq(:ok) }
+
+ it { expect( described_class.error('hello') ).not_to be_ok }
+ it { expect( described_class.error('hello').status ).to eq(:error) }
+ end
+
+ context 'nil is just another value' do
+ it { expect( described_class.ok(nil) ).to be_ok }
+ it { expect( described_class.ok(nil).value ).to be_nil }
+ end
+end
diff --git a/spec/models/api/v1/api_key_spec.rb b/spec/models/api/v1/api_key_spec.rb
index 8a34c9221..5f39a65e4 100644
--- a/spec/models/api/v1/api_key_spec.rb
+++ b/spec/models/api/v1/api_key_spec.rb
@@ -1,11 +1,34 @@
describe Api::V1::ApiKey, :type => :model do
- let!(:referential){create(:referential)}
- subject { Api::V1::ApiKey.create( :name => "test", :referential => referential)}
- it "test" do
- expect(subject).to be_valid
+ let(:referential){ create :referential }
+
+ subject { described_class.create( :name => "test", :referential => referential)}
+
+ it "validity test" do
+ expect_it.to be_valid
expect(subject.referential).to eq(referential)
+ end
+
+ context 'Creation' do
+ let( :name ){ SecureRandom.urlsafe_base64 }
+
+ it 'can be created from a referential with a name, iff needed' do
+ # 1st time create a new record
+ expect{ described_class.from(referential, name: name) }.to change{ described_class.count }.by(1)
+ expect( described_class.last.attributes.values_at(*%w{referential_id name}) ).to eq([
+ referential.id, name
+ ])
+
+ # 2nd time get the same record
+ expect{ described_class.from(referential, name: name) }.not_to change{ described_class.count }
+ expect( described_class.last.attributes.values_at(*%w{referential_id name}) ).to eq([
+ referential.id, name
+ ])
+ end
+ it 'cannot be created without a referential' do
+ expect{ described_class.from(nil, name:name) rescue nil }.not_to change{ described_class.count }
+ end
end
end
diff --git a/spec/models/import_spec.rb b/spec/models/import_spec.rb
index 34bfb0b23..c56858b44 100644
--- a/spec/models/import_spec.rb
+++ b/spec/models/import_spec.rb
@@ -1,11 +1,12 @@
-require 'rails_helper'
-
RSpec.describe Import, :type => :model do
+
it { should belong_to(:referential) }
it { should belong_to(:workbench) }
it { should belong_to(:parent).class_name(described_class.to_s) }
- it { should enumerize(:status).in(:new, :pending, :successful, :failed, :canceled, :running, :aborted ) }
+ it { should enumerize(:status).in("aborted", "canceled", "failed", "new", "pending", "running", "successful") }
it { should validate_presence_of(:file) }
+ it { should validate_presence_of(:referential) }
+ it { should validate_presence_of(:workbench) }
end
diff --git a/spec/models/organisation_spec.rb b/spec/models/organisation_spec.rb
index 527f71015..b16324a56 100644
--- a/spec/models/organisation_spec.rb
+++ b/spec/models/organisation_spec.rb
@@ -1,5 +1,3 @@
-require 'spec_helper'
-
describe Organisation, :type => :model do
it { should validate_presence_of(:name) }
it { should validate_uniqueness_of(:code) }
@@ -17,7 +15,7 @@ describe Organisation, :type => :model do
let(:conf) { Rails.application.config.stif_portail_api }
before :each do
stub_request(:get, "#{conf[:url]}/api/v1/organizations").
- with(headers: { 'Authorization' => "Token token=\"#{conf[:key]}\"" }).
+ with(stub_headers(authorization_token: conf[:key])).
to_return(body: File.open(File.join(Rails.root, 'spec', 'fixtures', 'organizations.json')), status: 200)
end
diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb
index 3a9ae37e9..51ccfccd3 100644
--- a/spec/models/user_spec.rb
+++ b/spec/models/user_spec.rb
@@ -67,7 +67,7 @@ RSpec.describe User, :type => :model do
let(:conf) { Rails.application.config.stif_portail_api }
before :each do
stub_request(:get, "#{conf[:url]}/api/v1/users").
- with(headers: { 'Authorization' => "Token token=\"#{conf[:key]}\"" }).
+ with(stub_headers(authorization_token: conf[:key])).
to_return(body: File.open(File.join(Rails.root, 'spec', 'fixtures', 'users.json')), status: 200)
end
diff --git a/spec/requests/api/v1/netex_import_spec.rb b/spec/requests/api/v1/netex_import_spec.rb
index 9fbf8f801..ab1e7f6ae 100644
--- a/spec/requests/api/v1/netex_import_spec.rb
+++ b/spec/requests/api/v1/netex_import_spec.rb
@@ -4,7 +4,7 @@ RSpec.describe "NetexImport", type: :request do
let( :referential ){ create :referential }
- let( :file_path ){'spec/fixtures/neptune.zip'}
+ let( :file_path ){ fixtures_path 'single_reference_import.zip' }
let( :file ){ fixture_file_upload( file_path ) }
let( :post_request ) do
@@ -19,7 +19,8 @@ RSpec.describe "NetexImport", type: :request do
{
name: 'hello world',
file: file,
- referential_id: referential.id
+ referential_id: referential.id,
+ workbench_id: referential.workbench_id
}
end
diff --git a/spec/services/file_service_spec.rb b/spec/services/file_service_spec.rb
new file mode 100644
index 000000000..4426ee145
--- /dev/null
+++ b/spec/services/file_service_spec.rb
@@ -0,0 +1,17 @@
+# TODO: Delete me after stable implementation of #1726
+# RSpec.describe FileService do
+
+# it 'computes a unique filename' do
+# expect( File ).to receive(:exists?).with('xxx/yyy_0').and_return( false )
+
+# expect(described_class.unique_filename('xxx/yyy')).to eq('xxx/yyy_0')
+# end
+
+# it 'handles duplicate names by means of a counter' do
+# expect( File ).to receive(:exists?).with('xxx/yyy_0').and_return( true )
+# expect( File ).to receive(:exists?).with('xxx/yyy_1').and_return( true )
+# expect( File ).to receive(:exists?).with('xxx/yyy_2').and_return( false )
+
+# expect(described_class.unique_filename('xxx/yyy')).to eq('xxx/yyy_2')
+# end
+# end
diff --git a/spec/services/http_service_spec.rb b/spec/services/http_service_spec.rb
new file mode 100644
index 000000000..8c8af480c
--- /dev/null
+++ b/spec/services/http_service_spec.rb
@@ -0,0 +1,74 @@
+RSpec.describe HTTPService do
+
+ subject{ described_class }
+
+ %i{host params path result}.each do |param|
+ let(param){ double(param) }
+ end
+ let( :token ){ SecureRandom.hex }
+
+ let( :faraday_connection ){ double('faraday_connection') }
+ let( :headers ){ {} }
+
+
+ context 'get_resource' do
+ let( :params ){ double('params') }
+
+ it 'sets authorization and returns result' do
+ expect(Faraday).to receive(:new).with(url: host).and_yield(faraday_connection)
+ expect(faraday_connection).to receive(:adapter).with(Faraday.default_adapter)
+ expect(faraday_connection).to receive(:headers).and_return headers
+ expect(faraday_connection).to receive(:get).with(path, params).and_return(result)
+
+ expect(subject.get_resource(host: host, path: path, token: token, params: params)).to eq(result)
+ expect(headers['Authorization']).to eq( "Token token=#{token.inspect}" )
+ end
+ end
+
+ context 'post_resource' do
+ %i{as_name mime_type name upload_io value}.each do | param |
+ let( param ){ double(param) }
+ end
+
+ let( :upload_list ){ [value, mime_type, as_name] }
+
+ it 'sets authorization and posts data' do
+ expect(Faraday::UploadIO).to receive(:new).with(*upload_list).and_return upload_io
+ expect(params).to receive(:update).with(name => upload_io)
+
+ expect(Faraday).to receive(:new).with(url: host).and_yield(faraday_connection)
+ expect(faraday_connection).to receive(:adapter).with(Faraday.default_adapter)
+ expect(faraday_connection).to receive(:headers).and_return headers
+ expect(faraday_connection).to receive(:request).with(:multipart)
+ expect(faraday_connection).to receive(:request).with(:url_encoded)
+
+ expect(faraday_connection).to receive(:post).with(path, params).and_return(result)
+
+ expect(subject.post_resource(
+ host: host,
+ path: path,
+ token: token,
+ params: params,
+ upload: {name => upload_list} )).to eq(result)
+ expect(headers['Authorization']).to eq( "Token token=#{token.inspect}" )
+ end
+
+ end
+
+ context 'get_json_resource' do
+
+ let( :content ){ SecureRandom.hex }
+
+ it 'delegates an parses the response' do
+ expect_it.to receive(:get_resource)
+ .with(host: host, path: path, token: token, params: params)
+ .and_return(double(body: {content: content}.to_json, status: 200))
+
+ expect( subject.get_json_resource(
+ host: host,
+ path: path,
+ token: token,
+ params: params) ).to eq('content' => content)
+ end
+ end
+end
diff --git a/spec/services/retry_service_spec.rb b/spec/services/retry_service_spec.rb
new file mode 100644
index 000000000..bb3416373
--- /dev/null
+++ b/spec/services/retry_service_spec.rb
@@ -0,0 +1,137 @@
+RSpec.describe RetryService do
+ subject { described_class.new delays: [2, 3], rescue_from: [NameError, ArgumentError] }
+
+ context 'no retry necessary' do
+ before do
+ expect( subject ).not_to receive(:sleep)
+ end
+
+ it 'returns an ok result' do
+ expect( subject.execute { 42 } ).to eq(Result.ok(42))
+ end
+ it 'does not fail on nil' do
+ expect( subject.execute { nil } ).to eq(Result.ok(nil))
+ end
+
+ it 'fails wihout retries if raising un unregistered exception' do
+ expect{ subject.execute{ raise KeyError } }.to raise_error(KeyError)
+ end
+
+ end
+
+ context 'all retries fail' do
+ before do
+ expect( subject ).to receive(:sleep).with(2)
+ expect( subject ).to receive(:sleep).with(3)
+ end
+ it 'fails after raising a registered exception n times' do
+ result = subject.execute{ raise ArgumentError }
+ expect( result.status ).to eq(:error)
+ expect( result.value ).to be_kind_of(ArgumentError)
+ end
+ it 'fails with an explicit try again (automatically registered exception)' do
+ result = subject.execute{ raise RetryService::Retry }
+ expect( result.status ).to eq(:error)
+ expect( result.value ).to be_kind_of(RetryService::Retry)
+ end
+ end
+
+ context "if at first you don't succeed" do
+ before do
+ @count = 0
+ expect( subject ).to receive(:sleep).with(2)
+ end
+
+ it 'succeeds the second time' do
+ expect( subject.execute{ succeed_later(ArgumentError){ 42 } } ).to eq(Result.ok(42))
+ end
+
+ it 'succeeds the second time with try again (automatically registered exception)' do
+ expect( subject.execute{ succeed_later(RetryService::Retry){ 42 } } ).to eq(Result.ok(42))
+ end
+ end
+
+ context 'last chance' do
+ before do
+ @count = 0
+ expect( subject ).to receive(:sleep).with(2)
+ expect( subject ).to receive(:sleep).with(3)
+ end
+ it 'succeeds the third time with try again (automatically registered exception)' do
+ result = subject.execute{ succeed_later(RetryService::Retry, count: 2){ 42 } }
+ expect( result ).to eq( Result.ok(42) )
+ end
+ end
+
+ context 'failure callback once' do
+ subject do
+ described_class.new delays: [2, 3], rescue_from: [NameError, ArgumentError] do |reason, count|
+ @reason=reason
+ @callback_count=count
+ @failures += 1
+ end
+ end
+
+ before do
+ @failures = 0
+ @count = 0
+ expect( subject ).to receive(:sleep).with(2)
+ end
+
+ it 'succeeds the second time and calls the failure_callback once' do
+ subject.execute{ succeed_later(RetryService::Retry){ 42 } }
+ expect( @failures ).to eq(1)
+ end
+ it '... and the failure is passed into the callback' do
+ subject.execute{ succeed_later(RetryService::Retry){ 42 } }
+ expect( @reason ).to be_a(RetryService::Retry)
+ expect( @callback_count ).to eq(1)
+ end
+ end
+
+ context 'failure callback twice' do
+ subject do
+ described_class.new delays: [2, 3], rescue_from: [NameError, ArgumentError] do |_reason, _count|
+ @failures += 1
+ end
+ end
+
+ before do
+ @failures = 0
+ @count = 0
+ expect( subject ).to receive(:sleep).with(2)
+ expect( subject ).to receive(:sleep).with(3)
+ end
+
+ it 'succeeds the third time and calls the failure_callback twice' do
+ subject.execute{ succeed_later(NameError, count: 2){ 42 } }
+ expect( @failures ).to eq(2)
+ end
+ end
+
+ context 'failure callback in constructor' do
+ subject do
+ described_class.new(delays: [1, 2], &method(:add2failures))
+ end
+ before do
+ @failures = []
+ @count = 0
+ expect( subject ).to receive(:sleep).with(1)
+ expect( subject ).to receive(:sleep).with(2)
+ end
+ it 'succeeds the second time and calls the failure_callback once' do
+ subject.execute{ succeed_later(RetryService::Retry, count: 2){ 42 } }
+ expect( @failures ).to eq([1,2])
+ end
+ end
+
+ def add2failures( e, c)
+ @failures << c
+ end
+
+ def succeed_later error, count: 1, &blk
+ return blk.() unless @count < count
+ @count += 1
+ raise error, 'error'
+ end
+end
diff --git a/spec/services/zip_service/zip_entry_data_spec.rb b/spec/services/zip_service/zip_entry_data_spec.rb
new file mode 100644
index 000000000..2a7226eb4
--- /dev/null
+++ b/spec/services/zip_service/zip_entry_data_spec.rb
@@ -0,0 +1,32 @@
+RSpec.describe ZipService do
+
+ subject{ described_class.new(read_fixture('multiple_references_import.zip')) }
+
+ it 'can group all entries' do
+ expect( subject.entry_groups.keys ).to eq(%w{ref1 ref2})
+ end
+
+ context 'creates correct zip data for each subdir' do
+ it 'e.g. reference1' do
+ reference1_stream = subject.entry_group_streams['ref1']
+ control_stream = Zip::InputStream.open( reference1_stream )
+ control_entries = described_class.entries(control_stream)
+ expect( control_entries.map{ |e| [e.name, e.get_input_stream.read]}.force ).to eq([
+ ["multiref/ref1/", ""],
+ ["multiref/ref1/datum-1", "multi-ref1-datum1\n"],
+ ["multiref/ref1/datum-2", "multi-ref1-datum2\n"]
+ ])
+ end
+ it 'e.g. reference2' do
+ reference2_stream = subject.entry_group_streams['ref2']
+ control_stream = Zip::InputStream.open( reference2_stream )
+ control_entries = described_class.entries(control_stream)
+ expect( control_entries.map{ |e| [e.name, e.get_input_stream.read]}.force ).to eq([
+ ["multiref/ref2/", ""],
+ ["multiref/ref2/datum-1", "multi-ref2-datum1\n"],
+ ["multiref/ref2/datum-2", "multi-ref2-datum2\n"]
+ ])
+ end
+ end
+
+end
diff --git a/spec/services/zip_service/zip_entry_dirs_spec.rb b/spec/services/zip_service/zip_entry_dirs_spec.rb
new file mode 100644
index 000000000..8ca1b0f1a
--- /dev/null
+++ b/spec/services/zip_service/zip_entry_dirs_spec.rb
@@ -0,0 +1,33 @@
+RSpec.describe ZipService do
+
+ let( :zip_service ){ described_class }
+
+ let( :zip_data ){ File.read zip_file }
+
+ shared_examples_for 'a correct zip entry reader' do
+ it 'gets all entries of the zip file' do
+ expect( zip_service.new(zip_data).entry_groups.keys ).to eq(expected)
+ end
+ end
+
+ context 'single entry' do
+ let( :zip_file ){ fixtures_path 'multiple_references_import.zip' }
+ let( :expected ){ %w{ref1 ref2} }
+
+ it_behaves_like 'a correct zip entry reader'
+ end
+
+ context 'more entries' do
+ let( :zip_file ){ fixtures_path 'single_reference_import.zip' }
+ let( :expected ){ %w{ref} }
+
+ it_behaves_like 'a correct zip entry reader'
+ end
+
+ context 'illegal file' do
+ let( :zip_file ){ fixtures_path 'nozip.zip' }
+ let( :expected ){ [] }
+
+ it_behaves_like 'a correct zip entry reader'
+ end
+end
diff --git a/spec/services/zip_service/zip_output_streams_spec.rb b/spec/services/zip_service/zip_output_streams_spec.rb
new file mode 100644
index 000000000..fbc60ae92
--- /dev/null
+++ b/spec/services/zip_service/zip_output_streams_spec.rb
@@ -0,0 +1,21 @@
+RSpec.describe ZipService do
+
+ subject{ described_class.new(read_fixture('multiple_references_import.zip')) }
+
+
+ it 'can write itself to a file' do
+ streams = subject.entry_group_streams
+ streams.each do | name, stream |
+ File.write("tmp/#{name}.zip", stream.string)
+ end
+ ref1_lines = %x(unzip -l tmp/ref1.zip).split("\n").grep(%r{multiref/ref}).map(&:strip).map(&:split).map(&:last)
+ ref2_lines = %x(unzip -l tmp/ref2.zip).split("\n").grep(%r{multiref/ref}).map(&:strip).map(&:split).map(&:last)
+
+ expect( ref1_lines ).to eq %w(multiref/ref1/ multiref/ref1/datum-1 multiref/ref1/datum-2)
+ expect( ref2_lines ).to eq %w(multiref/ref2/ multiref/ref2/datum-1 multiref/ref2/datum-2)
+ end
+
+ it "exposes its size" do
+ expect( subject.entry_group_streams.size ).to eq(2)
+ end
+end
diff --git a/spec/support/fixtures_helper.rb b/spec/support/fixtures_helper.rb
new file mode 100644
index 000000000..20963261b
--- /dev/null
+++ b/spec/support/fixtures_helper.rb
@@ -0,0 +1,18 @@
+module Support
+ module FixturesHelper
+ def fixtures_path *segments
+ Rails.root.join( fixture_path, *segments )
+ end
+
+ def open_fixture *segments
+ File.open(fixtures_path(*segments))
+ end
+ def read_fixture *segments
+ File.read(fixtures_path(*segments))
+ end
+ end
+end
+
+RSpec.configure do |c|
+ c.include Support::FixturesHelper
+end
diff --git a/spec/support/webmock/helpers.rb b/spec/support/webmock/helpers.rb
new file mode 100644
index 000000000..fc6c77850
--- /dev/null
+++ b/spec/support/webmock/helpers.rb
@@ -0,0 +1,18 @@
+module Support
+ module Webmock
+ module Helpers
+ def stub_headers(*args)
+ {headers: make_headers(*args)}
+ end
+
+ def make_headers(headers={}, authorization_token:)
+ headers.merge('Authorization' => "Token token=#{authorization_token.inspect}")
+ end
+ end
+ end
+end
+
+RSpec.configure do | conf |
+ conf.include Support::Webmock::Helpers, type: :model
+ conf.include Support::Webmock::Helpers, type: :worker
+end
diff --git a/spec/tasks/reflex_rake_spec.rb b/spec/tasks/reflex_rake_spec.rb
index 04c5886aa..6ece223d2 100644
--- a/spec/tasks/reflex_rake_spec.rb
+++ b/spec/tasks/reflex_rake_spec.rb
@@ -5,7 +5,7 @@ describe 'reflex:sync' do
before(:each) do
['getOP', 'getOR'].each do |method|
stub_request(:get, "#{Rails.application.config.reflex_api_url}/?format=xml&idRefa=0&method=#{method}").
- to_return(body: File.open("#{fixture_path}/reflex.zip"), status: 200)
+ to_return(body: open_fixture('reflex.zip'), status: 200)
end
stop_area_ref = create(:stop_area_referential, name: 'Reflex')
@@ -43,7 +43,7 @@ describe 'reflex:sync' do
before(:each) do
['getOP', 'getOR'].each do |method|
stub_request(:get, "#{Rails.application.config.reflex_api_url}/?format=xml&idRefa=0&method=#{method}").
- to_return(body: File.open("#{fixture_path}/reflex_updated.zip"), status: 200)
+ to_return(body: open_fixture('reflex_updated.zip'), status: 200)
end
Stif::ReflexSynchronization.synchronize
end
diff --git a/spec/workers/stop_area_referential_sync_worker_spec.rb b/spec/workers/stop_area_referential_sync_worker_spec.rb
index 48b64e55e..50c7cf45f 100644
--- a/spec/workers/stop_area_referential_sync_worker_spec.rb
+++ b/spec/workers/stop_area_referential_sync_worker_spec.rb
@@ -1,4 +1,3 @@
-require 'rails_helper'
RSpec.describe StopAreaReferentialSyncWorker, type: :worker do
let!(:stop_area_referential_sync) { create :stop_area_referential_sync }
diff --git a/spec/workers/workbench_import_worker_spec.rb b/spec/workers/workbench_import_worker_spec.rb
new file mode 100644
index 000000000..b719cbb98
--- /dev/null
+++ b/spec/workers/workbench_import_worker_spec.rb
@@ -0,0 +1,119 @@
+RSpec.describe WorkbenchImportWorker, type: [:worker, :request] do
+
+ let( :worker ) { described_class.new }
+ let( :import ){ build_stubbed :import, token_download: download_token, file: zip_file }
+
+ let( :workbench ){ import.workbench }
+ let( :referential ){ import.referential }
+ let( :api_key ){ build_stubbed :api_key, referential: referential, token: "#{referential.id}-#{SecureRandom.hex}" }
+ let( :params ) do
+ { netex_import:
+ { referential_id: referential.id, workbench_id: workbench.id }
+ }
+ end
+
+ # http://www.example.com/workbenches/:workbench_id/imports/:id/download
+ let( :host ){ Rails.configuration.rails_host }
+ let( :path ){ download_workbench_import_path(workbench, import) }
+
+ let( :downloaded_zip ){ double("downloaded zip") }
+ let( :download_zip_response ){ OpenStruct.new( body: downloaded_zip ) }
+ let( :download_token ){ SecureRandom.urlsafe_base64 }
+
+
+ let( :upload_path ) { api_v1_netex_imports_path(format: :json) }
+
+ let( :entry_group_streams ) do
+ entry_count.times.map{ |i| double( "entry group stream #{i}" ) }
+ end
+ let( :entry_groups ) do
+ entry_count.times.map do | i |
+ {"entry_group_name#{i}" => entry_group_streams[i] }
+ end
+ end
+
+ let( :zip_service ){ double("zip service") }
+ let( :zip_file ){ open_fixture('multiple_references_import.zip') }
+
+ let( :post_response_ok ){ double(status: 201, body: "{}") }
+
+ before do
+ # Silence Logger
+ allow_any_instance_of(Logger).to receive(:info)
+ allow_any_instance_of(Logger).to receive(:warn)
+
+ # That should be `build_stubbed's` job, no?
+ allow(Import).to receive(:find).with(import.id).and_return(import)
+
+ allow(Api::V1::ApiKey).to receive(:from).and_return(api_key)
+ allow(ZipService).to receive(:new).with(downloaded_zip).and_return zip_service
+ expect(zip_service).to receive(:entry_group_streams).and_return(entry_groups)
+ expect( import ).to receive(:update_attributes).with(status: 'running')
+ end
+
+
+ context 'multireferential zipfile, no errors' do
+ let( :entry_count ){ 2 }
+
+ it 'downloads a zip file, cuts it, and uploads all pieces' do
+
+ expect(HTTPService).to receive(:get_resource)
+ .with(host: host, path: path, params: {token: download_token})
+ .and_return( download_zip_response )
+
+ entry_groups.each do | entry_group_name, entry_group_stream |
+ mock_post entry_group_name, entry_group_stream, post_response_ok
+ end
+
+ expect( import ).to receive(:update_attributes).with(total_steps: 2)
+ expect( import ).to receive(:update_attributes).with(current_step: 1)
+ expect( import ).to receive(:update_attributes).with(current_step: 2)
+
+ worker.perform import.id
+
+ end
+ end
+
+ context 'multireferential zipfile with error' do
+ let( :entry_count ){ 3 }
+ let( :post_response_failure ){ double(status: 406, body: {error: 'What was you thinking'}) }
+
+ it 'downloads a zip file, cuts it, and uploads some pieces' do
+ expect(HTTPService).to receive(:get_resource)
+ .with(host: host, path: path, params: {token: download_token})
+ .and_return( download_zip_response )
+
+ # First entry_group succeeds
+ entry_groups[0..0].each do | entry_group_name, entry_group_stream |
+ mock_post entry_group_name, entry_group_stream, post_response_ok
+ end
+
+ # Second entry_group fails (M I S E R A B L Y)
+ entry_groups[1..1].each do | entry_group_name, entry_group_stream |
+ mock_post entry_group_name, entry_group_stream, post_response_failure
+ WorkbenchImportWorker::RETRY_DELAYS.each do | delay |
+ mock_post entry_group_name, entry_group_stream, post_response_failure
+ expect_any_instance_of(RetryService).to receive(:sleep).with(delay)
+ end
+ end
+
+ expect( import ).to receive(:update_attributes).with(total_steps: 3)
+ expect( import ).to receive(:update_attributes).with(current_step: 1)
+ expect( import ).to receive(:update_attributes).with(current_step: 2)
+ expect( import ).to receive(:update_attributes).with(current_step: 3, status: 'failed')
+
+ worker.perform import.id
+
+ end
+ end
+
+ def mock_post entry_group_name, entry_group_stream, response
+ expect( HTTPService ).to receive(:post_resource)
+ .with(host: host,
+ path: upload_path,
+ token: api_key.token,
+ params: params,
+ upload: {file: [entry_group_stream, 'application/zip', entry_group_name]})
+ .and_return(response)
+ end
+end