From 5b9fd9a7ec5a3f479d4a12e3dc60ce88c14fe521 Mon Sep 17 00:00:00 2001 From: mittalsonal Date: Mon, 10 Aug 2026 07:50:51 +0000 Subject: [PATCH 1/2] chore: cover sdk base64 helpers Co-authored-by: codex --- sdk/typescript/src/__tests__/base64.test.ts | 69 +++++++++++++++++++++ 1 file changed, 69 insertions(+) create mode 100644 sdk/typescript/src/__tests__/base64.test.ts diff --git a/sdk/typescript/src/__tests__/base64.test.ts b/sdk/typescript/src/__tests__/base64.test.ts new file mode 100644 index 00000000..1058e264 --- /dev/null +++ b/sdk/typescript/src/__tests__/base64.test.ts @@ -0,0 +1,69 @@ +import { afterEach, describe, expect, it } from "bun:test"; +import { decodeBase64ToUtf8, encodeUtf8ToBase64 } from "../base64"; + +const originalAtob = globalThis.atob; +const originalBtoa = globalThis.btoa; + +function setGlobalCapability(name: "atob" | "btoa", value: typeof globalThis.atob | undefined) { + Object.defineProperty(globalThis, name, { + configurable: true, + value, + writable: true, + }); +} + +afterEach(() => { + setGlobalCapability("atob", originalAtob); + setGlobalCapability("btoa", originalBtoa); +}); + +describe("base64 UTF-8 helpers", () => { + it("encodes known ASCII fixtures without Node Buffer", () => { + expect(encodeUtf8ToBase64("hello")).toBe("aGVsbG8="); + expect(encodeUtf8ToBase64("MicroAI Paygate")).toBe("TWljcm9BSSBQYXlnYXRl"); + }); + + it("round-trips ASCII, accented, non-Latin, and emoji text", () => { + const cases = [ + "plain ASCII receipt", + "Cr\u00e8me br\u00fbl\u00e9e", + "\u0928\u092e\u0938\u094d\u0924\u0947 \u092d\u0941\u0917\u0924\u093e\u0928", + "paid receipt \u{1f680}\u2705", + ]; + + for (const value of cases) { + expect(decodeBase64ToUtf8(encodeUtf8ToBase64(value))).toBe(value); + } + }); + + it("decodes valid UTF-8 base64 fixtures", () => { + expect(decodeBase64ToUtf8("SGVsbG8sIHdvcmxkIQ==")).toBe("Hello, world!"); + expect(decodeBase64ToUtf8("4pyF")).toBe("\u2705"); + }); + + it("encodes empty text to an empty base64 payload", () => { + expect(encodeUtf8ToBase64("")).toBe(""); + }); + + it("rejects empty, whitespace-padded, invalid-character, and invalid-padding input", () => { + for (const value of ["", " aGVsbG8=", "aGVsbG8= ", "abc@", "ab=", "abc==", "a==="]) { + expect(() => decodeBase64ToUtf8(value)).toThrow("invalid base64"); + } + }); + + it("reports unavailable decoding capability and restores globals", () => { + setGlobalCapability("atob", undefined); + + expect(() => decodeBase64ToUtf8("aGVsbG8=")).toThrow( + "base64 decoding is unavailable in this runtime", + ); + }); + + it("reports unavailable encoding capability and restores globals", () => { + setGlobalCapability("btoa", undefined); + + expect(() => encodeUtf8ToBase64("hello")).toThrow( + "base64 encoding is unavailable in this runtime", + ); + }); +}); From 5061ffe6fcc2cefeed17b6b226af4f05e8964b92 Mon Sep 17 00:00:00 2001 From: mittalsonal Date: Mon, 10 Aug 2026 08:01:00 +0000 Subject: [PATCH 2/2] chore: restore base64 globals by descriptor Co-authored-by: codex --- sdk/typescript/src/__tests__/base64.test.ts | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/sdk/typescript/src/__tests__/base64.test.ts b/sdk/typescript/src/__tests__/base64.test.ts index 1058e264..dddbfed5 100644 --- a/sdk/typescript/src/__tests__/base64.test.ts +++ b/sdk/typescript/src/__tests__/base64.test.ts @@ -1,10 +1,12 @@ import { afterEach, describe, expect, it } from "bun:test"; import { decodeBase64ToUtf8, encodeUtf8ToBase64 } from "../base64"; -const originalAtob = globalThis.atob; -const originalBtoa = globalThis.btoa; +type Base64Global = "atob" | "btoa"; -function setGlobalCapability(name: "atob" | "btoa", value: typeof globalThis.atob | undefined) { +const originalAtobDescriptor = Object.getOwnPropertyDescriptor(globalThis, "atob"); +const originalBtoaDescriptor = Object.getOwnPropertyDescriptor(globalThis, "btoa"); + +function setGlobalCapability(name: Base64Global, value: typeof globalThis.atob | undefined) { Object.defineProperty(globalThis, name, { configurable: true, value, @@ -12,9 +14,18 @@ function setGlobalCapability(name: "atob" | "btoa", value: typeof globalThis.ato }); } +function restoreGlobalCapability(name: Base64Global, descriptor: PropertyDescriptor | undefined) { + if (descriptor) { + Object.defineProperty(globalThis, name, descriptor); + return; + } + + Reflect.deleteProperty(globalThis, name); +} + afterEach(() => { - setGlobalCapability("atob", originalAtob); - setGlobalCapability("btoa", originalBtoa); + restoreGlobalCapability("atob", originalAtobDescriptor); + restoreGlobalCapability("btoa", originalBtoaDescriptor); }); describe("base64 UTF-8 helpers", () => {