diff --git a/apps/web/src/toasts/MobileGuideToast.test.ts b/apps/web/src/toasts/MobileGuideToast.test.ts new file mode 100644 index 0000000000..8206381a78 --- /dev/null +++ b/apps/web/src/toasts/MobileGuideToast.test.ts @@ -0,0 +1,41 @@ +/* +Copyright 2026 Element Creations Ltd. + +SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial +Please see LICENSE files in the repository root for full details. +*/ + +// @vitest-environment happy-dom +// @vitest-environment-options {"settings": {"navigator": {"userAgent": "Mozilla/5.0 (iPod touch; CPU iPhone OS 8_4_1 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) Version/8.0 Mobile/12H321 Safari/600.1.4" }}} + +import { type ComponentProps } from "react"; +import { vi, describe, it, expect, beforeEach } from "vitest"; + +import ToastStore from "../stores/ToastStore.ts"; +import { showToast } from "./MobileGuideToast.ts"; +import type GenericToast from "../components/views/toasts/GenericToast.tsx"; + +describe("showToast", () => { + const addOrReplaceToastSpy = vi.spyOn(ToastStore.sharedInstance(), "addOrReplaceToast"); + + beforeEach(() => { + sessionStorage.clear(); + }); + + it("should do nothing if sessionStorage has `skip_mobile_redirect`", () => { + sessionStorage.setItem("skip_mobile_redirect", "true"); + + showToast(); + expect(addOrReplaceToastSpy).not.toHaveBeenCalled(); + }); + + it("should set sessionStorage `skip_mobile_redirect` on reject", () => { + expect(sessionStorage.getItem("skip_mobile_redirect")).toBeFalsy(); + + showToast(); + const toast = addOrReplaceToastSpy.mock.calls[0][0]; + expect((toast.props as ComponentProps).secondaryLabel).toBe("Dismiss"); + (toast.props as ComponentProps).onSecondaryClick!(); + expect(sessionStorage.getItem("skip_mobile_redirect")).toBe("true"); + }); +}); diff --git a/apps/web/src/toasts/MobileGuideToast.ts b/apps/web/src/toasts/MobileGuideToast.ts index 566ea6aa93..f76893aaf0 100644 --- a/apps/web/src/toasts/MobileGuideToast.ts +++ b/apps/web/src/toasts/MobileGuideToast.ts @@ -16,7 +16,7 @@ const onAccept = (): void => { }; const onReject = (): void => { - document.cookie = "element_mobile_redirect_to_guide=false;path=/;max-age=14400"; + sessionStorage.setItem("skip_mobile_redirect", "true"); hideToast(); }; @@ -29,7 +29,7 @@ export const showToast = (): void => { if (!isIos && !isAndroid) { return; } - if (document.cookie.includes("element_mobile_redirect_to_guide=false")) { + if (sessionStorage.getItem("skip_mobile_redirect") === "true") { return; } ToastStore.sharedInstance().addOrReplaceToast({ diff --git a/apps/web/src/vector/index.ts b/apps/web/src/vector/index.ts index 5db075c26a..d69e74b0eb 100644 --- a/apps/web/src/vector/index.ts +++ b/apps/web/src/vector/index.ts @@ -150,7 +150,7 @@ async function start(): Promise { const isIos = /iPad|iPhone|iPod/.test(navigator.userAgent) && !window.MSStream; const isAndroid = /Android/.test(navigator.userAgent); if (isIos || isAndroid) { - if (document.cookie.indexOf("element_mobile_redirect_to_guide=false") === -1) { + if (sessionStorage.getItem("skip_mobile_redirect") !== "true") { window.location.href = "mobile_guide/"; return; } diff --git a/apps/web/src/vector/mobile_guide/index.test.ts b/apps/web/src/vector/mobile_guide/index.test.ts new file mode 100644 index 0000000000..c22ca8d735 --- /dev/null +++ b/apps/web/src/vector/mobile_guide/index.test.ts @@ -0,0 +1,45 @@ +/* +Copyright 2026 Element Creations Ltd. + +SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial +Please see LICENSE files in the repository root for full details. +*/ + +// @vitest-environment happy-dom + +import { vi, describe, it, expect, beforeEach, beforeAll } from "vitest"; +import { waitFor } from "@testing-library/dom"; +import fetchMock from "@fetch-mock/vitest"; + +vi.mock("../getconfig.ts", () => ({ + getVectorConfig: vi.fn().mockResolvedValue({ default_server_name: "server_name" }), +})); +vi.mock("./mobile-apps.ts"); + +describe("onBackToElementClick", () => { + beforeAll(async () => { + const backButton = document.createElement("a"); + backButton.id = "back_to_element_button"; + backButton.textContent = "Back"; + document.body.append(backButton); + + fetchMock.get("https://server_name/.well-known/matrix/client", { + "m.homeserver": { + base_url: "https://server/", + }, + }); + await import("./index.ts"); + }); + + beforeEach(async () => { + sessionStorage.clear(); + }); + + it("should set skip_mobile_redirect in sessionStorage", async () => { + expect(sessionStorage.getItem("skip_mobile_redirect")).toBeFalsy(); + const button = document.getElementById("back_to_element_button")!; + await waitFor(() => expect(button.onclick).toBeTruthy()); + button.click(); + expect(sessionStorage.getItem("skip_mobile_redirect")).toBe("true"); + }); +}); diff --git a/apps/web/src/vector/mobile_guide/index.ts b/apps/web/src/vector/mobile_guide/index.ts index 637b955e31..b8cb06afdf 100644 --- a/apps/web/src/vector/mobile_guide/index.ts +++ b/apps/web/src/vector/mobile_guide/index.ts @@ -15,8 +15,7 @@ import { getVectorConfig } from "../getconfig"; import { MobileAppVariant, mobileApps, updateMobilePage } from "./mobile-apps.ts"; function onBackToElementClick(): void { - // Cookie should expire in 4 hours - document.cookie = "element_mobile_redirect_to_guide=false;path=/;max-age=14400"; + sessionStorage.setItem("skip_mobile_redirect", "true"); window.location.href = "../"; }