Skip to content

Commit 75faa4e

Browse files
committed
Add unit tests and changelog
1 parent a2f6bdb commit 75faa4e

File tree

4 files changed

+267
-2
lines changed

4 files changed

+267
-2
lines changed

packages/stream_feeds/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
## unreleased
22
- Update follower and following counts on the feed state when receiving follow websocket events.
3+
- Improvement for stories and minor updates to other AggregatedActivity state updates.
34

45
## 0.3.1
56
- Update API client with renaming `addReaction` to `addActivityReaction` and `deleteReaction` to `deleteActivityReaction`.

packages/stream_feeds/test/state/feed_test.dart

Lines changed: 236 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -345,4 +345,240 @@ void main() {
345345
);
346346
});
347347
});
348+
349+
group('Story events', () {
350+
late StreamController<Object> wsStreamController;
351+
late MockWebSocketSink webSocketSink;
352+
353+
setUp(() async {
354+
wsStreamController = StreamController<Object>();
355+
webSocketSink = MockWebSocketSink();
356+
WsTestConnection(
357+
wsStreamController: wsStreamController,
358+
webSocketSink: webSocketSink,
359+
webSocketChannel: webSocketChannel,
360+
).setUp();
361+
362+
await client.connect();
363+
});
364+
365+
tearDown(() async {
366+
await webSocketSink.close();
367+
await wsStreamController.close();
368+
});
369+
370+
test('Watch story should update isWatched', () async {
371+
const feedId = FeedId(group: 'stories', id: 'target');
372+
final activity1 = createDefaultActivityResponse().activity.copyWith(
373+
isWatched: false,
374+
id: 'storyActivityId1',
375+
);
376+
377+
final activity2 = createDefaultActivityResponse().activity.copyWith(
378+
isWatched: false,
379+
id: 'storyActivityId2',
380+
);
381+
382+
when(
383+
() => feedsApi.getOrCreateFeed(
384+
feedGroupId: feedId.group,
385+
feedId: feedId.id,
386+
getOrCreateFeedRequest: any(named: 'getOrCreateFeedRequest'),
387+
),
388+
).thenAnswer(
389+
(_) async => Result.success(
390+
createDefaultGetOrCreateFeedResponse(
391+
aggregatedActivities: [
392+
createDefaultAggregatedActivityResponse(
393+
activities: [activity1, activity2],
394+
),
395+
],
396+
),
397+
),
398+
);
399+
400+
final feed = client.feedFromId(feedId);
401+
402+
final result = await feed.getOrCreate();
403+
result.getOrThrow();
404+
405+
expect(feed.state.aggregatedActivities.length, 1);
406+
expect(
407+
feed.state.aggregatedActivities.first.activities.first.isWatched,
408+
false,
409+
);
410+
expect(
411+
feed.state.aggregatedActivities.first.activities[1].isWatched,
412+
false,
413+
);
414+
415+
feed.notifier.stream.listen(
416+
expectAsync1(
417+
(event) {
418+
expect(event, isA<FeedState>());
419+
expect(
420+
event.aggregatedActivities.first.activities.first.isWatched,
421+
true,
422+
);
423+
expect(
424+
event.aggregatedActivities.first.activities[1].isWatched,
425+
false,
426+
);
427+
},
428+
),
429+
);
430+
431+
wsStreamController.add(
432+
jsonEncode(
433+
ActivityMarkEvent(
434+
type: EventTypes.activityMarked,
435+
createdAt: DateTime.now(),
436+
custom: const {},
437+
fid: feedId.toString(),
438+
markWatched: [activity1.id],
439+
),
440+
),
441+
);
442+
});
443+
444+
test('Pagination should load more aggregated activities', () async {
445+
const feedId = FeedId(group: 'stories', id: 'target');
446+
const nextPagination = 'next';
447+
const prevPagination = 'prev';
448+
449+
final activity1 = createDefaultActivityResponse()
450+
.activity
451+
.copyWith(id: 'storyActivityId1');
452+
453+
final activity2 = createDefaultActivityResponse()
454+
.activity
455+
.copyWith(id: 'storyActivityId2');
456+
457+
final activity3 = createDefaultActivityResponse()
458+
.activity
459+
.copyWith(id: 'storyActivityId3');
460+
461+
when(
462+
() => feedsApi.getOrCreateFeed(
463+
feedGroupId: feedId.group,
464+
feedId: feedId.id,
465+
getOrCreateFeedRequest: any(named: 'getOrCreateFeedRequest'),
466+
),
467+
).thenAnswer(
468+
(invocation) async {
469+
final request =
470+
invocation.namedArguments[const Symbol('getOrCreateFeedRequest')]
471+
as GetOrCreateFeedRequest;
472+
473+
if (request.next == null) {
474+
return Result.success(
475+
createDefaultGetOrCreateFeedResponse(
476+
nextPagination: nextPagination,
477+
aggregatedActivities: [
478+
createDefaultAggregatedActivityResponse(
479+
group: 'group1',
480+
activities: [activity1, activity2],
481+
),
482+
],
483+
),
484+
);
485+
}
486+
if (request.next == nextPagination) {
487+
return Result.success(
488+
createDefaultGetOrCreateFeedResponse(
489+
prevPagination: prevPagination,
490+
aggregatedActivities: [
491+
createDefaultAggregatedActivityResponse(
492+
group: 'group2',
493+
activities: [activity3],
494+
),
495+
],
496+
),
497+
);
498+
}
499+
throw Exception('Unexpected request');
500+
},
501+
);
502+
503+
final feed = client.feedFromId(feedId);
504+
505+
final result = await feed.getOrCreate();
506+
result.getOrThrow();
507+
508+
expect(feed.state.aggregatedActivities.length, 1);
509+
expect(feed.state.aggregatedActivities.first.activities.length, 2);
510+
511+
await feed.queryMoreActivities();
512+
513+
expect(feed.state.aggregatedActivities.length, 2);
514+
expect(feed.state.aggregatedActivities.last.activities.length, 1);
515+
});
516+
517+
test('StoriesFeedUpdatedEvent should update aggregated activities',
518+
() async {
519+
const feedId = FeedId(group: 'stories', id: 'target');
520+
521+
final activity1 = createDefaultActivityResponse()
522+
.activity
523+
.copyWith(id: 'storyActivityId1');
524+
525+
final activity2 = createDefaultActivityResponse()
526+
.activity
527+
.copyWith(id: 'storyActivityId2');
528+
529+
when(
530+
() => feedsApi.getOrCreateFeed(
531+
feedGroupId: feedId.group,
532+
feedId: feedId.id,
533+
getOrCreateFeedRequest: any(named: 'getOrCreateFeedRequest'),
534+
),
535+
).thenAnswer(
536+
(_) async => Result.success(
537+
createDefaultGetOrCreateFeedResponse(
538+
aggregatedActivities: [
539+
createDefaultAggregatedActivityResponse(
540+
group: 'group1',
541+
activities: [activity1],
542+
),
543+
],
544+
),
545+
),
546+
);
547+
548+
final feed = client.feedFromId(feedId);
549+
550+
final result = await feed.getOrCreate();
551+
result.getOrThrow();
552+
expect(feed.state.aggregatedActivities.length, 1);
553+
expect(feed.state.aggregatedActivities.first.activities.length, 1);
554+
555+
feed.notifier.stream.listen(
556+
expectAsync1(
557+
(event) {
558+
expect(event, isA<FeedState>());
559+
560+
expect(event.aggregatedActivities.length, 1);
561+
expect(event.aggregatedActivities.first.activities.length, 2);
562+
},
563+
),
564+
);
565+
566+
wsStreamController.add(
567+
jsonEncode(
568+
StoriesFeedUpdatedEvent(
569+
type: EventTypes.storiesFeedUpdated,
570+
createdAt: DateTime.now(),
571+
custom: const {},
572+
fid: feedId.toString(),
573+
aggregatedActivities: [
574+
createDefaultAggregatedActivityResponse(
575+
group: 'group1',
576+
activities: [activity1, activity2],
577+
),
578+
],
579+
),
580+
),
581+
);
582+
});
583+
});
348584
}

packages/stream_feeds/test/test_utils/event_types.dart

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
class EventTypes {
2+
static const String activityMarked = 'feeds.activity.marked';
3+
24
static const String followCreated = 'feeds.follow.created';
35
static const String followDeleted = 'feeds.follow.deleted';
46
static const String followUpdated = 'feeds.follow.updated';
@@ -7,4 +9,6 @@ class EventTypes {
79
static const String pollDeleted = 'feeds.poll.deleted';
810
static const String pollVoteCasted = 'feeds.poll.vote_casted';
911
static const String pollVoteRemoved = 'feeds.poll.vote_removed';
12+
13+
static const String storiesFeedUpdated = 'feeds.stories_feed.updated';
1014
}

packages/stream_feeds/test/test_utils/fakes.dart

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -102,20 +102,26 @@ PollResponseData createDefaultPollResponseData({
102102
GetOrCreateFeedResponse createDefaultGetOrCreateFeedResponse({
103103
int followerCount = 0,
104104
int followingCount = 0,
105+
List<AggregatedActivityResponse> aggregatedActivities = const [],
106+
List<ActivityResponse> activities = const [],
107+
String? prevPagination,
108+
String? nextPagination,
105109
}) =>
106110
GetOrCreateFeedResponse(
107111
feed: createDefaultFeedResponse(
108112
followerCount: followerCount,
109113
followingCount: followingCount,
110114
),
111-
activities: const [],
112-
aggregatedActivities: const [],
115+
activities: activities,
116+
aggregatedActivities: aggregatedActivities,
113117
created: true,
114118
duration: '',
115119
followers: const [],
116120
following: const [],
117121
members: const [],
118122
pinnedActivities: const [],
123+
next: nextPagination,
124+
prev: prevPagination,
119125
);
120126

121127
FeedResponse createDefaultFeedResponse({
@@ -151,3 +157,21 @@ FeedResponse createDefaultFeedResponse({
151157
pinCount: 0,
152158
updatedAt: DateTime.now(),
153159
);
160+
161+
AggregatedActivityResponse createDefaultAggregatedActivityResponse({
162+
List<ActivityResponse>? activities,
163+
String group = 'group',
164+
}) =>
165+
AggregatedActivityResponse(
166+
activities: activities ??
167+
[
168+
createDefaultActivityResponse().activity,
169+
],
170+
activityCount: activities?.length ?? 1,
171+
createdAt: DateTime(2021, 2, 1),
172+
group: group,
173+
score: 0,
174+
updatedAt: DateTime(2021, 2, 1),
175+
userCount: 1,
176+
userCountTruncated: false,
177+
);

0 commit comments

Comments
 (0)