import { test, expect } from './fixtures'; const suffix = () => `r${Date.now().toString(36)}${Math.random().toString(36).slice(2, 7)}`; // Reserves an item by registering a customer and adding it to their cart, which // is the only way an item legitimately reaches 'reserved'. async function reserveItem(page: import('@playwright/test').Page, itemName: string) { const email = `reserve-${suffix()}@example.com`; const created = await page.request.post('/api/admin/items', { multipart: { name: itemName, description: '', price: '75', category_id: '', tags: '[]' } }); expect(created.ok()).toBeTruthy(); const itemId = (await created.json()).id as number; // New items are pending, and a pending item cannot be reserved. expect((await page.request.post(`/api/admin/items/${itemId}/mark-available`)).ok()).toBeTruthy(); await page.goto('/register'); await page.getByRole('textbox', { name: 'Email' }).fill(email); await page.getByRole('textbox', { name: 'First name' }).fill('Test'); await page.getByRole('textbox', { name: 'Last name' }).fill('Customer'); await page.getByLabel('Password').fill('supersecret123'); await page.getByRole('button', { name: 'Create account' }).click(); await expect(page.getByRole('button', { name: 'My Account' })).toBeVisible({ timeout: 20000 }); const added = await page.request.post(`/api/cart/items/${itemId}`); expect(added.status()).toBe(201); return { email, itemId }; } test.describe('Admin reserved items', () => { test('shows a reserved count that opens the held items', async ({ page }) => { const itemName = `Held ${suffix()}`; const { email } = await reserveItem(page, itemName); await page.goto('/admin'); await page.getByRole('tab', { name: 'Customers' }).click(); const row = page.getByRole('row').filter({ hasText: email }); await expect(row).toBeVisible(); await row.getByRole('button', { name: /item/ }).click(); const dialog = page.getByRole('dialog', { name: /Items reserved by/ }); await expect(dialog.getByText(itemName)).toBeVisible(); }); test('releasing an item returns it to the storefront as available', async ({ page }) => { const itemName = `Freed ${suffix()}`; const { email, itemId } = await reserveItem(page, itemName); await page.goto('/admin'); await page.getByRole('tab', { name: 'Customers' }).click(); const row = page.getByRole('row').filter({ hasText: email }); await row.getByRole('button', { name: /item/ }).click(); const dialog = page.getByRole('dialog', { name: /Items reserved by/ }); await dialog.getByRole('button', { name: 'Release' }).click(); await expect(page.getByText(`Released "${itemName}"`)).toBeVisible(); // The point of releasing is that the item becomes purchasable again. const item = await (await page.request.get(`/api/items/${itemId}`)).json(); expect(item.status).toBe('available'); }); test('the count drops once the item is released', async ({ page }) => { const itemName = `Recount ${suffix()}`; const { email } = await reserveItem(page, itemName); await page.goto('/admin'); await page.getByRole('tab', { name: 'Customers' }).click(); const row = page.getByRole('row').filter({ hasText: email }); await row.getByRole('button', { name: /item/ }).click(); const dialog = page.getByRole('dialog', { name: /Items reserved by/ }); await dialog.getByRole('button', { name: 'Release' }).click(); await expect(dialog.getByText("This customer isn't holding any items")).toBeVisible(); // The row behind the dialog must agree with the dialog it opened. await dialog.getByRole('button', { name: 'Close' }).click(); await expect(row.getByRole('button', { name: /item/ })).toHaveCount(0); }); test('a customer holding nothing shows no link to click', async ({ page }) => { const email = `idle-${suffix()}@example.com`; await page.goto('/register'); await page.getByRole('textbox', { name: 'Email' }).fill(email); await page.getByRole('textbox', { name: 'First name' }).fill('Test'); await page.getByRole('textbox', { name: 'Last name' }).fill('Customer'); await page.getByLabel('Password').fill('supersecret123'); await page.getByRole('button', { name: 'Create account' }).click(); await expect(page.getByRole('button', { name: 'My Account' })).toBeVisible({ timeout: 20000 }); await page.goto('/admin'); await page.getByRole('tab', { name: 'Customers' }).click(); const row = page.getByRole('row').filter({ hasText: email }); await expect(row).toBeVisible(); await expect(row.getByRole('button', { name: /item/ })).toHaveCount(0); }); });