Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 14 additions & 1 deletion tests/integration/adaptation-editor/src/fixture.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import {
type ProjectConfig
} from './project';
import { satisfies } from 'semver';
import { generateFeV4Project } from './project/builder';

export type TestOptions = {
previewFrame: FrameLocator;
Expand Down Expand Up @@ -97,7 +98,19 @@ export const test = base.extend<TestOptions, WorkerFixtures>({

if (projectConfig.type === 'generated') {
if (projectConfig.kind === 'adp') {
await generateUi5Project(projectConfig.baseApp, workerInfo.parallelIndex.toString(), ui5Version);
if (projectConfig.baseApp.kind === 'fe-v4') {
await generateFeV4Project(
projectConfig.baseApp,
workerInfo.parallelIndex.toString(),
ui5Version
);
} else {
await generateUi5Project(
projectConfig.baseApp,
workerInfo.parallelIndex.toString(),
ui5Version
);
}
const root = await generateAdpProject(
projectConfig,
workerInfo.parallelIndex.toString(),
Expand Down
3 changes: 3 additions & 0 deletions tests/integration/adaptation-editor/src/global-setup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,9 @@ async function globalSetup(): Promise<void> {
},
{
name: 'sap.ui.generic.app'
},
{
name: 'sap.fe.templates'
}
]
},
Expand Down
117 changes: 113 additions & 4 deletions tests/integration/adaptation-editor/src/project/builder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ import { join } from 'node:path';
import type { Manifest } from '@sap-ux/project-access';
import { YamlDocument } from '@sap-ux/yaml';
import template from './templates/manifest-fe-v2.json';
import type { FIORI_ELEMENTS_V2, ADP_FIORI_ELEMENTS_V2 } from './projects';
import feV4ManifestTemplate from './templates/manifest-fe-v4.json';
import type { FIORI_ELEMENTS_V2, ADP_FIORI_ELEMENTS_V2, ADP_FIORI_ELEMENTS_V4 } from './projects';
import { existsSync } from 'node:fs';

export interface ProjectParameters {
Expand Down Expand Up @@ -97,21 +98,59 @@ export function createV2Manifest(userParameters: ProjectParameters, workerId: st
return result;
}

export function createV4Manifest(userParameters: ProjectParameters, workerId: string): Manifest {
const { id, mainServiceUri, entitySet } = getProjectParametersWithDefaults(userParameters);
const result = structuredClone(feV4ManifestTemplate) as Manifest;
result['sap.app'].id = id + '.' + workerId;
result['sap.app'].dataSources!.mainService.uri = mainServiceUri;
result['sap.app'].sourceTemplate!.id = 'preview-middleware-tests';
result['sap.app'].sourceTemplate!.version = '1.0.0';
result['sap.app'].sourceTemplate!.toolsId = id;
const listTarget = `${entitySet}List`;

result['sap.ui5']!.routing = {
config: {},
routes: [
{
'pattern': ':?query:',
'name': listTarget,
'target': listTarget
}
],
targets: {
[listTarget]: {
'type': 'Component',
id: listTarget,
name: 'sap.fe.templates.ListReport',
options: {
settings: {
contextPath: `/${entitySet}`
}
}
}
}
};

return result;
}

/**
* Creates a YAML file for the project.
*
* @param userParameters - The project parameters provided by the user.
* @param ui5Version - The UI5 version to be used.
* @param templateName - The name of the template file to be used.
* @param workerId - The unique worker ID for the project.
* @returns A string representation of the YAML file content.
*/
export async function createYamlFile(
userParameters: ProjectParameters,
ui5Version: string,
templateName: string,
workerId: string
): Promise<string> {
const { id, mainServiceUri } = getProjectParametersWithDefaults(userParameters);
const template = await readFile(join(__dirname, 'templates', 'ui5.yaml'), 'utf-8');
const template = await readFile(join(__dirname, 'templates', templateName), 'utf-8');
const document = await YamlDocument.newInstance(template);

document.setIn({ path: 'metadata.name', value: id + '.' + workerId });
Expand Down Expand Up @@ -144,6 +183,19 @@ export function createComponent(userParameters: ProjectParameters, workerId: str
);`;
}

export function createV4Component(userParameters: ProjectParameters, workerId: string): string {
const { id } = getProjectParametersWithDefaults(userParameters);
return `sap.ui.define(["sap/fe/core/AppComponent"], function (Component) {
"use strict";
return Component.extend("${id}.${workerId}.Component", {
metadata: {
manifest: "json"
}
});
}
);`;
}

/**
* Creates a package.json file for the project.
*
Expand All @@ -163,6 +215,56 @@ export function createPackageJson(id: string): string {
`;
}

export async function generateFeV4Project(
projectConfig: typeof FIORI_ELEMENTS_V2,
workerId: string,
ui5Version: string
): Promise<string> {
const { id } = getProjectParametersWithDefaults(projectConfig);
const root = join(__dirname, '..', '..', 'fixtures-copy', `${projectConfig.id}.${workerId}`);
const yamlContent = await createYamlFile(projectConfig, ui5Version, 'ui5-fe-v4.yaml', workerId);
const manifestContent = JSON.stringify(createV4Manifest(projectConfig, workerId), undefined, 2);

if (!existsSync(root)) {
await mkdir(root, { recursive: true });
}

if (!existsSync(join(root, 'webapp'))) {
await mkdir(join(root, 'webapp'), { recursive: true });
}

if (!existsSync(join(root, 'data'))) {
await mkdir(join(root, 'data'), { recursive: true });
}

await Promise.all([
writeFile(join(root, 'ui5.yaml'), yamlContent),
writeFile(join(root, 'package.json'), createPackageJson(id + workerId)),
writeFile(join(root, 'webapp', 'manifest.json'), manifestContent),
writeFile(join(root, 'webapp', 'Component.js'), createV4Component(projectConfig, workerId)),
writeFile(join(root, 'service.cds'), await readFile(join(__dirname, 'templates', 'service.cds'), 'utf-8')),
writeFile(
join(root, 'data', 'RootEntity.json'),
JSON.stringify(
[
{
'ID': 1,
'StringProperty': 'Hello',
'NumberProperty': 78.777,
'IntegerProperty': 89,
'BooleanProperty': true,
'Currency': 'JPY',
'TextProperty': 'Description'
}
],
undefined,
2
)
)
]);
return root;
}

/**
* Generates a UI5 project with the given configuration.
*
Expand All @@ -178,7 +280,7 @@ export async function generateUi5Project(
): Promise<string> {
const { id } = getProjectParametersWithDefaults(projectConfig);
const root = join(__dirname, '..', '..', 'fixtures-copy', `${projectConfig.id}.${workerId}`);
const yamlContent = await createYamlFile(projectConfig, ui5Version, workerId);
const yamlContent = await createYamlFile(projectConfig, ui5Version, 'ui5.yaml', workerId);
const manifestContent = JSON.stringify(createV2Manifest(projectConfig, workerId), undefined, 2);

if (!existsSync(root)) {
Expand Down Expand Up @@ -271,6 +373,7 @@ function getAdpProjectParametersWithDefaults(parameters: AdpProjectParameters):
*
* @param userParameters - The ADP project parameters provided by the user.
* @param ui5Version - The UI5 version to be used.
* @param odataVersion - The OData version to be used.
* @param backendUrl - The backend URL for the ADP project.
* @param mainServiceUri - The main service URI for the ADP project.
* @param livereloadPort - The livereload port for the ADP project.
Expand All @@ -279,6 +382,7 @@ function getAdpProjectParametersWithDefaults(parameters: AdpProjectParameters):
async function createAdpYamlFile(
userParameters: AdpProjectParameters,
ui5Version: string,
odataVersion: 'v2' | 'v4',
backendUrl: string,
mainServiceUri: string,
livereloadPort: number
Expand All @@ -288,6 +392,10 @@ async function createAdpYamlFile(
const document = await YamlDocument.newInstance(template);

document.setIn({ path: 'metadata.name', value: id });
document.setIn({
path: 'server.customMiddleware.0.configuration.metadataProcessor.options.odataVersion',
value: odataVersion
});
document.setIn({ path: 'server.customMiddleware.0.configuration.services.urlPath', value: mainServiceUri });
document.setIn({
path: 'server.customMiddleware.1.configuration.port',
Expand Down Expand Up @@ -332,7 +440,7 @@ export async function createAppDescriptorVariant(
* @returns The root path of the generated ADP project.
*/
export async function generateAdpProject(
projectConfig: typeof ADP_FIORI_ELEMENTS_V2,
projectConfig: typeof ADP_FIORI_ELEMENTS_V2 | typeof ADP_FIORI_ELEMENTS_V4,
workerId: string,
ui5Version: string,
backendUrl: string,
Expand All @@ -343,6 +451,7 @@ export async function generateAdpProject(
const yamlContent = await createAdpYamlFile(
projectConfig,
ui5Version,
projectConfig.baseApp.kind === 'fe-v4' ? 'v4' : 'v2',
backendUrl,
projectConfig.baseApp.mainServiceUri,
livereloadPort
Expand Down
23 changes: 19 additions & 4 deletions tests/integration/adaptation-editor/src/project/projects.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ export interface ProjectConfigBase {

export interface GeneratedBaseProjectConfig {
type: 'generated';
kind: 'ui5';
kind: 'ui5' | 'fe-v4' | 'fe-v2';
id: string;
mainServiceUri: string;
entitySet: string;
Expand All @@ -30,7 +30,7 @@ export const SIMPLE_APP: ProjectConfigBase = {

export const FIORI_ELEMENTS_V2: GeneratedBaseProjectConfig = {
type: 'generated',
kind: 'ui5',
kind: 'fe-v2',
id: 'fiori.elements.v2',
mainServiceUri: '/sap/opu/odata/sap/SERVICE/',
entitySet: 'RootEntity'
Expand All @@ -43,7 +43,22 @@ export const ADP_FIORI_ELEMENTS_V2: GeneratedAdpProjectConfig = {
id: 'adp.fiori.elements.v2'
};

export type UI5ProjectConfig = typeof SIMPLE_APP | typeof FIORI_ELEMENTS_V2;
export type AdpProjectConfig = typeof ADP_FIORI_ELEMENTS_V2;
export const FIORI_ELEMENTS_V4: GeneratedBaseProjectConfig = {
type: 'generated',
kind: 'fe-v4',
id: 'fiori.elements.v4',
mainServiceUri: '/sap/opu/odata/sap/SERVICE/',
entitySet: 'RootEntity'
};

export const ADP_FIORI_ELEMENTS_V4: GeneratedAdpProjectConfig = {
type: 'generated',
kind: 'adp',
baseApp: FIORI_ELEMENTS_V4,
id: 'adp.fiori.elements.v4'
};

export type UI5ProjectConfig = typeof SIMPLE_APP | typeof FIORI_ELEMENTS_V2 | typeof FIORI_ELEMENTS_V4;
export type AdpProjectConfig = typeof ADP_FIORI_ELEMENTS_V2 | typeof ADP_FIORI_ELEMENTS_V4;

export type ProjectConfig = UI5ProjectConfig | AdpProjectConfig;
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
{
"_version": "1.59.0",
"sap.app": {
"id": "incidents",
"type": "application",
"i18n": "i18n/i18n.properties",
"applicationVersion": {
"version": "0.0.1"
},
"title": "{{appTitle}}",
"description": "{{appDescription}}",
"resources": "resources.json",
"sourceTemplate": {
"id": "@sap/generator-fiori:lrop",
"version": "1.14.0",
"toolsId": "e6c2408d-f9dd-466a-9230-aeea9de61c25"
},
"dataSources": {
"mainService": {
"uri": "/odata/v4/incident/",
"type": "OData",
"settings": {
"annotations": [],
"odataVersion": "4.0"
}
}
}
},
"sap.ui": {
"technology": "UI5",
"icons": {
"icon": "",
"favIcon": "",
"phone": "",
"phone@2": "",
"tablet": "",
"tablet@2": ""
},
"deviceTypes": {
"desktop": true,
"tablet": true,
"phone": true
}
},
"sap.ui5": {
"flexEnabled": true,
"dependencies": {
"minUI5Version": "1.71.0",
"libs": {
"sap.m": {},
"sap.ui.core": {},
"sap.ushell": {},
"sap.fe.templates": {}
}
},
"contentDensities": {
"compact": true,
"cozy": true
},
"models": {
"i18n": {
"type": "sap.ui.model.resource.ResourceModel",
"settings": {
"bundleName": "incidents.i18n.i18n"
}
},
"": {
"dataSource": "mainService",
"preload": true,
"settings": {
"operationMode": "Server",
"synchronizationMode": "None",
"autoExpandSelect": true,
"earlyRequests": true
}
},
"@i18n": {
"type": "sap.ui.model.resource.ResourceModel",
"uri": "i18n/i18n.properties"
}
},
"resources": {
"css": []
}
},
"sap.fiori": {
"registrationIds": [],
"archeType": "transactional"
}
}

Loading
Loading