e2e/computation-validation.spec.ts
Linked repository file from this build.
import { resetDemoFixture } from "./demo-fixture";
import { expect, test, type APIRequestContext } from "@playwright/test";
import { createSeed } from "../src/programs/snap-negative/seed";
import { enterMoney } from "./money-input";
async function load(request: APIRequestContext) {
return request
.get("/api/reviews/aa1635c0-c99d-5f12-8f26-54d3f23bf13d")
.then((response) => response.json());
}
async function run(request: APIRequestContext, commands: unknown[]) {
const current = await load(request);
const response = await request.post("/api/reviews/aa1635c0-c99d-5f12-8f26-54d3f23bf13d", {
data: {
version: current.version,
requestId: crypto.randomUUID(),
commands: commands.map((command) => ({ id: crypto.randomUUID(), command })),
},
});
expect(response.ok()).toBe(true);
return response.json();
}
async function reset(request: APIRequestContext) {
await resetDemoFixture();
return run(request, [{ type: "reset_demo" }]);
}
test("computation household size accepts 1 through 20 and rejects 21 without losing the saved value", async ({
page,
request,
}) => {
await reset(request);
await page.goto("/reviews/aa1635c0-c99d-5f12-8f26-54d3f23bf13d");
await page.getByRole("tab", { name: "Computation", exact: true }).click();
const size = page.locator('input[id$="-compI-hh"]');
for (const value of ["1", "9", "20"]) {
await size.fill(value);
await size.blur();
await expect(size).toHaveValue(value);
await page.getByRole("button", { name: /Save Comp I column/ }).click();
await expect
.poll(async () => (await load(request)).review.facts.scenarios.compI.householdSize)
.toBe(Number(value));
}
await size.fill("21");
await size.blur();
await expect(size).toHaveValue("20");
await expect(size).toHaveAttribute("aria-invalid", "true");
await page.reload();
await page.getByRole("tab", { name: "Computation", exact: true }).click();
await expect(size).toHaveValue("20");
});
test("education and proration use explicit column saves and survive reload into Final SAQC", async ({
page,
request,
}) => {
await reset(request);
const template = createSeed();
await run(request, [
{ type: "household", value: template.facts.members },
{ type: "scenario", scenario: "eligibility", value: template.facts.scenarios.eligibility },
{ type: "scenario", scenario: "compI", value: template.facts.scenarios.compI },
{ type: "scenario", scenario: "compII", value: template.facts.scenarios.compII },
]);
await page.goto("/reviews/aa1635c0-c99d-5f12-8f26-54d3f23bf13d");
await page.getByRole("tab", { name: "Computation", exact: true }).click();
const grant = page.locator('input[id$="-compI-educationGrantCents"]');
const expenses = page.locator('input[id$="-compI-educationExpensesCents"]');
const day = page.locator('input[id$="-compI-applicationDay"]');
await enterMoney(grant, "100.00");
await grant.blur();
await enterMoney(expenses, "20.00");
await expenses.blur();
await day.fill("16");
await day.blur();
expect((await load(request)).review.facts.scenarios.compI.educationGrantCents).toBeUndefined();
await page.getByRole("button", { name: /Save Comp I column/ }).click();
await expect
.poll(async () => (await load(request)).review.facts.scenarios.compI.educationGrantCents)
.toBe(10000);
await enterMoney(grant, "200.00");
await grant.blur();
await page.getByRole("button", { name: /Reset Comp I column/ }).click();
await expect(grant).toHaveValue("100.00");
await page.reload();
await page.getByRole("tab", { name: "Computation", exact: true }).click();
await expect(day).toHaveValue("16");
await expect(expenses).toHaveValue("20.00");
await page.getByRole("button", { name: /Apply Final Results to Final SAQC/ }).click();
await expect
.poll(async () => (await load(request)).review.facts.final?.result.benefitCents)
.toBe(29200);
const saved = await load(request);
expect(saved.review.facts.final?.result.monthlyBenefitCents).toBe(58400);
expect(saved.review.facts.final?.inputs?.applicationDay).toBe(16);
await day.fill("0");
await day.blur();
await expect(day).toHaveValue("16");
await expect(day).toHaveAttribute("aria-invalid", "true");
});
test("income entered separately in the UI aligns across saved columns", async ({
page,
request,
}) => {
await reset(request);
await page.goto("/reviews/aa1635c0-c99d-5f12-8f26-54d3f23bf13d");
await page.getByRole("tab", { name: "Computation", exact: true }).click();
for (const [index, column, label] of [
[0, "eligibility", "Eligibility"],
[1, "compI", "Comp I"],
] as const) {
const householdSize = page.locator(`input[id$="-${column}-hh"]`);
await householdSize.fill("3");
await householdSize.blur();
await page.getByRole("button", { name: "Add income", exact: true }).nth(index).click();
const popover = page.getByRole("dialog", { name: "Add income", exact: true });
await popover.getByLabel("Income type code", { exact: true }).fill("WAGES");
await enterMoney(popover.getByLabel("Amount", { exact: true }), "1250.50");
await popover.getByRole("button", { name: "Confirm", exact: true }).click();
await page.getByRole("button", { name: `Save ${label} column`, exact: true }).click();
await expect
.poll(async () => (await load(request)).review.facts.scenarios[column].populated)
.toBe(true);
}
const incomeRow = page.getByRole("row").filter({ hasText: "WAGES" });
await expect(incomeRow).toHaveCount(1);
for (const column of [0, 1]) {
await expect(incomeRow.getByRole("cell").nth(column).getByRole("button")).toContainText(
"$1250.50",
);
}
const stored = await load(request);
expect(stored.review.facts.scenarios.eligibility.income[0].id).not.toBe(
stored.review.facts.scenarios.compI.income[0].id,
);
});