[Tests] Write much more tests

This commit is contained in:
Christian Pauly 2019-08-08 11:41:42 +02:00
parent df0cc1d273
commit 1617a8b7d5
5 changed files with 208 additions and 82 deletions

View file

@ -73,8 +73,12 @@ class Room {
return canonicalAlias.substring(1, canonicalAlias.length).split(":")[0]; return canonicalAlias.substring(1, canonicalAlias.length).split(":")[0];
if (mHeroes.length > 0) { if (mHeroes.length > 0) {
String displayname = ""; String displayname = "";
for (int i = 0; i < mHeroes.length; i++) for (int i = 0; i < mHeroes.length; i++) {
displayname += User(senderId: mHeroes[i]).calcDisplayname() + ", "; User hero = states[mHeroes[i]] != null
? states[mHeroes[i]].asUser
: User(stateKey: mHeroes[i]);
displayname += hero.calcDisplayname() + ", ";
}
return displayname.substring(0, displayname.length - 2); return displayname.substring(0, displayname.length - 2);
} }
return "Empty chat"; return "Empty chat";
@ -88,9 +92,9 @@ class Room {
/// The avatar of the room if set by a participant. /// The avatar of the room if set by a participant.
MxContent get avatar { MxContent get avatar {
if (states["m.room.avatar"] != null) if (states["m.room.avatar"] != null)
return MxContent(states["m.room.avatar"].content["avatar_url"]); return MxContent(states["m.room.avatar"].content["url"]);
if (mHeroes.length == 1 && states[mHeroes[0]] != null) if (mHeroes.length == 1 && states[mHeroes[0]] != null)
return (states[mHeroes[0]] as User).avatarUrl; return states[mHeroes[0]].asUser.avatarUrl;
return MxContent(""); return MxContent("");
} }
@ -307,10 +311,10 @@ class Room {
return res; return res;
} }
/// Call the Matrix API to unban a banned user from this room. /// Set the power level of the user with the [userID] to the value [power].
Future<dynamic> setPower(String userID, int power) async { Future<dynamic> setPower(String userID, int power) async {
if (states["m.room.power_levels"] == null) return null;
Map<String, int> powerMap = states["m.room.power_levels"].content["users"]; Map<String, int> powerMap = states["m.room.power_levels"].content["users"];
if (powerMap == null) return null;
powerMap[userID] = power; powerMap[userID] = power;
dynamic res = await client.connection.jsonRequest( dynamic res = await client.connection.jsonRequest(
@ -378,7 +382,7 @@ class Room {
/// Sets this room as a direct chat for this user. /// Sets this room as a direct chat for this user.
Future<dynamic> addToDirectChat(String userID) async { Future<dynamic> addToDirectChat(String userID) async {
Map<String, List<String>> directChats = client.directChats; Map<String, dynamic> directChats = client.directChats;
if (directChats.containsKey(userID)) if (!directChats[userID].contains(id)) if (directChats.containsKey(userID)) if (!directChats[userID].contains(id))
directChats[userID].add(id); directChats[userID].add(id);
else else
@ -413,6 +417,8 @@ class Room {
Future<List<Map<String, dynamic>>> roomAccountData}) async { Future<List<Map<String, dynamic>>> roomAccountData}) async {
Room newRoom = Room( Room newRoom = Room(
id: row["id"], id: row["id"],
membership: Membership.values
.firstWhere((e) => e.toString() == 'Membership.' + row["membership"]),
notificationCount: row["notification_count"], notificationCount: row["notification_count"],
highlightCount: row["highlight_count"], highlightCount: row["highlight_count"],
notificationSettings: row["notification_settings"], notificationSettings: row["notification_settings"],
@ -421,6 +427,8 @@ class Room {
mJoinedMemberCount: row["joined_member_count"], mJoinedMemberCount: row["joined_member_count"],
mHeroes: row["heroes"]?.split(",") ?? [], mHeroes: row["heroes"]?.split(",") ?? [],
client: matrix, client: matrix,
states: {},
roomAccountData: {},
); );
Map<String, State> newStates = {}; Map<String, State> newStates = {};
@ -463,10 +471,12 @@ class Room {
/// Load all events for a given room from the store. This includes all /// Load all events for a given room from the store. This includes all
/// senders of those events, who will be added to the participants list. /// senders of those events, who will be added to the participants list.
Future<List<Event>> loadEvents() async { Future<List<Event>> loadEvents() async {
return await client.store.getEventList(this); if (client.store != null) return await client.store.getEventList(this);
return [];
} }
/// Load all participants for a given room from the store. /// Load all participants for a given room from the store.
@deprecated
Future<List<User>> loadParticipants() async { Future<List<User>> loadParticipants() async {
return await client.store.loadParticipants(this); return await client.store.loadParticipants(this);
} }
@ -490,14 +500,14 @@ class Room {
} }
Future<User> getUserByMXID(String mxID) async { Future<User> getUserByMXID(String mxID) async {
if (states[mxID] != null) return states[mxID] as User; if (states[mxID] != null) return states[mxID].asUser;
final dynamic resp = await client.connection.jsonRequest( final dynamic resp = await client.connection.jsonRequest(
type: HTTPType.GET, type: HTTPType.GET,
action: "/client/r0/rooms/$id/state/m.room.member/$mxID"); action: "/client/r0/rooms/$id/state/m.room.member/$mxID");
if (resp is ErrorResponse) return null; if (resp is ErrorResponse) return null;
// Somehow we miss the mxid in the response and only get the content of the event. // Somehow we miss the mxid in the response and only get the content of the event.
resp["matrix_id"] = mxID; resp["matrix_id"] = mxID;
return State.fromJson(resp, this) as User; return State.fromJson(resp, this).asUser;
} }
/// Searches for the event in the store. If it isn't found, try to request it /// Searches for the event in the store. If it isn't found, try to request it
@ -514,18 +524,21 @@ class Room {
} }
/// Returns the user's own power level. /// Returns the user's own power level.
int get ownPowerLevel { int getPowerLevelByUserId(String userId) {
int powerLevel = 0; int powerLevel = 0;
State powerLevelState = states["m.room.power_levels"]; State powerLevelState = states["m.room.power_levels"];
if (powerLevelState == null) return powerLevel; if (powerLevelState == null) return powerLevel;
if (powerLevelState.content["users_default"] is int) if (powerLevelState.content["users_default"] is int)
powerLevel = powerLevelState.content["users_default"]; powerLevel = powerLevelState.content["users_default"];
if (powerLevelState.content["users"] is Map<String, int> && if (powerLevelState.content["users"] is Map<String, dynamic> &&
powerLevelState.content["users"][client.userID] != null) powerLevelState.content["users"][userId] != null)
powerLevel = powerLevelState.content["users"][client.userID]; powerLevel = powerLevelState.content["users"][userId];
return powerLevel; return powerLevel;
} }
/// Returns the user's own power level.
int get ownPowerLevel => getPowerLevelByUserId(client.userID);
/// Returns the power levels from all users for this room or null if not given. /// Returns the power levels from all users for this room or null if not given.
Map<String, int> get powerLevels { Map<String, int> get powerLevels {
State powerLevelState = states["m.room.power_levels"]; State powerLevelState = states["m.room.power_levels"];

View file

@ -300,7 +300,7 @@ class Store {
"SELECT * FROM States WHERE state_key=? AND room_id=?", "SELECT * FROM States WHERE state_key=? AND room_id=?",
[matrixID, room.id]); [matrixID, room.id]);
if (res.length != 1) return null; if (res.length != 1) return null;
return State.fromJson(res[0], room) as User; return State.fromJson(res[0], room).asUser;
} }
/// Loads all Users in the database to provide a contact list /// Loads all Users in the database to provide a contact list
@ -311,8 +311,7 @@ class Store {
[client.userID, exceptRoomID]); [client.userID, exceptRoomID]);
List<User> userList = []; List<User> userList = [];
for (int i = 0; i < res.length; i++) for (int i = 0; i < res.length; i++)
userList userList.add(State.fromJson(res[i], Room(id: "", client: client)).asUser);
.add(State.fromJson(res[i], Room(id: "", client: client)) as User);
return userList; return userList;
} }
@ -328,7 +327,7 @@ class Store {
List<User> participants = []; List<User> participants = [];
for (num i = 0; i < res.length; i++) { for (num i = 0; i < res.length; i++) {
participants.add(State.fromJson(res[i], room) as User); participants.add(State.fromJson(res[i], room).asUser);
} }
return participants; return participants;

View file

@ -60,7 +60,7 @@ class User extends State {
String get id => stateKey; String get id => stateKey;
/// The displayname of the user if the user has set one. /// The displayname of the user if the user has set one.
String get displayName => content["displayname"]; String get displayName => content != null ? content["displayname"] : null;
/// The membership status of the user. One of: /// The membership status of the user. One of:
/// join /// join
@ -75,12 +75,14 @@ class User extends State {
}); });
/// The avatar if the user has one. /// The avatar if the user has one.
MxContent avatarUrl; MxContent get avatarUrl => content != null && content["avatar_url"] is String
? MxContent(content["avatar_url"])
: MxContent("");
/// Returns the displayname or the local part of the Matrix ID if the user /// Returns the displayname or the local part of the Matrix ID if the user
/// has no displayname. /// has no displayname.
String calcDisplayname() => (displayName == null || displayName.isEmpty) String calcDisplayname() => (displayName == null || displayName.isEmpty)
? id.replaceFirst("@", "").split(":")[0] ? stateKey.replaceFirst("@", "").split(":")[0]
: displayName; : displayName;
/// Call the Matrix API to kick this user from this room. /// Call the Matrix API to kick this user from this room.

View file

@ -64,6 +64,20 @@ class FakeMatrixApi extends MockClient {
static final Map<String, Map<String, dynamic>> api = { static final Map<String, Map<String, dynamic>> api = {
"GET": { "GET": {
"/client/r0/rooms/!localpart:server.abc/state/m.room.member/@getme:example.com":
(var req) => {
"content": {
"membership": "join",
"displayname": "You got me",
},
"type": "m.room.member",
"event_id": "143273582443PhrSn:example.org",
"room_id": "!localpart:server.abc",
"sender": "@getme:example.com",
"state_key": "@getme:example.com",
"origin_server_ts": 1432735824653,
"unsigned": {"age": 1234}
},
"/client/r0/rooms/!localpart:server.abc/event/1234": (var req) => { "/client/r0/rooms/!localpart:server.abc/event/1234": (var req) => {
"content": { "content": {
"body": "This is an example text message", "body": "This is an example text message",
@ -503,12 +517,30 @@ class FakeMatrixApi extends MockClient {
"room_id": "!1234:fakeServer.notExisting", "room_id": "!1234:fakeServer.notExisting",
}, },
"/client/r0/rooms/!localpart:server.abc/read_markers": (var reqI) => {}, "/client/r0/rooms/!localpart:server.abc/read_markers": (var reqI) => {},
"/client/r0/rooms/!localpart:server.abc/kick": (var reqI) => {},
"/client/r0/rooms/!localpart:server.abc/ban": (var reqI) => {},
"/client/r0/rooms/!localpart:server.abc/unban": (var reqI) => {},
"/client/r0/rooms/!localpart:server.abc/invite": (var reqI) => {},
}, },
"PUT": { "PUT": {
"/client/r0/rooms/!1234:example.com/send/m.room.message/1234": "/client/r0/rooms/!1234:example.com/send/m.room.message/1234":
(var reqI) => { (var reqI) => {
"event_id": "42", "event_id": "42",
}, },
"/client/r0/rooms/!localpart:server.abc/state/m.room.name": (var reqI) =>
{
"event_id": "42",
},
"/client/r0/rooms/!localpart:server.abc/state/m.room.topic": (var reqI) =>
{
"event_id": "42",
},
"/client/r0/rooms/!localpart:server.abc/state/m.room.power_levels":
(var reqI) => {
"event_id": "42",
},
"/client/r0/user/@test:fakeServer.notExisting/account_data/m.direct":
(var reqI) => {},
}, },
"DELETE": { "DELETE": {
"/unknown/token": (var req) => {"errcode": "M_UNKNOWN_TOKEN"}, "/unknown/token": (var req) => {"errcode": "M_UNKNOWN_TOKEN"},

View file

@ -24,7 +24,10 @@
import 'package:famedlysdk/src/Client.dart'; import 'package:famedlysdk/src/Client.dart';
import 'package:famedlysdk/src/Event.dart'; import 'package:famedlysdk/src/Event.dart';
import 'package:famedlysdk/src/Room.dart'; import 'package:famedlysdk/src/Room.dart';
import 'package:famedlysdk/src/State.dart';
import 'package:famedlysdk/src/Timeline.dart';
import 'package:famedlysdk/src/User.dart'; import 'package:famedlysdk/src/User.dart';
import 'package:famedlysdk/src/utils/ChatTime.dart';
import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_test/flutter_test.dart';
import 'FakeMatrixApi.dart'; import 'FakeMatrixApi.dart';
@ -50,24 +53,9 @@ void main() {
test("Create from json", () async { test("Create from json", () async {
final String id = "!localpart:server.abc"; final String id = "!localpart:server.abc";
final String name = "My Room";
final Membership membership = Membership.join; final Membership membership = Membership.join;
final String topic = "This is my own room";
final int unread = DateTime.now().millisecondsSinceEpoch;
final int notificationCount = 2; final int notificationCount = 2;
final int highlightCount = 1; final int highlightCount = 1;
final String fullyRead = "fjh82jdjifd:server.abc";
final String notificationSettings = "all";
final String guestAccess = "forbidden";
final String canonicalAlias = "#testroom:example.com";
final String historyVisibility = "invite";
final String joinRules = "invite";
final int now = DateTime.now().millisecondsSinceEpoch;
final String msgtype = "m.text";
final String body = "Hello World";
final String formatted_body = "<b>Hello</b> World";
final String contentJson =
'{"msgtype":"$msgtype","body":"$body","formatted_body":"$formatted_body"}';
final List<String> heroes = [ final List<String> heroes = [
"@alice:matrix.org", "@alice:matrix.org",
"@bob:example.com", "@bob:example.com",
@ -77,35 +65,10 @@ void main() {
Map<String, dynamic> jsonObj = { Map<String, dynamic> jsonObj = {
"id": id, "id": id,
"membership": membership.toString().split('.').last, "membership": membership.toString().split('.').last,
"topic": name,
"description": topic,
"avatar_url": "", "avatar_url": "",
"notification_count": notificationCount, "notification_count": notificationCount,
"highlight_count": highlightCount, "highlight_count": highlightCount,
"unread": unread,
"fully_read": fullyRead,
"notification_settings": notificationSettings,
"direct_chat_matrix_id": "",
"draft": "",
"prev_batch": "", "prev_batch": "",
"guest_access": guestAccess,
"history_visibility": historyVisibility,
"join_rules": joinRules,
"canonical_alias": canonicalAlias,
"power_events_default": 0,
"power_state_default": 0,
"power_redact": 0,
"power_invite": 0,
"power_ban": 0,
"power_kick": 0,
"power_user_default": 0,
"power_event_avatar": 0,
"power_event_history_visibility": 0,
"power_event_canonical_alias": 0,
"power_event_aliases": 0,
"power_event_name": 0,
"power_event_power_levels": 0,
"content_json": contentJson,
"joined_member_count": notificationCount, "joined_member_count": notificationCount,
"invited_member_count": notificationCount, "invited_member_count": notificationCount,
"heroes": heroes.join(","), "heroes": heroes.join(","),
@ -115,33 +78,69 @@ void main() {
expect(room.id, id); expect(room.id, id);
expect(room.membership, membership); expect(room.membership, membership);
expect(room.name, name);
expect(room.displayname, name);
expect(room.topic, topic);
expect(room.avatar.mxc, "");
expect(room.notificationCount, notificationCount); expect(room.notificationCount, notificationCount);
expect(room.highlightCount, highlightCount); expect(room.highlightCount, highlightCount);
expect(room.unread.toTimeStamp(), unread);
expect(room.fullyRead, fullyRead);
expect(room.notificationSettings, notificationSettings);
expect(room.directChatMatrixID, "");
expect(room.canonicalAlias, canonicalAlias);
expect(room.prev_batch, "");
expect(room.lastMessage, body);
expect(room.timeCreated.toTimeStamp() >= now, true);
room.powerLevels.forEach((String key, int value) {
expect(value, 0);
});
expect(room.mJoinedMemberCount, notificationCount); expect(room.mJoinedMemberCount, notificationCount);
expect(room.mInvitedMemberCount, notificationCount); expect(room.mInvitedMemberCount, notificationCount);
expect(room.mHeroes, heroes); expect(room.mHeroes, heroes);
jsonObj["topic"] = "";
room = await Room.getRoomFromTableRow(jsonObj, matrix);
expect(room.displayname, "testroom");
jsonObj["canonical_alias"] = "";
room = await Room.getRoomFromTableRow(jsonObj, matrix);
expect(room.displayname, "alice, bob, charley"); expect(room.displayname, "alice, bob, charley");
room.states["m.room.canonical_alias"] = State(
senderId: "@test:example.com",
typeKey: "m.room.canonical_alias",
roomId: room.id,
room: room,
eventId: "123",
content: {"alias": "#testalias:example.com"},
stateKey: "");
expect(room.displayname, "testalias");
expect(room.canonicalAlias, "#testalias:example.com");
room.states["m.room.name"] = State(
senderId: "@test:example.com",
typeKey: "m.room.name",
roomId: room.id,
room: room,
eventId: "123",
content: {"name": "testname"},
stateKey: "");
expect(room.displayname, "testname");
expect(room.topic, "");
room.states["m.room.topic"] = State(
senderId: "@test:example.com",
typeKey: "m.room.topic",
roomId: room.id,
room: room,
eventId: "123",
content: {"topic": "testtopic"},
stateKey: "");
expect(room.topic, "testtopic");
expect(room.avatar.mxc, "");
room.states["m.room.avatar"] = State(
senderId: "@test:example.com",
typeKey: "m.room.avatar",
roomId: room.id,
room: room,
eventId: "123",
content: {"url": "mxc://testurl"},
stateKey: "");
expect(room.avatar.mxc, "mxc://testurl");
expect(room.lastEvent, null);
room.states["m.room.message"] = State(
senderId: "@test:example.com",
typeKey: "m.room.message",
roomId: room.id,
room: room,
eventId: "12345",
time: ChatTime.now(),
content: {"msgtype": "m.text", "body": "test"},
stateKey: "");
expect(room.lastEvent.eventId, "12345");
expect(room.lastMessage, "test");
expect(room.timeCreated, room.lastEvent.time);
}); });
test("sendReadReceipt", () async { test("sendReadReceipt", () async {
@ -165,5 +164,86 @@ void main() {
final Event event = await room.getEventById("1234"); final Event event = await room.getEventById("1234");
expect(event.eventId, "143273582443PhrSn:example.org"); expect(event.eventId, "143273582443PhrSn:example.org");
}); });
test("setName", () async {
final dynamic resp = await room.setName("Testname");
expect(resp["event_id"], "42");
});
test("setDescription", () async {
final dynamic resp = await room.setDescription("Testname");
expect(resp["event_id"], "42");
});
test("kick", () async {
final dynamic resp = await room.kick("Testname");
expect(resp, {});
});
test("ban", () async {
final dynamic resp = await room.ban("Testname");
expect(resp, {});
});
test("unban", () async {
final dynamic resp = await room.unban("Testname");
expect(resp, {});
});
test("PowerLevels", () async {
room.states["m.room.power_levels"] = State(
senderId: "@test:example.com",
typeKey: "m.room.power_levels",
roomId: room.id,
room: room,
eventId: "123",
content: {
"ban": 50,
"events": {"m.room.name": 100, "m.room.power_levels": 100},
"events_default": 0,
"invite": 50,
"kick": 50,
"notifications": {"room": 20},
"redact": 50,
"state_default": 50,
"users": {"@test:fakeServer.notExisting": 100},
"users_default": 10
},
stateKey: "");
expect(room.ownPowerLevel, 100);
expect(room.getPowerLevelByUserId(matrix.userID), room.ownPowerLevel);
expect(room.getPowerLevelByUserId("@nouser:example.com"), 10);
expect(room.powerLevels,
room.states["m.room.power_levels"].content["users"]);
final dynamic resp =
await room.setPower("@test:fakeServer.notExisting", 90);
expect(resp["event_id"], "42");
});
test("invite", () async {
final dynamic resp = await room.invite("Testname");
expect(resp, {});
});
test("addToDirectChat", () async {
final dynamic resp = await room.addToDirectChat("Testname");
expect(resp, {});
});
});
test("getTimeline", () async {
final Timeline timeline = await room.getTimeline();
expect(timeline.events, []);
});
test("loadEvents", () async {
final List<Event> events = await room.loadEvents();
expect(events, []);
});
test("getUserByMXID", () async {
final User user = await room.getUserByMXID("@getme:example.com");
expect(user.stateKey, "@getme:example.com");
expect(user.calcDisplayname(), "You got me");
}); });
} }