import { expect, test } from '@playwright/test'; const tinyPng = Buffer.from('iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNk+A8AAQUBAScY42YAAAAASUVORK5CYII=', 'base64'); test('signs in and publishes a listing after adding an inventory image', async ({ page }) => { const email = process.env.INITIAL_ADMIN_EMAIL; const password = process.env.INITIAL_ADMIN_PASSWORD; test.skip(!email || !password, 'Set INITIAL_ADMIN_EMAIL and INITIAL_ADMIN_PASSWORD for the local authenticated workflow.'); await page.goto('/login'); await page.getByLabel('Email').fill(email); await page.getByLabel('Password').fill(password); await page.getByRole('button', { name: 'Sign in' }).click(); await expect(page).toHaveURL(/\/admin$/); await expect(page.getByRole('heading', { name: 'Collector workspace' })).toBeVisible(); await expect(page.getByRole('status', { name: 'Loading inventory...' })).toHaveCount(0); await expect(page.getByRole('heading', { name: 'At a glance' })).toBeVisible(); await expect(page.getByText('Active inventory')).toBeVisible(); await expect(page.locator('.dashboard-summary__grid div').filter({ hasText: 'Missing images' }).getByRole('link')).toHaveAttribute('href', '#inventory-title'); const category = page.locator('#product-category option').nth(1); await expect(category).toBeAttached(); const productName = `Browser test collectible ${Date.now()}`; await page.getByLabel('Name').fill(productName); await page.getByLabel('Category').selectOption({ index: 1 }); await page.getByRole('button', { name: 'Create product' }).click(); await expect(page.locator('#inventory-product option').nth(1)).toBeAttached(); const createdProductId = await page.locator('#inventory-product').locator('option', { hasText: productName }).getAttribute('value'); await page.locator('#mapping-product').selectOption(createdProductId); await page.getByLabel('Provider ID').fill('fixture-provider'); await page.getByLabel('External identifier').fill('fixture-product-1'); await page.getByRole('button', { name: 'Save provider mapping' }).click(); await expect(page.getByRole('region', { name: 'Active provider mappings' })).toContainText('fixture-provider'); await page.locator('#inventory-product').selectOption(createdProductId); await page.getByLabel('Condition', { exact: true }).selectOption({ index: 1 }); await page.getByRole('button', { name: 'Create copy' }).click(); const createdInventoryRow = page.locator(`section[aria-labelledby="inventory-title"] li[data-product-id="${createdProductId}"]`).last(); const createdInventoryId = await createdInventoryRow.locator('a').getAttribute('href').then((href) => href.split('/').at(-2)); const inventoryLink = page.locator(`a[href="/admin/inventory/${createdInventoryId}/images"]`); await expect(inventoryLink).toBeVisible(); await page.locator('#acquisition-inventory').selectOption(createdInventoryId); await page.getByLabel('Method').fill('PURCHASE'); await page.getByLabel('Acquisition date').fill('2026-09-09'); await page.getByLabel('Cost (cents)').fill('1000'); await page.getByLabel('Shipping (cents)').fill('100'); await page.getByLabel('Tax (cents)').fill('50'); await page.getByRole('button', { name: 'Record acquisition' }).click(); await expect(page.locator('section[aria-labelledby="acquisitions-title"] li').first()).toContainText('Basis $11.50'); await page.locator('#pricing-inventory').selectOption(createdInventoryId); await page.getByLabel('Source identifier').fill('browser-price-1'); await page.getByLabel('Observed price (cents)').fill('2500'); const [observationResponse, valuationResponse] = await Promise.all([ page.waitForResponse((response) => response.url().includes('/admin/pricing/observations')), page.waitForResponse((response) => response.url().includes('/valuation') && response.request().method() === 'POST'), page.getByRole('button', { name: 'Add observation and calculate' }).click(), ]); expect(observationResponse.status()).toBe(201); expect(valuationResponse.status()).toBe(200); const valuationRow = page.getByRole('list', { name: 'Market valuations' }).getByText(createdInventoryId); await expect(valuationRow).toContainText('Market value $25.00'); await page.getByLabel('Manual value (cents)').fill('2700'); await page.getByLabel('Override reason').fill('Verified recent sale'); await page.getByRole('button', { name: 'Save manual value' }).click(); await expect(page.getByRole('list', { name: 'Market valuations' })).toContainText('Market value $27.00'); await expect(page.getByRole('list', { name: 'Market valuations' })).toContainText('OVERRIDE confidence'); await inventoryLink.click(); await expect(page).toHaveURL(/\/admin\/inventory\/[^/]+\/images$/); await expect(page.getByRole('heading', { name: 'Manage images' })).toBeVisible(); await page.getByLabel('Add image').setInputFiles({ name: 'front.png', mimeType: 'image/png', buffer: tinyPng, }); await expect(page.getByLabel('Alt text')).toHaveValue('front.png'); await page.goto('/admin'); await expect(page.getByRole('heading', { name: 'Create listing draft' })).toBeVisible(); await page.getByLabel('Inventory copy', { exact: true }).first().selectOption(createdInventoryId); await page.getByLabel('Asking price (cents)').fill('2499'); await page.getByRole('button', { name: 'Create listing' }).click(); const createdListing = page.locator('section[aria-labelledby="listings-title"] article').filter({ hasText: productName }).last(); await expect(createdListing.getByText('Add at least one image before publishing.')).toHaveCount(0); await createdListing.getByRole('button', { name: 'Publish' }).click(); await expect(createdListing).toContainText('AVAILABLE'); await page.locator('#sale-inventory').selectOption(createdInventoryId); await page.getByLabel('Sale date').fill('2026-09-09'); await page.getByLabel('Sold price (cents)').fill('2499'); await page.getByLabel('Cost basis (cents)').fill('1200'); await page.getByRole('button', { name: 'Record sale' }).click(); await expect(page.locator('section[aria-labelledby="inventory-title"]').getByText(`${createdInventoryId} · SOLD`)).toBeVisible(); await expect(page.getByRole('heading', { name: 'Sale history' })).toBeVisible(); const latestSale = page.locator('section[aria-labelledby="sales-title"] li').first(); await expect(latestSale).toContainText('Profit $12.99'); await latestSale.getByLabel('Void reason').fill('Browser test correction'); await latestSale.getByRole('button', { name: 'Void sale' }).click(); await expect(latestSale).toContainText('VOIDED'); await expect(page.locator('section[aria-labelledby="inventory-title"]').getByText(`${createdInventoryId} · ACTIVE`)).toBeVisible(); });