OverviewFilesCommitsIssuesDocsReleasesPeers

pearbrowser-desktop / test / names.test.js

75 lines · javascript ref:
// Tests for backend/names.cjs (naming Phase N1 — petname Hyperbee store).
// Uses a real on-disk Corestore (runs under node, like the autobee tests).
import test from 'node:test'
import assert from 'node:assert/strict'
import { mkdtemp, rm } from 'node:fs/promises'
import { tmpdir } from 'node:os'
import { join } from 'node:path'
import Corestore from 'corestore'
import namesMod from '../backend/names.cjs'
const { Names } = namesMod

const KEY = '0c35d12fd9b1115dd2d1fb1cd1751817c9173d3196ac7c62ae37d023340dcb75'

async function withStore (fn) {
  const dir = await mkdtemp(join(tmpdir(), 'names-test-'))
  try {
    const store = new Corestore(dir)
    await store.ready()
    const names = new Names(store, { now: () => 1700000000000 })
    await names.ready()
    await fn(names)
    await names.close()
    await store.close()
  } finally {
    await rm(dir, { recursive: true, force: true })
  }
}

test('setPetname + lookupPetname round-trips; names are normalized', async () => {
  await withStore(async (names) => {
    await names.setPetname({ name: 'KEET', key: KEY, label: 'My Keet' })
    const hit = await names.lookupPetname('keet')          // looked up case-folded
    assert.equal(hit.name, 'keet')
    assert.equal(hit.key, KEY)
    assert.equal(hit.label, 'My Keet')
    assert.equal(hit.addedAt, 1700000000000)
  })
})

test('petname accepts a link; requires key or link', async () => {
  await withStore(async (names) => {
    const r = await names.setPetname({ name: 'home', link: ' HYPER://abc/ ' })
    assert.equal(r.link, 'hyper://abc/')
    assert.equal(r.key, null)
    await assert.rejects(() => names.setPetname({ name: 'badlink', link: 'javascript:alert(1)' }), /needs a key or link/)
    await assert.rejects(() => names.setPetname({ name: 'web', link: 'https://example.com' }), /needs a key or link/)
    await assert.rejects(() => names.setPetname({ name: 'toolong', link: 'pear://' + 'x'.repeat(301) }), /needs a key or link/)
    await assert.rejects(() => names.setPetname({ name: 'bad' }), /needs a key or link/)
    await assert.rejects(() => names.setPetname({ name: '', key: KEY }), /name required/)
  })
})

test('list + petnameMap feed the resolver; remove works', async () => {
  await withStore(async (names) => {
    await names.setPetname({ name: 'keet', key: KEY })
    await names.setPetname({ name: 'home', link: 'hyper://abc/' })
    assert.equal((await names.list()).length, 2)
    const map = await names.petnameMap()
    assert.equal(map.keet.key, KEY)
    assert.equal(map.home.link, 'hyper://abc/')
    await names.removePetname('keet')
    assert.equal(await names.lookupPetname('keet'), null)
    assert.equal((await names.list()).length, 1)
  })
})

test('recordSeen stores under seen!, never as a resolvable petname', async () => {
  await withStore(async (names) => {
    await names.recordSeen(KEY, 'TotallyKeet')
    // a self-asserted nickname must NOT become a petname/resolvable
    assert.equal(await names.lookupPetname('totallykeet'), null)
    assert.equal((await names.list()).length, 0)   // list() is pet! only
  })
})