@@ -20,10 +20,85 @@ import { getAppFeatures } from './utils/modelUtils';
2020import {
2121 addIntegrationOldToGitignore ,
2222 addPathsToQUnitJs ,
23+ addPagesToJourneyRunner ,
2324 hasVirtualOPA5 ,
24- readHtmlTargetFromQUnitJs
25+ readHtmlTargetFromQUnitJs ,
26+ type JourneyRunnerPage
2527} from './utils/opaQUnitUtils' ;
2628
29+ /**
30+ * Generate OPA test files for a Fiori elements for OData V4 application.
31+ * Note: this can potentially overwrite existing files in the webapp/test folder.
32+ *
33+ * @param basePath - the absolute target path where the application will be generated
34+ * @param opaConfig - parameters for the generation
35+ * @param opaConfig.scriptName - the name of the OPA journey file. If not specified, 'FirstJourney' will be used
36+ * @param opaConfig.htmlTarget - the name of the html that will be used in OPA journey file. If not specified, 'index.html' will be used
37+ * @param opaConfig.appID - the appID. If not specified, will be read from the manifest in sap.app/id
38+ * @param metadata - optional metadata for the OPA test generation
39+ * @param fs - an optional reference to a mem-fs editor
40+ * @param log - optional logger instance
41+ * @param standalone - opa test generation run standalone, not during app generation
42+ * @returns Reference to a mem-fs-editor
43+ */
44+ export async function generateOPAFiles (
45+ basePath : string ,
46+ opaConfig : { scriptName ?: string ; appID ?: string ; htmlTarget ?: string } ,
47+ metadata ?: string ,
48+ fs ?: Editor ,
49+ log ?: Logger ,
50+ standalone = false
51+ ) : Promise < Editor > {
52+ const editor = fs ?? create ( createStorage ( ) ) ;
53+
54+ const manifest = readManifest ( editor , basePath ) ;
55+ const { applicationType, hideFilterBar } = getAppTypeAndHideFilterBarFromManifest ( manifest ) ;
56+
57+ const config = createConfig ( manifest , opaConfig , hideFilterBar ) ;
58+
59+ const rootCommonTemplateDirPath = join ( __dirname , '../templates/common' ) ;
60+ const rootV4TemplateDirPath = join ( __dirname , `../templates/${ applicationType } ` ) ; // Only v4 is supported for the time being
61+ const testOutDirPath = join ( await getWebappPath ( basePath ) , 'test' ) ;
62+
63+ // Access ux-specification to get feature data for OPA test generation
64+ const appFeatures = await getAppFeatures ( basePath , editor , log , metadata , manifest ) ;
65+ // OPA Journey file
66+ const startPages = config . pages . filter ( ( page ) => page . isStartup ) . map ( ( page ) => page . targetKey ) ;
67+ const LROP = findLROP ( config . pages , manifest ) ;
68+ const journeyParams : JourneyParams = {
69+ startPages,
70+ startLR : LROP . pageLR ?. targetKey ,
71+ navigatedOP : LROP . pageOP ?. targetKey ,
72+ hideFilterBar : config . hideFilterBar
73+ } ;
74+
75+ const writeContext : WriteContext = { config, rootV4TemplateDirPath, testOutDirPath, editor, journeyParams } ;
76+
77+ if ( standalone ) {
78+ const hasJourneyRunner = existsSync ( join ( testOutDirPath , 'integration' , 'pages' , 'JourneyRunner.js' ) ) ;
79+ const virtualOPA5Configured = await hasVirtualOPA5 ( basePath ) ;
80+ if ( hasJourneyRunner ) {
81+ writeJourneyFiles ( appFeatures , writeContext , true , true , virtualOPA5Configured ) ;
82+ } else {
83+ editor . move ( join ( testOutDirPath , 'integration' , '**' ) , join ( testOutDirPath , 'integration_old' ) ) ;
84+
85+ await addIntegrationOldToGitignore ( basePath , editor ) ;
86+ const htmlTarget = readHtmlTargetFromQUnitJs ( testOutDirPath , editor ) ?? config . htmlTarget ;
87+ const standaloneConfig = { ...config , htmlTarget } ;
88+ const standaloneWriteContext : WriteContext = { ...writeContext , config : standaloneConfig } ;
89+ if ( ! virtualOPA5Configured ) {
90+ writeCommonAndPageFiles ( standaloneWriteContext , rootCommonTemplateDirPath ) ;
91+ }
92+ writeJourneyFiles ( appFeatures , standaloneWriteContext , true , hasJourneyRunner , virtualOPA5Configured ) ;
93+ }
94+ } else {
95+ writeCommonAndPageFiles ( writeContext , rootCommonTemplateDirPath ) ;
96+ writeJourneyFiles ( appFeatures , writeContext , false ) ;
97+ }
98+
99+ return editor ;
100+ }
101+
27102/**
28103 * Reads the manifest for an app.
29104 *
@@ -263,7 +338,6 @@ function writeCommonAndPageFiles(writeContext: WriteContext, rootCommonTemplateD
263338 }
264339 ) ;
265340
266- // Pages files (one for each page in the app)
267341 config . pages . forEach ( ( page ) => {
268342 writePageObject ( page , rootV4TemplateDirPath , testOutDirPath , editor ) ;
269343 } ) ;
@@ -290,6 +364,36 @@ function writeCommonAndPageFiles(writeContext: WriteContext, rootCommonTemplateD
290364 ) ;
291365}
292366
367+ /**
368+ * Checks whether a page object file already exists for the given feature name.
369+ * If it doesn't exist, finds the matching page config and writes the file.
370+ *
371+ * @param featureName - the feature/page name (equals the manifest targetKey)
372+ * @param config - the OPA config containing all page configurations
373+ * @param rootV4TemplateDirPath - template root directory for v4 templates
374+ * @param testOutDirPath - output test directory (.../webapp/test)
375+ * @param editor - a reference to a mem-fs editor
376+ * @returns JourneyRunnerPage if the page was newly created, undefined otherwise
377+ */
378+ function ensurePageExists (
379+ featureName : string ,
380+ config : FEV4OPAConfig ,
381+ rootV4TemplateDirPath : string ,
382+ testOutDirPath : string ,
383+ editor : Editor
384+ ) : JourneyRunnerPage | undefined {
385+ const pageFilePath = join ( testOutDirPath , 'integration' , 'pages' , `${ featureName } .js` ) ;
386+ if ( editor . exists ( pageFilePath ) ) {
387+ return undefined ;
388+ }
389+ const pageConfig = config . pages . find ( ( p ) => p . targetKey === featureName ) ;
390+ if ( pageConfig ) {
391+ writePageObject ( pageConfig , rootV4TemplateDirPath , testOutDirPath , editor ) ;
392+ return { targetKey : featureName , appPath : config . appPath } ;
393+ }
394+ return undefined ;
395+ }
396+
293397/**
294398 * Writes journey files for list report, object pages and FPM pages.
295399 *
@@ -308,6 +412,7 @@ function writeJourneyFiles(
308412) : void {
309413 const { config, rootV4TemplateDirPath, testOutDirPath, editor, journeyParams } = writeContext ;
310414 const generatedJourneyPages : string [ ] = [ ] ;
415+ const newPages : JourneyRunnerPage [ ] = [ ] ;
311416
312417 if ( appFeatures . listReport ?. name ) {
313418 editor . copyTpl (
@@ -323,6 +428,16 @@ function writeJourneyFiles(
323428 }
324429 ) ;
325430 generatedJourneyPages . push ( appFeatures . listReport . name ) ;
431+ const lrPage = ensurePageExists (
432+ appFeatures . listReport . name ,
433+ config ,
434+ rootV4TemplateDirPath ,
435+ testOutDirPath ,
436+ editor
437+ ) ;
438+ if ( lrPage ) {
439+ newPages . push ( lrPage ) ;
440+ }
326441 }
327442
328443 if ( appFeatures . objectPages && appFeatures . objectPages . length > 0 ) {
@@ -342,6 +457,10 @@ function writeJourneyFiles(
342457 }
343458 ) ;
344459 generatedJourneyPages . push ( objectPage . name ) ;
460+ const opPage = ensurePageExists ( objectPage . name , config , rootV4TemplateDirPath , testOutDirPath , editor ) ;
461+ if ( opPage ) {
462+ newPages . push ( opPage ) ;
463+ }
345464 }
346465 } ) ;
347466 }
@@ -360,6 +479,14 @@ function writeJourneyFiles(
360479 }
361480 ) ;
362481 generatedJourneyPages . push ( appFeatures . fpm . name ) ;
482+ const fpmPage = ensurePageExists ( appFeatures . fpm . name , config , rootV4TemplateDirPath , testOutDirPath , editor ) ;
483+ if ( fpmPage ) {
484+ newPages . push ( fpmPage ) ;
485+ }
486+ }
487+
488+ if ( newPages . length > 0 ) {
489+ addPagesToJourneyRunner ( newPages , testOutDirPath , editor ) ;
363490 }
364491
365492 if ( ! virtualOPA5Configured ) {
@@ -410,79 +537,6 @@ function writePageObject(
410537 ) ;
411538}
412539
413- /**
414- * Generate OPA test files for a Fiori elements for OData V4 application.
415- * Note: this can potentially overwrite existing files in the webapp/test folder.
416- *
417- * @param basePath - the absolute target path where the application will be generated
418- * @param opaConfig - parameters for the generation
419- * @param opaConfig.scriptName - the name of the OPA journey file. If not specified, 'FirstJourney' will be used
420- * @param opaConfig.htmlTarget - the name of the html that will be used in OPA journey file. If not specified, 'index.html' will be used
421- * @param opaConfig.appID - the appID. If not specified, will be read from the manifest in sap.app/id
422- * @param metadata - optional metadata for the OPA test generation
423- * @param fs - an optional reference to a mem-fs editor
424- * @param log - optional logger instance
425- * @param standalone - opa test generation run standalone, not during app generation
426- * @returns Reference to a mem-fs-editor
427- */
428- export async function generateOPAFiles (
429- basePath : string ,
430- opaConfig : { scriptName ?: string ; appID ?: string ; htmlTarget ?: string } ,
431- metadata ?: string ,
432- fs ?: Editor ,
433- log ?: Logger ,
434- standalone = false
435- ) : Promise < Editor > {
436- const editor = fs ?? create ( createStorage ( ) ) ;
437-
438- const manifest = readManifest ( editor , basePath ) ;
439- const { applicationType, hideFilterBar } = getAppTypeAndHideFilterBarFromManifest ( manifest ) ;
440-
441- const config = createConfig ( manifest , opaConfig , hideFilterBar ) ;
442-
443- const rootCommonTemplateDirPath = join ( __dirname , '../templates/common' ) ;
444- const rootV4TemplateDirPath = join ( __dirname , `../templates/${ applicationType } ` ) ; // Only v4 is supported for the time being
445- const testOutDirPath = join ( await getWebappPath ( basePath ) , 'test' ) ;
446-
447- // Access ux-specification to get feature data for OPA test generation
448- const appFeatures = await getAppFeatures ( basePath , editor , log , metadata ) ;
449- // OPA Journey file
450- const startPages = config . pages . filter ( ( page ) => page . isStartup ) . map ( ( page ) => page . targetKey ) ;
451- const LROP = findLROP ( config . pages , manifest ) ;
452- const journeyParams : JourneyParams = {
453- startPages,
454- startLR : LROP . pageLR ?. targetKey ,
455- navigatedOP : LROP . pageOP ?. targetKey ,
456- hideFilterBar : config . hideFilterBar
457- } ;
458-
459- const writeContext : WriteContext = { config, rootV4TemplateDirPath, testOutDirPath, editor, journeyParams } ;
460-
461- if ( standalone ) {
462- const hasJourneyRunner = existsSync ( join ( testOutDirPath , 'integration' , 'pages' , 'JourneyRunner.js' ) ) ;
463- const virtualOPA5Configured = await hasVirtualOPA5 ( basePath ) ;
464- if ( hasJourneyRunner ) {
465- writeJourneyFiles ( appFeatures , writeContext , true , true , virtualOPA5Configured ) ;
466- } else {
467- editor . move ( join ( testOutDirPath , 'integration' , '**' ) , join ( testOutDirPath , 'integration_old' ) ) ;
468-
469- await addIntegrationOldToGitignore ( basePath , editor ) ;
470- const htmlTarget = readHtmlTargetFromQUnitJs ( testOutDirPath , editor ) ?? config . htmlTarget ;
471- const standaloneConfig = { ...config , htmlTarget } ;
472- const standaloneWriteContext : WriteContext = { ...writeContext , config : standaloneConfig } ;
473- if ( ! virtualOPA5Configured ) {
474- writeCommonAndPageFiles ( standaloneWriteContext , rootCommonTemplateDirPath ) ;
475- }
476- writeJourneyFiles ( appFeatures , standaloneWriteContext , true , true , virtualOPA5Configured ) ;
477- }
478- } else {
479- writeCommonAndPageFiles ( writeContext , rootCommonTemplateDirPath ) ;
480- writeJourneyFiles ( appFeatures , writeContext , false ) ;
481- }
482-
483- return editor ;
484- }
485-
486540/**
487541 * Generate a page object file for a Fiori elements for OData V4 application.
488542 * Note: this doesn't modify other existing files in the webapp/test folder.
@@ -499,7 +553,7 @@ export async function generatePageObjectFile(
499553 pageObjectParameters : { targetKey : string ; appID ?: string } ,
500554 fs ?: Editor
501555) : Promise < Editor > {
502- const editor = fs || create ( createStorage ( ) ) ;
556+ const editor = fs ?? create ( createStorage ( ) ) ;
503557
504558 const manifest = readManifest ( editor , basePath ) ;
505559 const { applicationType } = getAppTypeAndHideFilterBarFromManifest ( manifest ) ;
0 commit comments