@elastic/synthetics 1.0.0-beta.25 → 1.0.0-beta.26

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 (116) hide show
  1. package/README.md +1 -1
  2. package/dist/cli.js +42 -5
  3. package/dist/cli.js.map +1 -1
  4. package/dist/common_types.d.ts +59 -5
  5. package/dist/common_types.d.ts.map +1 -1
  6. package/dist/core/gatherer.d.ts +2 -2
  7. package/dist/core/gatherer.d.ts.map +1 -1
  8. package/dist/core/gatherer.js.map +1 -1
  9. package/dist/core/index.d.ts +4 -0
  10. package/dist/core/index.d.ts.map +1 -1
  11. package/dist/core/index.js +15 -1
  12. package/dist/core/index.js.map +1 -1
  13. package/dist/core/runner.d.ts +10 -58
  14. package/dist/core/runner.d.ts.map +1 -1
  15. package/dist/core/runner.js +88 -49
  16. package/dist/core/runner.js.map +1 -1
  17. package/dist/dsl/journey.d.ts +3 -0
  18. package/dist/dsl/journey.d.ts.map +1 -1
  19. package/dist/dsl/journey.js +15 -0
  20. package/dist/dsl/journey.js.map +1 -1
  21. package/dist/dsl/monitor.d.ts +64 -0
  22. package/dist/dsl/monitor.d.ts.map +1 -0
  23. package/dist/dsl/monitor.js +62 -0
  24. package/dist/dsl/monitor.js.map +1 -0
  25. package/dist/generator/index.d.ts +13 -0
  26. package/dist/generator/index.d.ts.map +1 -0
  27. package/dist/generator/index.js +123 -0
  28. package/dist/generator/index.js.map +1 -0
  29. package/dist/{reporters/reporter.js → generator/utils.d.ts} +3 -3
  30. package/dist/generator/utils.d.ts.map +1 -0
  31. package/dist/generator/utils.js +44 -0
  32. package/dist/generator/utils.js.map +1 -0
  33. package/dist/helpers.d.ts +12 -6
  34. package/dist/helpers.d.ts.map +1 -1
  35. package/dist/helpers.js +33 -43
  36. package/dist/helpers.js.map +1 -1
  37. package/dist/index.d.ts +2 -7
  38. package/dist/index.d.ts.map +1 -1
  39. package/dist/index.js +4 -3
  40. package/dist/index.js.map +1 -1
  41. package/dist/loader.js +4 -4
  42. package/dist/loader.js.map +1 -1
  43. package/dist/options.d.ts +12 -0
  44. package/dist/options.d.ts.map +1 -1
  45. package/dist/options.js +66 -4
  46. package/dist/options.js.map +1 -1
  47. package/dist/plugins/performance.d.ts +1 -16
  48. package/dist/plugins/performance.d.ts.map +1 -1
  49. package/dist/plugins/performance.js.map +1 -1
  50. package/dist/plugins/plugin-manager.d.ts +1 -1
  51. package/dist/push/bundler.d.ts +34 -0
  52. package/dist/push/bundler.d.ts.map +1 -0
  53. package/dist/push/bundler.js +119 -0
  54. package/dist/push/bundler.js.map +1 -0
  55. package/{src/reporters/reporter.ts → dist/push/index.d.ts} +4 -11
  56. package/dist/push/index.d.ts.map +1 -0
  57. package/dist/push/index.js +58 -0
  58. package/dist/push/index.js.map +1 -0
  59. package/dist/{reporters/reporter.d.ts → push/monitor.d.ts} +7 -8
  60. package/dist/push/monitor.d.ts.map +1 -0
  61. package/dist/push/monitor.js +67 -0
  62. package/dist/push/monitor.js.map +1 -0
  63. package/dist/push/plugin.d.ts +33 -0
  64. package/dist/push/plugin.d.ts.map +1 -0
  65. package/dist/push/plugin.js +123 -0
  66. package/dist/push/plugin.js.map +1 -0
  67. package/dist/push/request.d.ts +43 -0
  68. package/dist/push/request.d.ts.map +1 -0
  69. package/dist/push/request.js +95 -0
  70. package/dist/push/request.js.map +1 -0
  71. package/dist/reporters/base.d.ts +14 -6
  72. package/dist/reporters/base.d.ts.map +1 -1
  73. package/dist/reporters/base.js +45 -47
  74. package/dist/reporters/base.js.map +1 -1
  75. package/dist/reporters/index.d.ts +18 -8
  76. package/dist/reporters/index.d.ts.map +1 -1
  77. package/dist/reporters/index.js.map +1 -1
  78. package/dist/reporters/json.d.ts +7 -3
  79. package/dist/reporters/json.d.ts.map +1 -1
  80. package/dist/reporters/json.js +118 -118
  81. package/dist/reporters/json.js.map +1 -1
  82. package/dist/reporters/junit.d.ts +7 -1
  83. package/dist/reporters/junit.d.ts.map +1 -1
  84. package/dist/reporters/junit.js +91 -86
  85. package/dist/reporters/junit.js.map +1 -1
  86. package/dist/tsconfig.tsbuildinfo +1 -1
  87. package/package.json +12 -8
  88. package/src/cli.ts +65 -9
  89. package/src/common_types.ts +69 -5
  90. package/src/core/gatherer.ts +2 -2
  91. package/src/core/index.ts +15 -0
  92. package/src/core/runner.ts +86 -113
  93. package/src/dsl/journey.ts +18 -0
  94. package/src/dsl/monitor.ts +83 -0
  95. package/src/generator/index.ts +159 -0
  96. package/src/generator/utils.ts +41 -0
  97. package/src/helpers.ts +36 -52
  98. package/src/index.ts +9 -1
  99. package/src/loader.ts +4 -4
  100. package/src/options.ts +71 -8
  101. package/src/plugins/performance.ts +1 -17
  102. package/src/push/bundler.ts +99 -0
  103. package/src/push/index.ts +63 -0
  104. package/src/push/monitor.ts +77 -0
  105. package/src/push/plugin.ts +113 -0
  106. package/src/push/request.ts +123 -0
  107. package/src/reporters/base.ts +57 -56
  108. package/src/reporters/index.ts +26 -3
  109. package/src/reporters/json.ts +153 -145
  110. package/src/reporters/junit.ts +98 -93
  111. package/templates/journeys/example.journey.ts +18 -0
  112. package/templates/synthetics.config.ts +19 -0
  113. package/CHANGELOG.md +0 -348
  114. package/NOTICE.txt +0 -221
  115. package/dist/reporters/reporter.d.ts.map +0 -1
  116. package/dist/reporters/reporter.js.map +0 -1
@@ -47,8 +47,12 @@ import {
47
47
  PerfMetrics,
48
48
  Params,
49
49
  Screenshot,
50
+ StartEvent,
51
+ JourneyStartResult,
52
+ StepEndResult,
53
+ JourneyEndResult,
54
+ PageMetrics,
50
55
  } from '../common_types';
51
- import { PageMetrics } from '../plugins';
52
56
 
53
57
  /* eslint-disable @typescript-eslint/no-var-requires */
54
58
  const { version, name } = require('../../package.json');
@@ -296,179 +300,183 @@ export async function gatherScreenshots(
296
300
  }
297
301
 
298
302
  export default class JSONReporter extends BaseReporter {
299
- override _registerListeners() {
303
+ onStart(params: StartEvent) {
300
304
  /**
301
305
  * report the number of journeys that exists on a suite which
302
306
  * could be used for better sharding
303
307
  */
304
- this.runner.on('start', ({ numJourneys, networkConditions }) => {
305
- this.writeJSON({
306
- type: 'synthetics/metadata',
307
- root_fields: {
308
- num_journeys: numJourneys,
309
- },
310
- payload: networkConditions
311
- ? {
312
- network_conditions: networkConditions,
313
- }
314
- : undefined,
315
- });
308
+ this.writeJSON({
309
+ type: 'synthetics/metadata',
310
+ root_fields: {
311
+ num_journeys: params.numJourneys,
312
+ },
313
+ payload: params.networkConditions
314
+ ? {
315
+ network_conditions: params.networkConditions,
316
+ }
317
+ : undefined,
316
318
  });
319
+ }
317
320
 
318
- this.runner.on('journey:register', ({ journey }) => {
319
- this.writeJSON({
320
- type: 'journey/register',
321
- journey,
322
- });
321
+ onJourneyRegister(journey: Journey): void {
322
+ this.writeJSON({
323
+ type: 'journey/register',
324
+ journey,
323
325
  });
326
+ }
324
327
 
325
- this.runner.on('journey:start', ({ journey, timestamp, params }) => {
326
- this.writeJSON({
327
- type: 'journey/start',
328
- journey,
329
- timestamp,
330
- payload: { params, source: journey.callback.toString() },
331
- });
328
+ override onJourneyStart(
329
+ journey: Journey,
330
+ { timestamp, params }: JourneyStartResult
331
+ ) {
332
+ this.writeJSON({
333
+ type: 'journey/start',
334
+ journey,
335
+ timestamp,
336
+ payload: { params, source: journey.callback.toString() },
332
337
  });
338
+ }
333
339
 
334
- this.runner.on(
335
- 'step:end',
336
- ({
337
- journey,
338
- step,
339
- start,
340
- end,
341
- error,
342
- url,
343
- status,
344
- pagemetrics,
345
- traces,
346
- metrics,
347
- filmstrips,
348
- }) => {
349
- this.writeMetrics(journey, step, 'relative_trace', traces);
350
- this.writeMetrics(journey, step, 'experience', metrics);
351
- if (filmstrips) {
352
- // Write each filmstrip separately so that we don't get documents that are too large
353
- filmstrips.forEach((strip, index) => {
354
- this.writeJSON({
355
- type: 'step/filmstrips',
356
- journey,
357
- step,
358
- payload: { index },
359
- root_fields: {
360
- browser: { relative_trace: { start: strip.start } },
361
- },
362
- blob: strip.blob,
363
- blob_mime: strip.mime,
364
- });
365
- });
366
- }
340
+ override onStepEnd(
341
+ journey: Journey,
342
+ step: Step,
343
+ {
344
+ start,
345
+ end,
346
+ error,
347
+ url,
348
+ status,
349
+ pagemetrics,
350
+ traces,
351
+ metrics,
352
+ filmstrips,
353
+ }: StepEndResult
354
+ ) {
355
+ this.writeMetrics(journey, step, 'relative_trace', traces);
356
+ this.writeMetrics(journey, step, 'experience', metrics);
357
+ if (filmstrips) {
358
+ // Write each filmstrip separately so that we don't get documents that are too large
359
+ filmstrips.forEach((strip, index) => {
367
360
  this.writeJSON({
368
- type: 'step/end',
361
+ type: 'step/filmstrips',
369
362
  journey,
370
- step: {
371
- ...step,
372
- duration: {
373
- us: getDurationInUs(end - start),
374
- },
375
- },
376
- url,
377
- error,
378
- payload: {
379
- source: step.callback.toString(),
380
- url,
381
- status,
382
- pagemetrics,
363
+ step,
364
+ payload: { index },
365
+ root_fields: {
366
+ browser: { relative_trace: { start: strip.start } },
383
367
  },
368
+ blob: strip.blob,
369
+ blob_mime: strip.mime,
384
370
  });
385
- }
386
- );
371
+ });
372
+ }
387
373
 
388
- this.runner.on(
389
- 'journey:end',
390
- async ({
391
- journey,
392
- timestamp,
393
- start,
394
- end,
395
- networkinfo,
396
- browserconsole,
374
+ this.writeJSON({
375
+ type: 'step/end',
376
+ journey,
377
+ step: {
378
+ ...step,
379
+ duration: {
380
+ us: getDurationInUs(end - start),
381
+ },
382
+ },
383
+ url,
384
+ error,
385
+ payload: {
386
+ source: step.callback.toString(),
387
+ url,
397
388
  status,
398
- error,
399
- options,
400
- }) => {
401
- const { ssblocks, screenshots } = options;
402
- const writeScreenshots =
403
- screenshots === 'on' ||
404
- (screenshots === 'only-on-failure' && status === 'failed');
405
- if (writeScreenshots) {
406
- await gatherScreenshots(
407
- join(CACHE_PATH, 'screenshots'),
408
- async screenshot => {
409
- const { data, timestamp, step } = screenshot;
410
- if (!data) {
411
- return;
412
- }
413
- if (ssblocks) {
414
- await this.writeScreenshotBlocks(journey, screenshot);
415
- } else {
416
- this.writeJSON({
417
- type: 'step/screenshot',
418
- timestamp,
419
- journey,
420
- step,
421
- blob: data,
422
- blob_mime: 'image/jpeg',
423
- });
424
- }
425
- }
426
- );
427
- }
389
+ pagemetrics,
390
+ },
391
+ });
392
+ }
428
393
 
429
- if (networkinfo) {
430
- networkinfo.forEach(ni => {
431
- const { ecs, payload } = formatNetworkFields(ni);
432
- this.writeJSON({
433
- type: 'journey/network_info',
434
- journey,
435
- timestamp: ni.timestamp,
436
- root_fields: snakeCaseKeys(ecs),
437
- step: ni.step,
438
- payload: snakeCaseKeys(payload),
439
- });
440
- });
441
- }
442
- if (browserconsole) {
443
- browserconsole.forEach(({ timestamp, text, type, step, error }) => {
394
+ override async onJourneyEnd(
395
+ journey: Journey,
396
+ {
397
+ timestamp,
398
+ start,
399
+ end,
400
+ networkinfo,
401
+ browserconsole,
402
+ status,
403
+ error,
404
+ options,
405
+ }: JourneyEndResult
406
+ ) {
407
+ const { ssblocks, screenshots } = options;
408
+ const writeScreenshots =
409
+ screenshots === 'on' ||
410
+ (screenshots === 'only-on-failure' && status === 'failed');
411
+ if (writeScreenshots) {
412
+ await gatherScreenshots(
413
+ join(CACHE_PATH, 'screenshots'),
414
+ async screenshot => {
415
+ const { data, timestamp, step } = screenshot;
416
+ if (!data) {
417
+ return;
418
+ }
419
+ if (ssblocks) {
420
+ await this.writeScreenshotBlocks(journey, screenshot);
421
+ } else {
444
422
  this.writeJSON({
445
- type: 'journey/browserconsole',
446
- journey,
423
+ type: 'step/screenshot',
447
424
  timestamp,
425
+ journey,
448
426
  step,
449
- error,
450
- payload: {
451
- text,
452
- type,
453
- } as Payload,
427
+ blob: data,
428
+ blob_mime: 'image/jpeg',
454
429
  });
455
- });
430
+ }
456
431
  }
432
+ );
433
+ }
457
434
 
435
+ if (networkinfo) {
436
+ networkinfo.forEach(ni => {
437
+ const { ecs, payload } = formatNetworkFields(ni);
458
438
  this.writeJSON({
459
- type: 'journey/end',
439
+ type: 'journey/network_info',
440
+ journey,
441
+ timestamp: ni.timestamp,
442
+ root_fields: snakeCaseKeys(ecs),
443
+ step: ni.step,
444
+ payload: snakeCaseKeys(payload),
445
+ });
446
+ });
447
+ }
448
+
449
+ if (browserconsole) {
450
+ browserconsole.forEach(({ timestamp, text, type, step, error }) => {
451
+ this.writeJSON({
452
+ type: 'journey/browserconsole',
460
453
  journey,
461
454
  timestamp,
455
+ step,
462
456
  error,
463
457
  payload: {
464
- start,
465
- end,
466
- status,
467
- },
458
+ text,
459
+ type,
460
+ } as Payload,
468
461
  });
469
- process.nextTick(() => this.runner.emit('journey:end:reported', {}));
470
- }
471
- );
462
+ });
463
+ }
464
+
465
+ this.writeJSON({
466
+ type: 'journey/end',
467
+ journey,
468
+ timestamp,
469
+ error,
470
+ payload: {
471
+ start,
472
+ end,
473
+ status,
474
+ },
475
+ });
476
+ }
477
+
478
+ override onEnd() {
479
+ this.stream.flushSync();
472
480
  }
473
481
 
474
482
  async writeScreenshotBlocks(journey: Journey, screenshot: Screenshot) {
@@ -23,8 +23,14 @@
23
23
  *
24
24
  */
25
25
 
26
- import { mkdirSync, writeFileSync } from 'fs';
26
+ import { mkdir, writeFile } from 'fs/promises';
27
27
  import { dirname } from 'path';
28
+ import {
29
+ JourneyEndResult,
30
+ JourneyStartResult,
31
+ StepEndResult,
32
+ } from '../common_types';
33
+ import { Journey, Step } from '../dsl';
28
34
  import { formatError, indent, now } from '../helpers';
29
35
  import BaseReporter from './base';
30
36
 
@@ -51,104 +57,103 @@ export default class JUnitReporter extends BaseReporter {
51
57
  private totalTests = 0;
52
58
  private totalFailures = 0;
53
59
  private totalSkipped = 0;
60
+ #journeyMap = new Map<string, XMLEntry>();
54
61
 
55
- override _registerListeners() {
56
- const journeyMap = new Map<string, XMLEntry>();
62
+ override onJourneyStart(journey: Journey, {}: JourneyStartResult) {
63
+ if (!this.#journeyMap.has(journey.name)) {
64
+ const entry = {
65
+ name: 'testsuite',
66
+ attributes: {
67
+ name: journey.name,
68
+ tests: 0,
69
+ failures: 0,
70
+ skipped: 0,
71
+ errors: 0,
72
+ },
73
+ children: [],
74
+ };
75
+ this.#journeyMap.set(journey.name, entry);
76
+ }
77
+ }
57
78
 
58
- this.runner.on('journey:start', ({ journey }) => {
59
- if (!journeyMap.has(journey.name)) {
60
- const entry = {
61
- name: 'testsuite',
62
- attributes: {
63
- name: journey.name,
64
- tests: 0,
65
- failures: 0,
66
- skipped: 0,
67
- errors: 0,
68
- },
69
- children: [],
70
- };
71
- journeyMap.set(journey.name, entry);
72
- }
73
- });
79
+ override onStepEnd(
80
+ journey: Journey,
81
+ step: Step,
82
+ { status, error, start, end }: StepEndResult
83
+ ) {
84
+ if (!this.#journeyMap.has(journey.name)) {
85
+ return;
86
+ }
87
+ const entry = this.#journeyMap.get(journey.name);
88
+ const caseEntry = {
89
+ name: 'testcase',
90
+ attributes: {
91
+ name: step.name,
92
+ classname: journey.name + ' ' + step.name,
93
+ time: end - start,
94
+ },
95
+ children: [],
96
+ };
74
97
 
75
- this.runner.on(
76
- 'step:end',
77
- ({ journey, step, status, error, start, end }) => {
78
- if (!journeyMap.has(journey.name)) {
79
- return;
80
- }
81
- const entry = journeyMap.get(journey.name);
82
- const caseEntry = {
83
- name: 'testcase',
84
- attributes: {
85
- name: step.name,
86
- classname: journey.name + ' ' + step.name,
87
- time: end - start,
88
- },
89
- children: [],
90
- };
98
+ entry.attributes.tests++;
99
+ if (status === 'failed') {
100
+ const { name, message, stack } = formatError(error);
101
+ caseEntry.children.push({
102
+ name: 'failure',
103
+ attributes: {
104
+ message,
105
+ type: name,
106
+ },
107
+ text: stack,
108
+ });
109
+ entry.attributes.failures++;
110
+ } else if (status === 'skipped') {
111
+ caseEntry.children.push({
112
+ name: 'skipped',
113
+ attributes: {
114
+ message: 'previous step failed',
115
+ },
116
+ });
117
+ entry.attributes.skipped++;
118
+ }
119
+ entry.children.push(caseEntry);
120
+ }
91
121
 
92
- entry.attributes.tests++;
93
- if (status === 'failed') {
94
- const { name, message, stack } = formatError(error);
95
- caseEntry.children.push({
96
- name: 'failure',
97
- attributes: {
98
- message,
99
- type: name,
100
- },
101
- text: stack,
102
- });
103
- entry.attributes.failures++;
104
- } else if (status === 'skipped') {
105
- caseEntry.children.push({
106
- name: 'skipped',
107
- attributes: {
108
- message: 'previous step failed',
109
- },
110
- });
111
- entry.attributes.skipped++;
112
- }
113
- entry.children.push(caseEntry);
114
- }
115
- );
122
+ override onJourneyEnd(journey: Journey, {}: JourneyEndResult) {
123
+ if (!this.#journeyMap.has(journey.name)) {
124
+ return;
125
+ }
126
+ const { attributes } = this.#journeyMap.get(journey.name);
127
+ this.totalTests += attributes.tests;
128
+ this.totalFailures += attributes.failures;
129
+ this.totalSkipped += attributes.skipped;
130
+ }
116
131
 
117
- this.runner.on('journey:end', ({ journey }) => {
118
- if (!journeyMap.has(journey.name)) {
119
- return;
120
- }
121
- const { attributes } = journeyMap.get(journey.name);
122
- this.totalTests += attributes.tests;
123
- this.totalFailures += attributes.failures;
124
- this.totalSkipped += attributes.skipped;
125
- });
132
+ override async onEnd() {
133
+ const root: XMLEntry = {
134
+ name: 'testsuites',
135
+ attributes: {
136
+ name: '',
137
+ tests: this.totalTests,
138
+ failures: this.totalFailures,
139
+ skipped: this.totalSkipped,
140
+ errors: 0,
141
+ time: parseInt(String(now())) / 1000,
142
+ },
143
+ children: [...this.#journeyMap.values()],
144
+ };
126
145
 
127
- this.runner.on('end', () => {
128
- const root: XMLEntry = {
129
- name: 'testsuites',
130
- attributes: {
131
- name: '',
132
- tests: this.totalTests,
133
- failures: this.totalFailures,
134
- skipped: this.totalSkipped,
135
- errors: 0,
136
- time: parseInt(String(now())) / 1000,
137
- },
138
- children: [...journeyMap.values()],
139
- };
140
- const output = serializeEntries(root).join('\n');
141
- /**
142
- * write the xml output to a file if specified via env flag
143
- */
144
- const fileName = process.env['SYNTHETICS_JUNIT_FILE'];
145
- if (fileName) {
146
- mkdirSync(dirname(fileName), { recursive: true });
147
- writeFileSync(fileName, output);
148
- } else {
149
- this.write(output);
150
- }
151
- });
146
+ const output = serializeEntries(root).join('\n');
147
+ /**
148
+ * write the xml output to a file if specified via env flag
149
+ */
150
+ const fileName = process.env['SYNTHETICS_JUNIT_FILE'];
151
+ if (fileName) {
152
+ await mkdir(dirname(fileName), { recursive: true });
153
+ await writeFile(fileName, output);
154
+ } else {
155
+ this.write(output);
156
+ }
152
157
  }
153
158
  }
154
159
 
@@ -0,0 +1,18 @@
1
+ import { journey, step, monitor, expect } from '@elastic/synthetics';
2
+
3
+ journey('My Example Journey', ({ page, params }) => {
4
+ // Only relevant for the push command to create
5
+ // monitors in Kibana
6
+ monitor.use({
7
+ id: 'example-monitor',
8
+ schedule: 10,
9
+ });
10
+ step('launch application', async () => {
11
+ await page.goto(params.url);
12
+ });
13
+
14
+ step('assert title', async () => {
15
+ const header = await page.$('h1');
16
+ expect(await header.textContent()).toBe('todos');
17
+ });
18
+ });
@@ -0,0 +1,19 @@
1
+ import type { SyntheticsConfig } from '@elastic/synthetics';
2
+
3
+ export default env => {
4
+ const config: SyntheticsConfig = {
5
+ params: {
6
+ url: 'https://elastic.github.io/synthetics-demo/',
7
+ },
8
+ playwrightOptions: {
9
+ ignoreHTTPSErrors: false,
10
+ },
11
+ };
12
+ if (env !== 'development') {
13
+ /**
14
+ * Override configuration specific to environment
15
+ * Ex: config.params.url = ""
16
+ */
17
+ }
18
+ return config;
19
+ };