Add validation for max line length in compiler
This commit adds validation logic in compiler to check for max allowed characters per line for scripts. This allows preventing bugs caused by limitation of terminal emulators. Other supporting changes: - Rename/refactor related code for clarity and better maintainability. - Drop `I` prefix from interfaces to align with latest convention. - Refactor CodeValidator to be functional rather than object-oriented for simplicity. - Refactor syntax definition construction to be functional and be part of rule for better separation of concerns. - Refactored validation logic to use an enum-based factory pattern for improved maintainability and scalability.
This commit is contained in:
@@ -0,0 +1,115 @@
|
||||
import { describe } from 'vitest';
|
||||
import { analyzeEmptyLines } from '@/application/Parser/Executable/Script/Validation/Analyzers/AnalyzeEmptyLines';
|
||||
import type { CodeLine, InvalidCodeLine } from '@/application/Parser/Executable/Script/Validation/Analyzers/CodeValidationAnalyzer';
|
||||
import { ScriptingLanguage } from '@/domain/ScriptingLanguage';
|
||||
import { createCodeLines } from './CreateCodeLines';
|
||||
import { expectSameInvalidCodeLines } from './ExpectSameInvalidCodeLines';
|
||||
|
||||
describe('AnalyzeEmptyLines', () => {
|
||||
describe('analyzeEmptyLines', () => {
|
||||
it('returns no results for non-empty lines', () => {
|
||||
// arrange
|
||||
const expected: InvalidCodeLine[] = [];
|
||||
const context = new TestContext()
|
||||
.withLines([
|
||||
/* 1 */ 'non-empty-line1', /* 2 */ 'none-empty-line2',
|
||||
]);
|
||||
// act
|
||||
const actual = context.analyze();
|
||||
// assert
|
||||
expectSameInvalidCodeLines(actual, expected);
|
||||
});
|
||||
it('identifies single empty line', () => {
|
||||
// arrange
|
||||
const expected: InvalidCodeLine[] = [
|
||||
{ lineNumber: 2, error: 'Empty line' },
|
||||
];
|
||||
const context = new TestContext()
|
||||
.withLines([
|
||||
/* 1 */ 'first line', /* 2 */ '', /* 3 */ 'third line',
|
||||
]);
|
||||
// act
|
||||
const actual = context.analyze();
|
||||
// assert
|
||||
expectSameInvalidCodeLines(actual, expected);
|
||||
});
|
||||
it('identifies multiple empty lines', () => {
|
||||
// arrange
|
||||
const expected: InvalidCodeLine[] = [2, 4].map((index): InvalidCodeLine => ({ lineNumber: index, error: 'Empty line' }));
|
||||
const context = new TestContext()
|
||||
.withLines([
|
||||
/* 1 */ 'first line', /* 2 */ '', /* 3 */ 'third line', /* 4 */ '',
|
||||
]);
|
||||
// act
|
||||
const actual = context.analyze();
|
||||
// assert
|
||||
expectSameInvalidCodeLines(actual, expected);
|
||||
});
|
||||
it('identifies lines with only spaces', () => {
|
||||
// arrange
|
||||
const expected: InvalidCodeLine[] = [
|
||||
{ lineNumber: 2, error: 'Empty line: "{whitespace}{whitespace}"' },
|
||||
];
|
||||
const context = new TestContext()
|
||||
.withLines([
|
||||
/* 1 */ 'first line', /* 2 */ ' ', /* 3 */ 'third line',
|
||||
]);
|
||||
// act
|
||||
const actual = context.analyze();
|
||||
// assert
|
||||
expectSameInvalidCodeLines(actual, expected);
|
||||
});
|
||||
it('identifies lines with only tabs', () => {
|
||||
// arrange
|
||||
const expected: InvalidCodeLine[] = [
|
||||
{ lineNumber: 2, error: 'Empty line: "{tab}{tab}"' },
|
||||
];
|
||||
const context = new TestContext()
|
||||
.withLines([
|
||||
/* 1 */ 'first line', /* 2 */ '\t\t', /* 3 */ 'third line',
|
||||
]);
|
||||
// act
|
||||
const actual = context.analyze();
|
||||
// assert
|
||||
expectSameInvalidCodeLines(actual, expected);
|
||||
});
|
||||
it('identifies lines with mixed spaces and tabs', () => {
|
||||
// arrange
|
||||
const expected: InvalidCodeLine[] = [
|
||||
{ lineNumber: 2, error: 'Empty line: "{tab}{whitespace}{tab}"' },
|
||||
{ lineNumber: 4, error: 'Empty line: "{whitespace}{tab}{whitespace}"' },
|
||||
];
|
||||
const context = new TestContext()
|
||||
.withLines([
|
||||
/* 1 */ 'first line', /* 2 */ '\t \t', /* 3 */ 'third line', /* 4 */ ' \t ',
|
||||
]);
|
||||
// act
|
||||
const actual = context.analyze();
|
||||
// assert
|
||||
expectSameInvalidCodeLines(actual, expected);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
export class TestContext {
|
||||
private codeLines: readonly CodeLine[] = createCodeLines(['test-code-line']);
|
||||
|
||||
private language = ScriptingLanguage.batchfile;
|
||||
|
||||
public withLines(lines: readonly string[]): this {
|
||||
this.codeLines = createCodeLines(lines);
|
||||
return this;
|
||||
}
|
||||
|
||||
public withLanguage(language: ScriptingLanguage): this {
|
||||
this.language = language;
|
||||
return this;
|
||||
}
|
||||
|
||||
public analyze() {
|
||||
return analyzeEmptyLines(
|
||||
this.codeLines,
|
||||
this.language,
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user