82 lines
3.5 KiB
TypeScript
82 lines
3.5 KiB
TypeScript
|
|
/**
|
||
|
|
* @module tests/integration/related-verb-array
|
||
|
|
* @description related() honours EVERY verb type in an array (10.4.9).
|
||
|
|
*
|
||
|
|
* The storage fast paths for `sourceId + verbType` and `verbType` collapsed a
|
||
|
|
* verb-type ARRAY to its first element — `related({ from, type: [a, b] })`
|
||
|
|
* silently returned only `a` edges, whichever order the array came in. The
|
||
|
|
* same quiet-loss class as the graph-first paging defect, one seam over.
|
||
|
|
* These pins seed a store where the SECOND requested type's edge must come
|
||
|
|
* back, on every path the collapse lived in.
|
||
|
|
*/
|
||
|
|
import { describe, it, expect, beforeAll, afterAll } from 'vitest'
|
||
|
|
import { Brainy } from '../../src/brainy'
|
||
|
|
import { NounType, VerbType } from '../../src/types/graphTypes'
|
||
|
|
import { v5 } from '../../src/universal/uuid'
|
||
|
|
|
||
|
|
describe('related() with a verb-type array returns every requested type', () => {
|
||
|
|
let brain: Brainy<any>
|
||
|
|
|
||
|
|
beforeAll(async () => {
|
||
|
|
brain = new Brainy({ requireSubtype: false, storage: { type: 'memory' } })
|
||
|
|
await brain.init()
|
||
|
|
for (const id of ['a', 'b', 'c', 'd']) {
|
||
|
|
await brain.add({ id, data: `node ${id}`, type: NounType.Person })
|
||
|
|
}
|
||
|
|
await brain.relate({ from: 'a', to: 'b', type: VerbType.Supports })
|
||
|
|
await brain.relate({ from: 'a', to: 'c', type: VerbType.RelatedTo })
|
||
|
|
await brain.relate({ from: 'a', to: 'd', type: VerbType.Knows })
|
||
|
|
await brain.relate({ from: 'b', to: 'c', type: VerbType.RelatedTo })
|
||
|
|
})
|
||
|
|
|
||
|
|
afterAll(async () => {
|
||
|
|
brain = null as any
|
||
|
|
})
|
||
|
|
|
||
|
|
it('from + type array: the second type\'s edge comes back, both orders', async () => {
|
||
|
|
for (const types of [
|
||
|
|
[VerbType.Supports, VerbType.RelatedTo],
|
||
|
|
[VerbType.RelatedTo, VerbType.Supports]
|
||
|
|
]) {
|
||
|
|
const edges = await brain.related({ from: 'a', type: types })
|
||
|
|
const targets = new Set(edges.map((e) => e.to))
|
||
|
|
expect(targets.has(v5('b')), `types [${types}] missing Supports edge`).toBe(true)
|
||
|
|
expect(targets.has(v5('c')), `types [${types}] missing RelatedTo edge`).toBe(true)
|
||
|
|
expect(targets.has(v5('d'))).toBe(false)
|
||
|
|
expect(edges).toHaveLength(2)
|
||
|
|
}
|
||
|
|
})
|
||
|
|
|
||
|
|
it('a single-element array behaves exactly like the scalar', async () => {
|
||
|
|
const scalar = await brain.related({ from: 'a', type: VerbType.Supports })
|
||
|
|
const array = await brain.related({ from: 'a', type: [VerbType.Supports] })
|
||
|
|
expect(array.map((e) => e.id).sort()).toEqual(scalar.map((e) => e.id).sort())
|
||
|
|
expect(array).toHaveLength(1)
|
||
|
|
})
|
||
|
|
|
||
|
|
it('no duplicate edges when types overlap the same edge set', async () => {
|
||
|
|
const edges = await brain.related({
|
||
|
|
from: 'a',
|
||
|
|
type: [VerbType.Supports, VerbType.RelatedTo, VerbType.Knows]
|
||
|
|
})
|
||
|
|
const ids = edges.map((e) => e.id)
|
||
|
|
expect(new Set(ids).size).toBe(ids.length)
|
||
|
|
expect(edges).toHaveLength(3)
|
||
|
|
})
|
||
|
|
|
||
|
|
it('type-only asks (no anchor) honour the whole array too', async () => {
|
||
|
|
const edges = await brain.related({ type: [VerbType.Supports, VerbType.Knows] })
|
||
|
|
const verbs = new Set(edges.map((e) => e.type))
|
||
|
|
expect(verbs.has(VerbType.Supports)).toBe(true)
|
||
|
|
expect(verbs.has(VerbType.Knows)).toBe(true)
|
||
|
|
expect(edges).toHaveLength(2)
|
||
|
|
})
|
||
|
|
|
||
|
|
it('pagination stays consistent across the union', async () => {
|
||
|
|
const page1 = await brain.related({ from: 'a', type: [VerbType.Supports, VerbType.RelatedTo, VerbType.Knows], limit: 2 })
|
||
|
|
const page2 = await brain.related({ from: 'a', type: [VerbType.Supports, VerbType.RelatedTo, VerbType.Knows], limit: 2, offset: 2 })
|
||
|
|
const all = [...page1, ...page2].map((e) => e.id)
|
||
|
|
expect(new Set(all).size).toBe(3)
|
||
|
|
})
|
||
|
|
})
|