@@ -27,6 +27,8 @@ import { cypressEntityFiles, cypressFiles } from './files.js';
2727
2828const { ANGULAR } = clientFrameworkTypes ;
2929
30+ const WAIT_TIMEOUT = 3 * 60000 ;
31+
3032export 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 ? {
0 commit comments