Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions src/lib/commands.js
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Comment thread
RohitKushvaha01 marked this conversation as resolved.
Outdated
},
async "close-all-tabs"() {
let save = false;
const unsavedFiles = editorManager.files.filter(
Expand Down
9 changes: 9 additions & 0 deletions src/lib/keyBindings.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
import { description } from "components/quickTools/items";
import actions, { key } from "handlers/quickTools";
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

These imports appear to be unused in this file. Removing them will help keep the code clean and reduce bundle size.

Comment thread
RohitKushvaha01 marked this conversation as resolved.
Outdated

export default {
focusEditor: {
description: "Focus editor",
Expand Down Expand Up @@ -697,4 +700,10 @@ export default {
readOnly: true,
action: "new-terminal",
},
runTests: {
description: "Run Tests",
key: "Ctrl-T",
readOnly: true,
actions: "run-tests"
Comment thread
RohitKushvaha01 marked this conversation as resolved.
Outdated
Comment thread
RohitKushvaha01 marked this conversation as resolved.
Outdated
}
};
200 changes: 200 additions & 0 deletions src/test/editor.tests.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,200 @@
import { TestRunner } from '../tester.js';
Comment thread
RohitKushvaha01 marked this conversation as resolved.
Outdated

export async function runAceEditorTests(writeOutput) {
const runner = new TestRunner('Ace Editor API Tests');

let editor;
let container;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The editor and container variables are shared across multiple tests. This creates dependencies between tests, making them brittle and harder to debug. For instance, if the 'Editor creation' test fails, many subsequent tests will also fail with potentially misleading errors.

It's a best practice for unit tests to be independent. Each test should set up its own environment and clean up after itself. Consider refactoring these tests to create and destroy the editor instance within each test case, perhaps using a try...finally block to ensure cleanup.


// Helper to create editor safely
function createEditor() {
container = document.createElement('div');
container.style.width = '500px';
container.style.height = '300px';
container.style.backgroundColor = '#a02f2fff';
Comment thread
RohitKushvaha01 marked this conversation as resolved.
Outdated
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');
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

To avoid potential issues with type coercion and to follow best practices, it's recommended to use the strict inequality operator (!==) instead of the loose one (!=). This applies to other similar checks in this file as well.

Suggested change
test.assert(editor != null, 'Editor instance should be created');
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) => {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

For consistency with the other tests in this suite which are defined as async, it would be good to make this test function async as well.

Suggested change
runner.test('Redo manager works', (test) => {
runner.test('Redo manager works', async (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);
}
73 changes: 73 additions & 0 deletions src/test/sanity.tests.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
import { TestRunner } from '../tester.js';
Comment thread
RohitKushvaha01 marked this conversation as resolved.
Outdated



Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

These extra blank lines can be removed to improve code formatting and conciseness.

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);
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

This file is missing a final newline character. It's a common convention and good practice to end all source files with a newline.

Loading
Loading