@playwright/test 1.35.0-alpha-jun-5-2023 → 1.35.0-alpha-jun-7-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/.eslintrc.js +13 -1
- package/ThirdPartyNotices.txt +1 -61
- package/lib/cli.js +5 -2
- package/lib/common/process.js +1 -1
- package/lib/index.js +2 -2
- package/lib/matchers/toMatchSnapshot.js +6 -0
- package/lib/reporters/github.js +1 -1
- package/lib/reporters/html.js +4 -11
- package/lib/reporters/internalReporter.js +6 -1
- package/lib/reporters/merge.js +6 -2
- package/lib/runner/dispatcher.js +5 -5
- package/lib/runner/runner.js +2 -2
- package/lib/runner/uiMode.js +55 -68
- package/lib/util.js +19 -2
- package/lib/utilsBundle.js +1 -3
- package/lib/utilsBundleImpl.js +36 -36
- package/lib/worker/testInfo.js +1 -1
- package/lib/worker/workerMain.js +3 -3
- package/package.json +2 -2
- package/types/test.d.ts +119 -89
- package/types/testReporter.d.ts +16 -14
package/.eslintrc.js
CHANGED
|
@@ -1,3 +1,15 @@
|
|
|
1
|
+
const path = require('path');
|
|
2
|
+
|
|
1
3
|
module.exports = {
|
|
2
|
-
extends:
|
|
4
|
+
extends: '../.eslintrc.js',
|
|
5
|
+
parser: "@typescript-eslint/parser",
|
|
6
|
+
plugins: ["@typescript-eslint", "notice"],
|
|
7
|
+
parserOptions: {
|
|
8
|
+
ecmaVersion: 9,
|
|
9
|
+
sourceType: "module",
|
|
10
|
+
project: path.join(__dirname, '..', '..', 'tsconfig.json'),
|
|
11
|
+
},
|
|
12
|
+
rules: {
|
|
13
|
+
'@typescript-eslint/no-floating-promises': 'error',
|
|
14
|
+
},
|
|
3
15
|
};
|
package/ThirdPartyNotices.txt
CHANGED
|
@@ -99,7 +99,6 @@ This project incorporates components from the projects listed below. The origina
|
|
|
99
99
|
- color-name@1.1.4 (https://github.com/colorjs/color-name)
|
|
100
100
|
- convert-source-map@1.8.0 (https://github.com/thlorenz/convert-source-map)
|
|
101
101
|
- debug@4.3.4 (https://github.com/debug-js/debug)
|
|
102
|
-
- define-lazy-prop@2.0.0 (https://github.com/sindresorhus/define-lazy-prop)
|
|
103
102
|
- diff-sequences@27.5.1 (https://github.com/facebook/jest)
|
|
104
103
|
- electron-to-chromium@1.4.337 (https://github.com/kilian/electron-to-chromium)
|
|
105
104
|
- enquirer@2.3.6 (https://github.com/enquirer/enquirer)
|
|
@@ -115,11 +114,9 @@ This project incorporates components from the projects listed below. The origina
|
|
|
115
114
|
- has-flag@3.0.0 (https://github.com/sindresorhus/has-flag)
|
|
116
115
|
- has-flag@4.0.0 (https://github.com/sindresorhus/has-flag)
|
|
117
116
|
- is-binary-path@2.1.0 (https://github.com/sindresorhus/is-binary-path)
|
|
118
|
-
- is-docker@2.2.1 (https://github.com/sindresorhus/is-docker)
|
|
119
117
|
- is-extglob@2.1.1 (https://github.com/jonschlinkert/is-extglob)
|
|
120
118
|
- is-glob@4.0.3 (https://github.com/micromatch/is-glob)
|
|
121
119
|
- is-number@7.0.0 (https://github.com/jonschlinkert/is-number)
|
|
122
|
-
- is-wsl@2.2.0 (https://github.com/sindresorhus/is-wsl)
|
|
123
120
|
- jest-diff@27.5.1 (https://github.com/facebook/jest)
|
|
124
121
|
- jest-get-type@27.5.1 (https://github.com/facebook/jest)
|
|
125
122
|
- jest-matcher-utils@27.2.5 (https://github.com/facebook/jest)
|
|
@@ -133,7 +130,6 @@ This project incorporates components from the projects listed below. The origina
|
|
|
133
130
|
- ms@2.1.2 (https://github.com/zeit/ms)
|
|
134
131
|
- node-releases@2.0.10 (https://github.com/chicoxyzzy/node-releases)
|
|
135
132
|
- normalize-path@3.0.0 (https://github.com/jonschlinkert/normalize-path)
|
|
136
|
-
- open@8.4.0 (https://github.com/sindresorhus/open)
|
|
137
133
|
- picocolors@1.0.0 (https://github.com/alexeyraspopov/picocolors)
|
|
138
134
|
- picomatch@2.3.1 (https://github.com/micromatch/picomatch)
|
|
139
135
|
- pirates@4.0.4 (https://github.com/danez/pirates)
|
|
@@ -3105,20 +3101,6 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
|
3105
3101
|
=========================================
|
|
3106
3102
|
END OF debug@4.3.4 AND INFORMATION
|
|
3107
3103
|
|
|
3108
|
-
%% define-lazy-prop@2.0.0 NOTICES AND INFORMATION BEGIN HERE
|
|
3109
|
-
=========================================
|
|
3110
|
-
MIT License
|
|
3111
|
-
|
|
3112
|
-
Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)
|
|
3113
|
-
|
|
3114
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
|
3115
|
-
|
|
3116
|
-
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
|
3117
|
-
|
|
3118
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
3119
|
-
=========================================
|
|
3120
|
-
END OF define-lazy-prop@2.0.0 AND INFORMATION
|
|
3121
|
-
|
|
3122
3104
|
%% diff-sequences@27.5.1 NOTICES AND INFORMATION BEGIN HERE
|
|
3123
3105
|
=========================================
|
|
3124
3106
|
MIT License
|
|
@@ -3395,20 +3377,6 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
|
|
|
3395
3377
|
=========================================
|
|
3396
3378
|
END OF is-binary-path@2.1.0 AND INFORMATION
|
|
3397
3379
|
|
|
3398
|
-
%% is-docker@2.2.1 NOTICES AND INFORMATION BEGIN HERE
|
|
3399
|
-
=========================================
|
|
3400
|
-
MIT License
|
|
3401
|
-
|
|
3402
|
-
Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (https://sindresorhus.com)
|
|
3403
|
-
|
|
3404
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
|
3405
|
-
|
|
3406
|
-
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
|
3407
|
-
|
|
3408
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
3409
|
-
=========================================
|
|
3410
|
-
END OF is-docker@2.2.1 AND INFORMATION
|
|
3411
|
-
|
|
3412
3380
|
%% is-extglob@2.1.1 NOTICES AND INFORMATION BEGIN HERE
|
|
3413
3381
|
=========================================
|
|
3414
3382
|
The MIT License (MIT)
|
|
@@ -3487,20 +3455,6 @@ THE SOFTWARE.
|
|
|
3487
3455
|
=========================================
|
|
3488
3456
|
END OF is-number@7.0.0 AND INFORMATION
|
|
3489
3457
|
|
|
3490
|
-
%% is-wsl@2.2.0 NOTICES AND INFORMATION BEGIN HERE
|
|
3491
|
-
=========================================
|
|
3492
|
-
MIT License
|
|
3493
|
-
|
|
3494
|
-
Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)
|
|
3495
|
-
|
|
3496
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
|
3497
|
-
|
|
3498
|
-
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
|
3499
|
-
|
|
3500
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
3501
|
-
=========================================
|
|
3502
|
-
END OF is-wsl@2.2.0 AND INFORMATION
|
|
3503
|
-
|
|
3504
3458
|
%% jest-diff@27.5.1 NOTICES AND INFORMATION BEGIN HERE
|
|
3505
3459
|
=========================================
|
|
3506
3460
|
MIT License
|
|
@@ -3834,20 +3788,6 @@ THE SOFTWARE.
|
|
|
3834
3788
|
=========================================
|
|
3835
3789
|
END OF normalize-path@3.0.0 AND INFORMATION
|
|
3836
3790
|
|
|
3837
|
-
%% open@8.4.0 NOTICES AND INFORMATION BEGIN HERE
|
|
3838
|
-
=========================================
|
|
3839
|
-
MIT License
|
|
3840
|
-
|
|
3841
|
-
Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (https://sindresorhus.com)
|
|
3842
|
-
|
|
3843
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
|
3844
|
-
|
|
3845
|
-
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
|
3846
|
-
|
|
3847
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
3848
|
-
=========================================
|
|
3849
|
-
END OF open@8.4.0 AND INFORMATION
|
|
3850
|
-
|
|
3851
3791
|
%% picocolors@1.0.0 NOTICES AND INFORMATION BEGIN HERE
|
|
3852
3792
|
=========================================
|
|
3853
3793
|
ISC License
|
|
@@ -4284,6 +4224,6 @@ END OF yallist@3.1.1 AND INFORMATION
|
|
|
4284
4224
|
|
|
4285
4225
|
SUMMARY BEGIN HERE
|
|
4286
4226
|
=========================================
|
|
4287
|
-
Total Packages:
|
|
4227
|
+
Total Packages: 145
|
|
4288
4228
|
=========================================
|
|
4289
4229
|
END OF SUMMARY
|
package/lib/cli.js
CHANGED
|
@@ -126,7 +126,10 @@ async function runTests(args, opts) {
|
|
|
126
126
|
config.cliPassWithNoTests = !!opts.passWithNoTests;
|
|
127
127
|
const runner = new _runner.Runner(config);
|
|
128
128
|
let status;
|
|
129
|
-
if (opts.ui
|
|
129
|
+
if (opts.ui || opts.uiHost || opts.uiPort) status = await runner.uiAllTests({
|
|
130
|
+
host: opts.uiHost,
|
|
131
|
+
port: opts.uiPort ? +opts.uiPort : undefined
|
|
132
|
+
});else if (process.env.PWTEST_WATCH) status = await runner.watchAllTests();else status = await runner.runAllTests();
|
|
130
133
|
await (0, _utils.stopProfiling)('runner');
|
|
131
134
|
if (status === 'interrupted') process.exit(130);
|
|
132
135
|
process.exit(status === 'passed' ? 0 : 1);
|
|
@@ -262,7 +265,7 @@ function restartWithExperimentalTsEsm(configFile) {
|
|
|
262
265
|
return true;
|
|
263
266
|
}
|
|
264
267
|
const kTraceModes = ['on', 'off', 'on-first-retry', 'on-all-retries', 'retain-on-failure'];
|
|
265
|
-
const testOptions = [['--browser <browser>', `Browser to use for tests, one of "all", "chromium", "firefox" or "webkit" (default: "chromium")`], ['-c, --config <file>', `Configuration file, or a test directory with optional "playwright.config.{m,c}?{js,ts}"`], ['--debug', `Run tests with Playwright Inspector. Shortcut for "PWDEBUG=1" environment variable and "--timeout=0 --max-failures=1 --headed --workers=1" options`], ['--forbid-only', `Fail if test.only is called (default: false)`], ['--fully-parallel', `Run all tests in parallel (default: false)`], ['--global-timeout <timeout>', `Maximum time this test suite can run in milliseconds (default: unlimited)`], ['-g, --grep <grep>', `Only run tests matching this regular expression (default: ".*")`], ['-gv, --grep-invert <grep>', `Only run tests that do not match this regular expression`], ['--headed', `Run tests in headed browsers (default: headless)`], ['--ignore-snapshots', `Ignore screenshot and snapshot expectations`], ['--list', `Collect all the tests and report them, but do not run`], ['--max-failures <N>', `Stop after the first N failures`], ['--no-deps', 'Do not run project dependencies'], ['--output <dir>', `Folder for output artifacts (default: "test-results")`], ['--pass-with-no-tests', `Makes test run succeed even if no tests were found`], ['--project <project-name...>', `Only run tests from the specified list of projects (default: run all projects)`], ['--quiet', `Suppress stdio`], ['--repeat-each <N>', `Run each test N times (default: 1)`], ['--reporter <reporter>', `Reporter to use, comma-separated, can be ${_config.builtInReporters.map(name => `"${name}"`).join(', ')} (default: "${_config.defaultReporter}")`], ['--retries <retries>', `Maximum retry count for flaky tests, zero for no retries (default: no retries)`], ['--shard <shard>', `Shard tests and execute only the selected shard, specify in the form "current/all", 1-based, for example "3/5"`], ['--timeout <timeout>', `Specify test timeout threshold in milliseconds, zero for unlimited (default: ${_config.defaultTimeout})`], ['--trace <mode>', `Force tracing mode, can be ${kTraceModes.map(mode => `"${mode}"`).join(', ')}`], ['--ui', `Run tests in interactive UI mode`], ['-u, --update-snapshots', `Update snapshots with actual results (default: only create missing snapshots)`], ['-j, --workers <workers>', `Number of concurrent workers or percentage of logical CPU cores, use 1 to run in a single worker (default: 50%)`], ['-x', `Stop after the first failure`]];
|
|
268
|
+
const testOptions = [['--browser <browser>', `Browser to use for tests, one of "all", "chromium", "firefox" or "webkit" (default: "chromium")`], ['-c, --config <file>', `Configuration file, or a test directory with optional "playwright.config.{m,c}?{js,ts}"`], ['--debug', `Run tests with Playwright Inspector. Shortcut for "PWDEBUG=1" environment variable and "--timeout=0 --max-failures=1 --headed --workers=1" options`], ['--forbid-only', `Fail if test.only is called (default: false)`], ['--fully-parallel', `Run all tests in parallel (default: false)`], ['--global-timeout <timeout>', `Maximum time this test suite can run in milliseconds (default: unlimited)`], ['-g, --grep <grep>', `Only run tests matching this regular expression (default: ".*")`], ['-gv, --grep-invert <grep>', `Only run tests that do not match this regular expression`], ['--headed', `Run tests in headed browsers (default: headless)`], ['--ignore-snapshots', `Ignore screenshot and snapshot expectations`], ['--list', `Collect all the tests and report them, but do not run`], ['--max-failures <N>', `Stop after the first N failures`], ['--no-deps', 'Do not run project dependencies'], ['--output <dir>', `Folder for output artifacts (default: "test-results")`], ['--pass-with-no-tests', `Makes test run succeed even if no tests were found`], ['--project <project-name...>', `Only run tests from the specified list of projects (default: run all projects)`], ['--quiet', `Suppress stdio`], ['--repeat-each <N>', `Run each test N times (default: 1)`], ['--reporter <reporter>', `Reporter to use, comma-separated, can be ${_config.builtInReporters.map(name => `"${name}"`).join(', ')} (default: "${_config.defaultReporter}")`], ['--retries <retries>', `Maximum retry count for flaky tests, zero for no retries (default: no retries)`], ['--shard <shard>', `Shard tests and execute only the selected shard, specify in the form "current/all", 1-based, for example "3/5"`], ['--timeout <timeout>', `Specify test timeout threshold in milliseconds, zero for unlimited (default: ${_config.defaultTimeout})`], ['--trace <mode>', `Force tracing mode, can be ${kTraceModes.map(mode => `"${mode}"`).join(', ')}`], ['--ui', `Run tests in interactive UI mode`], ['--ui-host <host>', 'Host to serve UI on; specifying this option opens UI in a browser tab'], ['--ui-port <port>', 'Port to serve UI on, 0 for any free port; specifying this option opens UI in a browser tab'], ['-u, --update-snapshots', `Update snapshots with actual results (default: only create missing snapshots)`], ['-j, --workers <workers>', `Number of concurrent workers or percentage of logical CPU cores, use 1 to run in a single worker (default: 50%)`], ['-x', `Stop after the first failure`]];
|
|
266
269
|
addTestCommand(_program.default);
|
|
267
270
|
addShowReportCommand(_program.default);
|
|
268
271
|
addListFilesCommand(_program.default);
|
package/lib/common/process.js
CHANGED
|
@@ -57,7 +57,7 @@ process.on('message', async message => {
|
|
|
57
57
|
} = message.params;
|
|
58
58
|
setTtyParams(process.stdout, processParams.stdoutParams);
|
|
59
59
|
setTtyParams(process.stderr, processParams.stderrParams);
|
|
60
|
-
(0, _utils.startProfiling)();
|
|
60
|
+
void (0, _utils.startProfiling)();
|
|
61
61
|
const {
|
|
62
62
|
create
|
|
63
63
|
} = require(runnerScript);
|
package/lib/index.js
CHANGED
|
@@ -95,12 +95,12 @@ const playwrightFixtures = {
|
|
|
95
95
|
scope: 'worker',
|
|
96
96
|
option: true
|
|
97
97
|
}],
|
|
98
|
-
connectOptions: [({}, use) => {
|
|
98
|
+
connectOptions: [async ({}, use) => {
|
|
99
99
|
// Usually, when connect options are specified (e.g, in the config or in the environment),
|
|
100
100
|
// all launch() calls are turned into connect() calls.
|
|
101
101
|
// However, when running in "reuse browser" mode and connecting to the reusable server,
|
|
102
102
|
// only the default "browser" fixture should turn into reused browser.
|
|
103
|
-
use(process.env.PW_TEST_REUSE_CONTEXT ? undefined : connectOptionsFromEnv());
|
|
103
|
+
await use(process.env.PW_TEST_REUSE_CONTEXT ? undefined : connectOptionsFromEnv());
|
|
104
104
|
}, {
|
|
105
105
|
scope: 'worker',
|
|
106
106
|
option: true
|
|
@@ -149,6 +149,11 @@ class SnapshotHelper {
|
|
|
149
149
|
if (isWriteMissingMode) {
|
|
150
150
|
writeFileSync(this.snapshotPath, actual);
|
|
151
151
|
writeFileSync(this.actualPath, actual);
|
|
152
|
+
this.testInfo.attachments.push({
|
|
153
|
+
name: (0, _util.addSuffixToFilePath)(this.snapshotName, '-actual'),
|
|
154
|
+
contentType: this.mimeType,
|
|
155
|
+
path: this.actualPath
|
|
156
|
+
});
|
|
152
157
|
}
|
|
153
158
|
const message = `A snapshot doesn't exist at ${this.snapshotPath}${isWriteMissingMode ? ', writing actual.' : '.'}`;
|
|
154
159
|
if (this.updateSnapshots === 'all') {
|
|
@@ -283,6 +288,7 @@ async function toHaveScreenshot(pageOrLocator, nameOrOptions = {}, optOptions =
|
|
|
283
288
|
caret: (_config$caret = config === null || config === void 0 ? void 0 : config.caret) !== null && _config$caret !== void 0 ? _config$caret : 'hide',
|
|
284
289
|
...helper.allOptions,
|
|
285
290
|
mask: helper.allOptions.mask || [],
|
|
291
|
+
maskColor: helper.allOptions.maskColor,
|
|
286
292
|
name: undefined,
|
|
287
293
|
threshold: undefined,
|
|
288
294
|
maxDiffPixels: undefined,
|
package/lib/reporters/github.js
CHANGED
package/lib/reporters/html.js
CHANGED
|
@@ -8,7 +8,6 @@ exports.showHTMLReport = showHTMLReport;
|
|
|
8
8
|
exports.startHtmlReportServer = startHtmlReportServer;
|
|
9
9
|
var _utilsBundle = require("playwright-core/lib/utilsBundle");
|
|
10
10
|
var _fs = _interopRequireDefault(require("fs"));
|
|
11
|
-
var _utilsBundle2 = require("../utilsBundle");
|
|
12
11
|
var _path = _interopRequireDefault(require("path"));
|
|
13
12
|
var _stream = require("stream");
|
|
14
13
|
var _utils = require("playwright-core/lib/utils");
|
|
@@ -37,7 +36,6 @@ class HtmlReporter {
|
|
|
37
36
|
constructor(options) {
|
|
38
37
|
this.config = void 0;
|
|
39
38
|
this.suite = void 0;
|
|
40
|
-
this._montonicStartTime = 0;
|
|
41
39
|
this._options = void 0;
|
|
42
40
|
this._outputFolder = void 0;
|
|
43
41
|
this._attachmentsBaseURL = void 0;
|
|
@@ -49,7 +47,6 @@ class HtmlReporter {
|
|
|
49
47
|
return false;
|
|
50
48
|
}
|
|
51
49
|
onBegin(config, suite) {
|
|
52
|
-
this._montonicStartTime = (0, _utils.monotonicTime)();
|
|
53
50
|
this.config = config;
|
|
54
51
|
const {
|
|
55
52
|
outputFolder,
|
|
@@ -89,7 +86,6 @@ class HtmlReporter {
|
|
|
89
86
|
};
|
|
90
87
|
}
|
|
91
88
|
async onEnd() {
|
|
92
|
-
const duration = (0, _utils.monotonicTime)() - this._montonicStartTime;
|
|
93
89
|
const projectSuites = this.suite.suites;
|
|
94
90
|
const reports = projectSuites.map(suite => {
|
|
95
91
|
const rawReporter = new _raw.default();
|
|
@@ -98,10 +94,7 @@ class HtmlReporter {
|
|
|
98
94
|
});
|
|
99
95
|
await (0, _utils.removeFolders)([this._outputFolder]);
|
|
100
96
|
const builder = new HtmlBuilder(this._outputFolder, this._attachmentsBaseURL);
|
|
101
|
-
this._buildResult = await builder.build(
|
|
102
|
-
...this.config.metadata,
|
|
103
|
-
duration
|
|
104
|
-
}, reports);
|
|
97
|
+
this._buildResult = await builder.build(this.config.metadata, reports);
|
|
105
98
|
}
|
|
106
99
|
async onExit() {
|
|
107
100
|
if (process.env.CI || !this._buildResult) return;
|
|
@@ -153,9 +146,9 @@ async function showHTMLReport(reportFolder, host = 'localhost', port, testId) {
|
|
|
153
146
|
console.log('');
|
|
154
147
|
console.log(_utilsBundle.colors.cyan(` Serving HTML report at ${url}. Press Ctrl+C to quit.`));
|
|
155
148
|
if (testId) url += `#?testId=${testId}`;
|
|
156
|
-
await (0,
|
|
149
|
+
await (0, _utilsBundle.open)(url, {
|
|
157
150
|
wait: true
|
|
158
|
-
}).catch(() =>
|
|
151
|
+
}).catch(() => {});
|
|
159
152
|
await new Promise(() => {});
|
|
160
153
|
}
|
|
161
154
|
function startHtmlReportServer(folder) {
|
|
@@ -257,7 +250,7 @@ class HtmlBuilder {
|
|
|
257
250
|
projectNames: rawReports.map(r => r.project.name),
|
|
258
251
|
stats: {
|
|
259
252
|
...[...data.values()].reduce((a, e) => addStats(a, e.testFileSummary.stats), emptyStats()),
|
|
260
|
-
duration: metadata.
|
|
253
|
+
duration: metadata.totalTime
|
|
261
254
|
}
|
|
262
255
|
};
|
|
263
256
|
htmlReport.files.sort((f1, f2) => {
|
|
@@ -10,6 +10,7 @@ var _babelBundle = require("../transform/babelBundle");
|
|
|
10
10
|
var _test = require("../common/test");
|
|
11
11
|
var _multiplexer = require("./multiplexer");
|
|
12
12
|
var _base = require("./base");
|
|
13
|
+
var _utils = require("playwright-core/lib/utils");
|
|
13
14
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
14
15
|
/**
|
|
15
16
|
* Copyright (c) Microsoft Corporation.
|
|
@@ -32,12 +33,14 @@ class InternalReporter {
|
|
|
32
33
|
this._multiplexer = void 0;
|
|
33
34
|
this._deferred = [];
|
|
34
35
|
this._config = void 0;
|
|
36
|
+
this._montonicStartTime = 0;
|
|
35
37
|
this._multiplexer = new _multiplexer.Multiplexer(reporters);
|
|
36
38
|
}
|
|
37
39
|
onConfigure(config) {
|
|
38
40
|
this._config = config;
|
|
39
41
|
}
|
|
40
42
|
onBegin(config, suite) {
|
|
43
|
+
this._montonicStartTime = (0, _utils.monotonicTime)();
|
|
41
44
|
this._multiplexer.onBegin(config, suite);
|
|
42
45
|
const deferred = this._deferred;
|
|
43
46
|
this._deferred = null;
|
|
@@ -80,7 +83,9 @@ class InternalReporter {
|
|
|
80
83
|
this._addSnippetToTestErrors(test, result);
|
|
81
84
|
this._multiplexer.onTestEnd(test, result);
|
|
82
85
|
}
|
|
83
|
-
async onEnd() {
|
|
86
|
+
async onEnd() {
|
|
87
|
+
this._config.config.metadata.totalTime = (0, _utils.monotonicTime)() - this._montonicStartTime;
|
|
88
|
+
}
|
|
84
89
|
async onExit(result) {
|
|
85
90
|
if (this._deferred) {
|
|
86
91
|
// onBegin was not reported, emit it.
|
package/lib/reporters/merge.js
CHANGED
|
@@ -28,6 +28,7 @@ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { de
|
|
|
28
28
|
|
|
29
29
|
async function createMergedReport(config, dir, reporterDescriptions, resolvePaths) {
|
|
30
30
|
const shardFiles = await sortedShardFiles(dir);
|
|
31
|
+
if (shardFiles.length === 0) throw new Error(`No report files found in ${dir}`);
|
|
31
32
|
const events = await mergeEvents(dir, shardFiles);
|
|
32
33
|
if (resolvePaths) patchAttachmentPaths(events, dir);
|
|
33
34
|
const reporters = await (0, _reporters.createReporters)(config, 'merge', reporterDescriptions);
|
|
@@ -69,7 +70,9 @@ function mergeBeginEvents(beginEvents) {
|
|
|
69
70
|
configFile: undefined,
|
|
70
71
|
globalTimeout: 0,
|
|
71
72
|
maxFailures: 0,
|
|
72
|
-
metadata: {
|
|
73
|
+
metadata: {
|
|
74
|
+
totalTime: 0
|
|
75
|
+
},
|
|
73
76
|
rootDir: '',
|
|
74
77
|
version: '',
|
|
75
78
|
workers: 0,
|
|
@@ -97,7 +100,8 @@ function mergeConfigs(to, from) {
|
|
|
97
100
|
...from,
|
|
98
101
|
metadata: {
|
|
99
102
|
...to.metadata,
|
|
100
|
-
...from.metadata
|
|
103
|
+
...from.metadata,
|
|
104
|
+
totalTime: to.metadata.totalTime + from.metadata.totalTime
|
|
101
105
|
},
|
|
102
106
|
workers: to.workers + from.workers
|
|
103
107
|
};
|
package/lib/runner/dispatcher.js
CHANGED
|
@@ -88,7 +88,7 @@ class Dispatcher {
|
|
|
88
88
|
this._checkFinished();
|
|
89
89
|
|
|
90
90
|
// 5. We got a free worker - perhaps we can immediately start another job?
|
|
91
|
-
this._scheduleJob();
|
|
91
|
+
void this._scheduleJob();
|
|
92
92
|
}
|
|
93
93
|
async _startJobInWorker(index, job) {
|
|
94
94
|
let worker = this._workerSlots[index].worker;
|
|
@@ -156,7 +156,7 @@ class Dispatcher {
|
|
|
156
156
|
busy: false
|
|
157
157
|
});
|
|
158
158
|
// 2. Schedule enough jobs.
|
|
159
|
-
for (let i = 0; i < this._workerSlots.length; i++) this._scheduleJob();
|
|
159
|
+
for (let i = 0; i < this._workerSlots.length; i++) void this._scheduleJob();
|
|
160
160
|
this._checkFinished();
|
|
161
161
|
// 3. More jobs are scheduled when the worker becomes free, or a new job is added.
|
|
162
162
|
// 4. Wait for all jobs to finish.
|
|
@@ -306,13 +306,13 @@ class Dispatcher {
|
|
|
306
306
|
// - we are here not because something failed
|
|
307
307
|
// - no unrecoverable worker error
|
|
308
308
|
if (!remaining.length && !failedTestIds.size && !params.fatalErrors.length && !params.skipTestsDueToSetupFailure.length && !params.fatalUnknownTestIds && !params.unexpectedExitError) {
|
|
309
|
-
if (this._isWorkerRedundant(worker)) worker.stop();
|
|
309
|
+
if (this._isWorkerRedundant(worker)) void worker.stop();
|
|
310
310
|
doneWithJob();
|
|
311
311
|
return;
|
|
312
312
|
}
|
|
313
313
|
|
|
314
314
|
// When worker encounters error, we will stop it and create a new one.
|
|
315
|
-
worker.stop(true /* didFail */);
|
|
315
|
+
void worker.stop(true /* didFail */);
|
|
316
316
|
|
|
317
317
|
const massSkipTestsFromRemaining = (testIds, errors, onlyStartedTests) => {
|
|
318
318
|
remaining = remaining.filter(test => {
|
|
@@ -409,7 +409,7 @@ class Dispatcher {
|
|
|
409
409
|
});
|
|
410
410
|
this._queuedOrRunningHashCount.set(testGroup.workerHash, this._queuedOrRunningHashCount.get(testGroup.workerHash) + 1);
|
|
411
411
|
// Perhaps we can immediately start the new job if there is a worker available?
|
|
412
|
-
this._scheduleJob();
|
|
412
|
+
void this._scheduleJob();
|
|
413
413
|
}
|
|
414
414
|
|
|
415
415
|
// This job is over, we just scheduled another one.
|
package/lib/runner/runner.js
CHANGED
|
@@ -93,12 +93,12 @@ class Runner {
|
|
|
93
93
|
}));
|
|
94
94
|
return await (0, _watchMode.runWatchModeLoop)(config);
|
|
95
95
|
}
|
|
96
|
-
async uiAllTests() {
|
|
96
|
+
async uiAllTests(options) {
|
|
97
97
|
const config = this._config;
|
|
98
98
|
(0, _webServerPlugin.webServerPluginsForConfig)(config).forEach(p => config.plugins.push({
|
|
99
99
|
factory: p
|
|
100
100
|
}));
|
|
101
|
-
return await (0, _uiMode.runUIMode)(config);
|
|
101
|
+
return await (0, _uiMode.runUIMode)(config, options);
|
|
102
102
|
}
|
|
103
103
|
}
|
|
104
104
|
exports.Runner = Runner;
|
package/lib/runner/uiMode.js
CHANGED
|
@@ -12,6 +12,7 @@ var _teleEmitter = require("../reporters/teleEmitter");
|
|
|
12
12
|
var _reporters = require("./reporters");
|
|
13
13
|
var _tasks = require("./tasks");
|
|
14
14
|
var _utilsBundle = require("../utilsBundle");
|
|
15
|
+
var _utilsBundle2 = require("playwright-core/lib/utilsBundle");
|
|
15
16
|
var _list = _interopRequireDefault(require("../reporters/list"));
|
|
16
17
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
17
18
|
/**
|
|
@@ -33,7 +34,7 @@ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { de
|
|
|
33
34
|
class UIMode {
|
|
34
35
|
constructor(config) {
|
|
35
36
|
this._config = void 0;
|
|
36
|
-
this.
|
|
37
|
+
this._transport = void 0;
|
|
37
38
|
this._testRun = void 0;
|
|
38
39
|
this.globalCleanup = void 0;
|
|
39
40
|
this._globalWatcher = void 0;
|
|
@@ -59,17 +60,12 @@ class UIMode {
|
|
|
59
60
|
};
|
|
60
61
|
this._originalStdoutWrite = process.stdout.write;
|
|
61
62
|
this._originalStderrWrite = process.stderr.write;
|
|
62
|
-
this._globalWatcher = new Watcher('deep', () => this._dispatchEvent({
|
|
63
|
-
method: 'listChanged'
|
|
64
|
-
}));
|
|
63
|
+
this._globalWatcher = new Watcher('deep', () => this._dispatchEvent('listChanged', {}));
|
|
65
64
|
this._testWatcher = new Watcher('flat', events => {
|
|
66
65
|
const collector = new Set();
|
|
67
66
|
events.forEach(f => (0, _compilationCache.collectAffectedTestFiles)(f.file, collector));
|
|
68
|
-
this._dispatchEvent({
|
|
69
|
-
|
|
70
|
-
params: {
|
|
71
|
-
testFileNames: [...collector]
|
|
72
|
-
}
|
|
67
|
+
this._dispatchEvent('testFilesChanged', {
|
|
68
|
+
testFileNames: [...collector]
|
|
73
69
|
});
|
|
74
70
|
});
|
|
75
71
|
}
|
|
@@ -92,61 +88,57 @@ class UIMode {
|
|
|
92
88
|
this.globalCleanup = globalCleanup;
|
|
93
89
|
return status;
|
|
94
90
|
}
|
|
95
|
-
async showUI() {
|
|
96
|
-
|
|
91
|
+
async showUI(options) {
|
|
92
|
+
const exitPromise = new _utils.ManualPromise();
|
|
93
|
+
let queue = Promise.resolve();
|
|
94
|
+
this._transport = {
|
|
95
|
+
dispatch: async (method, params) => {
|
|
96
|
+
if (method === 'exit') {
|
|
97
|
+
exitPromise.resolve();
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
if (method === 'watch') {
|
|
101
|
+
this._watchFiles(params.fileNames);
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
if (method === 'open' && params.location) {
|
|
105
|
+
(0, _utilsBundle2.open)('vscode://file/' + params.location).catch(e => this._originalStderrWrite.call(process.stderr, String(e)));
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
if (method === 'resizeTerminal') {
|
|
109
|
+
process.stdout.columns = params.cols;
|
|
110
|
+
process.stdout.rows = params.rows;
|
|
111
|
+
process.stderr.columns = params.cols;
|
|
112
|
+
process.stderr.columns = params.rows;
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
115
|
+
if (method === 'stop') {
|
|
116
|
+
void this._stopTests();
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
queue = queue.then(() => this._queueListOrRun(method, params));
|
|
120
|
+
await queue;
|
|
121
|
+
},
|
|
122
|
+
onclose: () => exitPromise.resolve()
|
|
123
|
+
};
|
|
124
|
+
await (0, _server.showTraceViewer)([], 'chromium', {
|
|
97
125
|
app: 'uiMode.html',
|
|
98
|
-
headless: (0, _utils.isUnderTest)() && process.env.PWTEST_HEADED_FOR_TEST !== '1'
|
|
126
|
+
headless: (0, _utils.isUnderTest)() && process.env.PWTEST_HEADED_FOR_TEST !== '1',
|
|
127
|
+
transport: this._transport,
|
|
128
|
+
host: options.host,
|
|
129
|
+
port: options.port,
|
|
130
|
+
openInBrowser: options.host !== undefined || options.port !== undefined
|
|
99
131
|
});
|
|
100
132
|
if (!process.env.PWTEST_DEBUG) {
|
|
101
133
|
process.stdout.write = chunk => {
|
|
102
|
-
this._dispatchEvent(
|
|
103
|
-
method: 'stdio',
|
|
104
|
-
params: chunkToPayload('stdout', chunk)
|
|
105
|
-
});
|
|
134
|
+
this._dispatchEvent('stdio', chunkToPayload('stdout', chunk));
|
|
106
135
|
return true;
|
|
107
136
|
};
|
|
108
137
|
process.stderr.write = chunk => {
|
|
109
|
-
this._dispatchEvent(
|
|
110
|
-
method: 'stdio',
|
|
111
|
-
params: chunkToPayload('stderr', chunk)
|
|
112
|
-
});
|
|
138
|
+
this._dispatchEvent('stdio', chunkToPayload('stderr', chunk));
|
|
113
139
|
return true;
|
|
114
140
|
};
|
|
115
141
|
}
|
|
116
|
-
const exitPromise = new _utils.ManualPromise();
|
|
117
|
-
this._page.on('close', () => exitPromise.resolve());
|
|
118
|
-
let queue = Promise.resolve();
|
|
119
|
-
this._page.exposeBinding('sendMessage', false, async (source, data) => {
|
|
120
|
-
const {
|
|
121
|
-
method,
|
|
122
|
-
params
|
|
123
|
-
} = data;
|
|
124
|
-
if (method === 'exit') {
|
|
125
|
-
exitPromise.resolve();
|
|
126
|
-
return;
|
|
127
|
-
}
|
|
128
|
-
if (method === 'watch') {
|
|
129
|
-
this._watchFiles(params.fileNames);
|
|
130
|
-
return;
|
|
131
|
-
}
|
|
132
|
-
if (method === 'open' && params.location) {
|
|
133
|
-
(0, _utilsBundle.open)('vscode://file/' + params.location).catch(e => this._originalStderrWrite.call(process.stderr, String(e)));
|
|
134
|
-
return;
|
|
135
|
-
}
|
|
136
|
-
if (method === 'resizeTerminal') {
|
|
137
|
-
process.stdout.columns = params.cols;
|
|
138
|
-
process.stdout.rows = params.rows;
|
|
139
|
-
process.stderr.columns = params.cols;
|
|
140
|
-
process.stderr.columns = params.rows;
|
|
141
|
-
return;
|
|
142
|
-
}
|
|
143
|
-
if (method === 'stop') {
|
|
144
|
-
this._stopTests();
|
|
145
|
-
return;
|
|
146
|
-
}
|
|
147
|
-
queue = queue.then(() => this._queueListOrRun(method, params));
|
|
148
|
-
await queue;
|
|
149
|
-
});
|
|
150
142
|
await exitPromise;
|
|
151
143
|
if (!process.env.PWTEST_DEBUG) {
|
|
152
144
|
process.stdout.write = this._originalStdoutWrite;
|
|
@@ -157,14 +149,12 @@ class UIMode {
|
|
|
157
149
|
if (method === 'list') await this._listTests();
|
|
158
150
|
if (method === 'run') await this._runTests(params.testIds);
|
|
159
151
|
}
|
|
160
|
-
_dispatchEvent(
|
|
161
|
-
|
|
162
|
-
this.
|
|
163
|
-
isFunction: true
|
|
164
|
-
}, message).catch(e => this._originalStderrWrite.call(process.stderr, String(e)));
|
|
152
|
+
_dispatchEvent(method, params) {
|
|
153
|
+
var _this$_transport$send, _this$_transport;
|
|
154
|
+
(_this$_transport$send = (_this$_transport = this._transport).sendEvent) === null || _this$_transport$send === void 0 ? void 0 : _this$_transport$send.call(_this$_transport, method, params);
|
|
165
155
|
}
|
|
166
156
|
async _listTests() {
|
|
167
|
-
const listReporter = new _teleEmitter.TeleReporterEmitter(e => this._dispatchEvent(e));
|
|
157
|
+
const listReporter = new _teleEmitter.TeleReporterEmitter(e => this._dispatchEvent(e.method, e.params));
|
|
168
158
|
const reporter = new _internalReporter.InternalReporter([listReporter]);
|
|
169
159
|
this._config.cliListOnly = true;
|
|
170
160
|
this._config.testIdMatcher = undefined;
|
|
@@ -188,7 +178,7 @@ class UIMode {
|
|
|
188
178
|
this._config.cliListOnly = false;
|
|
189
179
|
this._config.testIdMatcher = id => !testIdSet || testIdSet.has(id);
|
|
190
180
|
const reporters = await (0, _reporters.createReporters)(this._config, 'ui');
|
|
191
|
-
reporters.push(new _teleEmitter.TeleReporterEmitter(e => this._dispatchEvent(e)));
|
|
181
|
+
reporters.push(new _teleEmitter.TeleReporterEmitter(e => this._dispatchEvent(e.method, e.params)));
|
|
192
182
|
const reporter = new _internalReporter.InternalReporter(reporters);
|
|
193
183
|
const taskRunner = (0, _tasks.createTaskRunnerForWatch)(this._config, reporter);
|
|
194
184
|
const testRun = new _tasks.TestRun(this._config, reporter);
|
|
@@ -209,7 +199,7 @@ class UIMode {
|
|
|
209
199
|
};
|
|
210
200
|
await run;
|
|
211
201
|
}
|
|
212
|
-
|
|
202
|
+
_watchFiles(fileNames) {
|
|
213
203
|
const files = new Set();
|
|
214
204
|
for (const fileName of fileNames) {
|
|
215
205
|
files.add(fileName);
|
|
@@ -223,15 +213,12 @@ class UIMode {
|
|
|
223
213
|
await ((_this$_testRun2 = this._testRun) === null || _this$_testRun2 === void 0 ? void 0 : _this$_testRun2.run);
|
|
224
214
|
}
|
|
225
215
|
}
|
|
226
|
-
|
|
227
|
-
window.dispatch(message);
|
|
228
|
-
});
|
|
229
|
-
async function runUIMode(config) {
|
|
216
|
+
async function runUIMode(config, options) {
|
|
230
217
|
var _uiMode$globalCleanup;
|
|
231
218
|
const uiMode = new UIMode(config);
|
|
232
219
|
const status = await uiMode.runGlobalSetup();
|
|
233
220
|
if (status !== 'passed') return status;
|
|
234
|
-
await uiMode.showUI();
|
|
221
|
+
await uiMode.showUI(options);
|
|
235
222
|
return (await ((_uiMode$globalCleanup = uiMode.globalCleanup) === null || _uiMode$globalCleanup === void 0 ? void 0 : _uiMode$globalCleanup.call(uiMode))) || 'passed';
|
|
236
223
|
}
|
|
237
224
|
function chunkToPayload(type, chunk) {
|
|
@@ -260,7 +247,7 @@ class Watcher {
|
|
|
260
247
|
if (JSON.stringify(this._watchedFiles) === JSON.stringify(watchedFiles)) return;
|
|
261
248
|
if (reportPending) this._reportEventsIfAny();
|
|
262
249
|
this._watchedFiles = watchedFiles;
|
|
263
|
-
(_this$_fsWatcher = this._fsWatcher) === null || _this$_fsWatcher === void 0 ? void 0 : _this$_fsWatcher.close()
|
|
250
|
+
void ((_this$_fsWatcher = this._fsWatcher) === null || _this$_fsWatcher === void 0 ? void 0 : _this$_fsWatcher.close());
|
|
264
251
|
this._fsWatcher = undefined;
|
|
265
252
|
this._collector.length = 0;
|
|
266
253
|
clearTimeout(this._throttleTimer);
|
package/lib/util.js
CHANGED
|
@@ -296,13 +296,30 @@ function envWithoutExperimentalLoaderOptions() {
|
|
|
296
296
|
// https://devblogs.microsoft.com/typescript/announcing-typescript-5-0-beta/#moduleresolution-bundler
|
|
297
297
|
const kExtLookups = new Map([['.js', ['.jsx', '.ts', '.tsx']], ['.jsx', ['.tsx']], ['.cjs', ['.cts']], ['.mjs', ['.mts']], ['', ['.js', '.ts', '.jsx', '.tsx', '.cjs', '.mjs', '.cts', '.mts']]]);
|
|
298
298
|
function resolveImportSpecifierExtension(resolved) {
|
|
299
|
-
if (
|
|
299
|
+
if (fileExists(resolved)) return resolved;
|
|
300
300
|
for (const [ext, others] of kExtLookups) {
|
|
301
301
|
if (!resolved.endsWith(ext)) continue;
|
|
302
302
|
for (const other of others) {
|
|
303
303
|
const modified = resolved.substring(0, resolved.length - ext.length) + other;
|
|
304
|
-
if (
|
|
304
|
+
if (fileExists(modified)) return modified;
|
|
305
305
|
}
|
|
306
306
|
break; // Do not try '' when a more specific extesion like '.jsx' matched.
|
|
307
307
|
}
|
|
308
|
+
// try directory imports last
|
|
309
|
+
if (dirExists(resolved)) {
|
|
310
|
+
const dirImport = _path.default.join(resolved, 'index');
|
|
311
|
+
return resolveImportSpecifierExtension(dirImport);
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
function fileExists(resolved) {
|
|
315
|
+
var _fs$statSync;
|
|
316
|
+
return (_fs$statSync = _fs.default.statSync(resolved, {
|
|
317
|
+
throwIfNoEntry: false
|
|
318
|
+
})) === null || _fs$statSync === void 0 ? void 0 : _fs$statSync.isFile();
|
|
319
|
+
}
|
|
320
|
+
function dirExists(resolved) {
|
|
321
|
+
var _fs$statSync2;
|
|
322
|
+
return (_fs$statSync2 = _fs.default.statSync(resolved, {
|
|
323
|
+
throwIfNoEntry: false
|
|
324
|
+
})) === null || _fs$statSync2 === void 0 ? void 0 : _fs$statSync2.isDirectory();
|
|
308
325
|
}
|