mirror of
https://github.com/status-im/sourcecred.git
synced 2025-03-01 04:30:29 +00:00
Create canonical demoAdapters for testing (#735)
PluginAdapters and Node/Edge types are increasingly fundamental to the cred explorer. Prior to this commit, we had no canonical demo adapters/types, and we would create ad-hoc and messy adapters whenever we needed them. This creates unnecessary repetition and lowers test quality. This commit creates a canonical demo adapter (loosely themed based on the wonderful game [Factorio]) and refactors most existing test cases to use the demo adapters. In particular, the horrible mess of pagerankTable adapters has been removed. [Factorio]: https://www.factorio.com/ I left `aggregate.test.js` untouched because I would have needed to materially re-write the tests to port them over. I added a comment so that if we ever do re-write those tests, we'll use the new demo adapters. Test plan: `yarn test` passes.
This commit is contained in:
parent
761b0f1282
commit
fc5c9ea589
@ -1,91 +1,22 @@
|
||||
// @flow
|
||||
|
||||
import {
|
||||
NodeAddress,
|
||||
EdgeAddress,
|
||||
type NodeAddressT,
|
||||
Graph,
|
||||
} from "../../core/graph";
|
||||
import type {DynamicPluginAdapter} from "./pluginAdapter";
|
||||
import {NodeAddress, EdgeAddress, Graph} from "../../core/graph";
|
||||
import {FactorioStaticAdapter} from "./demoAdapters";
|
||||
import {StaticAdapterSet} from "./adapterSet";
|
||||
import {FallbackStaticAdapter, FALLBACK_NAME} from "./fallbackAdapter";
|
||||
import {Assets} from "../assets";
|
||||
import {makeRepo, type Repo} from "../../core/repo";
|
||||
import {makeRepo} from "../../core/repo";
|
||||
|
||||
describe("app/adapters/adapterSet", () => {
|
||||
class TestStaticPluginAdapter {
|
||||
loadingMock: Function;
|
||||
constructor() {
|
||||
this.loadingMock = jest.fn();
|
||||
}
|
||||
name() {
|
||||
return "other plugin";
|
||||
}
|
||||
nodePrefix() {
|
||||
return NodeAddress.fromParts(["other"]);
|
||||
}
|
||||
edgePrefix() {
|
||||
return EdgeAddress.fromParts(["other"]);
|
||||
}
|
||||
nodeTypes() {
|
||||
return [
|
||||
{
|
||||
name: "other1",
|
||||
pluralName: "others1",
|
||||
defaultWeight: 0,
|
||||
prefix: NodeAddress.fromParts(["other", "1"]),
|
||||
},
|
||||
{
|
||||
name: "other2",
|
||||
pluralName: "others2",
|
||||
defaultWeight: 0,
|
||||
prefix: NodeAddress.fromParts(["other", "2"]),
|
||||
},
|
||||
];
|
||||
}
|
||||
edgeTypes() {
|
||||
return [
|
||||
{
|
||||
forwardName: "others_1",
|
||||
backwardName: "othered_by_1",
|
||||
prefix: EdgeAddress.fromParts(["other", "1"]),
|
||||
},
|
||||
{
|
||||
forwardName: "others_2",
|
||||
backwardName: "othered_by_2",
|
||||
prefix: EdgeAddress.fromParts(["other", "2"]),
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
load(assets: Assets, repo: Repo) {
|
||||
return this.loadingMock(assets, repo).then(
|
||||
() => new TestDynamicPluginAdapter()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class TestDynamicPluginAdapter implements DynamicPluginAdapter {
|
||||
graph() {
|
||||
return new Graph().addNode(NodeAddress.fromParts(["other1", "example"]));
|
||||
}
|
||||
nodeDescription(x: NodeAddressT) {
|
||||
return `Node from the test plugin: ${NodeAddress.toString(x)}`;
|
||||
}
|
||||
static() {
|
||||
return new TestStaticPluginAdapter();
|
||||
}
|
||||
}
|
||||
|
||||
describe("StaticAdapterSet", () => {
|
||||
function example() {
|
||||
const x = new TestStaticPluginAdapter();
|
||||
const x = new FactorioStaticAdapter();
|
||||
const fallback = new FallbackStaticAdapter();
|
||||
const sas = new StaticAdapterSet([x]);
|
||||
return {x, fallback, sas};
|
||||
}
|
||||
it("errors if two plugins have the same name", () => {
|
||||
const x = new TestStaticPluginAdapter();
|
||||
const x = new FactorioStaticAdapter();
|
||||
const shouldError = () => new StaticAdapterSet([x, x]);
|
||||
expect(shouldError).toThrowError("Multiple plugins with name");
|
||||
});
|
||||
@ -100,24 +31,30 @@ describe("app/adapters/adapterSet", () => {
|
||||
it("aggregates NodeTypes across plugins", () => {
|
||||
const {sas} = example();
|
||||
const nodeTypes = sas.nodeTypes();
|
||||
expect(nodeTypes).toHaveLength(3);
|
||||
const expectedNumNodeTypes =
|
||||
new FactorioStaticAdapter().nodeTypes().length +
|
||||
new FallbackStaticAdapter().nodeTypes().length;
|
||||
expect(nodeTypes).toHaveLength(expectedNumNodeTypes);
|
||||
});
|
||||
it("aggregates EdgeTypes across plugins", () => {
|
||||
const {sas} = example();
|
||||
const edgeTypes = sas.edgeTypes();
|
||||
expect(edgeTypes).toHaveLength(3);
|
||||
const expectedNumEdgeTypes =
|
||||
new FactorioStaticAdapter().edgeTypes().length +
|
||||
new FallbackStaticAdapter().edgeTypes().length;
|
||||
expect(edgeTypes).toHaveLength(expectedNumEdgeTypes);
|
||||
});
|
||||
it("finds adapter matching a node", () => {
|
||||
const {x, sas} = example();
|
||||
const matching = sas.adapterMatchingNode(
|
||||
NodeAddress.fromParts(["other", "foo"])
|
||||
NodeAddress.fromParts(["factorio", "inserter"])
|
||||
);
|
||||
expect(matching.name()).toBe(x.name());
|
||||
});
|
||||
it("finds adapter matching an edge", () => {
|
||||
const {x, sas} = example();
|
||||
const matching = sas.adapterMatchingEdge(
|
||||
EdgeAddress.fromParts(["other", "foo"])
|
||||
EdgeAddress.fromParts(["factorio", "assembles"])
|
||||
);
|
||||
expect(matching.name()).toBe(x.name());
|
||||
});
|
||||
@ -134,16 +71,16 @@ describe("app/adapters/adapterSet", () => {
|
||||
it("finds type matching a node", () => {
|
||||
const {sas} = example();
|
||||
const type = sas.typeMatchingNode(
|
||||
NodeAddress.fromParts(["other", "1", "foo"])
|
||||
NodeAddress.fromParts(["factorio", "inserter", "1", "foo"])
|
||||
);
|
||||
expect(type.name).toBe("other1");
|
||||
expect(type.name).toBe("inserter");
|
||||
});
|
||||
it("finds type matching an edge", () => {
|
||||
const {sas} = example();
|
||||
const type = sas.typeMatchingEdge(
|
||||
EdgeAddress.fromParts(["other", "1", "foo"])
|
||||
EdgeAddress.fromParts(["factorio", "assembles", "other", "1", "foo"])
|
||||
);
|
||||
expect(type.forwardName).toBe("others_1");
|
||||
expect(type.forwardName).toBe("assembles");
|
||||
});
|
||||
it("finds fallback type for unregistered node", () => {
|
||||
const {sas} = example();
|
||||
@ -161,6 +98,7 @@ describe("app/adapters/adapterSet", () => {
|
||||
});
|
||||
it("loads a dynamicAdapterSet", async () => {
|
||||
const {x, sas} = example();
|
||||
x.loadingMock = jest.fn();
|
||||
x.loadingMock.mockResolvedValue();
|
||||
expect(x.loadingMock).toHaveBeenCalledTimes(0);
|
||||
const assets = new Assets("/my/gateway/");
|
||||
@ -176,9 +114,8 @@ describe("app/adapters/adapterSet", () => {
|
||||
|
||||
describe("DynamicAdapterSet", () => {
|
||||
async function example() {
|
||||
const x = new TestStaticPluginAdapter();
|
||||
const x = new FactorioStaticAdapter();
|
||||
const sas = new StaticAdapterSet([x]);
|
||||
x.loadingMock.mockResolvedValue();
|
||||
const das = await sas.load(
|
||||
new Assets("/my/gateway/"),
|
||||
makeRepo("foo", "bar")
|
||||
@ -203,14 +140,14 @@ describe("app/adapters/adapterSet", () => {
|
||||
it("finds adapter matching a node", async () => {
|
||||
const {x, das} = await example();
|
||||
const matching = das.adapterMatchingNode(
|
||||
NodeAddress.fromParts(["other", "foo"])
|
||||
NodeAddress.fromParts(["factorio", "inserter"])
|
||||
);
|
||||
expect(matching.static().name()).toBe(x.name());
|
||||
});
|
||||
it("finds adapter matching an edge", async () => {
|
||||
const {x, das} = await example();
|
||||
const matching = das.adapterMatchingEdge(
|
||||
EdgeAddress.fromParts(["other", "foo"])
|
||||
EdgeAddress.fromParts(["factorio", "assembles"])
|
||||
);
|
||||
expect(matching.static().name()).toBe(x.name());
|
||||
});
|
||||
|
129
src/app/adapters/demoAdapters.js
Normal file
129
src/app/adapters/demoAdapters.js
Normal file
@ -0,0 +1,129 @@
|
||||
// @flow
|
||||
|
||||
import {Assets} from "../assets";
|
||||
import {
|
||||
Graph,
|
||||
NodeAddress,
|
||||
type NodeAddressT,
|
||||
EdgeAddress,
|
||||
} from "../../core/graph";
|
||||
import type {
|
||||
StaticPluginAdapter,
|
||||
DynamicPluginAdapter,
|
||||
EdgeType,
|
||||
NodeType,
|
||||
} from "./pluginAdapter";
|
||||
|
||||
import {StaticAdapterSet} from "./adapterSet";
|
||||
import {makeRepo, type Repo} from "../../core/repo";
|
||||
|
||||
export const inserterNodeType: NodeType = Object.freeze({
|
||||
name: "inserter",
|
||||
pluralName: "inserters",
|
||||
prefix: NodeAddress.fromParts(["factorio", "inserter"]),
|
||||
defaultWeight: 1,
|
||||
});
|
||||
|
||||
export const machineNodeType: NodeType = Object.freeze({
|
||||
name: "machine",
|
||||
pluralName: "machines",
|
||||
prefix: NodeAddress.fromParts(["factorio", "machine"]),
|
||||
defaultWeight: 2,
|
||||
});
|
||||
|
||||
export const assemblesEdgeType: EdgeType = Object.freeze({
|
||||
forwardName: "assembles",
|
||||
backwardName: "is assembled by",
|
||||
prefix: EdgeAddress.fromParts(["factorio", "assembles"]),
|
||||
});
|
||||
|
||||
export const transportsEdgeType: EdgeType = Object.freeze({
|
||||
forwardName: "transports",
|
||||
backwardName: "is transported by",
|
||||
prefix: EdgeAddress.fromParts(["factorio", "transports"]),
|
||||
});
|
||||
|
||||
export class FactorioStaticAdapter implements StaticPluginAdapter {
|
||||
loadingMock: Function;
|
||||
name() {
|
||||
return "Factorio demo adapter";
|
||||
}
|
||||
nodePrefix() {
|
||||
return NodeAddress.fromParts(["factorio"]);
|
||||
}
|
||||
nodeTypes() {
|
||||
return [inserterNodeType, machineNodeType];
|
||||
}
|
||||
edgePrefix() {
|
||||
return EdgeAddress.fromParts(["factorio"]);
|
||||
}
|
||||
edgeTypes() {
|
||||
return [assemblesEdgeType, transportsEdgeType];
|
||||
}
|
||||
async load(assets: Assets, repo: Repo): Promise<DynamicPluginAdapter> {
|
||||
if (this.loadingMock) {
|
||||
return this.loadingMock(assets, repo).then(
|
||||
() => new FactorioDynamicAdapter()
|
||||
);
|
||||
}
|
||||
return Promise.resolve(new FactorioDynamicAdapter());
|
||||
}
|
||||
}
|
||||
|
||||
export const factorioNodes = Object.freeze({
|
||||
inserter1: NodeAddress.fromParts(["factorio", "inserter", "1"]),
|
||||
machine1: NodeAddress.fromParts(["factorio", "machine", "1"]),
|
||||
inserter2: NodeAddress.fromParts(["factorio", "inserter", "2"]),
|
||||
machine2: NodeAddress.fromParts(["factorio", "machine", "2"]),
|
||||
});
|
||||
|
||||
export const factorioEdges = Object.freeze({
|
||||
transports1: Object.freeze({
|
||||
src: factorioNodes.inserter1,
|
||||
dst: factorioNodes.machine1,
|
||||
address: EdgeAddress.fromParts(["factorio", "transports", "1"]),
|
||||
}),
|
||||
assembles1: Object.freeze({
|
||||
src: factorioNodes.machine1,
|
||||
dst: factorioNodes.inserter2,
|
||||
address: EdgeAddress.fromParts(["factorio", "assembles", "1"]),
|
||||
}),
|
||||
transports2: Object.freeze({
|
||||
src: factorioNodes.inserter2,
|
||||
dst: factorioNodes.machine2,
|
||||
address: EdgeAddress.fromParts(["factorio", "assembles", "2"]),
|
||||
}),
|
||||
});
|
||||
export function factorioGraph() {
|
||||
return new Graph()
|
||||
.addNode(factorioNodes.inserter1)
|
||||
.addNode(factorioNodes.inserter2)
|
||||
.addNode(factorioNodes.machine1)
|
||||
.addNode(factorioNodes.machine2)
|
||||
.addEdge(factorioEdges.transports1)
|
||||
.addEdge(factorioEdges.transports2)
|
||||
.addEdge(factorioEdges.assembles1);
|
||||
}
|
||||
|
||||
export class FactorioDynamicAdapter implements DynamicPluginAdapter {
|
||||
graph() {
|
||||
return factorioGraph();
|
||||
}
|
||||
nodeDescription(x: NodeAddressT) {
|
||||
return NodeAddress.toString(x);
|
||||
}
|
||||
static() {
|
||||
return new FactorioStaticAdapter();
|
||||
}
|
||||
}
|
||||
|
||||
export function staticAdapterSet() {
|
||||
return new StaticAdapterSet([new FactorioStaticAdapter()]);
|
||||
}
|
||||
|
||||
export async function dynamicAdapterSet() {
|
||||
return await staticAdapterSet().load(
|
||||
new Assets("/gateway/"),
|
||||
makeRepo("foo", "bar")
|
||||
);
|
||||
}
|
@ -2,6 +2,7 @@
|
||||
|
||||
import React from "react";
|
||||
import {shallow} from "enzyme";
|
||||
|
||||
import * as NullUtil from "../../../util/null";
|
||||
import {NodeAddress, EdgeAddress} from "../../../core/graph";
|
||||
import type {NodeType, EdgeType} from "../../adapters/pluginAdapter";
|
||||
@ -15,6 +16,7 @@ import {Badge} from "./shared";
|
||||
import {example} from "./sharedTestUtils";
|
||||
import {aggregateFlat, type FlatAggregation} from "./aggregate";
|
||||
import {TableRow} from "./TableRow";
|
||||
import {factorioNodes} from "../../adapters/demoAdapters";
|
||||
|
||||
require("../../testUtil").configureEnzyme();
|
||||
|
||||
@ -31,8 +33,8 @@ describe("app/credExplorer/pagerankTable/Aggregation", () => {
|
||||
});
|
||||
describe("AggregationRowList", () => {
|
||||
it("instantiates AggregationRows for each aggregation", async () => {
|
||||
const {adapters, pnd, nodes} = await example();
|
||||
const node = nodes.bar1;
|
||||
const {adapters, pnd} = await example();
|
||||
const node = factorioNodes.inserter1;
|
||||
const depth = 20;
|
||||
const maxEntriesPerList = 50;
|
||||
const sharedProps = {adapters, pnd, maxEntriesPerList};
|
||||
@ -66,9 +68,9 @@ describe("app/credExplorer/pagerankTable/Aggregation", () => {
|
||||
|
||||
describe("AggregationRow", () => {
|
||||
async function setup() {
|
||||
const {pnd, adapters, nodes} = await example();
|
||||
const {pnd, adapters} = await example();
|
||||
const sharedProps = {adapters, pnd, maxEntriesPerList: 123};
|
||||
const target = nodes.bar1;
|
||||
const target = factorioNodes.inserter1;
|
||||
const {scoredConnections} = NullUtil.get(pnd.get(target));
|
||||
const aggregations = aggregateFlat(
|
||||
scoredConnections,
|
||||
|
@ -9,6 +9,7 @@ import {ConnectionRowList, ConnectionRow, ConnectionView} from "./Connection";
|
||||
import {example} from "./sharedTestUtils";
|
||||
import {TableRow} from "./TableRow";
|
||||
import {NodeRow} from "./Node";
|
||||
import {factorioNodes} from "../../adapters/demoAdapters";
|
||||
|
||||
require("../../testUtil").configureEnzyme();
|
||||
|
||||
@ -26,9 +27,9 @@ describe("app/credExplorer/pagerankTable/Connection", () => {
|
||||
|
||||
describe("ConnectionRowList", () => {
|
||||
async function setup(maxEntriesPerList: number = 100000) {
|
||||
const {adapters, pnd, nodes} = await example();
|
||||
const {adapters, pnd} = await example();
|
||||
const depth = 2;
|
||||
const node = nodes.bar1;
|
||||
const node = factorioNodes.inserter1;
|
||||
const sharedProps = {adapters, pnd, maxEntriesPerList};
|
||||
const connections = NullUtil.get(sharedProps.pnd.get(node))
|
||||
.scoredConnections;
|
||||
@ -76,15 +77,11 @@ describe("app/credExplorer/pagerankTable/Connection", () => {
|
||||
|
||||
describe("ConnectionRow", () => {
|
||||
async function setup() {
|
||||
const {pnd, adapters, nodes} = await example();
|
||||
const {pnd, adapters} = await example();
|
||||
const sharedProps = {adapters, pnd, maxEntriesPerList: 123};
|
||||
const target = nodes.bar1;
|
||||
const target = factorioNodes.inserter1;
|
||||
const {scoredConnections} = NullUtil.get(pnd.get(target));
|
||||
const alphaConnections = scoredConnections.filter(
|
||||
(sc) => sc.source === nodes.fooAlpha
|
||||
);
|
||||
expect(alphaConnections).toHaveLength(1);
|
||||
const scoredConnection = alphaConnections[0];
|
||||
const scoredConnection = scoredConnections[0];
|
||||
const depth = 2;
|
||||
const component = (
|
||||
<ConnectionRow
|
||||
@ -160,8 +157,8 @@ describe("app/credExplorer/pagerankTable/Connection", () => {
|
||||
});
|
||||
describe("ConnectionView", () => {
|
||||
async function setup() {
|
||||
const {pnd, adapters, nodes} = await example();
|
||||
const {scoredConnections} = NullUtil.get(pnd.get(nodes.bar1));
|
||||
const {pnd, adapters} = await example();
|
||||
const {scoredConnections} = NullUtil.get(pnd.get(factorioNodes.machine1));
|
||||
const connections = scoredConnections.map((sc) => sc.connection);
|
||||
function connectionByType(t) {
|
||||
return NullUtil.get(
|
||||
@ -208,8 +205,10 @@ describe("app/credExplorer/pagerankTable/Connection", () => {
|
||||
const outerSpan = view.find("span").first();
|
||||
const badge = outerSpan.find("Badge");
|
||||
const description = outerSpan.children().find("span");
|
||||
expect(badge.children().text()).toEqual("is barred by");
|
||||
expect(description.text()).toEqual('bar: NodeAddress["bar","a","1"]');
|
||||
expect(badge.children().text()).toEqual("is transported by");
|
||||
expect(description.text()).toEqual(
|
||||
'NodeAddress["factorio","inserter","1"]'
|
||||
);
|
||||
});
|
||||
it("for outward connections, renders a `Badge` and description", async () => {
|
||||
const {cvForConnection, outConnection} = await setup();
|
||||
@ -217,8 +216,10 @@ describe("app/credExplorer/pagerankTable/Connection", () => {
|
||||
const outerSpan = view.find("span").first();
|
||||
const badge = outerSpan.find("Badge");
|
||||
const description = outerSpan.children().find("span");
|
||||
expect(badge.children().text()).toEqual("bars");
|
||||
expect(description.text()).toEqual("xox node!");
|
||||
expect(badge.children().text()).toEqual("assembles");
|
||||
expect(description.text()).toEqual(
|
||||
'NodeAddress["factorio","inserter","2"]'
|
||||
);
|
||||
});
|
||||
it("for synthetic connections, renders only a `Badge`", async () => {
|
||||
const {cvForConnection, syntheticConnection} = await setup();
|
||||
|
@ -7,11 +7,12 @@ import * as NullUtil from "../../../util/null";
|
||||
import {TableRow} from "./TableRow";
|
||||
import {AggregationRowList} from "./Aggregation";
|
||||
|
||||
import {type NodeAddressT, NodeAddress} from "../../../core/graph";
|
||||
import type {NodeAddressT} from "../../../core/graph";
|
||||
|
||||
import {nodeDescription} from "./shared";
|
||||
import {example} from "./sharedTestUtils";
|
||||
import {NodeRowList, NodeRow, type NodeRowProps} from "./Node";
|
||||
import {factorioNodes} from "../../adapters/demoAdapters";
|
||||
|
||||
require("../../testUtil").configureEnzyme();
|
||||
|
||||
@ -32,14 +33,8 @@ describe("app/credExplorer/pagerankTable/Node", () => {
|
||||
}
|
||||
async function setup(maxEntriesPerList: number = 100000) {
|
||||
const {adapters, pnd} = await example();
|
||||
const nodes = sortedByScore(Array.from(pnd.keys()), pnd)
|
||||
.reverse() // ascending order!
|
||||
.filter((x) =>
|
||||
NodeAddress.hasPrefix(x, NodeAddress.fromParts(["foo"]))
|
||||
);
|
||||
const nodes = Array.from(pnd.keys());
|
||||
expect(nodes).not.toHaveLength(0);
|
||||
expect(nodes).not.toHaveLength(1);
|
||||
expect(nodes).not.toHaveLength(pnd.size);
|
||||
const sharedProps = {adapters, pnd, maxEntriesPerList};
|
||||
const component = <NodeRowList sharedProps={sharedProps} nodes={nodes} />;
|
||||
const element = shallow(component);
|
||||
@ -86,9 +81,9 @@ describe("app/credExplorer/pagerankTable/Node", () => {
|
||||
describe("NodeRow", () => {
|
||||
async function setup(props: $Shape<{...NodeRowProps}>) {
|
||||
props = props || {};
|
||||
const {pnd, adapters, nodes} = await example();
|
||||
const {pnd, adapters} = await example();
|
||||
const sharedProps = {adapters, pnd, maxEntriesPerList: 123};
|
||||
const node = nodes.bar1;
|
||||
const node = factorioNodes.inserter1;
|
||||
const component = shallow(
|
||||
<NodeRow
|
||||
node={NullUtil.orElse(props.node, node)}
|
||||
|
@ -70,8 +70,9 @@ describe("app/credExplorer/pagerankTable/Table", () => {
|
||||
});
|
||||
it("with the ability to filter nodes passed to NodeRowList", async () => {
|
||||
const {element, options} = await setup();
|
||||
const option1 = options.at(1);
|
||||
const value = option1.prop("value");
|
||||
const option = options.at(2);
|
||||
|
||||
const value = option.prop("value");
|
||||
expect(value).not.toEqual(NodeAddress.empty);
|
||||
const previousNodes = element.find("NodeRowList").prop("nodes");
|
||||
expect(
|
||||
@ -89,7 +90,7 @@ describe("app/credExplorer/pagerankTable/Table", () => {
|
||||
expect(element.state().topLevelFilter).toEqual(NodeAddress.empty);
|
||||
});
|
||||
it("filter defaults to defaultNodeFilter if available", async () => {
|
||||
const filter = NodeAddress.fromParts(["foo", "a"]);
|
||||
const filter = NodeAddress.fromParts(["factorio", "inserter"]);
|
||||
const {element} = await setup(filter);
|
||||
expect(element.state().topLevelFilter).toEqual(filter);
|
||||
});
|
||||
|
@ -13,44 +13,18 @@ Array [
|
||||
"style": Object {
|
||||
"fontWeight": "bold",
|
||||
},
|
||||
"text": "bar",
|
||||
"valueString": "NodeAddress[\\"bar\\"]",
|
||||
"text": "Factorio demo adapter",
|
||||
"valueString": "NodeAddress[\\"factorio\\"]",
|
||||
},
|
||||
Object {
|
||||
"style": undefined,
|
||||
"text": " alpha",
|
||||
"valueString": "NodeAddress[\\"bar\\",\\"a\\"]",
|
||||
},
|
||||
Object {
|
||||
"style": Object {
|
||||
"fontWeight": "bold",
|
||||
},
|
||||
"text": "foo",
|
||||
"valueString": "NodeAddress[\\"foo\\"]",
|
||||
"text": " inserter",
|
||||
"valueString": "NodeAddress[\\"factorio\\",\\"inserter\\"]",
|
||||
},
|
||||
Object {
|
||||
"style": undefined,
|
||||
"text": " alpha",
|
||||
"valueString": "NodeAddress[\\"foo\\",\\"a\\"]",
|
||||
},
|
||||
Object {
|
||||
"style": undefined,
|
||||
"text": " beta",
|
||||
"valueString": "NodeAddress[\\"foo\\",\\"b\\"]",
|
||||
},
|
||||
Object {
|
||||
"style": Object {
|
||||
"fontWeight": "bold",
|
||||
},
|
||||
"text": "unused",
|
||||
"valueString": "NodeAddress[\\"unused\\"]",
|
||||
},
|
||||
Object {
|
||||
"style": Object {
|
||||
"fontWeight": "bold",
|
||||
},
|
||||
"text": "xox",
|
||||
"valueString": "NodeAddress[\\"xox\\"]",
|
||||
"text": " machine",
|
||||
"valueString": "NodeAddress[\\"factorio\\",\\"machine\\"]",
|
||||
},
|
||||
]
|
||||
`;
|
||||
|
@ -11,6 +11,9 @@ import {
|
||||
} from "./aggregate";
|
||||
|
||||
describe("app/credExplorer/aggregate", () => {
|
||||
// TODO: If making major modifications to these tests, consider switching
|
||||
// from the hand-maintained connections and types, and instead use the demo
|
||||
// adadpters from app/adapters/demoAdapters
|
||||
function example() {
|
||||
const nodes = {
|
||||
root: NodeAddress.fromParts(["root"]),
|
||||
|
@ -1,151 +1,17 @@
|
||||
// @flow
|
||||
|
||||
import {Graph, NodeAddress, EdgeAddress} from "../../../core/graph";
|
||||
|
||||
import {StaticAdapterSet, DynamicAdapterSet} from "../../adapters/adapterSet";
|
||||
import type {DynamicPluginAdapter} from "../../adapters/pluginAdapter";
|
||||
import {dynamicAdapterSet} from "../../adapters/demoAdapters";
|
||||
import {pagerank} from "../../../core/attribution/pagerank";
|
||||
|
||||
export const COLUMNS = () => ["Description", "", "Cred"];
|
||||
|
||||
export async function example() {
|
||||
const graph = new Graph();
|
||||
const nodes = {
|
||||
fooAlpha: NodeAddress.fromParts(["foo", "a", "1"]),
|
||||
fooBeta: NodeAddress.fromParts(["foo", "b", "2"]),
|
||||
bar1: NodeAddress.fromParts(["bar", "a", "1"]),
|
||||
bar2: NodeAddress.fromParts(["bar", "2"]),
|
||||
xox: NodeAddress.fromParts(["xox"]),
|
||||
empty: NodeAddress.empty,
|
||||
};
|
||||
Object.values(nodes).forEach((n) => graph.addNode((n: any)));
|
||||
|
||||
function addEdge(parts, src, dst) {
|
||||
const edge = {address: EdgeAddress.fromParts(parts), src, dst};
|
||||
graph.addEdge(edge);
|
||||
return edge;
|
||||
}
|
||||
|
||||
const edges = {
|
||||
fooA: addEdge(["foo", "a"], nodes.fooAlpha, nodes.fooBeta),
|
||||
fooB: addEdge(["foo", "b"], nodes.fooAlpha, nodes.bar1),
|
||||
fooC: addEdge(["foo", "c"], nodes.fooAlpha, nodes.xox),
|
||||
barD: addEdge(["bar", "d"], nodes.bar1, nodes.bar1),
|
||||
barE: addEdge(["bar", "e"], nodes.bar1, nodes.xox),
|
||||
barF: addEdge(["bar", "f"], nodes.bar1, nodes.xox),
|
||||
};
|
||||
|
||||
const dynamicAdapters: DynamicPluginAdapter[] = [
|
||||
{
|
||||
static: () => ({
|
||||
name: () => "foo",
|
||||
nodePrefix: () => NodeAddress.fromParts(["foo"]),
|
||||
edgePrefix: () => EdgeAddress.fromParts(["foo"]),
|
||||
nodeTypes: () => [
|
||||
{
|
||||
pluralName: "alphas",
|
||||
name: "alpha",
|
||||
prefix: NodeAddress.fromParts(["foo", "a"]),
|
||||
defaultWeight: 1,
|
||||
},
|
||||
{
|
||||
pluralName: "betas",
|
||||
name: "beta",
|
||||
prefix: NodeAddress.fromParts(["foo", "b"]),
|
||||
defaultWeight: 1,
|
||||
},
|
||||
],
|
||||
edgeTypes: () => [
|
||||
{
|
||||
prefix: EdgeAddress.fromParts(["foo"]),
|
||||
forwardName: "foos",
|
||||
backwardName: "is fooed by",
|
||||
},
|
||||
],
|
||||
load: (_unused_repo) => {
|
||||
throw new Error("unused");
|
||||
},
|
||||
}),
|
||||
graph: () => {
|
||||
throw new Error("unused");
|
||||
},
|
||||
nodeDescription: (x) => `foo: ${NodeAddress.toString(x)}`,
|
||||
},
|
||||
{
|
||||
static: () => ({
|
||||
name: () => "bar",
|
||||
nodePrefix: () => NodeAddress.fromParts(["bar"]),
|
||||
edgePrefix: () => EdgeAddress.fromParts(["bar"]),
|
||||
nodeTypes: () => [
|
||||
{
|
||||
name: "alpha",
|
||||
pluralName: "alphas",
|
||||
prefix: NodeAddress.fromParts(["bar", "a"]),
|
||||
defaultWeight: 1,
|
||||
},
|
||||
],
|
||||
edgeTypes: () => [
|
||||
{
|
||||
prefix: EdgeAddress.fromParts(["bar"]),
|
||||
forwardName: "bars",
|
||||
backwardName: "is barred by",
|
||||
},
|
||||
],
|
||||
load: (_unused_repo) => {
|
||||
throw new Error("unused");
|
||||
},
|
||||
}),
|
||||
graph: () => {
|
||||
throw new Error("unused");
|
||||
},
|
||||
nodeDescription: (x) => `bar: ${NodeAddress.toString(x)}`,
|
||||
},
|
||||
{
|
||||
static: () => ({
|
||||
name: () => "xox",
|
||||
nodePrefix: () => NodeAddress.fromParts(["xox"]),
|
||||
edgePrefix: () => EdgeAddress.fromParts(["xox"]),
|
||||
nodeTypes: () => [],
|
||||
edgeTypes: () => [],
|
||||
load: (_unused_repo) => {
|
||||
throw new Error("unused");
|
||||
},
|
||||
}),
|
||||
graph: () => {
|
||||
throw new Error("unused");
|
||||
},
|
||||
nodeDescription: (_unused_arg) => `xox node!`,
|
||||
},
|
||||
{
|
||||
static: () => ({
|
||||
nodePrefix: () => NodeAddress.fromParts(["unused"]),
|
||||
edgePrefix: () => EdgeAddress.fromParts(["unused"]),
|
||||
nodeTypes: () => [],
|
||||
edgeTypes: () => [],
|
||||
name: () => "unused",
|
||||
load: (_unused_repo) => {
|
||||
throw new Error("unused");
|
||||
},
|
||||
}),
|
||||
graph: () => {
|
||||
throw new Error("unused");
|
||||
},
|
||||
nodeDescription: () => {
|
||||
throw new Error("Unused");
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
const staticAdapters = dynamicAdapters.map((x) => x.static());
|
||||
const adapters = new DynamicAdapterSet(
|
||||
new StaticAdapterSet(staticAdapters),
|
||||
dynamicAdapters
|
||||
);
|
||||
|
||||
const adapters = await dynamicAdapterSet();
|
||||
const graph = adapters.graph();
|
||||
const pnd = await pagerank(graph, (_unused_Edge) => ({
|
||||
toWeight: 1,
|
||||
froWeight: 1,
|
||||
}));
|
||||
|
||||
return {adapters, nodes, edges, graph, pnd};
|
||||
return {adapters, pnd};
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user