From 34033372e1dfd038d89d376bd5d5e7c48f7477ce Mon Sep 17 00:00:00 2001 From: RohitKushvaha01 Date: Tue, 13 Jan 2026 16:04:04 +0530 Subject: [PATCH 1/6] feat: added executor tests --- src/test/exec.tests.js | 179 +++++++++++++++++++++++++++++++++++++++++ src/test/tester.js | 81 ++++++++++++++----- 2 files changed, 240 insertions(+), 20 deletions(-) create mode 100644 src/test/exec.tests.js diff --git a/src/test/exec.tests.js b/src/test/exec.tests.js new file mode 100644 index 000000000..dbeebc2dd --- /dev/null +++ b/src/test/exec.tests.js @@ -0,0 +1,179 @@ +import { TestRunner } from "./tester"; + +export async function runExecutorTests(writeOutput) { + const runner = new TestRunner("Executor API Tests"); + + runner.test("Executor available", async (test) => { + test.assert(typeof Executor !== "undefined", "Executor should be available globally"); + }); + + runner.test("Background Executor available", async (test) => { + test.assert(typeof Executor.BackgroundExecutor !== "undefined", "Background Executor should be available globally"); + }); + + + runner.test("execute()", async (test) => { + + test.assert( + await Executor.execute("echo test123").includes("test123"), + "Command output should match" + ); + + }); + + + + runner.test("execute() (BackgroundExecutor)", async (test) => { + + test.assert( + await Executor.BackgroundExecutor.execute("echo test123").includes("test123"), + "Command output should match" + ); + + }); + + runner.test("start()", async (test) => { + let stdout = ""; + + const uuid = await Executor.start("sh", (type, data) => { + if (type === "stdout") stdout += data; + }); + + await Executor.write(uuid, "echo hello\n"); + + await Executor.stop(uuid); + + await new Promise(r => setTimeout(r, 200)); + + test.assert(stdout.includes("hello"), "Shell should echo output"); + }); + + + runner.test("start() (BackgroundExecutor)", async (test) => { + let stdout = ""; + + const uuid = await Executor.start("sh", (type, data) => { + if (type === "stdout") stdout += data; + }); + + await Executor.write(uuid, "echo hello\n"); + await Executor.stop(uuid); + + await new Promise(r => setTimeout(r, 200)); + + test.assert(stdout.includes("hello"), "Shell should echo output"); + }); + + + runner.test("start/stop()", async (test) => { + let stdout = ""; + + const uuid = await Executor.start("sh", (type, data) => { + + }); + + await new Promise(r => setTimeout(r, 200)); + + + + const isRunning = await Executor.isRunning(uuid); + + test.assert(isRunning === true, "Executor must be running"); + + + await new Promise(r => setTimeout(r, 200)); + + + await Executor.stop(uuid); + + await new Promise(r => setTimeout(r, 200)); + + + test.assert(isRunning !== await Executor.isRunning(uuid), "Executor must be stopped"); + test.assert(await Executor.isRunning(uuid) === false, "Executor must be stopped"); + + }); + + runner.test("start/stop() (BackgroundExecutor)", async (test) => { + let stdout = ""; + + const uuid = await Executor.start("sh", (type, data) => { + + }); + + await new Promise(r => setTimeout(r, 200)); + + + + const isRunning = await Executor.isRunning(uuid); + + test.assert(isRunning === true, "Executor must be running"); + + + await new Promise(r => setTimeout(r, 200)); + + + await Executor.stop(uuid); + + await new Promise(r => setTimeout(r, 200)); + + + test.assert(isRunning !== await Executor.isRunning(uuid), "Executor must be stopped"); + test.assert(await Executor.isRunning(uuid) === false, "Executor must be stopped"); + + }); + + + + + + + runner.test("start/stop()", async (test) => { + let stdout = ""; + + const uuid = await Executor.start("sh", (type, data) => { + + }); + + await new Promise(r => setTimeout(r, 200)); + + + + const isRunning = await Executor.isRunning(uuid); + + test.assert(isRunning === true, "Executor must be running"); + + + await new Promise(r => setTimeout(r, 200)); + + + await Executor.stop(uuid); + + await new Promise(r => setTimeout(r, 200)); + + + test.assert(isRunning !== await Executor.isRunning(uuid), "Executor must be stopped"); + test.assert(await Executor.isRunning(uuid) === false, "Executor must be stopped"); + + }); + + runner.test("FDROID env variable", async (test) => { + const result = await Executor.execute("echo $FDROID"); + + const isSet = result.trim().length > 0; + + test.assert( + isSet, + "FDROID env variable should be set" + ); + }); + + + + + + + + + return await runner.run(writeOutput); +} \ No newline at end of file diff --git a/src/test/tester.js b/src/test/tester.js index a51206523..3f0c515e1 100644 --- a/src/test/tester.js +++ b/src/test/tester.js @@ -16,6 +16,7 @@ export async function runAllTests() { // Run unit tests await runSanityTests(write); await runAceEditorTests(write); + await runExecutorTests(write); write("\x1b[36m\x1b[1mTests completed!\x1b[0m\n"); } catch (error) { @@ -80,6 +81,7 @@ class TestRunner { this.passed = 0; this.failed = 0; this.results = []; + this.skipped = 0; } /** @@ -104,6 +106,11 @@ class TestRunner { } } + skip(reason = "Skipped") { + throw new SkipTest(reason); + } + + async _runWithTimeout(fn, ctx, timeoutMs) { return new Promise((resolve, reject) => { let finished = false; @@ -161,32 +168,52 @@ class TestRunner { try { await delay(200); - await this._runWithTimeout(test.fn, this, 3000); stopSpinner(); this.passed++; - this.results.push({ name: test.name, status: "PASS", error: null }); + this.results.push({ name: test.name, status: "PASS" }); line(` ${COLORS.GREEN}✓${COLORS.RESET} ${test.name}`, COLORS.GREEN); + } catch (error) { stopSpinner(); - this.failed++; - this.results.push({ - name: test.name, - status: "FAIL", - error: error.message, - }); - line( - ` ${COLORS.RED}✗${COLORS.RESET} ${test.name}`, - COLORS.RED + COLORS.BRIGHT, - ); - line( - ` ${COLORS.DIM}└─ ${error.message}${COLORS.RESET}`, - COLORS.RED + COLORS.DIM, - ); + if (error instanceof SkipTest) { + this.skipped++; + this.results.push({ + name: test.name, + status: "SKIP", + reason: error.message, + }); + + line( + ` ${COLORS.YELLOW}?${COLORS.RESET} ${test.name}`, + COLORS.YELLOW + COLORS.BRIGHT, + ); + line( + ` ${COLORS.DIM}└─ ${error.message}${COLORS.RESET}`, + COLORS.YELLOW + COLORS.DIM, + ); + } else { + this.failed++; + this.results.push({ + name: test.name, + status: "FAIL", + error: error.message, + }); + + line( + ` ${COLORS.RED}✗${COLORS.RESET} ${test.name}`, + COLORS.RED + COLORS.BRIGHT, + ); + line( + ` ${COLORS.DIM}└─ ${error.message}${COLORS.RESET}`, + COLORS.RED + COLORS.DIM, + ); + } } + } // Summary @@ -194,15 +221,20 @@ class TestRunner { line("─────────────────────────────────────────────", COLORS.GRAY); const total = this.tests.length; - const percentage = total ? ((this.passed / total) * 100).toFixed(1) : "0.0"; + const effectiveTotal = total - this.skipped; + + const percentage = effectiveTotal + ? ((this.passed / effectiveTotal) * 100).toFixed(1) + : "0.0"; + const statusColor = this.failed === 0 ? COLORS.GREEN : COLORS.YELLOW; line( ` Tests: ${COLORS.BRIGHT}${total}${COLORS.RESET} | ` + - `${statusColor}Passed: ${this.passed}${COLORS.RESET} | ` + - `${COLORS.RED}Failed: ${this.failed}${COLORS.RESET}`, - statusColor, + `${COLORS.GREEN}Passed: ${this.passed}${COLORS.RESET} | ` + + `${COLORS.YELLOW}Skipped: ${this.skipped}${COLORS.RESET} | ` + + `${COLORS.RED}Failed: ${this.failed}${COLORS.RESET}`, ); line( @@ -226,4 +258,13 @@ class TestRunner { } } + +class SkipTest extends Error { + constructor(message = "Skipped") { + super(message); + this.name = "SkipTest"; + } +} + + export { TestRunner }; From 2edc3dbc852062575f422d116de5206592698217 Mon Sep 17 00:00:00 2001 From: Rohit Kushvaha Date: Tue, 13 Jan 2026 16:09:08 +0530 Subject: [PATCH 2/6] Update src/test/exec.tests.js Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> --- src/test/exec.tests.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/test/exec.tests.js b/src/test/exec.tests.js index dbeebc2dd..0f91b0d25 100644 --- a/src/test/exec.tests.js +++ b/src/test/exec.tests.js @@ -52,12 +52,12 @@ export async function runExecutorTests(writeOutput) { runner.test("start() (BackgroundExecutor)", async (test) => { let stdout = ""; - const uuid = await Executor.start("sh", (type, data) => { + const uuid = await Executor.BackgroundExecutor.start("sh", (type, data) => { if (type === "stdout") stdout += data; }); - await Executor.write(uuid, "echo hello\n"); - await Executor.stop(uuid); + await Executor.BackgroundExecutor.write(uuid, "echo hello\n"); + await Executor.BackgroundExecutor.stop(uuid); await new Promise(r => setTimeout(r, 200)); From 3502ba5df29aad84fbd4fa6ea466848f3f582104 Mon Sep 17 00:00:00 2001 From: RohitKushvaha01 Date: Tue, 13 Jan 2026 16:10:28 +0530 Subject: [PATCH 3/6] feat: added executor tests --- src/test/exec.tests.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/test/exec.tests.js b/src/test/exec.tests.js index 0f91b0d25..67d7726c0 100644 --- a/src/test/exec.tests.js +++ b/src/test/exec.tests.js @@ -97,7 +97,7 @@ export async function runExecutorTests(writeOutput) { runner.test("start/stop() (BackgroundExecutor)", async (test) => { let stdout = ""; - const uuid = await Executor.start("sh", (type, data) => { + const uuid = await Executor.BackgroundExecutor.start("sh", (type, data) => { }); @@ -105,7 +105,7 @@ export async function runExecutorTests(writeOutput) { - const isRunning = await Executor.isRunning(uuid); + const isRunning = await Executor.BackgroundExecutor.isRunning(uuid); test.assert(isRunning === true, "Executor must be running"); @@ -113,13 +113,13 @@ export async function runExecutorTests(writeOutput) { await new Promise(r => setTimeout(r, 200)); - await Executor.stop(uuid); + await Executor.BackgroundExecutor.stop(uuid); await new Promise(r => setTimeout(r, 200)); - test.assert(isRunning !== await Executor.isRunning(uuid), "Executor must be stopped"); - test.assert(await Executor.isRunning(uuid) === false, "Executor must be stopped"); + test.assert(isRunning !== await Executor.BackgroundExecutor.isRunning(uuid), "Executor must be stopped"); + test.assert(await Executor.BackgroundExecutor.isRunning(uuid) === false, "Executor must be stopped"); }); From 3bedaa2a3ab0e427193f230a4b1c3fda2f9fb3da Mon Sep 17 00:00:00 2001 From: RohitKushvaha01 Date: Tue, 13 Jan 2026 16:12:58 +0530 Subject: [PATCH 4/6] feat: added delay --- src/test/exec.tests.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/test/exec.tests.js b/src/test/exec.tests.js index 67d7726c0..b729b2a31 100644 --- a/src/test/exec.tests.js +++ b/src/test/exec.tests.js @@ -40,7 +40,7 @@ export async function runExecutorTests(writeOutput) { }); await Executor.write(uuid, "echo hello\n"); - + await new Promise(r => setTimeout(r, 200)); await Executor.stop(uuid); await new Promise(r => setTimeout(r, 200)); @@ -57,6 +57,7 @@ export async function runExecutorTests(writeOutput) { }); await Executor.BackgroundExecutor.write(uuid, "echo hello\n"); + await new Promise(r => setTimeout(r, 200)); await Executor.BackgroundExecutor.stop(uuid); await new Promise(r => setTimeout(r, 200)); From d332a9851f956eff81996c399b1feeb47ffa9166 Mon Sep 17 00:00:00 2001 From: RohitKushvaha01 Date: Tue, 13 Jan 2026 16:14:56 +0530 Subject: [PATCH 5/6] feat: added missing import --- src/test/tester.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/test/tester.js b/src/test/tester.js index 3f0c515e1..44644e2e4 100644 --- a/src/test/tester.js +++ b/src/test/tester.js @@ -1,5 +1,8 @@ -import { runAceEditorTests } from "./editor.tests"; + +import { runExecutorTests } from "./exec.tests"; import { runSanityTests } from "./sanity.tests"; +import { runAceEditorTests } from "./editor.tests"; + export async function runAllTests() { const terminal = acode.require("terminal"); From 9dd7c2555078a6bd5eb4bd1ef574de354761136a Mon Sep 17 00:00:00 2001 From: RohitKushvaha01 Date: Tue, 13 Jan 2026 16:16:05 +0530 Subject: [PATCH 6/6] feat: removed missing import --- src/test/exec.tests.js | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/test/exec.tests.js b/src/test/exec.tests.js index b729b2a31..0ce045971 100644 --- a/src/test/exec.tests.js +++ b/src/test/exec.tests.js @@ -89,8 +89,6 @@ export async function runExecutorTests(writeOutput) { await new Promise(r => setTimeout(r, 200)); - - test.assert(isRunning !== await Executor.isRunning(uuid), "Executor must be stopped"); test.assert(await Executor.isRunning(uuid) === false, "Executor must be stopped"); }); @@ -152,8 +150,6 @@ export async function runExecutorTests(writeOutput) { await new Promise(r => setTimeout(r, 200)); - - test.assert(isRunning !== await Executor.isRunning(uuid), "Executor must be stopped"); test.assert(await Executor.isRunning(uuid) === false, "Executor must be stopped"); });