import { test } from "node:test"; import assert from "node:assert/strict"; import { createUtf8Decoder, decodeEditableText, Utf8DecodingError } from "./text.ts"; import { HashlineError, TEXT_ERROR_MESSAGES } from "./errors.ts"; test("decodeEditableText rejects malformed input instead of replacing bytes", () => { assert.throws( () => decodeEditableText(Uint8Array.from([0xc3, 0x28])), (error: unknown) => error instanceof HashlineError && error.errorCode === "UNSUPPORTED_ENCODING", ); }); test("decodeEditableText preserves a leading BOM", () => { assert.equal(decodeEditableText(Uint8Array.from([0xef, 0xbb, 0xbf, 0x61])), "\ufeffa"); }); test("decodeEditableText rejects NUL bytes", () => { assert.throws( () => decodeEditableText(Uint8Array.from([0x61, 0, 0x62])), (error: unknown) => error instanceof HashlineError && error.errorCode === "UNSUPPORTED_TEXT", ); }); test("streaming UTF-8 decoders preserve a split BOM in strict and lossy modes", () => { for (const mode of ["strict", "lossy"] as const) { const decode = createUtf8Decoder(mode); assert.equal(decode(Uint8Array.from([0xef]), true), ""); assert.equal(decode(Uint8Array.from([0xbb, 0xbf, 0x61]), true), "\ufeffa"); assert.equal(decode(), ""); } }); test("lossy decoding replaces malformed bytes and flushes incomplete sequences at EOF", () => { const decode = createUtf8Decoder("lossy"); assert.equal(decode(Uint8Array.from([0xef, 0xbb, 0xbf, 0xff, 0xc3, 0x28]), true), "\ufeff��("); assert.equal(decode(Uint8Array.from([0xf0]), true), ""); assert.equal(decode(Uint8Array.from([0x9f]), true), ""); assert.equal(decode(), "�"); }); test("strict decoding rejects malformed sequences and incomplete EOF → one encoding classification", () => { const isEncodingError = (error: unknown) => error instanceof Utf8DecodingError && error.errorCode === "UNSUPPORTED_ENCODING" && error.message === TEXT_ERROR_MESSAGES.UNSUPPORTED_ENCODING && error.cause === undefined; assert.throws(() => createUtf8Decoder("strict")(Uint8Array.from([0xff])), isEncodingError); const decode = createUtf8Decoder("strict"); assert.equal(decode(Uint8Array.from([0xf0, 0x9f]), true), ""); assert.throws(() => decode(), isEncodingError); });