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 "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: "

Ciao {{contatto_nome}}

", 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: "

Versione A

", subject_b: "Oggetto B {{societa}}", body_html_b: "

Versione B

", 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: "

Corpo dal template B

" ) 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: "

Versione B dal template

" ) 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: "

Versione A

", 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