failed_email_spec.rb 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. # Copyright (C) 2012-2024 Zammad Foundation, https://zammad-foundation.org/
  2. require 'rails_helper'
  3. RSpec.describe FailedEmail, :aggregate_failures, type: :model do
  4. subject(:instance) { create(:failed_email) }
  5. describe '#parsing_error' do
  6. it 'sets parsing error' do
  7. instance.parsing_error = 'text'
  8. expect(instance).to have_attributes(parsing_error: 'text')
  9. end
  10. it 'sets parsing error off error' do
  11. instance.parsing_error = StandardError.new('Sample error')
  12. expect(instance).to have_attributes(parsing_error: include('Sample error'))
  13. end
  14. end
  15. describe '.by_filepath' do
  16. let!(:failed_email) { create(:failed_email) }
  17. it 'finds the email by filename' do
  18. expect(described_class.by_filepath("some/folder/#{failed_email.id}.eml")).to eq(failed_email)
  19. end
  20. it 'finds the email by id' do
  21. expect(described_class.by_filepath(failed_email.id.to_s)).to eq(failed_email)
  22. end
  23. it 'does not find with another extension' do
  24. expect(described_class.by_filepath("some/folder/#{failed_email.id}.yml")).to be_nil
  25. end
  26. it 'does not find if not existant' do
  27. expect(described_class.by_filepath('1337.eml')).to be_nil
  28. end
  29. end
  30. describe '#reprocess' do
  31. context 'when it succeeds' do
  32. it 'destroys entry' do
  33. instance.reprocess
  34. expect(instance).to be_destroyed
  35. end
  36. it 'creates a ticket' do
  37. ticket = instance.reprocess
  38. expect(ticket.articles.first).to have_attributes(
  39. body: 'Some Text'
  40. )
  41. end
  42. end
  43. context 'when it fails' do
  44. before do
  45. allow_any_instance_of(Channel::EmailParser)
  46. .to receive(:process_with_timeout)
  47. .and_return([])
  48. end
  49. it 'increases retries count on failure' do
  50. expect { instance.reprocess }
  51. .to change(instance, :retries).by(1)
  52. end
  53. it 'does not create a ticket' do
  54. expect { instance.reprocess }.not_to change(Ticket, :count)
  55. end
  56. end
  57. end
  58. describe '.reprocess_all' do
  59. let!(:failed_email) { create(:failed_email, :invalid) }
  60. let!(:failed_but_correct_email) { create(:failed_email) }
  61. before do
  62. failed_email
  63. failed_but_correct_email
  64. end
  65. it 'creates one ticket for the parseable mail and keeps the other' do
  66. expect { described_class.reprocess_all }
  67. .to change(Ticket, :count).by(1)
  68. .and(change(described_class, :count).by(-1))
  69. end
  70. it 'returns a list of processed email files' do
  71. expect(described_class.reprocess_all).to eq(["#{failed_but_correct_email.id}.eml"])
  72. end
  73. end
  74. describe '.export_all' do
  75. it 'calls export with all records' do
  76. instance
  77. allow_any_instance_of(described_class)
  78. .to receive(:export)
  79. .with('path')
  80. .and_return('path/file.eml')
  81. expect(described_class.export_all('path'))
  82. .to contain_exactly('path/file.eml')
  83. end
  84. end
  85. describe '#export' do
  86. it 'creates a file' do
  87. path = instance.export
  88. expect(File.binread(path)).to eq(instance.data)
  89. end
  90. end
  91. describe '.import_all' do
  92. it 'calls import with all files' do
  93. path = described_class.generate_path
  94. instance.export(path)
  95. allow(described_class)
  96. .to receive(:import)
  97. .with(path.join("#{instance.id}.eml"))
  98. .and_return('imported_path')
  99. expect(described_class.import_all(path))
  100. .to contain_exactly('imported_path')
  101. end
  102. end
  103. describe '.import' do
  104. let(:path) { described_class.generate_path }
  105. let!(:file_path) { instance.export(path) }
  106. let(:sample_text) { "#{instance.data}\n" }
  107. let(:import_result) { described_class.import(path.join("#{instance.id}.eml")) }
  108. after do
  109. file_path.unlink if file_path.exist?
  110. end
  111. context 'with unprocessable content' do
  112. subject(:instance) { create(:failed_email, data: Faker::Lorem.sentence) }
  113. it 'fails on reimporting' do
  114. expect(import_result).to be_nil
  115. expect(instance.reload.retries).to eq(2)
  116. end
  117. it 'keeps the file' do
  118. expect(file_path).to exist
  119. end
  120. context 'with changed valid file content' do
  121. before { File.binwrite(file_path, create(:failed_email).data) }
  122. it 'reimports correctly' do
  123. expect { import_result }.to change(Ticket, :count).by(1)
  124. expect(import_result).to eq(file_path)
  125. expect(file_path).not_to exist
  126. end
  127. end
  128. context 'with changed invalid file content' do
  129. before { File.binwrite(file_path, Faker::Lorem.sentence) }
  130. it 'fails to import again' do
  131. expect(import_result).to be_nil
  132. expect(instance.reload.retries).to eq(2)
  133. end
  134. end
  135. end
  136. it 'returns nil if database row does not exist' do
  137. expect(described_class.import(Pathname.new('tmp/1337.eml'))).to be_nil
  138. end
  139. end
  140. end