This commit is contained in:
2026-10-18 03:11:10 +07:00
parent 8610f45a29
commit 3e2608eae3
23 changed files with 1460 additions and 302 deletions
+88 -8
View File
@@ -15,6 +15,10 @@ module.exports = async function onlineSmoke({
let version = 1
let offline = false
let polls = 0
let music = null
let holdTrack = false
let releaseTrack
let trackRequested = false
let currentCommand = 'SCREEN_COMMAND_PLAY'
let plan = { steps: [{ mode: 2 }], currentStep: 0 }
let planSaveFailure = false
@@ -29,6 +33,10 @@ module.exports = async function onlineSmoke({
for await (const chunk of req) chunks.push(chunk)
const body = chunks.length ? JSON.parse(Buffer.concat(chunks).toString()) : {}
const path = req.url
if (offline && path !== '/api/screens/state') {
res.destroy()
return
}
requests.push(path)
const send = (value, status = 200) => {
res.writeHead(status, { 'Content-Type': 'application/json' })
@@ -79,8 +87,17 @@ module.exports = async function onlineSmoke({
version++
return send({})
}
if (path === '/api/games/6/music') return send({})
if (path === '/api/files/intro.wav') {
if (path === '/api/games/6/music')
return send(music ? { state: music, gamePlaylistId: 1, playlists: [music.playlist] } : {})
if (
['/api/files/intro.wav', '/api/files/music-a.wav', '/api/files/music-b.wav'].includes(path)
) {
if (path.endsWith('music-b.wav') && holdTrack) {
trackRequested = true
await new Promise((resolve) => {
releaseTrack = resolve
})
}
assert.equal(req.headers.authorization, undefined)
res.writeHead(200, { 'Content-Type': 'audio/wav' })
return res.end(readFileSync(join(root, 'fixtures/audio.wav')))
@@ -95,6 +112,8 @@ module.exports = async function onlineSmoke({
return send({
state: {
gameID: 6,
music,
introAudio: 'intro.wav',
mode: remoteMode,
text: remoteText,
timerLabel,
@@ -176,11 +195,10 @@ module.exports = async function onlineSmoke({
'control target stays on local package despite server game selection',
)
assert.notEqual(selectedBeforeDownload, 'HTTP smoke')
await act({ action: 'download', gameId: 6 })
await act({ action: 'connect', gameId: 6 })
const packages = await evaluate('window.screenBridge.packages()')
const pkg = packages.find((p) => p.name === 'HTTP smoke')
assert.ok(pkg)
await evaluate(`window.screenBridge.selectPackage(${JSON.stringify(pkg.key)})`)
await poll(
() =>
evaluate(
@@ -188,7 +206,11 @@ module.exports = async function onlineSmoke({
),
'control target follows selected local package',
)
await act({ action: 'connect' })
await poll(
async () => (await evaluate('window.screenBridge.onlineState()')).connection === 'connected',
'connected with output closed',
)
assert.equal((await state()).outputOpen, false)
await evaluate(`window.screenBridge.show(${displayId})`)
await poll(
async () => (await evaluate('window.screenBridge.onlineState()')).connection === 'connected',
@@ -201,7 +223,10 @@ module.exports = async function onlineSmoke({
),
'server sound assignment shown in UI',
)
assert.equal((await state()).channels.main.desired, 'stopped')
await poll(
async () => (await state()).channels.main.desired === 'playing',
'initial server state applied',
)
version++
await poll(
async () => (await state()).channels.main.status === 'playing',
@@ -229,7 +254,10 @@ module.exports = async function onlineSmoke({
async () => (await evaluate('window.screenBridge.onlineState()')).connection === 'connected',
'reconnect baseline',
)
assert.equal((await state()).channels.main.desired, 'playing')
await poll(
async () => (await state()).channels.main.status === 'stopped',
'reconnect applies current stop',
)
version++
await poll(async () => (await state()).channels.main.status === 'stopped', 'new remote stop')
const { powerMonitor } = require('electron')
@@ -241,7 +269,10 @@ module.exports = async function onlineSmoke({
const beforeReopenPolls = polls
await evaluate(`window.screenBridge.show(${displayId})`)
await poll(() => polls > beforeReopenPolls, 'post-incident baseline')
assert.equal((await state()).channels.main.desired, 'stopped')
await poll(
async () => (await state()).channels.main.status === 'playing',
'reopen applies server play',
)
version++
await poll(
async () => (await state()).channels.main.status === 'playing',
@@ -261,6 +292,55 @@ module.exports = async function onlineSmoke({
true,
)
}
// Новые серверные плейлисты автоматически сохраняются на диск до включения.
music = {
stateVersion: '1',
playlist: {
ID: 1,
name: 'Автомузыка',
tracks: [{ ID: 41, name: 'Первый', filename: 'music-a.wav' }],
},
trackIndex: 0,
playback: 2,
volume: 40,
loop: true,
}
await poll(
async () => (await state()).channels.music.status === 'playing',
'initial music automatically cached',
)
const oldMusic = (await state()).channels.music.source.url
holdTrack = true
music = {
...music,
stateVersion: '2',
playlist: {
...music.playlist,
tracks: [...music.playlist.tracks, { ID: 42, name: 'Новый', filename: 'music-b.wav' }],
},
trackIndex: 1,
}
await poll(() => trackRequested, 'missing server track download starts')
assert.equal((await state()).channels.music.source.url, oldMusic)
remoteMode = 8
remoteText = 'Текст не ждёт музыку'
currentCommand = 0
version++
await poll(
async () => (await state()).scene.text === remoteText,
'scene independent from pending music',
)
holdTrack = false
releaseTrack()
await poll(
async () =>
(await state()).channels.music.trackIndex === 1 &&
(await state()).channels.music.status === 'playing',
'downloaded track plays from disk',
)
assert.match((await state()).channels.music.source.url, /^screen-app:/)
assert.notEqual((await state()).channels.music.source.url, oldMusic)
console.log('SCREEN_LIVE_MATERIALS_SMOKE_PASS')
// Настоящий редактор: черновик, ошибка сохранения, порядок и переходы.
const clickPlan = async (label) => {
await poll(