diff --git a/src/core2/graph.js b/src/core2/graph.js index 1118531..e46988c 100644 --- a/src/core2/graph.js +++ b/src/core2/graph.js @@ -276,23 +276,28 @@ function findHandler(pluginMap: PluginMap, pluginName: string) { return pluginMap[pluginName]; } +const DELEGATE_NODE_REFERENCE_BASE = Symbol("base"); +function getBase(dnr: DelegateNodeReference): NodeReference { + // Flow doesn't know about Symbols, so we use this function to + // localize the `any`-casts as much as possible. + return (dnr: any)[DELEGATE_NODE_REFERENCE_BASE]; +} + export class DelegateNodeReference implements NodeReference { - // TODO(@wchargin): Use a Symbol here. - __DelegateNodeReference_base: NodeReference; constructor(base: NodeReference) { - this.__DelegateNodeReference_base = base; + (this: any)[DELEGATE_NODE_REFERENCE_BASE] = base; } graph() { - return this.__DelegateNodeReference_base.graph(); + return getBase(this).graph(); } address() { - return this.__DelegateNodeReference_base.address(); + return getBase(this).address(); } get() { - return this.__DelegateNodeReference_base.get(); + return getBase(this).get(); } neighbors(options?: NeighborsOptions) { - return this.__DelegateNodeReference_base.neighbors(options); + return getBase(this).neighbors(options); } } diff --git a/src/core2/graph.test.js b/src/core2/graph.test.js index 8364975..43ce9b6 100644 --- a/src/core2/graph.test.js +++ b/src/core2/graph.test.js @@ -3,7 +3,7 @@ import stringify from "json-stable-stringify"; import sortBy from "lodash.sortby"; import type {Node} from "./graph"; -import {Graph} from "./graph"; +import {DelegateNodeReference, Graph} from "./graph"; import { FooPayload, @@ -213,3 +213,59 @@ describe("graph", () => { }); }); }); + +describe("DelegateNodeReference", () => { + const makeBase = () => ({ + graph: jest.fn(), + address: jest.fn(), + get: jest.fn(), + neighbors: jest.fn(), + }); + + it("has a working constructor", () => { + expect(new DelegateNodeReference(makeBase())).toBeInstanceOf( + DelegateNodeReference + ); + }); + + it("delegates `graph`", () => { + const expected = new Graph([]); + const ref = { + ...makeBase(), + graph: jest.fn().mockReturnValueOnce(expected), + }; + expect(new DelegateNodeReference(ref).graph()).toBe(expected); + expect(ref.graph.mock.calls).toEqual([[]]); + }); + + it("delegates `address`", () => { + const expected = {owner: {plugin: "foo", type: "bar"}, id: "baz"}; + const ref = { + ...makeBase(), + address: jest.fn().mockReturnValueOnce(expected), + }; + expect(new DelegateNodeReference(ref).address()).toBe(expected); + expect(ref.address.mock.calls).toEqual([[]]); + }); + + it("delegates `get`", () => { + const expected = {some: "node"}; + const ref = { + ...makeBase(), + get: jest.fn().mockReturnValueOnce((expected: any)), + }; + expect(new DelegateNodeReference(ref).get()).toBe(expected); + expect(ref.get.mock.calls).toEqual([[]]); + }); + + it("delegates `neighbors`, with proper options", () => { + const options = {direction: "OUT", node: {plugin: "foo", type: "bar"}}; + const ref = { + ...makeBase(), + neighbors: jest.fn().mockImplementationOnce((...args) => (args: any)), + }; + const result = new DelegateNodeReference(ref).neighbors(options); + expect(result).toEqual([options]); + expect(ref.neighbors.mock.calls).toEqual([[options]]); + }); +});