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)