mirror of
https://github.com/Ark0N/Codeman.git
synced 2026-10-20 09:09:35 +02:00
109 lines
3.8 KiB
TypeScript
109 lines
3.8 KiB
TypeScript
import { beforeEach, describe, expect, it, vi } from 'vitest';
|
|||
|
|
import { execFile } from 'node:child_process';
|
||
|
|
import fs from 'node:fs/promises';
|
||
|
|
import { clearDocumentPreviewCache, getOfficePreviewPdfPath } from '../src/document-preview-cache.js';
|
||
|
|
|
||
|
|
vi.mock('node:child_process', () => ({
|
||
|
|
execFile: vi.fn((_cmd, _args, _options, callback) => {
|
||
|
|
setTimeout(() => callback(null, { stdout: '', stderr: '' }), 1);
|
||
|
|
return {};
|
||
|
|
}),
|
||
|
|
}));
|
||
|
|
|
||
|
|
vi.mock('node:fs/promises', () => ({
|
||
|
|
default: {
|
||
|
|
stat: vi.fn(),
|
||
|
|
mkdir: vi.fn(async () => undefined),
|
||
|
|
copyFile: vi.fn(async () => undefined),
|
||
|
|
mkdtemp: vi.fn(async () => '/tmp/codeman-document-preview-cache/work-test'),
|
||
|
|
readdir: vi.fn(async () => ['deck.pdf']),
|
||
|
|
rename: vi.fn(async () => undefined),
|
||
|
|
rm: vi.fn(async () => undefined),
|
||
|
|
},
|
||
|
|
}));
|
||
|
|
|
||
|
|
const mockedExecFile = vi.mocked(execFile);
|
||
|
|
const mockedStat = vi.mocked(fs.stat);
|
||
|
|
const mockedRename = vi.mocked(fs.rename);
|
||
|
|
|
||
|
|
describe('document-preview-cache', () => {
|
||
|
|
beforeEach(() => {
|
||
|
|
vi.clearAllMocks();
|
||
|
|
clearDocumentPreviewCache();
|
||
|
|
|
||
|
|
let cachedPdfExists = false;
|
||
|
|
mockedStat.mockImplementation(async (path) => {
|
||
|
|
const pathText = String(path);
|
||
|
|
if (pathText.includes('codeman-document-preview-cache') && pathText.endsWith('.pdf')) {
|
||
|
|
if (!cachedPdfExists) throw new Error('ENOENT');
|
||
|
|
return { size: 4096, isFile: () => true } as never;
|
||
|
|
}
|
||
|
|
|
||
|
|
return { size: 1845494, mtimeMs: 12345, isFile: () => true } as never;
|
||
|
|
});
|
||
|
|
mockedRename.mockImplementation(async () => {
|
||
|
|
cachedPdfExists = true;
|
||
|
|
});
|
||
|
|
mockedExecFile.mockImplementation((cmd, _args, _options, callback) => {
|
||
|
|
if (cmd === 'powershell.exe') {
|
||
|
|
cachedPdfExists = true;
|
||
|
|
}
|
||
|
|
|
||
|
|
setTimeout(() => callback(null, { stdout: '', stderr: '' }), 1);
|
||
|
|
return {} as never;
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
it('deduplicates concurrent Office preview conversions and reuses the cached PDF', async () => {
|
||
|
|
const [firstPath, secondPath] = await Promise.all([
|
||
|
|
getOfficePreviewPdfPath('/tmp/deck.pptx', 'pptx'),
|
||
|
|
getOfficePreviewPdfPath('/tmp/deck.pptx', 'pptx'),
|
||
|
|
]);
|
||
|
|
const thirdPath = await getOfficePreviewPdfPath('/tmp/deck.pptx', 'pptx');
|
||
|
|
|
||
|
|
expect(firstPath).toBeTruthy();
|
||
|
|
expect(secondPath).toBe(firstPath);
|
||
|
|
expect(thirdPath).toBe(firstPath);
|
||
|
|
expect(mockedExecFile).toHaveBeenCalledTimes(1);
|
||
|
|
expect(mockedExecFile).toHaveBeenCalledWith(
|
||
|
|
'soffice',
|
||
|
|
expect.arrayContaining([
|
||
|
|
'--headless',
|
||
|
|
'--convert-to',
|
||
|
|
'pdf',
|
||
|
|
expect.stringMatching(/^-env:UserInstallation=file:/),
|
||
|
|
]),
|
||
|
|
expect.any(Object),
|
||
|
|
expect.any(Function)
|
||
|
|
);
|
||
|
|
});
|
||
|
|
|
||
|
|
it('prefers Microsoft Word for DOCX files on Windows-mounted paths', async () => {
|
||
|
|
const result = await getOfficePreviewPdfPath(
|
||
|
|
'/mnt/c/Users/aakhter/Documents/codeman-inline-viewer-test.docx',
|
||
|
|
'docx'
|
||
|
|
);
|
||
|
|
|
||
|
|
expect(result).toContain('/mnt/c/Users/aakhter/AppData/Local/Temp/codeman-document-preview-cache/');
|
||
|
|
expect(mockedExecFile).toHaveBeenCalledWith(
|
||
|
|
'powershell.exe',
|
||
|
|
expect.arrayContaining(['-NoProfile', '-NonInteractive', '-EncodedCommand']),
|
||
|
|
expect.any(Object),
|
||
|
|
expect.any(Function)
|
||
|
|
);
|
||
|
|
const powerShellCall = mockedExecFile.mock.calls.find(([cmd]) => cmd === 'powershell.exe');
|
||
|
|
const encodedCommand = powerShellCall?.[1]?.at(-1);
|
||
|
|
const decodedCommand = Buffer.from(String(encodedCommand), 'base64').toString('utf16le');
|
||
|
|
expect(decodedCommand).toContain('$source = ');
|
||
|
|
expect(decodedCommand).toContain('C:\\Users\\aakhter\\AppData\\Local\\Temp\\codeman-document-preview-cache\\');
|
||
|
|
expect(decodedCommand).toContain('.docx');
|
||
|
|
expect(decodedCommand).toContain('$output = ');
|
||
|
|
expect(decodedCommand).toContain('.pdf');
|
||
|
|
expect(mockedExecFile).not.toHaveBeenCalledWith(
|
||
|
|
'soffice',
|
||
|
|
expect.any(Array),
|
||
|
|
expect.any(Object),
|
||
|
|
expect.any(Function)
|
||
|
|
);
|
||
|
|
});
|
||
|
|
});
|