main
  1import 'package:health_data_store/src/database_manager.dart';
  2import 'package:health_data_store/src/extensions/datetime_seconds.dart';
  3import 'package:sqflite_common_ffi/sqflite_ffi.dart';
  4import 'package:test/test.dart';
  5
  6/// Initialize sqflite for test.
  7void sqfliteTestInit() {
  8  // Initialize ffi implementation
  9  sqfliteFfiInit();
 10  // Set global factory
 11  databaseFactory = databaseFactoryFfi;
 12}
 13
 14void main() {
 15  sqfliteTestInit();
 16  test('should initialize without issues', () async {
 17    final db = await mockDBManager();
 18    addTearDown(db.close);
 19    expect(db.db.isOpen, isTrue);
 20  });
 21  test('should close', () async {
 22    final db = await mockDBManager();
 23    expect(db.db.isOpen, isTrue);
 24    await db.close();
 25    expect(db.db.isOpen, isFalse);
 26  });
 27  test('should setup medicine table', () async {
 28    final db = await mockDBManager();
 29    addTearDown(db.close);
 30
 31    final result = await db.db
 32        .query('medicine', columns: ['medID', 'designation', 'defaultDose']);
 33    expect(result, isEmpty);
 34
 35    final item1 = {
 36      'medID': 1,
 37      'designation': 'test',
 38      'defaultDose': 42,
 39    };
 40    final id1 = await db.db.insert('medicine', item1);
 41
 42    final item2 = {
 43      'medID': 2,
 44      'designation': 'test2',
 45      'defaultDose': 4.2,
 46    };
 47    final id2 = await db.db.insert('medicine', item2);
 48
 49    final item3 = {'medID': 3, 'designation': 'test2', 'defaultDose': null};
 50    final id3 = await db.db.insert('medicine', item3);
 51    expect(id2, greaterThan(id1));
 52    expect(id3, greaterThan(id2));
 53
 54    final resultCols = await db.db
 55        .query('medicine', columns: ['medID', 'designation', 'defaultDose']);
 56    expect(resultCols, hasLength(equals(3)));
 57    expect(
 58        resultCols.first.keys,
 59        containsAll([
 60          'medID',
 61          'designation',
 62          'defaultDose',
 63        ]));
 64    expect(
 65        resultCols,
 66        containsAllInOrder([
 67          item1,
 68          item2,
 69          item3,
 70        ]));
 71
 72    final resultAll = await db.db.query('medicine');
 73    expect(resultAll, hasLength(equals(3)));
 74    expect(
 75        resultCols.first.keys,
 76        containsAll([
 77          'medID',
 78          'designation',
 79          'defaultDose',
 80        ]));
 81    expect(resultCols.first.keys, hasLength(resultCols.first.keys.length),
 82        reason: 'no extra columns.');
 83
 84    final item4 = {'medID': 1, 'designation': null, 'defaultDose': null};
 85    await expectLater(
 86        () async => db.db.insert('medicine', item4), throwsException);
 87  });
 88  test('creates timestamps table correctly', () async {
 89    final db = await mockDBManager();
 90    addTearDown(db.close);
 91    await db.db.insert('Timestamps', {
 92      'entryID': 1,
 93      'timestampUnixS': DateTime.now().secondsSinceEpoch,
 94    });
 95    final data = await db.db.query('Timestamps');
 96    expect(data, hasLength(1));
 97    expect(data.first.keys, hasLength(2));
 98
 99    await expectLater(
100        () async => db.db.insert('Timestamps', {
101              'entryID': 1,
102              'timestampUnixS': DateTime.now().secondsSinceEpoch,
103            }),
104        throwsException);
105    await expectLater(
106        () async => db.db.insert('Timestamps', {
107              'entryID': 1,
108              'timestampUnixS': null,
109            }),
110        throwsException);
111  });
112  test('creates intake table correctly', () async {
113    final db = await mockDBManager();
114    addTearDown(db.close);
115
116    await db.db.insert('Intake', {
117      'entryID': 2,
118      'medID': 1,
119      'dosis': 1,
120    });
121    final data = await db.db.query('Intake');
122    expect(data, hasLength(1));
123    expect(data.first.keys, hasLength(3));
124  });
125  test('creates timestamps sys,dia,pul tables correctly', () async {
126    final db = await mockDBManager();
127    addTearDown(db.close);
128    for (final t in [
129      ('Systolic', 'sys'),
130      ('Diastolic', 'dia'),
131      ('Pulse', 'pul')
132    ]) {
133      await db.db.insert(t.$1, {
134        'entryID': 1,
135        t.$2: 1,
136      });
137      await db.db.insert(t.$1, {
138        'entryID': 2,
139        t.$2: null,
140      });
141      final data = await db.db.query(t.$1);
142      expect(data, hasLength(2));
143      expect(data.first.keys, hasLength(2));
144    }
145  });
146  test('creates notes table correctly', () async {
147    final db = await mockDBManager();
148    addTearDown(db.close);
149
150    await db.db.insert('Notes', {
151      'entryID': 2,
152      'note': 'This was a triumph',
153      'color': 0xFF990098,
154    });
155    final data = await db.db.query('Notes');
156    expect(data, hasLength(1));
157    expect(data.first.keys, hasLength(3));
158    expect(data.first['color'], equals(0xFF990098));
159  });
160  test('creates weight table correctly', () async {
161    final db = await mockDBManager();
162    addTearDown(db.close);
163
164    await db.db.insert('Weight', {
165      'entryID': 2,
166      'weightKg': 123.45,
167    });
168    final data = await db.db.query('Weight');
169    expect(data, hasLength(1));
170    expect(data.first.keys, hasLength(2));
171    expect(data.first['weightKg'], equals(123.45));
172  });
173  test('should cleanup unused timestamps', () async {
174    final db = await mockDBManager();
175    addTearDown(db.close);
176
177    await db.db.insert('Timestamps', {
178      'entryID': 1,
179      'timestampUnixS': DateTime.now().secondsSinceEpoch,
180    });
181    expect(await db.db.query('Timestamps'), hasLength(1));
182    await db.performCleanup();
183    expect(await db.db.query('Timestamps'), isEmpty);
184  });
185  test('should cleanup deleted medicines', () async {
186    final db = await mockDBManager();
187    addTearDown(db.close);
188
189    await db.db.insert('Medicine', {
190      'medID': 1,
191      'designation': 'test',
192      'defaultDose': 42,
193      'removed': 1,
194    });
195    await db.db.insert('Medicine', {
196      'medID': 2,
197      'designation': 'test2',
198      'removed': 1,
199    });
200    await db.db.insert('Intake', {
201      'entryID': 2,
202      'medID': 2,
203      'dosis': 1,
204    });
205
206    expect(await db.db.query('Medicine'), hasLength(2));
207    await db.performCleanup();
208    final data = await db.db.query('Medicine');
209    expect(data, hasLength(1));
210    expect(data, contains(isA<Map>().having((p0) => p0['medID'], 'medID', 2)));
211  });
212  test('cleanup should keep used timestamps', () async {
213    final db = await mockDBManager();
214    addTearDown(db.close);
215
216    for (int i = 1; i <= 7; i += 1) {
217      await db.db.insert('Timestamps', {
218        'entryID': i,
219        'timestampUnixS': i,
220      });
221    }
222    await db.db.insert('Intake', {
223      'entryID': 1,
224      'medID': 0,
225      'dosis': 0,
226    });
227    await db.db.insert('Systolic', {
228      'entryID': 2,
229    });
230    await db.db.insert('Diastolic', {
231      'entryID': 3,
232    });
233    await db.db.insert('Pulse', {
234      'entryID': 4,
235    });
236    await db.db.insert('Notes', {
237      'entryID': 5,
238    });
239    await db.db.insert('Weight', {'entryID': 6, 'weightKg': 1.0});
240
241    expect(await db.db.query('Timestamps'), hasLength(7));
242    await db.performCleanup();
243    expect(await db.db.query('Timestamps'), hasLength(6));
244    // only one isn't used
245  });
246}
247
248Future<DatabaseManager> mockDBManager() async => DatabaseManager.load(
249      await openDatabase(inMemoryDatabasePath),
250    );