@sprucelabs/jest-jira-reporter 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +76 -0
- package/build/.spruce/errors/errors.types.d.ts +31 -0
- package/build/.spruce/errors/errors.types.js +4 -0
- package/build/.spruce/errors/jestJiraReporter/transitionNotFound.schema.d.ts +3 -0
- package/build/.spruce/errors/jestJiraReporter/transitionNotFound.schema.js +19 -0
- package/build/.spruce/errors/options.types.d.ts +7 -0
- package/build/.spruce/errors/options.types.js +2 -0
- package/build/.spruce/schemas/fields/fieldClassMap.d.ts +2 -0
- package/build/.spruce/schemas/fields/fieldClassMap.js +4 -0
- package/build/.spruce/schemas/fields/fields.types.d.ts +1 -0
- package/build/.spruce/schemas/fields/fields.types.js +2 -0
- package/build/.spruce/settings.json +13 -0
- package/build/JestReporter.d.ts +26 -0
- package/build/JestReporter.js +79 -0
- package/build/errors/SpruceError.d.ts +6 -0
- package/build/errors/SpruceError.js +25 -0
- package/build/errors/transitionNotFound.builder.d.ts +18 -0
- package/build/errors/transitionNotFound.builder.js +26 -0
- package/build/esm/.spruce/errors/errors.types.d.ts +31 -0
- package/build/esm/.spruce/errors/errors.types.js +3 -0
- package/build/esm/.spruce/errors/options.types.d.ts +7 -0
- package/build/esm/.spruce/errors/options.types.js +1 -0
- package/build/esm/JestReporter.d.ts +26 -0
- package/build/esm/JestReporter.js +89 -0
- package/build/esm/errors/SpruceError.d.ts +6 -0
- package/build/esm/errors/SpruceError.js +19 -0
- package/build/esm/errors/transitionNotFound.builder.d.ts +18 -0
- package/build/esm/errors/transitionNotFound.builder.js +24 -0
- package/build/esm/index.d.ts +2 -0
- package/build/esm/index.js +2 -0
- package/build/esm/integrationTest.d.ts +1 -0
- package/build/esm/integrationTest.js +15 -0
- package/build/esm/jira.types.d.ts +9 -0
- package/build/esm/jira.types.js +1 -0
- package/build/index.d.ts +2 -0
- package/build/index.js +7 -0
- package/build/integrationTest.d.ts +1 -0
- package/build/integrationTest.js +20 -0
- package/build/jira.types.d.ts +9 -0
- package/build/jira.types.js +2 -0
- package/package.json +96 -0
package/README.md
ADDED
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
# Google Sheets Reporter
|
|
2
|
+
|
|
3
|
+
Update a Google Sheet when your tests pass or fail.
|
|
4
|
+
|
|
5
|
+
<img src="https://raw.githubusercontent.com/sprucelabsai/jest-sheets-reporter/master/docs/images/overview.png">
|
|
6
|
+
|
|
7
|
+
## Installing
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
yarn add -D @sprucelabs/jest-sheets-reporter
|
|
11
|
+
```
|
|
12
|
+
```bash
|
|
13
|
+
npm install --dev @sprucelabs/jest-sheets-reporter
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
## Example Jest config
|
|
17
|
+
Inside your `package.json` there is a `jest` block.
|
|
18
|
+
|
|
19
|
+
Add the following configuration:
|
|
20
|
+
```json
|
|
21
|
+
"jest": {
|
|
22
|
+
"reporters": [
|
|
23
|
+
"default",
|
|
24
|
+
[
|
|
25
|
+
"@sprucelabs/jest-sheets-reporter",
|
|
26
|
+
{
|
|
27
|
+
"sheetId": "{{spreadsheetId}}",
|
|
28
|
+
"worksheetId": 0,
|
|
29
|
+
"testMap": {
|
|
30
|
+
"testName": "destinationCell",
|
|
31
|
+
"getsGoodHealthCheckAndNothingElse": "C5",
|
|
32
|
+
"canGetLatestVersionBasedOnDir": "C16",
|
|
33
|
+
"canBuildSkill": "C24",
|
|
34
|
+
"canWatchAndBuild": "C25"
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
]
|
|
38
|
+
]
|
|
39
|
+
},
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
## How does it work
|
|
43
|
+
|
|
44
|
+
This simple reporter matches the name of your test against what is in your `jest` config and updates the cell whose name matches.
|
|
45
|
+
|
|
46
|
+
If a test passes, the cell is set to 1.
|
|
47
|
+
|
|
48
|
+
If a test fails, the cell is set to 0.
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
## Making it pretty
|
|
52
|
+
|
|
53
|
+
You can change the look of a cell by using conditional formatting:
|
|
54
|
+
|
|
55
|
+
<img src="https://raw.githubusercontent.com/sprucelabsai/jest-sheets-reporter/master/docs/images/conditional.png">
|
|
56
|
+
|
|
57
|
+
Then we set the background and the text color based on the value being exactly `1` or `0`.
|
|
58
|
+
|
|
59
|
+
<img src="https://raw.githubusercontent.com/sprucelabsai/jest-sheets-reporter/master/docs/images/stylerules.png">
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
## Getting your account credentials
|
|
63
|
+
|
|
64
|
+
1. Visit the [Google Console](https://console.developers.google.com/)
|
|
65
|
+
2. Create a new project, call it Test Integrations
|
|
66
|
+
3. After creation, go to the project dashboard and in the left meno go "API's & Services" -> "Enabled API's & Services"
|
|
67
|
+
4. Click "+ Enable API's and Services"
|
|
68
|
+
5. Find sheets and enable it.
|
|
69
|
+
6. After save, click "Create Credentials" in the upper right.
|
|
70
|
+
7. Give it a name, leave everything else blank and save
|
|
71
|
+
9. On the service account details page, click "KEYS" tab
|
|
72
|
+
10. Click Add Key -> JSON
|
|
73
|
+
11. Take the download private key and open it
|
|
74
|
+
12. client_email -> GOOGLE_SERVICE_EMAIL
|
|
75
|
+
13. private_key -> GOOGLE_SERVICE_PRIVATE_KEY
|
|
76
|
+
14. Remember to invite the service email to any spreadsheet you want it to update!
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { default as SchemaEntity } from '@sprucelabs/schema';
|
|
2
|
+
import * as SpruceSchema from '@sprucelabs/schema';
|
|
3
|
+
export declare namespace SpruceErrors.JestJiraReporter {
|
|
4
|
+
interface TransitionNotFound {
|
|
5
|
+
/** Transition. */
|
|
6
|
+
'transition': ("In Progress" | "Done");
|
|
7
|
+
}
|
|
8
|
+
interface TransitionNotFoundSchema extends SpruceSchema.Schema {
|
|
9
|
+
id: 'transitionNotFound';
|
|
10
|
+
namespace: 'JestJiraReporter';
|
|
11
|
+
name: 'Transition not found';
|
|
12
|
+
fields: {
|
|
13
|
+
/** Transition. */
|
|
14
|
+
'transition': {
|
|
15
|
+
label: 'Transition';
|
|
16
|
+
type: 'select';
|
|
17
|
+
isRequired: true;
|
|
18
|
+
options: {
|
|
19
|
+
choices: [{
|
|
20
|
+
"value": "In Progress";
|
|
21
|
+
"label": "In Progress";
|
|
22
|
+
}, {
|
|
23
|
+
"value": "Done";
|
|
24
|
+
"label": "Done";
|
|
25
|
+
}];
|
|
26
|
+
};
|
|
27
|
+
};
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
type TransitionNotFoundEntity = SchemaEntity<SpruceErrors.JestJiraReporter.TransitionNotFoundSchema>;
|
|
31
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const schema_1 = require("@sprucelabs/schema");
|
|
4
|
+
const transitionNotFoundSchema = {
|
|
5
|
+
id: 'transitionNotFound',
|
|
6
|
+
namespace: 'JestJiraReporter',
|
|
7
|
+
name: 'Transition not found',
|
|
8
|
+
fields: {
|
|
9
|
+
/** Transition. */
|
|
10
|
+
'transition': {
|
|
11
|
+
label: 'Transition',
|
|
12
|
+
type: 'select',
|
|
13
|
+
isRequired: true,
|
|
14
|
+
options: { choices: [{ "value": "In Progress", "label": "In Progress" }, { "value": "Done", "label": "Done" }], }
|
|
15
|
+
},
|
|
16
|
+
}
|
|
17
|
+
};
|
|
18
|
+
schema_1.SchemaRegistry.getInstance().trackSchema(transitionNotFoundSchema);
|
|
19
|
+
exports.default = transitionNotFoundSchema;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { SpruceErrors } from "./errors.types";
|
|
2
|
+
import { ErrorOptions as ISpruceErrorOptions } from "@sprucelabs/error";
|
|
3
|
+
export interface TransitionNotFoundErrorOptions extends SpruceErrors.JestJiraReporter.TransitionNotFound, ISpruceErrorOptions {
|
|
4
|
+
code: 'TRANSITION_NOT_FOUND';
|
|
5
|
+
}
|
|
6
|
+
type ErrorOptions = TransitionNotFoundErrorOptions;
|
|
7
|
+
export default ErrorOptions;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { FieldDefinitions, FieldDefinitionMap, FieldValueTypeGeneratorMap, FieldMap } from '@sprucelabs/schema';
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import JiraApi from 'jira-client';
|
|
2
|
+
import { JestTest, JestTestResults } from './jira.types';
|
|
3
|
+
export default class JestReporter {
|
|
4
|
+
protected client: JiraApi;
|
|
5
|
+
static JiraApi: typeof JiraApi;
|
|
6
|
+
private testMap;
|
|
7
|
+
private statusMap;
|
|
8
|
+
private transitions;
|
|
9
|
+
private transitionLoadPromise?;
|
|
10
|
+
constructor(options: JestReporterOptions);
|
|
11
|
+
private getTransitionForStatus;
|
|
12
|
+
private loadTransitions;
|
|
13
|
+
private throwTransitionNotFound;
|
|
14
|
+
private getFirstTestTitle;
|
|
15
|
+
private getJiraCodeForStatus;
|
|
16
|
+
onTestComplete(_: JestTest, testResult: JestTestResults): Promise<void>;
|
|
17
|
+
private optionallyLoadTransitions;
|
|
18
|
+
private getIssueId;
|
|
19
|
+
}
|
|
20
|
+
export interface JestReporterOptions {
|
|
21
|
+
protocol: string;
|
|
22
|
+
host: string;
|
|
23
|
+
apiVersion: string;
|
|
24
|
+
strictSSL: boolean;
|
|
25
|
+
testMap: Record<string, any>;
|
|
26
|
+
}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const schema_1 = require("@sprucelabs/schema");
|
|
7
|
+
const jira_client_1 = __importDefault(require("jira-client"));
|
|
8
|
+
const SpruceError_1 = __importDefault(require("./errors/SpruceError"));
|
|
9
|
+
class JestReporter {
|
|
10
|
+
constructor(options) {
|
|
11
|
+
this.statusMap = {
|
|
12
|
+
passed: 'Done',
|
|
13
|
+
failed: 'In Progress',
|
|
14
|
+
};
|
|
15
|
+
const username = process.env.JIRA_USERNAME;
|
|
16
|
+
const password = process.env.JIRA_PASSWORD;
|
|
17
|
+
const { protocol, host, apiVersion, strictSSL, testMap } = (0, schema_1.assertOptions)(Object.assign(Object.assign({}, options), { env: process.env }), [
|
|
18
|
+
'host',
|
|
19
|
+
'apiVersion',
|
|
20
|
+
'testMap',
|
|
21
|
+
'env.JIRA_USERNAME',
|
|
22
|
+
'env.JIRA_PASSWORD',
|
|
23
|
+
]);
|
|
24
|
+
this.client = new JestReporter.JiraApi({
|
|
25
|
+
protocol,
|
|
26
|
+
host,
|
|
27
|
+
apiVersion,
|
|
28
|
+
strictSSL,
|
|
29
|
+
username,
|
|
30
|
+
password,
|
|
31
|
+
});
|
|
32
|
+
this.testMap = testMap;
|
|
33
|
+
}
|
|
34
|
+
getTransitionForStatus(status) {
|
|
35
|
+
const code = this.getJiraCodeForStatus(status);
|
|
36
|
+
const transition = this.transitions.find((t) => t.name === code);
|
|
37
|
+
if (!transition) {
|
|
38
|
+
this.throwTransitionNotFound(code);
|
|
39
|
+
}
|
|
40
|
+
return transition;
|
|
41
|
+
}
|
|
42
|
+
async loadTransitions() {
|
|
43
|
+
const { transitions } = await this.client.listTransitions(this.getIssueId(this.getFirstTestTitle()));
|
|
44
|
+
this.transitions = transitions;
|
|
45
|
+
}
|
|
46
|
+
throwTransitionNotFound(transitionCode) {
|
|
47
|
+
throw new SpruceError_1.default({
|
|
48
|
+
code: 'TRANSITION_NOT_FOUND',
|
|
49
|
+
transition: transitionCode,
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
getFirstTestTitle() {
|
|
53
|
+
return Object.keys(this.testMap)[0];
|
|
54
|
+
}
|
|
55
|
+
getJiraCodeForStatus(status) {
|
|
56
|
+
return this.statusMap[status];
|
|
57
|
+
}
|
|
58
|
+
async onTestComplete(_, testResult) {
|
|
59
|
+
await this.optionallyLoadTransitions();
|
|
60
|
+
const { testResults } = testResult;
|
|
61
|
+
for (const test of testResults) {
|
|
62
|
+
const issueId = this.getIssueId(test.title);
|
|
63
|
+
await this.client.transitionIssue(issueId, {
|
|
64
|
+
transition: this.getTransitionForStatus(test.status),
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
async optionallyLoadTransitions() {
|
|
69
|
+
if (!this.transitionLoadPromise) {
|
|
70
|
+
this.transitionLoadPromise = this.loadTransitions();
|
|
71
|
+
}
|
|
72
|
+
await this.transitionLoadPromise;
|
|
73
|
+
}
|
|
74
|
+
getIssueId(title) {
|
|
75
|
+
return this.testMap[title];
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
JestReporter.JiraApi = jira_client_1.default;
|
|
79
|
+
exports.default = JestReporter;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import BaseSpruceError from '@sprucelabs/error';
|
|
2
|
+
import ErrorOptions from "./../.spruce/errors/options.types";
|
|
3
|
+
export default class SpruceError extends BaseSpruceError<ErrorOptions> {
|
|
4
|
+
/** an easy to understand version of the errors */
|
|
5
|
+
friendlyMessage(): string;
|
|
6
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const error_1 = __importDefault(require("@sprucelabs/error"));
|
|
7
|
+
class SpruceError extends error_1.default {
|
|
8
|
+
/** an easy to understand version of the errors */
|
|
9
|
+
friendlyMessage() {
|
|
10
|
+
const { options } = this;
|
|
11
|
+
let message;
|
|
12
|
+
switch (options === null || options === void 0 ? void 0 : options.code) {
|
|
13
|
+
case 'TRANSITION_NOT_FOUND':
|
|
14
|
+
message = 'A Transition not found just happened!';
|
|
15
|
+
break;
|
|
16
|
+
default:
|
|
17
|
+
message = super.friendlyMessage();
|
|
18
|
+
}
|
|
19
|
+
const fullMessage = options.friendlyMessage
|
|
20
|
+
? options.friendlyMessage
|
|
21
|
+
: message;
|
|
22
|
+
return fullMessage;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
exports.default = SpruceError;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
declare const _default: {
|
|
2
|
+
id: string;
|
|
3
|
+
name: string;
|
|
4
|
+
fields: {
|
|
5
|
+
transition: {
|
|
6
|
+
type: "select";
|
|
7
|
+
label: string;
|
|
8
|
+
isRequired: true;
|
|
9
|
+
options: {
|
|
10
|
+
choices: {
|
|
11
|
+
value: string;
|
|
12
|
+
label: string;
|
|
13
|
+
}[];
|
|
14
|
+
};
|
|
15
|
+
};
|
|
16
|
+
};
|
|
17
|
+
};
|
|
18
|
+
export default _default;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const schema_1 = require("@sprucelabs/schema");
|
|
4
|
+
exports.default = (0, schema_1.buildErrorSchema)({
|
|
5
|
+
id: 'transitionNotFound',
|
|
6
|
+
name: 'Transition not found',
|
|
7
|
+
fields: {
|
|
8
|
+
transition: {
|
|
9
|
+
type: 'select',
|
|
10
|
+
label: 'Transition',
|
|
11
|
+
isRequired: true,
|
|
12
|
+
options: {
|
|
13
|
+
choices: [
|
|
14
|
+
{
|
|
15
|
+
value: 'In Progress',
|
|
16
|
+
label: 'In Progress',
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
value: 'Done',
|
|
20
|
+
label: 'Done',
|
|
21
|
+
},
|
|
22
|
+
],
|
|
23
|
+
},
|
|
24
|
+
},
|
|
25
|
+
},
|
|
26
|
+
});
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { default as SchemaEntity } from '@sprucelabs/schema';
|
|
2
|
+
import * as SpruceSchema from '@sprucelabs/schema';
|
|
3
|
+
export declare namespace SpruceErrors.JestJiraReporter {
|
|
4
|
+
interface TransitionNotFound {
|
|
5
|
+
/** Transition. */
|
|
6
|
+
'transition': ("In Progress" | "Done");
|
|
7
|
+
}
|
|
8
|
+
interface TransitionNotFoundSchema extends SpruceSchema.Schema {
|
|
9
|
+
id: 'transitionNotFound';
|
|
10
|
+
namespace: 'JestJiraReporter';
|
|
11
|
+
name: 'Transition not found';
|
|
12
|
+
fields: {
|
|
13
|
+
/** Transition. */
|
|
14
|
+
'transition': {
|
|
15
|
+
label: 'Transition';
|
|
16
|
+
type: 'select';
|
|
17
|
+
isRequired: true;
|
|
18
|
+
options: {
|
|
19
|
+
choices: [{
|
|
20
|
+
"value": "In Progress";
|
|
21
|
+
"label": "In Progress";
|
|
22
|
+
}, {
|
|
23
|
+
"value": "Done";
|
|
24
|
+
"label": "Done";
|
|
25
|
+
}];
|
|
26
|
+
};
|
|
27
|
+
};
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
type TransitionNotFoundEntity = SchemaEntity<SpruceErrors.JestJiraReporter.TransitionNotFoundSchema>;
|
|
31
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { SpruceErrors } from "./errors.types";
|
|
2
|
+
import { ErrorOptions as ISpruceErrorOptions } from "@sprucelabs/error";
|
|
3
|
+
export interface TransitionNotFoundErrorOptions extends SpruceErrors.JestJiraReporter.TransitionNotFound, ISpruceErrorOptions {
|
|
4
|
+
code: 'TRANSITION_NOT_FOUND';
|
|
5
|
+
}
|
|
6
|
+
type ErrorOptions = TransitionNotFoundErrorOptions;
|
|
7
|
+
export default ErrorOptions;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import JiraApi from 'jira-client';
|
|
2
|
+
import { JestTest, JestTestResults } from './jira.types';
|
|
3
|
+
export default class JestReporter {
|
|
4
|
+
protected client: JiraApi;
|
|
5
|
+
static JiraApi: typeof JiraApi;
|
|
6
|
+
private testMap;
|
|
7
|
+
private statusMap;
|
|
8
|
+
private transitions;
|
|
9
|
+
private transitionLoadPromise?;
|
|
10
|
+
constructor(options: JestReporterOptions);
|
|
11
|
+
private getTransitionForStatus;
|
|
12
|
+
private loadTransitions;
|
|
13
|
+
private throwTransitionNotFound;
|
|
14
|
+
private getFirstTestTitle;
|
|
15
|
+
private getJiraCodeForStatus;
|
|
16
|
+
onTestComplete(_: JestTest, testResult: JestTestResults): Promise<void>;
|
|
17
|
+
private optionallyLoadTransitions;
|
|
18
|
+
private getIssueId;
|
|
19
|
+
}
|
|
20
|
+
export interface JestReporterOptions {
|
|
21
|
+
protocol: string;
|
|
22
|
+
host: string;
|
|
23
|
+
apiVersion: string;
|
|
24
|
+
strictSSL: boolean;
|
|
25
|
+
testMap: Record<string, any>;
|
|
26
|
+
}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
+
});
|
|
9
|
+
};
|
|
10
|
+
import { assertOptions } from '@sprucelabs/schema';
|
|
11
|
+
import JiraApi from 'jira-client';
|
|
12
|
+
import SpruceError from './errors/SpruceError.js';
|
|
13
|
+
class JestReporter {
|
|
14
|
+
constructor(options) {
|
|
15
|
+
this.statusMap = {
|
|
16
|
+
passed: 'Done',
|
|
17
|
+
failed: 'In Progress',
|
|
18
|
+
};
|
|
19
|
+
const username = process.env.JIRA_USERNAME;
|
|
20
|
+
const password = process.env.JIRA_PASSWORD;
|
|
21
|
+
const { protocol, host, apiVersion, strictSSL, testMap } = assertOptions(Object.assign(Object.assign({}, options), { env: process.env }), [
|
|
22
|
+
'host',
|
|
23
|
+
'apiVersion',
|
|
24
|
+
'testMap',
|
|
25
|
+
'env.JIRA_USERNAME',
|
|
26
|
+
'env.JIRA_PASSWORD',
|
|
27
|
+
]);
|
|
28
|
+
this.client = new JestReporter.JiraApi({
|
|
29
|
+
protocol,
|
|
30
|
+
host,
|
|
31
|
+
apiVersion,
|
|
32
|
+
strictSSL,
|
|
33
|
+
username,
|
|
34
|
+
password,
|
|
35
|
+
});
|
|
36
|
+
this.testMap = testMap;
|
|
37
|
+
}
|
|
38
|
+
getTransitionForStatus(status) {
|
|
39
|
+
const code = this.getJiraCodeForStatus(status);
|
|
40
|
+
const transition = this.transitions.find((t) => t.name === code);
|
|
41
|
+
if (!transition) {
|
|
42
|
+
this.throwTransitionNotFound(code);
|
|
43
|
+
}
|
|
44
|
+
return transition;
|
|
45
|
+
}
|
|
46
|
+
loadTransitions() {
|
|
47
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
48
|
+
const { transitions } = yield this.client.listTransitions(this.getIssueId(this.getFirstTestTitle()));
|
|
49
|
+
this.transitions = transitions;
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
throwTransitionNotFound(transitionCode) {
|
|
53
|
+
throw new SpruceError({
|
|
54
|
+
code: 'TRANSITION_NOT_FOUND',
|
|
55
|
+
transition: transitionCode,
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
getFirstTestTitle() {
|
|
59
|
+
return Object.keys(this.testMap)[0];
|
|
60
|
+
}
|
|
61
|
+
getJiraCodeForStatus(status) {
|
|
62
|
+
return this.statusMap[status];
|
|
63
|
+
}
|
|
64
|
+
onTestComplete(_, testResult) {
|
|
65
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
66
|
+
yield this.optionallyLoadTransitions();
|
|
67
|
+
const { testResults } = testResult;
|
|
68
|
+
for (const test of testResults) {
|
|
69
|
+
const issueId = this.getIssueId(test.title);
|
|
70
|
+
yield this.client.transitionIssue(issueId, {
|
|
71
|
+
transition: this.getTransitionForStatus(test.status),
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
optionallyLoadTransitions() {
|
|
77
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
78
|
+
if (!this.transitionLoadPromise) {
|
|
79
|
+
this.transitionLoadPromise = this.loadTransitions();
|
|
80
|
+
}
|
|
81
|
+
yield this.transitionLoadPromise;
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
getIssueId(title) {
|
|
85
|
+
return this.testMap[title];
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
JestReporter.JiraApi = JiraApi;
|
|
89
|
+
export default JestReporter;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import BaseSpruceError from '@sprucelabs/error';
|
|
2
|
+
import ErrorOptions from "./../.spruce/errors/options.types";
|
|
3
|
+
export default class SpruceError extends BaseSpruceError<ErrorOptions> {
|
|
4
|
+
/** an easy to understand version of the errors */
|
|
5
|
+
friendlyMessage(): string;
|
|
6
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import BaseSpruceError from '@sprucelabs/error';
|
|
2
|
+
export default class SpruceError extends BaseSpruceError {
|
|
3
|
+
/** an easy to understand version of the errors */
|
|
4
|
+
friendlyMessage() {
|
|
5
|
+
const { options } = this;
|
|
6
|
+
let message;
|
|
7
|
+
switch (options === null || options === void 0 ? void 0 : options.code) {
|
|
8
|
+
case 'TRANSITION_NOT_FOUND':
|
|
9
|
+
message = 'A Transition not found just happened!';
|
|
10
|
+
break;
|
|
11
|
+
default:
|
|
12
|
+
message = super.friendlyMessage();
|
|
13
|
+
}
|
|
14
|
+
const fullMessage = options.friendlyMessage
|
|
15
|
+
? options.friendlyMessage
|
|
16
|
+
: message;
|
|
17
|
+
return fullMessage;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
declare const _default: {
|
|
2
|
+
id: string;
|
|
3
|
+
name: string;
|
|
4
|
+
fields: {
|
|
5
|
+
transition: {
|
|
6
|
+
type: "select";
|
|
7
|
+
label: string;
|
|
8
|
+
isRequired: true;
|
|
9
|
+
options: {
|
|
10
|
+
choices: {
|
|
11
|
+
value: string;
|
|
12
|
+
label: string;
|
|
13
|
+
}[];
|
|
14
|
+
};
|
|
15
|
+
};
|
|
16
|
+
};
|
|
17
|
+
};
|
|
18
|
+
export default _default;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { buildErrorSchema } from '@sprucelabs/schema';
|
|
2
|
+
export default buildErrorSchema({
|
|
3
|
+
id: 'transitionNotFound',
|
|
4
|
+
name: 'Transition not found',
|
|
5
|
+
fields: {
|
|
6
|
+
transition: {
|
|
7
|
+
type: 'select',
|
|
8
|
+
label: 'Transition',
|
|
9
|
+
isRequired: true,
|
|
10
|
+
options: {
|
|
11
|
+
choices: [
|
|
12
|
+
{
|
|
13
|
+
value: 'In Progress',
|
|
14
|
+
label: 'In Progress',
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
value: 'Done',
|
|
18
|
+
label: 'Done',
|
|
19
|
+
},
|
|
20
|
+
],
|
|
21
|
+
},
|
|
22
|
+
},
|
|
23
|
+
},
|
|
24
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
require('dotenv').config();
|
|
2
|
+
import JestReporter from './JestReporter.js';
|
|
3
|
+
const reporter = new JestReporter({
|
|
4
|
+
protocol: 'https',
|
|
5
|
+
host: 'lumenalabs.atlassian.net/',
|
|
6
|
+
apiVersion: '2',
|
|
7
|
+
strictSSL: true,
|
|
8
|
+
testMap: { test1: 'LTEST-1', test2: 'LTEST-2' },
|
|
9
|
+
});
|
|
10
|
+
reporter.onTestComplete({}, {
|
|
11
|
+
testResults: [
|
|
12
|
+
{ title: 'test1', status: 'failed' },
|
|
13
|
+
{ title: 'test2', status: 'passed' },
|
|
14
|
+
],
|
|
15
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/build/index.d.ts
ADDED
package/build/index.js
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const JestReporter_1 = __importDefault(require("./JestReporter"));
|
|
7
|
+
exports.default = JestReporter_1.default;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
require('dotenv').config();
|
|
7
|
+
const JestReporter_1 = __importDefault(require("./JestReporter"));
|
|
8
|
+
const reporter = new JestReporter_1.default({
|
|
9
|
+
protocol: 'https',
|
|
10
|
+
host: 'lumenalabs.atlassian.net/',
|
|
11
|
+
apiVersion: '2',
|
|
12
|
+
strictSSL: true,
|
|
13
|
+
testMap: { test1: 'LTEST-1', test2: 'LTEST-2' },
|
|
14
|
+
});
|
|
15
|
+
reporter.onTestComplete({}, {
|
|
16
|
+
testResults: [
|
|
17
|
+
{ title: 'test1', status: 'failed' },
|
|
18
|
+
{ title: 'test2', status: 'passed' },
|
|
19
|
+
],
|
|
20
|
+
});
|
package/package.json
ADDED
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@sprucelabs/jest-jira-reporter",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"files": [
|
|
5
|
+
"build"
|
|
6
|
+
],
|
|
7
|
+
"main": "./build/index.js",
|
|
8
|
+
"types": "./build/index.d.ts",
|
|
9
|
+
"module": "./build/esm/index.js",
|
|
10
|
+
"sideEffects": false,
|
|
11
|
+
"keywords": [
|
|
12
|
+
"node",
|
|
13
|
+
"components",
|
|
14
|
+
"sprucebot",
|
|
15
|
+
"sprucelabs"
|
|
16
|
+
],
|
|
17
|
+
"license": "MIT",
|
|
18
|
+
"skill": {
|
|
19
|
+
"namespace": "jest-jira-reporter"
|
|
20
|
+
},
|
|
21
|
+
"scripts": {
|
|
22
|
+
"build.ci": "yarn build.tsc && yarn build.resolve-paths && yarn lint",
|
|
23
|
+
"build.dev": "yarn build.tsc --sourceMap ; yarn resolve-paths.lint",
|
|
24
|
+
"build.dist": "tsc --project tsconfig.dist.json && yarn build.resolve-paths && mv build esm && yarn build.esm-postbuild && yarn build.tsc && yarn build.resolve-paths && mv esm build/ && yarn clean.dist",
|
|
25
|
+
"build.copy-files": "mkdir -p build && rsync -avzq --exclude='*.ts' ./src/ ./build/",
|
|
26
|
+
"build.esm-postbuild": "esm-postbuild --target esm --patterns '**/*.js'",
|
|
27
|
+
"build.resolve-paths": "resolve-path-aliases --target build --patterns '**/*.js,**/*.d.ts'",
|
|
28
|
+
"build.tsc": "yarn build.copy-files && tsc",
|
|
29
|
+
"clean": "yarn clean.build",
|
|
30
|
+
"clean.all": "yarn clean.dependencies && yarn clean.build",
|
|
31
|
+
"clean.build": "rm -rf build/",
|
|
32
|
+
"clean.dependencies": "rm -rf node_modules/ package-lock.json yarn.lock",
|
|
33
|
+
"clean.dist": "rm -rf build/__tests__ build/esm/__tests__",
|
|
34
|
+
"fix.lint": "eslint --fix --cache '**/*.ts'",
|
|
35
|
+
"lint": "eslint --cache '**/*.ts'",
|
|
36
|
+
"lint.tsc": "tsc -p . --noEmit",
|
|
37
|
+
"post.watch.build": "yarn build.copy-files && yarn build.resolve-paths",
|
|
38
|
+
"rebuild": "yarn clean.all && yarn && yarn build.dev",
|
|
39
|
+
"release": "semantic-release",
|
|
40
|
+
"resolve-paths.lint": "yarn build.resolve-paths ; yarn lint",
|
|
41
|
+
"test": "jest",
|
|
42
|
+
"update.dependencies": "yarn clean.dependencies && yarn",
|
|
43
|
+
"watch.build.dev": "tsc-watch --sourceMap --onCompilationComplete 'yarn post.watch.build'",
|
|
44
|
+
"watch.lint": "concurrently 'yarn lint' \"chokidar 'src/**/*' -c 'yarn lint.tsc'\"",
|
|
45
|
+
"watch.rebuild": "yarn clean.all && yarn && yarn watch.build.dev",
|
|
46
|
+
"watch.tsc": "tsc -w"
|
|
47
|
+
},
|
|
48
|
+
"devDependencies": {
|
|
49
|
+
"@sprucelabs/esm-postbuild": "^5.0.47",
|
|
50
|
+
"@sprucelabs/jest-json-reporter": "^7.0.69",
|
|
51
|
+
"@sprucelabs/resolve-path-aliases": "^1.1.234",
|
|
52
|
+
"@sprucelabs/semantic-release": "^4.0.8",
|
|
53
|
+
"@sprucelabs/spruce-test-fixtures": "^60.0.41",
|
|
54
|
+
"@sprucelabs/test": "^8.0.5",
|
|
55
|
+
"@sprucelabs/test-utils": "^4.0.12",
|
|
56
|
+
"@types/jira-client": "^7.1.6",
|
|
57
|
+
"@types/node": "^20.4.8",
|
|
58
|
+
"@types/photoshop": "^25.0.0",
|
|
59
|
+
"chokidar-cli": "^3.0.0",
|
|
60
|
+
"concurrently": "^8.2.0",
|
|
61
|
+
"eslint": "^8.46.0",
|
|
62
|
+
"eslint-config-spruce": "^10.12.0",
|
|
63
|
+
"jest": "^29.6.2",
|
|
64
|
+
"jest-circus": "^29.6.2",
|
|
65
|
+
"prettier": "2.8.8",
|
|
66
|
+
"ts-node": "^10.9.1",
|
|
67
|
+
"tsc-watch": "^6.0.4",
|
|
68
|
+
"tsconfig-paths": "^4.2.0",
|
|
69
|
+
"typescript": "^5.1.6"
|
|
70
|
+
},
|
|
71
|
+
"jest": {
|
|
72
|
+
"testRunner": "jest-circus/runner",
|
|
73
|
+
"maxWorkers": 4,
|
|
74
|
+
"testTimeout": 120000,
|
|
75
|
+
"testEnvironment": "node",
|
|
76
|
+
"testPathIgnorePatterns": [
|
|
77
|
+
"<rootDir>/tmp/",
|
|
78
|
+
"<rootDir>/src/",
|
|
79
|
+
"<rootDir>/node_modules/",
|
|
80
|
+
"<rootDir>/build/__tests__/testDirsAndFiles/"
|
|
81
|
+
],
|
|
82
|
+
"testMatch": [
|
|
83
|
+
"**/__tests__/**/*.test.js?(x)"
|
|
84
|
+
],
|
|
85
|
+
"moduleNameMapper": {
|
|
86
|
+
"^#spruce/(.*)$": "<rootDir>/build/.spruce/$1"
|
|
87
|
+
}
|
|
88
|
+
},
|
|
89
|
+
"dependencies": {
|
|
90
|
+
"@sprucelabs/error": "^5.1.19",
|
|
91
|
+
"@sprucelabs/schema": "^29.0.23",
|
|
92
|
+
"@sprucelabs/spruce-core-schemas": "^39.0.29",
|
|
93
|
+
"@sprucelabs/spruce-skill-utils": "^29.1.50",
|
|
94
|
+
"jira-client": "^8.2.2"
|
|
95
|
+
}
|
|
96
|
+
}
|