"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.getImagesInfoByStateName = exports.getExpectedCacheKey = exports.saveErrorDetails = exports.formatTestResult = exports.mapPlugins = exports.forEachPlugin = exports.isUnexpectedPlugin = exports.getPluginMiddleware = exports.getPluginClientScriptPath = exports.runCustomGuiAction = exports.initializeCustomGui = exports.getDataForStaticFile = exports.getConfigForStaticFile = exports.copyToReportDir = exports.writeDatabaseUrlsFile = exports.isDbUrl = exports.isJsonUrl = exports.urlPathNameEndsWith = exports.copyPlugin = exports.copyPlugins = exports.saveStaticFilesToReportDir = exports.shouldUpdateAttempt = exports.prepareCommonJSData = exports.logError = exports.logPathToHtmlReport = exports.fileExists = exports.makeDirFor = exports.deleteFile = exports.copyFileAsync = exports.createHash = exports.getTempPath = exports.createPath = exports.getDiffAbsolutePath = exports.getCurrentAbsolutePath = exports.getReferenceAbsolutePath = exports.getDiffPath = exports.getCurrentPath = exports.getReferencePath = void 0;
const crypto_1 = __importDefault(require("crypto"));
const path_1 = __importDefault(require("path"));
const url_1 = __importDefault(require("url"));
const chalk_1 = __importDefault(require("chalk"));
const fs_extra_1 = __importDefault(require("fs-extra"));
const lodash_1 = __importDefault(require("lodash"));
const tmp_1 = __importDefault(require("tmp"));
const common_utils_1 = require("./common-utils");
const constants_1 = require("./constants");
const testplane_1 = require("./test-adapter/testplane");
const DATA_FILE_NAME = 'data.js';
const getReferencePath = (options, stateName) => createPath({ kind: 'ref', stateName, ...lodash_1.default.pick(options, ['attempt', 'browserId', 'imageDir']) });
exports.getReferencePath = getReferencePath;
const getCurrentPath = (options, stateName) => createPath({ kind: 'current', stateName, ...lodash_1.default.pick(options, ['attempt', 'browserId', 'imageDir']) });
exports.getCurrentPath = getCurrentPath;
const getDiffPath = (options, stateName) => createPath({ kind: 'diff', stateName, ...lodash_1.default.pick(options, ['attempt', 'browserId', 'imageDir']) });
exports.getDiffPath = getDiffPath;
const getReferenceAbsolutePath = (testResult, reportDir, stateName) => {
    const referenceImagePath = (0, exports.getReferencePath)({ attempt: testResult.attempt, imageDir: testResult.imageDir, browserId: testResult.browserId }, stateName);
    return path_1.default.resolve(reportDir, referenceImagePath);
};
exports.getReferenceAbsolutePath = getReferenceAbsolutePath;
const getCurrentAbsolutePath = (testResult, reportDir, stateName) => {
    const currentImagePath = (0, exports.getCurrentPath)({ attempt: testResult.attempt, imageDir: testResult.imageDir, browserId: testResult.browserId }, stateName);
    return path_1.default.resolve(reportDir, currentImagePath);
};
exports.getCurrentAbsolutePath = getCurrentAbsolutePath;
const getDiffAbsolutePath = (testResult, reportDir, stateName) => {
    const diffImagePath = (0, exports.getDiffPath)({ attempt: testResult.attempt, imageDir: testResult.imageDir, browserId: testResult.browserId }, stateName);
    return path_1.default.resolve(reportDir, diffImagePath);
};
exports.getDiffAbsolutePath = getDiffAbsolutePath;
function createPath({ attempt: attemptInput, imageDir: imageDirInput, browserId, kind, stateName }) {
    const attempt = attemptInput || 0;
    const imageDir = lodash_1.default.compact([constants_1.IMAGES_PATH, imageDirInput, stateName]);
    const components = imageDir.concat(`${browserId}~${kind}_${attempt}.png`);
    return path_1.default.join(...components);
}
exports.createPath = createPath;
const getTempPath = (destPath) => path_1.default.resolve(tmp_1.default.tmpdir, destPath);
exports.getTempPath = getTempPath;
function createHash(buffer) {
    return crypto_1.default
        .createHash('sha1')
        .update(buffer)
        .digest('base64');
}
exports.createHash = createHash;
function copyFileAsync(srcPath, destPath, { reportDir = '', overwrite = true } = {}) {
    const resolvedDestPath = path_1.default.resolve(reportDir, destPath);
    return makeDirFor(resolvedDestPath).then(() => fs_extra_1.default.copy(srcPath, resolvedDestPath, { overwrite }));
}
exports.copyFileAsync = copyFileAsync;
function deleteFile(filePath) {
    return fs_extra_1.default.remove(filePath);
}
exports.deleteFile = deleteFile;
function makeDirFor(destPath) {
    return fs_extra_1.default.mkdirs(path_1.default.dirname(destPath));
}
exports.makeDirFor = makeDirFor;
function fileExists(path) {
    return fs_extra_1.default.existsSync(path);
}
exports.fileExists = fileExists;
function logPathToHtmlReport(pluginConfig) {
    const reportPath = `file://${path_1.default.resolve(pluginConfig.path, 'index.html')}`;
    common_utils_1.logger.log(`Your HTML report is here: ${chalk_1.default.yellow(reportPath)}`);
    common_utils_1.logger.log(`To open it use: ${chalk_1.default.yellow('npx hermione gui')} or ${chalk_1.default.yellow(`npx http-server ${pluginConfig.path}`)}`);
}
exports.logPathToHtmlReport = logPathToHtmlReport;
function logError(e) {
    common_utils_1.logger.error(`Html-reporter runtime error: ${e.stack}`);
}
exports.logError = logError;
function prepareCommonJSData(data) {
    const stringifiedData = JSON.stringify(data, (_key, val) => {
        return typeof val === 'function' ? val.toString() : val;
    });
    return [
        `var data = ${stringifiedData};`,
        'try { module.exports = data; } catch(e) {}'
    ].join('\n');
}
exports.prepareCommonJSData = prepareCommonJSData;
function shouldUpdateAttempt(status) {
    return ![constants_1.SKIPPED, constants_1.UPDATED, constants_1.RUNNING, constants_1.IDLE].includes(status);
}
exports.shouldUpdateAttempt = shouldUpdateAttempt;
async function saveStaticFilesToReportDir(htmlReporter, pluginConfig, destPath) {
    const staticFolder = path_1.default.resolve(__dirname, './static');
    await fs_extra_1.default.ensureDir(destPath);
    await Promise.all([
        fs_extra_1.default.writeFile(path_1.default.resolve(destPath, DATA_FILE_NAME), prepareCommonJSData(getDataForStaticFile(htmlReporter, pluginConfig)), 'utf8'),
        copyToReportDir(destPath, ['report.min.js', 'report.min.css'], staticFolder),
        fs_extra_1.default.copy(path_1.default.resolve(staticFolder, 'index.html'), path_1.default.resolve(destPath, 'index.html')),
        fs_extra_1.default.copy(path_1.default.resolve(staticFolder, 'icons'), path_1.default.resolve(destPath, 'icons')),
        fs_extra_1.default.copy(require.resolve('@gemini-testing/sql.js/dist/sql-wasm.js'), path_1.default.resolve(destPath, 'sql-wasm.js')),
        fs_extra_1.default.copy(require.resolve('@gemini-testing/sql.js/dist/sql-wasm.wasm'), path_1.default.resolve(destPath, 'sql-wasm.wasm')),
        copyPlugins(pluginConfig, destPath)
    ]);
}
exports.saveStaticFilesToReportDir = saveStaticFilesToReportDir;
async function copyPlugins({ plugins, pluginsEnabled }, destPath) {
    if (!pluginsEnabled || !plugins?.length) {
        return;
    }
    try {
        const pluginsPath = path_1.default.resolve(destPath, 'plugins');
        await fs_extra_1.default.ensureDir(pluginsPath);
        await Promise.all(mapPlugins(plugins, pluginName => copyPlugin(pluginName, pluginsPath)));
    }
    catch (e) { // eslint-disable-line @typescript-eslint/no-explicit-any
        logError(e);
    }
}
exports.copyPlugins = copyPlugins;
async function copyPlugin(pluginName, pluginsPath) {
    const pluginPath = getPluginClientScriptPath(pluginName);
    if (!pluginPath) {
        return;
    }
    const destPluginPath = path_1.default.resolve(pluginsPath, pluginName, 'plugin.js');
    await fs_extra_1.default.ensureDir(path_1.default.dirname(destPluginPath));
    await fs_extra_1.default.copy(pluginPath, destPluginPath);
}
exports.copyPlugin = copyPlugin;
function urlPathNameEndsWith(currentUrl, searchString) {
    try {
        return url_1.default.parse(currentUrl).pathname?.endsWith(searchString) || false;
    }
    catch (e) {
        return false;
    }
}
exports.urlPathNameEndsWith = urlPathNameEndsWith;
function isJsonUrl(url) {
    return urlPathNameEndsWith(url, '.json');
}
exports.isJsonUrl = isJsonUrl;
function isDbUrl(url) {
    return urlPathNameEndsWith(url, '.db');
}
exports.isDbUrl = isDbUrl;
async function writeDatabaseUrlsFile(destPath, srcPaths) {
    const jsonUrls = srcPaths.filter(isJsonUrl);
    const dbUrls = srcPaths.filter(isDbUrl);
    const data = {
        dbUrls,
        jsonUrls
    };
    await fs_extra_1.default.writeJson(path_1.default.resolve(destPath, 'databaseUrls.json'), data);
}
exports.writeDatabaseUrlsFile = writeDatabaseUrlsFile;
function copyToReportDir(destPath, files, sourceDirectory) {
    return Promise.all(files.map(fileName => {
        const from = path_1.default.resolve(sourceDirectory, fileName);
        const to = path_1.default.resolve(destPath, fileName);
        return fs_extra_1.default.copy(from, to);
    }));
}
exports.copyToReportDir = copyToReportDir;
function getConfigForStaticFile(pluginConfig) {
    return lodash_1.default.pick(pluginConfig, [
        'defaultView',
        'diffMode',
        'baseHost',
        'errorPatterns',
        'metaInfoBaseUrls',
        'customScripts',
        'yandexMetrika',
        'pluginsEnabled',
        'plugins'
    ]);
}
exports.getConfigForStaticFile = getConfigForStaticFile;
function getDataForStaticFile(htmlReporter, pluginConfig) {
    return {
        skips: [],
        config: getConfigForStaticFile(pluginConfig),
        apiValues: htmlReporter.values,
        date: new Date().toString()
    };
}
exports.getDataForStaticFile = getDataForStaticFile;
async function initializeCustomGui(testplane, { customGui }) {
    await Promise.all((0, lodash_1.default)(customGui)
        .flatMap(lodash_1.default.identity)
        .map((ctx) => ctx.initialize?.({ testplane, hermione: testplane, ctx }))
        .value());
}
exports.initializeCustomGui = initializeCustomGui;
async function runCustomGuiAction(testplane, { customGui }, payload) {
    const { sectionName, groupIndex, controlIndex } = payload;
    const ctx = customGui[sectionName][groupIndex];
    const control = ctx.controls[controlIndex];
    await ctx.action({ testplane, hermione: testplane, control, ctx });
}
exports.runCustomGuiAction = runCustomGuiAction;
function getPluginClientScriptPath(pluginName) {
    try {
        return require.resolve(`${pluginName}/plugin.js`);
    }
    catch (e) { // eslint-disable-line @typescript-eslint/no-explicit-any
        logError(e);
        return null;
    }
}
exports.getPluginClientScriptPath = getPluginClientScriptPath;
function getPluginMiddleware(pluginName) {
    try {
        return require(`${pluginName}/middleware.js`);
    }
    catch (e) { // eslint-disable-line @typescript-eslint/no-explicit-any
        if (e.code !== 'MODULE_NOT_FOUND') {
            logError(e);
        }
        return null;
    }
}
exports.getPluginMiddleware = getPluginMiddleware;
function isUnexpectedPlugin(plugins, pluginName) {
    for (const { name } of plugins) {
        if (name === pluginName) {
            return false;
        }
    }
    return true;
}
exports.isUnexpectedPlugin = isUnexpectedPlugin;
function forEachPlugin(plugins, callback) {
    const seen = new Set();
    for (const plugin of plugins) {
        if (!seen.has(plugin.name)) {
            seen.add(plugin.name);
            callback(plugin.name);
        }
    }
}
exports.forEachPlugin = forEachPlugin;
function mapPlugins(plugins, callback) {
    const result = [];
    forEachPlugin(plugins, pluginName => result.push(callback(pluginName)));
    return result;
}
exports.mapPlugins = mapPlugins;
const formatTestResult = (rawResult, status, attempt = constants_1.UNKNOWN_ATTEMPT) => {
    return new testplane_1.TestplaneTestAdapter(rawResult, { attempt, status });
};
exports.formatTestResult = formatTestResult;
const saveErrorDetails = async (testResult, reportPath) => {
    if (!testResult.errorDetails) {
        return;
    }
    const detailsFilePath = path_1.default.resolve(reportPath, testResult.errorDetails.filePath);
    const detailsData = lodash_1.default.isObject(testResult.errorDetails.data)
        ? JSON.stringify(testResult.errorDetails.data, null, 2)
        : testResult.errorDetails.data;
    await makeDirFor(detailsFilePath);
    await fs_extra_1.default.writeFile(detailsFilePath, detailsData);
};
exports.saveErrorDetails = saveErrorDetails;
const getExpectedCacheKey = ([testResult, stateName]) => {
    const shortTestId = (0, common_utils_1.getShortMD5)((0, common_utils_1.mkTestId)(testResult.testPath.join(' '), testResult.browserId));
    return shortTestId + '#' + stateName;
};
exports.getExpectedCacheKey = getExpectedCacheKey;
const getImagesInfoByStateName = (imagesInfo, stateName) => {
    return imagesInfo.find(imagesInfo => imagesInfo.stateName === stateName);
};
exports.getImagesInfoByStateName = getImagesInfoByStateName;
//# sourceMappingURL=server-utils.js.map