@nx/playwright
Version:
176 lines (175 loc) • 9.18 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.default = default_1;
const devkit_1 = require("@nx/devkit");
const tsquery_1 = require("@phenomnomnominal/tsquery");
const add_e2e_ci_target_defaults_1 = require("./add-e2e-ci-target-defaults");
const loaded_nx_plugin_1 = require("nx/src/project-graph/plugins/loaded-nx-plugin");
const retrieve_workspace_files_1 = require("nx/src/project-graph/utils/retrieve-workspace-files");
const error_types_1 = require("nx/src/project-graph/error-types");
async function default_1(tree) {
const graph = await (0, devkit_1.createProjectGraphAsync)();
const collectedProjects = [];
(0, devkit_1.visitNotIgnoredFiles)(tree, '', async (path) => {
if (!path.endsWith('playwright.config.ts')) {
return;
}
let playwrightConfigFileContents = tree.read(path, 'utf-8');
const WEBSERVER_COMMAND_SELECTOR = 'PropertyAssignment:has(Identifier[name=webServer]) PropertyAssignment:has(Identifier[name=command]) > StringLiteral';
let ast = tsquery_1.tsquery.ast(playwrightConfigFileContents);
const nodes = (0, tsquery_1.tsquery)(ast, WEBSERVER_COMMAND_SELECTOR, {
visitAllChildren: true,
});
if (!nodes.length) {
return;
}
const commandValueNode = nodes[0];
const command = commandValueNode.getText();
let project;
let portFlagValue;
if (command.includes('nx run')) {
const NX_RUN_TARGET_REGEX = /(?<=nx run )([^' ]+)(?: [^']*--port[= ](\d+))?/;
const matches = command.match(NX_RUN_TARGET_REGEX);
if (!matches) {
return;
}
const targetString = matches[1];
const parsedTargetString = (0, devkit_1.parseTargetString)(targetString, graph);
if (parsedTargetString.target === 'serve-static' ||
parsedTargetString.target === 'preview') {
return;
}
project = parsedTargetString.project;
portFlagValue = matches[2];
}
else {
const NX_PROJECT_REGEX = /(?<=nx [^ ]+ )([^' ]+)(?: [^']*--port[= ](\d+))?/;
const matches = command.match(NX_PROJECT_REGEX);
if (!matches) {
return;
}
project = matches[1];
portFlagValue = matches[2];
}
if (!project || !graph.nodes[project]) {
return;
}
const pathToViteConfig = [
(0, devkit_1.joinPathFragments)(graph.nodes[project].data.root, 'vite.config.ts'),
(0, devkit_1.joinPathFragments)(graph.nodes[project].data.root, 'vite.config.js'),
].find((p) => tree.exists(p));
const pathToWebpackConfig = [
(0, devkit_1.joinPathFragments)(graph.nodes[project].data.root, 'webpack.config.ts'),
(0, devkit_1.joinPathFragments)(graph.nodes[project].data.root, 'webpack.config.js'),
].find((p) => tree.exists(p));
const configFile = pathToWebpackConfig ?? pathToViteConfig;
// Only migrate projects that have a webpack or vite config file
if (configFile) {
collectedProjects.push({
projectName: project,
configFile,
configFileType: pathToWebpackConfig ? 'webpack' : 'vite',
playwrightConfigFile: path,
commandValueNode,
portFlagValue,
});
}
});
for (const projectToMigrate of collectedProjects) {
let playwrightConfigFileContents = tree.read(projectToMigrate.playwrightConfigFile, 'utf-8');
const targetName = (await getServeStaticTargetNameForConfigFile(tree, projectToMigrate.configFileType === 'webpack'
? '@nx/webpack/plugin'
: '@nx/vite/plugin', projectToMigrate.configFile, projectToMigrate.configFileType === 'webpack'
? 'serve-static'
: 'preview', projectToMigrate.configFileType === 'webpack'
? 'serveStaticTargetName'
: 'previewTargetName', projectToMigrate.configFileType === 'webpack'
? require('@nx/webpack/plugin').createNodesV2
: require('@nx/vite/plugin')
.createNodesV2)) ??
getServeStaticLikeTarget(tree, graph, projectToMigrate.projectName, projectToMigrate.configFileType === 'webpack'
? '@nx/web:file-server'
: '@nx/vite:preview-server');
if (!targetName) {
continue;
}
const oldCommand = projectToMigrate.commandValueNode.getText();
const newCommand = oldCommand.replace(/nx.*[^"']/, `nx run ${projectToMigrate.projectName}:${targetName}${projectToMigrate.portFlagValue
? ` --port=${projectToMigrate.portFlagValue}`
: ''}`);
if (projectToMigrate.configFileType === 'webpack') {
tree.write(projectToMigrate.playwrightConfigFile, `${playwrightConfigFileContents.slice(0, projectToMigrate.commandValueNode.getStart())}${newCommand}${playwrightConfigFileContents.slice(projectToMigrate.commandValueNode.getEnd())}`);
}
else {
tree.write(projectToMigrate.playwrightConfigFile, `${playwrightConfigFileContents.slice(0, projectToMigrate.commandValueNode.getStart())}${newCommand}${playwrightConfigFileContents.slice(projectToMigrate.commandValueNode.getEnd())}`);
playwrightConfigFileContents = tree.read(projectToMigrate.playwrightConfigFile, 'utf-8');
let ast = tsquery_1.tsquery.ast(playwrightConfigFileContents);
const BASE_URL_SELECTOR = 'VariableDeclaration:has(Identifier[name=baseURL])';
const baseUrlNodes = (0, tsquery_1.tsquery)(ast, BASE_URL_SELECTOR, {
visitAllChildren: true,
});
if (!baseUrlNodes.length) {
return;
}
const serverUrl = `http://localhost:${projectToMigrate.portFlagValue ?? '4300'}`;
const baseUrlNode = baseUrlNodes[0];
const newBaseUrlVariableDeclaration = `baseURL = process.env['BASE_URL'] || '${serverUrl}';`;
tree.write(projectToMigrate.playwrightConfigFile, `${playwrightConfigFileContents.slice(0, baseUrlNode.getStart())}${newBaseUrlVariableDeclaration}${playwrightConfigFileContents.slice(baseUrlNode.getEnd())}`);
playwrightConfigFileContents = tree.read(projectToMigrate.playwrightConfigFile, 'utf-8');
ast = tsquery_1.tsquery.ast(playwrightConfigFileContents);
const WEB_SERVER_URL_SELECTOR = 'PropertyAssignment:has(Identifier[name=webServer]) PropertyAssignment:has(Identifier[name=url]) > StringLiteral';
const webServerUrlNodes = (0, tsquery_1.tsquery)(ast, WEB_SERVER_URL_SELECTOR, {
visitAllChildren: true,
});
if (!webServerUrlNodes.length) {
return;
}
const webServerUrlNode = webServerUrlNodes[0];
const newWebServerUrl = `'${serverUrl}'`;
tree.write(projectToMigrate.playwrightConfigFile, `${playwrightConfigFileContents.slice(0, webServerUrlNode.getStart())}${newWebServerUrl}${playwrightConfigFileContents.slice(webServerUrlNode.getEnd())}`);
}
}
await (0, add_e2e_ci_target_defaults_1.default)(tree);
await (0, devkit_1.formatFiles)(tree);
}
async function getServeStaticTargetNameForConfigFile(tree, pluginName, configFile, defaultTargetName, targetNamePluginOption, createNodesV2) {
const nxJson = (0, devkit_1.readNxJson)(tree);
const matchingPluginRegistrations = nxJson.plugins?.filter((p) => typeof p === 'string' ? p === pluginName : p.plugin === pluginName);
if (!matchingPluginRegistrations) {
return undefined;
}
let targetName = undefined;
for (const plugin of matchingPluginRegistrations) {
let projectConfigs;
try {
const loadedPlugin = new loaded_nx_plugin_1.LoadedNxPlugin({ createNodesV2, name: pluginName }, plugin);
projectConfigs = await (0, retrieve_workspace_files_1.retrieveProjectConfigurations)([loadedPlugin], tree.root, nxJson);
}
catch (e) {
if (e instanceof error_types_1.ProjectConfigurationsError) {
projectConfigs = e.partialProjectConfigurationsResult;
}
else {
throw e;
}
}
if (projectConfigs.matchingProjectFiles.includes(configFile)) {
targetName =
typeof plugin === 'string'
? defaultTargetName
: plugin.options?.[targetNamePluginOption] ??
defaultTargetName;
}
}
return targetName;
}
function getServeStaticLikeTarget(tree, graph, projectName, executorName) {
if (!graph.nodes[projectName]?.data?.targets) {
return;
}
for (const [targetName, targetOptions] of Object.entries(graph.nodes[projectName].data.targets)) {
if (targetOptions.executor && targetOptions.executor === executorName) {
return targetName;
}
}
}