add core/api tests

Signed-off-by: Sahil Kumar <[email protected]>
This commit is contained in:
Sahil Kumar
2021-06-08 16:09:17 +05:30
parent bdfbc27917
commit 89f989003d
35 changed files with 1788 additions and 56 deletions
@@ -38,10 +38,6 @@ import 'package:stream_chat/src/core/models/member.dart';
/// [LogRecord] as the only parameter.
typedef LogHandlerFunction = void Function(LogRecord record);
/// A function which can be used to request a Stream Chat API token from your
/// own backend server. Function requires a single [userId].
typedef TokenProvider = Future<String> Function(String userId);
final _levelEmojiMapper = {
Level.INFO: '',
Level.WARNING: '⚠️',
@@ -583,7 +579,6 @@ class StreamChatClient {
}
logger.info('Query channel start');
print('Query Channel Started : ${DateTime.now()}');
final res = await _chatApi.channel.queryChannels(
filter: filter,
sort: sort,
@@ -594,7 +589,6 @@ class StreamChatClient {
messageLimit: messageLimit,
paginationParams: paginationParams,
);
print('Query Channel Completed : ${DateTime.now()}');
if (res.channels.isEmpty && paginationParams.offset == 0) {
logger.warning('''
@@ -1,7 +1,6 @@
import 'package:dio/dio.dart';
import 'package:stream_chat/src/core/api/responses.dart';
import 'package:stream_chat/src/core/http/stream_http_client.dart';
import 'package:stream_chat/src/core/util/extension.dart';
import 'package:stream_chat/src/core/models/attachment_file.dart';
/// Class responsible for uploading images and files to a given channel
@@ -70,29 +69,10 @@ class StreamAttachmentFileUploader implements AttachmentFileUploader {
ProgressCallback? onSendProgress,
CancelToken? cancelToken,
}) async {
final filename = file.path?.split('/').last ?? file.name;
final mimeType = filename?.mimeType;
MultipartFile? multiPartFile;
if (file.path != null) {
multiPartFile = await MultipartFile.fromFile(
file.path!,
filename: filename,
contentType: mimeType,
);
} else if (file.bytes != null) {
multiPartFile = MultipartFile.fromBytes(
file.bytes!,
filename: filename,
contentType: mimeType,
);
}
final response = await _client.post(
final multiPartFile = await file.toMultipartFile();
final response = await _client.postFile(
'/channels/$channelType/$channelId/image',
data: FormData.fromMap({
'file': multiPartFile,
}),
multiPartFile,
onSendProgress: onSendProgress,
cancelToken: cancelToken,
);
@@ -107,29 +87,10 @@ class StreamAttachmentFileUploader implements AttachmentFileUploader {
ProgressCallback? onSendProgress,
CancelToken? cancelToken,
}) async {
final filename = file.path?.split('/').last ?? file.name;
final mimeType = filename?.mimeType;
MultipartFile? multiPartFile;
if (file.path != null) {
multiPartFile = await MultipartFile.fromFile(
file.path!,
filename: filename,
contentType: mimeType,
);
} else if (file.bytes != null) {
multiPartFile = MultipartFile.fromBytes(
file.bytes!,
filename: filename,
contentType: mimeType,
);
}
final response = await _client.post(
final multiPartFile = await file.toMultipartFile();
final response = await _client.postFile(
'/channels/$channelType/$channelId/file',
data: FormData.fromMap({
'file': multiPartFile,
}),
multiPartFile,
onSendProgress: onSendProgress,
cancelToken: cancelToken,
);
@@ -59,7 +59,6 @@ class ChannelApi {
bool presence = false,
PaginationParams paginationParams = const PaginationParams(),
}) async {
print('Query Channel Started 2 : ${DateTime.now()}');
final response = await _client.get(
'/channels',
queryParameters: {
@@ -80,7 +79,6 @@ class ChannelApi {
})
},
);
print('Query Channel Completed 2 : ${DateTime.now()}');
return QueryChannelsResponse.fromJson(response.data);
}
@@ -10,7 +10,8 @@ enum PushProvider {
apn
}
extension on PushProvider {
/// Helper extension for [PushProvider]
extension PushProviderX on PushProvider {
/// Returns the string notion for [PushProvider].
String get name => {
PushProvider.apn: 'apn',
@@ -1,9 +1,13 @@
import 'dart:typed_data';
import 'package:dio/dio.dart' show MultipartFile;
import 'package:freezed_annotation/freezed_annotation.dart';
import 'package:meta/meta.dart';
import 'package:stream_chat/src/core/platform_detector/platform_detector.dart';
import 'package:stream_chat/src/core/util/extension.dart';
part 'attachment_file.freezed.dart';
part 'attachment_file.g.dart';
/// Union class to hold various [UploadState] of a attachment.
@@ -58,14 +62,18 @@ String? _toString(Uint8List? bytes) {
@JsonSerializable()
class AttachmentFile {
/// Creates a new [AttachmentFile] instance.
const AttachmentFile({
AttachmentFile({
required this.size,
this.path,
this.name,
this.bytes,
}) : assert(
}) : assert(
path != null || bytes != null,
'Either path or bytes should be != null',
),
assert(
!CurrentPlatform.isWeb || bytes != null,
'File by path is not supported in web, Please provide bytes',
);
/// Create a new instance from a json
@@ -95,4 +103,27 @@ class AttachmentFile {
/// Serialize to json
Map<String, dynamic> toJson() => _$AttachmentFileToJson(this);
/// Converts this into a [MultipartFile]
Future<MultipartFile> toMultipartFile() async {
final filename = path?.split('/').last ?? name;
final mimeType = filename?.mimeType;
late MultipartFile multiPartFile;
if (CurrentPlatform.isWeb) {
multiPartFile = MultipartFile.fromBytes(
bytes!,
filename: filename,
contentType: mimeType,
);
} else {
multiPartFile = await MultipartFile.fromFile(
path!,
filename: filename,
contentType: mimeType,
);
}
return multiPartFile;
}
}
@@ -0,0 +1,57 @@
%PDF-1.7
%µí®û
3 0 obj
<< /Length 4 0 R >>
stream
/DeviceRGB cs /DeviceRGB CS
0 0 0.972549 SC
21.68 194 136.64 26 re
10 10 m 20 20 l S
BT
/F0 24 Tf
25.68 200 Td
(Hello World!) Tj
ET
endstream
endobj
4 0 obj
132
endobj
5 0 obj
<< /Type /Font /Subtype /Type1 /BaseFont /Times-Roman /Encoding /WinAnsiEncoding >>
endobj
6 0 obj
<< /Type /Page
/Parent 2 0 R
/Resources << /Font << /F0 5 0 R >> >>
/MediaBox [ 0 0 180 240 ]
/Contents 3 0 R
>>
endobj
2 0 obj
<< /Type /Pages
/Count 1
/Kids [ 6 0 R ]
>>
endobj
1 0 obj
<< /Type /Catalog
/Pages 2 0 R
>>
endobj
xref
0 7
0000000000 65535 f
0000000522 00000 n
0000000457 00000 n
0000000015 00000 n
0000000199 00000 n
0000000218 00000 n
0000000317 00000 n
trailer
<< /Size 7
/Root 1 0 R
>>
startxref
574
%%EOF
Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

@@ -0,0 +1,136 @@
import 'package:dio/dio.dart';
import 'package:mocktail/mocktail.dart';
import 'package:stream_chat/src/core/api/attachment_file_uploader.dart';
import 'package:stream_chat/src/core/models/attachment_file.dart';
import 'package:test/test.dart';
import '../../fakes.dart';
import '../../matchers.dart';
import '../../mocks.dart';
import '../../utils.dart';
void main() {
late final client = MockHttpClient();
late StreamAttachmentFileUploader fileUploader;
setUp(() {
fileUploader = StreamAttachmentFileUploader(client);
registerFallbackValue<MultipartFile>(FakeMultiPartFile());
});
Response successResponse(String path, {Object? data}) => Response(
data: data,
requestOptions: RequestOptions(path: path),
statusCode: 200,
);
test('sendImage', () async {
const channelId = 'test-channel-id';
const channelType = 'test-channel-type';
const path = '/channels/$channelType/$channelId/image';
final file = assetFile('test_image.jpeg');
final attachmentFile = AttachmentFile(
size: 333,
path: file.path,
bytes: file.readAsBytesSync(),
);
final multipartFile = await attachmentFile.toMultipartFile();
when(() => client.postFile(
path,
any(that: isSameMultipartFileAs(multipartFile)),
)).thenAnswer((_) async => successResponse(path, data: {
'file': 'test-file-url',
}));
final res = await fileUploader.sendImage(
attachmentFile,
channelId,
channelType,
);
expect(res, isNotNull);
expect(res.file, isNotNull);
expect(res.file, isNotEmpty);
verify(() => client.postFile(
path,
any(that: isSameMultipartFileAs(multipartFile)),
)).called(1);
verifyNoMoreInteractions(client);
});
test('sendFile', () async {
const channelId = 'test-channel-id';
const channelType = 'test-channel-type';
const path = '/channels/$channelType/$channelId/file';
final file = assetFile('example.pdf');
final attachmentFile = AttachmentFile(
size: 333,
path: file.path,
bytes: file.readAsBytesSync(),
);
final multipartFile = await attachmentFile.toMultipartFile();
when(() => client.postFile(
path,
any(that: isSameMultipartFileAs(multipartFile)),
)).thenAnswer((_) async => successResponse(path, data: {
'file': 'test-file-url',
}));
final res = await fileUploader.sendFile(
attachmentFile,
channelId,
channelType,
);
expect(res, isNotNull);
expect(res.file, isNotNull);
expect(res.file, isNotEmpty);
verify(() => client.postFile(
path,
any(that: isSameMultipartFileAs(multipartFile)),
)).called(1);
verifyNoMoreInteractions(client);
});
test('deleteImage', () async {
const channelId = 'test-channel-id';
const channelType = 'test-channel-type';
const path = '/channels/$channelType/$channelId/image';
const url = 'test-image-url';
when(() => client.delete(path, queryParameters: {'url': url})).thenAnswer(
(_) async => successResponse(path, data: <String, dynamic>{}));
final res = await fileUploader.deleteImage(url, channelId, channelType);
expect(res, isNotNull);
verify(() => client.delete(path, queryParameters: {'url': url})).called(1);
verifyNoMoreInteractions(client);
});
test('deleteFile', () async {
const channelId = 'test-channel-id';
const channelType = 'test-channel-type';
const path = '/channels/$channelType/$channelId/file';
const url = 'test-file-url';
when(() => client.delete(path, queryParameters: {'url': url})).thenAnswer(
(_) async => successResponse(path, data: <String, dynamic>{}));
final res = await fileUploader.deleteFile(url, channelId, channelType);
expect(res, isNotNull);
verify(() => client.delete(path, queryParameters: {'url': url})).called(1);
verifyNoMoreInteractions(client);
});
}
@@ -0,0 +1,492 @@
import 'package:dio/dio.dart';
import 'package:mocktail/mocktail.dart';
import 'package:stream_chat/src/core/api/channel_api.dart';
import 'package:stream_chat/src/core/models/channel_model.dart';
import 'package:stream_chat/src/core/models/channel_state.dart';
import 'package:stream_chat/stream_chat.dart';
import 'package:test/test.dart';
import '../../mocks.dart';
void main() {
String _getChannelUrl(String channelId, String channelType) =>
'/channels/$channelType/$channelId';
ChannelState _generateChannelState(
String channelId,
String channelType,
) {
final channel = ChannelModel(id: channelId, type: channelType);
final messages = List.generate(
3,
(index) => Message(
id: 'test-message-id-$index',
text: 'test-message-text-$index',
),
);
final members = List.generate(
3,
(index) => Member(userId: 'test-user-id-$index'),
);
final reads = List.generate(
3,
(index) => Read(
lastRead: DateTime.now(),
user: User(id: 'test-user-id-$index'),
),
);
final watchers = List.generate(
3,
(index) => User(id: 'test-user-id-$index'),
);
final state = ChannelState(
channel: channel,
messages: messages,
pinnedMessages: messages,
members: members,
read: reads,
watchers: watchers,
watcherCount: watchers.length,
);
return state;
}
Response successResponse(String path, {Object? data}) => Response(
data: data,
requestOptions: RequestOptions(path: path),
statusCode: 200,
);
late final client = MockHttpClient();
late ChannelApi channelApi;
setUp(() {
channelApi = ChannelApi(client);
});
test('queryChannel', () async {
const channelId = 'test-channel-id';
const channelType = 'test-channel-type';
const channelData = <String, Object>{'name': 'test-channel'};
const messagePagination = PaginationParams();
const membersPagination = PaginationParams();
const watchersPagination = PaginationParams();
const channelPath = '/channels/$channelType/$channelId';
const path = '$channelPath/query';
final channelState = _generateChannelState(channelId, channelType);
when(() => client.post(path, data: any(named: 'data')))
.thenAnswer((_) async => successResponse(
path,
data: channelState.toJson(),
));
final res = await channelApi.queryChannel(
channelType,
channelId: channelId,
channelData: channelData,
messagesPagination: messagePagination,
membersPagination: membersPagination,
watchersPagination: watchersPagination,
);
expect(res, isNotNull);
expect(res.messages.length, channelState.messages.length);
expect(res.pinnedMessages.length, channelState.pinnedMessages.length);
expect(res.members.length, channelState.members.length);
expect(res.read.length, channelState.read.length);
expect(res.watchers.length, channelState.watchers.length);
expect(res.watcherCount, channelState.watcherCount);
verify(() => client.post(path, data: any(named: 'data'))).called(1);
verifyNoMoreInteractions(client);
});
test('queryChannels', () async {
const channelId = 'test-channel-id';
const channelType = 'test-channel-type';
final filter = Filter.in_('cid', const ['test-cid']);
const sort = [SortOption<ChannelModel>('test-field')];
const memberLimit = 33;
const messageLimit = 33;
const path = '/channels';
final channelState = _generateChannelState(channelId, channelType);
when(() => client.get(path, queryParameters: any(named: 'queryParameters')))
.thenAnswer((_) async => successResponse(
path,
data: {
'channels': [channelState.toJson()]
},
));
final res = await channelApi.queryChannels(
filter: filter,
sort: sort,
memberLimit: memberLimit,
messageLimit: messageLimit,
);
expect(res, isNotNull);
expect(res.channels, isNotEmpty);
verify(
() => client.get(path, queryParameters: any(named: 'queryParameters')),
).called(1);
verifyNoMoreInteractions(client);
});
test('markAllRead', () async {
const path = 'channels/read';
when(() => client.post(path)).thenAnswer(
(_) async => successResponse(path, data: <String, dynamic>{}));
final res = await channelApi.markAllRead();
expect(res, isNotNull);
verify(() => client.post(path)).called(1);
verifyNoMoreInteractions(client);
});
test('updateChannel', () async {
const channelId = 'test-channel-id';
const channelType = 'test-channel-type';
const data = {'name': 'test-channel-name'};
final message = Message(id: 'test-message-id', text: 'channel-updated');
final path = _getChannelUrl(channelId, channelType);
final channelModel = ChannelModel(
id: channelId,
type: channelType,
extraData: data,
);
when(() => client.post(path, data: any(named: 'data')))
.thenAnswer((_) async => successResponse(path, data: {
'channel': channelModel.toJson(),
'message': message.toJson(),
}));
final res = await channelApi.updateChannel(
channelId,
channelType,
data,
message: message,
);
expect(res, isNotNull);
expect(res.channel.cid, channelModel.cid);
expect(res.message?.id, message.id);
verify(() => client.post(path, data: any(named: 'data'))).called(1);
verifyNoMoreInteractions(client);
});
test('updateChannelPartial', () async {
const channelId = 'test-channel-id';
const channelType = 'test-channel-type';
const data = {'name': 'test-channel-name'};
final path = _getChannelUrl(channelId, channelType);
final channelModel = ChannelModel(
id: channelId,
type: channelType,
extraData: data,
);
when(() => client.patch(path, data: any(named: 'data')))
.thenAnswer((_) async => successResponse(path, data: {
'channel': channelModel.toJson(),
}));
final res = await channelApi.updateChannelPartial(
channelId,
channelType,
data,
);
expect(res, isNotNull);
verify(() => client.patch(path, data: any(named: 'data'))).called(1);
verifyNoMoreInteractions(client);
});
test('acceptChannelInvite', () async {
const channelId = 'test-channel-id';
const channelType = 'test-channel-type';
final message = Message(id: 'test-message-id', text: 'channel-accepted');
final channelModel = ChannelModel(id: channelId, type: channelType);
final path = _getChannelUrl(channelId, channelType);
when(() => client.post(path, data: any(named: 'data')))
.thenAnswer((_) async => successResponse(path, data: {
'channel': channelModel.toJson(),
'message': message.toJson(),
}));
final res = await channelApi.acceptChannelInvite(
channelId,
channelType,
message: message,
);
expect(res, isNotNull);
expect(res.channel.cid, channelModel.cid);
expect(res.message?.id, message.id);
verify(() => client.post(path, data: any(named: 'data'))).called(1);
verifyNoMoreInteractions(client);
});
test('rejectChannelInvite', () async {
const channelId = 'test-channel-id';
const channelType = 'test-channel-type';
final message = Message(id: 'test-message-id', text: 'channel-rejected');
final channelModel = ChannelModel(id: channelId, type: channelType);
final path = _getChannelUrl(channelId, channelType);
when(() => client.post(path, data: any(named: 'data')))
.thenAnswer((_) async => successResponse(path, data: {
'channel': channelModel.toJson(),
'message': message.toJson(),
}));
final res = await channelApi.rejectChannelInvite(
channelId,
channelType,
message: message,
);
expect(res, isNotNull);
expect(res.channel.cid, channelModel.cid);
expect(res.message?.id, message.id);
verify(() => client.post(path, data: any(named: 'data'))).called(1);
verifyNoMoreInteractions(client);
});
test('inviteChannelMembers', () async {
const channelId = 'test-channel-id';
const channelType = 'test-channel-type';
const memberIds = ['test-member-id-1', 'test-member-id-2'];
final channelModel = ChannelModel(id: channelId, type: channelType);
final message = Message(id: 'test-message-id', text: 'members-invited');
final path = _getChannelUrl(channelId, channelType);
when(() => client.post(path, data: any(named: 'data')))
.thenAnswer((_) async => successResponse(path, data: {
'channel': channelModel.toJson(),
'message': message.toJson(),
}));
final res = await channelApi.inviteChannelMembers(
channelId,
channelType,
memberIds,
message: message,
);
expect(res, isNotNull);
expect(res.channel.cid, channelModel.cid);
expect(res.message?.id, message.id);
verify(() => client.post(path, data: any(named: 'data'))).called(1);
verifyNoMoreInteractions(client);
});
test('addMembers', () async {
const channelId = 'test-channel-id';
const channelType = 'test-channel-type';
const memberIds = ['test-member-id-1', 'test-member-id-2'];
final channelModel = ChannelModel(id: channelId, type: channelType);
final message = Message(id: 'test-message-id', text: 'members-added');
final path = _getChannelUrl(channelId, channelType);
when(() => client.post(path, data: any(named: 'data')))
.thenAnswer((_) async => successResponse(path, data: {
'channel': channelModel.toJson(),
'message': message.toJson(),
}));
final res = await channelApi.addMembers(
channelId,
channelType,
memberIds,
message: message,
);
expect(res, isNotNull);
expect(res.channel.cid, channelModel.cid);
expect(res.message?.id, message.id);
verify(() => client.post(path, data: any(named: 'data'))).called(1);
verifyNoMoreInteractions(client);
});
test('removeMembers', () async {
const channelId = 'test-channel-id';
const channelType = 'test-channel-type';
const memberIds = ['test-member-id-1', 'test-member-id-2'];
final channelModel = ChannelModel(id: channelId, type: channelType);
final message = Message(id: 'test-message-id', text: 'members-removed');
final path = _getChannelUrl(channelId, channelType);
when(() => client.post(path, data: any(named: 'data')))
.thenAnswer((_) async => successResponse(path, data: {
'channel': channelModel.toJson(),
'message': message.toJson(),
}));
final res = await channelApi.removeMembers(
channelId,
channelType,
memberIds,
message: message,
);
expect(res, isNotNull);
expect(res.channel.cid, channelModel.cid);
expect(res.message?.id, message.id);
verify(() => client.post(path, data: any(named: 'data'))).called(1);
verifyNoMoreInteractions(client);
});
test('sendEvent', () async {
const channelId = 'test-channel-id';
const channelType = 'test-channel-type';
final event = Event(type: 'event.test');
final path = '${_getChannelUrl(channelId, channelType)}/event';
when(() => client.post(path, data: any(named: 'data'))).thenAnswer(
(_) async => successResponse(path, data: <String, dynamic>{}));
final res = await channelApi.sendEvent(channelId, channelType, event);
expect(res, isNotNull);
verify(() => client.post(path, data: any(named: 'data'))).called(1);
verifyNoMoreInteractions(client);
});
test('deleteChannel', () async {
const channelId = 'test-channel-id';
const channelType = 'test-channel-type';
final path = _getChannelUrl(channelId, channelType);
when(() => client.delete(path)).thenAnswer(
(_) async => successResponse(path, data: <String, dynamic>{}));
final res = await channelApi.deleteChannel(channelId, channelType);
expect(res, isNotNull);
verify(() => client.delete(path)).called(1);
verifyNoMoreInteractions(client);
});
test('truncateChannel', () async {
const channelId = 'test-channel-id';
const channelType = 'test-channel-type';
final path = '${_getChannelUrl(channelId, channelType)}/truncate';
when(() => client.post(path)).thenAnswer(
(_) async => successResponse(path, data: <String, dynamic>{}));
final res = await channelApi.truncateChannel(channelId, channelType);
expect(res, isNotNull);
verify(() => client.post(path)).called(1);
verifyNoMoreInteractions(client);
});
test('hideChannel', () async {
const channelId = 'test-channel-id';
const channelType = 'test-channel-type';
final path = '${_getChannelUrl(channelId, channelType)}/hide';
when(() => client.post(path, data: any(named: 'data'))).thenAnswer(
(_) async => successResponse(path, data: <String, dynamic>{}));
final res = await channelApi.hideChannel(channelId, channelType);
expect(res, isNotNull);
verify(() => client.post(path, data: any(named: 'data'))).called(1);
verifyNoMoreInteractions(client);
});
test('showChannel', () async {
const channelId = 'test-channel-id';
const channelType = 'test-channel-type';
final path = '${_getChannelUrl(channelId, channelType)}/show';
when(() => client.post(path)).thenAnswer(
(_) async => successResponse(path, data: <String, dynamic>{}));
final res = await channelApi.showChannel(channelId, channelType);
expect(res, isNotNull);
verify(() => client.post(path)).called(1);
verifyNoMoreInteractions(client);
});
test('markRead', () async {
const channelId = 'test-channel-id';
const channelType = 'test-channel-type';
const messageId = 'test-message-id';
final path = '${_getChannelUrl(channelId, channelType)}/read';
when(() => client.post(path, data: any(named: 'data'))).thenAnswer(
(_) async => successResponse(path, data: <String, dynamic>{}));
final res = await channelApi.markRead(
channelId,
channelType,
messageId: messageId,
);
expect(res, isNotNull);
verify(() => client.post(path, data: any(named: 'data'))).called(1);
verifyNoMoreInteractions(client);
});
test('stopWatching', () async {
const channelId = 'test-channel-id';
const channelType = 'test-channel-type';
final path = '${_getChannelUrl(channelId, channelType)}/stop-watching';
when(() => client.post(path)).thenAnswer(
(_) async => successResponse(path, data: <String, dynamic>{}));
final res = await channelApi.stopWatching(channelId, channelType);
expect(res, isNotNull);
verify(() => client.post(path)).called(1);
verifyNoMoreInteractions(client);
});
}
@@ -0,0 +1,84 @@
import 'package:dio/dio.dart';
import 'package:mocktail/mocktail.dart';
import 'package:stream_chat/src/core/api/device_api.dart';
import 'package:stream_chat/stream_chat.dart';
import 'package:test/test.dart';
import '../../mocks.dart';
void main() {
Response successResponse(String path, {Object? data}) => Response(
data: data,
requestOptions: RequestOptions(path: path),
statusCode: 200,
);
late final client = MockHttpClient();
late DeviceApi deviceApi;
setUp(() {
deviceApi = DeviceApi(client);
});
test('addDevice', () async {
const deviceId = 'test-device-id';
const pushProvider = PushProvider.firebase;
const path = '/devices';
when(() => client.post(path, data: any(named: 'data'))).thenAnswer(
(_) async => successResponse(path, data: <String, dynamic>{}));
final res = await deviceApi.addDevice(deviceId, pushProvider);
expect(res, isNotNull);
verify(() => client.post(path, data: any(named: 'data'))).called(1);
verifyNoMoreInteractions(client);
});
test('getDevices', () async {
const path = '/devices';
final devices = List.generate(
3,
(index) => Device(
id: 'test-device-id-$index',
pushProvider: PushProvider.firebase.name,
),
);
when(() => client.get(path)).thenAnswer(
(_) async => successResponse(path, data: {
'devices': [...devices.map((it) => it.toJson())]
}),
);
final res = await deviceApi.getDevices();
expect(res, isNotNull);
expect(res.devices.length, devices.length);
verify(() => client.get(path)).called(1);
verifyNoMoreInteractions(client);
});
test('removeDevice', () async {
const deviceId = 'test-device-id';
const path = '/devices';
when(
() => client.delete(path, queryParameters: any(named: 'queryParameters')),
).thenAnswer((_) async => successResponse(path, data: <String, dynamic>{}));
final res = await deviceApi.removeDevice(deviceId);
expect(res, isNotNull);
verify(
() => client.delete(path, queryParameters: any(named: 'queryParameters')),
).called(1);
verifyNoMoreInteractions(client);
});
}
@@ -0,0 +1,211 @@
import 'package:dio/dio.dart';
import 'package:mocktail/mocktail.dart';
import 'package:stream_chat/src/core/api/general_api.dart';
import 'package:stream_chat/src/core/api/requests.dart';
import 'package:stream_chat/src/core/models/channel_model.dart';
import 'package:stream_chat/src/core/models/event.dart';
import 'package:stream_chat/src/core/models/filter.dart';
import 'package:stream_chat/stream_chat.dart';
import 'package:test/test.dart';
import '../../mocks.dart';
void main() {
Response successResponse(String path, {Object? data}) => Response(
data: data,
requestOptions: RequestOptions(path: path),
statusCode: 200,
);
late final client = MockHttpClient();
late GeneralApi generalApi;
setUp(() {
generalApi = GeneralApi(client);
});
test('sync', () async {
const cids = ['test-cid-1', 'test-cid-2', 'test-cid-3'];
final lastSyncAt = DateTime.now();
const path = '/sync';
final events =
List.generate(3, (index) => Event(type: 'test-event-type-$index'));
when(() => client.post(path, data: any(named: 'data')))
.thenAnswer((_) async => successResponse(path, data: {
'events': [...events.map((it) => it.toJson())]
}));
final res = await generalApi.sync(cids, lastSyncAt);
expect(res, isNotNull);
verify(() => client.post(path, data: any(named: 'data'))).called(1);
verifyNoMoreInteractions(client);
});
group('searchMessages', () {
test(
'should throw if `query` and `messageFilters` is not provided',
() async {
final filter = Filter.in_('cid', const ['test-cid-1', 'test-cid-2']);
try {
await generalApi.searchMessages(filter);
} catch (e) {
expect(e, isA<ArgumentError>());
}
},
);
test(
'should throw if `query` and `messageFilters` both are provided',
() async {
final filter = Filter.in_('cid', const ['test-cid-1', 'test-cid-2']);
const query = 'test-query';
final messageFilter = Filter.query('key', 'text');
try {
await generalApi.searchMessages(
filter,
query: query,
messageFilters: messageFilter,
);
} catch (e) {
expect(e, isA<ArgumentError>());
}
},
);
test('should run successfully with `query`', () async {
final filter = Filter.in_('cid', const ['test-cid-1', 'test-cid-2']);
const query = 'test-query';
const sort = [SortOption<ChannelModel>('test-field')];
const pagination = PaginationParams();
const path = '/search';
when(
() => client.get(path, queryParameters: any(named: 'queryParameters')),
).thenAnswer((_) async => successResponse(path, data: {'results': []}));
final res = await generalApi.searchMessages(
filter,
query: query,
sort: sort,
pagination: pagination,
);
expect(res, isNotNull);
expect(res.results, isEmpty);
verify(
() => client.get(path, queryParameters: any(named: 'queryParameters')),
).called(1);
verifyNoMoreInteractions(client);
});
test('should run successfully with `messageFilter`', () async {
final filter = Filter.in_('cid', const ['test-cid-1', 'test-cid-2']);
const sort = [SortOption<ChannelModel>('test-field')];
final messageFilter = Filter.query('key', 'text');
const pagination = PaginationParams();
const path = '/search';
when(
() => client.get(path, queryParameters: any(named: 'queryParameters')),
).thenAnswer((_) async => successResponse(path, data: {'results': []}));
final res = await generalApi.searchMessages(
filter,
messageFilters: messageFilter,
sort: sort,
pagination: pagination,
);
expect(res, isNotNull);
expect(res.results, isEmpty);
verify(
() => client.get(path, queryParameters: any(named: 'queryParameters')),
).called(1);
verifyNoMoreInteractions(client);
});
});
group('queryMembers', () {
test('with `channelId`', () async {
const channelType = 'test-channel-type';
const channelId = 'test-channel-id';
final filter = Filter.in_('cid', const ['test-cid-1', 'test-cid-2']);
const pagination = PaginationParams();
const sort = [SortOption('test-field')];
const path = '/members';
final members = List.generate(
3,
(index) => Member(userId: 'test-user-id=$index'),
);
when(() =>
client.get(path, queryParameters: any(named: 'queryParameters')))
.thenAnswer((_) async => successResponse(path, data: {
'members': [...members.map((it) => it.toJson())]
}));
final res = await generalApi.queryMembers(
channelType,
channelId: channelId,
filter: filter,
pagination: pagination,
sort: sort,
);
expect(res, isNotNull);
expect(res.members.length, members.length);
verify(
() => client.get(path, queryParameters: any(named: 'queryParameters')),
).called(1);
verifyNoMoreInteractions(client);
});
test('with `members`', () async {
const channelType = 'test-channel-type';
final filter = Filter.in_('cid', const ['test-cid-1', 'test-cid-2']);
const pagination = PaginationParams();
const sort = [SortOption('test-field')];
const path = '/members';
final members = List.generate(
3,
(index) => Member(userId: 'test-user-id=$index'),
);
when(() =>
client.get(path, queryParameters: any(named: 'queryParameters')))
.thenAnswer((_) async => successResponse(path, data: {
'members': [...members.map((it) => it.toJson())]
}));
final res = await generalApi.queryMembers(
channelType,
filter: filter,
pagination: pagination,
sort: sort,
members: members,
);
expect(res, isNotNull);
expect(res.members.length, members.length);
verify(
() => client.get(path, queryParameters: any(named: 'queryParameters')),
).called(1);
verifyNoMoreInteractions(client);
});
});
}
@@ -0,0 +1,44 @@
import 'package:dio/dio.dart';
import 'package:mocktail/mocktail.dart';
import 'package:stream_chat/src/core/api/guest_api.dart';
import 'package:stream_chat/stream_chat.dart';
import 'package:test/test.dart';
import '../../mocks.dart';
void main() {
Response successResponse(String path, {Object? data}) => Response(
data: data,
requestOptions: RequestOptions(path: path),
statusCode: 200,
);
late final client = MockHttpClient();
late GuestApi guestApi;
setUp(() {
guestApi = GuestApi(client);
});
test('getGuestUser', () async {
const accessToken = 'test-guest-token';
final user = User(id: 'test-user-id');
const path = '/guest';
when(() => client.post(path, data: any(named: 'data')))
.thenAnswer((_) async => successResponse(path, data: {
'access_token': accessToken,
'user': user.toJson(),
}));
final res = await guestApi.getGuestUser(user);
expect(res, isNotNull);
expect(res.accessToken, accessToken);
expect(res.user.id, user.id);
verify(() => client.post(path, data: any(named: 'data'))).called(1);
verifyNoMoreInteractions(client);
});
}
@@ -0,0 +1,291 @@
import 'package:dio/dio.dart';
import 'package:mocktail/mocktail.dart';
import 'package:stream_chat/src/core/api/message_api.dart';
import 'package:stream_chat/stream_chat.dart';
import 'package:test/test.dart';
import '../../mocks.dart';
void main() {
Response successResponse(String path, {Object? data}) => Response(
data: data,
requestOptions: RequestOptions(path: path),
statusCode: 200,
);
late final client = MockHttpClient();
late MessageApi messageApi;
setUp(() {
messageApi = MessageApi(client);
});
test('sendMessage', () async {
const channelId = 'test-channel-id';
const channelType = 'test-channel-type';
final message = Message(id: 'test-message-id', text: 'test-message-text');
const path = '/channels/$channelType/$channelId/message';
when(() => client.post(path, data: any(named: 'data')))
.thenAnswer((_) async => successResponse(path, data: {
'message': message.toJson(),
}));
final res = await messageApi.sendMessage(channelId, channelType, message);
expect(res, isNotNull);
expect(res.message.id, message.id);
verify(() => client.post(path, data: any(named: 'data'))).called(1);
verifyNoMoreInteractions(client);
});
test('getMessagesById', () async {
const channelId = 'test-channel-id';
const channelType = 'test-channel-type';
const messageIds = ['test-message-id-1', 'test-message-id-2'];
const path = '/channels/$channelType/$channelId/messages';
final messages = List.generate(
3,
(index) => Message(id: 'test-message-id-$index'),
);
when(() => client.get(path, queryParameters: any(named: 'queryParameters')))
.thenAnswer((_) async => successResponse(path, data: {
'messages': [...messages.map((it) => it.toJson())],
}));
final res = await messageApi.getMessagesById(
channelId,
channelType,
messageIds,
);
expect(res, isNotNull);
expect(res.messages.length, messages.length);
verify(
() => client.get(path, queryParameters: any(named: 'queryParameters')),
).called(1);
verifyNoMoreInteractions(client);
});
test('getMessage', () async {
const messageId = 'test-message-id';
const path = '/messages/$messageId';
final message = Message(id: messageId);
when(() => client.get(path)).thenAnswer((_) async =>
successResponse(path, data: {'message': message.toJson()}));
final res = await messageApi.getMessage(messageId);
expect(res, isNotNull);
expect(res.message.id, messageId);
verify(() => client.get(path)).called(1);
verifyNoMoreInteractions(client);
});
test('updateMessage', () async {
final message = Message(id: 'test-message-id');
final path = '/messages/${message.id}';
when(() => client.post(path, data: any(named: 'data'))).thenAnswer(
(_) async => successResponse(path, data: {'message': message.toJson()}),
);
final res = await messageApi.updateMessage(message);
expect(res, isNotNull);
expect(res.message.id, message.id);
verify(() => client.post(path, data: any(named: 'data'))).called(1);
verifyNoMoreInteractions(client);
});
test('deleteMessage', () async {
const messageId = 'test-message-id';
const path = '/messages/$messageId';
when(() => client.delete(path)).thenAnswer(
(_) async => successResponse(path, data: <String, dynamic>{}),
);
final res = await messageApi.deleteMessage(messageId);
expect(res, isNotNull);
verify(() => client.delete(path)).called(1);
verifyNoMoreInteractions(client);
});
test('sendAction', () async {
const channelId = 'test-channel-id';
const channelType = 'test-channel-type';
const messageId = 'test-message-id';
const formData = {'test-key': 'test-data'};
const path = '/messages/$messageId/action';
when(() => client.post(path, data: any(named: 'data'))).thenAnswer(
(_) async => successResponse(path, data: <String, dynamic>{}));
final res = await messageApi.sendAction(
channelId,
channelType,
messageId,
formData,
);
expect(res, isNotNull);
verify(() => client.post(path, data: any(named: 'data'))).called(1);
verifyNoMoreInteractions(client);
});
test('sendReaction', () async {
const messageId = 'test-message-id';
const reactionType = 'test-reaction-type';
const extraData = {'test-key': 'test-data'};
const path = '/messages/$messageId/reaction';
final message = Message(id: messageId);
final reaction = Reaction(type: reactionType, messageId: messageId);
when(() => client.post(path, data: any(named: 'data')))
.thenAnswer((_) async => successResponse(path, data: {
'message': message.toJson(),
'reaction': reaction.toJson(),
}));
final res = await messageApi.sendReaction(
messageId,
reactionType,
extraData: extraData,
);
expect(res, isNotNull);
expect(res.message.id, messageId);
expect(res.reaction.messageId, messageId);
expect(res.reaction.type, reactionType);
verify(() => client.post(path, data: any(named: 'data'))).called(1);
verifyNoMoreInteractions(client);
});
test('deleteReaction', () async {
const messageId = 'test-message-id';
const reactionType = 'test-reaction-type';
const path = '/messages/$messageId/reaction/$reactionType';
when(() => client.delete(path)).thenAnswer(
(_) async => successResponse(path, data: <String, dynamic>{}));
final res = await messageApi.deleteReaction(messageId, reactionType);
expect(res, isNotNull);
verify(() => client.delete(path)).called(1);
verifyNoMoreInteractions(client);
});
test('getReactions', () async {
const messageId = 'test-message-id';
const options = PaginationParams();
const path = '/messages/$messageId/reactions';
final reactions = List.generate(
3,
(index) => Reaction(
type: 'test-reaction-type-$index',
messageId: messageId,
),
);
when(() => client.get(path, queryParameters: any(named: 'queryParameters')))
.thenAnswer((_) async => successResponse(path, data: {
'reactions': [...reactions.map((it) => it.toJson())]
}));
final res = await messageApi.getReactions(messageId, options);
expect(res, isNotNull);
expect(res.reactions.length, reactions.length);
expect(res.reactions.every((it) => it.messageId == messageId), isTrue);
verify(
() => client.get(path, queryParameters: any(named: 'queryParameters')),
).called(1);
verifyNoMoreInteractions(client);
});
test('translateMessage', () async {
const messageId = 'test-message-id';
const messageText = 'hello';
const language = 'hi'; // Hindi
final message = Message(id: messageId, text: messageText);
final path = '/messages/${message.id}/translate';
const translatedMessageText = 'नमस्ते';
final translatedMessage = TranslatedMessage(const {
language: translatedMessageText,
});
when(() => client.post(path, data: any(named: 'data')))
.thenAnswer((_) async => successResponse(path, data: {
'message': translatedMessage.toJson(),
}));
final res = await messageApi.translateMessage(messageId, language);
expect(res, isNotNull);
expect(res.message.i18n?.containsKey(language), isTrue);
expect(res.message.i18n?[language], translatedMessageText);
verify(() => client.post(path, data: any(named: 'data'))).called(1);
verifyNoMoreInteractions(client);
});
test('getReplies', () async {
const parentId = 'test-parent-id';
const options = PaginationParams();
const path = '/messages/$parentId/replies';
final messages = List.generate(
3,
(index) => Message(
id: 'test-message-id-$index',
parentId: parentId,
),
);
when(() => client.get(path, queryParameters: any(named: 'queryParameters')))
.thenAnswer((_) async => successResponse(path, data: {
'messages': [...messages.map((it) => it.toJson())]
}));
final res = await messageApi.getReplies(parentId, options);
expect(res, isNotNull);
expect(res.messages.length, messages.length);
expect(res.messages.every((it) => it.parentId == parentId), isTrue);
verify(
() => client.get(path, queryParameters: any(named: 'queryParameters')),
).called(1);
verifyNoMoreInteractions(client);
});
}
@@ -0,0 +1,190 @@
import 'package:dio/dio.dart';
import 'package:mocktail/mocktail.dart';
import 'package:stream_chat/src/core/api/moderation_api.dart';
import 'package:test/test.dart';
import '../../mocks.dart';
void main() {
Response successResponse(String path, {Object? data}) => Response(
data: data,
requestOptions: RequestOptions(path: path),
statusCode: 200,
);
late final client = MockHttpClient();
late ModerationApi moderationApi;
setUp(() {
moderationApi = ModerationApi(client);
});
test('muteUser', () async {
const userId = 'test-user-id';
const path = '/moderation/mute';
when(() => client.post(path, data: any(named: 'data'))).thenAnswer(
(_) async => successResponse(path, data: <String, dynamic>{}));
final res = await moderationApi.muteUser(userId);
expect(res, isNotNull);
verify(() => client.post(path, data: any(named: 'data'))).called(1);
verifyNoMoreInteractions(client);
});
test('unmuteUser', () async {
const userId = 'test-user-id';
const path = '/moderation/unmute';
when(() => client.post(path, data: any(named: 'data'))).thenAnswer(
(_) async => successResponse(path, data: <String, dynamic>{}));
final res = await moderationApi.unmuteUser(userId);
expect(res, isNotNull);
verify(() => client.post(path, data: any(named: 'data'))).called(1);
verifyNoMoreInteractions(client);
});
test('muteChannel', () async {
const channelCid = 'test-channel-cid';
const expiration = Duration(days: 3);
const path = '/moderation/mute/channel';
when(() => client.post(path, data: any(named: 'data'))).thenAnswer(
(_) async => successResponse(path, data: <String, dynamic>{}));
final res = await moderationApi.muteChannel(
channelCid,
expiration: expiration,
);
expect(res, isNotNull);
verify(() => client.post(path, data: any(named: 'data'))).called(1);
verifyNoMoreInteractions(client);
});
test('unmuteChannel', () async {
const channelCid = 'test-channel-cid';
const path = '/moderation/unmute/channel';
when(() => client.post(path, data: any(named: 'data'))).thenAnswer(
(_) async => successResponse(path, data: <String, dynamic>{}));
final res = await moderationApi.unmuteChannel(channelCid);
expect(res, isNotNull);
verify(() => client.post(path, data: any(named: 'data'))).called(1);
verifyNoMoreInteractions(client);
});
test('flagMessage', () async {
const messageId = 'test-message-id';
const path = '/moderation/flag';
when(() => client.post(path, data: any(named: 'data'))).thenAnswer(
(_) async => successResponse(path, data: <String, dynamic>{}));
final res = await moderationApi.flagMessage(messageId);
expect(res, isNotNull);
verify(() => client.post(path, data: any(named: 'data'))).called(1);
verifyNoMoreInteractions(client);
});
test('unflagMessage', () async {
const messageId = 'test-message-id';
const path = '/moderation/unflag';
when(() => client.post(path, data: any(named: 'data'))).thenAnswer(
(_) async => successResponse(path, data: <String, dynamic>{}));
final res = await moderationApi.unflagMessage(messageId);
expect(res, isNotNull);
verify(() => client.post(path, data: any(named: 'data'))).called(1);
verifyNoMoreInteractions(client);
});
test('flagUser', () async {
const userId = 'test-message-id';
const path = '/moderation/flag';
when(() => client.post(path, data: any(named: 'data'))).thenAnswer(
(_) async => successResponse(path, data: <String, dynamic>{}));
final res = await moderationApi.flagUser(userId);
expect(res, isNotNull);
verify(() => client.post(path, data: any(named: 'data'))).called(1);
verifyNoMoreInteractions(client);
});
test('unflagUser', () async {
const userId = 'test-message-id';
const path = '/moderation/unflag';
when(() => client.post(path, data: any(named: 'data'))).thenAnswer(
(_) async => successResponse(path, data: <String, dynamic>{}));
final res = await moderationApi.unflagUser(userId);
expect(res, isNotNull);
verify(() => client.post(path, data: any(named: 'data'))).called(1);
verifyNoMoreInteractions(client);
});
test('banUser', () async {
const targetUserId = 'test-target-user-id';
const options = {'key': 'value'};
const path = '/moderation/ban';
when(() => client.post(path, data: any(named: 'data'))).thenAnswer(
(_) async => successResponse(path, data: <String, dynamic>{}));
final res = await moderationApi.banUser(targetUserId, options: options);
expect(res, isNotNull);
verify(() => client.post(path, data: any(named: 'data'))).called(1);
verifyNoMoreInteractions(client);
});
test('unbanUser', () async {
const targetUserId = 'test-target-user-id';
const options = {'key': 'value'};
const path = '/moderation/ban';
when(
() => client.delete(path, queryParameters: any(named: 'queryParameters')),
).thenAnswer((_) async => successResponse(path, data: <String, dynamic>{}));
final res = await moderationApi.unbanUser(targetUserId, options: options);
expect(res, isNotNull);
verify(
() => client.delete(path, queryParameters: any(named: 'queryParameters')),
).called(1);
verifyNoMoreInteractions(client);
});
}
@@ -0,0 +1,49 @@
import 'package:stream_chat/src/core/api/stream_chat_api.dart';
import 'package:test/test.dart';
import '../../mocks.dart';
void main() {
const apiKey = 'test-api-key';
late final client = MockHttpClient();
late StreamChatApi streamChatApi;
setUp(() {
streamChatApi = StreamChatApi(
apiKey,
client: client,
);
});
test('`.user`', () {
expect(streamChatApi.user, isNotNull);
});
test('`.guest`', () {
expect(streamChatApi.guest, isNotNull);
});
test('`.message`', () {
expect(streamChatApi.message, isNotNull);
});
test('`.channel`', () {
expect(streamChatApi.channel, isNotNull);
});
test('`.device`', () {
expect(streamChatApi.device, isNotNull);
});
test('`.moderation`', () {
expect(streamChatApi.moderation, isNotNull);
});
test('`.general`', () {
expect(streamChatApi.general, isNotNull);
});
test('`.fileUploader`', () {
expect(streamChatApi.fileUploader, isNotNull);
});
}
@@ -0,0 +1,77 @@
import 'package:dio/dio.dart';
import 'package:mocktail/mocktail.dart';
import 'package:stream_chat/src/core/api/requests.dart';
import 'package:stream_chat/src/core/api/user_api.dart';
import 'package:stream_chat/src/core/models/filter.dart';
import 'package:stream_chat/stream_chat.dart';
import 'package:test/test.dart';
import '../../mocks.dart';
void main() {
Response successResponse(String path, {Object? data}) => Response(
data: data,
requestOptions: RequestOptions(path: path),
statusCode: 200,
);
late final client = MockHttpClient();
late UserApi userApi;
setUp(() {
userApi = UserApi(client);
});
test('queryUsers', () async {
const presence = true;
final filter = Filter.in_('cid', const ['test-cid-1', 'test-cid-2']);
const sort = [SortOption('test-field')];
const pagination = PaginationParams();
const path = '/users';
final users = List.generate(3, (index) => User(id: 'test-user-id-$index'));
when(() => client.get(path, queryParameters: any(named: 'queryParameters')))
.thenAnswer((_) async => successResponse(path, data: {
'users': [...users.map((it) => it.toJson())]
}));
final res = await userApi.queryUsers(
presence: presence,
filter: filter,
sort: sort,
pagination: pagination,
);
expect(res, isNotNull);
expect(res.users.length, users.length);
verify(
() => client.get(path, queryParameters: any(named: 'queryParameters')),
).called(1);
verifyNoMoreInteractions(client);
});
test('updateUsers', () async {
final users = List.generate(3, (index) => User(id: 'test-user-id-$index'));
const path = '/users';
final updatedUsers = {for (final user in users) user.id: user};
when(() => client.post(path, data: any(named: 'data'))).thenAnswer(
(_) async => successResponse(path, data: {
'users': updatedUsers
.map((key, value) => MapEntry(key, value.toJson()))
}));
final res = await userApi.updateUsers(users);
expect(res, isNotNull);
expect(res.users.length, updatedUsers.length);
verify(() => client.post(path, data: any(named: 'data'))).called(1);
verifyNoMoreInteractions(client);
});
}
+57
View File
@@ -1,6 +1,18 @@
import 'package:dio/dio.dart';
import 'package:mocktail/mocktail.dart';
import 'package:stream_chat/src/core/api/channel_api.dart';
import 'package:stream_chat/src/core/api/device_api.dart';
import 'package:stream_chat/src/core/api/general_api.dart';
import 'package:stream_chat/src/core/api/message_api.dart';
import 'package:stream_chat/src/core/api/moderation_api.dart';
import 'package:stream_chat/src/core/api/stream_chat_api.dart';
import 'package:stream_chat/src/core/api/user_api.dart';
import 'package:stream_chat/src/core/api/guest_api.dart';
import 'package:stream_chat/src/core/http/token.dart';
import 'package:stream_chat/src/core/http/token_manager.dart';
import 'package:stream_chat/stream_chat.dart';
import 'mocks.dart';
class FakeTokenManager extends Fake implements TokenManager {
final token = Token.development('test-user-id');
@@ -25,3 +37,48 @@ class FakeTokenManager extends Fake implements TokenManager {
@override
void reset() {}
}
class FakeMultiPartFile extends Fake implements MultipartFile {}
class FakeChatApi extends Fake implements StreamChatApi {
UserApi? _user;
@override
UserApi get user => _user ??= MockUserApi();
GuestApi? _guest;
@override
GuestApi get guest => _guest ??= MockGuestApi();
MessageApi? _message;
@override
MessageApi get message => _message ??= MockMessageApi();
ChannelApi? _channel;
@override
ChannelApi get channel => _channel ??= MockChannelApi();
DeviceApi? _device;
@override
DeviceApi get device => _device ??= MockDeviceApi();
ModerationApi? _moderation;
@override
ModerationApi get moderation => _moderation ??= MockModerationApi();
GeneralApi? _general;
@override
GeneralApi get general => _general ??= MockGeneralApi();
AttachmentFileUploader? _fileUploader;
@override
AttachmentFileUploader get fileUploader =>
_fileUploader ??= MockAttachmentFileUploader();
}
@@ -0,0 +1,19 @@
import 'package:dio/dio.dart' show MultipartFile;
import 'package:test/test.dart';
Matcher isSameMultipartFileAs(MultipartFile targetFile) =>
_IsSameMultipartFileAs(targetFile: targetFile);
class _IsSameMultipartFileAs extends Matcher {
const _IsSameMultipartFileAs({required this.targetFile});
final MultipartFile targetFile;
@override
Description describe(Description description) =>
description.add('is same multipartFile as $targetFile');
@override
bool matches(covariant MultipartFile file, Map matchState) =>
file.length == targetFile.length;
}
+25
View File
@@ -1,6 +1,14 @@
import 'package:dio/dio.dart';
import 'package:logging/logging.dart';
import 'package:mocktail/mocktail.dart';
import 'package:stream_chat/src/core/api/attachment_file_uploader.dart';
import 'package:stream_chat/src/core/api/channel_api.dart';
import 'package:stream_chat/src/core/api/device_api.dart';
import 'package:stream_chat/src/core/api/general_api.dart';
import 'package:stream_chat/src/core/api/guest_api.dart';
import 'package:stream_chat/src/core/api/message_api.dart';
import 'package:stream_chat/src/core/api/moderation_api.dart';
import 'package:stream_chat/src/core/api/user_api.dart';
import 'package:stream_chat/src/core/http/connection_id_manager.dart';
import 'package:stream_chat/src/core/http/stream_http_client.dart';
import 'package:stream_chat/src/core/http/token_manager.dart';
@@ -32,3 +40,20 @@ class MockHttpClient extends Mock implements StreamHttpClient {}
class MockTokenManager extends Mock implements TokenManager {}
class MockConnectionIdManager extends Mock implements ConnectionIdManager {}
class MockUserApi extends Mock implements UserApi {}
class MockGuestApi extends Mock implements GuestApi {}
class MockMessageApi extends Mock implements MessageApi {}
class MockChannelApi extends Mock implements ChannelApi {}
class MockDeviceApi extends Mock implements DeviceApi {}
class MockModerationApi extends Mock implements ModerationApi {}
class MockGeneralApi extends Mock implements GeneralApi {}
class MockAttachmentFileUploader extends Mock
implements AttachmentFileUploader {}
+15
View File
@@ -0,0 +1,15 @@
import 'dart:io';
File assetFile(String name) {
final dir = currentDirectory.path;
return File('$dir/test/assets/$name');
}
// https://github.com/flutter/flutter/issues/20907
Directory get currentDirectory {
var directory = Directory.current;
if (directory.path.endsWith('/test')) {
directory = directory.parent;
}
return directory;
}