Files
privacy.sexy/tests/unit/application/Parser/ScriptingDefinition/ScriptingDefinitionParser.spec.ts
undergroundwires dc03bff324 Add schema validation for collection files #369
This commit improves collection file editing and error detection
directly in the IDE. It adds YAML schema, IDE configuration and
automatic tests to validate it.

- Introduce a YAML schema for collection file.
- Use `yaml-language-server` for enhanced YAML support in VSCode.
- Add telemetry disabling in `configure_vscode.py` to respect user
  privacy.
- Add automated checks to validate YAML file structure against the
  schema.
- Remove unused properties and do not allow them in compiler.
2024-06-17 14:01:07 +02:00

147 lines
5.3 KiB
TypeScript

import { describe, it, expect } from 'vitest';
import { ScriptingLanguage } from '@/domain/ScriptingLanguage';
import type { EnumParser } from '@/application/Common/Enum';
import type { ICodeSubstituter } from '@/application/Parser/ScriptingDefinition/ICodeSubstituter';
import type { IScriptingDefinition } from '@/domain/IScriptingDefinition';
import { ProjectDetailsStub } from '@tests/unit/shared/Stubs/ProjectDetailsStub';
import { EnumParserStub } from '@tests/unit/shared/Stubs/EnumParserStub';
import { ScriptingDefinitionDataStub } from '@tests/unit/shared/Stubs/ScriptingDefinitionDataStub';
import { CodeSubstituterStub } from '@tests/unit/shared/Stubs/CodeSubstituterStub';
import { parseScriptingDefinition } from '@/application/Parser/ScriptingDefinition/ScriptingDefinitionParser';
import type { ObjectAssertion, TypeValidator } from '@/application/Parser/Common/TypeValidator';
import { TypeValidatorStub } from '@tests/unit/shared/Stubs/TypeValidatorStub';
import type { ScriptingDefinitionData } from '@/application/collections/';
import type { ProjectDetails } from '@/domain/Project/ProjectDetails';
describe('ScriptingDefinitionParser', () => {
describe('parseScriptingDefinition', () => {
it('validates data', () => {
// arrange
const data = new ScriptingDefinitionDataStub();
const expectedAssertion: ObjectAssertion<ScriptingDefinitionData> = {
value: data,
valueName: 'scripting definition',
allowedProperties: ['language', 'startCode', 'endCode'],
};
const validatorStub = new TypeValidatorStub();
const context = new TestContext()
.withTypeValidator(validatorStub)
.withData(data);
// act
context.parseScriptingDefinition();
// assert
validatorStub.assertObject(expectedAssertion);
});
describe('language', () => {
it('parses as expected', () => {
// arrange
const expectedLanguage = ScriptingLanguage.batchfile;
const languageText = 'batchfile';
const expectedName = 'language';
const definition = new ScriptingDefinitionDataStub()
.withLanguage(languageText);
const parserMock = new EnumParserStub<ScriptingLanguage>()
.setup(expectedName, languageText, expectedLanguage);
const context = new TestContext()
.withParser(parserMock)
.withData(definition);
// act
const actual = context.parseScriptingDefinition();
// assert
expect(actual.language).to.equal(expectedLanguage);
});
});
describe('substitutes code as expected', () => {
// arrange
const code = 'hello';
const expected = 'substituted';
const testScenarios: readonly {
readonly description: string;
getActualValue(result: IScriptingDefinition): string;
readonly data: ScriptingDefinitionData;
}[] = [
{
description: 'startCode',
getActualValue: (result: IScriptingDefinition) => result.startCode,
data: new ScriptingDefinitionDataStub()
.withStartCode(code),
},
{
description: 'endCode',
getActualValue: (result: IScriptingDefinition) => result.endCode,
data: new ScriptingDefinitionDataStub()
.withEndCode(code),
},
];
testScenarios.forEach(({
description, data, getActualValue,
}) => {
it(description, () => {
const projectDetails = new ProjectDetailsStub();
const substituterMock = new CodeSubstituterStub()
.setup(code, projectDetails, expected);
const context = new TestContext()
.withData(data)
.withProjectDetails(projectDetails)
.withSubstituter(substituterMock);
// act
const definition = context.parseScriptingDefinition();
// assert
const actual = getActualValue(definition);
expect(actual).to.equal(expected);
});
});
});
});
});
class TestContext {
private languageParser: EnumParser<ScriptingLanguage> = new EnumParserStub<ScriptingLanguage>()
.setupDefaultValue(ScriptingLanguage.shellscript);
private codeSubstituter: ICodeSubstituter = new CodeSubstituterStub();
private validator: TypeValidator = new TypeValidatorStub();
private data: ScriptingDefinitionData = new ScriptingDefinitionDataStub();
private projectDetails: ProjectDetails = new ProjectDetailsStub();
public withData(data: ScriptingDefinitionData): this {
this.data = data;
return this;
}
public withProjectDetails(projectDetails: ProjectDetails): this {
this.projectDetails = projectDetails;
return this;
}
public withParser(parser: EnumParser<ScriptingLanguage>): this {
this.languageParser = parser;
return this;
}
public withSubstituter(substituter: ICodeSubstituter): this {
this.codeSubstituter = substituter;
return this;
}
public withTypeValidator(validator: TypeValidator): this {
this.validator = validator;
return this;
}
public parseScriptingDefinition() {
return parseScriptingDefinition(
this.data,
this.projectDetails,
{
languageParser: this.languageParser,
codeSubstituter: this.codeSubstituter,
validator: this.validator,
},
);
}
}