Skip to content

Commit b8a59d5

Browse files
committed
[FEATURE] projectPreprocessor: Allow application project dependency on non-root level
Resolves #61
1 parent 7f2366f commit b8a59d5

File tree

2 files changed

+150
-6
lines changed

2 files changed

+150
-6
lines changed

lib/projectPreprocessor.js

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -283,12 +283,19 @@ class ProjectPreprocessor {
283283
throw new Error(`Root project needs to be of kind "project". ${project.id} is of kind ${project.kind}`);
284284
}
285285

286-
if (project.kind === "project" && project.type === "application" && project._level !== 0) {
287-
// There is only one project project of type application allowed
288-
// That project needs to be the root project
289-
log.verbose(`[Warn] Ignoring project ${project.id} with type application`+
290-
` (distance to root: ${project._level}). Type application is only allowed for the root project`);
291-
return false; // ignore this project
286+
if (project.kind === "project" && project.type === "application") {
287+
// There must be exactly one application project per dependency tree
288+
// If multiple are found, all but the one closest to the root are rejected (ignored)
289+
// If there are two projects equally close to the root, an error is being thrown
290+
if (!this.qualifiedApplicationProject) {
291+
this.qualifiedApplicationProject = project;
292+
} else if (this.qualifiedApplicationProject._level === project._level) {
293+
throw new Error(`Found at least two projects ${this.qualifiedApplicationProject.id} and ` +
294+
`${project.id} of type application with the same distance to the root project. ` +
295+
"Only one project of type application can be used. Failed to decide which one to ignore.");
296+
} else {
297+
return false; // ignore this project
298+
}
292299
}
293300

294301
return true;

test/lib/projectPreprocessor.js

Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,143 @@ test("Missing dependencies", (t) => {
200200
"Gracefully accepted project with no dependency attribute");
201201
});
202202

203+
test("Single non-root application-project", (t) => {
204+
const tree = ({
205+
id: "library.a",
206+
version: "1.0.0",
207+
path: libraryAPath,
208+
dependencies: [{
209+
id: "application.a",
210+
version: "1.0.0",
211+
path: applicationAPath,
212+
dependencies: []
213+
}]
214+
});
215+
return projectPreprocessor.processTree(tree).then((parsedTree) => {
216+
t.deepEqual(parsedTree.id, "library.a", "Correct root project");
217+
t.deepEqual(parsedTree.dependencies.length, 1, "application-project dependency was not ignored");
218+
t.deepEqual(parsedTree.dependencies[0].id, "application.a", "application-project is on second level");
219+
});
220+
});
221+
222+
test("Multiple non-root application-projects on same level", (t) => {
223+
const tree = ({
224+
id: "library.a",
225+
version: "1.0.0",
226+
path: libraryAPath,
227+
dependencies: [{
228+
id: "application.a",
229+
version: "1.0.0",
230+
path: applicationAPath,
231+
dependencies: []
232+
}, {
233+
id: "application.b",
234+
version: "1.0.0",
235+
path: applicationBPath,
236+
dependencies: []
237+
}]
238+
});
239+
return t.throws(projectPreprocessor.processTree(tree),
240+
"Found at least two projects application.a and application.b of type application with the same distance to " +
241+
"the root project. Only one project of type application can be used. Failed to decide which one to ignore.",
242+
"Rejected with error");
243+
});
244+
245+
test("Multiple non-root application-projects on different levels", (t) => {
246+
const tree = ({
247+
id: "library.a",
248+
version: "1.0.0",
249+
path: libraryAPath,
250+
dependencies: [{
251+
id: "application.a",
252+
version: "1.0.0",
253+
path: applicationAPath,
254+
dependencies: []
255+
}, {
256+
id: "library.b",
257+
version: "1.0.0",
258+
path: libraryBPath,
259+
dependencies: [{
260+
id: "application.b",
261+
version: "1.0.0",
262+
path: applicationBPath,
263+
dependencies: []
264+
}]
265+
}]
266+
});
267+
return projectPreprocessor.processTree(tree).then((parsedTree) => {
268+
t.deepEqual(parsedTree.id, "library.a", "Correct root project");
269+
t.deepEqual(parsedTree.dependencies.length, 2, "No dependency of the first level got ignored");
270+
t.deepEqual(parsedTree.dependencies[0].id, "application.a", "First application-project did not get ignored");
271+
t.deepEqual(parsedTree.dependencies[1].dependencies.length, 0,
272+
"Second (deeper) application-project got ignored");
273+
});
274+
});
275+
276+
test("Root- and non-root application-projects", (t) => {
277+
const tree = ({
278+
id: "application.a",
279+
version: "1.0.0",
280+
path: applicationAPath,
281+
dependencies: [{
282+
id: "library.a",
283+
version: "1.0.0",
284+
path: libraryAPath,
285+
dependencies: [{
286+
id: "application.b",
287+
version: "1.0.0",
288+
path: applicationBPath,
289+
dependencies: []
290+
}]
291+
}]
292+
});
293+
return projectPreprocessor.processTree(tree).then((parsedTree) => {
294+
t.deepEqual(parsedTree.id, "application.a", "Correct root project");
295+
t.deepEqual(parsedTree.dependencies[0].id, "library.a", "Correct library dependency");
296+
t.deepEqual(parsedTree.dependencies[0].dependencies[0], undefined,
297+
"Second application-project dependency was ignored");
298+
});
299+
});
300+
301+
test("Ignores additional application-projects", (t) => {
302+
const tree = ({
303+
id: "application.a",
304+
version: "1.0.0",
305+
path: applicationAPath,
306+
dependencies: [{
307+
id: "application.b",
308+
version: "1.0.0",
309+
path: applicationBPath,
310+
dependencies: []
311+
}]
312+
});
313+
return projectPreprocessor.processTree(tree).then((parsedTree) => {
314+
t.deepEqual(parsedTree, {
315+
_level: 0,
316+
type: "application",
317+
metadata: {
318+
name: "application.a"
319+
},
320+
resources: {
321+
configuration: {
322+
paths: {
323+
webapp: "webapp"
324+
}
325+
},
326+
pathMappings: {
327+
"/": "webapp",
328+
}
329+
},
330+
dependencies: [],
331+
id: "application.a",
332+
kind: "project",
333+
version: "1.0.0",
334+
specVersion: "0.1",
335+
path: applicationAPath
336+
}, "Parsed correctly");
337+
});
338+
});
339+
203340
test("Inconsistent dependencies with same ID", (t) => {
204341
// The one closer to the root should win
205342
const tree = {

0 commit comments

Comments
 (0)