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('& < > " ''), '& < > " \'')
})
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'))
})