@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.
Files changed (168) hide show
  1. package/dist/browser/common/types.d.ts +1 -1
  2. package/dist/browser/common/types.d.ts.map +1 -1
  3. package/dist/browser/common/types.js.map +1 -1
  4. package/dist/browser/index.d.ts +1 -1
  5. package/dist/browser/index.d.ts.map +1 -1
  6. package/dist/browser/index.js.map +1 -1
  7. package/dist/browser/utils/PlaywrightServiceClient.d.ts +1 -1
  8. package/dist/browser/utils/PlaywrightServiceClient.d.ts.map +1 -1
  9. package/dist/browser/utils/PlaywrightServiceClient.js.map +1 -1
  10. package/dist/browser/utils/playwrightReporterStorageManager.d.ts.map +1 -1
  11. package/dist/browser/utils/playwrightReporterStorageManager.js.map +1 -1
  12. package/dist/browser/utils/utils.d.ts +2 -2
  13. package/dist/browser/utils/utils.d.ts.map +1 -1
  14. package/dist/browser/utils/utils.js.map +1 -1
  15. package/dist/commonjs/common/constants.js +127 -95
  16. package/dist/commonjs/common/constants.js.map +7 -1
  17. package/dist/commonjs/common/customerConfig.js +31 -14
  18. package/dist/commonjs/common/customerConfig.js.map +7 -1
  19. package/dist/commonjs/common/entraIdAccessToken.js +106 -83
  20. package/dist/commonjs/common/entraIdAccessToken.js.map +7 -1
  21. package/dist/commonjs/common/environmentVariables.js +43 -24
  22. package/dist/commonjs/common/environmentVariables.js.map +7 -1
  23. package/dist/commonjs/common/executor.js +88 -67
  24. package/dist/commonjs/common/executor.js.map +7 -1
  25. package/dist/commonjs/common/httpService.js +54 -35
  26. package/dist/commonjs/common/httpService.js.map +7 -1
  27. package/dist/commonjs/common/logger.js +28 -8
  28. package/dist/commonjs/common/logger.js.map +7 -1
  29. package/dist/commonjs/common/messages.js +189 -169
  30. package/dist/commonjs/common/messages.js.map +7 -1
  31. package/dist/commonjs/common/playwrightServiceConfig.js +113 -98
  32. package/dist/commonjs/common/playwrightServiceConfig.js.map +7 -1
  33. package/dist/commonjs/common/state.js +30 -10
  34. package/dist/commonjs/common/state.js.map +7 -1
  35. package/dist/commonjs/common/types.d.ts +1 -1
  36. package/dist/commonjs/common/types.d.ts.map +1 -1
  37. package/dist/commonjs/common/types.js +15 -5
  38. package/dist/commonjs/common/types.js.map +7 -1
  39. package/dist/commonjs/core/global/playwright-service-global-setup.js +52 -26
  40. package/dist/commonjs/core/global/playwright-service-global-setup.js.map +7 -1
  41. package/dist/commonjs/core/global/playwright-service-global-teardown.js +49 -20
  42. package/dist/commonjs/core/global/playwright-service-global-teardown.js.map +7 -1
  43. package/dist/commonjs/core/initializePlaywrightServiceTestRun.js +39 -27
  44. package/dist/commonjs/core/initializePlaywrightServiceTestRun.js.map +7 -1
  45. package/dist/commonjs/core/playwrightService.js +166 -205
  46. package/dist/commonjs/core/playwrightService.js.map +7 -1
  47. package/dist/commonjs/core/playwrightServiceEntra.js +67 -48
  48. package/dist/commonjs/core/playwrightServiceEntra.js.map +7 -1
  49. package/dist/commonjs/core/playwrightServiceUtils.d.ts +1 -1
  50. package/dist/commonjs/core/playwrightServiceUtils.d.ts.map +1 -0
  51. package/dist/commonjs/core/playwrightServiceUtils.js +44 -11
  52. package/dist/commonjs/core/playwrightServiceUtils.js.map +7 -0
  53. package/dist/commonjs/index.d.ts +1 -1
  54. package/dist/commonjs/index.d.ts.map +1 -1
  55. package/dist/commonjs/index.js +36 -18
  56. package/dist/commonjs/index.js.map +7 -1
  57. package/dist/commonjs/reporter/index.js +34 -15
  58. package/dist/commonjs/reporter/index.js.map +7 -1
  59. package/dist/commonjs/reporter/playwrightReporter.js +222 -216
  60. package/dist/commonjs/reporter/playwrightReporter.js.map +7 -1
  61. package/dist/commonjs/tsdoc-metadata.json +1 -1
  62. package/dist/commonjs/utils/PlaywrightServiceClient.d.ts +1 -1
  63. package/dist/commonjs/utils/PlaywrightServiceClient.d.ts.map +1 -1
  64. package/dist/commonjs/utils/PlaywrightServiceClient.js +140 -91
  65. package/dist/commonjs/utils/PlaywrightServiceClient.js.map +7 -1
  66. package/dist/commonjs/utils/cIInfoProvider.js +81 -74
  67. package/dist/commonjs/utils/cIInfoProvider.js.map +7 -1
  68. package/dist/commonjs/utils/getPackageVersion.d.ts +1 -1
  69. package/dist/commonjs/utils/getPackageVersion.d.ts.map +1 -0
  70. package/dist/commonjs/utils/getPackageVersion.js +50 -19
  71. package/dist/commonjs/utils/getPackageVersion.js.map +7 -0
  72. package/dist/commonjs/utils/getPlaywrightVersion.js +42 -21
  73. package/dist/commonjs/utils/getPlaywrightVersion.js.map +7 -1
  74. package/dist/commonjs/utils/packageManager.js +59 -40
  75. package/dist/commonjs/utils/packageManager.js.map +7 -1
  76. package/dist/commonjs/utils/parseJwt.js +37 -17
  77. package/dist/commonjs/utils/parseJwt.js.map +7 -1
  78. package/dist/commonjs/utils/playwrightReporterStorageManager.d.ts.map +1 -1
  79. package/dist/commonjs/utils/playwrightReporterStorageManager.js +381 -342
  80. package/dist/commonjs/utils/playwrightReporterStorageManager.js.map +7 -1
  81. package/dist/commonjs/utils/utils.d.ts +2 -2
  82. package/dist/commonjs/utils/utils.d.ts.map +1 -1
  83. package/dist/commonjs/utils/utils.js +417 -369
  84. package/dist/commonjs/utils/utils.js.map +7 -1
  85. package/dist/esm/common/constants.js +92 -92
  86. package/dist/esm/common/constants.js.map +7 -1
  87. package/dist/esm/common/customerConfig.js +11 -11
  88. package/dist/esm/common/customerConfig.js.map +7 -1
  89. package/dist/esm/common/entraIdAccessToken.js +85 -77
  90. package/dist/esm/common/entraIdAccessToken.js.map +7 -1
  91. package/dist/esm/common/environmentVariables.js +19 -19
  92. package/dist/esm/common/environmentVariables.js.map +7 -1
  93. package/dist/esm/common/executor.js +51 -58
  94. package/dist/esm/common/executor.js.map +7 -1
  95. package/dist/esm/common/httpService.js +34 -29
  96. package/dist/esm/common/httpService.js.map +7 -1
  97. package/dist/esm/common/logger.js +4 -4
  98. package/dist/esm/common/logger.js.map +7 -1
  99. package/dist/esm/common/messages.js +166 -166
  100. package/dist/esm/common/messages.js.map +7 -1
  101. package/dist/esm/common/playwrightServiceConfig.js +91 -91
  102. package/dist/esm/common/playwrightServiceConfig.js.map +7 -1
  103. package/dist/esm/common/state.js +7 -7
  104. package/dist/esm/common/state.js.map +7 -1
  105. package/dist/esm/common/types.d.ts +1 -1
  106. package/dist/esm/common/types.d.ts.map +1 -1
  107. package/dist/esm/common/types.js +0 -4
  108. package/dist/esm/common/types.js.map +7 -1
  109. package/dist/esm/core/global/playwright-service-global-setup.js +17 -17
  110. package/dist/esm/core/global/playwright-service-global-setup.js.map +7 -1
  111. package/dist/esm/core/global/playwright-service-global-teardown.js +16 -13
  112. package/dist/esm/core/global/playwright-service-global-teardown.js.map +7 -1
  113. package/dist/esm/core/initializePlaywrightServiceTestRun.js +13 -21
  114. package/dist/esm/core/initializePlaywrightServiceTestRun.js.map +7 -1
  115. package/dist/esm/core/playwrightService.js +144 -195
  116. package/dist/esm/core/playwrightService.js.map +7 -1
  117. package/dist/esm/core/playwrightServiceEntra.js +44 -42
  118. package/dist/esm/core/playwrightServiceEntra.js.map +7 -1
  119. package/dist/esm/core/playwrightServiceUtils.js +6 -8
  120. package/dist/esm/core/playwrightServiceUtils.js.map +7 -1
  121. package/dist/esm/index.d.ts +1 -1
  122. package/dist/esm/index.d.ts.map +1 -1
  123. package/dist/esm/index.js +7 -9
  124. package/dist/esm/index.js.map +7 -1
  125. package/dist/esm/reporter/index.js +4 -11
  126. package/dist/esm/reporter/index.js.map +7 -1
  127. package/dist/esm/reporter/playwrightReporter.js +202 -207
  128. package/dist/esm/reporter/playwrightReporter.js.map +7 -1
  129. package/dist/esm/utils/PlaywrightServiceClient.d.ts +1 -1
  130. package/dist/esm/utils/PlaywrightServiceClient.d.ts.map +1 -1
  131. package/dist/esm/utils/PlaywrightServiceClient.js +120 -85
  132. package/dist/esm/utils/PlaywrightServiceClient.js.map +7 -1
  133. package/dist/esm/utils/cIInfoProvider.js +58 -71
  134. package/dist/esm/utils/cIInfoProvider.js.map +7 -1
  135. package/dist/esm/utils/getPackageVersion.js +12 -17
  136. package/dist/esm/utils/getPackageVersion.js.map +7 -1
  137. package/dist/esm/utils/getPlaywrightVersion.js +15 -13
  138. package/dist/esm/utils/getPlaywrightVersion.js.map +7 -1
  139. package/dist/esm/utils/packageManager.js +37 -37
  140. package/dist/esm/utils/packageManager.js.map +7 -1
  141. package/dist/esm/utils/parseJwt.js +15 -14
  142. package/dist/esm/utils/parseJwt.js.map +7 -1
  143. package/dist/esm/utils/playwrightReporterStorageManager.d.ts.map +1 -1
  144. package/dist/esm/utils/playwrightReporterStorageManager.js +358 -333
  145. package/dist/esm/utils/playwrightReporterStorageManager.js.map +7 -1
  146. package/dist/esm/utils/utils.d.ts +2 -2
  147. package/dist/esm/utils/utils.d.ts.map +1 -1
  148. package/dist/esm/utils/utils.js +377 -350
  149. package/dist/esm/utils/utils.js.map +7 -1
  150. package/dist/react-native/common/types.d.ts +1 -1
  151. package/dist/react-native/common/types.d.ts.map +1 -1
  152. package/dist/react-native/common/types.js.map +1 -1
  153. package/dist/react-native/index.d.ts +1 -1
  154. package/dist/react-native/index.d.ts.map +1 -1
  155. package/dist/react-native/index.js.map +1 -1
  156. package/dist/react-native/utils/PlaywrightServiceClient.d.ts +1 -1
  157. package/dist/react-native/utils/PlaywrightServiceClient.d.ts.map +1 -1
  158. package/dist/react-native/utils/PlaywrightServiceClient.js.map +1 -1
  159. package/dist/react-native/utils/playwrightReporterStorageManager.d.ts.map +1 -1
  160. package/dist/react-native/utils/playwrightReporterStorageManager.js.map +1 -1
  161. package/dist/react-native/utils/utils.d.ts +2 -2
  162. package/dist/react-native/utils/utils.d.ts.map +1 -1
  163. package/dist/react-native/utils/utils.js.map +1 -1
  164. package/package.json +6 -24
  165. package/dist/commonjs/core/playwrightServiceUtils-cjs.cjs.map +0 -1
  166. package/dist/commonjs/core/playwrightServiceUtils-cjs.d.cts.map +0 -1
  167. package/dist/commonjs/utils/getPackageVersion-cjs.cjs.map +0 -1
  168. package/dist/commonjs/utils/getPackageVersion-cjs.d.cts.map +0 -1
@@ -1,6 +1,11 @@
1
- // Copyright (c) Microsoft Corporation.
2
- // Licensed under the MIT License.
3
- import { Constants, InternalEnvironmentVariables, ServiceEnvironmentVariable, RunConfigConstants, GitHubActionsConstants, UrlConstants, } from "../common/constants.js";
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
- // Re-exporting for backward compatibility
18
- export { getPlaywrightVersion } from "./getPlaywrightVersion.js";
19
- export { parseJwt } from "./parseJwt.js";
20
- export const getPackageVersion = () => {
21
- // hacky way to get package version
22
- // try from dist folder first (customer perspective)
23
- const distVersion = getPackageVersionFromFolder("../../../");
24
- if (distVersion) {
25
- return distVersion;
26
- }
27
- // if not found, try from src folder (internal test suite)
28
- const srcVersion = getPackageVersionFromFolder("../../");
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
- export const exitWithFailureMessage = (error, errorDetails) => {
35
- console.log();
36
- if (error.formatWithErrorDetails && errorDetails) {
37
- console.error(error.formatWithErrorDetails(errorDetails));
38
- }
39
- else {
40
- console.error(error.message);
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
- export const throwErrorWithFailureMessage = (error, errorDetails) => {
46
- console.log();
47
- const finalMessage = error.formatWithErrorDetails && errorDetails
48
- ? error.formatWithErrorDetails(errorDetails)
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
- export const populateValuesFromServiceUrl = () => {
53
- // Service URL format: wss://<region>.api.playwright.microsoft.com/accounts/<workspace-id>/browsers
54
- const url = process.env["PLAYWRIGHT_SERVICE_URL"];
55
- if (url) {
56
- const parts = url.split("/");
57
- if (parts.length > 2) {
58
- const subdomainParts = parts[2].split(".");
59
- const region = subdomainParts.length > 0 ? subdomainParts[0] : null;
60
- const domain = subdomainParts.slice(2).join(".");
61
- const accountId = parts[4];
62
- return { region: region, domain: domain, accountId: accountId };
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
- export const getAccessToken = () => {
68
- return process.env[ServiceEnvironmentVariable.PLAYWRIGHT_SERVICE_ACCESS_TOKEN];
63
+ const getAccessToken = () => {
64
+ return process.env[ServiceEnvironmentVariable.PLAYWRIGHT_SERVICE_ACCESS_TOKEN];
69
65
  };
70
- export const getServiceBaseURL = () => {
71
- return process.env[ServiceEnvironmentVariable.PLAYWRIGHT_SERVICE_URL];
66
+ const getServiceBaseURL = () => {
67
+ return process.env[ServiceEnvironmentVariable.PLAYWRIGHT_SERVICE_URL];
72
68
  };
73
- export const isValidGuid = (guid) => {
74
- if (!guid) {
75
- return false;
76
- }
77
- const guidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
78
- return guidRegex.test(guid);
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
- export const getAndSetRunId = () => {
81
- const runId = randomUUID();
82
- process.env[InternalEnvironmentVariables.MPT_SERVICE_RUN_ID] = runId;
83
- return runId;
76
+ const getAndSetRunId = () => {
77
+ const runId = randomUUID();
78
+ process.env[InternalEnvironmentVariables.MPT_SERVICE_RUN_ID] = runId;
79
+ return runId;
84
80
  };
85
- export const getServiceWSEndpoint = (runId, os, apiVersion) => {
86
- return `${getServiceBaseURL()}?runId=${encodeURIComponent(runId)}&os=${os}&api-version=${apiVersion}`;
81
+ const getServiceWSEndpoint = (runId, os, apiVersion) => {
82
+ return `${getServiceBaseURL()}?runId=${encodeURIComponent(runId)}&os=${os}&api-version=${apiVersion}`;
87
83
  };
88
- export const validateServiceUrl = () => {
89
- const serviceUrl = getServiceBaseURL();
90
- if (!serviceUrl) {
91
- exitWithFailureMessage(ServiceErrorMessageConstants.NO_SERVICE_URL_ERROR);
92
- }
84
+ const validateServiceUrl = () => {
85
+ const serviceUrl = getServiceBaseURL();
86
+ if (!serviceUrl) {
87
+ exitWithFailureMessage(ServiceErrorMessageConstants.NO_SERVICE_URL_ERROR);
88
+ }
93
89
  };
94
- export const ValidateRunID = (runID) => {
95
- const isValidRunID = isValidGuid(runID);
96
- if (!isValidRunID) {
97
- const errorMessage = ServiceErrorMessageConstants.INVALID_RUN_ID_FORMAT.message;
98
- throw new Error(errorMessage);
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
- export const validateMptPAT = (validationFailureCallback) => {
102
- try {
103
- const accessToken = getAccessToken();
104
- const result = populateValuesFromServiceUrl();
105
- if (!accessToken) {
106
- validationFailureCallback(ServiceErrorMessageConstants.NO_AUTH_ERROR_PAT_TOKEN);
107
- }
108
- const claims = parseJwt(accessToken);
109
- if (!claims.exp) {
110
- validationFailureCallback(ServiceErrorMessageConstants.INVALID_MPT_PAT_ERROR);
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
- catch (err) {
120
- coreLogger.error(err);
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
- return expirationTime * 1000 - currentTime <= Constants.SevenDaysInMS;
120
+ return expirationTime * 1e3 - currentTime <= Constants.SevenDaysInMS;
126
121
  };
127
122
  const warnAboutTokenExpiry = (expirationTime, currentTime) => {
128
- const daysToExpiration = Math.ceil((expirationTime * 1000 - currentTime) / Constants.OneDayInMS);
129
- const expirationDate = new Date(expirationTime * 1000).toLocaleDateString();
130
- 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/`;
131
- console.warn(expirationWarning);
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
- export const warnIfAccessTokenCloseToExpiry = () => {
134
- const accessToken = getAccessToken();
135
- if (!accessToken) {
136
- throw new Error(ServiceErrorMessageConstants.NO_AUTH_ERROR_PAT_TOKEN.message);
137
- }
138
- const claims = parseJwt(accessToken);
139
- const currentTime = Date.now();
140
- if (isTokenExpiringSoon(claims.exp, currentTime)) {
141
- warnAboutTokenExpiry(claims.exp, currentTime);
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
- export const fetchOrValidateAccessToken = async (credential) => {
145
- const entraIdAccessToken = createEntraIdAccessToken(credential);
146
- // Fetch a token or refresh if needed in a single call
147
- if (entraIdAccessToken.doesEntraIdAccessTokenNeedRotation()) {
148
- await entraIdAccessToken.fetchEntraIdAccessToken();
149
- }
150
- const token = getAccessToken();
151
- if (!token) {
152
- throw new Error(ServiceErrorMessageConstants.NO_AUTH_ERROR_ENTRA_TOKEN.message);
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
- export const getVersionInfo = (version) => {
157
- const regex = /^(\d+)(?:\.(\d+))?(?:\.(\d+))?/;
158
- const match = version.match(regex);
159
- const versionInfo = {
160
- major: 0,
161
- minor: 0,
162
- patch: 0,
163
- };
164
- versionInfo.major = match && match[1] ? parseInt(match[1], 10) : 0;
165
- versionInfo.minor = match && match[2] ? parseInt(match[2], 10) : 0;
166
- versionInfo.patch = match && match[3] ? parseInt(match[3], 10) : 0;
167
- return versionInfo;
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
- export const validatePlaywrightVersion = () => {
170
- const minimumSupportedVersion = Constants.MinimumSupportedPlaywrightVersion;
171
- const installedVersion = getPlaywrightVersion();
172
- const minimumSupportedVersionInfo = getVersionInfo(minimumSupportedVersion);
173
- const installedVersionInfo = getVersionInfo(installedVersion);
174
- const isInstalledVersionGreater = installedVersionInfo.major > minimumSupportedVersionInfo.major ||
175
- (installedVersionInfo.major === minimumSupportedVersionInfo.major &&
176
- installedVersionInfo.minor >= minimumSupportedVersionInfo.minor);
177
- if (!isInstalledVersionGreater) {
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
- export const getTestRunConfig = (config) => {
182
- const maxWorkers = config.workers || config.metadata.actualWorkers;
183
- const frameWorkVersion = config.version;
184
- const testRunConfig = {
185
- framework: {
186
- name: RunConfigConstants.TEST_FRAMEWORK_NAME,
187
- version: frameWorkVersion,
188
- runnerName: RunConfigConstants.TEST_FRAMEWORK_RUNNERNAME,
189
- },
190
- sdkLanguage: RunConfigConstants.TEST_SDK_LANGUAGE,
191
- maxWorkers: maxWorkers,
192
- };
193
- return testRunConfig;
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
- export function getTestRunApiUrl() {
196
- const result = populateValuesFromServiceUrl();
197
- const runId = process.env[InternalEnvironmentVariables.MPT_SERVICE_RUN_ID];
198
- if (!result?.region || !result?.domain || !result?.accountId) {
199
- exitWithFailureMessage(ServiceErrorMessageConstants.NO_SERVICE_URL_ERROR);
200
- }
201
- const baseUrl = `https://${result?.region}.${UrlConstants.ReportingApiSubdomain}.${result?.domain}/${UrlConstants.PlaywrightWorkspacesPath}/${result?.accountId}/${UrlConstants.TestRunsPath}`;
202
- const url = runId ? `${baseUrl}/${runId}` : baseUrl;
203
- return `${url}?api-version=${Constants.LatestAPIVersion}`;
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
- export function isNullOrEmpty(str) {
206
- return !str || str.trim() === "";
197
+ function isNullOrEmpty(str) {
198
+ return !str || str.trim() === "";
207
199
  }
208
200
  async function runCommand(command) {
209
- return new Promise((resolve, reject) => {
210
- exec(command, (error, stdout, stderr) => {
211
- if (error) {
212
- reject(error);
213
- return;
214
- }
215
- if (stderr) {
216
- reject(new Error(stderr));
217
- return;
218
- }
219
- resolve(stdout.trim());
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
- export async function getRunName(ciInfo) {
224
- if (ciInfo.providerName === CI_PROVIDERS.GITHUB &&
225
- process.env["GITHUB_EVENT_NAME"] === "pull_request") {
226
- const prNumber = `${process.env["GITHUB_REF_NAME"]?.split("/")[0]}`;
227
- const prLink = `${process.env["GITHUB_REPOSITORY"]}/pull/${prNumber}`;
228
- return `PR# ${prNumber} on Repo: ${process.env["GITHUB_REPOSITORY"]} (${prLink})`;
229
- }
230
- try {
231
- const gitVersion = await runCommand(GitHubActionsConstants.GIT_VERSION_COMMAND);
232
- if (isNullOrEmpty(gitVersion)) {
233
- throw new Error("Git is not installed on the machine");
234
- }
235
- const isInsideWorkTree = await runCommand(GitHubActionsConstants.GIT_REV_PARSE);
236
- if (isInsideWorkTree !== "true") {
237
- throw new Error("Not inside a git repository");
238
- }
239
- const gitCommitMessage = await runCommand(GitHubActionsConstants.GIT_COMMIT_MESSAGE_COMMAND);
240
- return gitCommitMessage;
241
- }
242
- catch (err) {
243
- coreLogger.error(`Error in getting git commit message: ${err}.`);
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
- export function extractErrorMessage(responseBody) {
248
- if (!responseBody) {
249
- return "";
250
- }
251
- try {
252
- const errorResponse = JSON.parse(responseBody);
253
- if (errorResponse.error && errorResponse.error.message) {
254
- return errorResponse.error.message;
255
- }
256
- return responseBody;
257
- }
258
- catch (e) {
259
- return responseBody;
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
- export function getWorkspaceMetaDataApiUrl() {
263
- const result = populateValuesFromServiceUrl();
264
- if (!result?.region || !result?.domain || !result?.accountId) {
265
- exitWithFailureMessage(ServiceErrorMessageConstants.NO_SERVICE_URL_ERROR);
266
- }
267
- const baseUrl = `https://${result?.region}.${UrlConstants.ApiSubdomain}.${result?.domain}/${UrlConstants.PlaywrightWorkspacesPath}/${result?.accountId}`;
268
- return `${baseUrl}?api-version=${Constants.LatestAPIVersion}`;
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
- export function getHtmlReporterOutputFolder(config) {
271
- const defaultFolder = "playwright-report";
272
- if (!config?.reporter) {
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
- export function getContentType(filePath) {
289
- const ext = filePath.toLowerCase().split(".").pop();
290
- const contentTypes = {
291
- html: "text/html",
292
- css: "text/css",
293
- js: "application/javascript",
294
- json: "application/json",
295
- png: "image/png",
296
- jpg: "image/jpeg",
297
- jpeg: "image/jpeg",
298
- svg: "image/svg+xml",
299
- ico: "image/x-icon",
300
- txt: "text/plain",
301
- ttf: "font/ttf",
302
- woff: "font/woff",
303
- woff2: "font/woff2",
304
- webmanifest: "application/manifest+json",
305
- map: "application/json",
306
- xml: "application/xml",
307
- pdf: "application/pdf",
308
- zip: "application/zip",
309
- };
310
- return contentTypes[ext || ""] || "application/octet-stream";
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
- export function calculateOptimalConcurrency(files) {
313
- const totalFiles = files.length;
314
- const totalSize = files.reduce((sum, f) => sum + f.size, 0);
315
- const avgFileSize = totalSize / totalFiles;
316
- let optimalConcurrency;
317
- if (totalFiles <= 10) {
318
- optimalConcurrency = Math.min(totalFiles, 10);
319
- }
320
- else if (avgFileSize < UploadConstants.SMALL_FILE_THRESHOLD) {
321
- optimalConcurrency = Math.min(UploadConstants.MAX_CONCURRENCY, Math.max(UploadConstants.BASE_CONCURRENCY, totalFiles / 50));
322
- }
323
- else if (totalFiles > 1000) {
324
- optimalConcurrency = Math.min(UploadConstants.MAX_CONCURRENCY, UploadConstants.BASE_CONCURRENCY + Math.floor(totalFiles / 200));
325
- }
326
- else {
327
- optimalConcurrency = Math.min(UploadConstants.MAX_CONCURRENCY, UploadConstants.BASE_CONCURRENCY);
328
- }
329
- return Math.floor(optimalConcurrency);
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
- export function collectAllFiles(folderPath, basePath, runIdFolderPrefix) {
332
- const files = [];
333
- const stack = [folderPath];
334
- while (stack.length > 0) {
335
- const currentPath = stack.pop();
336
- try {
337
- const items = readdirSync(currentPath);
338
- for (const item of items) {
339
- const itemPath = join(currentPath, item);
340
- const stats = statSync(itemPath);
341
- if (stats.isDirectory()) {
342
- stack.push(itemPath);
343
- }
344
- else {
345
- let relativePath = relative(basePath, itemPath).split("\\").join("/");
346
- if (runIdFolderPrefix) {
347
- relativePath = `${runIdFolderPrefix}/${relativePath}`;
348
- }
349
- files.push({
350
- fullPath: itemPath,
351
- relativePath,
352
- size: stats.size,
353
- contentType: getContentType(itemPath),
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
- return files;
353
+ }
354
+ return files;
363
355
  }
364
- export function resolveTenantDomain(tenantId, tenants) {
365
- if (!tenantId || tenants.length === 0) {
366
- return undefined;
367
- }
368
- const matchingTenant = tenants.find((t) => t.tenantId === tenantId);
369
- coreLogger.info(`Resolved tenant domain: ${JSON.stringify(matchingTenant?.defaultDomain)} for tenant ID: ${tenantId}`);
370
- return matchingTenant?.defaultDomain;
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
- export function getPortalTestRunUrl(workspaceMetadata, tenantDomain) {
373
- const { subscriptionId, resourceId, name } = workspaceMetadata ?? {};
374
- if (!subscriptionId || !resourceId || !name) {
375
- throw new Error("Missing required workspace metadata: subscriptionId, resourceId, and name are required");
376
- }
377
- // Extract resource group from resourceId
378
- const resourceIdParts = resourceId.split("/");
379
- const resourceGroupIndex = resourceIdParts.findIndex((part) => part.toLowerCase() === UrlConstants.ResourceGroupsPath);
380
- if (resourceGroupIndex === -1 || resourceGroupIndex + 1 >= resourceIdParts.length) {
381
- throw new Error("Invalid resourceId format: could not extract resource group name");
382
- }
383
- const resourceGroupName = resourceIdParts[resourceGroupIndex + 1];
384
- const tenantFragment = tenantDomain ? `#@${tenantDomain}` : "#";
385
- return `${UrlConstants.AzurePortalBaseUrl}/${tenantFragment}${UrlConstants.ResourcePath}${UrlConstants.SubscriptionsPath}/${encodeURIComponent(subscriptionId)}${UrlConstants.ResourceGroupsUrlPath}/${encodeURIComponent(resourceGroupName)}${UrlConstants.ProvidersPath}/${UrlConstants.LoadTestServiceProvider}/${UrlConstants.PlaywrightWorkspacesResourceType}/${encodeURIComponent(name)}/${UrlConstants.TestRunsRoute}`;
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
- export const getStorageAccountNameFromUri = (storageUri) => {
388
- try {
389
- if (!storageUri || typeof storageUri !== "string") {
390
- return null;
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
- catch (error) {
402
- console.warn("Failed to extract storage account name from URI:", storageUri, error);
403
- return null;
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