Sets up the core infrastructure for Playwright-based automated testing, including: - Docker support for consistent environments - Azure Pipelines configuration for CI/CD - Page Object Model structure for maintainable tests - Test data, validation, and rule engine implementation - Test configuration for alerts and other scenarios
111 lines
No EOL
4.4 KiB
TypeScript
111 lines
No EOL
4.4 KiB
TypeScript
import { ValidationResult } from "@business-logic/types/RuleEngine";
|
|
import EnumUtils from "./EnumUtils";
|
|
|
|
export type ExtractName<T> = { [K in keyof T]: () => K; };
|
|
|
|
type GetValueOptions = {
|
|
isRequired: boolean;
|
|
};
|
|
|
|
function isNullOrWhiteSpace(input: unknown): boolean {
|
|
if (typeof input !== "string")
|
|
return input == null;
|
|
return input.trim().length === 0;
|
|
}
|
|
|
|
// Matches: '() => _Enums.*****', e.g.: '() => _Enums.ModificationTypes'
|
|
// Matches: '() => *****', e.g.: '() => ModificationTypes'
|
|
// Returns: EnumName, e.g.: 'ModificationTypes'
|
|
function getEnumName(propertySelector: () => object): string {
|
|
const functionString = propertySelector.toString();
|
|
const match = functionString.match(/\(\s*\)\s*=>\s*(?:_?[A-Z]\w*\.)?(\w+)(?::)?/);
|
|
return match ? match[1] : "Unknown";
|
|
}
|
|
|
|
// Matches: 'x => x.*****', e.g.: 'x => x.name', 'x => x.tags'
|
|
// Returns: PropertyName, e.g.: 'name', 'tags'
|
|
function getNameof<T>(propertySelector: (obj: T) => any): string {
|
|
const propertyString = propertySelector.toString();
|
|
const match = propertyString.match(/(?:=>|return)\s*([\w\s.]+)/);
|
|
|
|
if (match && match[1]) {
|
|
const parts = match[1].split('.');
|
|
return parts[parts.length - 1].trim();
|
|
}
|
|
|
|
throw new Error(`Invalid property selector: ${propertyString}`);
|
|
}
|
|
|
|
function getValueOrNull<T>(json: any, propertySelector: (obj: T) => any): any | null {
|
|
if (json == null)
|
|
return null;
|
|
|
|
const property = getNameof(propertySelector);
|
|
|
|
if (json.hasOwnProperty(property))
|
|
return json[property];
|
|
|
|
return null;
|
|
}
|
|
|
|
function getValue<T>(json: any, typeName: string, validationResults: ValidationResult[], options: GetValueOptions, propertySelector: (obj: T) => any): any | null {
|
|
const retval = getValueOrNull(json, propertySelector);
|
|
|
|
if (retval == null)
|
|
validationResults.push(options.isRequired ? ValidationResult.FromFailure(`Value for ${typeName}.${getNameof(propertySelector)} is null but is required!`) : ValidationResult.FromSuccess(retval, `Value for ${typeName}.${getNameof(propertySelector)} is null but is NOT required.`));
|
|
else {
|
|
if (isNullOrWhiteSpace(retval))
|
|
validationResults.push(ValidationResult.FromFailure(`Value for ${typeName}.${getNameof(propertySelector)} is empty!`));
|
|
else
|
|
validationResults.push(ValidationResult.FromSuccess(retval, `Value for ${typeName}.${getNameof(propertySelector)} is valid.`));
|
|
}
|
|
|
|
return retval;
|
|
}
|
|
|
|
function hasProperty<T>(json: any, typeName: string, validationResults: ValidationResult[], options: GetValueOptions, propertySelector: (obj: ExtractName<T>) => () => keyof T): boolean {
|
|
const retval = json.hasOwnProperty(getNameof(propertySelector));
|
|
|
|
if (retval)
|
|
validationResults.push(ValidationResult.FromSuccess(retval, `Value for ${typeName}.${getNameof(propertySelector)} is valid.`));
|
|
else
|
|
validationResults.push(options.isRequired ? ValidationResult.FromSuccess(retval, `Value for ${typeName}.${getNameof(propertySelector)} is not defined but is required!`) : ValidationResult.FromFailure(`Value for ${typeName}.${getNameof(propertySelector)} is not defined but is NOT required!`));
|
|
|
|
return retval;
|
|
}
|
|
|
|
function getEnumValueOrNull<T>(json: any, enumType: object, propertySelector: (obj: T) => any): any | null {
|
|
if (json == null)
|
|
return null;
|
|
|
|
const property = getNameof(propertySelector);
|
|
const retval = EnumUtils.validateEnumProperty(json, property, enumType);
|
|
|
|
if (retval != null)
|
|
return retval;
|
|
else if (Object.values(enumType).includes(json[property]))
|
|
return json[property];
|
|
|
|
return null;
|
|
}
|
|
|
|
function getEnumValue<T>(json: any, typeName: string, validationResults: ValidationResult[], enumType: object, enumTypeInstance: () => object, options: GetValueOptions, propertySelector: (obj: T) => any): any | null {
|
|
const retval = getEnumValueOrNull(json, enumType, propertySelector);
|
|
|
|
if (retval == null)
|
|
validationResults.push(options.isRequired ? ValidationResult.FromFailure(`Value for ${typeName}.${getNameof(propertySelector)} [${getEnumName(enumTypeInstance)}] is null but is required!`) : ValidationResult.FromSuccess(retval, `Value for ${typeName}.${getNameof(propertySelector)} [${getEnumName(enumTypeInstance)}] is null but is NOT required.`));
|
|
else
|
|
validationResults.push(ValidationResult.FromSuccess(retval, `Value for ${typeName}.${getNameof(propertySelector)} is valid.`));
|
|
|
|
return retval;
|
|
}
|
|
|
|
export { getEnumName, getEnumValueOrNull, getNameof, getValueOrNull };
|
|
|
|
const PropertyUtils = {
|
|
hasProperty,
|
|
getValue,
|
|
getEnumValue
|
|
};
|
|
|
|
export default PropertyUtils; |