Refactor code to comply with ESLint rules
Major refactoring using ESLint with rules from AirBnb and Vue. Enable most of the ESLint rules and do necessary linting in the code. Also add more information for rules that are disabled to describe what they are and why they are disabled. Allow logging (`console.log`) in test files, and in development mode (e.g. when working with `npm run serve`), but disable it when environment is production (as pre-configured by Vue). Also add flag (`--mode production`) in `lint:eslint` command so production linting is executed earlier in lifecycle. Disable rules that requires a separate work. Such as ESLint rules that are broken in TypeScript: no-useless-constructor (eslint/eslint#14118) and no-shadow (eslint/eslint#13014).
This commit is contained in:
@@ -1,69 +1,74 @@
|
||||
interface IComparerTestCase<T> {
|
||||
readonly name: string;
|
||||
readonly first: readonly T[];
|
||||
readonly second: readonly T[];
|
||||
readonly expected: boolean;
|
||||
readonly name: string;
|
||||
readonly first: readonly T[];
|
||||
readonly second: readonly T[];
|
||||
readonly expected: boolean;
|
||||
}
|
||||
|
||||
export class ComparerTestScenario {
|
||||
private readonly testCases: Array<IComparerTestCase<number>> = [];
|
||||
private readonly testCases: Array<IComparerTestCase<number>> = [];
|
||||
|
||||
public addEmptyArrays(expectedResult: boolean) {
|
||||
return this.addTestCase({
|
||||
name: 'empty array',
|
||||
first: [ ],
|
||||
second: [ ],
|
||||
expected: expectedResult,
|
||||
}, true);
|
||||
}
|
||||
public addSameItemsWithSameOrder(expectedResult: boolean) {
|
||||
return this.addTestCase({
|
||||
name: 'same items with same order',
|
||||
first: [ 1, 2, 3 ],
|
||||
second: [ 1, 2, 3 ],
|
||||
expected: expectedResult,
|
||||
}, true);
|
||||
}
|
||||
public addSameItemsWithDifferentOrder(expectedResult: boolean) {
|
||||
return this.addTestCase({
|
||||
name: 'same items with different order',
|
||||
first: [ 1, 2, 3 ],
|
||||
second: [ 2, 3, 1 ],
|
||||
expected: expectedResult,
|
||||
}, true);
|
||||
}
|
||||
public addDifferentItemsWithSameLength(expectedResult: boolean) {
|
||||
return this.addTestCase({
|
||||
name: 'different items with same length',
|
||||
first: [ 1, 2, 3 ],
|
||||
second: [ 4, 5, 6 ],
|
||||
expected: expectedResult,
|
||||
}, true);
|
||||
}
|
||||
public addDifferentItemsWithDifferentLength(expectedResult: boolean) {
|
||||
return this.addTestCase({
|
||||
name: 'different items with different length',
|
||||
first: [ 1, 2 ],
|
||||
second: [ 3, 4, 5 ],
|
||||
expected: expectedResult,
|
||||
}, true);
|
||||
}
|
||||
public forEachCase(handler: (testCase: IComparerTestCase<number>) => void) {
|
||||
for (const testCase of this.testCases) {
|
||||
handler(testCase);
|
||||
}
|
||||
}
|
||||
public addEmptyArrays(expectedResult: boolean) {
|
||||
return this.addTestCase({
|
||||
name: 'empty array',
|
||||
first: [],
|
||||
second: [],
|
||||
expected: expectedResult,
|
||||
}, true);
|
||||
}
|
||||
|
||||
private addTestCase(testCase: IComparerTestCase<number>, addReversed: boolean) {
|
||||
this.testCases.push(testCase);
|
||||
if (addReversed) {
|
||||
this.testCases.push({
|
||||
name: `${testCase.name} (reversed)`,
|
||||
first: testCase.second,
|
||||
second: testCase.first,
|
||||
expected: testCase.expected,
|
||||
});
|
||||
}
|
||||
return this;
|
||||
public addSameItemsWithSameOrder(expectedResult: boolean) {
|
||||
return this.addTestCase({
|
||||
name: 'same items with same order',
|
||||
first: [1, 2, 3],
|
||||
second: [1, 2, 3],
|
||||
expected: expectedResult,
|
||||
}, true);
|
||||
}
|
||||
|
||||
public addSameItemsWithDifferentOrder(expectedResult: boolean) {
|
||||
return this.addTestCase({
|
||||
name: 'same items with different order',
|
||||
first: [1, 2, 3],
|
||||
second: [2, 3, 1],
|
||||
expected: expectedResult,
|
||||
}, true);
|
||||
}
|
||||
|
||||
public addDifferentItemsWithSameLength(expectedResult: boolean) {
|
||||
return this.addTestCase({
|
||||
name: 'different items with same length',
|
||||
first: [1, 2, 3],
|
||||
second: [4, 5, 6],
|
||||
expected: expectedResult,
|
||||
}, true);
|
||||
}
|
||||
|
||||
public addDifferentItemsWithDifferentLength(expectedResult: boolean) {
|
||||
return this.addTestCase({
|
||||
name: 'different items with different length',
|
||||
first: [1, 2],
|
||||
second: [3, 4, 5],
|
||||
expected: expectedResult,
|
||||
}, true);
|
||||
}
|
||||
|
||||
public forEachCase(handler: (testCase: IComparerTestCase<number>) => void) {
|
||||
for (const testCase of this.testCases) {
|
||||
handler(testCase);
|
||||
}
|
||||
}
|
||||
|
||||
private addTestCase(testCase: IComparerTestCase<number>, addReversed: boolean) {
|
||||
this.testCases.push(testCase);
|
||||
if (addReversed) {
|
||||
this.testCases.push({
|
||||
name: `${testCase.name} (reversed)`,
|
||||
first: testCase.second,
|
||||
second: testCase.first,
|
||||
expected: testCase.expected,
|
||||
});
|
||||
}
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,68 +1,67 @@
|
||||
import 'mocha';
|
||||
import { expect } from 'chai';
|
||||
import { scrambledEqual } from '@/application/Common/Array';
|
||||
import { sequenceEqual } from '@/application/Common/Array';
|
||||
import { scrambledEqual, sequenceEqual } from '@/application/Common/Array';
|
||||
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);
|
||||
});
|
||||
it('second arguments is undefined', () => {
|
||||
const expectedError = 'undefined second array';
|
||||
const act = () => scrambledEqual([], undefined);
|
||||
expect(act).to.throw(expectedError);
|
||||
});
|
||||
});
|
||||
describe('returns as expected', () => {
|
||||
// arrange
|
||||
const scenario = new ComparerTestScenario()
|
||||
.addSameItemsWithSameOrder(true)
|
||||
.addSameItemsWithDifferentOrder(true)
|
||||
.addDifferentItemsWithSameLength(false)
|
||||
.addDifferentItemsWithDifferentLength(false);
|
||||
// act
|
||||
scenario.forEachCase((testCase) => {
|
||||
it(testCase.name, () => {
|
||||
const actual = scrambledEqual(testCase.first, testCase.second);
|
||||
// assert
|
||||
expect(actual).to.equal(testCase.expected);
|
||||
});
|
||||
});
|
||||
});
|
||||
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);
|
||||
});
|
||||
it('second arguments is undefined', () => {
|
||||
const expectedError = 'undefined second array';
|
||||
const act = () => scrambledEqual([], undefined);
|
||||
expect(act).to.throw(expectedError);
|
||||
});
|
||||
});
|
||||
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);
|
||||
});
|
||||
it('second arguments is undefined', () => {
|
||||
const expectedError = 'undefined second array';
|
||||
const act = () => sequenceEqual([], undefined);
|
||||
expect(act).to.throw(expectedError);
|
||||
});
|
||||
});
|
||||
describe('returns as expected', () => {
|
||||
// arrange
|
||||
const scenario = new ComparerTestScenario()
|
||||
.addSameItemsWithSameOrder(true)
|
||||
.addSameItemsWithDifferentOrder(true)
|
||||
.addDifferentItemsWithSameLength(false)
|
||||
.addDifferentItemsWithDifferentLength(false);
|
||||
// act
|
||||
scenario.forEachCase((testCase) => {
|
||||
it(testCase.name, () => {
|
||||
const actual = scrambledEqual(testCase.first, testCase.second);
|
||||
// assert
|
||||
expect(actual).to.equal(testCase.expected);
|
||||
});
|
||||
});
|
||||
describe('returns as expected', () => {
|
||||
// arrange
|
||||
const scenario = new ComparerTestScenario()
|
||||
.addSameItemsWithSameOrder(true)
|
||||
.addSameItemsWithDifferentOrder(true)
|
||||
.addDifferentItemsWithSameLength(false)
|
||||
.addDifferentItemsWithDifferentLength(false);
|
||||
// act
|
||||
scenario.forEachCase((testCase) => {
|
||||
it(testCase.name, () => {
|
||||
const actual = scrambledEqual(testCase.first, testCase.second);
|
||||
// assert
|
||||
expect(actual).to.equal(testCase.expected);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
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);
|
||||
});
|
||||
it('second arguments is undefined', () => {
|
||||
const expectedError = 'undefined second array';
|
||||
const act = () => sequenceEqual([], undefined);
|
||||
expect(act).to.throw(expectedError);
|
||||
});
|
||||
});
|
||||
describe('returns as expected', () => {
|
||||
// arrange
|
||||
const scenario = new ComparerTestScenario()
|
||||
.addSameItemsWithSameOrder(true)
|
||||
.addSameItemsWithDifferentOrder(true)
|
||||
.addDifferentItemsWithSameLength(false)
|
||||
.addDifferentItemsWithDifferentLength(false);
|
||||
// act
|
||||
scenario.forEachCase((testCase) => {
|
||||
it(testCase.name, () => {
|
||||
const actual = scrambledEqual(testCase.first, testCase.second);
|
||||
// assert
|
||||
expect(actual).to.equal(testCase.expected);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,109 +1,111 @@
|
||||
import 'mocha';
|
||||
import { expect } from 'chai';
|
||||
import { getEnumNames, getEnumValues, createEnumParser, assertInRange } from '@/application/Common/Enum';
|
||||
import { EnumRangeTestRunner } from './EnumRangeTestRunner';
|
||||
import {
|
||||
getEnumNames, getEnumValues, createEnumParser, assertInRange,
|
||||
} from '@/application/Common/Enum';
|
||||
import { scrambledEqual } from '@/application/Common/Array';
|
||||
import { EnumRangeTestRunner } from './EnumRangeTestRunner';
|
||||
|
||||
describe('Enum', () => {
|
||||
describe('createEnumParser', () => {
|
||||
enum ParsableEnum { Value1, value2 }
|
||||
describe('parses as expected', () => {
|
||||
// arrange
|
||||
const testCases = [
|
||||
{
|
||||
name: 'case insensitive',
|
||||
value: 'vALuE1',
|
||||
expected: ParsableEnum.Value1,
|
||||
},
|
||||
{
|
||||
name: 'exact match',
|
||||
value: 'value2',
|
||||
expected: ParsableEnum.value2,
|
||||
},
|
||||
];
|
||||
// act
|
||||
for (const testCase of testCases) {
|
||||
it(testCase.name, () => {
|
||||
const parser = createEnumParser(ParsableEnum);
|
||||
const actual = parser.parseEnum(testCase.value, 'non-important');
|
||||
// assert
|
||||
expect(actual).to.equal(testCase.expected);
|
||||
});
|
||||
}
|
||||
});
|
||||
describe('throws as expected', () => {
|
||||
// arrange
|
||||
const enumName = 'ParsableEnum';
|
||||
const testCases = [
|
||||
{
|
||||
name: 'undefined',
|
||||
value: undefined,
|
||||
expectedError: `undefined ${enumName}`,
|
||||
},
|
||||
{
|
||||
name: 'empty',
|
||||
value: '',
|
||||
expectedError: `undefined ${enumName}`,
|
||||
},
|
||||
{
|
||||
name: 'out of range',
|
||||
value: 'value3',
|
||||
expectedError: `unknown ${enumName}: "value3"`,
|
||||
},
|
||||
{
|
||||
name: 'out of range',
|
||||
value: 'value3',
|
||||
expectedError: `unknown ${enumName}: "value3"`,
|
||||
},
|
||||
{
|
||||
name: 'unexpected type',
|
||||
value: 55 as any,
|
||||
expectedError: `unexpected type of ${enumName}: "number"`,
|
||||
},
|
||||
];
|
||||
// act
|
||||
for (const testCase of testCases) {
|
||||
it(testCase.name, () => {
|
||||
const parser = createEnumParser(ParsableEnum);
|
||||
const act = () => parser.parseEnum(testCase.value, enumName);
|
||||
// assert
|
||||
expect(act).to.throw(testCase.expectedError);
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
describe('getEnumNames', () => {
|
||||
it('parses as expected', () => {
|
||||
// arrange
|
||||
enum TestEnum { TestValue1, testValue2, testvalue3, TESTVALUE4 }
|
||||
const expected = [ 'TestValue1', 'testValue2', 'testvalue3', 'TESTVALUE4' ];
|
||||
// act
|
||||
const actual = getEnumNames(TestEnum);
|
||||
// assert
|
||||
expect(scrambledEqual(expected, actual));
|
||||
});
|
||||
});
|
||||
describe('getEnumValues', () => {
|
||||
it('parses as expected', () => {
|
||||
// arrange
|
||||
enum TestEnum { Red, Green, Blue }
|
||||
const expected = [ TestEnum.Red, TestEnum.Green, TestEnum.Blue ];
|
||||
// act
|
||||
const actual = getEnumValues(TestEnum);
|
||||
// assert
|
||||
expect(scrambledEqual(expected, actual));
|
||||
});
|
||||
});
|
||||
describe('assertInRange', () => {
|
||||
// arrange
|
||||
enum TestEnum { Red, Green, Blue }
|
||||
const validValue = TestEnum.Red;
|
||||
describe('createEnumParser', () => {
|
||||
enum ParsableEnum { Value1, value2 }
|
||||
describe('parses as expected', () => {
|
||||
// arrange
|
||||
const testCases = [
|
||||
{
|
||||
name: 'case insensitive',
|
||||
value: 'vALuE1',
|
||||
expected: ParsableEnum.Value1,
|
||||
},
|
||||
{
|
||||
name: 'exact match',
|
||||
value: 'value2',
|
||||
expected: ParsableEnum.value2,
|
||||
},
|
||||
];
|
||||
// act
|
||||
const act = (value: TestEnum) => assertInRange(value, TestEnum);
|
||||
// assert
|
||||
new EnumRangeTestRunner(act)
|
||||
.testOutOfRangeThrows()
|
||||
.testUndefinedValueThrows()
|
||||
.testValidValueDoesNotThrow(validValue);
|
||||
for (const testCase of testCases) {
|
||||
it(testCase.name, () => {
|
||||
const parser = createEnumParser(ParsableEnum);
|
||||
const actual = parser.parseEnum(testCase.value, 'non-important');
|
||||
// assert
|
||||
expect(actual).to.equal(testCase.expected);
|
||||
});
|
||||
}
|
||||
});
|
||||
describe('throws as expected', () => {
|
||||
// arrange
|
||||
const enumName = 'ParsableEnum';
|
||||
const testCases = [
|
||||
{
|
||||
name: 'undefined',
|
||||
value: undefined,
|
||||
expectedError: `undefined ${enumName}`,
|
||||
},
|
||||
{
|
||||
name: 'empty',
|
||||
value: '',
|
||||
expectedError: `undefined ${enumName}`,
|
||||
},
|
||||
{
|
||||
name: 'out of range',
|
||||
value: 'value3',
|
||||
expectedError: `unknown ${enumName}: "value3"`,
|
||||
},
|
||||
{
|
||||
name: 'out of range',
|
||||
value: 'value3',
|
||||
expectedError: `unknown ${enumName}: "value3"`,
|
||||
},
|
||||
{
|
||||
name: 'unexpected type',
|
||||
value: 55 as never,
|
||||
expectedError: `unexpected type of ${enumName}: "number"`,
|
||||
},
|
||||
];
|
||||
// act
|
||||
for (const testCase of testCases) {
|
||||
it(testCase.name, () => {
|
||||
const parser = createEnumParser(ParsableEnum);
|
||||
const act = () => parser.parseEnum(testCase.value, enumName);
|
||||
// assert
|
||||
expect(act).to.throw(testCase.expectedError);
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
describe('getEnumNames', () => {
|
||||
it('parses as expected', () => {
|
||||
// arrange
|
||||
enum TestEnum { TestValue1, testValue2, testvalue3, TESTVALUE4 }
|
||||
const expected = ['TestValue1', 'testValue2', 'testvalue3', 'TESTVALUE4'];
|
||||
// act
|
||||
const actual = getEnumNames(TestEnum);
|
||||
// assert
|
||||
expect(scrambledEqual(expected, actual));
|
||||
});
|
||||
});
|
||||
describe('getEnumValues', () => {
|
||||
it('parses as expected', () => {
|
||||
// arrange
|
||||
enum TestEnum { Red, Green, Blue }
|
||||
const expected = [TestEnum.Red, TestEnum.Green, TestEnum.Blue];
|
||||
// act
|
||||
const actual = getEnumValues(TestEnum);
|
||||
// assert
|
||||
expect(scrambledEqual(expected, actual));
|
||||
});
|
||||
});
|
||||
describe('assertInRange', () => {
|
||||
// arrange
|
||||
enum TestEnum { Red, Green, Blue }
|
||||
const validValue = TestEnum.Red;
|
||||
// act
|
||||
const act = (value: TestEnum) => assertInRange(value, TestEnum);
|
||||
// assert
|
||||
new EnumRangeTestRunner(act)
|
||||
.testOutOfRangeThrows()
|
||||
.testUndefinedValueThrows()
|
||||
.testValidValueDoesNotThrow(validValue);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -3,52 +3,56 @@ import { expect } from 'chai';
|
||||
import { EnumType } from '@/application/Common/Enum';
|
||||
|
||||
export class EnumRangeTestRunner<TEnumValue extends EnumType> {
|
||||
constructor(private readonly runner: (value: TEnumValue) => any) {
|
||||
}
|
||||
public testOutOfRangeThrows() {
|
||||
it('throws when value is out of range', () => {
|
||||
// arrange
|
||||
const value = Number.MAX_SAFE_INTEGER as TEnumValue;
|
||||
const expectedError = `enum value "${value}" is out of range`;
|
||||
// act
|
||||
const act = () => this.runner(value);
|
||||
// assert
|
||||
expect(act).to.throw(expectedError);
|
||||
});
|
||||
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);
|
||||
});
|
||||
return this;
|
||||
}
|
||||
public testInvalidValueThrows(invalidValue: TEnumValue, expectedError: string) {
|
||||
it(`throws ${expectedError}`, () => {
|
||||
// arrange
|
||||
const value = invalidValue;
|
||||
// act
|
||||
const act = () => this.runner(value);
|
||||
// assert
|
||||
expect(act).to.throw(expectedError);
|
||||
});
|
||||
return this;
|
||||
}
|
||||
public testValidValueDoesNotThrow(validValue: TEnumValue) {
|
||||
it('throws when value is undefined', () => {
|
||||
// arrange
|
||||
const value = validValue;
|
||||
// act
|
||||
const act = () => this.runner(value);
|
||||
// assert
|
||||
expect(act).to.not.throw();
|
||||
});
|
||||
return this;
|
||||
}
|
||||
constructor(private readonly runner: (value: TEnumValue) => void) {
|
||||
}
|
||||
|
||||
public testOutOfRangeThrows() {
|
||||
it('throws when value is out of range', () => {
|
||||
// arrange
|
||||
const value = Number.MAX_SAFE_INTEGER as TEnumValue;
|
||||
const expectedError = `enum value "${value}" is out of range`;
|
||||
// act
|
||||
const act = () => this.runner(value);
|
||||
// assert
|
||||
expect(act).to.throw(expectedError);
|
||||
});
|
||||
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);
|
||||
});
|
||||
return this;
|
||||
}
|
||||
|
||||
public testInvalidValueThrows(invalidValue: TEnumValue, expectedError: string) {
|
||||
it(`throws ${expectedError}`, () => {
|
||||
// arrange
|
||||
const value = invalidValue;
|
||||
// act
|
||||
const act = () => this.runner(value);
|
||||
// assert
|
||||
expect(act).to.throw(expectedError);
|
||||
});
|
||||
return this;
|
||||
}
|
||||
|
||||
public testValidValueDoesNotThrow(validValue: TEnumValue) {
|
||||
it('throws when value is undefined', () => {
|
||||
// arrange
|
||||
const value = validValue;
|
||||
// act
|
||||
const act = () => this.runner(value);
|
||||
// assert
|
||||
expect(act).to.not.throw();
|
||||
});
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,59 +2,58 @@ import 'mocha';
|
||||
import { expect } from 'chai';
|
||||
import { ScriptingLanguage } from '@/domain/ScriptingLanguage';
|
||||
import { ScriptingLanguageFactory } from '@/application/Common/ScriptingLanguage/ScriptingLanguageFactory';
|
||||
import { ScriptingLanguageFactoryTestRunner } from './ScriptingLanguageFactoryTestRunner';
|
||||
import { EnumRangeTestRunner } from '@tests/unit/application/Common/EnumRangeTestRunner';
|
||||
import { ScriptingLanguageFactoryTestRunner } from './ScriptingLanguageFactoryTestRunner';
|
||||
|
||||
class ScriptingLanguageConcrete extends ScriptingLanguageFactory<number> {
|
||||
public registerGetter(language: ScriptingLanguage, getter: () => number) {
|
||||
super.registerGetter(language, getter);
|
||||
}
|
||||
public registerGetter(language: ScriptingLanguage, getter: () => number) {
|
||||
super.registerGetter(language, getter);
|
||||
}
|
||||
}
|
||||
|
||||
describe('ScriptingLanguageFactory', () => {
|
||||
describe('registerGetter', () => {
|
||||
describe('validates language', () => {
|
||||
// arrange
|
||||
const validValue = ScriptingLanguage.batchfile;
|
||||
const getter = () => undefined;
|
||||
const sut = new ScriptingLanguageConcrete();
|
||||
// act
|
||||
const act = (language: ScriptingLanguage) => sut.registerGetter(language, getter);
|
||||
// assert
|
||||
new EnumRangeTestRunner(act)
|
||||
.testOutOfRangeThrows()
|
||||
.testUndefinedValueThrows()
|
||||
.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);
|
||||
});
|
||||
it('throw when language is already registered', () => {
|
||||
// arrange
|
||||
const language = ScriptingLanguage.batchfile;
|
||||
const expectedError = `${ScriptingLanguage[language]} is already registered`;
|
||||
const getter = () => undefined;
|
||||
const sut = new ScriptingLanguageConcrete();
|
||||
// act
|
||||
sut.registerGetter(language, getter);
|
||||
const reRegister = () => sut.registerGetter(language, getter);
|
||||
// assert
|
||||
expect(reRegister).to.throw(expectedError);
|
||||
});
|
||||
describe('registerGetter', () => {
|
||||
describe('validates language', () => {
|
||||
// arrange
|
||||
const validValue = ScriptingLanguage.batchfile;
|
||||
const getter = () => undefined;
|
||||
const sut = new ScriptingLanguageConcrete();
|
||||
// act
|
||||
const act = (language: ScriptingLanguage) => sut.registerGetter(language, getter);
|
||||
// assert
|
||||
new EnumRangeTestRunner(act)
|
||||
.testOutOfRangeThrows()
|
||||
.testUndefinedValueThrows()
|
||||
.testValidValueDoesNotThrow(validValue);
|
||||
});
|
||||
describe('create', () => {
|
||||
const sut = new ScriptingLanguageConcrete();
|
||||
sut.registerGetter(ScriptingLanguage.batchfile, () => undefined);
|
||||
const runner = new ScriptingLanguageFactoryTestRunner();
|
||||
runner.testCreateMethod(sut);
|
||||
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);
|
||||
});
|
||||
it('throw when language is already registered', () => {
|
||||
// arrange
|
||||
const language = ScriptingLanguage.batchfile;
|
||||
const expectedError = `${ScriptingLanguage[language]} is already registered`;
|
||||
const getter = () => undefined;
|
||||
const sut = new ScriptingLanguageConcrete();
|
||||
// act
|
||||
sut.registerGetter(language, getter);
|
||||
const reRegister = () => sut.registerGetter(language, getter);
|
||||
// assert
|
||||
expect(reRegister).to.throw(expectedError);
|
||||
});
|
||||
});
|
||||
describe('create', () => {
|
||||
const sut = new ScriptingLanguageConcrete();
|
||||
sut.registerGetter(ScriptingLanguage.batchfile, () => undefined);
|
||||
const runner = new ScriptingLanguageFactoryTestRunner();
|
||||
runner.testCreateMethod(sut);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -5,45 +5,48 @@ import { ScriptingLanguage } from '@/domain/ScriptingLanguage';
|
||||
import { EnumRangeTestRunner } from '@tests/unit/application/Common/EnumRangeTestRunner';
|
||||
|
||||
export class ScriptingLanguageFactoryTestRunner<T> {
|
||||
private expectedTypes = new Map<ScriptingLanguage, T>();
|
||||
public expect(language: ScriptingLanguage, resultType: T) {
|
||||
this.expectedTypes.set(language, resultType);
|
||||
return this;
|
||||
}
|
||||
public testCreateMethod(sut: IScriptingLanguageFactory<T>) {
|
||||
if (!sut) { throw new Error('undefined sut'); }
|
||||
testLanguageValidation(sut);
|
||||
testExpectedInstanceTypes(sut, this.expectedTypes);
|
||||
}
|
||||
private expectedTypes = new Map<ScriptingLanguage, T>();
|
||||
|
||||
public expect(language: ScriptingLanguage, resultType: T) {
|
||||
this.expectedTypes.set(language, resultType);
|
||||
return this;
|
||||
}
|
||||
|
||||
public testCreateMethod(sut: IScriptingLanguageFactory<T>) {
|
||||
if (!sut) { throw new Error('undefined sut'); }
|
||||
testLanguageValidation(sut);
|
||||
testExpectedInstanceTypes(sut, this.expectedTypes);
|
||||
}
|
||||
}
|
||||
|
||||
function testExpectedInstanceTypes<T>(
|
||||
sut: IScriptingLanguageFactory<T>,
|
||||
expectedTypes: Map<ScriptingLanguage, T>) {
|
||||
describe('create returns expected instances', () => {
|
||||
// arrange
|
||||
for (const language of Array.from(expectedTypes.keys())) {
|
||||
it(ScriptingLanguage[language], () => {
|
||||
// act
|
||||
const expected = expectedTypes.get(language);
|
||||
const result = sut.create(language);
|
||||
// assert
|
||||
expect(result).to.be.instanceOf(expected, `Actual was: ${result.constructor.name}`);
|
||||
});
|
||||
}
|
||||
});
|
||||
sut: IScriptingLanguageFactory<T>,
|
||||
expectedTypes: Map<ScriptingLanguage, T>,
|
||||
) {
|
||||
describe('create returns expected instances', () => {
|
||||
// arrange
|
||||
for (const language of Array.from(expectedTypes.keys())) {
|
||||
it(ScriptingLanguage[language], () => {
|
||||
// act
|
||||
const expected = expectedTypes.get(language);
|
||||
const result = sut.create(language);
|
||||
// assert
|
||||
expect(result).to.be.instanceOf(expected, `Actual was: ${result.constructor.name}`);
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function testLanguageValidation<T>(sut: IScriptingLanguageFactory<T>) {
|
||||
describe('validates language', () => {
|
||||
// arrange
|
||||
const validValue = ScriptingLanguage.batchfile;
|
||||
// act
|
||||
const act = (value: ScriptingLanguage) => sut.create(value);
|
||||
// assert
|
||||
new EnumRangeTestRunner(act)
|
||||
.testOutOfRangeThrows()
|
||||
.testUndefinedValueThrows()
|
||||
.testValidValueDoesNotThrow(validValue);
|
||||
});
|
||||
describe('validates language', () => {
|
||||
// arrange
|
||||
const validValue = ScriptingLanguage.batchfile;
|
||||
// act
|
||||
const act = (value: ScriptingLanguage) => sut.create(value);
|
||||
// assert
|
||||
new EnumRangeTestRunner(act)
|
||||
.testOutOfRangeThrows()
|
||||
.testUndefinedValueThrows()
|
||||
.testValidValueDoesNotThrow(validValue);
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user