Files
duty-teller/webapp-next/src/hooks/use-telegram-theme.test.ts
Nikolay Tatarinov 07e22079ee feat: enhance CSS and components for Telegram Mini App performance
- Updated CSS to utilize viewport variables for safe area insets and stable height, improving layout consistency across devices.
- Introduced haptic feedback triggers in various components to enhance user interaction, mimicking native Telegram behavior.
- Added functionality to detect Android performance class, minimizing animations on low-performance devices for better user experience.
- Refactored components to incorporate new CSS classes for content safety and improved responsiveness.
2026-03-04 19:19:14 +03:00

142 lines
4.5 KiB
TypeScript

/**
* Unit tests for useTelegramTheme, getFallbackScheme, and applyTheme.
* Ported from webapp/js/theme.test.js (getTheme, applyTheme).
*/
import { describe, it, expect, vi, afterEach } from "vitest";
import { renderHook } from "@testing-library/react";
import {
useTelegramTheme,
getFallbackScheme,
applyTheme,
} from "./use-telegram-theme";
vi.mock("@telegram-apps/sdk-react", () => ({
useSignal: vi.fn(() => undefined),
isThemeParamsDark: vi.fn(),
setMiniAppBackgroundColor: { isAvailable: vi.fn(() => false) },
setMiniAppHeaderColor: { isAvailable: vi.fn(() => false) },
setMiniAppBottomBarColor: { isAvailable: vi.fn(() => false) },
}));
describe("getFallbackScheme", () => {
const originalMatchMedia = window.matchMedia;
const originalGetComputedStyle = window.getComputedStyle;
afterEach(() => {
window.matchMedia = originalMatchMedia;
window.getComputedStyle = originalGetComputedStyle;
document.documentElement.removeAttribute("data-theme");
vi.clearAllMocks();
});
it("returns dark when prefers-color-scheme is dark", () => {
window.matchMedia = vi.fn((query: string) => ({
matches: query === "(prefers-color-scheme: dark)",
media: query,
addEventListener: vi.fn(),
removeEventListener: vi.fn(),
addListener: vi.fn(),
removeListener: vi.fn(),
dispatchEvent: vi.fn(),
onchange: null,
})) as unknown as typeof window.matchMedia;
expect(getFallbackScheme()).toBe("dark");
});
it("returns light when prefers-color-scheme is light", () => {
window.matchMedia = vi.fn((query: string) => ({
matches: query === "(prefers-color-scheme: light)",
media: query,
addEventListener: vi.fn(),
removeEventListener: vi.fn(),
addListener: vi.fn(),
removeListener: vi.fn(),
dispatchEvent: vi.fn(),
onchange: null,
})) as unknown as typeof window.matchMedia;
expect(getFallbackScheme()).toBe("light");
});
it("uses --tg-color-scheme when set on document", () => {
window.getComputedStyle = vi.fn(() =>
Object.assign(
{},
{
getPropertyValue: (prop: string) =>
prop === "--tg-color-scheme" ? " light " : "",
}
)
) as unknown as typeof window.getComputedStyle;
expect(getFallbackScheme()).toBe("light");
});
it("uses --tg-color-scheme dark when set", () => {
window.getComputedStyle = vi.fn(() =>
Object.assign(
{},
{
getPropertyValue: (prop: string) =>
prop === "--tg-color-scheme" ? "dark" : "",
}
)
) as unknown as typeof window.getComputedStyle;
expect(getFallbackScheme()).toBe("dark");
});
});
describe("applyTheme", () => {
afterEach(() => {
document.documentElement.removeAttribute("data-theme");
vi.clearAllMocks();
});
it("sets data-theme to given scheme", () => {
applyTheme("light");
expect(document.documentElement.getAttribute("data-theme")).toBe("light");
applyTheme("dark");
expect(document.documentElement.getAttribute("data-theme")).toBe("dark");
});
it("resolves scheme via getFallbackScheme when no argument", () => {
window.matchMedia = vi.fn((query: string) => ({
matches: query === "(prefers-color-scheme: dark)",
media: query,
addEventListener: vi.fn(),
removeEventListener: vi.fn(),
addListener: vi.fn(),
removeListener: vi.fn(),
dispatchEvent: vi.fn(),
onchange: null,
})) as unknown as typeof window.matchMedia;
applyTheme();
expect(document.documentElement.getAttribute("data-theme")).toBe("dark");
});
});
describe("useTelegramTheme", () => {
const originalMatchMedia = window.matchMedia;
const originalGetComputedStyle = window.getComputedStyle;
afterEach(() => {
window.matchMedia = originalMatchMedia;
window.getComputedStyle = originalGetComputedStyle;
document.documentElement.removeAttribute("data-theme");
vi.clearAllMocks();
});
it("sets data-theme to dark when useSignal returns true", async () => {
const { useSignal } = await import("@telegram-apps/sdk-react");
vi.mocked(useSignal).mockReturnValue(true);
renderHook(() => useTelegramTheme());
expect(document.documentElement.getAttribute("data-theme")).toBe("dark");
});
it("sets data-theme to light when useSignal returns false", async () => {
const { useSignal } = await import("@telegram-apps/sdk-react");
vi.mocked(useSignal).mockReturnValue(false);
renderHook(() => useTelegramTheme());
expect(document.documentElement.getAttribute("data-theme")).toBe("light");
});
});