import { describe, expect, it } from "vitest"; import { getInitialMarriageProfile } from "@/hooks/marriage/use-profile-main"; import type { MarriageProfileResponse } from "@/hooks/marriage/types"; /** * Robust parser replicating the layout.tsx and auth-bridge.ts cookie resolution strategy. */ export function parseMarriageCookie( rawCookie: string | null | undefined, ): { parsedJson: any; profile?: MarriageProfileResponse } | null { if (!rawCookie || !rawCookie.trim()) return null; const trimmed = rawCookie.trim(); // Strategy 1: Try decoding URI component first (Standard RFC-6265 percent-encoded cookie from Flutter) try { const decoded = decodeURIComponent(trimmed); const parsed = JSON.parse(decoded); return { parsedJson: parsed, profile: getInitialMarriageProfile(parsed), }; } catch { // Strategy 2: Fallback for legacy raw unencoded JSON cookies try { const parsed = JSON.parse(trimmed); return { parsedJson: parsed, profile: getInitialMarriageProfile(parsed), }; } catch { return null; } } } describe("HABIB_MARRIAGE_DATA Cookie Encoding & Decoding Suite", () => { it("successfully parses standard URL-encoded JSON with Persian characters (Uri.encodeComponent)", () => { const originalData = { id: 101, status: "match_found", gender: "male", city: "تهران", bio: "مهندس کامپیوتر، علاقه‌مند به کتاب‌خوانی و طبیعت‌گردی", match_summary: { id: 202, gender: "female", public_info: [ { label: "شهر", value: "اصفهان" }, { label: "تحصیلات", value: "کارشناسی ارشد" }, ], }, }; // Simulate Flutter: Uri.encodeComponent(json.encode(marriageData)) const encodedCookie = encodeURIComponent(JSON.stringify(originalData)); // Verify it's purely US-ASCII expect(/^[\x00-\x7F]*$/.test(encodedCookie)).toBe(true); const result = parseMarriageCookie(encodedCookie); expect(result).not.toBeNull(); expect(result?.parsedJson.city).toBe("تهران"); expect(result?.parsedJson.bio).toBe("مهندس کامپیوتر، علاقه‌مند به کتاب‌خوانی و طبیعت‌گردی"); expect(result?.parsedJson.match_summary.public_info[0].value).toBe("اصفهان"); expect(result?.profile?.status).toBe("match_found"); }); it("successfully parses legacy raw unencoded JSON with Persian characters", () => { const legacyRawCookie = JSON.stringify({ id: 102, status: "active", gender: "female", city: "مشهد", interests: ["زیارت", "خانواده"], }); const result = parseMarriageCookie(legacyRawCookie); expect(result).not.toBeNull(); expect(result?.parsedJson.city).toBe("مشهد"); expect(result?.parsedJson.interests).toEqual(["زیارت", "خانواده"]); }); it("handles complex strings with percentage signs, quotes, and emojis without crashing", () => { const complexData = { id: 103, status: "match_found", note: "تطابق با دقت ۱۰۰% و رضایت ۹۵% 💍❤️", query: "param1=val¶m2=50%off", }; const encodedCookie = encodeURIComponent(JSON.stringify(complexData)); const result = parseMarriageCookie(encodedCookie); expect(result).not.toBeNull(); expect(result?.parsedJson.note).toBe("تطابق با دقت ۱۰۰% و رضایت ۹۵% 💍❤️"); expect(result?.parsedJson.query).toBe("param1=val¶m2=50%off"); }); it("handles unencoded JSON containing raw percent sign gracefully via fallback", () => { // If an unencoded cookie contains raw %, decodeURIComponent will throw URIError. // The parser MUST catch it and fallback to JSON.parse directly. const rawWithPercent = '{"status":"active","progress":"100% completed","city":"شیراز"}'; const result = parseMarriageCookie(rawWithPercent); expect(result).not.toBeNull(); expect(result?.parsedJson.progress).toBe("100% completed"); expect(result?.parsedJson.city).toBe("شیراز"); }); it("returns null safely for corrupted, empty, or invalid cookies", () => { expect(parseMarriageCookie(null)).toBeNull(); expect(parseMarriageCookie("")).toBeNull(); expect(parseMarriageCookie(" ")).toBeNull(); expect(parseMarriageCookie("undefined")).toBeNull(); expect(parseMarriageCookie("invalid-not-json")).toBeNull(); expect(parseMarriageCookie("%E0%A4%A")).toBeNull(); // Malformed URI sequence }); });