'use strict'; const assert = require('node:assert/strict'); const fs = require('node:fs'); const os = require('node:os'); const path = require('node:path'); const coordinatorModule = require('../js/instance-coordinator'); const coordinators = []; (async () => { const root = fs.mkdtempSync(path.join(os.tmpdir(), 'spine-instance-coordinator-')); const storage = coordinatorModule.createFileStorage(path.join(root, '用户 data', 'instance-state.json')); let timestamp = 1000; let hidden = 0; const changes = { a: [], b: [], c: [], d: [] }; const make = (id, visible) => { const coordinator = coordinatorModule.createCoordinator({ storage, id, now: () => timestamp, hide: () => { hidden += 1; }, isVisible: () => visible, onActiveChanged: (active) => changes[id].push(active), }); coordinators.push(coordinator); return coordinator; }; const hiddenService = make('a', false); const visibleUi = make('b', true); const duplicateUi = make('c', true); hiddenService.start(); assert.equal(hiddenService.isActive(), true); visibleUi.start(); assert.equal(hiddenService.evaluate(), false); assert.equal(visibleUi.isActive(), true); duplicateUi.start(); assert.equal(duplicateUi.isActive(), true, 'the later window takes ownership'); assert.equal(visibleUi.evaluate(), false); assert.equal(hidden, 1, 'the previous visible window is hidden'); const laterWindow = make('d', false); laterWindow.start(); assert.equal(laterWindow.isActive(), false, 'a hidden background window must not steal visible UI'); assert.equal(duplicateUi.isActive(), true); assert.equal(hidden, 1); timestamp += coordinatorModule.STALE_MS + 1; assert.equal(laterWindow.evaluate(), true, 'stale owner allows background takeover'); assert.equal(duplicateUi.evaluate(), false); assert.equal(hidden, 2); hiddenService.stop(); visibleUi.stop(); duplicateUi.stop(); laterWindow.stop(); console.log('PASS: opened UI takes ownership and background instances respect it'); fs.rmSync(root, { recursive: true, force: true }); })().catch((error) => { for (const coordinator of coordinators) coordinator.stop(); console.error(error); process.exitCode = 1; });