update
This commit is contained in:
71
tests/unit/renderer/lib/drop-bridge-missing.test.ts
Normal file
71
tests/unit/renderer/lib/drop-bridge-missing.test.ts
Normal file
@@ -0,0 +1,71 @@
|
||||
// tests/unit/renderer/lib/drop-bridge-missing.test.ts
|
||||
//
|
||||
// 守 drop.ts 的降级契约(2026-10-20,r197):
|
||||
//
|
||||
// 「拿不到 OS 绝对路径就返 '' / 退回 f.path,绝不抛」。
|
||||
//
|
||||
// 桥缺失有两种形态,旧实现只挡了第一种:
|
||||
// ① 桥**不存在** → api Proxy.get 返 undefined → `api.getPathForFile(file)`
|
||||
// 抛 TypeError(not a function)。r81 已 guard 住「属性读取」。
|
||||
// ② 桥**存在但调用抛异常**(preload 实现变化 / 测试替身 / 第三方注入)
|
||||
// → 异常一路逃出 getDroppedFilePath → 下面的 legacy f.path 兜底
|
||||
// 永远走不到,整条 drop 流程炸掉。r197 补上这层。
|
||||
//
|
||||
// 不 mock api 模块:必须用真实 Proxy(旧 drop.test.ts 的 vi.mock 恰好绕开了
|
||||
// 这条路径,才让缺口活到今天)。这里直接改写 window.api —— api Proxy 在
|
||||
// 每次属性读取时实时取 window.api 的当前值。
|
||||
import { afterEach, beforeEach, describe, expect, it } from 'vitest';
|
||||
import type { Api } from '@shared/api-types';
|
||||
|
||||
import { getDroppedFilePath, collectDroppedPaths } from '../../../../src/renderer/src/lib/drop';
|
||||
|
||||
const originalApi = (globalThis as { window?: Window }).window?.api;
|
||||
|
||||
function fakeFile(name: string, legacyPath?: string): File {
|
||||
const f = { name } as unknown as File;
|
||||
if (legacyPath !== undefined) {
|
||||
(f as unknown as { path?: string }).path = legacyPath;
|
||||
}
|
||||
return f;
|
||||
}
|
||||
|
||||
describe('getDroppedFilePath 桥异常降级(r197)', () => {
|
||||
beforeEach(() => {
|
||||
(globalThis as unknown as { window: { api: Api } }).window.api = {
|
||||
getPathForFile: () => {
|
||||
throw new Error('bridge exploded');
|
||||
},
|
||||
} as unknown as Api;
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
(globalThis as unknown as { window: { api: Api } }).window.api = originalApi as Api;
|
||||
});
|
||||
|
||||
it('桥调用抛异常时退回 legacy file.path(不抛)', () => {
|
||||
const f = fakeFile('note.md', '/legacy/note.md');
|
||||
expect(() => getDroppedFilePath(f)).not.toThrow();
|
||||
expect(getDroppedFilePath(f)).toBe('/legacy/note.md');
|
||||
});
|
||||
|
||||
it('桥调用抛异常且无 legacy path → 返空串(跳过此 file)', () => {
|
||||
expect(getDroppedFilePath(fakeFile('note.md'))).toBe('');
|
||||
});
|
||||
|
||||
it('桥方法缺失(属性是 undefined)→ 同样走 legacy 兜底', () => {
|
||||
(globalThis as unknown as { window: { api: Api } }).window.api = {} as unknown as Api;
|
||||
expect(getDroppedFilePath(fakeFile('note.md', '/legacy/note.md'))).toBe('/legacy/note.md');
|
||||
expect(getDroppedFilePath(fakeFile('note.md'))).toBe('');
|
||||
});
|
||||
|
||||
it('collectDroppedPaths:整批降级不炸,空路径被过滤掉', () => {
|
||||
const files = [fakeFile('a.md', '/legacy/a.md'), fakeFile('b.md'), fakeFile('c.md', '/legacy/c.md')];
|
||||
expect(collectDroppedPaths(files)).toEqual(['/legacy/a.md', '/legacy/c.md']);
|
||||
});
|
||||
|
||||
it('桥调用抛异常时,legacy path 优先于抛异常(顺序契约不变)', () => {
|
||||
// 主路径优先级:webUtils > f.path。桥异常时 webUtils 视为「拿不到」。
|
||||
const f = fakeFile('note.md', '/legacy/note.md');
|
||||
expect(getDroppedFilePath(f)).toBe('/legacy/note.md');
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user