Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support Nunjucks templating engine for API call construction #30

Merged
merged 9 commits into from
Sep 3, 2021
76 changes: 76 additions & 0 deletions __test__/data/multi_input_edge.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
{
"input": {
"id": "MONDO:0005252",
"fields": [
"subject",
"association"
],
"specialpath": "/querytest"
},
"query_operation": {
"path_params": [
"path"
],
"params": {
"fields": "{{ fields | join(',') }}",
"q": "object.MONDO:\"{{ id }}\" AND subject.type:SmallMolecule",
"size": 1000,
"path": "{{ specialpath }}"
},
"request_body": {
"body": {
"q": "{{ id }}",
"fields": "{{ fields | join(',') }}"
},
"header": "application/x-www-form-urlencoded"
},
"supportBatch": false,
"method": "get",
"pathParams": [],
"server": "https://biothings.ncats.io/text_mining_co_occurrence_kp",
"path": "{path}",
"tags": [
"gene",
"chemical",
"association",
"annotation",
"query",
"translator",
"biothings",
"biothings_graph"
]
},
"association": {
"input_id": "MONDO",
"input_type": "Disease",
"output_id": "CHEBI",
"output_type": "SmallMolecule",
"predicate": "related_to",
"source": "Text Mining KP",
"api_name": "Text Mining CO-OCCURRENCE API",
"smartapi": {},
"x-translator": {
"component": "KP",
"team": [
"Text Mining Provider",
"Service Provider"
]
}
},
"response_mapping": {
"related_to": {
"CHEBI": "hits.subject.CHEBI",
"ngd": "hits.association.ngd"
}
},
"tags": [
"gene",
"chemical",
"association",
"annotation",
"query",
"translator",
"biothings",
"biothings_graph"
]
}
2 changes: 1 addition & 1 deletion __test__/integration/integration.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -64,4 +64,4 @@ describe("Integration test", () => {
expect(res.length).toEqual(mydisease_res.data["mondo.descendants"].length)
})
})
})
})
35 changes: 34 additions & 1 deletion __test__/query_builder.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
*/

const qb = require("../src/builder/query_builder");
const path = require("path");
const fs = require ("fs");

describe("test query builder class", () => {

Expand Down Expand Up @@ -64,6 +66,15 @@ describe("test query builder class", () => {
const res = builder._getUrl(edge, 'hello');
expect(res).toBe("https://google.com/hello/json/query")
})

test("if _getUrl nunjucks templates are filled", () => {
const edge_path = path.resolve(__dirname, "data/multi_input_edge.json");
edge = JSON.parse(fs.readFileSync(edge_path));

const builder = new qb(edge);
const res = builder._getUrl(edge, edge.input);
expect(res).toEqual("https://biothings.ncats.io/text_mining_co_occurrence_kp/querytest");
})
})

describe("Test _getInput function", () => {
Expand Down Expand Up @@ -175,6 +186,19 @@ describe("test query builder class", () => {
const res = builder._getParams(edge, '1017');
expect(res.output).toEqual(1);
})

test("if _getParams nunjucks templates are filled", () => {
const edge_path = path.resolve(__dirname, "data/multi_input_edge.json");
edge = JSON.parse(fs.readFileSync(edge_path));

const builder = new qb(edge);
const res = builder._getParams(edge, edge.input);
expect(res).toEqual({
fields: "subject,association",
q: 'object.MONDO:"MONDO:0005252" AND subject.type:SmallMolecule',
size: 1000,
});
})
})

describe("test _getRequestBody function", () => {
Expand Down Expand Up @@ -230,6 +254,15 @@ describe("test query builder class", () => {
const res = builder._getRequestBody(edge, "1017");
expect(res).toEqual("geneid=hello&output=1017")
})

test("if nunjucks _getRequestBody templates are filled", () => {
const edge_path = path.resolve(__dirname, "data/multi_input_edge.json");
edge = JSON.parse(fs.readFileSync(edge_path));

const builder = new qb(edge);
const res = builder._getRequestBody(edge, edge.input);
expect(res).toEqual("q=MONDO:0005252&fields=subject,association");
});
})

describe("test constructAxiosRequestConfig function", () => {
Expand Down Expand Up @@ -323,4 +356,4 @@ describe("test query builder class", () => {
expect(res).toBeFalsy();
})
})
})
})
101 changes: 101 additions & 0 deletions __test__/template_funcs.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
const nunjucks = require("nunjucks");
const nunjucksConfig = require("../src/builder/nunjucks_config");
const env = nunjucks.configure({ autoescape: false });
nunjucksConfig(env);

describe("test templateFuncs", () => {

test("substr behavior", () => {
const str = "abcdefghi";
const run = (str, begin, end) => nunjucks.renderString(`{{ test | substr(${begin}, ${end}) }}`, {test: str});
let res;
res = run(str);
expect(res).toEqual(str);
res = run(str, 1);
expect(res).toEqual(str.slice(1));
res = run(str, 3, 6);
expect(res).toEqual(str.slice(3, 6));
res = run(str, 0, -3);
expect(res).toEqual(str.slice(0, -3));
});

test("addPrefix behavior", () => {
const has = "PREFIX:usefulid";
const hasnot = "usefulid";
const run = (str, prefix, delim) => {
prefix = typeof prefix === 'undefined' ? undefined : `"${prefix}"`;
delim = typeof delim === 'undefined' ? undefined : `"${delim}"`;
return nunjucks.renderString(`{{ test | addPrefix(${prefix}, ${delim}) }}`, {test: str})
};
let res;
res = run(hasnot, "PREFIX");
expect(res).toEqual(has);
res = run(hasnot, "PREFIX", "-");
expect(res).toEqual("PREFIX-" + hasnot);
});

test("rmPrefix behavior", () => {
const has = "PREFIX:usefulid";
const hasnot = "usefulid";
const run = (str, delim) => {
delim = typeof delim === 'undefined' ? undefined : `"${delim}"`;
return nunjucks.renderString(`{{ test | rmPrefix(${delim}) }}`, {test: str})
};
let res;
res = run(has);
expect(res).toEqual(hasnot);
res = run(has, "-");
expect(res).toEqual(has);
res = run(hasnot);
expect(res).toEqual(hasnot);
});

test("replPrefix behavior", () => {
const has = "PREFIX:usefulid";
const hasnot = "usefulid";
const run = (str, prefix, delim) => {
prefix = typeof prefix === 'undefined' ? undefined : `"${prefix}"`;
delim = typeof delim === 'undefined' ? undefined : `"${delim}"`;
return nunjucks.renderString(`{{ test | replPrefix(${prefix}, ${delim}) }}`, {test: str})
};
let res;
res = run(has, "NEWFIX");
expect(res).toEqual("NEWFIX:" + hasnot);
res = run(hasnot, "NEWFIX");
expect(res).toEqual("NEWFIX:" + hasnot);
res = run(has);
expect(res).toEqual(hasnot);
res = run(has, "NEWFIX", "-");
expect(res).toEqual("NEWFIX-PREFIX:" + hasnot);
});

test("array usage", () => {
const has = ["PREFIX:id0", "PREFIX:id1", "PREFIX:id2"];
const hasnot = "usefulid";
let res;
let run = (str, delim) => {
prefix = typeof prefix === "undefined" ? undefined : `"${prefix}"`;
delim = typeof delim === "undefined" ? undefined : `"${delim}"`;
return nunjucks.renderString(`{{ test | rmPrefix(${prefix}, ${delim}) | join(",") }}`, { test: str });
};
res = run(has);
expect(res).toEqual("id0,id1,id2");
run = (str, prefix, delim) => {
prefix = typeof prefix === "undefined" ? undefined : `"${prefix}"`;
delim = typeof delim === "undefined" ? undefined : `"${delim}"`;
return nunjucks.renderString(`{{ test | addPrefix(${prefix}, ${delim}) | join(",") }}`, { test: str });
};
res = run(has, "test", ":");
expect(res).toEqual('test:PREFIX:id0,test:PREFIX:id1,test:PREFIX:id2');
run = (str, prefix, delim) => {
prefix = typeof prefix === "undefined" ? undefined : `"${prefix}"`;
delim = typeof delim === "undefined" ? undefined : `"${delim}"`;
return nunjucks.renderString(`{{ test | replPrefix(${prefix}, ${delim}) | join(",") }}`, { test: str });
};
res = run(has, "test");
expect(res).toEqual("test:id0,test:id1,test:id2");
run = run = (str, begin, end) => nunjucks.renderString(`{{ test | substr(${begin}, ${end}) }}`, { test: str });
res = run(has, -3);
expect(res).toEqual("id0,id1,id2");
})
});
66 changes: 65 additions & 1 deletion __test__/trapi_query_builder.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,4 +30,68 @@ describe("test trapi query builder class", () => {
expect(res.data.message.query_graph.edges.e01.predicates).toContain('biolink:related_to');
})
})
})

describe("test nunjucks support", () => {
test("if _getUrl nunjucks templates are filled", () => {
const edge = {
query_operation: {
server: "https://google.com/",
path: "{path}",
path_params: ["path"],
params: {path: "{{ specialpath }}"}
},
association: {
input_type: "Pathway",
output_type: "Gene",
predicate: "related_to",
},
input: {specialpath: "/querytest"},
};
const builder = new qb(edge);
const res = builder._getUrl(edge, edge.input);
expect(res).toEqual("https://google.com/querytest");
})

test("if _getBody nunjucks templates are filled", () => {
const edge = {
query_operation: {
server: "https://google.com/",
path: "/query"
},
association: {
input_type: ['Pathway', 'SomethingElse', '{{ SpecialInput }}'],
output_type: 'Gene',
predicate: 'related_to'
},
input: {
ids: ['123', '456'],
SpecialInput: "TestSuccess"
}
}
const builder = new qb(edge);
const res = builder._getRequestBody(edge, edge.input);
expect(res).toEqual({
message: {
query_graph: {
nodes: {
n0: {
ids: ['123', '456'],
categories: ['biolink:Pathway', 'biolink:SomethingElse', 'biolink:TestSuccess'],
},
n1: {
categories: ['biolink:Gene'],
},
},
edges: {
e01: {
subject: "n0",
object: "n1",
predicates: ['biolink:related_to'],
},
},
},
},
});
})
})
})