@xray-app/xray-automation
Version:
Library for uploading test results to Xray Test Management
335 lines (334 loc) • 14.3 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.XrayCloudClient = void 0;
const graphql_request_1 = require("graphql-request");
const axios_1 = __importDefault(require("axios"));
const fs_1 = __importDefault(require("fs"));
const form_data_1 = __importDefault(require("form-data"));
const xray_error_response_1 = __importDefault(require("./xray-error-response"));
const xray_cloud_response_v2_1 = __importDefault(require("./xray-cloud-response-v2"));
// import XrayCloudGraphQLResponseV2 from './xray-cloud-graphql-response-v2';
const xray_cloud_graphql_error_response_1 = __importDefault(require("./xray-cloud-graphql-error-response"));
const index_1 = require("./index");
const xrayCloudBaseUrl = "https://xray.cloud.getxray.app/api/v2";
const authenticateUrl = xrayCloudBaseUrl + "/authenticate";
class XrayCloudClient {
constructor(xraySettings) {
this.supportedFormats = [
index_1.XRAY_FORMAT,
index_1.JUNIT_FORMAT,
index_1.TESTNG_FORMAT,
index_1.ROBOT_FORMAT,
index_1.NUNIT_FORMAT,
index_1.XUNIT_FORMAT,
index_1.CUCUMBER_FORMAT,
index_1.BEHAVE_FORMAT,
];
this.clientId = xraySettings.clientId;
this.clientSecret = xraySettings.clientSecret;
if (xraySettings.timeout !== undefined)
this.timeout = xraySettings.timeout;
else
this.timeout = 50000;
axios_1.default.defaults.timeout = this.timeout;
}
async submitResults(reportPath, config) {
if (config.format === undefined)
throw new xray_error_response_1.default("ERROR: format must be specified");
if (!this.supportedFormats.includes(config.format))
throw new xray_error_response_1.default("ERROR: unsupported format " + config.format);
let reportContent;
try {
reportContent = fs_1.default.readFileSync(reportPath).toString();
}
catch (error) {
throw new xray_error_response_1.default(error.message);
}
// use a CancelToken as the timeout setting is not reliable
const cancelTokenSource = axios_1.default.CancelToken.source();
const timeoutFn = setTimeout(() => {
cancelTokenSource.cancel("request timeout");
}, this.timeout);
return axios_1.default
.post(authenticateUrl, { client_id: this.clientId, client_secret: this.clientSecret }, {
timeout: this.timeout,
cancelToken: cancelTokenSource.token,
})
.then((response) => {
const authToken = response.data;
return authToken;
})
.then((authToken) => {
let endpointUrl;
if (config.format === index_1.XRAY_FORMAT) {
endpointUrl = xrayCloudBaseUrl + "/import/execution";
}
else {
endpointUrl = xrayCloudBaseUrl + "/import/execution/" + config.format;
}
const params = {};
let url = endpointUrl;
// all formats support GET parameters, except for xray and cucumber
if (![index_1.XRAY_FORMAT, index_1.CUCUMBER_FORMAT, index_1.BEHAVE_FORMAT].includes(config.format)) {
if (config.projectKey === undefined &&
config.testExecKey === undefined) {
throw new xray_error_response_1.default("ERROR: projectKey or testExecKey must be defined");
}
if (config.projectKey !== undefined) {
params.projectKey = config.projectKey;
}
if (config.testPlanKey !== undefined) {
params.testPlanKey = config.testPlanKey;
}
if (config.testExecKey !== undefined) {
params.testExecKey = config.testExecKey;
}
if (config.version !== undefined) {
params.fixVersion = config.version;
}
if (config.revision !== undefined) {
params.revision = config.revision;
}
if (config.testEnvironment !== undefined) {
params.testEnvironments = config.testEnvironment;
}
if (config.testEnvironments !== undefined) {
params.testEnvironments = config.testEnvironments.join(";");
}
const urlParams = new URLSearchParams({ ...params }).toString();
url = endpointUrl + "?" + urlParams;
}
let contentType;
if ([
index_1.JUNIT_FORMAT,
index_1.TESTNG_FORMAT,
index_1.NUNIT_FORMAT,
index_1.XUNIT_FORMAT,
index_1.ROBOT_FORMAT,
].includes(config.format)) {
contentType = "application/xml";
}
else {
contentType = "application/json";
}
return axios_1.default.post(url, reportContent, {
timeout: this.timeout,
cancelToken: cancelTokenSource.token,
headers: {
Authorization: "Bearer " + authToken,
"Content-Type": contentType,
},
});
})
.then((response) => {
clearTimeout(timeoutFn);
return new xray_cloud_response_v2_1.default(response);
})
.catch((error) => {
if (error.response !== undefined)
throw new xray_error_response_1.default(error.response);
else
throw new xray_error_response_1.default(error.message || error._response);
});
}
async submitResultsMultipart(reportPath, config) {
if (config.format === undefined)
throw new xray_error_response_1.default("ERROR: format must be specified");
if (!this.supportedFormats.includes(config.format))
throw new xray_error_response_1.default("ERROR: unsupported format " + config.format);
if (config.testExecInfoFile === undefined &&
config.testExecInfo === undefined)
throw new xray_error_response_1.default("ERROR: testExecInfoFile or testExecInfo must be defined");
// use a CancelToken as the timeout setting is not reliable
const cancelTokenSource = axios_1.default.CancelToken.source();
const timeoutFn = setTimeout(() => {
cancelTokenSource.cancel("request timeout");
}, this.timeout);
return axios_1.default
.post(authenticateUrl, { client_id: this.clientId, client_secret: this.clientSecret }, {
timeout: this.timeout,
cancelToken: cancelTokenSource.token,
})
.then((response) => {
// clearTimeout(timeoutFn);
const authToken = response.data;
return authToken;
})
.then((authToken) => {
let endpointUrl;
if (config.format === index_1.XRAY_FORMAT) {
endpointUrl = xrayCloudBaseUrl + "/import/execution/multipart";
}
else {
endpointUrl =
xrayCloudBaseUrl +
"/import/execution/" +
config.format +
"/multipart";
}
let reportContent;
let testInfoContent;
let testExecInfoContent;
try {
reportContent = fs_1.default.readFileSync(reportPath).toString();
if (config.testInfoFile !== undefined)
testInfoContent = fs_1.default.readFileSync(config.testInfoFile).toString();
if (config.testInfo !== undefined)
testInfoContent = config.testInfo.toString();
if (config.testExecInfoFile !== undefined)
testExecInfoContent = fs_1.default
.readFileSync(config.testExecInfoFile)
.toString();
else
testExecInfoContent = config.testExecInfo.toString();
}
catch (error) {
throw new xray_error_response_1.default(error.message);
}
const bodyFormData = new form_data_1.default();
let fileName;
if ([
index_1.JUNIT_FORMAT,
index_1.TESTNG_FORMAT,
index_1.NUNIT_FORMAT,
index_1.XUNIT_FORMAT,
index_1.ROBOT_FORMAT,
].includes(config.format)) {
fileName = "report.xml";
}
else {
fileName = "report.json";
}
bodyFormData.append("results", reportContent, fileName);
bodyFormData.append("info", testExecInfoContent, "info.json");
if (testInfoContent !== undefined &&
[
index_1.JUNIT_FORMAT,
index_1.TESTNG_FORMAT,
index_1.NUNIT_FORMAT,
index_1.XUNIT_FORMAT,
index_1.ROBOT_FORMAT,
].includes(config.format))
bodyFormData.append("testInfo", testInfoContent, "testInfo.json");
return axios_1.default.post(endpointUrl, bodyFormData, {
timeout: this.timeout,
cancelToken: cancelTokenSource.token,
headers: {
Authorization: "Bearer " + authToken,
...bodyFormData.getHeaders(),
},
});
})
.then((response) => {
clearTimeout(timeoutFn);
return new xray_cloud_response_v2_1.default(response);
})
.catch((error) => {
if (error.response !== undefined)
throw new xray_error_response_1.default(error.response);
else
throw new xray_error_response_1.default(error.message || error._response);
});
}
async authenticate() {
// use a CancelToken as the timeout setting is not reliable
const cancelTokenSource = axios_1.default.CancelToken.source();
const timeoutFn = setTimeout(() => {
cancelTokenSource.cancel("request timeout");
}, this.timeout);
return axios_1.default
.post(authenticateUrl, { client_id: this.clientId, client_secret: this.clientSecret }, {
timeout: this.timeout,
cancelToken: cancelTokenSource.token,
})
.then((response) => {
clearTimeout(timeoutFn);
const authToken = response.data;
return authToken;
});
}
async associateTestExecutionToTestPlanByIds(testExecIssueId, testPlanIssueId) {
// use a CancelToken as the timeout setting is not reliable
const cancelTokenSource = axios_1.default.CancelToken.source();
const timeoutFn = setTimeout(() => {
cancelTokenSource.cancel("request timeout");
}, this.timeout);
return axios_1.default
.post(authenticateUrl, { client_id: this.clientId, client_secret: this.clientSecret }, {
timeout: this.timeout,
cancelToken: cancelTokenSource.token,
})
.then((response) => {
clearTimeout(timeoutFn);
const authToken = response.data;
return authToken;
})
.then((authToken) => {
const graphQLEndpoint = xrayCloudBaseUrl + "/graphql";
const graphQLClient = new graphql_request_1.GraphQLClient(graphQLEndpoint, {
headers: {
authorization: "Bearer " + authToken,
},
});
const mutation = (0, graphql_request_1.gql) `
mutation {
addTestExecutionsToTestPlan(
issueId: "${testPlanIssueId}",
testExecIssueIds: ["${testExecIssueId}"]
) {
addedTestExecutions
warning
}
}
`;
return graphQLClient.request(mutation);
})
.then((response) => {
return (response.data.addTestExecutionsToTestPlan.addedTestExecutions[0] ||
testExecIssueId);
// return new XrayCloudGraphQLResponseV2(response, response.data.addTestExecutionsToTestPlan.addedTestExecutions[0] || testExecIssueId);
})
.catch((error) => {
const errorMessages = error.response.errors.map((err) => {
return err.message;
});
throw new xray_cloud_graphql_error_response_1.default(error, errorMessages);
});
}
async getTestPlanId(testPlanIssueKey) {
return this.authenticate()
.then((authToken) => {
const graphQLEndpoint = xrayCloudBaseUrl + "/graphql";
const graphQLClient = new graphql_request_1.GraphQLClient(graphQLEndpoint, {
headers: {
authorization: "Bearer " + authToken,
},
});
const query = (0, graphql_request_1.gql) `
{
getTestPlans(jql: "key = ${testPlanIssueKey}", limit: 1) {
total
results {
issueId
}
}
}
`;
return graphQLClient.request(query);
})
.then((response) => {
return response.getTestPlans.results[0].issueId;
})
.catch((error) => {
const errorMessages = error.response.errors.map((err) => {
return err.message;
});
throw new xray_cloud_graphql_error_response_1.default(error, errorMessages);
});
}
}
exports.XrayCloudClient = XrayCloudClient;
exports.default = XrayCloudClient;