fix(context): clear project loading on ssh reset
This commit is contained in:
parent
2fdbf301b4
commit
1b36d1daa6
2 changed files with 80 additions and 0 deletions
|
|
@ -85,7 +85,13 @@ export const createConnectionSlice: StateCreator<AppState, [], [], ConnectionSli
|
||||||
? {
|
? {
|
||||||
activeContextId: `ssh-${config.host}`,
|
activeContextId: `ssh-${config.host}`,
|
||||||
projects: [],
|
projects: [],
|
||||||
|
projectsLoading: false,
|
||||||
|
projectsInitialized: false,
|
||||||
|
projectsError: null,
|
||||||
repositoryGroups: [],
|
repositoryGroups: [],
|
||||||
|
repositoryGroupsLoading: false,
|
||||||
|
repositoryGroupsInitialized: false,
|
||||||
|
repositoryGroupsError: null,
|
||||||
openTabs: [],
|
openTabs: [],
|
||||||
activeTabId: null,
|
activeTabId: null,
|
||||||
selectedTabIds: [],
|
selectedTabIds: [],
|
||||||
|
|
@ -149,7 +155,13 @@ export const createConnectionSlice: StateCreator<AppState, [], [], ConnectionSli
|
||||||
activeContextId: 'local',
|
activeContextId: 'local',
|
||||||
// Clear all stale SSH data including tabs so dashboard shows fresh local data
|
// Clear all stale SSH data including tabs so dashboard shows fresh local data
|
||||||
projects: [],
|
projects: [],
|
||||||
|
projectsLoading: false,
|
||||||
|
projectsInitialized: false,
|
||||||
|
projectsError: null,
|
||||||
repositoryGroups: [],
|
repositoryGroups: [],
|
||||||
|
repositoryGroupsLoading: false,
|
||||||
|
repositoryGroupsInitialized: false,
|
||||||
|
repositoryGroupsError: null,
|
||||||
openTabs: [],
|
openTabs: [],
|
||||||
activeTabId: null,
|
activeTabId: null,
|
||||||
selectedTabIds: [],
|
selectedTabIds: [],
|
||||||
|
|
|
||||||
|
|
@ -121,6 +121,12 @@ function deferred<T>(): {
|
||||||
return { promise, resolve };
|
return { promise, resolve };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function flushMicrotasks(): Promise<void> {
|
||||||
|
await Promise.resolve();
|
||||||
|
await Promise.resolve();
|
||||||
|
await Promise.resolve();
|
||||||
|
}
|
||||||
|
|
||||||
describe('context slice team/task reset', () => {
|
describe('context slice team/task reset', () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
vi.clearAllMocks();
|
vi.clearAllMocks();
|
||||||
|
|
@ -374,6 +380,40 @@ describe('context slice team/task reset', () => {
|
||||||
expect(apiMock.teams.getAllTasks).toHaveBeenCalledTimes(1);
|
expect(apiMock.teams.getAllTasks).toHaveBeenCalledTimes(1);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('clears project and repository loading guards before direct SSH connect refetches', async () => {
|
||||||
|
const projectScan = deferred<unknown[]>();
|
||||||
|
const repositoryScan = deferred<unknown[]>();
|
||||||
|
apiMock.getProjects.mockReturnValue(projectScan.promise);
|
||||||
|
apiMock.getRepositoryGroups.mockReturnValue(repositoryScan.promise);
|
||||||
|
const store = createTestStore();
|
||||||
|
store.setState({
|
||||||
|
activeContextId: 'local',
|
||||||
|
projectsLoading: true,
|
||||||
|
repositoryGroupsLoading: true,
|
||||||
|
} as never);
|
||||||
|
|
||||||
|
await store.getState().connectSsh({
|
||||||
|
host: 'dev',
|
||||||
|
port: 22,
|
||||||
|
username: 'me',
|
||||||
|
authMethod: 'privateKey',
|
||||||
|
privateKeyPath: '/tmp/key',
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(apiMock.getProjects).toHaveBeenCalledTimes(1);
|
||||||
|
expect(apiMock.getRepositoryGroups).toHaveBeenCalledTimes(1);
|
||||||
|
expect(store.getState().projectsLoading).toBe(true);
|
||||||
|
expect(store.getState().repositoryGroupsLoading).toBe(true);
|
||||||
|
|
||||||
|
projectScan.resolve([]);
|
||||||
|
repositoryScan.resolve([]);
|
||||||
|
await Promise.all([projectScan.promise, repositoryScan.promise]);
|
||||||
|
await flushMicrotasks();
|
||||||
|
|
||||||
|
expect(store.getState().projectsLoading).toBe(false);
|
||||||
|
expect(store.getState().repositoryGroupsLoading).toBe(false);
|
||||||
|
});
|
||||||
|
|
||||||
it('drops previous-context team and task caches on direct SSH disconnect', async () => {
|
it('drops previous-context team and task caches on direct SSH disconnect', async () => {
|
||||||
const store = createTestStore();
|
const store = createTestStore();
|
||||||
store.setState({
|
store.setState({
|
||||||
|
|
@ -419,4 +459,32 @@ describe('context slice team/task reset', () => {
|
||||||
expect(apiMock.teams.list).toHaveBeenCalledTimes(1);
|
expect(apiMock.teams.list).toHaveBeenCalledTimes(1);
|
||||||
expect(apiMock.teams.getAllTasks).toHaveBeenCalledTimes(1);
|
expect(apiMock.teams.getAllTasks).toHaveBeenCalledTimes(1);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('clears project and repository loading guards before direct SSH disconnect refetches', async () => {
|
||||||
|
const projectScan = deferred<unknown[]>();
|
||||||
|
const repositoryScan = deferred<unknown[]>();
|
||||||
|
apiMock.getProjects.mockReturnValue(projectScan.promise);
|
||||||
|
apiMock.getRepositoryGroups.mockReturnValue(repositoryScan.promise);
|
||||||
|
const store = createTestStore();
|
||||||
|
store.setState({
|
||||||
|
activeContextId: 'ssh-dev',
|
||||||
|
projectsLoading: true,
|
||||||
|
repositoryGroupsLoading: true,
|
||||||
|
} as never);
|
||||||
|
|
||||||
|
await store.getState().disconnectSsh();
|
||||||
|
|
||||||
|
expect(apiMock.getProjects).toHaveBeenCalledTimes(1);
|
||||||
|
expect(apiMock.getRepositoryGroups).toHaveBeenCalledTimes(1);
|
||||||
|
expect(store.getState().projectsLoading).toBe(true);
|
||||||
|
expect(store.getState().repositoryGroupsLoading).toBe(true);
|
||||||
|
|
||||||
|
projectScan.resolve([]);
|
||||||
|
repositoryScan.resolve([]);
|
||||||
|
await Promise.all([projectScan.promise, repositoryScan.promise]);
|
||||||
|
await flushMicrotasks();
|
||||||
|
|
||||||
|
expect(store.getState().projectsLoading).toBe(false);
|
||||||
|
expect(store.getState().repositoryGroupsLoading).toBe(false);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue