feat: PWA offline capture — IndexedDB queue, service worker cache, auto-sync on reconnect

This commit is contained in:
2026-07-11 19:07:35 +08:00
parent 8c88118b15
commit c048878600
7 changed files with 251 additions and 4 deletions
+64
View File
@@ -0,0 +1,64 @@
import { describe, it, expect, vi, beforeEach } from 'vitest'
const mockDb = {
add: vi.fn(),
getAll: vi.fn(),
delete: vi.fn(),
count: vi.fn(),
}
vi.mock('idb', () => ({
openDB: vi.fn().mockResolvedValue(mockDb),
}))
// Import AFTER mock is set up
const { addPendingReport, getPendingReports, removePendingReport, getPendingCount } =
await import('@/lib/offline/db')
beforeEach(() => vi.clearAllMocks())
describe('addPendingReport', () => {
it('calls db.add on pending_reports store and returns the id', async () => {
mockDb.add.mockResolvedValueOnce(42)
const report = {
zone_token: 'abc',
incident_type: 'near_miss' as const,
description: 'Slippery floor',
injury_involved: false,
asset_involved: false,
created_at: '2026-07-11T00:00:00Z',
}
const id = await addPendingReport(report)
expect(mockDb.add).toHaveBeenCalledWith('pending_reports', report)
expect(id).toBe(42)
})
})
describe('getPendingReports', () => {
it('calls db.getAll on pending_reports store', async () => {
const reports = [
{ id: 1, zone_token: 'abc', incident_type: 'near_miss', description: 'test', injury_involved: false, asset_involved: false, created_at: '2026-07-11T00:00:00Z' },
]
mockDb.getAll.mockResolvedValueOnce(reports)
const result = await getPendingReports()
expect(mockDb.getAll).toHaveBeenCalledWith('pending_reports')
expect(result).toEqual(reports)
})
})
describe('removePendingReport', () => {
it('calls db.delete on pending_reports store with the id', async () => {
mockDb.delete.mockResolvedValueOnce(undefined)
await removePendingReport(1)
expect(mockDb.delete).toHaveBeenCalledWith('pending_reports', 1)
})
})
describe('getPendingCount', () => {
it('calls db.count and returns the result', async () => {
mockDb.count.mockResolvedValueOnce(3)
const count = await getPendingCount()
expect(mockDb.count).toHaveBeenCalledWith('pending_reports')
expect(count).toBe(3)
})
})