/** * Sprint 16 — flows 08 realtime + misc (5 flows): * 8.1 SignalR connect → message на /hubs/notifications не падает * 8.2 dashboard live-status = on после wsConnect * 8.3 search global: 'товар' возвращает результат * 8.4 retail-points список содержит дефолтный «Касса 1» * 8.5 health/ready возвращает Healthy при работающей БД */ import { expect, test } from '@playwright/test' import { request } from '../factories/api-client.js' import { OrgFactory } from '../factories/OrgFactory.js' import { attachSession } from '../lib/ui.js' test.describe('flow 08 — realtime + misc', () => { test('8.1 dashboard рендерится без console-ошибок (SignalR опц.)', async ({ page }) => { const b = await OrgFactory.for('rt81').build() const errs: string[] = [] page.on('console', (m) => { if (m.type() !== 'error') return const t = m.text() if (/Failed to load resource|net::ERR_/.test(t)) return errs.push(t) }) await attachSession(page, b.session, '/dashboard') await page.waitForLoadState('networkidle') expect(errs, 'console-ошибок на /dashboard быть не должно').toEqual([]) }) test('8.2 live-status элемент отображается на dashboard', async ({ page }) => { const b = await OrgFactory.for('rt82').build() await attachSession(page, b.session, '/dashboard') // Sidebar показывает Wifi/WifiOff title — поэтому проверяем по title через // accessible name на иконке (Live on / Live off). const live = page.locator('[title*="live" i], [title*="реальн" i]').first() await expect(live).toBeVisible({ timeout: 10_000 }) }) test('8.3 search global возвращает товар по части имени @smoke', async () => { const b = await OrgFactory.for('rt83').withProducts(2).build() // Берём первое слово первого товара (например, "Товар"). const needle = b.products[0]!.name.split(' ')[0] ?? 'Товар' const r = await request<{ products: Array<{ id: string; name: string }> }>( `/api/search/global?q=${encodeURIComponent(needle)}`, { token: b.session.accessToken }, ) expect(r.products.length).toBeGreaterThan(0) }) test('8.4 retail-points список содержит дефолтную «Касса 1»', async () => { const b = await OrgFactory.for('rt84').build() const r = await request<{ items: Array<{ id: string; name: string }> }>( '/api/catalog/retail-points', { token: b.session.accessToken }, ) expect(r.items.length).toBeGreaterThanOrEqual(1) expect(r.items.find(x => /касса 1/i.test(x.name)), 'Касса 1 должна быть посеена').toBeDefined() }) test('8.5 health/ready возвращает Healthy', async () => { const r = await request<{ status: string }>('/health/ready') expect(r.status).toBe('Healthy') }) })