Fix failing of functions without revert code

Add missing empty/undefined handling to fix a bug where defining new
functions without `revertCode:` fails.
This commit is contained in:
undergroundwires
2021-12-21 06:01:16 +01:00
parent 5a2c263af3
commit 87de017afd
5 changed files with 61 additions and 9 deletions

View File

@@ -10,11 +10,14 @@ export class ExpressionsCompiler implements IExpressionsCompiler {
public constructor(
private readonly extractor: IExpressionParser = new CompositeExpressionParser()) { }
public compileExpressions(
code: string,
code: string | undefined,
args: IReadOnlyFunctionCallArgumentCollection): string {
if (!args) {
throw new Error('undefined args, send empty collection instead');
}
if (!code) {
return code;
}
const expressions = this.extractor.findExpressions(code);
ensureParamsUsedInCodeHasArgsProvided(expressions, args);
const context = new ExpressionEvaluationContext(args);

View File

@@ -2,6 +2,6 @@ import { IReadOnlyFunctionCallArgumentCollection } from '../Function/Call/Argume
export interface IExpressionsCompiler {
compileExpressions(
code: string,
code: string | undefined,
args: IReadOnlyFunctionCallArgumentCollection): string;
}

View File

@@ -15,6 +15,9 @@ export abstract class RegexParser implements IExpressionParser {
protected abstract buildExpression(match: RegExpMatchArray): IPrimitiveExpression;
private* findRegexExpressions(code: string): Iterable<IExpression> {
if (!code) {
throw new Error('undefined code');
}
const matches = Array.from(code.matchAll(this.regex));
for (const match of matches) {
const startPos = match.index;

View File

@@ -8,6 +8,28 @@ import { FunctionCallArgumentCollectionStub } from '@tests/unit/stubs/FunctionCa
describe('ExpressionsCompiler', () => {
describe('compileExpressions', () => {
describe('returns code when it is empty or undefined', () => {
// arrange
const testCases = [{
name: 'empty',
value: '',
}, {
name: 'undefined',
value: undefined,
},
];
for (const test of testCases) {
it(`given ${test.name}`, () => {
const expected = test.value;
const sut = new SystemUnderTest();
const args = new FunctionCallArgumentCollectionStub();
// act
const value = sut.compileExpressions(test.value, args);
// assert
expect(value).to.equal(expected);
});
}
});
describe('combines expressions as expected', () => {
// arrange
const code = 'part1 {{ a }} part2 {{ b }} part3';
@@ -49,7 +71,7 @@ describe('ExpressionsCompiler', () => {
const expressionParserMock = new ExpressionParserStub()
.withResult(testCase.expressions);
const args = new FunctionCallArgumentCollectionStub();
const sut = new MockableExpressionsCompiler(expressionParserMock);
const sut = new SystemUnderTest(expressionParserMock);
// act
const actual = sut.compileExpressions(code, args);
// assert
@@ -69,7 +91,7 @@ describe('ExpressionsCompiler', () => {
];
const expressionParserMock = new ExpressionParserStub()
.withResult(expressions);
const sut = new MockableExpressionsCompiler(expressionParserMock);
const sut = new SystemUnderTest(expressionParserMock);
// act
sut.compileExpressions(code, expected);
// assert
@@ -83,7 +105,7 @@ describe('ExpressionsCompiler', () => {
const expectedError = 'undefined args, send empty collection instead';
const args = undefined;
const expressionParserMock = new ExpressionParserStub();
const sut = new MockableExpressionsCompiler(expressionParserMock);
const sut = new SystemUnderTest(expressionParserMock);
// act
const act = () => sut.compileExpressions('code', args);
// assert
@@ -135,7 +157,7 @@ describe('ExpressionsCompiler', () => {
const code = 'non-important-code';
const expressionParserMock = new ExpressionParserStub()
.withResult(testCase.expressions);
const sut = new MockableExpressionsCompiler(expressionParserMock);
const sut = new SystemUnderTest(expressionParserMock);
// act
const act = () => sut.compileExpressions(code, testCase.args);
// assert
@@ -147,7 +169,7 @@ describe('ExpressionsCompiler', () => {
// arrange
const expected = 'expected-code';
const expressionParserMock = new ExpressionParserStub();
const sut = new MockableExpressionsCompiler(expressionParserMock);
const sut = new SystemUnderTest(expressionParserMock);
const args = new FunctionCallArgumentCollectionStub();
// act
sut.compileExpressions(expected, args);
@@ -158,8 +180,8 @@ describe('ExpressionsCompiler', () => {
});
});
class MockableExpressionsCompiler extends ExpressionsCompiler {
constructor(extractor: IExpressionParser) {
class SystemUnderTest extends ExpressionsCompiler {
constructor(extractor: IExpressionParser = new ExpressionParserStub()) {
super(extractor);
}
}

View File

@@ -7,6 +7,30 @@ import { FunctionParameterStub } from '@tests/unit/stubs/FunctionParameterStub';
describe('RegexParser', () => {
describe('findExpressions', () => {
describe('throws when code is unexpected', () => {
// arrange
const testCases = [
{
name: 'undefined',
value: undefined,
expectedError: 'undefined code',
},
{
name: 'empty',
value: '',
expectedError: 'undefined code',
},
];
for (const testCase of testCases) {
it(`given ${testCase.name}`, () => {
const sut = new RegexParserConcrete(/unimportant/);
// act
const act = () => sut.findExpressions(testCase.value);
// assert
expect(act).to.throw(testCase.expectedError);
});
}
});
describe('matches regex as expected', () => {
// arrange
const testCases = [