From da766f364ccae7199c3de5fbd7e21afa0ad3b601 Mon Sep 17 00:00:00 2001 From: Sirz Benjie <142067137+SirzBenjie@users.noreply.github.com> Date: Thu, 18 Sep 2025 07:52:15 -0500 Subject: [PATCH] [Tests] Cleanup `getCookie` and add many unit tests (#6562) Cleanup `getCookie` and add many unit tests --- src/utils/cookies.ts | 16 +++++----- test/utils/cookies.test.ts | 62 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 69 insertions(+), 9 deletions(-) create mode 100644 test/utils/cookies.test.ts diff --git a/src/utils/cookies.ts b/src/utils/cookies.ts index e16d9d78556..407bd75da14 100644 --- a/src/utils/cookies.ts +++ b/src/utils/cookies.ts @@ -17,19 +17,17 @@ export function removeCookie(cName: string): void { export function getCookie(cName: string): string { // check if there are multiple cookies with the same name and delete them - if (document.cookie.split(";").filter(c => c.includes(cName)).length > 1) { + if (document.cookie.split(";").filter(c => c.trim().includes(cName)).length > 1) { removeCookie(cName); return ""; } const name = `${cName}=`; - const ca = document.cookie.split(";"); - for (let c of ca) { - // ⚠️ DO NOT REPLACE THIS WITH C = C.TRIM() - IT BREAKS IN NON-CHROMIUM BROWSERS ⚠️ - while (c.charAt(0) === " ") { - c = c.substring(1); - } - if (c.indexOf(name) === 0) { - return c.substring(name.length, c.length); + const cookieArray = document.cookie.split(";"); + // Check all cookies in the document and see if any of them match, grabbing the first one whose value lines up + for (const cookie of cookieArray) { + const cookieTrimmed = cookie.trim(); + if (cookieTrimmed.startsWith(name)) { + return cookieTrimmed.slice(name.length, cookieTrimmed.length); } } return ""; diff --git a/test/utils/cookies.test.ts b/test/utils/cookies.test.ts new file mode 100644 index 00000000000..a5ea248c236 --- /dev/null +++ b/test/utils/cookies.test.ts @@ -0,0 +1,62 @@ +import { getCookie } from "#utils/cookies"; +import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; + +describe("Unit Tests - cookies.ts", () => { + describe("getCookie", () => { + const cookieStart = document.cookie; + beforeEach(() => { + // clear cookie before each test + document.cookie = ""; + }); + + afterEach(() => { + // restore original cookie after each test + document.cookie = cookieStart; + }); + /** + * Spies on `document.cookie` and replaces its value with the provided string. + */ + function setDocumentCookie(value: string) { + vi.spyOn(document, "cookie", "get").mockReturnValue(value); + } + it("returns the value of a single cookie", () => { + setDocumentCookie("foo=bar"); + expect(getCookie("foo")).toBe("bar"); + }); + + it("returns empty string if cookie is not found", () => { + setDocumentCookie("foo=bar"); + expect(getCookie("baz")).toBe(""); + }); + + it("returns the value when multiple cookies exist", () => { + setDocumentCookie("foo=bar; baz=qux"); + expect(getCookie("baz")).toBe("qux"); + }); + + it("trims leading spaces in cookies", () => { + setDocumentCookie("foo=bar; baz=qux"); + expect(getCookie("baz")).toBe("qux"); + }); + + it("returns the value of the first matching cookie if only one exists", () => { + setDocumentCookie("foo=bar; test=val"); + expect(getCookie("foo")).toBe("bar"); + }); + + it("returns empty string if document.cookie is empty", () => { + setDocumentCookie(""); + expect(getCookie("foo")).toBe(""); + }); + + it("handles cookies that aren't separated with a space", () => { + setDocumentCookie("foo=bar;baz=qux;quux=corge;grault=garply"); + expect(getCookie("baz")).toBe("qux"); + }); + + it("handles cookies that may have leading tab characters", () => { + setDocumentCookie("foo=bar;\tbaz=qux"); + expect(getCookie("baz")).toBe("qux"); + }); + }); +});