Files
privacy.sexy/tests/unit/application/Parser/NodeValidation/NodeValidatorTestRunner.ts
undergroundwires 949fac1a7c Refactor to enforce strictNullChecks
This commit applies `strictNullChecks` to the entire codebase to improve
maintainability and type safety. Key changes include:

- Remove some explicit null-checks where unnecessary.
- Add necessary null-checks.
- Refactor static factory functions for a more functional approach.
- Improve some test names and contexts for better debugging.
- Add unit tests for any additional logic introduced.
- Refactor `createPositionFromRegexFullMatch` to its own function as the
  logic is reused.
- Prefer `find` prefix on functions that may return `undefined` and
  `get` prefix for those that always return a value.
2023-11-12 22:54:00 +01:00

88 lines
2.6 KiB
TypeScript

import { describe, it } from 'vitest';
import { NodeDataError, INodeDataErrorContext } from '@/application/Parser/NodeValidation/NodeDataError';
import { NodeData } from '@/application/Parser/NodeValidation/NodeData';
import { getAbsentObjectTestCases, getAbsentStringTestCases, itEachAbsentTestCase } from '@tests/unit/shared/TestCases/AbsentTests';
import { expectDeepThrowsError } from '@tests/shared/Assertions/ExpectDeepThrowsError';
export interface ITestScenario {
readonly act: () => void;
readonly expectedContext: INodeDataErrorContext;
}
export class NodeValidationTestRunner {
public testInvalidNodeName(
testBuildPredicate: (invalidName: string) => ITestScenario,
) {
describe('throws given invalid names', () => {
// arrange
const testCases = [
...getAbsentStringTestCases().map((testCase) => ({
testName: `missing name (${testCase.valueName})`,
nameValue: testCase.absentValue,
expectedMessage: 'missing name',
})),
{
testName: 'invalid type',
nameValue: 33,
expectedMessage: 'Name (33) is not a string but number.',
},
];
for (const testCase of testCases) {
it(`given "${testCase.testName}"`, () => {
const test = testBuildPredicate(testCase.nameValue as never);
expectThrowsNodeError(test, testCase.expectedMessage);
});
}
});
return this;
}
public testMissingNodeData(
testBuildPredicate: (missingNode: NodeData) => ITestScenario,
) {
describe('throws given missing node data', () => {
itEachAbsentTestCase([
...getAbsentObjectTestCases(),
{
valueName: 'empty object',
absentValue: {},
},
], (absentValue) => {
// arrange
const expectedError = 'missing node data';
// act
const test = testBuildPredicate(absentValue as NodeData);
// assert
expectThrowsNodeError(test, expectedError);
});
});
return this;
}
public runThrowingCase(
testCase: {
readonly name: string,
readonly scenario: ITestScenario,
readonly expectedMessage: string
},
) {
it(testCase.name, () => {
expectThrowsNodeError(testCase.scenario, testCase.expectedMessage);
});
return this;
}
}
export function expectThrowsNodeError(
test: ITestScenario,
expectedMessage: string,
) {
// arrange
const expected = new NodeDataError(expectedMessage, test.expectedContext);
// act
const act = () => test.act();
// assert
expectDeepThrowsError(act, expected);
return this;
}