Skip to content

Commit

Permalink
merge latest from main
Browse files Browse the repository at this point in the history
  • Loading branch information
tokebe committed Jan 3, 2023
2 parents a5431b3 + a015626 commit 85d434a
Show file tree
Hide file tree
Showing 32 changed files with 1,475 additions and 1,452 deletions.
File renamed without changes.
40 changes: 22 additions & 18 deletions __test__/integration/QEdge2BTEEdgeHandler.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,25 +3,28 @@ const QEdge = require('../../src/query_edge');
const NodeUpdateHandler = require('../../src/update_nodes');

describe('Testing NodeUpdateHandler Module', () => {
const gene_node1 = new QNode('n1', { categories: ['Gene'], ids: ['NCBIGene:1017'] });
const gene_node1 = new QNode({ id: 'n1', categories: ['Gene'], ids: ['NCBIGene:1017'] });
const node1_equivalent_ids = {
'NCBIGene:1017': {
db_ids: {
NCBIGene: ['1017'],
SYMBOL: ['CDK2'],
'NCBIGene:1017': [
{
semanticTypes: [],
db_ids: {
NCBIGene: ['1017'],
SYMBOL: ['CDK2'],
},
},
},
],
};

const gene_node2 = new QNode('n2', { categories: ['Gene'], ids: ['NCBIGene:1017', 'NCBIGene:1018'] });
const gene_node1_with_id_annotated = new QNode('n1', { categories: ['Gene'], ids: ['NCBIGene:1017'] });
const gene_node2 = new QNode({ id: 'n2', categories: ['Gene'], ids: ['NCBIGene:1017', 'NCBIGene:1018'] });
const gene_node1_with_id_annotated = new QNode({ id: 'n1', categories: ['Gene'], ids: ['NCBIGene:1017'] });
gene_node1_with_id_annotated.setEquivalentIDs(node1_equivalent_ids);
//gene_node2.setEquivalentIDs(node2_equivalent_ids);
const chemical_node1 = new QNode('n3', { categories: ['SmallMolecule'] });
const edge1 = new QEdge('e01', { subject: gene_node1, object: chemical_node1 });
const edge2 = new QEdge('e02', { subject: gene_node1_with_id_annotated, object: chemical_node1 });
const edge3 = new QEdge('e04', { subject: gene_node2, object: chemical_node1 });
const edge4 = new QEdge('e05', { object: gene_node2, subject: chemical_node1 });
const chemical_node1 = new QNode({ id: 'n3', categories: ['SmallMolecule'] });
const edge1 = new QEdge({ id: 'e01', subject: gene_node1, object: chemical_node1 });
const edge2 = new QEdge({ id: 'e02', subject: gene_node1_with_id_annotated, object: chemical_node1 });
const edge3 = new QEdge({ id: 'e04', subject: gene_node2, object: chemical_node1 });
const edge4 = new QEdge({ id: 'e05', object: gene_node2, subject: chemical_node1 });

describe('Testing _getCuries function', () => {
test('test edge with one curie input return an array of one', () => {
Expand All @@ -36,11 +39,12 @@ describe('Testing NodeUpdateHandler Module', () => {
expect(res.Gene.length).toEqual(2);
});

test('test edge with input node annotated should return an empty array', () => {
const nodeUpdater = new NodeUpdateHandler([edge2]);
const res = nodeUpdater._getCuries([edge2]);
expect(res).toEqual({});
});
// test deprecated: proper update handling outside of updater ensures minimal redundancy
// test('test edge with input node annotated should return an empty array', () => {
// const nodeUpdater = new NodeUpdateHandler([edge2]);
// const res = nodeUpdater._getCuries([edge2]);
// expect(res).toEqual({});
// });

test('test edge with input on object end should be handled', () => {
const nodeUpdater = new NodeUpdateHandler([edge4]);
Expand Down
115 changes: 79 additions & 36 deletions __test__/integration/QueryEdge.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ const QNode = require('../../src/query_node');
const QEdge = require('../../src/query_edge');

describe('Testing QueryEdge Module', () => {
const gene_node1 = new QNode('n1', { categories: ['Gene'], ids: ['NCBIGene:1017'] });
const type_node = new QNode('n2', { categories: ['SmallMolecule'] });
const disease1_node = new QNode('n1', { categories: ['Disease'], ids: ['MONDO:000123'] });
const gene_node1 = new QNode({ id: 'n1', categories: ['Gene'], ids: ['NCBIGene:1017'] });
const type_node = new QNode({ id: 'n2', categories: ['SmallMolecule'] });
const disease1_node = new QNode({ id: 'n1', categories: ['Disease'], ids: ['MONDO:000123'] });
const node1_equivalent_ids = {
'NCBIGene:1017': {
db_ids: {
Expand All @@ -14,15 +14,15 @@ describe('Testing QueryEdge Module', () => {
},
};

const gene_node2 = new QNode('n2', { categories: 'Gene', ids: ['NCBIGene:1017', 'NCBIGene:1018'] });
const gene_node1_with_id_annotated = new QNode('n1', { categories: ['Gene'], ids: ['NCBIGene:1017'] });
const gene_node2 = new QNode({ id: 'n2', categories: 'Gene', ids: ['NCBIGene:1017', 'NCBIGene:1018'] });
const gene_node1_with_id_annotated = new QNode({ id: 'n1', categories: ['Gene'], ids: ['NCBIGene:1017'] });
gene_node1_with_id_annotated.setEquivalentIDs(node1_equivalent_ids);
const chemical_node1 = new QNode('n3', { categories: ['SmallMolecule'] });
const edge1 = new QEdge('e01', { subject: gene_node1, object: chemical_node1 });
const edge2 = new QEdge('e02', { subject: gene_node1_with_id_annotated, object: chemical_node1 });
const edge3 = new QEdge('e04', { subject: gene_node2, object: chemical_node1 });
const edge4 = new QEdge('e05', { object: gene_node2, subject: chemical_node1 });
const edge5 = new QEdge('e06', { object: gene_node1_with_id_annotated, subject: chemical_node1 });
const chemical_node1 = new QNode({ id: 'n3', categories: ['SmallMolecule'] });
const edge1 = new QEdge({ id: 'e01', subject: gene_node1, object: chemical_node1 });
const edge2 = new QEdge({ id: 'e02', subject: gene_node1_with_id_annotated, object: chemical_node1 });
const edge3 = new QEdge({ id: 'e04', subject: gene_node2, object: chemical_node1 });
const edge4 = new QEdge({ id: 'e05', object: gene_node2, subject: chemical_node1 });
const edge5 = new QEdge({ id: 'e06', object: gene_node1_with_id_annotated, subject: chemical_node1 });

describe('Testing isReversed function', () => {
test('test if only the object of the edge has curie defined, should return true', () => {
Expand All @@ -36,9 +36,9 @@ describe('Testing QueryEdge Module', () => {
});

test('test if both subject and object curie not defined, should return false', () => {
const node1 = new QNode('n1', { categories: ['Gene'] });
const node2 = new QNode('n2', { categories: ['SmallMolecule'] });
const edge = new QEdge('e01', { subject: node1, object: node2 });
const node1 = new QNode({ id: 'n1', categories: ['Gene'] });
const node2 = new QNode({ id: 'n2', categories: ['SmallMolecule'] });
const edge = new QEdge({ id: 'e01', subject: node1, object: node2 });
expect(edge.isReversed()).toBeFalsy();
});
});
Expand Down Expand Up @@ -77,39 +77,41 @@ describe('Testing QueryEdge Module', () => {
});

test('test return false if both subject and object has no curies specified', () => {
const node1 = new QNode('n1', { categories: ['Gene'] });
const node2 = new QNode('n2', { categories: ['SmallMolecule'] });
const edge = new QEdge('e01', { subject: node1, object: node2 });
const node1 = new QNode({ id: 'n1', categories: ['Gene'] });
const node2 = new QNode({ id: 'n2', categories: ['SmallMolecule'] });
const edge = new QEdge({ id: 'e01', subject: node1, object: node2 });
expect(edge.hasInput()).toBeFalsy();
});
});

describe('Testing hasInputResolved function', () => {
test('test return true if subject has input resolved', () => {
const res = edge2.hasInputResolved();
expect(res).toBeTruthy();
});
// Removed because new QEdge has different implementation for hasInputResolved
// describe("Testing hasInputResolved function", () => {
// test("test return true if subject has input resolved", () => {
// const res = edge2.hasInputResolved();
// expect(res).toBeTruthy();
// });

test('test return false if both subject and object do not have input resolved', () => {
const res = edge1.hasInputResolved();
expect(res).toBeFalsy();
});
// test("test return false if both subject and object do not have input resolved", () => {
// const res = edge1.hasInputResolved();
// expect(res).toBeFalsy();
// });

test("test return true if subject doesn't have input resolved, but object does", () => {
const res = edge5.hasInputResolved();
expect(res).toBeTruthy();
});
});
// test("test return true if subject doesn't have input resolved, but object does", () => {
// const res = edge5.hasInputResolved();
// expect(res).toBeTruthy();
// });

// })

describe('Testing getPredicate function', () => {
test('test get reverse predicate if query is reversed', () => {
const edge = new QEdge('e01', { subject: type_node, object: disease1_node, predicates: ['biolink:treats'] });
const edge = new QEdge({ id: 'e01', subject: type_node, object: disease1_node, predicates: ['biolink:treats'] });
const res = edge.getPredicate();
expect(res).toContain('treated_by');
});

test('test get reverse predicate if query is reversed and expanded', () => {
const edge = new QEdge('e01', { subject: type_node, object: disease1_node, predicates: ['biolink:affects'] });
const edge = new QEdge({ id: 'e01', subject: type_node, object: disease1_node, predicates: ['biolink:affects'] });
const res = edge.getPredicate();
expect(res).toContain('affected_by');
expect(res).toContain('disrupted_by');
Expand All @@ -118,7 +120,8 @@ describe('Testing QueryEdge Module', () => {

describe('Testing expandPredicates function', () => {
test('All predicates are correctly expanded if in biolink model', () => {
const edge = new QEdge('e01', {
const edge = new QEdge({
id: 'e01',
subject: type_node,
object: disease1_node,
predicates: ['biolink:contributes_to'],
Expand All @@ -129,7 +132,8 @@ describe('Testing QueryEdge Module', () => {
});

test('Multiple predicates can be resolved', () => {
const edge = new QEdge('e01', {
const edge = new QEdge({
id: 'e01',
subject: type_node,
object: disease1_node,
predicates: ['biolink:contributes_to'],
Expand All @@ -142,7 +146,8 @@ describe('Testing QueryEdge Module', () => {
});

test('Predicates not in biolink model should return itself', () => {
const edge = new QEdge('e01', {
const edge = new QEdge({
id: 'e01',
subject: type_node,
object: disease1_node,
predicates: 'biolink:contributes_to',
Expand All @@ -153,4 +158,42 @@ describe('Testing QueryEdge Module', () => {
expect(res).toContain('amelio');
});
});

describe('chooseLowerEntityValue', () => {
test('Should reverse if subject has more curies', () => {
const qEdgeClone = new QEdge(edge1.freeze());
qEdgeClone.subject.entity_count = 2;
qEdgeClone.object.entity_count = 1;

qEdgeClone.chooseLowerEntityValue();

expect(qEdgeClone.isReversed()).toBeTruthy();
});

test("Shouldn't reverse if object has more curies", () => {
const qEdgeClone = new QEdge(edge1.freeze());
qEdgeClone.subject.entity_count = 1;
qEdgeClone.object.entity_count = 2;

qEdgeClone.chooseLowerEntityValue();

expect(qEdgeClone.isReversed()).toBeFalsy();
});

test("Shouldn't reverse if both have same number", () => {
const qEdgeClone = new QEdge(edge1.freeze());
qEdgeClone.subject.entity_count = 2;
qEdgeClone.object.entity_count = 2;

qEdgeClone.chooseLowerEntityValue();

expect(qEdgeClone.isReversed()).toBeFalsy();
});
});

test('getHashedEdgeRepresentation', () => {
const qEdge1 = new QEdge({ id: 'e01', subject: type_node, object: disease1_node, predicates: ['biolink:treats'] });
const qEdge2 = new QEdge(qEdge1.freeze(), true);
expect(qEdge1.getHashedEdgeRepresentation()).not.toEqual(qEdge2.getHashedEdgeRepresentation());
});
});
31 changes: 10 additions & 21 deletions __test__/integration/QueryGraphHandler.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -240,22 +240,14 @@ describe('Testing QueryGraphHandler Module', () => {
});
});

describe('test _storeEdges function', () => {
describe('test calculateEdges function', () => {
test('test storeEdges with one hop query', async () => {
let handler = new QueryGraphHandler(OneHopQuery);
let edges = await handler._storeEdges();
expect(edges).toHaveProperty('e01');
expect(edges).not.toHaveProperty('e02');
expect(edges.e01).toBeInstanceOf(QEdge);
expect(edges.e01.getSubject()).toBeInstanceOf(QNode2);
});

test('test storeEdges with multi hop query', async () => {
let handler = new QueryGraphHandler(FourHopQuery);
let edges = await handler._storeEdges();
expect(edges).toHaveProperty('e01');
expect(edges).toHaveProperty('e02');
expect(edges.e01).toBeInstanceOf(QEdge);
await handler.calculateEdges();
expect(handler.edges).toHaveProperty('e01');
expect(handler.edges).not.toHaveProperty('e02');
expect(handler.edges.e01).toBeInstanceOf(QEdge);
expect(handler.edges.e01.getInputNode()).toBeInstanceOf(QNode2);
});
});

Expand All @@ -264,23 +256,20 @@ describe('Testing QueryGraphHandler Module', () => {
let handler = new QueryGraphHandler(ThreeHopExplainQuery);
let edges = await handler.calculateEdges();
expect(Object.keys(edges)).toHaveLength(3);
expect(edges[0]).toHaveLength(1);
expect(edges[1]).toHaveLength(1);
expect(edges[2]).toHaveLength(1);
});
});
describe('test cycle/duplicate edge detection for query graphs', () => {
test('Duplicate Edge Graph #1', async () => {
const handler = new QueryGraphHandler(QueryWithDuplicateEdge1);
expect(handler.calculateEdges()).rejects.toThrow(InvalidQueryGraphError);
await expect(handler.calculateEdges()).rejects.toThrow(InvalidQueryGraphError);
});
test('Query Graph Cycle #1', async () => {
const handler = new QueryGraphHandler(QueryWithCycle1);
expect(handler.calculateEdges()).rejects.toThrow(InvalidQueryGraphError);
await expect(handler.calculateEdges()).rejects.toThrow(InvalidQueryGraphError);
});
test('Query Graph Cycle #2', async () => {
const handler = new QueryGraphHandler(QueryWithCycle2);
expect(handler.calculateEdges()).rejects.toThrow(InvalidQueryGraphError);
await expect(handler.calculateEdges()).rejects.toThrow(InvalidQueryGraphError);
});
});

Expand All @@ -293,7 +282,7 @@ describe('Testing QueryGraphHandler Module', () => {
const handler = new QueryGraphHandler(QueryWithNullPredicate);
const edges = await handler.calculateEdges();
// if this is undefined (not null) then smartapi-kg treats as if the field doesn't exist (desired behavior)
expect(edges[0][0].getPredicate()).toBe(undefined);
expect(edges[0].getPredicate()).toBe(undefined);
});
test('Graph without any ids', async () => {
const handler = new QueryGraphHandler(QueryWithNullIds);
Expand Down
Loading

0 comments on commit 85d434a

Please sign in to comment.