testbeats 2.2.1 → 2.2.3

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 CHANGED
@@ -1,5 +1,3 @@
1
- > This npm package has been renamed from [test-results-reporter](https://www.npmjs.com/package/test-results-reporter) to [testbeats](https://www.npmjs.com/package/testbeats). test-results-reporter will soon be phased out, and users are encouraged to transition to testbeats.
2
-
3
1
  <span align="center">
4
2
 
5
3
  ![logo](https://github.com/test-results-reporter/testbeats/raw/main/assets/logo.png)
@@ -37,10 +35,12 @@ Read more about the project at [https://testbeats.com](https://testbeats.com)
37
35
 
38
36
  #### Results in Portal
39
37
 
40
- ![testbeats-failure-summary](./assets/testbeats-failure-summary.png)
38
+ ![testbeats-test-run-case-details](./assets/testbeats-test-run-case-details.png)
41
39
 
42
40
  <br />
43
41
 
42
+ > Read more about the project at [https://testbeats.com](https://testbeats.com)
43
+
44
44
  ## Need Help
45
45
 
46
46
  We use [Github Discussions](https://github.com/test-results-reporter/testbeats/discussions) to receive feedback, discuss ideas & answer questions. Head over to it and feel free to start a discussion. We are always happy to help 😊.
@@ -51,4 +51,9 @@ Like this project! Star it on [Github](https://github.com/test-results-reporter/
51
51
 
52
52
  <br />
53
53
 
54
- > Read more about the project at [https://testbeats.com](https://testbeats.com)
54
+ > Read more about the project at [https://testbeats.com](https://testbeats.com)
55
+
56
+
57
+ ## Notes
58
+
59
+ This npm package has been renamed from [test-results-reporter](https://www.npmjs.com/package/test-results-reporter) to [testbeats](https://www.npmjs.com/package/testbeats). test-results-reporter will soon be phased out, and users are encouraged to transition to testbeats.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "testbeats",
3
- "version": "2.2.1",
3
+ "version": "2.2.3",
4
4
  "description": "Publish test results to Microsoft Teams, Google Chat, Slack and InfluxDB",
5
5
  "main": "src/index.js",
6
6
  "types": "./src/index.d.ts",
@@ -56,7 +56,7 @@
56
56
  "prompts": "^2.4.2",
57
57
  "rosters": "0.0.1",
58
58
  "sade": "^1.8.1",
59
- "test-results-parser": "0.2.5"
59
+ "test-results-parser": "0.2.8"
60
60
  },
61
61
  "devDependencies": {
62
62
  "c8": "^10.1.2",
@@ -99,7 +99,7 @@ class BeatsAttachments {
99
99
  }
100
100
  form.append('file_images', JSON.stringify(file_images));
101
101
  await this.api.uploadAttachments(form.getHeaders(), form.getBuffer());
102
- logger.info(`🏞️ Uploaded ${count} attachments`);
102
+ logger.info(`🏞️ Uploaded ${count} attachments`);
103
103
  }
104
104
  } catch (error) {
105
105
  logger.error(`❌ Unable to upload attachments: ${error.message}`, error);
@@ -128,6 +128,7 @@ class Beats {
128
128
  this.config.extensions.push({
129
129
  name: 'ai-failure-summary',
130
130
  hook: HOOK.AFTER_SUMMARY,
131
+ order: 100,
131
132
  inputs: {
132
133
  data: this.test_run
133
134
  }
@@ -151,6 +152,7 @@ class Beats {
151
152
  this.config.extensions.push({
152
153
  name: 'failure-analysis',
153
154
  hook: HOOK.AFTER_SUMMARY,
155
+ order: 200,
154
156
  inputs: {
155
157
  data: metrics
156
158
  }
@@ -170,6 +172,7 @@ class Beats {
170
172
  this.config.extensions.push({
171
173
  name: 'smart-analysis',
172
174
  hook: HOOK.AFTER_SUMMARY,
175
+ order: 300,
173
176
  inputs: {
174
177
  data: this.test_run
175
178
  }
@@ -225,6 +228,7 @@ class Beats {
225
228
  this.config.extensions.push({
226
229
  name: 'error-clusters',
227
230
  hook: HOOK.AFTER_SUMMARY,
231
+ order: 400,
228
232
  inputs: {
229
233
  data: res.values
230
234
  }
@@ -11,6 +11,7 @@ const { processData } = require('../helpers/helper');
11
11
  const { ExtensionsSetup } = require('../setups/extensions.setup');
12
12
  const pkg = require('../../package.json');
13
13
  const { MIN_NODE_VERSION } = require('../helpers/constants');
14
+ const { sortExtensionsByOrder } = require('../helpers/extension.helper');
14
15
 
15
16
  class PublishCommand {
16
17
 
@@ -212,7 +213,7 @@ class PublishCommand {
212
213
  }
213
214
 
214
215
  async #setupExtensions() {
215
- logger.info('⚙️ Setting up extensions...');
216
+ logger.info('⚙️ Setting up extensions...');
216
217
  try {
217
218
  for (const config of this.configs) {
218
219
  const extensions = config.extensions || [];
@@ -242,6 +243,7 @@ class PublishCommand {
242
243
  }
243
244
  target.extensions = target.extensions || [];
244
245
  target.extensions = config.extensions.concat(target.extensions);
246
+ target.extensions = sortExtensionsByOrder(target.extensions);
245
247
  await target_manager.run(target, result);
246
248
  }
247
249
  } else {
@@ -19,7 +19,7 @@ async function getAutomationBuilds(inputs) {
19
19
  url: `${getBaseUrl(inputs)}/automate/builds.json?limit=100`,
20
20
  auth: {
21
21
  username: inputs.username,
22
- password: inputs.password
22
+ password: inputs.access_key
23
23
  },
24
24
  });
25
25
  }
@@ -34,7 +34,7 @@ async function getAutomationBuildSessions(inputs, build_id) {
34
34
  url: `${getBaseUrl(inputs)}/automate/builds/${build_id}/sessions.json`,
35
35
  auth: {
36
36
  username: inputs.username,
37
- password: inputs.password
37
+ password: inputs.access_key
38
38
  },
39
39
  });
40
40
  }
@@ -100,8 +100,28 @@ function addChatExtension({ payload, extension, text }) {
100
100
  });
101
101
  }
102
102
 
103
+ /**
104
+ * Sort extensions by their order property.
105
+ * Extensions without order will appear last, maintaining their original relative order.
106
+ *
107
+ * @param {import("..").IExtension[]} extensions - the extensions array to sort
108
+ * @return {import("..").IExtension[]} sorted extensions array
109
+ */
110
+ function sortExtensionsByOrder(extensions) {
111
+ if (!extensions || !Array.isArray(extensions)) {
112
+ return extensions;
113
+ }
114
+
115
+ return extensions.slice().sort((a, b) => {
116
+ const orderA = typeof a.order === 'number' ? a.order : 1000;
117
+ const orderB = typeof b.order === 'number' ? b.order : 1000;
118
+ return orderA - orderB;
119
+ });
120
+ }
121
+
103
122
  module.exports = {
104
123
  addSlackExtension,
105
124
  addTeamsExtension,
106
- addChatExtension
125
+ addChatExtension,
126
+ sortExtensionsByOrder
107
127
  }
package/src/index.d.ts CHANGED
@@ -2,7 +2,9 @@ import { PerformanceParseOptions } from 'performance-results-parser';
2
2
  import PerformanceTestResult from 'performance-results-parser/src/models/PerformanceTestResult';
3
3
  import { Schedule, User } from 'rosters';
4
4
  import { ParseOptions } from 'test-results-parser';
5
- export import TestResult from 'test-results-parser/src/models/TestResult';
5
+ import TestResult from 'test-results-parser/src/models/TestResult';
6
+
7
+ export { TestResult };
6
8
 
7
9
  export interface ITarget {
8
10
  name: TargetName;
@@ -17,6 +19,7 @@ export interface IExtension {
17
19
  enable?: string | boolean;
18
20
  condition?: Condition;
19
21
  hook?: Hook;
22
+ order?: number;
20
23
  inputs?: ReportPortalAnalysisInputs | ReportPortalHistoryInputs | HyperlinkInputs | MentionInputs | QuickChartTestSummaryInputs | PercyAnalysisInputs | CustomExtensionInputs | MetadataInputs | CIInfoInputs | AIFailureSummaryInputs | BrowserstackInputs;
21
24
  }
22
25
 
@@ -229,7 +232,9 @@ export interface TargetInputs {
229
232
  metrics?: MetricConfig[];
230
233
  }
231
234
 
232
- export interface SlackInputs extends TargetInputs { }
235
+ export interface SlackInputs extends TargetInputs {
236
+ message_format?: 'blocks' | 'attachments';
237
+ }
233
238
 
234
239
  export interface TeamsInputs extends TargetInputs {
235
240
  width?: string;
@@ -9,7 +9,11 @@ const { getValidMetrics, getMetricValuesText } = require('../helpers/performance
9
9
  const TestResult = require('test-results-parser/src/models/TestResult');
10
10
  const { getPlatform } = require('../platforms');
11
11
 
12
-
12
+ const STATUSES = {
13
+ GOOD: ':white_check_mark:',
14
+ WARNING: ':warning:',
15
+ DANGER: ':x:'
16
+ }
13
17
 
14
18
  const COLORS = {
15
19
  GOOD: '#36A64F',
@@ -78,7 +82,15 @@ function getTitleText(result, target, {allowTitleLink = true} = {}) {
78
82
  if (allowTitleLink && target.inputs.title_link) {
79
83
  text = `<${target.inputs.title_link}|${text}>`;
80
84
  }
81
- return text;
85
+ if (target.inputs.message_format === 'blocks') {
86
+ if (result.status !== 'PASS') {
87
+ return `${STATUSES.DANGER} ${text}`;
88
+ } else {
89
+ return `${STATUSES.GOOD} ${text}`;
90
+ }
91
+ } else {
92
+ return text;
93
+ }
82
94
  }
83
95
 
84
96
  function getResultText(result) {
@@ -160,15 +172,25 @@ function getRootPayload({ result, target, payload }) {
160
172
  color = COLORS.DANGER;
161
173
  }
162
174
  }
163
- return {
164
- "attachments": [
165
- {
166
- "color": color,
167
- "blocks": payload.blocks,
168
- "fallback": `${getTitleText(result, target, {allowTitleLink: false})}\nResults: ${getResultText(result)}`,
169
- }
170
- ]
171
- };
175
+
176
+ const fallback_text = `${getTitleText(result, target, {allowTitleLink: false})}\nResults: ${getResultText(result)}`;
177
+
178
+ if (target.inputs.message_format === 'blocks') {
179
+ return {
180
+ "text": fallback_text,
181
+ "blocks": payload.blocks
182
+ }
183
+ } else {
184
+ return {
185
+ "attachments": [
186
+ {
187
+ "color": color,
188
+ "blocks": payload.blocks,
189
+ "fallback": fallback_text,
190
+ }
191
+ ]
192
+ }
193
+ }
172
194
  }
173
195
 
174
196
  async function setPerformancePayload({ result, target, payload }) {
@@ -280,7 +302,7 @@ async function handleErrors({ target, errors }) {
280
302
  }
281
303
  });
282
304
 
283
- const payload = {
305
+ let payload = {
284
306
  "attachments": [
285
307
  {
286
308
  "color": COLORS.DANGER,
@@ -290,6 +312,13 @@ async function handleErrors({ target, errors }) {
290
312
  ]
291
313
  };
292
314
 
315
+ if (target.inputs.message_format === 'blocks') {
316
+ payload = {
317
+ "text": title, // fallback text
318
+ blocks
319
+ }
320
+ }
321
+
293
322
  return request.post({
294
323
  url: target.inputs.url,
295
324
  body: payload