const { test } = require('node:test') const assert = require('node:assert/strict') const fs = require('node:fs') const vm = require('node:vm') const ts = require('typescript') const source = ts.createSourceFile('App.tsx', fs.readFileSync(require.resolve('../src/renderer/src/App.tsx'), 'utf8'), ts.ScriptTarget.Latest, true, ts.ScriptKind.TSX) const names = ['isRemotePlatformStatusPending', 'filteredPlatformOptions', 'platformFilterCounts'] const declarations = new Map() function visit(node) { if (ts.isVariableDeclaration(node) && names.includes(node.name.getText(source))) { declarations.set(node.name.getText(source), node.getText(source)) } ts.forEachChild(node, visit) } visit(source) for (const name of names) assert.ok(declarations.has(name), `missing ${name}`) const filterScript = ts.transpileModule(`${names.map(name => `const ${declarations.get(name)}`).join('\n')} result = { counts: platformFilterCounts, ids: filteredPlatformOptions.map(platform => platform.id) }`, { compilerOptions: { target: ts.ScriptTarget.ES2022 } }).outputText const controlSource = fs.readFileSync(require.resolve('../src/renderer/src/features/platforms/platformControl.ts'), 'utf8') const control = {} vm.runInNewContext(ts.transpileModule(controlSource, { compilerOptions: { module: ts.ModuleKind.CommonJS } }).outputText, { exports: control, require: name => { assert.equal(name, '../../config/appConfig') return { LMS_API_BASE_URL: 'http://unused.invalid' } } }) function classify(platformOptions, checkedIds = ['mini'], platformFilter = 'all') { const context = { platformOptions, platformFilter, checkedRemotePlatformStatusIds: new Set(checkedIds), isPlatformUnavailable: control.isPlatformUnavailable } vm.runInNewContext(filterScript, context) return JSON.parse(JSON.stringify(context.result)) } const simulation = { id: 'sim', platformKey: 'futuredrive-local-pc', state: 'ready', status: '사용 가능', action: '시작' } const mini = { id: 'mini', platformKey: 'mkmini', state: 'ready', status: '사용 가능', action: '제어권 요청', connection: { headscaleOnline: true, agentHealthy: true } } test('disconnected ready platform counts as unavailable and appears only in that tab', () => { const disconnected = { ...mini, status: '연결 끊김', connection: { headscaleOnline: false, agentHealthy: false } } const platforms = [simulation, disconnected] assert.deepEqual(classify(platforms), { counts: { all: 2, available: 1, unavailable: 1 }, ids: ['sim', 'mini'] }) assert.deepEqual(classify(platforms, ['mini'], 'available').ids, ['sim']) assert.deepEqual(classify(platforms, ['mini'], 'unavailable').ids, ['mini']) }) test('offline network, unhealthy agent and explicit unavailability all exclude ready platforms', () => { for (const patch of [ { connection: { headscaleOnline: false, agentHealthy: true } }, { connection: { headscaleOnline: true, agentHealthy: false } }, { connection: undefined, status: '연결 끊김' }, { connection: undefined, status: '연결 불가' }, { connection: undefined, action: '연결 불가' } ]) { const platforms = [simulation, { ...mini, ...patch }] assert.deepEqual(classify(platforms).counts, { all: 2, available: 1, unavailable: 1 }) assert.deepEqual(classify(platforms, ['mini'], 'unavailable').ids, ['mini']) } }) test('pending remote status remains in All without prematurely entering either availability tab', () => { const platforms = [simulation, mini] assert.deepEqual(classify(platforms, []).counts, { all: 2, available: 1, unavailable: 0 }) assert.deepEqual(classify(platforms, [], 'available').ids, ['sim']) assert.deepEqual(classify(platforms, [], 'unavailable').ids, []) }) test('reconnecting moves a platform back to available without changing All', () => { assert.deepEqual(classify([simulation, mini]).counts, { all: 2, available: 2, unavailable: 0 }) assert.deepEqual(classify([simulation, mini], ['mini'], 'available').ids, ['sim', 'mini']) assert.deepEqual(classify([simulation, mini], ['mini'], 'unavailable').ids, []) }) test('locked, requested and reserved platform classifications are preserved', () => { for (const state of ['locked', 'request', 'reserved']) { const platforms = [simulation, { ...mini, state }] assert.deepEqual(classify(platforms).counts, { all: 2, available: 1, unavailable: 1 }) assert.deepEqual(classify(platforms, ['mini'], 'unavailable').ids, ['mini']) } })