/** * Sprint 16 — flows 03 catalog (5 flows): * 3.1 product create → list → get-by-id (CRUD smoke) * 3.2 product update → изменения сохраняются * 3.3 counterparty create (юрлицо) → list * 3.4 store: дефолтный «Главный» существует, можно добавить ещё * 3.5 price-type «Розничная» существует и помечена IsSystem+IsRetail */ import { expect, test } from '@playwright/test' import { request, ApiError } from '../factories/api-client.js' import { Endpoints } from '../factories/types.js' import { OrgFactory } from '../factories/OrgFactory.js' test.describe('flow 03 — catalog', () => { test('3.1 product create → list → get-by-id @smoke', async () => { const b = await OrgFactory.for('cat31').withProducts(1).build() const p = b.products[0]! const list = await request<{ items: Array<{ id: string; name: string }> }>( Endpoints.products + '?pageSize=10', { token: b.session.accessToken }, ) expect(list.items.find(x => x.id === p.id)).toBeTruthy() const single = await request<{ id: string; name: string }>( `${Endpoints.products}/${p.id}`, { token: b.session.accessToken }, ) expect(single.name).toBe(p.name) }) test('3.2 product update изменения сохраняются', async () => { const b = await OrgFactory.for('cat32').withProducts(1).build() const p = b.products[0]! // Получаем полный объект для PUT (бекенд требует ImageUrl, Code, etc.) const full = await request(`${Endpoints.products}/${p.id}`, { token: b.session.accessToken }) const newName = full.name + ' UPDATED' await request(`${Endpoints.products}/${p.id}`, { token: b.session.accessToken, method: 'PUT', body: { ...full, name: newName }, }) const after = await request<{ name: string }>(`${Endpoints.products}/${p.id}`, { token: b.session.accessToken }) expect(after.name).toBe(newName) }) test('3.3 counterparty create + list @smoke', async () => { const b = await OrgFactory.for('cat33').withCounterparties(2).build() const list = await request<{ items: Array<{ id: string }> }>( Endpoints.counterparties + '?pageSize=10', { token: b.session.accessToken }, ) expect(list.items.length).toBeGreaterThanOrEqual(2) for (const c of b.counterparties) { expect(list.items.find(x => x.id === c.id)).toBeTruthy() } }) test('3.4 store дефолтный «Главный» существует', async () => { const b = await OrgFactory.for('cat34').build() const list = await request<{ items: Array<{ id: string; name: string; isMain: boolean }> }>( Endpoints.refs.stores, { token: b.session.accessToken }, ) const main = list.items.find(s => s.isMain) expect(main, 'Главный склад должен быть создан при signup').toBeDefined() expect(main!.id).toBe(b.refs.storeId) }) test('3.5 price-type системный розничный есть', async () => { const b = await OrgFactory.for('cat35').build() const list = await request<{ items: Array<{ id: string; name: string; isRetail: boolean; isSystem: boolean }> }>( Endpoints.refs.priceTypes, { token: b.session.accessToken }, ) const sys = list.items.find(p => p.isRetail && p.isSystem) expect(sys, 'системный розничный price-type должен быть после signup').toBeDefined() expect(sys!.id).toBe(b.refs.priceTypeId) }) })