82 lines
2.4 KiB
Dart
82 lines
2.4 KiB
Dart
import 'package:flutter_test/flutter_test.dart';
|
|
import 'package:ikar/core/storage/message_persistence.dart';
|
|
import 'package:sqflite_common_ffi/sqflite_ffi.dart';
|
|
|
|
void main() {
|
|
sqfliteFfiInit();
|
|
late Database db;
|
|
final queued = <String, dynamic>{
|
|
'id': 'temp',
|
|
'account_id': 42,
|
|
'chat_id': 7,
|
|
'text': 'ciphertext',
|
|
'status': 'pending',
|
|
'deleted': 0,
|
|
};
|
|
setUp(() async {
|
|
db = await databaseFactoryFfi.openDatabase(inMemoryDatabasePath);
|
|
await db.execute(
|
|
'CREATE TABLE messages (id TEXT NOT NULL, account_id INTEGER NOT NULL, '
|
|
'chat_id INTEGER NOT NULL, text TEXT NOT NULL, status TEXT, deleted INTEGER, '
|
|
'PRIMARY KEY (account_id, id))',
|
|
);
|
|
await db.insert('messages', queued);
|
|
});
|
|
tearDown(() => db.close());
|
|
|
|
test('receipt replaces a pending item atomically', () async {
|
|
expect(
|
|
await MessagePersistence.replacePending(db, {
|
|
...queued,
|
|
'id': 'ack',
|
|
'status': 'sent',
|
|
}, pendingId: 'temp'),
|
|
isTrue,
|
|
);
|
|
expect((await db.query('messages')).single['id'], 'ack');
|
|
});
|
|
for (final mode in [
|
|
'removed',
|
|
'deleted',
|
|
'already sent',
|
|
'other account',
|
|
'other chat',
|
|
]) {
|
|
test('late result cannot overwrite $mode item', () async {
|
|
if (mode == 'removed') await db.delete('messages');
|
|
if (mode == 'deleted') await db.update('messages', {'deleted': 1});
|
|
if (mode == 'already sent') {
|
|
await db.update('messages', {'status': 'sent'});
|
|
}
|
|
final before = await db.query('messages');
|
|
expect(
|
|
await MessagePersistence.replacePending(db, {
|
|
...queued,
|
|
'status': 'error',
|
|
if (mode == 'other account') 'account_id': 84,
|
|
if (mode == 'other chat') 'chat_id': 8,
|
|
}, pendingId: 'temp'),
|
|
isFalse,
|
|
);
|
|
expect(await db.query('messages'), before);
|
|
});
|
|
}
|
|
test(
|
|
'failed delete rolls back receipt and preserves retryable wire text',
|
|
() async {
|
|
await db.execute(
|
|
"CREATE TRIGGER reject_delete BEFORE DELETE ON messages BEGIN SELECT RAISE(ABORT, 'disk error'); END",
|
|
);
|
|
await expectLater(
|
|
MessagePersistence.replacePending(db, {
|
|
...queued,
|
|
'id': 'ack',
|
|
'status': 'sent',
|
|
}, pendingId: 'temp'),
|
|
throwsA(isA<DatabaseException>()),
|
|
);
|
|
expect((await db.query('messages')).single, queued);
|
|
},
|
|
);
|
|
}
|