veza/tests/e2e/30-marketplace-checkout.spec.ts
senke 3640aec716 test(e2e): convert all remaining 298 console.log to real expect()
Convert 20 files from fake assertions (console.log with ✓/✗) to real
expect() assertions. This completes the conversion started in the
previous session — zero console.log calls remain in the E2E suite.

Files converted (by batch):
Batch 1: 16-forms-validation (38→0), 13-workflows (18→0), 14-edge-cases (8→0)
Batch 2: 15-routes-coverage (8→0), 20-network-errors (5→0), 04-tracks (4→0),
         32-deep-pages (4→0), 19-responsive (3→0), 11-accessibility-ethics (3→0)
Batch 3: 25-profile (2→0), 12-api (2→0), 29-chat-functional (2→0),
         30-marketplace-checkout (1→0), 22-performance (1→0),
         31-auth-sessions (1→0), 26-smoke (1→0), 02-navigation (1→0)
Batch 4: 24-cross-browser (0 fakes, 12 info→0), 34-workflows-empty (0→0),
         33-visual-bugs (0→0)

Total: 139 fake assertions → real expect(), 159 informational logs removed

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-08 15:50:17 +02:00

253 lines
9.2 KiB
TypeScript

import { test, expect } from '@chromatic-com/playwright';
import { loginViaAPI, CONFIG, navigateTo } from './helpers';
/**
* MARKETPLACE & CHECKOUT — Tests du flux d'achat
* Sélecteurs basés sur MarketplacePage.tsx, ProductCard.tsx, Cart.tsx, CartStore.ts
*/
test.describe('MARKETPLACE & CHECKOUT @critical', () => {
test.beforeEach(async ({ page }) => {
await loginViaAPI(page, CONFIG.users.listener.email, CONFIG.users.listener.password);
// Clear cart before each test
await page.evaluate(() => {
localStorage.removeItem('veza-cart-storage');
});
});
test('Marketplace — produits affichés avec prix et boutons @critical', async ({ page }) => {
await navigateTo(page, '/marketplace');
// Wait for products grid to load
const productCard = page.locator('[aria-label^="Product:"]').first()
.or(page.locator('[class*="CardFooter"]').first());
const hasProducts = await productCard.isVisible({ timeout: 10_000 }).catch(() => false);
if (hasProducts) {
// Verify price is visible
const price = page.locator('text=/\\$|€|USD/').first();
await expect(price).toBeVisible({ timeout: 3000 });
// Verify Buy button exists
const buyBtn = page.getByRole('button', { name: /buy|acheter/i }).first();
await expect(buyBtn).toBeVisible({ timeout: 3000 });
} else {
// Empty marketplace is valid — just check the page loaded without crash
const body = await page.textContent('body') || '';
expect(body).not.toMatch(/500|Internal Server Error/);
expect(body.length).toBeGreaterThan(50);
}
});
test('Recherche marketplace — filtrer les produits', async ({ page }) => {
await navigateTo(page, '/marketplace');
const searchInput = page.locator('input[placeholder*="Search" i]').first()
.or(page.locator('input[placeholder*="Recherch" i]').first());
const hasSearch = await searchInput.isVisible({ timeout: 5000 }).catch(() => false);
if (!hasSearch) {
test.skip(true, 'Search input not available on marketplace');
return;
}
await searchInput.fill('beat');
await page.waitForTimeout(1000);
// Results should update (either products or empty state)
const body = await page.textContent('body');
expect(body!.length).toBeGreaterThan(50);
});
test('Ajout au panier → badge panier incrémente @critical', async ({ page }) => {
await navigateTo(page, '/marketplace');
// Find a product card
const productCard = page.locator('[aria-label^="Product:"]').first();
const hasProduct = await productCard.isVisible({ timeout: 10_000 }).catch(() => false);
if (!hasProduct) {
test.skip(true, 'No products available in marketplace');
return;
}
// Hover to reveal Add to Cart
await productCard.hover();
await page.waitForTimeout(300);
const addToCartBtn = productCard.getByRole('button', { name: /add to cart|ajouter/i }).first()
.or(productCard.locator('button[class*="outline"]').first());
const hasAddBtn = await addToCartBtn.isVisible({ timeout: 3000 }).catch(() => false);
if (!hasAddBtn) {
test.skip(true, 'Add to cart button not available');
return;
}
await addToCartBtn.click();
await page.waitForTimeout(500);
// Check cart badge updated
const cartBadge = page.locator('text=/^1$|^[1-9]$/').first();
await expect(cartBadge).toBeVisible({ timeout: 3000 });
});
test('Ouvrir le panier — affiche les produits ajoutés @critical', async ({ page }) => {
await navigateTo(page, '/marketplace');
// Add a product to cart first
const productCard = page.locator('[aria-label^="Product:"]').first();
const hasProduct = await productCard.isVisible({ timeout: 10_000 }).catch(() => false);
if (!hasProduct) {
test.skip(true, 'No products available in marketplace');
return;
}
await productCard.hover();
await page.waitForTimeout(300);
const addBtn = productCard.getByRole('button', { name: /add to cart|ajouter/i }).first()
.or(productCard.locator('button[class*="outline"]').first());
const hasAddBtn = await addBtn.isVisible({ timeout: 3000 }).catch(() => false);
if (!hasAddBtn) {
test.skip(true, 'Add to cart button not available');
return;
}
await addBtn.click();
await page.waitForTimeout(500);
// Open cart
const cartBtn = page.getByRole('button', { name: /cart|panier/i }).first()
.or(page.locator('button').filter({ has: page.locator('[class*="ShoppingCart"]') }).first());
const hasCartBtn = await cartBtn.isVisible({ timeout: 5000 }).catch(() => false);
if (!hasCartBtn) {
test.skip(true, 'Cart button not visible');
return;
}
await cartBtn.click();
await page.waitForTimeout(500);
// Cart dialog should open
const cartDialog = page.locator('[role="dialog"]').first();
await expect(cartDialog).toBeVisible({ timeout: 3000 });
// Should show cart title
const cartTitle = cartDialog.locator('text=/shopping cart|panier/i').first();
await expect(cartTitle).toBeVisible({ timeout: 3000 });
});
test('Panier — supprimer un produit @critical', async ({ page }) => {
await navigateTo(page, '/marketplace');
// Add product then open cart
const productCard = page.locator('[aria-label^="Product:"]').first();
const hasProduct = await productCard.isVisible({ timeout: 10_000 }).catch(() => false);
if (!hasProduct) {
test.skip(true, 'No products available in marketplace');
return;
}
await productCard.hover();
const addBtn = productCard.getByRole('button', { name: /add to cart|ajouter/i }).first()
.or(productCard.locator('button[class*="outline"]').first());
const hasAddBtn = await addBtn.isVisible({ timeout: 3000 }).catch(() => false);
if (!hasAddBtn) {
test.skip(true, 'Add to cart button not available');
return;
}
await addBtn.click();
await page.waitForTimeout(500);
const cartBtn = page.getByRole('button', { name: /cart|panier/i }).first();
const hasCartBtn = await cartBtn.isVisible({ timeout: 3000 }).catch(() => false);
if (!hasCartBtn) {
test.skip(true, 'Cart button not visible');
return;
}
await cartBtn.click();
await page.waitForTimeout(500);
const removeBtn = page.locator('[aria-label="Remove item"]').first();
const hasRemoveBtn = await removeBtn.isVisible({ timeout: 3000 }).catch(() => false);
if (!hasRemoveBtn) {
test.skip(true, 'Remove item button not visible in cart');
return;
}
await removeBtn.click();
await page.waitForTimeout(500);
// Cart should now show empty
const emptyCart = page.locator('text=/cart is empty|panier est vide/i').first();
await expect(emptyCart).toBeVisible({ timeout: 3000 });
});
test('Panier vide — message et CTA vers marketplace', async ({ page }) => {
await navigateTo(page, '/marketplace');
// Open cart without adding anything
const cartBtn = page.getByRole('button', { name: /cart|panier/i }).first();
const hasCartBtn = await cartBtn.isVisible({ timeout: 5000 }).catch(() => false);
if (!hasCartBtn) {
test.skip(true, 'Cart button not visible');
return;
}
await cartBtn.click();
await page.waitForTimeout(500);
const emptyMsg = page.locator('text=/cart is empty|panier est vide/i').first();
await expect(emptyMsg).toBeVisible({ timeout: 3000 });
});
test('Checkout — le formulaire de paiement se charge @critical', async ({ page }) => {
await navigateTo(page, '/marketplace');
// Add product and go to checkout
const productCard = page.locator('[aria-label^="Product:"]').first();
const hasProduct = await productCard.isVisible({ timeout: 10_000 }).catch(() => false);
if (!hasProduct) {
test.skip(true, 'No products available in marketplace');
return;
}
await productCard.hover();
const addBtn = productCard.getByRole('button', { name: /add to cart|ajouter/i }).first()
.or(productCard.locator('button[class*="outline"]').first());
const hasAddBtn = await addBtn.isVisible({ timeout: 3000 }).catch(() => false);
if (!hasAddBtn) {
test.skip(true, 'Add to cart button not available');
return;
}
await addBtn.click();
await page.waitForTimeout(500);
const cartBtn = page.getByRole('button', { name: /cart|panier/i }).first();
const hasCartBtn = await cartBtn.isVisible({ timeout: 3000 }).catch(() => false);
if (!hasCartBtn) {
test.skip(true, 'Cart button not visible');
return;
}
await cartBtn.click();
await page.waitForTimeout(500);
// Look for checkout/pay button
const checkoutBtn = page.getByRole('button', { name: /checkout|payer|pay/i }).first();
const hasCheckout = await checkoutBtn.isVisible({ timeout: 3000 }).catch(() => false);
if (!hasCheckout) {
test.skip(true, 'Checkout button not visible in cart');
return;
}
await checkoutBtn.click();
await page.waitForTimeout(2000);
// Verify payment form loads (Hyperswitch iframe or payment form)
const paymentForm = page.locator('iframe').first()
.or(page.locator('text=/complete payment|paiement/i').first());
await expect(paymentForm).toBeVisible({ timeout: 5000 });
});
});