import { test, expect, createAdminContext, createCategory, uniqueSuffix } from './fixtures'; /** * The per-item background control in the inventory editor (#293). * * Asserts the control is offered, not that a cut-out happens. Pressing it needs * a live rembg sidecar, which takes forty seconds to start and which no test * should depend on — the swap itself is covered in the integration suite * against a stub. * * "Does not appear when the feature is unconfigured" is not written here as an * e2e case: unsetting REMBG_URL means restarting the backend mid-suite, which * this run has no way to do and should not gain one. GET /api/admin/config * answering `backgroundRemoval: false` is covered by Task 2's integration * tests, and the render condition that gates the button on it is plain enough * to read in Admin.tsx. */ const RUN = uniqueSuffix(); const NAME = `Vase ${RUN}`; // A category of its own, not shared: it exists only so filterByCategory below // has something unique to narrow the table down to, the same way // admin-inventory-filters.spec.ts uses one per run. const CATEGORY = `Backgrounds ${RUN}`; // The 1x1 PNG the other upload specs use, so this goes through the real // validated upload path rather than a buffer that merely starts correctly. const PNG = Buffer.from( 'iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8z8BQDwAEhQGAhKmMIQAAAABJRU5ErkJggg==', 'base64' ); test.beforeAll(async ({ playwright }) => { const api = await createAdminContext(playwright); const categoryId = await createCategory(api, CATEGORY); // Seeded with an image directly: createItem cannot attach one, and the // control does not render for an item with no photos. const res = await api.post('/api/admin/items', { multipart: { name: NAME, description: '', price: '50', category_id: String(categoryId), tags: '[]', images: { name: `${RUN}.png`, mimeType: 'image/png', buffer: PNG } } }); expect(res.ok(), `seeding ${NAME}`).toBeTruthy(); await api.dispose(); }); test.describe('Removing backgrounds from the item editor', () => { test('offers the control on an item that has photos', async ({ page, admin, adminInventory }) => { await admin.open('Inventory'); // The table paginates at 10 and this suite runs fullyParallel, so an // unfiltered page 1 is not a reliable place to find this fixture — see // AdminInventory.filterByCategory. Filtering to this item's own category // narrows the table down to just it, the way admin-inventory-filters.spec.ts // does. await adminInventory.filterByCategory(CATEGORY, NAME); await adminInventory.row(NAME).getByRole('button', { name: 'Edit' }).click(); await expect(page.getByRole('button', { name: 'Remove backgrounds' })).toBeVisible(); }); });