Refactor text utilities and expand their usage
This commit refactors existing text utility functions into the application layer for broad reuse and integrates them across the codebase. Initially, these utilities were confined to test code, which limited their application. Changes: - Move text utilities to the application layer. - Centralize text utilities into dedicated files for better maintainability. - Improve robustness of utility functions with added type checks. - Replace duplicated logic with centralized utility functions throughout the codebase. - Expand unit tests to cover refactored code parts.
This commit is contained in:
@@ -5,6 +5,7 @@ import { CodePosition } from '@/application/Context/State/Code/Position/CodePosi
|
||||
import { SelectedScriptStub } from '@tests/unit/shared/Stubs/SelectedScriptStub';
|
||||
import { ScriptStub } from '@tests/unit/shared/Stubs/ScriptStub';
|
||||
import type { SelectedScript } from '@/application/Context/State/Selection/Script/SelectedScript';
|
||||
import { collectExceptionMessage } from '@tests/unit/shared/ExceptionCollector';
|
||||
|
||||
describe('CodeChangedEvent', () => {
|
||||
describe('ctor', () => {
|
||||
@@ -19,16 +20,34 @@ describe('CodeChangedEvent', () => {
|
||||
[new SelectedScriptStub(new ScriptStub('2')), new CodePosition(0, nonExistingLine2)],
|
||||
]);
|
||||
// act
|
||||
let errorText = '';
|
||||
try {
|
||||
const actualErrorMessage = collectExceptionMessage(() => {
|
||||
new CodeChangedEventBuilder()
|
||||
.withCode(code)
|
||||
.withNewScripts(newScripts)
|
||||
.build();
|
||||
} catch (error) { errorText = error.message; }
|
||||
});
|
||||
// assert
|
||||
expect(errorText).to.include(nonExistingLine1);
|
||||
expect(errorText).to.include(nonExistingLine2);
|
||||
expect(actualErrorMessage).to.include(nonExistingLine1);
|
||||
expect(actualErrorMessage).to.include(nonExistingLine2);
|
||||
});
|
||||
it('invalid line position validation counts empty lines', () => {
|
||||
// arrange
|
||||
const totalEmptyLines = 5;
|
||||
const code = '\n'.repeat(totalEmptyLines);
|
||||
// If empty lines would not be counted, this would result in error
|
||||
const existingLineEnd = totalEmptyLines;
|
||||
const newScripts = new Map<SelectedScript, ICodePosition>([
|
||||
[new SelectedScriptStub(new ScriptStub('1')), new CodePosition(0, existingLineEnd)],
|
||||
]);
|
||||
// act
|
||||
const act = () => {
|
||||
new CodeChangedEventBuilder()
|
||||
.withCode(code)
|
||||
.withNewScripts(newScripts)
|
||||
.build();
|
||||
};
|
||||
// assert
|
||||
expect(act).to.not.throw();
|
||||
});
|
||||
describe('does not throw with valid code position', () => {
|
||||
// arrange
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
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 {
|
||||
@@ -47,10 +48,24 @@ describe('CodeBuilder', () => {
|
||||
.appendLine(expected);
|
||||
// assert
|
||||
const result = sut.toString();
|
||||
const lines = getLines(result);
|
||||
const lines = splitTextIntoLines(result);
|
||||
expect(lines[1]).to.equal('str');
|
||||
});
|
||||
describe('append multi-line string as multiple lines', () => {
|
||||
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) {
|
||||
@@ -64,7 +79,7 @@ describe('CodeBuilder', () => {
|
||||
sut.appendLine(code);
|
||||
// assert
|
||||
const result = sut.toString();
|
||||
const lines = getLines(result);
|
||||
const lines = splitTextIntoLines(result);
|
||||
expect(lines).to.have.lengthOf(2);
|
||||
expect(lines[0]).to.equal(line1);
|
||||
expect(lines[1]).to.equal(line2);
|
||||
@@ -111,7 +126,7 @@ describe('CodeBuilder', () => {
|
||||
sut.appendTrailingHyphensCommentLine(totalHyphens);
|
||||
// assert
|
||||
const result = sut.toString();
|
||||
const lines = getLines(result);
|
||||
const lines = splitTextIntoLines(result);
|
||||
expect(lines[0]).to.equal(expected);
|
||||
});
|
||||
it('appendCommentLine', () => {
|
||||
@@ -126,7 +141,7 @@ describe('CodeBuilder', () => {
|
||||
.appendCommentLine(comment)
|
||||
.toString();
|
||||
// assert
|
||||
const lines = getLines(result);
|
||||
const lines = splitTextIntoLines(result);
|
||||
expect(lines[0]).to.equal(expected);
|
||||
});
|
||||
it('appendCommentLineWithHyphensAround', () => {
|
||||
@@ -142,7 +157,7 @@ describe('CodeBuilder', () => {
|
||||
.appendCommentLineWithHyphensAround(sectionName, totalHyphens)
|
||||
.toString();
|
||||
// assert
|
||||
const lines = getLines(result);
|
||||
const lines = splitTextIntoLines(result);
|
||||
expect(lines[1]).to.equal(expected);
|
||||
});
|
||||
describe('currentLine', () => {
|
||||
@@ -180,7 +195,3 @@ describe('CodeBuilder', () => {
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
function getLines(text: string): string[] {
|
||||
return text.split(/\r\n|\r|\n/);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import type { SelectedScript } from '@/application/Context/State/Selection/Script/SelectedScript';
|
||||
import { indentText } from '@/application/Common/Text/IndentText';
|
||||
import { formatAssertionMessage } from '@tests/shared/FormatAssertionMessage';
|
||||
|
||||
export function expectEqualSelectedScripts(
|
||||
@@ -37,11 +38,11 @@ function expectSameRevertStates(
|
||||
expect(scriptsWithDifferentRevertStates).to.have.lengthOf(0, formatAssertionMessage([
|
||||
'Scripts with different revert states:',
|
||||
scriptsWithDifferentRevertStates
|
||||
.map((s) => [
|
||||
.map((s) => indentText([
|
||||
`Script ID: "${s.id}"`,
|
||||
`Actual revert state: "${s.revert}"`,
|
||||
`Expected revert state: "${expected.find((existing) => existing.id === s.id)?.revert ?? 'unknown'}"`,
|
||||
].map((line) => `\t${line}`).join('\n'))
|
||||
].join('\n')))
|
||||
.join('\n---\n'),
|
||||
]));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user