128 lines
4.6 KiB
TypeScript
128 lines
4.6 KiB
TypeScript
import 'mocha';
|
|
import { expect } from 'chai';
|
|
import { ExpressionPosition } from '@/application/Parser/Script/Compiler/Expressions/Expression/ExpressionPosition';
|
|
import { IExpressionParser } from '@/application/Parser/Script/Compiler/Expressions/Parser/IExpressionParser';
|
|
import { FunctionCallArgumentCollectionStub } from '@tests/unit/shared/Stubs/FunctionCallArgumentCollectionStub';
|
|
import { ExpressionEvaluationContextStub } from '@tests/unit/shared/Stubs/ExpressionEvaluationContextStub';
|
|
import { PipelineCompilerStub } from '@tests/unit/shared/Stubs/PipelineCompilerStub';
|
|
|
|
export class SyntaxParserTestsRunner {
|
|
constructor(private readonly sut: IExpressionParser) {
|
|
}
|
|
|
|
public expectPosition(...testCases: IExpectPositionTestCase[]) {
|
|
for (const testCase of testCases) {
|
|
it(testCase.name, () => {
|
|
// act
|
|
const expressions = this.sut.findExpressions(testCase.code);
|
|
// assert
|
|
const actual = expressions.map((e) => e.position);
|
|
expect(actual).to.deep.equal(testCase.expected);
|
|
});
|
|
}
|
|
return this;
|
|
}
|
|
|
|
public expectResults(...testCases: IExpectResultTestCase[]) {
|
|
for (const testCase of testCases) {
|
|
it(testCase.name, () => {
|
|
// arrange
|
|
const args = testCase.args(new FunctionCallArgumentCollectionStub());
|
|
const context = new ExpressionEvaluationContextStub()
|
|
.withArgs(args);
|
|
// act
|
|
const expressions = this.sut.findExpressions(testCase.code);
|
|
// assert
|
|
const actual = expressions.map((e) => e.evaluate(context));
|
|
expect(actual).to.deep.equal(testCase.expected);
|
|
});
|
|
}
|
|
return this;
|
|
}
|
|
|
|
public expectPipeHits(data: IExpectPipeHitTestData) {
|
|
for (const validPipePart of PipeTestCases.ValidValues) {
|
|
this.expectHitPipePart(validPipePart, data);
|
|
}
|
|
for (const invalidPipePart of PipeTestCases.InvalidValues) {
|
|
this.expectMissPipePart(invalidPipePart, data);
|
|
}
|
|
}
|
|
|
|
private expectHitPipePart(pipeline: string, data: IExpectPipeHitTestData) {
|
|
it(`"${pipeline}" hits`, () => {
|
|
// arrange
|
|
const expectedPipePart = pipeline.trim();
|
|
const code = data.codeBuilder(pipeline);
|
|
const args = new FunctionCallArgumentCollectionStub()
|
|
.withArgument(data.parameterName, data.parameterValue);
|
|
const pipelineCompiler = new PipelineCompilerStub();
|
|
const context = new ExpressionEvaluationContextStub()
|
|
.withPipelineCompiler(pipelineCompiler)
|
|
.withArgs(args);
|
|
// act
|
|
const expressions = this.sut.findExpressions(code);
|
|
expressions[0].evaluate(context);
|
|
// assert
|
|
expect(expressions).has.lengthOf(1);
|
|
expect(pipelineCompiler.compileHistory).has.lengthOf(1);
|
|
const actualPipeNames = pipelineCompiler.compileHistory[0].pipeline;
|
|
const actualValue = pipelineCompiler.compileHistory[0].value;
|
|
expect(actualPipeNames).to.equal(expectedPipePart);
|
|
expect(actualValue).to.equal(data.parameterValue);
|
|
});
|
|
}
|
|
|
|
private expectMissPipePart(pipeline: string, data: IExpectPipeHitTestData) {
|
|
it(`"${pipeline}" misses`, () => {
|
|
// arrange
|
|
const args = new FunctionCallArgumentCollectionStub()
|
|
.withArgument(data.parameterName, data.parameterValue);
|
|
const pipelineCompiler = new PipelineCompilerStub();
|
|
const context = new ExpressionEvaluationContextStub()
|
|
.withPipelineCompiler(pipelineCompiler)
|
|
.withArgs(args);
|
|
const code = data.codeBuilder(pipeline);
|
|
// act
|
|
const expressions = this.sut.findExpressions(code);
|
|
expressions[0]?.evaluate(context); // Because an expression may include another with pipes
|
|
// assert
|
|
expect(pipelineCompiler.compileHistory).has.lengthOf(0);
|
|
});
|
|
}
|
|
}
|
|
interface IExpectResultTestCase {
|
|
name: string;
|
|
code: string;
|
|
args: (builder: FunctionCallArgumentCollectionStub) => FunctionCallArgumentCollectionStub;
|
|
expected: readonly string[];
|
|
}
|
|
|
|
interface IExpectPositionTestCase {
|
|
name: string;
|
|
code: string;
|
|
expected: readonly ExpressionPosition[];
|
|
}
|
|
|
|
interface IExpectPipeHitTestData {
|
|
codeBuilder: (pipeline: string) => string;
|
|
parameterName: string;
|
|
parameterValue: string;
|
|
}
|
|
|
|
const PipeTestCases = {
|
|
ValidValues: [
|
|
// Single pipe with different whitespace combinations
|
|
' | pipe1', ' |pipe1', '|pipe1', ' |pipe1', ' | pipe1',
|
|
|
|
// Double pipes with different whitespace combinations
|
|
' | pipe1 | pipe2', '| pipe1|pipe2', '|pipe1|pipe2', ' |pipe1 |pipe2', '| pipe1 | pipe2| pipe3 |pipe4',
|
|
|
|
// Wrong cases, but should match anyway and let pipelineCompiler throw errors
|
|
'| pip€', '| pip{e} ',
|
|
],
|
|
InvalidValues: [
|
|
' pipe1 |pipe2', ' pipe1',
|
|
],
|
|
};
|