@azure/microsoft-playwright-testing 1.0.0-alpha.20240911.2
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/CHANGELOG.md +17 -0
- package/LICENSE +21 -0
- package/README.md +151 -0
- package/dist/common/constants.d.ts +92 -0
- package/dist/common/constants.d.ts.map +1 -0
- package/dist/common/constants.js +222 -0
- package/dist/common/constants.js.map +1 -0
- package/dist/common/customerConfig.d.ts +9 -0
- package/dist/common/customerConfig.d.ts.map +1 -0
- package/dist/common/customerConfig.js +15 -0
- package/dist/common/customerConfig.js.map +1 -0
- package/dist/common/entraIdAccessToken.d.ts +12 -0
- package/dist/common/entraIdAccessToken.d.ts.map +1 -0
- package/dist/common/entraIdAccessToken.js +72 -0
- package/dist/common/entraIdAccessToken.js.map +1 -0
- package/dist/common/environmentVariables.d.ts +12 -0
- package/dist/common/environmentVariables.d.ts.map +1 -0
- package/dist/common/environmentVariables.js +17 -0
- package/dist/common/environmentVariables.js.map +1 -0
- package/dist/common/executor.d.ts +2 -0
- package/dist/common/executor.d.ts.map +1 -0
- package/dist/common/executor.js +79 -0
- package/dist/common/executor.js.map +1 -0
- package/dist/common/httpService.d.ts +5 -0
- package/dist/common/httpService.d.ts.map +1 -0
- package/dist/common/httpService.js +37 -0
- package/dist/common/httpService.js.map +1 -0
- package/dist/common/logger.d.ts +3 -0
- package/dist/common/logger.d.ts.map +1 -0
- package/dist/common/logger.js +9 -0
- package/dist/common/logger.js.map +1 -0
- package/dist/common/messages.d.ts +9 -0
- package/dist/common/messages.d.ts.map +1 -0
- package/dist/common/messages.js +14 -0
- package/dist/common/messages.js.map +1 -0
- package/dist/common/multimap.d.ts +16 -0
- package/dist/common/multimap.d.ts.map +1 -0
- package/dist/common/multimap.js +64 -0
- package/dist/common/multimap.js.map +1 -0
- package/dist/common/playwrightServiceConfig.d.ts +12 -0
- package/dist/common/playwrightServiceConfig.d.ts.map +1 -0
- package/dist/common/playwrightServiceConfig.js +39 -0
- package/dist/common/playwrightServiceConfig.js.map +1 -0
- package/dist/common/types.d.ts +301 -0
- package/dist/common/types.d.ts.map +1 -0
- package/dist/common/types.js +5 -0
- package/dist/common/types.js.map +1 -0
- package/dist/core/global/playwright-service-global-setup.d.ts +4 -0
- package/dist/core/global/playwright-service-global-setup.d.ts.map +1 -0
- package/dist/core/global/playwright-service-global-setup.js +19 -0
- package/dist/core/global/playwright-service-global-setup.js.map +1 -0
- package/dist/core/global/playwright-service-global-teardown.d.ts +4 -0
- package/dist/core/global/playwright-service-global-teardown.d.ts.map +1 -0
- package/dist/core/global/playwright-service-global-teardown.js +19 -0
- package/dist/core/global/playwright-service-global-teardown.js.map +1 -0
- package/dist/core/playwrightService.d.ts +63 -0
- package/dist/core/playwrightService.d.ts.map +1 -0
- package/dist/core/playwrightService.js +131 -0
- package/dist/core/playwrightService.js.map +1 -0
- package/dist/core/playwrightServiceEntra.d.ts +16 -0
- package/dist/core/playwrightServiceEntra.d.ts.map +1 -0
- package/dist/core/playwrightServiceEntra.js +51 -0
- package/dist/core/playwrightServiceEntra.js.map +1 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +19 -0
- package/dist/index.js.map +1 -0
- package/dist/model/entraTokenDetails.d.ts +5 -0
- package/dist/model/entraTokenDetails.d.ts.map +1 -0
- package/dist/model/entraTokenDetails.js +9 -0
- package/dist/model/entraTokenDetails.js.map +1 -0
- package/dist/model/mptTokenDetails.d.ts +11 -0
- package/dist/model/mptTokenDetails.d.ts.map +1 -0
- package/dist/model/mptTokenDetails.js +14 -0
- package/dist/model/mptTokenDetails.js.map +1 -0
- package/dist/model/shard.d.ts +41 -0
- package/dist/model/shard.d.ts.map +1 -0
- package/dist/model/shard.js +24 -0
- package/dist/model/shard.js.map +1 -0
- package/dist/model/storageUri.d.ts +14 -0
- package/dist/model/storageUri.d.ts.map +1 -0
- package/dist/model/storageUri.js +22 -0
- package/dist/model/storageUri.js.map +1 -0
- package/dist/model/testResult.d.ts +40 -0
- package/dist/model/testResult.d.ts.map +1 -0
- package/dist/model/testResult.js +9 -0
- package/dist/model/testResult.js.map +1 -0
- package/dist/model/testRun.d.ts +36 -0
- package/dist/model/testRun.d.ts.map +1 -0
- package/dist/model/testRun.js +12 -0
- package/dist/model/testRun.js.map +1 -0
- package/dist/reporter/index.d.ts +10 -0
- package/dist/reporter/index.d.ts.map +1 -0
- package/dist/reporter/index.js +15 -0
- package/dist/reporter/index.js.map +1 -0
- package/dist/reporter/mptReporter.d.ts +96 -0
- package/dist/reporter/mptReporter.d.ts.map +1 -0
- package/dist/reporter/mptReporter.js +350 -0
- package/dist/reporter/mptReporter.js.map +1 -0
- package/dist/tsdoc-metadata.json +11 -0
- package/dist/utils/cIInfoProvider.d.ts +25 -0
- package/dist/utils/cIInfoProvider.d.ts.map +1 -0
- package/dist/utils/cIInfoProvider.js +107 -0
- package/dist/utils/cIInfoProvider.js.map +1 -0
- package/dist/utils/packageManager.d.ts +15 -0
- package/dist/utils/packageManager.d.ts.map +1 -0
- package/dist/utils/packageManager.js +54 -0
- package/dist/utils/packageManager.js.map +1 -0
- package/dist/utils/reporterUtils.d.ts +57 -0
- package/dist/utils/reporterUtils.d.ts.map +1 -0
- package/dist/utils/reporterUtils.js +547 -0
- package/dist/utils/reporterUtils.js.map +1 -0
- package/dist/utils/serviceClient.d.ts +23 -0
- package/dist/utils/serviceClient.d.ts.map +1 -0
- package/dist/utils/serviceClient.js +91 -0
- package/dist/utils/serviceClient.js.map +1 -0
- package/dist/utils/storageClient.d.ts +6 -0
- package/dist/utils/storageClient.d.ts.map +1 -0
- package/dist/utils/storageClient.js +41 -0
- package/dist/utils/storageClient.js.map +1 -0
- package/dist/utils/utils.d.ts +17 -0
- package/dist/utils/utils.d.ts.map +1 -0
- package/dist/utils/utils.js +143 -0
- package/dist/utils/utils.js.map +1 -0
- package/package.json +104 -0
- package/types/microsoft-playwright-testing.d.ts +352 -0
- package/types/reporter/microsoft-playwright-testing.d.ts +146 -0
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// Copyright (c) Microsoft Corporation.
|
|
3
|
+
// Licensed under the MIT License.
|
|
4
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
5
|
+
exports.getPackageManager = exports.Yarn = exports.PNPM = exports.NPM = void 0;
|
|
6
|
+
class NPM {
|
|
7
|
+
constructor() {
|
|
8
|
+
this.runCommand = (command, args) => {
|
|
9
|
+
return `npx ${command} ${args}`;
|
|
10
|
+
};
|
|
11
|
+
this.getVersionFromStdout = (stdout) => {
|
|
12
|
+
const match = stdout.match(/Version\s(\d+\.\d+\.\d+(-\w+-\d{4}-\d{2}-\d{2})?)/);
|
|
13
|
+
return match ? match[1] : "Unknown version";
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
exports.NPM = NPM;
|
|
18
|
+
class PNPM {
|
|
19
|
+
constructor() {
|
|
20
|
+
this.runCommand = (command, args) => {
|
|
21
|
+
return `pnpm ${command} ${args}`;
|
|
22
|
+
};
|
|
23
|
+
this.getVersionFromStdout = (stdout) => {
|
|
24
|
+
const match = stdout.match(/Version\s(\d+\.\d+\.\d+(-\w+-\d{4}-\d{2}-\d{2})?)/);
|
|
25
|
+
return match ? match[1] : "Unknown version";
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
exports.PNPM = PNPM;
|
|
30
|
+
class Yarn {
|
|
31
|
+
constructor() {
|
|
32
|
+
this.runCommand = (command, args) => {
|
|
33
|
+
return `yarn ${command} ${args}`;
|
|
34
|
+
};
|
|
35
|
+
this.getVersionFromStdout = (stdout) => {
|
|
36
|
+
const match = stdout.match(/Version\s(\d+\.\d+\.\d+(-\w+-\d{4}-\d{2}-\d{2})?)/);
|
|
37
|
+
return match ? match[1] : "Unknown version";
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
exports.Yarn = Yarn;
|
|
42
|
+
// https://stackoverflow.com/questions/68133683/is-there-a-cross-platform-way-to-get-the-name-of-the-parent-process-in-node-js
|
|
43
|
+
const getPackageManager = () => {
|
|
44
|
+
if (process.env["npm_config_user_agent"]) {
|
|
45
|
+
const userAgent = process.env["npm_config_user_agent"];
|
|
46
|
+
if (userAgent.includes("yarn"))
|
|
47
|
+
return new Yarn();
|
|
48
|
+
if (userAgent.includes("pnpm"))
|
|
49
|
+
return new PNPM();
|
|
50
|
+
}
|
|
51
|
+
return new NPM();
|
|
52
|
+
};
|
|
53
|
+
exports.getPackageManager = getPackageManager;
|
|
54
|
+
//# sourceMappingURL=packageManager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"packageManager.js","sourceRoot":"","sources":["../../src/utils/packageManager.ts"],"names":[],"mappings":";AAAA,uCAAuC;AACvC,kCAAkC;;;AAIlC,MAAa,GAAG;IAAhB;QACE,eAAU,GAAG,CAAC,OAAe,EAAE,IAAY,EAAU,EAAE;YACrD,OAAO,OAAO,OAAO,IAAI,IAAI,EAAE,CAAC;QAClC,CAAC,CAAC;QACF,yBAAoB,GAAG,CAAC,MAAc,EAAU,EAAE;YAChD,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,mDAAmD,CAAC,CAAC;YAChF,OAAO,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,iBAAiB,CAAC;QAC9C,CAAC,CAAC;IACJ,CAAC;CAAA;AARD,kBAQC;AAED,MAAa,IAAI;IAAjB;QACE,eAAU,GAAG,CAAC,OAAe,EAAE,IAAY,EAAU,EAAE;YACrD,OAAO,QAAQ,OAAO,IAAI,IAAI,EAAE,CAAC;QACnC,CAAC,CAAC;QACF,yBAAoB,GAAG,CAAC,MAAc,EAAU,EAAE;YAChD,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,mDAAmD,CAAC,CAAC;YAChF,OAAO,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,iBAAiB,CAAC;QAC9C,CAAC,CAAC;IACJ,CAAC;CAAA;AARD,oBAQC;AAED,MAAa,IAAI;IAAjB;QACE,eAAU,GAAG,CAAC,OAAe,EAAE,IAAY,EAAU,EAAE;YACrD,OAAO,QAAQ,OAAO,IAAI,IAAI,EAAE,CAAC;QACnC,CAAC,CAAC;QACF,yBAAoB,GAAG,CAAC,MAAc,EAAU,EAAE;YAChD,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,mDAAmD,CAAC,CAAC;YAChF,OAAO,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,iBAAiB,CAAC;QAC9C,CAAC,CAAC;IACJ,CAAC;CAAA;AARD,oBAQC;AAED,8HAA8H;AACvH,MAAM,iBAAiB,GAAG,GAAmB,EAAE;IACpD,IAAI,OAAO,CAAC,GAAG,CAAC,uBAAuB,CAAC,EAAE,CAAC;QACzC,MAAM,SAAS,GAAG,OAAO,CAAC,GAAG,CAAC,uBAAuB,CAAC,CAAC;QACvD,IAAI,SAAS,CAAC,QAAQ,CAAC,MAAM,CAAC;YAAE,OAAO,IAAI,IAAI,EAAE,CAAC;QAClD,IAAI,SAAS,CAAC,QAAQ,CAAC,MAAM,CAAC;YAAE,OAAO,IAAI,IAAI,EAAE,CAAC;IACpD,CAAC;IACD,OAAO,IAAI,GAAG,EAAE,CAAC;AACnB,CAAC,CAAC;AAPW,QAAA,iBAAiB,qBAO5B","sourcesContent":["// Copyright (c) Microsoft Corporation.\n// Licensed under the MIT License.\n\nimport { PackageManager } from \"../common/types\";\n\nexport class NPM implements PackageManager {\n runCommand = (command: string, args: string): string => {\n return `npx ${command} ${args}`;\n };\n getVersionFromStdout = (stdout: string): string => {\n const match = stdout.match(/Version\\s(\\d+\\.\\d+\\.\\d+(-\\w+-\\d{4}-\\d{2}-\\d{2})?)/);\n return match ? match[1] : \"Unknown version\";\n };\n}\n\nexport class PNPM implements PackageManager {\n runCommand = (command: string, args: string): string => {\n return `pnpm ${command} ${args}`;\n };\n getVersionFromStdout = (stdout: string): string => {\n const match = stdout.match(/Version\\s(\\d+\\.\\d+\\.\\d+(-\\w+-\\d{4}-\\d{2}-\\d{2})?)/);\n return match ? match[1] : \"Unknown version\";\n };\n}\n\nexport class Yarn implements PackageManager {\n runCommand = (command: string, args: string): string => {\n return `yarn ${command} ${args}`;\n };\n getVersionFromStdout = (stdout: string): string => {\n const match = stdout.match(/Version\\s(\\d+\\.\\d+\\.\\d+(-\\w+-\\d{4}-\\d{2}-\\d{2})?)/);\n return match ? match[1] : \"Unknown version\";\n };\n}\n\n// https://stackoverflow.com/questions/68133683/is-there-a-cross-platform-way-to-get-the-name-of-the-parent-process-in-node-js\nexport const getPackageManager = (): PackageManager => {\n if (process.env[\"npm_config_user_agent\"]) {\n const userAgent = process.env[\"npm_config_user_agent\"];\n if (userAgent.includes(\"yarn\")) return new Yarn();\n if (userAgent.includes(\"pnpm\")) return new PNPM();\n }\n return new NPM();\n};\n"]}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import type { FullResult, TestCase, TestResult, FullConfig, Suite } from "@playwright/test/reporter";
|
|
2
|
+
import { IBackOffOptions } from "../common/types";
|
|
3
|
+
import { EnvironmentVariables } from "../common/environmentVariables";
|
|
4
|
+
import { TokenType } from "../model/mptTokenDetails";
|
|
5
|
+
import { Shard, UploadMetadata } from "../model/shard";
|
|
6
|
+
import { TestResult as MPTTestResult, RawTestResult } from "../model/testResult";
|
|
7
|
+
import { TestRun } from "../model/testRun";
|
|
8
|
+
import { CIInfo } from "./cIInfoProvider";
|
|
9
|
+
declare class ReporterUtils {
|
|
10
|
+
private envVariables;
|
|
11
|
+
private config;
|
|
12
|
+
totalTests: number;
|
|
13
|
+
failedTests: number;
|
|
14
|
+
skippedTests: number;
|
|
15
|
+
passedTests: number;
|
|
16
|
+
flakyTests: number;
|
|
17
|
+
startTime: number;
|
|
18
|
+
constructor(envVariables: EnvironmentVariables, config: FullConfig, _: Suite);
|
|
19
|
+
getTestRunObject(ciInfo: CIInfo): Promise<TestRun>;
|
|
20
|
+
getTestRunShardStartObject(): Shard;
|
|
21
|
+
getTestRunShardEndObject(result: FullResult, shard: Shard, errorMessages: string[], attachmentMetadata: UploadMetadata, workers: number): Shard;
|
|
22
|
+
getTestResultObject(test: TestCase, result: TestResult, jobName: string): MPTTestResult;
|
|
23
|
+
generateMarkdownSummary(testRunUrl: string): void;
|
|
24
|
+
getRawTestResultObject(result: TestResult): RawTestResult;
|
|
25
|
+
static getRunId(cIInfo: CIInfo): string;
|
|
26
|
+
static calculateSha1(buffer: Buffer | string): string;
|
|
27
|
+
static getTokenDetails<T>(accessToken: string, tokenType: TokenType): T;
|
|
28
|
+
static hasAudienceClaim(token: string): boolean;
|
|
29
|
+
static timestampToRFC3339(timestamp: number): string;
|
|
30
|
+
static getFileRelativePath(filePath: string): string;
|
|
31
|
+
static getReporterBackOffOptions: Partial<IBackOffOptions>;
|
|
32
|
+
static isTimeGreaterThanCurrentPlus10Minutes(isoString: string): boolean;
|
|
33
|
+
static getFileSize(attachmentPath: string): number;
|
|
34
|
+
redactAccessToken(info: string | undefined): string;
|
|
35
|
+
static populateValuesFromServiceUrl(): {
|
|
36
|
+
region: string;
|
|
37
|
+
accountId: string;
|
|
38
|
+
} | null;
|
|
39
|
+
static getRegionFromAccountID(accountId: string): string | undefined;
|
|
40
|
+
progressBar(current: number, total: number): void;
|
|
41
|
+
private getTestRunConfig;
|
|
42
|
+
private relativeLocation;
|
|
43
|
+
private extractTestTags;
|
|
44
|
+
private extractTestAnnotations;
|
|
45
|
+
private toPosixPath;
|
|
46
|
+
private getAttachmentStatus;
|
|
47
|
+
private dedupeSteps;
|
|
48
|
+
private serializeTestStep;
|
|
49
|
+
private getTestStatus;
|
|
50
|
+
private extractRootParentTitle;
|
|
51
|
+
private getRunName;
|
|
52
|
+
private runCommand;
|
|
53
|
+
static isNullOrEmpty(str: string | null | undefined): boolean;
|
|
54
|
+
private getOsName;
|
|
55
|
+
}
|
|
56
|
+
export default ReporterUtils;
|
|
57
|
+
//# sourceMappingURL=reporterUtils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reporterUtils.d.ts","sourceRoot":"","sources":["../../src/utils/reporterUtils.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,547 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// Copyright (c) Microsoft Corporation.
|
|
3
|
+
// Licensed under the MIT License.
|
|
4
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
5
|
+
const tslib_1 = require("tslib");
|
|
6
|
+
const child_process_1 = require("child_process");
|
|
7
|
+
const logger_1 = require("../common/logger");
|
|
8
|
+
const crypto_1 = require("crypto");
|
|
9
|
+
const fs_1 = tslib_1.__importDefault(require("fs"));
|
|
10
|
+
const os_1 = tslib_1.__importDefault(require("os"));
|
|
11
|
+
const path_1 = tslib_1.__importDefault(require("path"));
|
|
12
|
+
const constants_1 = require("../common/constants");
|
|
13
|
+
const mptTokenDetails_1 = require("../model/mptTokenDetails");
|
|
14
|
+
const shard_1 = require("../model/shard");
|
|
15
|
+
const testResult_1 = require("../model/testResult");
|
|
16
|
+
const testRun_1 = require("../model/testRun");
|
|
17
|
+
const cIInfoProvider_1 = require("./cIInfoProvider");
|
|
18
|
+
const cIInfoProvider_2 = require("./cIInfoProvider");
|
|
19
|
+
class ReporterUtils {
|
|
20
|
+
// eslint-disable-next-line @azure/azure-sdk/ts-use-interface-parameters
|
|
21
|
+
constructor(envVariables, config, _) {
|
|
22
|
+
this.config = config;
|
|
23
|
+
this.envVariables = envVariables;
|
|
24
|
+
this.startTime = Date.now();
|
|
25
|
+
this.totalTests = 0;
|
|
26
|
+
this.failedTests = 0;
|
|
27
|
+
this.skippedTests = 0;
|
|
28
|
+
this.passedTests = 0;
|
|
29
|
+
this.flakyTests = 0;
|
|
30
|
+
}
|
|
31
|
+
async getTestRunObject(ciInfo) {
|
|
32
|
+
const testRun = new testRun_1.TestRun();
|
|
33
|
+
const runName = await this.getRunName(ciInfo);
|
|
34
|
+
if (ReporterUtils.isNullOrEmpty(this.envVariables.runId)) {
|
|
35
|
+
if (!ReporterUtils.isNullOrEmpty(runName)) {
|
|
36
|
+
this.envVariables.runId = runName;
|
|
37
|
+
}
|
|
38
|
+
else {
|
|
39
|
+
this.envVariables.runId = (0, crypto_1.randomUUID)();
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
testRun.testRunId = this.envVariables.runId;
|
|
43
|
+
testRun.displayName = ReporterUtils.isNullOrEmpty(runName) ? (0, crypto_1.randomUUID)() : runName;
|
|
44
|
+
testRun.creatorName = this.envVariables.userName;
|
|
45
|
+
testRun.creatorId = this.envVariables.userId;
|
|
46
|
+
testRun.startTime = ReporterUtils.timestampToRFC3339(this.startTime);
|
|
47
|
+
testRun.ciConfig = {
|
|
48
|
+
ciProviderName: ciInfo.provider,
|
|
49
|
+
branch: ciInfo.branch,
|
|
50
|
+
author: ciInfo.author,
|
|
51
|
+
commitId: ciInfo.commitId,
|
|
52
|
+
revisionUrl: ciInfo.revisionUrl,
|
|
53
|
+
};
|
|
54
|
+
testRun.testRunConfig = this.getTestRunConfig();
|
|
55
|
+
testRun.cloudReportingEnabled = "true";
|
|
56
|
+
return testRun;
|
|
57
|
+
}
|
|
58
|
+
getTestRunShardStartObject() {
|
|
59
|
+
const shard = new shard_1.Shard();
|
|
60
|
+
if (this.config.shard !== null && this.config.shard !== undefined) {
|
|
61
|
+
this.envVariables.shardId = this.config.shard.current.toString();
|
|
62
|
+
}
|
|
63
|
+
else {
|
|
64
|
+
this.envVariables.shardId = "1";
|
|
65
|
+
}
|
|
66
|
+
shard.shardId = this.envVariables.shardId;
|
|
67
|
+
shard.summary = {
|
|
68
|
+
startTime: ReporterUtils.timestampToRFC3339(this.startTime),
|
|
69
|
+
};
|
|
70
|
+
shard.uploadCompleted = false;
|
|
71
|
+
return shard;
|
|
72
|
+
}
|
|
73
|
+
getTestRunShardEndObject(result,
|
|
74
|
+
// eslint-disable-next-line @azure/azure-sdk/ts-use-interface-parameters
|
|
75
|
+
shard, errorMessages, attachmentMetadata, workers) {
|
|
76
|
+
var _a;
|
|
77
|
+
shard.shardId = (_a = this.envVariables.shardId) !== null && _a !== void 0 ? _a : "1";
|
|
78
|
+
shard.summary.totalTime = result.duration;
|
|
79
|
+
shard.summary.endTime = ReporterUtils.timestampToRFC3339(Date.now());
|
|
80
|
+
shard.summary.status = shard_1.TestRunStatus.CLIENT_COMPLETE;
|
|
81
|
+
shard.summary.errorMessages = errorMessages;
|
|
82
|
+
shard.summary.uploadMetadata = attachmentMetadata;
|
|
83
|
+
shard.uploadCompleted = true;
|
|
84
|
+
shard.workers = workers;
|
|
85
|
+
return shard;
|
|
86
|
+
}
|
|
87
|
+
getTestResultObject(test, result, jobName) {
|
|
88
|
+
var _a, _b;
|
|
89
|
+
switch (test.outcome()) {
|
|
90
|
+
case "skipped":
|
|
91
|
+
this.skippedTests++;
|
|
92
|
+
this.totalTests++;
|
|
93
|
+
break;
|
|
94
|
+
case "expected":
|
|
95
|
+
this.passedTests++;
|
|
96
|
+
this.totalTests++;
|
|
97
|
+
break;
|
|
98
|
+
case "unexpected":
|
|
99
|
+
if (result.retry === test.retries) {
|
|
100
|
+
this.failedTests++;
|
|
101
|
+
this.totalTests++;
|
|
102
|
+
}
|
|
103
|
+
break;
|
|
104
|
+
case "flaky":
|
|
105
|
+
this.totalTests++;
|
|
106
|
+
this.flakyTests++;
|
|
107
|
+
break;
|
|
108
|
+
default:
|
|
109
|
+
break;
|
|
110
|
+
}
|
|
111
|
+
let browserName = (_a = test.parent.project().use.browserName) === null || _a === void 0 ? void 0 : _a.toLowerCase();
|
|
112
|
+
if (!browserName) {
|
|
113
|
+
browserName = (_b = test.parent.project().use.defaultBrowserType) === null || _b === void 0 ? void 0 : _b.toLowerCase();
|
|
114
|
+
}
|
|
115
|
+
const testResult = new testResult_1.TestResult();
|
|
116
|
+
testResult.runId = this.envVariables.runId;
|
|
117
|
+
testResult.shardId = this.envVariables.runId + "_" + this.envVariables.shardId;
|
|
118
|
+
testResult.accountId = this.envVariables.accountId;
|
|
119
|
+
testResult.suiteId = ReporterUtils.calculateSha1(`${test.parent.title}-${test.location.file}`);
|
|
120
|
+
testResult.testId = testResult.suiteId.concat(`-${ReporterUtils.calculateSha1(test.title)}`);
|
|
121
|
+
testResult.testCombinationId = test.id;
|
|
122
|
+
testResult.testExecutionId = (0, crypto_1.randomUUID)();
|
|
123
|
+
testResult.testTitle = test.title;
|
|
124
|
+
testResult.suiteTitle = this.extractRootParentTitle(test.parent);
|
|
125
|
+
testResult.fileName = test.location.file;
|
|
126
|
+
testResult.status = this.getTestStatus(test, result);
|
|
127
|
+
testResult.lineNumber = test.location.line;
|
|
128
|
+
testResult.retry = result.retry ? result.retry : 0;
|
|
129
|
+
testResult.webTestConfig = {
|
|
130
|
+
jobName: jobName,
|
|
131
|
+
projectName: test.parent.project().name,
|
|
132
|
+
browserType: browserName.toUpperCase(),
|
|
133
|
+
os: this.getOsName(),
|
|
134
|
+
};
|
|
135
|
+
testResult.annotations = this.extractTestAnnotations(test.annotations);
|
|
136
|
+
testResult.tags = this.extractTestTags(test);
|
|
137
|
+
testResult.resultsSummary = {
|
|
138
|
+
status: result.status.toUpperCase(),
|
|
139
|
+
duration: result.duration,
|
|
140
|
+
startTime: result.startTime.toISOString().replace(/\.\d+Z$/, "Z"),
|
|
141
|
+
attachmentsMetadata: this.getAttachmentStatus(result),
|
|
142
|
+
};
|
|
143
|
+
testResult.artifactsPath = result.attachments
|
|
144
|
+
.filter((attachment) => (attachment === null || attachment === void 0 ? void 0 : attachment.path) !== null && (attachment === null || attachment === void 0 ? void 0 : attachment.path) !== undefined) // Filter attachments with defined and non-null path property
|
|
145
|
+
.map((attachment) => `${testResult.testExecutionId}/${ReporterUtils.getFileRelativePath(attachment.path)}`);
|
|
146
|
+
return testResult;
|
|
147
|
+
}
|
|
148
|
+
generateMarkdownSummary(testRunUrl) {
|
|
149
|
+
try {
|
|
150
|
+
if (cIInfoProvider_2.CIInfoProvider.getCIProvider() === cIInfoProvider_1.CI_PROVIDERS.GITHUB) {
|
|
151
|
+
const markdownContent = `
|
|
152
|
+
#### Microsoft Playwright Testing run summary
|
|
153
|
+
|
|
154
|
+
#### Results:
|
|
155
|
+
|
|
156
|
+
 **Passed:** ${this.passedTests}
|
|
157
|
+
|
|
158
|
+
 **Failed:** ${this.failedTests}
|
|
159
|
+
|
|
160
|
+
 **Flaky:** ${this.flakyTests}
|
|
161
|
+
|
|
162
|
+
 **Skipped:** ${this.skippedTests}
|
|
163
|
+
|
|
164
|
+
#### For more details, visit the [service dashboard](${testRunUrl}).
|
|
165
|
+
`;
|
|
166
|
+
fs_1.default.writeFileSync(process.env["GITHUB_STEP_SUMMARY"], markdownContent);
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
catch (err) {
|
|
170
|
+
logger_1.reporterLogger.error(`\nCould not generate markdown summary - ${err}`);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
getRawTestResultObject(result) {
|
|
174
|
+
const rawTestResult = {
|
|
175
|
+
steps: this.dedupeSteps(result.steps).map((step) => this.serializeTestStep(step)),
|
|
176
|
+
errors: result.errors ? JSON.stringify(result.errors, null, 2) : "",
|
|
177
|
+
stdErr: result.stderr ? JSON.stringify(result.stderr, null, 2) : "",
|
|
178
|
+
stdOut: result.stdout ? JSON.stringify(result.stdout, null, 2) : "",
|
|
179
|
+
};
|
|
180
|
+
return rawTestResult;
|
|
181
|
+
}
|
|
182
|
+
static getRunId(cIInfo) {
|
|
183
|
+
if (cIInfo === null || cIInfo.provider === cIInfoProvider_1.CI_PROVIDERS.DEFAULT) {
|
|
184
|
+
return (0, crypto_1.randomUUID)();
|
|
185
|
+
}
|
|
186
|
+
const concatString = `${cIInfo.provider}-${cIInfo.repo}-${cIInfo.runId}-${cIInfo.runAttempt}`;
|
|
187
|
+
const runId = ReporterUtils.calculateSha1(concatString);
|
|
188
|
+
return runId;
|
|
189
|
+
}
|
|
190
|
+
static calculateSha1(buffer) {
|
|
191
|
+
const hash = (0, crypto_1.createHash)("sha1");
|
|
192
|
+
hash.update(buffer);
|
|
193
|
+
return hash.digest("hex");
|
|
194
|
+
}
|
|
195
|
+
/*
|
|
196
|
+
public static getTokenDetails(accessToken: string) {
|
|
197
|
+
let tokenDetails = new MPTTokenDetails();
|
|
198
|
+
try {
|
|
199
|
+
const token = accessToken.split('.')[1];
|
|
200
|
+
const _token = Buffer.from(token, 'base64');
|
|
201
|
+
tokenDetails = JSON.parse(_token.toString());
|
|
202
|
+
} catch (err) {
|
|
203
|
+
throw err;
|
|
204
|
+
}
|
|
205
|
+
return tokenDetails;
|
|
206
|
+
}
|
|
207
|
+
*/
|
|
208
|
+
static getTokenDetails(accessToken, tokenType) {
|
|
209
|
+
const token = accessToken.split(".")[1];
|
|
210
|
+
const _token = Buffer.from(token, "base64");
|
|
211
|
+
const tokenDetails = JSON.parse(_token.toString());
|
|
212
|
+
switch (tokenType) {
|
|
213
|
+
case mptTokenDetails_1.TokenType.MPT:
|
|
214
|
+
return tokenDetails;
|
|
215
|
+
case mptTokenDetails_1.TokenType.ENTRA:
|
|
216
|
+
return tokenDetails;
|
|
217
|
+
default:
|
|
218
|
+
throw new Error("Unsupported token type");
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
static hasAudienceClaim(token) {
|
|
222
|
+
try {
|
|
223
|
+
// Split the token into its three parts
|
|
224
|
+
const parts = token.split(".");
|
|
225
|
+
if (parts.length !== 3) {
|
|
226
|
+
throw new Error("Invalid token format");
|
|
227
|
+
}
|
|
228
|
+
// Base64 decode the payload
|
|
229
|
+
const payload = parts[1];
|
|
230
|
+
const decodedPayload = Buffer.from(payload, "base64");
|
|
231
|
+
// Parse the decoded payload as JSON
|
|
232
|
+
const payloadObject = JSON.parse(decodedPayload.toString());
|
|
233
|
+
// Check if the payload has an 'aud' claim
|
|
234
|
+
return "aud" in payloadObject;
|
|
235
|
+
}
|
|
236
|
+
catch (error) {
|
|
237
|
+
return false;
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
static timestampToRFC3339(timestamp) {
|
|
241
|
+
const date = new Date(timestamp);
|
|
242
|
+
const dateString = date.toISOString().replace(/\.\d+Z$/, "Z");
|
|
243
|
+
return dateString;
|
|
244
|
+
}
|
|
245
|
+
static getFileRelativePath(filePath) {
|
|
246
|
+
if (filePath) {
|
|
247
|
+
let parts = filePath.split("/");
|
|
248
|
+
if (parts.length > 1) {
|
|
249
|
+
return parts[parts.length - 1];
|
|
250
|
+
}
|
|
251
|
+
parts = filePath.split("\\");
|
|
252
|
+
if (parts.length > 1) {
|
|
253
|
+
return parts[parts.length - 1];
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
return filePath;
|
|
257
|
+
}
|
|
258
|
+
static isTimeGreaterThanCurrentPlus10Minutes(isoString) {
|
|
259
|
+
// Parse ISO 8601 string into a timestamp
|
|
260
|
+
const timestampFromIsoString = Date.parse(isoString);
|
|
261
|
+
// Calculate the current timestamp plus 10 minutes
|
|
262
|
+
const currentTimestampPlus10Minutes = Date.now() + 10 * 60 * 1000;
|
|
263
|
+
// Compare the timestamps
|
|
264
|
+
return timestampFromIsoString > currentTimestampPlus10Minutes;
|
|
265
|
+
}
|
|
266
|
+
static getFileSize(attachmentPath) {
|
|
267
|
+
try {
|
|
268
|
+
const stats = fs_1.default.statSync(attachmentPath);
|
|
269
|
+
return stats.size;
|
|
270
|
+
}
|
|
271
|
+
catch (err) {
|
|
272
|
+
return 0;
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
redactAccessToken(info) {
|
|
276
|
+
if (!info || ReporterUtils.isNullOrEmpty(this.envVariables.accessToken)) {
|
|
277
|
+
return "";
|
|
278
|
+
}
|
|
279
|
+
const accessTokenRegex = new RegExp(this.envVariables.accessToken, "g");
|
|
280
|
+
return info.replace(accessTokenRegex, constants_1.Constants.DEFAULT_REDACTED_MESSAGE);
|
|
281
|
+
}
|
|
282
|
+
static populateValuesFromServiceUrl() {
|
|
283
|
+
// Service URL format: wss://<region>.api.playwright.microsoft.com/accounts/<workspace-id>/browsers
|
|
284
|
+
const url = process.env["PLAYWRIGHT_SERVICE_URL"];
|
|
285
|
+
if (!ReporterUtils.isNullOrEmpty(url)) {
|
|
286
|
+
const parts = url.split("/");
|
|
287
|
+
if (parts.length > 2) {
|
|
288
|
+
const subdomainParts = parts[2].split(".");
|
|
289
|
+
const region = subdomainParts.length > 0 ? subdomainParts[0] : null;
|
|
290
|
+
const accountId = parts[4];
|
|
291
|
+
return { region: region, accountId: accountId };
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
return null;
|
|
295
|
+
}
|
|
296
|
+
static getRegionFromAccountID(accountId) {
|
|
297
|
+
if (accountId.includes("_")) {
|
|
298
|
+
return accountId.split("_")[0];
|
|
299
|
+
}
|
|
300
|
+
else {
|
|
301
|
+
return;
|
|
302
|
+
} // Handling for older workspaces without region in id
|
|
303
|
+
}
|
|
304
|
+
progressBar(current, total) {
|
|
305
|
+
const width = 40;
|
|
306
|
+
const percent = current / total;
|
|
307
|
+
const completed = Math.round(width * percent);
|
|
308
|
+
const remaining = width - completed;
|
|
309
|
+
process.stdout.write("\r");
|
|
310
|
+
process.stdout.write(`[${"=".repeat(completed)}${" ".repeat(remaining)}] ${Math.round(percent * 100)}%`);
|
|
311
|
+
}
|
|
312
|
+
getTestRunConfig() {
|
|
313
|
+
const testRunConfig = {
|
|
314
|
+
workers: this.config.workers,
|
|
315
|
+
pwVersion: this.config.version,
|
|
316
|
+
timeout: this.config.globalTimeout,
|
|
317
|
+
repeatEach: this.config.projects[0].repeatEach,
|
|
318
|
+
retries: this.config.projects[0].retries,
|
|
319
|
+
shards: this.config.shard ? this.config.shard : { total: 1 },
|
|
320
|
+
testFramework: {
|
|
321
|
+
name: constants_1.Constants.TEST_FRAMEWORK_NAME,
|
|
322
|
+
version: this.config.version,
|
|
323
|
+
runnerName: constants_1.Constants.TEST_FRAMEWORK_RUNNERNAME,
|
|
324
|
+
},
|
|
325
|
+
testType: constants_1.Constants.TEST_TYPE,
|
|
326
|
+
testSdkLanguage: constants_1.Constants.TEST_SDK_LANGUAGE,
|
|
327
|
+
reporterPackageVersion: constants_1.Constants.REPORTER_PACKAGE_VERSION,
|
|
328
|
+
};
|
|
329
|
+
return testRunConfig;
|
|
330
|
+
}
|
|
331
|
+
relativeLocation(location) {
|
|
332
|
+
if (!location) {
|
|
333
|
+
return undefined;
|
|
334
|
+
}
|
|
335
|
+
const file = this.toPosixPath(path_1.default.relative(this.config.rootDir, location.file));
|
|
336
|
+
return {
|
|
337
|
+
file,
|
|
338
|
+
line: location.line,
|
|
339
|
+
column: location.column,
|
|
340
|
+
};
|
|
341
|
+
}
|
|
342
|
+
extractTestTags(input) {
|
|
343
|
+
let tags = [];
|
|
344
|
+
if ("tags" in input && Array.isArray(input.tags) && input.tags.length > 0) {
|
|
345
|
+
tags = input.tags.map((tag) => tag.slice(1));
|
|
346
|
+
return tags;
|
|
347
|
+
}
|
|
348
|
+
// Check if the input string contains tags directly
|
|
349
|
+
const regex = /@(\w+)/g;
|
|
350
|
+
const matches = input.title.match(regex);
|
|
351
|
+
if (matches) {
|
|
352
|
+
tags = tags.concat(matches.map((match) => match.slice(1)));
|
|
353
|
+
}
|
|
354
|
+
// Try parsing the input string as a JavaScript object
|
|
355
|
+
try {
|
|
356
|
+
const obj = JSON.parse(`{${input}}`);
|
|
357
|
+
if (obj.tag && Array.isArray(obj.tag)) {
|
|
358
|
+
tags = tags.concat(obj.tag);
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
catch (error) {
|
|
362
|
+
// Ignore parsing errors
|
|
363
|
+
}
|
|
364
|
+
return tags;
|
|
365
|
+
}
|
|
366
|
+
extractTestAnnotations(annotations) {
|
|
367
|
+
const result = annotations.map((annotation) => {
|
|
368
|
+
if (annotation.type && annotation.description) {
|
|
369
|
+
return `${annotation.type}: ${annotation.description}`;
|
|
370
|
+
}
|
|
371
|
+
return annotation.type;
|
|
372
|
+
});
|
|
373
|
+
return result;
|
|
374
|
+
}
|
|
375
|
+
toPosixPath(aPath) {
|
|
376
|
+
return aPath.split(path_1.default.sep).join(path_1.default.posix.sep);
|
|
377
|
+
}
|
|
378
|
+
getAttachmentStatus(testResult) {
|
|
379
|
+
let attachmentStatus = "";
|
|
380
|
+
for (const attachment of testResult.attachments) {
|
|
381
|
+
if (attachment.contentType.includes("image")) {
|
|
382
|
+
if (attachmentStatus !== "") {
|
|
383
|
+
attachmentStatus += ",";
|
|
384
|
+
}
|
|
385
|
+
attachmentStatus += "image";
|
|
386
|
+
}
|
|
387
|
+
else if (attachment.contentType.includes("video")) {
|
|
388
|
+
if (attachmentStatus !== "") {
|
|
389
|
+
attachmentStatus += ",";
|
|
390
|
+
}
|
|
391
|
+
attachmentStatus += "video";
|
|
392
|
+
}
|
|
393
|
+
else if (attachment.contentType === "application/zip") {
|
|
394
|
+
if (attachmentStatus !== "") {
|
|
395
|
+
attachmentStatus += ",";
|
|
396
|
+
}
|
|
397
|
+
attachmentStatus += "trace";
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
return attachmentStatus;
|
|
401
|
+
}
|
|
402
|
+
dedupeSteps(steps) {
|
|
403
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
404
|
+
const result = [];
|
|
405
|
+
let lastResult = undefined;
|
|
406
|
+
for (const step of steps) {
|
|
407
|
+
const canDedupe = !step.error && step.duration >= 0 && ((_a = step.location) === null || _a === void 0 ? void 0 : _a.file) && !step.steps.length;
|
|
408
|
+
const lastStep = lastResult === null || lastResult === void 0 ? void 0 : lastResult.step;
|
|
409
|
+
if (canDedupe &&
|
|
410
|
+
lastResult &&
|
|
411
|
+
lastStep &&
|
|
412
|
+
step.category === lastStep.category &&
|
|
413
|
+
step.title === lastStep.title &&
|
|
414
|
+
((_b = step.location) === null || _b === void 0 ? void 0 : _b.file) === ((_c = lastStep.location) === null || _c === void 0 ? void 0 : _c.file) &&
|
|
415
|
+
((_d = step.location) === null || _d === void 0 ? void 0 : _d.line) === ((_e = lastStep.location) === null || _e === void 0 ? void 0 : _e.line) &&
|
|
416
|
+
((_f = step.location) === null || _f === void 0 ? void 0 : _f.column) === ((_g = lastStep.location) === null || _g === void 0 ? void 0 : _g.column)) {
|
|
417
|
+
++lastResult.count;
|
|
418
|
+
lastResult.duration += step.duration;
|
|
419
|
+
continue;
|
|
420
|
+
}
|
|
421
|
+
lastResult = { step, count: 1, duration: step.duration };
|
|
422
|
+
result.push(lastResult);
|
|
423
|
+
if (!canDedupe) {
|
|
424
|
+
lastResult = undefined;
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
return result;
|
|
428
|
+
}
|
|
429
|
+
serializeTestStep(dedupedStep) {
|
|
430
|
+
const { step, duration, count } = dedupedStep;
|
|
431
|
+
const result = {
|
|
432
|
+
title: step.title,
|
|
433
|
+
category: step.category,
|
|
434
|
+
startTime: step.startTime.toISOString(),
|
|
435
|
+
duration,
|
|
436
|
+
error: step.error ? step.error.message : undefined,
|
|
437
|
+
location: this.relativeLocation(step.location),
|
|
438
|
+
steps: this.dedupeSteps(step.steps).map((subStep) => this.serializeTestStep(subStep)),
|
|
439
|
+
count: count,
|
|
440
|
+
};
|
|
441
|
+
return result;
|
|
442
|
+
}
|
|
443
|
+
getTestStatus(test, result) {
|
|
444
|
+
if (test.expectedStatus === result.status) {
|
|
445
|
+
if (result.status === "skipped") {
|
|
446
|
+
return "SKIPPED";
|
|
447
|
+
}
|
|
448
|
+
else {
|
|
449
|
+
return "PASSED";
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
else if (result.status === "interrupted") {
|
|
453
|
+
return "SKIPPED";
|
|
454
|
+
}
|
|
455
|
+
else {
|
|
456
|
+
return "FAILED";
|
|
457
|
+
}
|
|
458
|
+
}
|
|
459
|
+
extractRootParentTitle(suite) {
|
|
460
|
+
// Traverse through the parent properties until reaching the root parent
|
|
461
|
+
let currentSuite = suite;
|
|
462
|
+
let depthCount = 0;
|
|
463
|
+
let suiteTitle = currentSuite.title;
|
|
464
|
+
const projectName = currentSuite.project().name;
|
|
465
|
+
while ((currentSuite === null || currentSuite === void 0 ? void 0 : currentSuite.parent) && !ReporterUtils.isNullOrEmpty(currentSuite.parent.title)) {
|
|
466
|
+
if (depthCount > 10 || currentSuite.parent.title === projectName) {
|
|
467
|
+
break;
|
|
468
|
+
}
|
|
469
|
+
suiteTitle = suiteTitle + " > " + currentSuite.parent.title;
|
|
470
|
+
currentSuite = currentSuite.parent;
|
|
471
|
+
depthCount++;
|
|
472
|
+
}
|
|
473
|
+
return suiteTitle;
|
|
474
|
+
}
|
|
475
|
+
async getRunName(ciInfo) {
|
|
476
|
+
var _a;
|
|
477
|
+
if (ciInfo.provider === cIInfoProvider_1.CI_PROVIDERS.GITHUB &&
|
|
478
|
+
process.env["GITHUB_EVENT_NAME"] === "pull_request") {
|
|
479
|
+
const prNumber = `${(_a = process.env["GITHUB_REF_NAME"]) === null || _a === void 0 ? void 0 : _a.split("/")[0]}`;
|
|
480
|
+
const prLink = `${process.env["GITHUB_REPOSITORY"]}/pull/${prNumber}`;
|
|
481
|
+
return `PR# ${prNumber} on Repo: ${process.env["GITHUB_REPOSITORY"]} (${prLink})`;
|
|
482
|
+
}
|
|
483
|
+
let gitCommitMessage = null;
|
|
484
|
+
try {
|
|
485
|
+
const gitVersion = await this.runCommand(constants_1.Constants.GIT_VERSION_COMMAND);
|
|
486
|
+
if (ReporterUtils.isNullOrEmpty(gitVersion)) {
|
|
487
|
+
throw new Error("Git is not installed on the machine");
|
|
488
|
+
}
|
|
489
|
+
const isInsideWorkTree = await this.runCommand(constants_1.Constants.GIT_REV_PARSE);
|
|
490
|
+
if (isInsideWorkTree !== "true") {
|
|
491
|
+
throw new Error("Not inside a git repository");
|
|
492
|
+
}
|
|
493
|
+
gitCommitMessage = await this.runCommand(constants_1.Constants.GIT_COMMIT_MESSAGE_COMMAND);
|
|
494
|
+
return gitCommitMessage;
|
|
495
|
+
}
|
|
496
|
+
catch (err) {
|
|
497
|
+
logger_1.reporterLogger.error(`\nError in getting git commit message: ${err}.`);
|
|
498
|
+
return "";
|
|
499
|
+
}
|
|
500
|
+
}
|
|
501
|
+
async runCommand(command) {
|
|
502
|
+
return new Promise((resolve, reject) => {
|
|
503
|
+
(0, child_process_1.exec)(command, (error, stdout, stderr) => {
|
|
504
|
+
if (error) {
|
|
505
|
+
reject(error);
|
|
506
|
+
return;
|
|
507
|
+
}
|
|
508
|
+
if (stderr) {
|
|
509
|
+
reject(new Error(stderr));
|
|
510
|
+
return;
|
|
511
|
+
}
|
|
512
|
+
resolve(stdout.trim());
|
|
513
|
+
});
|
|
514
|
+
});
|
|
515
|
+
}
|
|
516
|
+
static isNullOrEmpty(str) {
|
|
517
|
+
return !str || str.trim() === "";
|
|
518
|
+
}
|
|
519
|
+
getOsName() {
|
|
520
|
+
const osType = os_1.default.type();
|
|
521
|
+
switch (osType) {
|
|
522
|
+
case "Darwin":
|
|
523
|
+
return "MAC";
|
|
524
|
+
case "Linux":
|
|
525
|
+
return "LINUX";
|
|
526
|
+
case "Windows_NT":
|
|
527
|
+
return "WINDOWS";
|
|
528
|
+
default:
|
|
529
|
+
return "UNKNOWN";
|
|
530
|
+
}
|
|
531
|
+
}
|
|
532
|
+
}
|
|
533
|
+
ReporterUtils.getReporterBackOffOptions = {
|
|
534
|
+
numOfAttempts: 3,
|
|
535
|
+
jitter: "full",
|
|
536
|
+
retry: (error) => {
|
|
537
|
+
if (error.response) {
|
|
538
|
+
const status = error.response.status;
|
|
539
|
+
if (constants_1.Constants.NON_RETRYABLE_STATUS_CODES.includes(status)) {
|
|
540
|
+
return false;
|
|
541
|
+
}
|
|
542
|
+
}
|
|
543
|
+
return true;
|
|
544
|
+
},
|
|
545
|
+
};
|
|
546
|
+
exports.default = ReporterUtils;
|
|
547
|
+
//# sourceMappingURL=reporterUtils.js.map
|