UNPKG

jira-client-xray

Version:

An extended wrapper of the existing "jira-client" module, which adds support for the "Xray for Jira" Test Management plugin's REST API

482 lines (419 loc) 20.9 kB
'use strict'; // Node.js core modules var url = require('url'); var util = require('util'); // Userland modules var JiraApi = require('jira-client'); /** * @constructor * @param {JiraApiWithXrayOptions} options */ function JiraApiWithXray(options) { if (!(this instanceof JiraApiWithXray)) { return new JiraApiWithXray(options); } var opts = options || {}; // Invoke the super constructor JiraApi.call(this, opts); this.xrayVersion = opts.xrayVersion || '1.0'; } util.inherits(JiraApiWithXray, JiraApi); /** * @typedef JiraApiWithXrayOptions * @type {object} * @property {string} [protocol=http] - What protocol to use to connect to * Jira? Ex: http|https * @property {string} host - What host is this tool connecting to for the Jira * instance? Ex: jira.somehost.com * @property {string} [port] - What port is this tool connecting to Jira with? Only needed for * none standard ports. Ex: 8080, 3000, etc * @property {string} [username] - Specify a username for this tool to authenticate all * requests with. * @property {string} [password] - Specify a password for this tool to authenticate all * requests with. * @property {string} [apiVersion=2] - What version of the Jira REST API is the instance the * tool is connecting to? * @property {string} [base] - What other url parts exist, if any, before the rest/api/ * section? * @property {string} [intermediatePath] - If specified, overwrites the default rest/api/version * section of the uri * @property {boolean} [strictSSL=true] - Does this tool require each request to be * authenticated? Defaults to true. * @property {function} [request] - What method does this tool use to make its requests? * Defaults to request from request-promise * @property {number} [timeout] - Integer containing the number of milliseconds to wait for a * server to send response headers (and start the response body) before aborting the request. Note * that if the underlying TCP connection cannot be established, the OS-wide TCP connection timeout * will overrule the timeout option ([the default in Linux can be anywhere from 20-120 * * seconds](http://www.sekuda.com/overriding_the_default_linux_kernel_20_second_tcp_socket_connect_timeout)). * @property {string} [webhookVersion=1.0] - What webhook version does this api wrapper need to * hit? * @property {string} [greenhopperVersion=1.0] - What webhook version does this api wrapper need * to hit? * @property {OAuth} [oauth] - Specify an OAuth object for this tool to authenticate all requests * using OAuth. * @property {string} [bearer] - Specify a OAuth bearer token to authenticate all requests with. * @property {string} [xrayVersion=1.0] - What version of the "Xray for Jira" REST API is the * instance the tool is connecting to? */ /** * @typedef OAuth * @type {object} * @property {string} consumer_key - The consumer entered in Jira Preferences. * @property {string} consumer_secret - The private RSA file. * @property {string} access_token - The generated access token. * @property {string} access_token_secret - The generated access toke secret. * @property {string} signature_method [signature_method=RSA-SHA1] - OAuth signurate methode * Possible values RSA-SHA1, HMAC-SHA1, PLAINTEXT. Jira Cloud supports only RSA-SHA1. */ /** * Creates a URI object for a given pathName within the "Xray for Jira" REST API * @param {makeXrayUriOptions} [options] - An options object specifying uri information */ JiraApiWithXray.prototype.makeXrayUri = function(options) { var opts = options || {}; var intermediateToUse = this.intermediatePath || opts.intermediatePath; var tempPath = intermediateToUse || '/rest/raven/' + this.xrayVersion; var uri = url.format({ protocol: this.protocol, hostname: this.host, port: this.port, pathname: this.base + tempPath + opts.pathname, }); return decodeURIComponent(uri); }; /** * @typedef makeXrayUriOptions * @type {object} * @property {string} pathname - The url after the /rest/raven/version * @property {string} intermediatePath - If specified will overwrite the /rest/raven/version section */ /*jshint ignore:start */ /** * Import Test Execution results into "Xray for Jira" using the Xray JSON format. * @see https://confluence.xpand-addons.com/display/XRAY/Import+Execution+Results+-+REST#ImportExecutionResults-REST-XrayJSONresults * @param {TestExecXrayJson} testExecResults - The results of the Test Execution in the Xray JSON format */ /*jshint ignore:end */ JiraApiWithXray.prototype.importExecResultsFromXray = function(testExecResults) { return this.doRequest( this.makeRequestHeader( this.makeXrayUri({ method: 'POST', pathname: '/import/execution', body: testExecResults }) ) ); }; /*jshint ignore:start */ /** * @typedef TestExecXrayJson * @type {object} * @see https://confluence.xpand-addons.com/display/XRAY/Import+Execution+Results#ImportExecutionResults-XrayJSONformat * @property {string} [testExecutionKey] - The Jira issue key for an existing Test Execution that should be updated. If omitted, a new Test Execution is created automatically. * @property {TestExecXrayJsonInfo} [info] - Test Execution metadata * @property {TestExecXrayJsonTestRun[]} tests - The results of the Test Run */ /*jshint ignore:end */ /** * @typedef TestExecXrayJsonInfo * @type {object} * @property {string} [project] - The Jira project ID * @property {string} summary - Summary of the Test Execution * @property {string} [description] - Description of the Test Execution * @property {string} [user] - The Jira user logging the Test Execution results * @property {string} [version] - Version under test * @property {string} [revision] - The revision/build/branch under test * @property {string} [startDate] - The ISO date timestamp at which the Test Execution started * @property {string} [finishDate] - The ISO date timestamp at which the Test Execution finished * @property {string} [testPlanKey] - The Jira issue key for the associated Test Plan * @property {string[]} [testEnvironments] - The environmental configuration under test */ /** * @typedef TestExecXrayJsonTestRun * @type {object} * @property {string} testKey - The Jira issue key for the associated Test * @property {string} status - The "PASS" or "FAIL" status for the Test Run as a whole * @property {string} [comment] - A message about this Test Run * @property {string} [start] - The ISO date timestamp at which this Test Run started * @property {string} [finish] - The ISO date timestamp at which this Test Run finished * @property {string} [executedBy] - The Jira user who executed this Test Run * @property {TestExecXrayJsonEvidence[]} [evidences] - Attachments (e.g. screenshots) proving the Test Run's failure * @property {TestExecXrayJsonResult[]} [results] - Detailed results of individual test cases within this Test Run * @property {string[]} [examples] - The "PASS" or "FAIL" status for each of the Test Run's examples * @property {TestExecXrayJsonTestStep[]} [steps] - Details about each Test step and its outcome * @property {string[]} [defects] - The Jira issue keys for any associated bugs recorded during this Test Run */ /** * @typedef TestExecXrayJsonEvidence * @type {object} * @property {string} data - The base64-encoded string of data representing this attachment * @property {string} filename - The basename of the file associated with this attachment * @property {string} [contentType] - The MIME type associated with this attachment, e.g. "image/jpeg" */ /** * @typedef TestExecXrayJsonResult * @type {object} * @property {string} name - The name of the test case * @property {string} status - The "PASS" or "FAIL" status of this test case * @property {number} [duration] - The duration (milliseconds? seconds?) * @property {string} [log] - Any log messages that came out of this test case * @property {string[]} [examples] - The "PASS" or "FAIL" status for each of this test case's examples */ /** * @typedef TestExecXrayJsonTestStep * @type {object} * @property {string} status - The "PASS" or "FAIL" status of this step * @property {string} [comment] - A message about this step * @property {TestExecXrayJsonEvidence[]} [evidences] - Attachments (e.g. screenshots) proving this step's failure */ /** * Import Test Execution results into "Xray for Jira" using one of the supported JSON formats. * @access private * @param {string} type - The type of JSON result to be imported. Must be one of: "cucumber" or "behave". * @param {TestExecCucumberJson|TestExecBehaveJson} results - The results of the Test Execution * @param {JiraIssueCreationJson} [issueData] - Customized field data for creating a new Test Execution issue in Jira */ JiraApiWithXray.prototype._importExecResultsFromJson = function(type, results, issueData) { var hasIssueData = !!issueData; var requestOptions = { method: 'POST', pathname: '/import/execution/' + type + (hasIssueData ? '/multipart' : '') }; if (hasIssueData) { requestOptions.formData = { result: results, info: issueData }; } else { requestOptions.body = results; } return this.doRequest( this.makeRequestHeader( this.makeXrayUri( requestOptions ) ) ); }; /** * @external {JiraCloudIssueCreationJson} https://developer.atlassian.com/cloud/jira/platform/rest/#api-api-2-issue-post */ /*jshint ignore:start */ /** * @external {JiraServerIssueCreationJson} https://docs.atlassian.com/software/jira/docs/api/REST/7.9.0/#api/2/issue-createIssue */ /*jshint ignore:end */ /** * @typedef JiraIssueCreationJson * @type {JiraCloudIssueCreationJson|JiraServerIssueCreationJson} */ /*jshint ignore:start */ /** * Import Test Execution results into "Xray for Jira" using the Cucumber JSON format. * @see https://confluence.xpand-addons.com/display/XRAY/Import+Execution+Results+-+REST#ImportExecutionResults-REST-CucumberJSONresults * @see https://confluence.xpand-addons.com/display/XRAY/Import+Execution+Results+-+REST#ImportExecutionResults-REST-CucumberJSONresultsMultipart * @param {TestExecCucumberJson} testExecResults - The results of the Test Execution in the Cucumber JSON format * @param {JiraIssueCreationJson} [issueData] - Customized field data for creating a new Test Execution issue in Jira */ /*jshint ignore:end */ JiraApiWithXray.prototype.importExecResultsFromCucumber = function(testExecResults, issueData) { return this._importExecResultsFromJson('cucumber', testExecResults, issueData); }; /*jshint ignore:start */ /** * @external {TestExecCucumberJson} https://confluence.xpand-addons.com/display/XRAY/Import+Execution+Results#ImportExecutionResults-CucumberJSONoutputformat */ /*jshint ignore:end */ /*jshint ignore:start */ /** * Import Test Execution results into "Xray for Jira" using the Behave JSON format. * @see https://confluence.xpand-addons.com/display/XRAY/Import+Execution+Results+-+REST#ImportExecutionResults-REST-BehaveJSONresults * @see https://confluence.xpand-addons.com/display/XRAY/Import+Execution+Results+-+REST#ImportExecutionResults-REST-BehaveJSONresultsMultipart * @param {TestExecBehaveJson} testExecResults - The results of the Test Execution in the Behave JSON format * @param {JiraIssueCreationJson} [issueData] - Customized field data for creating a new Test Execution issue in Jira */ /*jshint ignore:end */ JiraApiWithXray.prototype.importExecResultsFromBehave = function(testExecResults, issueData) { return this._importExecResultsFromJson('behave', testExecResults, issueData); }; /** * @external {TestExecBehaveJson} https://github.com/behave/behave/blob/master/behave/formatter/json.py */ /** * Import Test Execution results into "Xray for Jira" using one of the supported XML formats. * @access private * @param {string} type - The type of XML result to be imported. Must be one of: "junit", "testng", "nunit", or "robot". * @param {TestExecJUnitXml|TestExecTestNGXml|TestExecNUnitXml|TestExecRobotXml|string|Buffer|ReadableStream} results - * The results of the Test Execution in an XML formatted string * @param {XrayImportQueryParams} [query] - Field data for creating a new Test Execution issue in Jira. * Either `query` or `issueData` must be provided but not both. * @param {JiraIssueCreationJson} [issueData] - Customized field data for creating a new Test Execution issue in Jira. * Either `query` or `issueData` must be provided but not both. */ JiraApiWithXray.prototype._importExecResultsFromXml = function(type, results, query, issueData) { var hasQuery = !!query; var hasIssueData = !hasQuery && !!issueData; var requestOptions = { method: 'POST', pathname: '/import/execution/' + type + (hasIssueData ? '/multipart' : ''), formData: { file: results } }; if (hasQuery) { var queryOptions = Object.assign({}, query); var testEnvs = queryOptions.testEnvironments || []; if (typeof testEnvs === 'string') { testEnvs = testEnvs.split(/\s*;\s*/); } if (Array.isArray(testEnvs)) { testEnvs = testEnvs.filter(function(te) { return !!te.replace(/^\s+|\s+$/g, ''); }); } if (testEnvs.length) { queryOptions.testEnvironments = testEnvs.join(';'); } requestOptions.query = queryOptions; } else if (hasIssueData) { requestOptions.form.info = issueData; } else { throw new TypeError('Must provide either the "query" or "issueData" parameter'); } return this.doRequest( this.makeRequestHeader( this.makeXrayUri( requestOptions ) ) ); }; /** * @typedef XrayImportQueryParams * @type object * @property {string} [testExecKey] - The Jira issue key for an existing Test Execution that should be updated. If * omitted, a new Test Execution is created automatically in the Jira project indicated by `projectKey`. Either * `testExecKey` or `projectKey` must be provided. * @property {string} [projectKey] - The Jira project key where the new Test Execution issue should be created. Not * needed if `testExecKey` is provided. Either `testExecKey` or `projectKey` must be provided. * @property {string} [testPlanKey] - The Jira issue key for the associated Test Plan * @property {string|string[]} [testEnvironments] - The list of test environments. If provided as a string, items must * be delimited by a ";". * @property {string} [revision] - Source code and documentation version used in the Test Execution * @property {string} [fixVersion] - The Jira "Fix Version" to be associated with the Test Execution */ /*jshint ignore:start */ /** * Import Test Execution results into "Xray for Jira" using the JUnit XML format. * @see https://confluence.xpand-addons.com/display/XRAY/Import+Execution+Results+-+REST#ImportExecutionResults-REST-JUnitXMLresults * @see https://confluence.xpand-addons.com/display/XRAY/Import+Execution+Results+-+REST#ImportExecutionResults-REST-JUnitXMLresultsMultipart * @param {TestExecJUnitXml|string|Buffer|ReadableStream} testExecResults - The results of the Test Execution in the * JUnit XML formatted string * @param {XrayImportQueryParams} [query] - Field data for creating a new Test Execution issue in Jira. * Either `query` or `issueData` must be provided but not both. * @param {JiraIssueCreationJson} [issueData] - Customized field data for creating a new Test Execution issue in Jira. * Either `query` or `issueData` must be provided but not both. */ /*jshint ignore:end */ JiraApiWithXray.prototype.importExecResultsFromJUnit = function(testExecResults, query, issueData) { return this._importExecResultsFromXml('junit', testExecResults, query, issueData); }; /*jshint ignore:start */ /** * @external {TestExecJUnitXml} https://confluence.xpand-addons.com/display/XRAY/Import+Execution+Results#ImportExecutionResults-JUnitXMLoutputformat */ /*jshint ignore:end */ /*jshint ignore:start */ /** * Import Test Execution results into "Xray for Jira" using the TestNG XML format. * @see https://confluence.xpand-addons.com/display/XRAY/Import+Execution+Results+-+REST#ImportExecutionResults-REST-TestNGXMLresults * @see https://confluence.xpand-addons.com/display/XRAY/Import+Execution+Results+-+REST#ImportExecutionResults-REST-TestNGXMLresultsMultipart * @param {TestExecTestNGXml|string|Buffer|ReadableStream} testExecResults - The results of the Test Execution in the * TestNG XML formatted string * @param {XrayImportQueryParams} [query] - Field data for creating a new Test Execution issue in Jira. * Either `query` or `issueData` must be provided but not both. * @param {JiraIssueCreationJson} [issueData] - Customized field data for creating a new Test Execution issue in Jira. * Either `query` or `issueData` must be provided but not both. */ /*jshint ignore:end */ JiraApiWithXray.prototype.importExecResultsFromTestNG = function(testExecResults, query, issueData) { return this._importExecResultsFromXml('testng', testExecResults, query, issueData); }; /*jshint ignore:start */ /** * @external {TestExecTestNGXml} https://confluence.xpand-addons.com/display/XRAY/Import+Execution+Results#ImportExecutionResults-TestNGXMLoutputformat */ /*jshint ignore:end */ /*jshint ignore:start */ /** * Import Test Execution results into "Xray for Jira" using the NUnit XML format. * @see https://confluence.xpand-addons.com/display/XRAY/Import+Execution+Results+-+REST#ImportExecutionResults-REST-NUnitXMLresults * @see https://confluence.xpand-addons.com/display/XRAY/Import+Execution+Results+-+REST#ImportExecutionResults-REST-NUnitXMLresultsMultipart * @param {TestExecNUnitXml|string|Buffer|ReadableStream} testExecResults - The results of the Test Execution in the NUnit XML formatted string * @param {XrayImportQueryParams} [query] - Field data for creating a new Test Execution issue in Jira. * Either `query` or `issueData` must be provided but not both. * @param {JiraIssueCreationJson} [issueData] - Customized field data for creating a new Test Execution issue in Jira. * Either `query` or `issueData` must be provided but not both. */ /*jshint ignore:end */ JiraApiWithXray.prototype.importExecResultsFromNUnit = function(testExecResults, query, issueData) { return this._importExecResultsFromXml('nunit', testExecResults, query, issueData); }; /*jshint ignore:start */ /** * @external {TestExecNUnit30Xml} https://confluence.xpand-addons.com/display/XRAY/Import+Execution+Results#ImportExecutionResults-NUnitv3.0XMLoutputformat */ /*jshint ignore:end */ /*jshint ignore:start */ /** * @external {TestExecNUnit26Xml} https://confluence.xpand-addons.com/display/XRAY/Import+Execution+Results#ImportExecutionResults-NUnitv2.6XMLoutputformat */ /*jshint ignore:end */ /** * @typedef TestExecNUnitXml * @type {TestExecNUnit30Xml|TestExecNUnit26Xml} */ /*jshint ignore:start */ /** * Import Test Execution results into "Xray for Jira" using the Robot Framework XML format. * @see https://confluence.xpand-addons.com/display/XRAY/Import+Execution+Results+-+REST#ImportExecutionResults-REST-RobotFrameworkXMLresults * @see https://confluence.xpand-addons.com/display/XRAY/Import+Execution+Results+-+REST#ImportExecutionResults-REST-RobotFrameworkXMLresultsMultipart * @param {TestExecRobotXml|string|Buffer|ReadableStream} testExecResults - The results of the Test Execution in the * Robot Framework XML formatted string * @param {XrayImportQueryParams} [query] - Field data for creating a new Test Execution issue in Jira. * Either `query` or `issueData` must be provided but not both. * @param {JiraIssueCreationJson} [issueData] - Customized field data for creating a new Test Execution issue in Jira. * Either `query` or `issueData` must be provided but not both. */ /*jshint ignore:end */ JiraApiWithXray.prototype.importExecResultsFromRobot = function(testExecResults, query, issueData) { return this._importExecResultsFromXml('robot', testExecResults, query, issueData); }; /** * @external {TestExecRobotXml} https://github.com/robotframework/robotframework/tree/master/doc/schema */ /*jshint ignore:start */ /** * Import multiple Test Execution results into "Xray for Jira" using a bundled compressed file (e.g. ZIP). * @see https://confluence.xpand-addons.com/display/XRAY/Import+Execution+Results+-+REST#ImportExecutionResults-REST-MultipleExecutionResults * @param {string|Buffer|ReadableStream} testExecResults - The results of the multiple Test Executions */ /*jshint ignore:end */ JiraApiWithXray.prototype.importMultipleExecResults = function(testExecResults) { return this.doRequest( this.makeRequestHeader( this.makeXrayUri({ method: 'POST', pathname: '/import/execution/bundle', formData: { file: testExecResults } }) ) ); }; // Export module.exports = JiraApiWithXray;