98 lines
3.2 KiB
TypeScript
98 lines
3.2 KiB
TypeScript
import { test, expect } from '@playwright/test'
|
|
import {
|
|
CREDENTIALS_HINT,
|
|
hasStaffCredentials,
|
|
trackDialogs,
|
|
expectDialog,
|
|
openAddProduct,
|
|
fillNewProduct,
|
|
submitProductForm,
|
|
gotoProductsAndSearch,
|
|
openProductEdit,
|
|
setProductName,
|
|
setProductPrice,
|
|
toggleSuspend,
|
|
isSuspendChecked,
|
|
openAddSlot,
|
|
fillSlotDatetimes,
|
|
addProductToSlot,
|
|
submitSlotForm,
|
|
futureSlotTimes,
|
|
waitForAppHydration,
|
|
} from '../helpers/admin-app'
|
|
|
|
test.skip(!hasStaffCredentials(), CREDENTIALS_HINT)
|
|
|
|
/**
|
|
* Long, single-instance workflow: add a product, update it, create a delivery
|
|
* slot for it, then suspend it — all in one browser page/context, mirroring how
|
|
* an admin actually works through the panel.
|
|
*
|
|
* Runs as one test with named steps so the whole chain shares page state.
|
|
*/
|
|
test('product lifecycle: create → update → slot → suspend', async ({ page }) => {
|
|
const productName = `E2E Product ${Date.now()}`
|
|
const updatedName = `${productName} Updated`
|
|
const dialogs = trackDialogs(page)
|
|
|
|
await test.step('dashboard is available (authenticated session)', async () => {
|
|
await page.goto('/dashboard')
|
|
await waitForAppHydration(page)
|
|
await expect(page.getByRole('button', { name: 'Products', exact: true })).toBeVisible()
|
|
})
|
|
|
|
await test.step('add a new product', async () => {
|
|
await openAddProduct(page)
|
|
await fillNewProduct(page, {
|
|
name: productName,
|
|
price: 250,
|
|
marketPrice: 300,
|
|
quantity: '1 kg',
|
|
})
|
|
await submitProductForm(page)
|
|
await expectDialog(dialogs, 'Product created successfully!')
|
|
})
|
|
|
|
await test.step('the product appears in the products list', async () => {
|
|
await gotoProductsAndSearch(page, productName)
|
|
await expect(page.getByText(productName).first()).toBeVisible()
|
|
})
|
|
|
|
await test.step('update the product name and price', async () => {
|
|
await openProductEdit(page, productName)
|
|
await setProductName(page, updatedName)
|
|
await setProductPrice(page, 275)
|
|
await submitProductForm(page)
|
|
await expectDialog(dialogs, 'Product updated successfully!')
|
|
})
|
|
|
|
await test.step('create a delivery slot for the product', async () => {
|
|
const { delivery, freeze } = futureSlotTimes()
|
|
await openAddSlot(page)
|
|
await fillSlotDatetimes(page, delivery, freeze)
|
|
await addProductToSlot(page, updatedName)
|
|
await submitSlotForm(page)
|
|
await expectDialog(dialogs, 'Slot created successfully!')
|
|
})
|
|
|
|
await test.step('the slot card lists the product', async () => {
|
|
// submitSlotForm navigates back to /dashboard/slots
|
|
await expect(page).toHaveURL(/\/dashboard\/slots/)
|
|
await expect(page.getByText(updatedName).first()).toBeVisible()
|
|
})
|
|
|
|
await test.step('suspend the product', async () => {
|
|
await openProductEdit(page, updatedName)
|
|
expect(await isSuspendChecked(page)).toBe(false)
|
|
await toggleSuspend(page)
|
|
// The toggle must take effect in the form before we save.
|
|
await expect.poll(() => isSuspendChecked(page), { timeout: 5_000 }).toBe(true)
|
|
await submitProductForm(page)
|
|
await expectDialog(dialogs, 'Product updated successfully!')
|
|
})
|
|
|
|
await test.step('suspension persists across reloads', async () => {
|
|
await openProductEdit(page, updatedName)
|
|
expect(await isSuspendChecked(page)).toBe(true)
|
|
})
|
|
})
|