# frozen_string_literal: true require 'rails_helper' RSpec.describe Users::ImportDataJob, type: :job do let(:user) { create(:user) } let(:import) { create(:import, user: user, source: :user_data_archive, name: 'test_export.zip') } let(:archive_path) { Rails.root.join('tmp', 'test_export.zip') } let(:job) { described_class.new } before do FileUtils.touch(archive_path) allow(import).to receive(:file).and_return( double('ActiveStorage::Attached::One', download: proc { |&block| File.read(archive_path).each_char { |c| block.call(c) } } ) ) end after do FileUtils.rm_f(archive_path) if File.exist?(archive_path) end describe '#perform' do context 'when import is successful' do before do import_service = instance_double(Users::ImportData) allow(Users::ImportData).to receive(:new).and_return(import_service) allow(import_service).to receive(:import).and_return({ settings_updated: true, areas_created: 2, places_created: 3, imports_created: 1, exports_created: 1, trips_created: 2, stats_created: 1, notifications_created: 2, visits_created: 4, points_created: 1000, files_restored: 7 }) allow(File).to receive(:exist?).and_return(true) allow(File).to receive(:delete) allow(Rails.logger).to receive(:info) end it 'calls the import service with correct parameters' do expect(Users::ImportData).to receive(:new).with(user, anything) job.perform(import.id) end it 'calls import on the service' do import_service = instance_double(Users::ImportData) allow(Users::ImportData).to receive(:new).and_return(import_service) expect(import_service).to receive(:import) job.perform(import.id) end it 'completes successfully without updating import status' do expect(import).not_to receive(:update!) job.perform(import.id) end it 'does not create error notifications when successful' do expect(::Notifications::Create).not_to receive(:new) job.perform(import.id) end end context 'when import fails' do let(:error_message) { 'Import failed due to invalid archive' } let(:error) { StandardError.new(error_message) } before do import_service = instance_double(Users::ImportData) allow(Users::ImportData).to receive(:new).and_return(import_service) allow(import_service).to receive(:import).and_raise(error) notification_service = instance_double(::Notifications::Create, call: true) allow(::Notifications::Create).to receive(:new).and_return(notification_service) allow(File).to receive(:exist?).and_return(true) allow(File).to receive(:delete) allow(Rails.logger).to receive(:info) allow(ExceptionReporter).to receive(:call) end it 'reports the error to ExceptionReporter' do expect(ExceptionReporter).to receive(:call).with(error, "Import job failed for user #{user.id}") expect { job.perform(import.id) }.to raise_error(StandardError, error_message) end it 'does not update import status on failure' do expect(import).not_to receive(:update!) expect { job.perform(import.id) }.to raise_error(StandardError, error_message) end it 'creates a failure notification for the user' do expect(::Notifications::Create).to receive(:new).with( user: user, title: 'Data import failed', content: "Your data import failed with error: #{error_message}. Please check the archive format and try again.", kind: :error ) expect { job.perform(import.id) }.to raise_error(StandardError, error_message) end it 're-raises the error' do expect { job.perform(import.id) }.to raise_error(StandardError, error_message) end end context 'when import does not exist' do let(:non_existent_import_id) { 999999 } it 'raises ActiveRecord::RecordNotFound' do expect { job.perform(non_existent_import_id) }.to raise_error(ActiveRecord::RecordNotFound) end it 'does not create a notification when import is not found' do expect(::Notifications::Create).not_to receive(:new) expect { job.perform(non_existent_import_id) }.to raise_error(ActiveRecord::RecordNotFound) end end context 'when archive file download fails' do let(:error_message) { 'File download error' } let(:error) { StandardError.new(error_message) } before do allow(import).to receive(:file).and_return( double('ActiveStorage::Attached::One', download: proc { raise error }) ) notification_service = instance_double(::Notifications::Create, call: true) allow(::Notifications::Create).to receive(:new).and_return(notification_service) end it 'creates notification with the correct user object' do notification_service = instance_double(::Notifications::Create, call: true) expect(::Notifications::Create).to receive(:new).with( user: user, title: 'Data import failed', content: a_string_matching(/Your data import failed with error:.*Please check the archive format and try again\./), kind: :error ).and_return(notification_service) expect(notification_service).to receive(:call) expect { job.perform(import.id) }.to raise_error(StandardError) end end end describe 'job configuration' do it 'is queued in the imports queue' do expect(described_class.queue_name).to eq('imports') end end end