aboutsummaryrefslogtreecommitdiffstats
path: root/actionmailer/test/message_delivery_test.rb
blob: 46260f64140d645dd2dbd464b48f2a0f365784eb (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
# frozen_string_literal: true

require "abstract_unit"
require "active_job"
require "mailers/delayed_mailer"

class MessageDeliveryTest < ActiveSupport::TestCase
  include ActiveJob::TestHelper

  setup do
    @previous_logger = ActiveJob::Base.logger
    @previous_delivery_method = ActionMailer::Base.delivery_method
    @previous_deliver_later_queue_name = ActionMailer::Base.deliver_later_queue_name
    ActionMailer::Base.deliver_later_queue_name = :test_queue
    ActionMailer::Base.delivery_method = :test
    ActiveJob::Base.logger = Logger.new(nil)
    ActiveJob::Base.queue_adapter.perform_enqueued_at_jobs = true
    ActiveJob::Base.queue_adapter.perform_enqueued_jobs = true

    DelayedMailer.last_error = nil
    DelayedMailer.last_rescue_from_instance = nil

    @mail = DelayedMailer.test_message(1, 2, 3)
  end

  teardown do
    ActionMailer::Base.deliveries.clear

    ActiveJob::Base.logger = @previous_logger
    ActionMailer::Base.delivery_method = @previous_delivery_method
    ActionMailer::Base.deliver_later_queue_name = @previous_deliver_later_queue_name

    DelayedMailer.last_error = nil
    DelayedMailer.last_rescue_from_instance = nil
  end

  test "should have a message" do
    assert @mail.message
  end

  test "its message should be a Mail::Message" do
    assert_equal Mail::Message, @mail.message.class
  end

  test "should respond to .deliver_later" do
    assert_respond_to @mail, :deliver_later
  end

  test "should respond to .deliver_later!" do
    assert_respond_to @mail, :deliver_later!
  end

  test "should respond to .deliver_now" do
    assert_respond_to @mail, :deliver_now
  end

  test "should respond to .deliver_now!" do
    assert_respond_to @mail, :deliver_now!
  end

  def test_should_enqueue_and_run_correctly_in_activejob
    @mail.deliver_later!
    assert_equal 1, ActionMailer::Base.deliveries.size
  end

  test "should enqueue the email with :deliver_now delivery method" do
    assert_performed_with(job: ActionMailer::MailDeliveryJob, args: ["DelayedMailer", "test_message", "deliver_now", args: [1, 2, 3]]) do
      @mail.deliver_later
    end
  end

  test "should enqueue the email with :deliver_now! delivery method" do
    assert_performed_with(job: ActionMailer::MailDeliveryJob, args: ["DelayedMailer", "test_message", "deliver_now!", args: [1, 2, 3]]) do
      @mail.deliver_later!
    end
  end

  test "should enqueue a delivery with a delay" do
    travel_to Time.new(2004, 11, 24, 01, 04, 44) do
      assert_performed_with(job: ActionMailer::MailDeliveryJob, at: Time.current + 10.minutes, args: ["DelayedMailer", "test_message", "deliver_now", args: [1, 2, 3]]) do
        @mail.deliver_later wait: 10.minutes
      end
    end
  end

  test "should enqueue a delivery at a specific time" do
    later_time = Time.current + 1.hour
    assert_performed_with(job: ActionMailer::MailDeliveryJob, at: later_time, args: ["DelayedMailer", "test_message", "deliver_now", args: [1, 2, 3]]) do
      @mail.deliver_later wait_until: later_time
    end
  end

  test "should enqueue the job on the correct queue" do
    assert_performed_with(job: ActionMailer::MailDeliveryJob, args: ["DelayedMailer", "test_message", "deliver_now", args: [1, 2, 3]], queue: "test_queue") do
      @mail.deliver_later
    end
  end

  test "should enqueue the job with the correct delivery job" do
    old_delivery_job = DelayedMailer.delivery_job
    DelayedMailer.delivery_job = DummyJob

    assert_performed_with(job: DummyJob, args: ["DelayedMailer", "test_message", "deliver_now", args: [1, 2, 3]]) do
      @mail.deliver_later
    end

    DelayedMailer.delivery_job = old_delivery_job
  end

  class DummyJob < ActionMailer::MailDeliveryJob; end

  test "can override the queue when enqueuing mail" do
    assert_performed_with(job: ActionMailer::MailDeliveryJob, args: ["DelayedMailer", "test_message", "deliver_now", args: [1, 2, 3]], queue: "another_queue") do
      @mail.deliver_later(queue: :another_queue)
    end
  end

  test "deliver_later after accessing the message is disallowed" do
    @mail.message # Load the message, which calls the mailer method.

    assert_raise RuntimeError do
      @mail.deliver_later
    end
  end

  test "job delegates error handling to mailer" do
    # Superclass not rescued by mailer's rescue_from RuntimeError
    message = DelayedMailer.test_raise("StandardError")
    assert_raise(StandardError) { message.deliver_later }
    assert_nil DelayedMailer.last_error
    assert_nil DelayedMailer.last_rescue_from_instance

    # Rescued by mailer's rescue_from RuntimeError
    message = DelayedMailer.test_raise("DelayedMailerError")
    assert_nothing_raised { message.deliver_later }
    assert_equal "boom", DelayedMailer.last_error.message
    assert_kind_of DelayedMailer, DelayedMailer.last_rescue_from_instance
  end

  class DeserializationErrorFixture
    include GlobalID::Identification

    def self.find(id)
      raise "boom, missing find"
    end

    attr_reader :id
    def initialize(id = 1)
      @id = id
    end

    def to_global_id(options = {})
      super app: "foo"
    end
  end

  test "job delegates deserialization errors to mailer class" do
    # Inject an argument that can't be deserialized.
    message = DelayedMailer.test_message(DeserializationErrorFixture.new)

    # DeserializationError is raised, rescued, and delegated to the handler
    # on the mailer class.
    assert_nothing_raised { message.deliver_later }
    assert_equal DelayedMailer, DelayedMailer.last_rescue_from_instance
    assert_equal "Error while trying to deserialize arguments: boom, missing find", DelayedMailer.last_error.message
  end
end