refactor(sync): replace the session-status setState monkeypatch with an owned API
The global session-status store patched its own setState to derive active membership for callers replacing statusById — a boundary that silently trusted any caller passing both fields to keep them consistent. replaceGlobalSessionStatusById is now the one sanctioned way to swap the map from outside the event reducers; the runtime-switch reset and the tests that replaced the map directly go through it, and the patch is gone. Follow-up to #3126 review.
This commit is contained in:
@@ -4,7 +4,7 @@ import type { Event } from '@opencode-ai/sdk/v2/client';
|
||||
import React, { act } from 'react';
|
||||
import { createRoot, type Root } from 'react-dom/client';
|
||||
import { deriveRecentSessions } from '../recent/activitySections';
|
||||
import { applyGlobalSessionStatusEvent, useGlobalSessionStatusStore } from '@/sync/global-session-status';
|
||||
import { applyGlobalSessionStatusEvent, useGlobalSessionStatusStore , replaceGlobalSessionStatusById} from '@/sync/global-session-status';
|
||||
import {
|
||||
buildSidebarSessionProjection,
|
||||
getDescendantIds,
|
||||
@@ -270,7 +270,7 @@ describe('useRecentSessionCollection', () => {
|
||||
};
|
||||
|
||||
try {
|
||||
useGlobalSessionStatusStore.setState({ statusById: new Map() });
|
||||
replaceGlobalSessionStatusById(new Map());
|
||||
await act(async () => root.render(React.createElement(Harness)));
|
||||
expect(renderedIds).toEqual([]);
|
||||
|
||||
@@ -296,7 +296,7 @@ describe('useRecentSessionCollection', () => {
|
||||
expect(timeReadCount).toBe(activeDeriveOperationCount);
|
||||
} finally {
|
||||
await act(async () => root.unmount());
|
||||
useGlobalSessionStatusStore.setState({ statusById: new Map() });
|
||||
replaceGlobalSessionStatusById(new Map());
|
||||
dom.restore();
|
||||
}
|
||||
});
|
||||
|
||||
+5
-9
@@ -2,7 +2,7 @@ import { describe, expect, test } from 'bun:test';
|
||||
import React, { act } from 'react';
|
||||
import { createRoot } from 'react-dom/client';
|
||||
import type { Session } from '@opencode-ai/sdk/v2';
|
||||
import { useGlobalSessionStatusStore } from '@/sync/global-session-status';
|
||||
import { useGlobalSessionStatusStore , replaceGlobalSessionStatusById} from '@/sync/global-session-status';
|
||||
import { useNotificationStore } from '@/sync/notification-store';
|
||||
import { useCollapsedSessionActivityState } from './collapsedActivityState';
|
||||
import type { SessionNode } from '../types';
|
||||
@@ -15,7 +15,7 @@ describe('collapsed activity scalar selector', () => {
|
||||
test('does not rerender for unrelated updates and rerenders for relevant scalar changes', async () => {
|
||||
const dom = installHookTestDom();
|
||||
const root = createRoot(dom.container);
|
||||
useGlobalSessionStatusStore.setState({ statusById: new Map() });
|
||||
replaceGlobalSessionStatusById(new Map());
|
||||
useNotificationStore.setState({
|
||||
list: [],
|
||||
index: { session: { unseenCount: {}, unseenHasError: {} }, project: { unseenCount: {}, unseenHasError: {} } },
|
||||
@@ -30,9 +30,7 @@ describe('collapsed activity scalar selector', () => {
|
||||
try {
|
||||
await act(async () => root.render(React.createElement(Harness)));
|
||||
const initialRenders = capture.renders;
|
||||
await act(async () => useGlobalSessionStatusStore.setState({
|
||||
statusById: new Map([['unrelated', { status: { type: 'busy' }, directory: '/other' }]]),
|
||||
}));
|
||||
await act(async () => replaceGlobalSessionStatusById(new Map([['unrelated', { status: { type: 'busy' }, directory: '/other' }]])));
|
||||
await act(async () => useNotificationStore.getState().append({
|
||||
type: 'turn-complete', session: 'unrelated', time: Date.now(), viewed: false,
|
||||
}));
|
||||
@@ -43,14 +41,12 @@ describe('collapsed activity scalar selector', () => {
|
||||
}));
|
||||
expect(capture.state).toBe('unread');
|
||||
const unreadRenders = capture.renders;
|
||||
await act(async () => useGlobalSessionStatusStore.setState({
|
||||
statusById: new Map([['relevant', { status: { type: 'busy' }, directory: '/workspace' }]]),
|
||||
}));
|
||||
await act(async () => replaceGlobalSessionStatusById(new Map([['relevant', { status: { type: 'busy' }, directory: '/workspace' }]])));
|
||||
expect(capture.state).toBe('active');
|
||||
expect(capture.renders).toBe(unreadRenders + 1);
|
||||
} finally {
|
||||
await act(async () => root.unmount());
|
||||
useGlobalSessionStatusStore.setState({ statusById: new Map() });
|
||||
replaceGlobalSessionStatusById(new Map());
|
||||
useNotificationStore.setState({
|
||||
list: [],
|
||||
index: { session: { unseenCount: {}, unseenHasError: {} }, project: { unseenCount: {}, unseenHasError: {} } },
|
||||
|
||||
Reference in New Issue
Block a user