migrate code

This commit is contained in:
Salvatore Giordano
2021-04-20 12:44:11 +02:00
parent 34f2539595
commit 987da10cba
25 changed files with 986 additions and 1264 deletions
@@ -3,7 +3,6 @@ analyzer:
- lib/**/*.g.dart - lib/**/*.g.dart
- lib/**/*.freezed.dart - lib/**/*.freezed.dart
- example/* - example/*
- test/*
linter: linter:
rules: rules:
- always_use_package_imports - always_use_package_imports
@@ -69,23 +69,7 @@ class ChannelListCore extends StatefulWidget {
limit: 25, limit: 25,
), ),
this.channelListController, this.channelListController,
}) : assert( }) : super(key: key);
errorBuilder != null,
'Parameter errorBuilder should not be null',
),
assert(
emptyBuilder != null,
'Parameter emptyBuilder should not be null',
),
assert(
loadingBuilder != null,
'Parameter loadingBuilder should not be null',
),
assert(
listBuilder != null,
'Parameter listBuilder should not be null',
),
super(key: key);
/// A [ChannelListController] allows reloading and pagination. /// A [ChannelListController] allows reloading and pagination.
/// Use [ChannelListController.loadData] and /// Use [ChannelListController.loadData] and
@@ -100,7 +84,7 @@ class ChannelListCore extends StatefulWidget {
final WidgetBuilder loadingBuilder; final WidgetBuilder loadingBuilder;
/// The builder which is used when list of channels loads /// The builder which is used when list of channels loads
final Function(BuildContext, List<Channel?>) listBuilder; final Function(BuildContext, List<Channel>) listBuilder;
/// The builder used when the channel list is empty. /// The builder used when the channel list is empty.
final WidgetBuilder emptyBuilder; final WidgetBuilder emptyBuilder;
@@ -142,14 +126,14 @@ class ChannelListCoreState extends State<ChannelListCore> {
return _buildListView(channelsBloc); return _buildListView(channelsBloc);
} }
StreamBuilder<List<Channel?>> _buildListView( StreamBuilder<List<Channel>> _buildListView(
ChannelsBlocState channelsBlocState, ChannelsBlocState channelsBlocState,
) => ) =>
StreamBuilder<List<Channel?>>( StreamBuilder<List<Channel>>(
stream: channelsBlocState.channelsStream, stream: channelsBlocState.channelsStream,
builder: (context, snapshot) { builder: (context, snapshot) {
if (snapshot.hasError) { if (snapshot.hasError) {
return widget.errorBuilder(context, snapshot.error); return widget.errorBuilder(context, snapshot.error!);
} }
if (!snapshot.hasData) { if (!snapshot.hasData) {
return widget.loadingBuilder(context); return widget.loadingBuilder(context);
@@ -215,8 +199,8 @@ class ChannelListCoreState extends State<ChannelListCore> {
if (widget.filter?.toString() != oldWidget.filter?.toString() || if (widget.filter?.toString() != oldWidget.filter?.toString() ||
jsonEncode(widget.sort) != jsonEncode(oldWidget.sort) || jsonEncode(widget.sort) != jsonEncode(oldWidget.sort) ||
widget.options?.toString() != oldWidget.options?.toString() || widget.options?.toString() != oldWidget.options?.toString() ||
widget.pagination?.toJson()?.toString() != widget.pagination.toJson().toString() !=
oldWidget.pagination?.toJson()?.toString()) { oldWidget.pagination.toJson().toString()) {
loadData(); loadData();
} }
} }
@@ -35,7 +35,7 @@ class ChannelsBloc extends StatefulWidget {
final bool lockChannelsOrder; final bool lockChannelsOrder;
/// Comparator used to sort the channels when a message.new event is received /// Comparator used to sort the channels when a message.new event is received
final Comparator<Channel?>? channelsComparator; final Comparator<Channel>? channelsComparator;
/// Function used to evaluate if a channel should be added to the list when a /// Function used to evaluate if a channel should be added to the list when a
/// message.new event is received /// message.new event is received
@@ -68,14 +68,14 @@ class ChannelsBlocState extends State<ChannelsBloc>
} }
/// The current channel list /// The current channel list
List<Channel>? get channels => _channelsController.value as List<Channel>?; List<Channel>? get channels => _channelsController.value;
/// The current channel list as a stream /// The current channel list as a stream
Stream<List<Channel?>> get channelsStream => _channelsController.stream; Stream<List<Channel>> get channelsStream => _channelsController.stream;
final _queryChannelsLoadingController = BehaviorSubject.seeded(false); final _queryChannelsLoadingController = BehaviorSubject.seeded(false);
final BehaviorSubject<List<Channel?>> _channelsController = final BehaviorSubject<List<Channel>> _channelsController =
BehaviorSubject<List<Channel>>(); BehaviorSubject<List<Channel>>();
/// The stream notifying the state of queryChannel call /// The stream notifying the state of queryChannel call
@@ -90,7 +90,7 @@ class ChannelsBlocState extends State<ChannelsBloc>
Future<void> queryChannels({ Future<void> queryChannels({
Map<String, dynamic>? filter, Map<String, dynamic>? filter,
List<SortOption<ChannelModel>>? sortOptions, List<SortOption<ChannelModel>>? sortOptions,
PaginationParams? paginationParams, PaginationParams paginationParams = const PaginationParams(limit: 30),
Map<String, dynamic>? options, Map<String, dynamic>? options,
}) async { }) async {
final client = StreamChatCore.of(context).client; final client = StreamChatCore.of(context).client;
@@ -104,14 +104,14 @@ class ChannelsBlocState extends State<ChannelsBloc>
} }
try { try {
final clear = paginationParams == null || paginationParams.offset == 0; final clear = paginationParams.offset == 0;
final oldChannels = List<Channel>.from(channels ?? []); final oldChannels = List<Channel>.from(channels ?? []);
var newChannels = <Channel>[]; var newChannels = <Channel>[];
await for (final channels in client.queryChannels( await for (final channels in client.queryChannels(
filter: filter!, filter: filter,
sort: sortOptions!, sort: sortOptions,
options: options!, options: options,
paginationParams: paginationParams!, paginationParams: paginationParams,
)) { )) {
newChannels = channels; newChannels = channels;
if (clear) { if (clear) {
@@ -147,8 +147,8 @@ class ChannelsBlocState extends State<ChannelsBloc>
if (!widget.lockChannelsOrder) { if (!widget.lockChannelsOrder) {
_subscriptions.add(client.on(EventType.messageNew).listen((e) { _subscriptions.add(client.on(EventType.messageNew).listen((e) {
final newChannels = List<Channel?>.from(channels ?? []); final newChannels = List<Channel>.from(channels ?? []);
final index = newChannels.indexWhere((c) => c!.cid == e.cid); final index = newChannels.indexWhere((c) => c.cid == e.cid);
if (index != -1) { if (index != -1) {
if (index > 0) { if (index > 0) {
final channel = newChannels.removeAt(index); final channel = newChannels.removeAt(index);
@@ -162,7 +162,7 @@ class ChannelsBlocState extends State<ChannelsBloc>
} else { } else {
if (client.state.channels != null && if (client.state.channels != null &&
client.state.channels?[e.cid] != null) { client.state.channels?[e.cid] != null) {
newChannels.insert(0, client.state.channels?[e.cid]); newChannels.insert(0, client.state.channels![e.cid]!);
} }
} }
} }
@@ -17,8 +17,7 @@ class LazyLoadScrollView extends StatefulWidget {
this.onPageScrollEnd, this.onPageScrollEnd,
this.onInBetweenOfPage, this.onInBetweenOfPage,
this.scrollOffset = 100, this.scrollOffset = 100,
}) : assert(child != null, 'Parameter child should not be null'), }) : super(key: key);
super(key: key);
/// The [Widget] that this widget watches for changes on /// The [Widget] that this widget watches for changes on
final Widget child; final Widget child;
@@ -46,7 +45,7 @@ class LazyLoadScrollView extends StatefulWidget {
} }
class _LazyLoadScrollViewState extends State<LazyLoadScrollView> { class _LazyLoadScrollViewState extends State<LazyLoadScrollView> {
_LoadingStatus _loadMoreStatus = _LoadingStatus.stable; var _loadMoreStatus = _LoadingStatus.stable;
double _scrollPosition = 0; double _scrollPosition = 0;
@override @override
@@ -73,7 +72,7 @@ class _LazyLoadScrollViewState extends State<LazyLoadScrollView> {
final pixels = notification.metrics.pixels; final pixels = notification.metrics.pixels;
final maxScrollExtent = notification.metrics.maxScrollExtent; final maxScrollExtent = notification.metrics.maxScrollExtent;
final minScrollExtent = notification.metrics.minScrollExtent; final minScrollExtent = notification.metrics.minScrollExtent;
final scrollOffset = widget.scrollOffset ?? 0; final scrollOffset = widget.scrollOffset;
if (pixels > (minScrollExtent + scrollOffset) && if (pixels > (minScrollExtent + scrollOffset) &&
pixels < (maxScrollExtent - scrollOffset)) { pixels < (maxScrollExtent - scrollOffset)) {
@@ -114,7 +113,7 @@ class _LazyLoadScrollViewState extends State<LazyLoadScrollView> {
} }
void _onEndOfPage() { void _onEndOfPage() {
if (_loadMoreStatus != null && _loadMoreStatus == _LoadingStatus.stable) { if (_loadMoreStatus == _LoadingStatus.stable) {
if (widget.onEndOfPage != null) { if (widget.onEndOfPage != null) {
_loadMoreStatus = _LoadingStatus.loading; _loadMoreStatus = _LoadingStatus.loading;
widget.onEndOfPage!().whenComplete(() { widget.onEndOfPage!().whenComplete(() {
@@ -125,7 +124,7 @@ class _LazyLoadScrollViewState extends State<LazyLoadScrollView> {
} }
void _onStartOfPage() { void _onStartOfPage() {
if (_loadMoreStatus != null && _loadMoreStatus == _LoadingStatus.stable) { if (_loadMoreStatus == _LoadingStatus.stable) {
if (widget.onStartOfPage != null) { if (widget.onStartOfPage != null) {
_loadMoreStatus = _LoadingStatus.loading; _loadMoreStatus = _LoadingStatus.loading;
widget.onStartOfPage!().whenComplete(() { widget.onStartOfPage!().whenComplete(() {
@@ -111,18 +111,18 @@ class MessageListCore extends StatefulWidget {
class MessageListCoreState extends State<MessageListCore> { class MessageListCoreState extends State<MessageListCore> {
late StreamChannelState _streamChannel; late StreamChannelState _streamChannel;
bool get _upToDate => _streamChannel.channel.state.isUpToDate; bool get _upToDate => _streamChannel.channel.state?.isUpToDate ?? true;
bool get _isThreadConversation => widget.parentMessage != null; bool get _isThreadConversation => widget.parentMessage != null;
OwnUser get _currentUser => _streamChannel.channel.client.state.user; OwnUser? get _currentUser => _streamChannel.channel.client.state.user;
var _messages = <Message>[]; var _messages = <Message>[];
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final messagesStream = _isThreadConversation final messagesStream = _isThreadConversation
? _streamChannel.channel.state.threadsStream ? _streamChannel.channel.state?.threadsStream
.where((threads) => threads.containsKey(widget.parentMessage!.id)) .where((threads) => threads.containsKey(widget.parentMessage!.id))
.map((threads) => threads[widget.parentMessage!.id]) .map((threads) => threads[widget.parentMessage!.id])
: _streamChannel.channel.state?.messagesStream; : _streamChannel.channel.state?.messagesStream;
@@ -141,7 +141,7 @@ class MessageListCoreState extends State<MessageListCore> {
)), )),
builder: (context, snapshot) { builder: (context, snapshot) {
if (snapshot.hasError) { if (snapshot.hasError) {
return widget.errorWidgetBuilder(context, snapshot.error); return widget.errorWidgetBuilder(context, snapshot.error!);
} else if (!snapshot.hasData) { } else if (!snapshot.hasData) {
return widget.loadingBuilder(context); return widget.loadingBuilder(context);
} else { } else {
@@ -163,8 +163,9 @@ class MessageListCoreState extends State<MessageListCore> {
/// Fetches more messages with updated pagination and updates the widget. /// Fetches more messages with updated pagination and updates the widget.
/// ///
/// Optionally pass the fetch direction, defaults to [QueryDirection.bottom] /// Optionally pass the fetch direction, defaults to [QueryDirection.bottom]
Future<void> paginateData( Future<void> paginateData({
{QueryDirection? direction = QueryDirection.bottom}) { QueryDirection direction = QueryDirection.bottom,
}) {
if (!_isThreadConversation) { if (!_isThreadConversation) {
return _streamChannel.queryMessages(direction: direction); return _streamChannel.queryMessages(direction: direction);
} else { } else {
@@ -199,5 +200,5 @@ class MessageListCoreState extends State<MessageListCore> {
/// Controller used for paginating data in [ChannelListView] /// Controller used for paginating data in [ChannelListView]
class MessageListController { class MessageListController {
/// Call this function to load further data /// Call this function to load further data
Future<void> Function({QueryDirection? direction})? paginateData; Future<void> Function({QueryDirection direction})? paginateData;
} }
@@ -58,7 +58,7 @@ class MessageSearchBlocState extends State<MessageSearchBloc>
/// Calls [StreamChatClient.search] updating /// Calls [StreamChatClient.search] updating
/// [messagesStream] and [queryMessagesLoading] stream /// [messagesStream] and [queryMessagesLoading] stream
Future<void> search({ Future<void> search({
Map<String, dynamic>? filter, required Map<String, dynamic> filter,
Map<String, dynamic>? messageFilter, Map<String, dynamic>? messageFilter,
List<SortOption>? sort, List<SortOption>? sort,
String? query, String? query,
@@ -77,20 +77,18 @@ class MessageSearchBlocState extends State<MessageSearchBloc>
final oldMessages = List<GetMessageResponse>.from(messageResponses ?? []); final oldMessages = List<GetMessageResponse>.from(messageResponses ?? []);
final messages = await client.search( final messages = await client.search(
filter!, filter,
sort: sort!, sort: sort,
query: query!, query: query,
paginationParams: pagination!, paginationParams: pagination,
messageFilters: messageFilter!, messageFilters: messageFilter,
); );
if (messages.results != null) { if (clear) {
if (clear) { _messageResponses.add(messages.results);
_messageResponses.add(messages.results!); } else {
} else { final temp = oldMessages + messages.results;
final temp = oldMessages + messages.results!; _messageResponses.add(temp);
_messageResponses.add(temp);
}
} }
if (_messageResponses.hasValue && if (_messageResponses.hasValue &&
_queryMessagesLoadingController.value!) { _queryMessagesLoadingController.value!) {
@@ -47,17 +47,13 @@ class MessageSearchListCore extends StatefulWidget {
required this.errorBuilder, required this.errorBuilder,
required this.loadingBuilder, required this.loadingBuilder,
required this.childBuilder, required this.childBuilder,
required this.filters,
this.messageQuery, this.messageQuery,
this.filters,
this.sortOptions, this.sortOptions,
this.paginationParams, this.paginationParams,
this.messageFilters, this.messageFilters,
this.messageSearchListController, this.messageSearchListController,
}) : assert(emptyBuilder != null, 'emptyBuilder should not be null'), }) : super(key: key);
assert(errorBuilder != null, 'errorBuilder should not be null'),
assert(loadingBuilder != null, 'loadingBuilder should not be null'),
assert(childBuilder != null, 'childBuilder should not be null'),
super(key: key);
/// A [MessageSearchListController] allows reloading and pagination. /// A [MessageSearchListController] allows reloading and pagination.
/// Use [MessageSearchListController.loadData] and /// Use [MessageSearchListController.loadData] and
@@ -71,7 +67,7 @@ class MessageSearchListCore extends StatefulWidget {
/// The query filters to use. /// The query filters to use.
/// You can query on any of the custom fields you've defined on the [Channel]. /// You can query on any of the custom fields you've defined on the [Channel].
/// You can also filter other built-in channel fields. /// You can also filter other built-in channel fields.
final Map<String, dynamic>? filters; final Map<String, dynamic> filters;
/// The sorting used for the channels matching the filters. /// The sorting used for the channels matching the filters.
/// Sorting is based on field and direction, multiple sorting options can be /// Sorting is based on field and direction, multiple sorting options can be
@@ -92,7 +88,7 @@ class MessageSearchListCore extends StatefulWidget {
final Map<String, dynamic>? messageFilters; final Map<String, dynamic>? messageFilters;
/// The builder that is used when the search messages are fetched /// The builder that is used when the search messages are fetched
final Widget Function(List<GetMessageResponse>?) childBuilder; final Widget Function(List<GetMessageResponse>) childBuilder;
/// The builder used when the channel list is empty. /// The builder used when the channel list is empty.
final WidgetBuilder emptyBuilder; final WidgetBuilder emptyBuilder;
@@ -130,7 +126,7 @@ class MessageSearchListCoreState extends State<MessageSearchListCore> {
stream: messageSearchBloc.messagesStream, stream: messageSearchBloc.messagesStream,
builder: (context, snapshot) { builder: (context, snapshot) {
if (snapshot.hasError) { if (snapshot.hasError) {
return widget.errorBuilder(context, snapshot.error); return widget.errorBuilder(context, snapshot.error!);
} }
if (!snapshot.hasData) { if (!snapshot.hasData) {
return widget.loadingBuilder(context); return widget.loadingBuilder(context);
@@ -139,7 +135,7 @@ class MessageSearchListCoreState extends State<MessageSearchListCore> {
if (items.isEmpty) { if (items.isEmpty) {
return widget.emptyBuilder(context); return widget.emptyBuilder(context);
} }
return widget.childBuilder(snapshot.data); return widget.childBuilder(items);
}, },
); );
@@ -172,13 +168,13 @@ class MessageSearchListCoreState extends State<MessageSearchListCore> {
@override @override
void didUpdateWidget(MessageSearchListCore oldWidget) { void didUpdateWidget(MessageSearchListCore oldWidget) {
super.didUpdateWidget(oldWidget); super.didUpdateWidget(oldWidget);
if (widget.filters?.toString() != oldWidget.filters?.toString() || if (widget.filters.toString() != oldWidget.filters.toString() ||
jsonEncode(widget.sortOptions) != jsonEncode(oldWidget.sortOptions) || jsonEncode(widget.sortOptions) != jsonEncode(oldWidget.sortOptions) ||
widget.messageQuery?.toString() != oldWidget.messageQuery?.toString() || widget.messageQuery?.toString() != oldWidget.messageQuery?.toString() ||
widget.messageFilters?.toString() != widget.messageFilters?.toString() !=
oldWidget.messageFilters?.toString() || oldWidget.messageFilters?.toString() ||
widget.paginationParams?.toJson()?.toString() != widget.paginationParams?.toJson().toString() !=
oldWidget.paginationParams?.toJson()?.toString()) { oldWidget.paginationParams?.toJson().toString()) {
loadData(); loadData();
} }
} }
@@ -1,5 +1,6 @@
import 'dart:async'; import 'dart:async';
import 'package:collection/collection.dart';
import 'package:flutter/foundation.dart'; import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:rxdart/rxdart.dart'; import 'package:rxdart/rxdart.dart';
@@ -28,7 +29,7 @@ class StreamChannel extends StatefulWidget {
this.initialMessageId, this.initialMessageId,
}) : super(key: key); }) : super(key: key);
// ignore: public_member_api_docs /// The child of the widget
final Widget child; final Widget child;
/// [channel] specifies the channel with which child should be wrapped /// [channel] specifies the channel with which child should be wrapped
@@ -68,8 +69,8 @@ class StreamChannelState extends State<StreamChannel> {
String? get initialMessageId => widget.initialMessageId; String? get initialMessageId => widget.initialMessageId;
/// Current channel state stream /// Current channel state stream
Stream<ChannelState> get channelStateStream => Stream<ChannelState>? get channelStateStream =>
widget.channel.state.channelStateStream; widget.channel.state?.channelStateStream;
final _queryTopMessagesController = BehaviorSubject.seeded(false); final _queryTopMessagesController = BehaviorSubject.seeded(false);
final _queryBottomMessagesController = BehaviorSubject.seeded(false); final _queryBottomMessagesController = BehaviorSubject.seeded(false);
@@ -87,16 +88,18 @@ class StreamChannelState extends State<StreamChannel> {
int limit = 20, int limit = 20,
bool preferOffline = false, bool preferOffline = false,
}) async { }) async {
if (_topPaginationEnded || _queryTopMessagesController?.value == true) { if (_topPaginationEnded ||
_queryTopMessagesController.value == true ||
channel.state == null) {
return; return;
} }
_queryTopMessagesController.add(true); _queryTopMessagesController.add(true);
if (channel.state.messages.isEmpty) { if (channel.state!.messages.isEmpty) {
return _queryTopMessagesController.add(false); return _queryTopMessagesController.add(false);
} }
final oldestMessage = channel.state.messages.first; final oldestMessage = channel.state!.messages.first;
try { try {
final state = await queryBeforeMessage( final state = await queryBeforeMessage(
@@ -118,15 +121,16 @@ class StreamChannelState extends State<StreamChannel> {
bool preferOffline = false, bool preferOffline = false,
}) async { }) async {
if (_bottomPaginationEnded || if (_bottomPaginationEnded ||
_queryBottomMessagesController?.value == true || _queryBottomMessagesController.value == true ||
channel?.state?.isUpToDate == true) return; channel.state == null ||
channel.state!.isUpToDate == true) return;
_queryBottomMessagesController.add(true); _queryBottomMessagesController.add(true);
if (channel.state.messages.isEmpty) { if (channel.state!.messages.isEmpty) {
return _queryBottomMessagesController.add(false); return _queryBottomMessagesController.add(false);
} }
final recentMessage = channel.state.messages.last; final recentMessage = channel.state!.messages.last;
try { try {
final state = await queryAfterMessage( final state = await queryAfterMessage(
@@ -155,12 +159,14 @@ class StreamChannelState extends State<StreamChannel> {
int limit = 50, int limit = 50,
bool preferOffline = false, bool preferOffline = false,
}) async { }) async {
if (_topPaginationEnded || _queryTopMessagesController.value!) return; if (_topPaginationEnded ||
_queryTopMessagesController.value! ||
channel.state == null) return;
_queryTopMessagesController.add(true); _queryTopMessagesController.add(true);
late Message message; late Message message;
if (channel.state.threads.containsKey(parentId)) { if (channel.state!.threads.containsKey(parentId)) {
final thread = channel.state.threads[parentId]!; final thread = channel.state!.threads[parentId]!;
if (thread.isNotEmpty) { if (thread.isNotEmpty) {
message = thread.first; message = thread.first;
} }
@@ -170,7 +176,7 @@ class StreamChannelState extends State<StreamChannel> {
final response = await channel.getReplies( final response = await channel.getReplies(
parentId, parentId,
PaginationParams( PaginationParams(
lessThan: message?.id, lessThan: message.id,
limit: limit, limit: limit,
), ),
preferOffline: preferOffline, preferOffline: preferOffline,
@@ -224,8 +230,8 @@ class StreamChannelState extends State<StreamChannel> {
bool preferOffline = false, bool preferOffline = false,
}) async { }) async {
if (channel.state == null) return []; if (channel.state == null) return [];
channel.state.isUpToDate = false; channel.state!.isUpToDate = false;
channel.state.truncate(); channel.state!.truncate();
if (messageId == null) { if (messageId == null) {
await channel.query( await channel.query(
@@ -234,7 +240,7 @@ class StreamChannelState extends State<StreamChannel> {
), ),
preferOffline: preferOffline, preferOffline: preferOffline,
); );
channel.state.isUpToDate = true; channel.state!.isUpToDate = true;
return []; return [];
} }
@@ -280,14 +286,14 @@ class StreamChannelState extends State<StreamChannel> {
preferOffline: preferOffline, preferOffline: preferOffline,
); );
if (state.messages.isEmpty || state.messages.length < limit) { if (state.messages.isEmpty || state.messages.length < limit) {
channel.state.isUpToDate = true; channel.state?.isUpToDate = true;
} }
return state; return state;
} }
/// ///
Future<Message> getMessage(String messageId) async { Future<Message> getMessage(String messageId) async {
var message = channel.state.messages.firstWhereOrNull( var message = channel.state?.messages.firstWhereOrNull(
(it) => it.id == messageId, (it) => it.id == messageId,
); );
if (message == null) { if (message == null) {
@@ -43,9 +43,7 @@ class StreamChatCore extends StatefulWidget {
required this.child, required this.child,
this.onBackgroundEventReceived, this.onBackgroundEventReceived,
this.backgroundKeepAlive = const Duration(minutes: 1), this.backgroundKeepAlive = const Duration(minutes: 1),
}) : assert(client != null, 'Stream Chat Client should not be null'), }) : super(key: key);
assert(child != null, 'Child should not be null'),
super(key: key);
/// Instance of Stream Chat Client containing information about the current /// Instance of Stream Chat Client containing information about the current
/// application. /// application.
@@ -93,15 +91,15 @@ class StreamChatCoreState extends State<StreamChatCore>
Widget build(BuildContext context) => widget.child; Widget build(BuildContext context) => widget.child;
/// The current user /// The current user
User? get user => client.state?.user; User? get user => client.state.user;
/// The current user as a stream /// The current user as a stream
Stream<User>? get userStream => client.state?.userStream; Stream<User?> get userStream => client.state.userStream;
@override @override
void initState() { void initState() {
super.initState(); super.initState();
WidgetsBinding.instance!.addObserver(this); WidgetsBinding.instance?.addObserver(this);
} }
StreamSubscription? _eventSubscription; StreamSubscription? _eventSubscription;
@@ -119,15 +117,15 @@ class StreamChatCoreState extends State<StreamChatCore>
); );
void onTimerComplete() { void onTimerComplete() {
_eventSubscription!.cancel(); _eventSubscription?.cancel();
client.disconnect(); client.disconnect();
} }
_disconnectTimer = Timer(widget.backgroundKeepAlive, onTimerComplete); _disconnectTimer = Timer(widget.backgroundKeepAlive, onTimerComplete);
} else if (state == AppLifecycleState.resumed) { } else if (state == AppLifecycleState.resumed) {
if (_disconnectTimer?.isActive == true) { if (_disconnectTimer?.isActive == true) {
_eventSubscription!.cancel(); _eventSubscription?.cancel();
_disconnectTimer!.cancel(); _disconnectTimer?.cancel();
} else { } else {
if (client.wsConnectionStatus == ConnectionStatus.disconnected) { if (client.wsConnectionStatus == ConnectionStatus.disconnected) {
client.connect(); client.connect();
@@ -139,7 +137,7 @@ class StreamChatCoreState extends State<StreamChatCore>
@override @override
void dispose() { void dispose() {
WidgetsBinding.instance!.removeObserver(this); WidgetsBinding.instance?.removeObserver(this);
_eventSubscription?.cancel(); _eventSubscription?.cancel();
_disconnectTimer?.cancel(); _disconnectTimer?.cancel();
super.dispose(); super.dispose();
@@ -4,7 +4,7 @@ import 'package:stream_chat/stream_chat.dart';
/// A signature for a callback which exposes an error and returns a function. /// A signature for a callback which exposes an error and returns a function.
/// This Callback can be used in cases where an API failure occurs and the /// This Callback can be used in cases where an API failure occurs and the
/// widget is unable to render data. /// widget is unable to render data.
typedef ErrorBuilder = Widget Function(BuildContext context, Object? error); typedef ErrorBuilder = Widget Function(BuildContext context, Object error);
/// A Signature for a handler function which will expose a [event]. /// A Signature for a handler function which will expose a [event].
typedef EventHandler = void Function(Event event); typedef EventHandler = void Function(Event event);
@@ -68,11 +68,7 @@ class UserListCore extends StatefulWidget {
this.pagination, this.pagination,
this.groupAlphabetically = false, this.groupAlphabetically = false,
this.userListController, this.userListController,
}) : assert(errorBuilder != null, ''), }) : super(key: key);
assert(emptyBuilder != null, ''),
assert(loadingBuilder != null, ''),
assert(listBuilder != null, ''),
super(key: key);
/// A [UserListController] allows reloading and pagination. /// A [UserListController] allows reloading and pagination.
/// Use [UserListController.loadData] and [UserListController.paginateData] /// Use [UserListController.loadData] and [UserListController.paginateData]
@@ -80,7 +76,7 @@ class UserListCore extends StatefulWidget {
final UserListController? userListController; final UserListController? userListController;
/// The builder that will be used in case of error /// The builder that will be used in case of error
final Widget Function(Object? error) errorBuilder; final Widget Function(Object error) errorBuilder;
/// The builder that will be used to build the list /// The builder that will be used to build the list
final Widget Function(BuildContext context, List<ListItem> users) listBuilder; final Widget Function(BuildContext context, List<ListItem> users) listBuilder;
@@ -180,7 +176,7 @@ class UserListCoreState extends State<UserListCore>
stream: _buildUserStream(usersBlocState), stream: _buildUserStream(usersBlocState),
builder: (context, snapshot) { builder: (context, snapshot) {
if (snapshot.hasError) { if (snapshot.hasError) {
return widget.errorBuilder(snapshot.error); return widget.errorBuilder(snapshot.error!);
} }
if (!snapshot.hasData) { if (!snapshot.hasData) {
return widget.loadingBuilder(context); return widget.loadingBuilder(context);
@@ -223,8 +219,8 @@ class UserListCoreState extends State<UserListCore>
if (widget.filter?.toString() != oldWidget.filter?.toString() || if (widget.filter?.toString() != oldWidget.filter?.toString() ||
jsonEncode(widget.sort) != jsonEncode(oldWidget.sort) || jsonEncode(widget.sort) != jsonEncode(oldWidget.sort) ||
widget.options?.toString() != oldWidget.options?.toString() || widget.options?.toString() != oldWidget.options?.toString() ||
widget.pagination?.toJson()?.toString() != widget.pagination?.toJson().toString() !=
oldWidget.pagination?.toJson()?.toString()) { oldWidget.pagination?.toJson().toString()) {
loadData(); loadData();
} }
} }
@@ -16,11 +16,7 @@ class UsersBloc extends StatefulWidget {
const UsersBloc({ const UsersBloc({
required this.child, required this.child,
Key? key, Key? key,
}) : assert( }) : super(key: key);
child != null,
'When constructing a UsersBloc, the parameter '
'child should not be null.'),
super(key: key);
/// The widget child /// The widget child
final Widget child; final Widget child;
@@ -76,17 +72,15 @@ class UsersBlocState extends State<UsersBloc>
} }
try { try {
final clear = pagination == null || final clear = pagination == null || pagination.offset == 0;
pagination.offset == null ||
pagination.offset == 0;
final oldUsers = List<User>.from(users ?? []); final oldUsers = List<User>.from(users ?? []);
final usersResponse = await client.queryUsers( final usersResponse = await client.queryUsers(
filter: filter!, filter: filter,
sort: sort!, sort: sort,
options: options!, options: options,
pagination: pagination!, pagination: pagination,
); );
if (clear) { if (clear) {
@@ -12,12 +12,12 @@ environment:
flutter: ">=1.17.0" flutter: ">=1.17.0"
dependencies: dependencies:
collection: ^1.15.0-nullsafety.4
flutter: flutter:
sdk: flutter sdk: flutter
meta: ^1.2.4 meta: ^1.3.0
rxdart: ^0.26.0 rxdart: ^0.26.0
stream_chat: ^1.5.0 stream_chat: ^1.5.2
collection: ^1.15.0-nullsafety.4
dependency_overrides: dependency_overrides:
stream_chat: stream_chat:
@@ -27,5 +27,5 @@ dev_dependencies:
fake_async: ^1.2.0 fake_async: ^1.2.0
flutter_test: flutter_test:
sdk: flutter sdk: flutter
mockito: ^5.0.3 mocktail: ^0.1.1
@@ -1,8 +1,8 @@
import 'dart:async'; import 'dart:async';
import 'package:flutter_test/flutter_test.dart';
import 'package:flutter/widgets.dart'; import 'package:flutter/widgets.dart';
import 'package:mockito/mockito.dart'; import 'package:flutter_test/flutter_test.dart';
import 'package:mocktail/mocktail.dart';
import 'package:stream_chat_flutter_core/src/channel_list_core.dart'; import 'package:stream_chat_flutter_core/src/channel_list_core.dart';
import 'package:stream_chat_flutter_core/stream_chat_flutter_core.dart'; import 'package:stream_chat_flutter_core/stream_chat_flutter_core.dart';
@@ -30,58 +30,6 @@ void main() {
); );
} }
test(
'should throw assertion error in case listBuilder is null',
() {
final channelListCore = () => ChannelListCore(
listBuilder: null,
loadingBuilder: (BuildContext context) => Offstage(),
emptyBuilder: (BuildContext context) => Offstage(),
errorBuilder: (BuildContext context, Object error) => Offstage(),
);
expect(channelListCore, throwsA(isA<AssertionError>()));
},
);
test(
'should throw assertion error in case loadingBuilder is null',
() {
final channelListCore = () => ChannelListCore(
listBuilder: (_, __) => Offstage(),
loadingBuilder: null,
emptyBuilder: (BuildContext context) => Offstage(),
errorBuilder: (BuildContext context, Object error) => Offstage(),
);
expect(channelListCore, throwsA(isA<AssertionError>()));
},
);
test(
'should throw assertion error in case emptyBuilder is null',
() {
final channelListCore = () => ChannelListCore(
listBuilder: (_, __) => Offstage(),
loadingBuilder: (BuildContext context) => Offstage(),
emptyBuilder: null,
errorBuilder: (BuildContext context, Object error) => Offstage(),
);
expect(channelListCore, throwsA(isA<AssertionError>()));
},
);
test(
'should throw assertion error in case errorBuilder is null',
() {
final channelListCore = () => ChannelListCore(
listBuilder: (_, __) => Offstage(),
loadingBuilder: (BuildContext context) => Offstage(),
emptyBuilder: (BuildContext context) => Offstage(),
errorBuilder: null,
);
expect(channelListCore, throwsA(isA<AssertionError>()));
},
);
testWidgets( testWidgets(
'should throw if ChannelListCore is used where ChannelsBloc is not present ' 'should throw if ChannelListCore is used where ChannelsBloc is not present '
'in the widget tree', 'in the widget tree',
@@ -116,7 +64,8 @@ void main() {
final mockClient = MockClient(); final mockClient = MockClient();
when(mockClient.on(any, any, any, any)).thenAnswer((_) => Stream.empty()); when(() => mockClient.on(any(), any(), any(), any()))
.thenAnswer((_) => Stream.empty());
await tester.pumpWidget( await tester.pumpWidget(
StreamChatCore( StreamChatCore(
@@ -151,7 +100,8 @@ void main() {
final mockClient = MockClient(); final mockClient = MockClient();
when(mockClient.on(any, any, any, any)).thenAnswer((_) => Stream.empty()); when(() => mockClient.on(any(), any(), any(), any()))
.thenAnswer((_) => Stream.empty());
await tester.pumpWidget( await tester.pumpWidget(
StreamChatCore( StreamChatCore(
@@ -185,15 +135,16 @@ void main() {
final mockClient = MockClient(); final mockClient = MockClient();
when(mockClient.on(any, any, any, any)).thenAnswer((_) => Stream.empty()); when(() => mockClient.on(any(), any(), any(), any()))
.thenAnswer((_) => Stream.empty());
const error = 'Error! Error! Error!'; const error = 'Error! Error! Error!';
when(mockClient.queryChannels( when(() => mockClient.queryChannels(
filter: anyNamed('filter'), filter: any(named: 'filter'),
sort: anyNamed('sort'), sort: any(named: 'sort'),
options: anyNamed('options'), options: any(named: 'options'),
paginationParams: pagination, paginationParams: pagination,
)).thenThrow(error); )).thenThrow(error);
await tester.pumpWidget( await tester.pumpWidget(
StreamChatCore( StreamChatCore(
@@ -208,12 +159,12 @@ void main() {
expect(find.byKey(errorWidgetKey), findsOneWidget); expect(find.byKey(errorWidgetKey), findsOneWidget);
verify(mockClient.queryChannels( verify(() => mockClient.queryChannels(
filter: anyNamed('filter'), filter: any(named: 'filter'),
sort: anyNamed('sort'), sort: any(named: 'sort'),
options: anyNamed('options'), options: any(named: 'options'),
paginationParams: pagination, paginationParams: pagination,
)).called(1); )).called(1);
}, },
); );
@@ -233,15 +184,16 @@ void main() {
final mockClient = MockClient(); final mockClient = MockClient();
when(mockClient.on(any, any, any, any)).thenAnswer((_) => Stream.empty()); when(() => mockClient.on(any(), any(), any(), any()))
.thenAnswer((_) => Stream.empty());
const channels = <Channel>[]; const channels = <Channel>[];
when(mockClient.queryChannels( when(() => mockClient.queryChannels(
filter: anyNamed('filter'), filter: any(named: 'filter'),
sort: anyNamed('sort'), sort: any(named: 'sort'),
options: anyNamed('options'), options: any(named: 'options'),
paginationParams: pagination, paginationParams: pagination,
)).thenAnswer((_) => Stream.value(channels)); )).thenAnswer((_) => Stream.value(channels));
await tester.pumpWidget( await tester.pumpWidget(
StreamChatCore( StreamChatCore(
@@ -256,12 +208,12 @@ void main() {
expect(find.byKey(emptyWidgetKey), findsOneWidget); expect(find.byKey(emptyWidgetKey), findsOneWidget);
verify(mockClient.queryChannels( verify(() => mockClient.queryChannels(
filter: anyNamed('filter'), filter: any(named: 'filter'),
sort: anyNamed('sort'), sort: any(named: 'sort'),
options: anyNamed('options'), options: any(named: 'options'),
paginationParams: pagination, paginationParams: pagination,
)).called(1); )).called(1);
}, },
); );
@@ -281,15 +233,16 @@ void main() {
final mockClient = MockClient(); final mockClient = MockClient();
when(mockClient.on(any, any, any, any)).thenAnswer((_) => Stream.empty()); when(() => mockClient.on(any(), any(), any(), any()))
.thenAnswer((_) => Stream.empty());
final channels = _generateChannels(mockClient); final channels = _generateChannels(mockClient);
when(mockClient.queryChannels( when(() => mockClient.queryChannels(
filter: anyNamed('filter'), filter: any(named: 'filter'),
sort: anyNamed('sort'), sort: any(named: 'sort'),
options: anyNamed('options'), options: any(named: 'options'),
paginationParams: pagination, paginationParams: pagination,
)).thenAnswer((_) => Stream.value(channels)); )).thenAnswer((_) => Stream.value(channels));
await tester.pumpWidget( await tester.pumpWidget(
StreamChatCore( StreamChatCore(
@@ -304,12 +257,12 @@ void main() {
expect(find.byKey(listWidgetKey), findsOneWidget); expect(find.byKey(listWidgetKey), findsOneWidget);
verify(mockClient.queryChannels( verify(() => mockClient.queryChannels(
filter: anyNamed('filter'), filter: any(named: 'filter'),
sort: anyNamed('sort'), sort: any(named: 'sort'),
options: anyNamed('options'), options: any(named: 'options'),
paginationParams: pagination, paginationParams: pagination,
)).called(1); )).called(1);
}, },
); );
@@ -337,15 +290,16 @@ void main() {
final mockClient = MockClient(); final mockClient = MockClient();
when(mockClient.on(any, any, any, any)).thenAnswer((_) => Stream.empty()); when(() => mockClient.on(any(), any(), any(), any()))
.thenAnswer((_) => Stream.empty());
final channels = _generateChannels(mockClient); final channels = _generateChannels(mockClient);
when(mockClient.queryChannels( when(() => mockClient.queryChannels(
filter: anyNamed('filter'), filter: any(named: 'filter'),
sort: anyNamed('sort'), sort: any(named: 'sort'),
options: anyNamed('options'), options: any(named: 'options'),
paginationParams: pagination, paginationParams: pagination,
)).thenAnswer((_) => Stream.value(channels)); )).thenAnswer((_) => Stream.value(channels));
await tester.pumpWidget( await tester.pumpWidget(
Directionality( Directionality(
@@ -364,12 +318,12 @@ void main() {
expect(find.byKey(listWidgetKey), findsOneWidget); expect(find.byKey(listWidgetKey), findsOneWidget);
expect(find.text(channels.map((e) => e.cid).join(',')), findsOneWidget); expect(find.text(channels.map((e) => e.cid).join(',')), findsOneWidget);
verify(mockClient.queryChannels( verify(() => mockClient.queryChannels(
filter: anyNamed('filter'), filter: any(named: 'filter'),
sort: anyNamed('sort'), sort: any(named: 'sort'),
options: anyNamed('options'), options: any(named: 'options'),
paginationParams: pagination, paginationParams: pagination,
)).called(1); )).called(1);
final channelListCoreState = tester.state<ChannelListCoreState>( final channelListCoreState = tester.state<ChannelListCoreState>(
find.byKey(channelListCoreKey), find.byKey(channelListCoreKey),
@@ -378,12 +332,12 @@ void main() {
final offset = channels.length; final offset = channels.length;
final paginatedChannels = _generateChannels(mockClient, offset: offset); final paginatedChannels = _generateChannels(mockClient, offset: offset);
final updatedPagination = pagination.copyWith(offset: offset); final updatedPagination = pagination.copyWith(offset: offset);
when(mockClient.queryChannels( when(() => mockClient.queryChannels(
filter: anyNamed('filter'), filter: any(named: 'filter'),
sort: anyNamed('sort'), sort: any(named: 'sort'),
options: anyNamed('options'), options: any(named: 'options'),
paginationParams: updatedPagination, paginationParams: updatedPagination,
)).thenAnswer((_) => Stream.value(paginatedChannels)); )).thenAnswer((_) => Stream.value(paginatedChannels));
await channelListCoreState.paginateData(); await channelListCoreState.paginateData();
@@ -398,12 +352,12 @@ void main() {
findsOneWidget, findsOneWidget,
); );
verify(mockClient.queryChannels( verify(() => mockClient.queryChannels(
filter: anyNamed('filter'), filter: any(named: 'filter'),
sort: anyNamed('sort'), sort: any(named: 'sort'),
options: anyNamed('options'), options: any(named: 'options'),
paginationParams: updatedPagination, paginationParams: updatedPagination,
)).called(1); )).called(1);
}, },
); );
@@ -411,8 +365,8 @@ void main() {
'should rebuild ChannelListCore with updated widget data ' 'should rebuild ChannelListCore with updated widget data '
'on calling setState()', 'on calling setState()',
(tester) async { (tester) async {
StateSetter _stateSetter; StateSetter? _stateSetter;
int limit = pagination.limit; var limit = pagination.limit;
const channelListCoreKey = Key('channelListCore'); const channelListCoreKey = Key('channelListCore');
const listWidgetKey = Key('listWidget'); const listWidgetKey = Key('listWidget');
@@ -435,15 +389,16 @@ void main() {
final mockClient = MockClient(); final mockClient = MockClient();
when(mockClient.on(any, any, any, any)).thenAnswer((_) => Stream.empty()); when(() => mockClient.on(any(), any(), any(), any()))
.thenAnswer((_) => Stream.empty());
final channels = _generateChannels(mockClient); final channels = _generateChannels(mockClient);
when(mockClient.queryChannels( when(() => mockClient.queryChannels(
filter: anyNamed('filter'), filter: any(named: 'filter'),
sort: anyNamed('sort'), sort: any(named: 'sort'),
options: anyNamed('options'), options: any(named: 'options'),
paginationParams: pagination, paginationParams: pagination,
)).thenAnswer((_) => Stream.value(channels)); )).thenAnswer((_) => Stream.value(channels));
await tester.pumpWidget( await tester.pumpWidget(
Directionality( Directionality(
@@ -466,24 +421,24 @@ void main() {
expect(find.byKey(listWidgetKey), findsOneWidget); expect(find.byKey(listWidgetKey), findsOneWidget);
expect(find.text(channels.map((e) => e.cid).join(',')), findsOneWidget); expect(find.text(channels.map((e) => e.cid).join(',')), findsOneWidget);
verify(mockClient.queryChannels( verify(() => mockClient.queryChannels(
filter: anyNamed('filter'), filter: any(named: 'filter'),
sort: anyNamed('sort'), sort: any(named: 'sort'),
options: anyNamed('options'), options: any(named: 'options'),
paginationParams: pagination, paginationParams: pagination,
)).called(1); )).called(1);
// Rebuilding ChannelListCore with new pagination limit // Rebuilding ChannelListCore with new pagination limit
_stateSetter(() => limit = 6); _stateSetter?.call(() => limit = 6);
final updatedChannels = _generateChannels(mockClient, count: limit); final updatedChannels = _generateChannels(mockClient, count: limit);
final updatedPagination = pagination.copyWith(limit: limit); final updatedPagination = pagination.copyWith(limit: limit);
when(mockClient.queryChannels( when(() => mockClient.queryChannels(
filter: anyNamed('filter'), filter: any(named: 'filter'),
sort: anyNamed('sort'), sort: any(named: 'sort'),
options: anyNamed('options'), options: any(named: 'options'),
paginationParams: updatedPagination, paginationParams: updatedPagination,
)).thenAnswer((_) => Stream.value(updatedChannels)); )).thenAnswer((_) => Stream.value(updatedChannels));
await tester.pumpAndSettle(); await tester.pumpAndSettle();
@@ -493,12 +448,12 @@ void main() {
findsOneWidget, findsOneWidget,
); );
verify(mockClient.queryChannels( verify(() => mockClient.queryChannels(
filter: anyNamed('filter'), filter: any(named: 'filter'),
sort: anyNamed('sort'), sort: any(named: 'sort'),
options: anyNamed('options'), options: any(named: 'options'),
paginationParams: updatedPagination, paginationParams: updatedPagination,
)).called(1); )).called(1);
}, },
); );
} }
@@ -2,13 +2,17 @@ import 'dart:async';
import 'package:flutter/widgets.dart'; import 'package:flutter/widgets.dart';
import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_test/flutter_test.dart';
import 'package:mockito/mockito.dart'; import 'package:mocktail/mocktail.dart';
import 'package:stream_chat_flutter_core/stream_chat_flutter_core.dart'; import 'package:stream_chat_flutter_core/stream_chat_flutter_core.dart';
import 'matchers/channel_matcher.dart'; import 'matchers/channel_matcher.dart';
import 'mocks.dart'; import 'mocks.dart';
void main() { void main() {
setUpAll(() {
registerFallbackValue<PaginationParams>(const PaginationParams());
});
List<Channel> _generateChannels( List<Channel> _generateChannels(
StreamChatClient client, { StreamChatClient client, {
int count = 3, int count = 3,
@@ -28,18 +32,6 @@ void main() {
); );
} }
test(
'should throw assertion error if child is null',
() async {
const channelsBlocKey = Key('channelsBloc');
final channelsBloc = () => ChannelsBloc(
key: channelsBlocKey,
child: null,
);
expect(channelsBloc, throwsA(isA<AssertionError>()));
},
);
testWidgets( testWidgets(
'should throw if ChannelsBloc is used where StreamChat is not present in the widget tree', 'should throw if ChannelsBloc is used where StreamChat is not present in the widget tree',
(tester) async { (tester) async {
@@ -70,7 +62,8 @@ void main() {
final mockClient = MockClient(); final mockClient = MockClient();
when(mockClient.on(any, any, any, any)).thenAnswer((_) => Stream.empty()); when(() => mockClient.on(any(), any(), any(), any()))
.thenAnswer((_) => Stream.empty());
await tester.pumpWidget( await tester.pumpWidget(
StreamChatCore( StreamChatCore(
@@ -101,7 +94,8 @@ void main() {
final mockClient = MockClient(); final mockClient = MockClient();
when(mockClient.on(any, any, any, any)).thenAnswer((_) => Stream.empty()); when(() => mockClient.on(any(), any(), any(), any()))
.thenAnswer((_) => Stream.empty());
await tester.pumpWidget( await tester.pumpWidget(
StreamChatCore( StreamChatCore(
@@ -117,12 +111,12 @@ void main() {
final offlineChannels = _generateChannels(mockClient); final offlineChannels = _generateChannels(mockClient);
final onlineChannels = _generateChannels(mockClient, offset: 3); final onlineChannels = _generateChannels(mockClient, offset: 3);
when(mockClient.queryChannels( when(() => mockClient.queryChannels(
filter: anyNamed('filter'), filter: any(named: 'filter'),
sort: anyNamed('sort'), sort: any(named: 'sort'),
options: anyNamed('options'), options: any(named: 'options'),
paginationParams: anyNamed('paginationParams'), paginationParams: any(named: 'paginationParams'),
)).thenAnswer( )).thenAnswer(
(_) => Stream.fromIterable([offlineChannels, onlineChannels]), (_) => Stream.fromIterable([offlineChannels, onlineChannels]),
); );
@@ -136,12 +130,12 @@ void main() {
]), ]),
); );
verify(mockClient.queryChannels( verify(() => mockClient.queryChannels(
filter: anyNamed('filter'), filter: any(named: 'filter'),
sort: anyNamed('sort'), sort: any(named: 'sort'),
options: anyNamed('options'), options: any(named: 'options'),
paginationParams: anyNamed('paginationParams'), paginationParams: any(named: 'paginationParams'),
)).called(1); )).called(1);
}, },
); );
@@ -163,7 +157,8 @@ void main() {
final mockClient = MockClient(); final mockClient = MockClient();
when(mockClient.on(any, any, any, any)).thenAnswer((_) => Stream.empty()); when(() => mockClient.on(any(), any(), any(), any()))
.thenAnswer((_) => Stream.empty());
await tester.pumpWidget( await tester.pumpWidget(
StreamChatCore( StreamChatCore(
@@ -176,14 +171,14 @@ void main() {
find.byKey(channelsBlocKey), find.byKey(channelsBlocKey),
); );
final error = 'Error! Error! Error!'; const error = 'Error! Error! Error!';
when(mockClient.queryChannels( when(() => mockClient.queryChannels(
filter: anyNamed('filter'), filter: any(named: 'filter'),
sort: anyNamed('sort'), sort: any(named: 'sort'),
options: anyNamed('options'), options: any(named: 'options'),
paginationParams: anyNamed('paginationParams'), paginationParams: any(named: 'paginationParams'),
)).thenThrow(error); )).thenThrow(error);
channelsBlocState.queryChannels(); channelsBlocState.queryChannels();
@@ -192,12 +187,12 @@ void main() {
emitsError(error), emitsError(error),
); );
verify(mockClient.queryChannels( verify(() => mockClient.queryChannels(
filter: anyNamed('filter'), filter: any(named: 'filter'),
sort: anyNamed('sort'), sort: any(named: 'sort'),
options: anyNamed('options'), options: any(named: 'options'),
paginationParams: anyNamed('paginationParams'), paginationParams: any(named: 'paginationParams'),
)).called(1); )).called(1);
}, },
); );
@@ -214,7 +209,8 @@ void main() {
final mockClient = MockClient(); final mockClient = MockClient();
when(mockClient.on(any, any, any, any)).thenAnswer((_) => Stream.empty()); when(() => mockClient.on(any(), any(), any(), any()))
.thenAnswer((_) => Stream.empty());
await tester.pumpWidget( await tester.pumpWidget(
StreamChatCore( StreamChatCore(
@@ -229,38 +225,41 @@ void main() {
final channels = _generateChannels(mockClient); final channels = _generateChannels(mockClient);
when(mockClient.queryChannels( when(() => mockClient.queryChannels(
filter: anyNamed('filter'), filter: any(named: 'filter'),
sort: anyNamed('sort'), sort: any(named: 'sort'),
options: anyNamed('options'), options: any(named: 'options'),
paginationParams: anyNamed('paginationParams'), paginationParams: any(named: 'paginationParams'),
)).thenAnswer((_) => Stream.value(channels)); )).thenAnswer((_) => Stream.value(channels));
channelsBlocState.queryChannels(); const pagination = PaginationParams(limit: 3);
channelsBlocState.queryChannels(
paginationParams: pagination,
);
await expectLater( await expectLater(
channelsBlocState.channelsStream, channelsBlocState.channelsStream,
emits(isSameChannelListAs(channels)), emits(isSameChannelListAs(channels)),
); );
verify(mockClient.queryChannels( verify(() => mockClient.queryChannels(
filter: anyNamed('filter'), filter: any(named: 'filter'),
sort: anyNamed('sort'), sort: any(named: 'sort'),
options: anyNamed('options'), options: any(named: 'options'),
paginationParams: anyNamed('paginationParams'), paginationParams: any(named: 'paginationParams'),
)).called(1); )).called(1);
final offset = channels.length; final offset = channels.length;
final paginationParams = PaginationParams(offset: offset); final paginationParams = pagination.copyWith(offset: offset);
final newChannels = _generateChannels(mockClient, offset: offset); final newChannels = _generateChannels(mockClient, offset: offset);
when(mockClient.queryChannels( when(() => mockClient.queryChannels(
filter: anyNamed('filter'), filter: any(named: 'filter'),
sort: anyNamed('sort'), sort: any(named: 'sort'),
options: anyNamed('options'), options: any(named: 'options'),
paginationParams: paginationParams, paginationParams: paginationParams,
)).thenAnswer( )).thenAnswer(
(_) => Stream.value(newChannels), (_) => Stream.value(newChannels),
); );
@@ -277,12 +276,12 @@ void main() {
), ),
]); ]);
verify(mockClient.queryChannels( verify(() => mockClient.queryChannels(
filter: anyNamed('filter'), filter: any(named: 'filter'),
sort: anyNamed('sort'), sort: any(named: 'sort'),
options: anyNamed('options'), options: any(named: 'options'),
paginationParams: paginationParams, paginationParams: paginationParams,
)).called(1); )).called(1);
}, },
); );
@@ -299,7 +298,8 @@ void main() {
final mockClient = MockClient(); final mockClient = MockClient();
when(mockClient.on(any, any, any, any)).thenAnswer((_) => Stream.empty()); when(() => mockClient.on(any(), any(), any(), any()))
.thenAnswer((_) => Stream.empty());
await tester.pumpWidget( await tester.pumpWidget(
StreamChatCore( StreamChatCore(
@@ -313,39 +313,41 @@ void main() {
); );
final channels = _generateChannels(mockClient); final channels = _generateChannels(mockClient);
final paginationParams = const PaginationParams(
limit: 3,
);
when(mockClient.queryChannels( when(() => mockClient.queryChannels(
filter: anyNamed('filter'), filter: any(named: 'filter'),
sort: anyNamed('sort'), sort: any(named: 'sort'),
options: anyNamed('options'), options: any(named: 'options'),
paginationParams: anyNamed('paginationParams'), paginationParams: paginationParams,
)).thenAnswer((_) => Stream.value(channels)); )).thenAnswer((_) => Stream.value(channels));
channelsBlocState.queryChannels(); channelsBlocState.queryChannels(
paginationParams: paginationParams,
);
await expectLater( await expectLater(
channelsBlocState.channelsStream, channelsBlocState.channelsStream,
emits(isSameChannelListAs(channels)), emits(isSameChannelListAs(channels)),
); );
verify(mockClient.queryChannels( verify(() => mockClient.queryChannels(
filter: anyNamed('filter'), filter: any(named: 'filter'),
sort: anyNamed('sort'), sort: any(named: 'sort'),
options: anyNamed('options'), options: any(named: 'options'),
paginationParams: anyNamed('paginationParams'), paginationParams: paginationParams,
)).called(1); )).called(1);
final offset = channels.length;
final paginationParams = PaginationParams(offset: offset);
final error = 'Error! Error! Error!'; final error = 'Error! Error! Error!';
when(mockClient.queryChannels( when(() => mockClient.queryChannels(
filter: anyNamed('filter'), filter: any(named: 'filter'),
sort: anyNamed('sort'), sort: any(named: 'sort'),
options: anyNamed('options'), options: any(named: 'options'),
paginationParams: paginationParams, paginationParams: paginationParams,
)).thenThrow(error); )).thenThrow(error);
channelsBlocState.queryChannels(paginationParams: paginationParams); channelsBlocState.queryChannels(paginationParams: paginationParams);
@@ -354,17 +356,17 @@ void main() {
emitsError(error), emitsError(error),
); );
verify(mockClient.queryChannels( verify(() => mockClient.queryChannels(
filter: anyNamed('filter'), filter: any(named: 'filter'),
sort: anyNamed('sort'), sort: any(named: 'sort'),
options: anyNamed('options'), options: any(named: 'options'),
paginationParams: paginationParams, paginationParams: paginationParams,
)).called(1); )).called(1);
}, },
); );
group('event controller test', () { group('event controller test', () {
StreamController<Event> eventController; late StreamController<Event> eventController;
setUp(() { setUp(() {
eventController = StreamController<Event>.broadcast(); eventController = StreamController<Event>.broadcast();
}); });
@@ -379,12 +381,12 @@ void main() {
child: Offstage(), child: Offstage(),
); );
when(mockClient.on(any, any, any, any)) when(() => mockClient.on(any(), any(), any(), any()))
.thenAnswer((_) => Stream.empty()); .thenAnswer((_) => Stream.empty());
when(mockClient.on( when(() => mockClient.on(
EventType.channelHidden, EventType.channelHidden,
)).thenAnswer((_) => eventController.stream); )).thenAnswer((_) => eventController.stream);
await tester.pumpWidget( await tester.pumpWidget(
StreamChatCore( StreamChatCore(
@@ -399,23 +401,23 @@ void main() {
final channels = _generateChannels(mockClient); final channels = _generateChannels(mockClient);
when(mockClient.queryChannels( when(() => mockClient.queryChannels(
filter: anyNamed('filter'), filter: any(named: 'filter'),
sort: anyNamed('sort'), sort: any(named: 'sort'),
options: anyNamed('options'), options: any(named: 'options'),
paginationParams: anyNamed('paginationParams'), paginationParams: any(named: 'paginationParams'),
)).thenAnswer( )).thenAnswer(
(_) => Stream.value(channels), (_) => Stream.value(channels),
); );
await channelsBlocState.queryChannels(); await channelsBlocState.queryChannels();
verify(mockClient.queryChannels( verify(() => mockClient.queryChannels(
filter: anyNamed('filter'), filter: any(named: 'filter'),
sort: anyNamed('sort'), sort: any(named: 'sort'),
options: anyNamed('options'), options: any(named: 'options'),
paginationParams: anyNamed('paginationParams'), paginationParams: any(named: 'paginationParams'),
)).called(1); )).called(1);
final channelHiddenEvent = Event( final channelHiddenEvent = Event(
type: EventType.channelHidden, type: EventType.channelHidden,
@@ -435,7 +437,7 @@ void main() {
]), ]),
); );
verify(mockClient.on(EventType.channelHidden)).called(1); verify(() => mockClient.on(EventType.channelHidden)).called(1);
}, },
); );
@@ -450,13 +452,13 @@ void main() {
child: Offstage(), child: Offstage(),
); );
when(mockClient.on(any, any, any, any)) when(() => mockClient.on(any(), any(), any(), any()))
.thenAnswer((_) => Stream.empty()); .thenAnswer((_) => Stream.empty());
when(mockClient.on( when(() => mockClient.on(
EventType.channelDeleted, EventType.channelDeleted,
EventType.notificationRemovedFromChannel, EventType.notificationRemovedFromChannel,
)).thenAnswer((_) => eventController.stream); )).thenAnswer((_) => eventController.stream);
await tester.pumpWidget( await tester.pumpWidget(
StreamChatCore( StreamChatCore(
@@ -471,31 +473,38 @@ void main() {
final channels = _generateChannels(mockClient); final channels = _generateChannels(mockClient);
when(mockClient.queryChannels( when(() => mockClient.queryChannels(
filter: anyNamed('filter'), filter: any(named: 'filter'),
sort: anyNamed('sort'), sort: any(named: 'sort'),
options: anyNamed('options'), options: any(named: 'options'),
paginationParams: anyNamed('paginationParams'), paginationParams: any(named: 'paginationParams'),
)).thenAnswer( )).thenAnswer(
(_) => Stream.value(channels), (_) => Stream.value(channels),
); );
await channelsBlocState.queryChannels(); await channelsBlocState.queryChannels();
verify(mockClient.queryChannels( verify(() => mockClient.queryChannels(
filter: anyNamed('filter'), filter: any(named: 'filter'),
sort: anyNamed('sort'), sort: any(named: 'sort'),
options: anyNamed('options'), options: any(named: 'options'),
paginationParams: anyNamed('paginationParams'), paginationParams: any(named: 'paginationParams'),
)).called(1); )).called(1);
final channelDeletedOrNotificationRemovedEvent = Event( final channelDeletedOrNotificationRemovedEvent = Event(
channel: EventChannel(cid: channels.first.cid), channel: EventChannel(
cid: channels.first.cid!,
updatedAt: DateTime.now(),
config: ChannelConfig(),
createdAt: DateTime.now(),
memberCount: 1,
),
); );
eventController.add(channelDeletedOrNotificationRemovedEvent); eventController.add(channelDeletedOrNotificationRemovedEvent);
final channelCid = channelDeletedOrNotificationRemovedEvent.channel.cid; final channelCid =
channelDeletedOrNotificationRemovedEvent.channel?.cid;
final newChannels = [...channels] final newChannels = [...channels]
..removeWhere((it) => it.cid == channelCid); ..removeWhere((it) => it.cid == channelCid);
@@ -507,10 +516,10 @@ void main() {
]), ]),
); );
verify(mockClient.on( verify(() => mockClient.on(
EventType.channelDeleted, EventType.channelDeleted,
EventType.notificationRemovedFromChannel, EventType.notificationRemovedFromChannel,
)).called(1); )).called(1);
}, },
); );
@@ -525,12 +534,12 @@ void main() {
child: Offstage(), child: Offstage(),
); );
when(mockClient.on(any, any, any, any)) when(() => mockClient.on(any(), any(), any(), any()))
.thenAnswer((_) => Stream.empty()); .thenAnswer((_) => Stream.empty());
when(mockClient.on( when(() => mockClient.on(
EventType.messageNew, EventType.messageNew,
)).thenAnswer((_) => eventController.stream); )).thenAnswer((_) => eventController.stream);
await tester.pumpWidget( await tester.pumpWidget(
StreamChatCore( StreamChatCore(
@@ -545,23 +554,23 @@ void main() {
final channels = _generateChannels(mockClient); final channels = _generateChannels(mockClient);
when(mockClient.queryChannels( when(() => mockClient.queryChannels(
filter: anyNamed('filter'), filter: any(named: 'filter'),
sort: anyNamed('sort'), sort: any(named: 'sort'),
options: anyNamed('options'), options: any(named: 'options'),
paginationParams: anyNamed('paginationParams'), paginationParams: any(named: 'paginationParams'),
)).thenAnswer( )).thenAnswer(
(_) => Stream.value(channels), (_) => Stream.value(channels),
); );
await channelsBlocState.queryChannels(); await channelsBlocState.queryChannels();
verify(mockClient.queryChannels( verify(() => mockClient.queryChannels(
filter: anyNamed('filter'), filter: any(named: 'filter'),
sort: anyNamed('sort'), sort: any(named: 'sort'),
options: anyNamed('options'), options: any(named: 'options'),
paginationParams: anyNamed('paginationParams'), paginationParams: any(named: 'paginationParams'),
)).called(1); )).called(1);
final messageNewEvent = Event( final messageNewEvent = Event(
type: EventType.messageNew, type: EventType.messageNew,
@@ -585,7 +594,7 @@ void main() {
]), ]),
); );
verify(mockClient.on(EventType.messageNew)).called(1); verify(() => mockClient.on(EventType.messageNew)).called(1);
}, },
); );
@@ -609,16 +618,16 @@ void main() {
shouldAddChannel: (e) => channels.map((it) => it.cid).contains(e.cid), shouldAddChannel: (e) => channels.map((it) => it.cid).contains(e.cid),
); );
when(mockClient.on(any, any, any, any)) when(() => mockClient.on(any(), any(), any(), any()))
.thenAnswer((_) => Stream.empty()); .thenAnswer((_) => Stream.empty());
when(mockClient.on( when(() => mockClient.on(
EventType.channelHidden, EventType.channelHidden,
)).thenAnswer((_) => hiddenChannelEventController.stream); )).thenAnswer((_) => hiddenChannelEventController.stream);
when(mockClient.on( when(() => mockClient.on(
EventType.messageNew, EventType.messageNew,
)).thenAnswer((_) => eventController.stream); )).thenAnswer((_) => eventController.stream);
final messageNewEvent = Event( final messageNewEvent = Event(
type: EventType.messageNew, type: EventType.messageNew,
@@ -636,23 +645,23 @@ void main() {
find.byKey(channelsBlocKey), find.byKey(channelsBlocKey),
); );
when(mockClient.queryChannels( when(() => mockClient.queryChannels(
filter: anyNamed('filter'), filter: any(named: 'filter'),
sort: anyNamed('sort'), sort: any(named: 'sort'),
options: anyNamed('options'), options: any(named: 'options'),
paginationParams: anyNamed('paginationParams'), paginationParams: any(named: 'paginationParams'),
)).thenAnswer( )).thenAnswer(
(_) => Stream.value(channels), (_) => Stream.value(channels),
); );
await channelsBlocState.queryChannels(); await channelsBlocState.queryChannels();
verify(mockClient.queryChannels( verify(() => mockClient.queryChannels(
filter: anyNamed('filter'), filter: any(named: 'filter'),
sort: anyNamed('sort'), sort: any(named: 'sort'),
options: anyNamed('options'), options: any(named: 'options'),
paginationParams: anyNamed('paginationParams'), paginationParams: any(named: 'paginationParams'),
)).called(1); )).called(1);
final channelHiddenEvent = Event( final channelHiddenEvent = Event(
type: EventType.channelHidden, type: EventType.channelHidden,
@@ -681,8 +690,8 @@ void main() {
]), ]),
); );
verify(mockClient.on(EventType.channelHidden)).called(1); verify(() => mockClient.on(EventType.channelHidden)).called(1);
verify(mockClient.on(EventType.messageNew)).called(1); verify(() => mockClient.on(EventType.messageNew)).called(1);
}, },
); );
@@ -703,14 +712,14 @@ void main() {
shouldAddChannel: (_) => true, shouldAddChannel: (_) => true,
); );
when(mockClient.state.channels).thenReturn(stateChannels); when(() => mockClient.state.channels).thenReturn(stateChannels);
when(mockClient.on(any, any, any, any)) when(() => mockClient.on(any(), any(), any(), any()))
.thenAnswer((_) => Stream.empty()); .thenAnswer((_) => Stream.empty());
when(mockClient.on( when(() => mockClient.on(
EventType.messageNew, EventType.messageNew,
)).thenAnswer((_) => eventController.stream); )).thenAnswer((_) => eventController.stream);
await tester.pumpWidget( await tester.pumpWidget(
StreamChatCore( StreamChatCore(
@@ -723,23 +732,23 @@ void main() {
find.byKey(channelsBlocKey), find.byKey(channelsBlocKey),
); );
when(mockClient.queryChannels( when(() => mockClient.queryChannels(
filter: anyNamed('filter'), filter: any(named: 'filter'),
sort: anyNamed('sort'), sort: any(named: 'sort'),
options: anyNamed('options'), options: any(named: 'options'),
paginationParams: anyNamed('paginationParams'), paginationParams: any(named: 'paginationParams'),
)).thenAnswer( )).thenAnswer(
(_) => Stream.value(channels), (_) => Stream.value(channels),
); );
await channelsBlocState.queryChannels(); await channelsBlocState.queryChannels();
verify(mockClient.queryChannels( verify(() => mockClient.queryChannels(
filter: anyNamed('filter'), filter: any(named: 'filter'),
sort: anyNamed('sort'), sort: any(named: 'sort'),
options: anyNamed('options'), options: any(named: 'options'),
paginationParams: anyNamed('paginationParams'), paginationParams: any(named: 'paginationParams'),
)).called(1); )).called(1);
final messageNewEvent = Event( final messageNewEvent = Event(
type: EventType.messageNew, type: EventType.messageNew,
@@ -749,7 +758,7 @@ void main() {
eventController.add(messageNewEvent); eventController.add(messageNewEvent);
final newChannels = [...channels] final newChannels = [...channels]
..insert(0, stateChannels[stateChannels.keys.first]); ..insert(0, stateChannels[stateChannels.keys.first]!);
await expectLater( await expectLater(
channelsBlocState.channelsStream, channelsBlocState.channelsStream,
@@ -759,7 +768,7 @@ void main() {
]), ]),
); );
verify(mockClient.on(EventType.messageNew)).called(1); verify(() => mockClient.on(EventType.messageNew)).called(1);
}, },
); );
@@ -770,8 +779,8 @@ void main() {
final mockClient = MockClient(); final mockClient = MockClient();
final channels = _generateChannels(mockClient); final channels = _generateChannels(mockClient);
int channelComparator(Channel a, Channel b) { int channelComparator(Channel a, Channel b) {
final aData = a.extraData['extra_data_key'] as String; final aData = a.extraData!['extra_data_key'] as String;
final bData = b.extraData['extra_data_key'] as String; final bData = b.extraData!['extra_data_key'] as String;
return bData.compareTo(aData); return bData.compareTo(aData);
} }
@@ -783,12 +792,12 @@ void main() {
channelsComparator: channelComparator, channelsComparator: channelComparator,
); );
when(mockClient.on(any, any, any, any)) when(() => mockClient.on(any(), any(), any(), any()))
.thenAnswer((_) => Stream.empty()); .thenAnswer((_) => Stream.empty());
when(mockClient.on( when(() => mockClient.on(
EventType.messageNew, EventType.messageNew,
)).thenAnswer((_) => eventController.stream); )).thenAnswer((_) => eventController.stream);
await tester.pumpWidget( await tester.pumpWidget(
StreamChatCore( StreamChatCore(
@@ -801,23 +810,23 @@ void main() {
find.byKey(channelsBlocKey), find.byKey(channelsBlocKey),
); );
when(mockClient.queryChannels( when(() => mockClient.queryChannels(
filter: anyNamed('filter'), filter: any(named: 'filter'),
sort: anyNamed('sort'), sort: any(named: 'sort'),
options: anyNamed('options'), options: any(named: 'options'),
paginationParams: anyNamed('paginationParams'), paginationParams: any(named: 'paginationParams'),
)).thenAnswer( )).thenAnswer(
(_) => Stream.value(channels), (_) => Stream.value(channels),
); );
await channelsBlocState.queryChannels(); await channelsBlocState.queryChannels();
verify(mockClient.queryChannels( verify(() => mockClient.queryChannels(
filter: anyNamed('filter'), filter: any(named: 'filter'),
sort: anyNamed('sort'), sort: any(named: 'sort'),
options: anyNamed('options'), options: any(named: 'options'),
paginationParams: anyNamed('paginationParams'), paginationParams: any(named: 'paginationParams'),
)).called(1); )).called(1);
final messageNewEvent = Event( final messageNewEvent = Event(
type: EventType.messageNew, type: EventType.messageNew,
@@ -836,7 +845,7 @@ void main() {
]), ]),
); );
verify(mockClient.on(EventType.messageNew)).called(1); verify(() => mockClient.on(EventType.messageNew)).called(1);
}, },
); );
@@ -3,18 +3,6 @@ import 'package:flutter_test/flutter_test.dart';
import 'package:stream_chat_flutter_core/src/lazy_load_scroll_view.dart'; import 'package:stream_chat_flutter_core/src/lazy_load_scroll_view.dart';
void main() { void main() {
test(
'should throw assertion error if child is null',
() async {
const lazyLoadScrollViewKey = Key('lazyLoadScrollView');
final lazyLoadScrollView = () => LazyLoadScrollView(
key: lazyLoadScrollViewKey,
child: null,
);
expect(lazyLoadScrollView, throwsA(isA<AssertionError>()));
},
);
testWidgets( testWidgets(
'should render LazyLoadScrollView if child is provided', 'should render LazyLoadScrollView if child is provided',
(tester) async { (tester) async {
@@ -1,4 +1,3 @@
import 'package:meta/meta.dart';
import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_test/flutter_test.dart';
import 'package:stream_chat_flutter_core/stream_chat_flutter_core.dart'; import 'package:stream_chat_flutter_core/stream_chat_flutter_core.dart';
@@ -8,14 +7,14 @@ Matcher isSameMessageResponseAs(GetMessageResponse targetResponse) =>
class _IsSameMessageResponseAs extends Matcher { class _IsSameMessageResponseAs extends Matcher {
const _IsSameMessageResponseAs({ const _IsSameMessageResponseAs({
required this.targetResponse, required this.targetResponse,
}) : assert(targetResponse != null, ''); });
final GetMessageResponse targetResponse; final GetMessageResponse targetResponse;
@override @override
bool matches(covariant GetMessageResponse response, Map matchState) => bool matches(covariant GetMessageResponse response, Map matchState) =>
response.message.id == targetResponse.message.id && response.message.id == targetResponse.message.id &&
response.channel.cid == targetResponse.channel.cid; response.channel?.cid == targetResponse.channel?.cid;
@override @override
Description describe(Description description) => Description describe(Description description) =>
@@ -29,14 +28,14 @@ Matcher isSameMessageResponseListAs(
class _IsSameMessageResponseListAs extends Matcher { class _IsSameMessageResponseListAs extends Matcher {
const _IsSameMessageResponseListAs({ const _IsSameMessageResponseListAs({
required this.targetResponseList, required this.targetResponseList,
}) : assert(targetResponseList != null, ''); });
final List<GetMessageResponse> targetResponseList; final List<GetMessageResponse> targetResponseList;
@override @override
bool matches( bool matches(
covariant List<GetMessageResponse> responseList, Map matchState) { covariant List<GetMessageResponse> responseList, Map matchState) {
bool matches = true; var matches = true;
for (var i = 0; i < responseList.length; i++) { for (var i = 0; i < responseList.length; i++) {
final response = responseList[i]; final response = responseList[i];
final targetResponse = targetResponseList[i]; final targetResponse = targetResponseList[i];
@@ -2,7 +2,7 @@ import 'dart:async';
import 'package:flutter/widgets.dart'; import 'package:flutter/widgets.dart';
import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_test/flutter_test.dart';
import 'package:mockito/mockito.dart'; import 'package:mocktail/mocktail.dart';
import 'package:stream_chat_flutter_core/src/message_list_core.dart'; import 'package:stream_chat_flutter_core/src/message_list_core.dart';
import 'package:stream_chat_flutter_core/stream_chat_flutter_core.dart'; import 'package:stream_chat_flutter_core/stream_chat_flutter_core.dart';
@@ -62,61 +62,6 @@ void main() {
return threads ? threadMessages : messages; return threads ? threadMessages : messages;
} }
test(
'should throw assertion error in case messageListBuilder is null',
() {
final messageListCore = () => MessageListCore(
messageListBuilder: null,
loadingBuilder: (BuildContext context) => Offstage(),
emptyBuilder: (BuildContext context) => Offstage(),
errorWidgetBuilder: (BuildContext context, Object error) =>
Offstage(),
);
expect(messageListCore, throwsA(isA<AssertionError>()));
},
);
test(
'should throw assertion error in case loadingBuilder is null',
() {
final messageListCore = () => MessageListCore(
messageListBuilder: (_, __) => Offstage(),
loadingBuilder: null,
emptyBuilder: (BuildContext context) => Offstage(),
errorWidgetBuilder: (BuildContext context, Object error) =>
Offstage(),
);
expect(messageListCore, throwsA(isA<AssertionError>()));
},
);
test(
'should throw assertion error in case emptyBuilder is null',
() {
final messageListCore = () => MessageListCore(
messageListBuilder: (_, __) => Offstage(),
loadingBuilder: (BuildContext context) => Offstage(),
emptyBuilder: null,
errorWidgetBuilder: (BuildContext context, Object error) =>
Offstage(),
);
expect(messageListCore, throwsA(isA<AssertionError>()));
},
);
test(
'should throw assertion error in case errorWidgetBuilder is null',
() {
final messageListCore = () => MessageListCore(
messageListBuilder: (_, __) => Offstage(),
loadingBuilder: (BuildContext context) => Offstage(),
emptyBuilder: (BuildContext context) => Offstage(),
errorWidgetBuilder: null,
);
expect(messageListCore, throwsA(isA<AssertionError>()));
},
);
testWidgets( testWidgets(
'should throw if MessageListCore is used where StreamChannel is not present ' 'should throw if MessageListCore is used where StreamChannel is not present '
'in the widget tree', 'in the widget tree',
@@ -150,8 +95,11 @@ void main() {
); );
final mockChannel = MockChannel(); final mockChannel = MockChannel();
when(() => mockChannel.initialized).thenAnswer((_) => Future.value(true));
when(mockChannel.state.isUpToDate).thenReturn(true); when(() => mockChannel.state.isUpToDate).thenReturn(true);
when(() => mockChannel.state.messagesStream)
.thenAnswer((_) => Stream.value([]));
await tester.pumpWidget( await tester.pumpWidget(
StreamChannel( StreamChannel(
@@ -182,7 +130,10 @@ void main() {
final mockChannel = MockChannel(); final mockChannel = MockChannel();
when(mockChannel.state.isUpToDate).thenReturn(true); when(() => mockChannel.state.isUpToDate).thenReturn(true);
when(() => mockChannel.state.messagesStream)
.thenAnswer((_) => Stream.value([]));
when(() => mockChannel.initialized).thenAnswer((_) => Future.value(true));
await tester.pumpWidget( await tester.pumpWidget(
StreamChannel( StreamChannel(
@@ -213,11 +164,11 @@ void main() {
final mockChannel = MockChannel(); final mockChannel = MockChannel();
when(mockChannel.state.isUpToDate).thenReturn(true); when(() => mockChannel.state.isUpToDate).thenReturn(true);
when(mockChannel.initialized).thenAnswer((_) async => true); when(() => mockChannel.initialized).thenAnswer((_) async => true);
const error = 'Error! Error! Error!'; const error = 'Error! Error! Error!';
when(mockChannel.state.messagesStream) when(() => mockChannel.state.messagesStream)
.thenAnswer((_) => Stream.error(error)); .thenAnswer((_) => Stream.error(error));
await tester.pumpWidget( await tester.pumpWidget(
@@ -252,11 +203,11 @@ void main() {
final mockChannel = MockChannel(); final mockChannel = MockChannel();
when(mockChannel.state.isUpToDate).thenReturn(true); when(() => mockChannel.state.isUpToDate).thenReturn(true);
when(mockChannel.initialized).thenAnswer((_) async => true); when(() => mockChannel.initialized).thenAnswer((_) async => true);
const messages = <Message>[]; const messages = <Message>[];
when(mockChannel.state.messagesStream) when(() => mockChannel.state.messagesStream)
.thenAnswer((_) => Stream.value(messages)); .thenAnswer((_) => Stream.value(messages));
await tester.pumpWidget( await tester.pumpWidget(
@@ -291,11 +242,18 @@ void main() {
final mockChannel = MockChannel(); final mockChannel = MockChannel();
when(mockChannel.state.isUpToDate).thenReturn(false); when(() => mockChannel.state.isUpToDate).thenReturn(false);
when(mockChannel.initialized).thenAnswer((_) async => true); when(() => mockChannel.initialized).thenAnswer((_) async => true);
when(() => mockChannel.query(
options: any(named: 'options'),
membersPagination: any(named: 'membersPagination'),
messagesPagination: any(named: 'messagesPagination'),
preferOffline: any(named: 'preferOffline'),
watchersPagination: any(named: 'watchersPagination'),
)).thenAnswer((_) async => ChannelState());
const messages = <Message>[]; const messages = <Message>[];
when(mockChannel.state.messagesStream) when(() => mockChannel.state.messagesStream)
.thenAnswer((_) => Stream.value(messages)); .thenAnswer((_) => Stream.value(messages));
await tester.pumpWidget( await tester.pumpWidget(
@@ -335,11 +293,11 @@ void main() {
final mockChannel = MockChannel(); final mockChannel = MockChannel();
when(mockChannel.state.isUpToDate).thenReturn(true); when(() => mockChannel.state.isUpToDate).thenReturn(true);
when(mockChannel.initialized).thenAnswer((_) async => true); when(() => mockChannel.initialized).thenAnswer((_) async => true);
final messages = _generateMessages(); final messages = _generateMessages();
when(mockChannel.state.messagesStream) when(() => mockChannel.state.messagesStream)
.thenAnswer((_) => Stream.value(messages)); .thenAnswer((_) => Stream.value(messages));
await tester.pumpWidget( await tester.pumpWidget(
@@ -382,13 +340,13 @@ void main() {
final mockChannel = MockChannel(); final mockChannel = MockChannel();
when(mockChannel.state.isUpToDate).thenReturn(true); when(() => mockChannel.state.isUpToDate).thenReturn(true);
when(mockChannel.initialized).thenAnswer((_) async => true); when(() => mockChannel.initialized).thenAnswer((_) async => true);
final threads = {parentMessage.id: messages}; final threads = {parentMessage.id: messages};
when(mockChannel.state.threads).thenReturn(threads); when(() => mockChannel.state.threads).thenReturn(threads);
when(mockChannel.state.threadsStream) when(() => mockChannel.state.threadsStream)
.thenAnswer((_) => Stream.value(threads)); .thenAnswer((_) => Stream.value(threads));
await tester.pumpWidget( await tester.pumpWidget(
@@ -1,6 +1,6 @@
import 'package:flutter/widgets.dart'; import 'package:flutter/widgets.dart';
import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_test/flutter_test.dart';
import 'package:mockito/mockito.dart'; import 'package:mocktail/mocktail.dart';
import 'package:stream_chat/stream_chat.dart'; import 'package:stream_chat/stream_chat.dart';
import 'package:stream_chat_flutter_core/src/message_search_bloc.dart'; import 'package:stream_chat_flutter_core/src/message_search_bloc.dart';
import 'package:stream_chat_flutter_core/stream_chat_flutter_core.dart'; import 'package:stream_chat_flutter_core/stream_chat_flutter_core.dart';
@@ -23,24 +23,12 @@ void main() {
text: 'testTextData$index', text: 'testTextData$index',
) )
..channel = ChannelModel( ..channel = ChannelModel(
cid: 'testCid', cid: 'testCid:id',
); );
}, },
); );
} }
test(
'should throw assertion error if child is null',
() async {
const messageSearchBlocKey = Key('messageSearchBloc');
final messageSearchBloc = () => MessageSearchBloc(
key: messageSearchBlocKey,
child: null,
);
expect(messageSearchBloc, throwsA(isA<AssertionError>()));
},
);
testWidgets( testWidgets(
'messageSearchBlocState.search() should throw if used where ' 'messageSearchBlocState.search() should throw if used where '
'StreamChat is not present in the widget tree', 'StreamChat is not present in the widget tree',
@@ -62,7 +50,7 @@ void main() {
); );
try { try {
await usersBlocState.search(); await usersBlocState.search(filter: {});
} catch (e) { } catch (e) {
expect(e, isInstanceOf<Exception>()); expect(e, isInstanceOf<Exception>());
} }
@@ -93,30 +81,30 @@ void main() {
final messageResponseList = _generateMessages(); final messageResponseList = _generateMessages();
when(mockClient.search( when(() => mockClient.search(
any, any(),
query: anyNamed('query'), query: any(named: 'query'),
sort: anyNamed('sort'), sort: any(named: 'sort'),
messageFilters: anyNamed('messageFilters'), messageFilters: any(named: 'messageFilters'),
paginationParams: anyNamed('paginationParams'), paginationParams: any(named: 'paginationParams'),
)).thenAnswer( )).thenAnswer(
(_) async => SearchMessagesResponse()..results = messageResponseList, (_) async => SearchMessagesResponse()..results = messageResponseList,
); );
messageSearchBlocState.search(); messageSearchBlocState.search(filter: {});
await expectLater( await expectLater(
messageSearchBlocState.messagesStream, messageSearchBlocState.messagesStream,
emits(isSameMessageResponseListAs(messageResponseList)), emits(isSameMessageResponseListAs(messageResponseList)),
); );
verify(mockClient.search( verify(() => mockClient.search(
any, any(),
query: anyNamed('query'), query: any(named: 'query'),
sort: anyNamed('sort'), sort: any(named: 'sort'),
messageFilters: anyNamed('messageFilters'), messageFilters: any(named: 'messageFilters'),
paginationParams: anyNamed('paginationParams'), paginationParams: any(named: 'paginationParams'),
)).called(1); )).called(1);
}, },
); );
@@ -144,28 +132,28 @@ void main() {
); );
const error = 'Error! Error! Error!'; const error = 'Error! Error! Error!';
when(mockClient.search( when(() => mockClient.search(
any, any(),
query: anyNamed('query'), query: any(named: 'query'),
sort: anyNamed('sort'), sort: any(named: 'sort'),
messageFilters: anyNamed('messageFilters'), messageFilters: any(named: 'messageFilters'),
paginationParams: anyNamed('paginationParams'), paginationParams: any(named: 'paginationParams'),
)).thenThrow(error); )).thenThrow(error);
messageSearchBlocState.search(); messageSearchBlocState.search(filter: {});
await expectLater( await expectLater(
messageSearchBlocState.messagesStream, messageSearchBlocState.messagesStream,
emitsError(error), emitsError(error),
); );
verify(mockClient.search( verify(() => mockClient.search(
any, any(),
query: anyNamed('query'), query: any(named: 'query'),
sort: anyNamed('sort'), sort: any(named: 'sort'),
messageFilters: anyNamed('messageFilters'), messageFilters: any(named: 'messageFilters'),
paginationParams: anyNamed('paginationParams'), paginationParams: any(named: 'paginationParams'),
)).called(1); )).called(1);
}, },
); );
@@ -196,47 +184,47 @@ void main() {
final messageResponseList = _generateMessages(); final messageResponseList = _generateMessages();
when(mockClient.search( when(() => mockClient.search(
any, any(),
query: anyNamed('query'), query: any(named: 'query'),
sort: anyNamed('sort'), sort: any(named: 'sort'),
messageFilters: anyNamed('messageFilters'), messageFilters: any(named: 'messageFilters'),
paginationParams: anyNamed('paginationParams'), paginationParams: any(named: 'paginationParams'),
)).thenAnswer( )).thenAnswer(
(_) async => SearchMessagesResponse()..results = messageResponseList, (_) async => SearchMessagesResponse()..results = messageResponseList,
); );
messageSearchBlocState.search(); messageSearchBlocState.search(filter: {});
await expectLater( await expectLater(
messageSearchBlocState.messagesStream, messageSearchBlocState.messagesStream,
emits(isSameMessageResponseListAs(messageResponseList)), emits(isSameMessageResponseListAs(messageResponseList)),
); );
verify(mockClient.search( verify(() => mockClient.search(
any, any(),
query: anyNamed('query'), query: any(named: 'query'),
sort: anyNamed('sort'), sort: any(named: 'sort'),
messageFilters: anyNamed('messageFilters'), messageFilters: any(named: 'messageFilters'),
paginationParams: anyNamed('paginationParams'), paginationParams: any(named: 'paginationParams'),
)).called(1); )).called(1);
final offset = messageResponseList.length; final offset = messageResponseList.length;
final paginatedMessageResponseList = _generateMessages(offset: offset); final paginatedMessageResponseList = _generateMessages(offset: offset);
final pagination = PaginationParams(offset: offset); final pagination = PaginationParams(offset: offset);
when(mockClient.search( when(() => mockClient.search(
any, any(),
query: anyNamed('query'), query: any(named: 'query'),
sort: anyNamed('sort'), sort: any(named: 'sort'),
messageFilters: anyNamed('messageFilters'), messageFilters: any(named: 'messageFilters'),
paginationParams: pagination, paginationParams: pagination,
)).thenAnswer( )).thenAnswer(
(_) async => (_) async =>
SearchMessagesResponse()..results = paginatedMessageResponseList, SearchMessagesResponse()..results = paginatedMessageResponseList,
); );
messageSearchBlocState.search(pagination: pagination); messageSearchBlocState.search(pagination: pagination, filter: {});
await Future.wait([ await Future.wait([
expectLater( expectLater(
@@ -251,13 +239,13 @@ void main() {
), ),
]); ]);
verify(mockClient.search( verify(() => mockClient.search(
any, any(),
query: anyNamed('query'), query: any(named: 'query'),
sort: anyNamed('sort'), sort: any(named: 'sort'),
messageFilters: anyNamed('messageFilters'), messageFilters: any(named: 'messageFilters'),
paginationParams: pagination, paginationParams: pagination,
)).called(1); )).called(1);
}, },
); );
@@ -288,57 +276,57 @@ void main() {
final messageResponseList = _generateMessages(); final messageResponseList = _generateMessages();
when(mockClient.search( when(() => mockClient.search(
any, any(),
query: anyNamed('query'), query: any(named: 'query'),
sort: anyNamed('sort'), sort: any(named: 'sort'),
messageFilters: anyNamed('messageFilters'), messageFilters: any(named: 'messageFilters'),
paginationParams: anyNamed('paginationParams'), paginationParams: any(named: 'paginationParams'),
)).thenAnswer( )).thenAnswer(
(_) async => SearchMessagesResponse()..results = messageResponseList, (_) async => SearchMessagesResponse()..results = messageResponseList,
); );
messageSearchBlocState.search(); messageSearchBlocState.search(filter: {});
await expectLater( await expectLater(
messageSearchBlocState.messagesStream, messageSearchBlocState.messagesStream,
emits(isSameMessageResponseListAs(messageResponseList)), emits(isSameMessageResponseListAs(messageResponseList)),
); );
verify(mockClient.search( verify(() => mockClient.search(
any, any(),
query: anyNamed('query'), query: any(named: 'query'),
sort: anyNamed('sort'), sort: any(named: 'sort'),
messageFilters: anyNamed('messageFilters'), messageFilters: any(named: 'messageFilters'),
paginationParams: anyNamed('paginationParams'), paginationParams: any(named: 'paginationParams'),
)).called(1); )).called(1);
final offset = messageResponseList.length; final offset = messageResponseList.length;
final pagination = PaginationParams(offset: offset); final pagination = PaginationParams(offset: offset);
const error = 'Error! Error! Error!'; const error = 'Error! Error! Error!';
when(mockClient.search( when(() => mockClient.search(
any, any(),
query: anyNamed('query'), query: any(named: 'query'),
sort: anyNamed('sort'), sort: any(named: 'sort'),
messageFilters: anyNamed('messageFilters'), messageFilters: any(named: 'messageFilters'),
paginationParams: pagination, paginationParams: pagination,
)).thenThrow(error); )).thenThrow(error);
messageSearchBlocState.search(pagination: pagination); messageSearchBlocState.search(pagination: pagination, filter: {});
await expectLater( await expectLater(
messageSearchBlocState.queryMessagesLoading, messageSearchBlocState.queryMessagesLoading,
emitsError(error), emitsError(error),
); );
verify(mockClient.search( verify(() => mockClient.search(
any, any(),
query: anyNamed('query'), query: any(named: 'query'),
sort: anyNamed('sort'), sort: any(named: 'sort'),
messageFilters: anyNamed('messageFilters'), messageFilters: any(named: 'messageFilters'),
paginationParams: pagination, paginationParams: pagination,
)).called(1); )).called(1);
}, },
); );
} }
@@ -1,8 +1,8 @@
import 'package:flutter/widgets.dart'; import 'package:flutter/widgets.dart';
import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_test/flutter_test.dart';
import 'package:mockito/mockito.dart'; import 'package:mocktail/mocktail.dart';
import 'package:stream_chat_flutter_core/stream_chat_flutter_core.dart';
import 'package:stream_chat_flutter_core/src/message_search_list_core.dart'; import 'package:stream_chat_flutter_core/src/message_search_list_core.dart';
import 'package:stream_chat_flutter_core/stream_chat_flutter_core.dart';
import 'mocks.dart'; import 'mocks.dart';
@@ -10,74 +10,21 @@ void main() {
List<GetMessageResponse> _generateMessages({ List<GetMessageResponse> _generateMessages({
int count = 3, int count = 3,
int offset = 0, int offset = 0,
}) { }) =>
return List.generate( List.generate(
count, count,
(index) { (index) {
index = index + offset; index = index + offset;
return GetMessageResponse() return GetMessageResponse()
..message = Message( ..message = Message(
id: 'testId$index', id: 'testId$index',
text: 'testTextData$index', text: 'testTextData$index',
) )
..channel = ChannelModel( ..channel = ChannelModel(
cid: 'testCid', cid: 'test:Cid',
); );
}, },
); );
}
test(
'should throw assertion error in case childBuilder is null',
() {
final messageSearchListCore = () => MessageSearchListCore(
childBuilder: null,
loadingBuilder: (BuildContext context) => Offstage(),
emptyBuilder: (BuildContext context) => Offstage(),
errorBuilder: (BuildContext context, Object error) => Offstage(),
);
expect(messageSearchListCore, throwsA(isA<AssertionError>()));
},
);
test(
'should throw assertion error in case loadingBuilder is null',
() {
final messageSearchListCore = () => MessageSearchListCore(
childBuilder: (List<GetMessageResponse> messages) => Offstage(),
loadingBuilder: null,
emptyBuilder: (BuildContext context) => Offstage(),
errorBuilder: (BuildContext context, Object error) => Offstage(),
);
expect(messageSearchListCore, throwsA(isA<AssertionError>()));
},
);
test(
'should throw assertion error in case emptyBuilder is null',
() {
final messageSearchListCore = () => MessageSearchListCore(
childBuilder: (List<GetMessageResponse> messages) => Offstage(),
loadingBuilder: (BuildContext context) => Offstage(),
emptyBuilder: null,
errorBuilder: (BuildContext context, Object error) => Offstage(),
);
expect(messageSearchListCore, throwsA(isA<AssertionError>()));
},
);
test(
'should throw assertion error in case errorBuilder is null',
() {
final messageSearchListCore = () => MessageSearchListCore(
childBuilder: (List<GetMessageResponse> messages) => Offstage(),
loadingBuilder: (BuildContext context) => Offstage(),
emptyBuilder: (BuildContext context) => Offstage(),
errorBuilder: null,
);
expect(messageSearchListCore, throwsA(isA<AssertionError>()));
},
);
testWidgets( testWidgets(
'should throw if MessageSearchListCore is used where MessageSearchBloc ' 'should throw if MessageSearchListCore is used where MessageSearchBloc '
@@ -86,10 +33,11 @@ void main() {
const messageSearchListCoreKey = Key('messageSearchListCore'); const messageSearchListCoreKey = Key('messageSearchListCore');
final messageSearchListCore = MessageSearchListCore( final messageSearchListCore = MessageSearchListCore(
key: messageSearchListCoreKey, key: messageSearchListCoreKey,
childBuilder: (List<GetMessageResponse> messages) => Offstage(), childBuilder: (List<GetMessageResponse>? messages) => const Offstage(),
loadingBuilder: (BuildContext context) => Offstage(), loadingBuilder: (BuildContext context) => const Offstage(),
emptyBuilder: (BuildContext context) => Offstage(), emptyBuilder: (BuildContext context) => const Offstage(),
errorBuilder: (BuildContext context, Object error) => Offstage(), errorBuilder: (BuildContext context, Object? error) => const Offstage(),
filters: const {},
); );
await tester.pumpWidget(messageSearchListCore); await tester.pumpWidget(messageSearchListCore);
@@ -109,7 +57,8 @@ void main() {
childBuilder: (List<GetMessageResponse> messages) => Offstage(), childBuilder: (List<GetMessageResponse> messages) => Offstage(),
loadingBuilder: (BuildContext context) => Offstage(), loadingBuilder: (BuildContext context) => Offstage(),
emptyBuilder: (BuildContext context) => Offstage(), emptyBuilder: (BuildContext context) => Offstage(),
errorBuilder: (BuildContext context, Object error) => Offstage(), errorBuilder: (BuildContext context, Object? error) => Offstage(),
filters: {},
); );
final mockClient = MockClient(); final mockClient = MockClient();
@@ -140,6 +89,7 @@ void main() {
emptyBuilder: (BuildContext context) => Offstage(), emptyBuilder: (BuildContext context) => Offstage(),
errorBuilder: (BuildContext context, Object error) => Offstage(), errorBuilder: (BuildContext context, Object error) => Offstage(),
messageSearchListController: controller, messageSearchListController: controller,
filters: {},
); );
expect(controller.loadData, isNull); expect(controller.loadData, isNull);
@@ -175,18 +125,19 @@ void main() {
errorBuilder: (BuildContext context, Object error) => Offstage( errorBuilder: (BuildContext context, Object error) => Offstage(
key: errorWidgetKey, key: errorWidgetKey,
), ),
filters: {},
); );
final mockClient = MockClient(); final mockClient = MockClient();
const error = 'Error! Error! Error!'; const error = 'Error! Error! Error!';
when(mockClient.search( when(() => mockClient.search(
any, any(),
query: anyNamed('query'), query: any(named: 'query'),
sort: anyNamed('sort'), sort: any(named: 'sort'),
messageFilters: anyNamed('messageFilters'), messageFilters: any(named: 'messageFilters'),
paginationParams: anyNamed('paginationParams'), paginationParams: any(named: 'paginationParams'),
)).thenThrow(error); )).thenThrow(error);
await tester.pumpWidget( await tester.pumpWidget(
StreamChatCore( StreamChatCore(
@@ -201,13 +152,13 @@ void main() {
expect(find.byKey(errorWidgetKey), findsOneWidget); expect(find.byKey(errorWidgetKey), findsOneWidget);
verify(mockClient.search( verify(() => mockClient.search(
any, any(),
query: anyNamed('query'), query: any(named: 'query'),
sort: anyNamed('sort'), sort: any(named: 'sort'),
messageFilters: anyNamed('messageFilters'), messageFilters: any(named: 'messageFilters'),
paginationParams: anyNamed('paginationParams'), paginationParams: any(named: 'paginationParams'),
)).called(1); )).called(1);
}, },
); );
@@ -223,18 +174,19 @@ void main() {
loadingBuilder: (BuildContext context) => Offstage(), loadingBuilder: (BuildContext context) => Offstage(),
emptyBuilder: (BuildContext context) => Offstage(key: emptyWidgetKey), emptyBuilder: (BuildContext context) => Offstage(key: emptyWidgetKey),
errorBuilder: (BuildContext context, Object error) => Offstage(), errorBuilder: (BuildContext context, Object error) => Offstage(),
filters: {},
); );
final mockClient = MockClient(); final mockClient = MockClient();
final messageResponseList = <GetMessageResponse>[]; final messageResponseList = <GetMessageResponse>[];
when(mockClient.search( when(() => mockClient.search(
any, any(),
query: anyNamed('query'), query: any(named: 'query'),
sort: anyNamed('sort'), sort: any(named: 'sort'),
messageFilters: anyNamed('messageFilters'), messageFilters: any(named: 'messageFilters'),
paginationParams: anyNamed('paginationParams'), paginationParams: any(named: 'paginationParams'),
)).thenAnswer( )).thenAnswer(
(_) async => SearchMessagesResponse()..results = messageResponseList, (_) async => SearchMessagesResponse()..results = messageResponseList,
); );
@@ -251,13 +203,13 @@ void main() {
expect(find.byKey(emptyWidgetKey), findsOneWidget); expect(find.byKey(emptyWidgetKey), findsOneWidget);
verify(mockClient.search( verify(() => mockClient.search(
any, any(),
query: anyNamed('query'), query: any(named: 'query'),
sort: anyNamed('sort'), sort: any(named: 'sort'),
messageFilters: anyNamed('messageFilters'), messageFilters: any(named: 'messageFilters'),
paginationParams: anyNamed('paginationParams'), paginationParams: any(named: 'paginationParams'),
)).called(1); )).called(1);
}, },
); );
@@ -274,18 +226,19 @@ void main() {
loadingBuilder: (BuildContext context) => Offstage(), loadingBuilder: (BuildContext context) => Offstage(),
emptyBuilder: (BuildContext context) => Offstage(), emptyBuilder: (BuildContext context) => Offstage(),
errorBuilder: (BuildContext context, Object error) => Offstage(), errorBuilder: (BuildContext context, Object error) => Offstage(),
filters: {},
); );
final mockClient = MockClient(); final mockClient = MockClient();
final messageResponseList = _generateMessages(); final messageResponseList = _generateMessages();
when(mockClient.search( when(() => mockClient.search(
any, any(),
query: anyNamed('query'), query: any(named: 'query'),
sort: anyNamed('sort'), sort: any(named: 'sort'),
messageFilters: anyNamed('messageFilters'), messageFilters: any(named: 'messageFilters'),
paginationParams: anyNamed('paginationParams'), paginationParams: any(named: 'paginationParams'),
)).thenAnswer( )).thenAnswer(
(_) async => SearchMessagesResponse()..results = messageResponseList, (_) async => SearchMessagesResponse()..results = messageResponseList,
); );
@@ -302,13 +255,13 @@ void main() {
expect(find.byKey(childWidgetKey), findsOneWidget); expect(find.byKey(childWidgetKey), findsOneWidget);
verify(mockClient.search( verify(() => mockClient.search(
any, any(),
query: anyNamed('query'), query: any(named: 'query'),
sort: anyNamed('sort'), sort: any(named: 'sort'),
messageFilters: anyNamed('messageFilters'), messageFilters: any(named: 'messageFilters'),
paginationParams: anyNamed('paginationParams'), paginationParams: any(named: 'paginationParams'),
)).called(1); )).called(1);
}, },
); );
@@ -324,25 +277,26 @@ void main() {
childBuilder: (List<GetMessageResponse> messages) => Container( childBuilder: (List<GetMessageResponse> messages) => Container(
key: childWidgetKey, key: childWidgetKey,
child: Text( child: Text(
messages.map((e) => '${e.channel.cid}-${e.message.id}').join(','), messages.map((e) => '${e.channel?.cid}-${e.message.id}').join(','),
), ),
), ),
loadingBuilder: (BuildContext context) => Offstage(), loadingBuilder: (BuildContext context) => Offstage(),
emptyBuilder: (BuildContext context) => Offstage(), emptyBuilder: (BuildContext context) => Offstage(),
errorBuilder: (BuildContext context, Object error) => Offstage(), errorBuilder: (BuildContext context, Object error) => Offstage(),
paginationParams: pagination, paginationParams: pagination,
filters: {},
); );
final mockClient = MockClient(); final mockClient = MockClient();
final messageResponseList = _generateMessages(); final messageResponseList = _generateMessages();
when(mockClient.search( when(() => mockClient.search(
any, any(),
query: anyNamed('query'), query: any(named: 'query'),
sort: anyNamed('sort'), sort: any(named: 'sort'),
messageFilters: anyNamed('messageFilters'), messageFilters: any(named: 'messageFilters'),
paginationParams: pagination, paginationParams: pagination,
)).thenAnswer( )).thenAnswer(
(_) async => SearchMessagesResponse()..results = messageResponseList, (_) async => SearchMessagesResponse()..results = messageResponseList,
); );
@@ -364,19 +318,19 @@ void main() {
expect( expect(
find.text( find.text(
messageResponseList messageResponseList
.map((e) => '${e.channel.cid}-${e.message.id}') .map((e) => '${e.channel?.cid}-${e.message.id}')
.join(','), .join(','),
), ),
findsOneWidget, findsOneWidget,
); );
verify(mockClient.search( verify(() => mockClient.search(
any, any(),
query: anyNamed('query'), query: any(named: 'query'),
sort: anyNamed('sort'), sort: any(named: 'sort'),
messageFilters: anyNamed('messageFilters'), messageFilters: any(named: 'messageFilters'),
paginationParams: pagination, paginationParams: pagination,
)).called(1); )).called(1);
final messageSearchListCoreState = final messageSearchListCoreState =
tester.state<MessageSearchListCoreState>( tester.state<MessageSearchListCoreState>(
@@ -386,13 +340,13 @@ void main() {
final offset = messageResponseList.length; final offset = messageResponseList.length;
final paginatedMessageResponseList = _generateMessages(offset: offset); final paginatedMessageResponseList = _generateMessages(offset: offset);
final updatedPagination = pagination.copyWith(offset: offset); final updatedPagination = pagination.copyWith(offset: offset);
when(mockClient.search( when(() => mockClient.search(
any, any(),
query: anyNamed('query'), query: any(named: 'query'),
sort: anyNamed('sort'), sort: any(named: 'sort'),
messageFilters: anyNamed('messageFilters'), messageFilters: any(named: 'messageFilters'),
paginationParams: updatedPagination, paginationParams: updatedPagination,
)).thenAnswer( )).thenAnswer(
(_) async => (_) async =>
SearchMessagesResponse()..results = paginatedMessageResponseList, SearchMessagesResponse()..results = paginatedMessageResponseList,
); );
@@ -406,17 +360,17 @@ void main() {
find.text([ find.text([
...messageResponseList, ...messageResponseList,
...paginatedMessageResponseList, ...paginatedMessageResponseList,
].map((e) => '${e.channel.cid}-${e.message.id}').join(',')), ].map((e) => '${e.channel?.cid}-${e.message.id}').join(',')),
findsOneWidget, findsOneWidget,
); );
verify(mockClient.search( verify(() => mockClient.search(
any, any(),
query: anyNamed('query'), query: any(named: 'query'),
sort: anyNamed('sort'), sort: any(named: 'sort'),
messageFilters: anyNamed('messageFilters'), messageFilters: any(named: 'messageFilters'),
paginationParams: updatedPagination, paginationParams: updatedPagination,
)).called(1); )).called(1);
}, },
); );
@@ -426,8 +380,8 @@ void main() {
(tester) async { (tester) async {
const pagination = PaginationParams(); const pagination = PaginationParams();
StateSetter _stateSetter; StateSetter? _stateSetter;
int limit = pagination.limit; var limit = pagination.limit;
const messageSearchListCoreKey = Key('messageSearchListCore'); const messageSearchListCoreKey = Key('messageSearchListCore');
const childWidgetKey = Key('childWidget'); const childWidgetKey = Key('childWidget');
@@ -438,7 +392,7 @@ void main() {
key: childWidgetKey, key: childWidgetKey,
child: Text( child: Text(
messages messages
.map((e) => '${e.channel.cid}-${e.message.id}') .map((e) => '${e.channel?.cid}-${e.message.id}')
.join(','), .join(','),
), ),
), ),
@@ -446,18 +400,19 @@ void main() {
emptyBuilder: (BuildContext context) => Offstage(), emptyBuilder: (BuildContext context) => Offstage(),
errorBuilder: (BuildContext context, Object error) => Offstage(), errorBuilder: (BuildContext context, Object error) => Offstage(),
paginationParams: pagination.copyWith(limit: limit), paginationParams: pagination.copyWith(limit: limit),
filters: {},
); );
final mockClient = MockClient(); final mockClient = MockClient();
final messageResponseList = _generateMessages(); final messageResponseList = _generateMessages();
when(mockClient.search( when(() => mockClient.search(
any, any(),
query: anyNamed('query'), query: any(named: 'query'),
sort: anyNamed('sort'), sort: any(named: 'sort'),
messageFilters: anyNamed('messageFilters'), messageFilters: any(named: 'messageFilters'),
paginationParams: pagination, paginationParams: pagination,
)).thenAnswer( )).thenAnswer(
(_) async => SearchMessagesResponse()..results = messageResponseList, (_) async => SearchMessagesResponse()..results = messageResponseList,
); );
@@ -483,32 +438,32 @@ void main() {
expect( expect(
find.text( find.text(
messageResponseList messageResponseList
.map((e) => '${e.channel.cid}-${e.message.id}') .map((e) => '${e.channel?.cid}-${e.message.id}')
.join(','), .join(','),
), ),
findsOneWidget, findsOneWidget,
); );
verify(mockClient.search( verify(() => mockClient.search(
any, any(),
query: anyNamed('query'), query: any(named: 'query'),
sort: anyNamed('sort'), sort: any(named: 'sort'),
messageFilters: anyNamed('messageFilters'), messageFilters: any(named: 'messageFilters'),
paginationParams: pagination, paginationParams: pagination,
)).called(1); )).called(1);
// Rebuilding MessageSearchListCore with new pagination limit // Rebuilding MessageSearchListCore with new pagination limit
_stateSetter(() => limit = 6); _stateSetter?.call(() => limit = 6);
final updatedMessageResponseList = _generateMessages(count: limit); final updatedMessageResponseList = _generateMessages(count: limit);
final updatedPagination = pagination.copyWith(limit: limit); final updatedPagination = pagination.copyWith(limit: limit);
when(mockClient.search( when(() => mockClient.search(
any, any(),
query: anyNamed('query'), query: any(named: 'query'),
sort: anyNamed('sort'), sort: any(named: 'sort'),
messageFilters: anyNamed('messageFilters'), messageFilters: any(named: 'messageFilters'),
paginationParams: updatedPagination, paginationParams: updatedPagination,
)).thenAnswer( )).thenAnswer(
(_) async => (_) async =>
SearchMessagesResponse()..results = updatedMessageResponseList, SearchMessagesResponse()..results = updatedMessageResponseList,
); );
@@ -518,18 +473,18 @@ void main() {
expect(find.byKey(childWidgetKey), findsOneWidget); expect(find.byKey(childWidgetKey), findsOneWidget);
expect( expect(
find.text(updatedMessageResponseList find.text(updatedMessageResponseList
.map((e) => '${e.channel.cid}-${e.message.id}') .map((e) => '${e.channel?.cid}-${e.message.id}')
.join(',')), .join(',')),
findsOneWidget, findsOneWidget,
); );
verify(mockClient.search( verify(() => mockClient.search(
any, any(),
query: anyNamed('query'), query: any(named: 'query'),
sort: anyNamed('sort'), sort: any(named: 'sort'),
messageFilters: anyNamed('messageFilters'), messageFilters: any(named: 'messageFilters'),
paginationParams: updatedPagination, paginationParams: updatedPagination,
)).called(1); )).called(1);
}, },
); );
} }
@@ -1,19 +1,20 @@
import 'package:mockito/mockito.dart'; import 'package:mocktail/mocktail.dart';
import 'package:stream_chat/stream_chat.dart'; import 'package:stream_chat/stream_chat.dart';
class MockLogger extends Mock implements Logger {} class MockLogger extends Mock implements Logger {}
class MockClient extends Mock implements StreamChatClient { class MockClient extends Mock implements StreamChatClient {
@override
final Logger logger = MockLogger(); final Logger logger = MockLogger();
ClientState _state; ClientState? _state;
@override @override
ClientState get state => _state ??= MockClientState(); ClientState get state => _state ??= MockClientState();
} }
class MockClientState extends Mock implements ClientState { class MockClientState extends Mock implements ClientState {
OwnUser _user; OwnUser? _user;
@override @override
OwnUser get user => _user ??= OwnUser( OwnUser get user => _user ??= OwnUser(
@@ -25,12 +26,12 @@ class MockClientState extends Mock implements ClientState {
} }
class MockChannel extends Mock implements Channel { class MockChannel extends Mock implements Channel {
ChannelClientState _state; ChannelClientState? _state;
@override @override
ChannelClientState get state => _state ??= MockChannelState(); ChannelClientState get state => _state ??= MockChannelState();
StreamChatClient _client; StreamChatClient? _client;
@override @override
StreamChatClient get client => _client ??= MockClient(); StreamChatClient get client => _client ??= MockClient();
@@ -3,7 +3,7 @@ import 'dart:async';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart'; import 'package:flutter/widgets.dart';
import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_test/flutter_test.dart';
import 'package:mockito/mockito.dart'; import 'package:mocktail/mocktail.dart';
import 'package:stream_chat_flutter_core/stream_chat_flutter_core.dart'; import 'package:stream_chat_flutter_core/stream_chat_flutter_core.dart';
import 'mocks.dart'; import 'mocks.dart';
@@ -62,39 +62,13 @@ void main() {
return threads ? threadMessages : messages; return threads ? threadMessages : messages;
} }
test(
'should throw assertion error if child is null',
() async {
final mockChannel = MockChannel();
const streamChannelKey = Key('streamChannel');
final streamChannel = () => StreamChannel(
key: streamChannelKey,
channel: mockChannel,
child: null,
);
expect(streamChannel, throwsA(isA<AssertionError>()));
},
);
test(
'should throw assertion error if channel is null',
() async {
const streamChannelKey = Key('streamChannel');
final streamChannel = () => StreamChannel(
key: streamChannelKey,
child: Offstage(),
channel: null,
);
expect(streamChannel, throwsA(isA<AssertionError>()));
},
);
testWidgets( testWidgets(
'should render StreamChannel if both channel and child is provided', 'should render StreamChannel if both channel and child is provided',
(tester) async { (tester) async {
final mockChannel = MockChannel(); final mockChannel = MockChannel();
const streamChannelKey = Key('streamChannel'); const streamChannelKey = Key('streamChannel');
const childKey = Key('childKey'); const childKey = Key('childKey');
when(() => mockChannel.initialized).thenAnswer((_) => Future.value(true));
final streamChannel = StreamChannel( final streamChannel = StreamChannel(
key: streamChannelKey, key: streamChannelKey,
channel: mockChannel, channel: mockChannel,
@@ -121,8 +95,13 @@ void main() {
); );
final errorMessage = 'Error! Error! Error!'; final errorMessage = 'Error! Error! Error!';
final error = DioError(type: DioErrorType.response, error: errorMessage); final error = DioError(
when(mockChannel.initialized).thenAnswer((_) => Future.error(error)); type: DioErrorType.response,
error: errorMessage,
requestOptions: RequestOptions(path: ''),
);
when(() => mockChannel.initialized)
.thenAnswer((_) => Future.error(error));
await tester.pumpWidget( await tester.pumpWidget(
Directionality( Directionality(
@@ -135,7 +114,7 @@ void main() {
expect(find.text(errorMessage), findsOneWidget); expect(find.text(errorMessage), findsOneWidget);
verify(mockChannel.initialized).called(1); verify(() => mockChannel.initialized).called(1);
}, },
); );
@@ -153,7 +132,7 @@ void main() {
showLoading: true, showLoading: true,
); );
when(mockChannel.initialized).thenAnswer((_) async => false); when(() => mockChannel.initialized).thenAnswer((_) async => false);
await tester.pumpWidget( await tester.pumpWidget(
Directionality( Directionality(
@@ -166,7 +145,7 @@ void main() {
expect(find.byType(CircularProgressIndicator), findsOneWidget); expect(find.byType(CircularProgressIndicator), findsOneWidget);
verify(mockChannel.initialized).called(1); verify(() => mockChannel.initialized).called(1);
}, },
); );
@@ -183,15 +162,15 @@ void main() {
initialMessageId: 'testInitialMessageId', initialMessageId: 'testInitialMessageId',
); );
when(mockChannel.initialized).thenAnswer((_) async => true); when(() => mockChannel.initialized).thenAnswer((_) async => true);
final messages = _generateMessages(); final messages = _generateMessages();
when(mockChannel.query( when(() => mockChannel.query(
options: anyNamed('options'), options: any(named: 'options'),
messagesPagination: anyNamed('messagesPagination'), messagesPagination: any(named: 'messagesPagination'),
membersPagination: anyNamed('membersPagination'), membersPagination: any(named: 'membersPagination'),
watchersPagination: anyNamed('watchersPagination'), watchersPagination: any(named: 'watchersPagination'),
preferOffline: anyNamed('preferOffline'), preferOffline: any(named: 'preferOffline'),
)).thenAnswer((_) async => ChannelState(messages: messages)); )).thenAnswer((_) async => ChannelState(messages: messages));
await tester.pumpWidget( await tester.pumpWidget(
Directionality( Directionality(
@@ -202,14 +181,14 @@ void main() {
await tester.pumpAndSettle(); await tester.pumpAndSettle();
verify(mockChannel.initialized).called(1); verify(() => mockChannel.initialized).called(1);
verify(mockChannel.query( verify(() => mockChannel.query(
options: anyNamed('options'), options: any(named: 'options'),
messagesPagination: anyNamed('messagesPagination'), messagesPagination: any(named: 'messagesPagination'),
membersPagination: anyNamed('membersPagination'), membersPagination: any(named: 'membersPagination'),
watchersPagination: anyNamed('watchersPagination'), watchersPagination: any(named: 'watchersPagination'),
preferOffline: anyNamed('preferOffline'), preferOffline: any(named: 'preferOffline'),
)).called( )).called(
2, // Fetching After messages + Fetching Before messages, 2, // Fetching After messages + Fetching Before messages,
); );
}, },
@@ -219,7 +198,7 @@ void main() {
'should rebuild StreamChannel with updated widget data ' 'should rebuild StreamChannel with updated widget data '
'on calling setState()', 'on calling setState()',
(tester) async { (tester) async {
StateSetter _stateSetter; StateSetter? _stateSetter;
var initialMessageId = 'testInitialMessageId'; var initialMessageId = 'testInitialMessageId';
@@ -244,25 +223,25 @@ void main() {
limit: 20, limit: 20,
); );
when(mockChannel.initialized).thenAnswer((_) async => true); when(() => mockChannel.initialized).thenAnswer((_) async => true);
final messages = _generateMessages(); final messages = _generateMessages();
when(mockChannel.query( when(() => mockChannel.query(
options: anyNamed('options'), options: any(named: 'options'),
messagesPagination: beforePagination, messagesPagination: beforePagination,
membersPagination: anyNamed('membersPagination'), membersPagination: any(named: 'membersPagination'),
watchersPagination: anyNamed('watchersPagination'), watchersPagination: any(named: 'watchersPagination'),
preferOffline: anyNamed('preferOffline'), preferOffline: any(named: 'preferOffline'),
)).thenAnswer((_) async => ChannelState(messages: messages)); )).thenAnswer((_) async => ChannelState(messages: messages));
when(mockChannel.query( when(() => mockChannel.query(
options: anyNamed('options'), options: any(named: 'options'),
messagesPagination: afterPagination, messagesPagination: afterPagination,
membersPagination: anyNamed('membersPagination'), membersPagination: any(named: 'membersPagination'),
watchersPagination: anyNamed('watchersPagination'), watchersPagination: any(named: 'watchersPagination'),
preferOffline: anyNamed('preferOffline'), preferOffline: any(named: 'preferOffline'),
)).thenAnswer((_) async => ChannelState(messages: messages)); )).thenAnswer((_) async => ChannelState(messages: messages));
await tester.pumpWidget( await tester.pumpWidget(
Directionality( Directionality(
@@ -279,23 +258,23 @@ void main() {
await tester.pumpAndSettle(); await tester.pumpAndSettle();
verify(mockChannel.query( verify(() => mockChannel.query(
options: anyNamed('options'), options: any(named: 'options'),
messagesPagination: beforePagination, messagesPagination: beforePagination,
membersPagination: anyNamed('membersPagination'), membersPagination: any(named: 'membersPagination'),
watchersPagination: anyNamed('watchersPagination'), watchersPagination: any(named: 'watchersPagination'),
preferOffline: anyNamed('preferOffline'), preferOffline: any(named: 'preferOffline'),
)).called(1); )).called(1);
verify(mockChannel.query( verify(() => mockChannel.query(
options: anyNamed('options'), options: any(named: 'options'),
messagesPagination: afterPagination, messagesPagination: afterPagination,
membersPagination: anyNamed('membersPagination'), membersPagination: any(named: 'membersPagination'),
watchersPagination: anyNamed('watchersPagination'), watchersPagination: any(named: 'watchersPagination'),
preferOffline: anyNamed('preferOffline'), preferOffline: any(named: 'preferOffline'),
)).called(1); )).called(1);
_stateSetter(() => initialMessageId = 'testInitialMessageId2'); _stateSetter?.call(() => initialMessageId = 'testInitialMessageId2');
final updatedBeforePagination = beforePagination.copyWith( final updatedBeforePagination = beforePagination.copyWith(
lessThan: initialMessageId, lessThan: initialMessageId,
@@ -305,39 +284,39 @@ void main() {
greaterThanOrEqual: initialMessageId, greaterThanOrEqual: initialMessageId,
); );
when(mockChannel.query( when(() => mockChannel.query(
options: anyNamed('options'), options: any(named: 'options'),
messagesPagination: updatedBeforePagination, messagesPagination: updatedBeforePagination,
membersPagination: anyNamed('membersPagination'), membersPagination: any(named: 'membersPagination'),
watchersPagination: anyNamed('watchersPagination'), watchersPagination: any(named: 'watchersPagination'),
preferOffline: anyNamed('preferOffline'), preferOffline: any(named: 'preferOffline'),
)).thenAnswer((_) async => ChannelState(messages: messages)); )).thenAnswer((_) async => ChannelState(messages: messages));
when(mockChannel.query( when(() => mockChannel.query(
options: anyNamed('options'), options: any(named: 'options'),
messagesPagination: updatedAfterPagination, messagesPagination: updatedAfterPagination,
membersPagination: anyNamed('membersPagination'), membersPagination: any(named: 'membersPagination'),
watchersPagination: anyNamed('watchersPagination'), watchersPagination: any(named: 'watchersPagination'),
preferOffline: anyNamed('preferOffline'), preferOffline: any(named: 'preferOffline'),
)).thenAnswer((_) async => ChannelState(messages: messages)); )).thenAnswer((_) async => ChannelState(messages: messages));
await tester.pumpAndSettle(); await tester.pumpAndSettle();
verify(mockChannel.query( verify(() => mockChannel.query(
options: anyNamed('options'), options: any(named: 'options'),
messagesPagination: updatedBeforePagination, messagesPagination: updatedBeforePagination,
membersPagination: anyNamed('membersPagination'), membersPagination: any(named: 'membersPagination'),
watchersPagination: anyNamed('watchersPagination'), watchersPagination: any(named: 'watchersPagination'),
preferOffline: anyNamed('preferOffline'), preferOffline: any(named: 'preferOffline'),
)).called(1); )).called(1);
verify(mockChannel.query( verify(() => mockChannel.query(
options: anyNamed('options'), options: any(named: 'options'),
messagesPagination: updatedAfterPagination, messagesPagination: updatedAfterPagination,
membersPagination: anyNamed('membersPagination'), membersPagination: any(named: 'membersPagination'),
watchersPagination: anyNamed('watchersPagination'), watchersPagination: any(named: 'watchersPagination'),
preferOffline: anyNamed('preferOffline'), preferOffline: any(named: 'preferOffline'),
)).called(1); )).called(1);
}, },
); );
} }
@@ -2,7 +2,7 @@ import 'dart:async';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_test/flutter_test.dart';
import 'package:mockito/mockito.dart'; import 'package:mocktail/mocktail.dart';
import 'package:stream_chat_flutter_core/stream_chat_flutter_core.dart'; import 'package:stream_chat_flutter_core/stream_chat_flutter_core.dart';
import 'mocks.dart'; import 'mocks.dart';
@@ -12,29 +12,6 @@ class MockOnBackgroundEventReceived extends Mock {
} }
void main() { void main() {
test(
'should throw assertion error in case client is null',
() {
final streamChatCore = () => StreamChatCore(
client: null,
child: Offstage(),
);
expect(streamChatCore, throwsA(isA<AssertionError>()));
},
);
test(
'should throw assertion error in case child is null',
() {
final mockClient = MockClient();
final streamChatCore = () => StreamChatCore(
client: mockClient,
child: null,
);
expect(streamChatCore, throwsA(isA<AssertionError>()));
},
);
testWidgets( testWidgets(
'should render StreamChatCore if both client and child is provided', 'should render StreamChatCore if both client and child is provided',
(tester) async { (tester) async {
@@ -92,7 +69,7 @@ void main() {
expect(find.byKey(streamChatCoreKey), findsOneWidget); expect(find.byKey(streamChatCoreKey), findsOneWidget);
expect(find.byKey(childKey), findsOneWidget); expect(find.byKey(childKey), findsOneWidget);
when(mockClient.disconnect()).thenAnswer((_) async { when(() => mockClient.disconnect()).thenAnswer((_) async {
return; return;
}); });
@@ -102,7 +79,7 @@ void main() {
streamChatCoreState.didChangeAppLifecycleState(AppLifecycleState.paused); streamChatCoreState.didChangeAppLifecycleState(AppLifecycleState.paused);
verify(mockClient.disconnect()).called(1); verify(() => mockClient.disconnect()).called(1);
}, },
); );
@@ -131,8 +108,8 @@ void main() {
expect(find.byKey(childKey), findsOneWidget); expect(find.byKey(childKey), findsOneWidget);
final event = Event(); final event = Event();
when(mockClient.on()).thenAnswer((_) => Stream.value(event)); when(() => mockClient.on()).thenAnswer((_) => Stream.value(event));
when(mockClient.disconnect()).thenAnswer((_) async { when(() => mockClient.disconnect()).thenAnswer((_) async {
return; return;
}); });
@@ -143,14 +120,14 @@ void main() {
streamChatCoreState streamChatCoreState
.didChangeAppLifecycleState(AppLifecycleState.paused); .didChangeAppLifecycleState(AppLifecycleState.paused);
await untilCalled(mockOnBackgroundEventReceived.call(event)); await untilCalled(() => mockOnBackgroundEventReceived.call(event));
verify(mockOnBackgroundEventReceived.call(event)).called(1); verify(() => mockOnBackgroundEventReceived.call(event)).called(1);
await Future.delayed(backgroundKeepAlive); await Future.delayed(backgroundKeepAlive);
verify(mockClient.disconnect()).called(1); verify(() => mockClient.disconnect()).called(1);
verifyNever(mockOnBackgroundEventReceived.call(event)); verifyNever(() => mockOnBackgroundEventReceived.call(event));
}); });
}, },
); );
@@ -180,7 +157,7 @@ void main() {
expect(find.byKey(childKey), findsOneWidget); expect(find.byKey(childKey), findsOneWidget);
final event = Event(); final event = Event();
when(mockClient.on()).thenAnswer((_) => Stream.value(event)); when(() => mockClient.on()).thenAnswer((_) => Stream.value(event));
final streamChatCoreState = tester.state<StreamChatCoreState>( final streamChatCoreState = tester.state<StreamChatCoreState>(
find.byKey(streamChatCoreKey), find.byKey(streamChatCoreKey),
@@ -189,14 +166,14 @@ void main() {
streamChatCoreState streamChatCoreState
.didChangeAppLifecycleState(AppLifecycleState.paused); .didChangeAppLifecycleState(AppLifecycleState.paused);
await untilCalled(mockOnBackgroundEventReceived.call(event)); await untilCalled(() => mockOnBackgroundEventReceived.call(event));
verify(mockOnBackgroundEventReceived.call(event)).called(1); verify(() => mockOnBackgroundEventReceived.call(event)).called(1);
streamChatCoreState streamChatCoreState
.didChangeAppLifecycleState(AppLifecycleState.resumed); .didChangeAppLifecycleState(AppLifecycleState.resumed);
verifyNever(mockOnBackgroundEventReceived.call(event)); verifyNever(() => mockOnBackgroundEventReceived.call(event));
}); });
}, },
); );
@@ -222,9 +199,10 @@ void main() {
expect(find.byKey(childKey), findsOneWidget); expect(find.byKey(childKey), findsOneWidget);
final event = Event(); final event = Event();
when(mockClient.on()).thenAnswer((_) => Stream.value(event)); when(() => mockClient.on()).thenAnswer((_) => Stream.value(event));
when(mockClient.connect()).thenAnswer((_) async => event); when(() => mockClient.connect()).thenAnswer((_) async => event);
when(mockClient.wsConnectionStatus) when(mockClient.disconnect).thenAnswer((_) async => null);
when(() => mockClient.wsConnectionStatus)
.thenReturn(ConnectionStatus.disconnected); .thenReturn(ConnectionStatus.disconnected);
final streamChatCoreState = tester.state<StreamChatCoreState>( final streamChatCoreState = tester.state<StreamChatCoreState>(
@@ -239,7 +217,7 @@ void main() {
streamChatCoreState streamChatCoreState
.didChangeAppLifecycleState(AppLifecycleState.resumed); .didChangeAppLifecycleState(AppLifecycleState.resumed);
verify(mockClient.connect()).called(1); verify(() => mockClient.connect()).called(1);
}); });
}, },
); );
@@ -265,7 +243,7 @@ void main() {
expect(find.byKey(streamChatCoreKey), findsOneWidget); expect(find.byKey(streamChatCoreKey), findsOneWidget);
expect(find.byKey(childKey), findsOneWidget); expect(find.byKey(childKey), findsOneWidget);
when(mockClient.state.userStream) when(() => mockClient.state.userStream)
.thenAnswer((_) => userController.stream); .thenAnswer((_) => userController.stream);
final streamChatCoreState = tester.state<StreamChatCoreState>( final streamChatCoreState = tester.state<StreamChatCoreState>(
@@ -1,6 +1,6 @@
import 'package:flutter/widgets.dart'; import 'package:flutter/widgets.dart';
import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_test/flutter_test.dart';
import 'package:mockito/mockito.dart'; import 'package:mocktail/mocktail.dart';
import 'package:stream_chat_flutter_core/src/user_list_core.dart'; import 'package:stream_chat_flutter_core/src/user_list_core.dart';
import 'package:stream_chat_flutter_core/stream_chat_flutter_core.dart'; import 'package:stream_chat_flutter_core/stream_chat_flutter_core.dart';
@@ -33,58 +33,6 @@ void main() {
); );
} }
test(
'should throw assertion error in case listBuilder is null',
() {
final userListCore = () => UserListCore(
listBuilder: null,
loadingBuilder: (BuildContext context) => Offstage(),
emptyBuilder: (BuildContext context) => Offstage(),
errorBuilder: (Object error) => Offstage(),
);
expect(userListCore, throwsA(isA<AssertionError>()));
},
);
test(
'should throw assertion error in case loadingBuilder is null',
() {
final userListCore = () => UserListCore(
listBuilder: (_, __) => Offstage(),
loadingBuilder: null,
emptyBuilder: (BuildContext context) => Offstage(),
errorBuilder: (Object error) => Offstage(),
);
expect(userListCore, throwsA(isA<AssertionError>()));
},
);
test(
'should throw assertion error in case emptyBuilder is null',
() {
final userListCore = () => UserListCore(
listBuilder: (_, __) => Offstage(),
loadingBuilder: (BuildContext context) => Offstage(),
emptyBuilder: null,
errorBuilder: (Object error) => Offstage(),
);
expect(userListCore, throwsA(isA<AssertionError>()));
},
);
test(
'should throw assertion error in case errorBuilder is null',
() {
final userListCore = () => UserListCore(
listBuilder: (_, __) => Offstage(),
loadingBuilder: (BuildContext context) => Offstage(),
emptyBuilder: (BuildContext context) => Offstage(),
errorBuilder: null,
);
expect(userListCore, throwsA(isA<AssertionError>()));
},
);
testWidgets( testWidgets(
'should throw if UserListCore is used where UsersBloc is not present ' 'should throw if UserListCore is used where UsersBloc is not present '
'in the widget tree', 'in the widget tree',
@@ -183,12 +131,12 @@ void main() {
final mockClient = MockClient(); final mockClient = MockClient();
const error = 'Error! Error! Error!'; const error = 'Error! Error! Error!';
when(mockClient.queryUsers( when(() => mockClient.queryUsers(
filter: anyNamed('filter'), filter: any(named: 'filter'),
sort: anyNamed('sort'), sort: any(named: 'sort'),
options: anyNamed('options'), options: any(named: 'options'),
pagination: anyNamed('pagination'), pagination: any(named: 'pagination'),
)).thenThrow(error); )).thenThrow(error);
await tester.pumpWidget( await tester.pumpWidget(
StreamChatCore( StreamChatCore(
@@ -203,12 +151,12 @@ void main() {
expect(find.byKey(errorWidgetKey), findsOneWidget); expect(find.byKey(errorWidgetKey), findsOneWidget);
verify(mockClient.queryUsers( verify(() => mockClient.queryUsers(
filter: anyNamed('filter'), filter: any(named: 'filter'),
sort: anyNamed('sort'), sort: any(named: 'sort'),
options: anyNamed('options'), options: any(named: 'options'),
pagination: anyNamed('pagination'), pagination: any(named: 'pagination'),
)).called(1); )).called(1);
}, },
); );
@@ -228,12 +176,12 @@ void main() {
final mockClient = MockClient(); final mockClient = MockClient();
const users = <User>[]; const users = <User>[];
when(mockClient.queryUsers( when(() => mockClient.queryUsers(
filter: anyNamed('filter'), filter: any(named: 'filter'),
sort: anyNamed('sort'), sort: any(named: 'sort'),
options: anyNamed('options'), options: any(named: 'options'),
pagination: anyNamed('pagination'), pagination: any(named: 'pagination'),
)).thenAnswer((_) async => QueryUsersResponse()..users = users); )).thenAnswer((_) async => QueryUsersResponse()..users = users);
await tester.pumpWidget( await tester.pumpWidget(
StreamChatCore( StreamChatCore(
@@ -248,12 +196,12 @@ void main() {
expect(find.byKey(emptyWidgetKey), findsOneWidget); expect(find.byKey(emptyWidgetKey), findsOneWidget);
verify(mockClient.queryUsers( verify(() => mockClient.queryUsers(
filter: anyNamed('filter'), filter: any(named: 'filter'),
sort: anyNamed('sort'), sort: any(named: 'sort'),
options: anyNamed('options'), options: any(named: 'options'),
pagination: anyNamed('pagination'), pagination: any(named: 'pagination'),
)).called(1); )).called(1);
}, },
); );
@@ -273,12 +221,12 @@ void main() {
final mockClient = MockClient(); final mockClient = MockClient();
final users = _generateUsers(); final users = _generateUsers();
when(mockClient.queryUsers( when(() => mockClient.queryUsers(
filter: anyNamed('filter'), filter: any(named: 'filter'),
sort: anyNamed('sort'), sort: any(named: 'sort'),
options: anyNamed('options'), options: any(named: 'options'),
pagination: anyNamed('pagination'), pagination: any(named: 'pagination'),
)).thenAnswer((_) async => QueryUsersResponse()..users = users); )).thenAnswer((_) async => QueryUsersResponse()..users = users);
await tester.pumpWidget( await tester.pumpWidget(
StreamChatCore( StreamChatCore(
@@ -293,12 +241,12 @@ void main() {
expect(find.byKey(listWidgetKey), findsOneWidget); expect(find.byKey(listWidgetKey), findsOneWidget);
verify(mockClient.queryUsers( verify(() => mockClient.queryUsers(
filter: anyNamed('filter'), filter: any(named: 'filter'),
sort: anyNamed('sort'), sort: any(named: 'sort'),
options: anyNamed('options'), options: any(named: 'options'),
pagination: anyNamed('pagination'), pagination: any(named: 'pagination'),
)).called(1); )).called(1);
}, },
); );
@@ -314,7 +262,7 @@ void main() {
child: ListView( child: ListView(
children: items.map((e) { children: items.map((e) {
return Container( return Container(
key: Key(e.key), key: Key(e.key ?? ''),
child: e.when( child: e.when(
headerItem: (heading) => Text(heading), headerItem: (heading) => Text(heading),
userItem: (user) => Text(user.id), userItem: (user) => Text(user.id),
@@ -332,12 +280,12 @@ void main() {
final mockClient = MockClient(); final mockClient = MockClient();
final users = _generateUsers(); final users = _generateUsers();
when(mockClient.queryUsers( when(() => mockClient.queryUsers(
filter: anyNamed('filter'), filter: any(named: 'filter'),
sort: anyNamed('sort'), sort: any(named: 'sort'),
options: anyNamed('options'), options: any(named: 'options'),
pagination: anyNamed('pagination'), pagination: any(named: 'pagination'),
)).thenAnswer((_) async => QueryUsersResponse()..users = users); )).thenAnswer((_) async => QueryUsersResponse()..users = users);
await tester.pumpWidget( await tester.pumpWidget(
Directionality( Directionality(
@@ -359,12 +307,12 @@ void main() {
expect(find.byKey(Key('USER-${user.id}')), findsOneWidget); expect(find.byKey(Key('USER-${user.id}')), findsOneWidget);
} }
verify(mockClient.queryUsers( verify(() => mockClient.queryUsers(
filter: anyNamed('filter'), filter: any(named: 'filter'),
sort: anyNamed('sort'), sort: any(named: 'sort'),
options: anyNamed('options'), options: any(named: 'options'),
pagination: anyNamed('pagination'), pagination: any(named: 'pagination'),
)).called(1); )).called(1);
}, },
); );
@@ -382,7 +330,7 @@ void main() {
child: ListView( child: ListView(
children: items.map((e) { children: items.map((e) {
return Container( return Container(
key: Key(e.key), key: Key(e.key ?? ''),
child: e.when( child: e.when(
headerItem: (heading) => Text(heading), headerItem: (heading) => Text(heading),
userItem: (user) => Text(user.id), userItem: (user) => Text(user.id),
@@ -401,12 +349,12 @@ void main() {
final mockClient = MockClient(); final mockClient = MockClient();
final users = _generateUsers(); final users = _generateUsers();
when(mockClient.queryUsers( when(() => mockClient.queryUsers(
filter: anyNamed('filter'), filter: any(named: 'filter'),
sort: anyNamed('sort'), sort: any(named: 'sort'),
options: anyNamed('options'), options: any(named: 'options'),
pagination: anyNamed('pagination'), pagination: any(named: 'pagination'),
)).thenAnswer((_) async => QueryUsersResponse()..users = users); )).thenAnswer((_) async => QueryUsersResponse()..users = users);
await tester.pumpWidget( await tester.pumpWidget(
Directionality( Directionality(
@@ -428,12 +376,12 @@ void main() {
expect(find.byKey(Key('USER-${user.id}')), findsOneWidget); expect(find.byKey(Key('USER-${user.id}')), findsOneWidget);
} }
verify(mockClient.queryUsers( verify(() => mockClient.queryUsers(
filter: anyNamed('filter'), filter: any(named: 'filter'),
sort: anyNamed('sort'), sort: any(named: 'sort'),
options: anyNamed('options'), options: any(named: 'options'),
pagination: anyNamed('pagination'), pagination: any(named: 'pagination'),
)).called(1); )).called(1);
final userListCoreState = tester.state<UserListCoreState>( final userListCoreState = tester.state<UserListCoreState>(
find.byKey(userListCoreKey), find.byKey(userListCoreKey),
@@ -442,12 +390,14 @@ void main() {
final offset = users.length; final offset = users.length;
final paginatedUsers = _generateUsers(offset: offset); final paginatedUsers = _generateUsers(offset: offset);
final updatedPagination = pagination.copyWith(offset: offset); final updatedPagination = pagination.copyWith(offset: offset);
when(mockClient.queryUsers( when(() => mockClient.queryUsers(
filter: anyNamed('filter'), filter: any(named: 'filter'),
sort: anyNamed('sort'), sort: any(named: 'sort'),
options: anyNamed('options'), options: any(named: 'options'),
pagination: updatedPagination, pagination: updatedPagination,
)).thenAnswer((_) async => QueryUsersResponse()..users = paginatedUsers); ))
.thenAnswer(
(_) async => QueryUsersResponse()..users = paginatedUsers);
await userListCoreState.paginateData(); await userListCoreState.paginateData();
@@ -458,12 +408,12 @@ void main() {
expect(find.byKey(Key('USER-${user.id}')), findsOneWidget); expect(find.byKey(Key('USER-${user.id}')), findsOneWidget);
} }
verify(mockClient.queryUsers( verify(() => mockClient.queryUsers(
filter: anyNamed('filter'), filter: any(named: 'filter'),
sort: anyNamed('sort'), sort: any(named: 'sort'),
options: anyNamed('options'), options: any(named: 'options'),
pagination: updatedPagination, pagination: updatedPagination,
)).called(1); )).called(1);
}, },
); );
@@ -473,7 +423,7 @@ void main() {
(tester) async { (tester) async {
const pagination = PaginationParams(); const pagination = PaginationParams();
StateSetter _stateSetter; StateSetter? _stateSetter;
int limit = pagination.limit; int limit = pagination.limit;
const userListCoreKey = Key('userListCore'); const userListCoreKey = Key('userListCore');
@@ -485,7 +435,7 @@ void main() {
child: ListView( child: ListView(
children: items.map((e) { children: items.map((e) {
return Container( return Container(
key: Key(e.key), key: Key(e.key ?? ''),
child: e.when( child: e.when(
headerItem: (heading) => Text(heading), headerItem: (heading) => Text(heading),
userItem: (user) => Text(user.id), userItem: (user) => Text(user.id),
@@ -504,12 +454,12 @@ void main() {
final mockClient = MockClient(); final mockClient = MockClient();
final users = _generateUsers(); final users = _generateUsers();
when(mockClient.queryUsers( when(() => mockClient.queryUsers(
filter: anyNamed('filter'), filter: any(named: 'filter'),
sort: anyNamed('sort'), sort: any(named: 'sort'),
options: anyNamed('options'), options: any(named: 'options'),
pagination: anyNamed('pagination'), pagination: any(named: 'pagination'),
)).thenAnswer((_) async => QueryUsersResponse()..users = users); )).thenAnswer((_) async => QueryUsersResponse()..users = users);
await tester.pumpWidget( await tester.pumpWidget(
Directionality( Directionality(
@@ -535,24 +485,25 @@ void main() {
expect(find.byKey(Key('USER-${user.id}')), findsOneWidget); expect(find.byKey(Key('USER-${user.id}')), findsOneWidget);
} }
verify(mockClient.queryUsers( verify(() => mockClient.queryUsers(
filter: anyNamed('filter'), filter: any(named: 'filter'),
sort: anyNamed('sort'), sort: any(named: 'sort'),
options: anyNamed('options'), options: any(named: 'options'),
pagination: anyNamed('pagination'), pagination: any(named: 'pagination'),
)).called(1); )).called(1);
// Rebuilding UserListCore with new pagination limit // Rebuilding UserListCore with new pagination limit
_stateSetter(() => limit = 6); _stateSetter?.call(() => limit = 6);
final updatedUsers = _generateUsers(count: limit); final updatedUsers = _generateUsers(count: limit);
final updatedPagination = pagination.copyWith(limit: limit); final updatedPagination = pagination.copyWith(limit: limit);
when(mockClient.queryUsers( when(() => mockClient.queryUsers(
filter: anyNamed('filter'), filter: any(named: 'filter'),
sort: anyNamed('sort'), sort: any(named: 'sort'),
options: anyNamed('options'), options: any(named: 'options'),
pagination: updatedPagination, pagination: updatedPagination,
)).thenAnswer((_) async => QueryUsersResponse()..users = updatedUsers); ))
.thenAnswer((_) async => QueryUsersResponse()..users = updatedUsers);
await tester.pumpAndSettle(); await tester.pumpAndSettle();
@@ -561,12 +512,12 @@ void main() {
expect(find.byKey(Key('USER-${user.id}')), findsOneWidget); expect(find.byKey(Key('USER-${user.id}')), findsOneWidget);
} }
verify(mockClient.queryUsers( verify(() => mockClient.queryUsers(
filter: anyNamed('filter'), filter: any(named: 'filter'),
sort: anyNamed('sort'), sort: any(named: 'sort'),
options: anyNamed('options'), options: any(named: 'options'),
pagination: updatedPagination, pagination: updatedPagination,
)).called(1); )).called(1);
}, },
); );
} }
@@ -1,9 +1,9 @@
import 'package:flutter/widgets.dart'; import 'package:flutter/widgets.dart';
import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_test/flutter_test.dart';
import 'package:mocktail/mocktail.dart';
import 'package:stream_chat/stream_chat.dart'; import 'package:stream_chat/stream_chat.dart';
import 'package:stream_chat_flutter_core/src/stream_chat_core.dart'; import 'package:stream_chat_flutter_core/src/stream_chat_core.dart';
import 'package:stream_chat_flutter_core/src/users_bloc.dart'; import 'package:stream_chat_flutter_core/src/users_bloc.dart';
import 'package:mockito/mockito.dart';
import 'matchers/users_matcher.dart'; import 'matchers/users_matcher.dart';
import 'mocks.dart'; import 'mocks.dart';
@@ -31,18 +31,6 @@ void main() {
); );
} }
test(
'should throw assertion error if child is null',
() async {
const usersBlocKey = Key('usersBloc');
final usersBloc = () => UsersBloc(
key: usersBlocKey,
child: null,
);
expect(usersBloc, throwsA(isA<AssertionError>()));
},
);
testWidgets( testWidgets(
'usersBlocState.queryUsers() should throw if used where ' 'usersBlocState.queryUsers() should throw if used where '
'StreamChat is not present in the widget tree', 'StreamChat is not present in the widget tree',
@@ -96,12 +84,12 @@ void main() {
final users = _generateUsers(); final users = _generateUsers();
when(mockClient.queryUsers( when(() => mockClient.queryUsers(
filter: anyNamed('filter'), filter: any(named: 'filter'),
sort: anyNamed('sort'), sort: any(named: 'sort'),
options: anyNamed('options'), options: any(named: 'options'),
pagination: anyNamed('pagination'), pagination: any(named: 'pagination'),
)).thenAnswer((_) async => QueryUsersResponse()..users = users); )).thenAnswer((_) async => QueryUsersResponse()..users = users);
usersBlocState.queryUsers(); usersBlocState.queryUsers();
@@ -110,12 +98,12 @@ void main() {
emits(isSameUserListAs(users)), emits(isSameUserListAs(users)),
); );
verify(mockClient.queryUsers( verify(() => mockClient.queryUsers(
filter: anyNamed('filter'), filter: any(named: 'filter'),
sort: anyNamed('sort'), sort: any(named: 'sort'),
options: anyNamed('options'), options: any(named: 'options'),
pagination: anyNamed('pagination'), pagination: any(named: 'pagination'),
)).called(1); )).called(1);
}, },
); );
@@ -145,12 +133,12 @@ void main() {
final error = 'Error! Error! Error!'; final error = 'Error! Error! Error!';
when(mockClient.queryUsers( when(() => mockClient.queryUsers(
filter: anyNamed('filter'), filter: any(named: 'filter'),
sort: anyNamed('sort'), sort: any(named: 'sort'),
options: anyNamed('options'), options: any(named: 'options'),
pagination: anyNamed('pagination'), pagination: any(named: 'pagination'),
)).thenThrow(error); )).thenThrow(error);
usersBlocState.queryUsers(); usersBlocState.queryUsers();
@@ -159,12 +147,12 @@ void main() {
emitsError(error), emitsError(error),
); );
verify(mockClient.queryUsers( verify(() => mockClient.queryUsers(
filter: anyNamed('filter'), filter: any(named: 'filter'),
sort: anyNamed('sort'), sort: any(named: 'sort'),
options: anyNamed('options'), options: any(named: 'options'),
pagination: anyNamed('pagination'), pagination: any(named: 'pagination'),
)).called(1); )).called(1);
}, },
); );
@@ -195,12 +183,12 @@ void main() {
final users = _generateUsers(); final users = _generateUsers();
when(mockClient.queryUsers( when(() => mockClient.queryUsers(
filter: anyNamed('filter'), filter: any(named: 'filter'),
sort: anyNamed('sort'), sort: any(named: 'sort'),
options: anyNamed('options'), options: any(named: 'options'),
pagination: anyNamed('pagination'), pagination: any(named: 'pagination'),
)).thenAnswer((_) async => QueryUsersResponse()..users = users); )).thenAnswer((_) async => QueryUsersResponse()..users = users);
usersBlocState.queryUsers(); usersBlocState.queryUsers();
@@ -209,23 +197,25 @@ void main() {
emits(isSameUserListAs(users)), emits(isSameUserListAs(users)),
); );
verify(mockClient.queryUsers( verify(() => mockClient.queryUsers(
filter: anyNamed('filter'), filter: any(named: 'filter'),
sort: anyNamed('sort'), sort: any(named: 'sort'),
options: anyNamed('options'), options: any(named: 'options'),
pagination: anyNamed('pagination'), pagination: any(named: 'pagination'),
)).called(1); )).called(1);
final offset = users.length; final offset = users.length;
final paginatedUsers = _generateUsers(offset: offset); final paginatedUsers = _generateUsers(offset: offset);
final pagination = PaginationParams(offset: offset); final pagination = PaginationParams(offset: offset);
when(mockClient.queryUsers( when(() => mockClient.queryUsers(
filter: anyNamed('filter'), filter: any(named: 'filter'),
sort: anyNamed('sort'), sort: any(named: 'sort'),
options: anyNamed('options'), options: any(named: 'options'),
pagination: pagination, pagination: pagination,
)).thenAnswer((_) async => QueryUsersResponse()..users = paginatedUsers); ))
.thenAnswer(
(_) async => QueryUsersResponse()..users = paginatedUsers);
usersBlocState.queryUsers(pagination: pagination); usersBlocState.queryUsers(pagination: pagination);
@@ -240,12 +230,12 @@ void main() {
), ),
]); ]);
verify(mockClient.queryUsers( verify(() => mockClient.queryUsers(
filter: anyNamed('filter'), filter: any(named: 'filter'),
sort: anyNamed('sort'), sort: any(named: 'sort'),
options: anyNamed('options'), options: any(named: 'options'),
pagination: pagination, pagination: pagination,
)).called(1); )).called(1);
}, },
); );
@@ -276,12 +266,12 @@ void main() {
final users = _generateUsers(); final users = _generateUsers();
when(mockClient.queryUsers( when(() => mockClient.queryUsers(
filter: anyNamed('filter'), filter: any(named: 'filter'),
sort: anyNamed('sort'), sort: any(named: 'sort'),
options: anyNamed('options'), options: any(named: 'options'),
pagination: anyNamed('pagination'), pagination: any(named: 'pagination'),
)).thenAnswer((_) async => QueryUsersResponse()..users = users); )).thenAnswer((_) async => QueryUsersResponse()..users = users);
usersBlocState.queryUsers(); usersBlocState.queryUsers();
@@ -290,24 +280,24 @@ void main() {
emits(isSameUserListAs(users)), emits(isSameUserListAs(users)),
); );
verify(mockClient.queryUsers( verify(() => mockClient.queryUsers(
filter: anyNamed('filter'), filter: any(named: 'filter'),
sort: anyNamed('sort'), sort: any(named: 'sort'),
options: anyNamed('options'), options: any(named: 'options'),
pagination: anyNamed('pagination'), pagination: any(named: 'pagination'),
)).called(1); )).called(1);
final offset = users.length; final offset = users.length;
final pagination = PaginationParams(offset: offset); final pagination = PaginationParams(offset: offset);
final error = 'Error! Error! Error!'; final error = 'Error! Error! Error!';
when(mockClient.queryUsers( when(() => mockClient.queryUsers(
filter: anyNamed('filter'), filter: any(named: 'filter'),
sort: anyNamed('sort'), sort: any(named: 'sort'),
options: anyNamed('options'), options: any(named: 'options'),
pagination: pagination, pagination: pagination,
)).thenThrow(error); )).thenThrow(error);
usersBlocState.queryUsers(pagination: pagination); usersBlocState.queryUsers(pagination: pagination);
@@ -316,12 +306,12 @@ void main() {
emitsError(error), emitsError(error),
); );
verify(mockClient.queryUsers( verify(() => mockClient.queryUsers(
filter: anyNamed('filter'), filter: any(named: 'filter'),
sort: anyNamed('sort'), sort: any(named: 'sort'),
options: anyNamed('options'), options: any(named: 'options'),
pagination: pagination, pagination: pagination,
)).called(1); )).called(1);
}, },
); );
} }