From 097be7713693531ae3bbc5bdf967f2fe87598971 Mon Sep 17 00:00:00 2001 From: RohitKushvaha01 Date: Mon, 12 Jan 2026 14:32:19 +0530 Subject: [PATCH 01/16] feat: added tests --- src/lib/commands.js | 4 + src/lib/keyBindings.js | 9 ++ src/test/editor.tests.js | 200 +++++++++++++++++++++++++++++++++ src/test/sanity.tests.js | 73 ++++++++++++ src/test/tester.js | 232 +++++++++++++++++++++++++++++++++++++++ 5 files changed, 518 insertions(+) create mode 100644 src/test/editor.tests.js create mode 100644 src/test/sanity.tests.js create mode 100644 src/test/tester.js diff --git a/src/lib/commands.js b/src/lib/commands.js index 8e01e4583..b06e3adaa 100644 --- a/src/lib/commands.js +++ b/src/lib/commands.js @@ -32,8 +32,12 @@ import run from "./run"; import saveState from "./saveState"; import appSettings from "./settings"; import showFileInfo from "./showFileInfo"; +import { runAllTests } from "test/tester"; export default { + async "run-tests"() { + runAllTests(); + }, async "close-all-tabs"() { let save = false; const unsavedFiles = editorManager.files.filter( diff --git a/src/lib/keyBindings.js b/src/lib/keyBindings.js index b7ab35b9a..eab2c6b5a 100644 --- a/src/lib/keyBindings.js +++ b/src/lib/keyBindings.js @@ -1,3 +1,6 @@ +import { description } from "components/quickTools/items"; +import actions, { key } from "handlers/quickTools"; + export default { focusEditor: { description: "Focus editor", @@ -697,4 +700,10 @@ export default { readOnly: true, action: "new-terminal", }, + runTests: { + description: "Run Tests", + key: "Ctrl-T", + readOnly: true, + actions: "run-tests" + } }; diff --git a/src/test/editor.tests.js b/src/test/editor.tests.js new file mode 100644 index 000000000..555c0582d --- /dev/null +++ b/src/test/editor.tests.js @@ -0,0 +1,200 @@ +import { TestRunner } from '../tester.js'; + +export async function runAceEditorTests(writeOutput) { + const runner = new TestRunner('Ace Editor API Tests'); + + let editor; + let container; + + // Helper to create editor safely + function createEditor() { + container = document.createElement('div'); + container.style.width = '500px'; + container.style.height = '300px'; + container.style.backgroundColor = '#a02f2fff'; + document.body.appendChild(container); + return ace.edit(container); + } + + // Test 1: Ace is available + runner.test('Ace is loaded', async (test) => { + test.assert(typeof ace !== 'undefined', 'Ace should be available globally'); + test.assert(typeof ace.edit === 'function', 'ace.edit should be a function'); + }); + + // Test 2: Editor creation + runner.test('Editor creation', async (test) => { + editor = createEditor(); + test.assert(editor != null, 'Editor instance should be created'); + test.assert(typeof editor.getSession === 'function', 'Editor should expose getSession'); + }); + + // Test 3: Session access + runner.test('Session access', async (test) => { + const session = editor.getSession(); + test.assert(session != null, 'Editor session should exist'); + test.assert(typeof session.getValue === 'function', 'Session should expose getValue'); + }); + + // Test 4: Set and get value + runner.test('Set and get value', async (test) => { + const text = 'Hello Ace Editor'; + editor.setValue(text, -1); + const value = editor.getValue(); + test.assertEqual(value, text, 'Editor value should match the set value'); + }); + + // Test 5: Cursor movement + runner.test('Cursor movement', async (test) => { + editor.setValue('line1\nline2\nline3', -1); + editor.moveCursorTo(1, 2); + + const pos = editor.getCursorPosition(); + test.assertEqual(pos.row, 1, 'Cursor row should be correct'); + test.assertEqual(pos.column, 2, 'Cursor column should be correct'); + }); + + // Test 6: Selection API + runner.test('Selection handling', async (test) => { + editor.setValue('abc\ndef', -1); + editor.selectAll(); + + const selected = editor.getSelectedText(); + test.assert(selected.length > 0, 'Selected text should not be empty'); + }); + + // Test 7: Undo manager + runner.test('Undo manager works', async (test) => { + const session = editor.getSession(); + const undoManager = session.getUndoManager(); + + session.setValue('one'); + undoManager.reset(); + + editor.insert('\ntwo'); + editor.undo(); + + const value = editor.getValue(); + test.assertEqual(value, 'one', 'Undo should revert last change'); + }); + + + // Test 8: Mode setting + runner.test('Mode setting', async (test) => { + const session = editor.getSession(); + session.setMode('ace/mode/javascript'); + + const mode = session.getMode(); + test.assert( + mode && mode.$id === 'ace/mode/javascript', + 'Editor mode should be JavaScript' + ); + }); + + // Test 9: Theme setting + runner.test('Theme setting', async (test) => { + editor.setTheme('ace/theme/monokai'); + const theme = editor.getTheme(); + test.assert( + theme && theme.includes('monokai'), + 'Editor theme should be monokai' + ); + }); + + + // Test 11: Line count + runner.test('Line count', async (test) => { + editor.setValue('a\nb\nc\nd', -1); + const lines = editor.session.getLength(); + test.assertEqual(lines, 4, 'Editor should report correct number of lines'); + }); + + // Test 12: Replace text + runner.test('Replace text', async (test) => { + editor.setValue('hello world', -1); + editor.find('world'); + editor.replace('ace'); + + const value = editor.getValue(); + test.assertEqual(value, 'hello ace', 'Replace should work correctly'); + }); + + // Test 13: Search API + runner.test('Search API', async (test) => { + editor.setValue('foo bar foo', -1); + editor.find('foo'); + + const range = editor.getSelectionRange(); + test.assert( + range.start.column === 0, + 'Search should select first match' + ); + }); + + // Test 14: Renderer availability + runner.test('Renderer exists', async (test) => { + const renderer = editor.renderer; + test.assert(renderer != null, 'Editor renderer should exist'); + test.assert( + typeof renderer.updateFull === 'function', + 'Renderer should expose updateFull' + ); + }); + + // Test 15: Editor options + runner.test('Editor options', async (test) => { + editor.setOption('showPrintMargin', false); + const value = editor.getOption('showPrintMargin'); + test.assertEqual(value, false, 'Editor option should be applied'); + }); + + // Test 16: Scroll API + runner.test('Scroll API', async (test) => { + editor.setValue(Array(100).fill('line').join('\n'), -1); + editor.scrollToLine(50, true, true, () => { }); + + const firstVisibleRow = editor.renderer.getFirstVisibleRow(); + test.assert( + firstVisibleRow >= 0, + 'Editor should support scrolling' + ); + }); + + // Test 17: Redo manager + runner.test('Redo manager works', (test) => { + const session = editor.getSession(); + const undoManager = session.getUndoManager(); + + session.setValue('one'); + undoManager.reset(); + + session.insert({ row: 0, column: 3 }, '\ntwo'); + + editor.undo(); + editor.redo(); + + const value = editor.getValue(); + test.assertEqual(value, 'one\ntwo', 'Redo should restore undone change'); + }); + + + // Test 18: Focus and blur + runner.test('Focus and blur', async (test) => { + editor.focus(); + test.assert(editor.isFocused(), 'Editor should be focused'); + + editor.blur(); + test.assert(!editor.isFocused(), 'Editor should be blurred'); + }); + + + // Cleanup + runner.test('Cleanup editor', async (test) => { + editor.destroy(); + container.remove(); + test.assert(true, 'Editor destroyed and DOM cleaned'); + }); + + // Run all tests + return await runner.run(writeOutput); +} diff --git a/src/test/sanity.tests.js b/src/test/sanity.tests.js new file mode 100644 index 000000000..82cce39fd --- /dev/null +++ b/src/test/sanity.tests.js @@ -0,0 +1,73 @@ +import { TestRunner } from '../tester.js'; + + + +export async function runSanityTests(writeOutput) { + const runner = new TestRunner('JS (WebView) Sanity Tests'); + + // Test 1: String operations + runner.test('String concatenation', (test) => { + const result = 'Hello' + ' ' + 'World'; + test.assertEqual(result, 'Hello World', 'String concatenation should work'); + }); + + // Test 2: Number operations + runner.test('Basic arithmetic', (test) => { + const sum = 5 + 3; + test.assertEqual(sum, 8, 'Addition should work correctly'); + }); + + // Test 3: Array operations + runner.test('Array operations', (test) => { + + const arr = [1, 2, 3]; + test.assertEqual(arr.length, 3, 'Array length should be correct'); + test.assert(arr.includes(2), 'Array should include 2'); + }); + + // Test 4: Object operations + runner.test('Object operations', (test) => { + const obj = { name: 'Test', value: 42 }; + test.assertEqual(obj.name, 'Test', 'Object property should be accessible'); + test.assertEqual(obj.value, 42, 'Object value should be correct'); + }); + + // Test 5: Function execution + runner.test('Function execution', (test) => { + const add = (a, b) => a + b; + const result = add(10, 20); + test.assertEqual(result, 30, 'Function should return correct value'); + }); + + // Test 6: Async function + runner.test('Async function handling', async (test) => { + const asyncFunc = async () => { + return new Promise((resolve) => { + setTimeout(() => resolve('done'), 10); + }); + }; + + const result = await asyncFunc(); + test.assertEqual(result, 'done', 'Async function should work correctly'); + }); + + + // Test 7: Error handling + runner.test('Error handling', (test) => { + try { + throw new Error('Test error'); + } catch (e) { + test.assert(e instanceof Error, 'Should catch Error instances'); + } + }); + + // Test 8: Conditional logic + runner.test('Conditional logic', (test) => { + const value = 10; + test.assert(value > 5, 'Condition should be true'); + test.assert(!(value < 5), 'Negation should work'); + }); + + // Run all tests + return await runner.run(writeOutput); +} \ No newline at end of file diff --git a/src/test/tester.js b/src/test/tester.js new file mode 100644 index 000000000..e86bb37cb --- /dev/null +++ b/src/test/tester.js @@ -0,0 +1,232 @@ +/** + * Runtime Test Suite for Acode Plugin + * Tests execute at plugin initialization and print results to terminal + */ + + + + + + +export async function runAllTests() { + const terminal = acode.require('terminal'); + const local = await terminal.createLocal({ name: 'TestCode' }); + function write(data) { + terminal.write(local.id, data); + } + + // Run tests at runtime + write('\x1b[36m\x1b[1m๐Ÿš€ TestCode Plugin Loaded\x1b[0m\n'); + write('\x1b[36m\x1b[1mStarting test execution...\x1b[0m\n'); + + try { + // Run unit tests + await runSanityTests(write); + await runAceEditorTests(write); + + + write('\x1b[36m\x1b[1mTests completed!\x1b[0m\n'); + } catch (error) { + write(`\x1b[31mโš ๏ธ Test execution error: ${error.message}\x1b[0m\n`); + } +} + + + + + +// ANSI color codes for terminal output +const COLORS = { + RESET: '\x1b[0m', + BRIGHT: '\x1b[1m', + DIM: '\x1b[2m', + ITALIC: '\x1b[3m', + + // Foreground colors + RED: '\x1b[31m', + GREEN: '\x1b[32m', + YELLOW: '\x1b[33m', + BLUE: '\x1b[34m', + MAGENTA: '\x1b[35m', + CYAN: '\x1b[36m', + WHITE: '\x1b[37m', + GRAY: '\x1b[90m', + + // Background colors + BG_RED: '\x1b[41m', + BG_GREEN: '\x1b[42m', + BG_YELLOW: '\x1b[43m', + BG_BLUE: '\x1b[44m', +}; + +function delay(ms) { + return new Promise(resolve => setTimeout(resolve, ms)); +} + +function startSpinner(writeOutput, text) { + let index = 0; + let active = true; + + const timer = setInterval(() => { + if (!active) return; + const frame = SPINNER_FRAMES[index++ % SPINNER_FRAMES.length]; + // \r moves cursor to start, \x1b[K clears the line to the right + writeOutput(`\r ${COLORS.CYAN}${frame}${COLORS.RESET} ${text}`); + }, 80); + + return () => { + active = false; + clearInterval(timer); + // Clear the line so the "Success/Fail" message can take its place + writeOutput('\r\x1b[K'); + }; +} + + +// Spinner frames +const SPINNER_FRAMES = ['โ ‹', 'โ ™', 'โ น', 'โ ธ', 'โ ผ', 'โ ด', 'โ ฆ', 'โ ง', 'โ ‡', 'โ ']; + +class TestRunner { + constructor(name = 'Test Suite') { + this.name = name; + this.tests = []; + this.passed = 0; + this.failed = 0; + this.results = []; + } + + /** + * Register a test + */ + test(testName, testFn) { + this.tests.push({ name: testName, fn: testFn }); + } + + /** + * Assertions + */ + assert(condition, message) { + if (!condition) { + throw new Error(message || 'Assertion failed'); + } + } + + assertEqual(actual, expected, message) { + if (actual !== expected) { + throw new Error(message || `Expected ${expected}, got ${actual}`); + } + } + + + async _runWithTimeout(fn, ctx, timeoutMs) { + return new Promise((resolve, reject) => { + let finished = false; + + const timer = setTimeout(() => { + if (finished) return; + finished = true; + reject(new Error(`Test timed out after ${timeoutMs}ms`)); + }, timeoutMs); + + Promise.resolve() + .then(() => fn(ctx)) + .then((result) => { + if (finished) return; + finished = true; + clearTimeout(timer); + resolve(result); + }) + .catch((err) => { + if (finished) return; + finished = true; + clearTimeout(timer); + reject(err); + }); + }); + } + + + + + /** + * Run all tests + */ + async run(writeOutput) { + const line = (text = '', color = '') => { + writeOutput(`${color}${text}${COLORS.RESET}\n`); + }; + + // Header + line(); + line('โ•”โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•—', COLORS.CYAN + COLORS.BRIGHT); + line(`โ•‘ ๐Ÿงช ${this._padCenter(this.name, 35)} โ”‚`, COLORS.CYAN + COLORS.BRIGHT); + line('โ•šโ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•', COLORS.CYAN + COLORS.BRIGHT); + line(); + + // Run tests with spinner + for (const test of this.tests) { + const stopSpinner = startSpinner( + writeOutput, + `Running ${test.name}...` + ); + + + try { + await delay(500); + + await this._runWithTimeout(test.fn, this, 3000); + + stopSpinner(); + + this.passed++; + this.results.push({ name: test.name, status: 'PASS', error: null }); + 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); + } + + } + + // Summary + line(); + line('โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€', COLORS.GRAY); + + const total = this.tests.length; + const percentage = total + ? ((this.passed / total) * 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 + ); + + line(` Success Rate: ${statusColor}${percentage}%${COLORS.RESET}`, statusColor); + line('โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€', COLORS.GRAY); + line(); + + return this.results; + } + + /** + * Center text helper + */ + _padCenter(text, width) { + const pad = Math.max(0, width - text.length); + return ' '.repeat(Math.floor(pad / 2)) + + text + + ' '.repeat(Math.ceil(pad / 2)); + } +} + +export { TestRunner }; From 04b9e5e46a6d58a601dcfdd9f379fe01eec446be Mon Sep 17 00:00:00 2001 From: Rohit Kushvaha Date: Mon, 12 Jan 2026 14:41:45 +0530 Subject: [PATCH 02/16] Update src/lib/commands.js Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> --- src/lib/commands.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/commands.js b/src/lib/commands.js index b06e3adaa..b32d82695 100644 --- a/src/lib/commands.js +++ b/src/lib/commands.js @@ -36,7 +36,7 @@ import { runAllTests } from "test/tester"; export default { async "run-tests"() { - runAllTests(); + await runAllTests(); }, async "close-all-tabs"() { let save = false; From 367cfcea987ab2dcd12dd42fc5276560da510b1a Mon Sep 17 00:00:00 2001 From: Rohit Kushvaha Date: Mon, 12 Jan 2026 14:42:42 +0530 Subject: [PATCH 03/16] Update src/lib/keyBindings.js Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> --- src/lib/keyBindings.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/keyBindings.js b/src/lib/keyBindings.js index eab2c6b5a..6cd172e43 100644 --- a/src/lib/keyBindings.js +++ b/src/lib/keyBindings.js @@ -704,6 +704,6 @@ export default { description: "Run Tests", key: "Ctrl-T", readOnly: true, - actions: "run-tests" + action: "run-tests" } }; From 0674335e4c9afe2c8ad1c57e85b48e3dfc743eea Mon Sep 17 00:00:00 2001 From: Rohit Kushvaha Date: Mon, 12 Jan 2026 14:43:23 +0530 Subject: [PATCH 04/16] Update src/test/editor.tests.js Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> --- src/test/editor.tests.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/editor.tests.js b/src/test/editor.tests.js index 555c0582d..516ca6298 100644 --- a/src/test/editor.tests.js +++ b/src/test/editor.tests.js @@ -11,7 +11,7 @@ export async function runAceEditorTests(writeOutput) { container = document.createElement('div'); container.style.width = '500px'; container.style.height = '300px'; - container.style.backgroundColor = '#a02f2fff'; + container.style.backgroundColor = '#a02f2f'; document.body.appendChild(container); return ace.edit(container); } From cf039970d88992bf6b563d7502482628b053a1fb Mon Sep 17 00:00:00 2001 From: RohitKushvaha01 Date: Mon, 12 Jan 2026 15:00:28 +0530 Subject: [PATCH 05/16] format --- src/lib/commands.js | 2 +- src/lib/keyBindings.js | 4 +- src/test/editor.tests.js | 393 ++++++++++++++++++------------------ src/test/sanity.tests.js | 118 ++++++----- src/test/tester.js | 415 +++++++++++++++++++-------------------- 5 files changed, 463 insertions(+), 469 deletions(-) diff --git a/src/lib/commands.js b/src/lib/commands.js index b32d82695..162e1e494 100644 --- a/src/lib/commands.js +++ b/src/lib/commands.js @@ -20,6 +20,7 @@ import findFile from "palettes/findFile"; import browser from "plugins/browser"; import help from "settings/helpSettings"; import mainSettings from "settings/mainSettings"; +import { runAllTests } from "test/tester"; import { getColorRange } from "utils/color/regex"; import helpers from "utils/helpers"; import Url from "utils/Url"; @@ -32,7 +33,6 @@ import run from "./run"; import saveState from "./saveState"; import appSettings from "./settings"; import showFileInfo from "./showFileInfo"; -import { runAllTests } from "test/tester"; export default { async "run-tests"() { diff --git a/src/lib/keyBindings.js b/src/lib/keyBindings.js index 6cd172e43..5d1fe9e6d 100644 --- a/src/lib/keyBindings.js +++ b/src/lib/keyBindings.js @@ -704,6 +704,6 @@ export default { description: "Run Tests", key: "Ctrl-T", readOnly: true, - action: "run-tests" - } + action: "run-tests", + }, }; diff --git a/src/test/editor.tests.js b/src/test/editor.tests.js index 516ca6298..cbf7ad5bb 100644 --- a/src/test/editor.tests.js +++ b/src/test/editor.tests.js @@ -1,200 +1,199 @@ -import { TestRunner } from '../tester.js'; +import { TestRunner } from "../tester.js"; export async function runAceEditorTests(writeOutput) { - const runner = new TestRunner('Ace Editor API Tests'); - - let editor; - let container; - - // Helper to create editor safely - function createEditor() { - container = document.createElement('div'); - container.style.width = '500px'; - container.style.height = '300px'; - container.style.backgroundColor = '#a02f2f'; - document.body.appendChild(container); - return ace.edit(container); - } - - // Test 1: Ace is available - runner.test('Ace is loaded', async (test) => { - test.assert(typeof ace !== 'undefined', 'Ace should be available globally'); - test.assert(typeof ace.edit === 'function', 'ace.edit should be a function'); - }); - - // Test 2: Editor creation - runner.test('Editor creation', async (test) => { - editor = createEditor(); - test.assert(editor != null, 'Editor instance should be created'); - test.assert(typeof editor.getSession === 'function', 'Editor should expose getSession'); - }); - - // Test 3: Session access - runner.test('Session access', async (test) => { - const session = editor.getSession(); - test.assert(session != null, 'Editor session should exist'); - test.assert(typeof session.getValue === 'function', 'Session should expose getValue'); - }); - - // Test 4: Set and get value - runner.test('Set and get value', async (test) => { - const text = 'Hello Ace Editor'; - editor.setValue(text, -1); - const value = editor.getValue(); - test.assertEqual(value, text, 'Editor value should match the set value'); - }); - - // Test 5: Cursor movement - runner.test('Cursor movement', async (test) => { - editor.setValue('line1\nline2\nline3', -1); - editor.moveCursorTo(1, 2); - - const pos = editor.getCursorPosition(); - test.assertEqual(pos.row, 1, 'Cursor row should be correct'); - test.assertEqual(pos.column, 2, 'Cursor column should be correct'); - }); - - // Test 6: Selection API - runner.test('Selection handling', async (test) => { - editor.setValue('abc\ndef', -1); - editor.selectAll(); - - const selected = editor.getSelectedText(); - test.assert(selected.length > 0, 'Selected text should not be empty'); - }); - - // Test 7: Undo manager - runner.test('Undo manager works', async (test) => { - const session = editor.getSession(); - const undoManager = session.getUndoManager(); - - session.setValue('one'); - undoManager.reset(); - - editor.insert('\ntwo'); - editor.undo(); - - const value = editor.getValue(); - test.assertEqual(value, 'one', 'Undo should revert last change'); - }); - - - // Test 8: Mode setting - runner.test('Mode setting', async (test) => { - const session = editor.getSession(); - session.setMode('ace/mode/javascript'); - - const mode = session.getMode(); - test.assert( - mode && mode.$id === 'ace/mode/javascript', - 'Editor mode should be JavaScript' - ); - }); - - // Test 9: Theme setting - runner.test('Theme setting', async (test) => { - editor.setTheme('ace/theme/monokai'); - const theme = editor.getTheme(); - test.assert( - theme && theme.includes('monokai'), - 'Editor theme should be monokai' - ); - }); - - - // Test 11: Line count - runner.test('Line count', async (test) => { - editor.setValue('a\nb\nc\nd', -1); - const lines = editor.session.getLength(); - test.assertEqual(lines, 4, 'Editor should report correct number of lines'); - }); - - // Test 12: Replace text - runner.test('Replace text', async (test) => { - editor.setValue('hello world', -1); - editor.find('world'); - editor.replace('ace'); - - const value = editor.getValue(); - test.assertEqual(value, 'hello ace', 'Replace should work correctly'); - }); - - // Test 13: Search API - runner.test('Search API', async (test) => { - editor.setValue('foo bar foo', -1); - editor.find('foo'); - - const range = editor.getSelectionRange(); - test.assert( - range.start.column === 0, - 'Search should select first match' - ); - }); - - // Test 14: Renderer availability - runner.test('Renderer exists', async (test) => { - const renderer = editor.renderer; - test.assert(renderer != null, 'Editor renderer should exist'); - test.assert( - typeof renderer.updateFull === 'function', - 'Renderer should expose updateFull' - ); - }); - - // Test 15: Editor options - runner.test('Editor options', async (test) => { - editor.setOption('showPrintMargin', false); - const value = editor.getOption('showPrintMargin'); - test.assertEqual(value, false, 'Editor option should be applied'); - }); - - // Test 16: Scroll API - runner.test('Scroll API', async (test) => { - editor.setValue(Array(100).fill('line').join('\n'), -1); - editor.scrollToLine(50, true, true, () => { }); - - const firstVisibleRow = editor.renderer.getFirstVisibleRow(); - test.assert( - firstVisibleRow >= 0, - 'Editor should support scrolling' - ); - }); - - // Test 17: Redo manager - runner.test('Redo manager works', (test) => { - const session = editor.getSession(); - const undoManager = session.getUndoManager(); - - session.setValue('one'); - undoManager.reset(); - - session.insert({ row: 0, column: 3 }, '\ntwo'); - - editor.undo(); - editor.redo(); - - const value = editor.getValue(); - test.assertEqual(value, 'one\ntwo', 'Redo should restore undone change'); - }); - - - // Test 18: Focus and blur - runner.test('Focus and blur', async (test) => { - editor.focus(); - test.assert(editor.isFocused(), 'Editor should be focused'); - - editor.blur(); - test.assert(!editor.isFocused(), 'Editor should be blurred'); - }); - - - // Cleanup - runner.test('Cleanup editor', async (test) => { - editor.destroy(); - container.remove(); - test.assert(true, 'Editor destroyed and DOM cleaned'); - }); - - // Run all tests - return await runner.run(writeOutput); + const runner = new TestRunner("Ace Editor API Tests"); + + let editor; + let container; + + // Helper to create editor safely + function createEditor() { + container = document.createElement("div"); + container.style.width = "500px"; + container.style.height = "300px"; + container.style.backgroundColor = "#a02f2f"; + document.body.appendChild(container); + return ace.edit(container); + } + + // Test 1: Ace is available + runner.test("Ace is loaded", async (test) => { + test.assert(typeof ace !== "undefined", "Ace should be available globally"); + test.assert( + typeof ace.edit === "function", + "ace.edit should be a function", + ); + }); + + // Test 2: Editor creation + runner.test("Editor creation", async (test) => { + editor = createEditor(); + test.assert(editor != null, "Editor instance should be created"); + test.assert( + typeof editor.getSession === "function", + "Editor should expose getSession", + ); + }); + + // Test 3: Session access + runner.test("Session access", async (test) => { + const session = editor.getSession(); + test.assert(session != null, "Editor session should exist"); + test.assert( + typeof session.getValue === "function", + "Session should expose getValue", + ); + }); + + // Test 4: Set and get value + runner.test("Set and get value", async (test) => { + const text = "Hello Ace Editor"; + editor.setValue(text, -1); + const value = editor.getValue(); + test.assertEqual(value, text, "Editor value should match the set value"); + }); + + // Test 5: Cursor movement + runner.test("Cursor movement", async (test) => { + editor.setValue("line1\nline2\nline3", -1); + editor.moveCursorTo(1, 2); + + const pos = editor.getCursorPosition(); + test.assertEqual(pos.row, 1, "Cursor row should be correct"); + test.assertEqual(pos.column, 2, "Cursor column should be correct"); + }); + + // Test 6: Selection API + runner.test("Selection handling", async (test) => { + editor.setValue("abc\ndef", -1); + editor.selectAll(); + + const selected = editor.getSelectedText(); + test.assert(selected.length > 0, "Selected text should not be empty"); + }); + + // Test 7: Undo manager + runner.test("Undo manager works", async (test) => { + const session = editor.getSession(); + const undoManager = session.getUndoManager(); + + session.setValue("one"); + undoManager.reset(); + + editor.insert("\ntwo"); + editor.undo(); + + const value = editor.getValue(); + test.assertEqual(value, "one", "Undo should revert last change"); + }); + + // Test 8: Mode setting + runner.test("Mode setting", async (test) => { + const session = editor.getSession(); + session.setMode("ace/mode/javascript"); + + const mode = session.getMode(); + test.assert( + mode && mode.$id === "ace/mode/javascript", + "Editor mode should be JavaScript", + ); + }); + + // Test 9: Theme setting + runner.test("Theme setting", async (test) => { + editor.setTheme("ace/theme/monokai"); + const theme = editor.getTheme(); + test.assert( + theme && theme.includes("monokai"), + "Editor theme should be monokai", + ); + }); + + // Test 11: Line count + runner.test("Line count", async (test) => { + editor.setValue("a\nb\nc\nd", -1); + const lines = editor.session.getLength(); + test.assertEqual(lines, 4, "Editor should report correct number of lines"); + }); + + // Test 12: Replace text + runner.test("Replace text", async (test) => { + editor.setValue("hello world", -1); + editor.find("world"); + editor.replace("ace"); + + const value = editor.getValue(); + test.assertEqual(value, "hello ace", "Replace should work correctly"); + }); + + // Test 13: Search API + runner.test("Search API", async (test) => { + editor.setValue("foo bar foo", -1); + editor.find("foo"); + + const range = editor.getSelectionRange(); + test.assert(range.start.column === 0, "Search should select first match"); + }); + + // Test 14: Renderer availability + runner.test("Renderer exists", async (test) => { + const renderer = editor.renderer; + test.assert(renderer != null, "Editor renderer should exist"); + test.assert( + typeof renderer.updateFull === "function", + "Renderer should expose updateFull", + ); + }); + + // Test 15: Editor options + runner.test("Editor options", async (test) => { + editor.setOption("showPrintMargin", false); + const value = editor.getOption("showPrintMargin"); + test.assertEqual(value, false, "Editor option should be applied"); + }); + + // Test 16: Scroll API + runner.test("Scroll API", async (test) => { + editor.setValue(Array(100).fill("line").join("\n"), -1); + editor.scrollToLine(50, true, true, () => {}); + + const firstVisibleRow = editor.renderer.getFirstVisibleRow(); + test.assert(firstVisibleRow >= 0, "Editor should support scrolling"); + }); + + // Test 17: Redo manager + runner.test("Redo manager works", (test) => { + const session = editor.getSession(); + const undoManager = session.getUndoManager(); + + session.setValue("one"); + undoManager.reset(); + + session.insert({ row: 0, column: 3 }, "\ntwo"); + + editor.undo(); + editor.redo(); + + const value = editor.getValue(); + test.assertEqual(value, "one\ntwo", "Redo should restore undone change"); + }); + + // Test 18: Focus and blur + runner.test("Focus and blur", async (test) => { + editor.focus(); + test.assert(editor.isFocused(), "Editor should be focused"); + + editor.blur(); + test.assert(!editor.isFocused(), "Editor should be blurred"); + }); + + // Cleanup + runner.test("Cleanup editor", async (test) => { + editor.destroy(); + container.remove(); + test.assert(true, "Editor destroyed and DOM cleaned"); + }); + + // Run all tests + return await runner.run(writeOutput); } diff --git a/src/test/sanity.tests.js b/src/test/sanity.tests.js index 82cce39fd..853ea3c9e 100644 --- a/src/test/sanity.tests.js +++ b/src/test/sanity.tests.js @@ -1,73 +1,69 @@ -import { TestRunner } from '../tester.js'; - - +import { TestRunner } from "../tester.js"; export async function runSanityTests(writeOutput) { - const runner = new TestRunner('JS (WebView) Sanity Tests'); - - // Test 1: String operations - runner.test('String concatenation', (test) => { - const result = 'Hello' + ' ' + 'World'; - test.assertEqual(result, 'Hello World', 'String concatenation should work'); - }); - - // Test 2: Number operations - runner.test('Basic arithmetic', (test) => { - const sum = 5 + 3; - test.assertEqual(sum, 8, 'Addition should work correctly'); - }); + const runner = new TestRunner("JS (WebView) Sanity Tests"); - // Test 3: Array operations - runner.test('Array operations', (test) => { + // Test 1: String operations + runner.test("String concatenation", (test) => { + const result = "Hello" + " " + "World"; + test.assertEqual(result, "Hello World", "String concatenation should work"); + }); - const arr = [1, 2, 3]; - test.assertEqual(arr.length, 3, 'Array length should be correct'); - test.assert(arr.includes(2), 'Array should include 2'); - }); + // Test 2: Number operations + runner.test("Basic arithmetic", (test) => { + const sum = 5 + 3; + test.assertEqual(sum, 8, "Addition should work correctly"); + }); - // Test 4: Object operations - runner.test('Object operations', (test) => { - const obj = { name: 'Test', value: 42 }; - test.assertEqual(obj.name, 'Test', 'Object property should be accessible'); - test.assertEqual(obj.value, 42, 'Object value should be correct'); - }); + // Test 3: Array operations + runner.test("Array operations", (test) => { + const arr = [1, 2, 3]; + test.assertEqual(arr.length, 3, "Array length should be correct"); + test.assert(arr.includes(2), "Array should include 2"); + }); - // Test 5: Function execution - runner.test('Function execution', (test) => { - const add = (a, b) => a + b; - const result = add(10, 20); - test.assertEqual(result, 30, 'Function should return correct value'); - }); + // Test 4: Object operations + runner.test("Object operations", (test) => { + const obj = { name: "Test", value: 42 }; + test.assertEqual(obj.name, "Test", "Object property should be accessible"); + test.assertEqual(obj.value, 42, "Object value should be correct"); + }); - // Test 6: Async function - runner.test('Async function handling', async (test) => { - const asyncFunc = async () => { - return new Promise((resolve) => { - setTimeout(() => resolve('done'), 10); - }); - }; + // Test 5: Function execution + runner.test("Function execution", (test) => { + const add = (a, b) => a + b; + const result = add(10, 20); + test.assertEqual(result, 30, "Function should return correct value"); + }); - const result = await asyncFunc(); - test.assertEqual(result, 'done', 'Async function should work correctly'); - }); + // Test 6: Async function + runner.test("Async function handling", async (test) => { + const asyncFunc = async () => { + return new Promise((resolve) => { + setTimeout(() => resolve("done"), 10); + }); + }; + const result = await asyncFunc(); + test.assertEqual(result, "done", "Async function should work correctly"); + }); - // Test 7: Error handling - runner.test('Error handling', (test) => { - try { - throw new Error('Test error'); - } catch (e) { - test.assert(e instanceof Error, 'Should catch Error instances'); - } - }); + // Test 7: Error handling + runner.test("Error handling", (test) => { + try { + throw new Error("Test error"); + } catch (e) { + test.assert(e instanceof Error, "Should catch Error instances"); + } + }); - // Test 8: Conditional logic - runner.test('Conditional logic', (test) => { - const value = 10; - test.assert(value > 5, 'Condition should be true'); - test.assert(!(value < 5), 'Negation should work'); - }); + // Test 8: Conditional logic + runner.test("Conditional logic", (test) => { + const value = 10; + test.assert(value > 5, "Condition should be true"); + test.assert(!(value < 5), "Negation should work"); + }); - // Run all tests - return await runner.run(writeOutput); -} \ No newline at end of file + // Run all tests + return await runner.run(writeOutput); +} diff --git a/src/test/tester.js b/src/test/tester.js index e86bb37cb..1a120aaa0 100644 --- a/src/test/tester.js +++ b/src/test/tester.js @@ -3,230 +3,229 @@ * Tests execute at plugin initialization and print results to terminal */ - - - - - export async function runAllTests() { - const terminal = acode.require('terminal'); - const local = await terminal.createLocal({ name: 'TestCode' }); - function write(data) { - terminal.write(local.id, data); - } - - // Run tests at runtime - write('\x1b[36m\x1b[1m๐Ÿš€ TestCode Plugin Loaded\x1b[0m\n'); - write('\x1b[36m\x1b[1mStarting test execution...\x1b[0m\n'); - - try { - // Run unit tests - await runSanityTests(write); - await runAceEditorTests(write); - - - write('\x1b[36m\x1b[1mTests completed!\x1b[0m\n'); - } catch (error) { - write(`\x1b[31mโš ๏ธ Test execution error: ${error.message}\x1b[0m\n`); - } + const terminal = acode.require("terminal"); + const local = await terminal.createLocal({ name: "TestCode" }); + function write(data) { + terminal.write(local.id, data); + } + + // Run tests at runtime + write("\x1b[36m\x1b[1m๐Ÿš€ TestCode Plugin Loaded\x1b[0m\n"); + write("\x1b[36m\x1b[1mStarting test execution...\x1b[0m\n"); + + try { + // Run unit tests + await runSanityTests(write); + await runAceEditorTests(write); + + write("\x1b[36m\x1b[1mTests completed!\x1b[0m\n"); + } catch (error) { + write(`\x1b[31mโš ๏ธ Test execution error: ${error.message}\x1b[0m\n`); + } } - - - - // ANSI color codes for terminal output const COLORS = { - RESET: '\x1b[0m', - BRIGHT: '\x1b[1m', - DIM: '\x1b[2m', - ITALIC: '\x1b[3m', - - // Foreground colors - RED: '\x1b[31m', - GREEN: '\x1b[32m', - YELLOW: '\x1b[33m', - BLUE: '\x1b[34m', - MAGENTA: '\x1b[35m', - CYAN: '\x1b[36m', - WHITE: '\x1b[37m', - GRAY: '\x1b[90m', - - // Background colors - BG_RED: '\x1b[41m', - BG_GREEN: '\x1b[42m', - BG_YELLOW: '\x1b[43m', - BG_BLUE: '\x1b[44m', + RESET: "\x1b[0m", + BRIGHT: "\x1b[1m", + DIM: "\x1b[2m", + ITALIC: "\x1b[3m", + + // Foreground colors + RED: "\x1b[31m", + GREEN: "\x1b[32m", + YELLOW: "\x1b[33m", + BLUE: "\x1b[34m", + MAGENTA: "\x1b[35m", + CYAN: "\x1b[36m", + WHITE: "\x1b[37m", + GRAY: "\x1b[90m", + + // Background colors + BG_RED: "\x1b[41m", + BG_GREEN: "\x1b[42m", + BG_YELLOW: "\x1b[43m", + BG_BLUE: "\x1b[44m", }; function delay(ms) { - return new Promise(resolve => setTimeout(resolve, ms)); + return new Promise((resolve) => setTimeout(resolve, ms)); } function startSpinner(writeOutput, text) { - let index = 0; - let active = true; - - const timer = setInterval(() => { - if (!active) return; - const frame = SPINNER_FRAMES[index++ % SPINNER_FRAMES.length]; - // \r moves cursor to start, \x1b[K clears the line to the right - writeOutput(`\r ${COLORS.CYAN}${frame}${COLORS.RESET} ${text}`); - }, 80); - - return () => { - active = false; - clearInterval(timer); - // Clear the line so the "Success/Fail" message can take its place - writeOutput('\r\x1b[K'); - }; + let index = 0; + let active = true; + + const timer = setInterval(() => { + if (!active) return; + const frame = SPINNER_FRAMES[index++ % SPINNER_FRAMES.length]; + // \r moves cursor to start, \x1b[K clears the line to the right + writeOutput(`\r ${COLORS.CYAN}${frame}${COLORS.RESET} ${text}`); + }, 80); + + return () => { + active = false; + clearInterval(timer); + // Clear the line so the "Success/Fail" message can take its place + writeOutput("\r\x1b[K"); + }; } - // Spinner frames -const SPINNER_FRAMES = ['โ ‹', 'โ ™', 'โ น', 'โ ธ', 'โ ผ', 'โ ด', 'โ ฆ', 'โ ง', 'โ ‡', 'โ ']; +const SPINNER_FRAMES = ["โ ‹", "โ ™", "โ น", "โ ธ", "โ ผ", "โ ด", "โ ฆ", "โ ง", "โ ‡", "โ "]; class TestRunner { - constructor(name = 'Test Suite') { - this.name = name; - this.tests = []; - this.passed = 0; - this.failed = 0; - this.results = []; - } - - /** - * Register a test - */ - test(testName, testFn) { - this.tests.push({ name: testName, fn: testFn }); - } - - /** - * Assertions - */ - assert(condition, message) { - if (!condition) { - throw new Error(message || 'Assertion failed'); - } - } - - assertEqual(actual, expected, message) { - if (actual !== expected) { - throw new Error(message || `Expected ${expected}, got ${actual}`); - } - } - - - async _runWithTimeout(fn, ctx, timeoutMs) { - return new Promise((resolve, reject) => { - let finished = false; - - const timer = setTimeout(() => { - if (finished) return; - finished = true; - reject(new Error(`Test timed out after ${timeoutMs}ms`)); - }, timeoutMs); - - Promise.resolve() - .then(() => fn(ctx)) - .then((result) => { - if (finished) return; - finished = true; - clearTimeout(timer); - resolve(result); - }) - .catch((err) => { - if (finished) return; - finished = true; - clearTimeout(timer); - reject(err); - }); - }); - } - - - - - /** - * Run all tests - */ - async run(writeOutput) { - const line = (text = '', color = '') => { - writeOutput(`${color}${text}${COLORS.RESET}\n`); - }; - - // Header - line(); - line('โ•”โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•—', COLORS.CYAN + COLORS.BRIGHT); - line(`โ•‘ ๐Ÿงช ${this._padCenter(this.name, 35)} โ”‚`, COLORS.CYAN + COLORS.BRIGHT); - line('โ•šโ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•', COLORS.CYAN + COLORS.BRIGHT); - line(); - - // Run tests with spinner - for (const test of this.tests) { - const stopSpinner = startSpinner( - writeOutput, - `Running ${test.name}...` - ); - - - try { - await delay(500); - - await this._runWithTimeout(test.fn, this, 3000); - - stopSpinner(); - - this.passed++; - this.results.push({ name: test.name, status: 'PASS', error: null }); - 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); - } - - } - - // Summary - line(); - line('โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€', COLORS.GRAY); - - const total = this.tests.length; - const percentage = total - ? ((this.passed / total) * 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 - ); - - line(` Success Rate: ${statusColor}${percentage}%${COLORS.RESET}`, statusColor); - line('โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€', COLORS.GRAY); - line(); - - return this.results; - } - - /** - * Center text helper - */ - _padCenter(text, width) { - const pad = Math.max(0, width - text.length); - return ' '.repeat(Math.floor(pad / 2)) + - text + - ' '.repeat(Math.ceil(pad / 2)); - } + constructor(name = "Test Suite") { + this.name = name; + this.tests = []; + this.passed = 0; + this.failed = 0; + this.results = []; + } + + /** + * Register a test + */ + test(testName, testFn) { + this.tests.push({ name: testName, fn: testFn }); + } + + /** + * Assertions + */ + assert(condition, message) { + if (!condition) { + throw new Error(message || "Assertion failed"); + } + } + + assertEqual(actual, expected, message) { + if (actual !== expected) { + throw new Error(message || `Expected ${expected}, got ${actual}`); + } + } + + async _runWithTimeout(fn, ctx, timeoutMs) { + return new Promise((resolve, reject) => { + let finished = false; + + const timer = setTimeout(() => { + if (finished) return; + finished = true; + reject(new Error(`Test timed out after ${timeoutMs}ms`)); + }, timeoutMs); + + Promise.resolve() + .then(() => fn(ctx)) + .then((result) => { + if (finished) return; + finished = true; + clearTimeout(timer); + resolve(result); + }) + .catch((err) => { + if (finished) return; + finished = true; + clearTimeout(timer); + reject(err); + }); + }); + } + + /** + * Run all tests + */ + async run(writeOutput) { + const line = (text = "", color = "") => { + writeOutput(`${color}${text}${COLORS.RESET}\n`); + }; + + // Header + line(); + line( + "โ•”โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•—", + COLORS.CYAN + COLORS.BRIGHT, + ); + line( + `โ•‘ ๐Ÿงช ${this._padCenter(this.name, 35)} โ”‚`, + COLORS.CYAN + COLORS.BRIGHT, + ); + line( + "โ•šโ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•", + COLORS.CYAN + COLORS.BRIGHT, + ); + line(); + + // Run tests with spinner + for (const test of this.tests) { + const stopSpinner = startSpinner(writeOutput, `Running ${test.name}...`); + + try { + await delay(500); + + await this._runWithTimeout(test.fn, this, 3000); + + stopSpinner(); + + this.passed++; + this.results.push({ name: test.name, status: "PASS", error: null }); + 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, + ); + } + } + + // Summary + line(); + line("โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€", COLORS.GRAY); + + const total = this.tests.length; + const percentage = total ? ((this.passed / total) * 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, + ); + + line( + ` Success Rate: ${statusColor}${percentage}%${COLORS.RESET}`, + statusColor, + ); + line("โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€", COLORS.GRAY); + line(); + + return this.results; + } + + /** + * Center text helper + */ + _padCenter(text, width) { + const pad = Math.max(0, width - text.length); + return ( + " ".repeat(Math.floor(pad / 2)) + text + " ".repeat(Math.ceil(pad / 2)) + ); + } } export { TestRunner }; From 8caa7cee486056e3e85db8cc4dc5272fe8ba9d13 Mon Sep 17 00:00:00 2001 From: RohitKushvaha01 Date: Mon, 12 Jan 2026 15:05:08 +0530 Subject: [PATCH 06/16] fix: bugs --- src/lib/keyBindings.js | 3 --- src/test/editor.tests.js | 2 +- src/test/sanity.tests.js | 2 +- src/test/tester.js | 10 ++++------ 4 files changed, 6 insertions(+), 11 deletions(-) diff --git a/src/lib/keyBindings.js b/src/lib/keyBindings.js index 5d1fe9e6d..8c0995818 100644 --- a/src/lib/keyBindings.js +++ b/src/lib/keyBindings.js @@ -1,6 +1,3 @@ -import { description } from "components/quickTools/items"; -import actions, { key } from "handlers/quickTools"; - export default { focusEditor: { description: "Focus editor", diff --git a/src/test/editor.tests.js b/src/test/editor.tests.js index cbf7ad5bb..e8cfa22fb 100644 --- a/src/test/editor.tests.js +++ b/src/test/editor.tests.js @@ -1,4 +1,4 @@ -import { TestRunner } from "../tester.js"; +import { TestRunner } from "./tester"; export async function runAceEditorTests(writeOutput) { const runner = new TestRunner("Ace Editor API Tests"); diff --git a/src/test/sanity.tests.js b/src/test/sanity.tests.js index 853ea3c9e..28bc84355 100644 --- a/src/test/sanity.tests.js +++ b/src/test/sanity.tests.js @@ -1,4 +1,4 @@ -import { TestRunner } from "../tester.js"; +import { TestRunner } from "./tester"; export async function runSanityTests(writeOutput) { const runner = new TestRunner("JS (WebView) Sanity Tests"); diff --git a/src/test/tester.js b/src/test/tester.js index 1a120aaa0..9e1057250 100644 --- a/src/test/tester.js +++ b/src/test/tester.js @@ -1,7 +1,5 @@ -/** - * Runtime Test Suite for Acode Plugin - * Tests execute at plugin initialization and print results to terminal - */ +import { runAceEditorTests } from "./editor.tests"; +import { runSanityTests } from "./sanity.tests"; export async function runAllTests() { const terminal = acode.require("terminal"); @@ -16,8 +14,8 @@ export async function runAllTests() { try { // Run unit tests - await runSanityTests(write); - await runAceEditorTests(write); + await runSanityTests(); + await runAceEditorTests(); write("\x1b[36m\x1b[1mTests completed!\x1b[0m\n"); } catch (error) { From dcf0f3971be16c1eb0d1dd2f478308f9d2b07acd Mon Sep 17 00:00:00 2001 From: RohitKushvaha01 Date: Mon, 12 Jan 2026 15:06:19 +0530 Subject: [PATCH 07/16] fix: write arg --- src/test/tester.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/test/tester.js b/src/test/tester.js index 9e1057250..4182479e4 100644 --- a/src/test/tester.js +++ b/src/test/tester.js @@ -14,8 +14,8 @@ export async function runAllTests() { try { // Run unit tests - await runSanityTests(); - await runAceEditorTests(); + await runSanityTests(write); + await runAceEditorTests(write); write("\x1b[36m\x1b[1mTests completed!\x1b[0m\n"); } catch (error) { @@ -200,8 +200,8 @@ class TestRunner { line( ` Tests: ${COLORS.BRIGHT}${total}${COLORS.RESET} | ` + - `${statusColor}Passed: ${this.passed}${COLORS.RESET} | ` + - `${COLORS.RED}Failed: ${this.failed}${COLORS.RESET}`, + `${statusColor}Passed: ${this.passed}${COLORS.RESET} | ` + + `${COLORS.RED}Failed: ${this.failed}${COLORS.RESET}`, statusColor, ); From d51b7905df86a5e81b63eff991d8ae41b0c67c55 Mon Sep 17 00:00:00 2001 From: RohitKushvaha01 Date: Mon, 12 Jan 2026 15:28:10 +0530 Subject: [PATCH 08/16] feat: add to command palatte --- src/ace/commands.js | 8 ++++++++ src/lib/keyBindings.js | 2 +- src/test/tester.js | 6 +++--- 3 files changed, 12 insertions(+), 4 deletions(-) diff --git a/src/ace/commands.js b/src/ace/commands.js index e917fd847..dcb707a51 100644 --- a/src/ace/commands.js +++ b/src/ace/commands.js @@ -357,6 +357,14 @@ const commands = [ }, readOnly: true, }, + { + name: "run-tests", + description: "Run Tests", + exec() { + acode.exec("run-tests"); + }, + readOnly: true, + }, ]; export function setCommands(editor) { diff --git a/src/lib/keyBindings.js b/src/lib/keyBindings.js index 8c0995818..4d2ab68e3 100644 --- a/src/lib/keyBindings.js +++ b/src/lib/keyBindings.js @@ -697,7 +697,7 @@ export default { readOnly: true, action: "new-terminal", }, - runTests: { + "run-tests": { description: "Run Tests", key: "Ctrl-T", readOnly: true, diff --git a/src/test/tester.js b/src/test/tester.js index 4182479e4..e936a7534 100644 --- a/src/test/tester.js +++ b/src/test/tester.js @@ -160,7 +160,7 @@ class TestRunner { const stopSpinner = startSpinner(writeOutput, `Running ${test.name}...`); try { - await delay(500); + await delay(300); await this._runWithTimeout(test.fn, this, 3000); @@ -200,8 +200,8 @@ class TestRunner { line( ` Tests: ${COLORS.BRIGHT}${total}${COLORS.RESET} | ` + - `${statusColor}Passed: ${this.passed}${COLORS.RESET} | ` + - `${COLORS.RED}Failed: ${this.failed}${COLORS.RESET}`, + `${statusColor}Passed: ${this.passed}${COLORS.RESET} | ` + + `${COLORS.RED}Failed: ${this.failed}${COLORS.RESET}`, statusColor, ); From 689587c6b06f02567d175c3daa0f703fb9012b4a Mon Sep 17 00:00:00 2001 From: RohitKushvaha01 Date: Mon, 12 Jan 2026 15:50:54 +0530 Subject: [PATCH 09/16] feat: use a saperate editor instance for every test --- src/test/editor.tests.js | 210 +++++++++++++++++++++------------------ src/test/tester.js | 6 +- 2 files changed, 117 insertions(+), 99 deletions(-) diff --git a/src/test/editor.tests.js b/src/test/editor.tests.js index e8cfa22fb..4bdad0428 100644 --- a/src/test/editor.tests.js +++ b/src/test/editor.tests.js @@ -3,17 +3,30 @@ import { TestRunner } from "./tester"; export async function runAceEditorTests(writeOutput) { const runner = new TestRunner("Ace Editor API Tests"); - let editor; - let container; - - // Helper to create editor safely function createEditor() { - container = document.createElement("div"); + const container = document.createElement("div"); container.style.width = "500px"; container.style.height = "300px"; container.style.backgroundColor = "#a02f2f"; document.body.appendChild(container); - return ace.edit(container); + + const editor = ace.edit(container); + return { editor, container }; + } + + async function withEditor(test, fn) { + let editor, container; + + try { + ({ editor, container } = createEditor()); + test.assert(editor != null, "Editor instance should be created"); + await new Promise((resolve) => setTimeout(resolve, 100)); + await fn(editor); + await new Promise((resolve) => setTimeout(resolve, 200)); + } finally { + if (editor) editor.destroy(); + if (container) container.remove(); + } } // Test 1: Ace is available @@ -27,173 +40,178 @@ export async function runAceEditorTests(writeOutput) { // Test 2: Editor creation runner.test("Editor creation", async (test) => { - editor = createEditor(); + const { editor, container } = createEditor(); test.assert(editor != null, "Editor instance should be created"); test.assert( typeof editor.getSession === "function", "Editor should expose getSession", ); + editor.destroy(); + container.remove(); }); // Test 3: Session access runner.test("Session access", async (test) => { - const session = editor.getSession(); - test.assert(session != null, "Editor session should exist"); - test.assert( - typeof session.getValue === "function", - "Session should expose getValue", - ); + await withEditor(test, async (editor) => { + const session = editor.getSession(); + test.assert(session != null, "Editor session should exist"); + test.assert( + typeof session.getValue === "function", + "Session should expose getValue", + ); + }); }); // Test 4: Set and get value runner.test("Set and get value", async (test) => { - const text = "Hello Ace Editor"; - editor.setValue(text, -1); - const value = editor.getValue(); - test.assertEqual(value, text, "Editor value should match the set value"); + await withEditor(test, async (editor) => { + const text = "Hello Ace Editor"; + editor.setValue(text, -1); + test.assertEqual(editor.getValue(), text); + }); }); // Test 5: Cursor movement runner.test("Cursor movement", async (test) => { - editor.setValue("line1\nline2\nline3", -1); - editor.moveCursorTo(1, 2); + await withEditor(test, async (editor) => { + editor.setValue("line1\nline2\nline3", -1); + editor.moveCursorTo(1, 2); - const pos = editor.getCursorPosition(); - test.assertEqual(pos.row, 1, "Cursor row should be correct"); - test.assertEqual(pos.column, 2, "Cursor column should be correct"); + const pos = editor.getCursorPosition(); + test.assertEqual(pos.row, 1); + test.assertEqual(pos.column, 2); + }); }); // Test 6: Selection API runner.test("Selection handling", async (test) => { - editor.setValue("abc\ndef", -1); - editor.selectAll(); - - const selected = editor.getSelectedText(); - test.assert(selected.length > 0, "Selected text should not be empty"); + await withEditor(test, async (editor) => { + editor.setValue("abc\ndef", -1); + editor.selectAll(); + test.assert(editor.getSelectedText().length > 0); + }); }); // Test 7: Undo manager runner.test("Undo manager works", async (test) => { - const session = editor.getSession(); - const undoManager = session.getUndoManager(); + await withEditor(test, async (editor) => { + const session = editor.getSession(); + const undoManager = session.getUndoManager(); - session.setValue("one"); - undoManager.reset(); + session.setValue("one"); + undoManager.reset(); - editor.insert("\ntwo"); - editor.undo(); + editor.insert("\ntwo"); + editor.undo(); - const value = editor.getValue(); - test.assertEqual(value, "one", "Undo should revert last change"); + test.assertEqual(editor.getValue(), "one"); + }); }); // Test 8: Mode setting runner.test("Mode setting", async (test) => { - const session = editor.getSession(); - session.setMode("ace/mode/javascript"); + await withEditor(test, async (editor) => { + const session = editor.getSession(); + session.setMode("ace/mode/javascript"); - const mode = session.getMode(); - test.assert( - mode && mode.$id === "ace/mode/javascript", - "Editor mode should be JavaScript", - ); + const mode = session.getMode(); + test.assert(mode && mode.$id === "ace/mode/javascript"); + }); }); // Test 9: Theme setting runner.test("Theme setting", async (test) => { - editor.setTheme("ace/theme/monokai"); - const theme = editor.getTheme(); - test.assert( - theme && theme.includes("monokai"), - "Editor theme should be monokai", - ); + await withEditor(test, async (editor) => { + editor.setTheme("ace/theme/monokai"); + test.assert(editor.getTheme().includes("monokai")); + }); }); // Test 11: Line count runner.test("Line count", async (test) => { - editor.setValue("a\nb\nc\nd", -1); - const lines = editor.session.getLength(); - test.assertEqual(lines, 4, "Editor should report correct number of lines"); + await withEditor(test, async (editor) => { + editor.setValue("a\nb\nc\nd", -1); + test.assertEqual(editor.session.getLength(), 4); + }); }); // Test 12: Replace text runner.test("Replace text", async (test) => { - editor.setValue("hello world", -1); - editor.find("world"); - editor.replace("ace"); + await withEditor(test, async (editor) => { + editor.setValue("hello world", -1); + editor.find("world"); + editor.replace("ace"); - const value = editor.getValue(); - test.assertEqual(value, "hello ace", "Replace should work correctly"); + test.assertEqual(editor.getValue(), "hello ace"); + }); }); // Test 13: Search API runner.test("Search API", async (test) => { - editor.setValue("foo bar foo", -1); - editor.find("foo"); + await withEditor(test, async (editor) => { + editor.setValue("foo bar foo", -1); + editor.find("foo"); - const range = editor.getSelectionRange(); - test.assert(range.start.column === 0, "Search should select first match"); + const range = editor.getSelectionRange(); + test.assert(range.start.column === 0); + }); }); // Test 14: Renderer availability runner.test("Renderer exists", async (test) => { - const renderer = editor.renderer; - test.assert(renderer != null, "Editor renderer should exist"); - test.assert( - typeof renderer.updateFull === "function", - "Renderer should expose updateFull", - ); + await withEditor(test, async (editor) => { + const renderer = editor.renderer; + test.assert(renderer != null); + test.assert(typeof renderer.updateFull === "function"); + }); }); // Test 15: Editor options runner.test("Editor options", async (test) => { - editor.setOption("showPrintMargin", false); - const value = editor.getOption("showPrintMargin"); - test.assertEqual(value, false, "Editor option should be applied"); + await withEditor(test, async (editor) => { + editor.setOption("showPrintMargin", false); + test.assertEqual(editor.getOption("showPrintMargin"), false); + }); }); // Test 16: Scroll API runner.test("Scroll API", async (test) => { - editor.setValue(Array(100).fill("line").join("\n"), -1); - editor.scrollToLine(50, true, true, () => {}); + await withEditor(test, async (editor) => { + editor.setValue(Array(100).fill("line").join("\n"), -1); + editor.scrollToLine(50, true, true, () => { }); - const firstVisibleRow = editor.renderer.getFirstVisibleRow(); - test.assert(firstVisibleRow >= 0, "Editor should support scrolling"); + const firstVisibleRow = editor.renderer.getFirstVisibleRow(); + test.assert(firstVisibleRow >= 0); + }); }); // Test 17: Redo manager - runner.test("Redo manager works", (test) => { - const session = editor.getSession(); - const undoManager = session.getUndoManager(); + runner.test("Redo manager works", async (test) => { + await withEditor(test, async (editor) => { + const session = editor.getSession(); + const undoManager = session.getUndoManager(); - session.setValue("one"); - undoManager.reset(); + session.setValue("one"); + undoManager.reset(); - session.insert({ row: 0, column: 3 }, "\ntwo"); + session.insert({ row: 0, column: 3 }, "\ntwo"); + editor.undo(); + editor.redo(); - editor.undo(); - editor.redo(); - - const value = editor.getValue(); - test.assertEqual(value, "one\ntwo", "Redo should restore undone change"); + test.assertEqual(editor.getValue(), "one\ntwo"); + }); }); // Test 18: Focus and blur runner.test("Focus and blur", async (test) => { - editor.focus(); - test.assert(editor.isFocused(), "Editor should be focused"); - - editor.blur(); - test.assert(!editor.isFocused(), "Editor should be blurred"); - }); + await withEditor(test, async (editor) => { + editor.focus(); + test.assert(editor.isFocused()); - // Cleanup - runner.test("Cleanup editor", async (test) => { - editor.destroy(); - container.remove(); - test.assert(true, "Editor destroyed and DOM cleaned"); + editor.blur(); + test.assert(!editor.isFocused()); + }); }); - // Run all tests return await runner.run(writeOutput); } diff --git a/src/test/tester.js b/src/test/tester.js index e936a7534..a298487b4 100644 --- a/src/test/tester.js +++ b/src/test/tester.js @@ -160,7 +160,7 @@ class TestRunner { const stopSpinner = startSpinner(writeOutput, `Running ${test.name}...`); try { - await delay(300); + await delay(200); await this._runWithTimeout(test.fn, this, 3000); @@ -200,8 +200,8 @@ class TestRunner { line( ` Tests: ${COLORS.BRIGHT}${total}${COLORS.RESET} | ` + - `${statusColor}Passed: ${this.passed}${COLORS.RESET} | ` + - `${COLORS.RED}Failed: ${this.failed}${COLORS.RESET}`, + `${statusColor}Passed: ${this.passed}${COLORS.RESET} | ` + + `${COLORS.RED}Failed: ${this.failed}${COLORS.RESET}`, statusColor, ); From d3d08bf5609a037f3a05c7a5a17ddae2c955dadb Mon Sep 17 00:00:00 2001 From: RohitKushvaha01 Date: Mon, 12 Jan 2026 15:51:28 +0530 Subject: [PATCH 10/16] format --- src/test/editor.tests.js | 2 +- src/test/tester.js | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/test/editor.tests.js b/src/test/editor.tests.js index 4bdad0428..d48b07973 100644 --- a/src/test/editor.tests.js +++ b/src/test/editor.tests.js @@ -178,7 +178,7 @@ export async function runAceEditorTests(writeOutput) { runner.test("Scroll API", async (test) => { await withEditor(test, async (editor) => { editor.setValue(Array(100).fill("line").join("\n"), -1); - editor.scrollToLine(50, true, true, () => { }); + editor.scrollToLine(50, true, true, () => {}); const firstVisibleRow = editor.renderer.getFirstVisibleRow(); test.assert(firstVisibleRow >= 0); diff --git a/src/test/tester.js b/src/test/tester.js index a298487b4..a51206523 100644 --- a/src/test/tester.js +++ b/src/test/tester.js @@ -200,8 +200,8 @@ class TestRunner { line( ` Tests: ${COLORS.BRIGHT}${total}${COLORS.RESET} | ` + - `${statusColor}Passed: ${this.passed}${COLORS.RESET} | ` + - `${COLORS.RED}Failed: ${this.failed}${COLORS.RESET}`, + `${statusColor}Passed: ${this.passed}${COLORS.RESET} | ` + + `${COLORS.RED}Failed: ${this.failed}${COLORS.RESET}`, statusColor, ); From 62ba88895080920a4937f11aca5c9ac67a76f9a1 Mon Sep 17 00:00:00 2001 From: Rohit Kushvaha Date: Mon, 12 Jan 2026 16:05:22 +0530 Subject: [PATCH 11/16] Update src/test/editor.tests.js Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com> --- src/test/editor.tests.js | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/src/test/editor.tests.js b/src/test/editor.tests.js index d48b07973..4f9cc9952 100644 --- a/src/test/editor.tests.js +++ b/src/test/editor.tests.js @@ -18,16 +18,30 @@ export async function runAceEditorTests(writeOutput) { let editor, container; try { - ({ editor, container } = createEditor()); + const result = createEditor(); + editor = result.editor; + container = result.container; test.assert(editor != null, "Editor instance should be created"); await new Promise((resolve) => setTimeout(resolve, 100)); await fn(editor); await new Promise((resolve) => setTimeout(resolve, 200)); + } catch (error) { + // Re-throw to let test runner handle it + throw error; } finally { - if (editor) editor.destroy(); - if (container) container.remove(); + try { + if (editor) editor.destroy(); + } catch (cleanupError) { + console.warn("Failed to destroy editor:", cleanupError); + } + try { + if (container && container.parentNode) container.remove(); + } catch (cleanupError) { + console.warn("Failed to remove container:", cleanupError); + } } } + } // Test 1: Ace is available runner.test("Ace is loaded", async (test) => { From e5fe7d5485c352dab149d867fe97e08e570c841d Mon Sep 17 00:00:00 2001 From: Rohit Kushvaha Date: Mon, 12 Jan 2026 16:06:26 +0530 Subject: [PATCH 12/16] Update src/test/editor.tests.js Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com> --- src/test/editor.tests.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/test/editor.tests.js b/src/test/editor.tests.js index 4f9cc9952..99a3bb2a4 100644 --- a/src/test/editor.tests.js +++ b/src/test/editor.tests.js @@ -167,7 +167,11 @@ export async function runAceEditorTests(writeOutput) { editor.find("foo"); const range = editor.getSelectionRange(); - test.assert(range.start.column === 0); + const range = editor.getSelectionRange(); + test.assert(range.start.row === 0, "Selection should be on first row"); + test.assert(range.start.column === 0, "Selection should start at column 0"); + test.assert(range.end.column === 3, "Selection should end at column 3 (length of 'foo')"); + test.assertEqual(editor.getSelectedText(), "foo", "Should select 'foo'"); }); }); From d12a4cc56c3638b3f5ce95fddd391a26b7d299d2 Mon Sep 17 00:00:00 2001 From: Rohit Kushvaha Date: Mon, 12 Jan 2026 16:08:18 +0530 Subject: [PATCH 13/16] Update src/test/editor.tests.js Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com> --- src/test/editor.tests.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/test/editor.tests.js b/src/test/editor.tests.js index 99a3bb2a4..55fbb1b65 100644 --- a/src/test/editor.tests.js +++ b/src/test/editor.tests.js @@ -44,8 +44,7 @@ export async function runAceEditorTests(writeOutput) { } // Test 1: Ace is available - runner.test("Ace is loaded", async (test) => { - test.assert(typeof ace !== "undefined", "Ace should be available globally"); + test.assert(typeof ace === "object" && ace !== null, "Ace should be available globally as an object"); test.assert( typeof ace.edit === "function", "ace.edit should be a function", From 1326145f9af63857ad9f0cdef429f081b016bfb6 Mon Sep 17 00:00:00 2001 From: RohitKushvaha01 Date: Mon, 12 Jan 2026 16:09:36 +0530 Subject: [PATCH 14/16] feat:change keybind --- src/lib/keyBindings.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/keyBindings.js b/src/lib/keyBindings.js index 4d2ab68e3..f09f4d600 100644 --- a/src/lib/keyBindings.js +++ b/src/lib/keyBindings.js @@ -699,7 +699,7 @@ export default { }, "run-tests": { description: "Run Tests", - key: "Ctrl-T", + key: "Ctrl-Shift-T", readOnly: true, action: "run-tests", }, From 583d683b411339fb59bf632ed27ed8deccca2283 Mon Sep 17 00:00:00 2001 From: RohitKushvaha01 Date: Mon, 12 Jan 2026 16:12:47 +0530 Subject: [PATCH 15/16] revert: ai chnages --- src/test/editor.tests.js | 31 +++++++------------------------ 1 file changed, 7 insertions(+), 24 deletions(-) diff --git a/src/test/editor.tests.js b/src/test/editor.tests.js index 55fbb1b65..4bdad0428 100644 --- a/src/test/editor.tests.js +++ b/src/test/editor.tests.js @@ -18,33 +18,20 @@ export async function runAceEditorTests(writeOutput) { let editor, container; try { - const result = createEditor(); - editor = result.editor; - container = result.container; + ({ editor, container } = createEditor()); test.assert(editor != null, "Editor instance should be created"); await new Promise((resolve) => setTimeout(resolve, 100)); await fn(editor); await new Promise((resolve) => setTimeout(resolve, 200)); - } catch (error) { - // Re-throw to let test runner handle it - throw error; } finally { - try { - if (editor) editor.destroy(); - } catch (cleanupError) { - console.warn("Failed to destroy editor:", cleanupError); - } - try { - if (container && container.parentNode) container.remove(); - } catch (cleanupError) { - console.warn("Failed to remove container:", cleanupError); - } + if (editor) editor.destroy(); + if (container) container.remove(); } } - } // Test 1: Ace is available - test.assert(typeof ace === "object" && ace !== null, "Ace should be available globally as an object"); + runner.test("Ace is loaded", async (test) => { + test.assert(typeof ace !== "undefined", "Ace should be available globally"); test.assert( typeof ace.edit === "function", "ace.edit should be a function", @@ -166,11 +153,7 @@ export async function runAceEditorTests(writeOutput) { editor.find("foo"); const range = editor.getSelectionRange(); - const range = editor.getSelectionRange(); - test.assert(range.start.row === 0, "Selection should be on first row"); - test.assert(range.start.column === 0, "Selection should start at column 0"); - test.assert(range.end.column === 3, "Selection should end at column 3 (length of 'foo')"); - test.assertEqual(editor.getSelectedText(), "foo", "Should select 'foo'"); + test.assert(range.start.column === 0); }); }); @@ -195,7 +178,7 @@ export async function runAceEditorTests(writeOutput) { runner.test("Scroll API", async (test) => { await withEditor(test, async (editor) => { editor.setValue(Array(100).fill("line").join("\n"), -1); - editor.scrollToLine(50, true, true, () => {}); + editor.scrollToLine(50, true, true, () => { }); const firstVisibleRow = editor.renderer.getFirstVisibleRow(); test.assert(firstVisibleRow >= 0); From fa3b85aed40899915eed8542dd5528647185904c Mon Sep 17 00:00:00 2001 From: RohitKushvaha01 Date: Mon, 12 Jan 2026 16:14:01 +0530 Subject: [PATCH 16/16] format --- src/test/editor.tests.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/editor.tests.js b/src/test/editor.tests.js index 4bdad0428..d48b07973 100644 --- a/src/test/editor.tests.js +++ b/src/test/editor.tests.js @@ -178,7 +178,7 @@ export async function runAceEditorTests(writeOutput) { runner.test("Scroll API", async (test) => { await withEditor(test, async (editor) => { editor.setValue(Array(100).fill("line").join("\n"), -1); - editor.scrollToLine(50, true, true, () => { }); + editor.scrollToLine(50, true, true, () => {}); const firstVisibleRow = editor.renderer.getFirstVisibleRow(); test.assert(firstVisibleRow >= 0);