next
Version:
The React Framework
170 lines (169 loc) • 8.16 kB
JavaScript
Object.defineProperty(exports, "__esModule", {
value: true
});
0 && (module.exports = {
SUPPORTED_TEST_RUNNERS_LIST: null,
nextTest: null
});
function _export(target, all) {
for(var name in all)Object.defineProperty(target, name, {
enumerable: true,
get: all[name]
});
}
_export(exports, {
SUPPORTED_TEST_RUNNERS_LIST: function() {
return SUPPORTED_TEST_RUNNERS_LIST;
},
nextTest: function() {
return nextTest;
}
});
const _fs = require("fs");
const _getprojectdir = require("../lib/get-project-dir");
const _utils = require("../server/lib/utils");
const _config = /*#__PURE__*/ _interop_require_default(require("../server/config"));
const _constants = require("../shared/lib/constants");
const _hasnecessarydependencies = require("../lib/has-necessary-dependencies");
const _installdependencies = require("../lib/install-dependencies");
const _findup = /*#__PURE__*/ _interop_require_default(require("next/dist/compiled/find-up"));
const _findpagesdir = require("../lib/find-pages-dir");
const _verifytypescriptsetup = require("../lib/verify-typescript-setup");
const _path = /*#__PURE__*/ _interop_require_default(require("path"));
const _crossspawn = /*#__PURE__*/ _interop_require_default(require("next/dist/compiled/cross-spawn"));
function _interop_require_default(obj) {
return obj && obj.__esModule ? obj : {
default: obj
};
}
const SUPPORTED_TEST_RUNNERS_LIST = [
'playwright'
];
const requiredPackagesByTestRunner = {
playwright: [
{
file: 'playwright',
pkg: '@playwright/test',
exportsRestrict: false
}
]
};
async function nextTest(directory, testRunnerArgs = [], options = {}) {
// The following mess is in order to support an existing Next.js CLI pattern of optionally, passing a project `directory` as the first argument to execute the command on.
// This is problematic for `next test` because as a wrapper around a test runner's `test` command, it needs to pass through any additional arguments and options.
// Thus, `directory` could either be a valid Next.js project directory (that the user intends to run `next test` on), or it is the first argument for the test runner.
// Unfortunately, since many test runners support passing a path (to a test file or directory containing test files), we must check if `directory` is both a valid path and a valid Next.js project.
let baseDir, nextConfig;
try {
// if directory is `undefined` or a valid path this will succeed.
baseDir = (0, _getprojectdir.getProjectDir)(directory, false);
} catch (err) {
// if that failed, then `directory` is not a valid path, so it must have meant to be the first item for `testRunnerArgs`
// @ts-expect-error directory is a string here since `getProjectDir` will succeed if its undefined
testRunnerArgs.unshift(directory);
// intentionally set baseDir to the resolved '.' path
baseDir = (0, _getprojectdir.getProjectDir)();
}
try {
// but, `baseDir` might not be a Next.js project directory, it could be a path-like argument for the test runner (i.e. `playwright test test/foo.spec.js`)
// if this succeeds, it means that `baseDir` is a Next.js project directory
nextConfig = await (0, _config.default)(_constants.PHASE_PRODUCTION_BUILD, baseDir);
} catch (err) {
// if it doesn't, then most likely `baseDir` is not a Next.js project directory
// @ts-expect-error directory is a string here since `getProjectDir` will succeed if its undefined
testRunnerArgs.unshift(directory);
// intentionally set baseDir to the resolved '.' path
baseDir = (0, _getprojectdir.getProjectDir)();
nextConfig = await (0, _config.default)(_constants.PHASE_PRODUCTION_BUILD, baseDir) // let this error bubble up if the `basePath` is still not a valid Next.js project
;
}
// set the test runner. priority is CLI option > next config > default 'playwright'
const configuredTestRunner = (options == null ? void 0 : options.testRunner) ?? // --test-runner='foo'
nextConfig.experimental.defaultTestRunner ?? // { experimental: { defaultTestRunner: 'foo' }}
'playwright';
if (!nextConfig.experimental.testProxy) {
return (0, _utils.printAndExit)(`\`next experimental-test\` requires the \`experimental.testProxy: true\` configuration option.`);
}
// execute test runner specific function
switch(configuredTestRunner){
case 'playwright':
return runPlaywright(baseDir, nextConfig, testRunnerArgs);
default:
return (0, _utils.printAndExit)(`Test runner ${configuredTestRunner} is not supported.`);
}
}
async function checkRequiredDeps(baseDir, testRunner) {
const deps = await (0, _hasnecessarydependencies.hasNecessaryDependencies)(baseDir, requiredPackagesByTestRunner[testRunner]);
if (deps.missing.length > 0) {
await (0, _installdependencies.installDependencies)(baseDir, deps.missing, true);
const playwright = (0, _crossspawn.default)(_path.default.join(baseDir, 'node_modules', '.bin', 'playwright'), [
'install'
], {
cwd: baseDir,
shell: false,
stdio: 'inherit',
env: {
...process.env
}
});
return new Promise((resolve, reject)=>{
playwright.on('close', (c)=>resolve(c));
playwright.on('error', (err)=>reject(err));
});
}
}
async function runPlaywright(baseDir, nextConfig, testRunnerArgs) {
await checkRequiredDeps(baseDir, 'playwright');
const playwrightConfigFile = await (0, _findup.default)([
'playwright.config.js',
'playwright.config.ts'
], {
cwd: baseDir
});
if (!playwrightConfigFile) {
const { pagesDir, appDir } = (0, _findpagesdir.findPagesDir)(baseDir);
const { version: typeScriptVersion } = await (0, _verifytypescriptsetup.verifyTypeScriptSetup)({
dir: baseDir,
distDir: nextConfig.distDir,
intentDirs: [
pagesDir,
appDir
].filter(Boolean),
typeCheckPreflight: false,
tsconfigPath: nextConfig.typescript.tsconfigPath,
disableStaticImages: nextConfig.images.disableStaticImages,
hasAppDir: !!appDir,
hasPagesDir: !!pagesDir
});
const isUsingTypeScript = !!typeScriptVersion;
const playwrightConfigFilename = isUsingTypeScript ? 'playwright.config.ts' : 'playwright.config.js';
(0, _fs.writeFileSync)(_path.default.join(baseDir, playwrightConfigFilename), defaultPlaywrightConfig(isUsingTypeScript));
return (0, _utils.printAndExit)(`Successfully generated ${playwrightConfigFilename}. Create your first test and then run \`next experimental-test\`.`, 0);
} else {
const playwright = (0, _crossspawn.default)(_path.default.join(baseDir, 'node_modules', '.bin', 'playwright'), [
'test',
...testRunnerArgs
], {
cwd: baseDir,
shell: false,
stdio: 'inherit',
env: {
...process.env
}
});
return new Promise((resolve, reject)=>{
playwright.on('close', (c)=>resolve(c));
playwright.on('error', (err)=>reject(err));
});
}
}
function defaultPlaywrightConfig(typescript) {
const comment = `/*
* Specify any additional Playwright config options here.
* They will be merged with Next.js' default Playwright config.
* You can access the default config by importing \`defaultPlaywrightConfig\` from \`'next/experimental/testmode/playwright'\`.
*/`;
return typescript ? `import { defineConfig } from 'next/experimental/testmode/playwright';\n\n${comment}\nexport default defineConfig({});` : `const { defineConfig } = require('next/experimental/testmode/playwright');\n\n${comment}\nmodule.exports = defineConfig({});`;
}
//# sourceMappingURL=next-test.js.map
;