"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    var desc = Object.getOwnPropertyDescriptor(m, k);
    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
      desc = { enumerable: true, get: function() { return m[k]; } };
    }
    Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
    var ownKeys = function(o) {
        ownKeys = Object.getOwnPropertyNames || function (o) {
            var ar = [];
            for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
            return ar;
        };
        return ownKeys(o);
    };
    return function (mod) {
        if (mod && mod.__esModule) return mod;
        var result = {};
        if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
        __setModuleDefault(result, mod);
        return result;
    };
})();
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const taskLib = __importStar(require("azure-pipelines-task-lib/task"));
const logger_1 = __importDefault(require("./logger"));
const types_1 = require("./types");
const report_1 = require("./report");
const helpers_1 = require("./helpers");
let devOpsApi;
let ea;
const execute = async (executionParams, onDispatch) => {
    let statistics;
    try {
        const executionOutput = await ea.runEntity(executionParams, onDispatch);
        (0, helpers_1.publishExecutionVariables)(executionOutput);
        (0, report_1.displayResults)(executionOutput, executionParams);
        statistics = (0, report_1.getExecutionStatistics)(executionOutput);
        if ((0, report_1.executionFailed)(executionOutput)) {
            const errorReport = (0, report_1.getStatusReports)(executionOutput).find((r) => r.status === types_1.ExecutionStatus.ERROR);
            throw new Error(`\n${statistics}\n\n${errorReport ? errorReport.logs : ""}`);
        }
    }
    catch (err) {
        throw new Error(err);
    }
    logger_1.default.info(`Statistics: ${JSON.stringify(statistics, null, 2)}`);
    return statistics;
};
const executeTestCase = async (scriptId, configuration, onDispatch) => {
    try {
        const executionOutput = await ea.runEntity({ type: "script", id: scriptId, configuration }, onDispatch);
        if (!executionOutput) {
            throw new Error("Cannot execute ea scripts");
        }
        (0, helpers_1.publishExecutionVariables)(executionOutput);
        return {
            status: executionOutput[0].status,
            messages: (0, report_1.getAllMessages)(executionOutput[0]),
            duration: parseInt(executionOutput[0].duration, 10),
            errors: (0, report_1.getErrors)(executionOutput[0]),
        };
    }
    catch (err) {
        throw new Error(err);
    }
};
const getTestPoints = async (testPlan, testSuites) => {
    const testPointsIds = [];
    const configurationIdsMap = {};
    for (const suite of testSuites) {
        const points = await devOpsApi.getSuiteTestPoints(testPlan, suite);
        points.forEach((point) => {
            testPointsIds.push(point.id);
            if (point.configuration?.id) {
                const configurationId = Number.parseInt(String(point.configuration.id), 10);
                if (!Number.isNaN(configurationId)) {
                    configurationIdsMap[configurationId] = true;
                }
            }
        });
    }
    return {
        testPointsIds,
        configurationIds: Object.keys(configurationIdsMap).map((id) => Number.parseInt(id, 10)),
    };
};
const createTestRun = async (testPlan, testPoints) => {
    const newTestRun = await devOpsApi.createTestRun({
        name: "PipelineTestrun",
        plan: {
            id: testPlan,
        },
        pointIds: testPoints,
        configurationIds: [],
    });
    return newTestRun;
};
const getTestRestultCases = (testRunResults) => testRunResults
    .filter((tr) => tr.testCase && tr.testCase.id !== undefined)
    .map((tr) => tr.testCase.id);
const getTestSuiteConfigurations = async (configurationIds) => {
    if (configurationIds.length === 0) {
        console.log("No suite configurations found for selected test suites.");
        return;
    }
    const configurations = await Promise.all(configurationIds.map(async (configurationId) => {
        const configuration = await devOpsApi.getTestConfiguration(configurationId);
        return {
            id: configuration.id,
            name: configuration.name,
            description: configuration.description,
            values: (configuration.values || []).map((value) => ({
                name: value.name,
                value: value.value,
            })),
        };
    }));
    return configurations.reduce((acc, configuration) => {
        acc[configuration.id] = configuration;
        return acc;
    }, {});
};
async function run() {
    const testSelection = taskLib.getInput("testSelector");
    logger_1.default.info(`Execution mode ${testSelection}`);
    ea = await (0, helpers_1.initEaApi)();
    devOpsApi = await (0, helpers_1.initDevOpsApi)();
    if (testSelection === "manual") {
        await runManualTask();
    }
    else {
        const testPlan = taskLib.getInput("testPlan", true);
        if (!testPlan) {
            throw new Error("Test plan is not configured");
        }
        logger_1.default.info(`Executing test plan ${testPlan}...`);
        const testSuiteStrings = taskLib.getDelimitedInput("testSuite", ",", true);
        if (!testSuiteStrings) {
            throw new Error("Test suites are not configured");
        }
        const testSuites = new Array();
        testSuiteStrings.forEach((element) => {
            const testSuiteId = parseInt(element, 10);
            testSuites.push(testSuiteId);
        });
        try {
            const { testPointsIds: testPoints, configurationIds } = await getTestPoints(testPlan, testSuites);
            const testSuiteConfigurations = await getTestSuiteConfigurations(configurationIds);
            let testRun = await createTestRun(testPlan, testPoints);
            const testRunResults = await devOpsApi.getTestRunResults(testRun.id);
            const scriptsToRun = await ea.getScriptTestCaseMapping(getTestRestultCases(testRunResults));
            if (Object.keys(scriptsToRun).length === 0) {
                testRun = await devOpsApi.updateTestRun({ state: "Completed" }, testRun.id);
                taskLib.setResult(taskLib.TaskResult.Succeeded, "No scripts to run");
                return;
            }
            testRun = await devOpsApi.updateTestRun({ state: "InProgress" }, testRun.id);
            for (const testRunResult of testRunResults) {
                try {
                    await devOpsApi.updateTestRunResult(testRunResults.map((tr) => ({ ...tr, state: "Queued" })), testRun.id);
                    const testCaseId = testRunResult.testCase.id;
                    let outcome = "";
                    let comment = "";
                    let durationInMs = 0;
                    let errorMessage = "";
                    let testStatus = taskLib.TaskResult.Succeeded;
                    const scriptId = scriptsToRun[testCaseId];
                    if (scriptId) {
                        logger_1.default.info(`Executing test case ${testCaseId} - script ${scriptId}`);
                        const { status, messages, duration, errors } = await executeTestCase(scriptId, (0, helpers_1.mergeExecutionConfiguration)(testSuiteConfigurations?.[testRunResult.configuration?.id ?? 0]), async () => {
                            await devOpsApi.updateTestRunResult([{ id: testRunResult.id, state: "InProgress" }], testRun.id);
                        });
                        outcome = helpers_1.statusMap[status];
                        comment = messages;
                        durationInMs = duration;
                        errorMessage = errors;
                        testStatus =
                            status !== types_1.ExecutionStatus.ERROR
                                ? taskLib.TaskResult.Succeeded
                                : taskLib.TaskResult.Failed;
                    }
                    else {
                        outcome = "NotExecuted";
                        comment = `Script for test case ${testCaseId} not found`;
                        logger_1.default.warn(`Test case ${testCaseId} - automation script not found`);
                    }
                    await devOpsApi.updateTestRunResult([
                        {
                            id: testRunResult.id,
                            outcome,
                            state: "Completed",
                            comment,
                            durationInMs,
                            errorMessage,
                            completedDate: new Date(),
                        },
                    ], testRun.id);
                    logger_1.default.info(`Test case ${testCaseId} completed with status ${outcome}`);
                    taskLib.setResult(testStatus, errorMessage);
                }
                catch (err) {
                    taskLib.setResult(taskLib.TaskResult.Failed, err.message);
                    await devOpsApi.updateTestRunResult([
                        {
                            id: testRunResult.id,
                            outcome: "Failed",
                            state: "Completed",
                            comment: err.message,
                            completedDate: new Date(),
                        },
                    ], testRun.id);
                }
            }
            testRun = await devOpsApi.updateTestRun({ state: "Completed" }, testRun.id);
        }
        catch (error) {
            console.error(error);
            taskLib.setResult(taskLib.TaskResult.Failed, error.message);
        }
        taskLib.setResult(taskLib.TaskResult.Succeeded, "DONE");
    }
}
run();
async function runManualTask() {
    try {
        const entity = taskLib.getInput("entity", true);
        if (!entity) {
            throw new Error("Entity is not configured");
        }
        const [id, type] = entity.split(";");
        const stats = await execute({
            type: type,
            id: Number.parseInt(id, 10),
            configuration: (0, helpers_1.mergeExecutionConfiguration)(),
        });
        taskLib.setResult(taskLib.TaskResult.Succeeded, stats);
    }
    catch (err) {
        taskLib.setResult(taskLib.TaskResult.Failed, err.message);
    }
}
//# sourceMappingURL=index.js.map