Rende usabili i filtri destinatari e permette di eliminare le bozze email.
CI / scan_ruby (push) Failing after 12m54s
CI / scan_js (push) Successful in 12m34s
CI / lint (push) Failing after 13m10s

Le listbox non applicavano sport e altri criteri; ora i filtri sono checkbox, c'è «mai contattati» e dal cruscotto si cancellano le bozze. La lista organizzazioni allinea le colonne al foglio campagna.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-09-07 07:57:50 +02:00
co-authored by Cursor
parent e492c43bf8
commit 3e73e708e4
16 changed files with 1114 additions and 90 deletions
@@ -67,6 +67,9 @@ class MailingsControllerTest < ActionDispatch::IntegrationTest
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
@@ -79,6 +82,8 @@ class MailingsControllerTest < ActionDispatch::IntegrationTest
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?
@@ -86,6 +91,26 @@ class MailingsControllerTest < ActionDispatch::IntegrationTest
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?
@@ -242,6 +267,42 @@ class MailingsControllerTest < ActionDispatch::IntegrationTest
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 "cancel stops pending recipients and keeps sent ones" do
login_as users(:admin)
follow_redirect! if response.redirect?
@@ -27,4 +27,15 @@ class OrganizationsControllerTest < ActionDispatch::IntegrationTest
assert_no_match(/ASD Test Calcio/, response.body)
assert_select "select[name=sport] option[value='Calcio a 5'][selected]"
end
test "index table uses campaign spreadsheet columns" do
login_as users(:admin)
get organizations_path(project_code: "matchlivetv")
assert_response :success
%w[N. Regione Prov. Società Email\ verificata Streaming\ rilevato Evidenza\ /\ fit\ commerciale Stato\ invio Fonte\ contatto\ /\ ricerca Note\ follow-up].each do |header|
assert_select "th", text: header
end
assert_select "th", text: "Organizzazione", count: 0
end
end
+7
View File
@@ -22,4 +22,11 @@ class ApplicationHelperTest < ActionView::TestCase
assert_includes html, "dark:bg-sky-950"
assert_includes html, "dark:text-sky-200"
end
test "table clip keeps a title with the full value" do
html = table_clip("Società affiliata FIPAV con un testo molto lungo da accorciare", length: 20)
assert_includes html, "title=\"Società affiliata FIPAV con un testo molto lungo da accorciare\""
assert_includes html, ""
end
end
@@ -47,6 +47,24 @@ class MailingsAudienceQueryTest < ActiveSupport::TestCase
assert_includes ids, @volley.id
end
test "never contacted checkbox maps to history never" do
filters = Mailings::AudienceFilters.new("preset" => "all", "never_contacted" => "1")
assert_equal "never", filters.history_kind
end
test "history never excludes orgs with email_sent activity" do
Activity.create!(
organization: @acme,
activity_type: "email_sent",
subject: "Lancio già inviato",
happened_at: 1.day.ago
)
ids = query({ "preset" => "all", "never_contacted" => "1" }).relation.pluck(:id)
assert_not_includes ids, @acme.id
assert_includes ids, @volley.id
end
test "exclude customers drops active customers" do
@volley.update!(status: "active_customer")
ids = query({ "preset" => "all", "exclude_customers" => true }).relation.pluck(:id)