1a85afc57d
* UI: #334 add config page language setting * temporary remove logout button * Unify fullscreen view class for dialog expanded and settings view - Replace dialog-expanded and settings-view with single fullscreen-view class - Update ResponsiveDialog to use fullscreen-view class - Update CalendarLayout to use fullscreen-view class for settings view - Consolidate CSS rules in Menubar.styl to use fullscreen-view - Update test cases to use new class name --------- Co-authored-by: Lê Nhân Phụng <lenhanphung@Phung-Mac-M4.local>
159 lines
4.9 KiB
TypeScript
159 lines
4.9 KiB
TypeScript
import { fireEvent, screen, waitFor } from "@testing-library/react";
|
|
import "@testing-library/jest-dom";
|
|
import SettingsPage from "../../../src/features/Settings/SettingsPage";
|
|
import { renderWithProviders } from "../../utils/Renderwithproviders";
|
|
|
|
describe("SettingsPage", () => {
|
|
const preloadedState = {
|
|
user: {
|
|
userData: {
|
|
sub: "test",
|
|
email: "test@test.com",
|
|
family_name: "Doe",
|
|
name: "John",
|
|
sid: "mockSid",
|
|
openpaasId: "667037022b752d0026472254",
|
|
},
|
|
},
|
|
settings: {
|
|
language: "en",
|
|
view: "settings",
|
|
},
|
|
};
|
|
|
|
it("renders settings page with sidebar and content layout", () => {
|
|
renderWithProviders(<SettingsPage />, preloadedState);
|
|
|
|
expect(screen.getByRole("main")).toHaveClass(
|
|
"main-layout",
|
|
"settings-layout"
|
|
);
|
|
});
|
|
|
|
it("displays sidebar navigation with Settings and Notifications items", () => {
|
|
const { container } = renderWithProviders(<SettingsPage />, preloadedState);
|
|
|
|
// Check sidebar navigation items
|
|
const sidebar = container.querySelector(".settings-sidebar");
|
|
expect(sidebar).toBeInTheDocument();
|
|
expect(screen.getAllByText(/settings.title/i).length).toBeGreaterThan(0);
|
|
expect(screen.getByText(/settings.notifications/i)).toBeInTheDocument();
|
|
});
|
|
|
|
it("highlights active navigation item", () => {
|
|
const { container } = renderWithProviders(<SettingsPage />, preloadedState);
|
|
|
|
const settingsNavItem = container.querySelector(
|
|
".settings-nav-item.active"
|
|
);
|
|
expect(settingsNavItem).toBeInTheDocument();
|
|
});
|
|
|
|
it("navigates back to calendar view when clicking back button", async () => {
|
|
const { store } = renderWithProviders(<SettingsPage />, preloadedState);
|
|
|
|
const backButton = screen.getByLabelText("settings.back");
|
|
fireEvent.click(backButton);
|
|
|
|
await waitFor(() => {
|
|
const state = store.getState();
|
|
expect(state.settings.view).toBe("calendar");
|
|
});
|
|
});
|
|
|
|
it("switches between Settings and Notifications tabs", () => {
|
|
renderWithProviders(<SettingsPage />, preloadedState);
|
|
|
|
const notificationsTab = screen.getByRole("tab", {
|
|
name: /settings.notifications/i,
|
|
});
|
|
fireEvent.click(notificationsTab);
|
|
|
|
expect(
|
|
screen.getByText(/settings.notifications.empty/i)
|
|
).toBeInTheDocument();
|
|
});
|
|
|
|
it("displays language select in Settings tab", () => {
|
|
renderWithProviders(<SettingsPage />, preloadedState);
|
|
|
|
expect(
|
|
screen.getByLabelText("settings.languageSelector")
|
|
).toBeInTheDocument();
|
|
});
|
|
|
|
it("displays all available language options", async () => {
|
|
renderWithProviders(<SettingsPage />, preloadedState);
|
|
|
|
const languageSelect = screen.getByLabelText("settings.languageSelector");
|
|
|
|
// Click on the select to open dropdown
|
|
fireEvent.mouseDown(languageSelect);
|
|
|
|
// Wait for menu to appear - MUI Select uses Menu internally
|
|
// Note: In test environment, Select may not open menu, so we verify Select exists and has correct value
|
|
expect(languageSelect).toBeInTheDocument();
|
|
expect(languageSelect).toHaveTextContent("English");
|
|
});
|
|
|
|
it("dispatches setLanguage action when language is changed", async () => {
|
|
const { store } = renderWithProviders(<SettingsPage />, preloadedState);
|
|
|
|
const languageSelect = screen.getByLabelText("settings.languageSelector");
|
|
|
|
// MUI Select uses a native input element - find and change it
|
|
const nativeInput = languageSelect.querySelector(
|
|
'input[aria-hidden="true"]'
|
|
) as HTMLInputElement;
|
|
expect(nativeInput).toBeInTheDocument();
|
|
|
|
// Simulate change event on the native input
|
|
Object.defineProperty(nativeInput, "value", {
|
|
writable: true,
|
|
value: "fr",
|
|
});
|
|
fireEvent.change(nativeInput, { target: { value: "fr" } });
|
|
|
|
await waitFor(() => {
|
|
const state = store.getState();
|
|
expect(state.settings.language).toBe("fr");
|
|
});
|
|
});
|
|
|
|
it("saves language change to localStorage", async () => {
|
|
const { store } = renderWithProviders(<SettingsPage />, preloadedState);
|
|
|
|
const languageSelect = screen.getByLabelText("settings.languageSelector");
|
|
|
|
// MUI Select uses a native input element - find and change it
|
|
const nativeInput = languageSelect.querySelector(
|
|
'input[aria-hidden="true"]'
|
|
) as HTMLInputElement;
|
|
expect(nativeInput).toBeInTheDocument();
|
|
|
|
// Simulate change event on the native input
|
|
Object.defineProperty(nativeInput, "value", {
|
|
writable: true,
|
|
value: "fr",
|
|
});
|
|
fireEvent.change(nativeInput, { target: { value: "fr" } });
|
|
|
|
await waitFor(() => {
|
|
expect(localStorage.getItem("lang")).toBe("fr");
|
|
});
|
|
});
|
|
|
|
it("shows empty state in Notifications tab", () => {
|
|
renderWithProviders(<SettingsPage />, preloadedState);
|
|
|
|
const notificationsTab = screen.getByRole("tab", {
|
|
name: /settings.notifications/i,
|
|
});
|
|
fireEvent.click(notificationsTab);
|
|
|
|
expect(
|
|
screen.getByText("settings.notifications.empty")
|
|
).toBeInTheDocument();
|
|
});
|
|
});
|