16import * as
fs from
'fs/promises';
17import * as
path from
'path';
20import { RandomLogo } from
'../modules/randomLogo';
21import {
CodeConfig } from
'../modules/processConfiguration';
45 rangeIncludingLineBreak:
vscode.Range;
47 firstNonWhitespaceCharacterIndex: number;
49 isEmptyOrWhitespace: boolean;
79 public version: number;
81 public isClosed: boolean;
83 public lineCount: number = 0;
85 public fileName:
string =
'';
87 public isUntitled:
boolean =
false;
89 public encoding:
string =
'utf8';
91 public isDirty:
boolean =
false;
107 content:
string =
'',
108 languageId:
string =
'typescript',
110 isClosed:
boolean =
false
112 this.uri =
vscode.Uri.file(filePath);
113 this.languageId = languageId;
116 this.isClosed = isClosed;
118 this.setContent(content);
131 setContent(content:
string): void {
132 const lines = content.split(
'\n');
133 this.lines = lines.map((text, index) => ({
135 range:
new vscode.Range(index, 0, index, text.length),
137 rangeIncludingLineBreak:
new vscode.Range(index, 0, index + 1, 0),
138 firstNonWhitespaceCharacterIndex: text.search(/\S/),
139 isEmptyOrWhitespace: text.trim().length === 0
141 this.lineCount = this.lines.length;
142 this.fileName =
path.basename(this.uri.fsPath);
151 lineAt(lineOrPosition: number |
vscode.Position):
vscode.TextLine {
152 const line = typeof lineOrPosition ===
'number' ? lineOrPosition : lineOrPosition.line;
153 if (line < 0 || line >= this.lines.length) {
154 throw new Error(`Line ${line} is out of range`);
156 return this.lines[line] as
vscode.TextLine;
164 offsetAt(position:
vscode.Position): number {
166 for (let i = 0; i < position.line && i < this.lines.length; i++) {
167 offset += this.lines[i].text.length + 1;
169 return offset + Math.min(position.character,
this.lines[position.line]?.text.length || 0);
177 positionAt(offset: number):
vscode.Position {
178 let currentOffset = 0;
179 for (let line = 0; line < this.lines.length; line++) {
180 const lineLength = this.lines[line].text.length + 1;
181 if (currentOffset + lineLength > offset) {
182 return new vscode.Position(line, offset - currentOffset);
184 currentOffset += lineLength;
186 return new vscode.Position(this.lines.length - 1, (
this.lines[
this.lines.length - 1]?.text.length || 0));
196 return this.lines.map(line => line.text).join(
'\n');
199 if (range.start.line === range.end.line) {
200 const line = this.lines[range.start.line];
201 return line ? line.text.substring(range.start.character, range.end.character) :
'';
205 for (let i = range.start.line; i <= range.end.line && i <
this.lines.length; i++) {
206 const line = this.lines[i];
207 if (!line) { continue; }
209 if (i === range.start.line) {
210 result += line.text.substring(range.start.character);
211 }
else if (i === range.end.line) {
212 result += line.text.substring(0, range.end.character);
217 if (i < range.end.line) {
238 validatePosition(position:
vscode.Position):
vscode.Position {
248 getWordRangeAtPosition(position:
vscode.Position, regex?: RegExp):
vscode.Range | undefined {
249 const line = this.lines[position.line];
250 if (!line) {
return undefined; }
252 const wordRegex = regex || /[\w]+/g;
254 while ((match = wordRegex.exec(line.text)) !==
null) {
255 if (match.index <= position.character && match.index + match[0].length >= position.character) {
256 return new vscode.Range(position.line, match.index, position.line, match.index + match[0].length);
266 save(): Thenable<boolean> {
267 return Promise.resolve(
true);
296 this.document = document as unknown as
vscode.TextDocument;
299 async edit(callback: (editBuilder:
vscode.TextEditorEdit) =>
void): Promise<boolean> {
300 const mockEditBuilder = {
310 position: location.start,
318 callback(mockEditBuilder as
vscode.TextEditorEdit);
334suite(
'CommentGenerator Test Suite',
function () {
338 let languageConfigFile:
string;
342 let mockRandomLogo: RandomLogo;
356 tempDir = await
fs.mkdtemp(
path.join(require(
'os').tmpdir(),
'commentgen-test-'));
359 languageConfigFile =
path.join(tempDir,
'languages.json');
360 const languageConfig = {
363 langs: [
'typescript',
'javascript'],
365 typescript: [
'.ts',
'.tsx'],
366 javascript: [
'.js',
'.jsx']
369 multiLine: [
'/*',
' *',
' */'],
370 prompt_comment_opening_type:
false
379 prompt_comment_opening_type:
false
385 cpp: [
'.cpp',
'.hpp',
'.cxx']
388 multiLine: [
'/*',
' *',
' */'],
389 prompt_comment_opening_type:
true
393 await
fs.writeFile(languageConfigFile, JSON.stringify(languageConfig,
null, 2));
399 mockRandomLogo =
new RandomLogo();
413 Object.defineProperty(
vscode.window,
'activeTextEditor', {
414 get: () => mockActiveTextEditor,
418 (
vscode.window as any).showInputBox = async (options?:
vscode.InputBoxOptions) => {
422 (
vscode.window as any).showQuickPick = async (items:
string[], options?:
vscode.QuickPickOptions) => {
438 teardown(async () => {
441 await
fs.rm(tempDir, { recursive:
true, force:
true });
447 Object.defineProperty(
vscode.window,
'activeTextEditor', {
448 value: originalActiveTextEditor,
461 suite(
'Constructor and Initialization', () => {
466 test(
'should create instance with all parameters provided', () => {
470 generator =
new CommentGenerator(lazyFileLoader, editor as any, mockRandomLogo);
472 assert.ok(generator,
'Generator should be created successfully');
479 test(
'should create instance with minimal parameters', () => {
482 assert.ok(generator,
'Generator should be created with undefined parameters');
489 test(
'should create instance with only language loader', () => {
492 assert.ok(generator,
'Generator should be created with language loader only');
499 test(
'should handle undefined editor gracefully', () => {
500 generator =
new CommentGenerator(lazyFileLoader, undefined, mockRandomLogo);
502 assert.ok(generator,
'Generator should handle undefined editor');
513 suite(
'File Information Processing', () => {
518 test(
'should extract correct file metadata from TypeScript editor', () => {
519 const filePath =
'/home/user/project/test.ts';
523 generator =
new CommentGenerator(lazyFileLoader, editor as any, mockRandomLogo);
526 const generatorAny = generator as any;
527 assert.strictEqual(generatorAny.fileName,
'test.ts');
528 assert.strictEqual(generatorAny.fileExtension,
'ts');
529 assert.strictEqual(generatorAny.languageId,
'typescript');
530 assert.strictEqual(generatorAny.filePath, filePath);
537 test(
'should extract correct file metadata from Python editor', () => {
538 const filePath =
'/home/user/project/script.py';
542 generator =
new CommentGenerator(lazyFileLoader, editor as any, mockRandomLogo);
544 const generatorAny = generator as any;
545 assert.strictEqual(generatorAny.fileName,
'script.py');
546 assert.strictEqual(generatorAny.fileExtension,
'py');
547 assert.strictEqual(generatorAny.languageId,
'python');
554 test(
'should handle files without extensions', () => {
555 const filePath =
'/home/user/Makefile';
559 generator =
new CommentGenerator(lazyFileLoader, editor as any, mockRandomLogo);
561 const generatorAny = generator as any;
562 assert.strictEqual(generatorAny.fileName,
'Makefile');
563 assert.strictEqual(generatorAny.fileExtension,
'none');
570 test(
'should handle different EOL types', () => {
574 generator =
new CommentGenerator(lazyFileLoader, editor as any, mockRandomLogo);
576 const generatorAny = generator as any;
577 assert.strictEqual(generatorAny.documentEOL,
vscode.EndOfLine.CRLF);
588 suite(
'Comment Style Detection', () => {
593 test(
'should detect TypeScript comment style correctly', async () => {
597 generator =
new CommentGenerator(lazyFileLoader, editor as any, mockRandomLogo);
599 const generatorAny = generator as any;
600 const commentStyle = await generatorAny.determineCorrectComment();
602 assert.deepStrictEqual(commentStyle.singleLine, [
'//']);
603 assert.deepStrictEqual(commentStyle.multiLine, [
'/*',
' *',
' */']);
604 assert.strictEqual(commentStyle.prompt_comment_opening_type,
false);
611 test(
'should detect Python comment style correctly', async () => {
615 generator =
new CommentGenerator(lazyFileLoader, editor as any, mockRandomLogo);
617 const generatorAny = generator as any;
618 const commentStyle = await generatorAny.determineCorrectComment();
620 assert.deepStrictEqual(commentStyle.singleLine, [
'#']);
621 assert.deepStrictEqual(commentStyle.multiLine, []);
628 test(
'should detect C++ comment style with prompting', async () => {
632 generator =
new CommentGenerator(lazyFileLoader, editor as any, mockRandomLogo);
634 const generatorAny = generator as any;
635 const commentStyle = await generatorAny.determineCorrectComment();
637 assert.deepStrictEqual(commentStyle.singleLine, [
'//']);
638 assert.deepStrictEqual(commentStyle.multiLine, [
'/*',
' *',
' */']);
639 assert.strictEqual(commentStyle.prompt_comment_opening_type,
true);
646 test(
'should fallback to file extension matching', async () => {
650 generator =
new CommentGenerator(lazyFileLoader, editor as any, mockRandomLogo);
652 const generatorAny = generator as any;
653 const commentStyle = await generatorAny.determineCorrectComment();
656 assert.deepStrictEqual(commentStyle.singleLine, [
'//']);
657 assert.deepStrictEqual(commentStyle.multiLine, [
'/*',
' *',
' */']);
664 test(
'should return empty style for unknown language', async () => {
668 generator =
new CommentGenerator(lazyFileLoader, editor as any, mockRandomLogo);
670 const generatorAny = generator as any;
671 const commentStyle = await generatorAny.determineCorrectComment();
673 assert.deepStrictEqual(commentStyle.singleLine, []);
674 assert.deepStrictEqual(commentStyle.multiLine, []);
675 assert.strictEqual(commentStyle.prompt_comment_opening_type,
false);
686 suite(
'User Input Handling', () => {
691 test(
'should get file description from user input', async () => {
694 generator =
new CommentGenerator(lazyFileLoader, editor as any, mockRandomLogo);
698 const generatorAny = generator as any;
699 const description = await generatorAny.determineHeaderDescription();
701 assert.deepStrictEqual(description, [
'This is a test file for the application']);
708 test(
'should handle empty description input', async () => {
711 generator =
new CommentGenerator(lazyFileLoader, editor as any, mockRandomLogo);
715 const generatorAny = generator as any;
716 const description = await generatorAny.determineHeaderDescription();
718 assert.deepStrictEqual(description, [
'']);
725 test(
'should get file purpose from user input', async () => {
728 generator =
new CommentGenerator(lazyFileLoader, editor as any, mockRandomLogo);
732 const generatorAny = generator as any;
733 const purpose = await generatorAny.determineHeaderPurpose();
735 assert.deepStrictEqual(purpose, [
'Main entry point for the application']);
742 test(
'should get single comment option without prompting', async () => {
745 generator =
new CommentGenerator(lazyFileLoader, editor as any, mockRandomLogo);
747 const generatorAny = generator as any;
748 const result = await generatorAny.getSingleCommentOption([
'//']);
750 assert.strictEqual(result,
'//');
757 test(
'should prompt for comment selection when multiple options', async () => {
760 generator =
new CommentGenerator(lazyFileLoader, editor as any, mockRandomLogo);
764 const generatorAny = generator as any;
765 const result = await generatorAny.getSingleCommentOption([
'//',
'/*']);
767 assert.strictEqual(result,
'/*');
774 test(
'should return first option when user cancels selection', async () => {
777 generator =
new CommentGenerator(lazyFileLoader, editor as any, mockRandomLogo);
781 const generatorAny = generator as any;
782 const result = await generatorAny.getSingleCommentOption([
'//',
'/*']);
784 assert.strictEqual(result,
'//');
791 test(
'should throw error for empty comment options', async () => {
794 generator =
new CommentGenerator(lazyFileLoader, editor as any, mockRandomLogo);
796 const generatorAny = generator as any;
799 async () => await generatorAny.getSingleCommentOption([]),
812 suite(
'Header Content Generation', () => {
817 test(
'should generate correct header opener', () => {
820 generator =
new CommentGenerator(lazyFileLoader, editor as any, mockRandomLogo);
822 const generatorAny = generator as any;
823 const opener = generatorAny.headerOpener(
' * ',
vscode.EndOfLine.LF,
'TestProject');
825 assert.ok(opener.includes(
'TestProject'));
826 assert.ok(opener.includes(
' * '));
827 assert.ok(opener.endsWith(
'\n'));
834 test(
'should generate correct header closer', () => {
837 generator =
new CommentGenerator(lazyFileLoader, editor as any, mockRandomLogo);
839 const generatorAny = generator as any;
840 const closer = generatorAny.headerCloser(
' * ',
vscode.EndOfLine.LF,
'TestProject');
842 assert.ok(closer.includes(
'TestProject'));
843 assert.ok(closer.includes(
' * '));
844 assert.ok(closer.endsWith(
'\n'));
851 test(
'should generate creation date with correct format', () => {
854 generator =
new CommentGenerator(lazyFileLoader, editor as any, mockRandomLogo);
856 const generatorAny = generator as any;
857 const creationDate = generatorAny.addCreationDate(
' * ',
vscode.EndOfLine.LF);
859 assert.ok(creationDate.includes(
' * '));
860 assert.ok(creationDate.includes(
'2025'));
861 assert.ok(creationDate.endsWith(
'\n'));
868 test(
'should generate last modified date with time', () => {
871 generator =
new CommentGenerator(lazyFileLoader, editor as any, mockRandomLogo);
873 const generatorAny = generator as any;
874 const modifiedDate = generatorAny.addLastModifiedDate(
' * ',
vscode.EndOfLine.LF);
876 assert.ok(modifiedDate.includes(
' * '));
877 assert.ok(modifiedDate.includes(
'2025'));
878 assert.ok(modifiedDate.includes(
':'));
879 assert.ok(modifiedDate.endsWith(
'\n'));
886 test(
'should generate single line key-value pair', () => {
889 generator =
new CommentGenerator(lazyFileLoader, editor as any, mockRandomLogo);
891 const generatorAny = generator as any;
892 const singleLine = generatorAny.addSingleLineKey(
' * ',
vscode.EndOfLine.LF,
'Author',
'John Doe');
894 assert.ok(singleLine.includes(
' * '));
895 assert.ok(singleLine.includes(
'Author'));
896 assert.ok(singleLine.includes(
'John Doe'));
897 assert.ok(singleLine.endsWith(
'\n'));
904 test(
'should generate multi-line key section', () => {
907 generator =
new CommentGenerator(lazyFileLoader, editor as any, mockRandomLogo);
909 const generatorAny = generator as any;
910 const multiLine = generatorAny.addMultilineKey(
' * ',
vscode.EndOfLine.LF,
'Description', [
'Line 1',
'Line 2']);
912 assert.ok(multiLine.includes(
' * '));
913 assert.ok(multiLine.includes(
'Description'));
914 assert.ok(multiLine.includes(
'Line 1'));
915 assert.ok(multiLine.includes(
'Line 2'));
922 test(
'should handle CRLF line endings correctly', () => {
925 generator =
new CommentGenerator(lazyFileLoader, editor as any, mockRandomLogo);
927 const generatorAny = generator as any;
928 const eolString = generatorAny.determineNewLine(
vscode.EndOfLine.CRLF);
930 assert.strictEqual(eolString,
'\r\n');
937 test(
'should handle LF line endings correctly', () => {
940 generator =
new CommentGenerator(lazyFileLoader, editor as any, mockRandomLogo);
942 const generatorAny = generator as any;
943 const eolString = generatorAny.determineNewLine(
vscode.EndOfLine.LF);
945 assert.strictEqual(eolString,
'\n');
956 suite(
'Comment Prefix Processing', () => {
961 test(
'should process multi-line comments with three parts', async () => {
964 generator =
new CommentGenerator(lazyFileLoader, editor as any, mockRandomLogo);
966 const commentStyle = {
968 multiLine: [
'/*',
' *',
' */'],
969 prompt_comment_opening_type:
false
972 const generatorAny = generator as any;
973 const prefixes = await generatorAny.getCorrectCommentPrefix(commentStyle);
975 assert.strictEqual(prefixes.length, 3);
976 assert.ok(prefixes[0].includes(
'/*'));
977 assert.ok(prefixes[1].includes(
' *'));
978 assert.ok(prefixes[2].includes(
' */'));
985 test(
'should process multi-line comments with two parts', async () => {
988 generator =
new CommentGenerator(lazyFileLoader, editor as any, mockRandomLogo);
990 const commentStyle = {
992 multiLine: [
'<!--',
'-->'],
993 prompt_comment_opening_type:
false
996 const generatorAny = generator as any;
997 const prefixes = await generatorAny.getCorrectCommentPrefix(commentStyle);
999 assert.strictEqual(prefixes.length, 3);
1000 assert.ok(prefixes[0].includes(
'<!--'));
1001 assert.strictEqual(prefixes[1].trim(),
'');
1002 assert.ok(prefixes[2].includes(
'-->'));
1009 test(
'should process single-line comments without prompting', async () => {
1012 generator =
new CommentGenerator(lazyFileLoader, editor as any, mockRandomLogo);
1014 const commentStyle = {
1017 prompt_comment_opening_type:
false
1020 const generatorAny = generator as any;
1021 const prefixes = await generatorAny.getCorrectCommentPrefix(commentStyle);
1023 assert.strictEqual(prefixes.length, 3);
1024 assert.ok(prefixes[0].includes(
'#'));
1025 assert.ok(prefixes[1].includes(
'#'));
1026 assert.ok(prefixes[2].includes(
'#'));
1033 test(
'should prompt for single-line comment selection', async () => {
1036 generator =
new CommentGenerator(lazyFileLoader, editor as any, mockRandomLogo);
1040 const commentStyle = {
1041 singleLine: [
'//',
'#'],
1043 prompt_comment_opening_type:
true
1046 const generatorAny = generator as any;
1047 const prefixes = await generatorAny.getCorrectCommentPrefix(commentStyle);
1049 assert.strictEqual(prefixes.length, 3);
1050 assert.ok(prefixes[0].includes(
'//'));
1051 assert.ok(prefixes[1].includes(
'//'));
1052 assert.ok(prefixes[2].includes(
'//'));
1059 test(
'should handle empty comment configurations', async () => {
1062 generator =
new CommentGenerator(lazyFileLoader, editor as any, mockRandomLogo);
1064 const commentStyle = {
1067 prompt_comment_opening_type:
false
1070 const generatorAny = generator as any;
1071 const prefixes = await generatorAny.getCorrectCommentPrefix(commentStyle);
1073 assert.strictEqual(prefixes.length, 3);
1075 assert.strictEqual(prefixes[0],
' ');
1076 assert.strictEqual(prefixes[1],
' ');
1077 assert.ok(prefixes[2].includes(
' '));
1088 suite(
'Header Detection and Parsing', () => {
1093 test(
'should detect existing header correctly', () => {
1094 const headerContent = `
1111const someCode =
true;`;
1115 generator =
new CommentGenerator(lazyFileLoader, editor as any, mockRandomLogo);
1117 const generatorAny = generator as any;
1118 const comments = [
' * ',
' * ',
' * '];
1119 const hasHeader = generatorAny.locateIfHeaderPresent(comments);
1121 assert.strictEqual(hasHeader,
true);
1122 assert.ok(typeof generatorAny.headerInnerStart ===
'number');
1123 assert.ok(typeof generatorAny.headerInnerEnd ===
'number');
1130 test(
'should detect missing header correctly', () => {
1131 const content = `
const someCode =
true;
1132function myFunction() {
1138 generator =
new CommentGenerator(lazyFileLoader, editor as any, mockRandomLogo);
1140 const generatorAny = generator as any;
1141 const comments = [
' * ',
' * ',
' * '];
1142 const hasHeader = generatorAny.locateIfHeaderPresent(comments);
1144 assert.strictEqual(hasHeader,
false);
1145 assert.strictEqual(generatorAny.headerInnerStart, undefined);
1146 assert.strictEqual(generatorAny.headerInnerEnd, undefined);
1153 test(
'should detect broken header (opener without closer)', () => {
1154 const brokenContent = `
1176 test('should detect broken header (closer without opener)', () => {
1177 const brokenContent = `const someCode = true;
1178 * ═══════════════════════ ◄ END TestProject ► ═══════════════════════
1183 generator =
new CommentGenerator(lazyFileLoader, editor as any, mockRandomLogo);
1185 const generatorAny = generator as any;
1186 const comments = [
' * ',
' * ',
' * '];
1187 const hasHeader = generatorAny.locateIfHeaderPresent(comments);
1189 assert.strictEqual(hasHeader,
false);
1196 test(
'should handle closed document gracefully', () => {
1199 generator =
new CommentGenerator(lazyFileLoader, editor as any, mockRandomLogo);
1201 const generatorAny = generator as any;
1202 const comments = [
' * ',
' * ',
' * '];
1203 const hasHeader = generatorAny.locateIfHeaderPresent(comments);
1205 assert.strictEqual(hasHeader, undefined);
1212 test(
'should respect max scan length limit', () => {
1213 const longContent = Array(1000).fill(
'const line = true;').join(
'\n');
1216 generator =
new CommentGenerator(lazyFileLoader, editor as any, mockRandomLogo);
1218 const generatorAny = generator as any;
1219 const comments = [
' * ',
' * ',
' * '];
1220 const hasHeader = generatorAny.locateIfHeaderPresent(comments);
1222 assert.strictEqual(hasHeader,
false);
1232 suite(
'Logo Integration', () => {
1237 test(
'should update logo randomizer instance', () => {
1239 const newRandomLogo =
new RandomLogo();
1241 generator.updateLogoInstanceRandomiser(newRandomLogo);
1255 suite(
'File Writing Operations', () => {
1260 test(
'should write header to empty file', async () => {
1267 generator =
new CommentGenerator(lazyFileLoader, editor as any, mockRandomLogo);
1269 const generatorAny = generator as any;
1270 const comments = [
'/* ',
' * ',
' */'];
1271 const status = await generatorAny.writeHeaderToFile(editor, comments);
1284 test(
'should update existing header timestamp', async () => {
1285 const headerContent = `
1304 generator =
new CommentGenerator(lazyFileLoader, editor as any, mockRandomLogo);
1306 const generatorAny = generator as any;
1307 const comments = [
'/* ',
' * ',
' */'];
1310 generatorAny.headerInnerStart = 1;
1311 generatorAny.headerInnerEnd = 15;
1313 await generatorAny.updateEditDate(editor, comments);
1319 assert.ok(editText.includes(
'Last Modified') || editText.includes(
'*'),
'Should include Last Modified or comment prefix');
1320 assert.ok(editText.includes(
'2025') || editText.length > 0,
'Should include year or have content');
1331 suite(
'Main API Methods', () => {
1336 test(
'should inject header when no active editor', async () => {
1342 await generator.injectHeader();
1351 test(
'should inject header to TypeScript file', async () => {
1358 generator =
new CommentGenerator(lazyFileLoader, undefined, mockRandomLogo);
1360 await generator.injectHeader();
1371 test(
'should refresh header when configured', async () => {
1372 const headerContent = `
1385 generator =
new CommentGenerator(lazyFileLoader, editor as any, mockRandomLogo);
1387 await generator.refreshHeader(document as any);
1398 test(
'should handle refresh with no document', async () => {
1401 await generator.refreshHeader(undefined);
1410 test(
'should handle refresh with closed document', async () => {
1416 generator =
new CommentGenerator(lazyFileLoader, editor as any, mockRandomLogo);
1418 await generator.refreshHeader(document as any);
1424 suite(
'Error Handling and Edge Cases', () => {
1429 test(
'should handle missing language comment loader', async () => {
1433 generator =
new CommentGenerator(undefined, editor as any, mockRandomLogo);
1435 const generatorAny = generator as any;
1436 const commentStyle = await generatorAny.determineCorrectComment();
1438 assert.deepStrictEqual(commentStyle.singleLine, []);
1439 assert.deepStrictEqual(commentStyle.multiLine, []);
1446 test(
'should handle corrupted language configuration', async () => {
1448 const corruptedConfigFile =
path.join(tempDir,
'corrupted.json');
1449 await
fs.writeFile(corruptedConfigFile,
'{"invalid": structure}');
1451 const corruptedLoader =
new LazyFileLoader(corruptedConfigFile, tempDir);
1455 generator =
new CommentGenerator(corruptedLoader, editor as any, mockRandomLogo);
1457 const generatorAny = generator as any;
1458 const commentStyle = await generatorAny.determineCorrectComment();
1460 assert.deepStrictEqual(commentStyle.singleLine, []);
1461 assert.deepStrictEqual(commentStyle.multiLine, []);
1468 test(
'should handle update without header bounds', async () => {
1472 generator =
new CommentGenerator(lazyFileLoader, editor as any, mockRandomLogo);
1474 const generatorAny = generator as any;
1475 const comments = [
' * ',
' * ',
' * '];
1478 await generatorAny.updateEditDate(editor, comments);
1488 test(
'should handle undefined document in update', async () => {
1492 generator =
new CommentGenerator(lazyFileLoader, editor as any, mockRandomLogo);
1494 const generatorAny = generator as any;
1495 const comments = [
' * ',
' * ',
' * '];
1498 generatorAny.documentBody = undefined;
1500 await generatorAny.updateEditDate(editor, comments);
1509 test(
'should handle very long file paths', () => {
1510 const longPath =
'/very/' +
'long/'.repeat(100) +
'path/to/file.ts';
1514 generator =
new CommentGenerator(lazyFileLoader, editor as any, mockRandomLogo);
1516 const generatorAny = generator as any;
1517 assert.strictEqual(generatorAny.fileName,
'file.ts');
1518 assert.strictEqual(generatorAny.fileExtension,
'ts');
1525 test(
'should handle empty file names', () => {
1529 generator =
new CommentGenerator(lazyFileLoader, editor as any, mockRandomLogo);
1531 const generatorAny = generator as any;
1532 assert.strictEqual(generatorAny.fileName,
'unknown');
1539 test(
'should handle special characters in file names', () => {
1540 const specialPath =
'/test/file with spaces & symbols!.ts';
1544 generator =
new CommentGenerator(lazyFileLoader, editor as any, mockRandomLogo);
1546 const generatorAny = generator as any;
1547 assert.strictEqual(generatorAny.fileName,
'file with spaces & symbols!.ts');
1548 assert.strictEqual(generatorAny.fileExtension,
'ts');
1559 suite(
'Integration Tests', () => {
1564 test(
'should complete full header injection workflow', async () => {
1571 generator =
new CommentGenerator(lazyFileLoader, editor as any, mockRandomLogo);
1573 await generator.injectHeader();
1580 assert.ok(headerText.includes(
'/*'));
1581 assert.ok(headerText.includes(
'Main application entry point'));
1582 assert.ok(headerText.includes(
'main.ts'));
1583 assert.ok(headerText.includes(
'2025'));
1584 assert.ok(headerText.includes(
'*/'));
1591 test(
'should handle complete refresh workflow with existing header', async () => {
1592 const existingHeader = `
1601const app =
'Hello World';`;
1603 const document =
new MockTextDocument(
'/test/main.ts', existingHeader,
'typescript');
1608 generator =
new CommentGenerator(lazyFileLoader, editor as any, mockRandomLogo);
1610 await generator.refreshHeader(document as any);
1620 test(
'should handle multiple rapid operations', async () => {
1627 generator =
new CommentGenerator(lazyFileLoader, editor as any, mockRandomLogo);
1631 generator.injectHeader(),
1632 generator.refreshHeader(document as any),
1633 generator.injectHeader()
Generic lazy file loader with caching and type safety @template T The expected type of the loaded fil...
Mock implementation of VS Code TextDocument for testing purposes.
constructor(filePath:string, content:string='', languageId:string='typescript', eol:vscode.EndOfLine=vscode.EndOfLine.LF, isClosed:boolean=false)
Creates a new mock text document with specified configuration.
Mock implementation of VS Code TextEditor for testing text editing operations.
constructor(document:MockTextDocument)
Creates a new mock text editor for the specified document.
import *as vscode from vscode
Represents a single line within a mock VS Code document for testing.
export const Record< string,(...args:any[])=> string
export const CodeConfig
Exported configuration singleton for extension-wide access @export Primary configuration interface us...