Fix duplicate node position entries in cytoscapeStore saveNodePosition

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RaRBJFZKSTA7naHGuQHfnQ
This commit is contained in:
2026-07-04 22:21:30 +08:00
co-authored by Claude Fable 5
parent 217c18659b
commit 7095db5ee9
2 changed files with 69 additions and 12 deletions
+6 -12
View File
@@ -26,8 +26,8 @@ export interface Node {
}
export interface NodePositions {
[direction: string]: {
[graphId: string]: Node[];
[graphId: string]: {
[direction: string]: Node[];
}
}
@@ -51,16 +51,10 @@ export const useCytoscapeStore = defineStore('cytoscapeStore', {
if (!this.nodePositions[this.currentGraphId][direction]) {
this.nodePositions[this.currentGraphId][direction] = [];
}
// If this graph's data was previously stored in localStorage
if (localStorage.getItem(SAVE_KEY_NAME)) {
const nodeToSave = this.nodePositions[this.currentGraphId][direction]
.find(node => node.id === nodeId);
if (nodeToSave) {
nodeToSave.position = position;
} else {
this.nodePositions[this.currentGraphId][direction]
.push({ id: nodeId, position: position });
}
const nodeToSave = this.nodePositions[this.currentGraphId][direction]
.find(node => node.id === nodeId);
if (nodeToSave) {
nodeToSave.position = position;
} else {
this.nodePositions[this.currentGraphId][direction]
.push({ id: nodeId, position: position });
@@ -0,0 +1,63 @@
// The Lucia project.
// Copyright 2026-2026 DSP, inc. All rights reserved.
// Authors:
// imacat.yang@dsp.im (imacat), 2026/07/04
import { describe, it, expect, beforeEach, vi } from "vitest";
import { setActivePinia, createPinia } from "pinia";
import { useCytoscapeStore } from "@/stores/cytoscapeStore";
// Mock localStorage since jsdom's localStorage is limited
const localStorageMock = (() => {
let store = {};
return {
getItem: vi.fn((key) => store[key] || null),
setItem: vi.fn((key, value) => {
store[key] = value;
}),
removeItem: vi.fn((key) => {
delete store[key];
}),
clear: vi.fn(() => {
store = {};
}),
};
})();
Object.defineProperty(globalThis, "localStorage", {
value: localStorageMock,
});
describe("cytoscapeStore saveNodePosition without stored data", () => {
let store;
beforeEach(() => {
setActivePinia(createPinia());
store = useCytoscapeStore();
localStorageMock.clear();
vi.clearAllMocks();
// Keep localStorage empty for SAVE_KEY_NAME throughout, as when
// storage is unavailable or cleared externally between saves.
localStorageMock.getItem.mockReturnValue(null);
});
it("does not duplicate a node saved twice without stored data", () => {
store.setCurrentGraphId("graph1");
store.saveNodePosition("node1", { x: 10, y: 20 }, "TB");
store.saveNodePosition("node1", { x: 30, y: 40 }, "TB");
expect(store.nodePositions["graph1"]["TB"]).toHaveLength(1);
expect(store.nodePositions["graph1"]["TB"][0]).toEqual({
id: "node1",
position: { x: 30, y: 40 },
});
});
it("adds separate entries for different nodes", () => {
store.setCurrentGraphId("graph1");
store.saveNodePosition("node1", { x: 10, y: 20 }, "TB");
store.saveNodePosition("node2", { x: 30, y: 40 }, "TB");
expect(store.nodePositions["graph1"]["TB"]).toEqual([
{ id: "node1", position: { x: 10, y: 20 } },
{ id: "node2", position: { x: 30, y: 40 } },
]);
});
});