// The bytes↔text seam of the RN IPC bridge, tested off-device.
//
// This is where a fully-booted node looked dead: bare-kit hands up a Uint8Array, `.toString()` on it
// returns "123,34,116,..." (Array.prototype.toString), and the message parser silently saw garbage
// forever. These tests pin both directions and the chunk-boundary case that a naive fix would miss.
import test from 'brittle'
import { encodeUtf8, createUtf8Decoder } from '../lib/utf8.js'
test('round-trips the node’s own log line, em dash included', (t) => {
const line = JSON.stringify({ t: 'log', msg: 'no DID paired — read-only until pairing' }) + '\n'
const decode = createUtf8Decoder()
t.is(decode(encodeUtf8(line)), line)
})
test('decodes what bare-kit actually pushes: a plain Uint8Array', (t) => {
const decode = createUtf8Decoder()
const bytes = new Uint8Array(encodeUtf8('{"t":"ready"}\n'))
t.is(decode(bytes), '{"t":"ready"}\n')
t.not(decode(bytes), String(bytes), 'must not be the comma-joined byte values')
})
test('a multi-byte character split across two chunks is not corrupted', (t) => {
const line = 'appview ready — 100%\n'
const full = encodeUtf8(line)
const decode = createUtf8Decoder()
// Cut mid-em-dash: the 3-byte sequence starts at `cut - 1`.
const cut = full.indexOf(0xe2) + 1
t.ok(cut > 0, 'the fixture really does contain a multi-byte character')
const first = decode(full.subarray(0, cut))
const second = decode(full.subarray(cut))
t.is(first + second, line)
})
test('holds back an incomplete trailing sequence rather than emitting a replacement char', (t) => {
const decode = createUtf8Decoder()
const full = encodeUtf8('— done')
t.is(decode(full.subarray(0, 1)), '', 'a lone lead byte decodes to nothing yet')
t.is(decode(full.subarray(1)), '— done')
})
test('encodes 4-byte code points (surrogate pairs)', (t) => {
const decode = createUtf8Decoder()
t.is(decode(encodeUtf8('🌱')), '🌱')
})