test: herschrijf tests voor timestamp-based sync, vervang updateMeasurement door setDeletedAt
This commit is contained in:
parent
8e1783306a
commit
d0dd2f4e39
2 changed files with 41 additions and 58 deletions
|
|
@ -18,7 +18,6 @@ const mockMeasurement: Measurement = {
|
||||||
measuredAt: '2024-01-01T08:00:00.000Z',
|
measuredAt: '2024-01-01T08:00:00.000Z',
|
||||||
createdAt: '2024-01-01T08:00:00.000Z',
|
createdAt: '2024-01-01T08:00:00.000Z',
|
||||||
updatedAt: '2024-01-01T08:00:00.000Z',
|
updatedAt: '2024-01-01T08:00:00.000Z',
|
||||||
syncStatus: 'local',
|
|
||||||
}
|
}
|
||||||
|
|
||||||
describe('database', () => {
|
describe('database', () => {
|
||||||
|
|
@ -27,7 +26,7 @@ describe('database', () => {
|
||||||
let insertMeasurement: any
|
let insertMeasurement: any
|
||||||
let getAllMeasurements: any
|
let getAllMeasurements: any
|
||||||
let getLatestMeasurement: any
|
let getLatestMeasurement: any
|
||||||
let updateMeasurement: any
|
let setDeletedAt: any
|
||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
jest.resetModules()
|
jest.resetModules()
|
||||||
|
|
@ -46,7 +45,7 @@ describe('database', () => {
|
||||||
insertMeasurement = mod.insertMeasurement
|
insertMeasurement = mod.insertMeasurement
|
||||||
getAllMeasurements = mod.getAllMeasurements
|
getAllMeasurements = mod.getAllMeasurements
|
||||||
getLatestMeasurement = mod.getLatestMeasurement
|
getLatestMeasurement = mod.getLatestMeasurement
|
||||||
updateMeasurement = mod.updateMeasurement
|
setDeletedAt = mod.setDeletedAt
|
||||||
})
|
})
|
||||||
|
|
||||||
it('initDatabase creates the measurements table', async () => {
|
it('initDatabase creates the measurements table', async () => {
|
||||||
|
|
@ -82,13 +81,13 @@ describe('database', () => {
|
||||||
expect(result!.id).toBe(mockMeasurement.id)
|
expect(result!.id).toBe(mockMeasurement.id)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('updateMeasurement updates syncStatus', async () => {
|
it('setDeletedAt sets the deletedAt timestamp', async () => {
|
||||||
db.runAsync.mockResolvedValue(undefined)
|
db.runAsync.mockResolvedValue(undefined)
|
||||||
await initDatabase()
|
await initDatabase()
|
||||||
await updateMeasurement(mockMeasurement.id, 'synced')
|
await setDeletedAt(mockMeasurement.id)
|
||||||
expect(db.runAsync).toHaveBeenCalledWith(
|
expect(db.runAsync).toHaveBeenCalledWith(
|
||||||
expect.stringContaining('UPDATE measurements'),
|
expect.stringContaining('UPDATE measurements SET deletedAt'),
|
||||||
expect.arrayContaining(['synced', mockMeasurement.id])
|
expect.arrayContaining([mockMeasurement.id])
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
|
||||||
|
|
@ -1,72 +1,56 @@
|
||||||
import { mergeMeasurements } from '../src/sync/syncService'
|
import { mergeMeasurements } from '../src/sync/syncService'
|
||||||
import { Measurement } from '../src/types'
|
import { Measurement } from '../src/types'
|
||||||
|
|
||||||
jest.mock('expo-sqlite', () => ({
|
jest.mock('expo-sqlite', () => ({ openDatabaseAsync: jest.fn() }))
|
||||||
openDatabaseAsync: jest.fn(),
|
|
||||||
}))
|
|
||||||
|
|
||||||
const base: Measurement = {
|
const make = (overrides: Partial<Measurement> = {}): Measurement => ({
|
||||||
id: 'id-1',
|
id: 'id-1', weight: 75, bmi: 22, bodyFatPercentage: 15, fatMass: 10,
|
||||||
weight: 75,
|
musclePercentage: 40, muscleMass: 30, visceralFat: 8, bmr: 1600,
|
||||||
bmi: 22,
|
measuredAt: '2024-06-01T08:00:00.000Z', createdAt: '2024-06-01T08:00:00.000Z',
|
||||||
bodyFatPercentage: 15,
|
updatedAt: '2024-06-01T08:00:00.000Z', ...overrides,
|
||||||
fatMass: 10,
|
})
|
||||||
musclePercentage: 40,
|
|
||||||
muscleMass: 30,
|
|
||||||
visceralFat: 8,
|
|
||||||
bmr: 1600,
|
|
||||||
measuredAt: '2024-06-01T08:00:00.000Z',
|
|
||||||
createdAt: '2024-06-01T08:00:00.000Z',
|
|
||||||
updatedAt: '2024-06-01T08:00:00.000Z',
|
|
||||||
syncStatus: 'local',
|
|
||||||
}
|
|
||||||
|
|
||||||
describe('mergeMeasurements', () => {
|
describe('mergeMeasurements', () => {
|
||||||
it('returns empty array when both are empty', () => {
|
it('both empty returns empty', () => {
|
||||||
expect(mergeMeasurements([], [])).toEqual([])
|
expect(mergeMeasurements([], [])).toEqual([])
|
||||||
})
|
})
|
||||||
|
|
||||||
it('keeps local items not on remote', () => {
|
it('local only kept', () => {
|
||||||
const result = mergeMeasurements([base], [])
|
const r = mergeMeasurements([make()], [])
|
||||||
expect(result).toHaveLength(1)
|
expect(r).toHaveLength(1)
|
||||||
expect(result[0].id).toBe('id-1')
|
|
||||||
})
|
})
|
||||||
|
|
||||||
it('keeps remote items not on local', () => {
|
it('remote only kept', () => {
|
||||||
const remote = { ...base, syncStatus: 'synced' as const }
|
const r = mergeMeasurements([], [make({ id: 'r1' })])
|
||||||
const result = mergeMeasurements([], [remote])
|
expect(r).toHaveLength(1)
|
||||||
expect(result).toHaveLength(1)
|
expect(r[0].id).toBe('r1')
|
||||||
expect(result[0].id).toBe('id-1')
|
|
||||||
})
|
})
|
||||||
|
|
||||||
it('picks the newer version when both have same id', () => {
|
it('last-writer-wins: remote newer', () => {
|
||||||
const local = { ...base, weight: 75, updatedAt: '2024-06-02T08:00:00.000Z' }
|
const local = make({ weight: 75, updatedAt: '2024-06-02T08:00:00.000Z' })
|
||||||
const remote = { ...base, weight: 76, updatedAt: '2024-06-03T08:00:00.000Z' }
|
const remote = make({ weight: 76, updatedAt: '2024-06-03T08:00:00.000Z' })
|
||||||
const result = mergeMeasurements([local], [remote])
|
const r = mergeMeasurements([local], [remote])
|
||||||
expect(result).toHaveLength(1)
|
expect(r[0].weight).toBe(76)
|
||||||
expect(result[0].weight).toBe(76)
|
|
||||||
})
|
})
|
||||||
|
|
||||||
it('picks local when local is newer', () => {
|
it('last-writer-wins: local newer', () => {
|
||||||
const local = { ...base, weight: 77, updatedAt: '2024-06-04T08:00:00.000Z' }
|
const local = make({ weight: 77, updatedAt: '2024-06-04T08:00:00.000Z' })
|
||||||
const remote = { ...base, weight: 76, updatedAt: '2024-06-03T08:00:00.000Z' }
|
const remote = make({ weight: 76, updatedAt: '2024-06-03T08:00:00.000Z' })
|
||||||
const result = mergeMeasurements([local], [remote])
|
const r = mergeMeasurements([local], [remote])
|
||||||
expect(result).toHaveLength(1)
|
expect(r[0].weight).toBe(77)
|
||||||
expect(result[0].weight).toBe(77)
|
|
||||||
})
|
})
|
||||||
|
|
||||||
it('excludes ids in excludeIds from both sides', () => {
|
it('remote deleted wins over older local', () => {
|
||||||
const local = { ...base, id: 'id-1' }
|
const local = make({ updatedAt: '2024-06-01T08:00:00.000Z' })
|
||||||
const remote = { ...base, id: 'id-2' }
|
const remote = make({ updatedAt: '2024-06-03T08:00:00.000Z', deletedAt: '2024-06-03T08:00:00.000Z' })
|
||||||
const result = mergeMeasurements([local], [remote], new Set(['id-1', 'id-2']))
|
const r = mergeMeasurements([local], [remote])
|
||||||
expect(result).toHaveLength(0)
|
expect(r[0].deletedAt).toBe('2024-06-03T08:00:00.000Z')
|
||||||
})
|
})
|
||||||
|
|
||||||
it('keeps ids not in excludeIds', () => {
|
it('local wins over older remote deleted', () => {
|
||||||
const local = { ...base, id: 'id-1' }
|
const local = make({ updatedAt: '2024-06-03T08:00:00.000Z' })
|
||||||
const remote = { ...base, id: 'id-2' }
|
const remote = make({ updatedAt: '2024-06-01T08:00:00.000Z', deletedAt: '2024-06-01T08:00:00.000Z' })
|
||||||
const result = mergeMeasurements([local], [remote], new Set(['id-1']))
|
const r = mergeMeasurements([local], [remote])
|
||||||
expect(result).toHaveLength(1)
|
expect(r[0].deletedAt).toBeUndefined()
|
||||||
expect(result[0].id).toBe('id-2')
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue