This commit is contained in:
2026-10-18 04:51:12 +07:00
parent 41d3e8ac5e
commit 7a97b9b506
13 changed files with 604 additions and 182 deletions
+66 -3
View File
@@ -201,7 +201,7 @@ test('отказы API и некорректный JSON не выдают час
prepareScreenPackage({ server, gameId: 7, token: 'SECRET' }, async () => {
throw new Error('SECRET')
}),
/^Error: Описание игры: Сервер недоступен$/,
/^Error: Описание игры · GET \/api\/games\/7: Сервер недоступен \[NETWORK\]$/,
)
})
@@ -261,7 +261,7 @@ test('сетевая ошибка называет запрос и журнал
},
),
new RegExp(
`^Error: ${suffix === '/music' ? 'Музыка игры' : suffix === '/screen-plan' ? 'План экранов' : 'Описание игры'}: Не удалось определить адрес сервера$`,
`^Error: ${suffix === '/music' ? 'Музыка игры' : suffix === '/screen-plan' ? 'План экранов' : 'Описание игры'} · GET /api/games/7${suffix}: Не удалось определить адрес сервера \\[ENOTFOUND\\]$`,
),
)
assert.deepEqual(failures, [{ path: `/api/games/{id}${suffix}`, reason: 'ENOTFOUND' }])
@@ -298,8 +298,71 @@ test('таймаут и отмена подготовки различаются
return Response.json({})
},
),
new RegExp(`^Error: Описание игры: ${message}$`),
new RegExp(`^Error: Описание игры · GET /api/games/7: ${message} \\[${reason}\\]$`),
)
assert.ok(failures.every((f) => f.reason === reason))
}
})
test('ошибка структуры описания называет запрос, поле и тип, не раскрывая значения', async () => {
for (const [badValue, expectedType] of [
[null, 'null'],
[undefined, 'поле отсутствует'],
[[], 'массив'],
['SECRET', 'string'],
] as const) {
const data = fixture()
;(data.game.game.scenario as Record<string, unknown>).story = badValue
await assert.rejects(
prepareScreenPackage({ server, gameId: 7, token: 'TOKEN-SECRET' }, async (input) =>
Response.json(
String(input).endsWith('/music')
? data.music
: String(input).endsWith('/screen-plan')
? data.plan
: data.game,
),
),
(error) => {
assert.ok(error instanceof Error)
assert.match(error.message, /Описание игры · GET \/api\/games\/7/)
assert.ok(error.message.includes('поле game.scenario.story'))
assert.ok(error.message.includes(`получено ${expectedType}`))
assert.ok(!error.message.includes('SECRET'))
return true
},
)
}
})
test('ошибки элементов плана и треков сохраняют индекс и источник ответа', async () => {
const plan = fixture()
plan.plan.plan.steps[0]!.mode = 'SECRET'
const music = fixture()
;(music.music.playlists[1]!.tracks[0] as Record<string, unknown>).filename = {
password: 'SECRET',
}
for (const [data, field, path] of [
[plan, 'plan.steps[0].mode', '/screen-plan'],
[music, 'music.playlists[1].tracks[0].filename', '/music'],
] as const) {
await assert.rejects(
prepareScreenPackage({ server, gameId: 7, token: 'SECRET' }, async (input) =>
Response.json(
String(input).endsWith('/music')
? data.music
: String(input).endsWith('/screen-plan')
? data.plan
: data.game,
),
),
(error) => {
assert.ok(error instanceof Error)
assert.ok(error.message.includes(`/api/games/7${path}:`))
assert.ok(error.message.includes(`поле ${field}`))
assert.ok(!error.message.includes('SECRET'))
return true
},
)
}
})