diff --git a/frontend/src/customer/Orders.tsx b/frontend/src/customer/Orders.tsx
index 1bd22ea..b70774c 100644
--- a/frontend/src/customer/Orders.tsx
+++ b/frontend/src/customer/Orders.tsx
@@ -38,7 +38,16 @@ const COLUMNS = [
dataIndex: 'status',
render: (v: string) => {v}
},
- { title: 'Processor', dataIndex: 'processor' },
+ {
+ title: 'Processor',
+ dataIndex: 'processor',
+ // `demo` used to render as a raw column value, which is not an explanation:
+ // a customer has no reason to read it as "this did not happen", and the row
+ // was otherwise identical to a real one — real price, `completed` status,
+ // same neutral tag. The cart says it is a demo (#195, #203) for about three
+ // seconds; this is the record they come back to. See #205.
+ render: (v: string) => (v === 'demo' ? Demo (not charged) : v)
+ },
{ title: 'Date', dataIndex: 'created_at', render: (v: string) => new Date(v).toLocaleDateString() }
];
@@ -69,6 +78,12 @@ function OrdersBody({ loading, error, orders, onRetry }: BodyProps) {
);
}
+ // Shown only when there is one to explain. The per-row tag says which order,
+ // this says what it means — a tag reading "Demo" still assumes the reader
+ // knows what a demo order is, and the thing they actually want to know is
+ // whether to expect a parcel.
+ const hasDemoOrder = orders.some(o => o.processor === 'demo');
+
if (orders.length === 0) {
return (
@@ -79,15 +94,26 @@ function OrdersBody({ loading, error, orders, onRetry }: BodyProps) {
}
return (
-
+ <>
+ {hasDemoOrder && (
+
+ )}
+
+ >
);
}
diff --git a/frontend/tests/e2e/demo-checkout.spec.ts b/frontend/tests/e2e/demo-checkout.spec.ts
index 333d398..70ab312 100644
--- a/frontend/tests/e2e/demo-checkout.spec.ts
+++ b/frontend/tests/e2e/demo-checkout.spec.ts
@@ -61,6 +61,32 @@ test.describe('Demo mode says so to the customer', () => {
await expect(cart.demoNotice).toBeVisible({ timeout: 20000 });
});
+ // The toast is three seconds; this is the record the customer comes back to
+ // when they wonder where their item is. It showed `demo` as a raw value under
+ // a "Processor" heading, beside a real price and a neutral `completed` tag —
+ // nothing a customer would read as "this did not happen". See #205.
+ test('order history marks the demo order rather than showing it as a real one', async ({
+ page,
+ customer,
+ cart,
+ orders
+ }) => {
+ const name = `Demo h${uniqueSuffix()}`;
+ const item = await createItem(page.request, { name, price: '80' });
+ expect((await page.request.post(`/api/cart/items/${item.id}`)).status()).toBe(201);
+ expect((await page.request.post('/api/customers/me/addresses', { data: ADDRESS })).ok()).toBe(true);
+
+ await cart.goto();
+ await expect(cart.checkoutButton).toBeVisible({ timeout: 20000 });
+ await cart.checkoutButton.click();
+ await expect(page.getByText(/nothing was charged/i)).toBeVisible({ timeout: 20000 });
+
+ await orders.goto();
+
+ await expect(orders.demoOrderMarker).toBeVisible({ timeout: 20000 });
+ await expect(orders.demoNotice).toBeVisible();
+ });
+
test('the confirmation says nothing was charged', async ({ page, customer, cart }) => {
const name = `Demo p${uniqueSuffix()}`;
const item = await createItem(page.request, { name, price: '80' });
diff --git a/frontend/tests/e2e/pages/OrdersPage.ts b/frontend/tests/e2e/pages/OrdersPage.ts
index b13357e..cc49341 100644
--- a/frontend/tests/e2e/pages/OrdersPage.ts
+++ b/frontend/tests/e2e/pages/OrdersPage.ts
@@ -14,6 +14,8 @@ export class OrdersPage {
readonly continueShoppingButton: Locator;
readonly backToShopButton: Locator;
readonly anyDialog: Locator;
+ readonly demoNotice: Locator;
+ readonly demoOrderMarker: Locator;
constructor(private readonly page: Page) {
this.heading = page.getByRole('heading', { name: 'Order History' });
@@ -21,6 +23,8 @@ export class OrdersPage {
this.continueShoppingButton = page.getByRole('button', { name: 'Continue Shopping' });
this.backToShopButton = page.getByRole('button', { name: 'Back to Shop' });
this.anyDialog = page.getByRole('dialog');
+ this.demoNotice = page.getByText('Some of these are demo orders');
+ this.demoOrderMarker = page.getByText('Demo (not charged)');
}
async goto(): Promise {