Comprehensive Angular plugin for Nx workspaces providing executors, generators, and utilities for managing Angular applications and libraries.
90
Testing integration in @nx/angular provides comprehensive support for Cypress component testing and Storybook development workflows, enabling developers to test Angular components in isolation and document component APIs.
Sets up Storybook for an Angular project with automatic story generation capabilities.
/**
* Adds Storybook configuration to an Angular project
* @param tree - Virtual file system tree
* @param options - Storybook configuration options
* @returns Promise resolving to callback function
*/
async function storybookConfigurationGenerator(
tree: Tree,
options: StorybookConfigurationSchema
): Promise<GeneratorCallback>;
interface StorybookConfigurationSchema {
project: string;
interactionTests?: boolean;
generateStories?: boolean;
linter?: 'eslint' | 'none';
tsConfiguration?: boolean;
configureStaticServe?: boolean;
skipFormat?: boolean;
ignorePaths?: string[];
}Usage Example:
import { storybookConfigurationGenerator } from "@nx/angular/generators";
await storybookConfigurationGenerator(tree, {
project: "my-lib",
interactionTests: true,
generateStories: true,
configureStaticServe: true
});Creates stories for all components declared in a project.
/**
* Creates stories for all components in a project
* @param tree - Virtual file system tree
* @param options - Stories generation options
* @returns Promise resolving to callback function
*/
async function storiesGenerator(
tree: Tree,
options: StoriesSchema
): Promise<GeneratorCallback>;
interface StoriesSchema {
project: string;
generateCypressSpecs?: boolean;
cypressProject?: string;
ignorePaths?: string[];
skipFormat?: boolean;
}Usage Example:
import { storiesGenerator } from "@nx/angular/generators";
await storiesGenerator(tree, {
project: "ui-components",
generateCypressSpecs: true,
cypressProject: "ui-components-e2e"
});Creates a stories file for a specific component.
/**
* Creates a stories file for a component
* @param tree - Virtual file system tree
* @param options - Component story options
* @returns Promise resolving to callback function
*/
async function componentStoryGenerator(
tree: Tree,
options: ComponentStorySchema
): Promise<GeneratorCallback>;
interface ComponentStorySchema {
componentPath: string;
project: string;
componentName?: string;
componentFileName?: string;
skipFormat?: boolean;
}Sets up Cypress component testing for an Angular project.
/**
* Sets up Cypress component testing for a project
* @param tree - Virtual file system tree
* @param options - Cypress component configuration options
* @returns Promise resolving to callback function
*/
async function cypressComponentConfigurationGenerator(
tree: Tree,
options: CypressComponentConfigurationSchema
): Promise<GeneratorCallback>;
interface CypressComponentConfigurationSchema {
project: string;
buildTarget?: string;
skipFormat?: boolean;
bundler?: 'vite' | 'webpack';
}Usage Example:
import { cypressComponentConfigurationGenerator } from "@nx/angular/generators";
await cypressComponentConfigurationGenerator(tree, {
project: "my-app",
buildTarget: "my-app:build",
bundler: "vite"
});Creates a Cypress component test file for a specific component.
/**
* Creates a Cypress component test file for a component
* @param tree - Virtual file system tree
* @param options - Component test options
* @returns Promise resolving to callback function
*/
async function componentTestGenerator(
tree: Tree,
options: ComponentTestSchema
): Promise<GeneratorCallback>;
interface ComponentTestSchema {
project: string;
componentName: string;
componentPath: string;
componentFileName?: string;
skipFormat?: boolean;
}Usage Example:
import { componentTestGenerator } from "@nx/angular/generators";
await componentTestGenerator(tree, {
project: "my-app",
componentName: "UserProfile",
componentPath: "src/app/user-profile/user-profile.component.ts"
});The component testing preset provides pre-configured Cypress settings optimized for Angular component testing within Nx workspaces.
/**
* Angular Nx preset for Cypress Component Testing
* @param pathToConfig - Path to the Cypress configuration file
* @param options - Optional preset configuration
* @returns Cypress configuration object
*/
function nxComponentTestingPreset(
pathToConfig: string,
options?: NxComponentTestingPresetOptions
): CypressConfig;
interface NxComponentTestingPresetOptions {
buildTarget?: string;
ctViteConfig?: string;
}
interface CypressConfig {
component: {
devServer: {
framework: string;
bundler: string;
options?: {
projectConfig?: any;
};
};
specPattern: string;
indexHtmlFile?: string;
};
}Usage Example:
// cypress.config.ts
import { nxComponentTestingPreset } from "@nx/angular/plugins/component-testing";
export default nxComponentTestingPreset(__filename, {
buildTarget: "my-app:build"
});// Set up Storybook for a library
await storybookConfigurationGenerator(tree, {
project: "ui-components",
configureCypress: true,
generateStories: true,
standaloneConfig: true
});
// Generate stories for all components
await storiesGenerator(tree, {
project: "ui-components",
generateCypressSpecs: true
});// Configure Cypress component testing
await cypressComponentConfigurationGenerator(tree, {
project: "my-app",
buildTarget: "my-app:build",
bundler: "vite"
});
// Create component test for specific component
await componentTestGenerator(tree, {
project: "my-app",
componentName: "HeaderComponent",
componentPath: "src/app/header/header.component.ts"
});When using the component test generator, it creates files like:
// header.component.cy.ts
import { HeaderComponent } from './header.component';
describe('HeaderComponent', () => {
it('should render', () => {
cy.mount(HeaderComponent, {
componentProperties: {
title: 'Test Title'
}
});
cy.get('[data-cy=header-title]')
.should('contain.text', 'Test Title');
});
it('should handle click events', () => {
cy.mount(HeaderComponent, {
componentProperties: {
onMenuClick: cy.stub().as('menuClickStub')
}
});
cy.get('[data-cy=menu-button]').click();
cy.get('@menuClickStub').should('have.been.called');
});
});When using the stories generator, it creates files like:
// header.component.stories.ts
import type { Meta, StoryObj } from '@storybook/angular';
import { HeaderComponent } from './header.component';
const meta: Meta<HeaderComponent> = {
title: 'Components/Header',
component: HeaderComponent,
parameters: {
layout: 'fullscreen'
},
argTypes: {
title: {
control: 'text'
},
showMenu: {
control: 'boolean'
}
}
};
export default meta;
type Story = StoryObj<HeaderComponent>;
export const Default: Story = {
args: {
title: 'My Application',
showMenu: true
}
};
export const WithoutMenu: Story = {
args: {
title: 'My Application',
showMenu: false
}
};
export const LongTitle: Story = {
args: {
title: 'My Very Long Application Title That Might Wrap',
showMenu: true
}
};interface Tree {
read(filePath: string): Buffer | null;
write(filePath: string, content: Buffer | string): void;
exists(filePath: string): boolean;
delete(filePath: string): void;
rename(from: string, to: string): void;
children(dirPath: string): string[];
isFile(filePath: string): boolean;
}
interface GeneratorCallback {
(): void | Promise<void>;
}
type Linter = 'eslint' | 'none';
type Bundler = 'vite' | 'webpack';
interface NxComponentTestingPresetOptions {
buildTarget?: string;
ctViteConfig?: string;
}
interface CypressConfig {
component: {
devServer: {
framework: string;
bundler: string;
options?: any;
};
specPattern: string;
indexHtmlFile?: string;
};
}Install with Tessl CLI
npx tessl i tessl/npm-nx--angularevals
scenario-1
scenario-2
scenario-3
scenario-4
scenario-5
scenario-6
scenario-7
scenario-8
scenario-9
scenario-10