Skip to content

Commit 9824290

Browse files
committed
add new file dialog utils
1 parent bb5e4f5 commit 9824290

2 files changed

Lines changed: 92 additions & 0 deletions

File tree

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
import {beforeEach, describe, expect, it, vi} from 'vitest';
2+
3+
const openMock = vi.fn();
4+
const onChangeRegistrations: Array<(files: FileList | null) => void> = [];
5+
const resetMock = vi.fn();
6+
7+
vi.mock('@vueuse/core', () => ({
8+
useFileDialog: vi.fn(() => ({
9+
open: openMock,
10+
onChange: (handler: (files: FileList | null) => void) => {
11+
onChangeRegistrations.push(handler);
12+
},
13+
reset: resetMock,
14+
})),
15+
}));
16+
17+
describe('createLazySingleFileDialog', () => {
18+
beforeEach(() => {
19+
vi.resetModules();
20+
vi.clearAllMocks();
21+
onChangeRegistrations.length = 0;
22+
vi.useFakeTimers();
23+
});
24+
25+
it('reuses one dialog registration and routes selection to the latest handler', async () => {
26+
const {createLazySingleFileDialog} = await import('@/utility/fileDialogUtils.ts');
27+
28+
const dialog = createLazySingleFileDialog('.csv');
29+
const firstHandler = vi.fn();
30+
const secondHandler = vi.fn();
31+
32+
dialog.openForSelection(firstHandler);
33+
dialog.openForSelection(secondHandler);
34+
35+
expect(onChangeRegistrations).toHaveLength(1);
36+
expect(openMock).not.toHaveBeenCalled();
37+
38+
vi.runAllTimers();
39+
40+
expect(openMock).toHaveBeenCalledTimes(2);
41+
42+
const files = {0: new File(['a'], 'test.csv'), length: 1} as unknown as FileList;
43+
onChangeRegistrations[0]!(files);
44+
45+
expect(firstHandler).not.toHaveBeenCalled();
46+
expect(secondHandler).toHaveBeenCalledWith(files);
47+
expect(resetMock).toHaveBeenCalledTimes(1);
48+
});
49+
});
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
import {useFileDialog} from '@vueuse/core';
2+
3+
type FileSelectionHandler = (files: FileList) => void;
4+
5+
export function createLazySingleFileDialog(accept: string, openDelayMs: number = 3) {
6+
let currentHandler: FileSelectionHandler | undefined;
7+
let dialog:
8+
| {
9+
open: () => void;
10+
onChange: (handler: (files: FileList | null) => void) => void;
11+
reset: () => void;
12+
}
13+
| undefined;
14+
15+
function ensureDialog() {
16+
if (!dialog) {
17+
const {open, onChange, reset} = useFileDialog({
18+
accept,
19+
multiple: false,
20+
});
21+
22+
onChange((files: FileList | null) => {
23+
if (files && files.length > 0) {
24+
currentHandler?.(files);
25+
}
26+
reset();
27+
});
28+
29+
dialog = {open, onChange, reset};
30+
}
31+
return dialog;
32+
}
33+
34+
return {
35+
openForSelection(handler: FileSelectionHandler) {
36+
currentHandler = handler;
37+
const {open} = ensureDialog();
38+
setTimeout(() => {
39+
open();
40+
}, openDelayMs);
41+
},
42+
};
43+
}

0 commit comments

Comments
 (0)