You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
420 lines
18 KiB
420 lines
18 KiB
import 'dart:async'; |
|
import 'dart:convert'; |
|
|
|
import 'package:built_value/json_object.dart'; |
|
import 'package:nextcloud/core.dart' as core; |
|
import 'package:nextcloud/spreed.dart' as spreed; |
|
import 'package:test/test.dart'; |
|
|
|
import 'helper.dart'; |
|
|
|
void main() { |
|
group( |
|
'spreed', |
|
() { |
|
late DockerImage image; |
|
setUpAll(() async => image = await getDockerImage()); |
|
|
|
late DockerContainer container; |
|
late TestNextcloudClient client1; |
|
setUp(() async { |
|
container = await getDockerContainer(image); |
|
client1 = await getTestClient(container); |
|
}); |
|
tearDown(() => container.destroy()); |
|
|
|
Future<spreed.Room> createTestRoom() async => (await client1.spreed.room.createRoom( |
|
roomType: spreed.RoomType.public.value, |
|
roomName: 'Test', |
|
)) |
|
.body |
|
.ocs |
|
.data; |
|
|
|
group('Helpers', () { |
|
test('Is supported', () async { |
|
final response = await client1.core.ocs.getCapabilities(); |
|
expect(response.statusCode, 200); |
|
expect(() => response.headers, isA<void>()); |
|
|
|
final result = client1.spreed.isSupported(response.body.ocs.data); |
|
expect(result.isSupported, isTrue); |
|
}); |
|
|
|
test('Participant permissions', () async { |
|
expect(spreed.ParticipantPermission.$default.value, 0); |
|
expect(spreed.ParticipantPermission.fromValue(0), {spreed.ParticipantPermission.$default}); |
|
expect({spreed.ParticipantPermission.$default}.value, 0); |
|
|
|
expect(spreed.ParticipantPermission.custom.value, 1); |
|
expect(spreed.ParticipantPermission.canSendMessageAndShareAndReact.value, 128); |
|
expect(spreed.ParticipantPermission.fromValue(129), { |
|
spreed.ParticipantPermission.custom, |
|
spreed.ParticipantPermission.canSendMessageAndShareAndReact, |
|
}); |
|
expect( |
|
{ |
|
spreed.ParticipantPermission.custom, |
|
spreed.ParticipantPermission.canSendMessageAndShareAndReact, |
|
}.value, |
|
129, |
|
); |
|
}); |
|
}); |
|
|
|
group('Room', () { |
|
test('Get rooms', () async { |
|
final response = await client1.spreed.room.getRooms(); |
|
expect(response.body.ocs.data, hasLength(1)); |
|
expect(response.body.ocs.data[0].id, 1); |
|
expect(response.body.ocs.data[0].token, isNotEmpty); |
|
expect(response.body.ocs.data[0].type, spreed.RoomType.changelog.value); |
|
expect(response.body.ocs.data[0].name, 'user1'); |
|
expect(response.body.ocs.data[0].displayName, 'Talk updates ✅'); |
|
expect(response.body.ocs.data[0].participantType, spreed.ParticipantType.user.value); |
|
expect(spreed.ParticipantPermission.fromValue(response.body.ocs.data[0].permissions), { |
|
spreed.ParticipantPermission.startCall, |
|
spreed.ParticipantPermission.joinCall, |
|
spreed.ParticipantPermission.canPublishAudio, |
|
spreed.ParticipantPermission.canPublishVideo, |
|
spreed.ParticipantPermission.canScreenShare, |
|
spreed.ParticipantPermission.canSendMessageAndShareAndReact, |
|
}); |
|
}); |
|
|
|
test('Session', () async { |
|
var room = await createTestRoom(); |
|
expect(room.sessionId, '0'); |
|
|
|
final response = await client1.spreed.room.joinRoom(token: room.token); |
|
expect(response.body.ocs.data.id, room.id); |
|
expect(response.body.ocs.data.sessionId, isNot(room.sessionId)); |
|
|
|
room = (await client1.spreed.room.getSingleRoom(token: room.token)).body.ocs.data; |
|
expect(room.sessionId, response.body.ocs.data.sessionId); |
|
|
|
await client1.spreed.room.leaveRoom(token: room.token); |
|
room = (await client1.spreed.room.getSingleRoom(token: room.token)).body.ocs.data; |
|
expect(room.sessionId, '0'); |
|
}); |
|
|
|
group('Create room', () { |
|
test('One-to-One', () async { |
|
final response = await client1.spreed.room.createRoom( |
|
roomType: spreed.RoomType.oneToOne.value, |
|
invite: 'user2', |
|
); |
|
expect(response.body.ocs.data.id, 1); |
|
expect(response.body.ocs.data.token, isNotEmpty); |
|
expect(response.body.ocs.data.type, spreed.RoomType.oneToOne.value); |
|
expect(response.body.ocs.data.name, 'user2'); |
|
expect(response.body.ocs.data.displayName, 'User Two'); |
|
expect(response.body.ocs.data.participantType, spreed.ParticipantType.owner.value); |
|
expect(spreed.ParticipantPermission.fromValue(response.body.ocs.data.permissions), { |
|
spreed.ParticipantPermission.startCall, |
|
spreed.ParticipantPermission.joinCall, |
|
spreed.ParticipantPermission.canIgnoreLobby, |
|
spreed.ParticipantPermission.canPublishAudio, |
|
spreed.ParticipantPermission.canPublishVideo, |
|
spreed.ParticipantPermission.canScreenShare, |
|
spreed.ParticipantPermission.canSendMessageAndShareAndReact, |
|
}); |
|
}); |
|
|
|
test('Group', () async { |
|
final response = await client1.spreed.room.createRoom( |
|
roomType: spreed.RoomType.group.value, |
|
invite: 'admin', |
|
); |
|
expect(response.body.ocs.data.id, 1); |
|
expect(response.body.ocs.data.token, isNotEmpty); |
|
expect(response.body.ocs.data.type, spreed.RoomType.group.value); |
|
expect(response.body.ocs.data.name, 'admin'); |
|
expect(response.body.ocs.data.displayName, 'admin'); |
|
expect(response.body.ocs.data.participantType, spreed.ParticipantType.owner.value); |
|
expect(spreed.ParticipantPermission.fromValue(response.body.ocs.data.permissions), { |
|
spreed.ParticipantPermission.startCall, |
|
spreed.ParticipantPermission.joinCall, |
|
spreed.ParticipantPermission.canIgnoreLobby, |
|
spreed.ParticipantPermission.canPublishAudio, |
|
spreed.ParticipantPermission.canPublishVideo, |
|
spreed.ParticipantPermission.canScreenShare, |
|
spreed.ParticipantPermission.canSendMessageAndShareAndReact, |
|
}); |
|
}); |
|
|
|
test('Public', () async { |
|
final response = await client1.spreed.room.createRoom( |
|
roomType: spreed.RoomType.public.value, |
|
roomName: 'abc', |
|
); |
|
expect(response.body.ocs.data.id, 1); |
|
expect(response.body.ocs.data.token, isNotEmpty); |
|
expect(response.body.ocs.data.type, spreed.RoomType.public.value); |
|
expect(response.body.ocs.data.name, 'abc'); |
|
expect(response.body.ocs.data.displayName, 'abc'); |
|
expect(response.body.ocs.data.participantType, spreed.ParticipantType.owner.value); |
|
expect(spreed.ParticipantPermission.fromValue(response.body.ocs.data.permissions), { |
|
spreed.ParticipantPermission.startCall, |
|
spreed.ParticipantPermission.joinCall, |
|
spreed.ParticipantPermission.canIgnoreLobby, |
|
spreed.ParticipantPermission.canPublishAudio, |
|
spreed.ParticipantPermission.canPublishVideo, |
|
spreed.ParticipantPermission.canScreenShare, |
|
spreed.ParticipantPermission.canSendMessageAndShareAndReact, |
|
}); |
|
}); |
|
}); |
|
}); |
|
|
|
group('Chat', () { |
|
test('Send message', () async { |
|
final startTime = DateTime.now(); |
|
final room = (await client1.spreed.room.createRoom( |
|
roomType: spreed.RoomType.oneToOne.value, |
|
invite: 'user2', |
|
)) |
|
.body |
|
.ocs |
|
.data; |
|
|
|
final response = await client1.spreed.chat.sendMessage( |
|
token: room.token, |
|
message: 'bla', |
|
); |
|
expect(response.body.ocs.data!.id, 2); |
|
expect(response.body.ocs.data!.actorType, spreed.ActorType.users.name); |
|
expect(response.body.ocs.data!.actorId, 'user1'); |
|
expect(response.body.ocs.data!.actorDisplayName, 'User One'); |
|
expectDateInReasonableTimeRange( |
|
DateTime.fromMillisecondsSinceEpoch(response.body.ocs.data!.timestamp * 1000), |
|
startTime, |
|
); |
|
expect(response.body.ocs.data!.message, 'bla'); |
|
expect(response.body.ocs.data!.messageType, spreed.MessageType.comment.name); |
|
}); |
|
|
|
group('Get messages', () { |
|
test('Directly', () async { |
|
final startTime = DateTime.now(); |
|
final room = (await client1.spreed.room.createRoom( |
|
roomType: spreed.RoomType.oneToOne.value, |
|
invite: 'user2', |
|
)) |
|
.body |
|
.ocs |
|
.data; |
|
await client1.spreed.chat.sendMessage( |
|
token: room.token, |
|
message: '123', |
|
replyTo: (await client1.spreed.chat.sendMessage( |
|
token: room.token, |
|
message: 'bla', |
|
)) |
|
.body |
|
.ocs |
|
.data! |
|
.id, |
|
); |
|
|
|
final response = await client1.spreed.chat.receiveMessages( |
|
token: room.token, |
|
lookIntoFuture: 0, |
|
); |
|
expect(response.headers.xChatLastGiven, '1'); |
|
expect(response.headers.xChatLastCommonRead, '1'); |
|
|
|
expect(response.body.ocs.data, hasLength(3)); |
|
|
|
expect(response.body.ocs.data[0].id, 3); |
|
expect(response.body.ocs.data[0].actorType, spreed.ActorType.users.name); |
|
expect(response.body.ocs.data[0].actorId, 'user1'); |
|
expect(response.body.ocs.data[0].actorDisplayName, 'User One'); |
|
expectDateInReasonableTimeRange( |
|
DateTime.fromMillisecondsSinceEpoch(response.body.ocs.data[0].timestamp * 1000), |
|
startTime, |
|
); |
|
expect(response.body.ocs.data[0].message, '123'); |
|
expect(response.body.ocs.data[0].messageType, spreed.MessageType.comment.name); |
|
|
|
expect(response.body.ocs.data[0].parent!.id, 2); |
|
expect(response.body.ocs.data[0].parent!.actorType, spreed.ActorType.users.name); |
|
expect(response.body.ocs.data[0].parent!.actorId, 'user1'); |
|
expect(response.body.ocs.data[0].parent!.actorDisplayName, 'User One'); |
|
expectDateInReasonableTimeRange( |
|
DateTime.fromMillisecondsSinceEpoch(response.body.ocs.data[0].parent!.timestamp * 1000), |
|
startTime, |
|
); |
|
expect(response.body.ocs.data[0].parent!.message, 'bla'); |
|
expect(response.body.ocs.data[0].parent!.messageType, spreed.MessageType.comment.name); |
|
|
|
expect(response.body.ocs.data[1].id, 2); |
|
expect(response.body.ocs.data[1].actorType, spreed.ActorType.users.name); |
|
expect(response.body.ocs.data[1].actorId, 'user1'); |
|
expect(response.body.ocs.data[1].actorDisplayName, 'User One'); |
|
expectDateInReasonableTimeRange( |
|
DateTime.fromMillisecondsSinceEpoch(response.body.ocs.data[1].timestamp * 1000), |
|
startTime, |
|
); |
|
expect(response.body.ocs.data[1].message, 'bla'); |
|
expect(response.body.ocs.data[1].messageType, spreed.MessageType.comment.name); |
|
|
|
expect(response.body.ocs.data[2].id, 1); |
|
expect(response.body.ocs.data[2].actorType, spreed.ActorType.users.name); |
|
expect(response.body.ocs.data[2].actorId, 'user1'); |
|
expect(response.body.ocs.data[2].actorDisplayName, 'User One'); |
|
expectDateInReasonableTimeRange( |
|
DateTime.fromMillisecondsSinceEpoch(response.body.ocs.data[2].timestamp * 1000), |
|
startTime, |
|
); |
|
expect(response.body.ocs.data[2].message, 'You created the conversation'); |
|
expect(response.body.ocs.data[2].systemMessage, 'conversation_created'); |
|
expect(response.body.ocs.data[2].messageType, spreed.MessageType.system.name); |
|
}); |
|
|
|
test('Polling', () async { |
|
final startTime = DateTime.now(); |
|
|
|
final room = await createTestRoom(); |
|
final message = (await client1.spreed.chat.sendMessage( |
|
token: room.token, |
|
message: 'bla', |
|
)) |
|
.body |
|
.ocs |
|
.data!; |
|
unawaited( |
|
Future<void>.delayed(const Duration(seconds: 1)).then((final _) async { |
|
await client1.spreed.chat.sendMessage( |
|
token: room.token, |
|
message: '123', |
|
); |
|
}), |
|
); |
|
|
|
final response = await client1.spreed.chat.receiveMessages( |
|
token: room.token, |
|
lookIntoFuture: 1, |
|
timeout: 3, |
|
lastKnownMessageId: message.id, |
|
); |
|
expect(response.body.ocs.data, hasLength(1)); |
|
expect(response.body.ocs.data[0].id, 3); |
|
expect(response.body.ocs.data[0].actorType, spreed.ActorType.users.name); |
|
expect(response.body.ocs.data[0].actorId, 'user1'); |
|
expect(response.body.ocs.data[0].actorDisplayName, 'User One'); |
|
expectDateInReasonableTimeRange( |
|
DateTime.fromMillisecondsSinceEpoch(response.body.ocs.data[0].timestamp * 1000), |
|
startTime, |
|
); |
|
expect(response.body.ocs.data[0].message, '123'); |
|
expect(response.body.ocs.data[0].messageType, spreed.MessageType.comment.name); |
|
}); |
|
}); |
|
}); |
|
|
|
group('Call', () { |
|
test('Start and end call', () async { |
|
var room = await createTestRoom(); |
|
expect(room.hasCall, isFalse); |
|
room = (await client1.spreed.room.joinRoom(token: room.token)).body.ocs.data; |
|
|
|
await client1.spreed.call.joinCall(token: room.token); |
|
room = (await client1.spreed.room.getSingleRoom(token: room.token)).body.ocs.data; |
|
expect(room.hasCall, isTrue); |
|
|
|
await client1.spreed.call.leaveCall(token: room.token); |
|
room = (await client1.spreed.room.getSingleRoom(token: room.token)).body.ocs.data; |
|
expect(room.hasCall, isFalse); |
|
}); |
|
}); |
|
|
|
group('Signaling', () { |
|
test('Get settings', () async { |
|
final room = await createTestRoom(); |
|
|
|
final response = await client1.spreed.signaling.getSettings(token: room.token); |
|
expect(response.body.ocs.data.signalingMode, 'internal'); |
|
expect(response.body.ocs.data.userId, 'user1'); |
|
expect(response.body.ocs.data.hideWarning, false); |
|
expect(response.body.ocs.data.server, ''); |
|
expect(response.body.ocs.data.ticket, contains(':user1:')); |
|
expect(response.body.ocs.data.helloAuthParams.$10.userid, 'user1'); |
|
expect(response.body.ocs.data.helloAuthParams.$10.ticket, contains(':user1:')); |
|
expect(response.body.ocs.data.helloAuthParams.$20.token.split('').where((final x) => x == '.'), hasLength(2)); |
|
expect(response.body.ocs.data.stunservers, hasLength(1)); |
|
expect(response.body.ocs.data.stunservers[0].urls, hasLength(1)); |
|
expect(response.body.ocs.data.stunservers[0].urls[0], 'stun:stun.nextcloud.com:443'); |
|
expect(response.body.ocs.data.turnservers, hasLength(1)); |
|
expect(response.body.ocs.data.turnservers[0].urls, hasLength(4)); |
|
expect( |
|
response.body.ocs.data.turnservers[0].urls[0], |
|
'turn:staticauth.openrelay.metered.ca:443?transport=udp', |
|
); |
|
expect( |
|
response.body.ocs.data.turnservers[0].urls[1], |
|
'turn:staticauth.openrelay.metered.ca:443?transport=tcp', |
|
); |
|
expect( |
|
response.body.ocs.data.turnservers[0].urls[2], |
|
'turns:staticauth.openrelay.metered.ca:443?transport=udp', |
|
); |
|
expect( |
|
response.body.ocs.data.turnservers[0].urls[3], |
|
'turns:staticauth.openrelay.metered.ca:443?transport=tcp', |
|
); |
|
expect(response.body.ocs.data.turnservers[0].username, isNotEmpty); |
|
expect((response.body.ocs.data.turnservers[0].credential as StringJsonObject).asString, isNotEmpty); |
|
expect(response.body.ocs.data.sipDialinInfo, ''); |
|
}); |
|
|
|
test('Send and receive messages', () async { |
|
final room = (await client1.spreed.room.createRoom( |
|
roomType: spreed.RoomType.oneToOne.value, |
|
invite: 'user2', |
|
)) |
|
.body |
|
.ocs |
|
.data; |
|
|
|
final room1 = (await client1.spreed.room.joinRoom(token: room.token)).body.ocs.data; |
|
await client1.spreed.call.joinCall(token: room.token); |
|
|
|
final client2 = await getTestClient( |
|
container, |
|
username: 'user2', |
|
); |
|
|
|
final room2 = (await client2.spreed.room.joinRoom(token: room.token)).body.ocs.data; |
|
await client2.spreed.call.joinCall(token: room.token); |
|
|
|
await client1.spreed.signaling.sendMessages( |
|
token: room.token, |
|
messages: json.encode([ |
|
{ |
|
'ev': 'message', |
|
'sessionId': room1.sessionId, |
|
'fn': json.encode({ |
|
'to': room2.sessionId, |
|
}), |
|
}, |
|
]), |
|
); |
|
|
|
await Future<void>.delayed(const Duration(seconds: 1)); |
|
|
|
final messages = (await client2.spreed.signaling.pullMessages(token: room.token)).body.ocs.data; |
|
expect(messages, hasLength(2)); |
|
expect(messages[0].type, 'message'); |
|
expect(json.decode(messages[0].data.string!), {'to': room2.sessionId, 'from': room1.sessionId}); |
|
expect(messages[1].type, 'usersInRoom'); |
|
expect(messages[1].data.builtListSignalingSession, hasLength(2)); |
|
expect(messages[1].data.builtListSignalingSession![0].userId, 'user1'); |
|
expect(messages[1].data.builtListSignalingSession![1].userId, 'user2'); |
|
}); |
|
}); |
|
}, |
|
retry: retryCount, |
|
timeout: timeout, |
|
); |
|
}
|
|
|