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:
@@ -2,17 +2,20 @@ import 'mocha';
|
||||
import { expect } from 'chai';
|
||||
import { ApplicationFactory, ApplicationGetterType } from '@/application/ApplicationFactory';
|
||||
import { ApplicationStub } from '@tests/unit/stubs/ApplicationStub';
|
||||
import { itEachAbsentObjectValue } from '@tests/unit/shared/TestCases/AbsentTests';
|
||||
|
||||
describe('ApplicationFactory', () => {
|
||||
describe('ctor', () => {
|
||||
it('throws if getter is undefined', () => {
|
||||
// arrange
|
||||
const expectedError = 'undefined getter';
|
||||
const getter = undefined;
|
||||
// act
|
||||
const act = () => new SystemUnderTest(getter);
|
||||
// assert
|
||||
expect(act).to.throw(expectedError);
|
||||
describe('throws if getter is absent', () => {
|
||||
itEachAbsentObjectValue((absentValue) => {
|
||||
// arrange
|
||||
const expectedError = 'missing getter';
|
||||
const getter: ApplicationGetterType = absentValue;
|
||||
// act
|
||||
const act = () => new SystemUnderTest(getter);
|
||||
// assert
|
||||
expect(act).to.throw(expectedError);
|
||||
});
|
||||
});
|
||||
});
|
||||
describe('getApp', () => {
|
||||
|
||||
@@ -1,20 +1,35 @@
|
||||
import 'mocha';
|
||||
import { expect } from 'chai';
|
||||
import { scrambledEqual, sequenceEqual } from '@/application/Common/Array';
|
||||
import { itEachAbsentObjectValue } from '@tests/unit/shared/TestCases/AbsentTests';
|
||||
import { ComparerTestScenario } from './Array.ComparerTestScenario';
|
||||
|
||||
describe('Array', () => {
|
||||
describe('scrambledEqual', () => {
|
||||
describe('throws if arguments are undefined', () => {
|
||||
it('first argument is undefined', () => {
|
||||
const expectedError = 'undefined first array';
|
||||
const act = () => scrambledEqual(undefined, []);
|
||||
expect(act).to.throw(expectedError);
|
||||
describe('throws if arguments are absent', () => {
|
||||
describe('first argument is absent', () => {
|
||||
itEachAbsentObjectValue((absentValue) => {
|
||||
// arrange
|
||||
const expectedError = 'missing first array';
|
||||
const firstArray = absentValue;
|
||||
const secondArray = [];
|
||||
// act
|
||||
const act = () => scrambledEqual(firstArray, secondArray);
|
||||
// assert
|
||||
expect(act).to.throw(expectedError);
|
||||
});
|
||||
});
|
||||
it('second arguments is undefined', () => {
|
||||
const expectedError = 'undefined second array';
|
||||
const act = () => scrambledEqual([], undefined);
|
||||
expect(act).to.throw(expectedError);
|
||||
describe('second argument is absent', () => {
|
||||
itEachAbsentObjectValue((absentValue) => {
|
||||
// arrange
|
||||
const expectedError = 'missing second array';
|
||||
const firstArray = [];
|
||||
const secondArray = absentValue;
|
||||
// act
|
||||
const act = () => scrambledEqual(firstArray, secondArray);
|
||||
// assert
|
||||
expect(act).to.throw(expectedError);
|
||||
});
|
||||
});
|
||||
});
|
||||
describe('returns as expected', () => {
|
||||
@@ -35,16 +50,30 @@ describe('Array', () => {
|
||||
});
|
||||
});
|
||||
describe('sequenceEqual', () => {
|
||||
describe('throws if arguments are undefined', () => {
|
||||
it('first argument is undefined', () => {
|
||||
const expectedError = 'undefined first array';
|
||||
const act = () => sequenceEqual(undefined, []);
|
||||
expect(act).to.throw(expectedError);
|
||||
describe('throws if arguments are absent', () => {
|
||||
describe('first argument is absent', () => {
|
||||
itEachAbsentObjectValue((absentValue) => {
|
||||
// arrange
|
||||
const expectedError = 'missing first array';
|
||||
const firstArray = absentValue;
|
||||
const secondArray = [];
|
||||
// act
|
||||
const act = () => sequenceEqual(firstArray, secondArray);
|
||||
// assert
|
||||
expect(act).to.throw(expectedError);
|
||||
});
|
||||
});
|
||||
it('second arguments is undefined', () => {
|
||||
const expectedError = 'undefined second array';
|
||||
const act = () => sequenceEqual([], undefined);
|
||||
expect(act).to.throw(expectedError);
|
||||
describe('second argument is absent', () => {
|
||||
itEachAbsentObjectValue((absentValue) => {
|
||||
// arrange
|
||||
const expectedError = 'missing second array';
|
||||
const firstArray = [];
|
||||
const secondArray = absentValue;
|
||||
// act
|
||||
const act = () => sequenceEqual(firstArray, secondArray);
|
||||
// assert
|
||||
expect(act).to.throw(expectedError);
|
||||
});
|
||||
});
|
||||
});
|
||||
describe('returns as expected', () => {
|
||||
|
||||
@@ -4,6 +4,7 @@ import {
|
||||
getEnumNames, getEnumValues, createEnumParser, assertInRange,
|
||||
} from '@/application/Common/Enum';
|
||||
import { scrambledEqual } from '@/application/Common/Array';
|
||||
import { AbsentStringTestCases } from '@tests/unit/shared/TestCases/AbsentTests';
|
||||
import { EnumRangeTestRunner } from './EnumRangeTestRunner';
|
||||
|
||||
describe('Enum', () => {
|
||||
@@ -37,16 +38,11 @@ describe('Enum', () => {
|
||||
// arrange
|
||||
const enumName = 'ParsableEnum';
|
||||
const testCases = [
|
||||
{
|
||||
name: 'undefined',
|
||||
value: undefined,
|
||||
expectedError: `undefined ${enumName}`,
|
||||
},
|
||||
{
|
||||
name: 'empty',
|
||||
value: '',
|
||||
expectedError: `undefined ${enumName}`,
|
||||
},
|
||||
...AbsentStringTestCases.map((test) => ({
|
||||
name: test.valueName,
|
||||
value: test.absentValue,
|
||||
expectedError: `missing ${enumName}`,
|
||||
})),
|
||||
{
|
||||
name: 'out of range',
|
||||
value: 'value3',
|
||||
@@ -105,7 +101,7 @@ describe('Enum', () => {
|
||||
// assert
|
||||
new EnumRangeTestRunner(act)
|
||||
.testOutOfRangeThrows()
|
||||
.testUndefinedValueThrows()
|
||||
.testAbsentValueThrows()
|
||||
.testValidValueDoesNotThrow(validValue);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import 'mocha';
|
||||
import { expect } from 'chai';
|
||||
import { EnumType } from '@/application/Common/Enum';
|
||||
import { itEachAbsentObjectValue } from '@tests/unit/shared/TestCases/AbsentTests';
|
||||
|
||||
export class EnumRangeTestRunner<TEnumValue extends EnumType> {
|
||||
constructor(private readonly runner: (value: TEnumValue) => void) {
|
||||
@@ -19,15 +20,17 @@ export class EnumRangeTestRunner<TEnumValue extends EnumType> {
|
||||
return this;
|
||||
}
|
||||
|
||||
public testUndefinedValueThrows() {
|
||||
it('throws when value is undefined', () => {
|
||||
// arrange
|
||||
const value = undefined;
|
||||
const expectedError = 'undefined enum value';
|
||||
// act
|
||||
const act = () => this.runner(value);
|
||||
// assert
|
||||
expect(act).to.throw(expectedError);
|
||||
public testAbsentValueThrows() {
|
||||
describe('throws when value is absent', () => {
|
||||
itEachAbsentObjectValue((absentValue) => {
|
||||
// arrange
|
||||
const value = absentValue;
|
||||
const expectedError = 'absent enum value';
|
||||
// act
|
||||
const act = () => this.runner(value);
|
||||
// assert
|
||||
expect(act).to.throw(expectedError);
|
||||
});
|
||||
});
|
||||
return this;
|
||||
}
|
||||
@@ -45,7 +48,7 @@ export class EnumRangeTestRunner<TEnumValue extends EnumType> {
|
||||
}
|
||||
|
||||
public testValidValueDoesNotThrow(validValue: TEnumValue) {
|
||||
it('throws when value is undefined', () => {
|
||||
it('does not throw with valid value', () => {
|
||||
// arrange
|
||||
const value = validValue;
|
||||
// act
|
||||
|
||||
@@ -3,6 +3,7 @@ import { expect } from 'chai';
|
||||
import { ScriptingLanguage } from '@/domain/ScriptingLanguage';
|
||||
import { ScriptingLanguageFactory } from '@/application/Common/ScriptingLanguage/ScriptingLanguageFactory';
|
||||
import { EnumRangeTestRunner } from '@tests/unit/application/Common/EnumRangeTestRunner';
|
||||
import { itEachAbsentObjectValue } from '@tests/unit/shared/TestCases/AbsentTests';
|
||||
import { ScriptingLanguageFactoryTestRunner } from './ScriptingLanguageFactoryTestRunner';
|
||||
|
||||
class ScriptingLanguageConcrete extends ScriptingLanguageFactory<number> {
|
||||
@@ -16,32 +17,34 @@ describe('ScriptingLanguageFactory', () => {
|
||||
describe('validates language', () => {
|
||||
// arrange
|
||||
const validValue = ScriptingLanguage.batchfile;
|
||||
const getter = () => undefined;
|
||||
const getter = () => 1;
|
||||
const sut = new ScriptingLanguageConcrete();
|
||||
// act
|
||||
const act = (language: ScriptingLanguage) => sut.registerGetter(language, getter);
|
||||
// assert
|
||||
new EnumRangeTestRunner(act)
|
||||
.testOutOfRangeThrows()
|
||||
.testUndefinedValueThrows()
|
||||
.testAbsentValueThrows()
|
||||
.testValidValueDoesNotThrow(validValue);
|
||||
});
|
||||
it('throw when getter is undefined', () => {
|
||||
// arrange
|
||||
const expectedError = 'undefined getter';
|
||||
const language = ScriptingLanguage.batchfile;
|
||||
const getter = undefined;
|
||||
const sut = new ScriptingLanguageConcrete();
|
||||
// act
|
||||
const act = () => sut.registerGetter(language, getter);
|
||||
// assert
|
||||
expect(act).to.throw(expectedError);
|
||||
describe('describe when getter is absent', () => {
|
||||
itEachAbsentObjectValue((absentValue) => {
|
||||
// arrange
|
||||
const expectedError = 'missing getter';
|
||||
const language = ScriptingLanguage.batchfile;
|
||||
const getter = absentValue;
|
||||
const sut = new ScriptingLanguageConcrete();
|
||||
// act
|
||||
const act = () => sut.registerGetter(language, getter);
|
||||
// assert
|
||||
expect(act).to.throw(expectedError);
|
||||
});
|
||||
});
|
||||
it('throw when language is already registered', () => {
|
||||
// arrange
|
||||
const language = ScriptingLanguage.batchfile;
|
||||
const expectedError = `${ScriptingLanguage[language]} is already registered`;
|
||||
const getter = () => undefined;
|
||||
const getter = () => 1;
|
||||
const sut = new ScriptingLanguageConcrete();
|
||||
// act
|
||||
sut.registerGetter(language, getter);
|
||||
@@ -51,9 +54,12 @@ describe('ScriptingLanguageFactory', () => {
|
||||
});
|
||||
});
|
||||
describe('create', () => {
|
||||
// arrange
|
||||
const sut = new ScriptingLanguageConcrete();
|
||||
sut.registerGetter(ScriptingLanguage.batchfile, () => undefined);
|
||||
const runner = new ScriptingLanguageFactoryTestRunner();
|
||||
// act
|
||||
sut.registerGetter(ScriptingLanguage.batchfile, () => 1);
|
||||
// assert
|
||||
runner.testCreateMethod(sut);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -13,7 +13,7 @@ export class ScriptingLanguageFactoryTestRunner<T> {
|
||||
}
|
||||
|
||||
public testCreateMethod(sut: IScriptingLanguageFactory<T>) {
|
||||
if (!sut) { throw new Error('undefined sut'); }
|
||||
if (!sut) { throw new Error('missing sut'); }
|
||||
testLanguageValidation(sut);
|
||||
testExpectedInstanceTypes(sut, this.expectedTypes);
|
||||
}
|
||||
@@ -46,7 +46,7 @@ function testLanguageValidation<T>(sut: IScriptingLanguageFactory<T>) {
|
||||
// assert
|
||||
new EnumRangeTestRunner(act)
|
||||
.testOutOfRangeThrows()
|
||||
.testUndefinedValueThrows()
|
||||
.testAbsentValueThrows()
|
||||
.testValidValueDoesNotThrow(validValue);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ import { IApplication } from '@/domain/IApplication';
|
||||
import { ApplicationStub } from '@tests/unit/stubs/ApplicationStub';
|
||||
import { CategoryCollectionStub } from '@tests/unit/stubs/CategoryCollectionStub';
|
||||
import { EnumRangeTestRunner } from '@tests/unit/application/Common/EnumRangeTestRunner';
|
||||
import { itEachAbsentObjectValue } from '@tests/unit/shared/TestCases/AbsentTests';
|
||||
|
||||
describe('ApplicationContext', () => {
|
||||
describe('changeContext', () => {
|
||||
@@ -125,18 +126,33 @@ describe('ApplicationContext', () => {
|
||||
expect(duplicates.length).to.be.equal(0);
|
||||
});
|
||||
});
|
||||
describe('throws with invalid os', () => {
|
||||
new EnumRangeTestRunner((os: OperatingSystem) => {
|
||||
// arrange
|
||||
const sut = new ObservableApplicationContextFactory()
|
||||
.construct();
|
||||
// act
|
||||
sut.changeContext(os);
|
||||
})
|
||||
// assert
|
||||
.testOutOfRangeThrows()
|
||||
.testAbsentValueThrows()
|
||||
.testInvalidValueThrows(OperatingSystem.Android, 'os "Android" is not defined in application');
|
||||
});
|
||||
});
|
||||
describe('ctor', () => {
|
||||
describe('app', () => {
|
||||
it('throw when app is undefined', () => {
|
||||
// arrange
|
||||
const expectedError = 'undefined app';
|
||||
const app = undefined;
|
||||
const os = OperatingSystem.Windows;
|
||||
// act
|
||||
const act = () => new ApplicationContext(app, os);
|
||||
// assert
|
||||
expect(act).to.throw(expectedError);
|
||||
describe('throw when app is missing', () => {
|
||||
itEachAbsentObjectValue((absentValue) => {
|
||||
// arrange
|
||||
const expectedError = 'missing app';
|
||||
const app = absentValue;
|
||||
const os = OperatingSystem.Windows;
|
||||
// act
|
||||
const act = () => new ApplicationContext(app, os);
|
||||
// assert
|
||||
expect(act).to.throw(expectedError);
|
||||
});
|
||||
});
|
||||
});
|
||||
describe('collection', () => {
|
||||
@@ -188,7 +204,7 @@ describe('ApplicationContext', () => {
|
||||
// assert
|
||||
new EnumRangeTestRunner(act)
|
||||
.testOutOfRangeThrows()
|
||||
.testUndefinedValueThrows()
|
||||
.testAbsentValueThrows()
|
||||
.testInvalidValueThrows(OperatingSystem.Android, 'os "Android" is not defined in application');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -8,6 +8,7 @@ import { IApplication } from '@/domain/IApplication';
|
||||
import { EnvironmentStub } from '@tests/unit/stubs/EnvironmentStub';
|
||||
import { ApplicationStub } from '@tests/unit/stubs/ApplicationStub';
|
||||
import { CategoryCollectionStub } from '@tests/unit/stubs/CategoryCollectionStub';
|
||||
import { expectThrowsAsync } from '@tests/unit/shared/Assertions/ExpectThrowsAsync';
|
||||
|
||||
describe('ApplicationContextFactory', () => {
|
||||
describe('buildContext', () => {
|
||||
@@ -23,6 +24,15 @@ describe('ApplicationContextFactory', () => {
|
||||
// assert
|
||||
expect(expected).to.equal(context.app);
|
||||
});
|
||||
it('throws when null', async () => {
|
||||
// arrange
|
||||
const expectedError = 'missing factory';
|
||||
const factory = null;
|
||||
// act
|
||||
const act = async () => { await buildContext(factory); };
|
||||
// assert
|
||||
expectThrowsAsync(act, expectedError);
|
||||
});
|
||||
});
|
||||
describe('environment', () => {
|
||||
describe('sets initial OS as expected', () => {
|
||||
@@ -69,6 +79,16 @@ describe('ApplicationContextFactory', () => {
|
||||
expect(expectedOs).to.equal(actual, `Expected: ${OperatingSystem[expectedOs]}, actual: ${OperatingSystem[actual]}`);
|
||||
});
|
||||
});
|
||||
it('throws when null', async () => {
|
||||
// arrange
|
||||
const expectedError = 'missing environment';
|
||||
const factory = mockFactoryWithApp(undefined);
|
||||
const environment = null;
|
||||
// act
|
||||
const act = async () => { await buildContext(factory, environment); };
|
||||
// assert
|
||||
expectThrowsAsync(act, expectedError);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -13,6 +13,8 @@ import { ScriptingDefinitionStub } from '@tests/unit/stubs/ScriptingDefinitionSt
|
||||
import { CategoryStub } from '@tests/unit/stubs/CategoryStub';
|
||||
import { ScriptStub } from '@tests/unit/stubs/ScriptStub';
|
||||
import { CategoryCollectionStub } from '@tests/unit/stubs/CategoryCollectionStub';
|
||||
import { itEachAbsentObjectValue } from '@tests/unit/shared/TestCases/AbsentTests';
|
||||
import { UserSelectionStub } from '@tests/unit/stubs/UserSelectionStub';
|
||||
|
||||
describe('ApplicationCode', () => {
|
||||
describe('ctor', () => {
|
||||
@@ -46,6 +48,41 @@ describe('ApplicationCode', () => {
|
||||
// assert
|
||||
expect(actual).to.equal(expected.code);
|
||||
});
|
||||
describe('throws when userSelection is missing', () => {
|
||||
itEachAbsentObjectValue((absentValue) => {
|
||||
// arrange
|
||||
const expectedError = 'missing userSelection';
|
||||
const userSelection = absentValue;
|
||||
const definition = new ScriptingDefinitionStub();
|
||||
// act
|
||||
const act = () => new ApplicationCode(userSelection, definition);
|
||||
// assert
|
||||
expect(act).to.throw(expectedError);
|
||||
});
|
||||
});
|
||||
describe('throws when scriptingDefinition is missing', () => {
|
||||
itEachAbsentObjectValue((absentValue) => {
|
||||
// arrange
|
||||
const expectedError = 'missing scriptingDefinition';
|
||||
const userSelection = new UserSelectionStub([]);
|
||||
const definition = absentValue;
|
||||
// act
|
||||
const act = () => new ApplicationCode(userSelection, definition);
|
||||
// assert
|
||||
expect(act).to.throw(expectedError);
|
||||
});
|
||||
});
|
||||
it('throws when generator is missing', () => {
|
||||
// arrange
|
||||
const expectedError = 'missing generator';
|
||||
const userSelection = new UserSelectionStub([]);
|
||||
const definition = new ScriptingDefinitionStub();
|
||||
const generator = null;
|
||||
// act
|
||||
const act = () => new ApplicationCode(userSelection, definition, generator);
|
||||
// assert
|
||||
expect(act).to.throw(expectedError);
|
||||
});
|
||||
});
|
||||
describe('changed event', () => {
|
||||
describe('code', () => {
|
||||
|
||||
@@ -6,6 +6,8 @@ import { ICodeBuilderFactory } from '@/application/Context/State/Code/Generation
|
||||
import { ICodeBuilder } from '@/application/Context/State/Code/Generation/ICodeBuilder';
|
||||
import { ScriptStub } from '@tests/unit/stubs/ScriptStub';
|
||||
import { ScriptingDefinitionStub } from '@tests/unit/stubs/ScriptingDefinitionStub';
|
||||
import { itEachAbsentObjectValue, itEachAbsentStringValue } from '@tests/unit/shared/TestCases/AbsentTests';
|
||||
import { SelectedScriptStub } from '@tests/unit/stubs/SelectedScriptStub';
|
||||
|
||||
describe('UserScriptGenerator', () => {
|
||||
describe('scriptingDefinition', () => {
|
||||
@@ -18,8 +20,7 @@ describe('UserScriptGenerator', () => {
|
||||
.withCode('code\nmulti-lined')
|
||||
.toSelectedScript();
|
||||
const definition = new ScriptingDefinitionStub()
|
||||
.withStartCode(startCode)
|
||||
.withEndCode(undefined);
|
||||
.withStartCode(startCode);
|
||||
const expectedStart = `${startCode}\n`;
|
||||
// act
|
||||
const code = sut.buildCode([script], definition);
|
||||
@@ -27,24 +28,25 @@ describe('UserScriptGenerator', () => {
|
||||
const actual = code.code;
|
||||
expect(actual.startsWith(expectedStart));
|
||||
});
|
||||
it('is not prepended if empty', () => {
|
||||
// arrange
|
||||
const codeBuilderStub = new CodeBuilderStub();
|
||||
const sut = new UserScriptGenerator(mockCodeBuilderFactory(codeBuilderStub));
|
||||
const script = new ScriptStub('id')
|
||||
.withCode('code\nmulti-lined')
|
||||
.toSelectedScript();
|
||||
const definition = new ScriptingDefinitionStub()
|
||||
.withStartCode(undefined)
|
||||
.withEndCode(undefined);
|
||||
const expectedStart = codeBuilderStub
|
||||
.appendFunction(script.script.name, script.script.code.execute)
|
||||
.toString();
|
||||
// act
|
||||
const code = sut.buildCode([script], definition);
|
||||
// assert
|
||||
const actual = code.code;
|
||||
expect(actual.startsWith(expectedStart));
|
||||
describe('is not prepended if empty', () => {
|
||||
itEachAbsentStringValue((absentValue) => {
|
||||
// arrange
|
||||
const codeBuilderStub = new CodeBuilderStub();
|
||||
const sut = new UserScriptGenerator(mockCodeBuilderFactory(codeBuilderStub));
|
||||
const script = new ScriptStub('id')
|
||||
.withCode('code\nmulti-lined')
|
||||
.toSelectedScript();
|
||||
const definition = new ScriptingDefinitionStub()
|
||||
.withStartCode(absentValue);
|
||||
const expectedStart = codeBuilderStub
|
||||
.appendFunction(script.script.name, script.script.code.execute)
|
||||
.toString();
|
||||
// act
|
||||
const code = sut.buildCode([script], definition);
|
||||
// assert
|
||||
const actual = code.code;
|
||||
expect(actual.startsWith(expectedStart));
|
||||
});
|
||||
});
|
||||
});
|
||||
describe('endCode', () => {
|
||||
@@ -64,23 +66,38 @@ describe('UserScriptGenerator', () => {
|
||||
const actual = code.code;
|
||||
expect(actual.endsWith(expectedEnd));
|
||||
});
|
||||
it('is not appended if empty', () => {
|
||||
describe('is not appended if empty', () => {
|
||||
itEachAbsentStringValue((absentValue) => {
|
||||
// arrange
|
||||
const codeBuilderStub = new CodeBuilderStub();
|
||||
const sut = new UserScriptGenerator(mockCodeBuilderFactory(codeBuilderStub));
|
||||
const script = new ScriptStub('id')
|
||||
.withCode('code\nmulti-lined')
|
||||
.toSelectedScript();
|
||||
const expectedEnd = codeBuilderStub
|
||||
.appendFunction(script.script.name, script.script.code.execute)
|
||||
.toString();
|
||||
const definition = new ScriptingDefinitionStub()
|
||||
.withEndCode(absentValue);
|
||||
// act
|
||||
const code = sut.buildCode([script], definition);
|
||||
// assert
|
||||
const actual = code.code;
|
||||
expect(actual.endsWith(expectedEnd));
|
||||
});
|
||||
});
|
||||
});
|
||||
describe('throws when absent', () => {
|
||||
itEachAbsentObjectValue((absentValue) => {
|
||||
// arrange
|
||||
const codeBuilderStub = new CodeBuilderStub();
|
||||
const sut = new UserScriptGenerator(mockCodeBuilderFactory(codeBuilderStub));
|
||||
const script = new ScriptStub('id')
|
||||
.withCode('code\nmulti-lined')
|
||||
.toSelectedScript();
|
||||
const expectedEnd = codeBuilderStub
|
||||
.appendFunction(script.script.name, script.script.code.execute)
|
||||
.toString();
|
||||
const definition = new ScriptingDefinitionStub()
|
||||
.withEndCode(undefined);
|
||||
const expectedError = 'missing definition';
|
||||
const sut = new UserScriptGenerator();
|
||||
const scriptingDefinition = absentValue;
|
||||
const selectedScripts = [new SelectedScriptStub('a')];
|
||||
// act
|
||||
const code = sut.buildCode([script], definition);
|
||||
const act = () => sut.buildCode(selectedScripts, scriptingDefinition);
|
||||
// assert
|
||||
const actual = code.code;
|
||||
expect(actual.endsWith(expectedEnd));
|
||||
expect(act).to.throw(expectedError);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -200,6 +217,21 @@ describe('UserScriptGenerator', () => {
|
||||
});
|
||||
});
|
||||
});
|
||||
describe('selectedScripts', () => {
|
||||
describe('throws when absent', () => {
|
||||
itEachAbsentObjectValue((absentValue) => {
|
||||
// arrange
|
||||
const expectedError = 'missing scripts';
|
||||
const sut = new UserScriptGenerator();
|
||||
const scriptingDefinition = new ScriptingDefinitionStub();
|
||||
const selectedScripts = absentValue;
|
||||
// act
|
||||
const act = () => sut.buildCode(selectedScripts, scriptingDefinition);
|
||||
// assert
|
||||
expect(act).to.throw(expectedError);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
function mockCodeBuilderFactory(mock: ICodeBuilder): ICodeBuilderFactory {
|
||||
|
||||
@@ -2,17 +2,21 @@ import 'mocha';
|
||||
import { expect } from 'chai';
|
||||
import { OperatingSystem } from '@/domain/OperatingSystem';
|
||||
import { BrowserOsDetector } from '@/application/Environment/BrowserOs/BrowserOsDetector';
|
||||
import { itEachAbsentStringValue } from '@tests/unit/shared/TestCases/AbsentTests';
|
||||
import { BrowserOsTestCases } from './BrowserOsTestCases';
|
||||
|
||||
describe('BrowserOsDetector', () => {
|
||||
it('returns undefined when user agent is undefined', () => {
|
||||
// arrange
|
||||
const expected = undefined;
|
||||
const sut = new BrowserOsDetector();
|
||||
// act
|
||||
const actual = sut.detect(undefined);
|
||||
// assert
|
||||
expect(actual).to.equal(expected);
|
||||
describe('returns undefined when user agent is absent', () => {
|
||||
itEachAbsentStringValue((absentValue) => {
|
||||
// arrange
|
||||
const expected = undefined;
|
||||
const userAgent = absentValue;
|
||||
const sut = new BrowserOsDetector();
|
||||
// act
|
||||
const actual = sut.detect(userAgent);
|
||||
// assert
|
||||
expect(actual).to.equal(expected);
|
||||
});
|
||||
});
|
||||
it('detects as expected', () => {
|
||||
BrowserOsTestCases.forEach((testCase) => {
|
||||
|
||||
@@ -13,6 +13,7 @@ import { getEnumValues } from '@/application/Common/Enum';
|
||||
import { CategoryCollectionStub } from '@tests/unit/stubs/CategoryCollectionStub';
|
||||
import { getProcessEnvironmentStub } from '@tests/unit/stubs/ProcessEnvironmentStub';
|
||||
import { CollectionDataStub } from '@tests/unit/stubs/CollectionDataStub';
|
||||
import { getAbsentCollectionTestCases, AbsentObjectTestCases } from '@tests/unit/shared/TestCases/AbsentTests';
|
||||
|
||||
describe('ApplicationParser', () => {
|
||||
describe('parseApplication', () => {
|
||||
@@ -112,21 +113,23 @@ describe('ApplicationParser', () => {
|
||||
describe('throws when data is invalid', () => {
|
||||
// arrange
|
||||
const testCases = [
|
||||
{
|
||||
expectedError: 'no collection provided',
|
||||
data: [],
|
||||
},
|
||||
{
|
||||
expectedError: 'undefined collection provided',
|
||||
data: [new CollectionDataStub(), undefined],
|
||||
},
|
||||
...getAbsentCollectionTestCases<CollectionData>().map((testCase) => ({
|
||||
name: `given absent collection "${testCase.valueName}"`,
|
||||
value: testCase.absentValue,
|
||||
expectedError: 'missing collections',
|
||||
})).filter((test) => test.value !== undefined /* the default value is set */),
|
||||
...AbsentObjectTestCases.map((testCase) => ({
|
||||
name: `given absent item "${testCase.valueName}"`,
|
||||
value: [testCase.absentValue],
|
||||
expectedError: 'missing collection provided',
|
||||
})),
|
||||
];
|
||||
for (const testCase of testCases) {
|
||||
it(testCase.expectedError, () => {
|
||||
it(testCase.name, () => {
|
||||
const parserMock = new CategoryCollectionParserSpy().mockParser();
|
||||
const env = getProcessEnvironmentStub();
|
||||
// act
|
||||
const act = () => parseApplication(parserMock, env, testCase.data);
|
||||
const act = () => parseApplication(parserMock, env, testCase.value);
|
||||
// assert
|
||||
expect(act).to.throw(testCase.expectedError);
|
||||
});
|
||||
|
||||
@@ -15,30 +15,35 @@ import { CategoryDataStub } from '@tests/unit/stubs/CategoryDataStub';
|
||||
import { ScriptDataStub } from '@tests/unit/stubs/ScriptDataStub';
|
||||
import { FunctionDataStub } from '@tests/unit/stubs/FunctionDataStub';
|
||||
import { FunctionCallDataStub } from '@tests/unit/stubs/FunctionCallDataStub';
|
||||
import { itEachAbsentObjectValue } from '@tests/unit/shared/TestCases/AbsentTests';
|
||||
|
||||
describe('CategoryCollectionParser', () => {
|
||||
describe('parseCategoryCollection', () => {
|
||||
it('throws when undefined', () => {
|
||||
// arrange
|
||||
const expectedError = 'content is null or undefined';
|
||||
const info = new ProjectInformationStub();
|
||||
// act
|
||||
const act = () => parseCategoryCollection(undefined, info);
|
||||
// assert
|
||||
expect(act).to.throw(expectedError);
|
||||
});
|
||||
describe('actions', () => {
|
||||
it('throws when undefined actions', () => {
|
||||
describe('throws with absent content', () => {
|
||||
itEachAbsentObjectValue((absentValue) => {
|
||||
// arrange
|
||||
const expectedError = 'content does not define any action';
|
||||
const collection = new CollectionDataStub()
|
||||
.withActions(undefined);
|
||||
const expectedError = 'missing content';
|
||||
const info = new ProjectInformationStub();
|
||||
// act
|
||||
const act = () => parseCategoryCollection(collection, info);
|
||||
const act = () => parseCategoryCollection(absentValue, info);
|
||||
// assert
|
||||
expect(act).to.throw(expectedError);
|
||||
});
|
||||
});
|
||||
describe('actions', () => {
|
||||
describe('throws with absent actions', () => {
|
||||
itEachAbsentObjectValue((absentValue) => {
|
||||
// arrange
|
||||
const expectedError = 'content does not define any action';
|
||||
const collection = new CollectionDataStub()
|
||||
.withActions(absentValue);
|
||||
const info = new ProjectInformationStub();
|
||||
// act
|
||||
const act = () => parseCategoryCollection(collection, info);
|
||||
// assert
|
||||
expect(act).to.throw(expectedError);
|
||||
});
|
||||
});
|
||||
it('throws when has no actions', () => {
|
||||
// arrange
|
||||
const expectedError = 'content does not define any action';
|
||||
|
||||
@@ -8,53 +8,44 @@ import { ScriptDataStub } from '@tests/unit/stubs/ScriptDataStub';
|
||||
import { CategoryCollectionParseContextStub } from '@tests/unit/stubs/CategoryCollectionParseContextStub';
|
||||
import { LanguageSyntaxStub } from '@tests/unit/stubs/LanguageSyntaxStub';
|
||||
import { CategoryDataStub } from '@tests/unit/stubs/CategoryDataStub';
|
||||
import { itEachAbsentCollectionValue, itEachAbsentObjectValue, itEachAbsentStringValue } from '@tests/unit/shared/TestCases/AbsentTests';
|
||||
|
||||
describe('CategoryParser', () => {
|
||||
describe('parseCategory', () => {
|
||||
describe('invalid category', () => {
|
||||
it('throws when undefined', () => {
|
||||
// arrange
|
||||
const expectedMessage = 'category is null or undefined';
|
||||
const category = undefined;
|
||||
const context = new CategoryCollectionParseContextStub();
|
||||
// act
|
||||
const act = () => parseCategory(category, context);
|
||||
// assert
|
||||
expect(act).to.throw(expectedMessage);
|
||||
describe('throws when category data is absent', () => {
|
||||
itEachAbsentObjectValue((absentValue) => {
|
||||
// arrange
|
||||
const expectedMessage = 'missing category';
|
||||
const category = absentValue;
|
||||
const context = new CategoryCollectionParseContextStub();
|
||||
// act
|
||||
const act = () => parseCategory(category, context);
|
||||
// assert
|
||||
expect(act).to.throw(expectedMessage);
|
||||
});
|
||||
});
|
||||
it('throws when children are empty', () => {
|
||||
// arrange
|
||||
const categoryName = 'test';
|
||||
const expectedMessage = `category has no children: "${categoryName}"`;
|
||||
const category = new CategoryDataStub()
|
||||
.withName(categoryName)
|
||||
.withChildren([]);
|
||||
const context = new CategoryCollectionParseContextStub();
|
||||
// act
|
||||
const act = () => parseCategory(category, context);
|
||||
// assert
|
||||
expect(act).to.throw(expectedMessage);
|
||||
});
|
||||
it('throws when children are undefined', () => {
|
||||
// arrange
|
||||
const categoryName = 'test';
|
||||
const expectedMessage = `category has no children: "${categoryName}"`;
|
||||
const category = new CategoryDataStub()
|
||||
.withName(categoryName)
|
||||
.withChildren(undefined);
|
||||
const context = new CategoryCollectionParseContextStub();
|
||||
// act
|
||||
const act = () => parseCategory(category, context);
|
||||
// assert
|
||||
expect(act).to.throw(expectedMessage);
|
||||
});
|
||||
it('throws when name is empty or undefined', () => {
|
||||
// arrange
|
||||
const expectedMessage = 'category has no name';
|
||||
const invalidNames = ['', undefined];
|
||||
invalidNames.forEach((invalidName) => {
|
||||
describe('throws when category children is absent', () => {
|
||||
itEachAbsentCollectionValue((absentValue) => {
|
||||
// arrange
|
||||
const categoryName = 'test';
|
||||
const expectedMessage = `category has no children: "${categoryName}"`;
|
||||
const category = new CategoryDataStub()
|
||||
.withName(invalidName);
|
||||
.withName(categoryName)
|
||||
.withChildren(absentValue);
|
||||
const context = new CategoryCollectionParseContextStub();
|
||||
// act
|
||||
const act = () => parseCategory(category, context);
|
||||
// assert
|
||||
expect(act).to.throw(expectedMessage);
|
||||
});
|
||||
});
|
||||
describe('throws when name is absent', () => {
|
||||
itEachAbsentStringValue((absentValue) => {
|
||||
// arrange
|
||||
const expectedMessage = 'category has no name';
|
||||
const category = new CategoryDataStub()
|
||||
.withName(absentValue);
|
||||
const context = new CategoryCollectionParseContextStub();
|
||||
// act
|
||||
const act = () => parseCategory(category, context);
|
||||
@@ -63,15 +54,17 @@ describe('CategoryParser', () => {
|
||||
});
|
||||
});
|
||||
});
|
||||
it('throws when context is undefined', () => {
|
||||
// arrange
|
||||
const expectedError = 'undefined context';
|
||||
const context = undefined;
|
||||
const category = new CategoryDataStub();
|
||||
// act
|
||||
const act = () => parseCategory(category, context);
|
||||
// assert
|
||||
expect(act).to.throw(expectedError);
|
||||
describe('throws when context is absent', () => {
|
||||
itEachAbsentObjectValue((absentValue) => {
|
||||
// arrange
|
||||
const expectedError = 'missing context';
|
||||
const context = absentValue;
|
||||
const category = new CategoryDataStub();
|
||||
// act
|
||||
const act = () => parseCategory(category, context);
|
||||
// assert
|
||||
expect(act).to.throw(expectedError);
|
||||
});
|
||||
});
|
||||
it('returns expected docs', () => {
|
||||
// arrange
|
||||
|
||||
@@ -2,11 +2,19 @@ import 'mocha';
|
||||
import { expect } from 'chai';
|
||||
import { DocumentableData } from 'js-yaml-loader!@/*';
|
||||
import { parseDocUrls } from '@/application/Parser/DocumentationParser';
|
||||
import { itEachAbsentObjectValue } from '@tests/unit/shared/TestCases/AbsentTests';
|
||||
|
||||
describe('DocumentationParser', () => {
|
||||
describe('parseDocUrls', () => {
|
||||
it('throws when undefined', () => {
|
||||
expect(() => parseDocUrls(undefined)).to.throw('documentable is null or undefined');
|
||||
describe('throws when absent', () => {
|
||||
itEachAbsentObjectValue((absentValue) => {
|
||||
// arrange
|
||||
const expectedError = 'missing documentable';
|
||||
// act
|
||||
const act = () => parseDocUrls(absentValue);
|
||||
// assert
|
||||
expect(act).to.throw(expectedError);
|
||||
});
|
||||
});
|
||||
it('returns empty when empty', () => {
|
||||
// arrange
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import 'mocha';
|
||||
import { expect } from 'chai';
|
||||
import { FunctionData } from 'js-yaml-loader!@/*';
|
||||
import { ISyntaxFactory } from '@/application/Parser/Script/Syntax/ISyntaxFactory';
|
||||
import { ScriptingLanguage } from '@/domain/ScriptingLanguage';
|
||||
import { CategoryCollectionParseContext } from '@/application/Parser/Script/CategoryCollectionParseContext';
|
||||
@@ -9,32 +8,36 @@ import { ScriptCompiler } from '@/application/Parser/Script/Compiler/ScriptCompi
|
||||
import { LanguageSyntaxStub } from '@tests/unit/stubs/LanguageSyntaxStub';
|
||||
import { ScriptingDefinitionStub } from '@tests/unit/stubs/ScriptingDefinitionStub';
|
||||
import { FunctionDataStub } from '@tests/unit/stubs/FunctionDataStub';
|
||||
import { itEachAbsentCollectionValue, itEachAbsentObjectValue } from '@tests/unit/shared/TestCases/AbsentTests';
|
||||
|
||||
describe('CategoryCollectionParseContext', () => {
|
||||
describe('ctor', () => {
|
||||
describe('functionsData', () => {
|
||||
it('can create with empty values', () => {
|
||||
// arrange
|
||||
const testData: FunctionData[][] = [undefined, []];
|
||||
const scripting = new ScriptingDefinitionStub();
|
||||
for (const functionsData of testData) {
|
||||
describe('can create with absent data', () => {
|
||||
itEachAbsentCollectionValue((absentValue) => {
|
||||
// arrange
|
||||
const scripting = new ScriptingDefinitionStub();
|
||||
// act
|
||||
const act = () => new CategoryCollectionParseContext(absentValue, scripting);
|
||||
// assert
|
||||
expect(act).to.not.throw();
|
||||
});
|
||||
});
|
||||
});
|
||||
describe('scripting', () => {
|
||||
describe('throws when missing', () => {
|
||||
itEachAbsentObjectValue((absentValue) => {
|
||||
// arrange
|
||||
const expectedError = 'missing scripting';
|
||||
const scripting = absentValue;
|
||||
const functionsData = [FunctionDataStub.createWithCode()];
|
||||
// act
|
||||
const act = () => new CategoryCollectionParseContext(functionsData, scripting);
|
||||
// assert
|
||||
expect(act).to.not.throw();
|
||||
}
|
||||
expect(act).to.throw(expectedError);
|
||||
});
|
||||
});
|
||||
});
|
||||
it('scripting', () => {
|
||||
// arrange
|
||||
const expectedError = 'undefined scripting';
|
||||
const scripting = undefined;
|
||||
const functionsData = [FunctionDataStub.createWithCode()];
|
||||
// act
|
||||
const act = () => new CategoryCollectionParseContext(functionsData, scripting);
|
||||
// assert
|
||||
expect(act).to.throw(expectedError);
|
||||
});
|
||||
});
|
||||
describe('compiler', () => {
|
||||
it('constructed as expected', () => {
|
||||
|
||||
@@ -10,20 +10,24 @@ import { ExpressionEvaluationContextStub } from '@tests/unit/stubs/ExpressionEva
|
||||
import { IPipelineCompiler } from '@/application/Parser/Script/Compiler/Expressions/Pipes/IPipelineCompiler';
|
||||
import { PipelineCompilerStub } from '@tests/unit/stubs/PipelineCompilerStub';
|
||||
import { IReadOnlyFunctionParameterCollection } from '@/application/Parser/Script/Compiler/Function/Parameter/IFunctionParameterCollection';
|
||||
import { AbsentObjectTestCases, itEachAbsentObjectValue } from '@tests/unit/shared/TestCases/AbsentTests';
|
||||
import { IExpressionEvaluationContext } from '@/application/Parser/Script/Compiler/Expressions/Expression/ExpressionEvaluationContext';
|
||||
|
||||
describe('Expression', () => {
|
||||
describe('ctor', () => {
|
||||
describe('position', () => {
|
||||
it('throws if undefined', () => {
|
||||
// arrange
|
||||
const expectedError = 'undefined position';
|
||||
const position = undefined;
|
||||
// act
|
||||
const act = () => new ExpressionBuilder()
|
||||
.withPosition(position)
|
||||
.build();
|
||||
// assert
|
||||
expect(act).to.throw(expectedError);
|
||||
describe('throws when missing', () => {
|
||||
itEachAbsentObjectValue((absentValue) => {
|
||||
// arrange
|
||||
const expectedError = 'missing position';
|
||||
const position = absentValue;
|
||||
// act
|
||||
const act = () => new ExpressionBuilder()
|
||||
.withPosition(position)
|
||||
.build();
|
||||
// assert
|
||||
expect(act).to.throw(expectedError);
|
||||
});
|
||||
});
|
||||
it('sets as expected', () => {
|
||||
// arrange
|
||||
@@ -37,17 +41,19 @@ describe('Expression', () => {
|
||||
});
|
||||
});
|
||||
describe('parameters', () => {
|
||||
it('defaults to empty array if undefined', () => {
|
||||
// arrange
|
||||
const parameters = undefined;
|
||||
// act
|
||||
const actual = new ExpressionBuilder()
|
||||
.withParameters(parameters)
|
||||
.build();
|
||||
// assert
|
||||
expect(actual.parameters);
|
||||
expect(actual.parameters.all);
|
||||
expect(actual.parameters.all.length).to.equal(0);
|
||||
describe('defaults to empty array if absent', () => {
|
||||
itEachAbsentObjectValue((absentValue) => {
|
||||
// arrange
|
||||
const parameters = absentValue;
|
||||
// act
|
||||
const actual = new ExpressionBuilder()
|
||||
.withParameters(parameters)
|
||||
.build();
|
||||
// assert
|
||||
expect(actual.parameters);
|
||||
expect(actual.parameters.all);
|
||||
expect(actual.parameters.all.length).to.equal(0);
|
||||
});
|
||||
});
|
||||
it('sets as expected', () => {
|
||||
// arrange
|
||||
@@ -63,37 +69,44 @@ describe('Expression', () => {
|
||||
});
|
||||
});
|
||||
describe('evaluator', () => {
|
||||
it('throws if undefined', () => {
|
||||
// arrange
|
||||
const expectedError = 'undefined evaluator';
|
||||
const evaluator = undefined;
|
||||
// act
|
||||
const act = () => new ExpressionBuilder()
|
||||
.withEvaluator(evaluator)
|
||||
.build();
|
||||
// assert
|
||||
expect(act).to.throw(expectedError);
|
||||
describe('throws if missing', () => {
|
||||
itEachAbsentObjectValue((absentValue) => {
|
||||
// arrange
|
||||
const expectedError = 'missing evaluator';
|
||||
const evaluator = absentValue;
|
||||
// act
|
||||
const act = () => new ExpressionBuilder()
|
||||
.withEvaluator(evaluator)
|
||||
.build();
|
||||
// assert
|
||||
expect(act).to.throw(expectedError);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
describe('evaluate', () => {
|
||||
describe('throws with invalid arguments', () => {
|
||||
const testCases = [
|
||||
{
|
||||
name: 'throws if arguments is undefined',
|
||||
context: undefined,
|
||||
expectedError: 'undefined context',
|
||||
},
|
||||
const testCases: readonly {
|
||||
name: string,
|
||||
context: IExpressionEvaluationContext,
|
||||
expectedError: string,
|
||||
sutBuilder?: (builder: ExpressionBuilder) => ExpressionBuilder,
|
||||
}[] = [
|
||||
...AbsentObjectTestCases.map((testCase) => ({
|
||||
name: `throws if arguments is ${testCase.valueName}`,
|
||||
context: testCase.absentValue,
|
||||
expectedError: 'missing context',
|
||||
})),
|
||||
{
|
||||
name: 'throws when some of the required args are not provided',
|
||||
sut: (i: ExpressionBuilder) => i.withParameterNames(['a', 'b', 'c'], false),
|
||||
sutBuilder: (i: ExpressionBuilder) => i.withParameterNames(['a', 'b', 'c'], false),
|
||||
context: new ExpressionEvaluationContextStub()
|
||||
.withArgs(new FunctionCallArgumentCollectionStub().withArgument('b', 'provided')),
|
||||
expectedError: 'argument values are provided for required parameters: "a", "c"',
|
||||
},
|
||||
{
|
||||
name: 'throws when none of the required args are not provided',
|
||||
sut: (i: ExpressionBuilder) => i.withParameterNames(['a', 'b'], false),
|
||||
sutBuilder: (i: ExpressionBuilder) => i.withParameterNames(['a', 'b'], false),
|
||||
context: new ExpressionEvaluationContextStub()
|
||||
.withArgs(new FunctionCallArgumentCollectionStub().withArgument('c', 'unrelated')),
|
||||
expectedError: 'argument values are provided for required parameters: "a", "b"',
|
||||
@@ -103,8 +116,8 @@ describe('Expression', () => {
|
||||
it(testCase.name, () => {
|
||||
// arrange
|
||||
const sutBuilder = new ExpressionBuilder();
|
||||
if (testCase.sut) {
|
||||
testCase.sut(sutBuilder);
|
||||
if (testCase.sutBuilder) {
|
||||
testCase.sutBuilder(sutBuilder);
|
||||
}
|
||||
const sut = sutBuilder.build();
|
||||
// act
|
||||
|
||||
@@ -5,19 +5,23 @@ import { IReadOnlyFunctionCallArgumentCollection } from '@/application/Parser/Sc
|
||||
import { IPipelineCompiler } from '@/application/Parser/Script/Compiler/Expressions/Pipes/IPipelineCompiler';
|
||||
import { FunctionCallArgumentCollectionStub } from '@tests/unit/stubs/FunctionCallArgumentCollectionStub';
|
||||
import { PipelineCompilerStub } from '@tests/unit/stubs/PipelineCompilerStub';
|
||||
import { itEachAbsentObjectValue } from '@tests/unit/shared/TestCases/AbsentTests';
|
||||
|
||||
describe('ExpressionEvaluationContext', () => {
|
||||
describe('ctor', () => {
|
||||
describe('args', () => {
|
||||
it('throws if args are undefined', () => {
|
||||
// arrange
|
||||
const expectedError = 'undefined args';
|
||||
const builder = new ExpressionEvaluationContextBuilder()
|
||||
.withArgs(undefined);
|
||||
// act
|
||||
const act = () => builder.build();
|
||||
// assert
|
||||
expect(act).throw(expectedError);
|
||||
describe('throws if args is missing', () => {
|
||||
itEachAbsentObjectValue((absentValue) => {
|
||||
// arrange
|
||||
const expectedError = 'missing args, send empty collection instead.';
|
||||
const args = absentValue;
|
||||
// act
|
||||
const act = () => new ExpressionEvaluationContextBuilder()
|
||||
.withArgs(args)
|
||||
.build();
|
||||
// assert
|
||||
expect(act).throw(expectedError);
|
||||
});
|
||||
});
|
||||
it('sets as expected', () => {
|
||||
// arrange
|
||||
|
||||
@@ -5,30 +5,21 @@ import { IExpressionParser } from '@/application/Parser/Script/Compiler/Expressi
|
||||
import { ExpressionStub } from '@tests/unit/stubs/ExpressionStub';
|
||||
import { ExpressionParserStub } from '@tests/unit/stubs/ExpressionParserStub';
|
||||
import { FunctionCallArgumentCollectionStub } from '@tests/unit/stubs/FunctionCallArgumentCollectionStub';
|
||||
import { itEachAbsentObjectValue, itEachAbsentStringValue } from '@tests/unit/shared/TestCases/AbsentTests';
|
||||
|
||||
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('returns code when it is absent', () => {
|
||||
itEachAbsentStringValue((absentValue) => {
|
||||
// arrange
|
||||
const expected = absentValue;
|
||||
const sut = new SystemUnderTest();
|
||||
const args = new FunctionCallArgumentCollectionStub();
|
||||
// act
|
||||
const value = sut.compileExpressions(absentValue, args);
|
||||
// assert
|
||||
expect(value).to.equal(expected);
|
||||
});
|
||||
});
|
||||
describe('combines expressions as expected', () => {
|
||||
// arrange
|
||||
@@ -100,16 +91,18 @@ describe('ExpressionsCompiler', () => {
|
||||
expect(expressions[1].callHistory).to.have.lengthOf(1);
|
||||
expect(expressions[1].callHistory[0].args).to.equal(expected);
|
||||
});
|
||||
it('throws if arguments is undefined', () => {
|
||||
// arrange
|
||||
const expectedError = 'undefined args, send empty collection instead';
|
||||
const args = undefined;
|
||||
const expressionParserMock = new ExpressionParserStub();
|
||||
const sut = new SystemUnderTest(expressionParserMock);
|
||||
// act
|
||||
const act = () => sut.compileExpressions('code', args);
|
||||
// assert
|
||||
expect(act).to.throw(expectedError);
|
||||
describe('throws if arguments is missing', () => {
|
||||
itEachAbsentObjectValue((absentValue) => {
|
||||
// arrange
|
||||
const expectedError = 'missing args, send empty collection instead.';
|
||||
const args = absentValue;
|
||||
const expressionParserMock = new ExpressionParserStub();
|
||||
const sut = new SystemUnderTest(expressionParserMock);
|
||||
// act
|
||||
const act = () => sut.compileExpressions('code', args);
|
||||
// assert
|
||||
expect(act).to.throw(expectedError);
|
||||
});
|
||||
});
|
||||
});
|
||||
describe('throws when expected argument is not provided but used in code', () => {
|
||||
|
||||
@@ -4,18 +4,30 @@ import { IExpression } from '@/application/Parser/Script/Compiler/Expressions/Ex
|
||||
import { IExpressionParser } from '@/application/Parser/Script/Compiler/Expressions/Parser/IExpressionParser';
|
||||
import { CompositeExpressionParser } from '@/application/Parser/Script/Compiler/Expressions/Parser/CompositeExpressionParser';
|
||||
import { ExpressionStub } from '@tests/unit/stubs/ExpressionStub';
|
||||
import { itEachAbsentObjectValue } from '@tests/unit/shared/TestCases/AbsentTests';
|
||||
|
||||
describe('CompositeExpressionParser', () => {
|
||||
describe('ctor', () => {
|
||||
it('throws if one of the parsers is undefined', () => {
|
||||
it('throws if null parsers given', () => {
|
||||
// arrange
|
||||
const expectedError = 'undefined leaf';
|
||||
const parsers: readonly IExpressionParser[] = [undefined, mockParser()];
|
||||
const expectedError = 'missing leafs';
|
||||
const parsers = null;
|
||||
// act
|
||||
const act = () => new CompositeExpressionParser(parsers);
|
||||
// assert
|
||||
expect(act).to.throw(expectedError);
|
||||
});
|
||||
describe('throws if one of the parsers is undefined', () => {
|
||||
itEachAbsentObjectValue((absentValue) => {
|
||||
// arrange
|
||||
const expectedError = 'missing leaf';
|
||||
const parsers: readonly IExpressionParser[] = [absentValue, mockParser()];
|
||||
// act
|
||||
const act = () => new CompositeExpressionParser(parsers);
|
||||
// assert
|
||||
expect(act).to.throw(expectedError);
|
||||
});
|
||||
});
|
||||
});
|
||||
describe('findExpressions', () => {
|
||||
describe('returns result from parsers as expected', () => {
|
||||
|
||||
@@ -4,32 +4,20 @@ import { ExpressionEvaluator } from '@/application/Parser/Script/Compiler/Expres
|
||||
import { IPrimitiveExpression, RegexParser } from '@/application/Parser/Script/Compiler/Expressions/Parser/Regex/RegexParser';
|
||||
import { ExpressionPosition } from '@/application/Parser/Script/Compiler/Expressions/Expression/ExpressionPosition';
|
||||
import { FunctionParameterStub } from '@tests/unit/stubs/FunctionParameterStub';
|
||||
import { itEachAbsentStringValue } from '@tests/unit/shared/TestCases/AbsentTests';
|
||||
|
||||
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('throws when code is absent', () => {
|
||||
itEachAbsentStringValue((absentValue) => {
|
||||
// arrange
|
||||
const expectedError = 'missing code';
|
||||
const sut = new RegexParserConcrete(/unimportant/);
|
||||
// act
|
||||
const act = () => sut.findExpressions(absentValue);
|
||||
// assert
|
||||
expect(act).to.throw(expectedError);
|
||||
});
|
||||
});
|
||||
it('throws when position is invalid', () => {
|
||||
// arrange
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import 'mocha';
|
||||
import { EscapeDoubleQuotes } from '@/application/Parser/Script/Compiler/Expressions/Pipes/PipeDefinitions/EscapeDoubleQuotes';
|
||||
import { AbsentStringTestCases } from '@tests/unit/shared/TestCases/AbsentTests';
|
||||
import { runPipeTests } from './PipeTestRunner';
|
||||
|
||||
describe('EscapeDoubleQuotes', () => {
|
||||
@@ -22,10 +23,10 @@ describe('EscapeDoubleQuotes', () => {
|
||||
input: '""hello world""',
|
||||
expectedOutput: '"^"""^""hello world"^"""^""',
|
||||
},
|
||||
{
|
||||
name: 'returns undefined when if input is undefined',
|
||||
input: undefined,
|
||||
expectedOutput: undefined,
|
||||
},
|
||||
...AbsentStringTestCases.map((testCase) => ({
|
||||
name: 'returns as it is when if input is missing',
|
||||
input: testCase.absentValue,
|
||||
expectedOutput: testCase.absentValue,
|
||||
})),
|
||||
]);
|
||||
});
|
||||
|
||||
@@ -2,6 +2,7 @@ import 'mocha';
|
||||
import { expect } from 'chai';
|
||||
import { PipeFactory } from '@/application/Parser/Script/Compiler/Expressions/Pipes/PipeFactory';
|
||||
import { PipeStub } from '@tests/unit/stubs/PipeStub';
|
||||
import { AbsentStringTestCases, itEachAbsentObjectValue } from '@tests/unit/shared/TestCases/AbsentTests';
|
||||
|
||||
describe('PipeFactory', () => {
|
||||
describe('ctor', () => {
|
||||
@@ -19,10 +20,21 @@ describe('PipeFactory', () => {
|
||||
// expect
|
||||
expect(act).to.throw(expectedError);
|
||||
});
|
||||
it('throws when a pipe is undefined', () => {
|
||||
describe('throws when a pipe is missing', () => {
|
||||
itEachAbsentObjectValue((absentValue) => {
|
||||
// arrange
|
||||
const expectedError = 'missing pipe in list';
|
||||
const pipes = [new PipeStub(), absentValue];
|
||||
// act
|
||||
const act = () => new PipeFactory(pipes);
|
||||
// expect
|
||||
expect(act).to.throw(expectedError);
|
||||
});
|
||||
});
|
||||
it('throws when pipes are null', () => {
|
||||
// arrange
|
||||
const expectedError = 'undefined pipe in list';
|
||||
const pipes = [new PipeStub(), undefined];
|
||||
const expectedError = 'missing pipes';
|
||||
const pipes = null;
|
||||
// act
|
||||
const act = () => new PipeFactory(pipes);
|
||||
// expect
|
||||
@@ -70,44 +82,34 @@ describe('PipeFactory', () => {
|
||||
|
||||
function testPipeNameValidation(testRunner: (invalidName: string) => void) {
|
||||
const testCases = [
|
||||
{
|
||||
exceptionBuilder: () => 'empty pipe name',
|
||||
values: [null, undefined, ''],
|
||||
},
|
||||
{
|
||||
exceptionBuilder: (name: string) => `Pipe name should be camelCase: "${name}"`,
|
||||
values: [
|
||||
'PascalCase',
|
||||
'snake-case',
|
||||
'includesNumb3rs',
|
||||
'includes Whitespace',
|
||||
'noSpec\'ial',
|
||||
],
|
||||
},
|
||||
// Validate missing value
|
||||
...AbsentStringTestCases.map((testCase) => ({
|
||||
name: `empty pipe name (${testCase.valueName})`,
|
||||
value: testCase.absentValue,
|
||||
expectedError: 'empty pipe name',
|
||||
})),
|
||||
// Validate camelCase
|
||||
...[
|
||||
'PascalCase',
|
||||
'snake-case',
|
||||
'includesNumb3rs',
|
||||
'includes Whitespace',
|
||||
'noSpec\'ial',
|
||||
].map((nonCamelCaseValue) => ({
|
||||
name: `non camel case value (${nonCamelCaseValue})`,
|
||||
value: nonCamelCaseValue,
|
||||
expectedError: `Pipe name should be camelCase: "${nonCamelCaseValue}"`,
|
||||
})),
|
||||
];
|
||||
for (const testCase of testCases) {
|
||||
for (const invalidName of testCase.values) {
|
||||
it(`invalid name (${printValue(invalidName)}) throws`, () => {
|
||||
// arrange
|
||||
const expectedError = testCase.exceptionBuilder(invalidName);
|
||||
// act
|
||||
const act = () => testRunner(invalidName);
|
||||
// expect
|
||||
expect(act).to.throw(expectedError);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function printValue(value: string) {
|
||||
switch (value) {
|
||||
case undefined:
|
||||
return 'undefined';
|
||||
case null:
|
||||
return 'null';
|
||||
case '':
|
||||
return 'empty';
|
||||
default:
|
||||
return value;
|
||||
it(testCase.name, () => {
|
||||
// arrange
|
||||
const invalidName = testCase.value;
|
||||
const { expectedError } = testCase;
|
||||
// act
|
||||
const act = () => testRunner(invalidName);
|
||||
// expect
|
||||
expect(act).to.throw(expectedError);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ import { IPipelineCompiler } from '@/application/Parser/Script/Compiler/Expressi
|
||||
import { IPipeFactory } from '@/application/Parser/Script/Compiler/Expressions/Pipes/PipeFactory';
|
||||
import { PipeStub } from '@tests/unit/stubs/PipeStub';
|
||||
import { PipeFactoryStub } from '@tests/unit/stubs/PipeFactoryStub';
|
||||
import { AbsentStringTestCases } from '@tests/unit/shared/TestCases/AbsentTests';
|
||||
|
||||
describe('PipelineCompiler', () => {
|
||||
describe('compile', () => {
|
||||
@@ -15,26 +16,16 @@ describe('PipelineCompiler', () => {
|
||||
expectedError: string;
|
||||
}
|
||||
const testCases: ITestCase[] = [
|
||||
{
|
||||
name: '"value" is empty',
|
||||
act: (test) => test.withValue(''),
|
||||
expectedError: 'undefined value',
|
||||
},
|
||||
{
|
||||
name: '"value" is undefined',
|
||||
act: (test) => test.withValue(undefined),
|
||||
expectedError: 'undefined value',
|
||||
},
|
||||
{
|
||||
name: '"pipeline" is empty',
|
||||
act: (test) => test.withPipeline(''),
|
||||
expectedError: 'undefined pipeline',
|
||||
},
|
||||
{
|
||||
name: '"pipeline" is undefined',
|
||||
act: (test) => test.withPipeline(undefined),
|
||||
expectedError: 'undefined pipeline',
|
||||
},
|
||||
...AbsentStringTestCases.map((testCase) => ({
|
||||
name: `"value" is ${testCase.valueName}`,
|
||||
act: (test) => test.withValue(testCase.absentValue),
|
||||
expectedError: 'missing value',
|
||||
})),
|
||||
...AbsentStringTestCases.map((testCase) => ({
|
||||
name: `"pipeline" is ${testCase.valueName}`,
|
||||
act: (test) => test.withPipeline(testCase.absentValue),
|
||||
expectedError: 'missing pipeline',
|
||||
})),
|
||||
{
|
||||
name: '"pipeline" does not start with pipe',
|
||||
act: (test) => test.withPipeline('pipeline |'),
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import 'mocha';
|
||||
import { ExpressionPosition } from '@/application/Parser/Script/Compiler/Expressions/Expression/ExpressionPosition';
|
||||
import { WithParser } from '@/application/Parser/Script/Compiler/Expressions/SyntaxParsers/WithParser';
|
||||
import { AbsentStringTestCases } from '@tests/unit/shared/TestCases/AbsentTests';
|
||||
import { SyntaxParserTestsRunner } from './SyntaxParserTestsRunner';
|
||||
|
||||
describe('WithParser', () => {
|
||||
@@ -84,20 +85,13 @@ describe('WithParser', () => {
|
||||
describe('renders scope conditionally', () => {
|
||||
describe('does not render scope if argument is undefined', () => {
|
||||
runner.expectResults(
|
||||
{
|
||||
name: 'does not render when value is undefined',
|
||||
...AbsentStringTestCases.map((testCase) => ({
|
||||
name: `does not render when value is "${testCase.valueName}"`,
|
||||
code: '{{ with $parameter }}dark{{ end }} ',
|
||||
args: (args) => args
|
||||
.withArgument('parameter', undefined),
|
||||
.withArgument('parameter', testCase.absentValue),
|
||||
expected: [''],
|
||||
},
|
||||
{
|
||||
name: 'does not render when value is empty',
|
||||
code: '{{ with $parameter }}dark {{.}}{{ end }}',
|
||||
args: (args) => args
|
||||
.withArgument('parameter', ''),
|
||||
expected: [''],
|
||||
},
|
||||
})),
|
||||
{
|
||||
name: 'does not render when argument is not provided',
|
||||
code: '{{ with $parameter }}dark{{ end }}',
|
||||
|
||||
@@ -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);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -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', () => {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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', () => {
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import 'mocha';
|
||||
import { expect } from 'chai';
|
||||
import { AbsentStringTestCases } from '@tests/unit/shared/TestCases/AbsentTests';
|
||||
|
||||
export function testParameterName(action: (parameterName: string) => string) {
|
||||
describe('name', () => {
|
||||
@@ -22,16 +23,11 @@ export function testParameterName(action: (parameterName: string) => string) {
|
||||
describe('throws if invalid', () => {
|
||||
// arrange
|
||||
const testCases = [
|
||||
{
|
||||
name: 'undefined',
|
||||
value: undefined,
|
||||
expectedError: 'undefined parameter name',
|
||||
},
|
||||
{
|
||||
name: 'empty',
|
||||
value: '',
|
||||
expectedError: 'undefined parameter name',
|
||||
},
|
||||
...AbsentStringTestCases.map((test) => ({
|
||||
name: test.valueName,
|
||||
value: test.absentValue,
|
||||
expectedError: 'missing parameter name',
|
||||
})),
|
||||
{
|
||||
name: 'has @',
|
||||
value: 'b@d',
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import 'mocha';
|
||||
import { expect } from 'chai';
|
||||
import { FunctionData } from 'js-yaml-loader!@/*';
|
||||
import { ILanguageSyntax } from '@/domain/ScriptCode';
|
||||
import { ILanguageSyntax, ScriptCode } from '@/domain/ScriptCode';
|
||||
import { ScriptCompiler } from '@/application/Parser/Script/Compiler/ScriptCompiler';
|
||||
import { ISharedFunctionsParser } from '@/application/Parser/Script/Compiler/Function/ISharedFunctionsParser';
|
||||
import { ICompiledCode } from '@/application/Parser/Script/Compiler/Function/Call/Compiler/ICompiledCode';
|
||||
@@ -14,33 +14,39 @@ import { SharedFunctionsParserStub } from '@tests/unit/stubs/SharedFunctionsPars
|
||||
import { SharedFunctionCollectionStub } from '@tests/unit/stubs/SharedFunctionCollectionStub';
|
||||
import { parseFunctionCalls } from '@/application/Parser/Script/Compiler/Function/Call/FunctionCallParser';
|
||||
import { FunctionCallDataStub } from '@tests/unit/stubs/FunctionCallDataStub';
|
||||
import { itEachAbsentObjectValue } from '@tests/unit/shared/TestCases/AbsentTests';
|
||||
|
||||
describe('ScriptCompiler', () => {
|
||||
describe('ctor', () => {
|
||||
it('throws if syntax is undefined', () => {
|
||||
// arrange
|
||||
const expectedError = 'undefined syntax';
|
||||
// act
|
||||
const act = () => new ScriptCompilerBuilder()
|
||||
.withSomeFunctions()
|
||||
.withSyntax(undefined)
|
||||
.build();
|
||||
// assert
|
||||
expect(act).to.throw(expectedError);
|
||||
describe('throws if syntax is missing', () => {
|
||||
itEachAbsentObjectValue((absentValue) => {
|
||||
// arrange
|
||||
const expectedError = 'missing syntax';
|
||||
const syntax = absentValue;
|
||||
// act
|
||||
const act = () => new ScriptCompilerBuilder()
|
||||
.withSomeFunctions()
|
||||
.withSyntax(syntax)
|
||||
.build();
|
||||
// assert
|
||||
expect(act).to.throw(expectedError);
|
||||
});
|
||||
});
|
||||
});
|
||||
describe('canCompile', () => {
|
||||
it('throws if script is undefined', () => {
|
||||
// arrange
|
||||
const expectedError = 'undefined script';
|
||||
const argument = undefined;
|
||||
const builder = new ScriptCompilerBuilder()
|
||||
.withEmptyFunctions()
|
||||
.build();
|
||||
// act
|
||||
const act = () => builder.canCompile(argument);
|
||||
// assert
|
||||
expect(act).to.throw(expectedError);
|
||||
describe('throws if script is missing', () => {
|
||||
itEachAbsentObjectValue((absentValue) => {
|
||||
// arrange
|
||||
const expectedError = 'missing script';
|
||||
const argument = absentValue;
|
||||
const builder = new ScriptCompilerBuilder()
|
||||
.withEmptyFunctions()
|
||||
.build();
|
||||
// act
|
||||
const act = () => builder.canCompile(argument);
|
||||
// assert
|
||||
expect(act).to.throw(expectedError);
|
||||
});
|
||||
});
|
||||
it('returns true if "call" is defined', () => {
|
||||
// arrange
|
||||
@@ -66,17 +72,19 @@ describe('ScriptCompiler', () => {
|
||||
});
|
||||
});
|
||||
describe('compile', () => {
|
||||
it('throws if script is undefined', () => {
|
||||
// arrange
|
||||
const expectedError = 'undefined script';
|
||||
const argument = undefined;
|
||||
const builder = new ScriptCompilerBuilder()
|
||||
.withEmptyFunctions()
|
||||
.build();
|
||||
// act
|
||||
const act = () => builder.compile(argument);
|
||||
// assert
|
||||
expect(act).to.throw(expectedError);
|
||||
describe('throws if script is missing', () => {
|
||||
itEachAbsentObjectValue((absentValue) => {
|
||||
// arrange
|
||||
const expectedError = 'missing script';
|
||||
const argument = absentValue;
|
||||
const builder = new ScriptCompilerBuilder()
|
||||
.withEmptyFunctions()
|
||||
.build();
|
||||
// act
|
||||
const act = () => builder.compile(argument);
|
||||
// assert
|
||||
expect(act).to.throw(expectedError);
|
||||
});
|
||||
});
|
||||
it('returns code as expected', () => {
|
||||
// arrange
|
||||
@@ -148,15 +156,21 @@ describe('ScriptCompiler', () => {
|
||||
it('rethrows error from ScriptCode with script name', () => {
|
||||
// arrange
|
||||
const scriptName = 'scriptName';
|
||||
const expectedError = `Script "${scriptName}" code is empty or undefined`;
|
||||
const syntax = new LanguageSyntaxStub();
|
||||
const invalidCode: ICompiledCode = { code: undefined, revertCode: undefined };
|
||||
const realExceptionMessage = collectExceptionMessage(
|
||||
() => new ScriptCode(invalidCode.code, invalidCode.revertCode, syntax),
|
||||
);
|
||||
const expectedError = `Script "${scriptName}" ${realExceptionMessage}`;
|
||||
const callCompiler: IFunctionCallCompiler = {
|
||||
compileCall: () => ({ code: undefined, revertCode: undefined }),
|
||||
compileCall: () => invalidCode,
|
||||
};
|
||||
const scriptData = ScriptDataStub.createWithCall()
|
||||
.withName(scriptName);
|
||||
const sut = new ScriptCompilerBuilder()
|
||||
.withSomeFunctions()
|
||||
.withFunctionCallCompiler(callCompiler)
|
||||
.withSyntax(syntax)
|
||||
.build();
|
||||
// act
|
||||
const act = () => sut.compile(scriptData);
|
||||
@@ -230,3 +244,13 @@ class ScriptCompilerBuilder {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function collectExceptionMessage(action: () => unknown) {
|
||||
let message = '';
|
||||
try {
|
||||
action();
|
||||
} catch (e) {
|
||||
message = e.message;
|
||||
}
|
||||
return message;
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ import { EnumParserStub } from '@tests/unit/stubs/EnumParserStub';
|
||||
import { ScriptCodeStub } from '@tests/unit/stubs/ScriptCodeStub';
|
||||
import { CategoryCollectionParseContextStub } from '@tests/unit/stubs/CategoryCollectionParseContextStub';
|
||||
import { LanguageSyntaxStub } from '@tests/unit/stubs/LanguageSyntaxStub';
|
||||
import { itEachAbsentObjectValue, itEachAbsentStringValue } from '@tests/unit/shared/TestCases/AbsentTests';
|
||||
|
||||
describe('ScriptParser', () => {
|
||||
describe('parseScript', () => {
|
||||
@@ -37,15 +38,17 @@ describe('ScriptParser', () => {
|
||||
expect(actual.documentationUrls).to.deep.equal(expected);
|
||||
});
|
||||
describe('invalid script', () => {
|
||||
it('throws when script is undefined', () => {
|
||||
// arrange
|
||||
const expectedError = 'undefined script';
|
||||
const parseContext = new CategoryCollectionParseContextStub();
|
||||
const script = undefined;
|
||||
// act
|
||||
const act = () => parseScript(script, parseContext);
|
||||
// assert
|
||||
expect(act).to.throw(expectedError);
|
||||
describe('throws when script is absent', () => {
|
||||
itEachAbsentObjectValue((absentValue) => {
|
||||
// arrange
|
||||
const expectedError = 'missing script';
|
||||
const parseContext = new CategoryCollectionParseContextStub();
|
||||
const script = absentValue;
|
||||
// act
|
||||
const act = () => parseScript(script, parseContext);
|
||||
// assert
|
||||
expect(act).to.throw(expectedError);
|
||||
});
|
||||
});
|
||||
it('throws when both function call and code are defined', () => {
|
||||
// arrange
|
||||
@@ -83,13 +86,12 @@ describe('ScriptParser', () => {
|
||||
});
|
||||
});
|
||||
describe('level', () => {
|
||||
it('accepts undefined level', () => {
|
||||
const undefinedLevels: string[] = ['', undefined];
|
||||
undefinedLevels.forEach((undefinedLevel) => {
|
||||
describe('accepts absent level', () => {
|
||||
itEachAbsentStringValue((absentValue) => {
|
||||
// arrange
|
||||
const parseContext = new CategoryCollectionParseContextStub();
|
||||
const script = ScriptDataStub.createWithCode()
|
||||
.withRecommend(undefinedLevel);
|
||||
.withRecommend(absentValue);
|
||||
// act
|
||||
const actual = parseScript(script, parseContext);
|
||||
// assert
|
||||
@@ -140,15 +142,17 @@ describe('ScriptParser', () => {
|
||||
expect(actual).to.equal(expected);
|
||||
});
|
||||
describe('compiler', () => {
|
||||
it('throws when context is not defined', () => {
|
||||
// arrange
|
||||
const expectedMessage = 'undefined context';
|
||||
const script = ScriptDataStub.createWithCode();
|
||||
const context: ICategoryCollectionParseContext = undefined;
|
||||
// act
|
||||
const act = () => parseScript(script, context);
|
||||
// assert
|
||||
expect(act).to.throw(expectedMessage);
|
||||
describe('throws when context is not defined', () => {
|
||||
itEachAbsentObjectValue((absentValue) => {
|
||||
// arrange
|
||||
const expectedMessage = 'missing context';
|
||||
const script = ScriptDataStub.createWithCode();
|
||||
const context: ICategoryCollectionParseContext = absentValue;
|
||||
// act
|
||||
const act = () => parseScript(script, context);
|
||||
// assert
|
||||
expect(act).to.throw(expectedMessage);
|
||||
});
|
||||
});
|
||||
it('gets code from compiler', () => {
|
||||
// arrange
|
||||
|
||||
@@ -4,29 +4,36 @@ import { CodeSubstituter } from '@/application/Parser/ScriptingDefinition/CodeSu
|
||||
import { IExpressionsCompiler } from '@/application/Parser/Script/Compiler/Expressions/IExpressionsCompiler';
|
||||
import { ProjectInformationStub } from '@tests/unit/stubs/ProjectInformationStub';
|
||||
import { ExpressionsCompilerStub } from '@tests/unit/stubs/ExpressionsCompilerStub';
|
||||
import { AbsentObjectTestCases, AbsentStringTestCases } from '@tests/unit/shared/TestCases/AbsentTests';
|
||||
|
||||
describe('CodeSubstituter', () => {
|
||||
describe('throws with invalid parameters', () => {
|
||||
// arrange
|
||||
const testCases = [{
|
||||
expectedError: 'undefined code',
|
||||
parameters: {
|
||||
code: undefined,
|
||||
info: new ProjectInformationStub(),
|
||||
},
|
||||
},
|
||||
{
|
||||
expectedError: 'undefined info',
|
||||
parameters: {
|
||||
code: 'non empty code',
|
||||
info: undefined,
|
||||
},
|
||||
}];
|
||||
const testCases = [
|
||||
...AbsentStringTestCases.map((testCase) => ({
|
||||
name: `given code: ${testCase.valueName}`,
|
||||
expectedError: 'missing code',
|
||||
parameters: {
|
||||
code: testCase.absentValue,
|
||||
info: new ProjectInformationStub(),
|
||||
},
|
||||
})),
|
||||
...AbsentObjectTestCases.map((testCase) => ({
|
||||
name: `given info: ${testCase.valueName}`,
|
||||
expectedError: 'missing info',
|
||||
parameters: {
|
||||
code: 'non empty code',
|
||||
info: testCase.absentValue,
|
||||
},
|
||||
})),
|
||||
];
|
||||
for (const testCase of testCases) {
|
||||
it(`throws "${testCase.expectedError}" as expected`, () => {
|
||||
it(`${testCase.name} throws "${testCase.expectedError}"`, () => {
|
||||
// arrange
|
||||
const sut = new CodeSubstituterBuilder().build();
|
||||
const { code, info } = testCase.parameters;
|
||||
// act
|
||||
const act = () => sut.substitute(testCase.parameters.code, testCase.parameters.info);
|
||||
const act = () => sut.substitute(code, info);
|
||||
// assert
|
||||
expect(act).to.throw(testCase.expectedError);
|
||||
});
|
||||
|
||||
@@ -9,30 +9,37 @@ import { ProjectInformationStub } from '@tests/unit/stubs/ProjectInformationStub
|
||||
import { EnumParserStub } from '@tests/unit/stubs/EnumParserStub';
|
||||
import { ScriptingDefinitionDataStub } from '@tests/unit/stubs/ScriptingDefinitionDataStub';
|
||||
import { CodeSubstituterStub } from '@tests/unit/stubs/CodeSubstituterStub';
|
||||
import { itEachAbsentObjectValue } from '@tests/unit/shared/TestCases/AbsentTests';
|
||||
|
||||
describe('ScriptingDefinitionParser', () => {
|
||||
describe('parseScriptingDefinition', () => {
|
||||
it('throws when info is undefined', () => {
|
||||
// arrange
|
||||
const info = undefined;
|
||||
const definition = new ScriptingDefinitionDataStub();
|
||||
const sut = new ScriptingDefinitionParserBuilder()
|
||||
.build();
|
||||
// act
|
||||
const act = () => sut.parse(definition, info);
|
||||
// assert
|
||||
expect(act).to.throw('undefined info');
|
||||
describe('throws when info is missing', () => {
|
||||
itEachAbsentObjectValue((absentValue) => {
|
||||
// arrange
|
||||
const expectedError = 'missing info';
|
||||
const info = absentValue;
|
||||
const definition = new ScriptingDefinitionDataStub();
|
||||
const sut = new ScriptingDefinitionParserBuilder()
|
||||
.build();
|
||||
// act
|
||||
const act = () => sut.parse(definition, info);
|
||||
// assert
|
||||
expect(act).to.throw(expectedError);
|
||||
});
|
||||
});
|
||||
it('throws when definition is undefined', () => {
|
||||
// arrange
|
||||
const info = new ProjectInformationStub();
|
||||
const definition = undefined;
|
||||
const sut = new ScriptingDefinitionParserBuilder()
|
||||
.build();
|
||||
// act
|
||||
const act = () => sut.parse(definition, info);
|
||||
// assert
|
||||
expect(act).to.throw('undefined definition');
|
||||
describe('throws when definition is missing', () => {
|
||||
itEachAbsentObjectValue((absentValue) => {
|
||||
// arrange
|
||||
const expectedError = 'missing definition';
|
||||
const info = new ProjectInformationStub();
|
||||
const definition = absentValue;
|
||||
const sut = new ScriptingDefinitionParserBuilder()
|
||||
.build();
|
||||
// act
|
||||
const act = () => sut.parse(definition, info);
|
||||
// assert
|
||||
expect(act).to.throw(expectedError);
|
||||
});
|
||||
});
|
||||
describe('language', () => {
|
||||
it('parses as expected', () => {
|
||||
|
||||
Reference in New Issue
Block a user