OverviewFilesCommitsIssuesDocsReleasesPeers

codetree / test / rank.test.js

73 lines · javascript ref:
import { test } from 'brittle'
import { layout } from '../lib/layout.js'

// An explicit rank: which COLUMN an item belongs in, when the caller already
// knows. Layering derives columns from edges, which is right when that is the
// only information there is — but a relation view knows each node's hop distance
// and side exactly, and re-deriving it from edges loses that.

test('layout: an explicit rank decides the column', (t) => {
  // Ranks deliberately DISAGREE with the edges: b supplies a, so layering would
  // put b left of a. The rank says otherwise and must win.
  const out = layout({
    nodes: [
      { id: 'a', container: null, w: 100, h: 40, rank: 0 },
      { id: 'b', container: null, w: 100, h: 40, rank: 1 },
      { id: 'c', container: null, w: 100, h: 40, rank: 2 }
    ],
    links: [{ from: 'b', to: 'a' }],
    containers: []
  })
  const x = new Map(out.nodes.map(n => [n.id, n.x]))
  t.ok(x.get('a') < x.get('b'), 'a is left of b, as ranked')
  t.ok(x.get('b') < x.get('c'), 'b is left of c')
})

test('layout: ranks and edges are not mixed within one group', (t) => {
  // Half-ranked columns would be a silent guess about what the caller meant.
  // If anything in a group is ranked, ranks decide the whole group and an
  // unranked sibling sits at 0.
  const out = layout({
    nodes: [
      { id: 'a', container: null, w: 100, h: 40, rank: 3 },
      { id: 'b', container: null, w: 100, h: 40 },
      { id: 'c', container: null, w: 100, h: 40 }
    ],
    links: [{ from: 'b', to: 'c' }],
    containers: []
  })
  const x = new Map(out.nodes.map(n => [n.id, n.x]))
  t.is(x.get('b'), x.get('c'), 'b and c are both unranked, so both at column 0')
  t.ok(x.get('a') > x.get('b'), 'the ranked item still lands right of them')
})

test('layout: a container can be ranked too', (t) => {
  const out = layout({
    nodes: [
      { id: 'a', container: 'far', w: 100, h: 40 },
      { id: 'b', container: 'near', w: 100, h: 40 }
    ],
    links: [],
    containers: [
      { id: 'near', parent: null, label: 'near', rank: 0 },
      { id: 'far', parent: null, label: 'far', rank: 1 }
    ]
  })
  const x = new Map(out.containers.map(c => [c.id, c.x]))
  t.ok(x.get('near') < x.get('far'), 'near is left of far, with no edges at all')
})

test('layout: unranked input is unaffected', (t) => {
  const input = {
    nodes: [
      { id: 'a', container: null, w: 100, h: 40 },
      { id: 'b', container: null, w: 100, h: 40 }
    ],
    links: [{ from: 'a', to: 'b' }],
    containers: []
  }
  const out = layout(input)
  const x = new Map(out.nodes.map(n => [n.id, n.x]))
  t.ok(x.get('a') < x.get('b'), 'layering still decides when nothing is ranked')
})