Skip to content

Commit

Permalink
[FEATURE] TaskUtil: Add getProject/getDependencies API to interface
Browse files Browse the repository at this point in the history
New API is only available to custom tasks defining specVerson 3.0 and
later.
  • Loading branch information
RandomByte committed Nov 24, 2022
1 parent 75e88b9 commit 51f2949
Show file tree
Hide file tree
Showing 5 changed files with 147 additions and 16 deletions.
11 changes: 11 additions & 0 deletions lib/build/helpers/ProjectBuildContext.js
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,17 @@ class ProjectBuildContext {
return this._project;
}

/**
* Retrieve a list of direct dependencies of a given project from the dependency graph
*
* @param {string} [projectName] Name of the project to retrieve. Defaults to the project currently being built
* @returns {string[]} Names of all direct dependencies
* @throws {Error} If the requested project is unknown to the graph
*/
getDependencies(projectName) {
return this._buildContext.getGraph().getDependencies(projectName || this._project.getName());
}

getResourceTagCollection(resource, tag) {
if (!resource.hasProject()) {
this._log.silly(`Associating resource ${resource.getPath()} with project ${this._project.getName()}`);
Expand Down
25 changes: 23 additions & 2 deletions lib/build/helpers/TaskUtil.js
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,7 @@ class TaskUtil {
* This method is only available to custom task extensions defining
* <b>Specification Version 3.0 and above</b>.
*
* @param {string} projectName Name of the project to retrieve
* @param {string} [projectName] Name of the project to retrieve. Defaults to the project currently being built
* @returns {@ui5/project/specifications/Project|undefined}
* project instance or undefined if the project is unknown to the graph
* @public
Expand All @@ -186,6 +186,23 @@ class TaskUtil {
return this._projectBuildContext.getProject(projectName);
}

/**
* Retrieve a list of direct dependencies of a given project from the dependency graph.
* Note that this list does not include transitive dependencies.
*
* </br></br>
* This method is only available to custom task extensions defining
* <b>Specification Version 3.0 and above</b>.
*
* @param {string} [projectName] Name of the project to retrieve. Defaults to the project currently being built
* @returns {string[]} Names of all direct dependencies
* @throws {Error} If the requested project is unknown to the graph
* @public
*/
getDependencies(projectName) {
return this._projectBuildContext.getDependencies(projectName);
}

/**
* Get an interface to an instance of this class that only provides those functions
* that are supported by the given custom task extension specification version.
Expand Down Expand Up @@ -216,13 +233,17 @@ class TaskUtil {
const project = this.getProject(projectName);
const baseProjectInterface = {};
bindFunctions(project, baseProjectInterface, [
"getName", "getVersion", "getNamespace"
"getSpecVersion", "getType", "getName", "getVersion", "getNamespace",
"getRootReader", "getReader", "getCustomConfiguration", "isFrameworkProject"
]);
switch (specVersion) {
case "3.0":
return baseProjectInterface;
}
};
baseInterface.getDependencies = (projectName) => {
return this.getDependencies(projectName);
};
return baseInterface;
default:
throw new Error(`TaskUtil: Unknown or unsupported Specification Version ${specVersion}`);
Expand Down
2 changes: 1 addition & 1 deletion lib/graph/ProjectGraph.js
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,7 @@ class ProjectGraph {
*
* @public
* @param {string} projectName Name of the project to retrieve the dependencies of
* @returns {string[]} Project names
* @returns {string[]} Names of all direct dependencies
*/
getDependencies(projectName) {
const adjacencies = this._adjList[projectName];
Expand Down
61 changes: 60 additions & 1 deletion test/lib/build/helpers/ProjectBuildContext.js
Original file line number Diff line number Diff line change
Expand Up @@ -219,13 +219,72 @@ test("getProject", (t) => {
});

t.is(projectBuildContext.getProject("pony project"), "pony", "Returned correct value");
t.is(getProjectStub.callCount, 1);
t.is(getProjectStub.callCount, 1, "getProject got called once");
t.is(getProjectStub.getCall(0).args[0], "pony project", "getProject got called with correct argument");

t.is(projectBuildContext.getProject(), project);
t.is(getProjectStub.callCount, 1, "getProject is not called again when requesting current project");
});

test("getProject: No name provided", (t) => {
const project = "project";
const getProjectStub = sinon.stub().returns("pony");
const projectBuildContext = new ProjectBuildContext({
buildContext: {
getGraph: () => {
return {
getProject: getProjectStub
};
}
},
project,
log: "log"
});

t.is(projectBuildContext.getProject(), "project", "Returned correct value");
t.is(getProjectStub.callCount, 0, "getProject has not been called");
});

test("getDependencies", (t) => {
const project = "project";
const getDependenciesStub = sinon.stub().returns(["dep a", "dep b"]);
const projectBuildContext = new ProjectBuildContext({
buildContext: {
getGraph: () => {
return {
getDependencies: getDependenciesStub
};
}
},
project,
log: "log"
});

t.deepEqual(projectBuildContext.getDependencies("pony project"), ["dep a", "dep b"], "Returned correct value");
t.is(getDependenciesStub.callCount, 1, "getDependencies got called once");
t.is(getDependenciesStub.getCall(0).args[0], "pony project", "getProject got called with correct arguments");
});

test("getDependencies: No name provided", (t) => {
const project = {getName: () => "project"};
const getDependenciesStub = sinon.stub().returns(["dep a", "dep b"]);
const projectBuildContext = new ProjectBuildContext({
buildContext: {
getGraph: () => {
return {
getDependencies: getDependenciesStub
};
}
},
project,
log: "log"
});

t.deepEqual(projectBuildContext.getDependencies(), ["dep a", "dep b"], "Returned correct value");
t.is(getDependenciesStub.callCount, 1, "getDependencies got called once");
t.is(getDependenciesStub.getCall(0).args[0], "project", "getProject got called with correct arguments");
});

test("getTaskUtil", (t) => {
const projectBuildContext = new ProjectBuildContext({
buildContext: {},
Expand Down
64 changes: 52 additions & 12 deletions test/lib/build/helpers/TaskUtil.js
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,6 @@ test("getBuildOption", (t) => {
t.is(res, "Pony", "Correct result");
});


test("getProject", (t) => {
const getProjectStub = sinon.stub().returns("Pony farm!");
const taskUtil = new TaskUtil({
Expand All @@ -164,12 +163,26 @@ test("getProject", (t) => {
}
});

const res = taskUtil.getProject("pony farm?");
const res = taskUtil.getProject("pony farm");

t.is(getProjectStub.callCount, 1, "ProjectBuildContext#getProject got called once");
t.is(res, "Pony farm!", "Correct result");
});

test("getDependencies", (t) => {
const getDependenciesStub = sinon.stub().returns("Pony farm!");
const taskUtil = new TaskUtil({
projectBuildContext: {
getDependencies: getDependenciesStub
}
});

const res = taskUtil.getDependencies("pony farm");

t.is(getDependenciesStub.callCount, 1, "ProjectBuildContext#getDependencies got called once");
t.is(res, "Pony farm!", "Correct result");
});

test("registerCleanupTask", (t) => {
const registerCleanupTaskStub = sinon.stub();
const taskUtil = new TaskUtil({
Expand Down Expand Up @@ -316,15 +329,23 @@ test("getInterface: specVersion 2.6", (t) => {

test("getInterface: specVersion 3.0", (t) => {
const getProjectStub = sinon.stub().returns({
getName: () => "",
getVersion: () => "",
getNamespace: () => "",
hasBuildManifest: () => "", // Should not be exposed
getFrameworkVersion: () => "", // Should not be exposed
getSpecVersion: () => "specVersion",
getType: () => "type",
getName: () => "name",
getVersion: () => "version",
getNamespace: () => "namespace",
getRootReader: () => "rootReader",
getReader: () => "reader",
getCustomConfiguration: () => "customConfiguration",
isFrameworkProject: () => "isFrameworkProject",
hasBuildManifest: () => "hasBuildManifest", // Should not be exposed
getFrameworkVersion: () => "frameworkVersion", // Should not be exposed
});
const getDependenciesStub = sinon.stub().returns(["dep a", "dep b"]);
const taskUtil = new TaskUtil({
projectBuildContext: {
getProject: getProjectStub
getProject: getProjectStub,
getDependencies: getDependenciesStub
}
});

Expand All @@ -337,7 +358,8 @@ test("getInterface: specVersion 3.0", (t) => {
"getTag",
"isRootProject",
"registerCleanupTask",
"getProject"
"getProject",
"getDependencies"
], "Correct methods are provided");

t.deepEqual(interfacedTaskUtil.STANDARD_TAGS, STANDARD_TAGS, "attribute STANDARD_TAGS is provided");
Expand All @@ -350,13 +372,31 @@ test("getInterface: specVersion 3.0", (t) => {

const interfacedProject = interfacedTaskUtil.getProject("pony");
t.deepEqual(Object.keys(interfacedProject), [
"getSpecVersion",
"getType",
"getName",
"getVersion",
"getNamespace",
"getRootReader",
"getReader",
"getCustomConfiguration",
"isFrameworkProject",
], "Correct methods are provided");
t.is(typeof interfacedProject.getName, "function", "function getName is provided");
t.is(typeof interfacedProject.getVersion, "function", "function getVersion is provided");
t.is(typeof interfacedProject.getNamespace, "function", "function getNamespace is provided");

t.is(interfacedProject.getSpecVersion(), "specVersion", "getSpecVersion function is bound correctly");
t.is(interfacedProject.getType(), "type", "getType function is bound correctly");
t.is(interfacedProject.getName(), "name", "getName function is bound correctly");
t.is(interfacedProject.getVersion(), "version", "getVersion function is bound correctly");
t.is(interfacedProject.getNamespace(), "namespace", "getNamespace function is bound correctly");
t.is(interfacedProject.getRootReader(), "rootReader", "getRootReader function is bound correctly");
t.is(interfacedProject.getReader(), "reader", "getReader function is bound correctly");
t.is(interfacedProject.getCustomConfiguration(), "customConfiguration",
"getCustomConfiguration function is bound correctly");
t.is(interfacedProject.isFrameworkProject(), "isFrameworkProject",
"isFrameworkProject function is bound correctly");

t.deepEqual(interfacedTaskUtil.getDependencies("pony"), ["dep a", "dep b"],
"getDependencies function is available and bound correctly");
});

test("getInterface: specVersion undefined", (t) => {
Expand Down

0 comments on commit 51f2949

Please sign in to comment.