Files
TREK/client/tests/unit/utils/fileDownload.native.test.ts
T
Maurice 2f03554a60 feat(native): files open in the system viewer instead of the share sheet
A PDF, image or document opened in the app went straight to the share sheet.
It now opens in Quick Look on iOS, to page through and zoom with its own share
button, and in the app that views its type on Android. An app without the
viewer (feature filePreview), or a type nothing on the device shows, gets the
share sheet as before.
2026-11-10 00:21:28 +01:00

52 lines
2.2 KiB
TypeScript

import { beforeEach, describe, expect, it, vi } from 'vitest';
import { openNativeFile, shareFile } from '../../../src/native/nativeFiles';
import { downloadBlob, downloadFile, openFile } from '../../../src/utils/fileDownload';
vi.mock('../../../src/db/offlineDb', () => ({ getCachedBlob: vi.fn() }));
vi.mock('../../../src/native/platform', () => ({ isNativeApp: () => true }));
vi.mock('../../../src/native/nativeFiles', async () => {
const actual = await vi.importActual<typeof import('../../../src/native/nativeFiles')>(
'../../../src/native/nativeFiles'
);
return { ...actual, shareFile: vi.fn(), openNativeFile: vi.fn() };
});
const pdf = new Blob(['%PDF'], { type: 'application/pdf' });
beforeEach(() => {
vi.mocked(shareFile).mockReset().mockResolvedValue();
vi.mocked(openNativeFile).mockReset().mockResolvedValue();
vi.stubGlobal('fetch', vi.fn().mockResolvedValue({ ok: true, status: 200, blob: () => Promise.resolve(pdf) }));
});
describe('fileDownload inside the native app', () => {
it('hands an in-memory blob to the share sheet instead of an anchor', () => {
const click = vi.spyOn(HTMLAnchorElement.prototype, 'click');
downloadBlob(pdf, 'report.pdf');
expect(shareFile).toHaveBeenCalledWith(pdf, 'report.pdf');
expect(click).not.toHaveBeenCalled();
});
it('logs a share that failed rather than losing it', async () => {
const report = vi.fn();
vi.stubGlobal('reportError', report);
vi.mocked(shareFile).mockRejectedValue(new Error('no space'));
downloadBlob(pdf, 'report.pdf');
await vi.waitFor(() => expect(report).toHaveBeenCalledWith(expect.any(Error)));
});
it('shares a protected file under its given name, or the one from its URL', async () => {
await downloadFile('/api/trips/1/files/2/download', 'Boarding pass.pdf');
expect(shareFile).toHaveBeenLastCalledWith(pdf, 'Boarding pass.pdf');
await downloadFile('/uploads/files/ticket%20A.pdf');
expect(shareFile).toHaveBeenLastCalledWith(pdf, 'ticket A.pdf');
});
it('opens files in the system viewer, since there is no tab to open them in', async () => {
await openFile('/api/trips/1/files/2/download');
expect(openNativeFile).toHaveBeenLastCalledWith(pdf, 'download');
expect(shareFile).not.toHaveBeenCalled();
});
});