diff --git a/lib/processors/manifestCreator.js b/lib/processors/manifestCreator.js index ed9395095..92696b323 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"; @@ -114,6 +115,7 @@ class Library { parser.parseString(content, (err, xml) => { if ( err ) { reject(err); + return; } resolve(new Library(xml.library)); }); @@ -123,13 +125,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 +163,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 +348,18 @@ async function createManifest(libraryResource, libBundle, descriptorVersion, _in return osComponents.length > 0 ? osComponents : undefined; } - + const i18nText = getChildTextContent(manifestAppData, "i18n"); + let i18n; + if (typeof i18nText === "string") { + 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() }, @@ -456,25 +487,24 @@ 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"); - if ( i18nElement ) { - const i18n = i18nElement._; + let i18n = getChildTextContent(libraryAppData, "i18n"); + if ( typeof i18n === "string") { 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 { + // i18n not defined and no messagebundle.properties return false; } } + return createI18nSection(i18n, i18nToSupportedLocales); } // css: @@ -525,6 +555,64 @@ 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 === undefined) { + return undefined; + } + 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 i18nPathPrefix = i18n.substring(0, i18n.length - ".properties".length) + "_"; + // e.g. i18n/i18n_ + + libBundle.getResources().forEach((resource) => { + const resPath = resource.getPath(); + // 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, "-")); + } + } + }); + i18nToSupportedLocales.set(i18n, supportedLocales); + } + + const supportedLocalesArray = Array.from(supportedLocales); + supportedLocalesArray.sort(); + return { + bundleUrl: i18n, + supportedLocales: supportedLocalesArray + }; + } + function createSapFiori() { // collect registrationIds if present function registrationIds() { @@ -613,7 +701,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-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/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/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", diff --git a/test/lib/processors/manifestCreator.js b/test/lib/processors/manifestCreator.js index a57bf8008..9e853085b 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 = ` @@ -16,37 +17,79 @@ const libraryContent = ` sap.ui.core + + + + i18n/i18n.properties + + `; -const expectedManifestContent = `{ - "_version": "1.9.0", - "sap.app": { - "id": "library.e", - "type": "library", - "embeds": [], - "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 libraryContentSpecialChars = ` + + library.e + SAP SE + my copyright + 1.0.0 + Library E + + + + sap.ui.core + + + + + + i18n(.*)./i18n(.*).properties + + +`; + +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(); @@ -65,10 +108,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 +124,309 @@ 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: {}}); + 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 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/"; + 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`; + } + }; + }); + + // 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; + const prefix = "/resources/sap/apf/"; + const libraryResource = { getPath: () => { return "/resources/sap/apf/.library"; @@ -109,27 +445,38 @@ test.serial("manifest creation for sap/apf", async (t) => { const componentResource = { getPath: () => { - return "/resources/sap/apf/Component.js"; + return prefix + "Component.js"; } }; - - const result = await manifestCreator({libraryResource, resources: [componentResource], options: {}}); + const resources = ["", "_en", "_de"].map((lang) => { + return { + getPath: () => { + return `${prefix}i18n/i18n${lang}.properties`; + } + }; + }); + resources.push(componentResource); + 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 for sap/ui/core", async (t) => { const {manifestCreator, errorLogStub, verboseLogStub} = t.context; const expectedManifestContent = JSON.stringify({ - "_version": "1.9.0", + "_version": "1.21.0", "sap.app": { "id": "sap.ui.core", "type": "library", @@ -194,7 +541,7 @@ test.serial("manifest creation with .library / Component.js at same namespace", 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", @@ -267,7 +614,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", @@ -357,7 +704,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", @@ -441,7 +788,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", @@ -530,7 +877,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", @@ -619,7 +966,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", @@ -704,7 +1051,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", @@ -792,7 +1139,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", @@ -868,7 +1215,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", @@ -947,3 +1294,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 <"); +}); 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",