ledgerone_backend/test/tax.service.spec.ts

183 lines
5.9 KiB
TypeScript

import { TaxService } from "../src/tax/tax.service";
import { createPrismaMock } from "./utils/mock-prisma";
describe("TaxService", () => {
it("saves and submits complete intake as ready", async () => {
const prisma = createPrismaMock();
const createdAt = new Date("2026-07-16T00:00:00.000Z");
prisma.taxReturn.findFirst.mockResolvedValue({
id: "return_1",
userId: "user_1",
taxYear: 2026,
filingType: "individual",
jurisdictions: ["CA"],
status: "draft",
summary: {},
createdAt,
updatedAt: createdAt,
});
prisma.taxReturn.update.mockResolvedValue({
id: "return_1",
status: "ready",
summary: {},
});
prisma.auditLog.create.mockResolvedValue({});
const service = new TaxService(prisma as any);
const result = await service.saveIntake("user_1", "return_1", {
taxpayer: { name: "Jane Doe", filingStatus: "Single", address: "1 Main St" },
income: { total: 120000 },
deductions: { standard: true },
credits: {},
}, true);
expect(result.readiness.complete).toBe(true);
expect(prisma.taxReturn.update).toHaveBeenCalledWith({
where: { id: "return_1" },
data: expect.objectContaining({
status: "ready",
summary: expect.objectContaining({
intake: expect.any(Object),
intakeReadiness: expect.objectContaining({ complete: true }),
}),
}),
});
expect(prisma.auditLog.create).toHaveBeenCalledWith({
data: expect.objectContaining({
action: "tax.intake_submit",
}),
});
});
it("exports a versioned package with hash, manifest, and audit log", async () => {
const prisma = createPrismaMock();
const createdAt = new Date("2026-07-16T00:00:00.000Z");
prisma.taxReturn.findFirst.mockResolvedValue({
id: "return_1",
userId: "user_1",
taxYear: 2026,
filingType: "individual",
jurisdictions: ["CA"],
status: "draft",
summary: { grossIncome: 1000 },
createdAt,
updatedAt: createdAt,
documents: [
{
id: "doc_1",
taxReturnId: "return_1",
docType: "w2_or_1099",
metadata: { source: "upload" },
createdAt,
},
],
});
prisma.taxReturn.update.mockResolvedValue({});
prisma.auditLog.create.mockResolvedValue({});
const service = new TaxService(prisma as any);
const result = await service.exportReturn("user_1", "return_1");
expect(result.packageId).toMatch(/^taxpkg_/);
expect(result.packageVersion).toBe("2026.1");
expect(result.packageHash).toMatch(/^[a-f0-9]{64}$/);
expect(result.manifest).toEqual(expect.objectContaining({
taxReturnId: "return_1",
taxYear: 2026,
filingType: "individual",
documentCount: 1,
readiness: "needs_documents",
}));
expect(result.return.status).toBe("exported");
expect(result.documents).toHaveLength(1);
expect(prisma.auditLog.create).toHaveBeenCalledWith({
data: expect.objectContaining({
userId: "user_1",
action: "tax.export_package",
metadata: expect.objectContaining({
taxReturnId: "return_1",
packageHash: result.packageHash,
}),
}),
});
});
it("submits a ready return to the sandbox e-file provider", async () => {
const prisma = createPrismaMock();
const createdAt = new Date("2026-07-16T00:00:00.000Z");
prisma.taxReturn.findFirst.mockResolvedValue({
id: "return_1",
userId: "user_1",
taxYear: 2026,
filingType: "individual",
jurisdictions: ["CA"],
status: "ready",
summary: {
intake: {
taxpayer: { name: "Jane Doe", filingStatus: "Single", address: "1 Main St" },
income: { total: 120000 },
},
},
createdAt,
updatedAt: createdAt,
documents: [
{ id: "doc_1", docType: "w2_or_1099", metadata: {}, createdAt },
{ id: "doc_2", docType: "interest_and_dividend_forms", metadata: {}, createdAt },
{ id: "doc_3", docType: "deduction_support", metadata: {}, createdAt },
{ id: "doc_4", docType: "identity_information", metadata: {}, createdAt },
],
});
prisma.taxReturn.update.mockResolvedValue({
id: "return_1",
status: "efile_submitted",
summary: {},
});
prisma.auditLog.create.mockResolvedValue({});
const service = new TaxService(prisma as any);
const result = await service.submitEFile("user_1", "return_1", true);
expect(result.eFile.provider).toBe("sandbox");
expect(result.eFile.status).toBe("submitted");
expect(result.eFile.submissionId).toMatch(/^efile_/);
expect(result.eFile.packageHash).toMatch(/^[a-f0-9]{64}$/);
expect(prisma.taxReturn.update).toHaveBeenCalledWith({
where: { id: "return_1" },
data: expect.objectContaining({
status: "efile_submitted",
summary: expect.objectContaining({
eFile: expect.objectContaining({
provider: "sandbox",
status: "submitted",
}),
}),
}),
});
expect(prisma.auditLog.create).toHaveBeenCalledWith({
data: expect.objectContaining({
action: "tax.efile_submit",
}),
});
});
it("blocks e-file submission when intake or documents are incomplete", async () => {
const prisma = createPrismaMock();
prisma.taxReturn.findFirst.mockResolvedValue({
id: "return_1",
userId: "user_1",
taxYear: 2026,
filingType: "individual",
jurisdictions: ["CA"],
status: "draft",
summary: { intake: { taxpayer: { name: "Jane Doe" }, income: {} } },
documents: [],
});
const service = new TaxService(prisma as any);
await expect(service.submitEFile("user_1", "return_1", true)).rejects.toThrow(
"Tax return is not ready for e-file submission.",
);
expect(prisma.taxReturn.update).not.toHaveBeenCalled();
});
});