OverviewFilesCommitsIssuesDocsReleasesPeers

P2P-Hiverelay / test / unit / catalog-broadcast-dedup.test.js

56 lines · javascript ref:
/**
 * catalogForBroadcast() must collapse app-type rows by appId (keep latest
 * version), matching the HTTP catalog() view — the P2P broadcast previously
 * leaked superseded versions to peers. Redacted (appId null) + non-app rows
 * pass through.
 */

import test from 'brittle'
import { AppRegistry } from 'p2p-hiverelay/core/app-registry.js'

const A = 'a'.repeat(64)
const B = 'b'.repeat(64)
const D = 'd'.repeat(64)
const E = 'e'.repeat(64)

test('catalogForBroadcast collapses app versions by appId (keep latest)', (t) => {
  const r = new AppRegistry(null)
  r.set(A, { type: 'app', appId: 'cool', version: '1.0.0' })
  r.set(B, { type: 'app', appId: 'cool', version: '2.0.0' })

  const bc = r.catalogForBroadcast()
  const cool = bc.filter(x => x.type === 'app' && x.appId === 'cool')
  t.is(cool.length, 1, 'one broadcast row for appId cool')
  t.is(cool[0].version, '2.0.0', 'highest version kept')
  t.is(cool[0].appKey, B, 'the latest entry survives')

  // catalog() already dedups — regression guard that both views agree.
  const httpCool = r.catalog().filter(x => x.type === 'app' && x.id === 'cool')
  t.is(httpCool.length, 1)
  t.is(httpCool[0].version, '2.0.0')
})

test('non-app types and distinct appIds are never collapsed', (t) => {
  const r = new AppRegistry(null)
  r.set(A, { type: 'app', appId: 'one', version: '1.0.0' })
  r.set(B, { type: 'app', appId: 'two', version: '1.0.0' })
  r.set(D, { type: 'drive', appId: 'one' }) // same appId but a drive — not collapsed
  r.set(E, { type: 'dataset' })

  const bc = r.catalogForBroadcast()
  t.is(bc.filter(x => x.type === 'app').length, 2, 'both distinct apps kept')
  t.ok(bc.some(x => x.type === 'drive'), 'drive passes through')
  t.ok(bc.some(x => x.type === 'dataset'), 'dataset passes through')
})

test('blind/redacted rows (appId null) pass through, never collapsed', (t) => {
  const r = new AppRegistry(null)
  r.set(A, { type: 'app', appId: 'x', version: '1.0.0', blind: true, blindContentId: 'f'.repeat(64) })
  r.set(B, { type: 'app', appId: 'x', version: '2.0.0', blind: true, blindContentId: '9'.repeat(64) })

  const bc = r.catalogForBroadcast()
  const blindRows = bc.filter(x => x.blind === true)
  t.is(blindRows.length, 2, 'both blind rows survive (appId redacted to null, not collapsed)')
  t.ok(blindRows.every(x => x.appId === null), 'blind rows carry no appId')
})