Skip to content

Commit 73c1526

Browse files
committed
fix test types & fix some inconsistent schemas
1 parent 9751051 commit 73c1526

19 files changed

Lines changed: 137 additions & 103 deletions

src/edit_files.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ export const editFileActions = {
5252
text: z.string().meta({
5353
description: 'The text to insert.',
5454
}),
55-
position: _POSITION_SCHEMA,
55+
position: _POSITION_SCHEMA.optional(),
5656
}),
5757
handler: ({ data: { params } }) => returnHandleInsertText(params.text, params.position),
5858
preview: (context) => {
@@ -488,7 +488,7 @@ export function addEditingActions() {
488488
]);
489489
}
490490

491-
function returnHandleInsertText(text: string, position: { line: number, column: number, type: 'relative' | 'absolute' }) {
491+
function returnHandleInsertText(text: string, position?: { line: number, column: number, type: 'relative' | 'absolute' }) {
492492
const cursor = getVirtualCursor()!;
493493
let line: number;
494494
let column: number;
@@ -541,7 +541,7 @@ function returnHandleInsertText(text: string, position: { line: number, column:
541541
}
542542

543543
/** @deprecated Functions should now be inlined */
544-
export function handleInsertText(context: RCEContext<{ text: string; position: { line: number, column: number, type: 'relative' | 'absolute' } }>): RCEHandlerReturns {
544+
export function handleInsertText(context: RCEContext<{ text: string; position?: { line: number, column: number, type: 'relative' | 'absolute' } }>): RCEHandlerReturns {
545545
const { data: actionData } = context;
546546
const text: string = actionData.params!.text;
547547
const position = actionData.params!.position;

src/read_files.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -225,7 +225,7 @@ export const readFileActions = {
225225
}).optional(),
226226
highlight: z.boolean().meta({
227227
description: 'Set to true to highlight all matches.',
228-
}),
228+
}).optional(),
229229
}),
230230
handler(ctx) {
231231
const { find, match, highlight, useRegex, lineRange, moveCursor } = ctx.data.params;

src/test/suite/common/actionMetadataValidation.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ suite('Validate action metadata', async () => {
4444
const actions = Object.keys(gitActions) as (keyof typeof gitActions)[];
4545
for (const a of actions) {
4646
assert.strictEqual(a, gitActions[a].name);
47-
assert.ok([CATEGORY_GIT, CATEGORY_GIT_CONFIG, CATEGORY_GIT_REMOTES].includes(gitActions[a].category));
47+
assert.ok([CATEGORY_GIT, CATEGORY_GIT_CONFIG, CATEGORY_GIT_REMOTES].includes(gitActions[a].category ?? ''));
4848
if ('schema' in gitActions[a] && gitActions[a].schema) {
4949
// gitActions[a].schema is now safely accessible
5050
const schema = gitActions[a].schema;

src/test/suite/file_actions.test.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,14 @@ import * as assert from 'assert';
22
import * as vscode from 'vscode';
33
import * as fileActions from '@/file_operations';
44
import * as readFiles from '@/read_files';
5-
import { assertProperties, checkNoErrorWithTimeout, createTestDirectory, createTestFile, returnMockFunction } from '@test/test_utils';
5+
import { assertProperties, checkNoErrorWithTimeout, createTestDirectory, createTestFile, fakeContext } from '@test/test_utils';
66
import { ActionData } from 'neuro-game-sdk';
7-
import type { RCEContext } from '@/context/rce';
87
import { getPermissionLevel, PermissionLevel } from '@/config';
98
import { NeuroClient } from 'neuro-game-sdk';
109
import { NEURO } from '@/constants';
1110
import { anything, capture, instance, mock, verify } from 'ts-mockito';
1211

13-
const makeContext = <const TData extends unknown | undefined>(data: ActionData<TData>) => ({ data, updateStatus: returnMockFunction() } as unknown as RCEContext<TData>);
12+
const makeContext = (data: ActionData['params']) => fakeContext('igiveup', data);
1413

1514
const { readFileActions } = readFiles;
1615

src/test/test_utils.ts

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,15 @@
1-
import * as assert from 'assert';
1+
import assert from 'assert';
22
import * as vscode from 'vscode';
33
import { setVirtualCursor } from '@/utils/misc';
4+
import { RCEContext } from '@ctx/rce';
5+
import { ActionData } from 'neuro-game-sdk';
6+
import { randomUUID } from 'crypto';
7+
8+
export const fakeContext = <const TParams extends ActionData['params']>(name: string, params: TParams) => {
9+
const ctx = new RCEContext({ id: randomUUID(), name, params });
10+
ctx['_updateStatus'] = returnMockFunction();
11+
return ctx;
12+
};
413

514
/**
615
* Asserts that an object has the same properties as the expected object,

src/test/unit-test/delete_lines.simple.test.ts

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,13 @@
1-
import * as assert from 'assert';
1+
import assert from 'assert';
22
import { editFileActions } from '@/edit_files';
3-
import type { RCEContext } from '@/context/rce';
3+
import { fakeContext } from '@test/test_utils';
44

55
// Tests for the delete_lines action prompt generator using real logic
66
suite('delete_lines Action', () => {
77
test('generates a prompt and includes start and end for a normal range', () => {
8+
assert.ok(editFileActions.delete_lines.promptGenerator && typeof editFileActions.delete_lines.promptGenerator !== 'string');
89
// === Arrange & Act ===
9-
const prompt = editFileActions.delete_lines.promptGenerator({
10-
data: { params: { startLine: 3, endLine: 7 } },
11-
} as RCEContext);
10+
const prompt = editFileActions.delete_lines.promptGenerator(fakeContext('delete_lines', { startLine: 3, endLine: 7 }));
1211

1312
// === Assert ===
1413
assert.ok(typeof prompt === 'string' && prompt.length > 0, 'prompt should be a non-empty string');
@@ -17,21 +16,19 @@ suite('delete_lines Action', () => {
1716
});
1817

1918
test('generates a prompt and includes the single line when start=end', () => {
19+
assert.ok(editFileActions.delete_lines.promptGenerator && typeof editFileActions.delete_lines.promptGenerator !== 'string');
2020
// === Arrange & Act ===
21-
const prompt = editFileActions.delete_lines.promptGenerator({
22-
data: { params: { startLine: 5, endLine: 5 } },
23-
} as RCEContext);
21+
const prompt = editFileActions.delete_lines.promptGenerator(fakeContext('delete_lines', { startLine: 5, endLine: 5 }));
2422

2523
// === Assert ===
2624
assert.ok(typeof prompt === 'string' && prompt.length > 0, 'prompt should be a non-empty string');
2725
assert.ok(prompt.includes('5'), 'prompt should include the line number');
2826
});
2927

3028
test('generates a prompt even for reversed ranges (format-only responsibility)', () => {
29+
assert.ok(editFileActions.delete_lines.promptGenerator && typeof editFileActions.delete_lines.promptGenerator !== 'string');
3130
// === Arrange & Act ===
32-
const prompt = editFileActions.delete_lines.promptGenerator({
33-
data: { params: { startLine: 7, endLine: 3 } },
34-
} as RCEContext);
31+
const prompt = editFileActions.delete_lines.promptGenerator(fakeContext('delete_lines', { startLine: 7, endLine: 3 }));
3532
// Prompt generator formats only; validation handles correctness elsewhere
3633

3734
// === Assert ===

src/test/unit-test/delete_text.simple.test.ts

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,23 @@
11
import * as assert from 'assert';
22
import { editFileActions } from '@/edit_files';
3-
import type { RCEContext } from '@/context/rce';
3+
import { fakeContext } from '@test/test_utils';
44

55
// Tests for the delete_text action prompt generator using real logic
66
suite('delete_text Action', () => {
77
test('generates a prompt and includes raw find when useRegex is true', () => {
8+
assert.ok(editFileActions.delete_text.promptGenerator && typeof editFileActions.delete_text.promptGenerator !== 'string');
89
// === Arrange & Act ===
9-
const prompt = editFileActions.delete_text.promptGenerator({
10-
data: { params: { find: 'a+b', useRegex: true } },
11-
} as RCEContext);
10+
const prompt = editFileActions.delete_text.promptGenerator(fakeContext('delete_text', { find: 'a+b', match: 'firstInFile', useRegex: true }));
1211

1312
// === Assert ===
1413
assert.ok(typeof prompt === 'string' && prompt.length > 0);
1514
assert.ok(prompt.includes('a+b'));
1615
});
1716

1817
test('generates a prompt and includes raw find when useRegex is false', () => {
18+
assert.ok(editFileActions.delete_text.promptGenerator && typeof editFileActions.delete_text.promptGenerator !== 'string');
1919
// === Arrange ===
20-
const prompt = editFileActions.delete_text.promptGenerator({
21-
data: { params: { find: 'hello', useRegex: false } },
22-
} as RCEContext);
20+
const prompt = editFileActions.delete_text.promptGenerator(fakeContext('delete_text', { find: 'hello', match: 'firstInFile', useRegex: false }));
2321

2422
// === Act ===
2523

src/test/unit-test/file_actions.simple.test.ts

Lines changed: 21 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,84 +1,93 @@
11
import * as assert from 'assert';
22
import { fileActions } from '@/file_operations';
33
import { readFileActions } from '@/read_files';
4-
import type { RCEContext } from '@/context/rce';
4+
import { fakeContext } from '@test/test_utils';
55

66
// Tests for file action prompt generators using real logic with loose checks
77
suite('file Actions', () => {
88
test('get_workspace_files has a non-empty prompt', () => {
9+
assert.ok(fileActions.list_files_and_folders.promptGenerator && typeof fileActions.list_files_and_folders.promptGenerator !== 'string');
910
// === Arrange & Act ===
10-
const prompt = fileActions.list_files_and_folders.promptGenerator({ data: { params: {} } } as RCEContext);
11+
const prompt = fileActions.list_files_and_folders.promptGenerator(fakeContext('list_files_and_folders', {}));
1112

1213
// === Assert ===
1314
assert.ok(typeof prompt === 'string' && prompt.length > 0);
1415
});
1516

1617
test('get_workspace_files correctly includes the folder in prompt', () => {
18+
assert.ok(fileActions.list_files_and_folders.promptGenerator && typeof fileActions.list_files_and_folders.promptGenerator !== 'string');
1719
// === Arrange & Act ===
18-
const prompt = fileActions.list_files_and_folders.promptGenerator({ data: { params: { folder: 'src/' } } } as RCEContext);
20+
const prompt = fileActions.list_files_and_folders.promptGenerator(fakeContext('list_files_and_folders', { folder: 'src/' }));
1921

2022
// === Assert ===
2123
assert.ok(typeof prompt === 'string' && prompt.length > 0);
2224
assert.ok(prompt.includes('src'));
2325
});
2426

2527
test('get_workspace_files correctly states if Neuro asked for recursive', () => {
28+
assert.ok(fileActions.list_files_and_folders.promptGenerator && typeof fileActions.list_files_and_folders.promptGenerator !== 'string');
2629
// === Arrange & Act ===
27-
const prompt = fileActions.list_files_and_folders.promptGenerator({ data: { params: { recursive: true } } } as RCEContext);
30+
const prompt = fileActions.list_files_and_folders.promptGenerator(fakeContext('list_files_and_folders', { recursive: true }));
2831

2932
// === Assert ===
3033
assert.ok(typeof prompt === 'string' && prompt.length > 0);
3134
assert.ok(prompt.toLowerCase().includes('recursively'));
3235
});
3336

3437
test('get_workspace_files correctly omits recursive if Neuro didn\'t ask', () => {
38+
assert.ok(fileActions.list_files_and_folders.promptGenerator && typeof fileActions.list_files_and_folders.promptGenerator !== 'string');
3539
// === Arrange & Act ===
36-
const prompt = fileActions.list_files_and_folders.promptGenerator({ data: { params: { recursive: false } } } as RCEContext);
40+
const prompt = fileActions.list_files_and_folders.promptGenerator(fakeContext('list_files_and_folders', { recursive: false }));
3741

3842
// === Assert ===
3943
assert.ok(typeof prompt === 'string' && prompt.length > 0);
4044
assert.ok(!prompt.includes('recursively'));
4145
});
4246

4347
test('open_file prompt formats path', () => {
48+
assert.ok(readFileActions.switch_files.promptGenerator && typeof readFileActions.switch_files.promptGenerator !== 'string');
4449
// === Arrange & Act ===
45-
const prompt = readFileActions.switch_files.promptGenerator({ data: { params: { filePath: 'src/index.ts' } } } as RCEContext);
50+
const prompt = readFileActions.switch_files.promptGenerator(fakeContext('switch_files', { filePath: 'src/index.ts' }));
4651

4752
// === Assert ===
4853
assert.ok(typeof prompt === 'string' && prompt.length > 0);
4954
assert.ok(prompt.includes('src/index.ts'));
5055
});
5156

5257
test('read_file prompt formats path', () => {
58+
assert.ok(readFileActions.read_file.promptGenerator && typeof readFileActions.read_file.promptGenerator !== 'string');
5359
// === Arrange & Act ===
54-
const prompt = readFileActions.read_file.promptGenerator({ data: { params: { filePath: 'README.md' } } } as RCEContext);
60+
const prompt = readFileActions.read_file.promptGenerator(fakeContext('read_files', { filePath: 'README.md' }));
5561

5662
// === Assert ===
5763
assert.ok(typeof prompt === 'string' && prompt.length > 0);
5864
assert.ok(prompt.includes('README.md'));
5965
});
6066

6167
test('create_file prompt formats path', () => {
68+
assert.ok(fileActions.create_file.promptGenerator && typeof fileActions.create_file.promptGenerator !== 'string');
6269
// === Arrange & Act ===
63-
const prompt = fileActions.create_file.promptGenerator({ data: { params: { filePath: 'new/file.txt' } } } as RCEContext);
70+
const prompt = fileActions.create_file.promptGenerator(fakeContext('create_file', { filePath: 'new/file.txt' }));
6471

6572
// === Assert ===
6673
assert.ok(typeof prompt === 'string' && prompt.length > 0);
6774
assert.ok(prompt.includes('new/file.txt'));
6875
});
6976

7077
test('create_folder prompt formats path', () => {
78+
assert.ok(fileActions.create_folder.promptGenerator && typeof fileActions.create_folder.promptGenerator !== 'string');
7179
// === Arrange & Act ===
72-
const prompt = fileActions.create_folder.promptGenerator({ data: { params: { folderPath: 'new/folder' } } } as RCEContext);
80+
const prompt = fileActions.create_folder.promptGenerator(fakeContext('create_folder', { folderPath: 'new/folder' }));
7381

7482
// === Assert ===
7583
assert.ok(typeof prompt === 'string' && prompt.length > 0);
7684
assert.ok(prompt.includes('new/folder'));
7785
});
7886

7987
test('rename_file_or_folder prompt formats paths', () => {
88+
assert.ok(fileActions.rename_file_or_folder.promptGenerator && typeof fileActions.rename_file_or_folder.promptGenerator !== 'string');
8089
// === Arrange & Act ===
81-
const prompt = fileActions.rename_file_or_folder.promptGenerator({ data: { params: { oldPath: 'old/a.txt', newPath: 'new/a.txt' } } } as RCEContext);
90+
const prompt = fileActions.rename_file_or_folder.promptGenerator(fakeContext('rename_file_or_folder', { oldPath: 'old/a.txt', newPath: 'new/a.txt' }));
8291

8392
// === Assert ===
8493
assert.ok(typeof prompt === 'string' && prompt.length > 0);
@@ -87,8 +96,9 @@ suite('file Actions', () => {
8796
});
8897

8998
test('delete_file_or_folder prompt formats path', () => {
99+
assert.ok(fileActions.delete_file_or_folder.promptGenerator && typeof fileActions.delete_file_or_folder.promptGenerator !== 'string');
90100
// === Arrange & Act ===
91-
const prompt = fileActions.delete_file_or_folder.promptGenerator({ data: { params: { path: 'old/file.txt' } } } as RCEContext);
101+
const prompt = fileActions.delete_file_or_folder.promptGenerator(fakeContext('delete_file_or_folder', { path: 'old/file.txt' }));
92102

93103
// === Assert ===
94104
assert.ok(typeof prompt === 'string' && prompt.length > 0);

src/test/unit-test/find_text.simple.test.ts

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,23 @@
11
import * as assert from 'assert';
22
import { readFileActions } from '@/read_files';
3-
import type { RCEContext } from '@/context/rce';
3+
import { fakeContext } from '@test/test_utils';
44

55
// Tests for the find_text action prompt generator using real logic
66
suite('find_text Action', () => {
77
test('generates a prompt and includes raw find when useRegex is true', () => {
8+
assert.ok(readFileActions.find_text.promptGenerator && typeof readFileActions.find_text.promptGenerator !== 'string');
89
// === Arrange & Act ===
9-
const prompt = readFileActions.find_text.promptGenerator({
10-
data: { params: { find: 'foo(bar)', useRegex: true } },
11-
} as RCEContext);
10+
const prompt = readFileActions.find_text.promptGenerator(fakeContext('find_text', { find: 'foo(bar)', match: 'firstInFile', useRegex: true }));
1211

1312
// === Assert ===
1413
assert.ok(typeof prompt === 'string' && prompt.length > 0);
1514
assert.ok(prompt.includes('foo(bar)'));
1615
});
1716

1817
test('generates a prompt and includes raw find when useRegex is false', () => {
18+
assert.ok(readFileActions.find_text.promptGenerator && typeof readFileActions.find_text.promptGenerator !== 'string');
1919
// === Arrange & Act ===
20-
const prompt = readFileActions.find_text.promptGenerator({
21-
data: { params: { find: 'baz', useRegex: false } },
22-
} as RCEContext);
20+
const prompt = readFileActions.find_text.promptGenerator(fakeContext('find_text', { find: 'baz', match: 'firstInFile', useRegex: false }));
2321

2422
// === Assert ===
2523
assert.ok(typeof prompt === 'string' && prompt.length > 0);

0 commit comments

Comments
 (0)