@azure/playwright 1.1.2 → 1.1.3-alpha.20260310.1
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/dist/browser/common/types.d.ts +1 -1
- package/dist/browser/common/types.d.ts.map +1 -1
- package/dist/browser/common/types.js.map +1 -1
- package/dist/browser/index.d.ts +1 -1
- package/dist/browser/index.d.ts.map +1 -1
- package/dist/browser/index.js.map +1 -1
- package/dist/browser/utils/PlaywrightServiceClient.d.ts +1 -1
- package/dist/browser/utils/PlaywrightServiceClient.d.ts.map +1 -1
- package/dist/browser/utils/PlaywrightServiceClient.js.map +1 -1
- package/dist/browser/utils/playwrightReporterStorageManager.d.ts.map +1 -1
- package/dist/browser/utils/playwrightReporterStorageManager.js.map +1 -1
- package/dist/browser/utils/utils.d.ts +2 -2
- package/dist/browser/utils/utils.d.ts.map +1 -1
- package/dist/browser/utils/utils.js.map +1 -1
- package/dist/commonjs/common/constants.js +127 -95
- package/dist/commonjs/common/constants.js.map +7 -1
- package/dist/commonjs/common/customerConfig.js +31 -14
- package/dist/commonjs/common/customerConfig.js.map +7 -1
- package/dist/commonjs/common/entraIdAccessToken.js +106 -83
- package/dist/commonjs/common/entraIdAccessToken.js.map +7 -1
- package/dist/commonjs/common/environmentVariables.js +43 -24
- package/dist/commonjs/common/environmentVariables.js.map +7 -1
- package/dist/commonjs/common/executor.js +88 -67
- package/dist/commonjs/common/executor.js.map +7 -1
- package/dist/commonjs/common/httpService.js +54 -35
- package/dist/commonjs/common/httpService.js.map +7 -1
- package/dist/commonjs/common/logger.js +28 -8
- package/dist/commonjs/common/logger.js.map +7 -1
- package/dist/commonjs/common/messages.js +189 -169
- package/dist/commonjs/common/messages.js.map +7 -1
- package/dist/commonjs/common/playwrightServiceConfig.js +113 -98
- package/dist/commonjs/common/playwrightServiceConfig.js.map +7 -1
- package/dist/commonjs/common/state.js +30 -10
- package/dist/commonjs/common/state.js.map +7 -1
- package/dist/commonjs/common/types.d.ts +1 -1
- package/dist/commonjs/common/types.d.ts.map +1 -1
- package/dist/commonjs/common/types.js +15 -5
- package/dist/commonjs/common/types.js.map +7 -1
- package/dist/commonjs/core/global/playwright-service-global-setup.js +52 -26
- package/dist/commonjs/core/global/playwright-service-global-setup.js.map +7 -1
- package/dist/commonjs/core/global/playwright-service-global-teardown.js +49 -20
- package/dist/commonjs/core/global/playwright-service-global-teardown.js.map +7 -1
- package/dist/commonjs/core/initializePlaywrightServiceTestRun.js +39 -27
- package/dist/commonjs/core/initializePlaywrightServiceTestRun.js.map +7 -1
- package/dist/commonjs/core/playwrightService.js +166 -205
- package/dist/commonjs/core/playwrightService.js.map +7 -1
- package/dist/commonjs/core/playwrightServiceEntra.js +67 -48
- package/dist/commonjs/core/playwrightServiceEntra.js.map +7 -1
- package/dist/commonjs/core/playwrightServiceUtils.d.ts +1 -1
- package/dist/commonjs/core/playwrightServiceUtils.d.ts.map +1 -0
- package/dist/commonjs/core/playwrightServiceUtils.js +44 -11
- package/dist/commonjs/core/playwrightServiceUtils.js.map +7 -0
- package/dist/commonjs/index.d.ts +1 -1
- package/dist/commonjs/index.d.ts.map +1 -1
- package/dist/commonjs/index.js +36 -18
- package/dist/commonjs/index.js.map +7 -1
- package/dist/commonjs/reporter/index.js +34 -15
- package/dist/commonjs/reporter/index.js.map +7 -1
- package/dist/commonjs/reporter/playwrightReporter.js +222 -216
- package/dist/commonjs/reporter/playwrightReporter.js.map +7 -1
- package/dist/commonjs/tsdoc-metadata.json +1 -1
- package/dist/commonjs/utils/PlaywrightServiceClient.d.ts +1 -1
- package/dist/commonjs/utils/PlaywrightServiceClient.d.ts.map +1 -1
- package/dist/commonjs/utils/PlaywrightServiceClient.js +140 -91
- package/dist/commonjs/utils/PlaywrightServiceClient.js.map +7 -1
- package/dist/commonjs/utils/cIInfoProvider.js +81 -74
- package/dist/commonjs/utils/cIInfoProvider.js.map +7 -1
- package/dist/commonjs/utils/getPackageVersion.d.ts +1 -1
- package/dist/commonjs/utils/getPackageVersion.d.ts.map +1 -0
- package/dist/commonjs/utils/getPackageVersion.js +50 -19
- package/dist/commonjs/utils/getPackageVersion.js.map +7 -0
- package/dist/commonjs/utils/getPlaywrightVersion.js +42 -21
- package/dist/commonjs/utils/getPlaywrightVersion.js.map +7 -1
- package/dist/commonjs/utils/packageManager.js +59 -40
- package/dist/commonjs/utils/packageManager.js.map +7 -1
- package/dist/commonjs/utils/parseJwt.js +37 -17
- package/dist/commonjs/utils/parseJwt.js.map +7 -1
- package/dist/commonjs/utils/playwrightReporterStorageManager.d.ts.map +1 -1
- package/dist/commonjs/utils/playwrightReporterStorageManager.js +381 -342
- package/dist/commonjs/utils/playwrightReporterStorageManager.js.map +7 -1
- package/dist/commonjs/utils/utils.d.ts +2 -2
- package/dist/commonjs/utils/utils.d.ts.map +1 -1
- package/dist/commonjs/utils/utils.js +417 -369
- package/dist/commonjs/utils/utils.js.map +7 -1
- package/dist/esm/common/constants.js +92 -92
- package/dist/esm/common/constants.js.map +7 -1
- package/dist/esm/common/customerConfig.js +11 -11
- package/dist/esm/common/customerConfig.js.map +7 -1
- package/dist/esm/common/entraIdAccessToken.js +85 -77
- package/dist/esm/common/entraIdAccessToken.js.map +7 -1
- package/dist/esm/common/environmentVariables.js +19 -19
- package/dist/esm/common/environmentVariables.js.map +7 -1
- package/dist/esm/common/executor.js +51 -58
- package/dist/esm/common/executor.js.map +7 -1
- package/dist/esm/common/httpService.js +34 -29
- package/dist/esm/common/httpService.js.map +7 -1
- package/dist/esm/common/logger.js +4 -4
- package/dist/esm/common/logger.js.map +7 -1
- package/dist/esm/common/messages.js +166 -166
- package/dist/esm/common/messages.js.map +7 -1
- package/dist/esm/common/playwrightServiceConfig.js +91 -91
- package/dist/esm/common/playwrightServiceConfig.js.map +7 -1
- package/dist/esm/common/state.js +7 -7
- package/dist/esm/common/state.js.map +7 -1
- package/dist/esm/common/types.d.ts +1 -1
- package/dist/esm/common/types.d.ts.map +1 -1
- package/dist/esm/common/types.js +0 -4
- package/dist/esm/common/types.js.map +7 -1
- package/dist/esm/core/global/playwright-service-global-setup.js +17 -17
- package/dist/esm/core/global/playwright-service-global-setup.js.map +7 -1
- package/dist/esm/core/global/playwright-service-global-teardown.js +16 -13
- package/dist/esm/core/global/playwright-service-global-teardown.js.map +7 -1
- package/dist/esm/core/initializePlaywrightServiceTestRun.js +13 -21
- package/dist/esm/core/initializePlaywrightServiceTestRun.js.map +7 -1
- package/dist/esm/core/playwrightService.js +144 -195
- package/dist/esm/core/playwrightService.js.map +7 -1
- package/dist/esm/core/playwrightServiceEntra.js +44 -42
- package/dist/esm/core/playwrightServiceEntra.js.map +7 -1
- package/dist/esm/core/playwrightServiceUtils.js +6 -8
- package/dist/esm/core/playwrightServiceUtils.js.map +7 -1
- package/dist/esm/index.d.ts +1 -1
- package/dist/esm/index.d.ts.map +1 -1
- package/dist/esm/index.js +7 -9
- package/dist/esm/index.js.map +7 -1
- package/dist/esm/reporter/index.js +4 -11
- package/dist/esm/reporter/index.js.map +7 -1
- package/dist/esm/reporter/playwrightReporter.js +202 -207
- package/dist/esm/reporter/playwrightReporter.js.map +7 -1
- package/dist/esm/utils/PlaywrightServiceClient.d.ts +1 -1
- package/dist/esm/utils/PlaywrightServiceClient.d.ts.map +1 -1
- package/dist/esm/utils/PlaywrightServiceClient.js +120 -85
- package/dist/esm/utils/PlaywrightServiceClient.js.map +7 -1
- package/dist/esm/utils/cIInfoProvider.js +58 -71
- package/dist/esm/utils/cIInfoProvider.js.map +7 -1
- package/dist/esm/utils/getPackageVersion.js +12 -17
- package/dist/esm/utils/getPackageVersion.js.map +7 -1
- package/dist/esm/utils/getPlaywrightVersion.js +15 -13
- package/dist/esm/utils/getPlaywrightVersion.js.map +7 -1
- package/dist/esm/utils/packageManager.js +37 -37
- package/dist/esm/utils/packageManager.js.map +7 -1
- package/dist/esm/utils/parseJwt.js +15 -14
- package/dist/esm/utils/parseJwt.js.map +7 -1
- package/dist/esm/utils/playwrightReporterStorageManager.d.ts.map +1 -1
- package/dist/esm/utils/playwrightReporterStorageManager.js +358 -333
- package/dist/esm/utils/playwrightReporterStorageManager.js.map +7 -1
- package/dist/esm/utils/utils.d.ts +2 -2
- package/dist/esm/utils/utils.d.ts.map +1 -1
- package/dist/esm/utils/utils.js +377 -350
- package/dist/esm/utils/utils.js.map +7 -1
- package/dist/react-native/common/types.d.ts +1 -1
- package/dist/react-native/common/types.d.ts.map +1 -1
- package/dist/react-native/common/types.js.map +1 -1
- package/dist/react-native/index.d.ts +1 -1
- package/dist/react-native/index.d.ts.map +1 -1
- package/dist/react-native/index.js.map +1 -1
- package/dist/react-native/utils/PlaywrightServiceClient.d.ts +1 -1
- package/dist/react-native/utils/PlaywrightServiceClient.d.ts.map +1 -1
- package/dist/react-native/utils/PlaywrightServiceClient.js.map +1 -1
- package/dist/react-native/utils/playwrightReporterStorageManager.d.ts.map +1 -1
- package/dist/react-native/utils/playwrightReporterStorageManager.js.map +1 -1
- package/dist/react-native/utils/utils.d.ts +2 -2
- package/dist/react-native/utils/utils.d.ts.map +1 -1
- package/dist/react-native/utils/utils.js.map +1 -1
- package/package.json +6 -24
- package/dist/commonjs/core/playwrightServiceUtils-cjs.cjs.map +0 -1
- package/dist/commonjs/core/playwrightServiceUtils-cjs.d.cts.map +0 -1
- package/dist/commonjs/utils/getPackageVersion-cjs.cjs.map +0 -1
- package/dist/commonjs/utils/getPackageVersion-cjs.d.cts.map +0 -1
package/dist/esm/utils/utils.js
CHANGED
|
@@ -1,6 +1,11 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
import {
|
|
2
|
+
Constants,
|
|
3
|
+
InternalEnvironmentVariables,
|
|
4
|
+
ServiceEnvironmentVariable,
|
|
5
|
+
RunConfigConstants,
|
|
6
|
+
GitHubActionsConstants,
|
|
7
|
+
UrlConstants
|
|
8
|
+
} from "../common/constants.js";
|
|
4
9
|
import { ServiceErrorMessageConstants } from "../common/messages.js";
|
|
5
10
|
import { coreLogger } from "../common/logger.js";
|
|
6
11
|
import process from "node:process";
|
|
@@ -14,393 +19,415 @@ import { getPackageVersionFromFolder } from "./getPackageVersion.js";
|
|
|
14
19
|
import { readdirSync, statSync } from "fs";
|
|
15
20
|
import { join, relative } from "path";
|
|
16
21
|
import { UploadConstants } from "../common/constants.js";
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
if (srcVersion) {
|
|
30
|
-
return srcVersion;
|
|
31
|
-
}
|
|
32
|
-
return "unknown-version";
|
|
22
|
+
import { getPlaywrightVersion as getPlaywrightVersion2 } from "./getPlaywrightVersion.js";
|
|
23
|
+
import { parseJwt as parseJwt2 } from "./parseJwt.js";
|
|
24
|
+
const getPackageVersion = () => {
|
|
25
|
+
const distVersion = getPackageVersionFromFolder("../../../");
|
|
26
|
+
if (distVersion) {
|
|
27
|
+
return distVersion;
|
|
28
|
+
}
|
|
29
|
+
const srcVersion = getPackageVersionFromFolder("../../");
|
|
30
|
+
if (srcVersion) {
|
|
31
|
+
return srcVersion;
|
|
32
|
+
}
|
|
33
|
+
return "unknown-version";
|
|
33
34
|
};
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
// eslint-disable-next-line n/no-process-exit
|
|
43
|
-
process.exit(1);
|
|
35
|
+
const exitWithFailureMessage = (error, errorDetails) => {
|
|
36
|
+
console.log();
|
|
37
|
+
if (error.formatWithErrorDetails && errorDetails) {
|
|
38
|
+
console.error(error.formatWithErrorDetails(errorDetails));
|
|
39
|
+
} else {
|
|
40
|
+
console.error(error.message);
|
|
41
|
+
}
|
|
42
|
+
process.exit(1);
|
|
44
43
|
};
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
: error.message;
|
|
50
|
-
throw new Error(finalMessage);
|
|
44
|
+
const throwErrorWithFailureMessage = (error, errorDetails) => {
|
|
45
|
+
console.log();
|
|
46
|
+
const finalMessage = error.formatWithErrorDetails && errorDetails ? error.formatWithErrorDetails(errorDetails) : error.message;
|
|
47
|
+
throw new Error(finalMessage);
|
|
51
48
|
};
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
return null;
|
|
49
|
+
const populateValuesFromServiceUrl = () => {
|
|
50
|
+
const url = process.env["PLAYWRIGHT_SERVICE_URL"];
|
|
51
|
+
if (url) {
|
|
52
|
+
const parts = url.split("/");
|
|
53
|
+
if (parts.length > 2) {
|
|
54
|
+
const subdomainParts = parts[2].split(".");
|
|
55
|
+
const region = subdomainParts.length > 0 ? subdomainParts[0] : null;
|
|
56
|
+
const domain = subdomainParts.slice(2).join(".");
|
|
57
|
+
const accountId = parts[4];
|
|
58
|
+
return { region, domain, accountId };
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
return null;
|
|
66
62
|
};
|
|
67
|
-
|
|
68
|
-
|
|
63
|
+
const getAccessToken = () => {
|
|
64
|
+
return process.env[ServiceEnvironmentVariable.PLAYWRIGHT_SERVICE_ACCESS_TOKEN];
|
|
69
65
|
};
|
|
70
|
-
|
|
71
|
-
|
|
66
|
+
const getServiceBaseURL = () => {
|
|
67
|
+
return process.env[ServiceEnvironmentVariable.PLAYWRIGHT_SERVICE_URL];
|
|
72
68
|
};
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
69
|
+
const isValidGuid = (guid) => {
|
|
70
|
+
if (!guid) {
|
|
71
|
+
return false;
|
|
72
|
+
}
|
|
73
|
+
const guidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
74
|
+
return guidRegex.test(guid);
|
|
79
75
|
};
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
76
|
+
const getAndSetRunId = () => {
|
|
77
|
+
const runId = randomUUID();
|
|
78
|
+
process.env[InternalEnvironmentVariables.MPT_SERVICE_RUN_ID] = runId;
|
|
79
|
+
return runId;
|
|
84
80
|
};
|
|
85
|
-
|
|
86
|
-
|
|
81
|
+
const getServiceWSEndpoint = (runId, os, apiVersion) => {
|
|
82
|
+
return `${getServiceBaseURL()}?runId=${encodeURIComponent(runId)}&os=${os}&api-version=${apiVersion}`;
|
|
87
83
|
};
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
84
|
+
const validateServiceUrl = () => {
|
|
85
|
+
const serviceUrl = getServiceBaseURL();
|
|
86
|
+
if (!serviceUrl) {
|
|
87
|
+
exitWithFailureMessage(ServiceErrorMessageConstants.NO_SERVICE_URL_ERROR);
|
|
88
|
+
}
|
|
93
89
|
};
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
90
|
+
const ValidateRunID = (runID) => {
|
|
91
|
+
const isValidRunID = isValidGuid(runID);
|
|
92
|
+
if (!isValidRunID) {
|
|
93
|
+
const errorMessage = ServiceErrorMessageConstants.INVALID_RUN_ID_FORMAT.message;
|
|
94
|
+
throw new Error(errorMessage);
|
|
95
|
+
}
|
|
100
96
|
};
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
}
|
|
112
|
-
if (Date.now() >= claims.exp * 1000) {
|
|
113
|
-
validationFailureCallback(ServiceErrorMessageConstants.EXPIRED_MPT_PAT_ERROR);
|
|
114
|
-
}
|
|
115
|
-
if (result.accountId !== claims.pwid) {
|
|
116
|
-
validationFailureCallback(ServiceErrorMessageConstants.WORKSPACE_MISMATCH_ERROR);
|
|
117
|
-
}
|
|
97
|
+
const validateMptPAT = (validationFailureCallback) => {
|
|
98
|
+
try {
|
|
99
|
+
const accessToken = getAccessToken();
|
|
100
|
+
const result = populateValuesFromServiceUrl();
|
|
101
|
+
if (!accessToken) {
|
|
102
|
+
validationFailureCallback(ServiceErrorMessageConstants.NO_AUTH_ERROR_PAT_TOKEN);
|
|
103
|
+
}
|
|
104
|
+
const claims = parseJwt(accessToken);
|
|
105
|
+
if (!claims.exp) {
|
|
106
|
+
validationFailureCallback(ServiceErrorMessageConstants.INVALID_MPT_PAT_ERROR);
|
|
118
107
|
}
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
exitWithFailureMessage(ServiceErrorMessageConstants.INVALID_MPT_PAT_ERROR);
|
|
108
|
+
if (Date.now() >= claims.exp * 1e3) {
|
|
109
|
+
validationFailureCallback(ServiceErrorMessageConstants.EXPIRED_MPT_PAT_ERROR);
|
|
122
110
|
}
|
|
111
|
+
if (result.accountId !== claims.pwid) {
|
|
112
|
+
validationFailureCallback(ServiceErrorMessageConstants.WORKSPACE_MISMATCH_ERROR);
|
|
113
|
+
}
|
|
114
|
+
} catch (err) {
|
|
115
|
+
coreLogger.error(err);
|
|
116
|
+
exitWithFailureMessage(ServiceErrorMessageConstants.INVALID_MPT_PAT_ERROR);
|
|
117
|
+
}
|
|
123
118
|
};
|
|
124
119
|
const isTokenExpiringSoon = (expirationTime, currentTime) => {
|
|
125
|
-
|
|
120
|
+
return expirationTime * 1e3 - currentTime <= Constants.SevenDaysInMS;
|
|
126
121
|
};
|
|
127
122
|
const warnAboutTokenExpiry = (expirationTime, currentTime) => {
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
123
|
+
const daysToExpiration = Math.ceil((expirationTime * 1e3 - currentTime) / Constants.OneDayInMS);
|
|
124
|
+
const expirationDate = new Date(expirationTime * 1e3).toLocaleDateString();
|
|
125
|
+
const expirationWarning = `Warning: The access token used for this test run will expire in ${daysToExpiration} days on ${expirationDate}. Generate a new token from the portal to avoid failures. For a simpler, more secure solution, switch to Microsoft Entra ID and eliminate token management. https://learn.microsoft.com/entra/identity/`;
|
|
126
|
+
console.warn(expirationWarning);
|
|
132
127
|
};
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
128
|
+
const warnIfAccessTokenCloseToExpiry = () => {
|
|
129
|
+
const accessToken = getAccessToken();
|
|
130
|
+
if (!accessToken) {
|
|
131
|
+
throw new Error(ServiceErrorMessageConstants.NO_AUTH_ERROR_PAT_TOKEN.message);
|
|
132
|
+
}
|
|
133
|
+
const claims = parseJwt(accessToken);
|
|
134
|
+
const currentTime = Date.now();
|
|
135
|
+
if (isTokenExpiringSoon(claims.exp, currentTime)) {
|
|
136
|
+
warnAboutTokenExpiry(claims.exp, currentTime);
|
|
137
|
+
}
|
|
143
138
|
};
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
return token;
|
|
139
|
+
const fetchOrValidateAccessToken = async (credential) => {
|
|
140
|
+
const entraIdAccessToken = createEntraIdAccessToken(credential);
|
|
141
|
+
if (entraIdAccessToken.doesEntraIdAccessTokenNeedRotation()) {
|
|
142
|
+
await entraIdAccessToken.fetchEntraIdAccessToken();
|
|
143
|
+
}
|
|
144
|
+
const token = getAccessToken();
|
|
145
|
+
if (!token) {
|
|
146
|
+
throw new Error(ServiceErrorMessageConstants.NO_AUTH_ERROR_ENTRA_TOKEN.message);
|
|
147
|
+
}
|
|
148
|
+
return token;
|
|
155
149
|
};
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
150
|
+
const getVersionInfo = (version) => {
|
|
151
|
+
const regex = /^(\d+)(?:\.(\d+))?(?:\.(\d+))?/;
|
|
152
|
+
const match = version.match(regex);
|
|
153
|
+
const versionInfo = {
|
|
154
|
+
major: 0,
|
|
155
|
+
minor: 0,
|
|
156
|
+
patch: 0
|
|
157
|
+
};
|
|
158
|
+
versionInfo.major = match && match[1] ? parseInt(match[1], 10) : 0;
|
|
159
|
+
versionInfo.minor = match && match[2] ? parseInt(match[2], 10) : 0;
|
|
160
|
+
versionInfo.patch = match && match[3] ? parseInt(match[3], 10) : 0;
|
|
161
|
+
return versionInfo;
|
|
168
162
|
};
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
exitWithFailureMessage(ServiceErrorMessageConstants.INVALID_PLAYWRIGHT_VERSION_ERROR);
|
|
179
|
-
}
|
|
163
|
+
const validatePlaywrightVersion = () => {
|
|
164
|
+
const minimumSupportedVersion = Constants.MinimumSupportedPlaywrightVersion;
|
|
165
|
+
const installedVersion = getPlaywrightVersion();
|
|
166
|
+
const minimumSupportedVersionInfo = getVersionInfo(minimumSupportedVersion);
|
|
167
|
+
const installedVersionInfo = getVersionInfo(installedVersion);
|
|
168
|
+
const isInstalledVersionGreater = installedVersionInfo.major > minimumSupportedVersionInfo.major || installedVersionInfo.major === minimumSupportedVersionInfo.major && installedVersionInfo.minor >= minimumSupportedVersionInfo.minor;
|
|
169
|
+
if (!isInstalledVersionGreater) {
|
|
170
|
+
exitWithFailureMessage(ServiceErrorMessageConstants.INVALID_PLAYWRIGHT_VERSION_ERROR);
|
|
171
|
+
}
|
|
180
172
|
};
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
173
|
+
const getTestRunConfig = (config) => {
|
|
174
|
+
const maxWorkers = config.workers || config.metadata.actualWorkers;
|
|
175
|
+
const frameWorkVersion = config.version;
|
|
176
|
+
const testRunConfig = {
|
|
177
|
+
framework: {
|
|
178
|
+
name: RunConfigConstants.TEST_FRAMEWORK_NAME,
|
|
179
|
+
version: frameWorkVersion,
|
|
180
|
+
runnerName: RunConfigConstants.TEST_FRAMEWORK_RUNNERNAME
|
|
181
|
+
},
|
|
182
|
+
sdkLanguage: RunConfigConstants.TEST_SDK_LANGUAGE,
|
|
183
|
+
maxWorkers
|
|
184
|
+
};
|
|
185
|
+
return testRunConfig;
|
|
194
186
|
};
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
187
|
+
function getTestRunApiUrl() {
|
|
188
|
+
const result = populateValuesFromServiceUrl();
|
|
189
|
+
const runId = process.env[InternalEnvironmentVariables.MPT_SERVICE_RUN_ID];
|
|
190
|
+
if (!result?.region || !result?.domain || !result?.accountId) {
|
|
191
|
+
exitWithFailureMessage(ServiceErrorMessageConstants.NO_SERVICE_URL_ERROR);
|
|
192
|
+
}
|
|
193
|
+
const baseUrl = `https://${result?.region}.${UrlConstants.ReportingApiSubdomain}.${result?.domain}/${UrlConstants.PlaywrightWorkspacesPath}/${result?.accountId}/${UrlConstants.TestRunsPath}`;
|
|
194
|
+
const url = runId ? `${baseUrl}/${runId}` : baseUrl;
|
|
195
|
+
return `${url}?api-version=${Constants.LatestAPIVersion}`;
|
|
204
196
|
}
|
|
205
|
-
|
|
206
|
-
|
|
197
|
+
function isNullOrEmpty(str) {
|
|
198
|
+
return !str || str.trim() === "";
|
|
207
199
|
}
|
|
208
200
|
async function runCommand(command) {
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
});
|
|
201
|
+
return new Promise((resolve, reject) => {
|
|
202
|
+
exec(command, (error, stdout, stderr) => {
|
|
203
|
+
if (error) {
|
|
204
|
+
reject(error);
|
|
205
|
+
return;
|
|
206
|
+
}
|
|
207
|
+
if (stderr) {
|
|
208
|
+
reject(new Error(stderr));
|
|
209
|
+
return;
|
|
210
|
+
}
|
|
211
|
+
resolve(stdout.trim());
|
|
221
212
|
});
|
|
213
|
+
});
|
|
222
214
|
}
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
return "";
|
|
245
|
-
}
|
|
215
|
+
async function getRunName(ciInfo) {
|
|
216
|
+
if (ciInfo.providerName === CI_PROVIDERS.GITHUB && process.env["GITHUB_EVENT_NAME"] === "pull_request") {
|
|
217
|
+
const prNumber = `${process.env["GITHUB_REF_NAME"]?.split("/")[0]}`;
|
|
218
|
+
const prLink = `${process.env["GITHUB_REPOSITORY"]}/pull/${prNumber}`;
|
|
219
|
+
return `PR# ${prNumber} on Repo: ${process.env["GITHUB_REPOSITORY"]} (${prLink})`;
|
|
220
|
+
}
|
|
221
|
+
try {
|
|
222
|
+
const gitVersion = await runCommand(GitHubActionsConstants.GIT_VERSION_COMMAND);
|
|
223
|
+
if (isNullOrEmpty(gitVersion)) {
|
|
224
|
+
throw new Error("Git is not installed on the machine");
|
|
225
|
+
}
|
|
226
|
+
const isInsideWorkTree = await runCommand(GitHubActionsConstants.GIT_REV_PARSE);
|
|
227
|
+
if (isInsideWorkTree !== "true") {
|
|
228
|
+
throw new Error("Not inside a git repository");
|
|
229
|
+
}
|
|
230
|
+
const gitCommitMessage = await runCommand(GitHubActionsConstants.GIT_COMMIT_MESSAGE_COMMAND);
|
|
231
|
+
return gitCommitMessage;
|
|
232
|
+
} catch (err) {
|
|
233
|
+
coreLogger.error(`Error in getting git commit message: ${err}.`);
|
|
234
|
+
return "";
|
|
235
|
+
}
|
|
246
236
|
}
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
}
|
|
237
|
+
function extractErrorMessage(responseBody) {
|
|
238
|
+
if (!responseBody) {
|
|
239
|
+
return "";
|
|
240
|
+
}
|
|
241
|
+
try {
|
|
242
|
+
const errorResponse = JSON.parse(responseBody);
|
|
243
|
+
if (errorResponse.error && errorResponse.error.message) {
|
|
244
|
+
return errorResponse.error.message;
|
|
245
|
+
}
|
|
246
|
+
return responseBody;
|
|
247
|
+
} catch (e) {
|
|
248
|
+
return responseBody;
|
|
249
|
+
}
|
|
261
250
|
}
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
251
|
+
function getWorkspaceMetaDataApiUrl() {
|
|
252
|
+
const result = populateValuesFromServiceUrl();
|
|
253
|
+
if (!result?.region || !result?.domain || !result?.accountId) {
|
|
254
|
+
exitWithFailureMessage(ServiceErrorMessageConstants.NO_SERVICE_URL_ERROR);
|
|
255
|
+
}
|
|
256
|
+
const baseUrl = `https://${result?.region}.${UrlConstants.ApiSubdomain}.${result?.domain}/${UrlConstants.PlaywrightWorkspacesPath}/${result?.accountId}`;
|
|
257
|
+
return `${baseUrl}?api-version=${Constants.LatestAPIVersion}`;
|
|
269
258
|
}
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
return defaultFolder;
|
|
274
|
-
}
|
|
275
|
-
for (const reporter of config.reporter) {
|
|
276
|
-
if (Array.isArray(reporter)) {
|
|
277
|
-
const [reporterName, options] = reporter;
|
|
278
|
-
if (reporterName === "html" && options && typeof options === "object") {
|
|
279
|
-
return options.outputFolder || defaultFolder;
|
|
280
|
-
}
|
|
281
|
-
}
|
|
282
|
-
else if (typeof reporter === "string" && reporter === "html") {
|
|
283
|
-
return defaultFolder;
|
|
284
|
-
}
|
|
285
|
-
}
|
|
259
|
+
function getHtmlReporterOutputFolder(config) {
|
|
260
|
+
const defaultFolder = "playwright-report";
|
|
261
|
+
if (!config?.reporter) {
|
|
286
262
|
return defaultFolder;
|
|
263
|
+
}
|
|
264
|
+
for (const reporter of config.reporter) {
|
|
265
|
+
if (Array.isArray(reporter)) {
|
|
266
|
+
const [reporterName, options] = reporter;
|
|
267
|
+
if (reporterName === "html" && options && typeof options === "object") {
|
|
268
|
+
return options.outputFolder || defaultFolder;
|
|
269
|
+
}
|
|
270
|
+
} else if (typeof reporter === "string" && reporter === "html") {
|
|
271
|
+
return defaultFolder;
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
return defaultFolder;
|
|
287
275
|
}
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
276
|
+
function getContentType(filePath) {
|
|
277
|
+
const ext = filePath.toLowerCase().split(".").pop();
|
|
278
|
+
const contentTypes = {
|
|
279
|
+
html: "text/html",
|
|
280
|
+
css: "text/css",
|
|
281
|
+
js: "application/javascript",
|
|
282
|
+
json: "application/json",
|
|
283
|
+
png: "image/png",
|
|
284
|
+
jpg: "image/jpeg",
|
|
285
|
+
jpeg: "image/jpeg",
|
|
286
|
+
svg: "image/svg+xml",
|
|
287
|
+
ico: "image/x-icon",
|
|
288
|
+
txt: "text/plain",
|
|
289
|
+
ttf: "font/ttf",
|
|
290
|
+
woff: "font/woff",
|
|
291
|
+
woff2: "font/woff2",
|
|
292
|
+
webmanifest: "application/manifest+json",
|
|
293
|
+
map: "application/json",
|
|
294
|
+
xml: "application/xml",
|
|
295
|
+
pdf: "application/pdf",
|
|
296
|
+
zip: "application/zip"
|
|
297
|
+
};
|
|
298
|
+
return contentTypes[ext || ""] || "application/octet-stream";
|
|
311
299
|
}
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
300
|
+
function calculateOptimalConcurrency(files) {
|
|
301
|
+
const totalFiles = files.length;
|
|
302
|
+
const totalSize = files.reduce((sum, f) => sum + f.size, 0);
|
|
303
|
+
const avgFileSize = totalSize / totalFiles;
|
|
304
|
+
let optimalConcurrency;
|
|
305
|
+
if (totalFiles <= 10) {
|
|
306
|
+
optimalConcurrency = Math.min(totalFiles, 10);
|
|
307
|
+
} else if (avgFileSize < UploadConstants.SMALL_FILE_THRESHOLD) {
|
|
308
|
+
optimalConcurrency = Math.min(
|
|
309
|
+
UploadConstants.MAX_CONCURRENCY,
|
|
310
|
+
Math.max(UploadConstants.BASE_CONCURRENCY, totalFiles / 50)
|
|
311
|
+
);
|
|
312
|
+
} else if (totalFiles > 1e3) {
|
|
313
|
+
optimalConcurrency = Math.min(
|
|
314
|
+
UploadConstants.MAX_CONCURRENCY,
|
|
315
|
+
UploadConstants.BASE_CONCURRENCY + Math.floor(totalFiles / 200)
|
|
316
|
+
);
|
|
317
|
+
} else {
|
|
318
|
+
optimalConcurrency = Math.min(
|
|
319
|
+
UploadConstants.MAX_CONCURRENCY,
|
|
320
|
+
UploadConstants.BASE_CONCURRENCY
|
|
321
|
+
);
|
|
322
|
+
}
|
|
323
|
+
return Math.floor(optimalConcurrency);
|
|
330
324
|
}
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
});
|
|
355
|
-
}
|
|
356
|
-
}
|
|
357
|
-
}
|
|
358
|
-
catch (error) {
|
|
359
|
-
continue;
|
|
325
|
+
function collectAllFiles(folderPath, basePath, runIdFolderPrefix) {
|
|
326
|
+
const files = [];
|
|
327
|
+
const stack = [folderPath];
|
|
328
|
+
while (stack.length > 0) {
|
|
329
|
+
const currentPath = stack.pop();
|
|
330
|
+
try {
|
|
331
|
+
const items = readdirSync(currentPath);
|
|
332
|
+
for (const item of items) {
|
|
333
|
+
const itemPath = join(currentPath, item);
|
|
334
|
+
const stats = statSync(itemPath);
|
|
335
|
+
if (stats.isDirectory()) {
|
|
336
|
+
stack.push(itemPath);
|
|
337
|
+
} else {
|
|
338
|
+
let relativePath = relative(basePath, itemPath).split("\\").join("/");
|
|
339
|
+
if (runIdFolderPrefix) {
|
|
340
|
+
relativePath = `${runIdFolderPrefix}/${relativePath}`;
|
|
341
|
+
}
|
|
342
|
+
files.push({
|
|
343
|
+
fullPath: itemPath,
|
|
344
|
+
relativePath,
|
|
345
|
+
size: stats.size,
|
|
346
|
+
contentType: getContentType(itemPath)
|
|
347
|
+
});
|
|
360
348
|
}
|
|
349
|
+
}
|
|
350
|
+
} catch (error) {
|
|
351
|
+
continue;
|
|
361
352
|
}
|
|
362
|
-
|
|
353
|
+
}
|
|
354
|
+
return files;
|
|
363
355
|
}
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
356
|
+
function resolveTenantDomain(tenantId, tenants) {
|
|
357
|
+
if (!tenantId || tenants.length === 0) {
|
|
358
|
+
return void 0;
|
|
359
|
+
}
|
|
360
|
+
const matchingTenant = tenants.find((t) => t.tenantId === tenantId);
|
|
361
|
+
coreLogger.info(
|
|
362
|
+
`Resolved tenant domain: ${JSON.stringify(matchingTenant?.defaultDomain)} for tenant ID: ${tenantId}`
|
|
363
|
+
);
|
|
364
|
+
return matchingTenant?.defaultDomain;
|
|
371
365
|
}
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
366
|
+
function getPortalTestRunUrl(workspaceMetadata, tenantDomain) {
|
|
367
|
+
const { subscriptionId, resourceId, name } = workspaceMetadata ?? {};
|
|
368
|
+
if (!subscriptionId || !resourceId || !name) {
|
|
369
|
+
throw new Error(
|
|
370
|
+
"Missing required workspace metadata: subscriptionId, resourceId, and name are required"
|
|
371
|
+
);
|
|
372
|
+
}
|
|
373
|
+
const resourceIdParts = resourceId.split("/");
|
|
374
|
+
const resourceGroupIndex = resourceIdParts.findIndex(
|
|
375
|
+
(part) => part.toLowerCase() === UrlConstants.ResourceGroupsPath
|
|
376
|
+
);
|
|
377
|
+
if (resourceGroupIndex === -1 || resourceGroupIndex + 1 >= resourceIdParts.length) {
|
|
378
|
+
throw new Error("Invalid resourceId format: could not extract resource group name");
|
|
379
|
+
}
|
|
380
|
+
const resourceGroupName = resourceIdParts[resourceGroupIndex + 1];
|
|
381
|
+
const tenantFragment = tenantDomain ? `#@${tenantDomain}` : "#";
|
|
382
|
+
return `${UrlConstants.AzurePortalBaseUrl}/${tenantFragment}${UrlConstants.ResourcePath}${UrlConstants.SubscriptionsPath}/${encodeURIComponent(subscriptionId)}${UrlConstants.ResourceGroupsUrlPath}/${encodeURIComponent(resourceGroupName)}${UrlConstants.ProvidersPath}/${UrlConstants.LoadTestServiceProvider}/${UrlConstants.PlaywrightWorkspacesResourceType}/${encodeURIComponent(name)}/${UrlConstants.TestRunsRoute}`;
|
|
386
383
|
}
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
}
|
|
392
|
-
const url = new URL(storageUri);
|
|
393
|
-
const hostname = url.hostname;
|
|
394
|
-
// Extract storage account name from hostname pattern: {accountname}.blob.core.windows.net
|
|
395
|
-
const match = hostname.match(/^([^.]+)\.blob\.core\.windows\.net$/i);
|
|
396
|
-
if (match && match[1]) {
|
|
397
|
-
return match[1];
|
|
398
|
-
}
|
|
399
|
-
return null;
|
|
384
|
+
const getStorageAccountNameFromUri = (storageUri) => {
|
|
385
|
+
try {
|
|
386
|
+
if (!storageUri || typeof storageUri !== "string") {
|
|
387
|
+
return null;
|
|
400
388
|
}
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
389
|
+
const url = new URL(storageUri);
|
|
390
|
+
const hostname = url.hostname;
|
|
391
|
+
const match = hostname.match(/^([^.]+)\.blob\.core\.windows\.net$/i);
|
|
392
|
+
if (match && match[1]) {
|
|
393
|
+
return match[1];
|
|
404
394
|
}
|
|
395
|
+
return null;
|
|
396
|
+
} catch (error) {
|
|
397
|
+
console.warn("Failed to extract storage account name from URI:", storageUri, error);
|
|
398
|
+
return null;
|
|
399
|
+
}
|
|
400
|
+
};
|
|
401
|
+
export {
|
|
402
|
+
ValidateRunID,
|
|
403
|
+
calculateOptimalConcurrency,
|
|
404
|
+
collectAllFiles,
|
|
405
|
+
exitWithFailureMessage,
|
|
406
|
+
extractErrorMessage,
|
|
407
|
+
fetchOrValidateAccessToken,
|
|
408
|
+
getAccessToken,
|
|
409
|
+
getAndSetRunId,
|
|
410
|
+
getContentType,
|
|
411
|
+
getHtmlReporterOutputFolder,
|
|
412
|
+
getPackageVersion,
|
|
413
|
+
getPlaywrightVersion2 as getPlaywrightVersion,
|
|
414
|
+
getPortalTestRunUrl,
|
|
415
|
+
getRunName,
|
|
416
|
+
getServiceBaseURL,
|
|
417
|
+
getServiceWSEndpoint,
|
|
418
|
+
getStorageAccountNameFromUri,
|
|
419
|
+
getTestRunApiUrl,
|
|
420
|
+
getTestRunConfig,
|
|
421
|
+
getVersionInfo,
|
|
422
|
+
getWorkspaceMetaDataApiUrl,
|
|
423
|
+
isNullOrEmpty,
|
|
424
|
+
isValidGuid,
|
|
425
|
+
parseJwt2 as parseJwt,
|
|
426
|
+
populateValuesFromServiceUrl,
|
|
427
|
+
resolveTenantDomain,
|
|
428
|
+
throwErrorWithFailureMessage,
|
|
429
|
+
validateMptPAT,
|
|
430
|
+
validatePlaywrightVersion,
|
|
431
|
+
validateServiceUrl,
|
|
432
|
+
warnIfAccessTokenCloseToExpiry
|
|
405
433
|
};
|
|
406
|
-
//# sourceMappingURL=utils.js.map
|