@playwright/test 1.37.0-alpha-aug-4-2023 → 1.37.0-alpha-aug-5-2023

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/lib/cli.js CHANGED
@@ -245,18 +245,15 @@ function restartWithExperimentalTsEsm(configFile) {
245
245
  if (nodeVersion < 16) return false;
246
246
  if (!configFile) return false;
247
247
  if (process.env.PW_DISABLE_TS_ESM) return false;
248
- if (process.env.PW_TS_ESM_ON) {
249
- // clear execArgv after restart, so that childProcess.fork in user code does not inherit our loader.
250
- process.execArgv = (0, _util.execArgvWithoutExperimentalLoaderOptions)();
251
- return false;
252
- }
248
+ if (process.env.PW_TS_ESM_ON) return false;
253
249
  if (!(0, _util.fileIsModule)(configFile)) return false;
250
+ const NODE_OPTIONS = (process.env.NODE_OPTIONS || '') + (0, _util.experimentalLoaderOption)();
254
251
  const innerProcess = require('child_process').fork(require.resolve('./cli'), process.argv.slice(2), {
255
252
  env: {
256
253
  ...process.env,
254
+ NODE_OPTIONS,
257
255
  PW_TS_ESM_ON: '1'
258
- },
259
- execArgv: (0, _util.execArgvWithExperimentalLoaderOptions)()
256
+ }
260
257
  });
261
258
  innerProcess.on('close', code => {
262
259
  if (code !== 0 && code !== null) (0, _utils.gracefullyProcessExitDoNotHang)(code);
@@ -43,9 +43,6 @@ sendMessageToParent({
43
43
  process.on('disconnect', gracefullyCloseAndExit);
44
44
  process.on('SIGINT', () => {});
45
45
  process.on('SIGTERM', () => {});
46
-
47
- // Clear execArgv immediately, so that the user-code does not inherit our loader.
48
- process.execArgv = (0, _util.execArgvWithoutExperimentalLoaderOptions)();
49
46
  let processRunner;
50
47
  let processName;
51
48
  const startingEnv = {
@@ -0,0 +1,36 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.StringInternPool = void 0;
7
+ /**
8
+ * Copyright (c) Microsoft Corporation.
9
+ *
10
+ * Licensed under the Apache License, Version 2.0 (the "License");
11
+ * you may not use this file except in compliance with the License.
12
+ * You may obtain a copy of the License at
13
+ *
14
+ * http://www.apache.org/licenses/LICENSE-2.0
15
+ *
16
+ * Unless required by applicable law or agreed to in writing, software
17
+ * distributed under the License is distributed on an "AS IS" BASIS,
18
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19
+ * See the License for the specific language governing permissions and
20
+ * limitations under the License.
21
+ */
22
+
23
+ class StringInternPool {
24
+ constructor() {
25
+ this._stringCache = new Map();
26
+ }
27
+ internString(s) {
28
+ let result = this._stringCache.get(s);
29
+ if (!result) {
30
+ this._stringCache.set(s, s);
31
+ result = s;
32
+ }
33
+ return result;
34
+ }
35
+ }
36
+ exports.StringInternPool = StringInternPool;
@@ -6,6 +6,7 @@ Object.defineProperty(exports, "__esModule", {
6
6
  exports.baseFullConfig = exports.TeleTestCase = exports.TeleSuite = exports.TeleReporterReceiver = void 0;
7
7
  exports.parseRegexPatterns = parseRegexPatterns;
8
8
  exports.serializeRegexPatterns = serializeRegexPatterns;
9
+ var _stringInternPool = require("./stringInternPool");
9
10
  /**
10
11
  * Copyright (c) Microsoft Corporation.
11
12
  *
@@ -34,6 +35,7 @@ class TeleReporterReceiver {
34
35
  this._reuseTestCases = void 0;
35
36
  this._reportConfig = void 0;
36
37
  this._config = void 0;
38
+ this._stringPool = new _stringInternPool.StringInternPool();
37
39
  this._rootSuite = new TeleSuite('', 'root');
38
40
  this._pathSeparator = pathSeparator;
39
41
  this._reporter = reporter;
@@ -129,7 +131,7 @@ class TeleReporterReceiver {
129
131
  testResult.retry = payload.retry;
130
132
  testResult.workerIndex = payload.workerIndex;
131
133
  testResult.parallelIndex = payload.parallelIndex;
132
- testResult.startTime = new Date(payload.startTime);
134
+ testResult.setStartTimeNumber(payload.startTime);
133
135
  testResult.statusEx = 'running';
134
136
  (_this$_reporter$onTes = (_this$_reporter2 = this._reporter).onTestBegin) === null || _this$_reporter$onTes === void 0 ? void 0 : _this$_reporter$onTes.call(_this$_reporter2, test, testResult);
135
137
  }
@@ -147,25 +149,16 @@ class TeleReporterReceiver {
147
149
  result.error = (_result$errors = result.errors) === null || _result$errors === void 0 ? void 0 : _result$errors[0];
148
150
  result.attachments = this._parseAttachments(payload.attachments);
149
151
  (_this$_reporter$onTes2 = (_this$_reporter3 = this._reporter).onTestEnd) === null || _this$_reporter$onTes2 === void 0 ? void 0 : _this$_reporter$onTes2.call(_this$_reporter3, test, result);
152
+ // Free up the memory as won't see these step ids.
153
+ result.stepMap = new Map();
150
154
  }
151
155
  _onStepBegin(testId, resultId, payload) {
152
156
  var _this$_reporter$onSte, _this$_reporter4;
153
157
  const test = this._tests.get(testId);
154
158
  const result = test.resultsMap.get(resultId);
155
159
  const parentStep = payload.parentStepId ? result.stepMap.get(payload.parentStepId) : undefined;
156
- const step = {
157
- titlePath: () => {
158
- const parentPath = (parentStep === null || parentStep === void 0 ? void 0 : parentStep.titlePath()) || [];
159
- return [...parentPath, payload.title];
160
- },
161
- title: payload.title,
162
- category: payload.category,
163
- location: this._absoluteLocation(payload.location),
164
- parent: parentStep,
165
- startTime: new Date(payload.startTime),
166
- duration: -1,
167
- steps: []
168
- };
160
+ const location = this._absoluteLocation(payload.location);
161
+ const step = new TeleTestStep(payload, parentStep, location);
169
162
  if (parentStep) parentStep.steps.push(step);else result.steps.push(step);
170
163
  result.stepMap.set(payload.id, step);
171
164
  (_this$_reporter$onSte = (_this$_reporter4 = this._reporter).onStepBegin) === null || _this$_reporter$onSte === void 0 ? void 0 : _this$_reporter$onSte.call(_this$_reporter4, test, result, step);
@@ -203,6 +196,8 @@ class TeleReporterReceiver {
203
196
  }
204
197
  _onExit() {
205
198
  var _this$_reporter$onExi, _this$_reporter10;
199
+ // Free up the memory from the string pool.
200
+ this._stringPool = new _stringInternPool.StringInternPool();
206
201
  return (_this$_reporter$onExi = (_this$_reporter10 = this._reporter).onExit) === null || _this$_reporter$onExi === void 0 ? void 0 : _this$_reporter$onExi.call(_this$_reporter10);
207
202
  }
208
203
  _parseConfig(config) {
@@ -288,7 +283,7 @@ class TeleReporterReceiver {
288
283
  }
289
284
  _absolutePath(relativePath) {
290
285
  if (!relativePath) return relativePath;
291
- return this._rootDir + this._pathSeparator + relativePath;
286
+ return this._stringPool.internString(this._rootDir + this._pathSeparator + relativePath);
292
287
  }
293
288
  }
294
289
  exports.TeleReporterReceiver = TeleReporterReceiver;
@@ -368,27 +363,68 @@ class TeleTestCase {
368
363
  this.resultsMap.clear();
369
364
  }
370
365
  _createTestResult(id) {
371
- const result = {
372
- retry: this.results.length,
373
- parallelIndex: -1,
374
- workerIndex: -1,
375
- duration: -1,
376
- startTime: new Date(),
377
- stdout: [],
378
- stderr: [],
379
- attachments: [],
380
- status: 'skipped',
381
- statusEx: 'scheduled',
382
- steps: [],
383
- errors: [],
384
- stepMap: new Map()
385
- };
366
+ const result = new TeleTestResult(this.results.length);
386
367
  this.results.push(result);
387
368
  this.resultsMap.set(id, result);
388
369
  return result;
389
370
  }
390
371
  }
391
372
  exports.TeleTestCase = TeleTestCase;
373
+ class TeleTestStep {
374
+ constructor(payload, parentStep, location) {
375
+ this.title = void 0;
376
+ this.category = void 0;
377
+ this.location = void 0;
378
+ this.parent = void 0;
379
+ this.duration = -1;
380
+ this.steps = [];
381
+ this._startTime = 0;
382
+ this.title = payload.title;
383
+ this.category = payload.category;
384
+ this.location = location;
385
+ this.parent = parentStep;
386
+ this._startTime = payload.startTime;
387
+ }
388
+ titlePath() {
389
+ var _this$parent;
390
+ const parentPath = ((_this$parent = this.parent) === null || _this$parent === void 0 ? void 0 : _this$parent.titlePath()) || [];
391
+ return [...parentPath, this.title];
392
+ }
393
+ get startTime() {
394
+ return new Date(this._startTime);
395
+ }
396
+ set startTime(value) {
397
+ this._startTime = +value;
398
+ }
399
+ }
400
+ class TeleTestResult {
401
+ constructor(retry) {
402
+ this.retry = void 0;
403
+ this.parallelIndex = -1;
404
+ this.workerIndex = -1;
405
+ this.duration = -1;
406
+ this.stdout = [];
407
+ this.stderr = [];
408
+ this.attachments = [];
409
+ this.status = 'skipped';
410
+ this.steps = [];
411
+ this.errors = [];
412
+ this.error = void 0;
413
+ this.stepMap = new Map();
414
+ this.statusEx = 'scheduled';
415
+ this._startTime = 0;
416
+ this.retry = retry;
417
+ }
418
+ setStartTimeNumber(startTime) {
419
+ this._startTime = startTime;
420
+ }
421
+ get startTime() {
422
+ return new Date(this._startTime);
423
+ }
424
+ set startTime(value) {
425
+ this._startTime = +value;
426
+ }
427
+ }
392
428
  const baseFullConfig = {
393
429
  forbidOnly: false,
394
430
  fullyParallel: false,
@@ -8,6 +8,7 @@ var _path = _interopRequireDefault(require("path"));
8
8
  var _net = _interopRequireDefault(require("net"));
9
9
  var _utilsBundle = require("playwright-core/lib/utilsBundle");
10
10
  var _utils = require("playwright-core/lib/utils");
11
+ var _util = require("../util");
11
12
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
12
13
  /**
13
14
  * Copyright (c) Microsoft Corporation.
@@ -32,7 +33,7 @@ const DEFAULT_ENVIRONMENT_VARIABLES = {
32
33
  const debugWebServer = (0, _utilsBundle.debug)('pw:webserver');
33
34
  class WebServerPlugin {
34
35
  constructor(options, checkPortOnly) {
35
- this._isAvailable = void 0;
36
+ this._isAvailableCallback = void 0;
36
37
  this._killProcess = void 0;
37
38
  this._processExitedPromise = void 0;
38
39
  this._options = void 0;
@@ -45,7 +46,7 @@ class WebServerPlugin {
45
46
  async setup(config, configDir, reporter) {
46
47
  var _this$_reporter$onStd;
47
48
  this._reporter = reporter;
48
- this._isAvailable = getIsAvailableFunction(this._options.url, this._checkPortOnly, !!this._options.ignoreHTTPSErrors, (_this$_reporter$onStd = this._reporter.onStdErr) === null || _this$_reporter$onStd === void 0 ? void 0 : _this$_reporter$onStd.bind(this._reporter));
49
+ this._isAvailableCallback = this._options.url ? getIsAvailableFunction(this._options.url, this._checkPortOnly, !!this._options.ignoreHTTPSErrors, (_this$_reporter$onStd = this._reporter.onStdErr) === null || _this$_reporter$onStd === void 0 ? void 0 : _this$_reporter$onStd.bind(this._reporter)) : undefined;
49
50
  this._options.cwd = this._options.cwd ? _path.default.resolve(configDir, this._options.cwd) : configDir;
50
51
  try {
51
52
  await this._startProcess();
@@ -60,14 +61,15 @@ class WebServerPlugin {
60
61
  await ((_this$_killProcess = this._killProcess) === null || _this$_killProcess === void 0 ? void 0 : _this$_killProcess.call(this));
61
62
  }
62
63
  async _startProcess() {
64
+ var _this$_isAvailableCal;
63
65
  let processExitedReject = error => {};
64
66
  this._processExitedPromise = new Promise((_, reject) => processExitedReject = reject);
65
- const isAlreadyAvailable = await this._isAvailable();
67
+ const isAlreadyAvailable = await ((_this$_isAvailableCal = this._isAvailableCallback) === null || _this$_isAvailableCal === void 0 ? void 0 : _this$_isAvailableCal.call(this));
66
68
  if (isAlreadyAvailable) {
67
69
  var _this$_options$url;
68
70
  debugWebServer(`WebServer is already available`);
69
71
  if (this._options.reuseExistingServer) return;
70
- const port = new URL(this._options.url);
72
+ const port = new URL(this._options.url).port;
71
73
  throw new Error(`${(_this$_options$url = this._options.url) !== null && _this$_options$url !== void 0 ? _this$_options$url : `http://localhost${port ? ':' + port : ''}`} is already used, make sure that nothing is running on the port/url or set reuseExistingServer:true in config.webServer.`);
72
74
  }
73
75
  debugWebServer(`Starting WebServer process ${this._options.command}...`);
@@ -78,6 +80,7 @@ class WebServerPlugin {
78
80
  command: this._options.command,
79
81
  env: {
80
82
  ...DEFAULT_ENVIRONMENT_VARIABLES,
83
+ ...(0, _util.envWithoutExperimentalLoaderOptions)(),
81
84
  ...this._options.env
82
85
  },
83
86
  cwd: this._options.cwd,
@@ -102,20 +105,21 @@ class WebServerPlugin {
102
105
  });
103
106
  }
104
107
  async _waitForProcess() {
108
+ if (!this._isAvailableCallback) {
109
+ this._processExitedPromise.catch(() => {});
110
+ return;
111
+ }
105
112
  debugWebServer(`Waiting for availability...`);
106
- await this._waitForAvailability();
107
- debugWebServer(`WebServer available`);
108
- }
109
- async _waitForAvailability() {
110
113
  const launchTimeout = this._options.timeout || 60 * 1000;
111
114
  const cancellationToken = {
112
115
  canceled: false
113
116
  };
114
117
  const {
115
118
  timedOut
116
- } = await Promise.race([(0, _utils.raceAgainstDeadline)(() => waitFor(this._isAvailable, cancellationToken), (0, _utils.monotonicTime)() + launchTimeout), this._processExitedPromise]);
119
+ } = await Promise.race([(0, _utils.raceAgainstDeadline)(() => waitFor(this._isAvailableCallback, cancellationToken), (0, _utils.monotonicTime)() + launchTimeout), this._processExitedPromise]);
117
120
  cancellationToken.canceled = true;
118
121
  if (timedOut) throw new Error(`Timed out waiting ${launchTimeout}ms from config.webServer.`);
122
+ debugWebServer(`WebServer available`);
119
123
  }
120
124
  }
121
125
  exports.WebServerPlugin = WebServerPlugin;
@@ -186,11 +190,14 @@ const webServerPluginsForConfig = config => {
186
190
  const shouldSetBaseUrl = !!config.config.webServer;
187
191
  const webServerPlugins = [];
188
192
  for (const webServerConfig of config.webServers) {
189
- if (!webServerConfig.port && !webServerConfig.url || webServerConfig.port && webServerConfig.url) throw new Error(`Exactly one of 'port' or 'url' is required in config.webServer.`);
190
- const url = webServerConfig.url || `http://localhost:${webServerConfig.port}`;
193
+ if (webServerConfig.port && webServerConfig.url) throw new Error(`Either 'port' or 'url' should be specified in config.webServer.`);
194
+ let url;
195
+ if (webServerConfig.port || webServerConfig.url) {
196
+ url = webServerConfig.url || `http://localhost:${webServerConfig.port}`;
191
197
 
192
- // We only set base url when only the port is given. That's a legacy mode we have regrets about.
193
- if (shouldSetBaseUrl && !webServerConfig.url) process.env.PLAYWRIGHT_TEST_BASE_URL = url;
198
+ // We only set base url when only the port is given. That's a legacy mode we have regrets about.
199
+ if (shouldSetBaseUrl && !webServerConfig.url) process.env.PLAYWRIGHT_TEST_BASE_URL = url;
200
+ }
194
201
  webServerPlugins.push(new WebServerPlugin({
195
202
  ...webServerConfig,
196
203
  url
@@ -7,6 +7,7 @@ exports.createMergedReport = createMergedReport;
7
7
  var _fs = _interopRequireDefault(require("fs"));
8
8
  var _path = _interopRequireDefault(require("path"));
9
9
  var _teleReceiver = require("../isomorphic/teleReceiver");
10
+ var _stringInternPool = require("../isomorphic/stringInternPool");
10
11
  var _reporters = require("../runner/reporters");
11
12
  var _multiplexer = require("./multiplexer");
12
13
  var _utils = require("playwright-core/lib/utils");
@@ -209,6 +210,7 @@ function printStatusToStdout(message) {
209
210
  class ProjectNamePatcher {
210
211
  constructor(_allTestIds, _projectNameSuffix) {
211
212
  this._testIds = new Set();
213
+ this._stringPool = new _stringInternPool.StringInternPool();
212
214
  this._allTestIds = _allTestIds;
213
215
  this._projectNameSuffix = _projectNameSuffix;
214
216
  }
@@ -266,6 +268,6 @@ class ProjectNamePatcher {
266
268
  // To avoid reporters being confused by clashing test ids, we automatically
267
269
  // make them unique and produce a separate test from each blob.
268
270
  while (this._allTestIds.has(testId)) testId = testId + '1';
269
- return testId;
271
+ return this._stringPool.internString(testId);
270
272
  }
271
273
  }
@@ -203,7 +203,7 @@ class TeleReporterEmitter {
203
203
  retry: result.retry,
204
204
  workerIndex: result.workerIndex,
205
205
  parallelIndex: result.parallelIndex,
206
- startTime: result.startTime.toISOString()
206
+ startTime: +result.startTime
207
207
  };
208
208
  }
209
209
  _serializeResultEnd(result) {
@@ -231,7 +231,7 @@ class TeleReporterEmitter {
231
231
  parentStepId: (_step$parent = step.parent) === null || _step$parent === void 0 ? void 0 : _step$parent[idSymbol],
232
232
  title: step.title,
233
233
  category: step.category,
234
- startTime: step.startTime.toISOString(),
234
+ startTime: +step.startTime,
235
235
  location: this._relativeLocation(step.location)
236
236
  };
237
237
  }
@@ -7,7 +7,6 @@ exports.ProcessHost = void 0;
7
7
  var _child_process = _interopRequireDefault(require("child_process"));
8
8
  var _events = require("events");
9
9
  var _utilsBundle = require("playwright-core/lib/utilsBundle");
10
- var _util = require("../util");
11
10
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
12
11
  /**
13
12
  * Copyright Microsoft Corporation. All rights reserved.
@@ -50,10 +49,7 @@ class ProcessHost extends _events.EventEmitter {
50
49
  ...process.env,
51
50
  ...this._extraEnv
52
51
  },
53
- stdio: inheritStdio ? ['ignore', 'inherit', 'inherit', 'ipc'] : ['ignore', 'ignore', process.env.PW_RUNNER_DEBUG ? 'inherit' : 'ignore', 'ipc'],
54
- ...(process.env.PW_TS_ESM_ON ? {
55
- execArgv: (0, _util.execArgvWithExperimentalLoaderOptions)()
56
- } : {})
52
+ stdio: inheritStdio ? ['ignore', 'inherit', 'inherit', 'ipc'] : ['ignore', 'ignore', process.env.PW_RUNNER_DEBUG ? 'inherit' : 'ignore', 'ipc']
57
53
  });
58
54
  this.process.on('exit', (code, signal) => {
59
55
  this.didExit = true;
package/lib/util.js CHANGED
@@ -10,10 +10,10 @@ exports.createFileMatcher = createFileMatcher;
10
10
  exports.createFileMatcherFromArguments = createFileMatcherFromArguments;
11
11
  exports.createTitleMatcher = createTitleMatcher;
12
12
  exports.debugTest = void 0;
13
+ exports.envWithoutExperimentalLoaderOptions = envWithoutExperimentalLoaderOptions;
13
14
  exports.errorWithFile = errorWithFile;
14
- exports.execArgvWithExperimentalLoaderOptions = execArgvWithExperimentalLoaderOptions;
15
- exports.execArgvWithoutExperimentalLoaderOptions = execArgvWithoutExperimentalLoaderOptions;
16
15
  exports.expectTypes = expectTypes;
16
+ exports.experimentalLoaderOption = experimentalLoaderOption;
17
17
  exports.fileIsModule = fileIsModule;
18
18
  exports.filterStackFile = filterStackFile;
19
19
  exports.filterStackTrace = filterStackTrace;
@@ -283,12 +283,16 @@ function folderIsModule(folder) {
283
283
  // Rely on `require` internal caching logic.
284
284
  return require(packageJsonPath).type === 'module';
285
285
  }
286
- const kExperimentalLoaderOptions = ['--no-warnings', `--experimental-loader=${_url.default.pathToFileURL(require.resolve('@playwright/test/lib/transform/esmLoader')).toString()}`];
287
- function execArgvWithExperimentalLoaderOptions() {
288
- return [...process.execArgv, ...kExperimentalLoaderOptions];
286
+ function experimentalLoaderOption() {
287
+ return ` --no-warnings --experimental-loader=${_url.default.pathToFileURL(require.resolve('@playwright/test/lib/transform/esmLoader')).toString()}`;
289
288
  }
290
- function execArgvWithoutExperimentalLoaderOptions() {
291
- return process.execArgv.filter(arg => !kExperimentalLoaderOptions.includes(arg));
289
+ function envWithoutExperimentalLoaderOptions() {
290
+ const substring = experimentalLoaderOption();
291
+ const result = {
292
+ ...process.env
293
+ };
294
+ if (result.NODE_OPTIONS) result.NODE_OPTIONS = result.NODE_OPTIONS.replace(substring, '').trim() || undefined;
295
+ return result;
292
296
  }
293
297
 
294
298
  // This follows the --moduleResolution=bundler strategy from tsc.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@playwright/test",
3
- "version": "1.37.0-alpha-aug-4-2023",
3
+ "version": "1.37.0-alpha-aug-5-2023",
4
4
  "description": "A high-level API to automate web browsers",
5
5
  "repository": "github:Microsoft/playwright",
6
6
  "homepage": "https://playwright.dev",
@@ -41,7 +41,7 @@
41
41
  "license": "Apache-2.0",
42
42
  "dependencies": {
43
43
  "@types/node": "*",
44
- "playwright-core": "1.37.0-alpha-aug-4-2023"
44
+ "playwright-core": "1.37.0-alpha-aug-5-2023"
45
45
  },
46
46
  "optionalDependencies": {
47
47
  "fsevents": "2.3.2"
package/types/test.d.ts CHANGED
@@ -6735,15 +6735,15 @@ interface TestConfigWebServer {
6735
6735
  command: string;
6736
6736
 
6737
6737
  /**
6738
- * The port that your http server is expected to appear on. It does wait until it accepts connections. Exactly one of
6739
- * `port` or `url` is required.
6738
+ * The port that your http server is expected to appear on. It does wait until it accepts connections. Either `port`
6739
+ * or `url` should be specified.
6740
6740
  */
6741
6741
  port?: number;
6742
6742
 
6743
6743
  /**
6744
6744
  * The url on your http server that is expected to return a 2xx, 3xx, 400, 401, 402, or 403 status code when the
6745
6745
  * server is ready to accept connections. Redirects (3xx status codes) are being followed and the new location is
6746
- * checked. Exactly one of `port` or `url` is required.
6746
+ * checked. Either `port` or `url` should be specified.
6747
6747
  */
6748
6748
  url?: string;
6749
6749