From 3d1263b713a9f87054eacf2028e2ce54bfb9cc4c Mon Sep 17 00:00:00 2001 From: Eddy de Vink Date: Sat, 27 Jun 2026 23:27:24 +0200 Subject: [PATCH] fix: make initDatabase idempotent to prevent empty history after sync --- src/database/db.ts | 15 ++++++++------- tests/database.test.ts | 21 ++++++++++++++++++--- 2 files changed, 26 insertions(+), 10 deletions(-) diff --git a/src/database/db.ts b/src/database/db.ts index 1056020..a6cfa21 100644 --- a/src/database/db.ts +++ b/src/database/db.ts @@ -1,9 +1,10 @@ import * as SQLite from 'expo-sqlite' import { Measurement, SyncStatus } from '../types' -let db: SQLite.SQLiteDatabase +let db: SQLite.SQLiteDatabase | null = null export async function initDatabase(): Promise { + if (db) return db = await SQLite.openDatabaseAsync('weegschaal.db') await db.execAsync(` CREATE TABLE IF NOT EXISTS measurements ( @@ -25,7 +26,7 @@ export async function initDatabase(): Promise { } export async function insertMeasurement(m: Measurement): Promise { - await db.runAsync( + await db!.runAsync( `INSERT INTO measurements (id, weight, bmi, bodyFatPercentage, fatMass, musclePercentage, muscleMass, visceralFat, bmr, measuredAt, createdAt, updatedAt, syncStatus) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`, [m.id, m.weight, m.bmi, m.bodyFatPercentage, m.fatMass, m.musclePercentage, m.muscleMass, m.visceralFat, m.bmr, m.measuredAt, m.createdAt, m.updatedAt, m.syncStatus] @@ -33,28 +34,28 @@ export async function insertMeasurement(m: Measurement): Promise { } export async function getAllMeasurements(): Promise { - const rows = await db.getAllAsync( + const rows = await db!.getAllAsync( 'SELECT * FROM measurements ORDER BY measuredAt DESC' ) return rows as Measurement[] } export async function getLatestMeasurement(): Promise { - const rows = await db.getAllAsync( + const rows = await db!.getAllAsync( 'SELECT * FROM measurements ORDER BY measuredAt DESC LIMIT 1' ) return rows.length > 0 ? (rows[0] as Measurement) : null } export async function updateMeasurement(id: string, syncStatus: SyncStatus): Promise { - await db.runAsync( + await db!.runAsync( 'UPDATE measurements SET syncStatus = ?, updatedAt = ? WHERE id = ?', [syncStatus, new Date().toISOString(), id] ) } export async function upsertMeasurement(m: Measurement): Promise { - await db.runAsync( + await db!.runAsync( `INSERT OR REPLACE INTO measurements (id, weight, bmi, bodyFatPercentage, fatMass, musclePercentage, muscleMass, visceralFat, bmr, measuredAt, createdAt, updatedAt, syncStatus) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`, [m.id, m.weight, m.bmi, m.bodyFatPercentage, m.fatMass, m.musclePercentage, m.muscleMass, m.visceralFat, m.bmr, m.measuredAt, m.createdAt, m.updatedAt, m.syncStatus] @@ -62,7 +63,7 @@ export async function upsertMeasurement(m: Measurement): Promise { } export async function getUnsyncedMeasurements(): Promise { - const rows = await db.getAllAsync( + const rows = await db!.getAllAsync( "SELECT * FROM measurements WHERE syncStatus = 'local' ORDER BY updatedAt ASC" ) return rows as Measurement[] diff --git a/tests/database.test.ts b/tests/database.test.ts index 0a78538..48a7f22 100644 --- a/tests/database.test.ts +++ b/tests/database.test.ts @@ -1,4 +1,3 @@ -import { initDatabase, insertMeasurement, getAllMeasurements, getLatestMeasurement, updateMeasurement } from '../src/database/db' import { Measurement } from '../src/types' import * as SQLite from 'expo-sqlite' @@ -24,14 +23,30 @@ const mockMeasurement: Measurement = { describe('database', () => { let db: any + let initDatabase: any + let insertMeasurement: any + let getAllMeasurements: any + let getLatestMeasurement: any + let updateMeasurement: any - beforeEach(() => { + beforeEach(async () => { + jest.resetModules() + jest.doMock('expo-sqlite', () => ({ + openDatabaseAsync: jest.fn(), + })) db = { execAsync: jest.fn(), runAsync: jest.fn(), getAllAsync: jest.fn(), } - ;(SQLite.openDatabaseAsync as jest.Mock).mockResolvedValue(db) + const sqlite = require('expo-sqlite') + ;(sqlite.openDatabaseAsync as jest.Mock).mockResolvedValue(db) + const mod = require('../src/database/db') + initDatabase = mod.initDatabase + insertMeasurement = mod.insertMeasurement + getAllMeasurements = mod.getAllMeasurements + getLatestMeasurement = mod.getLatestMeasurement + updateMeasurement = mod.updateMeasurement }) it('initDatabase creates the measurements table', async () => {