1 parent
b2cf487734
commit
fe269a28db
14 files changed
+209
-6
No files matched your search
+24
-1
@@ -1,8 +1,31 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { formatZooKeeperMetadataRows, formatZooKeeperSummaryBadges, prettyPrintJsonText } from "@/lib/kv/kvValueDisplay";
|
||||
import { decodeBase64Utf8Preview, formatZooKeeperMetadataRows, formatZooKeeperSummaryBadges, prettyPrintJsonText } from "@/lib/kv/kvValueDisplay";
|
||||
import type { KvKeyMetadata } from "@/lib/backend/api";
|
||||
|
||||
describe("kv value display helpers", () => {
|
||||
it("decodes a valid Base64 value as a lossless UTF-8 preview", () => {
|
||||
expect(decodeBase64Utf8Preview("5L2g5aW9")).toEqual({
|
||||
ok: true,
|
||||
value: "你好",
|
||||
lossy: false,
|
||||
});
|
||||
});
|
||||
|
||||
it("marks replacement decoding of invalid UTF-8 bytes as lossy", () => {
|
||||
expect(decodeBase64Utf8Preview("ZoBv")).toEqual({
|
||||
ok: true,
|
||||
value: "f�o",
|
||||
lossy: true,
|
||||
});
|
||||
});
|
||||
|
||||
it("rejects malformed Base64 without throwing", () => {
|
||||
expect(decodeBase64Utf8Preview("not base64!")).toEqual({
|
||||
ok: false,
|
||||
error: "invalid_base64",
|
||||
});
|
||||
});
|
||||
|
||||
it("pretty prints valid JSON text", () => {
|
||||
expect(prettyPrintJsonText('{"name":"张三","roles":["admin","reader"]}')).toEqual({
|
||||
ok: true,
|
||||
|
||||
@@ -8,6 +8,8 @@ export interface PrettyPrintJsonResult {
|
||||
error?: "invalid_json";
|
||||
}
|
||||
|
||||
export type Base64Utf8PreviewResult = { ok: true; value: string; lossy: boolean } | { ok: false; error: "invalid_base64" };
|
||||
|
||||
export interface DisplayItem {
|
||||
label: string;
|
||||
value: string;
|
||||
@@ -20,6 +22,33 @@ export interface ZooKeeperSummaryLabels {
|
||||
size?: string;
|
||||
}
|
||||
|
||||
const strictBase64Pattern = /^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/;
|
||||
|
||||
export function decodeBase64Utf8Preview(value: string): Base64Utf8PreviewResult {
|
||||
const normalized = value.replace(/\s+/g, "");
|
||||
if (!strictBase64Pattern.test(normalized)) return { ok: false, error: "invalid_base64" };
|
||||
|
||||
try {
|
||||
const binary = atob(normalized);
|
||||
const bytes = Uint8Array.from(binary, (character) => character.charCodeAt(0));
|
||||
try {
|
||||
return {
|
||||
ok: true,
|
||||
value: new TextDecoder("utf-8", { fatal: true }).decode(bytes),
|
||||
lossy: false,
|
||||
};
|
||||
} catch {
|
||||
return {
|
||||
ok: true,
|
||||
value: new TextDecoder("utf-8").decode(bytes),
|
||||
lossy: true,
|
||||
};
|
||||
}
|
||||
} catch {
|
||||
return { ok: false, error: "invalid_base64" };
|
||||
}
|
||||
}
|
||||
|
||||
export function prettyPrintJsonText(text: string): PrettyPrintJsonResult {
|
||||
try {
|
||||
return { ok: true, value: safeJsonFormat(text, 2) };
|
||||
|
||||
Reference in new issue
Block a user