Skip to content

Commit 0fc364d

Browse files
committed
[FIX] generateResourcesJson: Include dependencies of XML resources
The XML analysis requires dependency resources to be able to list them as "required" in the resources.json. JIRA: CPOUI5FOUNDATION-294
1 parent fce35a5 commit 0fc364d

File tree

4 files changed

+137
-8
lines changed

4 files changed

+137
-8
lines changed

lib/processors/resourceListCreator.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -127,10 +127,11 @@ function makeResourcesJSON(list, prefix) {
127127
* @private
128128
* @param {object} parameters Parameters
129129
* @param {module:@ui5/fs.Resource[]} parameters.resources List of resources
130+
* @param {module:@ui5/fs.Resource[]} [parameters.dependencyResources=[]] List of dependency resources
130131
* @param {object} [parameters.options] Options
131132
* @returns {Promise<module:@ui5/fs.Resource[]>} Promise resolving with the resources.json resources
132133
*/
133-
module.exports = async function({resources, options}) {
134+
module.exports = async function({resources, dependencyResources = [], options}) {
134135
options = Object.assign({
135136
failOnOrphans: false,
136137
externalResources: undefined,
@@ -143,6 +144,7 @@ module.exports = async function({resources, options}) {
143144

144145
const pool = new LocatorResourcePool();
145146
await pool.prepare( resources );
147+
await pool.prepare( dependencyResources );
146148

147149
const collector = new ResourceCollector(pool);
148150
const visitPromises = resources.map((resource) => collector.visitResource(resource));

lib/tasks/generateResourcesJson.js

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -108,16 +108,25 @@ function getCreatorOptions(projectName) {
108108
* @alias module:@ui5/builder.tasks.generateResourcesJson
109109
* @param {object} parameters Parameters
110110
* @param {module:@ui5/fs.DuplexCollection} parameters.workspace DuplexCollection to read and write files
111+
* @param {module:@ui5/fs.AbstractReader} [parameters.dependencies] Reader or Collection to read dependency files
111112
* @param {object} parameters.options Options
112113
* @param {string} parameters.options.projectName Project name
113114
* @returns {Promise<undefined>} Promise resolving with <code>undefined</code> once data has been written
114115
*/
115-
module.exports = async function({workspace, options: {projectName}}) {
116+
module.exports = async function({workspace, dependencies, options: {projectName}}) {
116117
const resources = await workspace.byGlob(["/resources/**/*.*"].concat(DEFAULT_EXCLUDES));
117118

119+
// TODO 3.0: Make dependencies parameter mandatory
120+
let dependencyResources;
121+
if (dependencies) {
122+
dependencyResources =
123+
await dependencies.byGlob("/resources/**/*.{js,json,xml,html,properties,library}");
124+
}
125+
118126
const resourceLists = await resourceListCreator({
119127
resources,
120-
options: getCreatorOptions(projectName)
128+
dependencyResources,
129+
options: getCreatorOptions(projectName),
121130
});
122131
await Promise.all(
123132
resourceLists.map((resourceList) => workspace.write(resourceList))

test/lib/processors/resourceListCreator.js

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,3 +128,80 @@ test.serial("components and themes", async (t) => {
128128
]
129129
}`);
130130
});
131+
132+
test.serial("XML View with control resource as dependency", async (t) => {
133+
const myAppManifestJsonResource = resourceFactory.createResource({
134+
path: "/resources/my/app/manifest.json",
135+
string: JSON.stringify({"sap.app": {"id": "my.app"}})
136+
});
137+
const myAppXmlViewResource = resourceFactory.createResource({
138+
path: "/resources/my/app/view/Main.view.xml",
139+
string: `<mvc:View
140+
controllerName="my.app.controller.Main"
141+
xmlns="my.lib"
142+
xmlns:myapp="my.app.controls"
143+
xmlns:mvc="sap.ui.core.mvc">
144+
145+
<!-- Existing control, should be listed as "required" -->
146+
<Button></Button>
147+
148+
<!-- Nonexistent control, should not be listed -->
149+
<NonexistentControl></NonexistentControl>
150+
151+
<!-- Existing control within same project (app), should be listed as "required" -->
152+
<myapp:Button></myapp:Button>
153+
154+
<!-- Nonexistent control within same project (app), should not be listed -->
155+
<myapp:NonexistentControl></myapp:NonexistentControl>
156+
157+
</mvc:View>`
158+
});
159+
const myAppButtonResource = resourceFactory.createResource({
160+
path: "/resources/my/app/controls/Button.js",
161+
string: ""
162+
});
163+
const myLibButtonResource = resourceFactory.createResource({
164+
path: "/resources/my/lib/Button.js",
165+
string: ""
166+
});
167+
168+
const resourcesJson = await resourceListCreator({
169+
resources: [myAppManifestJsonResource, myAppXmlViewResource, myAppButtonResource],
170+
dependencyResources: [myLibButtonResource]
171+
});
172+
173+
t.is(resourcesJson.length, 1, "One resources.json should be returned");
174+
const myAppResourcesJson = resourcesJson[0];
175+
t.is(myAppResourcesJson.getPath(), "/resources/my/app/resources.json");
176+
const myAppResourcesJsonContent = await myAppResourcesJson.getString();
177+
t.is(myAppResourcesJsonContent, `{
178+
"_version": "1.1.0",
179+
"resources": [
180+
{
181+
"name": "controls/Button.js",
182+
"module": "my/app/controls/Button.js",
183+
"size": 0,
184+
"format": "raw"
185+
},
186+
{
187+
"name": "manifest.json",
188+
"module": "my/app/manifest.json",
189+
"size": 27
190+
},
191+
{
192+
"name": "resources.json",
193+
"size": 523
194+
},
195+
{
196+
"name": "view/Main.view.xml",
197+
"module": "my/app/view/Main.view.xml",
198+
"size": 592,
199+
"required": [
200+
"my/app/controller/Main.controller.js",
201+
"my/app/controls/Button.js",
202+
"my/lib/Button.js"
203+
]
204+
}
205+
]
206+
}`);
207+
});

test/lib/tasks/generateResourcesJson.js

Lines changed: 46 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -30,15 +30,17 @@ test.beforeEach((t) => {
3030
t.context.resourceListCreatorStub = sinon.stub();
3131
t.context.resourceListCreatorStub.returns(Promise.resolve([]));
3232
mock("../../../lib/processors/resourceListCreator", t.context.resourceListCreatorStub);
33-
mock.reRequire("../../../lib/processors/resourceListCreator");
33+
34+
t.context.generateResourcesJson = mock.reRequire("../../../lib/tasks/generateResourcesJson");
3435
});
3536

3637
test.afterEach.always((t) => {
37-
mock.stop("../../../lib/processors/resourceListCreator");
38+
sinon.restore();
39+
mock.stopAll();
3840
});
3941

40-
test("empty resources", async (t) => {
41-
const generateResourcesJson = require("../../../lib/tasks/generateResourcesJson");
42+
test.serial("empty resources (sap.ui.core)", async (t) => {
43+
const {generateResourcesJson, resourceListCreatorStub} = t.context;
4244

4345
const result = await generateResourcesJson({
4446
workspace: createWorkspace(),
@@ -48,7 +50,7 @@ test("empty resources", async (t) => {
4850
}
4951
});
5052
t.deepEqual(result, undefined, "no resources returned");
51-
t.is(t.context.resourceListCreatorStub.callCount, 1);
53+
t.is(resourceListCreatorStub.callCount, 1);
5254
const expectedOptions = {
5355
externalResources: {
5456
"sap/ui/core": [
@@ -70,5 +72,44 @@ test("empty resources", async (t) => {
7072
"**/library-preload.support.js"
7173
]
7274
};
75+
t.deepEqual(resourceListCreatorStub.getCall(0).args[0].options, expectedOptions, "options match");
76+
});
77+
78+
test.serial("empty resources (my.lib)", async (t) => {
79+
const generateResourcesJson = require("../../../lib/tasks/generateResourcesJson");
80+
81+
const result = await generateResourcesJson({
82+
workspace: createWorkspace(),
83+
dependencies: undefined,
84+
options: {
85+
projectName: "my.lib"
86+
}
87+
});
88+
t.deepEqual(result, undefined, "no resources returned");
89+
t.is(t.context.resourceListCreatorStub.callCount, 1);
90+
const expectedOptions = {};
91+
t.deepEqual(t.context.resourceListCreatorStub.getCall(0).args[0].options, expectedOptions, "options match");
92+
});
93+
94+
test.serial("empty resources (my.lib with dependencies)", async (t) => {
95+
const generateResourcesJson = require("../../../lib/tasks/generateResourcesJson");
96+
97+
const dependencyResources = [{"dependency": "resources"}];
98+
const dependencies = {
99+
byGlob: sinon.stub().resolves(dependencyResources)
100+
};
101+
102+
const result = await generateResourcesJson({
103+
workspace: createWorkspace(),
104+
dependencies,
105+
options: {
106+
projectName: "my.lib"
107+
}
108+
});
109+
t.deepEqual(result, undefined, "no resources returned");
110+
t.is(t.context.resourceListCreatorStub.callCount, 1);
111+
const expectedOptions = {};
73112
t.deepEqual(t.context.resourceListCreatorStub.getCall(0).args[0].options, expectedOptions, "options match");
113+
t.is(t.context.resourceListCreatorStub.getCall(0).args[0].dependencyResources, dependencyResources,
114+
"dependencyResources reference should be passed to resourceListCreator");
74115
});

0 commit comments

Comments
 (0)