0
# Testing
1
2
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.
3
4
## Capabilities
5
6
### Storybook Integration
7
8
#### Storybook Configuration Generator
9
10
Sets up Storybook for an Angular project with automatic story generation capabilities.
11
12
```typescript { .api }
13
/**
14
* Adds Storybook configuration to an Angular project
15
* @param tree - Virtual file system tree
16
* @param options - Storybook configuration options
17
* @returns Promise resolving to callback function
18
*/
19
async function storybookConfigurationGenerator(
20
tree: Tree,
21
options: StorybookConfigurationSchema
22
): Promise<GeneratorCallback>;
23
24
interface StorybookConfigurationSchema {
25
project: string;
26
interactionTests?: boolean;
27
generateStories?: boolean;
28
linter?: 'eslint' | 'none';
29
tsConfiguration?: boolean;
30
configureStaticServe?: boolean;
31
skipFormat?: boolean;
32
ignorePaths?: string[];
33
}
34
```
35
36
**Usage Example:**
37
38
```typescript
39
import { storybookConfigurationGenerator } from "@nx/angular/generators";
40
41
await storybookConfigurationGenerator(tree, {
42
project: "my-lib",
43
interactionTests: true,
44
generateStories: true,
45
configureStaticServe: true
46
});
47
```
48
49
#### Stories Generator
50
51
Creates stories for all components declared in a project.
52
53
```typescript { .api }
54
/**
55
* Creates stories for all components in a project
56
* @param tree - Virtual file system tree
57
* @param options - Stories generation options
58
* @returns Promise resolving to callback function
59
*/
60
async function storiesGenerator(
61
tree: Tree,
62
options: StoriesSchema
63
): Promise<GeneratorCallback>;
64
65
interface StoriesSchema {
66
project: string;
67
generateCypressSpecs?: boolean;
68
cypressProject?: string;
69
ignorePaths?: string[];
70
skipFormat?: boolean;
71
}
72
```
73
74
**Usage Example:**
75
76
```typescript
77
import { storiesGenerator } from "@nx/angular/generators";
78
79
await storiesGenerator(tree, {
80
project: "ui-components",
81
generateCypressSpecs: true,
82
cypressProject: "ui-components-e2e"
83
});
84
```
85
86
#### Component Story Generator
87
88
Creates a stories file for a specific component.
89
90
```typescript { .api }
91
/**
92
* Creates a stories file for a component
93
* @param tree - Virtual file system tree
94
* @param options - Component story options
95
* @returns Promise resolving to callback function
96
*/
97
async function componentStoryGenerator(
98
tree: Tree,
99
options: ComponentStorySchema
100
): Promise<GeneratorCallback>;
101
102
interface ComponentStorySchema {
103
componentPath: string;
104
project: string;
105
componentName?: string;
106
componentFileName?: string;
107
skipFormat?: boolean;
108
}
109
```
110
111
### Cypress Component Testing
112
113
#### Cypress Component Configuration Generator
114
115
Sets up Cypress component testing for an Angular project.
116
117
```typescript { .api }
118
/**
119
* Sets up Cypress component testing for a project
120
* @param tree - Virtual file system tree
121
* @param options - Cypress component configuration options
122
* @returns Promise resolving to callback function
123
*/
124
async function cypressComponentConfigurationGenerator(
125
tree: Tree,
126
options: CypressComponentConfigurationSchema
127
): Promise<GeneratorCallback>;
128
129
interface CypressComponentConfigurationSchema {
130
project: string;
131
buildTarget?: string;
132
skipFormat?: boolean;
133
bundler?: 'vite' | 'webpack';
134
}
135
```
136
137
**Usage Example:**
138
139
```typescript
140
import { cypressComponentConfigurationGenerator } from "@nx/angular/generators";
141
142
await cypressComponentConfigurationGenerator(tree, {
143
project: "my-app",
144
buildTarget: "my-app:build",
145
bundler: "vite"
146
});
147
```
148
149
#### Component Test Generator
150
151
Creates a Cypress component test file for a specific component.
152
153
```typescript { .api }
154
/**
155
* Creates a Cypress component test file for a component
156
* @param tree - Virtual file system tree
157
* @param options - Component test options
158
* @returns Promise resolving to callback function
159
*/
160
async function componentTestGenerator(
161
tree: Tree,
162
options: ComponentTestSchema
163
): Promise<GeneratorCallback>;
164
165
interface ComponentTestSchema {
166
project: string;
167
componentName: string;
168
componentPath: string;
169
componentFileName?: string;
170
skipFormat?: boolean;
171
}
172
```
173
174
**Usage Example:**
175
176
```typescript
177
import { componentTestGenerator } from "@nx/angular/generators";
178
179
await componentTestGenerator(tree, {
180
project: "my-app",
181
componentName: "UserProfile",
182
componentPath: "src/app/user-profile/user-profile.component.ts"
183
});
184
```
185
186
### Component Testing Preset
187
188
The component testing preset provides pre-configured Cypress settings optimized for Angular component testing within Nx workspaces.
189
190
```typescript { .api }
191
/**
192
* Angular Nx preset for Cypress Component Testing
193
* @param pathToConfig - Path to the Cypress configuration file
194
* @param options - Optional preset configuration
195
* @returns Cypress configuration object
196
*/
197
function nxComponentTestingPreset(
198
pathToConfig: string,
199
options?: NxComponentTestingPresetOptions
200
): CypressConfig;
201
202
interface NxComponentTestingPresetOptions {
203
buildTarget?: string;
204
ctViteConfig?: string;
205
}
206
207
interface CypressConfig {
208
component: {
209
devServer: {
210
framework: string;
211
bundler: string;
212
options?: {
213
projectConfig?: any;
214
};
215
};
216
specPattern: string;
217
indexHtmlFile?: string;
218
};
219
}
220
```
221
222
**Usage Example:**
223
224
```typescript
225
// cypress.config.ts
226
import { nxComponentTestingPreset } from "@nx/angular/plugins/component-testing";
227
228
export default nxComponentTestingPreset(__filename, {
229
buildTarget: "my-app:build"
230
});
231
```
232
233
### Testing Workflow Examples
234
235
#### Basic Storybook Setup
236
237
```typescript
238
// Set up Storybook for a library
239
await storybookConfigurationGenerator(tree, {
240
project: "ui-components",
241
configureCypress: true,
242
generateStories: true,
243
standaloneConfig: true
244
});
245
246
// Generate stories for all components
247
await storiesGenerator(tree, {
248
project: "ui-components",
249
generateCypressSpecs: true
250
});
251
```
252
253
#### Component Testing Setup
254
255
```typescript
256
// Configure Cypress component testing
257
await cypressComponentConfigurationGenerator(tree, {
258
project: "my-app",
259
buildTarget: "my-app:build",
260
bundler: "vite"
261
});
262
263
// Create component test for specific component
264
await componentTestGenerator(tree, {
265
project: "my-app",
266
componentName: "HeaderComponent",
267
componentPath: "src/app/header/header.component.ts"
268
});
269
```
270
271
#### Generated Test File Example
272
273
When using the component test generator, it creates files like:
274
275
```typescript
276
// header.component.cy.ts
277
import { HeaderComponent } from './header.component';
278
279
describe('HeaderComponent', () => {
280
it('should render', () => {
281
cy.mount(HeaderComponent, {
282
componentProperties: {
283
title: 'Test Title'
284
}
285
});
286
287
cy.get('[data-cy=header-title]')
288
.should('contain.text', 'Test Title');
289
});
290
291
it('should handle click events', () => {
292
cy.mount(HeaderComponent, {
293
componentProperties: {
294
onMenuClick: cy.stub().as('menuClickStub')
295
}
296
});
297
298
cy.get('[data-cy=menu-button]').click();
299
cy.get('@menuClickStub').should('have.been.called');
300
});
301
});
302
```
303
304
#### Generated Story File Example
305
306
When using the stories generator, it creates files like:
307
308
```typescript
309
// header.component.stories.ts
310
import type { Meta, StoryObj } from '@storybook/angular';
311
import { HeaderComponent } from './header.component';
312
313
const meta: Meta<HeaderComponent> = {
314
title: 'Components/Header',
315
component: HeaderComponent,
316
parameters: {
317
layout: 'fullscreen'
318
},
319
argTypes: {
320
title: {
321
control: 'text'
322
},
323
showMenu: {
324
control: 'boolean'
325
}
326
}
327
};
328
329
export default meta;
330
type Story = StoryObj<HeaderComponent>;
331
332
export const Default: Story = {
333
args: {
334
title: 'My Application',
335
showMenu: true
336
}
337
};
338
339
export const WithoutMenu: Story = {
340
args: {
341
title: 'My Application',
342
showMenu: false
343
}
344
};
345
346
export const LongTitle: Story = {
347
args: {
348
title: 'My Very Long Application Title That Might Wrap',
349
showMenu: true
350
}
351
};
352
```
353
354
## Types
355
356
```typescript { .api }
357
interface Tree {
358
read(filePath: string): Buffer | null;
359
write(filePath: string, content: Buffer | string): void;
360
exists(filePath: string): boolean;
361
delete(filePath: string): void;
362
rename(from: string, to: string): void;
363
children(dirPath: string): string[];
364
isFile(filePath: string): boolean;
365
}
366
367
interface GeneratorCallback {
368
(): void | Promise<void>;
369
}
370
371
type Linter = 'eslint' | 'none';
372
type Bundler = 'vite' | 'webpack';
373
374
interface NxComponentTestingPresetOptions {
375
buildTarget?: string;
376
ctViteConfig?: string;
377
}
378
379
interface CypressConfig {
380
component: {
381
devServer: {
382
framework: string;
383
bundler: string;
384
options?: any;
385
};
386
specPattern: string;
387
indexHtmlFile?: string;
388
};
389
}
390
```