OverviewFilesCommitsIssuesDocsReleasesPeers

hyper-rooms / test / compose-schemas.test.js

70 lines · javascript ref:
import test from 'brittle'
import Corestore from 'corestore'
import { mkdtempSync } from 'fs'
import { join } from 'path'
import { tmpdir } from 'os'
import { replicateAndSync } from 'autobase-test-helpers'
import { Room, jsonSchema, composeSchemas } from '../index.js'

function tmp () { return mkdtempSync(join(tmpdir(), 'rooms-compose-')) }

// Two disjoint toy op-domains, plus a shared idempotent op (set-meta) to
// exercise the documented "shared op.type runs all handlers" behaviour.
const alpha = jsonSchema({
  validate (op) { if (op.type === 'put-a' && !op.id) throw new Error('put-a needs id') },
  async apply (batch, op) {
    if (op.type === 'put-a') await batch.put('a:' + op.id, { v: op.v })
    else if (op.type === 'set-meta') await batch.put('meta:' + op.key, { value: op.value })
  }
})
const beta = jsonSchema({
  validate (op) { if (op.type === 'put-b' && !op.id) throw new Error('put-b needs id') },
  async apply (batch, op) {
    if (op.type === 'put-b') await batch.put('b:' + op.id, { v: op.v })
    else if (op.type === 'set-meta') await batch.put('meta:' + op.key, { value: op.value })
  }
})

test('composeSchemas: one Room carries two op-domains and replicates both', async (t) => {
  const roomA = new Room(new Corestore(tmp()), {
    schema: composeSchemas([alpha, beta]), namespace: 'shared'
  })
  await roomA.ready()

  await roomA.append({ type: 'put-a', id: '1', v: 'aaa' })
  await roomA.append({ type: 'put-b', id: '1', v: 'bbb' })
  await roomA.append({ type: 'set-meta', key: 'k', value: 'm' })
  await roomA.base.update()

  const roomB = new Room(new Corestore(tmp()), {
    schema: composeSchemas([alpha, beta]), namespace: 'shared', bootstrapKey: roomA.key
  })
  await roomB.ready()
  await replicateAndSync([roomA.base, roomB.base])

  const a = await roomB.view.get('a:1')
  const b = await roomB.view.get('b:1')
  const m = await roomB.view.get('meta:k')
  t.is(a && a.value.v, 'aaa', 'domain A op replicated to B')
  t.is(b && b.value.v, 'bbb', 'domain B op replicated to B')
  t.is(m && m.value.value, 'm', 'shared set-meta applied once without error')

  await roomA.close()
  await roomB.close()
})

test('composeSchemas: validateOp runs every schema; cross-domain ops do not throw', async (t) => {
  const room = new Room(new Corestore(tmp()), {
    schema: composeSchemas([alpha, beta]), namespace: 's'
  })
  await room.ready()
  // put-b is unknown to alpha's switch but valid for beta — must not throw.
  await t.execution(room.append({ type: 'put-b', id: '2', v: 'x' }))
  await room.close()
})

test('composeSchemas: rejects empty input', (t) => {
  t.exception(() => composeSchemas([]))
  t.exception(() => composeSchemas(null))
})