Skip to content

Commit df89139

Browse files
committed
Merge remote-tracking branch 'origin/main' into test/add-moderation-client-tests
# Conflicts: # packages/stream_feeds/dart_test.yaml # packages/stream_feeds_test/lib/src/helpers/test_data.dart # packages/stream_feeds_test/lib/stream_feeds_test.dart
2 parents 7f98b2e + d63b14c commit df89139

File tree

5 files changed

+675
-0
lines changed

5 files changed

+675
-0
lines changed

packages/stream_feeds_test/lib/src/helpers/test_data.dart

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -664,6 +664,61 @@ QueryCommentsResponse createDefaultQueryCommentsResponse({
664664
);
665665
}
666666

667+
FeedsReactionResponse createDefaultReactionResponse({
668+
String activityId = 'activity-id',
669+
String? commentId,
670+
String userId = 'user-id',
671+
String reactionType = 'like',
672+
}) {
673+
return FeedsReactionResponse(
674+
activityId: activityId,
675+
commentId: commentId,
676+
type: reactionType,
677+
createdAt: DateTime.timestamp(),
678+
updatedAt: DateTime.timestamp(),
679+
user: createDefaultUserResponse(id: userId),
680+
);
681+
}
682+
683+
QueryActivityReactionsResponse createDefaultQueryActivityReactionsResponse({
684+
String? next,
685+
String? prev,
686+
List<FeedsReactionResponse> reactions = const [],
687+
}) {
688+
return QueryActivityReactionsResponse(
689+
next: next,
690+
prev: prev,
691+
reactions: reactions,
692+
duration: '10ms',
693+
);
694+
}
695+
696+
QueryCommentReactionsResponse createDefaultQueryCommentReactionsResponse({
697+
String? next,
698+
String? prev,
699+
List<FeedsReactionResponse> reactions = const [],
700+
}) {
701+
return QueryCommentReactionsResponse(
702+
next: next,
703+
prev: prev,
704+
reactions: reactions,
705+
duration: '10ms',
706+
);
707+
}
708+
709+
QueryCommentsResponse createDefaultQueryCommentsResponse({
710+
String? next,
711+
String? prev,
712+
List<CommentResponse> comments = const [],
713+
}) {
714+
return QueryCommentsResponse(
715+
next: next,
716+
prev: prev,
717+
comments: comments,
718+
duration: '10ms',
719+
);
720+
}
721+
667722
FeedMemberResponse createDefaultFeedMemberResponse({
668723
String id = 'member-id',
669724
String role = 'member',
Lines changed: 162 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,162 @@
1+
import 'dart:async';
2+
3+
import 'package:meta/meta.dart';
4+
import 'package:stream_feeds/stream_feeds.dart';
5+
import 'package:test/test.dart' as test;
6+
7+
import '../helpers/mocks.dart';
8+
import '../helpers/test_data.dart';
9+
import 'base_tester.dart';
10+
11+
/// Test helper for activity reaction list operations.
12+
///
13+
/// Automatically sets up WebSocket connection, client, and test infrastructure.
14+
/// Tests are tagged with 'activity-reaction-list' by default for filtering.
15+
///
16+
/// [user] is optional, the authenticated user for the test client (defaults to luke_skywalker).
17+
18+
/// [build] constructs the [ActivityReactionList] under test using the provided [StreamFeedsClient].
19+
/// [setUp] is optional and runs before [body] for setting up mocks and test state.
20+
/// [body] is the test callback that receives an [ActivityReactionListTester] for interactions.
21+
/// [verify] is optional and runs after [body] for verifying API calls and interactions.
22+
/// [tearDown] is optional and runs after [verify] for cleanup operations.
23+
/// [skip] is optional, skip this test.
24+
/// [tags] is optional, tags for test filtering. Defaults to ['activity-reaction-list'].
25+
/// [timeout] is optional, custom timeout for this test.
26+
///
27+
/// Example:
28+
/// ```dart
29+
/// activityReactionListTest(
30+
/// 'queries initial reactions',
31+
/// build: (client) => client.activityReactionList(
32+
/// ActivityReactionsQuery(
33+
/// activityId: 'activity-1',
34+
/// ),
35+
/// ),
36+
/// setUp: (tester) => tester.get(),
37+
/// body: (tester) async {
38+
/// expect(tester.activityReactionListState.reactions, hasLength(3));
39+
/// },
40+
/// );
41+
/// ```
42+
@isTest
43+
void activityReactionListTest(
44+
String description, {
45+
User user = const User(id: 'luke_skywalker'),
46+
required ActivityReactionList Function(StreamFeedsClient client) build,
47+
FutureOr<void> Function(ActivityReactionListTester tester)? setUp,
48+
required FutureOr<void> Function(ActivityReactionListTester tester) body,
49+
FutureOr<void> Function(ActivityReactionListTester tester)? verify,
50+
FutureOr<void> Function(ActivityReactionListTester tester)? tearDown,
51+
bool skip = false,
52+
Iterable<String> tags = const ['activity-reaction-list'],
53+
test.Timeout? timeout,
54+
}) {
55+
return testWithTester(
56+
description,
57+
user: user,
58+
build: build,
59+
createTesterFn: _createActivityReactionListTester,
60+
setUp: setUp,
61+
body: body,
62+
verify: verify,
63+
tearDown: tearDown,
64+
skip: skip,
65+
tags: tags,
66+
timeout: timeout,
67+
);
68+
}
69+
70+
/// A test utility for activity reaction list operations with WebSocket support.
71+
///
72+
/// Provides helper methods for emitting events and verifying activity reaction list state.
73+
///
74+
/// Resources are automatically cleaned up after the test completes.
75+
final class ActivityReactionListTester
76+
extends BaseTester<ActivityReactionList> {
77+
const ActivityReactionListTester._({
78+
required ActivityReactionList activityReactionList,
79+
required super.wsStreamController,
80+
required super.feedsApi,
81+
}) : super(subject: activityReactionList);
82+
83+
/// The activity reaction list being tested.
84+
ActivityReactionList get activityReactionList => subject;
85+
86+
/// Current state of the activity reaction list.
87+
ActivityReactionListState get activityReactionListState {
88+
return activityReactionList.state;
89+
}
90+
91+
/// Stream of activity reaction list state updates.
92+
Stream<ActivityReactionListState> get activityReactionListStateStream {
93+
return activityReactionList.stream;
94+
}
95+
96+
/// Gets the activity reaction list by fetching it from the API.
97+
///
98+
/// Call this in event tests to set up initial state before emitting events.
99+
/// Skip this in API tests that only verify method calls.
100+
///
101+
/// Parameters:
102+
/// - [modifyResponse]: Optional function to customize the activity reaction list response
103+
Future<Result<List<FeedsReactionData>>> get({
104+
QueryActivityReactionsResponse Function(
105+
QueryActivityReactionsResponse,
106+
)? modifyResponse,
107+
}) {
108+
final query = activityReactionList.query;
109+
110+
final defaultReactionListResponse =
111+
createDefaultQueryActivityReactionsResponse(
112+
reactions: [
113+
createDefaultReactionResponse(activityId: query.activityId),
114+
createDefaultReactionResponse(
115+
activityId: query.activityId,
116+
userId: 'user-2',
117+
),
118+
createDefaultReactionResponse(
119+
activityId: query.activityId,
120+
userId: 'user-3',
121+
),
122+
],
123+
);
124+
125+
mockApi(
126+
(api) => api.queryActivityReactions(
127+
activityId: query.activityId,
128+
queryActivityReactionsRequest: query.toRequest(),
129+
),
130+
result: switch (modifyResponse) {
131+
final modifier? => modifier(defaultReactionListResponse),
132+
_ => defaultReactionListResponse,
133+
},
134+
);
135+
136+
return activityReactionList.get();
137+
}
138+
}
139+
140+
// Creates an ActivityReactionListTester for testing activity reaction list operations.
141+
//
142+
// Automatically sets up WebSocket connection and registers cleanup handlers.
143+
// This function is for internal use by activityReactionListTest only.
144+
Future<ActivityReactionListTester> _createActivityReactionListTester({
145+
required StreamFeedsClient client,
146+
required ActivityReactionList subject,
147+
required MockDefaultApi feedsApi,
148+
required MockWebSocketChannel webSocketChannel,
149+
}) {
150+
// Dispose activity reaction list after test
151+
test.addTearDown(subject.dispose);
152+
153+
return createTester(
154+
client: client,
155+
webSocketChannel: webSocketChannel,
156+
create: (wsStreamController) => ActivityReactionListTester._(
157+
activityReactionList: subject,
158+
wsStreamController: wsStreamController,
159+
feedsApi: feedsApi,
160+
),
161+
);
162+
}
Lines changed: 161 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,161 @@
1+
import 'dart:async';
2+
3+
import 'package:meta/meta.dart';
4+
import 'package:stream_feeds/stream_feeds.dart';
5+
import 'package:test/test.dart' as test;
6+
7+
import '../helpers/mocks.dart';
8+
import '../helpers/test_data.dart';
9+
import 'base_tester.dart';
10+
11+
/// Test helper for comment reaction list operations.
12+
///
13+
/// Automatically sets up WebSocket connection, client, and test infrastructure.
14+
/// Tests are tagged with 'comment-reaction-list' by default for filtering.
15+
///
16+
/// [user] is optional, the authenticated user for the test client (defaults to luke_skywalker).
17+
18+
/// [build] constructs the [CommentReactionList] under test using the provided [StreamFeedsClient].
19+
/// [setUp] is optional and runs before [body] for setting up mocks and test state.
20+
/// [body] is the test callback that receives a [CommentReactionListTester] for interactions.
21+
/// [verify] is optional and runs after [body] for verifying API calls and interactions.
22+
/// [tearDown] is optional and runs after [verify] for cleanup operations.
23+
/// [skip] is optional, skip this test.
24+
/// [tags] is optional, tags for test filtering. Defaults to ['comment-reaction-list'].
25+
/// [timeout] is optional, custom timeout for this test.
26+
///
27+
/// Example:
28+
/// ```dart
29+
/// commentReactionListTest(
30+
/// 'queries initial reactions',
31+
/// build: (client) => client.commentReactionList(
32+
/// CommentReactionsQuery(
33+
/// commentId: 'comment-1',
34+
/// ),
35+
/// ),
36+
/// setUp: (tester) => tester.get(),
37+
/// body: (tester) async {
38+
/// expect(tester.commentReactionListState.reactions, hasLength(3));
39+
/// },
40+
/// );
41+
/// ```
42+
@isTest
43+
void commentReactionListTest(
44+
String description, {
45+
User user = const User(id: 'luke_skywalker'),
46+
required CommentReactionList Function(StreamFeedsClient client) build,
47+
FutureOr<void> Function(CommentReactionListTester tester)? setUp,
48+
required FutureOr<void> Function(CommentReactionListTester tester) body,
49+
FutureOr<void> Function(CommentReactionListTester tester)? verify,
50+
FutureOr<void> Function(CommentReactionListTester tester)? tearDown,
51+
bool skip = false,
52+
Iterable<String> tags = const ['comment-reaction-list'],
53+
test.Timeout? timeout,
54+
}) {
55+
return testWithTester(
56+
description,
57+
user: user,
58+
build: build,
59+
createTesterFn: _createCommentReactionListTester,
60+
setUp: setUp,
61+
body: body,
62+
verify: verify,
63+
tearDown: tearDown,
64+
skip: skip,
65+
tags: tags,
66+
timeout: timeout,
67+
);
68+
}
69+
70+
/// A test utility for comment reaction list operations with WebSocket support.
71+
///
72+
/// Provides helper methods for emitting events and verifying comment reaction list state.
73+
///
74+
/// Resources are automatically cleaned up after the test completes.
75+
final class CommentReactionListTester extends BaseTester<CommentReactionList> {
76+
const CommentReactionListTester._({
77+
required CommentReactionList commentReactionList,
78+
required super.wsStreamController,
79+
required super.feedsApi,
80+
}) : super(subject: commentReactionList);
81+
82+
/// The comment reaction list being tested.
83+
CommentReactionList get commentReactionList => subject;
84+
85+
/// Current state of the comment reaction list.
86+
CommentReactionListState get commentReactionListState {
87+
return commentReactionList.state;
88+
}
89+
90+
/// Stream of comment reaction list state updates.
91+
Stream<CommentReactionListState> get commentReactionListStateStream {
92+
return commentReactionList.stream;
93+
}
94+
95+
/// Gets the comment reaction list by fetching it from the API.
96+
///
97+
/// Call this in event tests to set up initial state before emitting events.
98+
/// Skip this in API tests that only verify method calls.
99+
///
100+
/// Parameters:
101+
/// - [modifyResponse]: Optional function to customize the comment reaction list response
102+
Future<Result<List<FeedsReactionData>>> get({
103+
QueryCommentReactionsResponse Function(
104+
QueryCommentReactionsResponse,
105+
)? modifyResponse,
106+
}) {
107+
final query = commentReactionList.query;
108+
109+
final defaultReactionListResponse =
110+
createDefaultQueryCommentReactionsResponse(
111+
reactions: [
112+
createDefaultReactionResponse(commentId: query.commentId),
113+
createDefaultReactionResponse(
114+
commentId: query.commentId,
115+
userId: 'user-2',
116+
),
117+
createDefaultReactionResponse(
118+
commentId: query.commentId,
119+
userId: 'user-3',
120+
),
121+
],
122+
);
123+
124+
mockApi(
125+
(api) => api.queryCommentReactions(
126+
id: query.commentId,
127+
queryCommentReactionsRequest: query.toRequest(),
128+
),
129+
result: switch (modifyResponse) {
130+
final modifier? => modifier(defaultReactionListResponse),
131+
_ => defaultReactionListResponse,
132+
},
133+
);
134+
135+
return commentReactionList.get();
136+
}
137+
}
138+
139+
// Creates a CommentReactionListTester for testing comment reaction list operations.
140+
//
141+
// Automatically sets up WebSocket connection and registers cleanup handlers.
142+
// This function is for internal use by commentReactionListTest only.
143+
Future<CommentReactionListTester> _createCommentReactionListTester({
144+
required StreamFeedsClient client,
145+
required CommentReactionList subject,
146+
required MockDefaultApi feedsApi,
147+
required MockWebSocketChannel webSocketChannel,
148+
}) {
149+
// Dispose comment reaction list after test
150+
test.addTearDown(subject.dispose);
151+
152+
return createTester(
153+
client: client,
154+
webSocketChannel: webSocketChannel,
155+
create: (wsStreamController) => CommentReactionListTester._(
156+
commentReactionList: subject,
157+
wsStreamController: wsStreamController,
158+
feedsApi: feedsApi,
159+
),
160+
);
161+
}

0 commit comments

Comments
 (0)