Add more and unify tests for absent object cases

- Unify test data for nonexistence of an object/string and collection.
- Introduce more test through adding missing test data to existing tests.
- Improve logic for checking absence of values to match tests.
- Add missing tests for absent value validation.
- Update documentation to include shared test functionality.
This commit is contained in:
undergroundwires
2022-01-21 22:34:11 +01:00
parent 0e52a99efa
commit 44d79e2c9a
100 changed files with 1380 additions and 976 deletions

View File

@@ -1,6 +1,7 @@
import 'mocha';
import { expect } from 'chai';
import { FunctionCallArgument } from '@/application/Parser/Script/Compiler/Function/Call/Argument/FunctionCallArgument';
import { itEachAbsentStringValue } from '@tests/unit/shared/TestCases/AbsentTests';
import { testParameterName } from '../../../ParameterNameTestRunner';
describe('FunctionCallArgument', () => {
@@ -13,18 +14,20 @@ describe('FunctionCallArgument', () => {
.parameterName,
);
});
it('throws if argument value is undefined', () => {
// arrange
const parameterName = 'paramName';
const expectedError = `undefined argument value for "${parameterName}"`;
const argumentValue = undefined;
// act
const act = () => new FunctionCallArgumentBuilder()
.withParameterName(parameterName)
.withArgumentValue(argumentValue)
.build();
// assert
expect(act).to.throw(expectedError);
describe('throws if argument value is absent', () => {
itEachAbsentStringValue((absentValue) => {
// arrange
const parameterName = 'paramName';
const expectedError = `missing argument value for "${parameterName}"`;
const argumentValue = absentValue;
// act
const act = () => new FunctionCallArgumentBuilder()
.withParameterName(parameterName)
.withArgumentValue(argumentValue)
.build();
// assert
expect(act).to.throw(expectedError);
});
});
});
});

View File

@@ -2,18 +2,21 @@ import 'mocha';
import { expect } from 'chai';
import { FunctionCallArgumentCollection } from '@/application/Parser/Script/Compiler/Function/Call/Argument/FunctionCallArgumentCollection';
import { FunctionCallArgumentStub } from '@tests/unit/stubs/FunctionCallArgumentStub';
import { itEachAbsentObjectValue, itEachAbsentStringValue } from '@tests/unit/shared/TestCases/AbsentTests';
describe('FunctionCallArgumentCollection', () => {
describe('addArgument', () => {
it('throws if argument is undefined', () => {
// arrange
const errorMessage = 'undefined argument';
const arg = undefined;
const sut = new FunctionCallArgumentCollection();
// act
const act = () => sut.addArgument(arg);
// assert
expect(act).to.throw(errorMessage);
describe('throws if argument is missing', () => {
itEachAbsentObjectValue((absentValue) => {
// arrange
const errorMessage = 'missing argument';
const arg = absentValue;
const sut = new FunctionCallArgumentCollection();
// act
const act = () => sut.addArgument(arg);
// assert
expect(act).to.throw(errorMessage);
});
});
it('throws if parameter value is already provided', () => {
// arrange
@@ -58,17 +61,17 @@ describe('FunctionCallArgumentCollection', () => {
});
});
describe('getArgument', () => {
it('throws if parameter name is undefined', () => {
// arrange
const expectedError = 'undefined parameter name';
const undefinedValues = ['', undefined];
for (const undefinedValue of undefinedValues) {
describe('throws if parameter name is absent', () => {
itEachAbsentStringValue((absentValue) => {
// arrange
const expectedError = 'missing parameter name';
const sut = new FunctionCallArgumentCollection();
const parameterName = absentValue;
// act
const act = () => sut.getArgument(undefinedValue);
const act = () => sut.getArgument(parameterName);
// assert
expect(act).to.throw(expectedError);
}
});
});
it('throws if argument does not exist', () => {
// arrange
@@ -94,17 +97,17 @@ describe('FunctionCallArgumentCollection', () => {
});
});
describe('hasArgument', () => {
it('throws if parameter name is undefined', () => {
// arrange
const expectedError = 'undefined parameter name';
const undefinedValues = ['', undefined];
for (const undefinedValue of undefinedValues) {
describe('throws if parameter name is missing', () => {
itEachAbsentStringValue((absentValue) => {
// arrange
const expectedError = 'missing parameter name';
const parameterName = absentValue;
const sut = new FunctionCallArgumentCollection();
// act
const act = () => sut.hasArgument(undefinedValue);
const act = () => sut.hasArgument(parameterName);
// assert
expect(act).to.throw(expectedError);
}
});
});
describe('returns as expected', () => {
// arrange

View File

@@ -10,35 +10,40 @@ import { SharedFunctionStub } from '@tests/unit/stubs/SharedFunctionStub';
import { FunctionCallArgumentCollectionStub } from '@tests/unit/stubs/FunctionCallArgumentCollectionStub';
import { FunctionCallStub } from '@tests/unit/stubs/FunctionCallStub';
import { ExpressionsCompilerStub } from '@tests/unit/stubs/ExpressionsCompilerStub';
import { itEachAbsentObjectValue } from '@tests/unit/shared/TestCases/AbsentTests';
describe('FunctionCallCompiler', () => {
describe('compileCall', () => {
describe('parameter validation', () => {
describe('call', () => {
it('throws with undefined call', () => {
// arrange
const expectedError = 'undefined calls';
const call = undefined;
const functions = new SharedFunctionCollectionStub();
const sut = new MockableFunctionCallCompiler();
// act
const act = () => sut.compileCall(call, functions);
// assert
expect(act).to.throw(expectedError);
describe('throws with missing call', () => {
itEachAbsentObjectValue((absentValue) => {
// arrange
const expectedError = 'missing calls';
const call = absentValue;
const functions = new SharedFunctionCollectionStub();
const sut = new MockableFunctionCallCompiler();
// act
const act = () => sut.compileCall(call, functions);
// assert
expect(act).to.throw(expectedError);
});
});
it('throws if call sequence has undefined call', () => {
// arrange
const expectedError = 'undefined function call';
const call = [
new FunctionCallStub(),
undefined,
];
const functions = new SharedFunctionCollectionStub();
const sut = new MockableFunctionCallCompiler();
// act
const act = () => sut.compileCall(call, functions);
// assert
expect(act).to.throw(expectedError);
describe('throws if call sequence has absent call', () => {
itEachAbsentObjectValue((absentValue) => {
// arrange
const expectedError = 'missing function call';
const call = [
new FunctionCallStub(),
absentValue,
];
const functions = new SharedFunctionCollectionStub();
const sut = new MockableFunctionCallCompiler();
// act
const act = () => sut.compileCall(call, functions);
// assert
expect(act).to.throw(expectedError);
});
});
describe('throws if call parameters does not match function parameters', () => {
// arrange
@@ -109,16 +114,18 @@ describe('FunctionCallCompiler', () => {
});
});
describe('functions', () => {
it('throws with undefined functions', () => {
// arrange
const expectedError = 'undefined functions';
const call = new FunctionCallStub();
const functions = undefined;
const sut = new MockableFunctionCallCompiler();
// act
const act = () => sut.compileCall([call], functions);
// assert
expect(act).to.throw(expectedError);
describe('throws with missing functions', () => {
itEachAbsentObjectValue((absentValue) => {
// arrange
const expectedError = 'missing functions';
const call = new FunctionCallStub();
const functions = absentValue;
const sut = new MockableFunctionCallCompiler();
// act
const act = () => sut.compileCall([call], functions);
// assert
expect(act).to.throw(expectedError);
});
});
it('throws if function does not exist', () => {
// arrange

View File

@@ -3,20 +3,23 @@ import { expect } from 'chai';
import { FunctionCall } from '@/application/Parser/Script/Compiler/Function/Call/FunctionCall';
import { IReadOnlyFunctionCallArgumentCollection } from '@/application/Parser/Script/Compiler/Function/Call/Argument/IFunctionCallArgumentCollection';
import { FunctionCallArgumentCollectionStub } from '@tests/unit/stubs/FunctionCallArgumentCollectionStub';
import { itEachAbsentObjectValue, itEachAbsentStringValue } from '@tests/unit/shared/TestCases/AbsentTests';
describe('FunctionCall', () => {
describe('ctor', () => {
describe('args', () => {
it('throws when args is undefined', () => {
// arrange
const expectedError = 'undefined args';
const args = undefined;
// act
const act = () => new FunctionCallBuilder()
.withArgs(args)
.build();
// assert
expect(act).to.throw(expectedError);
describe('throws when args is missing', () => {
itEachAbsentObjectValue((absentValue) => {
// arrange
const expectedError = 'missing args';
const args = absentValue;
// act
const act = () => new FunctionCallBuilder()
.withArgs(args)
.build();
// assert
expect(act).to.throw(expectedError);
});
});
it('sets args as expected', () => {
// arrange
@@ -31,16 +34,18 @@ describe('FunctionCall', () => {
});
});
describe('functionName', () => {
it('throws when function name is undefined', () => {
// arrange
const expectedError = 'empty function name in function call';
const functionName = undefined;
// act
const act = () => new FunctionCallBuilder()
.withFunctionName(functionName)
.build();
// assert
expect(act).to.throw(expectedError);
describe('throws when function name is missing', () => {
itEachAbsentStringValue((absentValue) => {
// arrange
const expectedError = 'missing function name in function call';
const functionName = absentValue;
// act
const act = () => new FunctionCallBuilder()
.withFunctionName(functionName)
.build();
// assert
expect(act).to.throw(expectedError);
});
});
it('sets function name as expected', () => {
// arrange

View File

@@ -2,17 +2,20 @@ import 'mocha';
import { expect } from 'chai';
import { parseFunctionCalls } from '@/application/Parser/Script/Compiler/Function/Call/FunctionCallParser';
import { FunctionCallDataStub } from '@tests/unit/stubs/FunctionCallDataStub';
import { itEachAbsentObjectValue, itEachAbsentStringValue } from '@tests/unit/shared/TestCases/AbsentTests';
describe('FunctionCallParser', () => {
describe('parseFunctionCalls', () => {
it('throws with undefined call', () => {
// arrange
const expectedError = 'undefined call data';
const call = undefined;
// act
const act = () => parseFunctionCalls(call);
// assert
expect(act).to.throw(expectedError);
describe('throws with missing call data', () => {
itEachAbsentObjectValue((absentValue) => {
// arrange
const expectedError = 'missing call data';
const call = absentValue;
// act
const act = () => parseFunctionCalls(call);
// assert
expect(act).to.throw(expectedError);
});
});
it('throws if call is not an object', () => {
// arrange
@@ -25,29 +28,33 @@ describe('FunctionCallParser', () => {
expect(act).to.throw(expectedError);
});
});
it('throws if call sequence has undefined call', () => {
// arrange
const expectedError = 'undefined function call';
const data = [
new FunctionCallDataStub(),
undefined,
];
// act
const act = () => parseFunctionCalls(data);
// assert
expect(act).to.throw(expectedError);
describe('throws if call sequence has undefined call', () => {
itEachAbsentObjectValue((absentValue) => {
// arrange
const expectedError = 'missing call data';
const data = [
new FunctionCallDataStub(),
absentValue,
];
// act
const act = () => parseFunctionCalls(data);
// assert
expect(act).to.throw(expectedError);
});
});
it('throws if call sequence has undefined function name', () => {
// arrange
const expectedError = 'empty function name in function call';
const data = [
new FunctionCallDataStub().withName('function-name'),
new FunctionCallDataStub().withName(undefined),
];
// act
const act = () => parseFunctionCalls(data);
// assert
expect(act).to.throw(expectedError);
describe('throws if call sequence has undefined function name', () => {
itEachAbsentStringValue((absentValue) => {
// arrange
const expectedError = 'missing function name in function call';
const data = [
new FunctionCallDataStub().withName('function-name'),
new FunctionCallDataStub().withName(absentValue),
];
// act
const act = () => parseFunctionCalls(data);
// assert
expect(act).to.throw(expectedError);
});
});
it('parses single call as expected', () => {
// arrange

View File

@@ -2,6 +2,7 @@ import 'mocha';
import { expect } from 'chai';
import { FunctionParameterCollection } from '@/application/Parser/Script/Compiler/Function/Parameter/FunctionParameterCollection';
import { FunctionParameterStub } from '@tests/unit/stubs/FunctionParameterStub';
import { itEachAbsentObjectValue } from '@tests/unit/shared/TestCases/AbsentTests';
describe('FunctionParameterCollection', () => {
it('all returns added parameters as expected', () => {
@@ -34,15 +35,17 @@ describe('FunctionParameterCollection', () => {
expect(act).to.throw(expectedError);
});
describe('addParameter', () => {
it('throws if parameter is undefined', () => {
// arrange
const expectedError = 'undefined parameter';
const value = undefined;
const sut = new FunctionParameterCollection();
// act
const act = () => sut.addParameter(value);
// assert
expect(act).to.throw(expectedError);
describe('throws if parameter is undefined', () => {
itEachAbsentObjectValue((absentValue) => {
// arrange
const expectedError = 'missing parameter';
const value = absentValue;
const sut = new FunctionParameterCollection();
// act
const act = () => sut.addParameter(value);
// assert
expect(act).to.throw(expectedError);
});
});
});
});

View File

@@ -6,6 +6,10 @@ import { createCallerFunction, createFunctionWithInlineCode } from '@/applicatio
import { IFunctionCall } from '@/application/Parser/Script/Compiler/Function/Call/IFunctionCall';
import { FunctionCallStub } from '@tests/unit/stubs/FunctionCallStub';
import { FunctionBodyType, ISharedFunction } from '@/application/Parser/Script/Compiler/Function/ISharedFunction';
import {
AbsentStringTestCases, itEachAbsentCollectionValue, itEachAbsentObjectValue,
itEachAbsentStringValue,
} from '@tests/unit/shared/TestCases/AbsentTests';
describe('SharedFunction', () => {
describe('name', () => {
@@ -20,18 +24,17 @@ describe('SharedFunction', () => {
// assert
expect(sut.name).equal(expected);
});
it('throws if empty or undefined', () => {
// arrange
const expectedError = 'undefined function name';
const invalidValues = [undefined, ''];
for (const invalidValue of invalidValues) {
it('throws when absent', () => {
itEachAbsentStringValue((absentValue) => {
// arrange
const expectedError = 'missing function name';
const builder = new SharedFunctionBuilder()
.withName(invalidValue);
.withName(absentValue);
// act
const act = () => build(builder);
// assert
expect(act).to.throw(expectedError);
}
});
});
});
});
@@ -48,16 +51,18 @@ describe('SharedFunction', () => {
// assert
expect(sut.parameters).equal(expected);
});
it('throws if undefined', () => {
// arrange
const expectedError = 'undefined parameters';
const parameters = undefined;
const builder = new SharedFunctionBuilder()
.withParameters(parameters);
// act
const act = () => build(builder);
// assert
expect(act).to.throw(expectedError);
describe('throws if missing', () => {
itEachAbsentObjectValue((absentValue) => {
// arrange
const expectedError = 'missing parameters';
const parameters = absentValue;
const builder = new SharedFunctionBuilder()
.withParameters(parameters);
// act
const act = () => build(builder);
// assert
expect(act).to.throw(expectedError);
});
});
});
});
@@ -74,12 +79,12 @@ describe('SharedFunction', () => {
// assert
expect(sut.body.code.do).equal(expected);
});
it('throws if empty or undefined', () => {
// arrange
const functionName = 'expected-function-name';
const expectedError = `undefined code in function "${functionName}"`;
const invalidValues = [undefined, ''];
for (const invalidValue of invalidValues) {
describe('throws if absent', () => {
itEachAbsentStringValue((absentValue) => {
// arrange
const functionName = 'expected-function-name';
const expectedError = `undefined code in function "${functionName}"`;
const invalidValue = absentValue;
// act
const act = () => new SharedFunctionBuilder()
.withName(functionName)
@@ -87,13 +92,16 @@ describe('SharedFunction', () => {
.createFunctionWithInlineCode();
// assert
expect(act).to.throw(expectedError);
}
});
});
});
describe('revertCode', () => {
it('sets as expected', () => {
// arrange
const testData = ['expected-revert-code', undefined, ''];
const testData = [
'expected-revert-code',
...AbsentStringTestCases.map((testCase) => testCase.absentValue),
];
for (const data of testData) {
// act
const sut = new SharedFunctionBuilder()
@@ -138,31 +146,20 @@ describe('SharedFunction', () => {
// assert
expect(sut.body.calls).equal(expected);
});
it('throws if undefined', () => {
// arrange
const functionName = 'invalidFunction';
const callSequence = undefined;
const expectedError = `undefined call sequence in function "${functionName}"`;
// act
const act = () => new SharedFunctionBuilder()
.withName(functionName)
.withCallSequence(callSequence)
.createCallerFunction();
// assert
expect(act).to.throw(expectedError);
});
it('throws if empty', () => {
// arrange
const functionName = 'invalidFunction';
const callSequence = [];
const expectedError = `empty call sequence in function "${functionName}"`;
// act
const act = () => new SharedFunctionBuilder()
.withName(functionName)
.withCallSequence(callSequence)
.createCallerFunction();
// assert
expect(act).to.throw(expectedError);
describe('throws if missing', () => {
itEachAbsentCollectionValue((absentValue) => {
// arrange
const functionName = 'invalidFunction';
const callSequence = absentValue;
const expectedError = `missing call sequence in function "${functionName}"`;
// act
const act = () => new SharedFunctionBuilder()
.withName(functionName)
.withCallSequence(callSequence)
.createCallerFunction();
// assert
expect(act).to.throw(expectedError);
});
});
});
it('sets type as expected', () => {

View File

@@ -4,18 +4,21 @@ import { SharedFunctionCollection } from '@/application/Parser/Script/Compiler/F
import { SharedFunctionStub } from '@tests/unit/stubs/SharedFunctionStub';
import { FunctionBodyType } from '@/application/Parser/Script/Compiler/Function/ISharedFunction';
import { FunctionCallStub } from '@tests/unit/stubs/FunctionCallStub';
import { itEachAbsentObjectValue, itEachAbsentStringValue } from '@tests/unit/shared/TestCases/AbsentTests';
describe('SharedFunctionCollection', () => {
describe('addFunction', () => {
it('throws if function is undefined', () => {
// arrange
const expectedError = 'undefined function';
const func = undefined;
const sut = new SharedFunctionCollection();
// act
const act = () => sut.addFunction(func);
// assert
expect(act).to.throw(expectedError);
describe('throws if function is missing', () => {
itEachAbsentObjectValue((absentValue) => {
// arrange
const expectedError = 'missing function';
const func = absentValue;
const sut = new SharedFunctionCollection();
// act
const act = () => sut.addFunction(func);
// assert
expect(act).to.throw(expectedError);
});
});
it('throws if function with same name already exists', () => {
// arrange
@@ -32,18 +35,16 @@ describe('SharedFunctionCollection', () => {
});
});
describe('getFunctionByName', () => {
it('throws if name is undefined', () => {
// arrange
const expectedError = 'undefined function name';
const invalidValues = [undefined, ''];
const sut = new SharedFunctionCollection();
for (const invalidValue of invalidValues) {
const name = invalidValue;
describe('throws if name is absent', () => {
itEachAbsentStringValue((absentValue) => {
// arrange
const expectedError = 'missing function name';
const sut = new SharedFunctionCollection();
// act
const act = () => sut.getFunctionByName(name);
const act = () => sut.getFunctionByName(absentValue);
// assert
expect(act).to.throw(expectedError);
}
});
});
it('throws if function does not exist', () => {
// arrange

View File

@@ -7,19 +7,22 @@ import { FunctionDataStub } from '@tests/unit/stubs/FunctionDataStub';
import { ParameterDefinitionDataStub } from '@tests/unit/stubs/ParameterDefinitionDataStub';
import { FunctionParameter } from '@/application/Parser/Script/Compiler/Function/Parameter/FunctionParameter';
import { FunctionCallDataStub } from '@tests/unit/stubs/FunctionCallDataStub';
import { itEachAbsentCollectionValue, itEachAbsentObjectValue } from '@tests/unit/shared/TestCases/AbsentTests';
describe('SharedFunctionsParser', () => {
describe('parseFunctions', () => {
describe('validates functions', () => {
it('throws if one of the functions is undefined', () => {
// arrange
const expectedError = 'some functions are undefined';
const functions = [FunctionDataStub.createWithCode(), undefined];
const sut = new SharedFunctionsParser();
// act
const act = () => sut.parseFunctions(functions);
// assert
expect(act).to.throw(expectedError);
describe('throws if one of the functions is undefined', () => {
itEachAbsentObjectValue((absentValue) => {
// arrange
const expectedError = 'some functions are undefined';
const functions = [FunctionDataStub.createWithCode(), absentValue];
const sut = new SharedFunctionsParser();
// act
const act = () => sut.parseFunctions(functions);
// assert
expect(act).to.throw(expectedError);
});
});
it('throws when functions have same names', () => {
// arrange
@@ -143,17 +146,14 @@ describe('SharedFunctionsParser', () => {
expect(act).to.throw(expectedError);
});
});
describe('empty functions', () => {
it('returns empty collection', () => {
describe('given empty functions, returns empty collection', () => {
itEachAbsentCollectionValue((absentValue) => {
// arrange
const emptyValues = [[], undefined];
const sut = new SharedFunctionsParser();
for (const emptyFunctions of emptyValues) {
// act
const actual = sut.parseFunctions(emptyFunctions);
// assert
expect(actual).to.not.equal(undefined);
}
// act
const actual = sut.parseFunctions(absentValue);
// assert
expect(actual).to.not.equal(undefined);
});
});
describe('function with inline code', () => {