import_job_spec.rb 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266
  1. # Copyright (C) 2012-2024 Zammad Foundation, https://zammad-foundation.org/
  2. require 'rails_helper'
  3. RSpec.describe ImportJob do
  4. before do
  5. stub_const test_backend_name, test_backend_class
  6. stub_const test_backend_noreschedule_name, test_backend_noreschedule_class
  7. end
  8. let(:test_backend_name) { 'Import::Test' }
  9. let(:test_backend_class) do
  10. Class.new(Import::Base) do
  11. def start
  12. @import_job.result = { state: 'Done' }
  13. end
  14. end
  15. end
  16. let(:test_backend_noreschedule_name) { 'Import::NoRescheduleMethod' }
  17. let(:test_backend_noreschedule_class) do
  18. Class.new do
  19. def initialize(import_job)
  20. @import_job = import_job
  21. end
  22. def start
  23. @import_job.result = { state: 'Done' }
  24. end
  25. def reschedule?(_delayed_job)
  26. 'invalid_but_checkable_result'
  27. end
  28. end
  29. end
  30. describe '#dry_run' do
  31. it 'starts delayed dry run import job' do
  32. expect do
  33. described_class.dry_run(
  34. name: test_backend_name,
  35. payload: {}
  36. )
  37. end.to change(Delayed::Job, :count).by(1)
  38. end
  39. it 'starts dry run import job immediately' do
  40. expect do
  41. described_class.dry_run(
  42. name: test_backend_name,
  43. payload: {},
  44. delay: false
  45. )
  46. end.not_to change(Delayed::Job, :count)
  47. end
  48. it "doesn't start job if one exists" do
  49. create(:import_job, dry_run: true)
  50. expect do
  51. described_class.dry_run(
  52. name: test_backend_name,
  53. payload: {},
  54. )
  55. end.not_to change(Delayed::Job, :count)
  56. end
  57. end
  58. describe '#queue_registered' do
  59. it 'queues registered import jobs' do
  60. allow(Setting).to receive(:get)
  61. allow(Setting).to receive(:get).with('import_backends').and_return([test_backend_name])
  62. expect do
  63. described_class.queue_registered
  64. end.to change {
  65. described_class.exists?(name: test_backend_name)
  66. }
  67. end
  68. it "doesn't queue if backend isn't #queueable?" do
  69. allow(Setting).to receive(:get)
  70. allow(Setting).to receive(:get).with('import_backends').and_return([test_backend_name])
  71. allow(test_backend_class).to receive(:queueable?).and_return(false)
  72. expect do
  73. described_class.queue_registered
  74. end.not_to change {
  75. described_class.exists?(name: test_backend_name)
  76. }
  77. end
  78. it "doesn't queue if unfinished job entries exist" do
  79. create(:import_job)
  80. allow(Setting).to receive(:get)
  81. allow(Setting).to receive(:get).with('import_backends').and_return([test_backend_name])
  82. expect do
  83. described_class.queue_registered
  84. end.not_to change {
  85. described_class.exists?(name: test_backend_name)
  86. }
  87. end
  88. it 'logs errors for invalid registered backends' do
  89. allow(Setting).to receive(:get)
  90. allow(Setting).to receive(:get).with('import_backends').and_return(['InvalidBackend'])
  91. allow(described_class.logger).to receive(:error)
  92. described_class.queue_registered
  93. expect(described_class.logger).to have_received(:error)
  94. end
  95. end
  96. describe '#start' do
  97. it 'starts queued import jobs' do
  98. create_list(:import_job, 2)
  99. expect do
  100. described_class.start
  101. end.to change {
  102. described_class.where(started_at: nil).count
  103. }.by(-2)
  104. end
  105. it "doesn't start queued dry run import jobs" do
  106. create_list(:import_job, 2)
  107. create(:import_job, dry_run: true)
  108. expect do
  109. described_class.start
  110. end.to change {
  111. described_class.where(started_at: nil).count
  112. }.by(-2)
  113. end
  114. end
  115. describe '#start_registered' do
  116. it 'queues and starts registered import backends' do
  117. allow(Setting).to receive(:get)
  118. allow(Setting).to receive(:get).with('import_backends').and_return([test_backend_name])
  119. expect do
  120. described_class.start_registered
  121. end.to change {
  122. described_class.where.not(started_at: nil).where.not(finished_at: nil).count
  123. }.by(1)
  124. end
  125. end
  126. describe '#backend_valid?' do
  127. it 'detects existing backends' do
  128. expect(described_class.backend_valid?(test_backend_name)).to be true
  129. end
  130. it 'detects not existing backends' do
  131. expect(described_class.backend_valid?('InvalidBackend')).to be false
  132. end
  133. end
  134. describe '#backends' do
  135. it 'returns list of backend namespaces' do
  136. allow(Setting).to receive(:get).with('import_backends').and_return(['Import::Ldap'])
  137. allow(Import::Ldap).to receive(:active?).and_return(true)
  138. backends = described_class.backends
  139. expect(backends).to be_a(Array)
  140. expect(backends).not_to be_blank
  141. end
  142. it 'returns blank array if none are found' do
  143. allow(Setting).to receive(:get).with('import_backends')
  144. expect(described_class.backends).to eq([])
  145. end
  146. it "doesn't return invalid backends" do
  147. allow(Setting).to receive(:get).with('import_backends').and_return(['Import::InvalidBackend'])
  148. expect(described_class.backends).to eq([])
  149. end
  150. it "doesn't return inactive backends" do
  151. allow(Setting).to receive(:get).with('import_backends').and_return(['Import::Ldap'])
  152. allow(Import::Ldap).to receive(:active?).and_return(false)
  153. expect(described_class.backends).to eq([])
  154. end
  155. end
  156. describe '.start' do
  157. it 'runs import backend and updates started_at and finished_at' do
  158. instance = create(:import_job)
  159. expect do
  160. instance.start
  161. end.to change {
  162. instance.started_at
  163. }.and change {
  164. instance.finished_at
  165. }.and change {
  166. instance.result
  167. }
  168. end
  169. it 'handles exceptions as errors' do
  170. instance = create(:import_job)
  171. error_message = 'Some horrible error'
  172. allow_any_instance_of(test_backend_class).to receive(:start).and_raise(error_message)
  173. expect do
  174. instance.start
  175. instance.reload
  176. end.to change {
  177. instance.started_at
  178. }.and change {
  179. instance.finished_at
  180. }.and change {
  181. instance.result
  182. }
  183. expect(instance.result[:error]).to eq(error_message)
  184. end
  185. end
  186. describe '.reschedule?' do
  187. it 'returns false for already finished jobs' do
  188. instance = create(:import_job)
  189. delayed_job = double
  190. instance.update!(finished_at: Time.zone.now)
  191. expect(instance.reschedule?(delayed_job)).to be false
  192. end
  193. it 'returns false for backends not responding to reschedule?' do
  194. instance = create(:import_job)
  195. delayed_job = double
  196. expect(instance.reschedule?(delayed_job)).to be false
  197. end
  198. it 'returns the backend reschedule? value' do
  199. instance = create(:import_job, name: 'Import::NoRescheduleMethod')
  200. delayed_job = double
  201. expect(instance.reschedule?(delayed_job)).to eq 'invalid_but_checkable_result'
  202. end
  203. end
  204. end