feat: automações com envio de e-mail

This commit is contained in:
esdrasrenan 2025-12-13 12:38:08 -03:00
parent 469608a10b
commit 58a1ed6b36
6 changed files with 958 additions and 49 deletions

View file

@ -198,5 +198,97 @@ describe("automations.runTicketAutomationsForEvent", () => {
expect.objectContaining({ automationId, ticketId, eventType: "TICKET_CREATED" })
)
})
})
it("agenda envio de e-mail quando ação SEND_EMAIL é aplicada", async () => {
const runAfter = vi.fn(async () => {})
const ticketId = "ticket_1" as never
const automationId = "auto_1" as never
const ticket = {
_id: ticketId,
tenantId: "tenant-1",
reference: 123,
subject: "Teste de automação",
status: "PENDING",
priority: "MEDIUM",
channel: "EMAIL",
requesterId: "user_req_1" as never,
requesterSnapshot: { name: "Renan", email: "cliente@empresa.com" },
createdAt: 0,
updatedAt: 0,
}
const automations = [
{
_id: automationId,
tenantId: "tenant-1",
name: "Auto e-mail",
enabled: true,
trigger: "TICKET_CREATED",
timing: "IMMEDIATE",
delayMs: undefined,
conditions: null,
actions: [
{
type: "SEND_EMAIL",
subject: "Atualização do chamado #{{ticket.reference}}",
message: "Olá {{requester.name}}, recebemos seu chamado: {{ticket.subject}}",
ctaTarget: "PORTAL",
ctaLabel: "Abrir chamado",
recipients: [{ type: "REQUESTER" }],
},
],
createdBy: "user_1",
createdAt: 0,
updatedAt: 0,
},
]
const takeAutomations = vi.fn(async () => automations)
const filterAutomations = vi.fn(() => ({ take: takeAutomations }))
const withIndexAutomations = vi.fn(() => ({ filter: filterAutomations, take: takeAutomations }))
const takeRuns = vi.fn(async () => [])
const orderRuns = vi.fn(() => ({ take: takeRuns }))
const withIndexRuns = vi.fn(() => ({ order: orderRuns, take: takeRuns }))
const query = vi.fn((table: string) => {
if (table === "ticketAutomations") {
return { withIndex: withIndexAutomations }
}
if (table === "ticketAutomationRuns") {
return { withIndex: withIndexRuns }
}
throw new Error(`unexpected table: ${table}`)
})
const get = vi.fn(async (id: unknown) => {
if (id === ticketId) return ticket
return null
})
const insert = vi.fn(async () => "run_1" as never)
const patch = vi.fn(async () => {})
const del = vi.fn(async () => {})
await runTicketAutomationsForEvent(
{
db: { get, query, insert, patch, delete: del } as unknown,
scheduler: { runAfter } as unknown,
} as never,
{ tenantId: "tenant-1", ticketId, eventType: "TICKET_CREATED" }
)
expect(runAfter).toHaveBeenCalledTimes(1)
expect(runAfter).toHaveBeenCalledWith(
1,
expect.anything(),
expect.objectContaining({
to: ["cliente@empresa.com"],
subject: "Atualização do chamado #123",
html: expect.any(String),
})
)
})
})