import { describe, it, expect } from 'vitest'; import { CodeBuilder } from '@/application/Context/State/Code/Generation/CodeBuilder'; import { splitTextIntoLines } from '@/application/Common/Text/SplitTextIntoLines'; describe('CodeBuilder', () => { class CodeBuilderConcrete extends CodeBuilder { private commentDelimiter = '//'; private newLineTerminator = '\n'; public withCommentDelimiter(delimiter: string): CodeBuilderConcrete { this.commentDelimiter = delimiter; return this; } public withNewLineTerminator(terminator: string): CodeBuilderConcrete { this.newLineTerminator = terminator; return this; } protected getCommentDelimiter(): string { return this.commentDelimiter; } protected writeStandardOut(text: string): string { return text; } protected getNewLineTerminator(): string { return this.newLineTerminator; } } describe('appendLine', () => { it('when empty appends empty line', () => { // arrange const sut = new CodeBuilderConcrete(); // act sut.appendLine().appendLine().appendLine(); // assert expect(sut.toString()).to.equal('\n\n'); }); it('when not empty append string in new line', () => { // arrange const sut = new CodeBuilderConcrete(); const expected = 'str'; // act sut.appendLine() .appendLine(expected); // assert const result = sut.toString(); const lines = splitTextIntoLines(result); expect(lines[1]).to.equal('str'); }); describe('append multi-line string correctly', () => { it('appends multi-line string with empty lines preserved', () => { // arrange const sut = new CodeBuilderConcrete(); const expectedLines: string[] = ['', 'line1', '', 'line2', '', '', 'line3', '', '']; const multilineInput = expectedLines.join('\n'); // act sut.appendLine(multilineInput); const actual = sut.toString(); // assert const actualLines = splitTextIntoLines(actual); expect(actualLines).to.deep.equal(expectedLines); }); describe('recognizes different line terminators', () => { const delimiters = ['\n', '\r\n', '\r']; for (const delimiter of delimiters) { it(`using "${JSON.stringify(delimiter)}"`, () => { // arrange const line1 = 'line1'; const line2 = 'line2'; const code = `${line1}${delimiter}${line2}`; const sut = new CodeBuilderConcrete(); // act sut.appendLine(code); // assert const result = sut.toString(); const lines = splitTextIntoLines(result); expect(lines).to.have.lengthOf(2); expect(lines[0]).to.equal(line1); expect(lines[1]).to.equal(line2); }); } }); it('normalizes different line terminators', () => { // arrange const lineTerminator = '🐒'; const lines = ['line1', 'line2', 'line3', 'line4']; const code = `${lines[0]}\n${lines[1]}\r\n${lines[2]}\r${lines[3]}`; const expected = `${lines[0]}${lineTerminator}${lines[1]}${lineTerminator}${lines[2]}${lineTerminator}${lines[3]}`; const sut = new CodeBuilderConcrete() .withNewLineTerminator(lineTerminator); // act const actual = sut .appendLine(code) .toString(); // assert expect(actual).to.equal(expected); }); }); }); it('appendFunction', () => { // arrange const sut = new CodeBuilderConcrete(); const functionName = 'expected-function-name'; const code = 'expected-code'; // act sut.appendFunction(functionName, code); // assert const result = sut.toString(); expect(result).to.include(functionName); expect(result).to.include(code); }); it('appendTrailingHyphensCommentLine', () => { // arrange const commentDelimiter = '//'; const sut = new CodeBuilderConcrete() .withCommentDelimiter(commentDelimiter); const totalHyphens = 5; const expected = `${commentDelimiter} ${'-'.repeat(totalHyphens)}`; // act sut.appendTrailingHyphensCommentLine(totalHyphens); // assert const result = sut.toString(); const lines = splitTextIntoLines(result); expect(lines[0]).to.equal(expected); }); it('appendCommentLine', () => { // arrange const commentDelimiter = '//'; const sut = new CodeBuilderConcrete() .withCommentDelimiter(commentDelimiter); const comment = 'comment'; const expected = `${commentDelimiter} comment`; // act const result = sut .appendCommentLine(comment) .toString(); // assert const lines = splitTextIntoLines(result); expect(lines[0]).to.equal(expected); }); it('appendCommentLineWithHyphensAround', () => { // arrange const commentDelimiter = '//'; const sut = new CodeBuilderConcrete() .withCommentDelimiter(commentDelimiter); const sectionName = 'section'; const totalHyphens = sectionName.length + 3 * 2; const expected = `${commentDelimiter} ---section---`; // act const result = sut .appendCommentLineWithHyphensAround(sectionName, totalHyphens) .toString(); // assert const lines = splitTextIntoLines(result); expect(lines[1]).to.equal(expected); }); describe('currentLine', () => { it('no lines returns zero', () => { // arrange & act const sut = new CodeBuilderConcrete(); // assert expect(sut.currentLine).to.equal(0); }); it('single line returns one', () => { // arrange const sut = new CodeBuilderConcrete(); // act sut.appendLine(); // assert expect(sut.currentLine).to.equal(1); }); it('multiple lines returns as expected', () => { // arrange const sut = new CodeBuilderConcrete(); // act sut.appendLine('1') .appendCommentLine('2') .appendLine(); // assert expect(sut.currentLine).to.equal(3); }); it('multiple lines in code', () => { // arrange const sut = new CodeBuilderConcrete(); // act sut.appendLine('hello\ncode-here\nwith-3-lines'); // assert expect(sut.currentLine).to.equal(3); }); }); });