Skip to content
167 changes: 167 additions & 0 deletions e2e/nx-plugin-e2e/tests/plugin-derive-config.e2e.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
import { type Tree, writeJson } from '@nx/devkit';
import path from 'node:path';
import { readProjectConfiguration } from 'nx/src/generators/utils/project-configuration';
import { afterEach, expect } from 'vitest';
import { generateCodePushupConfig } from '@code-pushup/nx-plugin';
import {
generateProject,
generateWorkspaceAndProject,
materializeTree,
nxShowProjectJson,
nxTargetProject,
registerPluginInWorkspace,
} from '@code-pushup/test-nx-utils';
import { E2E_ENVIRONMENTS_DIR, TEST_OUTPUT_DIR } from '@code-pushup/test-utils';

describe('nx-plugin-derived-config', () => {
let root: string;
let tree: Tree;
const projectName = 'pkg';
const testFileDir = path.join(
E2E_ENVIRONMENTS_DIR,
nxTargetProject(),
TEST_OUTPUT_DIR,
'plugin-create-nodes',
);

beforeEach(async () => {
tree = await generateWorkspaceAndProject();
registerPluginInWorkspace(tree, '@code-pushup/nx-plugin');
await generateProject(tree, projectName);
root = readProjectConfiguration(tree, projectName).root;
generateCodePushupConfig(tree, root);
});

afterEach(async () => {
// await teardownTestFolder(testFileDir);
});

it('should derive config from project.json', async () => {
const cwd = path.join(testFileDir, 'project-config');
const projectJsonPath = path.join('libs', projectName, 'project.json');
const packageJsonPath = path.join('libs', projectName, 'package.json');
tree.delete(projectJsonPath);
tree.delete(packageJsonPath);
writeJson(tree, projectJsonPath, {
root,
name: projectName,
targets: {
'code-pushup': {
executor: `@code-pushup/nx-plugin:cli`,
options: {
'persist.filename': 'my-report',
},
},
},
});
await materializeTree(tree, cwd);

const { code, projectJson } = await nxShowProjectJson(cwd, projectName);
expect(code).toBe(0);

expect(projectJson.targets).toStrictEqual(
expect.objectContaining({
'code-pushup': {
configurations: {},
executor: `@code-pushup/nx-plugin:cli`,
options: {
'persist.filename': 'my-report',
},
parallelism: true,
},
}),
);
});

it('should derive config from package.json', async () => {
const cwd = path.join(testFileDir, 'package-config');
const projectJsonPath = path.join('libs', projectName, 'project.json');
const packageJsonPath = path.join('libs', projectName, 'package.json');
tree.delete(projectJsonPath);
tree.delete(packageJsonPath);
writeJson(tree, packageJsonPath, {
name: `@code-pushup/${projectName}`,
nx: {
root,
name: projectName,
targets: {
'code-pushup': {
executor: `@code-pushup/nx-plugin:cli`,
options: {
'persist.filename': 'my-report',
},
},
},
},
});
await materializeTree(tree, cwd);

const { code, projectJson } = await nxShowProjectJson(cwd, projectName);
expect(code).toBe(0);

expect(projectJson.targets).toStrictEqual(
expect.objectContaining({
'code-pushup': {
configurations: {},
executor: `@code-pushup/nx-plugin:cli`,
options: {
'persist.filename': 'my-report',
},
parallelism: true,
},
}),
);
});

it('should derive config from mixed', async () => {
const cwd = path.join(testFileDir, 'mixed-config');
const projectJsonPath = path.join('libs', projectName, 'project.json');
const packageJsonPath = path.join('libs', projectName, 'package.json');

writeJson(tree, projectJsonPath, {
root,
name: projectName,
targets: {
'code-pushup': {
executor: `@code-pushup/nx-plugin:cli`,
options: {
'persist.filename': 'my-report',
},
},
},
});
writeJson(tree, packageJsonPath, {
name: `@code-pushup/${projectName}`,
nx: {
root,
name: projectName,
targets: {
'code-pushup': {
executor: `@code-pushup/nx-plugin:cli`,
options: {
'persist.outputPath': 'my-dir',
},
},
},
},
});
await materializeTree(tree, cwd);

const { code, projectJson } = await nxShowProjectJson(cwd, projectName);
expect(code).toBe(0);

expect(projectJson.targets).toStrictEqual(
expect.objectContaining({
'code-pushup': {
configurations: {},
executor: `@code-pushup/nx-plugin:cli`,
options: {
'persist.filename': 'my-report',
'persist.outputPath': 'my-dir',
},
parallelism: true,
},
}),
);
});
});
40 changes: 35 additions & 5 deletions packages/nx-plugin/src/plugin/plugin.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
import type {
CreateNodes,
CreateNodesContext,
CreateNodesResult,
import {
type CreateNodes,
type CreateNodesContext,
type CreateNodesResult,
type CreateNodesV2,
createNodesFromFiles,
} from '@nx/devkit';
import { PROJECT_JSON_FILE_NAME } from '../internal/constants.js';
import { createTargets } from './target/targets.js';
import type { CreateNodesOptions } from './types.js';
import { normalizedCreateNodesContext } from './utils.js';

// name has to be "createNodes" to get picked up by Nx
/** Create the nodes for a V1 Plugin. The name `createNodes` is required by Nx in order to be picked up as a plugin. */
export const createNodes: CreateNodes = [
`**/${PROJECT_JSON_FILE_NAME}`,
async (
Expand All @@ -32,3 +34,31 @@ export const createNodes: CreateNodes = [
};
},
];

/** Create the nodes for a V2 Plugin. The name `createNodesV2` is required by Nx in order to be picked up as a plugin. */
export const createNodesV2: CreateNodesV2 = [
`**/${PROJECT_JSON_FILE_NAME}`,
async (configFiles, options, context) =>
createNodesFromFiles(
async (globMatchingFile, internalOptions) => {
const parsedCreateNodesOptions = internalOptions as CreateNodesOptions;

const normalizedContext = await normalizedCreateNodesContext(
context,
globMatchingFile,
parsedCreateNodesOptions,
);

return {
projects: {
[normalizedContext.projectRoot]: {
targets: await createTargets(normalizedContext),
},
},
};
},
configFiles,
options,
context,
),
];
Loading
Loading