up
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
import assert from 'node:assert/strict'
|
||||
import { test } from 'node:test'
|
||||
import { ApiError, SessionChangedError } from './request-error.js'
|
||||
import { buildScreenPackage, prepareScreenPackage } from './screen-package.js'
|
||||
|
||||
const server = 'https://example.test'
|
||||
@@ -200,7 +201,7 @@ test('отказы API и некорректный JSON не выдают час
|
||||
prepareScreenPackage({ server, gameId: 7, token: 'SECRET' }, async () => {
|
||||
throw new Error('SECRET')
|
||||
}),
|
||||
/^Error: Сервер недоступен$/,
|
||||
/^Error: Описание игры: Сервер недоступен$/,
|
||||
)
|
||||
})
|
||||
|
||||
@@ -236,3 +237,69 @@ test('отмена и недопустимые адреса обрабатыва
|
||||
)
|
||||
await assert.rejects(prepareScreenPackage({ server, gameId: 7, token: '' }), /токен/)
|
||||
})
|
||||
|
||||
test('сетевая ошибка называет запрос и журналирует только безопасную причину', async () => {
|
||||
for (const suffix of ['', '/screen-plan', '/music']) {
|
||||
const failures: { path: string; reason: string }[] = []
|
||||
const data = fixture()
|
||||
await assert.rejects(
|
||||
prepareScreenPackage(
|
||||
{ server, gameId: 7, token: 'SECRET', onRequestFailure: (f) => failures.push(f) },
|
||||
async (input) => {
|
||||
const url = String(input)
|
||||
if (url === `${server}/api/games/7${suffix}`)
|
||||
throw new TypeError('SECRET', {
|
||||
cause: Object.assign(new Error('SECRET'), { code: 'ENOTFOUND' }),
|
||||
})
|
||||
return Response.json(
|
||||
url.endsWith('/music')
|
||||
? data.music
|
||||
: url.endsWith('/screen-plan')
|
||||
? data.plan
|
||||
: data.game,
|
||||
)
|
||||
},
|
||||
),
|
||||
new RegExp(
|
||||
`^Error: ${suffix === '/music' ? 'Музыка игры' : suffix === '/screen-plan' ? 'План экранов' : 'Описание игры'}: Не удалось определить адрес сервера$`,
|
||||
),
|
||||
)
|
||||
assert.deepEqual(failures, [{ path: `/api/games/{id}${suffix}`, reason: 'ENOTFOUND' }])
|
||||
assert.ok(!JSON.stringify(failures).includes('SECRET'))
|
||||
}
|
||||
})
|
||||
|
||||
test('подготовка сохраняет ошибки авторизации и смены сессии', async () => {
|
||||
for (const error of [new ApiError(401), new ApiError(403), new SessionChangedError()]) {
|
||||
const data = fixture()
|
||||
await assert.rejects(
|
||||
prepareScreenPackage({ server, gameId: 7, token: 'SECRET' }, async (input) => {
|
||||
const url = String(input)
|
||||
if (url.endsWith('/screen-plan')) throw error
|
||||
return Response.json(url.endsWith('/music') ? data.music : data.game)
|
||||
}),
|
||||
(e) => e === error,
|
||||
)
|
||||
}
|
||||
})
|
||||
|
||||
test('таймаут и отмена подготовки различаются без утечки причины', async () => {
|
||||
for (const [name, message, reason] of [
|
||||
['TimeoutError', 'Превышено время ожидания ответа сервера', 'TIMEOUT'],
|
||||
['AbortError', 'Подготовка отменена', 'ABORTED'],
|
||||
]) {
|
||||
const signal = AbortSignal.abort(new DOMException('SECRET', name))
|
||||
const failures: { reason: string }[] = []
|
||||
await assert.rejects(
|
||||
prepareScreenPackage(
|
||||
{ server, gameId: 7, token: 'SECRET', signal, onRequestFailure: (f) => failures.push(f) },
|
||||
async (_input, init) => {
|
||||
init?.signal?.throwIfAborted()
|
||||
return Response.json({})
|
||||
},
|
||||
),
|
||||
new RegExp(`^Error: Описание игры: ${message}$`),
|
||||
)
|
||||
assert.ok(failures.every((f) => f.reason === reason))
|
||||
}
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user