Files
gold_land_user/e2e/session-resilience.spec.ts
safavimohadeseh78andCursor e3f0457dc9
Frontend CI / unit (test, type-check, build) (push) Successful in 1m11s
Frontend CI / browser E2E (frontend + pinned backend) (push) Failing after 2m48s
feat: complete server-backed six-lesson app and trial tooling
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-10-12 14:40:37 +03:30

94 lines
3.8 KiB
TypeScript

import { test, expect } from '@playwright/test'
import { fetchMe, loginViaUi, logoutViaProfile, registerViaUi, uniqueUsername } from './helpers/auth'
test.describe('session and errors', () => {
test('wrong password shows login failure', async ({ page }) => {
await page.goto('/login')
await page.getByLabel('نام کاربری').fill('no_such_user_e2e')
await page.getByLabel('رمز عبور').fill('wrongpass')
await page.getByRole('button', { name: 'ورود', exact: true }).click()
await expect(page.locator('.toast--error')).toBeVisible({ timeout: 10_000 })
await expect(page).toHaveURL(/login/)
})
test('second account does not show first account data', async ({ page }) => {
const u1 = uniqueUsername('acct1')
const u2 = uniqueUsername('acct2')
await registerViaUi(page, u1, 'pass1234', 'کاربر یک')
const me1 = await fetchMe(page)
await page.goto('/profile')
await expect(page.locator('.user-section__name')).toContainText(me1.user.name ?? 'کاربر یک')
await logoutViaProfile(page)
await page.getByRole('button', { name: 'ثبت‌نام کن' }).click()
await page.getByLabel('نام نمایشی').fill('کاربر دو')
await page.getByLabel('نام کاربری').fill(u2)
await page.getByLabel('رمز عبور').fill('pass1234')
await page.getByRole('button', { name: 'ثبت‌نام' }).click()
await page.waitForURL('/')
const me2 = await fetchMe(page)
await page.goto('/profile')
await expect(page.locator('.user-section__name')).toContainText(me2.user.name)
await expect(page.locator('.user-section__name')).not.toContainText('کاربر یک')
})
test('401 clears session to login', async ({ page }) => {
const user = uniqueUsername('401')
await registerViaUi(page, user, 'pass1234')
await page.goto('/wallet')
await page.evaluate(() => localStorage.setItem('gold-land-auth-token', 'invalid-token'))
await page.goto('/market')
await page.waitForURL('/login', { timeout: 15_000 })
})
test('catalog load retry after network failure', async ({ page }) => {
const user = uniqueUsername('net')
await registerViaUi(page, user, 'pass1234')
let storeCalls = 0
await page.route('**/api/store/products', async (route) => {
storeCalls += 1
if (storeCalls === 1) {
await route.abort('failed')
return
}
await route.continue()
})
await page.goto('/store')
await expect(page.locator('.store-status--error')).toBeVisible({ timeout: 15_000 })
await expect(page.getByText(/اتصال به سرور|خطا در دریافت/)).toBeVisible()
await page.getByRole('button', { name: 'تلاش مجدد' }).click()
await page.getByRole('button', { name: 'تقویت XP' }).waitFor({ timeout: 20_000 })
expect(storeCalls).toBeGreaterThan(1)
})
test('bootstrap network error keeps token and retry loads server data', async ({ page }) => {
const user = uniqueUsername('boot')
await registerViaUi(page, user, 'pass1234')
const meOk = await fetchMe(page)
let meCalls = 0
await page.route('**/api/me', async (route) => {
meCalls += 1
if (meCalls === 1) {
await route.abort('failed')
return
}
await route.continue()
})
await page.reload()
await expect(page.getByRole('alert')).toContainText('اتصال به سرور', { timeout: 15_000 })
expect(await page.evaluate(() => localStorage.getItem('gold-land-auth-token'))).toBeTruthy()
await page.getByRole('button', { name: 'تلاش مجدد' }).click()
await expect(page.getByRole('alert')).toBeHidden({ timeout: 20_000 })
const meAfter = await fetchMe(page)
expect(meAfter.user.xp).toBe(meOk.user.xp)
expect(meAfter.user.coins).toBe(meOk.user.coins)
expect(meCalls).toBeGreaterThan(1)
})
})