Mercurial > code > home > repos > streamed-graph
view src/layout/Layout.test.ts @ 119:8715633f5213
fancier column sorting to bring preds from the same type together
author | drewp@bigasterisk.com |
---|---|
date | Sun, 20 Mar 2022 01:17:35 -0700 |
parents | c2923b20bf5c |
children | 3584f24becf4 |
line wrap: on
line source
import { Quad, Store, Term } from "n3"; import { n3Graph } from "./fetchAndParse"; import { AlignedTable, Layout, LayoutResult } from "./Layout"; import { EX, rdf } from "./namespaces"; import { ViewConfig } from "./ViewConfig"; const twoStatements = async (): Promise<Store> => { return n3Graph(` @prefix : <http://example.com/> . :g1 { :a0 :b0 :c0 . :d0 :e0 :f0 . } `); }; const typedStatements = async (): Promise<Store> => { return n3Graph(` @prefix : <http://example.com/> . :g1 { :a a :T1 ; :color :red . :b a :T1 ; :color :blue . :c a :T1 . :d a :T2 ; :size :big . :e a :T1,:T2; :size :small } `); }; function G1(s: Term, p: Term, o: Term): Quad { return new Quad(s, p, o, EX("g1")); } describe("Layout", () => { it("accepts a ViewConfig", async () => { const vc = new ViewConfig(); await vc.readFromGraph(` @prefix ex: <http://example.com/> . @prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> . <> a ex:View; rdfs:label "repos" .`); const layout = new Layout(vc); const lr = layout.plan(await twoStatements()); }); it("returns no sections for empty graph", () => { const vc = new ViewConfig(); const layout = new Layout(vc); const lr = layout.plan(new Store()); expect(lr.sections).toHaveLength(0); }); it("defaults to putting all triples in the ungrouped list", async () => { const layout = new Layout(); const lr = layout.plan(await twoStatements()); expect(lr).toEqual({ sections: [ { subjRows: [ { subj: EX("a0"), predRows: [{ pred: EX("b0"), objs: [EX("c0")] }], }, { subj: EX("d0"), predRows: [{ pred: EX("e0"), objs: [EX("f0")] }], }, ], }, ], }); }); describe("makes a table as requested by ViewConfig", () => { let lr: LayoutResult; beforeAll(async () => { const vc = new ViewConfig(); await vc.readFromGraph(` @prefix : <http://example.com/> . @prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> . <> a :View; :table [ :primaryType :T1 ] .`); const layout = new Layout(vc); lr = layout.plan(await typedStatements()); }); it("returns 2 sections", () => { expect(lr.sections).toHaveLength(2); }); it("puts the right type in the table", async () => { const section0 = lr.sections[0] as AlignedTable; expect(section0.columnHeaders).toEqual([ { rdfTypes: [EX("T1")], pred: EX("color") }, { rdfTypes: [EX("T1"), EX("T2")], pred: EX("size") }, // and doesn't include rdf:type as a column header here ]); expect(section0.rowHeaders).toEqual([EX("a"), EX("b"), EX("c"), EX("e")]); expect(section0.rows).toEqual([ [[EX("red")], []], [[EX("blue")], []], [[], []], [[], [EX("small")]], ]); }); it("leaves the rest ungrouped", async () => { expect(lr.sections[1]).toEqual({ subjRows: [ { subj: EX("d"), predRows: [ { pred: EX("size"), objs: [EX("big")] }, { pred: rdf.type, objs: [EX("T2")] }, ], }, ], }); }); }); it("makes two tables", async () => { const vc = new ViewConfig(); await vc.readFromGraph(` @prefix ex: <http://example.com/> . @prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> . @prefix : <http://example.com/> . <> a :View; :table [ :primaryType :T1 ], [ :primaryType :T2 ] .`); const layout = new Layout(vc); const lr = layout.plan(await typedStatements()); expect(lr.sections).toHaveLength(2); const section0 = lr.sections[0] as AlignedTable; expect(section0.columnHeaders).toEqual([ { rdfTypes: [EX("T1")], pred: EX("color") }, { rdfTypes: [EX("T1"), EX("T2")], pred: EX("size") }, ]); expect(section0.rowHeaders).toEqual([EX("a"), EX("b"), EX("c"), EX("e")]); expect(section0.rows).toEqual([ [[EX("red")], []], [[EX("blue")], []], [[], []], [[], [EX("small")]], ]); const section1 = lr.sections[1] as AlignedTable; expect(section1.columnHeaders).toEqual([ { rdfTypes: [EX("T1"), EX("T2")], pred: EX("size") }, ]); expect(section1.rowHeaders).toEqual([EX("d"), EX("e")]); expect(section1.rows).toEqual([ [[EX("big")]], // [[EX("small")]], ]); }); describe("joins multiple types into one table", () => { it("can simply merge types", async () => { const vc = new ViewConfig(); await vc.readFromGraph(` @prefix ex: <http://example.com/> . @prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> . @prefix : <http://example.com/> . <> a :View; :table [ :primaryType :T1; :joinType :T2 ] . `); const layout = new Layout(vc); const lr = layout.plan( await n3Graph(` @prefix : <http://example.com/> . :g1 { :a a :T1 ; :color :red . :b a :T2 ; :size :big . } `) ); expect(lr.sections).toHaveLength(1); const section0 = lr.sections[0] as AlignedTable; expect(section0.columnHeaders).toEqual([ { rdfTypes: [EX("T1")], pred: EX("color") }, { rdfTypes: [EX("T2")], pred: EX("size") }, ]); expect(section0.rowHeaders).toEqual([EX("a"), EX("b")]); expect(section0.rows).toEqual([ [[EX("red")], []], [[], [EX("big")]], ]); }); it("groups columns by type", async()=>{ const vc = new ViewConfig(); await vc.readFromGraph(` @prefix ex: <http://example.com/> . @prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> . @prefix : <http://example.com/> . <> a :View; :table [ :primaryType :T1; :joinType :T2, :T3 ] . `); const layout = new Layout(vc); const lr = layout.plan( await n3Graph(` @prefix : <http://example.com/> . :g1 { :a a :T1; :p1 :red; :p3 :green . :b a :T2; :p2 :blue . } `) ); const section0 = lr.sections[0] as AlignedTable; expect(section0.columnHeaders).toEqual([ { rdfTypes: [EX("T1")], pred: EX("p1") }, { rdfTypes: [EX("T1")], pred: EX("p3") }, { rdfTypes: [EX("T2")], pred: EX("p2") }, ]); }) }); it.skip("makes a table out of ungrouped triples with the same type", async () => {}); });