Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ if [ "$platform" = "Darwin" ]; then
rm -rf "$appDir"
mkdir -p "$appDir"
cp "$elecDir/main.js" "$appDir/"
cp "$elecDir/preload.js" "$appDir/"
cp "$elecDir/package.json" "$appDir/"
cp -R "$elecDir/web" "$appDir/web"

Expand Down Expand Up @@ -157,10 +158,12 @@ else
appDir="$outDir/resources/app"
mkdir -p "$appDir"
cp "$elecDir/main.js" "$appDir/"
cp "$elecDir/preload.js" "$appDir/"
cp "$elecDir/package.json" "$appDir/"
cp -r "$elecDir/web" "$appDir/web"
mv "$outDir/electron" "$outDir/CuaTestHarness.Electron"
chmod +x "$outDir/CuaTestHarness.Electron"
mv "$outDir/electron" "$outDir/CuaTestHarness.Electron.bin"
cp "$elecDir/launcher-linux.sh" "$outDir/CuaTestHarness.Electron"
chmod +x "$outDir/CuaTestHarness.Electron" "$outDir/CuaTestHarness.Electron.bin"

cat <<EOF
[OK] Staged: $outDir/CuaTestHarness.Electron
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,20 @@
// tool routes through CDP when --remote-debugging-port is set, so we
// expose one here on a configurable port.

const { app, BrowserWindow } = require('electron');
const { app, BrowserWindow, ipcMain } = require('electron');
const fs = require('fs');
const http = require('http');
const path = require('path');
const sentinelMode = process.env.CUA_E2E_SENTINEL === '1';
const fixtureJournalUrl = process.env.CUA_E2E_FIXTURE_JOURNAL_URL || '';
const sentinelJournalPath = process.env.CUA_E2E_SENTINEL_JOURNAL || '';
if (process.env.CUA_E2E_USER_DATA_DIR) {
app.setPath('userData', process.env.CUA_E2E_USER_DATA_DIR);
}
if (process.platform === 'linux' && process.env.WAYLAND_DISPLAY) {
app.commandLine.appendSwitch('ozone-platform', 'wayland');
app.commandLine.appendSwitch('enable-features', 'UseOzonePlatform');
}

// Validate CUA_ELECTRON_CDP_PORT before forwarding to Chromium —
// remote-debugging-port=0 means "pick an ephemeral port" which would
Expand All @@ -20,19 +32,57 @@ if (!Number.isInteger(cdpPortNum) || cdpPortNum < 1 || cdpPortNum > 65535) {
const CDP_PORT = String(cdpPortNum);
app.commandLine.appendSwitch('remote-debugging-port', CDP_PORT);

ipcMain.on('cua-e2e-config', event => {
event.returnValue = { journalUrl: fixtureJournalUrl, sentinelMode };
});

ipcMain.on('cua-e2e-fixture-state', (_event, state) => {
if (!fixtureJournalUrl) return;
const body = JSON.stringify(state);
const request = http.request(fixtureJournalUrl, {
method: 'POST',
headers: {
'Content-Type': 'text/plain',
'Content-Length': Buffer.byteLength(body),
},
});
request.on('error', () => {});
request.end(body);
});

ipcMain.on('cua-e2e-sentinel-event', (_event, entry) => {
if (!sentinelMode || !sentinelJournalPath) return;
fs.appendFileSync(sentinelJournalPath, `${JSON.stringify(entry)}\n`, 'utf8');
});

let mainWindow;

function createWindow() {
const fixedTitle = `CuaTestHarness Electron [cdp=${CDP_PORT}]`;
const fixedTitle = sentinelMode
? `CuaTestHarness Sentinel [cdp=${CDP_PORT}]`
: `CuaTestHarness Electron [cdp=${CDP_PORT}]`;
mainWindow = new BrowserWindow({
width: 940,
height: 780,
width: sentinelMode ? 1280 : 940,
height: sentinelMode ? 900 : 780,
// Keep the normal fixture inside virtual desktops whose window manager
// has no persisted placement policy (notably Openbox under Xvfb).
x: sentinelMode ? 0 : 120,
y: sentinelMode ? 0 : 120,
title: fixedTitle,
show: false,
// Map the normal harness immediately. Xvfb/Openbox can enumerate a
// deferred BrowserWindow while never painting it into the root desktop.
// The sentinel stays hidden until it has maximized and claimed focus.
show: !sentinelMode,
// A floating-level macOS window is omitted by cua-driver's deliberate
// layer-0 top-level window contract. Foreground + maximized is sufficient
// for occlusion there and lets an unexpected target raise remain visible.
alwaysOnTop: sentinelMode && process.platform !== 'darwin',
autoHideMenuBar: true,
webPreferences: {
nodeIntegration: false,
contextIsolation: true,
sandbox: !sentinelMode,
preload: path.join(__dirname, 'preload.js'),
},
});

Expand Down Expand Up @@ -66,7 +116,21 @@ function createWindow() {
// our fixedTitle and break the harness-window-discovery test.
if (mainWindow && !mainWindow.isDestroyed()) {
mainWindow.setTitle(fixedTitle);
mainWindow.showInactive();
if (sentinelMode) {
if (process.platform !== 'darwin') {
mainWindow.setAlwaysOnTop(true);
}
mainWindow.maximize();
mainWindow.show();
mainWindow.focus();
} else {
// Xvfb/Openbox can keep a showInactive window inspectable through
// AT-SPI while never mapping it onto the captured root desktop.
// Show it normally; background cells subsequently foreground the
// occlusion sentinel before taking their desktop snapshot.
mainWindow.show();
mainWindow.focus();
}
}
})
.catch(err => {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
const { contextBridge, ipcRenderer } = require('electron');

const fixtureConfig = ipcRenderer.sendSync('cua-e2e-config');
const fixtureJournalUrl = fixtureConfig.journalUrl || '';

contextBridge.exposeInMainWorld('cuaE2E', {
journalUrl: fixtureJournalUrl,
publishFixtureState(state) {
if (fixtureJournalUrl) ipcRenderer.send('cua-e2e-fixture-state', state);
},
});

const sentinelMode = fixtureConfig.sentinelMode;

function record(kind, details = {}) {
if (!sentinelMode) return;
ipcRenderer.send('cua-e2e-sentinel-event', {
kind,
at_ms: Date.now(),
...details,
});
}

if (sentinelMode) {
window.addEventListener('DOMContentLoaded', () => {
document.body.innerHTML = `
<main style="min-height:100vh;background:#146c43;color:white;display:grid;place-content:center;text-align:center;font:24px system-ui">
<h1 style="font-size:52px;margin:0 0 16px">CUA OCCLUSION SENTINEL</h1>
<p>CUA_OCCLUSION_SENTINEL_v1</p>
</main>
`;
record('ready');
});
window.addEventListener('focus', () => record('focus'));
window.addEventListener('blur', () => record('blur'));
window.addEventListener('keydown', event =>
record('keydown', { key: event.key, code: event.code })
);
window.addEventListener('pointerdown', event =>
record('pointerdown', { button: event.button, x: event.clientX, y: event.clientY })
);
window.addEventListener('wheel', event =>
record('wheel', { delta_x: event.deltaX, delta_y: event.deltaY })
);
window.addEventListener('contextmenu', event =>
record('contextmenu', { x: event.clientX, y: event.clientY })
);
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,14 @@
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]

fn main() {
let journal_url = std::env::var("CUA_E2E_FIXTURE_JOURNAL_URL").unwrap_or_default();
let journal_plugin = tauri::plugin::Builder::<tauri::Wry, ()>::new("e2e-journal")
.js_init_script(format!(
"window.__CUA_E2E_FIXTURE_JOURNAL_URL = {journal_url:?};"
))
.build();
tauri::Builder::default()
.plugin(journal_plugin)
.run(tauri::generate_context!())
.expect("error while running CuaTestHarness.Tauri");
}
Loading