/** * Behavioral tests for ecc_dashboard.py helper functions. */ const assert = require('assert'); const path = require('path'); const { spawnSync } = require('child_process'); const repoRoot = path.join(__dirname, '..', '..'); const runtimeHelpersPath = path.join(repoRoot, 'scripts', 'lib', 'ecc_dashboard_runtime.py'); function test(name, fn) { try { fn(); console.log(` ✓ ${name}`); return true; } catch (error) { console.log(` ✗ ${name}`); console.log(` Error: ${error.message}`); return false; } } function runPython(source) { const candidates = process.platform === 'win32' ? ['python', 'python3'] : ['python3', 'python']; let lastError = null; for (const command of candidates) { const result = spawnSync(command, ['-c', source], { cwd: repoRoot, encoding: 'utf8', }); if (result.error && result.error.code === 'ENOENT') { lastError = result.error; continue; } if (result.status !== 0) { throw new Error((result.stderr || result.stdout || '').trim() || `${command} exited ${result.status}`); } return result.stdout.trim(); } throw lastError || new Error('No Python interpreter available'); } function runTests() { console.log('\n=== Testing ecc_dashboard.py ===\n'); let passed = 0; let failed = 0; if (test('build_terminal_launch keeps Linux path separate from shell command text', () => { const output = runPython(` import importlib.util, json spec = importlib.util.spec_from_file_location("ecc_dashboard_runtime", r"""${runtimeHelpersPath}""") module = importlib.util.module_from_spec(spec) spec.loader.exec_module(module) argv, kwargs = module.build_terminal_launch('/tmp/proj; rm -rf ~', os_name='posix', system_name='Linux') print(json.dumps({'argv': argv, 'kwargs': kwargs})) `); const parsed = JSON.parse(output); assert.deepStrictEqual( parsed.argv, ['x-terminal-emulator', '-e', 'bash', '-lc', 'cd -- "$1"; exec bash', 'bash', '/tmp/proj; rm -rf ~'] ); assert.deepStrictEqual(parsed.kwargs, {}); })) passed++; else failed++; if (test('build_terminal_launch uses cwd + CREATE_NEW_CONSOLE style launch on Windows', () => { const output = runPython(` import importlib.util, json spec = importlib.util.spec_from_file_location("ecc_dashboard_runtime", r"""${runtimeHelpersPath}""") module = importlib.util.module_from_spec(spec) spec.loader.exec_module(module) argv, kwargs = module.build_terminal_launch(r'C:\\\\Users\\\\user\\\\proj & del C:\\\\*', os_name='nt', system_name='Windows') print(json.dumps({'argv': argv, 'kwargs': kwargs})) `); const parsed = JSON.parse(output); assert.deepStrictEqual(parsed.argv.slice(0, 4), ['cmd.exe', '/k', 'cd', '/d']); assert.strictEqual(parsed.argv[4], parsed.kwargs.cwd); assert.ok(parsed.argv[4].includes('proj & del'), 'path should remain a literal argv entry'); assert.ok(parsed.argv[4].includes('C:'), 'windows drive prefix should be preserved'); assert.ok(Object.prototype.hasOwnProperty.call(parsed.kwargs, 'creationflags')); })) passed++; else failed++; if (test('maximize_window falls back to Linux zoom attribute when zoomed state is unsupported', () => { const output = runPython(` import importlib.util, json spec = importlib.util.spec_from_file_location("ecc_dashboard_runtime", r"""${runtimeHelpersPath}""") module = importlib.util.module_from_spec(spec) spec.loader.exec_module(module) class FakeWindow: def __init__(self): self.calls = [] def state(self, value): self.calls.append(['state', value]) raise RuntimeError('bad argument "zoomed"') def attributes(self, name, value): self.calls.append(['attributes', name, value]) original = module.platform.system module.platform.system = lambda: 'Linux' try: window = FakeWindow() module.maximize_window(window) finally: module.platform.system = original print(json.dumps(window.calls)) `); const parsed = JSON.parse(output); assert.deepStrictEqual(parsed, [ ['state', 'zoomed'], ['attributes', '-zoomed', true], ]); })) passed++; else failed++; console.log(`\nResults: Passed: ${passed}, Failed: ${failed}`); process.exit(failed > 0 ? 1 : 0); } runTests();