Skip to content

Commit

Permalink
[FEATURE] AbstractBuilder: Allow adding custom tasks for types that h…
Browse files Browse the repository at this point in the history
…ave no standard tasks

Types like "module" do not define any standard tasks. Hence custom tasks
can't reference anything in their "beforeTask" and "afterTask"
configuration.

With this change, the first custom task that a project of such type
defines can omit the before- or afterTask configuration and will be
automatically added as the first tasks.

Resolves https://github.com/SAP/ui5-builder/issues/368
  • Loading branch information
RandomByte committed Dec 17, 2019
1 parent 0b47505 commit 654450d
Show file tree
Hide file tree
Showing 2 changed files with 68 additions and 11 deletions.
29 changes: 18 additions & 11 deletions lib/types/AbstractBuilder.js
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,8 @@ class AbstractBuilder {
throw new Error(`Custom task definition ${taskDef.name} of project ${project.metadata.name} ` +
`defines both "beforeTask" and "afterTask" parameters. Only one must be defined.`);
}
if (!taskDef.beforeTask && !taskDef.afterTask) {
if (this.taskExecutionOrder.length && !taskDef.beforeTask && !taskDef.afterTask) {
// Iff there are tasks configured, beforeTask or afterTask must be given
throw new Error(`Custom task definition ${taskDef.name} of project ${project.metadata.name} ` +
`defines neither a "beforeTask" nor an "afterTask" parameter. One must be defined.`);
}
Expand Down Expand Up @@ -115,17 +116,23 @@ class AbstractBuilder {

this.tasks[newTaskName] = execTask;

const refTaskName = taskDef.beforeTask || taskDef.afterTask;
let refTaskIdx = this.taskExecutionOrder.indexOf(refTaskName);
if (refTaskIdx === -1) {
throw new Error(`Could not find task ${refTaskName}, referenced by custom task ${newTaskName}, ` +
`to be scheduled for project ${project.metadata.name}`);
}
if (taskDef.afterTask) {
// Insert after index of referenced task
refTaskIdx++;
if (this.taskExecutionOrder.length) {
// There is at least one task configured. Use before- and afterTask to add the custom task
const refTaskName = taskDef.beforeTask || taskDef.afterTask;
let refTaskIdx = this.taskExecutionOrder.indexOf(refTaskName);
if (refTaskIdx === -1) {
throw new Error(`Could not find task ${refTaskName}, referenced by custom task ${newTaskName}, ` +
`to be scheduled for project ${project.metadata.name}`);
}
if (taskDef.afterTask) {
// Insert after index of referenced task
refTaskIdx++;
}
this.taskExecutionOrder.splice(refTaskIdx, 0, newTaskName);
} else {
// There is no task configured so far. Just add the custom task
this.taskExecutionOrder.push(newTaskName);
}
this.taskExecutionOrder.splice(refTaskIdx, 0, newTaskName);
}
}

Expand Down
50 changes: 50 additions & 0 deletions test/lib/types/AbstractBuilder.js
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,16 @@ class CustomBuilder extends AbstractBuilder {
}
}

class EmptyBuilder extends AbstractBuilder {
constructor({project, resourceCollections}) {
super({parentLogger, project, resourceCollections});
}

addStandardTasks({resourceCollections, project}) {
// None - like the ModuleBuilder
}
}

test("Instantiation with standard tasks only", (t) => {
const project = clone(applicationBTree);

Expand Down Expand Up @@ -178,6 +188,46 @@ test.serial("Instantiation with custom task", (t) => {
"Order of tasks is correct");
});

test.serial("Instantiation of empty builder with custom tasks", (t) => {
const customTask = function() {};
sinon.stub(taskRepository, "getTask").returns(customTask);

const project = clone(applicationBTree);
project.builder = {
customTasks: [{
name: "myTask"
}, {
name: "myTask2",
beforeTask: "myTask"
}]
};
const customBuilder = new EmptyBuilder({project});
t.truthy(customBuilder.tasks["myTask"], "Custom task has been added to task array");
t.truthy(customBuilder.tasks["myTask2"], "Custom task 2 has been added to task array");
t.deepEqual(customBuilder.taskExecutionOrder,
["myTask2", "myTask"],
"Order of tasks is correct");
});

test.serial("Instantiation of empty builder with 2nd custom tasks defining neither beforeTask nor afterTask", (t) => {
const customTask = function() {};
sinon.stub(taskRepository, "getTask").returns(customTask);

const project = clone(applicationBTree);
project.builder = {
customTasks: [{
name: "myTask"
}, {
name: "myTask2" // should define before- or afterTask
}]
};
const error = t.throws(() => {
new EmptyBuilder({project});
}, Error);
t.deepEqual(error.message, `Custom task definition myTask2 of project application.b defines ` +
`neither a "beforeTask" nor an "afterTask" parameter. One must be defined.`, "Correct exception thrown");
});

test.serial("Instantiation with custom task defined three times", (t) => {
const customTask = function() {};
sinon.stub(taskRepository, "getTask").returns(customTask);
Expand Down

0 comments on commit 654450d

Please sign in to comment.