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:
undergroundwires
2022-01-02 18:20:14 +01:00
parent 96265b75de
commit 5b1fbe1e2f
341 changed files with 16126 additions and 15101 deletions

View File

@@ -7,181 +7,181 @@ import { ExpressionParserStub } from '@tests/unit/stubs/ExpressionParserStub';
import { FunctionCallArgumentCollectionStub } from '@tests/unit/stubs/FunctionCallArgumentCollectionStub';
describe('ExpressionsCompiler', () => {
describe('compileExpressions', () => {
describe('returns code when it is empty or undefined', () => {
// arrange
const testCases = [{
name: 'empty',
value: '',
}, {
name: 'undefined',
value: undefined,
},
];
for (const test of testCases) {
it(`given ${test.name}`, () => {
const expected = test.value;
const sut = new SystemUnderTest();
const args = new FunctionCallArgumentCollectionStub();
// act
const value = sut.compileExpressions(test.value, args);
// assert
expect(value).to.equal(expected);
});
}
});
describe('combines expressions as expected', () => {
// arrange
const code = 'part1 {{ a }} part2 {{ b }} part3';
const testCases = [
{
name: 'with ordered expressions',
expressions: [
new ExpressionStub().withPosition(6, 13).withEvaluatedResult('a'),
new ExpressionStub().withPosition(20, 27).withEvaluatedResult('b'),
],
expected: 'part1 a part2 b part3',
},
{
name: 'unordered expressions',
expressions: [
new ExpressionStub().withPosition(20, 27).withEvaluatedResult('b'),
new ExpressionStub().withPosition(6, 13).withEvaluatedResult('a'),
],
expected: 'part1 a part2 b part3',
},
{
name: 'with an optional expected argument that is not provided',
expressions: [
new ExpressionStub().withPosition(6, 13).withEvaluatedResult('a')
.withParameterNames(['optionalParameter'], true),
new ExpressionStub().withPosition(20, 27).withEvaluatedResult('b')
.withParameterNames(['optionalParameterTwo'], true),
],
expected: 'part1 a part2 b part3',
},
{
name: 'with no expressions',
expressions: [],
expected: code,
},
];
for (const testCase of testCases) {
it(testCase.name, () => {
const expressionParserMock = new ExpressionParserStub()
.withResult(testCase.expressions);
const args = new FunctionCallArgumentCollectionStub();
const sut = new SystemUnderTest(expressionParserMock);
// act
const actual = sut.compileExpressions(code, args);
// assert
expect(actual).to.equal(testCase.expected);
});
}
});
describe('arguments', () => {
it('passes arguments to expressions as expected', () => {
// arrange
const expected = new FunctionCallArgumentCollectionStub()
.withArgument('test-arg', 'test-value');
const code = 'non-important';
const expressions = [
new ExpressionStub(),
new ExpressionStub(),
];
const expressionParserMock = new ExpressionParserStub()
.withResult(expressions);
const sut = new SystemUnderTest(expressionParserMock);
// act
sut.compileExpressions(code, expected);
// assert
expect(expressions[0].callHistory).to.have.lengthOf(1);
expect(expressions[0].callHistory[0].args).to.equal(expected);
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 when expected argument is not provided but used in code', () => {
// arrange
const testCases = [
{
name: 'empty parameters',
expressions: [
new ExpressionStub().withParameterNames(['parameter'], false),
],
args: new FunctionCallArgumentCollectionStub(),
expectedError: 'parameter value(s) not provided for: "parameter" but used in code',
},
{
name: 'unnecessary parameter is provided',
expressions: [
new ExpressionStub().withParameterNames(['parameter'], false),
],
args: new FunctionCallArgumentCollectionStub()
.withArgument('unnecessaryParameter', 'unnecessaryValue'),
expectedError: 'parameter value(s) not provided for: "parameter" but used in code',
},
{
name: 'multiple values are not provided',
expressions: [
new ExpressionStub().withParameterNames(['parameter1'], false),
new ExpressionStub().withParameterNames(['parameter2', 'parameter3'], false),
],
args: new FunctionCallArgumentCollectionStub(),
expectedError: 'parameter value(s) not provided for: "parameter1", "parameter2", "parameter3" but used in code',
},
{
name: 'some values are provided',
expressions: [
new ExpressionStub().withParameterNames(['parameter1'], false),
new ExpressionStub().withParameterNames(['parameter2', 'parameter3'], false),
],
args: new FunctionCallArgumentCollectionStub()
.withArgument('parameter2', 'value'),
expectedError: 'parameter value(s) not provided for: "parameter1", "parameter3" but used in code',
},
];
for (const testCase of testCases) {
it(testCase.name, () => {
const code = 'non-important-code';
const expressionParserMock = new ExpressionParserStub()
.withResult(testCase.expressions);
const sut = new SystemUnderTest(expressionParserMock);
// act
const act = () => sut.compileExpressions(code, testCase.args);
// assert
expect(act).to.throw(testCase.expectedError);
});
}
});
it('calls parser with expected code', () => {
// arrange
const expected = 'expected-code';
const expressionParserMock = new ExpressionParserStub();
const sut = new SystemUnderTest(expressionParserMock);
const args = new FunctionCallArgumentCollectionStub();
// act
sut.compileExpressions(expected, args);
// assert
expect(expressionParserMock.callHistory).to.have.lengthOf(1);
expect(expressionParserMock.callHistory[0]).to.equal(expected);
describe('compileExpressions', () => {
describe('returns code when it is empty or undefined', () => {
// arrange
const testCases = [{
name: 'empty',
value: '',
}, {
name: 'undefined',
value: undefined,
},
];
for (const test of testCases) {
it(`given ${test.name}`, () => {
const expected = test.value;
const sut = new SystemUnderTest();
const args = new FunctionCallArgumentCollectionStub();
// act
const value = sut.compileExpressions(test.value, args);
// assert
expect(value).to.equal(expected);
});
}
});
describe('combines expressions as expected', () => {
// arrange
const code = 'part1 {{ a }} part2 {{ b }} part3';
const testCases = [
{
name: 'with ordered expressions',
expressions: [
new ExpressionStub().withPosition(6, 13).withEvaluatedResult('a'),
new ExpressionStub().withPosition(20, 27).withEvaluatedResult('b'),
],
expected: 'part1 a part2 b part3',
},
{
name: 'unordered expressions',
expressions: [
new ExpressionStub().withPosition(20, 27).withEvaluatedResult('b'),
new ExpressionStub().withPosition(6, 13).withEvaluatedResult('a'),
],
expected: 'part1 a part2 b part3',
},
{
name: 'with an optional expected argument that is not provided',
expressions: [
new ExpressionStub().withPosition(6, 13).withEvaluatedResult('a')
.withParameterNames(['optionalParameter'], true),
new ExpressionStub().withPosition(20, 27).withEvaluatedResult('b')
.withParameterNames(['optionalParameterTwo'], true),
],
expected: 'part1 a part2 b part3',
},
{
name: 'with no expressions',
expressions: [],
expected: code,
},
];
for (const testCase of testCases) {
it(testCase.name, () => {
const expressionParserMock = new ExpressionParserStub()
.withResult(testCase.expressions);
const args = new FunctionCallArgumentCollectionStub();
const sut = new SystemUnderTest(expressionParserMock);
// act
const actual = sut.compileExpressions(code, args);
// assert
expect(actual).to.equal(testCase.expected);
});
}
});
describe('arguments', () => {
it('passes arguments to expressions as expected', () => {
// arrange
const expected = new FunctionCallArgumentCollectionStub()
.withArgument('test-arg', 'test-value');
const code = 'non-important';
const expressions = [
new ExpressionStub(),
new ExpressionStub(),
];
const expressionParserMock = new ExpressionParserStub()
.withResult(expressions);
const sut = new SystemUnderTest(expressionParserMock);
// act
sut.compileExpressions(code, expected);
// assert
expect(expressions[0].callHistory).to.have.lengthOf(1);
expect(expressions[0].callHistory[0].args).to.equal(expected);
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 when expected argument is not provided but used in code', () => {
// arrange
const testCases = [
{
name: 'empty parameters',
expressions: [
new ExpressionStub().withParameterNames(['parameter'], false),
],
args: new FunctionCallArgumentCollectionStub(),
expectedError: 'parameter value(s) not provided for: "parameter" but used in code',
},
{
name: 'unnecessary parameter is provided',
expressions: [
new ExpressionStub().withParameterNames(['parameter'], false),
],
args: new FunctionCallArgumentCollectionStub()
.withArgument('unnecessaryParameter', 'unnecessaryValue'),
expectedError: 'parameter value(s) not provided for: "parameter" but used in code',
},
{
name: 'multiple values are not provided',
expressions: [
new ExpressionStub().withParameterNames(['parameter1'], false),
new ExpressionStub().withParameterNames(['parameter2', 'parameter3'], false),
],
args: new FunctionCallArgumentCollectionStub(),
expectedError: 'parameter value(s) not provided for: "parameter1", "parameter2", "parameter3" but used in code',
},
{
name: 'some values are provided',
expressions: [
new ExpressionStub().withParameterNames(['parameter1'], false),
new ExpressionStub().withParameterNames(['parameter2', 'parameter3'], false),
],
args: new FunctionCallArgumentCollectionStub()
.withArgument('parameter2', 'value'),
expectedError: 'parameter value(s) not provided for: "parameter1", "parameter3" but used in code',
},
];
for (const testCase of testCases) {
it(testCase.name, () => {
const code = 'non-important-code';
const expressionParserMock = new ExpressionParserStub()
.withResult(testCase.expressions);
const sut = new SystemUnderTest(expressionParserMock);
// act
const act = () => sut.compileExpressions(code, testCase.args);
// assert
expect(act).to.throw(testCase.expectedError);
});
}
});
it('calls parser with expected code', () => {
// arrange
const expected = 'expected-code';
const expressionParserMock = new ExpressionParserStub();
const sut = new SystemUnderTest(expressionParserMock);
const args = new FunctionCallArgumentCollectionStub();
// act
sut.compileExpressions(expected, args);
// assert
expect(expressionParserMock.callHistory).to.have.lengthOf(1);
expect(expressionParserMock.callHistory[0]).to.equal(expected);
});
});
});
class SystemUnderTest extends ExpressionsCompiler {
constructor(extractor: IExpressionParser = new ExpressionParserStub()) {
super(extractor);
}
constructor(extractor: IExpressionParser = new ExpressionParserStub()) {
super(extractor);
}
}