From cae3a92dc970c17f46d4c9df40d4d9c212f65b6c Mon Sep 17 00:00:00 2001 From: William Chargin Date: Fri, 2 Mar 2018 11:33:45 -0800 Subject: [PATCH] Add `getAllNodes` and `getAllEdges` functions (#53) Summary: Without these functions, it is not possible to meaningfully operate on an arbitrary graph. Paired with @dandelionmane. Test Plan: New unit tests included. Run `yarn flow && yarn test`. wchargin-branch: get-all --- src/backend/graph.js | 14 ++++++++++++ src/backend/graph.test.js | 47 +++++++++++++++++++++++++++++---------- 2 files changed, 49 insertions(+), 12 deletions(-) diff --git a/src/backend/graph.js b/src/backend/graph.js index e31e803..1fabbc3 100644 --- a/src/backend/graph.js +++ b/src/backend/graph.js @@ -99,6 +99,20 @@ export class Graph { } return addresses.map((e) => this.getEdge(e)); } + + /** + * Gets all nodes in the graph, in unspecified order. + */ + getAllNodes(): Node[] { + return Object.keys(this._nodes).map((k) => this._nodes[k]); + } + + /** + * Gets all edges in the graph, in unspecified order. + */ + getAllEdges(): Edge[] { + return Object.keys(this._edges).map((k) => this._edges[k]); + } } export function addressToString(address: Address) { diff --git a/src/backend/graph.test.js b/src/backend/graph.test.js index 8d9c523..1359ed6 100644 --- a/src/backend/graph.test.js +++ b/src/backend/graph.test.js @@ -5,6 +5,22 @@ import {Graph, addressToString, stringToAddress} from "./graph"; describe("graph", () => { describe("#Graph", () => { + // Some Graph functions return a set of results represented as an + // array with undefined order. We use these functions to + // canonicalize the ordering so that we can then test equality with + // `expect(...).toEqual(...)`. + function sortedByAddress(xs: T[]) { + function cmp(x1: T, x2: T) { + const a1 = addressToString(x1.address); + const a2 = addressToString(x2.address); + return a1 > a2 ? 1 : a1 < a2 ? -1 : 0; + } + return [...xs].sort(cmp); + } + function expectSameSorted(xs: T[], ys: T[]) { + expect(sortedByAddress(xs)).toEqual(sortedByAddress(ys)); + } + // A Seafood Fruit Mix is made by cooking Mighty Bananas (picked // from a tree) and a Razorclaw Crab (grabbed from the beach). In // this graph, an edge from `u` to `v` means that `u` thanks `v` for @@ -206,6 +222,25 @@ describe("graph", () => { }); }); + it("gets all nodes", () => { + const expected = [heroNode(), bananasNode(), crabNode(), mealNode()]; + const actual = mealGraph().getAllNodes(); + expectSameSorted(expected, actual); + }); + + it("gets all edges", () => { + const expected = [ + pickEdge(), + grabEdge(), + cookEdge(), + bananasIngredientEdge(), + crabIngredientEdge(), + eatEdge(), + ]; + const actual = mealGraph().getAllEdges(); + expectSameSorted(expected, actual); + }); + // For the next two test cases: we're documenting this behavior, // though we're not sure if it's the right behavior. Perhaps we want // the namespaces to be forced to be disjoint. In that case, we can @@ -227,18 +262,6 @@ describe("graph", () => { }); describe("in- and out-edges", () => { - function sortedByAddress(xs: T[]) { - function cmp(x1: T, x2: T) { - const a1 = addressToString(x1.address); - const a2 = addressToString(x2.address); - return a1 > a2 ? 1 : a1 < a2 ? -1 : 0; - } - return [...xs].sort(cmp); - } - function expectSameSorted(xs: T[], ys: T[]) { - expect(sortedByAddress(xs)).toEqual(sortedByAddress(ys)); - } - it("gets out-edges", () => { const nodeAndExpectedEdgePairs = [ [heroNode(), [eatEdge()]],