diff --git a/.changeset/light-moles-search.md b/.changeset/light-moles-search.md new file mode 100644 index 0000000000..b8808711d9 --- /dev/null +++ b/.changeset/light-moles-search.md @@ -0,0 +1,6 @@ +--- +"@sap-ux/adp-tooling": patch +"@sap-ux/preview-middleware": patch +--- + +fix: refresh descriptor after manifest changes diff --git a/packages/adp-tooling/src/preview/adp-preview.ts b/packages/adp-tooling/src/preview/adp-preview.ts index f16549cad3..9713ccf755 100644 --- a/packages/adp-tooling/src/preview/adp-preview.ts +++ b/packages/adp-tooling/src/preview/adp-preview.ts @@ -12,7 +12,6 @@ import RoutesHandler from './routes-handler'; import type { AdpPreviewConfig, CommonChangeProperties, DescriptorVariant, OperationType } from '../types'; import type { Editor } from 'mem-fs-editor'; import { addXmlFragment, isAddXMLChange, moduleNameContentMap, tryFixChange } from './change-handler'; - declare global { // false positive, const can't be used here https://github.com/eslint/eslint/issues/15896 // eslint-disable-next-line no-var @@ -119,9 +118,12 @@ export class AdpPreview { /** * Synchronize local changes with the backend. - * + * The descriptor is refreshed only if the global flag is set to true. */ async sync(): Promise { + if (!global.__SAP_UX_MANIFEST_SYNC_REQUIRED__ && this.mergedDescriptor) { + return; + } if (!this.lrep || !this.descriptorVariantId) { throw new Error('Not initialized'); } @@ -133,6 +135,7 @@ export class AdpPreview { const buffer = zip.toBuffer(); this.mergedDescriptor = (await this.lrep.mergeAppDescriptorVariant(buffer, '//'))[this.descriptorVariantId]; + global.__SAP_UX_MANIFEST_SYNC_REQUIRED__ = false; } /** @@ -144,10 +147,7 @@ export class AdpPreview { */ async proxy(req: Request, res: Response, next: NextFunction): Promise { if (req.path === '/manifest.json') { - if (global.__SAP_UX_MANIFEST_SYNC_REQUIRED__) { - await this.sync(); - global.__SAP_UX_MANIFEST_SYNC_REQUIRED__ = false; - } + await this.sync(); res.status(200); res.send(JSON.stringify(this.descriptor.manifest, undefined, 2)); } else if (req.path === '/Component-preload.js') { diff --git a/packages/adp-tooling/test/unit/preview/adp-preview.test.ts b/packages/adp-tooling/test/unit/preview/adp-preview.test.ts index 485f4671c3..282f3e7316 100644 --- a/packages/adp-tooling/test/unit/preview/adp-preview.test.ts +++ b/packages/adp-tooling/test/unit/preview/adp-preview.test.ts @@ -120,21 +120,23 @@ describe('AdaptationProject', () => { } }; - beforeAll(() => { - nock(backend) - .get((path) => path.startsWith('/sap/bc/lrep/actions/getcsrftoken/')) - .reply(200) - .persist(true); - nock(backend) - .put('/sap/bc/lrep/appdescr_variant_preview/?workspacePath=//') - .reply(200, { - 'my.adaptation': mockMergedDescriptor - }) - .persist(true); - }); - const logger = new ToolsLogger(); describe('init', () => { + beforeAll(() => { + nock(backend) + .get((path) => path.startsWith('/sap/bc/lrep/actions/getcsrftoken/')) + .reply(200) + .persist(true); + nock(backend) + .put('/sap/bc/lrep/appdescr_variant_preview/?workspacePath=//') + .reply(200, { + 'my.adaptation': mockMergedDescriptor + }) + .persist(true); + }); + afterAll(() => { + nock.cleanAll(); + }); test('default (no) config', async () => { const adp = new AdpPreview( { @@ -180,7 +182,37 @@ describe('AdaptationProject', () => { }); }); describe('sync', () => { + let secondCall: boolean = false; + beforeAll(() => { + nock(backend) + .get((path) => path.startsWith('/sap/bc/lrep/actions/getcsrftoken/')) + .reply(200) + .persist(true); + nock(backend) + .put('/sap/bc/lrep/appdescr_variant_preview/?workspacePath=//') + .reply(200, () => { + if (secondCall) { + return { + 'my.adaptation': 'testDescriptor' + }; + } + return { + 'my.adaptation': mockMergedDescriptor + }; + }) + .persist(true); + }); + + afterAll(() => { + nock.cleanAll(); + }); + + afterEach(() => { + global.__SAP_UX_MANIFEST_SYNC_REQUIRED__ = false; + }); + test('updates merged descriptor', async () => { + global.__SAP_UX_MANIFEST_SYNC_REQUIRED__ = true; const adp = new AdpPreview( { target: { @@ -203,11 +235,102 @@ describe('AdaptationProject', () => { await adp.sync(); expect(adp.descriptor).toBeDefined(); }); + + test('skip updating the merge descriptor if no manifest changes and descriptor was already fetched', async () => { + const adp = new AdpPreview( + { + target: { + url: backend + } + }, + mockProject as unknown as ReaderCollection, + middlewareUtil, + logger + ); + + mockProject.byGlob.mockResolvedValueOnce([ + { + getPath: () => '/manifest.appdescr_variant', + getBuffer: () => Buffer.from(descriptorVariant) + } + ]); + await adp.init(JSON.parse(descriptorVariant)); + (adp as any).mergedDescriptor = undefined; + await adp.sync(); + expect(adp.descriptor).toEqual(mockMergedDescriptor); + secondCall = true; + await adp.sync(); + secondCall = false; + expect(adp.descriptor).not.toEqual('testDescriptor'); + }); + + test('update descriptor if no manifest changes, but this is first descriptor fetch', async () => { + const adp = new AdpPreview( + { + target: { + url: backend + } + }, + mockProject as unknown as ReaderCollection, + middlewareUtil, + logger + ); + + mockProject.byGlob.mockResolvedValueOnce([ + { + getPath: () => '/manifest.appdescr_variant', + getBuffer: () => Buffer.from(descriptorVariant) + } + ]); + await adp.init(JSON.parse(descriptorVariant)); + (adp as any).mergedDescriptor = undefined; + await adp.sync(); + expect(adp.descriptor).toEqual(mockMergedDescriptor); + }); + + test('update descriptor if descriptor was already fetched, but there are manifest changes', async () => { + const adp = new AdpPreview( + { + target: { + url: backend + } + }, + mockProject as unknown as ReaderCollection, + middlewareUtil, + logger + ); + + mockProject.byGlob.mockResolvedValueOnce([ + { + getPath: () => '/manifest.appdescr_variant', + getBuffer: () => Buffer.from(descriptorVariant) + } + ]); + await adp.init(JSON.parse(descriptorVariant)); + (adp as any).mergedDescriptor = undefined; + await adp.sync(); + expect(adp.descriptor).toEqual(mockMergedDescriptor); + secondCall = true; + global.__SAP_UX_MANIFEST_SYNC_REQUIRED__ = true; + await adp.sync(); + secondCall = false; + expect(adp.descriptor).toEqual('testDescriptor'); + }); }); describe('proxy', () => { let server: SuperTest; const next = jest.fn().mockImplementation((_req, res) => res.status(200).send()); beforeAll(async () => { + nock(backend) + .get((path) => path.startsWith('/sap/bc/lrep/actions/getcsrftoken/')) + .reply(200) + .persist(true); + nock(backend) + .put('/sap/bc/lrep/appdescr_variant_preview/?workspacePath=//') + .reply(200, { + 'my.adaptation': mockMergedDescriptor + }) + .persist(true); const adp = new AdpPreview( { target: { @@ -235,6 +358,10 @@ describe('AdaptationProject', () => { server = supertest(app); }); + afterAll(() => { + nock.cleanAll(); + }); + afterEach(() => { global.__SAP_UX_MANIFEST_SYNC_REQUIRED__ = false; }); @@ -321,6 +448,16 @@ describe('AdaptationProject', () => { describe('addApis', () => { let server: SuperTest; beforeAll(async () => { + nock(backend) + .get((path) => path.startsWith('/sap/bc/lrep/actions/getcsrftoken/')) + .reply(200) + .persist(true); + nock(backend) + .put('/sap/bc/lrep/appdescr_variant_preview/?workspacePath=//') + .reply(200, { + 'my.adaptation': mockMergedDescriptor + }) + .persist(true); const adp = new AdpPreview( { target: { diff --git a/packages/preview-middleware/src/base/config.ts b/packages/preview-middleware/src/base/config.ts index 3d41e79a06..77c6ffb74f 100644 --- a/packages/preview-middleware/src/base/config.ts +++ b/packages/preview-middleware/src/base/config.ts @@ -206,23 +206,11 @@ function getFlexSettings(): TemplateConfig['ui5']['flex'] { * @param manifest manifest of the additional target app * @param app configuration for the preview * @param logger logger instance - * @param descriptor descriptor of the additional target app */ -export async function addApp( - templateConfig: TemplateConfig, - manifest: Partial, - app: App, - logger: Logger, - descriptor?: MergedAppDescriptor -) { +export async function addApp(templateConfig: TemplateConfig, manifest: Partial, app: App, logger: Logger) { const id = manifest['sap.app']?.id ?? ''; - app.intent ??= { - object: id.replace(/\./g, ''), - action: 'preview' - }; - - const appName = `${app.intent?.object}-${app.intent?.action}`; + const appName = getAppName(manifest, app.intent); templateConfig.ui5.resources[id] = app.target; templateConfig.apps[appName] = { title: (await getI18nTextFromProperty(app.local, manifest['sap.app']?.title, logger)) ?? id, @@ -231,9 +219,24 @@ export async function addApp( applicationType: 'URL', url: app.target }; - if (descriptor) { - templateConfig.apps[appName].applicationDependencies = descriptor; - } +} + +/** + * Get the application name based on the manifest and app configuration. + * + * @param manifest - The application manifest. + * @param intent - The app configuration. + * @returns The application name. + */ +export function getAppName(manifest: Partial, intent?: Intent): string { + const id = manifest['sap.app']?.id ?? ''; + + intent ??= { + object: id.replace(/\./g, ''), + action: 'preview' + }; + + return `${intent?.object}-${intent?.action}`; } /** diff --git a/packages/preview-middleware/src/base/flp.ts b/packages/preview-middleware/src/base/flp.ts index d9e3ab7e48..83fc884ec8 100644 --- a/packages/preview-middleware/src/base/flp.ts +++ b/packages/preview-middleware/src/base/flp.ts @@ -18,7 +18,6 @@ import { type OperationType } from '@sap-ux/adp-tooling'; import { isAppStudio, exposePort } from '@sap-ux/btp-utils'; -import type { MergedAppDescriptor } from '@sap-ux/axios-extension'; import { FeatureToggleAccess } from '@sap-ux/feature-toggle'; import { deleteChange, readChanges, writeChange } from './flex'; @@ -30,7 +29,8 @@ import { PREVIEW_URL, type TemplateConfig, createTestTemplateConfig, - addApp + addApp, + getAppName } from './config'; const DEVELOPER_MODE_CONFIG = new Map([ @@ -63,6 +63,8 @@ type OnChangeRequestHandler = ( * Class handling preview of a sandbox FLP. */ export class FlpSandbox { + private adp?: AdpPreview; + private manifest: Manifest; protected onChangeRequest: OnChangeRequestHandler | undefined; protected templateConfig: TemplateConfig; public readonly config: FlpConfig; @@ -106,18 +108,20 @@ export class FlpSandbox { * @param manifest application manifest * @param componentId optional componentId e.g. for adaptation projects * @param resources optional additional resource mappings - * @param descriptor optional additional descriptor mappings + * @param adp optional reference to the ADP tooling */ async init( manifest: Manifest, componentId?: string, resources: Record = {}, - descriptor?: MergedAppDescriptor + adp?: AdpPreview ): Promise { this.createFlexHandler(); this.config.libs ??= await this.hasLocateReuseLibsScript(); - const id = manifest['sap.app'].id; + const id = manifest['sap.app']?.id ?? ''; this.templateConfig = createFlpTemplateConfig(this.config, manifest, resources); + this.adp = adp; + this.manifest = manifest; await addApp( this.templateConfig, @@ -128,8 +132,7 @@ export class FlpSandbox { local: '.', intent: this.config.intent }, - this.logger, - descriptor + this.logger ); this.addStandardRoutes(); if (this.rta) { @@ -158,10 +161,12 @@ export class FlpSandbox { * @param editor editor configuration * @returns FLP sandbox html */ - private generateSandboxForEditor(rta: RtaConfig, editor: Editor): string { + private async generateSandboxForEditor(rta: RtaConfig, editor: Editor): Promise { const defaultGenerator = editor.developerMode ? '@sap-ux/control-property-editor' : '@sap-ux/preview-middleware'; + + await this.setApplicationDependencies(); const config = { ...this.templateConfig }; /* sap.ui.rta needs to be added to the list of preload libs for variants management and adaptation projects */ if (!config.ui5.libs.includes('sap.ui.rta')) { @@ -185,6 +190,20 @@ export class FlpSandbox { return render(template, config); } + /** + * Sets application dependencies in the template configuration. + * The descriptor is refreshed if the global flag is set. + * + * @returns Promise that resolves when the application dependencies are set + */ + private async setApplicationDependencies(): Promise { + if (this.adp) { + await this.adp.sync(); + const appName = getAppName(this.manifest, this.config.intent); + this.templateConfig.apps[appName].applicationDependencies = this.adp.descriptor; + } + } + /** * Add additional routes for configured editors. * @@ -227,7 +246,7 @@ export class FlpSandbox { this.router.use(`${path}editor`, serveStatic(cpe)); } - this.router.get(previewUrl, (req: Request, res: Response) => { + this.router.get(previewUrl, async (req: Request, res: Response) => { if (!req.query['fiori-tools-rta-mode']) { // Redirect to the same URL but add the necessary parameter const params = JSON.parse(JSON.stringify(req.query)); @@ -237,7 +256,7 @@ export class FlpSandbox { res.redirect(302, `${previewUrl}?${new URLSearchParams(params)}`); return; } - const html = this.generateSandboxForEditor(rta, editor).replace( + const html = (await this.generateSandboxForEditor(rta, editor)).replace( '', `\n` ); @@ -554,7 +573,7 @@ export async function initAdp( const descriptor = adp.descriptor; const { name, manifest } = descriptor; - await flp.init(manifest, name, adp.resources, descriptor); + await flp.init(manifest, name, adp.resources, adp); flp.router.use(adp.descriptor.url, adp.proxy.bind(adp) as RequestHandler); flp.addOnChangeRequestHandler(adp.onChangeRequest.bind(adp)); flp.router.use(json()); diff --git a/packages/preview-middleware/test/unit/base/__snapshots__/flp.test.ts.snap b/packages/preview-middleware/test/unit/base/__snapshots__/flp.test.ts.snap index 3d80758fb7..91caff7e98 100644 --- a/packages/preview-middleware/test/unit/base/__snapshots__/flp.test.ts.snap +++ b/packages/preview-middleware/test/unit/base/__snapshots__/flp.test.ts.snap @@ -343,74 +343,6 @@ Object { } `; -exports[`FlpSandbox init with passed descriptor 1`] = ` -Object { - "apps": Object { - "app-preview": Object { - "additionalInformation": "SAPUI5.Component=myComponent", - "applicationDependencies": Object { - "asyncHints": Object { - "requests": Array [ - Object { - "url": "myRequestUrl", - }, - ], - }, - "components": Array [ - Object { - "name": "myComponent", - "url": "myComponentUrl", - }, - ], - "libs": Array [ - Object { - "name": "myLib", - "url": "myLibUrl", - }, - ], - }, - "applicationType": "URL", - "description": "", - "title": "my.id", - "url": "..", - }, - }, - "basePath": "..", - "init": undefined, - "locateReuseLibsScript": false, - "ui5": Object { - "bootstrapOptions": "", - "flex": Array [ - Object { - "connector": "LrepConnector", - "layers": Array [], - "url": "/sap/bc/lrep", - }, - Object { - "applyConnector": "custom.connectors.WorkspaceConnector", - "custom": true, - "writeConnector": "custom.connectors.WorkspaceConnector", - }, - Object { - "connector": "LocalStorageConnector", - "layers": Array [ - "CUSTOMER", - "USER", - ], - }, - ], - "libs": "sap.m,sap.ui.core,sap.ushell", - "resources": Object { - "my.id": "..", - "myResources1": "myResourcesUrl1", - "myResources2": "myResourcesUrl2", - "open.ux.preview.client": "../preview/client", - }, - "theme": "sap_horizon", - }, -} -`; - exports[`FlpSandbox router GET /preview/api/changes 1`] = `"{\\"sap.ui.fl.myid\\":{\\"id\\":\\"myId\\"}}"`; exports[`FlpSandbox router custom opa5 path test/integration/opaTests.qunit.html 1`] = ` @@ -584,6 +516,156 @@ exports[`FlpSandbox router editor with config 1`] = ` exports[`FlpSandbox router rta 1`] = `"Found. Redirecting to /my/rta.html?sap-ui-xx-viewCache=false&fiori-tools-rta-mode=true&sap-ui-rta-skip-flex-validation=true"`; +exports[`FlpSandbox router rta with adp instance 1`] = ` +Object { + "apps": Object { + "app-preview": Object { + "additionalInformation": "SAPUI5.Component=myComponent", + "applicationType": "URL", + "description": "", + "title": "my.id", + "url": "..", + }, + "testfev2other-preview": Object { + "additionalInformation": "SAPUI5.Component=test.fe.v2.other", + "applicationType": "URL", + "description": "This is a very simple application.", + "title": "My Other App", + "url": "/yet/another/app", + }, + }, + "basePath": "..", + "init": undefined, + "locateReuseLibsScript": false, + "ui5": Object { + "bootstrapOptions": "", + "flex": Array [ + Object { + "connector": "LrepConnector", + "layers": Array [], + "url": "/sap/bc/lrep", + }, + Object { + "applyConnector": "custom.connectors.WorkspaceConnector", + "custom": true, + "writeConnector": "custom.connectors.WorkspaceConnector", + }, + Object { + "connector": "LocalStorageConnector", + "layers": Array [ + "CUSTOMER", + "USER", + ], + }, + ], + "libs": "sap.m,sap.ui.core,sap.ushell", + "resources": Object { + "my.id": "..", + "myResources1": "myResourcesUrl1", + "myResources2": "myResourcesUrl2", + "open.ux.preview.client": "../preview/client", + "test.fe.v2.other": "/yet/another/app", + }, + "theme": "sap_horizon", + }, +} +`; + +exports[`FlpSandbox router rta with adp instance 2`] = ` +" + + + + + + + + Local FLP Sandbox + + + + + + + + + + + + + + + + + + + + + +" +`; + exports[`FlpSandbox router rta with developerMode=true 1`] = ` " @@ -686,7 +768,7 @@ exports[`FlpSandbox router rta with developerMode=true and plugin 1`] = ` data-sap-ui-xx-viewCache=\\"false\\" data-sap-ui-oninit=\\"module:open/ux/preview/client/flp/init\\" data-open-ux-preview-features='[]' - data-open-ux-preview-flex-settings='{\\"layer\\":\\"CUSTOMER_BASE\\",\\"baseId\\":\\"test.fe.v2.app\\",\\"appName\\":\\"test.fe.v2.app\\",\\"generator\\":\\"@sap-ux/control-property-editor\\",\\"developerMode\\":true,\\"pluginScript\\":\\"open/ux/tools/plugin\\"}'> + data-open-ux-preview-flex-settings='{\\"layer\\":\\"CUSTOMER_BASE\\",\\"baseId\\":\\"myComponent\\",\\"appName\\":\\"my.id\\",\\"generator\\":\\"@sap-ux/control-property-editor\\",\\"developerMode\\":true,\\"pluginScript\\":\\"open/ux/tools/plugin\\"}'> diff --git a/packages/preview-middleware/test/unit/base/flp.test.ts b/packages/preview-middleware/test/unit/base/flp.test.ts index 1252792a09..fe24ea62e2 100644 --- a/packages/preview-middleware/test/unit/base/flp.test.ts +++ b/packages/preview-middleware/test/unit/base/flp.test.ts @@ -1,7 +1,7 @@ import type { ReaderCollection } from '@ui5/fs'; import type { TemplateConfig } from '../../../src/base/config'; import { FlpSandbox as FlpSandboxUnderTest, initAdp } from '../../../src'; -import type { FlpConfig } from '../../../src/types'; +import type { FlpConfig, MiddlewareConfig } from '../../../src/types'; import type { MiddlewareUtils } from '@ui5/server'; import type { Logger, ToolsLogger } from '@sap-ux/logger'; import type { ProjectAccess, I18nBundles, Manifest } from '@sap-ux/project-access'; @@ -151,42 +151,6 @@ describe('FlpSandbox', () => { expect(flp.templateConfig).toMatchSnapshot(); }); - test('with passed descriptor', async () => { - const flp = new FlpSandbox({}, mockProject, mockUtils, logger); - const manifest = { - 'sap.app': { id: 'my.id' } - } as Manifest; - const descriptor = { - components: [ - { - name: 'myComponent', - url: 'myComponentUrl' - } - ], - libs: [ - { - name: 'myLib', - url: 'myLibUrl' - } - ], - asyncHints: { - requests: [ - { - url: 'myRequestUrl' - } - ] - } - }; - const componendId = 'myComponent'; - const resources = { - 'myResources1': 'myResourcesUrl1', - 'myResources2': 'myResourcesUrl2' - }; - - await flp.init(manifest, componendId, resources, descriptor as unknown as MergedAppDescriptor); - expect(flp.templateConfig).toMatchSnapshot(); - }); - test('optional configurations', async () => { const flp = new FlpSandbox({}, mockProject, mockUtils, logger); const manifest = JSON.parse(readFileSync(join(fixtures, 'simple-app/webapp/manifest.json'), 'utf-8')); @@ -279,53 +243,54 @@ describe('FlpSandbox', () => { describe('router', () => { let server!: SuperTest; - - beforeAll(async () => { - const flp = new FlpSandbox( + const mockConfig = { + flp: { + apps: [ + { + target: '/yet/another/app', + local: join(fixtures, 'multi-app') + } + ] + }, + test: [ { - flp: { - apps: [ - { - target: '/yet/another/app', - local: join(fixtures, 'multi-app') - } - ] + framework: 'QUnit' + }, + { + framework: 'OPA5', + path: '/test/integration/opaTests.qunit.html', + init: '/test/integration/opaTests.qunit.js' + } + ], + rta: { + layer: 'CUSTOMER_BASE', + editors: [ + { + path: '/my/rta.html' }, - test: [ - { - framework: 'QUnit' - }, - { - framework: 'OPA5', - path: '/test/integration/opaTests.qunit.html', - init: '/test/integration/opaTests.qunit.js' - } - ], - rta: { - layer: 'CUSTOMER_BASE', - editors: [ - { - path: '/my/rta.html' - }, - { - path: 'without/slash/rta.html' - }, - { - path: '/my/editor.html', - developerMode: true - }, - { - path: '/with/plugin.html', - developerMode: true, - pluginScript: 'open/ux/tools/plugin' - }, - { - path: '/my/editorWithConfig.html', - generator: 'test-generator' - } - ] + { + path: 'without/slash/rta.html' + }, + { + path: '/my/editor.html', + developerMode: true + }, + { + path: '/with/plugin.html', + developerMode: true, + pluginScript: 'open/ux/tools/plugin' + }, + { + path: '/my/editorWithConfig.html', + generator: 'test-generator' } - }, + ] + } + }; + + beforeAll(async () => { + const flp = new FlpSandbox( + mockConfig as unknown as Partial, mockProject, mockUtils, logger @@ -367,6 +332,56 @@ describe('FlpSandbox', () => { expect(response.text).toMatchSnapshot(); }); + test('rta with adp instance', async () => { + const flp = new FlpSandbox( + mockConfig as unknown as Partial, + mockProject, + mockUtils, + logger + ); + const manifest = { + 'sap.app': { id: 'my.id' } + } as Manifest; + const componendId = 'myComponent'; + const resources = { + 'myResources1': 'myResourcesUrl1', + 'myResources2': 'myResourcesUrl2' + }; + const url = 'http://sap.example'; + const syncSpy = jest.fn().mockResolvedValueOnce({}); + const adpToolingMock = { + init: () => { + return 'CUSTOMER_BASE'; + }, + descriptor: { + manifest: {}, + name: 'descriptorName', + url, + asyncHints: { + requests: [] + } + }, + resources: [], + proxy: jest.fn(), + sync: syncSpy, + onChangeRequest: jest.fn(), + addApis: jest.fn() + } as unknown as adpTooling.AdpPreview; + + await flp.init(manifest, componendId, resources, adpToolingMock as unknown as adpTooling.AdpPreview); + const app = express(); + app.use(flp.router); + const server = await supertest(app); + + expect(flp.templateConfig).toMatchSnapshot(); + const response = await server + .get( + '/my/editor.html.inner.html?fiori-tools-rta-mode=forAdaptation&sap-ui-rta-skip-flex-validation=true' + ) + .expect(200); + expect(response.text).toMatchSnapshot(); + }); + test('livereload port from environment', async () => { process.env.FIORI_TOOLS_LIVERELOAD_PORT = '8080'; let response = await server.get('/my/editor.html').expect(200);