import { INestApplication } from "@nestjs/common"; import { afterAll, beforeAll, describe, expect, it, vi } from "vitest"; import { agent, bearer, closeTestApp, createTestApp, loginSuperAdmin, qaName, type AuthedTokens } from "./setup.js"; /** * `renderPdf` is mocked (real call path through quotes.service.ts still * runs) — what's under test is the ANATEL/RGC annex's computed content * (anatel-offer-template.ts), not Chromium itself (covered by the * documents-pdf.spec.ts suite + the manual smoke test in progress.md). * Business-critical regulatory content: this asserts the actual HTML * handed to the renderer contains the right computed fields, not just * that the endpoint returns 200. */ const renderPdfMock = vi.fn(async (_input: { html: string }) => Buffer.from("%PDF-1.4 fake anatel pdf")); vi.mock("@eden/integrations", () => ({ renderPdf: (input: { html: string }) => renderPdfMock(input), })); describe("quotes — anexo de conformidade ANATEL/RGC", () => { let app: INestApplication; let admin: AuthedTokens; let resellerId: string; let stfcProductId: string; let pabxProductId: string; let productTypeId: string; let unitId: string; beforeAll(async () => { app = await createTestApp(); admin = await loginSuperAdmin(app); const reseller = await agent(app) .post("/api/v1/resellers") .set(...bearer(admin.accessToken)) .send({ name: "qa-test- Revenda ANATEL" }) .expect(201); resellerId = reseller.body.id; const productType = await agent(app) .post("/api/v1/products/types") .set(...bearer(admin.accessToken)) .send({ name: qaName("Tipo ANATEL") }) .expect(201); productTypeId = productType.body.id; const unit = await agent(app) .post("/api/v1/products/units") .set(...bearer(admin.accessToken)) .send({ name: qaName("Unidade ANATEL") }) .expect(201); unitId = unit.body.id; const stfcProduct = await agent(app) .post("/api/v1/products") .set(...bearer(admin.accessToken)) .send({ name: "qa-test- Linha STFC", productTypeId, unitId, price0: 200, price12: 150, serviceType: "STFC", metered: true, minutesAllowance: 100, hasLdi: true, tariffRates: { LC: { normal: 0.1, reduced: 0.1 }, LDN: { normal: 0.2, reduced: 0.2 }, VC1: { normal: 0.15, reduced: 0.15 }, VC2: { normal: 0.25, reduced: 0.25 }, VC3: { normal: 0.3, reduced: 0.3 }, LDI: { normal: 1.5, reduced: 1.5 }, }, }) .expect(201); stfcProductId = stfcProduct.body.id; expect(stfcProduct.body.service_type).toBe("STFC"); expect(stfcProduct.body.tariff_rates.LC).toEqual({ normal: 0.1, reduced: 0.1 }); const pabxProduct = await agent(app) .post("/api/v1/products") .set(...bearer(admin.accessToken)) .send({ name: "qa-test- Ramal PABX", productTypeId, unitId, price0: 50, serviceType: "Serviço PABX" }) .expect(201); pabxProductId = pabxProduct.body.id; }); afterAll(async () => { await agent(app) .patch(`/api/v1/products/${stfcProductId}`) .set(...bearer(admin.accessToken)) .send({ active: false }) .expect(200); await agent(app) .patch(`/api/v1/products/${pabxProductId}`) .set(...bearer(admin.accessToken)) .send({ active: false }) .expect(200); await agent(app) .patch(`/api/v1/resellers/${resellerId}`) .set(...bearer(admin.accessToken)) .send({ active: false }) .expect(200); await closeTestApp(app); }); it("snapshots service_type/metered/tariffRates onto the quote item at creation", async () => { const quote = await agent(app) .post("/api/v1/quotes") .set(...bearer(admin.accessToken)) .send({ resellerId, clientName: "qa-test Cliente ANATEL", clientPhone: "11999998888", contractPeriod: 12, items: [{ productId: stfcProductId, quantity: 2 }], salesRepName: "qa-test Vendedor", }) .expect(201); const item = quote.body.items[0]; expect(item.serviceType).toBe("STFC"); expect(item.metered).toBe(true); expect(item.hasLdi).toBe(true); expect(item.tariffRates.LC).toEqual({ normal: 0.1, reduced: 0.1 }); expect(item.minutesAllowance).toBe(100); }); it("renders the RGC annex with the right computed fields for an STFC quote", async () => { renderPdfMock.mockClear(); const quote = await agent(app) .post("/api/v1/quotes") .set(...bearer(admin.accessToken)) .send({ resellerId, clientName: "qa-test Cliente ANATEL 2", clientPhone: "11999998888", contractPeriod: 12, items: [{ productId: stfcProductId, quantity: 1 }], salesRepName: "qa-test Vendedor", }) .expect(201); const download = await agent(app) .get(`/api/v1/quotes/${quote.body.id}/anatel-pdf`) .set(...bearer(admin.accessToken)) .expect(200); expect(download.headers["content-type"]).toBe("application/pdf"); expect(renderPdfMock).toHaveBeenCalledTimes(1); const html = renderPdfMock.mock.calls[0]![0].html; // Legal-basis section only renders because the quote has an STFC item. expect(html).toContain("Conformidade RGC — Resolução Anatel nº 765/2023"); expect(html).toContain("Prazo de Comercialização"); expect(html).toContain(quote.body.quote_number); expect(html).toContain("qa-test Cliente ANATEL 2"); expect(html).toContain("qa-test Vendedor"); // Tariff section, since the item is metered. expect(html).toContain("TABELA DE TARIFAÇÃO"); expect(html).toContain("LDI"); expect(html).toContain("A tecnologia utilizada para entrega das chamadas do serviço STFC ofertado é VoIP."); // Fixed regulatory fields. expect(html).toContain("Pós-paga"); expect(html).toContain("Nacional"); expect(html).toContain("Intervalo mínimo de 12 meses"); }); it("rejects (400) a quote with no STFC item", async () => { const quote = await agent(app) .post("/api/v1/quotes") .set(...bearer(admin.accessToken)) .send({ resellerId, clientName: "qa-test Cliente Sem STFC", clientPhone: "11999998888", contractPeriod: 0, items: [{ productId: pabxProductId, quantity: 1 }], }) .expect(201); const res = await agent(app) .get(`/api/v1/quotes/${quote.body.id}/anatel-pdf`) .set(...bearer(admin.accessToken)) .expect(400); expect(res.body.message).toContain("STFC"); }); });