docs(ops): stop the compose header contradicting itself, and name the four variables step 2 dropped (#204) #210
@@ -38,7 +38,16 @@ const COLUMNS = [
|
||||
dataIndex: 'status',
|
||||
render: (v: string) => <Tag color={STATUS_COLORS[v]}>{v}</Tag>
|
||||
},
|
||||
{ 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' ? <Tag color="warning">Demo (not charged)</Tag> : 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 (
|
||||
<Space direction="vertical" align="center" style={{ width: '100%', marginTop: 24 }}>
|
||||
@@ -79,6 +94,16 @@ function OrdersBody({ loading, error, orders, onRetry }: BodyProps) {
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
{hasDemoOrder && (
|
||||
<Alert
|
||||
type="warning"
|
||||
showIcon
|
||||
style={{ marginBottom: 16 }}
|
||||
message="Some of these are demo orders"
|
||||
description="A demo order is a pretend one: nothing was charged, and nothing will be shipped."
|
||||
/>
|
||||
)}
|
||||
<Table
|
||||
rowKey="id"
|
||||
dataSource={orders}
|
||||
@@ -88,6 +113,7 @@ function OrdersBody({ loading, error, orders, onRetry }: BodyProps) {
|
||||
scroll={{ x: 'max-content' }}
|
||||
columns={COLUMNS}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -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' });
|
||||
|
||||
@@ -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<void> {
|
||||
|
||||
Reference in New Issue
Block a user