diff --git a/packages/ui/src/stores/useFilesViewTabsStore.test.ts b/packages/ui/src/stores/useFilesViewTabsStore.test.ts new file mode 100644 index 00000000..11472c07 --- /dev/null +++ b/packages/ui/src/stores/useFilesViewTabsStore.test.ts @@ -0,0 +1,31 @@ +import { beforeEach, describe, expect, test } from 'bun:test'; +import { useFilesViewTabsStore } from './useFilesViewTabsStore'; + +describe('useFilesViewTabsStore', () => { + beforeEach(() => { + useFilesViewTabsStore.setState({ byRoot: {} }); + }); + + test('ignores runtime paths outside the requested root', () => { + const root = '/repo'; + const store = useFilesViewTabsStore.getState(); + + store.addOpenPath(root, '/other/file.ts'); + store.setSelectedPath(root, '/other/file.ts'); + store.expandPath(root, '/other'); + store.toggleExpandedPath(root, '/other'); + + expect(useFilesViewTabsStore.getState().byRoot).toEqual({}); + }); + + test('filters expanded path batches to the requested root', () => { + const root = '/repo'; + + useFilesViewTabsStore.getState().expandPaths(root, [ + '/repo/src', + '/other/src', + ]); + + expect(useFilesViewTabsStore.getState().byRoot[root]?.expandedPaths).toEqual(['/repo/src']); + }); +}); diff --git a/packages/ui/src/stores/useFilesViewTabsStore.ts b/packages/ui/src/stores/useFilesViewTabsStore.ts index d84e4bc7..721783b4 100644 --- a/packages/ui/src/stores/useFilesViewTabsStore.ts +++ b/packages/ui/src/stores/useFilesViewTabsStore.ts @@ -166,7 +166,7 @@ export const useFilesViewTabsStore = create()( addOpenPath: (root, path) => { const normalizedRoot = normalizePath((root || '').trim()); const normalizedPath = normalizePath((path || '').trim()); - if (!normalizedRoot || !normalizedPath) { + if (!normalizedRoot || !normalizedPath || !isPathWithinRoot(normalizedPath, normalizedRoot)) { return; } @@ -265,7 +265,7 @@ export const useFilesViewTabsStore = create()( setSelectedPath: (root, path) => { const normalizedRoot = normalizePath((root || '').trim()); const normalizedPath = path ? normalizePath(path.trim()) : null; - if (!normalizedRoot) { + if (!normalizedRoot || (normalizedPath && !isPathWithinRoot(normalizedPath, normalizedRoot))) { return; } @@ -314,7 +314,7 @@ export const useFilesViewTabsStore = create()( toggleExpandedPath: (root, path) => { const normalizedRoot = normalizePath((root || '').trim()); const normalizedPath = normalizePath((path || '').trim()); - if (!normalizedRoot || !normalizedPath) { + if (!normalizedRoot || !normalizedPath || !isPathWithinRoot(normalizedPath, normalizedRoot)) { return; } @@ -344,7 +344,7 @@ export const useFilesViewTabsStore = create()( expandPath: (root, path) => { const normalizedRoot = normalizePath((root || '').trim()); const normalizedPath = normalizePath((path || '').trim()); - if (!normalizedRoot || !normalizedPath) { + if (!normalizedRoot || !normalizedPath || !isPathWithinRoot(normalizedPath, normalizedRoot)) { return; } @@ -374,7 +374,12 @@ export const useFilesViewTabsStore = create()( return; } - const normalizedPaths = paths.map((p) => normalizePath((p || '').trim())).filter(Boolean); + const normalizedPaths = paths + .map((p) => normalizePath((p || '').trim())) + .filter((p) => p && isPathWithinRoot(p, normalizedRoot)); + if (normalizedPaths.length === 0) { + return; + } set((state) => { const prev = state.byRoot[normalizedRoot];