Skip to content

Commit

Permalink
feat(nx-plugin): update e2e tests to use local-registry and be simpler (
Browse files Browse the repository at this point in the history
  • Loading branch information
FrozenPandaz authored Jun 21, 2023
1 parent db3763e commit b7d05a0
Show file tree
Hide file tree
Showing 8 changed files with 149 additions and 63 deletions.
13 changes: 10 additions & 3 deletions e2e/plugin/src/nx-plugin.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,9 @@ describe('Nx Plugin', () => {
it('should be able to generate a Nx Plugin ', async () => {
const plugin = uniq('plugin');

runCLI(`generate @nx/plugin:plugin ${plugin} --linter=eslint`);
runCLI(
`generate @nx/plugin:plugin ${plugin} --linter=eslint --e2eTestRunner=jest --publishable`
);
const lintResults = runCLI(`lint ${plugin}`);
expect(lintResults).toContain('All files pass linting.');

Expand All @@ -45,6 +47,7 @@ describe('Nx Plugin', () => {
expect(project).toMatchObject({
tags: [],
});
runCLI(`e2e ${plugin}-e2e`);
}, 90000);

it('should be able to generate a migration', async () => {
Expand Down Expand Up @@ -405,9 +408,11 @@ describe('Nx Plugin', () => {
it('should be able to generate a create-package plugin ', async () => {
const plugin = uniq('plugin');
const createAppName = `create-${plugin}-app`;
runCLI(`generate @nx/plugin:plugin ${plugin}`);
runCLI(
`generate @nx/plugin:create-package ${createAppName} --project=${plugin}`
`generate @nx/plugin:plugin ${plugin} --e2eTestRunner jest --publishable`
);
runCLI(
`generate @nx/plugin:create-package ${createAppName} --project=${plugin} --e2eProject=${plugin}-e2e`
);

const buildResults = runCLI(`build ${createAppName}`);
Expand All @@ -418,6 +423,8 @@ describe('Nx Plugin', () => {
`libs/${createAppName}`,
`dist/libs/${createAppName}/bin/index.js`
);

runCLI(`e2e ${plugin}-e2e`);
});

it('should throw an error when run create-package for an invalid plugin ', async () => {
Expand Down
9 changes: 4 additions & 5 deletions packages/js/src/generators/setup-verdaccio/files/config.yml
Original file line number Diff line number Diff line change
@@ -1,10 +1,6 @@
# path to a directory with all packages
storage: ../tmp/local-registry/storage

auth:
htpasswd:
file: ./htpasswd

# a list of other known repositories we can talk to
uplinks:
npmjs:
Expand All @@ -26,4 +22,7 @@ packages:
logs:
type: stdout
format: pretty
level: http
level: warn

publish:
allow_offline: true # set offline to true to allow publish offline
1 change: 0 additions & 1 deletion packages/js/src/generators/setup-verdaccio/files/htpasswd

This file was deleted.

10 changes: 10 additions & 0 deletions packages/plugin/src/generators/create-package/create-package.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,16 @@ import {
runTasksInSerial,
joinPathFragments,
getProjects,
detectPackageManager,
getPackageManagerCommand,
} from '@nx/devkit';
import { libraryGenerator as jsLibraryGenerator } from '@nx/js';
import { nxVersion } from 'nx/src/utils/versions';
import generatorGenerator from '../generator/generator';
import { CreatePackageSchema } from './schema';
import { NormalizedSchema, normalizeSchema } from './utils/normalize-schema';
import { hasGenerator } from '../../utils/has-generator';
import { join } from 'path';

export async function createPackageGenerator(
host: Tree,
Expand Down Expand Up @@ -157,6 +160,11 @@ function addE2eProject(host: Tree, options: NormalizedSchema) {
host,
options.e2eProject
);
const projectConfiguration = readProjectConfiguration(host, options.project);
const { name: pluginPackageName } = readJson(
host,
join(projectConfiguration.root, 'package.json')
);

generateFiles(
host,
Expand All @@ -165,6 +173,8 @@ function addE2eProject(host: Tree, options: NormalizedSchema) {
{
pluginName: options.project,
cliName: options.name,
packageManagerCommands: getPackageManagerCommand('npm'),
pluginPackageName,
tmpl: '',
}
);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,31 +1,56 @@
import {
checkFilesExist,
removeTmpProject,
tmpFolder,
uniq,
} from '@nx/plugin/testing';
import { execSync } from 'child_process';
import { join } from 'path';

describe('<%= cliName %> e2e', () => {
let project: string;
beforeAll(async () => {
// create a workspace with cli
project = uniq('<%= cliName %>');
execSync(`npx <%= cliName %>@1.0.0 ${project}`, {
cwd: tmpFolder(),
env: process.env,
});
}, 240_000);
import { join, dirname } from 'path';
import { mkdirSync, rmSync } from 'fs';

describe('<%= cliName %>', () => {
let projectDirectory: string;

afterAll(() => {
// Remove the generated project from the file system
removeTmpProject(project);
// Cleanup the test project
rmSync(projectDirectory, {
recursive: true,
force: true,
});
});

it('should create project using <%= cliName %>', () => {
expect(() =>
checkFilesExist(join(tmpFolder(), project, 'package.json'))
).not.toThrow();

it('should be installed', () => {
projectDirectory = createTestProject();

// npm ls will fail if the package is not installed properly
execSync('<%= packageManagerCommands.list %> <%= pluginPackageName %>', {
cwd: projectDirectory,
stdio: 'inherit',
});
});
});

/**
* Creates a test project with create-nx-workspace and installs the plugin
* @returns The directory where the test project was created
*/
function createTestProject(extraArgs: string = '') {
const projectName = 'test-project';
const projectDirectory = join(process.cwd(), 'tmp', projectName);

// Ensure projectDirectory is empty
rmSync(projectDirectory, {
recursive: true,
force: true,
});
mkdirSync(dirname(projectDirectory), {
recursive: true,
});

execSync(
`<%= packageManagerCommands.exec %> --yes <%= cliName %>@e2e ${projectName} ${extraArgs}`,
{
cwd: dirname(projectDirectory),
stdio: 'inherit',
env: process.env,
}
);
console.log(`Created test project in "${projectDirectory}"`);

return projectDirectory;
}
4 changes: 4 additions & 0 deletions packages/plugin/src/generators/e2e-project/e2e.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {
readProjectConfiguration,
readJson,
getProjects,
writeJson,
} from '@nx/devkit';
import { createTreeWithEmptyWorkspace } from '@nx/devkit/testing';
import { e2eProjectGenerator } from './e2e';
Expand All @@ -18,6 +19,9 @@ describe('NxPlugin e2e-project Generator', () => {
root: 'libs/my-plugin',
targets: {},
});
writeJson(tree, 'libs/my-plugin/package.json', {
name: 'my-plugin',
});
});

it('should validate the plugin name', async () => {
Expand Down
17 changes: 14 additions & 3 deletions packages/plugin/src/generators/e2e-project/e2e.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,12 @@ import {
formatFiles,
generateFiles,
GeneratorCallback,
getPackageManagerCommand,
getWorkspaceLayout,
joinPathFragments,
names,
offsetFromRoot,
readJson,
readProjectConfiguration,
runTasksInSerial,
updateProjectConfiguration,
Expand All @@ -27,15 +29,14 @@ interface NormalizedSchema extends Schema {
projectRoot: string;
projectName: string;
pluginPropertyName: string;
npmScope: string;
linter: Linter;
}

function normalizeOptions(host: Tree, options: Schema): NormalizedSchema {
const { layoutDirectory, projectDirectory } = extractLayoutDirectory(
options.projectDirectory
);
const { npmScope, appsDir: defaultAppsDir } = getWorkspaceLayout(host);
const { appsDir: defaultAppsDir } = getWorkspaceLayout(host);
const appsDir = layoutDirectory ?? defaultAppsDir;

const projectName = options.rootProject ? 'e2e' : `${options.pluginName}-e2e`;
Expand All @@ -53,7 +54,6 @@ function normalizeOptions(host: Tree, options: Schema): NormalizedSchema {
linter: options.linter ?? Linter.EsLint,
pluginPropertyName,
projectRoot,
npmScope,
};
}

Expand All @@ -66,10 +66,21 @@ function validatePlugin(host: Tree, pluginName: string) {
}

function addFiles(host: Tree, options: NormalizedSchema) {
const projectConfiguration = readProjectConfiguration(
host,
options.pluginName
);
const { name: pluginPackageName } = readJson(
host,
join(projectConfiguration.root, 'package.json')
);

generateFiles(host, join(__dirname, './files'), options.projectRoot, {
...options,
tmpl: '',
rootTsConfigPath: getRelativePathToRootTsConfig(host, options.projectRoot),
packageManagerCommands: getPackageManagerCommand('npm'),
pluginPackageName,
});
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,35 +1,66 @@
import {
checkFilesExist,
ensureNxProject,
runNxCommandAsync,
runNxCommand,
} from '@nx/plugin/testing';

describe('<%= pluginName %> e2e', () => {
// Setting up individual workspaces per
// test can cause e2e runs to take a long time.
// For this reason, we recommend each suite only
// consumes 1 workspace. The tests should each operate
// on a unique project in the workspace, such that they
// are not dependant on one another.
import { execSync } from 'child_process';
import { join, dirname } from 'path';
import { mkdirSync, rmSync } from 'fs';

describe('<%= pluginName %>', () => {
let projectDirectory: string;

beforeAll(() => {
ensureNxProject('<%= npmPackageName %>', '<%= pluginOutputPath %>');
projectDirectory = createTestProject();

// The plugin has been built and published to a local registry in the jest globalSetup
// Install the plugin built with the latest source code into the test repo
execSync(`<%= packageManagerCommands.install %> <%= pluginPackageName %>@e2e`, {
cwd: projectDirectory,
stdio: 'inherit',
env: process.env,
});
});

afterAll(async () => {
// `nx reset` kills the daemon, and performs
// some work which can help clean up e2e leftovers
await runNxCommandAsync('reset');
afterAll(() => {
// Cleanup the test project
rmSync(projectDirectory, {
recursive: true,
force: true,
});
});


// Add some tests here to check that your plugin functionality works as expected.
// A sample test is included below to give you some ideas.
xit('should be able to build generated projects', async () => {
const name = 'proj';
const generator = 'PLACEHOLDER';
await runNxCommandAsync(`generate <%= npmPackageName %>:${generator} --name ${name}`);
expect(() => runNxCommand('build ${proj}')).not.toThrow();
expect(() => checkFilesExist(`dist/${name}/index.js`)).not.toThrow();
it('should be installed', () => {
// npm ls will fail if the package is not installed properly
execSync('<%= packageManagerCommands.list %> <%= pluginPackageName %>', {
cwd: projectDirectory,
stdio: 'inherit',
});
});
});

/**
* Creates a test project with create-nx-workspace and installs the plugin
* @returns The directory where the test project was created
*/
function createTestProject() {
const projectName = 'test-project';
const projectDirectory = join(process.cwd(), 'tmp', projectName);

// Ensure projectDirectory is empty
rmSync(projectDirectory, {
recursive: true,
force: true,
});
mkdirSync(dirname(projectDirectory), {
recursive: true,
});

execSync(
`<%= packageManagerCommands.exec %> --yes create-nx-workspace@latest ${projectName} --preset empty --no-nxCloud --no-interactive`,
{
cwd: dirname(projectDirectory),
stdio: 'inherit',
env: process.env,
}
);
console.log(`Created test project in "${projectDirectory}"`);

return projectDirectory;
}

1 comment on commit b7d05a0

@vercel
Copy link

@vercel vercel bot commented on b7d05a0 Jun 21, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

nx-dev – ./

nx-five.vercel.app
nx-dev-nrwl.vercel.app
nx-dev-git-master-nrwl.vercel.app
nx.dev

Please sign in to comment.