feat(core, ui): Improve pagination invocation by using paginationEnded flag.

Signed-off-by: xsahil03x <[email protected]>
This commit is contained in:
Sahil Kumar
2021-09-07 17:59:56 +05:30
committed by xsahil03x
parent fd6fcef9b2
commit 21647040e1
9 changed files with 272 additions and 100 deletions
@@ -31,8 +31,7 @@ void main() {
);
testWidgets(
'messageSearchBlocState.search() should throw if used where '
'StreamChat is not present in the widget tree',
'''messageSearchBlocState.search() should throw if used where StreamChat is not present in the widget tree''',
(tester) async {
const messageSearchBloc = MessageSearchBloc(
child: Offstage(),
@@ -74,7 +73,10 @@ void main() {
messageFilters: any(named: 'messageFilters'),
paginationParams: any(named: 'paginationParams'),
)).thenAnswer(
(_) async => SearchMessagesResponse()..results = messageResponseList,
(_) async => SearchMessagesResponse()
..results = messageResponseList
..next = null
..previous = null,
);
messageSearchBlocState.search(filter: testFilter);
@@ -95,8 +97,7 @@ void main() {
);
testWidgets(
'messageSearchBlocState.messagesStream should emit error '
'if client.search() throws',
'''messageSearchBlocState.messagesStream should emit error if client.search() throws''',
(tester) async {
const messageSearchBlocKey = Key('messageSearchBloc');
const childKey = Key('child');
@@ -144,9 +145,7 @@ void main() {
);
testWidgets(
'calling messageSearchBlocState.search() again with an offset '
'should emit new data through messagesStream and also emit loading state '
'through queryMessagesLoading',
'''calling messageSearchBlocState.search() again with an offset should emit new data through messagesStream and also emit loading state through queryMessagesLoading''',
(tester) async {
const messageSearchBlocKey = Key('messageSearchBloc');
const childKey = Key('child');
@@ -168,19 +167,23 @@ void main() {
find.byKey(messageSearchBlocKey),
);
final messageResponseList = _generateMessages();
const pagination = PaginationParams(limit: 25);
final messageResponseList = _generateMessages(count: 25);
when(() => mockClient.search(
testFilter,
query: any(named: 'query'),
sort: any(named: 'sort'),
messageFilters: any(named: 'messageFilters'),
paginationParams: any(named: 'paginationParams'),
paginationParams: pagination,
)).thenAnswer(
(_) async => SearchMessagesResponse()..results = messageResponseList,
(_) async => SearchMessagesResponse()
..results = messageResponseList
..next = null
..previous = null,
);
messageSearchBlocState.search(filter: testFilter);
messageSearchBlocState.search(pagination: pagination, filter: testFilter);
await expectLater(
messageSearchBlocState.messagesStream,
@@ -192,22 +195,24 @@ void main() {
query: any(named: 'query'),
sort: any(named: 'sort'),
messageFilters: any(named: 'messageFilters'),
paginationParams: any(named: 'paginationParams'),
paginationParams: pagination,
)).called(1);
final offset = messageResponseList.length;
final paginatedMessageResponseList = _generateMessages(offset: offset);
final pagination = PaginationParams(offset: offset);
final newPagination = pagination.copyWith(offset: offset);
when(() => mockClient.search(
testFilter,
query: any(named: 'query'),
sort: any(named: 'sort'),
messageFilters: any(named: 'messageFilters'),
paginationParams: pagination,
paginationParams: newPagination,
)).thenAnswer(
(_) async =>
SearchMessagesResponse()..results = paginatedMessageResponseList,
(_) async => SearchMessagesResponse()
..results = paginatedMessageResponseList
..next = null
..previous = null,
);
messageSearchBlocState.search(pagination: pagination, filter: testFilter);
@@ -236,9 +241,7 @@ void main() {
);
testWidgets(
'calling messageSearchBlocState.search() again with an offset '
'should emit error through queryUsersLoading if '
'client.search() throws',
'''calling messageSearchBlocState.search() again with an offset should emit error through queryUsersLoading if client.search() throws''',
(tester) async {
const messageSearchBlocKey = Key('messageSearchBloc');
const childKey = Key('child');
@@ -260,19 +263,23 @@ void main() {
find.byKey(messageSearchBlocKey),
);
final messageResponseList = _generateMessages();
const pagination = PaginationParams(limit: 25);
final messageResponseList = _generateMessages(count: 25);
when(() => mockClient.search(
testFilter,
query: any(named: 'query'),
sort: any(named: 'sort'),
messageFilters: any(named: 'messageFilters'),
paginationParams: any(named: 'paginationParams'),
paginationParams: pagination,
)).thenAnswer(
(_) async => SearchMessagesResponse()..results = messageResponseList,
(_) async => SearchMessagesResponse()
..results = messageResponseList
..next = null
..previous = null,
);
messageSearchBlocState.search(filter: testFilter);
messageSearchBlocState.search(pagination: pagination, filter: testFilter);
await expectLater(
messageSearchBlocState.messagesStream,
@@ -284,11 +291,11 @@ void main() {
query: any(named: 'query'),
sort: any(named: 'sort'),
messageFilters: any(named: 'messageFilters'),
paginationParams: any(named: 'paginationParams'),
paginationParams: pagination,
)).called(1);
final offset = messageResponseList.length;
final pagination = PaginationParams(offset: offset);
final newPagination = pagination.copyWith(offset: offset);
const error = 'Error! Error! Error!';
when(() => mockClient.search(
@@ -296,10 +303,13 @@ void main() {
query: any(named: 'query'),
sort: any(named: 'sort'),
messageFilters: any(named: 'messageFilters'),
paginationParams: pagination,
paginationParams: newPagination,
)).thenThrow(error);
messageSearchBlocState.search(pagination: pagination, filter: testFilter);
messageSearchBlocState.search(
pagination: newPagination,
filter: testFilter,
);
await expectLater(
messageSearchBlocState.queryMessagesLoading,
@@ -311,8 +321,80 @@ void main() {
query: any(named: 'query'),
sort: any(named: 'sort'),
messageFilters: any(named: 'messageFilters'),
paginationParams: pagination,
paginationParams: newPagination,
)).called(1);
},
);
testWidgets(
'''calling messageSearchBlocState.search() again with an offset should do nothing and return if pagination is completed''',
(tester) async {
const messageSearchBlocKey = Key('messageSearchBloc');
const childKey = Key('child');
const messageSearchBloc = MessageSearchBloc(
key: messageSearchBlocKey,
child: Offstage(key: childKey),
);
final mockClient = MockClient();
await tester.pumpWidget(
StreamChatCore(
client: mockClient,
child: messageSearchBloc,
),
);
final messageSearchBlocState = tester.state<MessageSearchBlocState>(
find.byKey(messageSearchBlocKey),
);
const pagination = PaginationParams(limit: 25);
final messageResponseList = _generateMessages(count: 20);
when(() => mockClient.search(
testFilter,
query: any(named: 'query'),
sort: any(named: 'sort'),
messageFilters: any(named: 'messageFilters'),
paginationParams: pagination,
)).thenAnswer(
(_) async => SearchMessagesResponse()
..results = messageResponseList
..next = null
..previous = null,
);
messageSearchBlocState.search(pagination: pagination, filter: testFilter);
await expectLater(
messageSearchBlocState.messagesStream,
emits(isSameMessageResponseListAs(messageResponseList)),
);
verify(() => mockClient.search(
testFilter,
query: any(named: 'query'),
sort: any(named: 'sort'),
messageFilters: any(named: 'messageFilters'),
paginationParams: pagination,
)).called(1);
final offset = messageResponseList.length;
final newPagination = pagination.copyWith(offset: offset);
messageSearchBlocState.search(
filter: testFilter,
pagination: newPagination,
);
// should emit nothing.
await expectLater(
// skipping the initial data (behaviorSubject).
messageSearchBlocState.messagesStream.skip(1),
emitsInOrder([]),
);
},
);
}
@@ -164,16 +164,17 @@ void main() {
find.byKey(usersBlocKey),
);
final users = _generateUsers();
const pagination = PaginationParams(limit: 25);
final users = _generateUsers(count: 25);
when(() => mockClient.queryUsers(
filter: any(named: 'filter'),
sort: any(named: 'sort'),
presence: any(named: 'presence'),
pagination: any(named: 'pagination'),
pagination: pagination,
)).thenAnswer((_) async => QueryUsersResponse()..users = users);
usersBlocState.queryUsers();
usersBlocState.queryUsers(pagination: pagination);
await expectLater(
usersBlocState.usersStream,
@@ -184,23 +185,23 @@ void main() {
filter: any(named: 'filter'),
sort: any(named: 'sort'),
presence: any(named: 'presence'),
pagination: any(named: 'pagination'),
pagination: pagination,
)).called(1);
final offset = users.length;
final paginatedUsers = _generateUsers(offset: offset);
final pagination = PaginationParams(offset: offset);
final newPagination = pagination.copyWith(offset: offset);
when(() => mockClient.queryUsers(
filter: any(named: 'filter'),
sort: any(named: 'sort'),
presence: any(named: 'presence'),
pagination: pagination,
))
.thenAnswer(
(_) async => QueryUsersResponse()..users = paginatedUsers);
filter: any(named: 'filter'),
sort: any(named: 'sort'),
presence: any(named: 'presence'),
pagination: newPagination,
)).thenAnswer(
(_) async => QueryUsersResponse()..users = paginatedUsers,
);
usersBlocState.queryUsers(pagination: pagination);
usersBlocState.queryUsers(pagination: newPagination);
await Future.wait([
expectLater(
@@ -217,7 +218,7 @@ void main() {
filter: any(named: 'filter'),
sort: any(named: 'sort'),
presence: any(named: 'presence'),
pagination: pagination,
pagination: newPagination,
)).called(1);
},
);
@@ -247,13 +248,89 @@ void main() {
find.byKey(usersBlocKey),
);
final users = _generateUsers();
const pagination = PaginationParams(limit: 25);
final users = _generateUsers(count: 25);
when(() => mockClient.queryUsers(
filter: any(named: 'filter'),
sort: any(named: 'sort'),
presence: any(named: 'presence'),
pagination: any(named: 'pagination'),
pagination: pagination,
)).thenAnswer((_) async => QueryUsersResponse()..users = users);
usersBlocState.queryUsers(pagination: pagination);
await expectLater(
usersBlocState.usersStream,
emits(isSameUserListAs(users)),
);
verify(() => mockClient.queryUsers(
filter: any(named: 'filter'),
sort: any(named: 'sort'),
presence: any(named: 'presence'),
pagination: pagination,
)).called(1);
final offset = users.length;
final newPagination = pagination.copyWith(offset: offset);
const error = 'Error! Error! Error!';
when(() => mockClient.queryUsers(
filter: any(named: 'filter'),
sort: any(named: 'sort'),
presence: any(named: 'presence'),
pagination: newPagination,
)).thenThrow(error);
usersBlocState.queryUsers(pagination: newPagination);
await expectLater(
usersBlocState.queryUsersLoading,
emitsError(error),
);
verify(() => mockClient.queryUsers(
filter: any(named: 'filter'),
sort: any(named: 'sort'),
presence: any(named: 'presence'),
pagination: newPagination,
)).called(1);
},
);
testWidgets(
'''calling usersBlocState.queryUsers() again with an offset should do nothing and return if pagination is completed''',
(tester) async {
const usersBlocKey = Key('usersBloc');
const childKey = Key('child');
const usersBloc = UsersBloc(
key: usersBlocKey,
child: Offstage(key: childKey),
);
final mockClient = MockClient();
await tester.pumpWidget(
StreamChatCore(
client: mockClient,
child: usersBloc,
),
);
final usersBlocState = tester.state<UsersBlocState>(
find.byKey(usersBlocKey),
);
const pagination = PaginationParams(limit: 30);
final users = _generateUsers(count: 25);
when(() => mockClient.queryUsers(
filter: any(named: 'filter'),
sort: any(named: 'sort'),
presence: any(named: 'presence'),
pagination: pagination,
)).thenAnswer((_) async => QueryUsersResponse()..users = users);
usersBlocState.queryUsers();
@@ -271,30 +348,16 @@ void main() {
)).called(1);
final offset = users.length;
final pagination = PaginationParams(offset: offset);
final newPagination = pagination.copyWith(offset: offset);
const error = 'Error! Error! Error!';
when(() => mockClient.queryUsers(
filter: any(named: 'filter'),
sort: any(named: 'sort'),
presence: any(named: 'presence'),
pagination: pagination,
)).thenThrow(error);
usersBlocState.queryUsers(pagination: pagination);
usersBlocState.queryUsers(pagination: newPagination);
// should emit nothing.
await expectLater(
usersBlocState.queryUsersLoading,
emitsError(error),
// skipping the initial data (behaviorSubject).
usersBlocState.usersStream,
emitsInOrder([]),
);
verify(() => mockClient.queryUsers(
filter: any(named: 'filter'),
sort: any(named: 'sort'),
presence: any(named: 'presence'),
pagination: pagination,
)).called(1);
},
);
}