feat(testing): use createNodesV2 for cypress and playwright (#26301)

This commit is contained in:
Jason Jean 2024-05-31 17:53:31 -04:00 committed by GitHub
parent 92718fd52b
commit 1e7cd7e9e6
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
12 changed files with 591 additions and 469 deletions

View File

@ -1 +1 @@
export { createNodes, createDependencies } from './src/plugins/plugin'; export { createNodesV2, createNodes } from './src/plugins/plugin';

View File

@ -1,13 +1,11 @@
import { import {
CreateNodesContext,
createProjectGraphAsync, createProjectGraphAsync,
formatFiles, formatFiles,
joinPathFragments,
type TargetConfiguration, type TargetConfiguration,
type Tree, type Tree,
} from '@nx/devkit'; } from '@nx/devkit';
import { migrateExecutorToPlugin } from '@nx/devkit/src/generators/plugin-migrations/executor-to-plugin-migrator'; import { migrateExecutorToPlugin } from '@nx/devkit/src/generators/plugin-migrations/executor-to-plugin-migrator';
import { createNodes } from '../../plugins/plugin'; import { createNodesV2 } from '../../plugins/plugin';
import { targetOptionsToCliMap } from './lib/target-options-map'; import { targetOptionsToCliMap } from './lib/target-options-map';
import { upsertBaseUrl } from './lib/upsert-baseUrl'; import { upsertBaseUrl } from './lib/upsert-baseUrl';
import { addDevServerTargetToConfig } from './lib/add-dev-server-target-to-config'; import { addDevServerTargetToConfig } from './lib/add-dev-server-target-to-config';
@ -31,7 +29,7 @@ export async function convertToInferred(tree: Tree, options: Schema) {
ciTargetName: 'e2e-ci', ciTargetName: 'e2e-ci',
}), }),
postTargetTransformer, postTargetTransformer,
createNodes, createNodesV2,
options.project options.project
); );
@ -45,7 +43,7 @@ export async function convertToInferred(tree: Tree, options: Schema) {
ciTargetName: 'e2e-ci', ciTargetName: 'e2e-ci',
}), }),
postTargetTransformer, postTargetTransformer,
createNodes, createNodesV2,
options.project options.project
); );

View File

@ -10,14 +10,10 @@ import {
Tree, Tree,
updateNxJson, updateNxJson,
} from '@nx/devkit'; } from '@nx/devkit';
import { import { addPlugin as _addPlugin } from '@nx/devkit/src/utils/add-plugin';
addPluginV1 as _addPlugin, import { createNodesV2 } from '../../plugins/plugin';
generateCombinations,
} from '@nx/devkit/src/utils/add-plugin';
import { createNodes } from '../../plugins/plugin';
import { cypressVersion, nxVersion } from '../../utils/versions'; import { cypressVersion, nxVersion } from '../../utils/versions';
import { Schema } from './schema'; import { Schema } from './schema';
import { CypressPluginOptions } from '../../plugins/plugin';
function setupE2ETargetDefaults(tree: Tree) { function setupE2ETargetDefaults(tree: Tree) {
const nxJson = readNxJson(tree); const nxJson = readNxJson(tree);
@ -69,7 +65,7 @@ export function addPlugin(
tree, tree,
graph, graph,
'@nx/cypress/plugin', '@nx/cypress/plugin',
createNodes, createNodesV2,
{ {
targetName: ['e2e', 'cypress:e2e', 'cypress-e2e'], targetName: ['e2e', 'cypress:e2e', 'cypress-e2e'],
openTargetName: ['open-cypress', 'cypress-open'], openTargetName: ['open-cypress', 'cypress-open'],

View File

@ -1,14 +1,14 @@
import { CreateNodesContext } from '@nx/devkit'; import { CreateNodesContext } from '@nx/devkit';
import { defineConfig } from 'cypress'; import { defineConfig } from 'cypress';
import { createNodes } from './plugin'; import { createNodesV2 } from './plugin';
import { TempFs } from 'nx/src/internal-testing-utils/temp-fs'; import { TempFs } from 'nx/src/internal-testing-utils/temp-fs';
import { resetWorkspaceContext } from 'nx/src/utils/workspace-context'; import { resetWorkspaceContext } from 'nx/src/utils/workspace-context';
import { join } from 'path'; import { join } from 'path';
import { nxE2EPreset } from '../../plugins/cypress-preset'; import { nxE2EPreset } from '../../plugins/cypress-preset';
describe('@nx/cypress/plugin', () => { describe('@nx/cypress/plugin', () => {
let createNodesFunction = createNodes[1]; let createNodesFunction = createNodesV2[1];
let context: CreateNodesContext; let context: CreateNodesContext;
let tempFs: TempFs; let tempFs: TempFs;
@ -65,7 +65,7 @@ describe('@nx/cypress/plugin', () => {
}) })
); );
const nodes = await createNodesFunction( const nodes = await createNodesFunction(
'cypress.config.js', ['cypress.config.js'],
{ {
targetName: 'e2e', targetName: 'e2e',
}, },
@ -73,6 +73,9 @@ describe('@nx/cypress/plugin', () => {
); );
expect(nodes).toMatchInlineSnapshot(` expect(nodes).toMatchInlineSnapshot(`
[
[
"cypress.config.js",
{ {
"projects": { "projects": {
".": { ".": {
@ -125,7 +128,9 @@ describe('@nx/cypress/plugin', () => {
}, },
}, },
}, },
} },
],
]
`); `);
}); });
@ -143,7 +148,7 @@ describe('@nx/cypress/plugin', () => {
}) })
); );
const nodes = await createNodesFunction( const nodes = await createNodesFunction(
'cypress.config.js', ['cypress.config.js'],
{ {
componentTestingTargetName: 'component-test', componentTestingTargetName: 'component-test',
}, },
@ -151,6 +156,9 @@ describe('@nx/cypress/plugin', () => {
); );
expect(nodes).toMatchInlineSnapshot(` expect(nodes).toMatchInlineSnapshot(`
[
[
"cypress.config.js",
{ {
"projects": { "projects": {
".": { ".": {
@ -198,7 +206,9 @@ describe('@nx/cypress/plugin', () => {
}, },
}, },
}, },
} },
],
]
`); `);
}); });
@ -220,7 +230,7 @@ describe('@nx/cypress/plugin', () => {
}) })
); );
const nodes = await createNodesFunction( const nodes = await createNodesFunction(
'cypress.config.js', ['cypress.config.js'],
{ {
componentTestingTargetName: 'component-test', componentTestingTargetName: 'component-test',
}, },
@ -228,6 +238,9 @@ describe('@nx/cypress/plugin', () => {
); );
expect(nodes).toMatchInlineSnapshot(` expect(nodes).toMatchInlineSnapshot(`
[
[
"cypress.config.js",
{ {
"projects": { "projects": {
".": { ".": {
@ -343,7 +356,9 @@ describe('@nx/cypress/plugin', () => {
}, },
}, },
}, },
} },
],
]
`); `);
}); });

View File

@ -1,9 +1,11 @@
import { import {
CreateDependencies,
CreateNodes, CreateNodes,
CreateNodesContext, CreateNodesContext,
createNodesFromFiles,
CreateNodesV2,
detectPackageManager, detectPackageManager,
joinPathFragments, joinPathFragments,
logger,
normalizePath, normalizePath,
NxJsonConfiguration, NxJsonConfiguration,
ProjectConfiguration, ProjectConfiguration,
@ -22,6 +24,7 @@ import { calculateHashForCreateNodes } from '@nx/devkit/src/utils/calculate-hash
import { projectGraphCacheDirectory } from 'nx/src/utils/cache-directory'; import { projectGraphCacheDirectory } from 'nx/src/utils/cache-directory';
import { NX_PLUGIN_OPTIONS } from '../utils/constants'; import { NX_PLUGIN_OPTIONS } from '../utils/constants';
import { loadConfigFile } from '@nx/devkit/src/utils/config-utils'; import { loadConfigFile } from '@nx/devkit/src/utils/config-utils';
import { hashObject } from 'nx/src/devkit-internals';
export interface CypressPluginOptions { export interface CypressPluginOptions {
ciTargetName?: string; ciTargetName?: string;
@ -30,29 +33,59 @@ export interface CypressPluginOptions {
componentTestingTargetName?: string; componentTestingTargetName?: string;
} }
const cachePath = join(projectGraphCacheDirectory, 'cypress.hash'); function readTargetsCache(cachePath: string): Record<string, CypressTargets> {
const targetsCache = readTargetsCache();
function readTargetsCache(): Record<string, CypressTargets> {
return existsSync(cachePath) ? readJsonFile(cachePath) : {}; return existsSync(cachePath) ? readJsonFile(cachePath) : {};
} }
function writeTargetsToCache() { function writeTargetsToCache(cachePath: string, results: CypressTargets) {
const oldCache = readTargetsCache(); writeJsonFile(cachePath, results);
writeJsonFile(cachePath, {
...oldCache,
targetsCache,
});
} }
export const createDependencies: CreateDependencies = () => { const cypressConfigGlob = '**/cypress.config.{js,ts,mjs,cjs}';
writeTargetsToCache();
return [];
};
export const createNodesV2: CreateNodesV2<CypressPluginOptions> = [
cypressConfigGlob,
async (configFiles, options, context) => {
const optionsHash = hashObject(options);
const cachePath = join(
projectGraphCacheDirectory,
`cypress-${optionsHash}.hash`
);
const targetsCache = readTargetsCache(cachePath);
try {
return await createNodesFromFiles(
(configFile, options, context) =>
createNodesInternal(configFile, options, context, targetsCache),
configFiles,
options,
context
);
} finally {
writeTargetsToCache(cachePath, targetsCache);
}
},
];
/**
* @deprecated This is replaced with {@link createNodesV2}. Update your plugin to export its own `createNodesV2` function that wraps this one instead.
* This function will change to the v2 function in Nx 20.
*/
export const createNodes: CreateNodes<CypressPluginOptions> = [ export const createNodes: CreateNodes<CypressPluginOptions> = [
'**/cypress.config.{js,ts,mjs,cjs}', cypressConfigGlob,
async (configFilePath, options, context) => { (configFile, options, context) => {
logger.warn(
'`createNodes` is deprecated. Update your plugin to utilize createNodesV2 instead. In Nx 20, this will change to the createNodesV2 API.'
);
return createNodesInternal(configFile, options, context, {});
},
];
async function createNodesInternal(
configFilePath: string,
options: CypressPluginOptions,
context: CreateNodesContext,
targetsCache: CypressTargets
) {
options = normalizeOptions(options); options = normalizeOptions(options);
const projectRoot = dirname(configFilePath); const projectRoot = dirname(configFilePath);
@ -88,8 +121,7 @@ export const createNodes: CreateNodes<CypressPluginOptions> = [
[projectRoot]: project, [projectRoot]: project,
}, },
}; };
}, }
];
function getOutputs( function getOutputs(
projectRoot: string, projectRoot: string,

View File

@ -17,6 +17,7 @@ import {
TargetConfiguration, TargetConfiguration,
Tree, Tree,
CreateNodes, CreateNodes,
CreateNodesV2,
} from 'nx/src/devkit-exports'; } from 'nx/src/devkit-exports';
import { import {
@ -52,8 +53,8 @@ class ExecutorToPluginMigrator<T> {
#targetDefaultsForExecutor: Partial<TargetConfiguration>; #targetDefaultsForExecutor: Partial<TargetConfiguration>;
#targetAndProjectsToMigrate: Map<string, Set<string>>; #targetAndProjectsToMigrate: Map<string, Set<string>>;
#pluginToAddForTarget: Map<string, ExpandedPluginConfiguration<T>>; #pluginToAddForTarget: Map<string, ExpandedPluginConfiguration<T>>;
#createNodes: CreateNodes<T>; #createNodes?: CreateNodes<T>;
#configFiles: string[]; #createNodesV2?: CreateNodesV2<T>;
#createNodesResultsForTargets: Map<string, ConfigurationResult>; #createNodesResultsForTargets: Map<string, ConfigurationResult>;
constructor( constructor(
@ -63,7 +64,8 @@ class ExecutorToPluginMigrator<T> {
pluginPath: string, pluginPath: string,
pluginOptionsBuilder: PluginOptionsBuilder<T>, pluginOptionsBuilder: PluginOptionsBuilder<T>,
postTargetTransformer: PostTargetTransformer, postTargetTransformer: PostTargetTransformer,
createNodes: CreateNodes<T>, createNodes?: CreateNodes<T>,
createNodesV2?: CreateNodesV2<T>,
specificProjectToMigrate?: string, specificProjectToMigrate?: string,
skipTargetFilter?: SkipTargetFilter skipTargetFilter?: SkipTargetFilter
) { ) {
@ -74,6 +76,7 @@ class ExecutorToPluginMigrator<T> {
this.#pluginOptionsBuilder = pluginOptionsBuilder; this.#pluginOptionsBuilder = pluginOptionsBuilder;
this.#postTargetTransformer = postTargetTransformer; this.#postTargetTransformer = postTargetTransformer;
this.#createNodes = createNodes; this.#createNodes = createNodes;
this.#createNodesV2 = createNodesV2;
this.#specificProjectToMigrate = specificProjectToMigrate; this.#specificProjectToMigrate = specificProjectToMigrate;
this.#skipTargetFilter = skipTargetFilter ?? ((...args) => [false, '']); this.#skipTargetFilter = skipTargetFilter ?? ((...args) => [false, '']);
} }
@ -224,6 +227,7 @@ class ExecutorToPluginMigrator<T> {
) { ) {
const loadedPlugin = new LoadedNxPlugin( const loadedPlugin = new LoadedNxPlugin(
{ {
createNodesV2: this.#createNodesV2,
createNodes: this.#createNodes, createNodes: this.#createNodes,
name: this.#pluginPath, name: this.#pluginPath,
}, },
@ -373,6 +377,7 @@ class ExecutorToPluginMigrator<T> {
for (const targetName of this.#targetAndProjectsToMigrate.keys()) { for (const targetName of this.#targetAndProjectsToMigrate.keys()) {
const loadedPlugin = new LoadedNxPlugin( const loadedPlugin = new LoadedNxPlugin(
{ {
createNodesV2: this.#createNodesV2,
createNodes: this.#createNodes, createNodes: this.#createNodes,
name: this.#pluginPath, name: this.#pluginPath,
}, },
@ -396,13 +401,38 @@ class ExecutorToPluginMigrator<T> {
} }
} }
this.#configFiles = Array.from(projectConfigs.matchingProjectFiles);
this.#createNodesResultsForTargets.set(targetName, projectConfigs); this.#createNodesResultsForTargets.set(targetName, projectConfigs);
} }
} }
} }
export async function migrateExecutorToPlugin<T>( export async function migrateExecutorToPlugin<T>(
tree: Tree,
projectGraph: ProjectGraph,
executor: string,
pluginPath: string,
pluginOptionsBuilder: PluginOptionsBuilder<T>,
postTargetTransformer: PostTargetTransformer,
createNodes: CreateNodesV2<T>,
specificProjectToMigrate?: string,
skipTargetFilter?: SkipTargetFilter
): Promise<Map<string, Set<string>>> {
const migrator = new ExecutorToPluginMigrator<T>(
tree,
projectGraph,
executor,
pluginPath,
pluginOptionsBuilder,
postTargetTransformer,
undefined,
createNodes,
specificProjectToMigrate,
skipTargetFilter
);
return await migrator.run();
}
export async function migrateExecutorToPluginV1<T>(
tree: Tree, tree: Tree,
projectGraph: ProjectGraph, projectGraph: ProjectGraph,
executor: string, executor: string,
@ -421,6 +451,7 @@ export async function migrateExecutorToPlugin<T>(
pluginOptionsBuilder, pluginOptionsBuilder,
postTargetTransformer, postTargetTransformer,
createNodes, createNodes,
undefined,
specificProjectToMigrate, specificProjectToMigrate,
skipTargetFilter skipTargetFilter
); );

View File

@ -6,7 +6,7 @@ import {
type Tree, type Tree,
} from '@nx/devkit'; } from '@nx/devkit';
import { createNodes, EslintPluginOptions } from '../../plugins/plugin'; import { createNodes, EslintPluginOptions } from '../../plugins/plugin';
import { migrateExecutorToPlugin } from '@nx/devkit/src/generators/plugin-migrations/executor-to-plugin-migrator'; import { migrateExecutorToPluginV1 } from '@nx/devkit/src/generators/plugin-migrations/executor-to-plugin-migrator';
import { targetOptionsToCliMap } from './lib/target-options-map'; import { targetOptionsToCliMap } from './lib/target-options-map';
import { interpolate } from 'nx/src/tasks-runner/utils'; import { interpolate } from 'nx/src/tasks-runner/utils';
@ -19,7 +19,7 @@ export async function convertToInferred(tree: Tree, options: Schema) {
const projectGraph = await createProjectGraphAsync(); const projectGraph = await createProjectGraphAsync();
const migratedProjectsModern = const migratedProjectsModern =
await migrateExecutorToPlugin<EslintPluginOptions>( await migrateExecutorToPluginV1<EslintPluginOptions>(
tree, tree,
projectGraph, projectGraph,
'@nx/eslint:lint', '@nx/eslint:lint',
@ -31,7 +31,7 @@ export async function convertToInferred(tree: Tree, options: Schema) {
); );
const migratedProjectsLegacy = const migratedProjectsLegacy =
await migrateExecutorToPlugin<EslintPluginOptions>( await migrateExecutorToPluginV1<EslintPluginOptions>(
tree, tree,
projectGraph, projectGraph,
'@nrwl/linter:eslint', '@nrwl/linter:eslint',

View File

@ -1,5 +1,5 @@
export { export {
createNodes, createNodes,
createNodesV2,
PlaywrightPluginOptions, PlaywrightPluginOptions,
createDependencies,
} from './src/plugins/plugin'; } from './src/plugins/plugin';

View File

@ -5,7 +5,7 @@ import {
type TargetConfiguration, type TargetConfiguration,
type Tree, type Tree,
} from '@nx/devkit'; } from '@nx/devkit';
import { createNodes, PlaywrightPluginOptions } from '../../plugins/plugin'; import { createNodesV2, PlaywrightPluginOptions } from '../../plugins/plugin';
import { migrateExecutorToPlugin } from '@nx/devkit/src/generators/plugin-migrations/executor-to-plugin-migrator'; import { migrateExecutorToPlugin } from '@nx/devkit/src/generators/plugin-migrations/executor-to-plugin-migrator';
interface Schema { interface Schema {
@ -24,7 +24,7 @@ export async function convertToInferred(tree: Tree, options: Schema) {
'@nx/playwright/plugin', '@nx/playwright/plugin',
(targetName) => ({ targetName, ciTargetName: 'e2e-ci' }), (targetName) => ({ targetName, ciTargetName: 'e2e-ci' }),
postTargetTransformer, postTargetTransformer,
createNodes, createNodesV2,
options.project options.project
); );

View File

@ -7,8 +7,8 @@ import {
runTasksInSerial, runTasksInSerial,
Tree, Tree,
} from '@nx/devkit'; } from '@nx/devkit';
import { addPluginV1 } from '@nx/devkit/src/utils/add-plugin'; import { addPlugin } from '@nx/devkit/src/utils/add-plugin';
import { createNodes } from '../../plugins/plugin'; import { createNodesV2 } from '../../plugins/plugin';
import { nxVersion, playwrightVersion } from '../../utils/versions'; import { nxVersion, playwrightVersion } from '../../utils/versions';
import { InitGeneratorSchema } from './schema'; import { InitGeneratorSchema } from './schema';
@ -45,11 +45,11 @@ export async function initGeneratorInternal(
} }
if (options.addPlugin) { if (options.addPlugin) {
await addPluginV1( await addPlugin(
tree, tree,
await createProjectGraphAsync(), await createProjectGraphAsync(),
'@nx/playwright/plugin', '@nx/playwright/plugin',
createNodes, createNodesV2,
{ targetName: ['e2e', 'playwright:e2e', 'playwright-e2e'] }, { targetName: ['e2e', 'playwright:e2e', 'playwright-e2e'] },
options.updatePackageScripts options.updatePackageScripts
); );

View File

@ -1,11 +1,11 @@
import { CreateNodesContext } from '@nx/devkit'; import { CreateNodesContext } from '@nx/devkit';
import { TempFs } from '@nx/devkit/internal-testing-utils'; import { TempFs } from '@nx/devkit/internal-testing-utils';
import { createNodes } from './plugin'; import { createNodesV2 } from './plugin';
import { PlaywrightTestConfig } from '@playwright/test'; import { PlaywrightTestConfig } from '@playwright/test';
describe('@nx/playwright/plugin', () => { describe('@nx/playwright/plugin', () => {
let createNodesFunction = createNodes[1]; let createNodesFunction = createNodesV2[1];
let context: CreateNodesContext; let context: CreateNodesContext;
let tempFs: TempFs; let tempFs: TempFs;
@ -35,16 +35,20 @@ describe('@nx/playwright/plugin', () => {
it('should create nodes with default playwright configuration', async () => { it('should create nodes with default playwright configuration', async () => {
await mockPlaywrightConfig(tempFs, {}); await mockPlaywrightConfig(tempFs, {});
const { projects } = await createNodesFunction( const results = await createNodesFunction(
'playwright.config.js', ['playwright.config.js'],
{ {
targetName: 'e2e', targetName: 'e2e',
}, },
context context
); );
expect(projects).toMatchInlineSnapshot(` expect(results).toMatchInlineSnapshot(`
[
[
"playwright.config.js",
{ {
"projects": {
".": { ".": {
"metadata": { "metadata": {
"targetGroups": { "targetGroups": {
@ -105,7 +109,10 @@ describe('@nx/playwright/plugin', () => {
}, },
}, },
}, },
} },
},
],
]
`); `);
}); });
@ -117,16 +124,20 @@ describe('@nx/playwright/plugin', () => {
['html', { outputFolder: 'test-results/html' }], ['html', { outputFolder: 'test-results/html' }],
], ],
}); });
const { projects } = await createNodesFunction( const results = await createNodesFunction(
'playwright.config.js', ['playwright.config.js'],
{ {
targetName: 'e2e', targetName: 'e2e',
}, },
context context
); );
expect(projects).toMatchInlineSnapshot(` expect(results).toMatchInlineSnapshot(`
[
[
"playwright.config.js",
{ {
"projects": {
".": { ".": {
"metadata": { "metadata": {
"targetGroups": { "targetGroups": {
@ -193,7 +204,10 @@ describe('@nx/playwright/plugin', () => {
}, },
}, },
}, },
} },
},
],
]
`); `);
}); });
@ -213,16 +227,17 @@ describe('@nx/playwright/plugin', () => {
'not-tests/run-me.spec.ts': '', 'not-tests/run-me.spec.ts': '',
}); });
const { projects } = await createNodesFunction( const results = await createNodesFunction(
'playwright.config.js', ['playwright.config.js'],
{ {
targetName: 'e2e', targetName: 'e2e',
ciTargetName: 'e2e-ci', ciTargetName: 'e2e-ci',
}, },
context context
); );
const { targets } = projects['.']; const project = results[0][1].projects['.'];
expect(projects['.'].metadata.targetGroups).toMatchInlineSnapshot(` const { targets } = project;
expect(project.metadata.targetGroups).toMatchInlineSnapshot(`
{ {
"E2E (CI)": [ "E2E (CI)": [
"e2e-ci--tests/run-me-2.spec.ts", "e2e-ci--tests/run-me-2.spec.ts",

View File

@ -2,11 +2,13 @@ import { existsSync, readdirSync } from 'fs';
import { dirname, join, relative } from 'path'; import { dirname, join, relative } from 'path';
import { import {
CreateDependencies,
CreateNodes, CreateNodes,
CreateNodesContext, CreateNodesContext,
createNodesFromFiles,
CreateNodesV2,
detectPackageManager, detectPackageManager,
joinPathFragments, joinPathFragments,
logger,
normalizePath, normalizePath,
ProjectConfiguration, ProjectConfiguration,
readJsonFile, readJsonFile,
@ -22,6 +24,7 @@ import { minimatch } from 'minimatch';
import { projectGraphCacheDirectory } from 'nx/src/utils/cache-directory'; import { projectGraphCacheDirectory } from 'nx/src/utils/cache-directory';
import { getLockFileName } from '@nx/js'; import { getLockFileName } from '@nx/js';
import { loadConfigFile } from '@nx/devkit/src/utils/config-utils'; import { loadConfigFile } from '@nx/devkit/src/utils/config-utils';
import { hashObject } from 'nx/src/hasher/file-hasher';
export interface PlaywrightPluginOptions { export interface PlaywrightPluginOptions {
targetName?: string; targetName?: string;
@ -33,32 +36,65 @@ interface NormalizedOptions {
ciTargetName?: string; ciTargetName?: string;
} }
const cachePath = join(projectGraphCacheDirectory, 'playwright.hash');
const targetsCache = readTargetsCache();
type PlaywrightTargets = Pick<ProjectConfiguration, 'targets' | 'metadata'>; type PlaywrightTargets = Pick<ProjectConfiguration, 'targets' | 'metadata'>;
function readTargetsCache(): Record<string, PlaywrightTargets> { function readTargetsCache(
cachePath: string
): Record<string, PlaywrightTargets> {
return existsSync(cachePath) ? readJsonFile(cachePath) : {}; return existsSync(cachePath) ? readJsonFile(cachePath) : {};
} }
function writeTargetsToCache() { function writeTargetsToCache(
const oldCache = readTargetsCache(); cachePath: string,
writeJsonFile(cachePath, { results: Record<string, PlaywrightTargets>
...readTargetsCache, ) {
targetsCache, writeJsonFile(cachePath, results);
});
} }
export const createDependencies: CreateDependencies = () => { const playwrightConfigGlob = '**/playwright.config.{js,ts,cjs,cts,mjs,mts}';
writeTargetsToCache(); export const createNodesV2: CreateNodesV2<PlaywrightPluginOptions> = [
return []; playwrightConfigGlob,
}; async (configFilePaths, options, context) => {
const optionsHash = hashObject(options);
const cachePath = join(
projectGraphCacheDirectory,
`playwright-${optionsHash}.hash`
);
const targetsCache = readTargetsCache(cachePath);
try {
return await createNodesFromFiles(
(configFile, options, context) =>
createNodesInternal(configFile, options, context, targetsCache),
configFilePaths,
options,
context
);
} finally {
writeTargetsToCache(cachePath, targetsCache);
}
},
];
/**
* @deprecated This is replaced with {@link createNodesV2}. Update your plugin to export its own `createNodesV2` function that wraps this one instead.
* This function will change to the v2 function in Nx 20.
*/
export const createNodes: CreateNodes<PlaywrightPluginOptions> = [ export const createNodes: CreateNodes<PlaywrightPluginOptions> = [
'**/playwright.config.{js,ts,cjs,cts,mjs,mts}', playwrightConfigGlob,
async (configFilePath, options, context) => { async (configFile, options, context) => {
logger.warn(
'`createNodes` is deprecated. Update your plugin to utilize createNodesV2 instead. In Nx 20, this will change to the createNodesV2 API.'
);
return createNodesInternal(configFile, options, context, {});
},
];
async function createNodesInternal(
configFilePath: string,
options: PlaywrightPluginOptions,
context: CreateNodesContext,
targetsCache: Record<string, PlaywrightTargets>
) {
const projectRoot = dirname(configFilePath); const projectRoot = dirname(configFilePath);
// Do not create a project if package.json and project.json isn't there. // Do not create a project if package.json and project.json isn't there.
@ -93,8 +129,7 @@ export const createNodes: CreateNodes<PlaywrightPluginOptions> = [
}, },
}, },
}; };
}, }
];
async function buildPlaywrightTargets( async function buildPlaywrightTargets(
configFilePath: string, configFilePath: string,