- Cache login tokens in loginViaAPI() to avoid rate limit / account lockout (429/423) when running 100+ tests sequentially - Add ACCOUNT_LOCKOUT_EXEMPT_EMAILS to playwright webServer config - Fix French-only regexes: add English alternatives (follow/back/etc.) - Fix Settings heading: "System Config" → include "Settings" alternative - Fix upload button selector: include "new/nouveau" alternative - Fix genre heading: include "by genre/genres" alternatives - Fix drag handle selector: include cursor-grab class Result: 57 passed, 36 failed (real bugs), 7 skipped Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
117 lines
4.5 KiB
TypeScript
117 lines
4.5 KiB
TypeScript
import { test, expect } from '@chromatic-com/playwright';
|
|
import { loginViaAPI, CONFIG, navigateTo } from './helpers';
|
|
|
|
test.describe('SOCIAL — Follow/Unfollow', () => {
|
|
test.beforeEach(async ({ page }) => {
|
|
await loginViaAPI(page, CONFIG.users.listener.email, CONFIG.users.listener.password);
|
|
});
|
|
|
|
test('01. Bouton follow visible sur un profil artiste @critical', async ({ page }) => {
|
|
await navigateTo(page, `/u/${CONFIG.users.creator.username}`);
|
|
await page.waitForLoadState('networkidle');
|
|
|
|
const followBtn = page.getByRole('button', { name: /suivre|abonné|abonnement|follow|following|unfollow/i }).first();
|
|
await expect(followBtn).toBeVisible();
|
|
});
|
|
|
|
test('02. Follow toggle fonctionne', async ({ page }) => {
|
|
await navigateTo(page, '/u/marcus_beats');
|
|
await page.waitForLoadState('networkidle');
|
|
|
|
const followBtn = page.getByRole('button', { name: /suivre|abonné|abonnement|désabonnement|follow|following|unfollow/i }).first();
|
|
await expect(followBtn).toBeVisible();
|
|
|
|
const initialText = await followBtn.textContent();
|
|
await followBtn.click();
|
|
await page.waitForTimeout(1_500);
|
|
const newText = await followBtn.textContent();
|
|
|
|
expect(newText?.trim()).not.toBe(initialText?.trim());
|
|
});
|
|
});
|
|
|
|
test.describe('SOCIAL — Profils', () => {
|
|
test.beforeEach(async ({ page }) => {
|
|
await loginViaAPI(page, CONFIG.users.listener.email, CONFIG.users.listener.password);
|
|
});
|
|
|
|
test('03. Mon profil se charge avec les bonnes infos @critical', async ({ page }) => {
|
|
await navigateTo(page, '/profile');
|
|
|
|
const body = await page.textContent('body') || '';
|
|
expect(body).not.toMatch(/500|Internal Server Error/);
|
|
expect(body).toContain(CONFIG.users.listener.username);
|
|
|
|
const avatar = page.locator('[class*="avatar"], img[alt*="avatar"], img[alt*="profil"]').first();
|
|
await expect(avatar).toBeVisible();
|
|
});
|
|
|
|
test('04. Éditer mon profil (bio, display name)', async ({ page }) => {
|
|
// Profile edit fields may be on /settings or /profile/edit
|
|
await navigateTo(page, '/settings');
|
|
|
|
const bioField = page.getByLabel(/bio/i).first()
|
|
.or(page.locator('textarea[name*="bio"]').first());
|
|
const nameField = page.getByLabel(/nom.*affichage|display.*name|first.*name|last.*name|nom/i).first();
|
|
|
|
// If not on /settings, try /profile/edit
|
|
const bioVisible = await bioField.isVisible().catch(() => false);
|
|
if (!bioVisible) {
|
|
await navigateTo(page, '/profile/edit');
|
|
}
|
|
|
|
await expect(page.getByLabel(/bio/i).first()
|
|
.or(page.locator('textarea[name*="bio"]').first())).toBeVisible();
|
|
});
|
|
|
|
test('05. L\'historique d\'écoute est privé (pas visible par d\'autres)', async ({ page }) => {
|
|
await navigateTo(page, `/u/${CONFIG.users.creator.username}`);
|
|
await page.waitForLoadState('networkidle');
|
|
|
|
const body = await page.textContent('body') || '';
|
|
expect(body).not.toMatch(/historique.*écoute|listening.*history|recently.*played/i);
|
|
});
|
|
|
|
test('06. Profil artiste affiche les stats (tracks, followers)', async ({ page }) => {
|
|
await navigateTo(page, `/u/${CONFIG.users.creator.username}`);
|
|
await page.waitForLoadState('networkidle');
|
|
|
|
const body = await page.textContent('body') || '';
|
|
expect(body).toContain('Tracks');
|
|
expect(body).toContain('Followers');
|
|
expect(body).toContain(CONFIG.users.creator.username);
|
|
});
|
|
});
|
|
|
|
test.describe('SOCIAL — Social Hub', () => {
|
|
test.beforeEach(async ({ page }) => {
|
|
await loginViaAPI(page, CONFIG.users.listener.email, CONFIG.users.listener.password);
|
|
});
|
|
|
|
test('07. Page social se charge @critical', async ({ page }) => {
|
|
await navigateTo(page, '/social');
|
|
|
|
const body = await page.textContent('body') || '';
|
|
expect(body).not.toMatch(/500|Internal Server Error/);
|
|
expect(body.length).toBeGreaterThan(100);
|
|
});
|
|
|
|
test('08. Social sidebar tabs (Fresh Tracks, Explore, Communities)', async ({ page }) => {
|
|
await navigateTo(page, '/social');
|
|
|
|
await expect(page.getByRole('button', { name: /fresh tracks/i })
|
|
.or(page.getByText(/fresh tracks/i))).toBeVisible();
|
|
await expect(page.getByRole('button', { name: /explore/i })
|
|
.or(page.getByText(/explore/i).first())).toBeVisible();
|
|
await expect(page.getByRole('button', { name: /communities/i })
|
|
.or(page.getByText(/communities/i))).toBeVisible();
|
|
});
|
|
|
|
test('09. Page feed se charge', async ({ page }) => {
|
|
await navigateTo(page, '/feed');
|
|
|
|
const body = await page.textContent('body') || '';
|
|
expect(body).not.toMatch(/500|Internal Server Error/);
|
|
expect(body.length).toBeGreaterThan(100);
|
|
});
|
|
});
|