From a0d9a1a2654b6efb69af1164ea42e1a39ea96c6e Mon Sep 17 00:00:00 2001 From: Tobias Sorn Date: Fri, 20 Nov 2020 17:39:05 +0100 Subject: [PATCH 01/13] [FEATURE] manifestCreator: i18n section v22 With app descriptor v22 (1.21.0) the i18n sections in the manifest are objects with: * bundleUrl * supportedLocales --- lib/processors/manifestCreator.js | 105 +++++++++++++++-- .../dest/resources/library/d/manifest.json | 2 +- .../resources/library/h/manifest.json | 2 +- .../dest/resources/library/h/manifest.json | 2 +- .../dest/resources/library/i/manifest.json | 2 +- .../library/k/manifest-bundle/manifest.json | 11 +- .../dest/resources/library/k/manifest.json | 2 +- test/lib/processors/manifestCreator.js | 109 ++++++------------ test/lib/tasks/generateLibraryManifest.js | 37 ++++-- 9 files changed, 175 insertions(+), 97 deletions(-) diff --git a/lib/processors/manifestCreator.js b/lib/processors/manifestCreator.js index ed9395095..7e18a5402 100644 --- a/lib/processors/manifestCreator.js +++ b/lib/processors/manifestCreator.js @@ -21,6 +21,7 @@ const APP_DESCRIPTOR_V3_SECTION_SAP_APP = new Version("1.2.0"); const APP_DESCRIPTOR_V3_OTHER_SECTIONS = new Version("1.1.0"); const APP_DESCRIPTOR_V5 = new Version("1.4.0"); const APP_DESCRIPTOR_V10 = new Version("1.9.0"); +const APP_DESCRIPTOR_V22 = new Version("1.21.0"); // namespaces used in .library files const XMLNS_UILIB = "http://www.sap.com/sap.ui.library.xsd"; @@ -123,13 +124,30 @@ class Library { class LibraryBundle { + /** + * + * @param {string} prefix + * @param {module:@ui5/fs.Resource[]} resources + */ constructor(prefix, resources) { this.prefix = prefix; this.resources = resources.filter((res) => res.getPath().startsWith(prefix)); } + + /** + * + * @param {string} name + * @returns {module:@ui5/fs.Resource} + */ findResource(name) { return this.resources.find((res) => res.getPath() === this.prefix + name); } + + /** + * + * @param {RegExp} pattern + * @returns {module:@ui5/fs.Resource[]} + */ getResources(pattern) { return this.resources.filter((res) => pattern == null || pattern.test(res.getPath())); } @@ -144,6 +162,13 @@ async function createManifest(libraryResource, libBundle, descriptorVersion, _in // collect information from library.js file const libraryJSInfo = await analyzeLibraryJS(libBundle.findResource("library.js")); + const includeSupportedLocalesInformation = descriptorVersion.compare(APP_DESCRIPTOR_V22) >= 0; + /** + * cache for supported locales + * + * @see createI18nSection + */ + const i18nToSupportedLocales = new Map(); const manifestAppData = library.getAppData("manifest", XMLNS_MANIFEST); const sapFioriAppData = findChild(manifestAppData, "sap.fiori"); @@ -322,13 +347,19 @@ async function createManifest(libraryResource, libBundle, descriptorVersion, _in return osComponents.length > 0 ? osComponents : undefined; } - + const i18nAppData = findChild(manifestAppData, "i18n"); + let i18n; + if (i18nAppData) { + const i18nText = i18nAppData._; // text content + i18n = createI18nSection(i18nText, i18nToSupportedLocales); + log.verbose(`sap.app/i18n taken from .library appData: '%s'`, i18nText); + } const sapApp = { _version: sectionVersion(APP_DESCRIPTOR_V3_SECTION_SAP_APP), id: library.getName(), type: "library", embeds: await findEmbeddedComponents(), - i18n: getChildTextContent(manifestAppData, "i18n"), + i18n, applicationVersion: { version: isValid(library.getVersion()) ? library.getVersion() : getProjectVersion() }, @@ -457,24 +488,28 @@ async function createManifest(libraryResource, libBundle, descriptorVersion, _in // - from library resources (if "messagebundle.properties" exists) function i18n() { const i18nElement = findChild(libraryAppData, "i18n"); + let i18n = null; if ( i18nElement ) { - const i18n = i18nElement._; + i18n = i18nElement._; // text content if ( i18n === "false" ) { return false; } else if ( i18n === "true" ) { - return "messagebundle.properties"; - } else { - return i18n; + i18n = "messagebundle.properties"; } // log.verbose(" sap.ui5/library/i18n property taken from .library appData: '%s'", library.i18n); } else { if ( libBundle.findResource("messagebundle.properties") != null ) { // log.verbose(" sap.ui5/library/i18n property determined from resources: '%s'", library.i18n); - return "messagebundle.properties"; + i18n = "messagebundle.properties"; } else { return false; } } + // i18n can be an empty string therefore check for not being null + if (i18n !== null) { + return createI18nSection(i18n, i18nToSupportedLocales); + } + return false; } // css: @@ -525,6 +560,60 @@ async function createManifest(libraryResource, libBundle, descriptorVersion, _in return sapUI5; } + /** + * Creates an i18n section: + * - either using bundleUrl and supportedLocales + * - or the i18n String + * + * @param {string} i18n bundle url, e.g. "messagebundle.properties" + * @param {Map>} i18nToSupportedLocales cache to determine the supportedLocales only once + * @returns {{bundleUrl: string, supportedLocales: string[]}|null|string} json structure with bundleUrl and supportedLocales or the i18n String if not a ".properties" file. + * null if given i18n String is null + */ + function createI18nSection(i18n, i18nToSupportedLocales) { + if (!i18n) { + return null; + } + if (!i18n.endsWith(".properties")) { + return i18n; + } + + // if the supported locales information should not be included use i18n text + if (!includeSupportedLocalesInformation) { + return i18n; + } + + let supportedLocales = i18nToSupportedLocales.get(i18n); + + if (!supportedLocales) { + supportedLocales = new Set(); + + if (libBundle.findResource(i18n) != null) { + supportedLocales.add(""); + } + const i18nPatternStr = i18n.substring(0, i18n.length - ".properties".length); + const i18nRegexp = new RegExp(i18nPatternStr + "_([^.]+)\\.properties$"); + + + libBundle.getResources().forEach((resource) => { + const resPath = resource.getPath(); + const result = i18nRegexp.exec(resPath); + + if (result) { + supportedLocales.add(result[1].replace(/_/g, "-")); + } + }); + i18nToSupportedLocales.set(i18n, supportedLocales); + } + + const supportedLocalesArray = [...supportedLocales]; + supportedLocalesArray.sort(); + return { + bundleUrl: i18n, + supportedLocales: supportedLocalesArray + }; + } + function createSapFiori() { // collect registrationIds if present function registrationIds() { @@ -613,7 +702,7 @@ async function createManifest(libraryResource, libBundle, descriptorVersion, _in module.exports = function({libraryResource, resources, options}) { // merge options with defaults options = Object.assign({ - descriptorVersion: APP_DESCRIPTOR_V10, + descriptorVersion: APP_DESCRIPTOR_V22, include3rdParty: true, prettyPrint: true }, options); diff --git a/test/expected/build/library.d/dest/resources/library/d/manifest.json b/test/expected/build/library.d/dest/resources/library/d/manifest.json index 4ad3d1aef..c4f9b3baa 100644 --- a/test/expected/build/library.d/dest/resources/library/d/manifest.json +++ b/test/expected/build/library.d/dest/resources/library/d/manifest.json @@ -1,5 +1,5 @@ { - "_version": "1.9.0", + "_version": "1.21.0", "sap.app": { "id": "library.d", "type": "library", diff --git a/test/expected/build/library.h/dest-resources-json/resources/library/h/manifest.json b/test/expected/build/library.h/dest-resources-json/resources/library/h/manifest.json index de1590b80..808d3df90 100644 --- a/test/expected/build/library.h/dest-resources-json/resources/library/h/manifest.json +++ b/test/expected/build/library.h/dest-resources-json/resources/library/h/manifest.json @@ -1,5 +1,5 @@ { - "_version": "1.9.0", + "_version": "1.21.0", "sap.app": { "id": "library.h", "type": "library", diff --git a/test/expected/build/library.h/dest/resources/library/h/manifest.json b/test/expected/build/library.h/dest/resources/library/h/manifest.json index de1590b80..808d3df90 100644 --- a/test/expected/build/library.h/dest/resources/library/h/manifest.json +++ b/test/expected/build/library.h/dest/resources/library/h/manifest.json @@ -1,5 +1,5 @@ { - "_version": "1.9.0", + "_version": "1.21.0", "sap.app": { "id": "library.h", "type": "library", diff --git a/test/expected/build/library.i/dest/resources/library/i/manifest.json b/test/expected/build/library.i/dest/resources/library/i/manifest.json index 9e09aa94d..77c819c00 100644 --- a/test/expected/build/library.i/dest/resources/library/i/manifest.json +++ b/test/expected/build/library.i/dest/resources/library/i/manifest.json @@ -1,5 +1,5 @@ { - "_version": "1.9.0", + "_version": "1.21.0", "sap.app": { "id": "library.i", "type": "library", diff --git a/test/expected/build/library.k/dest/resources/library/k/manifest-bundle/manifest.json b/test/expected/build/library.k/dest/resources/library/k/manifest-bundle/manifest.json index 4fe9e43c4..1db4fc634 100644 --- a/test/expected/build/library.k/dest/resources/library/k/manifest-bundle/manifest.json +++ b/test/expected/build/library.k/dest/resources/library/k/manifest-bundle/manifest.json @@ -1,5 +1,5 @@ { - "_version": "1.9.0", + "_version": "1.21.0", "sap.app": { "id": "library.k", "type": "library", @@ -22,7 +22,14 @@ "libs": {} }, "library": { - "i18n": "messagebundle.properties", + "i18n": { + "bundleUrl": "messagebundle.properties", + "supportedLocales": [ + "", + "de", + "en" + ] + }, "content": { "controls": [ "library.k.AnyControl" diff --git a/test/expected/build/library.k/dest/resources/library/k/manifest.json b/test/expected/build/library.k/dest/resources/library/k/manifest.json index d0f707f1c..aa1de1327 100644 --- a/test/expected/build/library.k/dest/resources/library/k/manifest.json +++ b/test/expected/build/library.k/dest/resources/library/k/manifest.json @@ -1,5 +1,5 @@ { - "_version": "1.9.0", + "_version": "1.21.0", "sap.app": { "id": "library.k", "type": "library", diff --git a/test/lib/processors/manifestCreator.js b/test/lib/processors/manifestCreator.js index a57bf8008..3dd3968c1 100644 --- a/test/lib/processors/manifestCreator.js +++ b/test/lib/processors/manifestCreator.js @@ -16,14 +16,28 @@ const libraryContent = ` sap.ui.core + + + + i18n/i18n.properties + + `; const expectedManifestContent = `{ - "_version": "1.9.0", + "_version": "1.21.0", "sap.app": { "id": "library.e", "type": "library", "embeds": [], + "i18n": { + "bundleUrl": "i18n/i18n.properties", + "supportedLocales": [ + "", + "de", + "en" + ] + }, "applicationVersion": { "version": "1.0.0" }, @@ -65,10 +79,10 @@ test.afterEach.always((t) => { test.serial("default manifest creation", async (t) => { const {manifestCreator, errorLogStub} = t.context; - + const prefix = "/resources/sap/ui/mine/"; const libraryResource = { getPath: () => { - return "/resources/sap/ui/mine/.library"; + return prefix + ".library"; }, getString: async () => { return libraryContent; @@ -81,16 +95,24 @@ test.serial("default manifest creation", async (t) => { }] } }; - + const resources = ["", "_en", "_de"].map((lang) => { + return { + getPath: () => { + return `${prefix}i18n/i18n${lang}.properties`; + } + }; + }); t.is(errorLogStub.callCount, 0); - const result = await manifestCreator({libraryResource, resources: [], options: {}}); + const result = await manifestCreator({libraryResource, resources, options: {}}); t.is(await result.getString(), expectedManifestContent, "Correct result returned"); }); test.serial("manifest creation for sap/apf", async (t) => { const {manifestCreator, errorLogStub, verboseLogStub} = t.context; + const prefix = "/resources/sap/apf/"; + const libraryResource = { getPath: () => { return "/resources/sap/apf/.library"; @@ -109,87 +131,30 @@ test.serial("manifest creation for sap/apf", async (t) => { const componentResource = { getPath: () => { - return "/resources/sap/apf/Component.js"; + return prefix + "Component.js"; } }; - + const resources = ["", "_en", "_de"].map((lang) => { + return { + getPath: () => { + return `${prefix}i18n/i18n${lang}.properties`; + } + }; + }); + resources.push(componentResource); const result = await manifestCreator({libraryResource, resources: [componentResource], options: {}}); t.is(await result.getString(), expectedManifestContent, "Correct result returned"); t.is(errorLogStub.callCount, 0); t.is(verboseLogStub.callCount, 9); + t.is(verboseLogStub.getCall(0).args[0], "sap.app/i18n taken from .library appData: '%s'"); t.is(verboseLogStub.getCall(1).args[0], "Package %s contains both '*.library' and 'Component.js'. " + "This is a known issue but can't be solved due to backward compatibility."); t.is(verboseLogStub.getCall(1).args[1], "/resources/sap/apf"); }); -test.serial("manifest creation for sap/ui/core", async (t) => { - const {manifestCreator, errorLogStub, verboseLogStub} = t.context; - - const expectedManifestContent = JSON.stringify({ - "_version": "1.9.0", - "sap.app": { - "id": "sap.ui.core", - "type": "library", - "embeds": [], - "applicationVersion": { - "version": "1.0.0" - }, - "title": "sap.ui.core", - "resources": "resources.json", - "offline": true - }, - "sap.ui": { - "technology": "UI5", - "supportedThemes": [] - }, - "sap.ui5": { - "dependencies": { - "libs": {} - }, - "library": { - "i18n": false - } - } - }, null, 2); - - const libraryResource = { - getPath: () => { - return "/resources/sap/ui/core/.library"; - }, - getString: async () => { - return ` - - sap.ui.core - 1.0.0 - `; - }, - _project: { - metadata: { - name: "sap.ui.core" - } - } - }; - - const componentResource = { - getPath: () => { - return "/resources/sap/ui/core/Component.js"; - } - }; - - const result = await manifestCreator({libraryResource, resources: [componentResource], options: {}}); - t.is(await result.getString(), expectedManifestContent, "Correct result returned"); - - t.is(errorLogStub.callCount, 0); - - t.is(verboseLogStub.callCount, 8); - t.is(verboseLogStub.getCall(1).args[0], - " sap.app/id taken from .library: '%s'"); - t.is(verboseLogStub.getCall(1).args[1], "sap.ui.core"); -}); - test.serial("manifest creation with .library / Component.js at same namespace", async (t) => { const {manifestCreator, errorLogStub, verboseLogStub} = t.context; diff --git a/test/lib/tasks/generateLibraryManifest.js b/test/lib/tasks/generateLibraryManifest.js index 30e2c9d66..fb33de921 100644 --- a/test/lib/tasks/generateLibraryManifest.js +++ b/test/lib/tasks/generateLibraryManifest.js @@ -79,7 +79,7 @@ test("integration: Library without i18n bundle file", async (t) => { })); await assertCreatedManifest(t, { - "_version": "1.9.0", + "_version": "1.21.0", "sap.app": { applicationVersion: { version: "2.0.0", @@ -137,7 +137,7 @@ test("integration: Library with i18n bundle file (messagebundle.properties)", as })); await assertCreatedManifest(t, { - "_version": "1.9.0", + "_version": "1.21.0", "sap.app": { applicationVersion: { version: "2.0.0", @@ -160,7 +160,10 @@ test("integration: Library with i18n bundle file (messagebundle.properties)", as minUI5Version: "1.0", }, library: { - i18n: "messagebundle.properties", + i18n: { + bundleUrl: "messagebundle.properties", + supportedLocales: [""] + } } }, }); @@ -198,9 +201,13 @@ test("integration: Library with i18n=true declared in .library", async (t) => { `, project: t.context.workspace._project })); + t.context.resources.push(resourceFactory.createResource({ + path: "/resources/test/lib/messagebundle.properties", + project: t.context.workspace._project + })); await assertCreatedManifest(t, { - "_version": "1.9.0", + "_version": "1.21.0", "sap.app": { applicationVersion: { version: "2.0.0", @@ -223,7 +230,10 @@ test("integration: Library with i18n=true declared in .library", async (t) => { minUI5Version: "1.0", }, library: { - i18n: "messagebundle.properties", + i18n: { + bundleUrl: "messagebundle.properties", + supportedLocales: [""] + } } }, }); @@ -263,7 +273,7 @@ test("integration: Library with i18n=false declared in .library", async (t) => { })); await assertCreatedManifest(t, { - "_version": "1.9.0", + "_version": "1.21.0", "sap.app": { applicationVersion: { version: "2.0.0", @@ -325,8 +335,12 @@ test("integration: Library with i18n=foo.properties declared in .library", async project: t.context.workspace._project })); + t.context.resources.push(resourceFactory.createResource({ + path: "/resources/test/lib/foo.properties", + project: t.context.workspace._project + })); await assertCreatedManifest(t, { - "_version": "1.9.0", + "_version": "1.21.0", "sap.app": { applicationVersion: { version: "2.0.0", @@ -349,7 +363,10 @@ test("integration: Library with i18n=foo.properties declared in .library", async minUI5Version: "1.0", }, library: { - i18n: "foo.properties" + i18n: { + bundleUrl: "foo.properties", + supportedLocales: [""] + } } }, }); @@ -389,7 +406,7 @@ test("integration: Library with css=true declared in .library", async (t) => { })); await assertCreatedManifest(t, { - "_version": "1.9.0", + "_version": "1.21.0", "sap.app": { applicationVersion: { version: "2.0.0", @@ -452,7 +469,7 @@ test("integration: Library with css=false declared in .library", async (t) => { })); await assertCreatedManifest(t, { - "_version": "1.9.0", + "_version": "1.21.0", "sap.app": { applicationVersion: { version: "2.0.0", From 546bc4716ee90f44ac92954ce9eb75568d5d371e Mon Sep 17 00:00:00 2001 From: Tobias Sorn Date: Thu, 26 Nov 2020 15:15:17 +0100 Subject: [PATCH 02/13] [FEATURE] manifestCreator: i18n section v22 adjusted line length --- lib/processors/manifestCreator.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/processors/manifestCreator.js b/lib/processors/manifestCreator.js index 7e18a5402..a2434d024 100644 --- a/lib/processors/manifestCreator.js +++ b/lib/processors/manifestCreator.js @@ -567,7 +567,8 @@ async function createManifest(libraryResource, libBundle, descriptorVersion, _in * * @param {string} i18n bundle url, e.g. "messagebundle.properties" * @param {Map>} i18nToSupportedLocales cache to determine the supportedLocales only once - * @returns {{bundleUrl: string, supportedLocales: string[]}|null|string} json structure with bundleUrl and supportedLocales or the i18n String if not a ".properties" file. + * @returns {{bundleUrl: string, supportedLocales: string[]}|null|string} json structure with bundleUrl and + * supportedLocales or the i18n String if not a ".properties" file. * null if given i18n String is null */ function createI18nSection(i18n, i18nToSupportedLocales) { From 84326219bab27a30e9506c11b71877ee494e05f9 Mon Sep 17 00:00:00 2001 From: Tobias Sorn Date: Tue, 1 Dec 2020 10:32:09 +0100 Subject: [PATCH 03/13] [FEATURE] manifestCreator: i18n section v22 fixed tests after rebase --- .../resources/library/h/resources.json | 2 +- test/lib/processors/manifestCreator.js | 27 ++++++++++--------- 2 files changed, 16 insertions(+), 13 deletions(-) diff --git a/test/expected/build/library.h/dest-resources-json/resources/library/h/resources.json b/test/expected/build/library.h/dest-resources-json/resources/library/h/resources.json index f3e80a739..9dc1a3a1f 100644 --- a/test/expected/build/library.h/dest-resources-json/resources/library/h/resources.json +++ b/test/expected/build/library.h/dest-resources-json/resources/library/h/resources.json @@ -133,7 +133,7 @@ { "name": "manifest.json", "module": "library/h/manifest.json", - "size": 613 + "size": 614 }, { "name": "not.js", diff --git a/test/lib/processors/manifestCreator.js b/test/lib/processors/manifestCreator.js index 3dd3968c1..99eeda5ba 100644 --- a/test/lib/processors/manifestCreator.js +++ b/test/lib/processors/manifestCreator.js @@ -142,24 +142,27 @@ test.serial("manifest creation for sap/apf", async (t) => { }; }); resources.push(componentResource); - const result = await manifestCreator({libraryResource, resources: [componentResource], options: {}}); + const result = await manifestCreator({libraryResource, resources, options: {}}); t.is(await result.getString(), expectedManifestContent, "Correct result returned"); t.is(errorLogStub.callCount, 0); - t.is(verboseLogStub.callCount, 9); + t.is(verboseLogStub.callCount, 10); t.is(verboseLogStub.getCall(0).args[0], "sap.app/i18n taken from .library appData: '%s'"); t.is(verboseLogStub.getCall(1).args[0], + "checking component at %s"); + t.is(verboseLogStub.getCall(1).args[1], "/resources/sap/apf"); + t.is(verboseLogStub.getCall(2).args[0], "Package %s contains both '*.library' and 'Component.js'. " + "This is a known issue but can't be solved due to backward compatibility."); - t.is(verboseLogStub.getCall(1).args[1], "/resources/sap/apf"); + t.is(verboseLogStub.getCall(2).args[1], "/resources/sap/apf"); }); test.serial("manifest creation with .library / Component.js at same namespace", async (t) => { const {manifestCreator, errorLogStub, verboseLogStub} = t.context; const expectedManifestContent = JSON.stringify({ - "_version": "1.9.0", + "_version": "1.21.0", "sap.app": { "id": "sap.lib1", "type": "library", @@ -232,7 +235,7 @@ test.serial("manifest creation with embedded component", async (t) => { const {manifestCreator, errorLogStub, verboseLogStub} = t.context; const expectedManifestContent = JSON.stringify({ - "_version": "1.9.0", + "_version": "1.21.0", "sap.app": { "id": "sap.lib1", "type": "library", @@ -322,7 +325,7 @@ test.serial("manifest creation with embedded component (Missing 'embeddedBy')", const {manifestCreator, errorLogStub, verboseLogStub} = t.context; const expectedManifestContent = JSON.stringify({ - "_version": "1.9.0", + "_version": "1.21.0", "sap.app": { "id": "sap.lib1", "type": "library", @@ -406,7 +409,7 @@ test.serial("manifest creation with embedded component ('embeddedBy' doesn't poi const {manifestCreator, errorLogStub, verboseLogStub} = t.context; const expectedManifestContent = JSON.stringify({ - "_version": "1.9.0", + "_version": "1.21.0", "sap.app": { "id": "sap.lib1", "type": "library", @@ -495,7 +498,7 @@ test.serial("manifest creation with embedded component ('embeddedBy' absolute pa const {manifestCreator, errorLogStub, verboseLogStub} = t.context; const expectedManifestContent = JSON.stringify({ - "_version": "1.9.0", + "_version": "1.21.0", "sap.app": { "id": "sap.lib1", "type": "library", @@ -584,7 +587,7 @@ test.serial("manifest creation with embedded component ('embeddedBy' empty strin const {manifestCreator, errorLogStub} = t.context; const expectedManifestContent = JSON.stringify({ - "_version": "1.9.0", + "_version": "1.21.0", "sap.app": { "id": "sap.lib1", "type": "library", @@ -669,7 +672,7 @@ test.serial("manifest creation with embedded component ('embeddedBy' object)", a const {manifestCreator, errorLogStub} = t.context; const expectedManifestContent = JSON.stringify({ - "_version": "1.9.0", + "_version": "1.21.0", "sap.app": { "id": "sap.lib1", "type": "library", @@ -757,7 +760,7 @@ test.serial("manifest creation with embedded component (no manifest.json)", asyn const {manifestCreator, errorLogStub, verboseLogStub} = t.context; const expectedManifestContent = JSON.stringify({ - "_version": "1.9.0", + "_version": "1.21.0", "sap.app": { "id": "sap.lib1", "type": "library", @@ -833,7 +836,7 @@ test.serial("manifest creation with embedded component (invalid manifest.json)", const {manifestCreator, errorLogStub} = t.context; const expectedManifestContent = JSON.stringify({ - "_version": "1.9.0", + "_version": "1.21.0", "sap.app": { "id": "sap.lib1", "type": "library", From c28962be6e1ead9e4e1892da6803ab67f1519db2 Mon Sep 17 00:00:00 2001 From: Tobias Sorn Date: Tue, 22 Dec 2020 15:28:44 +0100 Subject: [PATCH 04/13] [FEATURE] manifestCreator: i18n section v22 restored test --- test/lib/processors/manifestCreator.js | 65 ++++++++++++++++++++++++++ 1 file changed, 65 insertions(+) diff --git a/test/lib/processors/manifestCreator.js b/test/lib/processors/manifestCreator.js index 99eeda5ba..0d3c53eb6 100644 --- a/test/lib/processors/manifestCreator.js +++ b/test/lib/processors/manifestCreator.js @@ -158,6 +158,71 @@ test.serial("manifest creation for sap/apf", async (t) => { t.is(verboseLogStub.getCall(2).args[1], "/resources/sap/apf"); }); +test.serial("manifest creation for sap/ui/core", async (t) => { + const {manifestCreator, errorLogStub, verboseLogStub} = t.context; + + const expectedManifestContent = JSON.stringify({ + "_version": "1.21.0", + "sap.app": { + "id": "sap.ui.core", + "type": "library", + "embeds": [], + "applicationVersion": { + "version": "1.0.0" + }, + "title": "sap.ui.core", + "resources": "resources.json", + "offline": true + }, + "sap.ui": { + "technology": "UI5", + "supportedThemes": [] + }, + "sap.ui5": { + "dependencies": { + "libs": {} + }, + "library": { + "i18n": false + } + } + }, null, 2); + + const libraryResource = { + getPath: () => { + return "/resources/sap/ui/core/.library"; + }, + getString: async () => { + return ` + + sap.ui.core + 1.0.0 + `; + }, + _project: { + metadata: { + name: "sap.ui.core" + } + } + }; + + const componentResource = { + getPath: () => { + return "/resources/sap/ui/core/Component.js"; + } + }; + + const result = await manifestCreator({libraryResource, resources: [componentResource], options: {}}); + t.is(await result.getString(), expectedManifestContent, "Correct result returned"); + + t.is(errorLogStub.callCount, 0); + + t.is(verboseLogStub.callCount, 8); + t.is(verboseLogStub.getCall(1).args[0], + " sap.app/id taken from .library: '%s'"); + t.is(verboseLogStub.getCall(1).args[1], "sap.ui.core"); +}); + test.serial("manifest creation with .library / Component.js at same namespace", async (t) => { const {manifestCreator, errorLogStub, verboseLogStub} = t.context; From ddb480287a37ee72214519a3074465a11d079a7a Mon Sep 17 00:00:00 2001 From: Tobias Sorn Date: Tue, 22 Dec 2020 16:04:37 +0100 Subject: [PATCH 05/13] [FEATURE] manifestCreator: i18n section v22 Improve i18n language extraction code by avoiding regexp --- lib/processors/manifestCreator.js | 15 +++-- test/lib/processors/manifestCreator.js | 89 ++++++++++++++++++++++++++ 2 files changed, 97 insertions(+), 7 deletions(-) diff --git a/lib/processors/manifestCreator.js b/lib/processors/manifestCreator.js index a2434d024..7771af584 100644 --- a/lib/processors/manifestCreator.js +++ b/lib/processors/manifestCreator.js @@ -592,16 +592,17 @@ async function createManifest(libraryResource, libBundle, descriptorVersion, _in if (libBundle.findResource(i18n) != null) { supportedLocales.add(""); } - const i18nPatternStr = i18n.substring(0, i18n.length - ".properties".length); - const i18nRegexp = new RegExp(i18nPatternStr + "_([^.]+)\\.properties$"); - + const i18nPatternStr = i18n.substring(0, i18n.length - ".properties".length) + "_"; libBundle.getResources().forEach((resource) => { const resPath = resource.getPath(); - const result = i18nRegexp.exec(resPath); - - if (result) { - supportedLocales.add(result[1].replace(/_/g, "-")); + const i18nLastIndex = resPath.lastIndexOf(i18nPatternStr); + if (resPath.endsWith(".properties") && i18nLastIndex >= 0) { + const i18nPath = resPath.substring(i18nLastIndex + i18nPatternStr.length, + resPath.length - ".properties".length); + if (!i18nPath.includes(".")) { + supportedLocales.add(i18nPath.replace(/_/g, "-")); + } } }); i18nToSupportedLocales.set(i18n, supportedLocales); diff --git a/test/lib/processors/manifestCreator.js b/test/lib/processors/manifestCreator.js index 0d3c53eb6..21fa95a0c 100644 --- a/test/lib/processors/manifestCreator.js +++ b/test/lib/processors/manifestCreator.js @@ -24,6 +24,27 @@ const libraryContent = ` `; +const libraryContentSpecialChars = ` + + library.e + SAP SE + my copyright + 1.0.0 + Library E + + + + sap.ui.core + + + + + + i18n(.*)./i18n(.*).properties + + +`; + const expectedManifestContent = `{ "_version": "1.21.0", "sap.app": { @@ -61,6 +82,43 @@ const expectedManifestContent = `{ } } }`; +const expectedManifestContentSpecialChars = `{ + "_version": "1.21.0", + "sap.app": { + "id": "library.e", + "type": "library", + "embeds": [], + "i18n": { + "bundleUrl": "i18n(.*)./i18n(.*).properties", + "supportedLocales": [ + "", + "de", + "en" + ] + }, + "applicationVersion": { + "version": "1.0.0" + }, + "title": "Library E", + "description": "Library E", + "resources": "resources.json", + "offline": true + }, + "sap.ui": { + "technology": "UI5", + "supportedThemes": [] + }, + "sap.ui5": { + "dependencies": { + "libs": { + "sap.ui.core": {} + } + }, + "library": { + "i18n": false + } + } +}`; test.beforeEach((t) => { t.context.verboseLogStub = sinon.stub(); @@ -108,6 +166,37 @@ test.serial("default manifest creation", async (t) => { t.is(await result.getString(), expectedManifestContent, "Correct result returned"); }); +test.serial("default manifest creation with special characters", async (t) => { + const {manifestCreator, errorLogStub} = t.context; + const prefix = "/resources/sap/ui/mine/"; + const libraryResource = { + getPath: () => { + return prefix + ".library"; + }, + getString: async () => { + return libraryContentSpecialChars; + }, + _project: { + dependencies: [{ + metadata: { + name: "sap.ui.core" + } + }] + } + }; + const resources = ["", "_en", "_de"].map((lang) => { + return { + getPath: () => { + return `${prefix}i18n(.*)./i18n(.*)${lang}.properties`; + } + }; + }); + t.is(errorLogStub.callCount, 0); + + const result = await manifestCreator({libraryResource, resources, options: {}}); + t.is(await result.getString(), expectedManifestContentSpecialChars, "Correct result returned"); +}); + test.serial("manifest creation for sap/apf", async (t) => { const {manifestCreator, errorLogStub, verboseLogStub} = t.context; From ba802be773b1349181fa02e6a89ec6eef25c4f66 Mon Sep 17 00:00:00 2001 From: Tobias Sorn Date: Wed, 23 Dec 2020 09:54:15 +0100 Subject: [PATCH 06/13] [FEATURE] manifestCreator: i18n section v22 Add test and comments --- lib/processors/manifestCreator.js | 10 +- test/lib/processors/manifestCreator.js | 162 ++++++++++++++----------- 2 files changed, 94 insertions(+), 78 deletions(-) diff --git a/lib/processors/manifestCreator.js b/lib/processors/manifestCreator.js index 7771af584..3664c6f2a 100644 --- a/lib/processors/manifestCreator.js +++ b/lib/processors/manifestCreator.js @@ -592,13 +592,15 @@ async function createManifest(libraryResource, libBundle, descriptorVersion, _in if (libBundle.findResource(i18n) != null) { supportedLocales.add(""); } - const i18nPatternStr = i18n.substring(0, i18n.length - ".properties".length) + "_"; + const i18nPathPrefix = i18n.substring(0, i18n.length - ".properties".length) + "_"; + // e.g. i18n/i18n_ libBundle.getResources().forEach((resource) => { const resPath = resource.getPath(); - const i18nLastIndex = resPath.lastIndexOf(i18nPatternStr); - if (resPath.endsWith(".properties") && i18nLastIndex >= 0) { - const i18nPath = resPath.substring(i18nLastIndex + i18nPatternStr.length, + // e.g. sap/ui/mine/i18n/i18n_en.properties + const indexOfI18nPathPrefix = resPath.lastIndexOf(i18nPathPrefix); + if (resPath.endsWith(".properties") && indexOfI18nPathPrefix >= 0) { + const i18nPath = resPath.substring(indexOfI18nPathPrefix + i18nPathPrefix.length, resPath.length - ".properties".length); if (!i18nPath.includes(".")) { supportedLocales.add(i18nPath.replace(/_/g, "-")); diff --git a/test/lib/processors/manifestCreator.js b/test/lib/processors/manifestCreator.js index 21fa95a0c..5d1ac313e 100644 --- a/test/lib/processors/manifestCreator.js +++ b/test/lib/processors/manifestCreator.js @@ -2,6 +2,7 @@ const test = require("ava"); const sinon = require("sinon"); const mock = require("mock-require"); const logger = require("@ui5/logger"); +const {SemVer: Version} = require("semver"); const libraryContent = ` @@ -45,80 +46,50 @@ const libraryContentSpecialChars = ` `; -const expectedManifestContent = `{ - "_version": "1.21.0", - "sap.app": { - "id": "library.e", - "type": "library", - "embeds": [], - "i18n": { - "bundleUrl": "i18n/i18n.properties", - "supportedLocales": [ - "", - "de", - "en" - ] - }, - "applicationVersion": { - "version": "1.0.0" - }, - "title": "Library E", - "description": "Library E", - "resources": "resources.json", - "offline": true - }, - "sap.ui": { - "technology": "UI5", - "supportedThemes": [] - }, - "sap.ui5": { - "dependencies": { - "libs": { - "sap.ui.core": {} - } - }, - "library": { - "i18n": false - } - } -}`; -const expectedManifestContentSpecialChars = `{ - "_version": "1.21.0", - "sap.app": { - "id": "library.e", - "type": "library", - "embeds": [], - "i18n": { - "bundleUrl": "i18n(.*)./i18n(.*).properties", - "supportedLocales": [ - "", - "de", - "en" - ] - }, - "applicationVersion": { - "version": "1.0.0" - }, - "title": "Library E", - "description": "Library E", - "resources": "resources.json", - "offline": true - }, - "sap.ui": { - "technology": "UI5", - "supportedThemes": [] - }, - "sap.ui5": { - "dependencies": { - "libs": { - "sap.ui.core": {} - } - }, - "library": { - "i18n": false - } - } -}`; +const expectedManifestContentObject = () => { + return { + "_version": "1.21.0", + "sap.app": { + "id": "library.e", + "type": "library", + "embeds": [], + "i18n": { + "bundleUrl": "i18n/i18n.properties", + "supportedLocales": [ + "", + "de", + "en" + ] + }, + "applicationVersion": { + "version": "1.0.0" + }, + "title": "Library E", + "description": "Library E", + "resources": "resources.json", + "offline": true + }, + "sap.ui": { + "technology": "UI5", + "supportedThemes": [] + }, + "sap.ui5": { + "dependencies": { + "libs": { + "sap.ui.core": {} + } + }, + "library": { + "i18n": false + } + } + }; +}; + +const expectedManifestContent = JSON.stringify(expectedManifestContentObject(), null, 2); +const expectedManifestContentSpecialCharsObject = expectedManifestContentObject(); +expectedManifestContentSpecialCharsObject["sap.app"]["i18n"]["bundleUrl"] = "i18n(.*)./i18n(.*).properties"; +const expectedManifestContentSpecialChars = JSON.stringify(expectedManifestContentSpecialCharsObject, null, 2); test.beforeEach((t) => { t.context.verboseLogStub = sinon.stub(); @@ -191,12 +162,55 @@ test.serial("default manifest creation with special characters", async (t) => { } }; }); + + // additional non-i18n resource + resources.push({ + getPath: () => { + return `${prefix}model/data.json`; + } + }); t.is(errorLogStub.callCount, 0); const result = await manifestCreator({libraryResource, resources, options: {}}); t.is(await result.getString(), expectedManifestContentSpecialChars, "Correct result returned"); }); +test.serial("default manifest creation with special characters small app descriptor version", async (t) => { + const {manifestCreator, errorLogStub} = t.context; + const prefix = "/resources/sap/ui/mine/"; + const libraryResource = { + getPath: () => { + return prefix + ".library"; + }, + getString: async () => { + return libraryContent; + }, + _project: { + dependencies: [{ + metadata: { + name: "sap.ui.core" + } + }] + } + }; + const resources = ["", "_en", "_de"].map((lang) => { + return { + getPath: () => { + return `${prefix}i18n/i18n${lang}.properties`; + } + }; + }); + t.is(errorLogStub.callCount, 0); + + const options = {descriptorVersion: new Version("1.9.0")}; + const result = await manifestCreator({libraryResource, resources, options}); + const expectedManifestContentSmallVersion = expectedManifestContentObject(); + expectedManifestContentSmallVersion["_version"] = "1.9.0"; + expectedManifestContentSmallVersion["sap.app"]["i18n"] = "i18n/i18n.properties"; + const expectedManifestContentSmallVersionString = JSON.stringify(expectedManifestContentSmallVersion, null, 2); + t.is(await result.getString(), expectedManifestContentSmallVersionString, "Correct result returned"); +}); + test.serial("manifest creation for sap/apf", async (t) => { const {manifestCreator, errorLogStub, verboseLogStub} = t.context; From b561ea733399b2822340d2ed616560588e2fde2f Mon Sep 17 00:00:00 2001 From: Tobias Sorn Date: Wed, 23 Dec 2020 10:25:26 +0100 Subject: [PATCH 07/13] [FEATURE] manifestCreator: i18n section v22 Adjust test code --- .../dest/resources/library/\303\270/library-preload.js" | 2 +- .../dest/resources/library/\303\270/manifest.json" | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git "a/test/expected/build/library.\303\270/dest/resources/library/\303\270/library-preload.js" "b/test/expected/build/library.\303\270/dest/resources/library/\303\270/library-preload.js" index e7cc290a6..b25d5ac7a 100644 --- "a/test/expected/build/library.\303\270/dest/resources/library/\303\270/library-preload.js" +++ "b/test/expected/build/library.\303\270/dest/resources/library/\303\270/library-preload.js" @@ -1,6 +1,6 @@ //@ui5-bundle library/ø/library-preload.js sap.ui.require.preload({ - "library/ø/manifest.json":'{"_version":"1.9.0","sap.app":{"id":"library.ø","type":"library","embeds":[],"applicationVersion":{"version":"1.0.0"},"title":"Library Ø","description":"Library Ø","resources":"resources.json","offline":true},"sap.ui":{"technology":"UI5","supportedThemes":["цветя"]},"sap.ui5":{"dependencies":{"minUI5Version":"1.0","libs":{}},"library":{"i18n":false}}}', + "library/ø/manifest.json":'{"_version":"1.21.0","sap.app":{"id":"library.ø","type":"library","embeds":[],"applicationVersion":{"version":"1.0.0"},"title":"Library Ø","description":"Library Ø","resources":"resources.json","offline":true},"sap.ui":{"technology":"UI5","supportedThemes":["цветя"]},"sap.ui5":{"dependencies":{"minUI5Version":"1.0","libs":{}},"library":{"i18n":false}}}', "library/ø/some.js":function(){/*! * Some fancy copyright */ diff --git "a/test/expected/build/library.\303\270/dest/resources/library/\303\270/manifest.json" "b/test/expected/build/library.\303\270/dest/resources/library/\303\270/manifest.json" index 3d64a9fbe..e242222ee 100644 --- "a/test/expected/build/library.\303\270/dest/resources/library/\303\270/manifest.json" +++ "b/test/expected/build/library.\303\270/dest/resources/library/\303\270/manifest.json" @@ -1,5 +1,5 @@ { - "_version": "1.9.0", + "_version": "1.21.0", "sap.app": { "id": "library.ø", "type": "library", From 1bda4b2cc9d9e023f1cd76c8bf741ad5f8545bd6 Mon Sep 17 00:00:00 2001 From: Tobias Sorn Date: Wed, 23 Dec 2020 10:51:41 +0100 Subject: [PATCH 08/13] [FEATURE] manifestCreator: i18n section v22 avoid duplicate check for null because createI18nSection() also performs an existence check --- lib/processors/manifestCreator.js | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/lib/processors/manifestCreator.js b/lib/processors/manifestCreator.js index 3664c6f2a..68bc526fe 100644 --- a/lib/processors/manifestCreator.js +++ b/lib/processors/manifestCreator.js @@ -505,11 +505,7 @@ async function createManifest(libraryResource, libBundle, descriptorVersion, _in return false; } } - // i18n can be an empty string therefore check for not being null - if (i18n !== null) { - return createI18nSection(i18n, i18nToSupportedLocales); - } - return false; + return createI18nSection(i18n, i18nToSupportedLocales); } // css: From d443546fa7f75e3d2f2ce2eac89a1c49be53cc49 Mon Sep 17 00:00:00 2001 From: Tobias Sorn Date: Wed, 23 Dec 2020 10:55:39 +0100 Subject: [PATCH 09/13] [FEATURE] manifestCreator: i18n section v22 changed to Array.from instead of spread operator. --- lib/processors/manifestCreator.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/processors/manifestCreator.js b/lib/processors/manifestCreator.js index 68bc526fe..411336dca 100644 --- a/lib/processors/manifestCreator.js +++ b/lib/processors/manifestCreator.js @@ -606,7 +606,7 @@ async function createManifest(libraryResource, libBundle, descriptorVersion, _in i18nToSupportedLocales.set(i18n, supportedLocales); } - const supportedLocalesArray = [...supportedLocales]; + const supportedLocalesArray = Array.from(supportedLocales); supportedLocalesArray.sort(); return { bundleUrl: i18n, From fdec47a65ca64b1c432ab5e1c2ffe6d53edb9d21 Mon Sep 17 00:00:00 2001 From: Tobias Sorn Date: Tue, 5 Jan 2021 16:54:56 +0100 Subject: [PATCH 10/13] Adjust logic such that empty node (i18n) corresponds to the empty string and is reflected as such in the manifest.json "i18n": "" --- lib/processors/manifestCreator.js | 18 +++++----- test/lib/processors/manifestCreator.js | 46 ++++++++++++++++++++++++++ 2 files changed, 55 insertions(+), 9 deletions(-) diff --git a/lib/processors/manifestCreator.js b/lib/processors/manifestCreator.js index 411336dca..4e81d61ef 100644 --- a/lib/processors/manifestCreator.js +++ b/lib/processors/manifestCreator.js @@ -347,10 +347,9 @@ async function createManifest(libraryResource, libBundle, descriptorVersion, _in return osComponents.length > 0 ? osComponents : undefined; } - const i18nAppData = findChild(manifestAppData, "i18n"); + const i18nText = getChildTextContent(manifestAppData, "i18n"); let i18n; - if (i18nAppData) { - const i18nText = i18nAppData._; // text content + if (typeof i18nText === "string") { i18n = createI18nSection(i18nText, i18nToSupportedLocales); log.verbose(`sap.app/i18n taken from .library appData: '%s'`, i18nText); } @@ -487,10 +486,8 @@ async function createManifest(libraryResource, libBundle, descriptorVersion, _in // - from .library/appData/manifest/sap.ui5/library/i18n // - from library resources (if "messagebundle.properties" exists) function i18n() { - const i18nElement = findChild(libraryAppData, "i18n"); - let i18n = null; - if ( i18nElement ) { - i18n = i18nElement._; // text content + let i18n = getChildTextContent(libraryAppData, "i18n"); + if ( typeof i18n === "string") { if ( i18n === "false" ) { return false; } else if ( i18n === "true" ) { @@ -505,6 +502,9 @@ async function createManifest(libraryResource, libBundle, descriptorVersion, _in return false; } } + if (i18n === undefined) { + return false; + } return createI18nSection(i18n, i18nToSupportedLocales); } @@ -568,8 +568,8 @@ async function createManifest(libraryResource, libBundle, descriptorVersion, _in * null if given i18n String is null */ function createI18nSection(i18n, i18nToSupportedLocales) { - if (!i18n) { - return null; + if (i18n === undefined) { + return undefined; } if (!i18n.endsWith(".properties")) { return i18n; diff --git a/test/lib/processors/manifestCreator.js b/test/lib/processors/manifestCreator.js index 5d1ac313e..e30011fab 100644 --- a/test/lib/processors/manifestCreator.js +++ b/test/lib/processors/manifestCreator.js @@ -137,6 +137,52 @@ test.serial("default manifest creation", async (t) => { t.is(await result.getString(), expectedManifestContent, "Correct result returned"); }); +test.serial("default manifest creation i18n empty string", async (t) => { + const {manifestCreator, errorLogStub} = t.context; + const prefix = "/resources/sap/ui/mine/"; + const libraryResource = { + getPath: () => { + return prefix + ".library"; + }, + getString: async () => { + return ` + + library.e + SAP SE + my copyright + 1.0.0 + Library E + + + + sap.ui.core + + + + + + + + + `; + }, + _project: { + dependencies: [{ + metadata: { + name: "sap.ui.core" + } + }] + } + }; + + t.is(errorLogStub.callCount, 0); + const expectedManifestContentObjectModified = expectedManifestContentObject(); + expectedManifestContentObjectModified["sap.app"]["i18n"] = ""; + const expectedManifestContent = JSON.stringify(expectedManifestContentObjectModified, null, 2); + const result = await manifestCreator({libraryResource, resources: [], options: {}}); + t.is(await result.getString(), expectedManifestContent, "Correct result returned"); +}); + test.serial("default manifest creation with special characters", async (t) => { const {manifestCreator, errorLogStub} = t.context; const prefix = "/resources/sap/ui/mine/"; From 6d31f6a928a81f55512874048a73e6acde78ba3a Mon Sep 17 00:00:00 2001 From: Tobias Sorn Date: Fri, 8 Jan 2021 12:32:52 +0100 Subject: [PATCH 11/13] Add test for invalid .library content Add "return" after "reject() call", because a promise should either reject or resovle. --- lib/processors/manifestCreator.js | 1 + test/lib/processors/manifestCreator.js | 23 +++++++++++++++++++++++ 2 files changed, 24 insertions(+) diff --git a/lib/processors/manifestCreator.js b/lib/processors/manifestCreator.js index 4e81d61ef..2bc16b0df 100644 --- a/lib/processors/manifestCreator.js +++ b/lib/processors/manifestCreator.js @@ -115,6 +115,7 @@ class Library { parser.parseString(content, (err, xml) => { if ( err ) { reject(err); + return; } resolve(new Library(xml.library)); }); diff --git a/test/lib/processors/manifestCreator.js b/test/lib/processors/manifestCreator.js index e30011fab..8d5e1779a 100644 --- a/test/lib/processors/manifestCreator.js +++ b/test/lib/processors/manifestCreator.js @@ -1129,3 +1129,26 @@ test.serial("manifest creation with embedded component (invalid manifest.json)", ]); t.true(errorLogStub.getCall(0).args[2].startsWith("SyntaxError: Unexpected token")); }); + +test.serial("manifest creation for invalid .library content", async (t) => { + const {manifestCreator} = t.context; + + const libraryResource = { + getPath: () => { + return "/resources/sap/lib1/.library"; + }, + getString: async () => { + return ` + <<>`; + } + }; + + const error = await t.throwsAsync(manifestCreator({ + libraryResource, + resources: [] + })); + t.deepEqual(error.message, `Unencoded < +Line: 1 +Column: 5 +Char: <`, "error message for unencoded <"); +}); From 7fcc042fdc6e67b65a0ba31b32b4a6e7f2a5ce18 Mon Sep 17 00:00:00 2001 From: Tobias Sorn Date: Fri, 8 Jan 2021 15:10:04 +0100 Subject: [PATCH 12/13] remove unreachable code --- lib/processors/manifestCreator.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/lib/processors/manifestCreator.js b/lib/processors/manifestCreator.js index 2bc16b0df..92696b323 100644 --- a/lib/processors/manifestCreator.js +++ b/lib/processors/manifestCreator.js @@ -500,12 +500,10 @@ async function createManifest(libraryResource, libBundle, descriptorVersion, _in // log.verbose(" sap.ui5/library/i18n property determined from resources: '%s'", library.i18n); i18n = "messagebundle.properties"; } else { + // i18n not defined and no messagebundle.properties return false; } } - if (i18n === undefined) { - return false; - } return createI18nSection(i18n, i18nToSupportedLocales); } From d6e7c64c22d51b43523bc3d4d4c7903461c6a864 Mon Sep 17 00:00:00 2001 From: Tobias Sorn Date: Fri, 8 Jan 2021 16:30:10 +0100 Subject: [PATCH 13/13] add tests for manifestCreator to increase coverage --- test/lib/processors/manifestCreator.js | 165 +++++++++++++++++++++++++ 1 file changed, 165 insertions(+) diff --git a/test/lib/processors/manifestCreator.js b/test/lib/processors/manifestCreator.js index 8d5e1779a..9e853085b 100644 --- a/test/lib/processors/manifestCreator.js +++ b/test/lib/processors/manifestCreator.js @@ -183,6 +183,171 @@ test.serial("default manifest creation i18n empty string", async (t) => { t.is(await result.getString(), expectedManifestContent, "Correct result returned"); }); +test.serial("default manifest creation with invalid version", async (t) => { + const {manifestCreator, errorLogStub} = t.context; + const prefix = "/resources/sap/ui/mine/"; + const libraryResource = { + getPath: () => { + return prefix + ".library"; + }, + getString: async () => { + return ` + + library.e + SAP SE + @version@ + Library E + + + + sap.ui.core + + + + `; + }, + _project: { + dependencies: [{ + metadata: { + name: "sap.ui.core" + } + }], + version: "1.2.3" + } + }; + + t.is(errorLogStub.callCount, 0); + const expectedManifestContentObjectModified = expectedManifestContentObject(); + expectedManifestContentObjectModified["sap.app"]["i18n"] = undefined; + expectedManifestContentObjectModified["sap.app"]["applicationVersion"]["version"] = "1.2.3"; + const expectedManifestContent = JSON.stringify(expectedManifestContentObjectModified, null, 2); + const result = await manifestCreator({libraryResource, resources: [], options: {}}); + t.is(await result.getString(), expectedManifestContent, "Correct result returned"); +}); + +test.serial("default manifest creation with sourceTemplate and thirdparty", async (t) => { + const {manifestCreator, errorLogStub} = t.context; + const prefix = "/resources/sap/ui/mine/"; + const libraryResource = { + getPath: () => { + return prefix + ".library"; + }, + getString: async () => { + return ` + + library.e + SAP SE + @version@ + Library E + + + + sap.ui.core + + + my.lib + 4.5.6 + + + + + + + myid + 1.2.3 + + + + + + + + + `; + }, + _project: { + dependencies: [{ + metadata: { + name: "sap.ui.core" + } + }, { + metadata: { + name: "my.lib" + } + }], + version: "1.2.3" + } + }; + + t.is(errorLogStub.callCount, 0); + const expectedManifestContentObjectModified = expectedManifestContentObject(); + expectedManifestContentObjectModified["sap.app"]["i18n"] = undefined; + expectedManifestContentObjectModified["sap.app"]["applicationVersion"]["version"] = "1.2.3"; + expectedManifestContentObjectModified["sap.app"]["sourceTemplate"]= { + id: "myid", + version: "1.2.3" + }; + expectedManifestContentObjectModified["sap.app"]["openSourceComponents"]= [{ + "name": "jquery-3", + "packagedWithMySelf": true, + "version": "3.5.1" + }, { + "name": "jquery-2", + "packagedWithMySelf": true, + "version": "2.2.3" + }]; + expectedManifestContentObjectModified["sap.ui5"]["dependencies"]["libs"]["my.lib"] = { + "minVersion": "4.5.6" + }; + const expectedManifestContent = JSON.stringify(expectedManifestContentObjectModified, null, 2); + const result = await manifestCreator({libraryResource, resources: [], options: {}}); + t.is(await result.getString(), expectedManifestContent, "Correct result returned"); +}); + +test.serial("default manifest creation no dependency version", async (t) => { + const {manifestCreator, errorLogStub} = t.context; + const prefix = "/resources/sap/ui/mine/"; + const libraryResource = { + getPath: () => { + return prefix + ".library"; + }, + getString: async () => { + return ` + + library.e + SAP SE + Library E + + + + sap.ui.core + + + my.lib + + + + `; + }, + _project: { + dependencies: [{ + metadata: { + name: "sap.ui.core" + } + }] + } + }; + + t.is(errorLogStub.callCount, 0); + + const error = await t.throwsAsync(manifestCreator({ + libraryResource, + resources: [] + })); + t.deepEqual(error.message, + "Couldn't find version for library 'my.lib', project dependency missing?", "error message correct"); +}); + test.serial("default manifest creation with special characters", async (t) => { const {manifestCreator, errorLogStub} = t.context; const prefix = "/resources/sap/ui/mine/";