diff --git a/packages/graph-explorer/src/core/StateProvider/graphSession/useRestoreGraphSession.test.ts b/packages/graph-explorer/src/core/StateProvider/graphSession/useRestoreGraphSession.test.ts new file mode 100644 index 0000000000..aaded14415 --- /dev/null +++ b/packages/graph-explorer/src/core/StateProvider/graphSession/useRestoreGraphSession.test.ts @@ -0,0 +1,49 @@ +// @vitest-environment happy-dom +import { useAtomValue } from "jotai"; +import { act } from "react"; + +import { + createRandomVertex, + DbState, + FakeExplorer, + renderHookWithState, +} from "@/utils/testing"; + +import { + activeGraphSessionAtom, + type GraphSessionStorageModel, +} from "./storage"; +import { useAvailablePreviousSession } from "./useAvailablePreviousSession"; +import { useRestoreGraphSession } from "./useRestoreGraphSession"; + +test("clears a previous session when none of its entities still exist", async () => { + const missingVertex = createRandomVertex(); + const previousSession: GraphSessionStorageModel = { + vertices: new Set([missingVertex.id]), + edges: new Set(), + }; + const state = new DbState(new FakeExplorer()).withGraphSession( + previousSession, + ); + + const { result } = renderHookWithState(() => { + const restore = useRestoreGraphSession(); + const availablePreviousSession = useAvailablePreviousSession(); + const activeGraphSession = useAtomValue(activeGraphSessionAtom); + + return { restore, availablePreviousSession, activeGraphSession }; + }, state); + + expect(result.current.availablePreviousSession).toStrictEqual( + previousSession, + ); + + await act(() => result.current.restore.mutateAsync(previousSession)); + + expect(result.current.restore.isSuccess).toBe(true); + expect(result.current.availablePreviousSession).toBeNull(); + expect(result.current.activeGraphSession).toStrictEqual({ + vertices: new Set(), + edges: new Set(), + }); +}); diff --git a/packages/graph-explorer/src/core/StateProvider/graphSession/useRestoreGraphSession.ts b/packages/graph-explorer/src/core/StateProvider/graphSession/useRestoreGraphSession.ts index 5fb6345965..c9a4305a47 100644 --- a/packages/graph-explorer/src/core/StateProvider/graphSession/useRestoreGraphSession.ts +++ b/packages/graph-explorer/src/core/StateProvider/graphSession/useRestoreGraphSession.ts @@ -9,6 +9,8 @@ import { createDisplayError } from "@/utils/createDisplayError"; import type { GraphSessionStorageModel } from "./storage"; +import { useUpdateGraphSession } from "./useUpdateGraphSession"; + /** * Provides a mutation that restores the graph session from storage. */ @@ -16,6 +18,7 @@ export function useRestoreGraphSession() { const queryClient = useQueryClient(); const addToGraph = useAddToGraph(); const formatEntityCounts = useEntityCountFormatterCallback(); + const updateGraphSession = useUpdateGraphSession(); const mutation = useMutation({ mutationFn: async (graph: GraphSessionStorageModel) => { @@ -36,6 +39,12 @@ export function useRestoreGraphSession() { // Update Graph Explorer state await addToGraph(result.entities); + if ( + result.entities.vertices.length === 0 && + result.entities.edges.length === 0 + ) { + updateGraphSession(); + } return result; })(); diff --git a/packages/graph-explorer/src/utils/testing/DbState.ts b/packages/graph-explorer/src/utils/testing/DbState.ts index 54ad06c765..5cd2f4b45b 100644 --- a/packages/graph-explorer/src/utils/testing/DbState.ts +++ b/packages/graph-explorer/src/utils/testing/DbState.ts @@ -14,6 +14,7 @@ import { edgesTypesFilteredAtom, type EdgeType, explorerForTestingAtom, + type GraphSessionStorageModel, type GraphViewLayout, graphViewLayoutAtom, mapEdgeToTypeConfig, @@ -54,6 +55,7 @@ import { */ export class DbState { #activeSchema: SchemaStorageModel | null; + #graphSession: GraphSessionStorageModel | undefined; activeConfig: RawConfiguration; vertexStyles: Map; edgeStyles: Map; @@ -110,6 +112,12 @@ export class DbState { return this; } + /** Sets the persisted graph session independently from the current graph. */ + withGraphSession(graphSession: GraphSessionStorageModel) { + this.#graphSession = graphSession; + return this; + } + /** Adds the vertex to the graph and updates the schema to include the type config. */ addVertexToGraph(vertex: Vertex) { this.vertices.push(vertex); @@ -256,7 +264,7 @@ export class DbState { new Map([ [ this.activeConfig.id, - { + this.#graphSession ?? { vertices: new Set(this.vertices.map(v => v.id)), edges: new Set(this.edges.map(e => e.id)), },