aboutsummaryrefslogtreecommitdiff
path: root/plugin/test
diff options
context:
space:
mode:
author_ov4 <ov4@ov4.org>2026-10-13 08:21:59 +0000
committer_ov4 <ov4@ov4.org>2026-10-13 08:21:59 +0000
commita33ac452ba4bcfb9e7154a23a9ea38c93ed0c38d (patch)
tree2c039610874b5b5f570ec0cf232e17a7c7938ec7 /plugin/test
parent664e84149501a978bb5f63368c86ae2f53fe4cb8 (diff)
feat(plugin): run pseudocode files in the integrated terminal
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Diffstat (limited to 'plugin/test')
-rw-r--r--plugin/test/runner.test.js117
1 files changed, 117 insertions, 0 deletions
diff --git a/plugin/test/runner.test.js b/plugin/test/runner.test.js
new file mode 100644
index 0000000..a22d103
--- /dev/null
+++ b/plugin/test/runner.test.js
@@ -0,0 +1,117 @@
+'use strict';
+
+const assert = require('node:assert/strict');
+const { test } = require('node:test');
+const { spawnSync } = require('node:child_process');
+const { buildRunCommand, registerRunner } = require('../src/runner');
+
+test('commands quote paths and only run after changing directory', () => {
+ assert.equal(buildRunCommand('/tools/my cpsc', '/work/my file.cps', '/work/my project', 'posix'),
+ "cd '/work/my project' && '/tools/my cpsc' '/work/my file.cps' -r");
+ assert.equal(buildRunCommand('C:\\My Tools\\cpsc.exe', 'D:\\My Files\\test.cps', 'D:\\My Files', 'cmd'),
+ 'cd /d "D:\\My Files" && "C:\\My Tools\\cpsc.exe" "D:\\My Files\\test.cps" -r');
+ assert.equal(buildRunCommand('C:\\My Tools\\cpsc.exe', "D:\\Pat's Files\\test.cps", "D:\\Pat's Files", 'powershell'),
+ "Set-Location -LiteralPath 'D:\\Pat''s Files'; if ($?) { & 'C:\\My Tools\\cpsc.exe' 'D:\\Pat''s Files\\test.cps' -r }");
+ assert.throws(() => buildRunCommand('cpsc\nother', 'test.cps', '.', 'posix'), /line breaks/);
+ if (process.platform !== 'win32') {
+ const file = "/tmp/Pat's file $(echo unexpected) `echo unexpected`.cps";
+ const result = spawnSync('/bin/sh', ['-c', buildRunCommand('/usr/bin/printf', file, '/tmp', 'posix')], { encoding: 'utf8' });
+ assert.equal(result.status, 0);
+ assert.equal(result.stdout, file);
+ const failed = spawnSync('/bin/sh', ['-c', buildRunCommand('/usr/bin/printf', file, '/missing-cie-run-directory', 'posix')], { encoding: 'utf8' });
+ assert.notEqual(failed.status, 0);
+ assert.equal(failed.stdout, '');
+ }
+});
+
+function harness(platform = 'linux') {
+ let run, close;
+ const calls = { saved: 0, terminals: [], errors: [], settings: [] };
+ const document = {
+ languageId: 'cie-pseudocode', isUntitled: false,
+ uri: { scheme: 'file', fsPath: '/project/sub/my file.cps' },
+ async save() { calls.saved++; return true; }
+ };
+ const vscode = {
+ env: { shell: 'C:\\Windows\\System32\\cmd.exe' },
+ commands: { registerCommand(id, callback) { assert.equal(id, 'cie-pseudocode.runFile'); run = callback; return { dispose() {} }; } },
+ workspace: {
+ async openTextDocument() { return document; },
+ getWorkspaceFolder() { return { uri: { fsPath: '/project' } }; },
+ getConfiguration(section, uri) {
+ calls.settings.push({ section, uri });
+ return { get(key, fallback) { return section === 'cie-pseudocode' ? '/tools/my cpsc' : fallback; } };
+ }
+ },
+ window: {
+ activeTextEditor: { document },
+ async showTextDocument(doc) { this.activeTextEditor = { document: doc }; },
+ showErrorMessage(message) { calls.errors.push(message); },
+ onDidCloseTerminal(callback) { close = callback; return { dispose() {} }; },
+ createTerminal(name) {
+ const terminal = { name, sent: [], show(focus) { this.preserveFocus = focus; }, sendText(text) { this.sent.push(text); }, dispose() {} };
+ calls.terminals.push(terminal);
+ return terminal;
+ }
+ }
+ };
+ registerRunner(vscode, { subscriptions: [] }, platform);
+ return { vscode, document, calls, run: uri => run(uri), close: terminal => close(terminal) };
+}
+
+test('save before running the whole file, scope settings, reuse and recreate the terminal', async () => {
+ const h = harness();
+ await h.run(h.document.uri);
+ assert.equal(h.calls.saved, 1);
+ assert.equal(h.calls.terminals[0].preserveFocus, false);
+ assert.equal(h.calls.terminals[0].sent[0], "cd '/project' && '/tools/my cpsc' '/project/sub/my file.cps' -r");
+ assert.equal(h.calls.settings[0].uri, h.document.uri);
+ h.close({});
+ await h.run();
+ assert.equal(h.calls.terminals.length, 1);
+ h.close(h.calls.terminals[0]);
+ h.vscode.workspace.getWorkspaceFolder = () => undefined;
+ await h.run();
+ assert.equal(h.calls.terminals.length, 2);
+ assert.match(h.calls.terminals[1].sent[0], /^cd '\/project\/sub'/);
+ assert.deepEqual(h.calls.errors, []);
+});
+
+test('save cancellation and failure do not create a terminal; untitled files use the saved URI', async () => {
+ const h = harness();
+ h.document.isUntitled = true;
+ h.document.uri = { scheme: 'untitled', fsPath: 'Untitled-1' };
+ h.document.save = async () => false;
+ await h.run();
+ assert.equal(h.calls.terminals.length, 0);
+ h.document.save = async () => { throw new Error('Save failed'); };
+ await h.run();
+ assert.match(h.calls.errors[0], /Save failed/);
+ assert.equal(h.calls.terminals.length, 0);
+ h.document.save = async () => {
+ h.vscode.window.activeTextEditor = { document: { ...h.document, isUntitled: false,
+ uri: { scheme: 'file', fsPath: '/project/new file.cps' } } };
+ return true;
+ };
+ await h.run();
+ assert.match(h.calls.terminals[0].sent[0], /'\/project\/new file.cps' -r$/);
+});
+
+test('Windows recognizes custom pwsh and cmd profiles and retains the reused terminal shell', async () => {
+ const h = harness('win32');
+ let profile = 'My Shell';
+ h.vscode.workspace.getConfiguration = section => ({ get(key, fallback) {
+ if (section === 'cie-pseudocode') return 'cpsc';
+ if (key === 'integrated.defaultProfile.windows') return profile;
+ if (key === 'integrated.profiles.windows') return { 'My Shell': { path: 'C:\\Program Files\\PowerShell\\7\\pwsh.exe' } };
+ return fallback;
+ } });
+ await h.run();
+ assert.match(h.calls.terminals[0].sent[0], /^Set-Location.*& 'cpsc'/);
+ profile = 'Command Prompt';
+ await h.run();
+ assert.match(h.calls.terminals[0].sent[1], /^Set-Location/);
+ h.close(h.calls.terminals[0]);
+ await h.run();
+ assert.match(h.calls.terminals[1].sent[0], /^cd \/d .*&& "cpsc"/);
+});