OverviewFilesCommitsIssuesDocsReleasesPeers

hypercore-kb / hyper-social / bridge-mastodon / test / adapter.test.js

246 lines · javascript ref:
import test from 'brittle'
import { statusToEnvelope, keetToMastodon, envelopeToStatusText, statusToKeetText, stripHtml } from '../lib/adapter.js'
import { TYPES, PLATFORMS } from 'bridge-envelope'

test('stripHtml - basic tags', (t) => {
  t.is(stripHtml('<p>Hello</p>'), 'Hello')
  t.is(stripHtml('<p>Line 1</p><p>Line 2</p>'), 'Line 1\n\nLine 2')
  t.is(stripHtml('Hello<br/>World'), 'Hello\nWorld')
  t.is(stripHtml('Hello<br>World'), 'Hello\nWorld')
})

test('stripHtml - entities', (t) => {
  t.is(stripHtml('&amp; &lt; &gt; &quot; &#39;'), '& < > " \'')
})

test('stripHtml - nested tags', (t) => {
  t.is(stripHtml('<p>Hello <a href="https://example.com">link</a></p>'), 'Hello link')
  t.is(stripHtml('<p><span class="mention">@user</span> hi</p>'), '@user hi')
})

test('statusToEnvelope - basic status', (t) => {
  const status = {
    id: '12345',
    account: { acct: 'alice@mastodon.social', username: 'alice' },
    content: '<p>Hello world!</p>',
    visibility: 'public',
    media_attachments: [],
    tags: [],
    created_at: '2026-02-14T10:00:00.000Z'
  }

  const env = statusToEnvelope(status)
  t.ok(env)
  t.is(env.type, TYPES.TEXT)
  t.is(env.platform, PLATFORMS.MASTODON)
  t.is(env.author, 'alice@mastodon.social')
  t.is(env.content, 'Hello world!')
  t.is(env.channel, 'public')
  t.ok(env.id)
})

test('statusToEnvelope - status with media', (t) => {
  const status = {
    id: '12346',
    account: { acct: 'bob' },
    content: '<p>Check this out</p>',
    visibility: 'unlisted',
    media_attachments: [{
      url: 'https://files.mastodon.social/image.jpg',
      type: 'image',
      preview_url: 'https://files.mastodon.social/thumb.jpg'
    }],
    tags: []
  }

  const env = statusToEnvelope(status)
  t.is(env.type, TYPES.MEDIA)
  t.is(env.mediaUrl, 'https://files.mastodon.social/image.jpg')
  t.is(env.mediaType, 'image')
})

test('statusToEnvelope - reply', (t) => {
  const status = {
    id: '12347',
    account: { acct: 'carol' },
    content: '<p>@alice I agree!</p>',
    in_reply_to_id: '12345',
    visibility: 'public',
    media_attachments: [],
    tags: []
  }

  const env = statusToEnvelope(status)
  t.is(env.type, TYPES.REPLY)
  t.is(env.replyTo, '12345')
})

test('statusToEnvelope - boost (reblog)', (t) => {
  const status = {
    id: '99999',
    account: { acct: 'dave' },
    reblog: {
      id: '12345',
      account: { acct: 'alice@mastodon.social' },
      content: '<p>Original post</p>',
      visibility: 'public',
      media_attachments: [],
      tags: []
    }
  }

  const env = statusToEnvelope(status)
  t.ok(env)
  t.is(env.author, 'alice@mastodon.social')
  t.is(env.content, 'Original post')
  t.ok(env._isBoost)
  t.is(env._boostBy, 'dave')
  t.is(env.channel, 'boost')
})

test('statusToEnvelope - with tags', (t) => {
  const status = {
    id: '12348',
    account: { acct: 'eve' },
    content: '<p>Great discussion #p2p #hypercore</p>',
    visibility: 'public',
    media_attachments: [],
    tags: [{ name: 'p2p' }, { name: 'hypercore' }]
  }

  const env = statusToEnvelope(status)
  t.alike(env._tags, ['p2p', 'hypercore'])
})

test('statusToEnvelope - with spoiler text', (t) => {
  const status = {
    id: '12349',
    account: { acct: 'frank' },
    content: '<p>Spoiler content here</p>',
    spoiler_text: 'Movie spoiler',
    visibility: 'public',
    media_attachments: [],
    tags: []
  }

  const env = statusToEnvelope(status)
  t.is(env._spoilerText, 'Movie spoiler')
})

test('statusToEnvelope - null/empty', (t) => {
  t.is(statusToEnvelope(null), null)
  t.is(statusToEnvelope({ id: '1', account: { acct: 'x' }, content: '', media_attachments: [] }), null)
})

test('keetToMastodon - normal message', (t) => {
  const msg = { name: 'fleeky', text: 'Hello from Keet!', memberId: 'abc123' }
  const result = keetToMastodon(msg, 'bridge-id')
  t.ok(result)
  t.is(result.author, 'fleeky')
  t.is(result.text, 'Hello from Keet!')
})

test('keetToMastodon - skip bridge identity', (t) => {
  const msg = { name: 'clode', text: 'Hello', memberId: 'bridge-id' }
  const result = keetToMastodon(msg, 'bridge-id')
  t.is(result, null)
})

test('keetToMastodon - skip system messages', (t) => {
  const msg = { name: 'system', text: 'joined', type: 'system' }
  t.is(keetToMastodon(msg, 'bridge-id'), null)
})

test('keetToMastodon - skip already bridged', (t) => {
  const msg = { name: 'someone', text: '[mastodon] @alice: hello', memberId: 'x' }
  t.is(keetToMastodon(msg, 'bridge-id'), null)
})

test('keetToMastodon - skip empty', (t) => {
  t.is(keetToMastodon({ name: 'x', text: '', memberId: 'y' }, 'b'), null)
  t.is(keetToMastodon({ name: 'x', text: '   ', memberId: 'y' }, 'b'), null)
  t.is(keetToMastodon(null, 'b'), null)
})

test('envelopeToStatusText - from Keet', (t) => {
  const env = {
    platform: PLATFORMS.KEET,
    author: 'fleeky',
    content: 'Hello world'
  }
  t.is(envelopeToStatusText(env), '[Keet] fleeky: Hello world')
})

test('envelopeToStatusText - from IRC', (t) => {
  const env = {
    platform: PLATFORMS.IRC,
    author: 'nick',
    content: 'IRC message'
  }
  t.is(envelopeToStatusText(env), '[IRC] nick: IRC message')
})

test('statusToKeetText - basic', (t) => {
  const env = statusToEnvelope({
    id: '1',
    account: { acct: 'alice' },
    content: '<p>Hello!</p>',
    visibility: 'public',
    media_attachments: [],
    tags: []
  })
  const text = statusToKeetText(env)
  t.ok(text.includes('[mastodon]'))
  t.ok(text.includes('@alice'))
  t.ok(text.includes('Hello!'))
})

test('statusToKeetText - boost', (t) => {
  const env = statusToEnvelope({
    id: '2',
    account: { acct: 'bob' },
    reblog: {
      id: '1',
      account: { acct: 'alice' },
      content: '<p>Original</p>',
      visibility: 'public',
      media_attachments: [],
      tags: []
    }
  })
  const text = statusToKeetText(env)
  t.ok(text.includes('bob boosted'))
  t.ok(text.includes('@alice'))
})

test('statusToKeetText - content warning', (t) => {
  const env = statusToEnvelope({
    id: '3',
    account: { acct: 'carol' },
    content: '<p>Secret info</p>',
    spoiler_text: 'Spoiler ahead',
    visibility: 'public',
    media_attachments: [],
    tags: []
  })
  const text = statusToKeetText(env)
  t.ok(text.includes('[CW: Spoiler ahead]'))
})

test('statusToKeetText - with media', (t) => {
  const env = statusToEnvelope({
    id: '4',
    account: { acct: 'dave' },
    content: '<p>Look!</p>',
    visibility: 'public',
    media_attachments: [{
      url: 'https://example.com/image.jpg',
      type: 'image'
    }],
    tags: []
  })
  const text = statusToKeetText(env)
  t.ok(text.includes('[image:'))
  t.ok(text.includes('image.jpg'))
})