Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,9 @@ jest.mock("i18n-react/dist/i18n-react", () => ({
}));

jest.mock("../../../../utils/money", () => ({
currencyAmountFromCents: (amount) => `$${(amount / 100).toFixed(2)}`
currencyAmountFromCents: (amount) => `$${(amount / 100).toFixed(2)}`,
formatDiscount: (amount, type) =>
type === "Rate" ? `${amount / 100}%` : `$${(amount / 100).toFixed(2)}`
}));

jest.mock("../../../../utils/constants", () => ({
Expand Down Expand Up @@ -458,3 +460,141 @@ describe("SponsorOrderGrid", () => {
expect(screen.queryByText("sponsor_order_grid.reconciliation")).not.toBeInTheDocument();
});
});

// ─── Ledger-driven fixes ────────────────────────────────────────────────────
// Regression coverage for the three ways this grid used to diverge from the
// invoice PDF before both started consuming utils/order-ledger.

describe("SponsorOrderGrid — ledger-driven fixes", () => {
test("falls back to item.title for the details column when item.type is null (matches the invoice PDF)", () => {
const order = {
forms: [makeForm({ items: [makeItem({ type: null, title: "Booth Space" })] })],
total: 0
};
render(<SponsorOrderGrid order={order} />);
expect(screen.getByText(/Booth Space/)).toBeInTheDocument();
});

test("renders an item whose quantity is missing (undefined), defaulting to 1", () => {
const order = {
forms: [makeForm({ items: [makeItem({ quantity: undefined })] })],
total: 0
};
render(<SponsorOrderGrid order={order} />);
expect(screen.getAllByText("$100.00").length).toBeGreaterThan(0);
});

test("gives distinct row keys to multiple fees carrying line_id but no id (purchases-api v2 shape)", () => {
const consoleErrorSpy = jest.spyOn(console, "error").mockImplementation(() => {});
const order = {
forms: [makeForm({ items: [] })],
fees: [
{ line_id: 7001, title: "Processing Fee", amount: 500 },
{ line_id: 7002, title: "Late Fee", amount: 250 }
],
total: 0
};
render(<SponsorOrderGrid order={order} />);

expect(screen.getByText("Processing Fee")).toBeInTheDocument();
expect(screen.getByText("Late Fee")).toBeInTheDocument();
expect(consoleErrorSpy.mock.calls.join(" ")).not.toMatch(/same key/);
consoleErrorSpy.mockRestore();
});

test("renders no discount row when discount_in_cents is 0", () => {
const order = {
forms: [
makeForm({
discount_in_cents: 0,
discount_amount: 1000,
discount_type: "Rate",
items: [makeItem()]
})
],
total: 0
};
render(<SponsorOrderGrid order={order} />);
expect(screen.queryByText("mui_table.dis")).not.toBeInTheDocument();
});

test("formats the discount description from discount_amount/discount_type when the form carries no pre-formatted discount string (raw API shape)", () => {
const order = {
forms: [
makeForm({
discount: null,
discount_in_cents: 5000,
discount_amount: 1000,
discount_type: "Rate",
items: [makeItem()]
})
],
total: 0
};
render(<SponsorOrderGrid order={order} />);
expect(screen.getByText("10%")).toBeInTheDocument();
});

test("uses the pre-formatted discount string when the form is already normalized", () => {
const order = {
forms: [
makeForm({
discount: "10% off",
discount_in_cents: 5000,
discount_amount: 1000,
discount_type: "Rate",
items: [makeItem()]
})
],
total: 0
};
render(<SponsorOrderGrid order={order} />);
expect(screen.getByText("10% off")).toBeInTheDocument();
});

test("falls back to mui_table.card for the payment row when payment.method is absent (matches the invoice PDF)", () => {
const order = {
forms: [],
payments: [{ id: 1, amount: 10000, created: 1, method: null }],
total: 0
};
render(<SponsorOrderGrid order={order} />);
expect(screen.getByText(/mui_table\.paid_via mui_table\.card/)).toBeInTheDocument();
});

test("does not override payment.method when present", () => {
const order = {
forms: [],
payments: [{ id: 1, amount: 10000, created: 1, method: "wire" }],
total: 0
};
render(<SponsorOrderGrid order={order} />);
expect(screen.getByText(/mui_table\.paid_via wire/)).toBeInTheDocument();
});

test("falls back to mui_table.refund for the refund row when refund.reason is absent (matches the invoice PDF)", () => {
const order = {
forms: [],
refunds: [{ id: 1, amount: 3000, created: 1, reason: null }],
total: 0
};
render(<SponsorOrderGrid order={order} />);
// "mui_table.refund" also labels the row's type badge, so a second
// occurrence (the reason cell falling back to the same translation) is
// exactly what this asserts.
expect(screen.getAllByText("mui_table.refund")).toHaveLength(2);
});

test("does not override refund.reason when present", () => {
const order = {
forms: [],
refunds: [{ id: 1, amount: 3000, created: 1, reason: "duplicate charge" }],
total: 0
};
render(<SponsorOrderGrid order={order} />);
expect(screen.getByText("duplicate charge")).toBeInTheDocument();
// Only the type badge renders "mui_table.refund" -- the reason cell
// must not have been overridden with the fallback.
expect(screen.getAllByText("mui_table.refund")).toHaveLength(1);
});
});
Loading
Loading