WFDASH-WEBAPP/src/lib/quote-status.test.ts

79 lines
2.7 KiB
TypeScript
Raw Normal View History

import { describe, it, expect } from "vitest";
import { quoteStatusClassName, formatQuoteStatus } from "./quote-status";
describe("quoteStatusClassName", () => {
it("returns a styled class string for known statuses", () => {
const cls = quoteStatusClassName("new");
expect(cls).toContain("border-info");
expect(cls).toContain("bg-info");
});
it("returns a fallback class for unknown statuses", () => {
const cls = quoteStatusClassName("not_a_real_status");
expect(cls).toContain("border-muted");
expect(cls).toContain("bg-muted");
});
it("supports every documented quote status", () => {
const statuses = [
"new",
"claimed",
"processed",
"emailed",
"approval_pending",
"approved",
"rejected",
"problem",
"complete",
"cancelled",
"follow_up",
"email_failed",
"unmatched_bounce",
"template",
"sending",
"mail_failed",
// Added 2026-07-24 alongside the partial-approval flow.
"partial_approval_pending",
"partial_approved",
];
for (const s of statuses) {
const cls = quoteStatusClassName(s);
// Every known status must produce a border-using class so the
// pill has visual weight. The neutral `cancelled` shares the
// muted fallback on purpose (it's terminal — no semantic
// colour needed); everything else must produce its own map
// entry.
expect(cls, `class for ${s}`).toMatch(/border-/);
if (s !== "cancelled") {
expect(
cls,
`class for ${s}`,
).not.toContain("border-muted bg-muted text-muted-foreground");
}
}
});
});
describe("formatQuoteStatus", () => {
refactor(quotes): collapse 10 workflow tabs into 8, add follow-up + replied chips The list page had grown 10 colour-coded tabs (one per legacy PB status) that fragmented the workflow rather than grouping it. Merging the overlapping concepts into workflow buckets per the operator's flow: - new ← new + follow_up (follow-up rows show a bell chip) - claimed ← claimed - pending_approval ← processed + approval_pending + sending - completed ← approved + complete + emailed + cancelled + rejected (emailed renders as 'Awaiting reply', cancelled + rejected are substatus pills inside the Completed tab) - email_failed ← email_failed + mail_failed + unmatched_bounce (new tab) - problem ← problem - templates ← is_template = true - all ← catch-all Two row-level indicators added next to the quote number: - Bell chip for follow-up rows (status=follow_up OR follow_up_due set on an actionable status). Colour flips to red when overdue. - Reply-bubble chip for rows where last_reply_at is set, so the operator can distinguish 'fresh new' from 'replied new' at a glance. Implementation notes: - getQuotes now accepts string[] statuses and OR-chains them in the PB filter (PB 0.26 has no IN operator). getQuoteStatusCounts sums per-status totals into the new tab buckets in one batch. - formatQuoteStatus gains workflow-friendly label overrides ('Awaiting reply', 'Sending…', 'Pending approval', etc.) shared by the list, archived, and process pages. - The detail page's local statusLabels map is kept in sync so toast + history-row interpolations read correctly. Tests: 229/230 vitest (the 1 failure is the pre-existing attachments off-by-one, unrelated to this change). Updated quote-status.test.ts for the new label overrides.
2026-06-29 20:15:32 +00:00
it("uses workflow-friendly labels for email-status enums", () => {
expect(formatQuoteStatus("email_failed")).toBe("Email failed");
expect(formatQuoteStatus("mail_failed")).toBe("Mail failed");
expect(formatQuoteStatus("unmatched_bounce")).toBe("Unmatched bounce");
});
refactor(quotes): collapse 10 workflow tabs into 8, add follow-up + replied chips The list page had grown 10 colour-coded tabs (one per legacy PB status) that fragmented the workflow rather than grouping it. Merging the overlapping concepts into workflow buckets per the operator's flow: - new ← new + follow_up (follow-up rows show a bell chip) - claimed ← claimed - pending_approval ← processed + approval_pending + sending - completed ← approved + complete + emailed + cancelled + rejected (emailed renders as 'Awaiting reply', cancelled + rejected are substatus pills inside the Completed tab) - email_failed ← email_failed + mail_failed + unmatched_bounce (new tab) - problem ← problem - templates ← is_template = true - all ← catch-all Two row-level indicators added next to the quote number: - Bell chip for follow-up rows (status=follow_up OR follow_up_due set on an actionable status). Colour flips to red when overdue. - Reply-bubble chip for rows where last_reply_at is set, so the operator can distinguish 'fresh new' from 'replied new' at a glance. Implementation notes: - getQuotes now accepts string[] statuses and OR-chains them in the PB filter (PB 0.26 has no IN operator). getQuoteStatusCounts sums per-status totals into the new tab buckets in one batch. - formatQuoteStatus gains workflow-friendly label overrides ('Awaiting reply', 'Sending…', 'Pending approval', etc.) shared by the list, archived, and process pages. - The detail page's local statusLabels map is kept in sync so toast + history-row interpolations read correctly. Tests: 229/230 vitest (the 1 failure is the pre-existing attachments off-by-one, unrelated to this change). Updated quote-status.test.ts for the new label overrides.
2026-06-29 20:15:32 +00:00
it("renders workflow-friendly labels for the merged tabs", () => {
expect(formatQuoteStatus("approval_pending")).toBe("Pending approval");
expect(formatQuoteStatus("emailed")).toBe("Awaiting reply");
expect(formatQuoteStatus("sending")).toBe("Sending…");
expect(formatQuoteStatus("follow_up")).toBe("Follow up");
});
it("leaves single-word and terminal statuses unchanged", () => {
expect(formatQuoteStatus("new")).toBe("new");
expect(formatQuoteStatus("complete")).toBe("complete");
refactor(quotes): collapse 10 workflow tabs into 8, add follow-up + replied chips The list page had grown 10 colour-coded tabs (one per legacy PB status) that fragmented the workflow rather than grouping it. Merging the overlapping concepts into workflow buckets per the operator's flow: - new ← new + follow_up (follow-up rows show a bell chip) - claimed ← claimed - pending_approval ← processed + approval_pending + sending - completed ← approved + complete + emailed + cancelled + rejected (emailed renders as 'Awaiting reply', cancelled + rejected are substatus pills inside the Completed tab) - email_failed ← email_failed + mail_failed + unmatched_bounce (new tab) - problem ← problem - templates ← is_template = true - all ← catch-all Two row-level indicators added next to the quote number: - Bell chip for follow-up rows (status=follow_up OR follow_up_due set on an actionable status). Colour flips to red when overdue. - Reply-bubble chip for rows where last_reply_at is set, so the operator can distinguish 'fresh new' from 'replied new' at a glance. Implementation notes: - getQuotes now accepts string[] statuses and OR-chains them in the PB filter (PB 0.26 has no IN operator). getQuoteStatusCounts sums per-status totals into the new tab buckets in one batch. - formatQuoteStatus gains workflow-friendly label overrides ('Awaiting reply', 'Sending…', 'Pending approval', etc.) shared by the list, archived, and process pages. - The detail page's local statusLabels map is kept in sync so toast + history-row interpolations read correctly. Tests: 229/230 vitest (the 1 failure is the pre-existing attachments off-by-one, unrelated to this change). Updated quote-status.test.ts for the new label overrides.
2026-06-29 20:15:32 +00:00
expect(formatQuoteStatus("cancelled")).toBe("cancelled");
expect(formatQuoteStatus("rejected")).toBe("rejected");
expect(formatQuoteStatus("claimed")).toBe("claimed");
});
});