feat: migrate to Next.js for Mini App and enhance project structure
- Replaced the previous webapp with a new Mini App built using Next.js, improving performance and maintainability. - Updated the `.gitignore` to exclude Next.js build artifacts and node modules. - Revised documentation in `AGENTS.md`, `README.md`, and `architecture.md` to reflect the new Mini App structure and technology stack. - Enhanced Dockerfile to support the new build process for the Next.js application. - Updated CI workflow to build and test the Next.js application. - Added new configuration options for the Mini App, including `MINI_APP_SHORT_NAME` for improved deep linking. - Refactored frontend testing setup to accommodate the new structure and testing framework. - Removed legacy webapp files and dependencies to streamline the project.
This commit is contained in:
140
webapp-next/src/hooks/use-telegram-theme.test.ts
Normal file
140
webapp-next/src/hooks/use-telegram-theme.test.ts
Normal file
@@ -0,0 +1,140 @@
|
||||
/**
|
||||
* 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) },
|
||||
}));
|
||||
|
||||
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");
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user