Remote sync of webdav

This commit is contained in:
Courtney Arnold 2026-08-13 17:05:10 -05:00
parent f01186df79
commit 483fbeafb6
44 changed files with 4842 additions and 975 deletions

View file

@ -0,0 +1,98 @@
import 'dart:io';
import 'package:flutter_test/flutter_test.dart';
import 'package:fuel_tax_tracker/services/db_schema.dart';
import 'package:path/path.dart' as p;
import 'package:sqflite_common_ffi/sqflite_ffi.dart';
/// Regression coverage for a real bug: the "needs upload" query used to
/// match on `receipt_image_path IS NOT NULL` alone, which would have kept
/// re-uploading the same photo as a duplicate Drive file on every sync
/// once a "keep photos on this phone" option let an already-uploaded row
/// keep its local path. See [pendingReceiptUploadWhereClause].
void main() {
late Directory tempDir;
late Database db;
setUpAll(() {
sqfliteFfiInit();
databaseFactory = databaseFactoryFfi;
});
setUp(() async {
tempDir = await Directory.systemTemp.createTemp('pending_receipt_test_');
db = await databaseFactory.openDatabase(p.join(tempDir.path, 'test.db'));
await db.execute(createFuelEntriesTableSql);
});
tearDown(() async {
await db.close();
await tempDir.delete(recursive: true);
});
Future<void> insertEntry(
String id, {
String? receiptImagePath,
String? receiptDriveFileId,
int dirty = 1,
int? deletedAt,
}) {
return db.insert('fuel_entries', {
'id': id,
'vehicle_id': 'v1',
'date': 0,
'gallons': 10.0,
'price_per_gallon': 3.5,
'total_cost': 35.0,
'receipt_image_path': receiptImagePath,
'receipt_drive_file_id': receiptDriveFileId,
'updated_at': 0,
'deleted_at': deletedAt,
'dirty': dirty,
});
}
test('matches a row with a local photo not yet uploaded', () async {
await insertEntry('needs-upload', receiptImagePath: '/local/a.jpg');
final rows = await db.query('fuel_entries', where: pendingReceiptUploadWhereClause);
expect(rows.map((r) => r['id']), ['needs-upload']);
});
test('excludes a row already uploaded, even if the local copy was kept', () async {
await insertEntry(
'kept-after-upload',
receiptImagePath: '/local/a.jpg',
receiptDriveFileId: 'drive-file-1',
);
final rows = await db.query('fuel_entries', where: pendingReceiptUploadWhereClause);
expect(rows, isEmpty);
});
test('excludes a row with no local photo at all', () async {
await insertEntry('no-receipt');
final rows = await db.query('fuel_entries', where: pendingReceiptUploadWhereClause);
expect(rows, isEmpty);
});
test('excludes a soft-deleted row even if it has a pending local photo', () async {
await insertEntry('deleted', receiptImagePath: '/local/a.jpg', deletedAt: 123);
final rows = await db.query('fuel_entries', where: pendingReceiptUploadWhereClause);
expect(rows, isEmpty);
});
test('excludes a clean (already-synced) row', () async {
await insertEntry('clean', receiptImagePath: '/local/a.jpg', dirty: 0);
final rows = await db.query('fuel_entries', where: pendingReceiptUploadWhereClause);
expect(rows, isEmpty);
});
}