Files
evening_detective_screen/scripts/smoke.cjs
T
2026-10-17 18:54:57 +07:00

196 lines
7.5 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
const assert = require('node:assert/strict')
const { app, BrowserWindow, screen } = require('electron')
const root = require('node:path').resolve(__dirname, '..')
app.setAppPath(root)
app.setPath(
'userData',
require('node:fs').mkdtempSync(
require('node:path').join(require('node:os').tmpdir(), 'screen-smoke-'),
),
)
const delay = (ms) => new Promise((r) => setTimeout(r, ms))
let targetDisplay
let isSyntheticDisplay = false
const boundsBeforeFullscreen = new Map()
const fullscreenEntered = new Set()
app.on('browser-window-created', (_event, window) => {
window.on('enter-full-screen', () => fullscreenEntered.add(window.id))
let requestedBounds
const setBounds = window.setBounds.bind(window)
window.setBounds = (bounds, ...args) => {
requestedBounds = { ...bounds }
return setBounds(bounds, ...args)
}
const setFullScreen = window.setFullScreen.bind(window)
window.setFullScreen = (flag) => {
if (flag) boundsBeforeFullscreen.set(window.id, requestedBounds)
return setFullScreen(flag)
}
})
app.whenReady().then(() => {
const original = screen.getAllDisplays.bind(screen)
const displays = original()
targetDisplay = displays.find((display) => display.id !== screen.getPrimaryDisplay().id)
if (!targetDisplay) {
isSyntheticDisplay = true
targetDisplay = {
...displays[0],
id: 424242,
label: 'Synthetic test display',
bounds: { x: 1280, y: 0, width: 1280, height: 720 },
size: { width: 1280, height: 720 },
}
screen.getAllDisplays = () => [...original(), targetDisplay]
}
})
require(root + '/dist-electron/electron/main.js')
async function poll(check, label) {
for (let i = 0; i < 150; i++) {
const result = await check()
if (result) return result
await delay(100)
}
throw new Error('Timeout: ' + label)
}
app.whenReady().then(async () => {
try {
const control = await poll(() => BrowserWindow.getAllWindows()[0], 'control')
control.webContents.on('console-message', (_event, details) =>
console.log('renderer:', details.message),
)
await poll(
async () =>
!control.webContents.isLoading() &&
(await control.webContents.executeJavaScript(
'!!window.screenBridge && !!document.querySelector("h1")',
)),
'control UI',
)
const evaluate = (s) => control.webContents.executeJavaScript(s)
assert.equal(await evaluate('typeof window.require'), 'undefined')
await evaluate(`window.screenBridge.show(${targetDisplay.id})`)
const output = await poll(
() => BrowserWindow.getAllWindows().find((w) => w !== control),
'output',
)
output.webContents.on('console-message', (_event, details) =>
console.log('output:', details.message),
)
await poll(
async () =>
!output.webContents.isLoading() &&
(await output.webContents.executeJavaScript(
'document.querySelector("video")?.readyState >= 1',
)),
'metadata',
)
if (process.platform === 'linux')
assert.equal(app.commandLine.getSwitchValue('ozone-platform'), 'x11')
await poll(() => boundsBeforeFullscreen.has(output.id), 'output fullscreen requested')
assert.deepEqual(boundsBeforeFullscreen.get(output.id), targetDisplay.bounds)
if (!isSyntheticDisplay) {
await poll(() => fullscreenEntered.has(output.id), 'output entered fullscreen')
assert.ok(output.isFullScreen())
assert.equal(screen.getDisplayMatching(output.getBounds()).id, targetDisplay.id)
}
const range = await output.webContents.executeJavaScript(
`fetch('screen-app://app/media/video', {headers: {Range: 'bytes=100-199'}}).then(async r => ({status:r.status, size:(await r.arrayBuffer()).byteLength, range:r.headers.get('content-range')}))`,
)
assert.equal(range.status, 206)
assert.equal(range.size, 100)
const command = async (id, action, media = 'audio', position = 0) => {
await evaluate(
`window.screenBridge.command(${JSON.stringify({ id, action, media, position })})`,
)
return poll(async () => {
const s = await evaluate('window.screenBridge.state()')
if (s.status === 'error') throw new Error(s.error)
return s.status !== 'pending' && s.command.id === id && s
}, id)
}
await evaluate(
`Array.from(document.querySelectorAll('button')).find(b => b.textContent.includes('Пуск с начала')).click()`,
)
await poll(async () => {
const state = await evaluate('window.screenBridge.state()')
if (state.status === 'error') throw new Error(state.error)
return state.status === 'playing'
}, 'computer UI play')
assert.equal((await command('audio-play', 'play')).status, 'playing')
assert.equal((await command('audio-pause', 'pause')).status, 'paused')
assert.equal((await command('audio-stop', 'stop')).status, 'stopped')
assert.equal((await command('video-play', 'play', 'video')).status, 'playing')
await command('video-seek', 'seek', 'video', 30)
const position = await output.webContents.executeJavaScript(
'document.querySelector("video").currentTime',
)
assert.ok(position >= 29.9 && position < 35, 'video seek actual position')
await command('video-pause', 'pause', 'video')
assert.equal(
await output.webContents.executeJavaScript('document.querySelector("audio").paused'),
true,
)
assert.equal(
await output.webContents.executeJavaScript('document.querySelector("video").paused'),
true,
)
await assert.rejects(
output.webContents.executeJavaScript(
`window.screenBridge.command({id:'forbidden', action:'play', media:'audio', position:0})`,
),
)
assert.equal(
await evaluate("document.body.textContent.includes('Телефон по локальной сети')"),
false,
)
assert.deepEqual(Object.keys(await evaluate('window.screenBridge.host()')), ['displays'])
assert.equal(await evaluate('typeof window.screenBridge.lan'), 'undefined')
assert.equal(await evaluate('typeof window.screenBridge.approve'), 'undefined')
output.close()
await evaluate(`window.screenBridge.show(${targetDisplay.id})`)
const reopened = await poll(
() => BrowserWindow.getAllWindows().find((w) => w !== control),
'reopened output',
)
await poll(
async () =>
!reopened.webContents.isLoading() &&
(await reopened.webContents.executeJavaScript('!!document.querySelector("video")')),
'reopened ready',
)
await poll(() => boundsBeforeFullscreen.has(reopened.id), 'reopened fullscreen requested')
assert.deepEqual(boundsBeforeFullscreen.get(reopened.id), targetDisplay.bounds)
if (!isSyntheticDisplay) {
await poll(() => fullscreenEntered.has(reopened.id), 'reopened entered fullscreen')
assert.ok(reopened.isFullScreen())
assert.equal(screen.getDisplayMatching(reopened.getBounds()).id, targetDisplay.id)
}
assert.equal(
await reopened.webContents.executeJavaScript('document.querySelector("video").paused'),
true,
)
console.log(
'SCREEN_SMOKE_PASS',
JSON.stringify({
range,
display: {
id: targetDisplay.id,
bounds: targetDisplay.bounds,
synthetic: isSyntheticDisplay,
},
seek: position,
samples: (await evaluate('window.screenBridge.state()')).samples,
electron: process.versions.electron,
}),
)
app.exit(0)
} catch (error) {
console.error('SCREEN_SMOKE_FAIL', error)
app.exit(1)
}
})
setTimeout(() => {
console.error('Global timeout')
app.exit(1)
}, 45000)