- Add logo click handler to navigate to current week view from any view (month, day, or week) - Update MainTitle component to accept calendarRef and view change callbacks - Implement handleLogoClick that changes view to week and navigates to current week - Add comprehensive test cases for logo click behavior from all view types Co-authored-by: Lê Nhân Phụng <lenhanphung@Phung-Mac-M4.local>
This commit is contained in:
@@ -760,3 +760,219 @@ describe("Menubar logout flow", () => {
|
||||
expect(sessionStorage.length).toBe(0);
|
||||
});
|
||||
});
|
||||
|
||||
describe("Logo click navigation to current week", () => {
|
||||
const preloadedState = {
|
||||
user: {
|
||||
userData: {
|
||||
sub: "test",
|
||||
email: "test@test.com",
|
||||
family_name: "Doe",
|
||||
name: "John",
|
||||
sid: "mockSid",
|
||||
openpaasId: "667037022b752d0026472254",
|
||||
},
|
||||
},
|
||||
settings: {
|
||||
view: "calendar",
|
||||
language: "en",
|
||||
},
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
(window as any).appList = [];
|
||||
});
|
||||
|
||||
it("navigates to week view and current week when clicking logo from month view", async () => {
|
||||
const mockChangeView = jest.fn();
|
||||
const mockToday = jest.fn();
|
||||
const mockGetDate = jest.fn(() => new Date());
|
||||
const mockCalendarApi = {
|
||||
changeView: mockChangeView,
|
||||
today: mockToday,
|
||||
getDate: mockGetDate,
|
||||
};
|
||||
const mockCalendarRef = { current: mockCalendarApi as any };
|
||||
const mockOnRefresh = jest.fn();
|
||||
const mockOnViewChange = jest.fn();
|
||||
const mockOnDateChange = jest.fn();
|
||||
const mockCurrentDate = new Date("2024-04-15");
|
||||
|
||||
const { store } = renderWithProviders(
|
||||
<Menubar
|
||||
calendarRef={mockCalendarRef}
|
||||
onRefresh={mockOnRefresh}
|
||||
currentDate={mockCurrentDate}
|
||||
currentView="dayGridMonth"
|
||||
onViewChange={mockOnViewChange}
|
||||
onDateChange={mockOnDateChange}
|
||||
/>,
|
||||
preloadedState
|
||||
);
|
||||
|
||||
const logoElement = screen.getByAltText("menubar.logoAlt");
|
||||
await act(async () => {
|
||||
fireEvent.click(logoElement);
|
||||
});
|
||||
|
||||
await waitFor(() => {
|
||||
expect(store.getState().settings.view).toBe("calendar");
|
||||
});
|
||||
|
||||
expect(mockChangeView).toHaveBeenCalledWith("timeGridWeek");
|
||||
expect(mockToday).toHaveBeenCalled();
|
||||
expect(mockOnViewChange).toHaveBeenCalledWith("timeGridWeek");
|
||||
expect(mockOnDateChange).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("navigates to week view and current week when clicking logo from day view", async () => {
|
||||
const mockChangeView = jest.fn();
|
||||
const mockToday = jest.fn();
|
||||
const mockGetDate = jest.fn(() => new Date());
|
||||
const mockCalendarApi = {
|
||||
changeView: mockChangeView,
|
||||
today: mockToday,
|
||||
getDate: mockGetDate,
|
||||
};
|
||||
const mockCalendarRef = { current: mockCalendarApi as any };
|
||||
const mockOnRefresh = jest.fn();
|
||||
const mockOnViewChange = jest.fn();
|
||||
const mockOnDateChange = jest.fn();
|
||||
const mockCurrentDate = new Date("2024-04-15");
|
||||
|
||||
const { store } = renderWithProviders(
|
||||
<Menubar
|
||||
calendarRef={mockCalendarRef}
|
||||
onRefresh={mockOnRefresh}
|
||||
currentDate={mockCurrentDate}
|
||||
currentView="timeGridDay"
|
||||
onViewChange={mockOnViewChange}
|
||||
onDateChange={mockOnDateChange}
|
||||
/>,
|
||||
preloadedState
|
||||
);
|
||||
|
||||
const logoElement = screen.getByAltText("menubar.logoAlt");
|
||||
await act(async () => {
|
||||
fireEvent.click(logoElement);
|
||||
});
|
||||
|
||||
await waitFor(() => {
|
||||
expect(store.getState().settings.view).toBe("calendar");
|
||||
});
|
||||
|
||||
expect(mockChangeView).toHaveBeenCalledWith("timeGridWeek");
|
||||
expect(mockToday).toHaveBeenCalled();
|
||||
expect(mockOnViewChange).toHaveBeenCalledWith("timeGridWeek");
|
||||
expect(mockOnDateChange).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("navigates to current week when clicking logo from week view (not current week)", async () => {
|
||||
const mockChangeView = jest.fn();
|
||||
const mockToday = jest.fn();
|
||||
const mockGetDate = jest.fn(() => new Date());
|
||||
const mockCalendarApi = {
|
||||
changeView: mockChangeView,
|
||||
today: mockToday,
|
||||
getDate: mockGetDate,
|
||||
};
|
||||
const mockCalendarRef = { current: mockCalendarApi as any };
|
||||
const mockOnRefresh = jest.fn();
|
||||
const mockOnViewChange = jest.fn();
|
||||
const mockOnDateChange = jest.fn();
|
||||
const mockCurrentDate = new Date("2024-04-15");
|
||||
|
||||
const { store } = renderWithProviders(
|
||||
<Menubar
|
||||
calendarRef={mockCalendarRef}
|
||||
onRefresh={mockOnRefresh}
|
||||
currentDate={mockCurrentDate}
|
||||
currentView="timeGridWeek"
|
||||
onViewChange={mockOnViewChange}
|
||||
onDateChange={mockOnDateChange}
|
||||
/>,
|
||||
preloadedState
|
||||
);
|
||||
|
||||
const logoElement = screen.getByAltText("menubar.logoAlt");
|
||||
await act(async () => {
|
||||
fireEvent.click(logoElement);
|
||||
});
|
||||
|
||||
await waitFor(() => {
|
||||
expect(store.getState().settings.view).toBe("calendar");
|
||||
});
|
||||
|
||||
expect(mockChangeView).not.toHaveBeenCalled();
|
||||
expect(mockToday).toHaveBeenCalled();
|
||||
expect(mockOnDateChange).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("does not crash when calendarRef.current is null", async () => {
|
||||
const mockCalendarRef = { current: null };
|
||||
const mockOnRefresh = jest.fn();
|
||||
const mockOnViewChange = jest.fn();
|
||||
const mockOnDateChange = jest.fn();
|
||||
const mockCurrentDate = new Date("2024-04-15");
|
||||
|
||||
const { store } = renderWithProviders(
|
||||
<Menubar
|
||||
calendarRef={mockCalendarRef}
|
||||
onRefresh={mockOnRefresh}
|
||||
currentDate={mockCurrentDate}
|
||||
currentView="dayGridMonth"
|
||||
onViewChange={mockOnViewChange}
|
||||
onDateChange={mockOnDateChange}
|
||||
/>,
|
||||
preloadedState
|
||||
);
|
||||
|
||||
const logoElement = screen.getByAltText("menubar.logoAlt");
|
||||
await act(async () => {
|
||||
fireEvent.click(logoElement);
|
||||
});
|
||||
|
||||
await waitFor(() => {
|
||||
expect(store.getState().settings.view).toBe("calendar");
|
||||
});
|
||||
|
||||
expect(mockOnViewChange).not.toHaveBeenCalled();
|
||||
expect(mockOnDateChange).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("handles missing onViewChange and onDateChange callbacks", async () => {
|
||||
const mockChangeView = jest.fn();
|
||||
const mockToday = jest.fn();
|
||||
const mockGetDate = jest.fn(() => new Date());
|
||||
const mockCalendarApi = {
|
||||
changeView: mockChangeView,
|
||||
today: mockToday,
|
||||
getDate: mockGetDate,
|
||||
};
|
||||
const mockCalendarRef = { current: mockCalendarApi as any };
|
||||
const mockOnRefresh = jest.fn();
|
||||
const mockCurrentDate = new Date("2024-04-15");
|
||||
|
||||
const { store } = renderWithProviders(
|
||||
<Menubar
|
||||
calendarRef={mockCalendarRef}
|
||||
onRefresh={mockOnRefresh}
|
||||
currentDate={mockCurrentDate}
|
||||
currentView="dayGridMonth"
|
||||
/>,
|
||||
preloadedState
|
||||
);
|
||||
|
||||
const logoElement = screen.getByAltText("menubar.logoAlt");
|
||||
await act(async () => {
|
||||
fireEvent.click(logoElement);
|
||||
});
|
||||
|
||||
await waitFor(() => {
|
||||
expect(store.getState().settings.view).toBe("calendar");
|
||||
});
|
||||
|
||||
expect(mockChangeView).toHaveBeenCalledWith("timeGridWeek");
|
||||
expect(mockToday).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -160,7 +160,12 @@ export function Menubar({
|
||||
<header className="menubar">
|
||||
<div className="left-menu">
|
||||
<div className="menu-items">
|
||||
<MainTitle />
|
||||
<MainTitle
|
||||
calendarRef={calendarRef}
|
||||
currentView={currentView}
|
||||
onViewChange={onViewChange}
|
||||
onDateChange={onDateChange}
|
||||
/>
|
||||
</div>
|
||||
<div className="menu-items">
|
||||
<div className="navigation-controls">
|
||||
@@ -365,16 +370,49 @@ export function Menubar({
|
||||
);
|
||||
}
|
||||
|
||||
export function MainTitle() {
|
||||
export type MainTitleProps = {
|
||||
calendarRef: React.RefObject<CalendarApi | null>;
|
||||
currentView: string;
|
||||
onViewChange?: (view: string) => void;
|
||||
onDateChange?: (date: Date) => void;
|
||||
};
|
||||
|
||||
export function MainTitle({
|
||||
calendarRef,
|
||||
currentView,
|
||||
onViewChange,
|
||||
onDateChange,
|
||||
}: MainTitleProps) {
|
||||
const { t } = useI18n();
|
||||
const dispatch = useAppDispatch();
|
||||
|
||||
const handleLogoClick = async () => {
|
||||
if (!calendarRef.current) return;
|
||||
|
||||
await dispatch(setView("calendar"));
|
||||
|
||||
if (currentView !== "timeGridWeek") {
|
||||
calendarRef.current.changeView("timeGridWeek");
|
||||
if (onViewChange) {
|
||||
onViewChange("timeGridWeek");
|
||||
}
|
||||
}
|
||||
|
||||
calendarRef.current.today();
|
||||
|
||||
if (onDateChange) {
|
||||
const newDate = calendarRef.current.getDate();
|
||||
onDateChange(newDate);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="menubar-item tc-home">
|
||||
<img
|
||||
className="logo"
|
||||
src={logo}
|
||||
alt={t("menubar.logoAlt")}
|
||||
onClick={() => dispatch(setView("calendar"))}
|
||||
onClick={handleLogoClick}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user