artillery-plugin-slack 1.12.0 → 1.13.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.
Files changed (2) hide show
  1. package/index.js +60 -39
  2. package/package.json +1 -1
package/index.js CHANGED
@@ -15,7 +15,6 @@ class SlackPlugin {
15
15
  }
16
16
 
17
17
  this.config = script.config.plugins.slack || {};
18
- this.webhook = this.config.webhookUrl;
19
18
 
20
19
  if (!this.config.webhookUrl) {
21
20
  throw new SlackPluginError('Slack webhook URL not provided');
@@ -69,12 +68,14 @@ class SlackPlugin {
69
68
 
70
69
  // When ensure is enabled, whether the beforeExit or the checks event will be triggered first will depend on the order of plugins in the test script
71
70
  // Since we need data from both events, first event triggered will store the data and the second event will send the report
72
- if (
73
- this.exitCode !== undefined &&
74
- this.exitCode !== null &&
75
- this.report &&
76
- !this.reportSent
77
- ) {
71
+
72
+ // Make sure exitCode is properly set before potentially sending the report
73
+ if (this.exitCode === undefined || this.exitCode === null) {
74
+ this.exitCode = global.artillery.suggestedExitCode ?? 0;
75
+ debug('Setting initial exitCode in checks event:', this.exitCode);
76
+ }
77
+
78
+ if (this.report && !this.reportSent) {
78
79
  debug('Sending report from checks event');
79
80
  await this.sendReport(this.report, this.ensureChecks);
80
81
  this.reportSent = true;
@@ -85,7 +86,8 @@ class SlackPlugin {
85
86
  global.artillery.ext({
86
87
  ext: 'beforeExit',
87
88
  method: async (opts) => {
88
- this.exitCode = global.artillery.suggestedExitCode || opts.exitCode;
89
+ this.exitCode =
90
+ global.artillery.suggestedExitCode ?? opts.exitCode ?? 0;
89
91
  if (this.ensureEnabled && !this.ensureChecks && !this.reportSent) {
90
92
  this.report = opts.report;
91
93
  } else {
@@ -111,9 +113,17 @@ class SlackPlugin {
111
113
 
112
114
  assembleSlackPayload(report, ensureChecks) {
113
115
  const errorList = this.getErrors(report);
114
- const duration = report.lastMetricAt - report.firstMetricAt;
116
+ const duration =
117
+ report.lastMetricAt != null && report.firstMetricAt != null
118
+ ? report.lastMetricAt - report.firstMetricAt
119
+ : undefined;
120
+
121
+ // Ensure exitCode has a value before using it
122
+ const exitCode =
123
+ this.exitCode !== undefined && this.exitCode !== null ? this.exitCode : 0;
124
+
115
125
  const headerText =
116
- this.exitCode === 0
126
+ exitCode === 0
117
127
  ? '🟢 Artillery test run finished'
118
128
  : '🔴 Artillery test run failed';
119
129
 
@@ -155,10 +165,14 @@ class SlackPlugin {
155
165
  type: 'mrkdwn',
156
166
  text: `*VUs*\n${report.counters['vusers.completed']} completed / ${report.counters['vusers.created']} created`
157
167
  },
158
- {
159
- type: 'mrkdwn',
160
- text: `*Duration*\n${this.formatDuration(duration)}`
161
- }
168
+ ...(duration != null
169
+ ? [
170
+ {
171
+ type: 'mrkdwn',
172
+ text: `*Duration*\n${formatDuration(duration)}`
173
+ }
174
+ ]
175
+ : [])
162
176
  ]
163
177
  }
164
178
  ];
@@ -248,31 +262,6 @@ class SlackPlugin {
248
262
  }
249
263
  }
250
264
 
251
- formatDuration(durationInMs) {
252
- const duration = moment.duration(durationInMs);
253
- if (durationInMs < 1000) {
254
- return `${durationInMs} miliseconds`;
255
- }
256
- const miliseconds = duration.get('millisecond');
257
- const timeComponents = ['day', 'hour', 'minute', 'second'];
258
- const formatedTimeComponents = timeComponents
259
- .map((component) => {
260
- let value = duration.get(component);
261
- if (component === 'second' && miliseconds) {
262
- value += 1;
263
- }
264
- return value
265
- ? `${value} ${value === 1 ? component : component + 's'}`
266
- : '';
267
- })
268
- .filter((component) => !!component);
269
-
270
- const lastComponent = formatedTimeComponents.pop();
271
- return formatedTimeComponents.length
272
- ? formatedTimeComponents.join(', ') + ' and ' + lastComponent
273
- : lastComponent;
274
- }
275
-
276
265
  async cleanup(done) {
277
266
  debug('Cleaning up');
278
267
  done();
@@ -286,6 +275,38 @@ class SlackPluginError extends Error {
286
275
  }
287
276
  }
288
277
 
278
+ // from artillery/lib/util.js
279
+ function formatDuration(durationInMs) {
280
+ const duration = moment.duration(durationInMs);
281
+
282
+ const days = duration.days();
283
+ const hours = duration.hours();
284
+ const minutes = duration.minutes();
285
+ const seconds = duration.seconds();
286
+
287
+ const timeComponents = [];
288
+ if (days) {
289
+ timeComponents.push(`${days} ${maybePluralize(days, 'day')}`);
290
+ }
291
+
292
+ if (hours || days) {
293
+ timeComponents.push(`${hours} ${maybePluralize(hours, 'hour')}`);
294
+ }
295
+
296
+ if (minutes || hours || days) {
297
+ timeComponents.push(`${minutes} ${maybePluralize(minutes, 'minute')}`);
298
+ }
299
+
300
+ timeComponents.push(`${seconds} ${maybePluralize(seconds, 'second')}`);
301
+
302
+ return timeComponents.join(', ');
303
+ }
304
+
305
+ // from artillery/lib/util.js
306
+ function maybePluralize(amount, singular, plural = `${singular}s`) {
307
+ return amount === 1 ? singular : plural;
308
+ }
309
+
289
310
  module.exports = {
290
311
  Plugin: SlackPlugin,
291
312
  LEGACY_METRICS_FORMAT: false
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "artillery-plugin-slack",
3
- "version": "1.12.0",
3
+ "version": "1.13.0",
4
4
  "description": "Send Artillery.io test notifications to Slack",
5
5
  "main": "index.js",
6
6
  "publishConfig": {