@bigbinary/neeto-playwright-reporter 1.0.1 → 1.1.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/index.cjs.js CHANGED
@@ -1,32 +1,34 @@
1
1
  'use strict';
2
2
 
3
+ var require$$6 = require('fs');
3
4
  var require$$1 = require('util');
4
5
  var stream = require('stream');
5
6
  var require$$1$1 = require('path');
6
7
  var require$$3 = require('http');
7
8
  var require$$4 = require('https');
8
9
  var require$$0$1 = require('url');
9
- var require$$6 = require('fs');
10
10
  var require$$4$1 = require('assert');
11
11
  var require$$1$2 = require('tty');
12
12
  var require$$0$2 = require('os');
13
13
  var zlib = require('zlib');
14
14
  var EventEmitter = require('events');
15
+ var childProcess = require('child_process');
15
16
 
16
17
  function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
17
18
 
19
+ var require$$6__default = /*#__PURE__*/_interopDefaultLegacy(require$$6);
18
20
  var require$$1__default = /*#__PURE__*/_interopDefaultLegacy(require$$1);
19
21
  var stream__default = /*#__PURE__*/_interopDefaultLegacy(stream);
20
22
  var require$$1__default$1 = /*#__PURE__*/_interopDefaultLegacy(require$$1$1);
21
23
  var require$$3__default = /*#__PURE__*/_interopDefaultLegacy(require$$3);
22
24
  var require$$4__default = /*#__PURE__*/_interopDefaultLegacy(require$$4);
23
25
  var require$$0__default = /*#__PURE__*/_interopDefaultLegacy(require$$0$1);
24
- var require$$6__default = /*#__PURE__*/_interopDefaultLegacy(require$$6);
25
26
  var require$$4__default$1 = /*#__PURE__*/_interopDefaultLegacy(require$$4$1);
26
27
  var require$$1__default$2 = /*#__PURE__*/_interopDefaultLegacy(require$$1$2);
27
28
  var require$$0__default$1 = /*#__PURE__*/_interopDefaultLegacy(require$$0$2);
28
29
  var zlib__default = /*#__PURE__*/_interopDefaultLegacy(zlib);
29
30
  var EventEmitter__default = /*#__PURE__*/_interopDefaultLegacy(EventEmitter);
31
+ var childProcess__default = /*#__PURE__*/_interopDefaultLegacy(childProcess);
30
32
 
31
33
  function bind(fn, thisArg) {
32
34
  return function wrap() {
@@ -18446,54 +18448,207 @@ axios.HttpStatusCode = HttpStatusCode;
18446
18448
 
18447
18449
  axios.default = axios;
18448
18450
 
18449
- // dummy endpoint until neeto-playwright-reporter dashboard is up
18450
- const create = (payload) => axios.post(`https://webhook.site/1bff83d0-03a0-412f-a70a-2f11f3209534`, payload);
18451
- const dummyApi = { create };
18452
-
18453
- const getDescribePath = ({ titlePath, title, project, spec, }) => {
18454
- const describePaths = titlePath.filter((item, index) => index !== 0 && item !== title && item !== project && item !== spec);
18455
- return describePaths.join(" > ");
18456
- };
18457
-
18458
18451
  const HEADERS_KEYS = {
18459
18452
  applicationKey: "Application-Key",
18460
- xCsrfToken: "X-CSRF-TOKEN",
18461
18453
  contentType: "Content-Type",
18462
18454
  accept: "Accept",
18455
+ apiKey: "X-Api-Key",
18456
+ projectKey: "Project-Key",
18457
+ };
18458
+ const API_BASE_URL = "/api/v1";
18459
+
18460
+ const create$2 = (ciBuildId, history_id, payload) => axios.post(`${API_BASE_URL}/reporter/runs/${ciBuildId}/test_entities/${history_id}/attempts`, payload, { headers: { "Content-Type": "multipart/form-data" } });
18461
+ const update$1 = (ciBuildId, history_id, id, payload) => axios.put(`${API_BASE_URL}/reporter/runs/${ciBuildId}/test_entities/${history_id}/attempts/${id}`, payload, { headers: { "Content-Type": "multipart/form-data" } });
18462
+ const attemptsApi = { create: create$2, update: update$1 };
18463
+
18464
+ const ERRORS = {
18465
+ onBegin: {
18466
+ failedToGetCommitSha: "Failed to get current commit SHA.",
18467
+ failedToGetCommitMessage: "Failed to get current commit message.",
18468
+ failedToInitializeRun: "Failed to initialize run in reporter",
18469
+ },
18470
+ onTestBegin: {
18471
+ failedToReportTest: (testTitle, historyId) => `Failed to report test "${testTitle}" with history ID ${historyId}`,
18472
+ },
18473
+ onEnd: {
18474
+ failedToReportRunStatus: "Failed to report run status",
18475
+ },
18476
+ };
18477
+
18478
+ const MESSAGES = {
18479
+ onBegin: {
18480
+ testStarted: "Test has started reporting to neetoPlaywrightReporter",
18481
+ ciBuildId: (currentCiBuildId) => `CI BUILD ID: ${currentCiBuildId}`,
18482
+ totalShards: (totalShards) => `Total shards: ${totalShards}`,
18483
+ currentShard: (currentShard) => `Current shard: ${currentShard}`,
18484
+ },
18485
+ };
18486
+
18487
+ const consoleLogFormatted = {
18488
+ bold: (message) => console.log(console.log("\x1b[1m", message, "\x1b[0m")),
18489
+ dim: (message) => console.log(console.log("\x1b[2m", message, "\x1b[0m")),
18490
+ underline: (message) => console.log(console.log("\x1b[4m", message, "\x1b[0m")),
18491
+ invertBackground: (message) => console.log(console.log("\x1b[7m", message, "\x1b[0m")),
18492
+ hidden: (message) => console.log(console.log("\x1b[8m", message, "\x1b[0m")),
18493
+ error: (message) => console.log("\u001b[31m", "\x1b[1m", message, "\x1b[0m", "\u001b[0m"),
18494
+ warning: (message) => console.log("\u001b[33m", "\x1b[1m", message, "\x1b[0m", "\u001b[0m"),
18495
+ };
18496
+ const executeCommandLine = ({ command, messageOnError, shouldThrowError = false, logLevel = "warning", }) => {
18497
+ try {
18498
+ return childProcess__default["default"].execSync(command).toString().trim();
18499
+ }
18500
+ catch (err) {
18501
+ if (shouldThrowError) {
18502
+ throw err;
18503
+ }
18504
+ else {
18505
+ consoleLogFormatted[logLevel](messageOnError);
18506
+ }
18507
+ }
18463
18508
  };
18464
18509
 
18465
- const setAuthHeaders = (applicationKey) => {
18510
+ const createShardObject = ({ currentShard = 0, status = "running", duration = null, }) => ({
18511
+ [currentShard]: { status, duration },
18512
+ });
18513
+ const convertBufferToBlob = (buffer, contentType) => new Blob([buffer], { type: contentType });
18514
+
18515
+ const getDescribePath = ({ titlePath, title, project, spec, }) => titlePath.filter((item, index) => index !== 0 && item !== title && item !== project && item !== spec);
18516
+ const getCurrentCommitSha = () => executeCommandLine({
18517
+ command: "git rev-parse HEAD",
18518
+ messageOnError: ERRORS.onBegin.failedToGetCommitSha,
18519
+ });
18520
+ const getCurrentCommitMessage = () => executeCommandLine({
18521
+ command: "git show-branch --no-name HEAD",
18522
+ messageOnError: ERRORS.onBegin.failedToGetCommitMessage,
18523
+ });
18524
+ const getInitializerData = ({ rootDir }, rootSuite) => rootSuite.allTests().map(test => {
18525
+ var _a;
18526
+ const { title, parent, id: history_id, location: { file }, } = test;
18527
+ const titlePath = test.titlePath();
18528
+ const project = (_a = parent.project()) === null || _a === void 0 ? void 0 : _a.name;
18529
+ const spec = file.replace(`${rootDir}/`, "");
18530
+ const describe = getDescribePath({ titlePath, title, spec, project });
18531
+ return { title, describe, project, spec, history_id };
18532
+ });
18533
+
18534
+ const setAuthHeaders = (projectKey) => {
18535
+ var _a;
18466
18536
  axios.defaults.headers = {
18467
18537
  ...axios.defaults.headers,
18468
- [HEADERS_KEYS.applicationKey]: applicationKey,
18538
+ [HEADERS_KEYS.projectKey]: projectKey,
18539
+ [HEADERS_KEYS.apiKey]: (_a = process.env.API_KEY) !== null && _a !== void 0 ? _a : "",
18469
18540
  [HEADERS_KEYS.accept]: "application/json",
18470
18541
  [HEADERS_KEYS.contentType]: "application/json",
18471
18542
  };
18472
18543
  };
18473
- function initializeAxios(applicationKey) {
18474
- setAuthHeaders(applicationKey);
18544
+ function initializeAxios({ projectKey, baseURL, }) {
18545
+ axios.defaults.baseURL = baseURL;
18546
+ setAuthHeaders(projectKey);
18475
18547
  }
18476
18548
 
18549
+ const create$1 = (payload) => axios.post(`${API_BASE_URL}/reporter/runs`, {
18550
+ run: payload,
18551
+ });
18552
+ const update = (ciBuildId, payload) => axios.put(`${API_BASE_URL}/reporter/runs/${ciBuildId}`, {
18553
+ run: payload,
18554
+ });
18555
+ const runsApi = { create: create$1, update };
18556
+
18557
+ const create = (ciBuildId, payload) => axios.post(`${API_BASE_URL}/reporter/runs/${ciBuildId}/test_entities`, {
18558
+ test_entity: payload,
18559
+ });
18560
+ const testEntitiesApi = { create };
18561
+
18477
18562
  class MyReporter {
18478
18563
  constructor(options) {
18479
- this.onBegin = async (config, suite) => {
18480
- console.log("Run begin".padStart(5, "\n").padEnd(5, "\n"));
18481
- console.log("Config".padStart(20, "*").padEnd(40, "*"));
18482
- console.log(JSON.stringify(config, null, 4));
18483
- console.log("Suite".padStart(20, "*").padEnd(40, "*"));
18484
- const initializerData = suite.allTests().map(test => {
18485
- var _a;
18486
- const { rootDir } = config;
18487
- const { title, parent, id: history_id, location: { file }, } = test;
18488
- const titlePath = test.titlePath();
18489
- const project = (_a = parent.project()) === null || _a === void 0 ? void 0 : _a.name;
18490
- const spec = file.replace(`${rootDir}/`, "");
18491
- const describe = getDescribePath({ titlePath, title, spec, project });
18492
- return { title, describe, project, spec, history_id };
18493
- });
18494
- await dummyApi.create({ test_entity: { initializerData, config } });
18564
+ this.onBegin = async (config, rootSuite) => {
18565
+ const shard = config.shard;
18566
+ let attempts;
18567
+ try {
18568
+ const runDetails = {
18569
+ commit_id: getCurrentCommitSha(),
18570
+ commit_name: getCurrentCommitMessage(),
18571
+ ci_build_id: this.ciBuildId,
18572
+ configuration: config,
18573
+ shards: createShardObject({ currentShard: shard === null || shard === void 0 ? void 0 : shard.current }),
18574
+ };
18575
+ await runsApi.create(runDetails);
18576
+ ({ data: attempts } = await testEntitiesApi.create(this.ciBuildId, {
18577
+ test_entities: getInitializerData(config, rootSuite),
18578
+ }));
18579
+ }
18580
+ catch (error) {
18581
+ consoleLogFormatted.error(error);
18582
+ throw new Error(ERRORS.onBegin.failedToInitializeRun);
18583
+ }
18584
+ consoleLogFormatted.underline(MESSAGES.onBegin.testStarted);
18585
+ consoleLogFormatted.dim(MESSAGES.onBegin.ciBuildId(this.ciBuildId));
18586
+ if (shard) {
18587
+ consoleLogFormatted.dim(MESSAGES.onBegin.totalShards(shard.total));
18588
+ consoleLogFormatted.dim(MESSAGES.onBegin.currentShard(shard.current));
18589
+ }
18590
+ this.attempts = attempts;
18591
+ this.config = config;
18592
+ this.currentShard = shard === null || shard === void 0 ? void 0 : shard.current;
18593
+ };
18594
+ this.onTestBegin = async ({ id, title }, { retry }) => {
18595
+ try {
18596
+ const formData = new FormData();
18597
+ formData.append("attempt[status]", "running");
18598
+ retry === 0 &&
18599
+ (await attemptsApi.update(this.ciBuildId, id, this.attempts[id], formData));
18600
+ }
18601
+ catch (error) {
18602
+ consoleLogFormatted.error(ERRORS.onTestBegin.failedToReportTest(title, id));
18603
+ console.log(error);
18604
+ }
18605
+ };
18606
+ this.onTestEnd = async ({ id, title }, { status, duration, errors, retry, attachments }) => {
18607
+ try {
18608
+ const testResult = {
18609
+ status,
18610
+ duration,
18611
+ log: errors.map(error => { var _a; return (_a = error.message) !== null && _a !== void 0 ? _a : ""; }).join("\n"),
18612
+ };
18613
+ consoleLogFormatted.underline(title);
18614
+ const formData = new FormData();
18615
+ attachments.map(({ name, path, body, contentType }) => {
18616
+ consoleLogFormatted.dim(`${name}: ${path}`);
18617
+ if (["screenshot", "video", "trace"].includes(name)) {
18618
+ const buffer = path ? require$$6__default["default"].readFileSync(path) : body;
18619
+ formData.append(`attempt[${name}s][]`, convertBufferToBlob(buffer, contentType));
18620
+ }
18621
+ });
18622
+ Object.entries(testResult).map(([resultKey, resultValue]) => {
18623
+ formData.append(`attempt[${resultKey}]`, resultValue.toString());
18624
+ });
18625
+ retry === 0
18626
+ ? await attemptsApi.update(this.ciBuildId, id, this.attempts[id], formData)
18627
+ : await attemptsApi.create(this.ciBuildId, id, formData);
18628
+ }
18629
+ catch (error) {
18630
+ consoleLogFormatted.error(ERRORS.onTestBegin.failedToReportTest(title, id));
18631
+ console.log(error);
18632
+ }
18633
+ };
18634
+ this.onEnd = async ({ status, duration }) => {
18635
+ try {
18636
+ await runsApi.update(this.ciBuildId, {
18637
+ shards: createShardObject({
18638
+ currentShard: this.currentShard,
18639
+ status,
18640
+ duration,
18641
+ }),
18642
+ });
18643
+ }
18644
+ catch (error) {
18645
+ console.log(error);
18646
+ throw new Error(ERRORS.onEnd.failedToReportRunStatus);
18647
+ }
18495
18648
  };
18496
- initializeAxios(options.applicationKey);
18649
+ initializeAxios(options);
18650
+ this.attempts = {};
18651
+ this.ciBuildId = options.ciBuildId;
18497
18652
  }
18498
18653
  }
18499
18654