diff --git a/src/components/ProfileMenu/ProfileMenu.test.tsx b/src/components/ProfileMenu/ProfileMenu.test.tsx
index 6b4937c27f..e1a6c72aac 100644
--- a/src/components/ProfileMenu/ProfileMenu.test.tsx
+++ b/src/components/ProfileMenu/ProfileMenu.test.tsx
@@ -7,11 +7,14 @@ import { Util } from '../../utility/util';
import { useAppSelector } from '../../redux/hooks';
import { MemoryRouter } from 'react-router-dom';
import {
+ CURRENT_MODE,
EVENTS,
+ MODES,
PAGES,
STICKER_BOOK_NOTIFICATION_DOT_ENABLED,
ENABLE_STICKER_BOOK,
} from '../../common/constants';
+import { schoolUtil } from '../../utility/schoolUtil';
// --- Mocks ---
@@ -36,15 +39,22 @@ jest.mock('../../i18n', () => ({
}));
const mockPush = jest.fn();
+const mockReplace = jest.fn();
jest.mock('react-router', () => ({
...jest.requireActual('react-router'),
useHistory: () => ({
push: mockPush,
- replace: jest.fn(),
+ replace: mockReplace,
location: { pathname: '/' },
}),
}));
+jest.mock('../../utility/schoolUtil', () => ({
+ schoolUtil: {
+ setCurrentClass: jest.fn(),
+ },
+}));
+
// Mock useGbContext
jest.mock('../../growthbook/Growthbook', () => ({
useGbContext: () => ({ setGbUpdated: jest.fn() }),
@@ -60,10 +70,12 @@ const mockApi = {
};
const mockStudent = { id: 'student-123', name: 'Test Student' };
+const mockSetCurrentClass = schoolUtil.setCurrentClass as jest.Mock;
describe('ProfileMenu Notification Logic', () => {
beforeEach(() => {
jest.clearAllMocks();
+ localStorage.clear();
mockApi.getUserStickerBook.mockReset();
mockApi.getUserStickerBook.mockResolvedValue([]);
mockApi.markStciekercolledasTrue.mockReset();
@@ -191,4 +203,30 @@ describe('ProfileMenu Notification Logic', () => {
expect.any(Object),
);
});
+
+ test('keeps school-mode switch profile on SelectMode selection flow', async () => {
+ localStorage.setItem(CURRENT_MODE, MODES.TEACHER_SCHOOL);
+
+ render(
+
+
+ ,
+ );
+
+ await waitFor(() => expect(mockApi.getUserStickerBook).toHaveBeenCalled());
+
+ const switchProfileItem = screen
+ .getByText(/Switch Profile/i)
+ .closest('.profile-menu-item');
+ fireEvent.click(switchProfileItem!);
+
+ await waitFor(() => {
+ expect(Util.setCurrentStudent).toHaveBeenCalledWith(null);
+ });
+ expect(mockSetCurrentClass).not.toHaveBeenCalled();
+ expect(mockReplace).toHaveBeenCalledWith(PAGES.SELECT_MODE, {
+ from: '/',
+ fromSchoolModeSwitchProfile: true,
+ });
+ });
});
diff --git a/src/components/ProfileMenu/ProfileMenu.tsx b/src/components/ProfileMenu/ProfileMenu.tsx
index ee1add4a3a..c209da4a59 100644
--- a/src/components/ProfileMenu/ProfileMenu.tsx
+++ b/src/components/ProfileMenu/ProfileMenu.tsx
@@ -177,6 +177,7 @@ const ProfileMenu = ({ onClose }: ProfileMenuProps) => {
setGbUpdated(true);
history.replace(PAGES.SELECT_MODE, {
from: history.location.pathname,
+ fromSchoolModeSwitchProfile: true,
});
};
diff --git a/src/pages/SelectMode.test.tsx b/src/pages/SelectMode.test.tsx
index fbe5dd6ecc..f48b67d8c4 100644
--- a/src/pages/SelectMode.test.tsx
+++ b/src/pages/SelectMode.test.tsx
@@ -70,7 +70,12 @@ jest.mock('./assets/leftArrowIcon.svg', () => ({
}));
const mockHistoryReplace = jest.fn();
-let mockLocationState: { fromKidsAppLocationSchool?: boolean } | undefined;
+let mockLocationState:
+ | {
+ fromKidsAppLocationSchool?: boolean;
+ fromSchoolModeSwitchProfile?: boolean;
+ }
+ | undefined;
jest.mock('react-router', () => {
const actual = jest.requireActual('react-router');
return {
@@ -914,6 +919,41 @@ describe('SelectMode page', () => {
expect(mockHistoryReplace).not.toHaveBeenCalledWith(PAGES.DISPLAY_SCHOOLS);
});
+ it('keeps school-mode switch profile in school flow for teacher-role users', async () => {
+ const teacherSchool = { id: 'school-1', name: 'Teacher School' };
+ const classDoc = {
+ id: 'class-1',
+ name: 'Class 1',
+ school_id: teacherSchool.id,
+ };
+ mockLocationState = { fromSchoolModeSwitchProfile: true };
+ mockGetCurrMode.mockResolvedValue(MODES.TEACHER_SCHOOL);
+ mockAuthHandler.getCurrentUser.mockResolvedValue({
+ id: 'user-1',
+ name: 'Teacher User',
+ });
+ mockApiHandler.getSchoolsForUser.mockResolvedValue([
+ { school: teacherSchool, role: 'TEACHER' },
+ ]);
+ mockApiHandler.getSchoolsWithRoleAutouser.mockResolvedValue([]);
+ mockApiHandler.getClassesForSchool.mockResolvedValue([classDoc]);
+ mockApiHandler.getStudentsForClass.mockResolvedValue([
+ { id: 'student-1', name: 'Student 1' },
+ ]);
+
+ render();
+
+ await waitFor(() => {
+ expect(mockApiHandler.getClassesForSchool).toHaveBeenCalledWith(
+ teacherSchool.id,
+ 'user-1',
+ );
+ });
+ expect(mockSetCurrMode).not.toHaveBeenCalledWith(MODES.TEACHER);
+ expect(mockHistoryReplace).not.toHaveBeenCalledWith(PAGES.HOME_PAGE);
+ expect(mockHistoryReplace).not.toHaveBeenCalledWith(PAGES.DISPLAY_SCHOOLS);
+ });
+
it('uses the school picker when multiple teacher schools remain after stored school is removed', async () => {
const removedPrincipalSchool = {
id: 'school-removed',
diff --git a/src/pages/SelectMode.tsx b/src/pages/SelectMode.tsx
index d35d2f83af..6df066e11f 100644
--- a/src/pages/SelectMode.tsx
+++ b/src/pages/SelectMode.tsx
@@ -101,6 +101,7 @@ interface SchoolModeOption {
interface SelectModeLocationState {
fromKidsAppLocationSchool?: boolean;
+ fromSchoolModeSwitchProfile?: boolean;
}
const SUPPORTED_LANGUAGE_CODES = new Set(Object.values(LANG));
@@ -450,7 +451,8 @@ const SelectMode: FC = () => {
const shouldSuppressTeacherAutoEntry =
currentMode === MODES.TEACHER_SCHOOL &&
- location.state?.fromKidsAppLocationSchool === true;
+ (location.state?.fromKidsAppLocationSchool === true ||
+ location.state?.fromSchoolModeSwitchProfile === true);
const shouldAutoEnterTeacherApp =
teacherRoleEntries.length > 0 && !shouldSuppressTeacherAutoEntry;
const shouldUseEmptySchoolFallback = !shouldSuppressTeacherAutoEntry;