@elastic/synthetics 1.0.0-beta.25 → 1.0.0-beta.28
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 +2 -2
- package/dist/cli.js +56 -8
- package/dist/cli.js.map +1 -1
- package/dist/common_types.d.ts +59 -5
- package/dist/common_types.d.ts.map +1 -1
- package/dist/core/gatherer.d.ts +2 -2
- package/dist/core/gatherer.d.ts.map +1 -1
- package/dist/core/gatherer.js +2 -2
- package/dist/core/gatherer.js.map +1 -1
- package/dist/core/index.d.ts +4 -0
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js +15 -1
- package/dist/core/index.js.map +1 -1
- package/dist/core/runner.d.ts +10 -58
- package/dist/core/runner.d.ts.map +1 -1
- package/dist/core/runner.js +92 -49
- package/dist/core/runner.js.map +1 -1
- package/dist/dsl/journey.d.ts +3 -0
- package/dist/dsl/journey.d.ts.map +1 -1
- package/dist/dsl/journey.js +15 -0
- package/dist/dsl/journey.js.map +1 -1
- package/dist/{reporters/reporter.d.ts → dsl/locations.d.ts} +12 -8
- package/dist/dsl/locations.d.ts.map +1 -0
- package/dist/dsl/locations.js +41 -0
- package/dist/dsl/locations.js.map +1 -0
- package/dist/dsl/monitor.d.ts +65 -0
- package/dist/dsl/monitor.d.ts.map +1 -0
- package/dist/dsl/monitor.js +63 -0
- package/dist/dsl/monitor.js.map +1 -0
- package/dist/generator/index.d.ts +21 -0
- package/dist/generator/index.d.ts.map +1 -0
- package/dist/generator/index.js +169 -0
- package/dist/generator/index.js.map +1 -0
- package/{src/reporters/reporter.ts → dist/generator/utils.d.ts} +4 -11
- package/dist/generator/utils.d.ts.map +1 -0
- package/dist/generator/utils.js +57 -0
- package/dist/generator/utils.js.map +1 -0
- package/dist/helpers.d.ts +12 -6
- package/dist/helpers.d.ts.map +1 -1
- package/dist/helpers.js +33 -43
- package/dist/helpers.js.map +1 -1
- package/dist/index.d.ts +2 -7
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -3
- package/dist/index.js.map +1 -1
- package/dist/loader.js +4 -4
- package/dist/loader.js.map +1 -1
- package/dist/options.d.ts +7 -0
- package/dist/options.d.ts.map +1 -1
- package/dist/options.js +66 -12
- package/dist/options.js.map +1 -1
- package/dist/plugins/performance.d.ts +1 -16
- package/dist/plugins/performance.d.ts.map +1 -1
- package/dist/plugins/performance.js.map +1 -1
- package/dist/plugins/plugin-manager.d.ts +1 -1
- package/dist/push/bundler.d.ts +34 -0
- package/dist/push/bundler.d.ts.map +1 -0
- package/dist/push/bundler.js +119 -0
- package/dist/push/bundler.js.map +1 -0
- package/dist/{reporters/reporter.js → push/index.d.ts} +4 -3
- package/dist/push/index.d.ts.map +1 -0
- package/dist/push/index.js +58 -0
- package/dist/push/index.js.map +1 -0
- package/dist/push/monitor.d.ts +32 -0
- package/dist/push/monitor.d.ts.map +1 -0
- package/dist/push/monitor.js +62 -0
- package/dist/push/monitor.js.map +1 -0
- package/dist/push/plugin.d.ts +33 -0
- package/dist/push/plugin.d.ts.map +1 -0
- package/dist/push/plugin.js +123 -0
- package/dist/push/plugin.js.map +1 -0
- package/dist/push/request.d.ts +43 -0
- package/dist/push/request.d.ts.map +1 -0
- package/dist/push/request.js +89 -0
- package/dist/push/request.js.map +1 -0
- package/dist/reporters/base.d.ts +14 -6
- package/dist/reporters/base.d.ts.map +1 -1
- package/dist/reporters/base.js +45 -47
- package/dist/reporters/base.js.map +1 -1
- package/dist/reporters/index.d.ts +18 -8
- package/dist/reporters/index.d.ts.map +1 -1
- package/dist/reporters/index.js.map +1 -1
- package/dist/reporters/json.d.ts +7 -3
- package/dist/reporters/json.d.ts.map +1 -1
- package/dist/reporters/json.js +118 -118
- package/dist/reporters/json.js.map +1 -1
- package/dist/reporters/junit.d.ts +7 -1
- package/dist/reporters/junit.d.ts.map +1 -1
- package/dist/reporters/junit.js +91 -86
- package/dist/reporters/junit.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +17 -11
- package/src/cli.ts +91 -14
- package/src/common_types.ts +69 -5
- package/src/core/gatherer.ts +4 -4
- package/src/core/index.ts +15 -0
- package/src/core/runner.ts +93 -113
- package/src/dsl/journey.ts +18 -0
- package/src/dsl/locations.ts +38 -0
- package/src/dsl/monitor.ts +87 -0
- package/src/generator/index.ts +212 -0
- package/src/generator/utils.ts +54 -0
- package/src/helpers.ts +36 -52
- package/src/index.ts +9 -1
- package/src/loader.ts +4 -4
- package/src/options.ts +72 -15
- package/src/plugins/performance.ts +1 -17
- package/src/push/bundler.ts +99 -0
- package/src/push/index.ts +63 -0
- package/src/push/monitor.ts +68 -0
- package/src/push/plugin.ts +113 -0
- package/src/push/request.ts +116 -0
- package/src/reporters/base.ts +57 -56
- package/src/reporters/index.ts +26 -3
- package/src/reporters/json.ts +153 -145
- package/src/reporters/junit.ts +98 -93
- package/templates/.github/workflows/run-synthetics.yml +28 -0
- package/templates/README.md +21 -0
- package/templates/journeys/advanced-example-helpers.ts +54 -0
- package/templates/journeys/advanced-example.journey.ts +43 -0
- package/templates/journeys/example.journey.ts +18 -0
- package/templates/synthetics.config.ts +26 -0
- package/CHANGELOG.md +0 -348
- package/NOTICE.txt +0 -221
- package/dist/reporters/reporter.d.ts.map +0 -1
- package/dist/reporters/reporter.js.map +0 -1
package/src/reporters/json.ts
CHANGED
|
@@ -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
|
-
|
|
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.
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
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
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
});
|
|
321
|
+
onJourneyRegister(journey: Journey): void {
|
|
322
|
+
this.writeJSON({
|
|
323
|
+
type: 'journey/register',
|
|
324
|
+
journey,
|
|
323
325
|
});
|
|
326
|
+
}
|
|
324
327
|
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
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
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
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/
|
|
361
|
+
type: 'step/filmstrips',
|
|
369
362
|
journey,
|
|
370
|
-
step
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
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.
|
|
389
|
-
'
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
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
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
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
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
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: '
|
|
446
|
-
journey,
|
|
423
|
+
type: 'step/screenshot',
|
|
447
424
|
timestamp,
|
|
425
|
+
journey,
|
|
448
426
|
step,
|
|
449
|
-
|
|
450
|
-
|
|
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/
|
|
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
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
},
|
|
458
|
+
text,
|
|
459
|
+
type,
|
|
460
|
+
} as Payload,
|
|
468
461
|
});
|
|
469
|
-
|
|
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) {
|
package/src/reporters/junit.ts
CHANGED
|
@@ -23,8 +23,14 @@
|
|
|
23
23
|
*
|
|
24
24
|
*/
|
|
25
25
|
|
|
26
|
-
import {
|
|
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
|
|
56
|
-
|
|
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
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
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
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
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
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
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
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
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
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
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,28 @@
|
|
|
1
|
+
name: Synthetics Run
|
|
2
|
+
on:
|
|
3
|
+
push:
|
|
4
|
+
branches: [main]
|
|
5
|
+
pull_request:
|
|
6
|
+
schedule:
|
|
7
|
+
- cron: '* 0 * * *'
|
|
8
|
+
jobs:
|
|
9
|
+
todos_tests:
|
|
10
|
+
runs-on: ubuntu-latest
|
|
11
|
+
defaults:
|
|
12
|
+
run:
|
|
13
|
+
working-directory: 'todos/synthetics-tests'
|
|
14
|
+
steps:
|
|
15
|
+
- uses: actions/checkout@v2
|
|
16
|
+
- uses: actions/setup-node@v2
|
|
17
|
+
with:
|
|
18
|
+
node-version: '12.22.3'
|
|
19
|
+
- run: npm install
|
|
20
|
+
- run: "SYNTHETICS_JUNIT_FILE='junit-synthetics.xml' npx @elastic/synthetics . --reporter=junit"
|
|
21
|
+
continue-on-error: true
|
|
22
|
+
- name: Publish Unit Test Results
|
|
23
|
+
uses: EnricoMi/publish-unit-test-result-action@v1.19
|
|
24
|
+
if: always()
|
|
25
|
+
with:
|
|
26
|
+
files: '**/junit-*.xml'
|
|
27
|
+
fail_on: "test failures"
|
|
28
|
+
check_name: Todos Unit Tests
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
## Get started with Elastic Synthetics!
|
|
2
|
+
|
|
3
|
+
Browse the directory structure here to see an example skeleton of an [Elastic Synthetics](https://www.elastic.co/observability/synthetic-monitoring) project.
|
|
4
|
+
Make sure to [read the docs](https://www.elastic.co/guide/en/observability/current/monitor-uptime-synthetics.html) as well if you're unfamiliar with Elastic Synthetics.
|
|
5
|
+
|
|
6
|
+
This directory was created with the command `npx @elastic/synthetics <target-directory>`, with `<target-directory>` being the name of the directory you'd like it to make.
|
|
7
|
+
You can always use this command to create new projects.
|
|
8
|
+
|
|
9
|
+
Key places to look:
|
|
10
|
+
|
|
11
|
+
- The `synthetics.config.ts` file contains configuration for your project.
|
|
12
|
+
- The `journeys` directory contains both basic and more advanced examples of using synthetics. It tests a publicly hosted [Todos List](https://elastic.github.io/synthetics-demo/).
|
|
13
|
+
- The `.github` directory contains an example github action, demonstrating the use of a CI service for automatically running tests on merges and PR creation.
|
|
14
|
+
|
|
15
|
+
To run the tests here simply use the following command:
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
npx @elastic/synthetics .
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
Curious to learn more? [Read the docs](https://www.elastic.co/guide/en/observability/current/monitor-uptime-synthetics.html) to learn about pushing configurations to an Elastic cloud stack and more.
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { step, Page, expect } from '@elastic/synthetics';
|
|
2
|
+
|
|
3
|
+
// This file contains helper files for advanced-example.journey.ts
|
|
4
|
+
// The functions here let you write more concise tests and re-use functionality
|
|
5
|
+
// across tests.
|
|
6
|
+
|
|
7
|
+
export const loadAppStep = (page: Page, url: string) => {
|
|
8
|
+
step('launch app', async () => {
|
|
9
|
+
await page.goto(url);
|
|
10
|
+
});
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
export const addTaskStep = (page: Page, task: string) => {
|
|
14
|
+
step(`add task ${task}`, async () => {
|
|
15
|
+
const input = await page.$('input.new-todo');
|
|
16
|
+
await input.type(task);
|
|
17
|
+
await input.press('Enter');
|
|
18
|
+
});
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
const todosSelector = 'ul.todo-list li.todo';
|
|
22
|
+
|
|
23
|
+
export const findTask = async (page: Page, task: string) => {
|
|
24
|
+
return await page.waitForSelector(`${todosSelector} >> text="${task}"`);
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
export const assertTaskListSizeStep = async (page: Page, size: number) => {
|
|
28
|
+
step(`check that task list has exactly ${size} elements`, async () => {
|
|
29
|
+
expect((await page.$$(todosSelector)).length).toBe(size);
|
|
30
|
+
});
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
export const checkForTaskStep = async (page: Page, task: string) => {
|
|
34
|
+
step(`check for task '${task}' in list`, async () => {
|
|
35
|
+
return findTask(page, task);
|
|
36
|
+
});
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
export const destroyTaskStep = async (page: Page, task: string) => {
|
|
40
|
+
step(`destroy task '${task}'`, async () => {
|
|
41
|
+
const label = await findTask(page, task);
|
|
42
|
+
// xpath indexes arrays starting at 1!!! Easy to forget!
|
|
43
|
+
const li = await label.$('xpath=ancestor::li[1]');
|
|
44
|
+
const destroyButton = await li.$('button');
|
|
45
|
+
|
|
46
|
+
// The destroy button is not visible until hovered. Setup a click test which
|
|
47
|
+
// will wait up to 30s for the button to be visible.
|
|
48
|
+
const clickFuture = destroyButton.click();
|
|
49
|
+
// now hover, making the destroy button clickable
|
|
50
|
+
li.hover();
|
|
51
|
+
// now we are done
|
|
52
|
+
await clickFuture;
|
|
53
|
+
});
|
|
54
|
+
};
|