mirror of
https://github.com/twonlyapp/twonly-app.git
synced 2026-10-09 02:54:14 +00:00
144 lines
4.8 KiB
Dart
144 lines
4.8 KiB
Dart
import 'dart:async';
|
|
|
|
import 'package:drift/drift.dart';
|
|
import 'package:drift/native.dart';
|
|
import 'package:flutter_test/flutter_test.dart';
|
|
import 'package:twonly/src/database/tables/groups.table.dart';
|
|
import 'package:twonly/src/database/twonly.db.dart';
|
|
|
|
void main() {
|
|
late TwonlyDB database;
|
|
|
|
setUp(() async {
|
|
database = TwonlyDB(NativeDatabase.memory());
|
|
for (final statement in [
|
|
"INSERT INTO contacts(user_id, username) VALUES (7, 'alice'), (8, 'bob'), (9, 'carol'), (10, 'former')",
|
|
"INSERT INTO groups(group_id, group_name) VALUES ('group', 'Friends'), ('other', 'Other')",
|
|
"INSERT INTO groups(group_id, group_name, is_direct_chat) VALUES ('direct', 'Alice', 1)",
|
|
// Legacy (null), normal and admin members must all remain visible.
|
|
'INSERT INTO group_members(group_id, contact_id, member_state, last_type_indicator) '
|
|
"VALUES ('group', 7, NULL, 1), ('group', 8, 'normal', 1), ('group', 9, 'admin', 1), ('group', 10, 'leftGroup', 1)",
|
|
"INSERT INTO group_members(group_id, contact_id) VALUES ('other', 7), ('direct', 7)",
|
|
'INSERT INTO messages(group_id, message_id, sender_id, type, content) '
|
|
"VALUES ('group', 'message', 7, 'text', 'Hello')",
|
|
'INSERT INTO group_histories(group_history_id, group_id, affected_contact_id, type) '
|
|
"VALUES ('removal', 'group', 7, 'removedMember')",
|
|
]) {
|
|
await database.customStatement(statement);
|
|
}
|
|
});
|
|
|
|
tearDown(() => database.close());
|
|
|
|
Future<void> setMemberState(MemberState state) =>
|
|
database.groupsDao.insertOrUpdateGroupMember(
|
|
GroupMembersCompanion(
|
|
groupId: const Value('group'),
|
|
contactId: const Value(7),
|
|
memberState: Value(state),
|
|
),
|
|
);
|
|
|
|
test(
|
|
'removed members leave active queries while history is retained',
|
|
() async {
|
|
expect(
|
|
(await database.groupsDao.getGroupContact(
|
|
'group',
|
|
)).map((c) => c.userId),
|
|
unorderedEquals([7, 8, 9]),
|
|
);
|
|
|
|
await setMemberState(MemberState.leftGroup);
|
|
|
|
expect(
|
|
(await database.groupsDao.getGroupContact(
|
|
'group',
|
|
)).map((c) => c.userId),
|
|
unorderedEquals([8, 9]),
|
|
);
|
|
expect(
|
|
(await database.groupsDao.getGroupNonLeftMembers(
|
|
'group',
|
|
)).map((m) => m.contactId),
|
|
unorderedEquals([8, 9]),
|
|
);
|
|
expect(
|
|
await database.groupsDao.getAllGroupMembers('group'),
|
|
hasLength(4),
|
|
);
|
|
expect(
|
|
(await database.select(database.messages).get()).single.content,
|
|
'Hello',
|
|
);
|
|
expect(
|
|
(await database.groupsDao.watchGroupActions('group').first)
|
|
.single
|
|
.affectedContactId,
|
|
7,
|
|
);
|
|
expect(
|
|
(await database.groupsDao.getGroupContact('other')).single.userId,
|
|
7,
|
|
);
|
|
expect(
|
|
(await database.groupsDao.getGroupContact('direct')).single.userId,
|
|
7,
|
|
);
|
|
},
|
|
);
|
|
|
|
final memberStreams = <String, Stream<List<int>> Function()>{
|
|
'member list': () => database.groupsDao
|
|
.watchGroupMembers('group')
|
|
.map((rows) => rows.map((row) => row.$1.userId).toList()),
|
|
'group contacts': () => database.groupsDao
|
|
.watchGroupContact('group')
|
|
.map((rows) => rows.map((row) => row.userId).toList()),
|
|
'chat list members': () => database.groupsDao.watchAllGroupMembers().map(
|
|
(rows) => rows
|
|
.where((row) => row.$2.groupId == 'group')
|
|
.map((row) => row.$1.userId)
|
|
.toList(),
|
|
),
|
|
'typing members': () => database.groupsDao.watchTypingGroupMembers().map(
|
|
(rows) => rows.map((row) => row.contactId).toList(),
|
|
),
|
|
};
|
|
|
|
for (final entry in memberStreams.entries) {
|
|
test('${entry.key} updates on removal and rejoining', () async {
|
|
final stream = StreamIterator(entry.value());
|
|
addTearDown(stream.cancel);
|
|
expect(await stream.moveNext(), isTrue);
|
|
expect(stream.current, unorderedEquals([7, 8, 9]));
|
|
|
|
final removal = stream.moveNext();
|
|
await setMemberState(MemberState.leftGroup);
|
|
expect(await removal, isTrue);
|
|
expect(stream.current, unorderedEquals([8, 9]));
|
|
|
|
final rejoining = stream.moveNext();
|
|
await setMemberState(MemberState.normal);
|
|
expect(await rejoining, isTrue);
|
|
expect(stream.current, unorderedEquals([7, 8, 9]));
|
|
});
|
|
}
|
|
|
|
test('mutual groups update when a member is removed', () async {
|
|
final stream = StreamIterator(
|
|
database.groupsDao.watchNonDirectGroupsForMember(7),
|
|
);
|
|
addTearDown(stream.cancel);
|
|
expect(await stream.moveNext(), isTrue);
|
|
expect(
|
|
stream.current.map((g) => g.groupId),
|
|
unorderedEquals(['group', 'other']),
|
|
);
|
|
|
|
final removal = stream.moveNext();
|
|
await setMemberState(MemberState.leftGroup);
|
|
expect(await removal, isTrue);
|
|
expect(stream.current.map((g) => g.groupId), ['other']);
|
|
});
|
|
}
|