@playwright/test 1.37.0-alpha-aug-3-2023 → 1.37.0-alpha-aug-4-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,15 +245,18 @@ 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) 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
+ }
249
253
  if (!(0, _util.fileIsModule)(configFile)) return false;
250
- const NODE_OPTIONS = (process.env.NODE_OPTIONS || '') + (0, _util.experimentalLoaderOption)();
251
254
  const innerProcess = require('child_process').fork(require.resolve('./cli'), process.argv.slice(2), {
252
255
  env: {
253
256
  ...process.env,
254
- NODE_OPTIONS,
255
257
  PW_TS_ESM_ON: '1'
256
- }
258
+ },
259
+ execArgv: (0, _util.execArgvWithExperimentalLoaderOptions)()
257
260
  });
258
261
  innerProcess.on('close', code => {
259
262
  if (code !== 0 && code !== null) (0, _utils.gracefullyProcessExitDoNotHang)(code);
@@ -43,6 +43,9 @@ 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)();
46
49
  let processRunner;
47
50
  let processName;
48
51
  const startingEnv = {
@@ -76,7 +76,7 @@ class SnapshotHelper {
76
76
  let actualModifier = '';
77
77
  if (!name) {
78
78
  const fullTitleWithoutSpec = [...testInfo.titlePath.slice(1), ++snapshotNames.anonymousSnapshotIndex].join(' ');
79
- name = (0, _util.sanitizeForFilePath)((0, _util.trimLongString)(fullTitleWithoutSpec)) + '.' + anonymousSnapshotExtension;
79
+ name = (0, _utils.sanitizeForFilePath)((0, _util.trimLongString)(fullTitleWithoutSpec)) + '.' + anonymousSnapshotExtension;
80
80
  this.snapshotName = name;
81
81
  } else {
82
82
  const joinedName = Array.isArray(name) ? name.join(_path.default.sep) : name;
@@ -8,7 +8,6 @@ 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");
12
11
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
13
12
  /**
14
13
  * Copyright (c) Microsoft Corporation.
@@ -79,7 +78,6 @@ class WebServerPlugin {
79
78
  command: this._options.command,
80
79
  env: {
81
80
  ...DEFAULT_ENVIRONMENT_VARIABLES,
82
- ...(0, _util.envWithoutExperimentalLoaderOptions)(),
83
81
  ...this._options.env
84
82
  },
85
83
  cwd: this._options.cwd,
@@ -3,7 +3,7 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- exports.BlobReporter = void 0;
6
+ exports.currentBlobReportVersion = exports.BlobReporter = void 0;
7
7
  var _fs = _interopRequireDefault(require("fs"));
8
8
  var _path = _interopRequireDefault(require("path"));
9
9
  var _utils = require("playwright-core/lib/utils");
@@ -29,7 +29,8 @@ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { de
29
29
  * limitations under the License.
30
30
  */
31
31
 
32
- const currentVersion = 1;
32
+ const currentBlobReportVersion = 1;
33
+ exports.currentBlobReportVersion = currentBlobReportVersion;
33
34
  class BlobReporter extends _teleEmitter.TeleReporterEmitter {
34
35
  constructor(options) {
35
36
  super(message => this._messages.push(message), false);
@@ -37,13 +38,14 @@ class BlobReporter extends _teleEmitter.TeleReporterEmitter {
37
38
  this._attachments = [];
38
39
  this._options = void 0;
39
40
  this._salt = void 0;
41
+ this._reportName = void 0;
40
42
  this._options = options;
41
43
  this._salt = (0, _utils.createGuid)();
42
44
  }
43
45
  onConfigure(config) {
44
46
  var _config$shard;
45
47
  const metadata = {
46
- version: currentVersion,
48
+ version: currentBlobReportVersion,
47
49
  projectSuffix: process.env.PWTEST_BLOB_SUFFIX,
48
50
  shard: (_config$shard = config.shard) !== null && _config$shard !== void 0 ? _config$shard : undefined
49
51
  };
@@ -51,6 +53,7 @@ class BlobReporter extends _teleEmitter.TeleReporterEmitter {
51
53
  method: 'onBlobReportMetadata',
52
54
  params: metadata
53
55
  });
56
+ this._reportName = this._computeReportName(config);
54
57
  super.onConfigure(config);
55
58
  }
56
59
  async onEnd(result) {
@@ -60,14 +63,13 @@ class BlobReporter extends _teleEmitter.TeleReporterEmitter {
60
63
  await _fs.default.promises.mkdir(outputDir, {
61
64
  recursive: true
62
65
  });
63
- const reportName = `report-${(0, _utils.createGuid)()}`;
64
66
  const zipFile = new _zipBundle.yazl.ZipFile();
65
67
  const zipFinishPromise = new _utils.ManualPromise();
66
68
  const finishPromise = zipFinishPromise.catch(e => {
67
- throw new Error(`Failed to write report ${reportName + '.zip'}: ` + e.message);
69
+ throw new Error(`Failed to write report ${this._reportName + '.zip'}: ` + e.message);
68
70
  });
69
71
  zipFile.on('error', error => zipFinishPromise.reject(error));
70
- const zipFileName = _path.default.join(outputDir, reportName + '.zip');
72
+ const zipFileName = _path.default.join(outputDir, this._reportName + '.zip');
71
73
  zipFile.outputStream.pipe(_fs.default.createWriteStream(zipFileName)).on('close', () => {
72
74
  zipFinishPromise.resolve(undefined);
73
75
  }).on('error', error => zipFinishPromise.reject(error));
@@ -83,10 +85,19 @@ class BlobReporter extends _teleEmitter.TeleReporterEmitter {
83
85
  }
84
86
  const lines = this._messages.map(m => JSON.stringify(m) + '\n');
85
87
  const content = _stream.Readable.from(lines);
86
- zipFile.addReadStream(content, reportName + '.jsonl');
88
+ zipFile.addReadStream(content, this._reportName + '.jsonl');
87
89
  zipFile.end();
88
90
  await finishPromise;
89
91
  }
92
+ _computeReportName(config) {
93
+ let reportName = 'report';
94
+ if (process.env.PWTEST_BLOB_SUFFIX) reportName += (0, _utils.sanitizeForFilePath)(process.env.PWTEST_BLOB_SUFFIX);
95
+ if (config.shard) {
96
+ const paddedNumber = `${config.shard.current}`.padStart(`${config.shard.total}`.length, '0');
97
+ reportName += `-${paddedNumber}`;
98
+ }
99
+ return reportName;
100
+ }
90
101
  _serializeAttachments(attachments) {
91
102
  return super._serializeAttachments(attachments).map(attachment => {
92
103
  if (!attachment.path) return attachment;
@@ -401,7 +401,7 @@ class HtmlBuilder {
401
401
  _fs.default.mkdirSync(_path.default.join(this._reportFolder, 'data'), {
402
402
  recursive: true
403
403
  });
404
- const extension = (0, _util.sanitizeForFilePath)(_path.default.extname(a.name).replace(/^\./, '')) || _utilsBundle.mime.getExtension(a.contentType) || 'dat';
404
+ const extension = (0, _utils.sanitizeForFilePath)(_path.default.extname(a.name).replace(/^\./, '')) || _utilsBundle.mime.getExtension(a.contentType) || 'dat';
405
405
  const sha1 = (0, _utils.calculateSha1)(a.body) + '.' + extension;
406
406
  _fs.default.writeFileSync(_path.default.join(this._reportFolder, 'data', sha1), a.body);
407
407
  return {
@@ -10,6 +10,7 @@ var _teleReceiver = require("../isomorphic/teleReceiver");
10
10
  var _reporters = require("../runner/reporters");
11
11
  var _multiplexer = require("./multiplexer");
12
12
  var _utils = require("playwright-core/lib/utils");
13
+ var _blob = require("./blob");
13
14
  var _util = require("../util");
14
15
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
15
16
  /**
@@ -90,7 +91,9 @@ async function extractAndParseReports(dir, shardFiles, printStatus) {
90
91
  function findMetadata(events, file) {
91
92
  var _events$;
92
93
  if (((_events$ = events[0]) === null || _events$ === void 0 ? void 0 : _events$.method) !== 'onBlobReportMetadata') throw new Error(`No metadata event found in ${file}`);
93
- return events[0].params;
94
+ const metadata = events[0].params;
95
+ if (metadata.version > _blob.currentBlobReportVersion) throw new Error(`Blob report ${file} was created with a newer version of Playwright.`);
96
+ return metadata;
94
97
  }
95
98
  async function mergeEvents(dir, shardReportFiles, printStatus) {
96
99
  const events = [];
@@ -198,7 +201,7 @@ function mergeEndEvents(endEvents) {
198
201
  }
199
202
  async function sortedShardFiles(dir) {
200
203
  const files = await _fs.default.promises.readdir(dir);
201
- return files.filter(file => file.startsWith('report-') && file.endsWith('.zip')).sort();
204
+ return files.filter(file => file.startsWith('report') && file.endsWith('.zip')).sort();
202
205
  }
203
206
  function printStatusToStdout(message) {
204
207
  process.stdout.write(`${message}\n`);
@@ -7,7 +7,6 @@ exports.default = void 0;
7
7
  var _fs = _interopRequireDefault(require("fs"));
8
8
  var _path = _interopRequireDefault(require("path"));
9
9
  var _utils = require("playwright-core/lib/utils");
10
- var _util = require("../util");
11
10
  var _base = require("./base");
12
11
  var _json = require("./json");
13
12
  var _babelBundle = require("../transform/babelBundle");
@@ -49,7 +48,7 @@ class RawReporter {
49
48
  });
50
49
  let reportFile;
51
50
  for (let i = 0; i < 10; ++i) {
52
- reportFile = _path.default.join(reportFolder, (0, _util.sanitizeForFilePath)(project.name || 'project') + (i ? '-' + i : '') + '.report');
51
+ reportFile = _path.default.join(reportFolder, (0, _utils.sanitizeForFilePath)(project.name || 'project') + (i ? '-' + i : '') + '.report');
53
52
  try {
54
53
  if (_fs.default.existsSync(reportFile)) continue;
55
54
  } catch (e) {}
@@ -7,6 +7,7 @@ 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");
10
11
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
11
12
  /**
12
13
  * Copyright Microsoft Corporation. All rights reserved.
@@ -49,7 +50,10 @@ class ProcessHost extends _events.EventEmitter {
49
50
  ...process.env,
50
51
  ...this._extraEnv
51
52
  },
52
- stdio: inheritStdio ? ['ignore', 'inherit', 'inherit', 'ipc'] : ['ignore', 'ignore', process.env.PW_RUNNER_DEBUG ? 'inherit' : 'ignore', 'ipc']
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
+ } : {})
53
57
  });
54
58
  this.process.on('exit', (code, signal) => {
55
59
  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;
14
13
  exports.errorWithFile = errorWithFile;
14
+ exports.execArgvWithExperimentalLoaderOptions = execArgvWithExperimentalLoaderOptions;
15
+ exports.execArgvWithoutExperimentalLoaderOptions = execArgvWithoutExperimentalLoaderOptions;
15
16
  exports.expectTypes = expectTypes;
16
- exports.experimentalLoaderOption = experimentalLoaderOption;
17
17
  exports.fileIsModule = fileIsModule;
18
18
  exports.filterStackFile = filterStackFile;
19
19
  exports.filterStackTrace = filterStackTrace;
@@ -27,7 +27,6 @@ exports.normalizeAndSaveAttachment = normalizeAndSaveAttachment;
27
27
  exports.relativeFilePath = relativeFilePath;
28
28
  exports.resolveImportSpecifierExtension = resolveImportSpecifierExtension;
29
29
  exports.resolveReporterOutputPath = resolveReporterOutputPath;
30
- exports.sanitizeForFilePath = sanitizeForFilePath;
31
30
  exports.serializeError = serializeError;
32
31
  exports.stringifyStackFrames = stringifyStackFrames;
33
32
  exports.trimLongString = trimLongString;
@@ -187,9 +186,6 @@ function expectTypes(receiver, types, matcherName) {
187
186
  throw new Error(`${matcherName} can be only used with ${typesString} object${types.length > 1 ? 's' : ''}`);
188
187
  }
189
188
  }
190
- function sanitizeForFilePath(s) {
191
- return s.replace(/[\x00-\x2C\x2E-\x2F\x3A-\x40\x5B-\x60\x7B-\x7F]+/g, '-');
192
- }
193
189
  function trimLongString(s, length = 100) {
194
190
  if (s.length <= length) return s;
195
191
  const hash = (0, _utils.calculateSha1)(s);
@@ -203,7 +199,7 @@ function addSuffixToFilePath(filePath, suffix, customExtension, sanitize = false
203
199
  const ext = _path.default.extname(filePath);
204
200
  const name = _path.default.basename(filePath, ext);
205
201
  const base = _path.default.join(dirname, name);
206
- return (sanitize ? sanitizeForFilePath(base) : base) + suffix + (customExtension || ext);
202
+ return (sanitize ? (0, _utils.sanitizeForFilePath)(base) : base) + suffix + (customExtension || ext);
207
203
  }
208
204
 
209
205
  /**
@@ -253,7 +249,7 @@ async function normalizeAndSaveAttachment(outputPath, name, options = {}) {
253
249
  var _options$contentType;
254
250
  const hash = (0, _utils.calculateSha1)(options.path);
255
251
  if (!(0, _utils.isString)(name)) throw new Error('"name" should be string.');
256
- const sanitizedNamePrefix = sanitizeForFilePath(name) + '-';
252
+ const sanitizedNamePrefix = (0, _utils.sanitizeForFilePath)(name) + '-';
257
253
  const dest = _path.default.join(outputPath, 'attachments', sanitizedNamePrefix + hash + _path.default.extname(options.path));
258
254
  await _fs.default.promises.mkdir(_path.default.dirname(dest), {
259
255
  recursive: true
@@ -287,16 +283,12 @@ function folderIsModule(folder) {
287
283
  // Rely on `require` internal caching logic.
288
284
  return require(packageJsonPath).type === 'module';
289
285
  }
290
- function experimentalLoaderOption() {
291
- return ` --no-warnings --experimental-loader=${_url.default.pathToFileURL(require.resolve('@playwright/test/lib/transform/esmLoader')).toString()}`;
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];
292
289
  }
293
- function envWithoutExperimentalLoaderOptions() {
294
- const substring = experimentalLoaderOption();
295
- const result = {
296
- ...process.env
297
- };
298
- if (result.NODE_OPTIONS) result.NODE_OPTIONS = result.NODE_OPTIONS.replace(substring, '').trim() || undefined;
299
- return result;
290
+ function execArgvWithoutExperimentalLoaderOptions() {
291
+ return process.execArgv.filter(arg => !kExperimentalLoaderOptions.includes(arg));
300
292
  }
301
293
 
302
294
  // This follows the --moduleResolution=bundler strategy from tsc.
@@ -130,8 +130,8 @@ class TestInfoImpl {
130
130
  const relativeTestFilePath = _path.default.relative(this.project.testDir, test._requireFile.replace(/\.(spec|test)\.(js|ts|mjs)$/, ''));
131
131
  const sanitizedRelativePath = relativeTestFilePath.replace(process.platform === 'win32' ? new RegExp('\\\\', 'g') : new RegExp('/', 'g'), '-');
132
132
  const fullTitleWithoutSpec = test.titlePath().slice(1).join(' ');
133
- let testOutputDir = (0, _util.trimLongString)(sanitizedRelativePath + '-' + (0, _util.sanitizeForFilePath)(fullTitleWithoutSpec));
134
- if (projectInternal.id) testOutputDir += '-' + (0, _util.sanitizeForFilePath)(projectInternal.id);
133
+ let testOutputDir = (0, _util.trimLongString)(sanitizedRelativePath + '-' + (0, _utils.sanitizeForFilePath)(fullTitleWithoutSpec));
134
+ if (projectInternal.id) testOutputDir += '-' + (0, _utils.sanitizeForFilePath)(projectInternal.id);
135
135
  if (this.retry) testOutputDir += '-retry' + this.retry;
136
136
  if (this.repeatEachIndex) testOutputDir += '-repeat' + this.repeatEachIndex;
137
137
  return _path.default.join(this.project.outputDir, testOutputDir);
@@ -364,14 +364,14 @@ class TestInfoImpl {
364
364
  }
365
365
  _fsSanitizedTestName() {
366
366
  const fullTitleWithoutSpec = this.titlePath.slice(1).join(' ');
367
- return (0, _util.sanitizeForFilePath)((0, _util.trimLongString)(fullTitleWithoutSpec));
367
+ return (0, _utils.sanitizeForFilePath)((0, _util.trimLongString)(fullTitleWithoutSpec));
368
368
  }
369
369
  snapshotPath(...pathSegments) {
370
370
  const subPath = _path.default.join(...pathSegments);
371
371
  const parsedSubPath = _path.default.parse(subPath);
372
372
  const relativeTestFilePath = _path.default.relative(this.project.testDir, this._test._requireFile);
373
373
  const parsedRelativeTestFilePath = _path.default.parse(relativeTestFilePath);
374
- const projectNamePathSegment = (0, _util.sanitizeForFilePath)(this.project.name);
374
+ const projectNamePathSegment = (0, _utils.sanitizeForFilePath)(this.project.name);
375
375
  const snapshotPath = (this._projectInternal.snapshotPathTemplate || '').replace(/\{(.)?testDir\}/g, '$1' + this.project.testDir).replace(/\{(.)?snapshotDir\}/g, '$1' + this.project.snapshotDir).replace(/\{(.)?snapshotSuffix\}/g, this.snapshotSuffix ? '$1' + this.snapshotSuffix : '').replace(/\{(.)?testFileDir\}/g, '$1' + parsedRelativeTestFilePath.dir).replace(/\{(.)?platform\}/g, '$1' + process.platform).replace(/\{(.)?projectName\}/g, projectNamePathSegment ? '$1' + projectNamePathSegment : '').replace(/\{(.)?testName\}/g, '$1' + this._fsSanitizedTestName()).replace(/\{(.)?testFileName\}/g, '$1' + parsedRelativeTestFilePath.base).replace(/\{(.)?testFilePath\}/g, '$1' + relativeTestFilePath).replace(/\{(.)?arg\}/g, '$1' + _path.default.join(parsedSubPath.dir, parsedSubPath.name)).replace(/\{(.)?ext\}/g, parsedSubPath.ext ? '$1' + parsedSubPath.ext : '');
376
376
  return _path.default.normalize(_path.default.resolve(this._configInternal.configDir, snapshotPath));
377
377
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@playwright/test",
3
- "version": "1.37.0-alpha-aug-3-2023",
3
+ "version": "1.37.0-alpha-aug-4-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-3-2023"
44
+ "playwright-core": "1.37.0-alpha-aug-4-2023"
45
45
  },
46
46
  "optionalDependencies": {
47
47
  "fsevents": "2.3.2"