askui
Version:
Reliable, automated end-to-end-testing that depends on what is shown on your screen instead of the technology you are running on
146 lines (145 loc) • 7.21 kB
JavaScript
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.CacheManager = void 0;
const ui_control_commands_1 = require("../ui-control-commands");
const input_event_1 = require("../ui-control-commands/input-event");
const base_64_image_1 = require("../../utils/base_64_image/base-64-image");
const cache_entry_1 = require("./cache-entry");
const image_reference_1 = require("./image-reference");
const cache_entry_reference_1 = require("./cache-entry-reference");
const cahe_file_1 = require("./cahe-file");
class CacheManager {
constructor(config) {
var _a;
this.relevantData = {};
this.referenceWidth = 32;
this.referenceHeight = 16;
this.defaultValidationType = 'PixelPerfect';
this.validationType = (_a = config.validationType) !== null && _a !== void 0 ? _a : this.defaultValidationType;
this.cacheFile = new cahe_file_1.CacheFile(config.cacheFilePath);
}
loadFromFile() {
this.cacheFile.loadFromFile();
this.relevantData = this.cacheFile.getDataForValidationType(this.validationType);
}
saveToFile() {
this.cacheFile.saveToFile(this.validationType, this.relevantData);
}
add(key, value) {
if (this.relevantData[key] === undefined) {
this.relevantData[key] = [];
}
this.relevantData[key].push(value);
}
addCacheEntryFromControlCommand(instruction, controlCommand, customElements, image) {
return __awaiter(this, void 0, void 0, function* () {
let imageReference;
if (image !== undefined) {
const moveAction = controlCommand.actions.find((action) => action.inputEvent === input_event_1.InputEvent.MOUSE_MOVE);
const x = moveAction === null || moveAction === void 0 ? void 0 : moveAction.position.x;
const y = moveAction === null || moveAction === void 0 ? void 0 : moveAction.position.y;
if (x !== undefined && y !== undefined) {
const xTopLeft = Math.max(0, (x - this.referenceWidth / 2));
const yTopLeft = Math.max(0, (y - this.referenceHeight / 2));
const base64Image = yield base_64_image_1.Base64Image.fromString(image);
const croppedImage = yield base64Image.cropRegion(xTopLeft, yTopLeft, this.referenceWidth, this.referenceHeight);
imageReference = new image_reference_1.ImageReference(croppedImage.toString(true), this.referenceWidth, this.referenceHeight, xTopLeft, yTopLeft);
}
}
const cacheEntry = new cache_entry_1.CacheEntry(image === undefined, controlCommand, new cache_entry_reference_1.CacheEntryReference(imageReference));
const cacheKey = this.encodeKey(instruction, customElements);
this.add(cacheKey, cacheEntry);
});
}
isImageRequired(instruction, customElements) {
const cacheKey = this.encodeKey(instruction, customElements);
const cacheEntries = this.getCacheEntriesByKey(cacheKey);
if (cacheEntries.length === 0) {
return undefined;
}
return cacheEntries.find((entry) => entry.alwaysValid === false) !== undefined;
}
getCachedControlCommand(instruction, customElements, image) {
return __awaiter(this, void 0, void 0, function* () {
const cacheKey = this.encodeKey(instruction, customElements);
const cacheEntry = yield this.getValidCacheEntry(cacheKey, image);
if (cacheEntry === undefined || cacheEntry.controlCommand.code !== ui_control_commands_1.ControlCommandCode.OK) {
return undefined;
}
return cacheEntry.controlCommand;
});
}
// eslint-disable-next-line class-methods-use-this
encodeKey(instruction, customElements) {
let key = instruction;
if (customElements.length > 0) {
key += ` with CustomElements:${customElements.map((element, index) => `${index}:${element.asString()}`).join(',')}`;
}
return key;
}
getCacheEntriesByKey(key) {
if (this.relevantData[key] === undefined) {
return [];
}
const entries = this.relevantData[key];
if (entries === undefined) {
return [];
}
return entries;
}
getValidCacheEntry(key, screenshot) {
return __awaiter(this, void 0, void 0, function* () {
const cacheEntries = this.getCacheEntriesByKey(key);
if (cacheEntries.length === 0) {
return undefined;
}
if (this.validationType === 'PixelPerfect') {
/* eslint-disable no-restricted-syntax, no-await-in-loop */
for (const cacheEntry of cacheEntries) {
if (cacheEntry.alwaysValid) {
return cacheEntry;
}
const isValid = yield this.validateAccordingToPixelPerfect(cacheEntry, screenshot);
if (isValid) {
/* eslint-enable no-restricted-syntax, no-await-in-loop */
return cacheEntry;
}
}
/* eslint-enable no-restricted-syntax, no-await-in-loop */
}
return undefined;
});
}
// eslint-disable-next-line class-methods-use-this
validateAccordingToPixelPerfect(cacheEntry, screenshot) {
return __awaiter(this, void 0, void 0, function* () {
var _a;
if (screenshot === undefined) {
return false;
}
if (((_a = cacheEntry.reference) === null || _a === void 0 ? void 0 : _a.image) === undefined) {
return false;
}
try {
const referenceImage = yield base_64_image_1.Base64Image.fromString(screenshot);
const croppedScreenshot = yield referenceImage.cropRegion(cacheEntry.reference.image.xTopLeft, cacheEntry.reference.image.yTopLeft, cacheEntry.reference.image.width, cacheEntry.reference.image.height);
const croppedReferenceImageString = croppedScreenshot.toString(true);
const isValid = croppedReferenceImageString === cacheEntry.reference.image.base64Image;
return isValid;
}
catch (error) {
return false;
}
});
}
}
exports.CacheManager = CacheManager;