Skip to content

Commit 3c684f2

Browse files
committed
cypress: add @cypress/schematic for angular
1 parent 9f1f453 commit 3c684f2

File tree

8 files changed

+150
-24
lines changed

8 files changed

+150
-24
lines changed

generators/app/__snapshots__/generator.spec.ts.snap

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -286,6 +286,8 @@ exports[`generator - app with default config should match snapshot 1`] = `
286286
"communicationSpringWebsocket": false,
287287
"cucumberTests": false,
288288
"customizeTemplatePaths": [],
289+
"cypressAudit": undefined,
290+
"cypressCoverage": undefined,
289291
"cypressTests": false,
290292
"dasherizedBaseName": "jhipster",
291293
"databaseMigration": undefined,
@@ -650,6 +652,7 @@ exports[`generator - app with default config should match snapshot 1`] = `
650652
"@angular/cli": "ANGULAR_CLI_VERSION",
651653
"@angular/common": "ANGULAR_COMMON_VERSION",
652654
"@cypress/code-coverage": "CYPRESS_CODE_COVERAGE_VERSION",
655+
"@cypress/schematic": "CYPRESS_SCHEMATIC_VERSION",
653656
"@eslint/js": "ESLINT_JS_VERSION",
654657
"@fortawesome/angular-fontawesome": "FORTAWESOME_ANGULAR_FONTAWESOME_VERSION",
655658
"@fortawesome/fontawesome-svg-core": "FORTAWESOME_FONTAWESOME_SVG_CORE_VERSION",
@@ -952,6 +955,8 @@ exports[`generator - app with gateway should match snapshot 1`] = `
952955
"communicationSpringWebsocket": false,
953956
"cucumberTests": false,
954957
"customizeTemplatePaths": [],
958+
"cypressAudit": undefined,
959+
"cypressCoverage": undefined,
955960
"cypressTests": false,
956961
"dasherizedBaseName": "jhipster",
957962
"databaseMigration": undefined,
@@ -1312,6 +1317,7 @@ exports[`generator - app with gateway should match snapshot 1`] = `
13121317
"@angular/cli": "ANGULAR_CLI_VERSION",
13131318
"@angular/common": "ANGULAR_COMMON_VERSION",
13141319
"@cypress/code-coverage": "CYPRESS_CODE_COVERAGE_VERSION",
1320+
"@cypress/schematic": "CYPRESS_SCHEMATIC_VERSION",
13151321
"@eslint/js": "ESLINT_JS_VERSION",
13161322
"@fortawesome/angular-fontawesome": "FORTAWESOME_ANGULAR_FONTAWESOME_VERSION",
13171323
"@fortawesome/fontawesome-svg-core": "FORTAWESOME_FONTAWESOME_SVG_CORE_VERSION",
@@ -1613,6 +1619,8 @@ exports[`generator - app with microservice should match snapshot 1`] = `
16131619
"communicationSpringWebsocket": false,
16141620
"cucumberTests": false,
16151621
"customizeTemplatePaths": [],
1622+
"cypressAudit": undefined,
1623+
"cypressCoverage": undefined,
16161624
"cypressTests": false,
16171625
"dasherizedBaseName": "jhipster",
16181626
"databaseMigration": undefined,

generators/base-application/types.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,7 @@ export type CommonClientServerApplication<Entity> = BaseApplication &
147147
AuthenticationProperties<Entity> &
148148
SpringBootApplication &
149149
ClientApplication &
150+
ExportApplicationPropertiesFromCommand<typeof import('../cypress/command.ts').default> &
150151
ExportApplicationPropertiesFromCommand<typeof import('../git/command.ts').default> &
151152
ExportApplicationPropertiesFromCommand<typeof import('../project-name/command.ts').default> &
152153
ApplicationProperties & {

generators/client/resources/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
},
55
"devDependencies": {
66
"@cypress/code-coverage": "3.13.9",
7+
"@cypress/schematic": "2.5.1",
78
"babel-loader": "9.2.1",
89
"babel-plugin-istanbul": "7.0.0",
910
"cypress": "13.16.1",

generators/cypress/__snapshots__/generator.spec.ts.snap

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@ exports[`generator - cypress jwt-cypressAudit(false)-angular-withAdminUi(false)-
88
".yo-rc.json": {
99
"stateCleared": "modified",
1010
},
11+
"clientRoot/angular.json": {
12+
"stateCleared": "modified",
13+
},
1114
"clientRoot/cypress.config.ts": {
1215
"stateCleared": "modified",
1316
},
@@ -156,6 +159,9 @@ exports[`generator - cypress oauth2-cypressAudit(false)-angular-withAdminUi(fals
156159
".yo-rc.json": {
157160
"stateCleared": "modified",
158161
},
162+
"angular.json": {
163+
"stateCleared": "modified",
164+
},
159165
"cypress.config.ts": {
160166
"stateCleared": "modified",
161167
},
@@ -342,6 +348,9 @@ exports[`generator - cypress session-cypressAudit(false)-angular-withAdminUi(fal
342348
".yo-rc.json": {
343349
"stateCleared": "modified",
344350
},
351+
"angular.json": {
352+
"stateCleared": "modified",
353+
},
345354
"cypress.config.ts": {
346355
"stateCleared": "modified",
347356
},

generators/cypress/command.ts

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,19 +18,23 @@
1818
*/
1919
import type { JHipsterCommandDefinition } from '../../lib/command/index.js';
2020

21-
const command: JHipsterCommandDefinition = {
22-
options: {
21+
const command = {
22+
configs: {
2323
cypressCoverage: {
2424
description: 'Enable Cypress code coverage report generation',
25-
type: Boolean,
25+
cli: {
26+
type: Boolean,
27+
},
2628
scope: 'storage',
2729
},
2830
cypressAudit: {
2931
description: 'Enable cypress-audit/lighthouse report generation',
30-
type: Boolean,
32+
cli: {
33+
type: Boolean,
34+
},
3135
scope: 'storage',
3236
},
3337
},
34-
};
38+
} as const satisfies JHipsterCommandDefinition;
3539

3640
export default command;

generators/cypress/generator.ts

Lines changed: 121 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ import { cypressEntityFiles, cypressFiles } from './files.js';
2727

2828
const { ANGULAR } = clientFrameworkTypes;
2929

30+
const WAIT_TIMEOUT = 3 * 60000;
31+
3032
export default class CypressGenerator extends BaseApplicationGenerator {
3133
async beforeQueue() {
3234
if (!this.fromBlueprint) {
@@ -67,6 +69,21 @@ export default class CypressGenerator extends BaseApplicationGenerator {
6769
return this.delegateTasksToBlueprint(() => this.prompting);
6870
}
6971

72+
get configuring() {
73+
return this.asConfiguringTaskGroup({
74+
async configureCypressOptions() {
75+
if (this.jhipsterConfigWithDefaults.cypressCoverage && this.jhipsterConfigWithDefaults.clientBundler === 'experimentalEsbuild') {
76+
this.log.warn('Code coverage for Cypress tests is not supported with the experimental ESBuild bundler.');
77+
this.jhipsterConfig.cypressCoverage = false;
78+
}
79+
},
80+
});
81+
}
82+
83+
get [BaseApplicationGenerator.CONFIGURING]() {
84+
return this.delegateTasksToBlueprint(() => this.configuring);
85+
}
86+
7087
get loading() {
7188
return this.asLoadingTaskGroup({
7289
prepareForTemplates({ application }) {
@@ -188,22 +205,99 @@ export default class CypressGenerator extends BaseApplicationGenerator {
188205
},
189206

190207
configure({ application }) {
208+
const {
209+
clientFrameworkAngular,
210+
cypressCoverage,
211+
dasherizedBaseName,
212+
devServerPort,
213+
devServerPortProxy: devServerPortE2e = devServerPort,
214+
} = application;
215+
191216
const clientPackageJson = this.createStorage(this.destinationPath(application.clientRootDir!, 'package.json'));
192217
clientPackageJson.merge({
193218
devDependencies: {
194219
'eslint-plugin-cypress': application.nodeDependencies['eslint-plugin-cypress'],
195220
},
196221
scripts: {
197-
e2e: 'npm run e2e:cypress:headed --',
198-
'e2e:headless': 'npm run e2e:cypress --',
199-
'e2e:cypress:headed': 'npm run e2e:cypress -- --headed',
222+
'ci:e2e:run': 'concurrently -k -s first -n application,e2e -c red,blue npm:ci:e2e:server:start npm:e2e:headless',
223+
'ci:e2e:dev': `concurrently -k -s first -n application,e2e -c red,blue npm:app:start npm:e2e:headless`,
224+
cypress: 'cypress open --e2e',
200225
'e2e:cypress': 'cypress run --e2e --browser chrome',
226+
'e2e:cypress:headed': 'npm run e2e:cypress -- --headed',
201227
'e2e:cypress:record': 'npm run e2e:cypress -- --record',
202-
cypress: 'cypress open --e2e',
228+
'e2e:dev': `concurrently -k -s first -n application,e2e -c red,blue npm:app:start npm:e2e`,
229+
'pree2e:headless': 'npm run ci:server:await',
230+
'e2e:headless': 'npm run e2e:cypress --',
231+
...(clientFrameworkAngular
232+
? {
233+
e2e: 'ng e2e',
234+
'e2e:devserver': `concurrently -k -s first -n backend,e2e -c red,blue npm:backend:start "npm run ci:server:await && ng run ${dasherizedBaseName}:cypress-headless${cypressCoverage ? ':instrumenter' : ''}"`,
235+
}
236+
: {
237+
e2e: 'npm run e2e:cypress:headed --',
238+
'e2e:devserver': `concurrently -k -s first -n backend,frontend,e2e -c red,yellow,blue npm:backend:start npm:start "wait-on -t ${WAIT_TIMEOUT} http-get://127.0.0.1:${devServerPortE2e} && npm run e2e:headless -- -c baseUrl=http://localhost:${devServerPortE2e}"`,
239+
}),
203240
},
204241
});
205242
},
243+
cypressSchematics({ application, source }) {
244+
const { clientFrameworkAngular, dasherizedBaseName, clientRootDir } = application;
245+
if (!clientFrameworkAngular) return;
206246

247+
source.mergeClientPackageJson?.({
248+
devDependencies: {
249+
'@cypress/schematic': null,
250+
},
251+
});
252+
this.mergeDestinationJson(`${clientRootDir}angular.json`, {
253+
projects: {
254+
[application.dasherizedBaseName]: {
255+
architect: {
256+
e2e: {
257+
builder: '@cypress/schematic:cypress',
258+
options: {
259+
devServerTarget: `${dasherizedBaseName}:serve`,
260+
watch: false,
261+
headed: true,
262+
browser: 'chrome',
263+
},
264+
configurations: {
265+
production: {
266+
devServerTarget: `${dasherizedBaseName}:serve:production`,
267+
},
268+
},
269+
},
270+
'cypress-headless': {
271+
builder: '@cypress/schematic:cypress',
272+
options: {
273+
devServerTarget: `${dasherizedBaseName}:serve`,
274+
watch: false,
275+
browser: 'chrome',
276+
},
277+
configurations: {
278+
production: {
279+
devServerTarget: `${dasherizedBaseName}:serve:production`,
280+
},
281+
},
282+
},
283+
'cypress-open': {
284+
builder: '@cypress/schematic:cypress',
285+
options: {
286+
devServerTarget: `${dasherizedBaseName}:serve`,
287+
watch: true,
288+
headless: false,
289+
},
290+
configurations: {
291+
production: {
292+
devServerTarget: `${dasherizedBaseName}:serve:production`,
293+
},
294+
},
295+
},
296+
},
297+
},
298+
},
299+
});
300+
},
207301
configureAudits({ application }) {
208302
if (!application.cypressAudit) return;
209303
const clientPackageJson = this.createStorage(this.destinationPath(application.clientRootDir!, 'package.json'));
@@ -220,7 +314,7 @@ export default class CypressGenerator extends BaseApplicationGenerator {
220314
});
221315
},
222316
configureCoverage({ application, source }) {
223-
const { cypressCoverage, clientFrameworkAngular, dasherizedBaseName } = application;
317+
const { cypressCoverage, clientFrameworkAngular, clientRootDir, dasherizedBaseName } = application;
224318
if (!cypressCoverage) return;
225319
const clientPackageJson = this.createStorage(this.destinationPath(application.clientRootDir!, 'package.json'));
226320
clientPackageJson.merge({
@@ -241,7 +335,28 @@ export default class CypressGenerator extends BaseApplicationGenerator {
241335
});
242336
if (clientFrameworkAngular) {
243337
// Add 'ng build --configuration instrumenter' support
244-
this.createStorage('angular.json').setPath(`projects.${dasherizedBaseName}.architect.build.configurations.instrumenter`, {});
338+
const e2eConfigurations = {
339+
configurations: {
340+
instrumenter: {
341+
devServerTarget: `${dasherizedBaseName}:serve:instrumenter`,
342+
},
343+
},
344+
};
345+
346+
this.mergeDestinationJson(`${clientRootDir}angular.json`, {
347+
projects: {
348+
[dasherizedBaseName]: {
349+
architect: {
350+
build: { configurations: { instrumenter: {} } },
351+
serve: { configurations: { instrumenter: { buildTarget: `${dasherizedBaseName}:build:instrumenter` } } },
352+
e2e: e2eConfigurations,
353+
'cypress-headless': e2eConfigurations,
354+
'cypress-open': e2eConfigurations,
355+
},
356+
},
357+
},
358+
});
359+
245360
source.addWebpackConfig?.({
246361
config: `targetOptions.configuration === 'instrumenter'
247362
? {

generators/java/generators/server/generator.ts

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -98,9 +98,7 @@ export default class ServerGenerator extends BaseApplicationGenerator {
9898
});
9999
},
100100
packageJsonE2eScripts({ application }) {
101-
const { devServerPort, devServerPortProxy: devServerPortE2e = devServerPort } = application;
102101
const scriptsStorage = this.packageJson.createStorage('scripts');
103-
const buildCmd = application.buildToolGradle ? 'gradlew' : 'mvnw -ntp';
104102

105103
let applicationWaitTimeout = WAIT_TIMEOUT * (application.applicationTypeGateway ? 2 : 1);
106104
applicationWaitTimeout = application.authenticationTypeOauth2 ? applicationWaitTimeout * 2 : applicationWaitTimeout;
@@ -110,17 +108,6 @@ export default class ServerGenerator extends BaseApplicationGenerator {
110108
scriptsStorage.set({
111109
'ci:server:await': `echo "Waiting for server at port $npm_package_config_backend_port to start" && wait-on -t ${applicationWaitTimeout} ${applicationEndpoint} && echo "Server at port $npm_package_config_backend_port started"`,
112110
});
113-
114-
// TODO add e2eTests property to application.
115-
if (this.jhipsterConfig.testFrameworks?.includes('cypress')) {
116-
scriptsStorage.set({
117-
'pree2e:headless': 'npm run ci:server:await',
118-
'ci:e2e:run': 'concurrently -k -s first -n application,e2e -c red,blue npm:ci:e2e:server:start npm:e2e:headless',
119-
'ci:e2e:dev': `concurrently -k -s first -n application,e2e -c red,blue "./${buildCmd}" npm:e2e:headless`,
120-
'e2e:dev': `concurrently -k -s first -n application,e2e -c red,blue "./${buildCmd}" npm:e2e`,
121-
'e2e:devserver': `concurrently -k -s first -n backend,frontend,e2e -c red,yellow,blue npm:backend:start npm:start "wait-on -t ${WAIT_TIMEOUT} http-get://127.0.0.1:${devServerPortE2e} && npm run e2e:headless -- -c baseUrl=http://localhost:${devServerPortE2e}"`,
122-
});
123-
}
124111
},
125112
});
126113
}

lib/types/application/yo-rc.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ export type ApplicationConfiguration = Simplify<
1616
ExportStoragePropertiesFromCommand<typeof import('../../../generators/base/command.js').default> &
1717
ExportStoragePropertiesFromCommand<typeof import('../../../generators/bootstrap-application-base/command.js').default> &
1818
ExportStoragePropertiesFromCommand<typeof import('../../../generators/client/command.js').default> &
19+
ExportStoragePropertiesFromCommand<typeof import('../../../generators/cypress/command.js').default> &
1920
ExportStoragePropertiesFromCommand<typeof import('../../../generators/git/command.js').default> &
2021
ExportStoragePropertiesFromCommand<typeof import('../../../generators/java/generators/bootstrap/command.js').default> &
2122
ExportStoragePropertiesFromCommand<typeof import('../../../generators/java/generators/build-tool/command.js').default> &

0 commit comments

Comments
 (0)