whisper-money/resources/js/services/transaction-sync.test.ts

56 lines
1.7 KiB
TypeScript

import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
import { transactionSyncService } from './transaction-sync';
const dbMock = vi.hoisted(() => ({
transactions: {
delete: vi.fn(async () => undefined),
},
sync_metadata: { delete: vi.fn(), get: vi.fn(), put: vi.fn() },
}));
const axiosMock = vi.hoisted(() => ({
delete: vi.fn(async () => ({ data: {} })),
}));
// Keep the real withDb (reads globalThis live); swap only the Dexie-backed db.
vi.mock('@/lib/dexie-db', async (importOriginal) => {
const actual = await importOriginal<typeof import('@/lib/dexie-db')>();
return { ...actual, db: dbMock };
});
vi.mock('axios', () => ({ default: axiosMock }));
describe('transactionSyncService.delete', () => {
beforeEach(() => {
vi.clearAllMocks();
});
afterEach(() => {
vi.unstubAllGlobals();
});
it('deletes via the API but skips the cache eviction when IndexedDB is missing', async () => {
vi.stubGlobal('indexedDB', undefined);
await expect(
transactionSyncService.delete('txn-1'),
).resolves.toBeUndefined();
expect(axiosMock.delete).toHaveBeenCalledWith('/transactions/txn-1', {
data: undefined,
});
expect(dbMock.transactions.delete).not.toHaveBeenCalled();
});
it('deletes via the API and evicts the cache when IndexedDB is available', async () => {
vi.stubGlobal('indexedDB', {} as IDBFactory);
await transactionSyncService.delete('txn-1');
expect(axiosMock.delete).toHaveBeenCalledWith('/transactions/txn-1', {
data: undefined,
});
expect(dbMock.transactions.delete).toHaveBeenCalledWith('txn-1');
});
});