Files
kandev/apps/web/components/settings/notifications-settings.test.tsx
T
João Salavisa e4c4efec18 feat(i18n): localize Settings > General > Notifications
Settings > General > Notifications held all of its copy as literals, so the page
stayed English under a locale switch. Every string now resolves through t() /
<Trans> at render, and the page is on the i18nGuardFiles allowlist so it cannot
drift back.

Event titles, sound preset names and the permission button label resolve from
maps of catalog keys rather than module-scope t(), so they follow a locale
switch. The Apprise install notice is a single <Trans> message so the link stays
inside the sentence. SCREENS in the pseudo-locale oracle gains a per-screen
allow list for text the frontend must not translate (backend-owned provider
names).
2026-08-02 01:49:44 +02:00

71 lines
2.5 KiB
TypeScript

import { cleanup, render } from "@testing-library/react";
import { afterEach, describe, expect, it, vi } from "vitest";
import type { NotificationProvider } from "@/lib/types/http";
import { NotificationsSettings } from "./notifications-settings";
import { SettingsSaveProvider } from "./settings-save-provider";
const mocks = vi.hoisted(() => ({
createNotificationProvider: vi.fn(),
deleteNotificationProvider: vi.fn(),
testNotificationProvider: vi.fn(),
updateNotificationProvider: vi.fn(),
setNotificationProviders: vi.fn(),
}));
vi.mock("@/lib/api", () => ({
createNotificationProvider: mocks.createNotificationProvider,
deleteNotificationProvider: mocks.deleteNotificationProvider,
testNotificationProvider: mocks.testNotificationProvider,
updateNotificationProvider: mocks.updateNotificationProvider,
}));
// Identities must be stable: the hydration effect in `useNotificationsState`
// compares them by reference, so a fresh array per render re-hydrates forever.
const PROVIDERS: NotificationProvider[] = [];
const EVENTS = ["session.turn_finished"];
vi.mock("@/hooks/domains/settings/use-notification-providers", () => ({
useNotificationProviders: () => ({
providers: PROVIDERS,
events: EVENTS,
appriseAvailable: false,
loaded: true,
}),
}));
vi.mock("@/components/state-provider", () => ({
useAppStore: (selector: (state: Record<string, unknown>) => unknown) =>
selector({ setNotificationProviders: mocks.setNotificationProviders }),
}));
vi.mock("@/lib/desktop/native-notification-client", () => ({
nativeNotifications: {
isAvailable: () => false,
permission: { get: vi.fn(), request: vi.fn() },
},
}));
afterEach(cleanup);
describe("NotificationsSettings", () => {
it("renders the Apprise install notice as one sentence around its link", () => {
// <Trans> addresses the anchor by child index, and a drifted index renders
// duplicated fragments with an empty tag rather than failing (docs/i18n.md).
const { container } = render(
<SettingsSaveProvider>
<NotificationsSettings />
</SettingsSaveProvider>,
);
const anchor = container.querySelector("a");
expect(anchor?.textContent).toBe("View installation instructions");
expect(anchor?.getAttribute("href")).toBe(
"https://github.com/caronc/apprise?tab=readme-ov-file#installation",
);
expect(anchor?.parentElement?.textContent).toBe(
"Apprise is not installed yet. You can add it later to enable remote notifications. " +
"View installation instructions.",
);
});
});