@testlio/cli
Version:
Official Testlio platform command-line interface
196 lines (155 loc) • 7.64 kB
JavaScript
#!/usr/bin/env node
const fs = require('fs');
const axios = require('axios');
const Joi = require('joi');
const FormData = require('form-data');
require('dotenv').config();
const FAILURE = 1;
const SUCCESS = 0;
const ONE_MB_IN_BYTES = 1024 ** 2;
const DEVICE_RESULT_PACKAGE_MAX_FILE_SIZE_MB = 500 * ONE_MB_IN_BYTES;
const printHelp = () => {
console.log(`Parse Run Results Utility
Usage:
testlio parse-run-results [options]
Options:
--deviceResultId ID of the specific device result you want to submit results, if you don't know the deviceResult Id you can use find-device-result command or else you can pass automatedDeviceId/automatedBrowserId.
(Mutually exclusive with --automatedDeviceId and --automatedBrowserId; provide only one of these options.)
--automatedDeviceId ID of the automated device for which you want to submit results.
(Mutually exclusive with --deviceResultId and --automatedBrowserId; provide only one of these options.)
--automatedBrowserId ID of the automated browser for which you want to submit results.
(Mutually exclusive with --deviceResultId and --automatedDeviceId; provide only one of these options.)
--browserVersion REQUIRED. In case your device is browser, please pass on the exact browser version on which the tests were executed(e.g., 116.0.5845.110)
--externalSource Optional. Specifies the external source URL or identifier where the test execution took place.
--path REQUIRED. Specifies the local path to the zip package containing Allure results.
--projectConfig [path] Specifies the path to the project configuration file.
(Optional; default is 'project-config.json')
Note:
You must provide exactly one of the following: --deviceResultId, --automatedDeviceId, or --automatedBrowserId.
The --path option is mandatory and should point to a valid zip package containing Allure results.
The --browserVersion is mandatory in case your device is browser. Please pass on exact browser version on which the test were executed.
`);
};
const setAuthorizationToken = (token) => {
axios.defaults.headers.common.Authorization = `Bearer ${token}`;
};
const setBaseUri = (baseURI) => {
axios.defaults.baseURL = baseURI;
};
const getDeviceResultId = async (resultCollectionGuid, resultGuid, automatedId, idType) => {
const result = await axios.get(`/result/v1/collections/${resultCollectionGuid}/results/${resultGuid}`);
return result.data.deviceResults.find((deviceResult) => deviceResult[idType] === automatedId)?.id;
};
const parseRunResults = async (path, resultCollectionGuid, deviceResultId) => {
const { size } = fs.statSync(path);
if (size > DEVICE_RESULT_PACKAGE_MAX_FILE_SIZE_MB) {
throw new Error(
`Uploading ${path} failed: max. file size ${DEVICE_RESULT_PACKAGE_MAX_FILE_SIZE_MB / ONE_MB_IN_BYTES}MB`
);
}
const form = new FormData();
form.append('file', fs.createReadStream(path), {
filename: 'Customer Artifacts.zip',
contentType: 'application/zip',
knownLength: size
});
return axios.post(`/result/v1/collections/${resultCollectionGuid}/device-results/${deviceResultId}/parse`, form, {
headers: { ...form.getHeaders(), 'Content-Length': form.getLengthSync() },
maxContentLength: Infinity,
maxBodyLength: Infinity
});
};
const parseRunResultsSchema = Joi.object({
deviceResultId: Joi.string(),
automatedDeviceId: Joi.string().label(
'Pass on the automatedDeviceId against which the results should be submitted'
),
automatedBrowserId: Joi.string().label(
'Pass on the automatedBrowserId against which the results should be submitted'
),
path: Joi.string().required().label('Path to zip package containing Allure results'),
projectConfig: Joi.string().default('project-config.json'),
browserVersion: Joi.any(),
externalSource: Joi.string().optional().description('External source of the test results')
}).xor('deviceResultId', 'automatedDeviceId', 'automatedBrowserId');
module.exports = async (params) => {
if (params.h || params.help) {
printHelp();
return;
}
const validatedParams = Joi.attempt(params, parseRunResultsSchema);
if (validatedParams.automatedBrowserId && validatedParams.browserVersion === undefined) {
console.log(
`Please provide --browserVersion it is mandatory in case your device is browser. Please pass on exact browser version on which the test were executed.`
);
return FAILURE;
}
if (!fs.existsSync(validatedParams.projectConfig)) {
console.log(`File "${validatedParams.projectConfig}" not found!`);
return FAILURE;
}
try {
const projectConfigData = JSON.parse(fs.readFileSync(validatedParams.projectConfig).toString());
if (!process.env.RUN_API_TOKEN) {
console.log('Please provide RUN API TOKEN');
return FAILURE;
}
if (!process.env.RESULT_ID) {
console.log('For results parsing, RESULT_ID must be provided');
return FAILURE;
}
if (!fs.existsSync(params.path)) {
console.log(
`File "${params.path}" not found! Please provide a valid path to zip package containing Allure results`
);
return FAILURE;
}
setBaseUri(projectConfigData.baseURI);
setAuthorizationToken(process.env.RUN_API_TOKEN);
const deviceResultId =
validatedParams.deviceResultId ||
(await getDeviceResultId(
projectConfigData.resultCollectionGuid,
process.env.RESULT_ID,
validatedParams.automatedDeviceId,
'automatedDevice'
)) ||
(await getDeviceResultId(
projectConfigData.resultCollectionGuid,
process.env.RESULT_ID,
validatedParams.automatedBrowserId,
'automatedBrowser'
));
if (!deviceResultId) {
console.log('Device result id not found, cannot parse results');
return FAILURE;
}
const response = await parseRunResults(
validatedParams.path,
projectConfigData.resultCollectionGuid,
deviceResultId
);
const metadata = [];
if (validatedParams.browserVersion) {
metadata.push({ key: 'browserVersion', value: `${validatedParams.browserVersion}` });
}
if (validatedParams.externalSource) {
metadata.push({ key: 'externalSource', value: `${validatedParams.externalSource}` });
}
if (metadata.length > 0) {
await axios.post(
`/result/v1/collections/${projectConfigData.resultCollectionGuid}/device-results/${deviceResultId}/metadata`,
{ metadata }
);
}
if (response.data.deviceResultId === deviceResultId) {
console.log('Results file uploaded successfully');
return SUCCESS;
}
console.log('Something went wrong while uploading results file');
return FAILURE;
} catch (e) {
console.log('Something went wrong while parsing run results', e);
return FAILURE;
}
};