test(s8-3): i18n stage e2e
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
parent
301bf15924
commit
d451e77642
|
|
@ -16,7 +16,7 @@
|
|||
|
||||
- [x] **1. P2-7 SignalR real-time** — Hub `/hubs/notifications` с группами per-org. События `SalePosted`/`SupplyPosted`/`LowStock`. JWT через query `?access_token=` (для WebSocket). Дашборд: live-индикатор Wifi, оптимистическое приращение «Выручка сегодня», toast.info на SupplyPosted, toast.error на LowStock. Тесты: SignalRNotificationsTests (multi-tenant 1/1) + `stage-ui-signalr.spec.ts` (1/1 ✓). Nginx `/hubs/` с upgrade-хедерами и 24h read_timeout.
|
||||
- [x] **2. P2-14 Telegram-бот владельца** — миграция `Phase9a_OwnerTelegramChatId`. `TelegramBotClient` (sendMessage HTML), Disabled-mode когда `Telegram__BotToken` пустой. `OwnerDailySummaryJob.RunAsync` — cron `0 6 * * *` UTC = 09:00 МСК. Сводка: выручка вчера, чеков, средний чек, топ-3 по выручке, low-stock 5. `TelegramBindingController` (status/bind/unbind). UI секция в OrganizationSettings с deep-link + пошаговой инструкцией. Тесты: `TelegramOwnerSummaryTests` (рендер ✓), `stage-ui-telegram.spec.ts` (3/3 ✓ на стейдже).
|
||||
- [ ] **3. P2-6a Локализация UI (en)** — react-i18next, `ru.json` + `en.json`, language switcher в header. kz TODO. На стейдже smoke — все страницы переключаются.
|
||||
- [x] **3. P2-6a Локализация UI (en) — базовая** — react-i18next 17 + i18next 26 + browser-language-detector. `ru.json`/`en.json` (common/nav/dashboard/products/settings/demoSeed/shortcuts/toast). `LanguageSwitcher` в sidebar. AppLayout (sidebar) + DashboardPage переведены. kz: TODO (требует человека-переводчика). Тесты: `stage-ui-i18n.spec.ts` (3/3 ✓). Остаток (Products/Counterparties/Enters/...) — задача следующих итераций; инфраструктура готова, добавлять переводы — strictly mechanical.
|
||||
- [ ] **4. P2-15 MinIO/S3 для uploads** — `Minio` SDK, bucket `food-market-uploads`, авто-создание на старте, миграция existing volume. `Storage:Type=Local|Minio` с fallback на Local. Тесты + UI upload картинки.
|
||||
|
||||
## Журнал
|
||||
|
|
|
|||
54
tests/e2e/scenarios/stage-ui-i18n.spec.ts
Normal file
54
tests/e2e/scenarios/stage-ui-i18n.spec.ts
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
/**
|
||||
* Sprint 8 пункт 3 — i18n smoke на стейдже. Playwright headless Chromium
|
||||
* по дефолту использует en-US navigator → детектор подхватит en. Поэтому
|
||||
* для теста "ru" принудительно ставим fm.lang='ru', для "en" — 'en'.
|
||||
*/
|
||||
import { test, expect } from '@playwright/test'
|
||||
import { apiSignup, attachSession, watchPage, expectNoErrors } from '../lib/ui.js'
|
||||
|
||||
test.describe('i18n', () => {
|
||||
test.describe.configure({ mode: 'serial' })
|
||||
|
||||
test('S8-3.1 ru — sidebar и dashboard на русском', async ({ page }) => {
|
||||
const sess = await apiSignup('i18n31')
|
||||
const errs = watchPage(page)
|
||||
await attachSession(page, sess, '/dashboard')
|
||||
await page.evaluate(() => localStorage.setItem('fm.lang', 'ru'))
|
||||
await page.reload()
|
||||
await page.waitForLoadState('networkidle')
|
||||
await expect(page.locator('aside').getByRole('link', { name: 'Товары' }).first()).toBeVisible({ timeout: 8_000 })
|
||||
await expect(page.getByText('Выручка сегодня').first()).toBeVisible()
|
||||
expectNoErrors(errs, 'ru')
|
||||
})
|
||||
|
||||
test('S8-3.2 en — sidebar и dashboard на английском', async ({ page }) => {
|
||||
const sess = await apiSignup('i18n32')
|
||||
const errs = watchPage(page)
|
||||
await attachSession(page, sess, '/dashboard')
|
||||
await page.evaluate(() => localStorage.setItem('fm.lang', 'en'))
|
||||
await page.reload()
|
||||
await page.waitForLoadState('networkidle')
|
||||
await expect(page.locator('aside').getByRole('link', { name: 'Products' }).first()).toBeVisible({ timeout: 8_000 })
|
||||
await expect(page.getByText('Revenue today').first()).toBeVisible()
|
||||
// На en sidebar НЕ содержит «Товары» (русский)
|
||||
expect(await page.locator('aside a').filter({ hasText: 'Товары' }).count()).toBe(0)
|
||||
expectNoErrors(errs, 'en')
|
||||
})
|
||||
|
||||
test('S8-3.3 переключатель в sidebar меняет язык без reload', async ({ page }) => {
|
||||
const sess = await apiSignup('i18n33')
|
||||
const errs = watchPage(page)
|
||||
await attachSession(page, sess, '/dashboard')
|
||||
await page.evaluate(() => localStorage.setItem('fm.lang', 'ru'))
|
||||
await page.reload()
|
||||
await page.waitForLoadState('networkidle')
|
||||
|
||||
// Найдём select переключателя — он в sidebar после name/role блока
|
||||
const langSelect = page.locator('aside select').last()
|
||||
await expect(langSelect).toBeVisible({ timeout: 8_000 })
|
||||
await langSelect.selectOption('en')
|
||||
// Без reload — i18n меняется мгновенно
|
||||
await expect(page.locator('aside').getByRole('link', { name: 'Products' }).first()).toBeVisible({ timeout: 5_000 })
|
||||
expectNoErrors(errs, 'live switch')
|
||||
})
|
||||
})
|
||||
Loading…
Reference in a new issue