repositories / dotfiles
dotfiles
bugabingas dorkfiles
owned by admin
quickshell/nuguland/ui-test.test.mjs
Rawimport assert from 'node:assert/strict';
import { spawn, spawnSync } from 'node:child_process';
import { existsSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from 'node:fs';
import { createServer } from 'node:net';
import { tmpdir } from 'node:os';
import { join } from 'node:path';
import test from 'node:test';
import { runInNewContext } from 'node:vm';
import { assertCleanLog, assertNiriLog, assertPureService, assertSafeCapture, captureUiFailure, childEnvironment, finishUiRun, replayRequest, stopChild } from './ui-test.mjs';
import { assertSubscription, pngSize } from './test-fixtures/ui/niri-integration.mjs';
import { taskOverlayFixtures } from './test-fixtures/ui/tasks.mjs';
test('named replay defaults to all and rejects invalid selections before execution', () => {
assert.deepEqual(replayRequest([]), { version: 1, fixture: 'all', command: 'just ui-test all' });
for (const fixture of ['all', 'controls', 'popouts', 'privilege', 'noko', 'niri', 'tasks']) {
assert.deepEqual(replayRequest([fixture]), { version: 1, fixture, command: `just ui-test ${fixture}` });
}
for (const args of [[''], ['unknown'], ['../controls'], ['all', 'noko'], ['--help']]) {
assert.throws(() => replayRequest(args), /usage: just ui-test/);
}
});
test('task geometry and service overlays remain explicit and isolated', () => {
for (const size of ['1366x768', '2560x1440'])
assert.deepEqual(replayRequest(['tasks', size]), { version: 1, fixture: 'tasks', size, command: `just ui-test tasks ${size}` });
for (const args of [['tasks', '0x0'], ['tasks', '../host'], ['all', '1366x768'], ['tasks', '1366x768', 'extra']])
assert.throws(() => replayRequest(args));
assert.equal(new Set(taskOverlayFixtures.map(row => row.target)).size, taskOverlayFixtures.length);
for (const { source, target } of taskOverlayFixtures) {
assert.match(source, /^test-fixtures\/ui\/(?:task-)?services\/\w+\.qml$/);
assert.match(target, /^\w+\.qml$/);
assertPureService(readFileSync(source, 'utf8'));
}
const source = readFileSync('test-fixtures/ui/tasks.qml', 'utf8');
assert.match(source, /N\.Bar\s*\{/);
assert.match(source, /hasInput.*networkInput\.text\.length > 0/);
assert.match(source, /knownDraft.*receivedKnownDraft/);
assert.doesNotMatch(source, /\"(?:text|draft|passphrase)\":\s*(?:networkInput|notificationInput)\.text/);
const runner = readFileSync('ui-test.mjs', 'utf8');
assert.match(runner, /for \(const \[target, text\] of taskOriginals\)[\s\S]*?await prepareIntegration\(\)/);
});
test('subscription termination requires an exact native command and direct QML parent', () => {
const command = '/usr/bin/niri\0msg\0--json\0event-stream\0';
assert.doesNotThrow(() => assertSubscription(42, 30, 'Name:\tniri\nPPid:\t30\n', command));
for (const pid of [0, 1, -1, null, '42', 42.5]) {
assert.throws(() => assertSubscription(pid, 30, 'PPid:\t30\n', command));
}
for (const [parent, status, args] of [
[1, 'PPid:\t1\n', command], [30, 'PPid:\t99\n', command],
[30, 'Name:\tniri\n', command], [30, 'PPid:\t30\n', '/usr/bin/niri\0'],
[30, 'PPid:\t30\n', '/other/niri\0msg\0--json\0event-stream\0'],
[30, 'PPid:\t30\n', command.replace('event-stream', 'outputs')],
[30, 'PPid:\t30\n', command + 'extra\0']
]) assert.throws(() => assertSubscription(42, parent, status, args));
});
test('capture dimensions reject missing, non-PNG, truncated and zero-size headers', () => {
const bytes = Buffer.alloc(40);
Buffer.from([137, 80, 78, 71, 13, 10, 26, 10]).copy(bytes);
bytes.write('IHDR', 12);
bytes.writeUInt32BE(1280, 16);
bytes.writeUInt32BE(720, 20);
assert.deepEqual(pngSize(bytes), { width: 1280, height: 720 });
for (const invalid of [Buffer.alloc(0), bytes.subarray(0, 32), Buffer.alloc(40), Buffer.from(bytes).fill(0, 16, 20), Buffer.from(bytes).fill(0, 20, 24)]) {
assert.throws(() => pngSize(invalid));
}
});
test('niri fixture has a pure vault sink and the real Bar/Niri/Screenshots route', () => {
assertPureService(readFileSync('test-fixtures/ui/niri-integration-vault.qml', 'utf8'));
const fixture = readFileSync('test-fixtures/ui/niri-integration.qml', 'utf8');
for (const type of ['Bar', 'Niri', 'Screenshots']) assert(fixture.includes(`N.${type} {`));
assert.match(fixture, /function fixtureOutputs\(enabled: bool\)/);
const runner = readFileSync('ui-test.mjs', 'utf8');
assert.match(runner, /const integration = replay.fixture === 'all' \|\| replay.fixture === 'niri'/);
assert.match(runner, /await runNiriIntegration\(/);
});
test('failure screenshots allow masked input but never revealed input or unknown auth state', () => {
assert.doesNotThrow(() => assertSafeCapture({ auth: { visible: true, hasInput: true, inputMasked: true } }));
assert.doesNotThrow(() => assertSafeCapture({ auth: { visible: true, hasInput: false, inputMasked: false } }));
assert.throws(() => assertSafeCapture({ auth: { visible: true, hasInput: true, inputMasked: false } }), /unmasked input/);
assert.throws(() => assertSafeCapture({ auth: { visible: true } }), /unmasked input/);
assert.throws(() => assertSafeCapture(null), /snapshot unavailable/);
});
test('failure evidence retains the original error, named phase and last safe snapshot', async () => {
const calls = [];
const snapshot = { auth: { visible: true, hasInput: true, inputMasked: true } };
const error = new Error('original assertion');
const record = await captureUiFailure(error, {
evidence: '/evidence', fixture: 'privilege', phase: 'privilege', snapshot,
screenshot: async name => { calls.push(name); return '/evidence/failure.png'; },
write: (path, text) => calls.push([path, JSON.parse(text)])
});
assert.equal(record.error, error.stack);
assert.equal(record.fixture, 'privilege');
assert.equal(record.phase, 'privilege');
assert.deepEqual(record.snapshot, snapshot);
assert.equal(record.screenshot, '/evidence/failure.png');
assert.deepEqual(record.captureErrors, []);
assert.equal(calls[0], 'failure');
assert.deepEqual(calls[1], ['/evidence/failure.json', record]);
const failedCapture = await captureUiFailure(error, {
evidence: '/evidence', fixture: 'all', phase: 'controls', snapshot,
screenshot: async () => { throw new Error('capture socket gone'); }, write: () => {}
});
assert.equal(failedCapture.error, error.stack);
assert.equal(failedCapture.screenshot, null);
assert.match(failedCapture.captureErrors[0], /capture socket gone/);
assert.deepEqual(failedCapture.snapshot, snapshot);
});
test('runtime gate is captured before teardown; all children and complete logs are still checked', async () => {
for (const original of [null, new Error('original interaction')]) {
const calls = [];
const diagnostic = new Error('WARN private login1');
await assert.rejects(finishUiRun(original, {
children: ['weston', 'niri', 'fixture'],
checkLogs: () => { calls.push('logs'); throw diagnostic; },
capture: async error => { calls.push(['capture', error]); },
stop: async child => { calls.push(['stop', child]); }
}), error => error === (original || diagnostic));
assert.deepEqual(calls, ['logs', ['capture', original || diagnostic], ['stop', 'fixture'], ['stop', 'niri'], ['stop', 'weston'], 'logs']);
}
});
test('clean completion checks full logs on both sides of teardown without failure capture', async () => {
const calls = [];
const children = ['weston', 'niri'];
await finishUiRun(null, {
children,
checkLogs: () => calls.push('logs'),
capture: async () => assert.fail('unexpected failure capture'),
stop: async child => calls.push(child)
});
assert.deepEqual(calls, ['logs', 'niri', 'weston', 'logs']);
assert.deepEqual(children, ['weston', 'niri']);
});
test('capture and teardown errors cannot replace the original error or skip sibling cleanup', async () => {
const original = new Error('original assertion');
const stopped = [];
const secondary = [];
await assert.rejects(finishUiRun(original, {
children: ['weston', 'niri', 'fixture'],
checkLogs: () => {},
capture: async () => { throw new Error('evidence unwritable'); },
stop: async child => { stopped.push(child); if (child === 'fixture') throw new Error('teardown error'); },
report: error => secondary.push(error.message)
}), error => error === original);
assert.deepEqual(stopped, ['fixture', 'niri', 'weston']);
assert.deepEqual(secondary, ['evidence unwritable', 'teardown error']);
});
test('diagnostics produced only during teardown still fail the run', async () => {
const diagnostic = new Error('ERROR during shutdown');
let stopped = false;
let captured;
await assert.rejects(finishUiRun(null, {
children: ['niri'],
checkLogs: () => { if (stopped) throw diagnostic; },
capture: async error => { captured = error; },
stop: async () => { stopped = true; }
}), error => error === diagnostic);
assert.equal(captured, diagnostic);
});
test('fixture snapshots serialize predicates, never editable contents', () => {
const controls = readFileSync('ui-test.qml', 'utf8');
assert(!/query: root\.query|text: field\.text/.test(controls));
assert.match(controls, /queryMatchesInput: root\.query === field\.text/);
const refactor = readFileSync('test-fixtures/ui/refactor.qml', 'utf8');
assert.match(refactor, /child\.echoMode === undefined/);
assert.match(refactor, /hasInput: input \? input\.text\.length > 0 : false/);
assert.match(refactor, /inputMasked: input \? input\.echoMode === TextInput\.Password : false/);
});
test('snapshot predicates and visual-text selection redact hostile editable values', () => {
const sentinel = 'fixture-only\"\\nhttps://private.invalid/account';
const controls = readFileSync('ui-test.qml', 'utf8');
const body = controls.match(/function snapshot\(\): string \{([\s\S]*?)\n \}/)[1];
const field = { text: sentinel, input: {} };
const state = JSON.parse(runInNewContext(`(function () { ${body} })()`, {
root: { query: sentinel, rect: () => ({ x: 1, y: 2, width: 3, height: 4 }) },
field, window: {}, mute: {}, slider: { Accessible: {} }, surface: {},
actionCard: {}, nestedAction: {}, iconAction: { Accessible: {} }, disabledAction: {},
longAction: {}, iconField: { input: { text: sentinel } }
}));
assert.equal(state.queryMatchesInput, true);
assert.equal(state.queryIsHeadphones, false);
assert(!JSON.stringify(state).includes('fixture-only'));
const refactor = readFileSync('test-fixtures/ui/refactor.qml', 'utf8');
const visibleText = refactor.match(/function visibleText\(item: var, window: var\): var \{([\s\S]*?)\n \}/)[1];
for (const echoMode of [0, 1, 2, 3]) {
const rows = runInNewContext(`(function (item, window) { ${visibleText} })(null, null)`, {
tree: () => [{ visible: true, font: {}, text: sentinel, echoMode }, { visible: true, font: {}, text: 'safe label' }],
rect: () => ({ x: 1, y: 2, width: 3, height: 4 })
});
assert.equal(rows.length, 1);
assert.equal(rows[0].text, 'safe label');
assert(!JSON.stringify(rows).includes('fixture-only'));
}
});
test('input targets must be real sockets inside the owned runtime', async () => {
const runtime = mkdtempSync(join(tmpdir(), 'ui-boundary-'));
const outside = mkdtempSync(join(tmpdir(), 'ui-parent-'));
const servers = [];
async function socket(path) {
const server = createServer();
await new Promise((resolve, reject) => {
server.once('error', reject);
server.listen(path, resolve);
});
servers.push(server);
return path;
}
try {
const display = await socket(join(runtime, 'wayland-1'));
const ipc = await socket(join(runtime, 'niri.wayland-1.42.sock'));
const parent = await socket(join(outside, 'wayland-0'));
const weston = await socket(join(runtime, 'weston-headless'));
const env = childEnvironment(runtime, display, ipc);
assert.equal(env.WAYLAND_DISPLAY, display);
assert.equal(env.NIRI_SOCKET, ipc);
assert.equal(env.XDG_RUNTIME_DIR, runtime);
assert.throws(() => childEnvironment(runtime, parent, ipc), /refusing non-child socket/);
assert.throws(() => childEnvironment(runtime, weston, ipc), /regular expression/);
const file = join(runtime, 'wayland-2');
writeFileSync(file, 'not a socket');
assert.throws(() => childEnvironment(runtime, file, ipc), /must be a socket/);
assert.throws(() => childEnvironment(runtime, ipc, display), /regular expression/);
} finally {
for (const server of servers) await new Promise(resolve => server.close(resolve));
rmSync(runtime, { recursive: true });
rmSync(outside, { recursive: true });
}
});
test('runtime diagnostics fail rather than being filtered or downgraded', () => {
assert.doesNotThrow(() => assertCleanLog('INFO: Configuration Loaded\n'));
for (const diagnostic of ['WARN: unresolved binding', 'WARNING: unresolved binding', 'warning: deprecated API', 'Could not bind', 'failed to load', 'ERROR: creation failed', 'ReferenceError: missing', 'TypeError: wrong value', 'binding loop detected', 'Error parsing file']) {
assert.throws(() => assertCleanLog(diagnostic));
}
});
const niriRecord = (level, source, message) => `2026-09-06T14:51:45.642004Z ${level} ${source}: ${message}\n`;
const softwareFallback = niriRecord('DEBUG', 'niri::backend::winit', 'failed building default dmabuf feedback, falling back to v3: error getting EGL device render node\n\nCaused by:\n None of the following EGL extensions is supported by the underlying EGL implementation, at least one is required: ["EGL_EXT_device_drm"]');
const failedDestination = niriRecord('DEBUG', 'niri::niri', 'saving screenshot to "/evidence/missing-directory/native-failure.png"');
const nativeWriteWarning = niriRecord('WARN', 'niri::niri', 'error saving screenshot image: Os { code: 2, kind: NotFound, message: "No such file or directory" }');
test('only the exact Niri software fallback at DEBUG is a sandbox diagnostic exception', () => {
assert.deepEqual(assertNiriLog(''), { softwareFallbacks: 0, expectedWriteFailures: 0 });
assert.deepEqual(assertNiriLog(softwareFallback), { softwareFallbacks: 1, expectedWriteFailures: 0 });
assert.deepEqual(assertNiriLog(softwareFallback.replace('DEBUG', '\x1b[34mDEBUG\x1b[0m')), { softwareFallbacks: 1, expectedWriteFailures: 0 });
for (const invalid of [
softwareFallback.replace('DEBUG', 'WARN'), softwareFallback.replace('DEBUG', 'ERROR'),
softwareFallback.replace('niri::backend::winit', 'niri::renderer'),
softwareFallback.replace('EGL_EXT_device_drm', 'EGL_other_extension'),
softwareFallback.replace('falling back to v3', 'aborting'),
softwareFallback + softwareFallback, softwareFallback + 'WARN: unrelated\n',
niriRecord('DEBUG', 'niri::backend::winit', 'failed to initialize renderer'),
niriRecord('WARN', 'niri::dbus::freedesktop_login1', 'service absent'),
niriRecord('WARN', 'niri::dbus::freedesktop_locale1', 'service absent')
]) assert.throws(() => assertNiriLog(invalid));
// Production/default log checking has no exceptions.
assert.throws(() => assertCleanLog(softwareFallback));
assert.throws(() => assertCleanLog(nativeWriteWarning));
});
test('native failed-write warning is required exactly once inside its deliberate action interval', () => {
const before = softwareFallback + niriRecord('INFO', 'niri', 'ready');
const interval = failedDestination + nativeWriteWarning;
const after = niriRecord('INFO', 'niri', 'stopped');
const expected = { start: before.length, end: before.length + interval.length };
assert.deepEqual(assertNiriLog(before + interval + after, expected), { softwareFallbacks: 1, expectedWriteFailures: 1 });
for (const body of [
'', failedDestination, nativeWriteWarning, interval + nativeWriteWarning,
interval + interval, interval.replace('WARN', 'ERROR'),
interval.replace('code: 2', 'code: 13'), interval.replace('NotFound', 'PermissionDenied'),
interval.replace('niri::niri: error', 'other::source: error'),
interval.replace('missing-directory', 'different-directory'),
failedDestination + niriRecord('INFO', 'niri', 'different action') + nativeWriteWarning,
interval + 'TypeError: unrelated failure\n'
]) assert.throws(() => assertNiriLog(before + body + after, { start: before.length, end: before.length + body.length }));
assert.throws(() => assertNiriLog(before + interval + after));
assert.throws(() => assertNiriLog(nativeWriteWarning + before + interval, { start: nativeWriteWarning.length + before.length, end: nativeWriteWarning.length + before.length + interval.length }));
assert.throws(() => assertNiriLog(before + interval + nativeWriteWarning, expected));
for (const range of [{ start: -1, end: 1 }, { start: 0, end: 1e9 }, { start: 1, end: 2 }, { start: 0.5, end: 1 }, { start: 0, end: 0 }])
assert.throws(() => assertNiriLog(interval, range));
});
test('native diagnostic exceptions apply only to the child compositor and fixtures precede its launch', () => {
const runner = readFileSync('ui-test.mjs', 'utf8');
assert.match(runner, /log === join\(evidence, 'niri.log'\)\) diagnostics = assertNiriLog\(text, expectedWriteFailure\)/);
assert.match(runner, /else assertCleanLog\(text\)/);
assert(runner.indexOf("await waitFor('private login/locale fixtures'") < runner.indexOf("const compositor = start('niri'"));
assert.match(runner, /Niri consumed private login\/locale properties/);
const fixture = readFileSync('test-fixtures/ui/session-bus.c', 'utf8');
assert.match(fixture, /sd_bus_set_address\(bus, address\)/);
assert.match(fixture, /strcmp\(address, getenv\("DBUS_SYSTEM_BUS_ADDRESS"\)\)/);
assert(!/SD_BUS_METHOD|SD_BUS_WRITABLE_PROPERTY|sd_bus_open_system/.test(fixture), 'fixture exports no mutation or implicit system bus access');
});
test('overlay service doubles are pure QtQuick Item state/functions without privileged APIs', () => {
for (const name of ['CalDav', 'Resources', 'Privilege', 'Noko', 'Niri', 'Audio', 'Network', 'Vault']) {
assertPureService(readFileSync(`test-fixtures/ui/services/${name}.qml`, 'utf8'));
}
for (const body of ['Process {}', 'FileView {}', 'PolkitAgent {}', 'PamContext {}', 'WorkerScript {}', 'function bad() { Qt.openUrlExternally("test"); }', 'function bad() { new XMLHttpRequest(); }', 'function bad() { fetch("test"); }', 'function bad() { eval("test"); }', 'function bad() { Quickshell.execDetached([]); }']) {
assert.throws(() => assertPureService(`import QtQuick\nItem { ${body} }`));
}
assert.throws(() => assertPureService('import QtQuick\nimport Quickshell.Io\nItem {}'));
assert.throws(() => assertPureService('import "../../"\nItem {}'));
});
test('fixture replacement reaps only its own process, including an uncooperative child', { timeout: 8000 }, async () => {
const sibling = spawn(process.execPath, ['-e', 'setInterval(() => {}, 1000)']);
try {
for (const ignoreTerm of [false, true]) {
const child = spawn(process.execPath, ['-e', `${ignoreTerm ? 'process.on("SIGTERM", () => {});' : ''} console.log("ready"); setInterval(() => {}, 1000);`]);
try {
await new Promise(resolve => child.stdout.once('data', resolve));
await stopChild(child);
assert.equal(child.signalCode, ignoreTerm ? 'SIGKILL' : 'SIGTERM');
assert.equal(sibling.exitCode, null);
assert.equal(sibling.signalCode, null);
await stopChild(child);
} finally {
await stopChild(child);
}
}
} finally {
await stopChild(sibling);
}
});
test('an unsuccessful spawn has nothing to reap', async () => {
const child = spawn('/nonexistent-nuguland-fixture-command');
await new Promise(resolve => child.once('error', resolve));
await stopChild(child);
});
test('invalid invocation and unsandboxed internal invocation fail before launching a compositor', () => {
for (const args of [['unexpected'], ['--inside'], ['controls', 'noko'], ['--inside', 'invalid']]) {
const result = spawnSync(process.execPath, ['ui-test.mjs', ...args], { encoding: 'utf8', env: { PATH: process.env.PATH }, timeout: 5000 });
assert.equal(result.status, 1);
assert.match(result.stderr, args.length === 1 && args[0] === '--inside' ? /internal mode requires sandbox/ : /usage: just ui-test/);
assert(!result.stdout.includes('evidence:'));
}
});
test('named selections reach the sandbox and its original failure evidence is never overwritten', () => {
const dir = mkdtempSync(join(tmpdir(), 'ui-replay-'));
try {
writeFileSync(join(dir, 'bwrap'), `#!${process.execPath}
const fs = require('node:fs');
const args = process.argv.slice(2);
const evidence = args[args.indexOf('/evidence') - 1];
fs.writeFileSync(evidence + '/failure.json', JSON.stringify({ error: 'original inner assertion', fixture: args.at(-1) }));
process.exit(7);
`, { mode: 0o755 });
for (const fixture of ['all', 'controls', 'popouts', 'privilege', 'noko', 'niri', 'tasks']) {
const result = spawnSync(process.execPath, ['ui-test.mjs', fixture], { env: { PATH: dir }, encoding: 'utf8', timeout: 5000 });
const evidence = result.stdout.match(/^evidence: (.+)$/m)?.[1];
assert(evidence, result.stderr);
try {
assert.equal(result.status, 1);
assert.deepEqual(JSON.parse(readFileSync(join(evidence, 'failure.json'), 'utf8')), { error: 'original inner assertion', fixture });
assert.deepEqual(JSON.parse(readFileSync(join(evidence, 'replay.json'), 'utf8')), { ...replayRequest([fixture]), phase: 'startup' });
const { command } = JSON.parse(readFileSync(join(evidence, 'command.json'), 'utf8'));
assert.deepEqual(command.slice(-2), ['--inside', fixture]);
assert(!existsSync(command[command.indexOf('/run/user/1000') - 1]));
} finally {
rmSync(evidence, { recursive: true });
}
}
} finally {
rmSync(dir, { recursive: true });
}
});
test('sandbox failure, spawn error, and interruption remove the owned runtime and fail', { timeout: 10_000 }, async () => {
const dir = mkdtempSync(join(tmpdir(), 'ui-lifecycle-'));
try {
for (const mode of ['failure', 'interrupt', 'stubborn', 'missing']) {
const executable = join(dir, 'bwrap');
if (mode === 'missing') rmSync(executable);
else writeFileSync(executable, `#!${process.execPath}\n${mode === 'failure' ? 'process.exit(7)' : `process.on("SIGTERM", () => { ${mode === 'stubborn' ? '' : 'process.exit(0)'} }); console.log("sandbox-ready"); setInterval(() => {}, 1000)`}\n`, { mode: 0o755 });
const child = spawn(process.execPath, ['ui-test.mjs'], {
env: { PATH: dir },
stdio: ['ignore', 'pipe', 'pipe']
});
let stdout = '';
let stderr = '';
child.stdout.on('data', data => {
stdout += data;
if (['interrupt', 'stubborn'].includes(mode) && stdout.includes('sandbox-ready')) child.kill('SIGINT');
});
child.stderr.on('data', data => { stderr += data; });
const code = await new Promise((resolve, reject) => {
child.once('error', reject);
child.once('close', resolve);
});
const evidence = stdout.match(/^evidence: (.+)$/m)?.[1];
assert(evidence, `${mode}: no evidence directory`);
try {
assert.equal(code, 1, `${mode}: ${stderr}`);
const failure = JSON.parse(readFileSync(join(evidence, 'failure.json'), 'utf8'));
assert.equal(failure.fixture, 'all');
assert.equal(failure.phase, 'startup');
assert.equal(failure.snapshot, null);
assert.equal(failure.screenshot, null);
assert.match(failure.captureErrors[0], /sandbox unavailable/);
assert.match(failure.error, mode === 'missing' ? /ENOENT/ : ['interrupt', 'stubborn'].includes(mode) ? /interrupted/ : /nested UI test failed/);
const replay = JSON.parse(readFileSync(join(evidence, 'replay.json'), 'utf8'));
assert.deepEqual(replay, { ...replayRequest([]), phase: 'startup' });
const { command } = JSON.parse(readFileSync(join(evidence, 'command.json'), 'utf8'));
assert.deepEqual(command.slice(-2), ['--inside', 'all']);
const runtime = command[command.indexOf('/run/user/1000') - 1];
assert(runtime.startsWith(join(tmpdir(), 'nuguland-ui-runtime-')));
assert(!existsSync(runtime), `${mode}: runtime leaked`);
assert(!command.includes('WAYLAND_DISPLAY'), `${mode}: inherited display configuration`);
assert(!command.includes('/run/parent-display'), `${mode}: exposed host compositor`);
if (['interrupt', 'stubborn'].includes(mode)) assert.match(stderr, /interrupted/);
} finally {
rmSync(evidence, { recursive: true });
}
}
} finally {
rmSync(dir, { recursive: true });
}
});