@playwright/test 1.35.0-alpha-jun-2-2023 → 1.35.0-alpha-jun-3-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.
@@ -10,6 +10,7 @@ var _fs = _interopRequireDefault(require("fs"));
10
10
  var _path = _interopRequireDefault(require("path"));
11
11
  var _os = _interopRequireDefault(require("os"));
12
12
  var _util = require("../util");
13
+ var _transform = require("../transform/transform");
13
14
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
14
15
  /**
15
16
  * Copyright Microsoft Corporation. All rights reserved.
@@ -34,6 +35,7 @@ class FullConfigInternal {
34
35
  return config[configInternalSymbol];
35
36
  }
36
37
  constructor(configDir, configFile, config, configCLIOverrides) {
38
+ var _build, _config$build;
37
39
  this.config = void 0;
38
40
  this.globalOutputDir = void 0;
39
41
  this.configDir = void 0;
@@ -118,6 +120,10 @@ class FullConfigInternal {
118
120
  this.projects = projectConfigs.map(p => new FullProjectInternal(configDir, config, this, p, this.configCLIOverrides, throwawayArtifactsPath));
119
121
  resolveProjectDependencies(this.projects);
120
122
  this._assignUniqueProjectIds(this.projects);
123
+ (0, _transform.setTransformConfig)({
124
+ babelPlugins: ((_build = config.build) === null || _build === void 0 ? void 0 : _build.babelPlugins) || [],
125
+ external: ((_config$build = config.build) === null || _config$build === void 0 ? void 0 : _config$build.external) || []
126
+ });
121
127
  this.config.projects = this.projects.map(p => p.project);
122
128
  }
123
129
  _assignUniqueProjectIds(projects) {
@@ -45,12 +45,11 @@ class ConfigLoader {
45
45
  this._configCLIOverrides = configCLIOverrides || {};
46
46
  }
47
47
  static async deserialize(data) {
48
- (0, _transform.setBabelPlugins)(data.babelTransformPlugins);
49
48
  (0, _compilationCache.addToCompilationCache)(data.compilationCache);
50
- await (0, _esmLoaderHost.initializeEsmLoader)();
51
49
  const loader = new ConfigLoader(data.configCLIOverrides);
52
- if (data.configFile) return await loader.loadConfigFile(data.configFile);
53
- return await loader.loadEmptyConfig(data.configDir);
50
+ const config = data.configFile ? await loader.loadConfigFile(data.configFile) : await loader.loadEmptyConfig(data.configDir);
51
+ await (0, _esmLoaderHost.initializeEsmLoader)();
52
+ return config;
54
53
  }
55
54
  async loadConfigFile(file, ignoreProjectDependencies = false) {
56
55
  if (this._fullConfig) throw new Error('Cannot load two config files');
@@ -47,8 +47,8 @@ async function incorporateCompilationCache() {
47
47
  }
48
48
  async function initializeEsmLoader() {
49
49
  if (!loaderChannel) return;
50
- await loaderChannel.send('setBabelPlugins', {
51
- plugins: (0, _transform.getBabelPlugins)()
50
+ await loaderChannel.send('setTransformConfig', {
51
+ config: (0, _transform.transformConfig)()
52
52
  });
53
53
  await loaderChannel.send('addToCompilationCache', {
54
54
  cache: (0, _compilationCache.serializeCompilationCache)()
package/lib/common/ipc.js CHANGED
@@ -22,14 +22,11 @@ var _compilationCache = require("../transform/compilationCache");
22
22
  */
23
23
 
24
24
  function serializeConfig(config) {
25
- const babelTransformPlugins = [];
26
- for (const plugin of config.plugins) babelTransformPlugins.push(...(plugin.babelPlugins || []));
27
25
  const result = {
28
26
  configFile: config.config.configFile,
29
27
  configDir: config.configDir,
30
28
  configCLIOverrides: config.configCLIOverrides,
31
- compilationCache: (0, _compilationCache.serializeCompilationCache)(),
32
- babelTransformPlugins
29
+ compilationCache: (0, _compilationCache.serializeCompilationCache)()
33
30
  };
34
31
  return result;
35
32
  }
package/lib/index.js CHANGED
@@ -417,6 +417,7 @@ const playwrightFixtures = {
417
417
  ..._combinedContextOptions
418
418
  };
419
419
  playwright.request._defaultContextOptions.tracesDir = path.join(_artifactsDir(), 'traces');
420
+ playwright.request._defaultContextOptions.timeout = actionTimeout || 0;
420
421
  await use();
421
422
  playwright.request._defaultContextOptions = undefined;
422
423
  for (const browserType of [playwright.chromium, playwright.firefox, playwright.webkit]) {
@@ -778,6 +779,12 @@ class ArtifactsRecorder {
778
779
  await this._stopTracing(tracing, true);
779
780
  })));
780
781
 
782
+ // Either remove or attach temporary screenshots for contexts closed before
783
+ // collecting the test trace.
784
+ await Promise.all(this._temporaryScreenshots.map(async file => {
785
+ if (captureScreenshots) await fs.promises.rename(file, this._addScreenshotAttachment()).catch(() => {});else await fs.promises.unlink(file).catch(() => {});
786
+ }));
787
+
781
788
  // Collect test trace.
782
789
  if (this._preserveTrace()) {
783
790
  const events = this._testInfo._traceEvents;
@@ -793,8 +800,8 @@ class ArtifactsRecorder {
793
800
  }
794
801
  }
795
802
 
796
- // Either remove or attach temporary traces and screenshots for contexts closed
797
- // before the test has finished.
803
+ // Either remove or attach temporary traces for contexts closed before the
804
+ // test has finished.
798
805
  if (this._preserveTrace() && this._temporaryTraceFiles.length) {
799
806
  const tracePath = this._testInfo.outputPath(`trace.zip`);
800
807
  // This could be: beforeHooks, or beforeHooks + test, etc.
@@ -811,9 +818,6 @@ class ArtifactsRecorder {
811
818
  contentType: 'application/zip'
812
819
  });
813
820
  }
814
- await Promise.all(this._temporaryScreenshots.map(async file => {
815
- if (captureScreenshots) await fs.promises.rename(file, this._addScreenshotAttachment()).catch(() => {});else await fs.promises.unlink(file).catch(() => {});
816
- }));
817
821
  }
818
822
  _addScreenshotAttachment() {
819
823
  const testFailed = this._testInfo.status !== this._testInfo.expectedStatus;
@@ -180,6 +180,7 @@ class Dispatcher {
180
180
  worker.removeListener('testEnd', onTestEnd);
181
181
  worker.removeListener('stepBegin', onStepBegin);
182
182
  worker.removeListener('stepEnd', onStepEnd);
183
+ worker.removeListener('attach', onAttach);
183
184
  worker.removeListener('done', onDone);
184
185
  worker.removeListener('exit', onExit);
185
186
  doneCallback();
@@ -220,12 +221,6 @@ class Dispatcher {
220
221
  result.duration = params.duration;
221
222
  result.errors = params.errors;
222
223
  result.error = result.errors[0];
223
- result.attachments = params.attachments.map(a => ({
224
- name: a.name,
225
- path: a.path,
226
- contentType: a.contentType,
227
- body: a.body !== undefined ? Buffer.from(a.body, 'base64') : undefined
228
- }));
229
224
  result.status = params.status;
230
225
  test.expectedStatus = params.expectedStatus;
231
226
  test.annotations = params.annotations;
@@ -288,6 +283,20 @@ class Dispatcher {
288
283
  this._reporter.onStepEnd(data.test, result, step);
289
284
  };
290
285
  worker.on('stepEnd', onStepEnd);
286
+ const onAttach = params => {
287
+ const data = this._testById.get(params.testId);
288
+ const {
289
+ result
290
+ } = data.resultByWorkerIndex.get(worker.workerIndex);
291
+ const attachment = {
292
+ name: params.name,
293
+ path: params.path,
294
+ contentType: params.contentType,
295
+ body: params.body !== undefined ? Buffer.from(params.body, 'base64') : undefined
296
+ };
297
+ result.attachments.push(attachment);
298
+ };
299
+ worker.on('attach', onAttach);
291
300
  const onDone = params => {
292
301
  this._queuedOrRunningHashCount.set(worker.hash(), this._queuedOrRunningHashCount.get(worker.hash()) - 1);
293
302
  let remaining = [...remainingByTestId.values()];
@@ -10,7 +10,6 @@ var _test = require("../common/test");
10
10
  var _testLoader = require("../common/testLoader");
11
11
  var _poolBuilder = require("../common/poolBuilder");
12
12
  var _compilationCache = require("../transform/compilationCache");
13
- var _transform = require("../transform/transform");
14
13
  var _esmLoaderHost = require("../common/esmLoaderHost");
15
14
  /**
16
15
  * Copyright Microsoft Corporation. All rights reserved.
@@ -36,9 +35,6 @@ class InProcessLoaderHost {
36
35
  this._poolBuilder = _poolBuilder.PoolBuilder.createForLoader();
37
36
  }
38
37
  async start() {
39
- const babelTransformPlugins = [];
40
- for (const plugin of this._config.plugins) babelTransformPlugins.push(...(plugin.babelPlugins || []));
41
- (0, _transform.setBabelPlugins)(babelTransformPlugins);
42
38
  await (0, _esmLoaderHost.initializeEsmLoader)();
43
39
  }
44
40
  async loadTestFile(file, testErrors) {
@@ -115,13 +115,12 @@ function createPluginSetupTask(plugin) {
115
115
  config,
116
116
  reporter
117
117
  }) => {
118
- var _plugin$instance, _plugin$instance$setu, _plugin$instance2, _plugin$instance2$bab;
118
+ var _plugin$instance, _plugin$instance$setu;
119
119
  if (typeof plugin.factory === 'function') plugin.instance = await plugin.factory();else plugin.instance = plugin.factory;
120
120
  await ((_plugin$instance = plugin.instance) === null || _plugin$instance === void 0 ? void 0 : (_plugin$instance$setu = _plugin$instance.setup) === null || _plugin$instance$setu === void 0 ? void 0 : _plugin$instance$setu.call(_plugin$instance, config.config, config.configDir, reporter));
121
- plugin.babelPlugins = (await ((_plugin$instance2 = plugin.instance) === null || _plugin$instance2 === void 0 ? void 0 : (_plugin$instance2$bab = _plugin$instance2.babelPlugins) === null || _plugin$instance2$bab === void 0 ? void 0 : _plugin$instance2$bab.call(_plugin$instance2))) || [];
122
121
  return () => {
123
- var _plugin$instance3, _plugin$instance3$tea;
124
- return (_plugin$instance3 = plugin.instance) === null || _plugin$instance3 === void 0 ? void 0 : (_plugin$instance3$tea = _plugin$instance3.teardown) === null || _plugin$instance3$tea === void 0 ? void 0 : _plugin$instance3$tea.call(_plugin$instance3);
122
+ var _plugin$instance2, _plugin$instance2$tea;
123
+ return (_plugin$instance2 = plugin.instance) === null || _plugin$instance2 === void 0 ? void 0 : (_plugin$instance2$tea = _plugin$instance2.teardown) === null || _plugin$instance2$tea === void 0 ? void 0 : _plugin$instance2$tea.call(_plugin$instance2);
125
124
  };
126
125
  };
127
126
  }
@@ -129,11 +128,11 @@ function createPluginBeginTask(plugin) {
129
128
  return async ({
130
129
  rootSuite
131
130
  }) => {
132
- var _plugin$instance4, _plugin$instance4$beg;
133
- await ((_plugin$instance4 = plugin.instance) === null || _plugin$instance4 === void 0 ? void 0 : (_plugin$instance4$beg = _plugin$instance4.begin) === null || _plugin$instance4$beg === void 0 ? void 0 : _plugin$instance4$beg.call(_plugin$instance4, rootSuite));
131
+ var _plugin$instance3, _plugin$instance3$beg;
132
+ await ((_plugin$instance3 = plugin.instance) === null || _plugin$instance3 === void 0 ? void 0 : (_plugin$instance3$beg = _plugin$instance3.begin) === null || _plugin$instance3$beg === void 0 ? void 0 : _plugin$instance3$beg.call(_plugin$instance3, rootSuite));
134
133
  return () => {
135
- var _plugin$instance5, _plugin$instance5$end;
136
- return (_plugin$instance5 = plugin.instance) === null || _plugin$instance5 === void 0 ? void 0 : (_plugin$instance5$end = _plugin$instance5.end) === null || _plugin$instance5$end === void 0 ? void 0 : _plugin$instance5$end.call(_plugin$instance5);
134
+ var _plugin$instance4, _plugin$instance4$end;
135
+ return (_plugin$instance4 = plugin.instance) === null || _plugin$instance4 === void 0 ? void 0 : (_plugin$instance4$end = _plugin$instance4.end) === null || _plugin$instance4$end === void 0 ? void 0 : _plugin$instance4$end.call(_plugin$instance4);
137
136
  };
138
137
  };
139
138
  }
@@ -48,7 +48,7 @@ async function load(moduleUrl, context, defaultLoad) {
48
48
  if (!moduleUrl.startsWith('file://')) return defaultLoad(moduleUrl, context, defaultLoad);
49
49
  const filename = _url.default.fileURLToPath(moduleUrl);
50
50
  // Bail for node_modules.
51
- if ((0, _compilationCache.belongsToNodeModules)(filename)) return defaultLoad(moduleUrl, context, defaultLoad);
51
+ if (!(0, _transform.shouldTransform)(filename)) return defaultLoad(moduleUrl, context, defaultLoad);
52
52
  const code = _fs.default.readFileSync(filename, 'utf-8');
53
53
  const source = (0, _transform.transformHook)(code, filename, moduleUrl);
54
54
 
@@ -68,8 +68,8 @@ async function load(moduleUrl, context, defaultLoad) {
68
68
  let transport;
69
69
  function globalPreload(context) {
70
70
  transport = new _portTransport.PortTransport(context.port, async (method, params) => {
71
- if (method === 'setBabelPlugins') {
72
- (0, _transform.setBabelPlugins)(params.plugins);
71
+ if (method === 'setTransformConfig') {
72
+ (0, _transform.setTransformConfig)(params.config);
73
73
  return;
74
74
  }
75
75
  if (method === 'addToCompilationCache') {
@@ -3,10 +3,11 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- exports.getBabelPlugins = getBabelPlugins;
7
6
  exports.requireOrImport = requireOrImport;
8
7
  exports.resolveHook = resolveHook;
9
- exports.setBabelPlugins = setBabelPlugins;
8
+ exports.setTransformConfig = setTransformConfig;
9
+ exports.shouldTransform = shouldTransform;
10
+ exports.transformConfig = transformConfig;
10
11
  exports.transformHook = transformHook;
11
12
  exports.wrapFunctionWithLocation = wrapFunctionWithLocation;
12
13
  var _crypto = _interopRequireDefault(require("crypto"));
@@ -36,12 +37,17 @@ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { de
36
37
 
37
38
  const version = require('../../package.json').version;
38
39
  const cachedTSConfigs = new Map();
39
- let babelPlugins = [];
40
- function setBabelPlugins(plugins) {
41
- babelPlugins = plugins;
40
+ let _transformConfig = {
41
+ babelPlugins: [],
42
+ external: []
43
+ };
44
+ let _externalMatcher = () => false;
45
+ function setTransformConfig(config) {
46
+ _transformConfig = config;
47
+ _externalMatcher = (0, _util.createFileMatcher)(_transformConfig.external);
42
48
  }
43
- function getBabelPlugins() {
44
- return babelPlugins;
49
+ function transformConfig() {
50
+ return _transformConfig;
45
51
  }
46
52
  function validateTsConfig(tsconfig) {
47
53
  if (!tsconfig.tsConfigPath || !tsconfig.baseUrl) return;
@@ -74,7 +80,7 @@ const pathSeparator = process.platform === 'win32' ? ';' : ':';
74
80
  const builtins = new Set(_module.default.builtinModules);
75
81
  function resolveHook(filename, specifier) {
76
82
  if (specifier.startsWith('node:') || builtins.has(specifier)) return;
77
- if ((0, _compilationCache.belongsToNodeModules)(filename)) return;
83
+ if (!shouldTransform(filename)) return;
78
84
  if (isRelativeSpecifier(specifier)) return (0, _util.resolveImportSpecifierExtension)(_path.default.resolve(_path.default.dirname(filename), specifier));
79
85
  const isTypeScript = filename.endsWith('.ts') || filename.endsWith('.tsx');
80
86
  const tsconfig = loadAndValidateTsconfigForFile(filename);
@@ -124,10 +130,14 @@ function resolveHook(filename, specifier) {
124
130
  return (0, _util.resolveImportSpecifierExtension)(specifier);
125
131
  }
126
132
  }
133
+ function shouldTransform(filename) {
134
+ if (_externalMatcher(filename)) return false;
135
+ return !(0, _compilationCache.belongsToNodeModules)(filename);
136
+ }
127
137
  function transformHook(originalCode, filename, moduleUrl) {
128
138
  const isTypeScript = filename.endsWith('.ts') || filename.endsWith('.tsx') || filename.endsWith('.mts') || filename.endsWith('.cts');
129
139
  const hasPreprocessor = process.env.PW_TEST_SOURCE_TRANSFORM && process.env.PW_TEST_SOURCE_TRANSFORM_SCOPE && process.env.PW_TEST_SOURCE_TRANSFORM_SCOPE.split(pathSeparator).some(f => filename.startsWith(f));
130
- const pluginsPrologue = babelPlugins;
140
+ const pluginsPrologue = _transformConfig.babelPlugins;
131
141
  const pluginsEpilogue = hasPreprocessor ? [[process.env.PW_TEST_SOURCE_TRANSFORM]] : [];
132
142
  const hash = calculateHash(originalCode, filename, !!moduleUrl, pluginsPrologue, pluginsEpilogue);
133
143
  const {
@@ -182,7 +192,7 @@ function installTransform() {
182
192
  }
183
193
  _module.default._resolveFilename = resolveFilename;
184
194
  const revertPirates = _utilsBundle.pirates.addHook((code, filename) => {
185
- if ((0, _compilationCache.belongsToNodeModules)(filename)) return code;
195
+ if (!shouldTransform(filename)) return code;
186
196
  return transformHook(code, filename);
187
197
  }, {
188
198
  exts: ['.ts', '.tsx', '.js', '.jsx', '.mjs']
@@ -42,9 +42,10 @@ class TestInfoImpl {
42
42
  set timeout(timeout) {
43
43
  // Ignored.
44
44
  }
45
- constructor(configInternal, projectInternal, workerParams, test, retry, onStepBegin, onStepEnd) {
45
+ constructor(configInternal, projectInternal, workerParams, test, retry, onStepBegin, onStepEnd, onAttach) {
46
46
  this._onStepBegin = void 0;
47
47
  this._onStepEnd = void 0;
48
+ this._onAttach = void 0;
48
49
  this._test = void 0;
49
50
  this._timeoutManager = void 0;
50
51
  this._startTime = void 0;
@@ -84,10 +85,12 @@ class TestInfoImpl {
84
85
  this.outputDir = void 0;
85
86
  this.snapshotDir = void 0;
86
87
  this.errors = [];
88
+ this._attachmentsPush = void 0;
87
89
  this._test = test;
88
90
  this.testId = test.id;
89
91
  this._onStepBegin = onStepBegin;
90
92
  this._onStepEnd = onStepEnd;
93
+ this._onAttach = onAttach;
91
94
  this._startTime = (0, _utils.monotonicTime)();
92
95
  this._startWallTime = Date.now();
93
96
  this.repeatEachIndex = workerParams.repeatEachIndex;
@@ -120,6 +123,11 @@ class TestInfoImpl {
120
123
  const relativeTestFilePath = _path.default.relative(this.project.testDir, test._requireFile);
121
124
  return _path.default.join(this.project.snapshotDir, relativeTestFilePath + '-snapshots');
122
125
  })();
126
+ this._attachmentsPush = this.attachments.push.bind(this.attachments);
127
+ this.attachments.push = (...attachments) => {
128
+ for (const a of attachments) this._attach(a.name, a);
129
+ return this.attachments.length;
130
+ };
123
131
  }
124
132
  _modifier(type, modifierArgs) {
125
133
  if (typeof modifierArgs[1] === 'function') {
@@ -283,14 +291,28 @@ class TestInfoImpl {
283
291
  // ------------ TestInfo methods ------------
284
292
 
285
293
  async attach(name, options = {}) {
294
+ this._attach(name, await (0, _util.normalizeAndSaveAttachment)(this.outputPath(), name, options));
295
+ }
296
+ _attach(name, attachment) {
286
297
  const step = this._addStep({
287
298
  title: `attach "${name}"`,
288
299
  category: 'attach',
289
300
  wallTime: Date.now()
290
301
  });
291
- this.attachments.push(await (0, _util.normalizeAndSaveAttachment)(this.outputPath(), name, options));
302
+ this._attachWithoutStep(attachment);
292
303
  step.complete({});
293
304
  }
305
+ _attachWithoutStep(attachment) {
306
+ var _attachment$body;
307
+ this._attachmentsPush(attachment);
308
+ this._onAttach({
309
+ testId: this._test.id,
310
+ name: attachment.name,
311
+ contentType: attachment.contentType,
312
+ path: attachment.path,
313
+ body: (_attachment$body = attachment.body) === null || _attachment$body === void 0 ? void 0 : _attachment$body.toString('base64')
314
+ });
315
+ }
294
316
  outputPath(...pathSegments) {
295
317
  _fs.default.mkdirSync(this.outputDir, {
296
318
  recursive: true
@@ -331,7 +353,7 @@ class TestInfoImpl {
331
353
  }
332
354
  exports.TestInfoImpl = TestInfoImpl;
333
355
  function serializeAttachments(attachments, initialAttachments) {
334
- return attachments.filter(a => !initialAttachments.has(a)).map(a => {
356
+ return attachments.filter(a => a.name !== 'trace' && !initialAttachments.has(a)).map(a => {
335
357
  var _a$body;
336
358
  return {
337
359
  name: a.name,
@@ -228,7 +228,7 @@ class WorkerMain extends _process.ProcessRunner {
228
228
  }
229
229
  }
230
230
  async _runTest(test, retry, nextTest) {
231
- const testInfo = new _testInfo.TestInfoImpl(this._config, this._project, this._params, test, retry, stepBeginPayload => this.dispatchEvent('stepBegin', stepBeginPayload), stepEndPayload => this.dispatchEvent('stepEnd', stepEndPayload));
231
+ const testInfo = new _testInfo.TestInfoImpl(this._config, this._project, this._params, test, retry, stepBeginPayload => this.dispatchEvent('stepBegin', stepBeginPayload), stepEndPayload => this.dispatchEvent('stepEnd', stepEndPayload), attachment => this.dispatchEvent('attach', attachment));
232
232
  const processAnnotation = annotation => {
233
233
  testInfo.annotations.push(annotation);
234
234
  switch (annotation.type) {
@@ -595,16 +595,7 @@ function buildTestEndPayload(testInfo) {
595
595
  errors: testInfo.errors,
596
596
  expectedStatus: testInfo.expectedStatus,
597
597
  annotations: testInfo.annotations,
598
- timeout: testInfo.timeout,
599
- attachments: testInfo.attachments.map(a => {
600
- var _a$body;
601
- return {
602
- name: a.name,
603
- contentType: a.contentType,
604
- path: a.path,
605
- body: (_a$body = a.body) === null || _a$body === void 0 ? void 0 : _a$body.toString('base64')
606
- };
607
- })
598
+ timeout: testInfo.timeout
608
599
  };
609
600
  }
610
601
  function getSuites(test) {
package/package.json CHANGED
@@ -1,11 +1,11 @@
1
1
  {
2
2
  "name": "@playwright/test",
3
- "version": "1.35.0-alpha-jun-2-2023",
3
+ "version": "1.35.0-alpha-jun-3-2023",
4
4
  "description": "A high-level API to automate web browsers",
5
5
  "repository": "github:Microsoft/playwright",
6
6
  "homepage": "https://playwright.dev",
7
7
  "engines": {
8
- "node": ">=14"
8
+ "node": ">=16"
9
9
  },
10
10
  "main": "index.js",
11
11
  "exports": {
@@ -41,7 +41,7 @@
41
41
  "license": "Apache-2.0",
42
42
  "dependencies": {
43
43
  "@types/node": "*",
44
- "playwright-core": "1.35.0-alpha-jun-2-2023"
44
+ "playwright-core": "1.35.0-alpha-jun-3-2023"
45
45
  },
46
46
  "optionalDependencies": {
47
47
  "fsevents": "2.3.2"
package/types/test.d.ts CHANGED
@@ -569,6 +569,31 @@ interface TestConfig {
569
569
  *
570
570
  */
571
571
  webServer?: TestConfigWebServer | TestConfigWebServer[];
572
+ /**
573
+ * Transpiler configuration.
574
+ *
575
+ * **Usage**
576
+ *
577
+ * ```js
578
+ * // playwright.config.ts
579
+ * import { defineConfig } from '@playwright/test';
580
+ *
581
+ * export default defineConfig({
582
+ * build: {
583
+ * external: '**\/*bundle.js',
584
+ * },
585
+ * });
586
+ * ```
587
+ *
588
+ */
589
+ build?: {
590
+ /**
591
+ * Paths to exclude from the transpilation expressed as glob patterns. Typically heavy JS bundles your tests
592
+ * reference.
593
+ */
594
+ external?: Array<string>;
595
+ };
596
+
572
597
  /**
573
598
  * Configuration for the `expect` assertion library. Learn more about [various timeouts](https://playwright.dev/docs/test-timeouts).
574
599
  *