386 lines
15 KiB
Ruby
386 lines
15 KiB
Ruby
require "test_helper"
|
|
|
|
class MailingsControllerTest < ActionDispatch::IntegrationTest
|
|
setup do
|
|
@project = projects(:matchlivetv)
|
|
@identity = create_mail_identity
|
|
opportunities(:deal).update!(send_status: "to_send", pipeline_stage: "to_contact")
|
|
end
|
|
|
|
test "lists mailings in project space" do
|
|
login_as users(:admin)
|
|
follow_redirect! if response.redirect?
|
|
|
|
get dashboard_mailings_path(project_code: @project.code)
|
|
assert_response :success
|
|
assert_match(/Invii email/, response.body)
|
|
end
|
|
|
|
test "dashboard shows hourly send throughput" do
|
|
login_as users(:admin)
|
|
follow_redirect! if response.redirect?
|
|
|
|
mailing = create_mailing(identity: @identity, audience: "to_send")
|
|
org = organizations(:acme)
|
|
mailing.mailing_recipients.create!(
|
|
organization: org,
|
|
contact: org.contacts.first,
|
|
email: org.email,
|
|
status: "sent",
|
|
sent_at: 8.minutes.ago
|
|
)
|
|
|
|
get dashboard_mailings_path(project_code: @project.code)
|
|
assert_response :success
|
|
assert_select "div", text: "Mail / ora"
|
|
assert_match(/1 ultimi 15 min/, response.body)
|
|
end
|
|
|
|
test "creates a draft and opens audience filters" do
|
|
login_as users(:admin)
|
|
follow_redirect! if response.redirect?
|
|
|
|
assert_difference -> { Mailing.count } => 1, -> { MailingRecipient.count } => 0 do
|
|
post mailings_path(project_code: @project.code), params: {
|
|
mailing: {
|
|
name: "Lancio",
|
|
mail_identity_id: @identity.id,
|
|
audience: "to_send",
|
|
subject: "Ciao {{societa}}",
|
|
body_html: "<p>Ciao {{contatto_nome}}</p>",
|
|
interval_seconds: 0
|
|
}
|
|
}
|
|
end
|
|
mailing = Mailing.last
|
|
assert_redirected_to audience_mailing_path(mailing, project_code: @project.code)
|
|
assert mailing.mailing_recipients.none?
|
|
end
|
|
|
|
test "audience apply builds frozen recipient list" do
|
|
login_as users(:admin)
|
|
follow_redirect! if response.redirect?
|
|
mailing = create_mailing(identity: @identity, audience: "to_send")
|
|
|
|
patch audience_mailing_path(mailing, project_code: @project.code), params: {
|
|
intent: "apply",
|
|
filters: { preset: "to_send" }
|
|
}
|
|
|
|
assert_redirected_to mailing_path(mailing, project_code: @project.code)
|
|
assert mailing.reload.mailing_recipients.any?
|
|
assert_equal "pending", mailing.mailing_recipients.first.status
|
|
end
|
|
|
|
test "audience page shows live filter counts" do
|
|
login_as users(:admin)
|
|
follow_redirect! if response.redirect?
|
|
mailing = create_mailing(identity: @identity, audience: "to_send")
|
|
|
|
get audience_mailing_path(mailing, project_code: @project.code)
|
|
assert_response :success
|
|
assert_match(/Destinatari/, response.body)
|
|
assert_match(/Corrispondenze/, response.body)
|
|
assert_match(/Genera lista e rivedi/, response.body)
|
|
assert_match(/Chi deve ricevere questa email/, response.body)
|
|
assert_select "details[data-section=organization]"
|
|
assert_select "details[data-section=campaign]"
|
|
assert_select "details[data-section=history]"
|
|
assert_select "details[data-section=exclusions]"
|
|
assert_select "input[type=checkbox][name='filters[sports][]']"
|
|
assert_select "input[type=checkbox][name='filters[never_contacted]']"
|
|
assert_select "select[name='filters[sports][]']", false
|
|
end
|
|
|
|
test "audience preview saves filters without building recipients" do
|
|
login_as users(:admin)
|
|
follow_redirect! if response.redirect?
|
|
mailing = create_mailing(identity: @identity, audience: "to_send")
|
|
|
|
patch audience_mailing_path(mailing, project_code: @project.code), params: {
|
|
intent: "preview",
|
|
filters: { preset: "all", sports: [ "Calcio" ] }
|
|
}
|
|
|
|
assert_redirected_to audience_mailing_path(mailing, project_code: @project.code)
|
|
follow_redirect!
|
|
assert_response :success
|
|
assert_match(/Destinatari/, response.body)
|
|
assert mailing.reload.mailing_recipients.none?
|
|
assert_equal "all", mailing.audience
|
|
assert_equal [ "Calcio" ], mailing.parsed_audience_filters["sports"]
|
|
end
|
|
|
|
test "audience preview accepts a single sport value and never contacted" do
|
|
login_as users(:admin)
|
|
follow_redirect! if response.redirect?
|
|
mailing = create_mailing(identity: @identity, audience: "to_send")
|
|
|
|
patch audience_mailing_path(mailing, project_code: @project.code), params: {
|
|
intent: "preview",
|
|
filters: { preset: "all", sports: "Calcio", never_contacted: "1" }
|
|
}
|
|
|
|
assert_redirected_to audience_mailing_path(mailing, project_code: @project.code)
|
|
follow_redirect!
|
|
assert_response :success
|
|
mailing.reload
|
|
assert_equal [ "Calcio" ], mailing.parsed_audience_filters["sports"]
|
|
assert_equal "never", mailing.parsed_audience_filters.history_kind
|
|
assert_select "input[type=checkbox][name='filters[sports][]'][value=Calcio][checked]"
|
|
assert_select "input[type=checkbox][name='filters[never_contacted]'][checked]"
|
|
end
|
|
|
|
test "check recipients then queue send" do
|
|
login_as users(:admin)
|
|
follow_redirect! if response.redirect?
|
|
mailing = create_mailing(identity: @identity, audience: "to_send")
|
|
mailing.rebuild_recipients!
|
|
recipient = mailing.mailing_recipients.first
|
|
|
|
patch update_recipients_mailing_path(mailing, project_code: @project.code), params: { pending_ids: [recipient.id] }
|
|
assert_redirected_to mailing_path(mailing, project_code: @project.code)
|
|
assert_equal "pending", recipient.reload.status
|
|
|
|
post test_send_mailing_path(mailing, project_code: @project.code), params: {
|
|
to: users(:admin).email,
|
|
vars: { societa: "ASD Test Calcio", contatto_nome: "Mario" }
|
|
}
|
|
assert mailing.reload.tested?
|
|
|
|
perform_enqueued_jobs do
|
|
post queue_mailing_path(mailing, project_code: @project.code)
|
|
end
|
|
|
|
assert_redirected_to dashboard_mailings_path(project_code: @project.code)
|
|
assert_equal "sent", mailing.reload.status
|
|
assert_equal "sent", recipient.reload.status
|
|
assert_equal "sent", opportunities(:deal).reload.send_status
|
|
assert_equal "contacted", opportunities(:deal).pipeline_stage
|
|
assert_equal 2, ActionMailer::Base.deliveries.size
|
|
assert_equal "Ciao ASD Test Calcio", ActionMailer::Base.deliveries.last.subject
|
|
body = (ActionMailer::Base.deliveries.last.html_part || ActionMailer::Base.deliveries.last).body.to_s
|
|
assert_match(%r{/t/o/#{Regexp.escape(recipient.reload.tracking_token)}\.gif}, body)
|
|
end
|
|
|
|
test "queue send requires test email first" do
|
|
login_as users(:admin)
|
|
follow_redirect! if response.redirect?
|
|
mailing = create_mailing(identity: @identity, audience: "to_send")
|
|
mailing.rebuild_recipients!
|
|
recipient = mailing.mailing_recipients.first
|
|
patch update_recipients_mailing_path(mailing, project_code: @project.code), params: { pending_ids: [recipient.id] }
|
|
|
|
post queue_mailing_path(mailing, project_code: @project.code)
|
|
assert_redirected_to mailing_path(mailing, project_code: @project.code)
|
|
assert_equal "draft", mailing.reload.status
|
|
assert_not mailing.tested?
|
|
end
|
|
|
|
test "test send goes to current user" do
|
|
login_as users(:admin)
|
|
follow_redirect! if response.redirect?
|
|
mailing = create_mailing(identity: @identity, audience: "all")
|
|
mailing.rebuild_recipients!
|
|
|
|
assert_emails 1 do
|
|
post test_send_mailing_path(mailing, project_code: @project.code), params: {
|
|
to: users(:admin).email,
|
|
vars: { societa: "Società Prova", contatto_nome: "Anna Test" }
|
|
}
|
|
end
|
|
mail = ActionMailer::Base.deliveries.last
|
|
assert_equal [users(:admin).email], mail.to
|
|
assert_match(/\[TEST\]/, mail.subject)
|
|
body = (mail.html_part || mail).body.to_s
|
|
assert_match(/Società Prova/, mail.subject)
|
|
assert_no_match(%r{/t/o/}, body)
|
|
assert mailing.reload.tested?
|
|
assert_equal users(:admin).email, mailing.test_sent_to
|
|
end
|
|
|
|
test "creates an A/B mailing and sends variant B as test" do
|
|
login_as users(:admin)
|
|
follow_redirect! if response.redirect?
|
|
|
|
post mailings_path(project_code: @project.code), params: {
|
|
mailing: {
|
|
name: "AB lancio",
|
|
mail_identity_id: @identity.id,
|
|
audience: "to_send",
|
|
ab_test: "1",
|
|
ab_assignment: "from_record",
|
|
subject: "Oggetto A {{societa}}",
|
|
body_html: "<p>Versione A</p>",
|
|
subject_b: "Oggetto B {{societa}}",
|
|
body_html_b: "<p>Versione B</p>",
|
|
interval_seconds: 0
|
|
}
|
|
}
|
|
mailing = Mailing.last
|
|
assert mailing.ab_test?
|
|
patch audience_mailing_path(mailing, project_code: @project.code), params: {
|
|
intent: "apply",
|
|
filters: { preset: "to_send" }
|
|
}
|
|
assert_equal "A", mailing.reload.mailing_recipients.first.ab_variant
|
|
|
|
assert_emails 1 do
|
|
post test_send_mailing_path(mailing, project_code: @project.code), params: {
|
|
to: users(:admin).email,
|
|
variant: "B",
|
|
vars: { societa: "ASD Test Calcio" }
|
|
}
|
|
end
|
|
mail = ActionMailer::Base.deliveries.last
|
|
assert_match(/\[TEST B\] Oggetto B ASD Test Calcio/, mail.subject)
|
|
body = (mail.html_part || mail).body.to_s
|
|
assert_match(/Versione B/, body)
|
|
end
|
|
|
|
test "new mailing form embeds template content for the picker" do
|
|
login_as users(:admin)
|
|
follow_redirect! if response.redirect?
|
|
template = MailTemplate.create!(
|
|
project: @project,
|
|
name: "Variante B picker",
|
|
subject: "Oggetto dal template B",
|
|
body_html: "<p>Corpo dal template B</p>"
|
|
)
|
|
|
|
get new_mailing_path(project_code: @project.code)
|
|
assert_response :success
|
|
assert_match(/template-picker/, response.body)
|
|
assert_match(/Oggetto dal template B/, response.body)
|
|
assert_match(/Corpo dal template B/, response.body)
|
|
assert_includes response.body, template.id.to_s
|
|
end
|
|
|
|
test "create copies blank variant B fields from selected template" do
|
|
login_as users(:admin)
|
|
follow_redirect! if response.redirect?
|
|
template_b = MailTemplate.create!(
|
|
project: @project,
|
|
name: "Template B server",
|
|
subject: "B {{societa}}",
|
|
body_html: "<p>Versione B dal template</p>"
|
|
)
|
|
|
|
post mailings_path(project_code: @project.code), params: {
|
|
mailing: {
|
|
name: "AB da template",
|
|
mail_identity_id: @identity.id,
|
|
mail_template_b_id: template_b.id,
|
|
audience: "to_send",
|
|
ab_test: "1",
|
|
ab_assignment: "from_record",
|
|
subject: "Oggetto A",
|
|
body_html: "<p>Versione A</p>",
|
|
subject_b: "",
|
|
body_html_b: "",
|
|
interval_seconds: 0
|
|
}
|
|
}
|
|
mailing = Mailing.last
|
|
assert_redirected_to audience_mailing_path(mailing, project_code: @project.code)
|
|
assert_equal "B {{societa}}", mailing.subject_b
|
|
assert_includes mailing.body_html_b, "Versione B dal template"
|
|
end
|
|
|
|
test "dashboard lists a delete action for drafts" do
|
|
login_as users(:admin)
|
|
follow_redirect! if response.redirect?
|
|
mailing = create_mailing(identity: @identity, audience: "to_send", name: "Bozza da togliere")
|
|
|
|
get dashboard_mailings_path(project_code: @project.code)
|
|
assert_response :success
|
|
assert_select "form[action=?]", mailing_path(mailing, project_code: @project.code) do
|
|
assert_select "button", text: /Elimina/
|
|
end
|
|
end
|
|
|
|
test "destroys a draft mailing" do
|
|
login_as users(:admin)
|
|
follow_redirect! if response.redirect?
|
|
mailing = create_mailing(identity: @identity, audience: "to_send")
|
|
|
|
assert_difference -> { Mailing.count } => -1 do
|
|
delete mailing_path(mailing, project_code: @project.code)
|
|
end
|
|
assert_redirected_to dashboard_mailings_path(project_code: @project.code)
|
|
end
|
|
|
|
test "does not destroy a sending mailing" do
|
|
login_as users(:admin)
|
|
follow_redirect! if response.redirect?
|
|
mailing = create_mailing(identity: @identity, audience: "to_send")
|
|
mailing.update!(status: "sending", queued_at: Time.current, test_sent_at: Time.current, test_sent_to: "test@example.com")
|
|
|
|
assert_no_difference -> { Mailing.count } do
|
|
delete mailing_path(mailing, project_code: @project.code)
|
|
end
|
|
assert_redirected_to dashboard_mailings_path(project_code: @project.code)
|
|
assert mailing.reload.sending?
|
|
end
|
|
|
|
test "pause keeps remaining recipients and resume continues from there" do
|
|
login_as users(:admin)
|
|
follow_redirect! if response.redirect?
|
|
create_campaign_org(name: "Seconda societa", email: "seconda@example.com")
|
|
mailing = create_mailing(identity: @identity, audience: "to_send")
|
|
mailing.rebuild_recipients!
|
|
recipients = mailing.mailing_recipients.order(:id).to_a
|
|
assert recipients.size >= 2
|
|
recipients.first.update!(status: "sent", sent_at: Time.current)
|
|
recipients.second.update!(status: "queued")
|
|
mailing.update!(status: "sending", queued_at: Time.current, test_sent_at: Time.current, test_sent_to: "test@example.com")
|
|
|
|
post pause_mailing_path(mailing, project_code: @project.code)
|
|
|
|
assert_redirected_to dashboard_mailings_path(project_code: @project.code)
|
|
assert_equal "paused", mailing.reload.status
|
|
assert_equal "sent", recipients.first.reload.status
|
|
assert_equal "queued", recipients.second.reload.status
|
|
|
|
post resume_mailing_path(mailing, project_code: @project.code)
|
|
|
|
assert_redirected_to dashboard_mailings_path(project_code: @project.code)
|
|
assert_equal "sending", mailing.reload.status
|
|
assert_equal "queued", recipients.second.reload.status
|
|
end
|
|
|
|
test "cancel stops pending recipients and keeps sent ones" do
|
|
login_as users(:admin)
|
|
follow_redirect! if response.redirect?
|
|
create_campaign_org(name: "Seconda societa", email: "seconda@example.com")
|
|
mailing = create_mailing(identity: @identity, audience: "to_send")
|
|
mailing.rebuild_recipients!
|
|
recipients = mailing.mailing_recipients.order(:id).to_a
|
|
assert recipients.size >= 2
|
|
recipients.first.update!(status: "sent", sent_at: Time.current)
|
|
mailing.update!(status: "sending", queued_at: Time.current, test_sent_at: Time.current, test_sent_to: "test@example.com")
|
|
|
|
post cancel_mailing_path(mailing, project_code: @project.code)
|
|
|
|
assert_redirected_to dashboard_mailings_path(project_code: @project.code)
|
|
assert_equal "cancelled", mailing.reload.status
|
|
assert_equal "sent", recipients.first.reload.status
|
|
assert_equal "skipped", recipients.second.reload.status
|
|
assert_equal "invio annullato", recipients.second.skip_reason
|
|
assert mailing.mailing_recipients.pending.none?
|
|
end
|
|
|
|
test "sending mailing show updates inside a turbo frame" do
|
|
login_as users(:admin)
|
|
follow_redirect! if response.redirect?
|
|
mailing = create_mailing(identity: @identity, audience: "to_send")
|
|
mailing.rebuild_recipients!
|
|
mailing.update!(status: "sending", queued_at: Time.current, test_sent_at: Time.current, test_sent_to: "test@example.com")
|
|
|
|
get mailing_path(mailing, project_code: @project.code)
|
|
assert_response :success
|
|
assert_select "turbo-frame#mailing_live[target=_top]"
|
|
assert_select "[data-controller='auto-reload']"
|
|
end
|
|
end
|