123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266 |
- # Copyright (C) 2012-2024 Zammad Foundation, https://zammad-foundation.org/
- require 'rails_helper'
- RSpec.describe ImportJob do
- before do
- stub_const test_backend_name, test_backend_class
- stub_const test_backend_noreschedule_name, test_backend_noreschedule_class
- end
- let(:test_backend_name) { 'Import::Test' }
- let(:test_backend_class) do
- Class.new(Import::Base) do
- def start
- @import_job.result = { state: 'Done' }
- end
- end
- end
- let(:test_backend_noreschedule_name) { 'Import::NoRescheduleMethod' }
- let(:test_backend_noreschedule_class) do
- Class.new do
- def initialize(import_job)
- @import_job = import_job
- end
- def start
- @import_job.result = { state: 'Done' }
- end
- def reschedule?(_delayed_job)
- 'invalid_but_checkable_result'
- end
- end
- end
- describe '#dry_run' do
- it 'starts delayed dry run import job' do
- expect do
- described_class.dry_run(
- name: test_backend_name,
- payload: {}
- )
- end.to change(Delayed::Job, :count).by(1)
- end
- it 'starts dry run import job immediately' do
- expect do
- described_class.dry_run(
- name: test_backend_name,
- payload: {},
- delay: false
- )
- end.not_to change(Delayed::Job, :count)
- end
- it "doesn't start job if one exists" do
- create(:import_job, dry_run: true)
- expect do
- described_class.dry_run(
- name: test_backend_name,
- payload: {},
- )
- end.not_to change(Delayed::Job, :count)
- end
- end
- describe '#queue_registered' do
- it 'queues registered import jobs' do
- allow(Setting).to receive(:get)
- allow(Setting).to receive(:get).with('import_backends').and_return([test_backend_name])
- expect do
- described_class.queue_registered
- end.to change {
- described_class.exists?(name: test_backend_name)
- }
- end
- it "doesn't queue if backend isn't #queueable?" do
- allow(Setting).to receive(:get)
- allow(Setting).to receive(:get).with('import_backends').and_return([test_backend_name])
- allow(test_backend_class).to receive(:queueable?).and_return(false)
- expect do
- described_class.queue_registered
- end.not_to change {
- described_class.exists?(name: test_backend_name)
- }
- end
- it "doesn't queue if unfinished job entries exist" do
- create(:import_job)
- allow(Setting).to receive(:get)
- allow(Setting).to receive(:get).with('import_backends').and_return([test_backend_name])
- expect do
- described_class.queue_registered
- end.not_to change {
- described_class.exists?(name: test_backend_name)
- }
- end
- it 'logs errors for invalid registered backends' do
- allow(Setting).to receive(:get)
- allow(Setting).to receive(:get).with('import_backends').and_return(['InvalidBackend'])
- allow(described_class.logger).to receive(:error)
- described_class.queue_registered
- expect(described_class.logger).to have_received(:error)
- end
- end
- describe '#start' do
- it 'starts queued import jobs' do
- create_list(:import_job, 2)
- expect do
- described_class.start
- end.to change {
- described_class.where(started_at: nil).count
- }.by(-2)
- end
- it "doesn't start queued dry run import jobs" do
- create_list(:import_job, 2)
- create(:import_job, dry_run: true)
- expect do
- described_class.start
- end.to change {
- described_class.where(started_at: nil).count
- }.by(-2)
- end
- end
- describe '#start_registered' do
- it 'queues and starts registered import backends' do
- allow(Setting).to receive(:get)
- allow(Setting).to receive(:get).with('import_backends').and_return([test_backend_name])
- expect do
- described_class.start_registered
- end.to change {
- described_class.where.not(started_at: nil).where.not(finished_at: nil).count
- }.by(1)
- end
- end
- describe '#backend_valid?' do
- it 'detects existing backends' do
- expect(described_class.backend_valid?(test_backend_name)).to be true
- end
- it 'detects not existing backends' do
- expect(described_class.backend_valid?('InvalidBackend')).to be false
- end
- end
- describe '#backends' do
- it 'returns list of backend namespaces' do
- allow(Setting).to receive(:get).with('import_backends').and_return(['Import::Ldap'])
- allow(Import::Ldap).to receive(:active?).and_return(true)
- backends = described_class.backends
- expect(backends).to be_a(Array)
- expect(backends).not_to be_blank
- end
- it 'returns blank array if none are found' do
- allow(Setting).to receive(:get).with('import_backends')
- expect(described_class.backends).to eq([])
- end
- it "doesn't return invalid backends" do
- allow(Setting).to receive(:get).with('import_backends').and_return(['Import::InvalidBackend'])
- expect(described_class.backends).to eq([])
- end
- it "doesn't return inactive backends" do
- allow(Setting).to receive(:get).with('import_backends').and_return(['Import::Ldap'])
- allow(Import::Ldap).to receive(:active?).and_return(false)
- expect(described_class.backends).to eq([])
- end
- end
- describe '.start' do
- it 'runs import backend and updates started_at and finished_at' do
- instance = create(:import_job)
- expect do
- instance.start
- end.to change {
- instance.started_at
- }.and change {
- instance.finished_at
- }.and change {
- instance.result
- }
- end
- it 'handles exceptions as errors' do
- instance = create(:import_job)
- error_message = 'Some horrible error'
- allow_any_instance_of(test_backend_class).to receive(:start).and_raise(error_message)
- expect do
- instance.start
- instance.reload
- end.to change {
- instance.started_at
- }.and change {
- instance.finished_at
- }.and change {
- instance.result
- }
- expect(instance.result[:error]).to eq(error_message)
- end
- end
- describe '.reschedule?' do
- it 'returns false for already finished jobs' do
- instance = create(:import_job)
- delayed_job = double
- instance.update!(finished_at: Time.zone.now)
- expect(instance.reschedule?(delayed_job)).to be false
- end
- it 'returns false for backends not responding to reschedule?' do
- instance = create(:import_job)
- delayed_job = double
- expect(instance.reschedule?(delayed_job)).to be false
- end
- it 'returns the backend reschedule? value' do
- instance = create(:import_job, name: 'Import::NoRescheduleMethod')
- delayed_job = double
- expect(instance.reschedule?(delayed_job)).to eq 'invalid_but_checkable_result'
- end
- end
- end
|