Files
eminuxandCursor 36b3ffe507
CI / scan_ruby (push) Failing after 13m27s
CI / scan_js (push) Successful in 11m45s
CI / lint (push) Failing after 12m4s
Aggiunge IMAP bounce e flag email non valide nel CRM.
Permette di leggere i bounce dalla stessa MailIdentity SMTP, aggiornare le email in anagrafica e saltare gli indirizzi invalidi nei mailing.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-08 19:46:04 +02:00

151 lines
4.9 KiB
Ruby

require "test_helper"
class Api::V1::ApiTest < ActionDispatch::IntegrationTest
setup do
@admin_token = ApiToken.issue!(user: users(:admin), name: "test-admin")
@marco_token = ApiToken.issue!(user: users(:marco), name: "test-marco")
@org = organizations(:acme)
@task = tasks(:follow_up)
@opportunity = opportunities(:deal)
end
test "rejects missing token" do
get "/api/v1/projects", as: :json
assert_response :unauthorized
assert_equal "Non autenticato", json_body["error"]
end
test "rejects invalid token" do
get "/api/v1/projects", headers: bearer("crm_invalid"), as: :json
assert_response :unauthorized
end
test "lists accessible projects" do
get "/api/v1/projects", headers: bearer(@marco_token.plaintext), as: :json
assert_response :success
codes = json_body["projects"].map { |p| p["code"] }
assert_includes codes, "matchlivetv"
assert_not_includes codes, "riskmeter"
end
test "forbids project the user cannot access" do
get "/api/v1/p/riskmeter/today", headers: bearer(@marco_token.plaintext), as: :json
assert_response :forbidden
end
test "returns 404 for unknown project" do
get "/api/v1/p/sconosciuto/today", headers: bearer(@admin_token.plaintext), as: :json
assert_response :not_found
end
test "today includes due tasks" do
get "/api/v1/p/matchlivetv/today", headers: bearer(@admin_token.plaintext), as: :json
assert_response :success
ids = json_body["today_tasks"].map { |t| t["id"] }
assert_includes ids, @task.id
assert_equal "matchlivetv", json_body["project"]["code"]
end
test "search finds organization" do
get "/api/v1/p/matchlivetv/search", params: { q: "ASD Test" }, headers: bearer(@admin_token.plaintext), as: :json
assert_response :success
org_ids = json_body["organizations"].map { |o| o["id"] }
assert_includes org_ids, @org.id
end
test "shows organization card" do
get "/api/v1/p/matchlivetv/organizations/#{@org.id}", headers: bearer(@admin_token.plaintext), as: :json
assert_response :success
assert_equal @org.name, json_body["organization"]["name"]
assert json_body["contacts"].any?
assert json_body["open_opportunities"].any?
assert json_body["pending_tasks"].any?
end
test "creates activity" do
assert_difference -> { Activity.count }, 1 do
post "/api/v1/p/matchlivetv/activities",
params: {
organization_id: @org.id,
activity_type: "note",
subject: "Nota agente",
description: "Creato via API"
},
headers: bearer(@admin_token.plaintext),
as: :json
end
assert_response :created
assert_equal "Nota agente", json_body["activity"]["subject"]
end
test "creates and completes task" do
post "/api/v1/p/matchlivetv/tasks",
params: {
organization_id: @org.id,
title: "Richiamare dopo demo",
due_at: 1.day.from_now.iso8601,
task_type: "call",
priority: "high"
},
headers: bearer(@admin_token.plaintext),
as: :json
assert_response :created
task_id = json_body["task"]["id"]
post "/api/v1/p/matchlivetv/tasks/#{task_id}/complete",
headers: bearer(@admin_token.plaintext),
as: :json
assert_response :success
assert_equal "completed", json_body["task"]["status"]
end
test "updates opportunity stage" do
patch "/api/v1/p/matchlivetv/opportunities/#{@opportunity.id}/stage",
params: { pipeline_stage: "demo_trial", notes: "Demo fissata dall'agente" },
headers: bearer(@admin_token.plaintext),
as: :json
assert_response :success
assert_equal "demo_trial", json_body["opportunity"]["pipeline_stage"]
@opportunity.reload
assert_equal "demo_trial", @opportunity.pipeline_stage
end
test "updates organization email after bounce" do
patch "/api/v1/p/matchlivetv/organizations/#{@org.id}/email",
params: {
organization_id: @org.id,
bounced_email: "vecchia@example.com",
email: "nuova@example.com",
email_invalid: false,
bounce_reason: "User unknown",
activity_subject: "Email aggiornata dopo bounce"
},
headers: bearer(@admin_token.plaintext),
as: :json
assert_response :success
@org.reload
assert_equal "nuova@example.com", @org.email
assert_equal "vecchia@example.com", @org.bounced_email
assert_not @org.email_invalid?
assert json_body["activity"].present?
end
test "rejects lost stage without reason" do
patch "/api/v1/p/matchlivetv/opportunities/#{@opportunity.id}/stage",
params: { pipeline_stage: "lost" },
headers: bearer(@admin_token.plaintext),
as: :json
assert_response :unprocessable_entity
end
private
def bearer(plaintext)
{ "Authorization" => "Bearer #{plaintext}" }
end
def json_body
JSON.parse(response.body)
end
end