Skip to content

Commit

Permalink
fix(testing): handle more complex projects for react component testing (
Browse files Browse the repository at this point in the history
#11725)

* fix(testing): use @nrwl/web:webpack utils to generate a more robust webpack config

fixes: #11372

* fix(testing): do not overwrite existing component test

* fix(testing): add component-test to cacheable operations

* chore(testing): address pr feedback
  • Loading branch information
barbados-clemens authored Aug 30, 2022
1 parent 7c83135 commit c7249db
Show file tree
Hide file tree
Showing 23 changed files with 1,585 additions and 286 deletions.
7 changes: 6 additions & 1 deletion docs/generated/packages/react.json
Original file line number Diff line number Diff line change
Expand Up @@ -1207,7 +1207,7 @@
"name": "cypress-component-configuration",
"factory": "./src/generators/cypress-component-configuration/cypress-component-configuration#cypressComponentConfigGenerator",
"schema": {
"$schema": "http://json-schema.org/schema",
"$schema": "https://json-schema.org/schema",
"cli": "nx",
"$id": "NxReactCypressComponentTestConfiguration",
"title": "Add Cypress component testing",
Expand All @@ -1230,6 +1230,11 @@
"$default": { "$source": "projectName" },
"x-prompt": "What project should we add Cypress component testing to?"
},
"buildTarget": {
"type": "string",
"description": "A build target used to configure Cypress component testing in the format of `project:target[:configuration]`. The build target should be from a React app. If not provided we will try to infer it from your projects usage.",
"pattern": "^[^:\\s]+:[^:\\s]+(:\\S+)?$"
},
"generateTests": {
"type": "boolean",
"description": "Generate default component tests for existing components in the project",
Expand Down
27 changes: 24 additions & 3 deletions e2e/react/src/cypress-component-tests.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { newProject, runCLI, uniq } from '../../utils';
import { createFile, newProject, runCLI, uniq, updateFile } from '../../utils';

describe('React Cypress Component Tests', () => {
beforeAll(() => newProject());
Expand All @@ -17,14 +17,35 @@ describe('React Cypress Component Tests', () => {
);
}, 1000000);

it('should successfully test react app', () => {
it('should successfully test react lib', () => {
const libName = uniq('cy-react-lib');
const appName = uniq('cy-react-app-target');
runCLI(`generate @nrwl/react:app ${appName} --no-interactive`);
runCLI(`generate @nrwl/react:lib ${libName} --component --no-interactive`);
runCLI(
`generate @nrwl/react:setup-tailwind --project=${libName} --no-interactive`
);
runCLI(
`generate @nrwl/react:component fancy-component --project=${libName} --no-interactive`
);
createFile(
`libs/${libName}/src/styles.css`,
`
@tailwind components;
@tailwind base;
@tailwind utilities;
`
);
updateFile(
`libs/${libName}/src/lib/fancy-component/fancy-component.tsx`,
(content) => {
return `
import '../../styles.css';
${content}`;
}
);
runCLI(
`generate @nrwl/react:cypress-component-configuration --project=${libName} --generate-tests`
`generate @nrwl/react:cypress-component-configuration --project=${libName} --build-target=${appName}:build --generate-tests`
);
expect(runCLI(`component-test ${libName} --no-watch`)).toContain(
'All specs passed!'
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,14 @@
// mock so we can test multiple versions
jest.mock('@nrwl/cypress/src/utils/cypress-version');

// mock bc the nxE2EPreset uses fs for path normalization
jest.mock('fs', () => {
return {
...jest.requireActual('fs'),
lstatSync: jest.fn(() => ({
isDirectory: jest.fn(() => true),
})),
};
});
import { installedCypressVersion } from '@nrwl/cypress/src/utils/cypress-version';
import {
joinPathFragments,
Expand All @@ -13,6 +21,7 @@ import {
writeJson,
} from '@nrwl/devkit';
import { createTreeWithEmptyV1Workspace } from '@nrwl/devkit/testing';
import { lstatSync } from 'fs';
import { E2eMigrator } from './e2e.migrator';
import { MigrationProjectConfiguration } from './types';

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -562,7 +562,7 @@ export class E2eMigrator extends ProjectMigrator<SupportedTargets> {
}

private updateCypress10ConfigFile(configFilePath: string): void {
this.cypressPreset = nxE2EPreset(this.project.newRoot);
this.cypressPreset = nxE2EPreset(configFilePath);

const fileContent = this.tree.read(configFilePath, 'utf-8');
let sourceFile = tsquery.ast(fileContent);
Expand Down
6 changes: 6 additions & 0 deletions packages/cypress/migrations.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,12 @@
"version": "12.8.0-beta.0",
"description": "Remove Typescript Preprocessor Plugin",
"factory": "./src/migrations/update-12-8-0/remove-typescript-plugin"
},
"update-cypress-configs-preset": {
"cli": "nx",
"version": "14.6.1-beta.0",
"description": "Change Cypress e2e and component testing presets to use __filename instead of __dirname and include a devServerTarget for component testing.",
"factory": "./src/migrations/update-14-6-1/update-cypress-configs-presets"
}
},
"packageJsonUpdates": {
Expand Down
12 changes: 9 additions & 3 deletions packages/cypress/plugins/cypress-preset.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { workspaceRoot } from '@nrwl/devkit';
import { join, relative } from 'path';
import { dirname, join, relative } from 'path';
import { lstatSync } from 'fs';

interface BaseCypressPreset {
videosFolder: string;
Expand All @@ -9,8 +10,13 @@ interface BaseCypressPreset {
}

export function nxBaseCypressPreset(pathToConfig: string): BaseCypressPreset {
const projectPath = relative(workspaceRoot, pathToConfig);
const offset = relative(pathToConfig, workspaceRoot);
// prevent from placing path outside the root of the workspace
// if they pass in a file or directory
const normalizedPath = lstatSync(pathToConfig).isDirectory()
? pathToConfig
: dirname(pathToConfig);
const projectPath = relative(workspaceRoot, normalizedPath);
const offset = relative(normalizedPath, workspaceRoot);
const videosFolder = join(offset, 'dist', 'cypress', projectPath, 'videos');
const screenshotsFolder = join(
offset,
Expand Down
3 changes: 2 additions & 1 deletion packages/cypress/src/executors/cypress/cypress.impl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,8 @@ export default async function cypressExecutor(
context: ExecutorContext
) {
options = normalizeOptions(options, context);

// this is used by cypress component testing presets to build the executor contexts with the correct configuration options.
process.env.NX_CYPRESS_TARGET_CONFIGURATION = context.configurationName;
let success;

for await (const baseUrl of startDevServer(options, context)) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import {
addProjectConfiguration,
ProjectConfiguration,
readJson,
readProjectConfiguration,
Tree,
updateProjectConfiguration,
Expand Down Expand Up @@ -118,6 +119,19 @@ describe('Cypress Component Project', () => {
expect(projectConfig.targets['component-test']).toMatchSnapshot();
});

it('should update cacheable operations', async () => {
mockedInstalledCypressVersion.mockReturnValue(10);
await cypressComponentProject(tree, {
project: 'cool-lib',
skipFormat: false,
});

expect(
readJson(tree, 'nx.json').tasksRunnerOptions.default.options
.cacheableOperations
).toEqual(expect.arrayContaining(['component-test']));
});

it('should not error when rerunning on an existing project', async () => {
mockedInstalledCypressVersion.mockReturnValue(10);
tree.write('libs/cool-lib/cypress.config.ts', '');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@ import {
ProjectConfiguration,
readProjectConfiguration,
Tree,
updateJson,
updateProjectConfiguration,
NxJsonConfiguration,
} from '@nrwl/devkit';
import { installedCypressVersion } from '../../utils/cypress-version';

Expand Down Expand Up @@ -35,7 +37,7 @@ export async function cypressComponentProject(

addProjectFiles(tree, projectConfig, options);
addTargetToProject(tree, projectConfig, options);

addToCacheableOperations(tree);
if (!options.skipFormat) {
await formatFiles(tree);
}
Expand Down Expand Up @@ -87,3 +89,25 @@ function addTargetToProject(

updateProjectConfiguration(tree, options.project, projectConfig);
}

export function addToCacheableOperations(tree: Tree) {
updateJson(tree, 'nx.json', (json) => ({
...json,
tasksRunnerOptions: {
...json.tasksRunnerOptions,
default: {
...json.tasksRunnerOptions?.default,
options: {
...json.tasksRunnerOptions?.default?.options,
cacheableOperations: Array.from(
new Set([
...(json.tasksRunnerOptions?.default?.options
?.cacheableOperations ?? []),
'component-test',
])
),
},
},
},
}));
}
Loading

1 comment on commit c7249db

@vercel
Copy link

@vercel vercel bot commented on c7249db Aug 30, 2022

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-dev-nrwl.vercel.app
nx-dev-git-master-nrwl.vercel.app
nx-five.vercel.app
nx.dev

Please sign in to comment.