import { test, expect } from '@chromatic-com/playwright'; import { loginViaAPI, CONFIG, navigateTo } from './helpers'; test.describe('MARKETPLACE — Navigation', () => { test.beforeEach(async ({ page }) => { await loginViaAPI(page, CONFIG.users.listener.email, CONFIG.users.listener.password); }); test('01. Page marketplace se charge @critical', async ({ page }) => { await navigateTo(page, '/marketplace'); const body = await page.textContent('body') || ''; expect(body).not.toMatch(/500|Internal Server Error/); expect(body.length).toBeGreaterThan(50); const heading = page.locator('h1').filter({ hasText: /marketplace/i }); await expect(heading).toBeVisible({ timeout: 10_000 }); }); test('02. Les produits (beats/samples) s\'affichent', async ({ page }) => { await navigateTo(page, '/marketplace'); const products = page.locator('article[aria-label^="Product:"]'); expect(await products.count()).toBeGreaterThan(0); }); test('03. Filtres marketplace fonctionnent', async ({ page }) => { await navigateTo(page, '/marketplace'); const searchInput = page.getByPlaceholder(/search tracks|search/i).first(); await expect(searchInput).toBeVisible(); const filtersBtn = page.getByRole('button', { name: /filters/i }).first(); await expect(filtersBtn).toBeVisible(); const cartBtn = page.getByRole('button', { name: /cart/i }).first(); await expect(cartBtn).toBeVisible(); }); test('04. Page détail d\'un produit se charge', async ({ page }) => { await navigateTo(page, '/marketplace'); const products = page.locator('article[aria-label^="Product:"]'); const count = await products.count(); test.skip(count === 0, 'No products available in marketplace'); // The detail route /marketplace/products/:id exists in router, but ProductCard // does NOT currently expose a link to it — navigate directly to test the route. // Try to extract a product id from an existing link, else navigate to a seeded route. const productLink = page.locator('a[href*="/marketplace/products/"]').first(); const hasLink = await productLink.isVisible({ timeout: 2_000 }).catch(() => false); if (hasLink) { await productLink.click(); } else { // Known UX gap: ProductCard has no link to detail. Navigate via API to find an ID. const productId = await page.evaluate(async () => { const r = await fetch('/api/v1/marketplace/products?page=1&limit=1'); const d = await r.json(); return d?.data?.[0]?.id ?? d?.data?.products?.[0]?.id ?? null; }); test.skip(!productId, 'No product ID available to navigate to detail page'); await page.goto(`/marketplace/products/${productId}`); } await page.waitForLoadState('networkidle').catch(() => {}); const body = await page.textContent('body') || ''; expect(body).not.toMatch(/500|Internal Server Error/); }); test('05. Bouton Buy Now et Add to Cart présents', async ({ page }) => { await navigateTo(page, '/marketplace'); const firstProduct = page.locator('article[aria-label^="Product:"]').first(); await expect(firstProduct).toBeVisible(); await firstProduct.hover(); await page.waitForTimeout(500); const buyBtn = page.getByRole('button', { name: /buy now/i }).first(); const addToCartBtn = page.getByRole('button', { name: /add to cart/i }).first(); await expect(buyBtn).toBeVisible(); await expect(addToCartBtn).toBeVisible(); }); }); test.describe('MARKETPLACE — Dashboard vendeur', () => { test.beforeEach(async ({ page }) => { await loginViaAPI(page, CONFIG.users.creator.email, CONFIG.users.creator.password); }); test('06. Dashboard vendeur accessible @critical', async ({ page }) => { await navigateTo(page, '/sell'); const body = await page.textContent('body') || ''; expect(body).not.toMatch(/500|Internal Server Error/); expect(body.length).toBeGreaterThan(100); }); }); test.describe('MARKETPLACE — Wishlist', () => { test.beforeEach(async ({ page }) => { await loginViaAPI(page, CONFIG.users.listener.email, CONFIG.users.listener.password); }); test('07. Page wishlist accessible @critical', async ({ page }) => { await navigateTo(page, '/wishlist'); const body = await page.textContent('body') || ''; expect(body).not.toMatch(/500|Internal Server Error/); expect(body.length).toBeGreaterThan(50); }); }); test.describe('MARKETPLACE — Purchases', () => { test.beforeEach(async ({ page }) => { await loginViaAPI(page, CONFIG.users.listener.email, CONFIG.users.listener.password); }); test('08. Page purchases accessible', async ({ page }) => { await navigateTo(page, '/purchases'); const body = await page.textContent('body') || ''; expect(body).not.toMatch(/500|Internal Server Error/); expect(body.length).toBeGreaterThan(50); }); }); test.describe('MARKETPLACE — Cart (in-page)', () => { test.beforeEach(async ({ page }) => { await loginViaAPI(page, CONFIG.users.listener.email, CONFIG.users.listener.password); }); test('09. Cart s\'ouvre via le bouton Cart sur marketplace', async ({ page }) => { await navigateTo(page, '/marketplace'); const cartBtn = page.getByRole('button', { name: /cart/i }).first(); await expect(cartBtn).toBeVisible(); await cartBtn.click(); await page.waitForTimeout(500); // Cart panel should show something (empty cart message or items) const body = await page.textContent('body') || ''; expect(body).toMatch(/cart|panier|empty|vide|item/i); }); test('10. Ajouter un produit au cart affiche un feedback', async ({ page }) => { await navigateTo(page, '/marketplace'); const firstProduct = page.locator('article[aria-label^="Product:"]').first(); test.skip(!(await firstProduct.isVisible().catch(() => false)), 'No products available'); await firstProduct.hover(); await page.waitForTimeout(500); const addToCartBtn = firstProduct.getByRole('button', { name: /add to cart/i }); await expect(addToCartBtn).toBeVisible(); await addToCartBtn.click(); await page.waitForTimeout(1_000); // react-hot-toast renders with role="status" aria-live="polite" + text "added to cart" const toast = page.locator('[role="status"][aria-live]').filter({ hasText: /added to cart/i }).first(); await expect(toast).toBeVisible(); }); });