test(e2e): браузерный тест колокольчика — фоновый джоб кладёт агрегат минусов
Второй spec: seed + списания в минус, интервал 1 мин, ждём cron-джоб (*/5), открываем колокольчик → видно «N товаров ушли в минус» + «Пересчитать». Проходит на стенде (~3.4 мин ожидания джоба). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
560d52e8cd
commit
ff42db7e97
|
|
@ -64,4 +64,45 @@ test.describe('negative-stock admin UI', () => {
|
|||
// В таблице есть хотя бы одна строка с отрицательным остатком (красная).
|
||||
await expect(page.locator('tbody tr').first()).toBeVisible({ timeout: 15_000 })
|
||||
})
|
||||
|
||||
test('колокольчик: фоновый джоб кладёт агрегат «N товаров ушли в минус»', async ({ page }) => {
|
||||
test.setTimeout(480_000) // ждём cron-джоб (*/5), до ~6.5 мин
|
||||
|
||||
const sess = await apiSignup('negbell')
|
||||
const ctx = await apiRequest.newContext({
|
||||
baseURL: BASE, ignoreHTTPSErrors: true, timeout: 60_000,
|
||||
extraHTTPHeaders: { Authorization: `Bearer ${sess.accessToken}` },
|
||||
})
|
||||
await ctx.post('/api/admin/seed-demo', { timeout: 60_000 })
|
||||
// интервал 1 мин — чтобы джоб разослал на ближайшем тике
|
||||
const s = (await (await ctx.get('/api/organization/settings')).json())
|
||||
await ctx.put('/api/organization/settings', { data: { ...s, negStockNotifyEnabled: true, negStockNotifyIntervalMinutes: 1 } })
|
||||
|
||||
const storeId = (await (await ctx.get('/api/catalog/stores?pageSize=50')).json()).items[0].id
|
||||
const currencyId = (await (await ctx.get('/api/catalog/currencies?pageSize=50')).json())
|
||||
.items.find((c: { code: string }) => c.code === 'KZT').id
|
||||
const stock = (await (await ctx.get(`/api/inventory/stock?storeId=${storeId}&pageSize=200`)).json()).items
|
||||
for (const row of stock.filter((x: { quantity: number }) => x.quantity > 0).slice(0, 2)) {
|
||||
const loss = await ctx.post('/api/inventory/losses', {
|
||||
data: { date: new Date().toISOString(), storeId, currencyId, reason: 0, notes: 'bell e2e',
|
||||
lines: [{ productId: row.productId, quantity: Number(row.quantity) + 3, unitCost: 10 }] },
|
||||
})
|
||||
await ctx.post(`/api/inventory/losses/${(await loss.json()).id}/post`, { data: {} })
|
||||
}
|
||||
|
||||
// Ждём, пока cron-джоб создаст персистентное уведомление.
|
||||
let unread = 0
|
||||
for (let i = 0; i < 40 && unread === 0; i++) {
|
||||
unread = (await (await ctx.get('/api/notifications/count')).json()).unread
|
||||
if (unread === 0) await page.waitForTimeout(10_000)
|
||||
}
|
||||
expect(unread, 'джоб создал уведомление').toBeGreaterThan(0)
|
||||
await ctx.dispose()
|
||||
|
||||
// Открываем колокольчик — видно агрегат и кнопку «Пересчитать».
|
||||
await attachSession(page, sess, '/dashboard')
|
||||
await page.getByRole('button', { name: /Уведомления/ }).first().click()
|
||||
await expect(page.getByText(/ушл.* в минус/i).first()).toBeVisible({ timeout: 10_000 })
|
||||
await expect(page.getByRole('button', { name: /Пересчитать/ }).first()).toBeVisible()
|
||||
})
|
||||
})
|
||||
|
|
|
|||
Loading…
Reference in a new issue