diff --git a/.changeset/eighty-coins-sip.md b/.changeset/eighty-coins-sip.md new file mode 100644 index 00000000000..1c78d71ba97 --- /dev/null +++ b/.changeset/eighty-coins-sip.md @@ -0,0 +1,6 @@ +--- +'@sap-ux/generator-adp': patch +'@sap-ux/adp-tooling': patch +--- + +feat: Adapt CF projects' structure to work with preview-middleware diff --git a/packages/adp-tooling/src/cf/services/api.ts b/packages/adp-tooling/src/cf/services/api.ts index 464a1d903aa..e38468f531c 100644 --- a/packages/adp-tooling/src/cf/services/api.ts +++ b/packages/adp-tooling/src/cf/services/api.ts @@ -114,7 +114,7 @@ export function getFDCRequestArguments(cfConfig: CfConfig): RequestArguments { * @param {string[]} appHostIds - The app host ids. * @param {CfConfig} cfConfig - The CF config. * @param {ToolsLogger} logger - The logger. - * @returns {Promise} The FDC apps. + * @returns {Promise} The FDC apps. */ export async function getFDCApps(appHostIds: string[], cfConfig: CfConfig, logger: ToolsLogger): Promise { const requestArguments = getFDCRequestArguments(cfConfig); diff --git a/packages/adp-tooling/src/translations/adp-tooling.i18n.json b/packages/adp-tooling/src/translations/adp-tooling.i18n.json index 70f51a28af6..482df7ff73b 100644 --- a/packages/adp-tooling/src/translations/adp-tooling.i18n.json +++ b/packages/adp-tooling/src/translations/adp-tooling.i18n.json @@ -76,7 +76,7 @@ }, "error": { "appDoesNotSupportFlexibility": "The selected application does not support flexibility because it has `flexEnabled=false`. SAPUI5 Adaptation Project only supports applications that support flexibility. Please select a different application.", - "failedToParseXsAppJson": "Failed to parse `xs-app.json`. Error: {{error}}", + "failedToParseXsAppJson": "Failed to parse the `xs-app.json` file. Error: {{error}}", "failedToParseManifestJson": "Failed to parse the `manifest.json` file. Error: {{error}}", "oDataEndpointsValidationFailed": "Validation for the OData endpoints has failed. For more information, check the logs.", "adpDoesNotSupportSelectedApp": "Adaptation project doesn't support the selected application. Please select a different application.", diff --git a/packages/adp-tooling/src/writer/cf.ts b/packages/adp-tooling/src/writer/cf.ts index 3bba69af516..c5b8055e9a4 100644 --- a/packages/adp-tooling/src/writer/cf.ts +++ b/packages/adp-tooling/src/writer/cf.ts @@ -7,7 +7,7 @@ import { adjustMtaYaml } from '../cf'; import { getApplicationType } from '../source'; import { fillDescriptorContent } from './manifest'; import type { CfAdpWriterConfig, Content } from '../types'; -import { getCfVariant, writeCfTemplates } from './project-utils'; +import { getCfVariant, writeCfTemplates, writeCfUI5Yaml, writeCfUI5BuildYaml } from './project-utils'; import { getI18nDescription, getI18nModels, writeI18nModels } from './i18n'; /** @@ -53,6 +53,8 @@ export async function generateCf( fillDescriptorContent(variant.content as Content[], app.appType, ui5.version, app.i18nModels); await writeCfTemplates(basePath, variant, fullConfig, fs); + await writeCfUI5Yaml(fullConfig.project.folder, fullConfig, fs); + await writeCfUI5BuildYaml(fullConfig.project.folder, fullConfig, fs); return fs; } diff --git a/packages/adp-tooling/src/writer/options.ts b/packages/adp-tooling/src/writer/options.ts index 561af2f5447..b7c6738726b 100644 --- a/packages/adp-tooling/src/writer/options.ts +++ b/packages/adp-tooling/src/writer/options.ts @@ -15,8 +15,10 @@ import type { CloudApp, InternalInboundNavigation, CloudCustomTaskConfig, - CloudCustomTaskConfigTarget + CloudCustomTaskConfigTarget, + CfAdpWriterConfig } from '../types'; +import { UI5_CDN_URL } from '../base/constants'; const VSCODE_URL = 'https://REQUIRED_FOR_VSCODE.example'; @@ -335,3 +337,60 @@ export function enhanceManifestChangeContentWithFlpConfig( manifestChangeContent.push(removeOtherInboundsChange); } } + +/** + * Generate custom configuration required for the ui5.yaml. + * + * @param {UI5Config} ui5Config - Configuration representing the ui5.yaml. + * @param {CfAdpWriterConfig} config - Full project configuration. + */ +export function enhanceUI5YamlWithCfCustomTask(ui5Config: UI5Config, config: CfAdpWriterConfig): void { + const { baseApp, cf, project } = config; + ui5Config.addCustomTasks([ + { + name: 'app-variant-bundler-build', + beforeTask: 'escapeNonAsciiCharacters', + configuration: { + module: project.name, + appHostId: baseApp.appHostId, + appName: baseApp.appName, + appVersion: baseApp.appVersion, + html5RepoRuntime: cf.html5RepoRuntimeGuid, + org: cf.org.GUID, + space: cf.space.GUID, + sapCloudService: cf.businessSolutionName ?? '', + serviceInstanceName: cf.businessService + } + } + ]); +} + +/** + * Generate custom configuration required for the ui5.yaml. + * + * @param {UI5Config} ui5Config - Configuration representing the ui5.yaml. + */ +export function enhanceUI5YamlWithCfCustomMiddleware(ui5Config: UI5Config): void { + const ui5ConfigOptions: Partial = { + url: UI5_CDN_URL + }; + + ui5Config.addFioriToolsProxyMiddleware( + { + ui5: ui5ConfigOptions, + backend: [] + }, + 'compression' + ); + ui5Config.addCustomMiddleware([ + { + name: 'fiori-tools-preview', + afterMiddleware: 'fiori-tools-proxy', + configuration: { + flp: { + theme: 'sap_horizon' + } + } + } + ]); +} diff --git a/packages/adp-tooling/src/writer/project-utils.ts b/packages/adp-tooling/src/writer/project-utils.ts index afdd5349487..a928fa8366a 100644 --- a/packages/adp-tooling/src/writer/project-utils.ts +++ b/packages/adp-tooling/src/writer/project-utils.ts @@ -8,8 +8,7 @@ import { type CustomConfig, type TypesConfig, type CfAdpWriterConfig, - type DescriptorVariant, - ApplicationType + type DescriptorVariant } from '../types'; import { enhanceUI5DeployYaml, @@ -17,7 +16,9 @@ import { hasDeployConfig, enhanceUI5YamlWithCustomConfig, enhanceUI5YamlWithCustomTask, - enhanceUI5YamlWithTranspileMiddleware + enhanceUI5YamlWithTranspileMiddleware, + enhanceUI5YamlWithCfCustomTask, + enhanceUI5YamlWithCfCustomMiddleware } from './options'; import type { Package } from '@sap-ux/project-access'; @@ -125,30 +126,6 @@ export function getCfVariant(config: CfAdpWriterConfig): DescriptorVariant { return variant; } -/** - * Get the ADP config for the CF project. - * - * @param {CfAdpWriterConfig} config - The CF configuration. - * @returns {Record} The ADP config for the CF project. - */ -export function getCfAdpConfig(config: CfAdpWriterConfig): Record { - const { app, project, ui5, cf } = config; - const configJson = { - componentname: app.namespace, - appvariant: project.name, - layer: app.layer, - isOVPApp: app.appType === ApplicationType.FIORI_ELEMENTS_OVP, - isFioriElement: app.appType === ApplicationType.FIORI_ELEMENTS, - environment: 'CF', - ui5Version: ui5.version, - cfApiUrl: cf.url, - cfSpace: cf.space.GUID, - cfOrganization: cf.org.GUID - }; - - return configJson; -} - /** * Writes a given project template files within a specified folder in the project directory. * @@ -212,6 +189,54 @@ export async function writeUI5Yaml(projectPath: string, data: AdpWriterConfig, f } } +/** + * Writes a ui5.yaml file for CF project within a specified folder in the project directory. + * + * @param {string} projectPath - The root path of the project. + * @param {CfAdpWriterConfig} data - The data to be populated in the template file. + * @param {Editor} fs - The `mem-fs-editor` instance used for file operations. + * @returns {void} + */ +export async function writeCfUI5Yaml(projectPath: string, data: CfAdpWriterConfig, fs: Editor): Promise { + try { + const ui5ConfigPath = join(projectPath, 'ui5.yaml'); + const baseUi5ConfigContent = fs.read(ui5ConfigPath); + const ui5Config = await UI5Config.newInstance(baseUi5ConfigContent); + ui5Config.setConfiguration({ propertiesFileSourceEncoding: 'UTF-8', paths: { webapp: 'dist' } }); + + /** Middlewares */ + enhanceUI5YamlWithCfCustomMiddleware(ui5Config); + + fs.write(ui5ConfigPath, ui5Config.toString()); + } catch (e) { + throw new Error(`Could not write ui5.yaml file. Reason: ${e.message}`); + } +} + +/** + * Writes a ui5-build.yaml file for CF project within a specified folder in the project directory. + * + * @param {string} projectPath - The root path of the project. + * @param {CfAdpWriterConfig} data - The data to be populated in the template file. + * @param {Editor} fs - The `mem-fs-editor` instance used for file operations. + * @returns {void} + */ +export async function writeCfUI5BuildYaml(projectPath: string, data: CfAdpWriterConfig, fs: Editor): Promise { + try { + const ui5ConfigPath = join(projectPath, 'ui5-build.yaml'); + const baseUi5ConfigContent = fs.read(ui5ConfigPath); + const ui5Config = await UI5Config.newInstance(baseUi5ConfigContent); + ui5Config.setConfiguration({ propertiesFileSourceEncoding: 'UTF-8' }); + + /** Builder task */ + enhanceUI5YamlWithCfCustomTask(ui5Config, data); + + fs.write(ui5ConfigPath, ui5Config.toString()); + } catch (e) { + throw new Error(`Could not write ui5-build.yaml file. Reason: ${e.message}`); + } +} + /** * Writes a ui5-deploy.yaml file within a specified folder in the project directory. * @@ -251,7 +276,7 @@ export async function writeCfTemplates( ): Promise { const baseTmplPath = join(__dirname, '../../templates'); const templatePath = config.options?.templatePathOverwrite ?? baseTmplPath; - const { app, baseApp, cf, project, options } = config; + const { app, project, options } = config; fs.copyTpl( join(templatePath, 'project/webapp/manifest.appdescr_variant'), @@ -264,18 +289,12 @@ export async function writeCfTemplates( }); fs.copyTpl(join(templatePath, 'cf/ui5.yaml'), join(project.folder, 'ui5.yaml'), { - appHostId: baseApp.appHostId, - appName: baseApp.appName, - appVersion: baseApp.appVersion, - module: project.name, - html5RepoRuntime: cf.html5RepoRuntimeGuid, - org: cf.org.GUID, - space: cf.space.GUID, - sapCloudService: cf.businessSolutionName ?? '', - instanceName: cf.businessService + module: project.name }); - fs.writeJSON(join(project.folder, '.adp/config.json'), getCfAdpConfig(config)); + fs.copyTpl(join(templatePath, 'cf/ui5-build.yaml'), join(project.folder, 'ui5-build.yaml'), { + module: project.name + }); fs.copyTpl(join(templatePath, 'cf/i18n/i18n.properties'), join(project.folder, 'webapp/i18n/i18n.properties'), { module: project.name, diff --git a/packages/adp-tooling/templates/cf/package.json b/packages/adp-tooling/templates/cf/package.json index 1a40fa16c9e..43f3558d94b 100644 --- a/packages/adp-tooling/templates/cf/package.json +++ b/packages/adp-tooling/templates/cf/package.json @@ -4,7 +4,9 @@ "description": "", "main": "index.js", "scripts": { - "build": "npm run clean && ui5 build --include-task=generateCachebusterInfo && npm run zip", + "prestart": "npm run build", + "start": "fiori run --open /test/flp.html#app-preview", + "build": "npm run clean && ui5 build --config ui5-build.yaml --include-task=generateCachebusterInfo && npm run zip", "zip": "cd dist && npx bestzip ../<%= module %>.zip *", "clean": "npx rimraf <%= module %>.zip dist", "build-ui5": "npm explore @ui5/task-adaptation -- npm run rollup" @@ -20,11 +22,12 @@ ] }, "devDependencies": { - "@sap/ui5-builder-webide-extension": "1.0.x", - "@sapui5/ts-types": "^1.85.1", - "@ui5/cli": "^3.0.0", - "@ui5/task-adaptation": "^1.0.x", - "bestzip": "2.1.4", - "rimraf": "3.0.2" + "@sap/ui5-builder-webide-extension": "^1.1.9", + "@sapui5/ts-types": "^1.141.2", + "@sap/ux-ui5-tooling": "1", + "@ui5/cli": "^4.0.16", + "@ui5/task-adaptation": "^1.5.3", + "bestzip": "^2.2.1", + "rimraf": "^5.0.5" } } diff --git a/packages/adp-tooling/templates/cf/ui5-build.yaml b/packages/adp-tooling/templates/cf/ui5-build.yaml new file mode 100644 index 00000000000..a38bf6790e9 --- /dev/null +++ b/packages/adp-tooling/templates/cf/ui5-build.yaml @@ -0,0 +1,5 @@ +--- +specVersion: "2.2" +type: application +metadata: + name: <%= module %> diff --git a/packages/adp-tooling/templates/cf/ui5.yaml b/packages/adp-tooling/templates/cf/ui5.yaml index 9cd4fca23e9..a38bf6790e9 100644 --- a/packages/adp-tooling/templates/cf/ui5.yaml +++ b/packages/adp-tooling/templates/cf/ui5.yaml @@ -3,17 +3,3 @@ specVersion: "2.2" type: application metadata: name: <%= module %> -builder: - customTasks: - - name: app-variant-bundler-build - beforeTask: escapeNonAsciiCharacters - configuration: - appHostId: <%= appHostId %> - appName: <%= appName %> - appVersion: <%= appVersion %> - moduleName: <%= module %> - org: <%= org %> - space: <%= space %> - html5RepoRuntime: <%= html5RepoRuntime %> - sapCloudService: <%= sapCloudService %> - serviceInstanceName: <%= instanceName %> \ No newline at end of file diff --git a/packages/adp-tooling/test/unit/writer/__snapshots__/cf.test.ts.snap b/packages/adp-tooling/test/unit/writer/__snapshots__/cf.test.ts.snap index 9d1a30a5136..f8fe9226b03 100644 --- a/packages/adp-tooling/test/unit/writer/__snapshots__/cf.test.ts.snap +++ b/packages/adp-tooling/test/unit/writer/__snapshots__/cf.test.ts.snap @@ -72,22 +72,6 @@ resources: service-plan: app-runtime _schema-version: '3.3' description: Test MTA Project for CF Writer Tests -", - "state": "modified", - }, - "../minimal-cf/test-cf-project/.adp/config.json": Object { - "contents": "{ - \\"componentname\\": \\"test.namespace\\", - \\"appvariant\\": \\"test-cf-project\\", - \\"layer\\": \\"CUSTOMER_BASE\\", - \\"isOVPApp\\": false, - \\"isFioriElement\\": false, - \\"environment\\": \\"CF\\", - \\"ui5Version\\": \\"1.120.0\\", - \\"cfApiUrl\\": \\"/test.cf.com\\", - \\"cfSpace\\": \\"space-guid\\", - \\"cfOrganization\\": \\"org-guid\\" -} ", "state": "modified", }, @@ -108,7 +92,9 @@ UIAdaptation*.html \\"description\\": \\"\\", \\"main\\": \\"index.js\\", \\"scripts\\": { - \\"build\\": \\"npm run clean && ui5 build --include-task=generateCachebusterInfo && npm run zip\\", + \\"prestart\\": \\"npm run build\\", + \\"start\\": \\"fiori run --open /test/flp.html#app-preview\\", + \\"build\\": \\"npm run clean && ui5 build --config ui5-build.yaml --include-task=generateCachebusterInfo && npm run zip\\", \\"zip\\": \\"cd dist && npx bestzip ../test-cf-project.zip *\\", \\"clean\\": \\"npx rimraf test-cf-project.zip dist\\", \\"build-ui5\\": \\"npm explore @ui5/task-adaptation -- npm run rollup\\" @@ -124,37 +110,72 @@ UIAdaptation*.html ] }, \\"devDependencies\\": { - \\"@sap/ui5-builder-webide-extension\\": \\"1.0.x\\", - \\"@sapui5/ts-types\\": \\"^1.85.1\\", - \\"@ui5/cli\\": \\"^3.0.0\\", - \\"@ui5/task-adaptation\\": \\"^1.0.x\\", - \\"bestzip\\": \\"2.1.4\\", - \\"rimraf\\": \\"3.0.2\\" + \\"@sap/ui5-builder-webide-extension\\": \\"^1.1.9\\", + \\"@sapui5/ts-types\\": \\"^1.141.2\\", + \\"@sap/ux-ui5-tooling\\": \\"1\\", + \\"@ui5/cli\\": \\"^4.0.16\\", + \\"@ui5/task-adaptation\\": \\"^1.5.3\\", + \\"bestzip\\": \\"^2.2.1\\", + \\"rimraf\\": \\"^5.0.5\\" } } ", "state": "modified", }, - "../minimal-cf/test-cf-project/ui5.yaml": Object { + "../minimal-cf/test-cf-project/ui5-build.yaml": Object { "contents": "--- specVersion: \\"2.2\\" type: application metadata: name: test-cf-project +resources: + configuration: + propertiesFileSourceEncoding: UTF-8 builder: customTasks: - name: app-variant-bundler-build beforeTask: escapeNonAsciiCharacters configuration: + module: test-cf-project appHostId: app-host-id appName: Base App appVersion: 1.0.0 - moduleName: test-cf-project + html5RepoRuntime: runtime-guid org: org-guid space: space-guid - html5RepoRuntime: runtime-guid sapCloudService: test-solution - serviceInstanceName: test-service", + serviceInstanceName: test-service +", + "state": "modified", + }, + "../minimal-cf/test-cf-project/ui5.yaml": Object { + "contents": "--- +specVersion: \\"2.2\\" +type: application +metadata: + name: test-cf-project +resources: + configuration: + propertiesFileSourceEncoding: UTF-8 + paths: + webapp: dist +server: + customMiddleware: + - name: fiori-tools-proxy + afterMiddleware: compression + configuration: + ignoreCertErrors: false # If set to true, certificate errors will be ignored. E.g. self-signed certificates will be accepted + ui5: + path: + - /resources + - /test-resources + url: https://ui5.sap.com + - name: fiori-tools-preview + afterMiddleware: fiori-tools-proxy + configuration: + flp: + theme: sap_horizon +", "state": "modified", }, "../minimal-cf/test-cf-project/webapp/i18n/i18n.properties": Object { @@ -298,22 +319,6 @@ resources: version: 1.0.0 _schema-version: '3.3' description: Test MTA Project for CF Writer Tests -", - "state": "modified", - }, - "test-cf-project/.adp/config.json": Object { - "contents": "{ - \\"componentname\\": \\"test.namespace\\", - \\"appvariant\\": \\"test-cf-project\\", - \\"layer\\": \\"CUSTOMER_BASE\\", - \\"isOVPApp\\": false, - \\"isFioriElement\\": false, - \\"environment\\": \\"CF\\", - \\"ui5Version\\": \\"1.120.0\\", - \\"cfApiUrl\\": \\"/test.cf.com\\", - \\"cfSpace\\": \\"space-guid\\", - \\"cfOrganization\\": \\"org-guid\\" -} ", "state": "modified", }, @@ -334,7 +339,9 @@ UIAdaptation*.html \\"description\\": \\"\\", \\"main\\": \\"index.js\\", \\"scripts\\": { - \\"build\\": \\"npm run clean && ui5 build --include-task=generateCachebusterInfo && npm run zip\\", + \\"prestart\\": \\"npm run build\\", + \\"start\\": \\"fiori run --open /test/flp.html#app-preview\\", + \\"build\\": \\"npm run clean && ui5 build --config ui5-build.yaml --include-task=generateCachebusterInfo && npm run zip\\", \\"zip\\": \\"cd dist && npx bestzip ../test-cf-project.zip *\\", \\"clean\\": \\"npx rimraf test-cf-project.zip dist\\", \\"build-ui5\\": \\"npm explore @ui5/task-adaptation -- npm run rollup\\" @@ -350,37 +357,72 @@ UIAdaptation*.html ] }, \\"devDependencies\\": { - \\"@sap/ui5-builder-webide-extension\\": \\"1.0.x\\", - \\"@sapui5/ts-types\\": \\"^1.85.1\\", - \\"@ui5/cli\\": \\"^3.0.0\\", - \\"@ui5/task-adaptation\\": \\"^1.0.x\\", - \\"bestzip\\": \\"2.1.4\\", - \\"rimraf\\": \\"3.0.2\\" + \\"@sap/ui5-builder-webide-extension\\": \\"^1.1.9\\", + \\"@sapui5/ts-types\\": \\"^1.141.2\\", + \\"@sap/ux-ui5-tooling\\": \\"1\\", + \\"@ui5/cli\\": \\"^4.0.16\\", + \\"@ui5/task-adaptation\\": \\"^1.5.3\\", + \\"bestzip\\": \\"^2.2.1\\", + \\"rimraf\\": \\"^5.0.5\\" } } ", "state": "modified", }, - "test-cf-project/ui5.yaml": Object { + "test-cf-project/ui5-build.yaml": Object { "contents": "--- specVersion: \\"2.2\\" type: application metadata: name: test-cf-project +resources: + configuration: + propertiesFileSourceEncoding: UTF-8 builder: customTasks: - name: app-variant-bundler-build beforeTask: escapeNonAsciiCharacters configuration: + module: test-cf-project appHostId: app-host-id appName: Base App appVersion: 1.0.0 - moduleName: test-cf-project + html5RepoRuntime: runtime-guid org: org-guid space: space-guid - html5RepoRuntime: runtime-guid sapCloudService: test-solution - serviceInstanceName: test-service", + serviceInstanceName: test-service +", + "state": "modified", + }, + "test-cf-project/ui5.yaml": Object { + "contents": "--- +specVersion: \\"2.2\\" +type: application +metadata: + name: test-cf-project +resources: + configuration: + propertiesFileSourceEncoding: UTF-8 + paths: + webapp: dist +server: + customMiddleware: + - name: fiori-tools-proxy + afterMiddleware: compression + configuration: + ignoreCertErrors: false # If set to true, certificate errors will be ignored. E.g. self-signed certificates will be accepted + ui5: + path: + - /resources + - /test-resources + url: https://ui5.sap.com + - name: fiori-tools-preview + afterMiddleware: fiori-tools-proxy + configuration: + flp: + theme: sap_horizon +", "state": "modified", }, "test-cf-project/webapp/i18n/i18n.properties": Object { @@ -529,22 +571,6 @@ resources: version: 1.0.0 _schema-version: '3.3' description: Test MTA Project for CF Writer Tests -", - "state": "modified", - }, - "../managed-approuter/test-cf-project/.adp/config.json": Object { - "contents": "{ - \\"componentname\\": \\"test.namespace\\", - \\"appvariant\\": \\"test-cf-project\\", - \\"layer\\": \\"CUSTOMER_BASE\\", - \\"isOVPApp\\": false, - \\"isFioriElement\\": false, - \\"environment\\": \\"CF\\", - \\"ui5Version\\": \\"1.120.0\\", - \\"cfApiUrl\\": \\"/test.cf.com\\", - \\"cfSpace\\": \\"space-guid\\", - \\"cfOrganization\\": \\"org-guid\\" -} ", "state": "modified", }, @@ -565,7 +591,9 @@ UIAdaptation*.html \\"description\\": \\"\\", \\"main\\": \\"index.js\\", \\"scripts\\": { - \\"build\\": \\"npm run clean && ui5 build --include-task=generateCachebusterInfo && npm run zip\\", + \\"prestart\\": \\"npm run build\\", + \\"start\\": \\"fiori run --open /test/flp.html#app-preview\\", + \\"build\\": \\"npm run clean && ui5 build --config ui5-build.yaml --include-task=generateCachebusterInfo && npm run zip\\", \\"zip\\": \\"cd dist && npx bestzip ../test-cf-project.zip *\\", \\"clean\\": \\"npx rimraf test-cf-project.zip dist\\", \\"build-ui5\\": \\"npm explore @ui5/task-adaptation -- npm run rollup\\" @@ -581,37 +609,72 @@ UIAdaptation*.html ] }, \\"devDependencies\\": { - \\"@sap/ui5-builder-webide-extension\\": \\"1.0.x\\", - \\"@sapui5/ts-types\\": \\"^1.85.1\\", - \\"@ui5/cli\\": \\"^3.0.0\\", - \\"@ui5/task-adaptation\\": \\"^1.0.x\\", - \\"bestzip\\": \\"2.1.4\\", - \\"rimraf\\": \\"3.0.2\\" + \\"@sap/ui5-builder-webide-extension\\": \\"^1.1.9\\", + \\"@sapui5/ts-types\\": \\"^1.141.2\\", + \\"@sap/ux-ui5-tooling\\": \\"1\\", + \\"@ui5/cli\\": \\"^4.0.16\\", + \\"@ui5/task-adaptation\\": \\"^1.5.3\\", + \\"bestzip\\": \\"^2.2.1\\", + \\"rimraf\\": \\"^5.0.5\\" } } ", "state": "modified", }, - "../managed-approuter/test-cf-project/ui5.yaml": Object { + "../managed-approuter/test-cf-project/ui5-build.yaml": Object { "contents": "--- specVersion: \\"2.2\\" type: application metadata: name: test-cf-project +resources: + configuration: + propertiesFileSourceEncoding: UTF-8 builder: customTasks: - name: app-variant-bundler-build beforeTask: escapeNonAsciiCharacters configuration: + module: test-cf-project appHostId: app-host-id appName: Base App appVersion: 1.0.0 - moduleName: test-cf-project + html5RepoRuntime: runtime-guid org: org-guid space: space-guid - html5RepoRuntime: runtime-guid sapCloudService: test-solution - serviceInstanceName: test-service", + serviceInstanceName: test-service +", + "state": "modified", + }, + "../managed-approuter/test-cf-project/ui5.yaml": Object { + "contents": "--- +specVersion: \\"2.2\\" +type: application +metadata: + name: test-cf-project +resources: + configuration: + propertiesFileSourceEncoding: UTF-8 + paths: + webapp: dist +server: + customMiddleware: + - name: fiori-tools-proxy + afterMiddleware: compression + configuration: + ignoreCertErrors: false # If set to true, certificate errors will be ignored. E.g. self-signed certificates will be accepted + ui5: + path: + - /resources + - /test-resources + url: https://ui5.sap.com + - name: fiori-tools-preview + afterMiddleware: fiori-tools-proxy + configuration: + flp: + theme: sap_horizon +", "state": "modified", }, "../managed-approuter/test-cf-project/webapp/i18n/i18n.properties": Object { @@ -729,22 +792,6 @@ resources: service-plan: app-runtime _schema-version: '3.3' description: Test MTA Project for CF Writer Tests -", - "state": "modified", - }, - "../minimal-cf/test-cf-project/.adp/config.json": Object { - "contents": "{ - \\"componentname\\": \\"test.namespace\\", - \\"appvariant\\": \\"test-cf-project\\", - \\"layer\\": \\"CUSTOMER_BASE\\", - \\"isOVPApp\\": false, - \\"isFioriElement\\": false, - \\"environment\\": \\"CF\\", - \\"ui5Version\\": \\"1.120.0\\", - \\"cfApiUrl\\": \\"/test.cf.com\\", - \\"cfSpace\\": \\"space-guid\\", - \\"cfOrganization\\": \\"org-guid\\" -} ", "state": "modified", }, @@ -765,7 +812,9 @@ UIAdaptation*.html \\"description\\": \\"\\", \\"main\\": \\"index.js\\", \\"scripts\\": { - \\"build\\": \\"npm run clean && ui5 build --include-task=generateCachebusterInfo && npm run zip\\", + \\"prestart\\": \\"npm run build\\", + \\"start\\": \\"fiori run --open /test/flp.html#app-preview\\", + \\"build\\": \\"npm run clean && ui5 build --config ui5-build.yaml --include-task=generateCachebusterInfo && npm run zip\\", \\"zip\\": \\"cd dist && npx bestzip ../test-cf-project.zip *\\", \\"clean\\": \\"npx rimraf test-cf-project.zip dist\\", \\"build-ui5\\": \\"npm explore @ui5/task-adaptation -- npm run rollup\\" @@ -781,37 +830,72 @@ UIAdaptation*.html ] }, \\"devDependencies\\": { - \\"@sap/ui5-builder-webide-extension\\": \\"1.0.x\\", - \\"@sapui5/ts-types\\": \\"^1.85.1\\", - \\"@ui5/cli\\": \\"^3.0.0\\", - \\"@ui5/task-adaptation\\": \\"^1.0.x\\", - \\"bestzip\\": \\"2.1.4\\", - \\"rimraf\\": \\"3.0.2\\" + \\"@sap/ui5-builder-webide-extension\\": \\"^1.1.9\\", + \\"@sapui5/ts-types\\": \\"^1.141.2\\", + \\"@sap/ux-ui5-tooling\\": \\"1\\", + \\"@ui5/cli\\": \\"^4.0.16\\", + \\"@ui5/task-adaptation\\": \\"^1.5.3\\", + \\"bestzip\\": \\"^2.2.1\\", + \\"rimraf\\": \\"^5.0.5\\" } } ", "state": "modified", }, - "../minimal-cf/test-cf-project/ui5.yaml": Object { + "../minimal-cf/test-cf-project/ui5-build.yaml": Object { "contents": "--- specVersion: \\"2.2\\" type: application metadata: name: test-cf-project +resources: + configuration: + propertiesFileSourceEncoding: UTF-8 builder: customTasks: - name: app-variant-bundler-build beforeTask: escapeNonAsciiCharacters configuration: + module: test-cf-project appHostId: app-host-id appName: Base App appVersion: 1.0.0 - moduleName: test-cf-project + html5RepoRuntime: runtime-guid org: org-guid space: space-guid - html5RepoRuntime: runtime-guid sapCloudService: test-solution - serviceInstanceName: test-service", + serviceInstanceName: test-service +", + "state": "modified", + }, + "../minimal-cf/test-cf-project/ui5.yaml": Object { + "contents": "--- +specVersion: \\"2.2\\" +type: application +metadata: + name: test-cf-project +resources: + configuration: + propertiesFileSourceEncoding: UTF-8 + paths: + webapp: dist +server: + customMiddleware: + - name: fiori-tools-proxy + afterMiddleware: compression + configuration: + ignoreCertErrors: false # If set to true, certificate errors will be ignored. E.g. self-signed certificates will be accepted + ui5: + path: + - /resources + - /test-resources + url: https://ui5.sap.com + - name: fiori-tools-preview + afterMiddleware: fiori-tools-proxy + configuration: + flp: + theme: sap_horizon +", "state": "modified", }, "../minimal-cf/test-cf-project/webapp/i18n/i18n.properties": Object { @@ -991,22 +1075,6 @@ description: Test MTA Project for CF Writer Tests } ] } -", - "state": "modified", - }, - "test-cf-project/.adp/config.json": Object { - "contents": "{ - \\"componentname\\": \\"test.namespace\\", - \\"appvariant\\": \\"test-cf-project\\", - \\"layer\\": \\"CUSTOMER_BASE\\", - \\"isOVPApp\\": false, - \\"isFioriElement\\": false, - \\"environment\\": \\"CF\\", - \\"ui5Version\\": \\"1.120.0\\", - \\"cfApiUrl\\": \\"/test.cf.com\\", - \\"cfSpace\\": \\"space-guid\\", - \\"cfOrganization\\": \\"org-guid\\" -} ", "state": "modified", }, @@ -1027,7 +1095,9 @@ UIAdaptation*.html \\"description\\": \\"\\", \\"main\\": \\"index.js\\", \\"scripts\\": { - \\"build\\": \\"npm run clean && ui5 build --include-task=generateCachebusterInfo && npm run zip\\", + \\"prestart\\": \\"npm run build\\", + \\"start\\": \\"fiori run --open /test/flp.html#app-preview\\", + \\"build\\": \\"npm run clean && ui5 build --config ui5-build.yaml --include-task=generateCachebusterInfo && npm run zip\\", \\"zip\\": \\"cd dist && npx bestzip ../test-cf-project.zip *\\", \\"clean\\": \\"npx rimraf test-cf-project.zip dist\\", \\"build-ui5\\": \\"npm explore @ui5/task-adaptation -- npm run rollup\\" @@ -1043,37 +1113,72 @@ UIAdaptation*.html ] }, \\"devDependencies\\": { - \\"@sap/ui5-builder-webide-extension\\": \\"1.0.x\\", - \\"@sapui5/ts-types\\": \\"^1.85.1\\", - \\"@ui5/cli\\": \\"^3.0.0\\", - \\"@ui5/task-adaptation\\": \\"^1.0.x\\", - \\"bestzip\\": \\"2.1.4\\", - \\"rimraf\\": \\"3.0.2\\" + \\"@sap/ui5-builder-webide-extension\\": \\"^1.1.9\\", + \\"@sapui5/ts-types\\": \\"^1.141.2\\", + \\"@sap/ux-ui5-tooling\\": \\"1\\", + \\"@ui5/cli\\": \\"^4.0.16\\", + \\"@ui5/task-adaptation\\": \\"^1.5.3\\", + \\"bestzip\\": \\"^2.2.1\\", + \\"rimraf\\": \\"^5.0.5\\" } } ", "state": "modified", }, - "test-cf-project/ui5.yaml": Object { + "test-cf-project/ui5-build.yaml": Object { "contents": "--- specVersion: \\"2.2\\" type: application metadata: name: test-cf-project +resources: + configuration: + propertiesFileSourceEncoding: UTF-8 builder: customTasks: - name: app-variant-bundler-build beforeTask: escapeNonAsciiCharacters configuration: + module: test-cf-project appHostId: app-host-id appName: Base App appVersion: 1.0.0 - moduleName: test-cf-project + html5RepoRuntime: runtime-guid org: org-guid space: space-guid - html5RepoRuntime: runtime-guid sapCloudService: test-solution - serviceInstanceName: test-service", + serviceInstanceName: test-service +", + "state": "modified", + }, + "test-cf-project/ui5.yaml": Object { + "contents": "--- +specVersion: \\"2.2\\" +type: application +metadata: + name: test-cf-project +resources: + configuration: + propertiesFileSourceEncoding: UTF-8 + paths: + webapp: dist +server: + customMiddleware: + - name: fiori-tools-proxy + afterMiddleware: compression + configuration: + ignoreCertErrors: false # If set to true, certificate errors will be ignored. E.g. self-signed certificates will be accepted + ui5: + path: + - /resources + - /test-resources + url: https://ui5.sap.com + - name: fiori-tools-preview + afterMiddleware: fiori-tools-proxy + configuration: + flp: + theme: sap_horizon +", "state": "modified", }, "test-cf-project/webapp/i18n/i18n.properties": Object { @@ -1196,22 +1301,6 @@ resources: service-plan: app-runtime _schema-version: '3.3' description: Test MTA Project for CF Writer Tests -", - "state": "modified", - }, - "test-cf-project/.adp/config.json": Object { - "contents": "{ - \\"componentname\\": \\"test.namespace\\", - \\"appvariant\\": \\"test-cf-project\\", - \\"layer\\": \\"CUSTOMER_BASE\\", - \\"isOVPApp\\": false, - \\"isFioriElement\\": false, - \\"environment\\": \\"CF\\", - \\"ui5Version\\": \\"1.120.0\\", - \\"cfApiUrl\\": \\"/test.cf.com\\", - \\"cfSpace\\": \\"space-guid\\", - \\"cfOrganization\\": \\"org-guid\\" -} ", "state": "modified", }, @@ -1232,7 +1321,9 @@ UIAdaptation*.html \\"description\\": \\"\\", \\"main\\": \\"index.js\\", \\"scripts\\": { - \\"build\\": \\"npm run clean && ui5 build --include-task=generateCachebusterInfo && npm run zip\\", + \\"prestart\\": \\"npm run build\\", + \\"start\\": \\"fiori run --open /test/flp.html#app-preview\\", + \\"build\\": \\"npm run clean && ui5 build --config ui5-build.yaml --include-task=generateCachebusterInfo && npm run zip\\", \\"zip\\": \\"cd dist && npx bestzip ../test-cf-project.zip *\\", \\"clean\\": \\"npx rimraf test-cf-project.zip dist\\", \\"build-ui5\\": \\"npm explore @ui5/task-adaptation -- npm run rollup\\" @@ -1248,37 +1339,72 @@ UIAdaptation*.html ] }, \\"devDependencies\\": { - \\"@sap/ui5-builder-webide-extension\\": \\"1.0.x\\", - \\"@sapui5/ts-types\\": \\"^1.85.1\\", - \\"@ui5/cli\\": \\"^3.0.0\\", - \\"@ui5/task-adaptation\\": \\"^1.0.x\\", - \\"bestzip\\": \\"2.1.4\\", - \\"rimraf\\": \\"3.0.2\\" + \\"@sap/ui5-builder-webide-extension\\": \\"^1.1.9\\", + \\"@sapui5/ts-types\\": \\"^1.141.2\\", + \\"@sap/ux-ui5-tooling\\": \\"1\\", + \\"@ui5/cli\\": \\"^4.0.16\\", + \\"@ui5/task-adaptation\\": \\"^1.5.3\\", + \\"bestzip\\": \\"^2.2.1\\", + \\"rimraf\\": \\"^5.0.5\\" } } ", "state": "modified", }, - "test-cf-project/ui5.yaml": Object { + "test-cf-project/ui5-build.yaml": Object { "contents": "--- specVersion: \\"2.2\\" type: application metadata: name: test-cf-project +resources: + configuration: + propertiesFileSourceEncoding: UTF-8 builder: customTasks: - name: app-variant-bundler-build beforeTask: escapeNonAsciiCharacters configuration: + module: test-cf-project appHostId: app-host-id appName: Base App appVersion: 1.0.0 - moduleName: test-cf-project + html5RepoRuntime: runtime-guid org: org-guid space: space-guid - html5RepoRuntime: runtime-guid sapCloudService: test-solution - serviceInstanceName: test-service", + serviceInstanceName: test-service +", + "state": "modified", + }, + "test-cf-project/ui5.yaml": Object { + "contents": "--- +specVersion: \\"2.2\\" +type: application +metadata: + name: test-cf-project +resources: + configuration: + propertiesFileSourceEncoding: UTF-8 + paths: + webapp: dist +server: + customMiddleware: + - name: fiori-tools-proxy + afterMiddleware: compression + configuration: + ignoreCertErrors: false # If set to true, certificate errors will be ignored. E.g. self-signed certificates will be accepted + ui5: + path: + - /resources + - /test-resources + url: https://ui5.sap.com + - name: fiori-tools-preview + afterMiddleware: fiori-tools-proxy + configuration: + flp: + theme: sap_horizon +", "state": "modified", }, "test-cf-project/webapp/i18n/i18n.properties": Object { diff --git a/packages/adp-tooling/test/unit/writer/project-utils.test.ts b/packages/adp-tooling/test/unit/writer/project-utils.test.ts index f817527f1d8..214f9be8349 100644 --- a/packages/adp-tooling/test/unit/writer/project-utils.test.ts +++ b/packages/adp-tooling/test/unit/writer/project-utils.test.ts @@ -4,11 +4,13 @@ import type { Editor } from 'mem-fs-editor'; import { getTypesPackage, getTypesVersion, getEsmTypesVersion, UI5_DEFAULT } from '@sap-ux/ui5-config'; -import type { AdpWriterConfig } from '../../../src'; +import { type AdpWriterConfig, AppRouterType, FlexLayer } from '../../../src'; import { writeTemplateToFolder, writeUI5Yaml, writeUI5DeployYaml, + writeCfUI5Yaml, + writeCfUI5BuildYaml, getPackageJSONInfo, getTypes } from '../../../src/writer/project-utils'; @@ -33,6 +35,43 @@ const mockedGetTypesPackage = getTypesPackage as jest.Mock; const mockedGetTypesVersion = getTypesVersion as jest.Mock; const mockedGetEsmTypesVersion = getEsmTypesVersion as jest.Mock; +const cfData = { + app: { + id: 'my.test.cf.app', + title: 'My Test CF App', + layer: FlexLayer.CUSTOMER_BASE, + namespace: 'my.test.cf.app', + manifest: {} as any + }, + baseApp: { + appId: 'the.original.app', + appName: 'Original App', + appVersion: '1.0.0', + appHostId: 'host123', + serviceName: 'service123', + title: 'Original App Title' + }, + cf: { + url: '/cf.example.com', + org: { Name: 'test-org', GUID: 'org-guid' }, + space: { Name: 'test-space', GUID: 'space-guid' }, + html5RepoRuntimeGuid: 'runtime-guid', + approuter: AppRouterType.MANAGED, + businessService: 'business-service' + }, + project: { + name: 'my-test-cf-project', + path: '/test/path', + folder: '/test/path/my-test-cf-project' + }, + ui5: { + version: '1.133.1' + }, + options: { + addStandaloneApprouter: false + } +}; + describe('Project Utils', () => { const data: AdpWriterConfig = { app: { @@ -254,4 +293,100 @@ describe('Project Utils', () => { } }); }); + + describe('writeCfUI5Yaml', () => { + beforeEach(() => { + jest.clearAllMocks(); + }); + + const projectPath = 'project'; + + const ui5YamlContent = `# yaml-language-server: $schema=https://sap.github.io/ui5-tooling/schema/ui5.yaml.json +specVersion: "3.0" +metadata: + name: ${cfData.app.id} + type: application`; + + const writeFilesSpy = jest.fn(); + const mockFs = { + write: writeFilesSpy, + read: jest.fn().mockReturnValue(ui5YamlContent) + }; + + it('should write ui5.yaml for CF project to the specified folder', async () => { + await writeCfUI5Yaml(projectPath, cfData, mockFs as unknown as Editor); + + expect(mockFs.read).toHaveBeenCalledWith(path.join(projectPath, 'ui5.yaml')); + expect(writeFilesSpy).toHaveBeenCalledWith( + path.join(projectPath, 'ui5.yaml'), + expect.stringContaining('propertiesFileSourceEncoding: UTF-8') + ); + expect(writeFilesSpy).toHaveBeenCalledWith( + path.join(projectPath, 'ui5.yaml'), + expect.stringContaining('paths:') + ); + expect(writeFilesSpy).toHaveBeenCalledWith( + path.join(projectPath, 'ui5.yaml'), + expect.stringContaining('webapp: dist') + ); + }); + + it('should throw error when reading ui5.yaml fails', async () => { + const errMsg = 'File not found'; + mockFs.read.mockImplementation(() => { + throw new Error(errMsg); + }); + + try { + await writeCfUI5Yaml(projectPath, cfData, mockFs as unknown as Editor); + fail('Expected error to be thrown'); + } catch (error) { + expect(error.message).toBe(`Could not write ui5.yaml file. Reason: ${errMsg}`); + } + }); + }); + + describe('writeCfUI5BuildYaml', () => { + beforeEach(() => { + jest.clearAllMocks(); + }); + + const projectPath = 'project'; + + const ui5BuildYamlContent = `# yaml-language-server: $schema=https://sap.github.io/ui5-tooling/schema/ui5-build.yaml.json +specVersion: "3.0" +metadata: + name: ${cfData.app.id} + type: application`; + + const writeFilesSpy = jest.fn(); + const mockFs = { + write: writeFilesSpy, + read: jest.fn().mockReturnValue(ui5BuildYamlContent) + }; + + it('should write ui5-build.yaml for CF project to the specified folder', async () => { + await writeCfUI5BuildYaml(projectPath, cfData, mockFs as unknown as Editor); + + expect(mockFs.read).toHaveBeenCalledWith(path.join(projectPath, 'ui5-build.yaml')); + expect(writeFilesSpy).toHaveBeenCalledWith( + path.join(projectPath, 'ui5-build.yaml'), + expect.stringContaining('propertiesFileSourceEncoding: UTF-8') + ); + }); + + it('should throw error when reading ui5-build.yaml fails', async () => { + const errMsg = 'File not found'; + mockFs.read.mockImplementation(() => { + throw new Error(errMsg); + }); + + try { + await writeCfUI5BuildYaml(projectPath, cfData, mockFs as unknown as Editor); + fail('Expected error to be thrown'); + } catch (error) { + expect(error.message).toBe(`Could not write ui5-build.yaml file. Reason: ${errMsg}`); + } + }); + }); }); diff --git a/packages/generator-adp/src/app/index.ts b/packages/generator-adp/src/app/index.ts index e55b3af7552..e34def5d0fd 100644 --- a/packages/generator-adp/src/app/index.ts +++ b/packages/generator-adp/src/app/index.ts @@ -27,10 +27,12 @@ import { isExtensionInstalled, sendTelemetry } from '@sap-ux/fiori-generator-shared'; +import { isAppStudio } from '@sap-ux/btp-utils'; import { ToolsLogger } from '@sap-ux/logger'; import type { Manifest } from '@sap-ux/project-access'; import type { AbapServiceProvider } from '@sap-ux/axios-extension'; -import { isInternalFeaturesSettingEnabled } from '@sap-ux/feature-toggle'; +import type { YeomanEnvironment } from '@sap-ux/fiori-generator-shared'; +import { isInternalFeaturesSettingEnabled, isFeatureEnabled } from '@sap-ux/feature-toggle'; import type { CfConfig, CfServicesAnswers, AttributesAnswers, ConfigAnswers, UI5Version } from '@sap-ux/adp-tooling'; import { EventName } from '../telemetryEvents'; @@ -63,7 +65,6 @@ import { type AttributePromptOptions, type JsonInput } from './types'; -import { isAppStudio } from '@sap-ux/btp-utils'; import { getProjectPathPrompt, getTargetEnvPrompt } from './questions/target-env'; const generatorTitle = 'Adaptation Project'; @@ -165,14 +166,14 @@ export default class extends Generator { * CF services answers. */ private cfServicesAnswers: CfServicesAnswers; - /** - * Indicates if the extension is installed. - */ - private readonly isExtensionInstalled: boolean; /** * Indicates if CF is installed. */ private cfInstalled: boolean; + /** + * Indicates if the CF feature is enabled. + */ + private readonly isCfFeatureEnabled: boolean; /** * Creates an instance of the generator. @@ -190,13 +191,18 @@ export default class extends Generator { this.options = opts; this.isMtaYamlFound = isMtaProject(process.cwd()) as boolean; - this.isExtensionInstalled = isInternalFeaturesSettingEnabled() - ? isExtensionInstalled(opts.vscode, 'SAP.adp-ve-bas-ext') - : false; + + this.isCfFeatureEnabled = isFeatureEnabled('sap.ux.appGenerator.testBetaFeatures.adpCfExperimental'); + this.logger.debug(`isCfFeatureEnabled: ${this.isCfFeatureEnabled}`); const jsonInputString = getFirstArgAsString(args); this.jsonInput = parseJsonInput(jsonInputString, this.logger); + // Force the generator to overwrite existing files without additional prompting + if ((this.env as unknown as YeomanEnvironment).conflicter) { + (this.env as unknown as YeomanEnvironment).conflicter.force = this.options.force ?? true; + } + if (!this.jsonInput) { this.env.lookup({ packagePatterns: ['@sap/generator-fiori', '@bas-dev/generator-extensibility-sub'] @@ -228,7 +234,7 @@ export default class extends Generator { const isInternalUsage = isInternalFeaturesSettingEnabled(); if (!this.jsonInput) { - const shouldShowTargetEnv = isAppStudio() && this.cfInstalled && this.isExtensionInstalled; + const shouldShowTargetEnv = isAppStudio() && this.cfInstalled && this.isCfFeatureEnabled; this.prompts.splice(0, 0, getWizardPages(shouldShowTargetEnv)); this.prompter = this._getOrCreatePrompter(); this.cfPrompter = new CFServicesPrompter(isInternalUsage, this.isCfLoggedIn, this.logger); @@ -446,7 +452,7 @@ export default class extends Generator { * Sets the target environment and updates related state accordingly. */ private async _determineTargetEnv(): Promise { - const hasRequiredExtensions = this.isExtensionInstalled && this.cfInstalled; + const hasRequiredExtensions = this.isCfFeatureEnabled && this.cfInstalled; if (isAppStudio() && hasRequiredExtensions) { await this._promptForTargetEnvironment(); diff --git a/packages/generator-adp/test/__snapshots__/app.test.ts.snap b/packages/generator-adp/test/__snapshots__/app.test.ts.snap index 6166781a9a2..ec58ad356fc 100644 --- a/packages/generator-adp/test/__snapshots__/app.test.ts.snap +++ b/packages/generator-adp/test/__snapshots__/app.test.ts.snap @@ -167,7 +167,7 @@ server: exports[`Adaptation Project Generator Integration Test CF Environment should generate an adaptation project successfully 1`] = ` "{ "fileName": "manifest", - "layer": "VENDOR", + "layer": "CUSTOMER_BASE", "fileType": "appdescr_variant", "reference": "test-app-id", "id": "app.variant", @@ -194,9 +194,6 @@ exports[`Adaptation Project Generator Integration Test CF Environment should gen exports[`Adaptation Project Generator Integration Test CF Environment should generate an adaptation project successfully 2`] = ` "#Make sure you provide a unique prefix to the newly added keys in this file, to avoid overriding of SAP Fiori application keys. - -# This is the resource bundle for App Title -#__ldi.translation.uuid=mocked-uuid #XTIT: Application name app.variant_sap.app.title=App Title" `; @@ -207,23 +204,57 @@ specVersion: "2.2" type: application metadata: name: app.variant +resources: + configuration: + propertiesFileSourceEncoding: UTF-8 + paths: + webapp: dist +server: + customMiddleware: + - name: fiori-tools-proxy + afterMiddleware: compression + configuration: + ignoreCertErrors: false # If set to true, certificate errors will be ignored. E.g. self-signed certificates will be accepted + ui5: + path: + - /resources + - /test-resources + url: https://ui5.sap.com + - name: fiori-tools-preview + afterMiddleware: fiori-tools-proxy + configuration: + flp: + theme: sap_horizon +" +`; + +exports[`Adaptation Project Generator Integration Test CF Environment should generate an adaptation project successfully 4`] = ` +"--- +specVersion: "2.2" +type: application +metadata: + name: app.variant +resources: + configuration: + propertiesFileSourceEncoding: UTF-8 builder: customTasks: - name: app-variant-bundler-build beforeTask: escapeNonAsciiCharacters configuration: + module: app.variant appHostId: test-app-host-id appName: test-app-name appVersion: test-app-version - moduleName: app.variant + html5RepoRuntime: test-guid org: org-guid space: space-guid - html5RepoRuntime: test-guid sapCloudService: test-solution - serviceInstanceName: test-service" + serviceInstanceName: test-service +" `; -exports[`Adaptation Project Generator Integration Test CF Environment should generate an adaptation project successfully 4`] = ` +exports[`Adaptation Project Generator Integration Test CF Environment should generate an adaptation project successfully 5`] = ` "ID: mta-project version: 1.0.0 modules: @@ -322,14 +353,16 @@ description: Test MTA Project for CF Writer Tests " `; -exports[`Adaptation Project Generator Integration Test CF Environment should generate an adaptation project successfully 5`] = ` +exports[`Adaptation Project Generator Integration Test CF Environment should generate an adaptation project successfully 6`] = ` "{ "name": "app.variant", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { - "build": "npm run clean && ui5 build --include-task=generateCachebusterInfo && npm run zip", + "prestart": "npm run build", + "start": "fiori run --open /test/flp.html#app-preview", + "build": "npm run clean && ui5 build --config ui5-build.yaml --include-task=generateCachebusterInfo && npm run zip", "zip": "cd dist && npx bestzip ../app.variant.zip *", "clean": "npx rimraf app.variant.zip dist", "build-ui5": "npm explore @ui5/task-adaptation -- npm run rollup" @@ -345,12 +378,13 @@ exports[`Adaptation Project Generator Integration Test CF Environment should gen ] }, "devDependencies": { - "@sap/ui5-builder-webide-extension": "1.0.x", - "@sapui5/ts-types": "^1.85.1", - "@ui5/cli": "^3.0.0", - "@ui5/task-adaptation": "^1.0.x", - "bestzip": "2.1.4", - "rimraf": "3.0.2" + "@sap/ui5-builder-webide-extension": "^1.1.9", + "@sapui5/ts-types": "^1.141.2", + "@sap/ux-ui5-tooling": "1", + "@ui5/cli": "^4.0.16", + "@ui5/task-adaptation": "^1.5.3", + "bestzip": "^2.2.1", + "rimraf": "^5.0.5" } } " diff --git a/packages/generator-adp/test/app.test.ts b/packages/generator-adp/test/app.test.ts index 7b8550e0d44..2f91b0d5525 100644 --- a/packages/generator-adp/test/app.test.ts +++ b/packages/generator-adp/test/app.test.ts @@ -36,7 +36,7 @@ import { } from '@sap-ux/adp-tooling'; import { type AbapServiceProvider, AdaptationProjectType } from '@sap-ux/axios-extension'; import { isAppStudio } from '@sap-ux/btp-utils'; -import { isInternalFeaturesSettingEnabled } from '@sap-ux/feature-toggle'; +import { isInternalFeaturesSettingEnabled, isFeatureEnabled } from '@sap-ux/feature-toggle'; import { isCli, isExtensionInstalled, sendTelemetry } from '@sap-ux/fiori-generator-shared'; import type { ToolsLogger } from '@sap-ux/logger'; import * as Logger from '@sap-ux/logger'; @@ -61,7 +61,8 @@ import { CFServicesPrompter } from '../src/app/questions/cf-services'; jest.mock('@sap-ux/feature-toggle', () => ({ ...jest.requireActual('@sap-ux/feature-toggle'), - isInternalFeaturesSettingEnabled: jest.fn() + isInternalFeaturesSettingEnabled: jest.fn(), + isFeatureEnabled: jest.fn() })); jest.mock('../src/app/questions/helper/default-values.ts', () => ({ @@ -312,6 +313,7 @@ const createServicesMock = createServices as jest.MockedFunction; +const mockIsFeatureEnabled = isFeatureEnabled as jest.MockedFunction; describe('Adaptation Project Generator Integration Test', () => { jest.setTimeout(60000); @@ -324,6 +326,7 @@ describe('Adaptation Project Generator Integration Test', () => { beforeEach(() => { fs.mkdirSync(testOutputDir, { recursive: true }); mockIsInternalFeaturesSettingEnabled.mockReturnValue(false); + mockIsFeatureEnabled.mockReturnValue(false); isExtensionInstalledMock.mockReturnValueOnce(true); loadAppsMock.mockResolvedValue(apps); jest.spyOn(ConfigPrompter.prototype, 'provider', 'get').mockReturnValue(dummyProvider); @@ -567,8 +570,8 @@ describe('Adaptation Project Generator Integration Test', () => { mockIsAppStudio.mockReturnValue(true); jest.spyOn(Date, 'now').mockReturnValue(1234567890); - mockIsInternalFeaturesSettingEnabled.mockReturnValue(true); - isExtensionInstalledMock.mockReturnValue(true); + mockIsInternalFeaturesSettingEnabled.mockReturnValue(false); + mockIsFeatureEnabled.mockReturnValue(true); isCfInstalledMock.mockResolvedValue(true); isLoggedInCfMock.mockResolvedValue(true); loadAppsMock.mockResolvedValue(apps); @@ -624,23 +627,27 @@ describe('Adaptation Project Generator Integration Test', () => { const manifestPath = join(projectFolder, 'webapp', 'manifest.appdescr_variant'); const i18nPath = join(projectFolder, 'webapp', 'i18n', 'i18n.properties'); const ui5Yaml = join(projectFolder, 'ui5.yaml'); + const ui5BuildYaml = join(projectFolder, 'ui5-build.yaml'); const mtaYaml = join(cfTestOutputDir, 'mta.yaml'); const packageJson = join(projectFolder, 'package.json'); expect(fs.existsSync(manifestPath)).toBe(true); expect(fs.existsSync(i18nPath)).toBe(true); expect(fs.existsSync(ui5Yaml)).toBe(true); + expect(fs.existsSync(ui5BuildYaml)).toBe(true); expect(fs.existsSync(mtaYaml)).toBe(true); expect(fs.existsSync(packageJson)).toBe(true); const manifestContent = fs.readFileSync(manifestPath, 'utf8'); const i18nContent = fs.readFileSync(i18nPath, 'utf8'); const ui5Content = fs.readFileSync(ui5Yaml, 'utf8'); + const ui5BuildContent = fs.readFileSync(ui5BuildYaml, 'utf8'); const mtaContent = fs.readFileSync(mtaYaml, 'utf8'); const packageJsonContent = fs.readFileSync(packageJson, 'utf8'); expect(manifestContent).toMatchSnapshot(); expect(i18nContent).toMatchSnapshot(); expect(ui5Content).toMatchSnapshot(); + expect(ui5BuildContent).toMatchSnapshot(); expect(mtaContent).toMatchSnapshot(); expect(packageJsonContent).toMatchSnapshot(); });