Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(testing): provide better error messages around component test --build-target #12886

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Expand Up @@ -5,6 +5,7 @@ import {
ProjectGraph,
readProjectConfiguration,
Tree,
updateProjectConfiguration,
} from '@nrwl/devkit';
import { createTreeWithEmptyWorkspace } from '@nrwl/devkit/testing';
import { applicationGenerator } from '../application/application';
Expand Down Expand Up @@ -158,21 +159,60 @@ describe('Cypress Component Testing Configuration', () => {
});
});

it('should throw if --build-target is invalid', async () => {
it('should throw with invalid --build-target', async () => {
await applicationGenerator(tree, {
name: 'fancy-app',
});
await libraryGenerator(tree, {
name: 'fancy-lib',
});
await expect(
cypressComponentConfiguration(tree, {
await componentGenerator(tree, {
name: 'fancy-cmp',
project: 'fancy-lib',
export: true,
});
const appConfig = readProjectConfiguration(tree, 'fancy-app');
appConfig.targets['build'].executor = 'something/else';
updateProjectConfiguration(tree, 'fancy-app', appConfig);
projectGraph = {
nodes: {
'fancy-app': {
name: 'fancy-app',
type: 'app',
data: {
...appConfig,
},
},
'fancy-lib': {
name: 'fancy-lib',
type: 'lib',
data: {
...readProjectConfiguration(tree, 'fancy-lib'),
},
},
},
dependencies: {
'fancy-app': [
{
type: DependencyType.static,
source: 'fancy-app',
target: 'fancy-lib',
},
],
},
};
await expect(async () => {
await cypressComponentConfiguration(tree, {
project: 'fancy-lib',
buildTarget: 'fancy-app:build:development',
buildTarget: 'fancy-app:build',
generateTests: false,
})
).rejects
.toThrow(`Error trying to find build configuration. Try manually specifying the build target with the --build-target flag.
Provided project? fancy-lib
Provided build target? fancy-app:build:development
Provided Executors? @nrwl/angular:webpack-browser, @angular-devkit/build-angular:browser`);
});
}).rejects.toThrowErrorMatchingInlineSnapshot(`
"Error trying to find build configuration. Try manually specifying the build target with the --build-target flag.
Provided project? fancy-lib
Provided build target? fancy-app:build
Provided Executors? @nrwl/angular:webpack-browser, @angular-devkit/build-angular:browser"
`);
});
it('should use own project config', async () => {
await applicationGenerator(tree, {
Expand Down Expand Up @@ -273,6 +313,7 @@ Provided Executors? @nrwl/angular:webpack-browser, @angular-devkit/build-angular
});
});

it('should throw if an invalid --build-target', async () => {});
it('should work with simple components', async () => {
await libraryGenerator(tree, {
name: 'my-lib',
Expand Down
22 changes: 22 additions & 0 deletions packages/cypress/src/utils/find-target-options.ts
Expand Up @@ -58,6 +58,7 @@ export async function findBuildConfig(
// attempt to find any projects with the valid config in the graph that consumes this project
return await findInGraph(tree, graph, options);
} catch (e) {
logger.error(e);
throw new Error(stripIndents`Error trying to find build configuration. Try manually specifying the build target with the --build-target flag.
Provided project? ${options.project}
Provided build target? ${options.buildTarget}
Expand All @@ -74,6 +75,27 @@ function findInTarget(
options.buildTarget
);
const projectConfig = readProjectConfiguration(tree, project);
const executorName = projectConfig?.targets?.[target]?.executor;
if (!options.validExecutorNames.has(executorName)) {
logger.error(stripIndents`NX The provided build target, ${
options.buildTarget
}, uses the '${executorName}' executor.
But only the follow executors are allowed
${Array.from(options.validExecutorNames)
.map((ve) => ` - ${ve}`)
.join('\n')}

This is most likely because the provided --build-target is not a build target for an application.
For example, the provide build target, '${options.buildTarget}' is:
- the build target for a buildable/publishable library instead of an app.
- using a different framework than expected like react library using an angular app build target.

If you do not have an app in the workspace to you can make a new app with 'nx g app' and use it just for component testing
`);
throw new Error(
'The provided --build-target does not use an executor in the allow list of executors defined.'
);
}
const foundConfig =
configuration || projectConfig?.targets?.[target]?.defaultConfiguration;

Expand Down
Expand Up @@ -4,9 +4,14 @@ import {
ProjectGraph,
readJson,
readProjectConfiguration,
readTargetOptions,
Tree,
updateProjectConfiguration,
} from '@nrwl/devkit';
import { createTreeWithEmptyV1Workspace } from '@nrwl/devkit/testing';
import {
createTreeWithEmptyV1Workspace,
createTreeWithEmptyWorkspace,
} from '@nrwl/devkit/testing';
import { Linter } from '@nrwl/linter';
import { applicationGenerator } from '../application/application';
import { componentGenerator } from '../component/component';
Expand All @@ -16,6 +21,7 @@ import { cypressComponentConfigGenerator } from './cypress-component-configurati
let projectGraph: ProjectGraph;
jest.mock('@nrwl/devkit', () => ({
...jest.requireActual<any>('@nrwl/devkit'),
readTargetOptions: jest.fn().mockImplementation(() => ({})),
createProjectGraphAsync: jest
.fn()
.mockImplementation(async () => projectGraph),
Expand All @@ -27,7 +33,7 @@ describe('React:CypressComponentTestConfiguration', () => {
ReturnType<typeof assertMinimumCypressVersion>
> = assertMinimumCypressVersion as never;
beforeEach(() => {
tree = createTreeWithEmptyV1Workspace();
tree = createTreeWithEmptyWorkspace();
});
it('should generate cypress component test config with --build-target', async () => {
mockedAssertCypressVersion.mockReturnValue();
Expand Down Expand Up @@ -271,4 +277,57 @@ describe('React:CypressComponentTestConfiguration', () => {
tree.exists('libs/some-lib/src/lib/another-cmp/another-cmp.spec.cy.js')
).toBeFalsy();
});
it('should throw error when an invalid --build-target is provided', async () => {
mockedAssertCypressVersion.mockReturnValue();
await applicationGenerator(tree, {
e2eTestRunner: 'none',
linter: Linter.EsLint,
skipFormat: true,
style: 'scss',
unitTestRunner: 'none',
name: 'my-app',
});
await libraryGenerator(tree, {
name: 'some-lib',
style: 'scss',
unitTestRunner: 'none',
linter: Linter.None,
skipFormat: false,
skipTsConfig: false,
});
const appConfig = readProjectConfiguration(tree, 'my-app');
appConfig.targets['build'].executor = 'something/else';
updateProjectConfiguration(tree, 'my-app', appConfig);
projectGraph = {
nodes: {
'my-app': {
name: 'my-app',
type: 'app',
data: {
...appConfig,
},
},
'some-lib': {
name: 'some-lib',
type: 'lib',
data: {
...readProjectConfiguration(tree, 'some-lib'),
},
},
},
dependencies: {},
};
await expect(async () => {
await cypressComponentConfigGenerator(tree, {
project: 'some-lib',
generateTests: true,
buildTarget: 'my-app:build',
});
}).rejects.toThrowErrorMatchingInlineSnapshot(`
"Error trying to find build configuration. Try manually specifying the build target with the --build-target flag.
Provided project? some-lib
Provided build target? my-app:build
Provided Executors? @nrwl/webpack:webpack"
`);
});
});
Expand Up @@ -19,7 +19,7 @@ export async function updateProjectConfig(
validExecutorNames: new Set<string>(['@nrwl/webpack:webpack']),
});

assetValidConfig(found.config);
assetValidConfig(found?.config);

const projectConfig = readProjectConfiguration(tree, options.project);
projectConfig.targets['component-test'].options = {
Expand Down