/** * Sprint 16 — flows 06 multi-tenant isolation (3 flows): * 6.1 org A видит свои товары, в org B их нет в списке * 6.2 org B → GET /api/catalog/products/{id-from-A} → 404 * 6.3 org B → GET /api/sales/retail/{id-from-A} → 404 */ import { expect, test } from '@playwright/test' import { request } from '../factories/api-client.js' import { Endpoints } from '../factories/types.js' import { OrgFactory } from '../factories/OrgFactory.js' test.describe('flow 06 — multi-tenant isolation @smoke', () => { test('6.1 список товаров org B не содержит ID товара org A', async () => { const A = await OrgFactory.for('mt61A').withProducts(1).build() const B = await OrgFactory.for('mt61B').withProducts(1).build() const aProductId = A.products[0]!.id const bList = await request<{ items: Array<{ id: string }> }>( Endpoints.products + '?pageSize=500', { token: B.session.accessToken }, ) // Изоляция по Id — B не должен видеть Id A среди своих. expect(bList.items.some(p => p.id === aProductId), 'B не должен видеть продукт A').toBeFalsy() // У B должен быть свой продукт. expect(bList.items.some(p => p.id === B.products[0]!.id)).toBeTruthy() }) test('6.2 GET product-by-id org A под токеном org B → 404', async () => { const A = await OrgFactory.for('mt62A').withProducts(1).build() const B = await OrgFactory.for('mt62B').build() const resp = await fetch( `${process.env.E2E_ADMIN_URL ?? 'https://test.admin.food-market.kz'}${Endpoints.products}/${A.products[0]!.id}`, { headers: { Authorization: `Bearer ${B.session.accessToken}` } }, ) expect(resp.status).toBe(404) }) test('6.3 GET retail-sale org A под токеном org B → 404', async () => { const A = await OrgFactory.for('mt63A').withProducts(1).withSupplies(1).build() const B = await OrgFactory.for('mt63B').build() // Создаём чек у A const draft = await request<{ id: string }>(Endpoints.retailSales, { token: A.session.accessToken, body: { date: new Date().toISOString(), storeId: A.refs.storeId, retailPointId: A.refs.retailPointId, currencyId: A.refs.currencyId, payment: 0, isReturn: false, lines: [{ productId: A.products[0]!.id, quantity: 1, unitPrice: 100, discount: 0, vatPercent: 12 }], subtotal: 100, discountTotal: 0, total: 100, paidCash: 100, paidCard: 0, }, }) const resp = await fetch( `${process.env.E2E_ADMIN_URL ?? 'https://test.admin.food-market.kz'}${Endpoints.retailSales}/${draft.id}`, { headers: { Authorization: `Bearer ${B.session.accessToken}` } }, ) expect(resp.status).toBe(404) }) })