Skip to content

Saving group settings on Manage Group ends the active session #1691

Open

Description

@joshunrau

Saving the Manage Group page ends the clinician's active session. After a successful save, the page stores the returned group with changeGroup(updatedGroup). changeGroup is the group-switch action, and it always sets currentSession: null, because a session belongs to the group it was started in. Here the group is the same one; only its settings changed. A clinician who notices mid-assessment that an instrument is not enabled for the group, enables it on /group/manage and saves, loses the session for the subject in front of them. "Accessible Instruments" and "Remote Assignment" go disabled, and they have to start a new session, re-identifying the subject and creating a second session record.

Where

apps/web/src/store/slices/auth.slice.ts:27-29:

changeGroup: (group) => {
  set({ currentGroup: group, currentSession: null, preferredGroupId: group.id });
},

called with the group that is already current from apps/web/src/routes/_app/group/manage.tsx:975-978:

onSubmit: async (data) => {
  const updatedGroup = await updateGroupMutation.mutateAsync(data);
  changeGroup(updatedGroup);
},

Reproduce

  1. Sign in as a group manager and start a session for any subject.
  2. Open Manage Group from the sidebar, tick an additional instrument (or change any setting), and save.
  3. Look at the sidebar.

Actual: the session is gone. "Start Session" is enabled again, and "Accessible Instruments", "Remote Assignment" and "View Current Subject" are disabled.
Expected: the session survives, and the newly enabled instrument can be administered to the same subject straight away.

Tests

  • apps/web/src/store/slices/__tests__/auth.slice.test.ts: it('should keep the current session when the current group is replaced by an updated copy of itself, so saving group settings does not end an assessment'), plus it('should still end the session when switching to a different group').
  • testing/src/specs/group-manage.spec.ts: start a session, save a settings change on Manage Group, and assert the Accessible Instruments nav item is still enabled.

Suggested fix

Clear currentSession in changeGroup only when group.id !== get().currentGroup?.id. Alternatively, add a separate updateCurrentGroup(group) action that replaces the group object without touching the session, and call that from manage.tsx.

Activity

  1. added
    BugType: existing behavior is wrong
    Difficulty: LowIsolated change, about 2 hours or less
    Area: Webapps/web (clinician-facing React SPA)
    Good First IssueWell-scoped, low-risk and self-contained; a good entry point for a new contributor
    on Oct 7, 2026
  2. joshunrau commented on Oct 26, 2026

    @joshunrau
    CollaboratorAuthor

    Still reproduces on main (d86740e). No commit has touched the cited files since this was filed. #1660 touches auth.slice.ts, but only its CASL types.

    Take the second suggested fix

    Add updateCurrentGroup and keep changeGroup as the switch action. Making changeGroup conditional leaves a second bug in place. onSubmit calls changeGroup whenever the PATCH resolves. Say a manager switches from group A to group B in the group switcher while a save for A is in flight. When the response lands, it switches them back to A. The key at manage.tsx:972 remounts only the form, not RouteComponent, and the mutateAsync promise resolves either way. A conditional changeGroup sees a different id there and switches anyway.

    updateCurrentGroup(group) replaces currentGroup only when group.id matches the current group's id, and leaves currentSession and preferredGroupId alone. Declare it in AuthSlice (apps/web/src/store/types.ts:12-19). With #1719 it also replaces the matching entry in currentUser.groups.

    Call it from useUpdateGroupMutation's onSuccess, as the plan on #1719 does, rather than from manage.tsx. GroupEmailTemplates.tsx:123-135 saves through the same hook and never updates the store. onSubmit (manage.tsx:975-978) then only awaits mutateAsync.

    Tests

    • auth.slice.test.ts: the second test proposed above already exists at :111-115. Add the keep-the-session test. Also add one where a saved group that is not the current one leaves currentGroup unchanged.
    • manage.test.tsx:613-618 asserts that changeGroup receives the saved group. That assertion moves to useUpdateGroupMutation.test.ts, and the changeGroup mock at manage.test.tsx:16 and :41-42 goes. Two suites run the real hook, so their fake stores need the new action: useUpdateGroupMutation.test.ts:12 and GroupEmailTemplates.test.tsx:19.
    • e2e, a new test in group-manage.spec.ts. currentSession is not in PERSISTED_KEYS (apps/web/src/store/index.ts:19-24), so any page.goto after the session starts ends it. That rules out page.goto('/group/manage') as at :111, and getPageModel too. getPageModel also signs in again as the default role (testing/src/support/fixtures.ts:148-151). Sign in with isolatedGroupManager(), because the test changes its group. Open Start Session with new StartSessionPage(page) and goto, as start-session.spec.ts:270-271 does, and start the session as :294-298 does. Reach Manage Group through the sidebar (group-manage.spec.ts:134-135) and save a change. Navigate once more, then assert that nav-button-/instruments/accessible-instruments is enabled. The extra navigation is needed because the nav's disabled state settles in an effect (start-session.spec.ts:300-303).

    Land this in one PR with #1719 and #1642, one commit per issue. All three change useUpdateGroupMutation and its tests.

    Triage note written with Claude Code. Code references point at main @ d86740e.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Area: Webapps/web (clinician-facing React SPA)BugType: existing behavior is wrongDifficulty: LowIsolated change, about 2 hours or lessGood First IssueWell-scoped, low-risk and self-contained; a good entry point for a new contributorPriority: MediumReal value; schedule normally

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions