mirror of
https://github.com/echore/vault-autopilot.git
synced 2026-07-22 08:34:00 +00:00
Obsidian's Properties editor re-serializes frontmatter (drops quotes, rewrites inline lists to block style), which broke the exact-substring video_id match and the addDimension regex — every later clip created a permanent duplicate note. Cache misses (just-created notes) fall back to a quote-tolerant scan; cached non-matches skip the file read. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
41 lines
1.8 KiB
TypeScript
41 lines
1.8 KiB
TypeScript
import { validateClipPayload } from '../src/clip-validate';
|
|
import { routeClip, VaultOps } from '../src/clip-router';
|
|
|
|
function mockVaultOps(): VaultOps {
|
|
const files = new Map<string, string>();
|
|
return {
|
|
ensureFolder: async () => {},
|
|
createBinary: async () => {},
|
|
create: async (p, c) => { files.set(p, c); },
|
|
readFileSync: () => { throw new Error('no sop'); },
|
|
downloadUrl: async () => new ArrayBuffer(8),
|
|
fileExists: () => false,
|
|
listMarkdownFiles: () => [],
|
|
read: async () => '',
|
|
modify: async () => {},
|
|
getFrontmatter: () => null,
|
|
};
|
|
}
|
|
|
|
const RULES = {
|
|
thumbnail: { sopPath: '', outputFolder: 'V', thumbnailFolder: 'V/covers' },
|
|
screenshot: { sopPath: '', outputFolder: 'S', framesFolder: 'S/frames' },
|
|
hook: { sopPath: '', outputFolder: 'V', maxFrames: 5, framesFolder: 'V/frames' },
|
|
keyframe: { sopPath: '', outputFolder: 'V', maxFrames: 5, framesFolder: 'V/frames' },
|
|
} as any;
|
|
|
|
describe('extension -> backend contract', () => {
|
|
test('legacy single-shot screenshot (image field) is accepted and routed', async () => {
|
|
const raw = { mode: 'screenshot', image: 'YWJj', url: 'https://x.com', title: 'T', platform: 'other', captured_at: '2026-01-01T00:00:00Z' };
|
|
const payload = validateClipPayload(raw);
|
|
const r = await routeClip(payload, RULES, mockVaultOps());
|
|
expect(r.notePath).toBeTruthy();
|
|
});
|
|
|
|
test('hook payload with null video_title is accepted and routed', async () => {
|
|
const raw = { mode: 'hook', url: 'https://youtu.be/abc', title: 'T', platform: 'youtube', captured_at: '2026-01-01T00:00:00Z', frames: ['YWJj'], frames_select: 1, video_title: null, channel: null, time_range: { start: 0, end: 15 } };
|
|
const payload = validateClipPayload(raw);
|
|
const r = await routeClip(payload, RULES, mockVaultOps());
|
|
expect(r.notePath).toBeTruthy();
|
|
});
|
|
});
|