parent
637a517b4b
commit
665511f2f0
@ -1,19 +1,152 @@ |
|||||||
import { BrokenAvatarTransformer } from "./AvatarBrokenTransformer"; |
import type { |
||||||
import { AvatarErroringTransformer } from "./AvatarErroringTransformer"; |
TraverserDefinitions, |
||||||
import { aang } from "./sampleData"; |
ValidateTraverserTypes, |
||||||
|
} from "../../../src"; |
||||||
|
import { InstanceGraph } from "../../../src/instanceGraph/instanceGraph"; |
||||||
|
|
||||||
describe("Avatar", () => { |
describe("AvatarExample", () => { |
||||||
it("Throws an error before entering an infinite loop", async () => { |
/** |
||||||
await expect( |
* Types |
||||||
BrokenAvatarTransformer.transform(aang, "Bender", undefined), |
*/ |
||||||
).rejects.toThrow( |
type Element = "Water" | "Earth" | "Fire" | "Air"; |
||||||
`Circular dependency found. Use the 'setReturnPointer' function. The loop includes the 'Bender' type`, |
interface Bender { |
||||||
); |
name: string; |
||||||
|
element: Element; |
||||||
|
friends: Person[]; |
||||||
|
} |
||||||
|
interface NonBender { |
||||||
|
name: string; |
||||||
|
friends: Person[]; |
||||||
|
} |
||||||
|
type Person = Bender | NonBender; |
||||||
|
|
||||||
|
/** |
||||||
|
* Raw Data to Traverse |
||||||
|
*/ |
||||||
|
const aang: Bender = { |
||||||
|
name: "Aang", |
||||||
|
element: "Air", |
||||||
|
friends: [], |
||||||
|
}; |
||||||
|
const sokka: NonBender = { |
||||||
|
name: "Sokka", |
||||||
|
friends: [], |
||||||
|
}; |
||||||
|
const katara: Bender = { |
||||||
|
name: "Katara", |
||||||
|
element: "Water", |
||||||
|
friends: [], |
||||||
|
}; |
||||||
|
aang.friends.push(sokka, katara); |
||||||
|
sokka.friends.push(aang, katara); |
||||||
|
katara.friends.push(aang, sokka); |
||||||
|
|
||||||
|
/** |
||||||
|
* Traverser Types |
||||||
|
*/ |
||||||
|
type AvatarTraverserTypes = ValidateTraverserTypes<{ |
||||||
|
Element: { |
||||||
|
kind: "primitive"; |
||||||
|
type: Element; |
||||||
|
}; |
||||||
|
Bender: { |
||||||
|
kind: "interface"; |
||||||
|
type: Bender; |
||||||
|
properties: { |
||||||
|
element: "Element"; |
||||||
|
friends: "Person"; |
||||||
|
}; |
||||||
|
}; |
||||||
|
NonBender: { |
||||||
|
kind: "interface"; |
||||||
|
type: NonBender; |
||||||
|
properties: { |
||||||
|
friends: "Person"; |
||||||
|
}; |
||||||
|
}; |
||||||
|
Person: { |
||||||
|
kind: "union"; |
||||||
|
type: Person; |
||||||
|
typeNames: "Bender" | "NonBender"; |
||||||
|
}; |
||||||
|
}>; |
||||||
|
|
||||||
|
/** |
||||||
|
* Create the traverser definition |
||||||
|
*/ |
||||||
|
const avatarTraverserDefinition: TraverserDefinitions<AvatarTraverserTypes> = |
||||||
|
{ |
||||||
|
Element: { |
||||||
|
kind: "primitive", |
||||||
|
}, |
||||||
|
Bender: { |
||||||
|
kind: "interface", |
||||||
|
properties: { |
||||||
|
element: "Element", |
||||||
|
friends: "Person", |
||||||
|
}, |
||||||
|
}, |
||||||
|
NonBender: { |
||||||
|
kind: "interface", |
||||||
|
properties: { |
||||||
|
friends: "Person", |
||||||
|
}, |
||||||
|
}, |
||||||
|
Person: { |
||||||
|
kind: "union", |
||||||
|
selector: (item) => { |
||||||
|
return (item as Bender).element ? "Bender" : "NonBender"; |
||||||
|
}, |
||||||
|
}, |
||||||
|
}; |
||||||
|
|
||||||
|
it("returns child nodes when child methods are called.", () => { |
||||||
|
const graph = new InstanceGraph(avatarTraverserDefinition); |
||||||
|
const aangBender = graph.getNodeFor(aang, "Bender"); |
||||||
|
expect(aangBender.typeName).toBe("Bender"); |
||||||
|
expect(aangBender.instance.name).toBe("Aang"); |
||||||
|
// child
|
||||||
|
const aangElement = aangBender.child("element"); |
||||||
|
expect(aangElement.instance).toBe("Air"); |
||||||
|
expect(aangElement.typeName).toBe("Element"); |
||||||
|
const aangFriends = aangBender.child("friends"); |
||||||
|
expect(aangFriends.length).toBe(2); |
||||||
|
const sokkaPerson = aangFriends[0]; |
||||||
|
const kataraPerson = aangFriends[1]; |
||||||
|
expect(sokkaPerson.instance.name).toBe("Sokka"); |
||||||
|
expect(kataraPerson.instance.name).toBe("Katara"); |
||||||
|
expect(sokkaPerson.typeName).toBe("Person"); |
||||||
|
expect(kataraPerson.typeName).toBe("Person"); |
||||||
|
const sokkaNonBender = sokkaPerson.child(); |
||||||
|
expect(sokkaNonBender.instance.name).toBe("Sokka"); |
||||||
|
expect(sokkaNonBender.typeName).toBe("NonBender"); |
||||||
|
if (sokkaNonBender.typeName === "NonBender") { |
||||||
|
const aangPerson = sokkaNonBender.child("friends")[0]; |
||||||
|
const aangBender2 = aangPerson.child(); |
||||||
|
expect(aangBender2).toBe(aangBender); |
||||||
|
} |
||||||
|
// allChildren
|
||||||
|
const [childElemement, childSokka, childKatara] = aangBender.allChildren(); |
||||||
|
expect(childElemement.instance).toBe("Air"); |
||||||
|
expect((childSokka.instance as NonBender).name).toBe("Sokka"); |
||||||
|
expect((childKatara.instance as Bender).name).toBe("Katara"); |
||||||
|
const childOfSokkaPerson = sokkaPerson.allChildren(); |
||||||
|
expect(childOfSokkaPerson.length).toBe(1); |
||||||
|
expect(childOfSokkaPerson[0].instance.name).toBe("Sokka"); |
||||||
}); |
}); |
||||||
|
|
||||||
it("Bubbles errors", async () => { |
it("returns parent nodes when parent methods are called.", () => { |
||||||
await expect( |
const graph = new InstanceGraph(avatarTraverserDefinition); |
||||||
AvatarErroringTransformer.transform(aang, "Bender", undefined), |
const aangBender = graph.getNodeFor(aang, "Bender"); |
||||||
).rejects.toThrow("No Non Benders Allowed"); |
// parent
|
||||||
|
const [aangPerson] = aangBender.parent("Person"); |
||||||
|
expect(aangPerson.instance.name).toBe("Aang"); |
||||||
|
expect(aangPerson.typeName).toBe("Person"); |
||||||
|
const [sokkaNonBender] = aangPerson.parent("NonBender", "friends"); |
||||||
|
const [kataraBender] = aangPerson.parent("Bender", "friends"); |
||||||
|
expect(sokkaNonBender.typeName).toBe("NonBender"); |
||||||
|
expect(sokkaNonBender.instance.name).toBe("Sokka"); |
||||||
|
expect(kataraBender.typeName).toBe("Bender"); |
||||||
|
expect(kataraBender.instance.name).toBe("Katara"); |
||||||
}); |
}); |
||||||
}); |
}); |
||||||
|
@ -0,0 +1,19 @@ |
|||||||
|
import { BrokenAvatarTransformer } from "./AvatarBrokenTransformer"; |
||||||
|
import { AvatarErroringTransformer } from "./AvatarErroringTransformer"; |
||||||
|
import { aang } from "./sampleData"; |
||||||
|
|
||||||
|
describe("Avatar", () => { |
||||||
|
it("Throws an error before entering an infinite loop", async () => { |
||||||
|
await expect( |
||||||
|
BrokenAvatarTransformer.transform(aang, "Bender", undefined), |
||||||
|
).rejects.toThrow( |
||||||
|
`Circular dependency found. Use the 'setReturnPointer' function. The loop includes the 'Bender' type`, |
||||||
|
); |
||||||
|
}); |
||||||
|
|
||||||
|
it("Bubbles errors", async () => { |
||||||
|
await expect( |
||||||
|
AvatarErroringTransformer.transform(aang, "Bender", undefined), |
||||||
|
).rejects.toThrow("No Non Benders Allowed"); |
||||||
|
}); |
||||||
|
}); |
@ -1,7 +1,7 @@ |
|||||||
{ |
{ |
||||||
"extends": "../../tsconfig.base.json", |
"extends": "../../tsconfig.base.json", |
||||||
"compilerOptions": { |
"compilerOptions": { |
||||||
"outDir": "./dist" |
"outDir": "./dist", |
||||||
}, |
}, |
||||||
"include": ["./src"] |
"include": ["./src"] |
||||||
} |
} |
Loading…
Reference in new issue