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>
253 lines
9.2 KiB
TypeScript
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 });
|
|
});
|
|
});
|