diff --git a/codecov.yml b/codecov.yml index 774e6b4c..212bc9e5 100644 --- a/codecov.yml +++ b/codecov.yml @@ -7,4 +7,7 @@ coverage: base: auto patch: default: - target: 80% \ No newline at end of file + target: 80% + +ignore: + - "packages/stream_feeds_test/**/*" # Internal test utilities package \ No newline at end of file diff --git a/packages/stream_feeds/pubspec.yaml b/packages/stream_feeds/pubspec.yaml index bdc775b4..d40d1707 100644 --- a/packages/stream_feeds/pubspec.yaml +++ b/packages/stream_feeds/pubspec.yaml @@ -37,7 +37,6 @@ dev_dependencies: build_runner: ^2.4.15 freezed: ^3.0.0 json_serializable: ^6.9.5 - mocktail: ^1.0.4 retrofit_generator: ^9.6.0 - test: ^1.26.3 - web_socket_channel: ^3.0.3 \ No newline at end of file + stream_feeds_test: + path: ../stream_feeds_test \ No newline at end of file diff --git a/packages/stream_feeds/test/client/feeds_client_impl_test.dart b/packages/stream_feeds/test/client/feeds_client_impl_test.dart index 59ca90ab..e8cdc474 100644 --- a/packages/stream_feeds/test/client/feeds_client_impl_test.dart +++ b/packages/stream_feeds/test/client/feeds_client_impl_test.dart @@ -1,8 +1,7 @@ import 'package:stream_feeds/src/client/feeds_client_impl.dart'; import 'package:stream_feeds/stream_feeds.dart'; -import 'package:test/test.dart'; -import '../test_utils.dart'; +import 'package:stream_feeds_test/stream_feeds_test.dart'; void main() { test('Create a feeds client', () { diff --git a/packages/stream_feeds/test/models/feed_id_test.dart b/packages/stream_feeds/test/models/feed_id_test.dart index 7874e748..a3f1353a 100644 --- a/packages/stream_feeds/test/models/feed_id_test.dart +++ b/packages/stream_feeds/test/models/feed_id_test.dart @@ -1,5 +1,5 @@ import 'package:stream_feeds/stream_feeds.dart'; -import 'package:test/test.dart'; +import 'package:stream_feeds_test/stream_feeds_test.dart'; void main() { test('feed id should be created with group and id', () { diff --git a/packages/stream_feeds/test/resolvers/poll/poll_answer_casted_test.dart b/packages/stream_feeds/test/resolvers/poll/poll_answer_casted_test.dart index 84a9f569..8aa8b1c3 100644 --- a/packages/stream_feeds/test/resolvers/poll/poll_answer_casted_test.dart +++ b/packages/stream_feeds/test/resolvers/poll/poll_answer_casted_test.dart @@ -2,7 +2,7 @@ import 'package:stream_feeds/src/resolvers/resolvers.dart'; import 'package:stream_feeds/stream_feeds.dart'; -import 'package:test/test.dart'; +import 'package:stream_feeds_test/stream_feeds_test.dart'; void main() { group('pollAnswerCastedFeedEventResolver PollVoteCastedFeedEvent', () { diff --git a/packages/stream_feeds/test/resolvers/poll/poll_answer_removed_test.dart b/packages/stream_feeds/test/resolvers/poll/poll_answer_removed_test.dart index 705578fd..53fb1e5e 100644 --- a/packages/stream_feeds/test/resolvers/poll/poll_answer_removed_test.dart +++ b/packages/stream_feeds/test/resolvers/poll/poll_answer_removed_test.dart @@ -2,7 +2,7 @@ import 'package:stream_feeds/src/resolvers/resolvers.dart'; import 'package:stream_feeds/stream_feeds.dart'; -import 'package:test/test.dart'; +import 'package:stream_feeds_test/stream_feeds_test.dart'; void main() { group('pollAnswerRemovedFeedEventResolver', () { diff --git a/packages/stream_feeds/test/state/activity_comment_list_test.dart b/packages/stream_feeds/test/state/activity_comment_list_test.dart index 36f3dc76..83192280 100644 --- a/packages/stream_feeds/test/state/activity_comment_list_test.dart +++ b/packages/stream_feeds/test/state/activity_comment_list_test.dart @@ -1,7 +1,6 @@ import 'package:stream_feeds/stream_feeds.dart'; -import 'package:test/test.dart'; -import '../test_utils.dart'; +import 'package:stream_feeds_test/stream_feeds_test.dart'; void main() { const activityId = 'activity-1'; diff --git a/packages/stream_feeds/test/state/activity_list_test.dart b/packages/stream_feeds/test/state/activity_list_test.dart index e96fbbea..485cb38e 100644 --- a/packages/stream_feeds/test/state/activity_list_test.dart +++ b/packages/stream_feeds/test/state/activity_list_test.dart @@ -1,7 +1,6 @@ import 'package:stream_feeds/stream_feeds.dart'; -import 'package:test/test.dart'; -import '../test_utils.dart'; +import 'package:stream_feeds_test/stream_feeds_test.dart'; void main() { const activityId = 'activity-1'; diff --git a/packages/stream_feeds/test/state/activity_test.dart b/packages/stream_feeds/test/state/activity_test.dart index 3d9cbf18..18d5785a 100644 --- a/packages/stream_feeds/test/state/activity_test.dart +++ b/packages/stream_feeds/test/state/activity_test.dart @@ -1,8 +1,6 @@ -import 'package:mocktail/mocktail.dart'; import 'package:stream_feeds/stream_feeds.dart'; -import 'package:test/test.dart'; -import '../test_utils.dart'; +import 'package:stream_feeds_test/stream_feeds_test.dart'; void main() { const activityId = 'activity-1'; diff --git a/packages/stream_feeds/test/state/bookmark_folder_list_test.dart b/packages/stream_feeds/test/state/bookmark_folder_list_test.dart index b4e586ae..a9177673 100644 --- a/packages/stream_feeds/test/state/bookmark_folder_list_test.dart +++ b/packages/stream_feeds/test/state/bookmark_folder_list_test.dart @@ -1,7 +1,6 @@ import 'package:stream_feeds/stream_feeds.dart'; -import 'package:test/test.dart'; -import '../test_utils.dart'; +import 'package:stream_feeds_test/stream_feeds_test.dart'; void main() { // ============================================================ diff --git a/packages/stream_feeds/test/state/bookmark_list_test.dart b/packages/stream_feeds/test/state/bookmark_list_test.dart index b6f21520..56154008 100644 --- a/packages/stream_feeds/test/state/bookmark_list_test.dart +++ b/packages/stream_feeds/test/state/bookmark_list_test.dart @@ -1,7 +1,6 @@ import 'package:stream_feeds/stream_feeds.dart'; -import 'package:test/test.dart'; -import '../test_utils.dart'; +import 'package:stream_feeds_test/stream_feeds_test.dart'; void main() { // ============================================================ diff --git a/packages/stream_feeds/test/state/comment_list_test.dart b/packages/stream_feeds/test/state/comment_list_test.dart index 3a315728..510eecc9 100644 --- a/packages/stream_feeds/test/state/comment_list_test.dart +++ b/packages/stream_feeds/test/state/comment_list_test.dart @@ -1,7 +1,6 @@ import 'package:stream_feeds/stream_feeds.dart'; -import 'package:test/test.dart'; -import '../test_utils.dart'; +import 'package:stream_feeds_test/stream_feeds_test.dart'; void main() { // ============================================================ diff --git a/packages/stream_feeds/test/state/comment_reply_list_test.dart b/packages/stream_feeds/test/state/comment_reply_list_test.dart index f6756cd6..34595ddb 100644 --- a/packages/stream_feeds/test/state/comment_reply_list_test.dart +++ b/packages/stream_feeds/test/state/comment_reply_list_test.dart @@ -1,7 +1,6 @@ import 'package:stream_feeds/stream_feeds.dart'; -import 'package:test/test.dart'; -import '../test_utils.dart'; +import 'package:stream_feeds_test/stream_feeds_test.dart'; void main() { const commentId = 'comment-1'; diff --git a/packages/stream_feeds/test/state/feed_list_test.dart b/packages/stream_feeds/test/state/feed_list_test.dart index 6ea10e40..7bdbd112 100644 --- a/packages/stream_feeds/test/state/feed_list_test.dart +++ b/packages/stream_feeds/test/state/feed_list_test.dart @@ -1,7 +1,6 @@ import 'package:stream_feeds/stream_feeds.dart'; -import 'package:test/test.dart'; -import '../test_utils.dart'; +import 'package:stream_feeds_test/stream_feeds_test.dart'; void main() { // ============================================================ diff --git a/packages/stream_feeds/test/state/feed_test.dart b/packages/stream_feeds/test/state/feed_test.dart index 7bd2eb3e..89b3a3d9 100644 --- a/packages/stream_feeds/test/state/feed_test.dart +++ b/packages/stream_feeds/test/state/feed_test.dart @@ -1,11 +1,9 @@ // ignore_for_file: avoid_redundant_argument_values -import 'package:mocktail/mocktail.dart'; import 'package:stream_feeds/src/utils/filter.dart'; import 'package:stream_feeds/stream_feeds.dart'; -import 'package:test/test.dart'; -import '../test_utils.dart'; +import 'package:stream_feeds_test/stream_feeds_test.dart'; void main() { // ============================================================ @@ -1815,17 +1813,18 @@ void main() { group('OnNewActivity', () { const feedId = FeedId(group: 'user', id: 'john'); - const currentUserId = 'luke_skywalker'; - const otherUserId = 'other_user'; + const currentUser = User(id: 'luke_skywalker'); + const otherUser = User(id: 'other_user'); final initialActivities = [ - createDefaultActivityResponse(id: 'activity-1', userId: currentUserId), - createDefaultActivityResponse(id: 'activity-2', userId: currentUserId), - createDefaultActivityResponse(id: 'activity-3', userId: otherUserId), + createDefaultActivityResponse(id: 'activity-1', userId: currentUser.id), + createDefaultActivityResponse(id: 'activity-2', userId: currentUser.id), + createDefaultActivityResponse(id: 'activity-3', userId: otherUser.id), ]; feedTest( 'defaultOnNewActivity - should add current user activity to start when matching filter', + user: currentUser, build: (client) => client.feedFromQuery( FeedQuery( fid: feedId, @@ -1850,7 +1849,7 @@ void main() { fid: feedId.rawValue, activity: createDefaultActivityResponse( id: 'activity-4', - userId: currentUserId, + userId: currentUser.id, type: 'post', ), ), @@ -1863,6 +1862,7 @@ void main() { feedTest( 'defaultOnNewActivity - should ignore activity from other user', + user: currentUser, build: (client) => client.feedFromQuery( FeedQuery( fid: feedId, @@ -1887,7 +1887,7 @@ void main() { fid: feedId.rawValue, activity: createDefaultActivityResponse( id: 'activity-4', - userId: otherUserId, + userId: otherUser.id, type: 'post', ), ), @@ -1899,6 +1899,7 @@ void main() { feedTest( 'defaultOnNewActivity - should ignore current user activity that does not match filter', + user: currentUser, build: (client) => client.feedFromQuery( FeedQuery( fid: feedId, @@ -1923,7 +1924,7 @@ void main() { fid: feedId.rawValue, activity: createDefaultActivityResponse( id: 'activity-4', - userId: currentUserId, + userId: currentUser.id, type: 'comment', // Doesn't match 'post' filter ), ), @@ -1935,6 +1936,7 @@ void main() { feedTest( 'custom onNewActivity - should add to start', + user: currentUser, build: (client) => client.feedFromQuery( const FeedQuery(fid: feedId), onNewActivity: (query, activity, currentUserId) { @@ -1957,7 +1959,7 @@ void main() { fid: feedId.rawValue, activity: createDefaultActivityResponse( id: 'activity-4', - userId: otherUserId, + userId: otherUser.id, ), ), ); @@ -1969,6 +1971,7 @@ void main() { feedTest( 'custom onNewActivity - should add to end', + user: currentUser, build: (client) => client.feedFromQuery( const FeedQuery(fid: feedId), onNewActivity: (query, activity, currentUserId) { @@ -1991,7 +1994,7 @@ void main() { fid: feedId.rawValue, activity: createDefaultActivityResponse( id: 'activity-4', - userId: otherUserId, + userId: otherUser.id, ), ), ); @@ -2003,6 +2006,7 @@ void main() { feedTest( 'custom onNewActivity - should ignore', + user: currentUser, build: (client) => client.feedFromQuery( const FeedQuery(fid: feedId), onNewActivity: (query, activity, currentUserId) { @@ -2025,7 +2029,7 @@ void main() { fid: feedId.rawValue, activity: createDefaultActivityResponse( id: 'activity-4', - userId: currentUserId, + userId: currentUser.id, ), ), ); @@ -2036,6 +2040,7 @@ void main() { feedTest( 'custom onNewActivity - should use query and activity context', + user: currentUser, build: (client) => client.feedFromQuery( FeedQuery( fid: feedId, @@ -2069,7 +2074,7 @@ void main() { fid: feedId.rawValue, activity: createDefaultActivityResponse( id: 'activity-4', - userId: otherUserId, + userId: otherUser.id, type: 'post', ), ), @@ -2087,7 +2092,7 @@ void main() { fid: feedId.rawValue, activity: createDefaultActivityResponse( id: 'activity-5', - userId: otherUserId, + userId: otherUser.id, type: 'comment', // Doesn't match 'post' filter ), ), diff --git a/packages/stream_feeds/test/state/follow_list_test.dart b/packages/stream_feeds/test/state/follow_list_test.dart index 5ff17d33..ea270d84 100644 --- a/packages/stream_feeds/test/state/follow_list_test.dart +++ b/packages/stream_feeds/test/state/follow_list_test.dart @@ -1,7 +1,6 @@ import 'package:stream_feeds/stream_feeds.dart'; -import 'package:test/test.dart'; -import '../test_utils.dart'; +import 'package:stream_feeds_test/stream_feeds_test.dart'; void main() { // ============================================================ diff --git a/packages/stream_feeds/test/state/poll_list_test.dart b/packages/stream_feeds/test/state/poll_list_test.dart index dc14edf6..5258d76b 100644 --- a/packages/stream_feeds/test/state/poll_list_test.dart +++ b/packages/stream_feeds/test/state/poll_list_test.dart @@ -1,7 +1,6 @@ import 'package:stream_feeds/stream_feeds.dart'; -import 'package:test/test.dart'; -import '../test_utils.dart'; +import 'package:stream_feeds_test/stream_feeds_test.dart'; void main() { // ============================================================ diff --git a/packages/stream_feeds/test/state/poll_vote_list_test.dart b/packages/stream_feeds/test/state/poll_vote_list_test.dart index 68f1fd7e..2f00f6d1 100644 --- a/packages/stream_feeds/test/state/poll_vote_list_test.dart +++ b/packages/stream_feeds/test/state/poll_vote_list_test.dart @@ -1,7 +1,6 @@ import 'package:stream_feeds/stream_feeds.dart'; -import 'package:test/test.dart'; -import '../test_utils.dart'; +import 'package:stream_feeds_test/stream_feeds_test.dart'; void main() { // ============================================================ diff --git a/packages/stream_feeds/test/test_utils.dart b/packages/stream_feeds/test/test_utils.dart deleted file mode 100644 index 5d30c9b8..00000000 --- a/packages/stream_feeds/test/test_utils.dart +++ /dev/null @@ -1,16 +0,0 @@ -export 'test_utils/event_types.dart'; -export 'test_utils/fakes.dart'; -export 'test_utils/mocks.dart'; -export 'test_utils/testers/activity_comment_list_tester.dart'; -export 'test_utils/testers/activity_list_tester.dart'; -export 'test_utils/testers/activity_tester.dart'; -export 'test_utils/testers/bookmark_folder_list_tester.dart'; -export 'test_utils/testers/bookmark_list_tester.dart'; -export 'test_utils/testers/comment_list_tester.dart'; -export 'test_utils/testers/comment_reply_list_tester.dart'; -export 'test_utils/testers/feed_list_tester.dart'; -export 'test_utils/testers/feed_tester.dart'; -export 'test_utils/testers/follow_list_tester.dart'; -export 'test_utils/testers/poll_list_tester.dart'; -export 'test_utils/testers/poll_vote_list_tester.dart'; -export 'test_utils/web_socket_mocks.dart'; diff --git a/packages/stream_feeds/test/test_utils/testers/api_mocker_mixin.dart b/packages/stream_feeds/test/test_utils/testers/api_mocker_mixin.dart deleted file mode 100644 index aa9d7dfd..00000000 --- a/packages/stream_feeds/test/test_utils/testers/api_mocker_mixin.dart +++ /dev/null @@ -1,109 +0,0 @@ -import 'package:mocktail/mocktail.dart'; -import 'package:stream_feeds/stream_feeds.dart'; - -import '../mocks.dart'; - -/// Mixin for test utilities that need to mock and verify API calls. -/// -/// Provides a clean interface for mocking API calls and verifying -/// interactions without exposing the underlying API client. -mixin ApiMockerMixin { - /// The feeds API client used for mocking. - MockDefaultApi get feedsApi; - - /// Sets up a mock API response for the given API call. - /// - /// The API instance is injected into the callback for clean syntax: - /// ```dart - /// activityTest( - /// 'test', - /// build: (client) => client.activity(...), - /// setUp: (tester) async { - /// tester.mockApi( - /// (api) => api.activityFeedback( - /// activityId: 'activity-1', - /// activityFeedbackRequest: request, - /// ), - /// result: createDefaultActivityFeedbackResponse(), - /// ); - /// }, - /// ); - /// ``` - void mockApi( - Future> Function(MockDefaultApi api) apiCall, { - required T result, - }) { - return mockApiResult(apiCall, result: Result.success(result)); - } - - /// Sets up a mock API response with a custom Result. - /// - /// Use this when you need to return a failure: - /// ```dart - /// tester.mockApiResult( - /// (api) => api.addActivity(...), - /// result: Result.failure(NetworkException('Error')), - /// ); - /// ``` - void mockApiResult( - Future> Function(MockDefaultApi api) apiCall, { - required Result result, - }) { - return when( - () => apiCall(feedsApi), - ).thenAnswer((_) async => result); - } - - /// Verifies that an API call was made exactly once. - /// - /// The API instance is injected into the callback: - /// ```dart - /// activityTest( - /// 'test', - /// build: (client) => client.activity(...), - /// body: (tester) async { - /// tester.verifyApi( - /// (api) => api.activityFeedback( - /// activityId: 'activity-1', - /// activityFeedbackRequest: request, - /// ), - /// ); - /// }, - /// ); - /// ``` - void verifyApi( - Future> Function(MockDefaultApi api) apiCall, - ) { - return verifyApiCalled(apiCall, times: 1); - } - - /// Verifies that an API call was made a specific number of times. - /// - /// Use this when you need to verify multiple calls: - /// ```dart - /// tester.verifyApiCalled( - /// (api) => api.addActivity(...), - /// times: 3, - /// ); - /// ``` - void verifyApiCalled( - Future> Function(MockDefaultApi api) apiCall, { - required int times, - }) { - return verify(() => apiCall(feedsApi)).called(times); - } - - /// Verifies that an API call was never made. - /// - /// Use this to ensure an API wasn't called: - /// ```dart - /// tester.verifyNeverCalled( - /// (api) => api.deleteActivity(activityId: 'activity-1'), - /// ); - /// ``` - VerificationResult verifyNeverCalled( - Future> Function(MockDefaultApi api) apiCall, - ) { - return verifyNever(() => apiCall(feedsApi)); - } -} diff --git a/packages/stream_feeds_test/README.md b/packages/stream_feeds_test/README.md new file mode 100644 index 00000000..f05841c3 --- /dev/null +++ b/packages/stream_feeds_test/README.md @@ -0,0 +1,101 @@ +# stream_feeds_test + +Internal BDD-style test helpers and utilities for testing the Stream Feeds SDK. + +## Features + +This package provides: +- **Tester classes** for all state objects (Feed, ActivityList, CommentList, etc.) +- **Mock objects** for API and WebSocket testing +- **Helper functions** for creating test data and responses +- **API mocker mixin** for clean test setup and verification + +## Usage + +Add as a dev dependency in your `pubspec.yaml`: + +```yaml +dev_dependencies: + stream_feeds_test: + path: ../stream_feeds_test +``` + +### Example Test + +```dart +import 'package:stream_feeds/stream_feeds.dart'; +import 'package:stream_feeds_test/stream_feeds_test.dart'; + +void main() { + group('Feed Operations', () { + feedTest( + 'adds activity successfully', + build: (client) => client.feed(group: 'user', id: 'john'), + setUp: (tester) { + tester.mockApi( + (api) => api.addActivity(addActivityRequest: any(named: 'addActivityRequest')), + result: createDefaultActivityResponse(id: 'new-activity'), + ); + }, + body: (tester) async { + final result = await tester.feed.addActivity( + FeedAddActivityRequest(verb: 'post', object: 'picture:1'), + ); + + expect(result, isA>()); + expect(result.getOrThrow().id, 'new-activity'); + }, + verify: (tester) { + tester.verifyApi( + (api) => api.addActivity(addActivityRequest: any(named: 'addActivityRequest')), + ); + }, + ); + }); +} +``` + +## Available Testers + +- `feedTest` - For Feed operations +- `activityTest` - For Activity operations +- `activityListTest` - For ActivityList operations +- `activityCommentListTest` - For ActivityCommentList operations +- `commentListTest` - For CommentList operations +- `commentReplyListTest` - For CommentReplyList operations +- `feedListTest` - For FeedList operations +- `followListTest` - For FollowList operations +- `bookmarkListTest` - For BookmarkList operations +- `bookmarkFolderListTest` - For BookmarkFolderList operations +- `pollListTest` - For PollList operations +- `pollVoteListTest` - For PollVoteList operations + +## Helper Functions + +All test data factories from `test_data.dart` are available for creating mock responses: +- `createDefaultActivityResponse()` +- `createDefaultGetOrCreateFeedResponse()` +- `createDefaultCommentResponse()` +- And many more... + +## API Mocking + +Use the `ApiMockerMixin` methods in your testers: +- `mockApi()` - Set up a successful API response +- `mockApiResult()` - Set up a custom Result (success or failure) +- `verifyApi()` - Verify an API call was made once +- `verifyApiCalled()` - Verify an API call was made N times +- `verifyNeverCalled()` - Verify an API call was never made + +## WebSocket Testing + +Emit WebSocket events in your tests: + +```dart +await tester.emitEvent(ActivityAddedFeedEvent(...)); +await tester.pump(); // Wait for event processing +``` + +## License + +Internal package - not for public distribution. diff --git a/packages/stream_feeds_test/analysis_options.yaml b/packages/stream_feeds_test/analysis_options.yaml new file mode 100644 index 00000000..192f3dbb --- /dev/null +++ b/packages/stream_feeds_test/analysis_options.yaml @@ -0,0 +1,8 @@ +include: ../../analysis_options.yaml + +analyzer: + errors: + # Allow accessing @internal and @visibleForTesting members in test utilities + invalid_use_of_internal_member: ignore + invalid_use_of_visible_for_testing_member: ignore + invalid_use_of_protected_member: ignore diff --git a/packages/stream_feeds_test/example/stream_feeds_test_example.dart b/packages/stream_feeds_test/example/stream_feeds_test_example.dart new file mode 100644 index 00000000..1cf58a5c --- /dev/null +++ b/packages/stream_feeds_test/example/stream_feeds_test_example.dart @@ -0,0 +1,50 @@ +// ignore_for_file: avoid_redundant_argument_values + +import 'package:stream_feeds/stream_feeds.dart'; +import 'package:stream_feeds_test/stream_feeds_test.dart'; + +void main() { + group('Feed Operations Example', () { + feedTest( + 'gets or creates a feed', + build: (client) => client.feed(group: 'user', id: 'john'), + body: (tester) async { + final result = await tester.getOrCreate(); + + expect(result, isA>()); + final feedData = result.getOrThrow(); + expect(feedData.id, 'id'); + expect(feedData.groupId, 'group'); + }, + ); + + feedTest( + 'adds activity with text content', + build: (client) => client.feed(group: 'user', id: 'john'), + setUp: (tester) { + tester.mockApi( + (api) => api.addActivity( + addActivityRequest: any(named: 'addActivityRequest'), + ), + result: createDefaultActivityResponse( + id: 'new-activity', + type: 'post', + ), + ); + }, + body: (tester) async { + const request = FeedAddActivityRequest( + type: 'post', + text: 'Hello, world!', + custom: {'priority': 'high'}, + ); + + final result = await tester.feed.addActivity(request: request); + + expect(result, isA>()); + expect(result.getOrThrow().id, 'new-activity'); + expect(result.getOrThrow().type, 'post'); + }, + ); + }); +} diff --git a/packages/stream_feeds/test/test_utils/api_mocker_mixin.dart b/packages/stream_feeds_test/lib/src/helpers/api_mocker_mixin.dart similarity index 100% rename from packages/stream_feeds/test/test_utils/api_mocker_mixin.dart rename to packages/stream_feeds_test/lib/src/helpers/api_mocker_mixin.dart diff --git a/packages/stream_feeds/test/test_utils/event_types.dart b/packages/stream_feeds_test/lib/src/helpers/event_types.dart similarity index 100% rename from packages/stream_feeds/test/test_utils/event_types.dart rename to packages/stream_feeds_test/lib/src/helpers/event_types.dart diff --git a/packages/stream_feeds/test/test_utils/mocks.dart b/packages/stream_feeds_test/lib/src/helpers/mocks.dart similarity index 100% rename from packages/stream_feeds/test/test_utils/mocks.dart rename to packages/stream_feeds_test/lib/src/helpers/mocks.dart diff --git a/packages/stream_feeds/test/test_utils/fakes.dart b/packages/stream_feeds_test/lib/src/helpers/test_data.dart similarity index 100% rename from packages/stream_feeds/test/test_utils/fakes.dart rename to packages/stream_feeds_test/lib/src/helpers/test_data.dart diff --git a/packages/stream_feeds/test/test_utils/web_socket_mocks.dart b/packages/stream_feeds_test/lib/src/helpers/web_socket_mocks.dart similarity index 81% rename from packages/stream_feeds/test/test_utils/web_socket_mocks.dart rename to packages/stream_feeds_test/lib/src/helpers/web_socket_mocks.dart index f4ee984c..f41fbb76 100644 --- a/packages/stream_feeds/test/test_utils/web_socket_mocks.dart +++ b/packages/stream_feeds_test/lib/src/helpers/web_socket_mocks.dart @@ -2,7 +2,6 @@ import 'dart:async'; import 'dart:convert'; import 'package:mocktail/mocktail.dart'; -import 'package:stream_feeds/src/ws/events/events.dart'; import 'mocks.dart'; @@ -51,15 +50,18 @@ void whenListenWebSocket( if (event['token'] != null) { return wsStreamController.add( - jsonEncode( - HealthCheckEvent( - connectionId: 'connectionId', - createdAt: DateTime.now(), - custom: const {}, - type: 'health.check', - ), - ), + jsonEncode(_createHealthCheckEvent()), ); } }); } + +/// Creates a health check event for WebSocket authentication. +Map _createHealthCheckEvent() { + return { + 'type': 'health.check', + 'connection_id': 'connectionId', + 'created_at': DateTime.now().millisecondsSinceEpoch, + 'custom': {}, + }; +} diff --git a/packages/stream_feeds/test/test_utils/testers/activity_comment_list_tester.dart b/packages/stream_feeds_test/lib/src/testers/activity_comment_list_tester.dart similarity index 96% rename from packages/stream_feeds/test/test_utils/testers/activity_comment_list_tester.dart rename to packages/stream_feeds_test/lib/src/testers/activity_comment_list_tester.dart index a6786212..2b1d57b4 100644 --- a/packages/stream_feeds/test/test_utils/testers/activity_comment_list_tester.dart +++ b/packages/stream_feeds_test/lib/src/testers/activity_comment_list_tester.dart @@ -4,8 +4,8 @@ import 'package:meta/meta.dart'; import 'package:stream_feeds/stream_feeds.dart'; import 'package:test/test.dart' as test; -import '../fakes.dart'; -import '../mocks.dart'; +import '../helpers/mocks.dart'; +import '../helpers/test_data.dart'; import 'base_tester.dart'; /// Test helper for activity comment list operations. @@ -13,6 +13,8 @@ import 'base_tester.dart'; /// Automatically sets up WebSocket connection, client, and test infrastructure. /// Tests are tagged with 'activity-comment-list' by default for filtering. /// +/// [user] is optional, the authenticated user for the test client (defaults to luke_skywalker). + /// [build] constructs the [ActivityCommentList] under test using the provided [StreamFeedsClient]. /// [setUp] is optional and runs before [body] for setting up mocks and test state. /// [body] is the test callback that receives an [ActivityCommentListTester] for interactions. @@ -41,6 +43,7 @@ import 'base_tester.dart'; @isTest void activityCommentListTest( String description, { + User user = const User(id: 'luke_skywalker'), required ActivityCommentList Function(StreamFeedsClient client) build, FutureOr Function(ActivityCommentListTester tester)? setUp, required FutureOr Function(ActivityCommentListTester tester) body, @@ -52,6 +55,7 @@ void activityCommentListTest( }) { return testWithTester( description, + user: user, build: build, createTesterFn: _createActivityCommentListTester, setUp: setUp, diff --git a/packages/stream_feeds/test/test_utils/testers/activity_list_tester.dart b/packages/stream_feeds_test/lib/src/testers/activity_list_tester.dart similarity index 95% rename from packages/stream_feeds/test/test_utils/testers/activity_list_tester.dart rename to packages/stream_feeds_test/lib/src/testers/activity_list_tester.dart index 005e48fa..1fd69202 100644 --- a/packages/stream_feeds/test/test_utils/testers/activity_list_tester.dart +++ b/packages/stream_feeds_test/lib/src/testers/activity_list_tester.dart @@ -4,8 +4,8 @@ import 'package:meta/meta.dart'; import 'package:stream_feeds/stream_feeds.dart'; import 'package:test/test.dart' as test; -import '../fakes.dart'; -import '../mocks.dart'; +import '../helpers/mocks.dart'; +import '../helpers/test_data.dart'; import 'base_tester.dart'; /// Test helper for activity list operations. @@ -13,6 +13,8 @@ import 'base_tester.dart'; /// Automatically sets up WebSocket connection, client, and test infrastructure. /// Tests are tagged with 'activity-list' by default for filtering. /// +/// [user] is optional, the authenticated user for the test client (defaults to luke_skywalker). + /// [build] constructs the [ActivityList] under test using the provided [StreamFeedsClient]. /// [setUp] is optional and runs before [body] for setting up mocks and test state. /// [body] is the test callback that receives an [ActivityListTester] for interactions. @@ -45,6 +47,7 @@ import 'base_tester.dart'; @isTest void activityListTest( String description, { + User user = const User(id: 'luke_skywalker'), required ActivityList Function(StreamFeedsClient client) build, FutureOr Function(ActivityListTester tester)? setUp, required FutureOr Function(ActivityListTester tester) body, @@ -56,6 +59,7 @@ void activityListTest( }) { return testWithTester( description, + user: user, build: build, createTesterFn: _createActivityListTester, setUp: setUp, diff --git a/packages/stream_feeds/test/test_utils/testers/activity_tester.dart b/packages/stream_feeds_test/lib/src/testers/activity_tester.dart similarity index 96% rename from packages/stream_feeds/test/test_utils/testers/activity_tester.dart rename to packages/stream_feeds_test/lib/src/testers/activity_tester.dart index 3f38b38a..99d2dd88 100644 --- a/packages/stream_feeds/test/test_utils/testers/activity_tester.dart +++ b/packages/stream_feeds_test/lib/src/testers/activity_tester.dart @@ -4,8 +4,8 @@ import 'package:meta/meta.dart'; import 'package:stream_feeds/stream_feeds.dart'; import 'package:test/test.dart' as test; -import '../fakes.dart'; -import '../mocks.dart'; +import '../helpers/mocks.dart'; +import '../helpers/test_data.dart'; import 'base_tester.dart'; /// Test helper for activity operations. @@ -13,6 +13,8 @@ import 'base_tester.dart'; /// Automatically sets up WebSocket connection, client, and test infrastructure. /// Tests are tagged with 'activity' by default for filtering. /// +/// [user] is optional, the authenticated user for the test client (defaults to luke_skywalker). + /// [build] constructs the [Activity] under test using the provided [StreamFeedsClient]. /// [setUp] is optional and runs before [body] for setting up mocks and test state. /// [body] is the test callback that receives an [ActivityTester] for interactions. @@ -80,6 +82,7 @@ import 'base_tester.dart'; @isTest void activityTest( String description, { + User user = const User(id: 'luke_skywalker'), required Activity Function(StreamFeedsClient client) build, FutureOr Function(ActivityTester tester)? setUp, required FutureOr Function(ActivityTester tester) body, @@ -91,6 +94,7 @@ void activityTest( }) { return testWithTester( description, + user: user, build: build, createTesterFn: _createActivityTester, setUp: setUp, diff --git a/packages/stream_feeds/test/test_utils/testers/base_tester.dart b/packages/stream_feeds_test/lib/src/testers/base_tester.dart similarity index 94% rename from packages/stream_feeds/test/test_utils/testers/base_tester.dart rename to packages/stream_feeds_test/lib/src/testers/base_tester.dart index c9f6f827..d1194a8d 100644 --- a/packages/stream_feeds/test/test_utils/testers/base_tester.dart +++ b/packages/stream_feeds_test/lib/src/testers/base_tester.dart @@ -5,9 +5,9 @@ import 'package:meta/meta.dart'; import 'package:stream_feeds/stream_feeds.dart'; import 'package:test/test.dart' as test; -import '../api_mocker_mixin.dart'; -import '../mocks.dart'; -import '../web_socket_mocks.dart'; +import '../helpers/api_mocker_mixin.dart'; +import '../helpers/mocks.dart'; +import '../helpers/web_socket_mocks.dart'; /// Factory function signature for creating tester instances. /// @@ -100,6 +100,7 @@ Future createTester>({ /// Automatically sets up WebSocket connection, client, and test infrastructure. /// /// Parameters: +/// - user: the authenticated user for the test client (defaults to luke_skywalker) /// - build: constructs the subject under test using the provided StreamFeedsClient /// - createTesterFn: the concrete tester factory function /// - setUp: optional, runs before body for setting up mocks and test state @@ -113,6 +114,7 @@ Future createTester>({ /// This function is for internal use by concrete test helpers. void testWithTester>( String description, { + User user = const User(id: 'luke_skywalker'), required S Function(StreamFeedsClient client) build, required TesterFactory createTesterFn, FutureOr Function(T tester)? setUp, @@ -130,16 +132,15 @@ void testWithTester>( timeout: timeout, () async { await _runZonedGuarded(() async { - const user = User(id: 'luke_skywalker'); - final userToken = generateTestUserToken(user.id); - final feedsApi = MockDefaultApi(); final webSocketChannel = MockWebSocketChannel(); final client = StreamFeedsClient( apiKey: 'apiKey', user: user, - tokenProvider: TokenProvider.static(userToken), + tokenProvider: TokenProvider.static( + generateTestUserToken(user.id), + ), feedsRestApi: feedsApi, wsProvider: (options) => webSocketChannel, ); diff --git a/packages/stream_feeds/test/test_utils/testers/bookmark_folder_list_tester.dart b/packages/stream_feeds_test/lib/src/testers/bookmark_folder_list_tester.dart similarity index 95% rename from packages/stream_feeds/test/test_utils/testers/bookmark_folder_list_tester.dart rename to packages/stream_feeds_test/lib/src/testers/bookmark_folder_list_tester.dart index da3de8c8..1e44c546 100644 --- a/packages/stream_feeds/test/test_utils/testers/bookmark_folder_list_tester.dart +++ b/packages/stream_feeds_test/lib/src/testers/bookmark_folder_list_tester.dart @@ -4,8 +4,8 @@ import 'package:meta/meta.dart'; import 'package:stream_feeds/stream_feeds.dart'; import 'package:test/test.dart' as test; -import '../fakes.dart'; -import '../mocks.dart'; +import '../helpers/mocks.dart'; +import '../helpers/test_data.dart'; import 'base_tester.dart'; /// Test helper for bookmark folder list operations. @@ -13,6 +13,8 @@ import 'base_tester.dart'; /// Automatically sets up WebSocket connection, client, and test infrastructure. /// Tests are tagged with 'bookmark-folder-list' by default for filtering. /// +/// [user] is optional, the authenticated user for the test client (defaults to luke_skywalker). + /// [build] constructs the [BookmarkFolderList] under test using the provided [StreamFeedsClient]. /// [setUp] is optional and runs before [body] for setting up mocks and test state. /// [body] is the test callback that receives a [BookmarkFolderListTester] for interactions. @@ -40,6 +42,7 @@ import 'base_tester.dart'; @isTest void bookmarkFolderListTest( String description, { + User user = const User(id: 'luke_skywalker'), required BookmarkFolderList Function(StreamFeedsClient client) build, FutureOr Function(BookmarkFolderListTester tester)? setUp, required FutureOr Function(BookmarkFolderListTester tester) body, @@ -51,6 +54,7 @@ void bookmarkFolderListTest( }) { return testWithTester( description, + user: user, build: build, createTesterFn: _createBookmarkFolderListTester, setUp: setUp, diff --git a/packages/stream_feeds/test/test_utils/testers/bookmark_list_tester.dart b/packages/stream_feeds_test/lib/src/testers/bookmark_list_tester.dart similarity index 95% rename from packages/stream_feeds/test/test_utils/testers/bookmark_list_tester.dart rename to packages/stream_feeds_test/lib/src/testers/bookmark_list_tester.dart index 87380a40..9a2aa6a2 100644 --- a/packages/stream_feeds/test/test_utils/testers/bookmark_list_tester.dart +++ b/packages/stream_feeds_test/lib/src/testers/bookmark_list_tester.dart @@ -4,8 +4,8 @@ import 'package:meta/meta.dart'; import 'package:stream_feeds/stream_feeds.dart'; import 'package:test/test.dart' as test; -import '../fakes.dart'; -import '../mocks.dart'; +import '../helpers/mocks.dart'; +import '../helpers/test_data.dart'; import 'base_tester.dart'; /// Test helper for bookmark list operations. @@ -13,6 +13,8 @@ import 'base_tester.dart'; /// Automatically sets up WebSocket connection, client, and test infrastructure. /// Tests are tagged with 'bookmark-list' by default for filtering. /// +/// [user] is optional, the authenticated user for the test client (defaults to luke_skywalker). + /// [build] constructs the [BookmarkList] under test using the provided [StreamFeedsClient]. /// [setUp] is optional and runs before [body] for setting up mocks and test state. /// [body] is the test callback that receives a [BookmarkListTester] for interactions. @@ -40,6 +42,7 @@ import 'base_tester.dart'; @isTest void bookmarkListTest( String description, { + User user = const User(id: 'luke_skywalker'), required BookmarkList Function(StreamFeedsClient client) build, FutureOr Function(BookmarkListTester tester)? setUp, required FutureOr Function(BookmarkListTester tester) body, @@ -51,6 +54,7 @@ void bookmarkListTest( }) { return testWithTester( description, + user: user, build: build, createTesterFn: _createBookmarkListTester, setUp: setUp, diff --git a/packages/stream_feeds/test/test_utils/testers/comment_list_tester.dart b/packages/stream_feeds_test/lib/src/testers/comment_list_tester.dart similarity index 95% rename from packages/stream_feeds/test/test_utils/testers/comment_list_tester.dart rename to packages/stream_feeds_test/lib/src/testers/comment_list_tester.dart index 880d1fa4..627257d3 100644 --- a/packages/stream_feeds/test/test_utils/testers/comment_list_tester.dart +++ b/packages/stream_feeds_test/lib/src/testers/comment_list_tester.dart @@ -4,8 +4,8 @@ import 'package:meta/meta.dart'; import 'package:stream_feeds/stream_feeds.dart'; import 'package:test/test.dart' as test; -import '../fakes.dart'; -import '../mocks.dart'; +import '../helpers/mocks.dart'; +import '../helpers/test_data.dart'; import 'base_tester.dart'; /// Test helper for comment list operations. @@ -13,6 +13,8 @@ import 'base_tester.dart'; /// Automatically sets up WebSocket connection, client, and test infrastructure. /// Tests are tagged with 'comment-list' by default for filtering. /// +/// [user] is optional, the authenticated user for the test client (defaults to luke_skywalker). + /// [build] constructs the [CommentList] under test using the provided [StreamFeedsClient]. /// [setUp] is optional and runs before [body] for setting up mocks and test state. /// [body] is the test callback that receives a [CommentListTester] for interactions. @@ -40,6 +42,7 @@ import 'base_tester.dart'; @isTest void commentListTest( String description, { + User user = const User(id: 'luke_skywalker'), required CommentList Function(StreamFeedsClient client) build, FutureOr Function(CommentListTester tester)? setUp, required FutureOr Function(CommentListTester tester) body, @@ -51,6 +54,7 @@ void commentListTest( }) { return testWithTester( description, + user: user, build: build, createTesterFn: _createCommentListTester, setUp: setUp, diff --git a/packages/stream_feeds/test/test_utils/testers/comment_reply_list_tester.dart b/packages/stream_feeds_test/lib/src/testers/comment_reply_list_tester.dart similarity index 94% rename from packages/stream_feeds/test/test_utils/testers/comment_reply_list_tester.dart rename to packages/stream_feeds_test/lib/src/testers/comment_reply_list_tester.dart index 3a823a02..8987e80b 100644 --- a/packages/stream_feeds/test/test_utils/testers/comment_reply_list_tester.dart +++ b/packages/stream_feeds_test/lib/src/testers/comment_reply_list_tester.dart @@ -4,8 +4,8 @@ import 'package:meta/meta.dart'; import 'package:stream_feeds/stream_feeds.dart'; import 'package:test/test.dart' as test; -import '../fakes.dart'; -import '../mocks.dart'; +import '../helpers/mocks.dart'; +import '../helpers/test_data.dart'; import 'base_tester.dart'; /// Test helper for comment reply list operations. @@ -13,6 +13,8 @@ import 'base_tester.dart'; /// Automatically sets up WebSocket connection, client, and test infrastructure. /// Tests are tagged with 'comment-reply-list' by default for filtering. /// +/// [user] is optional, the authenticated user for the test client (defaults to luke_skywalker). + /// [build] constructs the [CommentReplyList] under test using the provided [StreamFeedsClient]. /// [setUp] is optional and runs before [body] for setting up mocks and test state. /// [body] is the test callback that receives a [CommentReplyListTester] for interactions. @@ -42,6 +44,7 @@ import 'base_tester.dart'; @isTest void commentReplyListTest( String description, { + User user = const User(id: 'luke_skywalker'), required CommentReplyList Function(StreamFeedsClient client) build, FutureOr Function(CommentReplyListTester tester)? setUp, required FutureOr Function(CommentReplyListTester tester) body, @@ -53,6 +56,7 @@ void commentReplyListTest( }) { return testWithTester( description, + user: user, build: build, createTesterFn: _createCommentReplyListTester, setUp: setUp, @@ -98,8 +102,9 @@ final class CommentReplyListTester extends BaseTester { /// Parameters: /// - [modifyResponse]: Optional function to customize the comment replies response Future>> get({ - GetCommentRepliesResponse Function(GetCommentRepliesResponse)? - modifyResponse, + GetCommentRepliesResponse Function( + GetCommentRepliesResponse, + )? modifyResponse, }) { final query = commentReplyList.query; diff --git a/packages/stream_feeds/test/test_utils/testers/feed_list_tester.dart b/packages/stream_feeds_test/lib/src/testers/feed_list_tester.dart similarity index 95% rename from packages/stream_feeds/test/test_utils/testers/feed_list_tester.dart rename to packages/stream_feeds_test/lib/src/testers/feed_list_tester.dart index 393bd812..820b8aab 100644 --- a/packages/stream_feeds/test/test_utils/testers/feed_list_tester.dart +++ b/packages/stream_feeds_test/lib/src/testers/feed_list_tester.dart @@ -4,8 +4,8 @@ import 'package:meta/meta.dart'; import 'package:stream_feeds/stream_feeds.dart'; import 'package:test/test.dart' as test; -import '../fakes.dart'; -import '../mocks.dart'; +import '../helpers/mocks.dart'; +import '../helpers/test_data.dart'; import 'base_tester.dart'; /// Test helper for feed list operations. @@ -13,6 +13,8 @@ import 'base_tester.dart'; /// Automatically sets up WebSocket connection, client, and test infrastructure. /// Tests are tagged with 'feed-list' by default for filtering. /// +/// [user] is optional, the authenticated user for the test client (defaults to luke_skywalker). + /// [build] constructs the [FeedList] under test using the provided [StreamFeedsClient]. /// [setUp] is optional and runs before [body] for setting up mocks and test state. /// [body] is the test callback that receives a [FeedListTester] for interactions. @@ -40,6 +42,7 @@ import 'base_tester.dart'; @isTest void feedListTest( String description, { + User user = const User(id: 'luke_skywalker'), required FeedList Function(StreamFeedsClient client) build, FutureOr Function(FeedListTester tester)? setUp, required FutureOr Function(FeedListTester tester) body, @@ -51,6 +54,7 @@ void feedListTest( }) { return testWithTester( description, + user: user, build: build, createTesterFn: _createFeedListTester, setUp: setUp, diff --git a/packages/stream_feeds/test/test_utils/testers/feed_tester.dart b/packages/stream_feeds_test/lib/src/testers/feed_tester.dart similarity index 95% rename from packages/stream_feeds/test/test_utils/testers/feed_tester.dart rename to packages/stream_feeds_test/lib/src/testers/feed_tester.dart index 0746e55c..fa3988e5 100644 --- a/packages/stream_feeds/test/test_utils/testers/feed_tester.dart +++ b/packages/stream_feeds_test/lib/src/testers/feed_tester.dart @@ -4,8 +4,8 @@ import 'package:meta/meta.dart'; import 'package:stream_feeds/stream_feeds.dart'; import 'package:test/test.dart' as test; -import '../fakes.dart'; -import '../mocks.dart'; +import '../helpers/mocks.dart'; +import '../helpers/test_data.dart'; import 'base_tester.dart'; /// Test helper for feed operations. @@ -13,6 +13,8 @@ import 'base_tester.dart'; /// Automatically sets up WebSocket connection, client, and test infrastructure. /// Tests are tagged with 'feed' by default for filtering. /// +/// [user] is optional, the authenticated user for the test client (defaults to luke_skywalker). + /// [build] constructs the [Feed] under test using the provided [StreamFeedsClient]. /// [setUp] is optional and runs before [body] for setting up mocks and test state. /// [body] is the test callback that receives a [FeedTester] for interactions. @@ -45,6 +47,7 @@ import 'base_tester.dart'; @isTest void feedTest( String description, { + User user = const User(id: 'luke_skywalker'), required Feed Function(StreamFeedsClient client) build, FutureOr Function(FeedTester tester)? setUp, required FutureOr Function(FeedTester tester) body, @@ -56,6 +59,7 @@ void feedTest( }) { return testWithTester( description, + user: user, build: build, createTesterFn: _createFeedTester, setUp: setUp, diff --git a/packages/stream_feeds/test/test_utils/testers/follow_list_tester.dart b/packages/stream_feeds_test/lib/src/testers/follow_list_tester.dart similarity index 95% rename from packages/stream_feeds/test/test_utils/testers/follow_list_tester.dart rename to packages/stream_feeds_test/lib/src/testers/follow_list_tester.dart index bb8d4b0f..c6355da5 100644 --- a/packages/stream_feeds/test/test_utils/testers/follow_list_tester.dart +++ b/packages/stream_feeds_test/lib/src/testers/follow_list_tester.dart @@ -4,8 +4,8 @@ import 'package:meta/meta.dart'; import 'package:stream_feeds/stream_feeds.dart'; import 'package:test/test.dart' as test; -import '../fakes.dart'; -import '../mocks.dart'; +import '../helpers/mocks.dart'; +import '../helpers/test_data.dart'; import 'base_tester.dart'; /// Test helper for follow list operations. @@ -13,6 +13,8 @@ import 'base_tester.dart'; /// Automatically sets up WebSocket connection, client, and test infrastructure. /// Tests are tagged with 'follow-list' by default for filtering. /// +/// [user] is optional, the authenticated user for the test client (defaults to luke_skywalker). + /// [build] constructs the [FollowList] under test using the provided [StreamFeedsClient]. /// [setUp] is optional and runs before [body] for setting up mocks and test state. /// [body] is the test callback that receives a [FollowListTester] for interactions. @@ -40,6 +42,7 @@ import 'base_tester.dart'; @isTest void followListTest( String description, { + User user = const User(id: 'luke_skywalker'), required FollowList Function(StreamFeedsClient client) build, FutureOr Function(FollowListTester tester)? setUp, required FutureOr Function(FollowListTester tester) body, @@ -51,6 +54,7 @@ void followListTest( }) { return testWithTester( description, + user: user, build: build, createTesterFn: _createFollowListTester, setUp: setUp, diff --git a/packages/stream_feeds/test/test_utils/testers/poll_list_tester.dart b/packages/stream_feeds_test/lib/src/testers/poll_list_tester.dart similarity index 95% rename from packages/stream_feeds/test/test_utils/testers/poll_list_tester.dart rename to packages/stream_feeds_test/lib/src/testers/poll_list_tester.dart index c7279c9f..8d7d63ec 100644 --- a/packages/stream_feeds/test/test_utils/testers/poll_list_tester.dart +++ b/packages/stream_feeds_test/lib/src/testers/poll_list_tester.dart @@ -4,8 +4,8 @@ import 'package:meta/meta.dart'; import 'package:stream_feeds/stream_feeds.dart'; import 'package:test/test.dart' as test; -import '../fakes.dart'; -import '../mocks.dart'; +import '../helpers/mocks.dart'; +import '../helpers/test_data.dart'; import 'base_tester.dart'; /// Test helper for poll list operations. @@ -13,6 +13,8 @@ import 'base_tester.dart'; /// Automatically sets up WebSocket connection, client, and test infrastructure. /// Tests are tagged with 'poll-list' by default for filtering. /// +/// [user] is optional, the authenticated user for the test client (defaults to luke_skywalker). + /// [build] constructs the [PollList] under test using the provided [StreamFeedsClient]. /// [setUp] is optional and runs before [body] for setting up mocks and test state. /// [body] is the test callback that receives a [PollListTester] for interactions. @@ -40,6 +42,7 @@ import 'base_tester.dart'; @isTest void pollListTest( String description, { + User user = const User(id: 'luke_skywalker'), required PollList Function(StreamFeedsClient client) build, FutureOr Function(PollListTester tester)? setUp, required FutureOr Function(PollListTester tester) body, @@ -51,6 +54,7 @@ void pollListTest( }) { return testWithTester( description, + user: user, build: build, createTesterFn: _createPollListTester, setUp: setUp, diff --git a/packages/stream_feeds/test/test_utils/testers/poll_vote_list_tester.dart b/packages/stream_feeds_test/lib/src/testers/poll_vote_list_tester.dart similarity index 95% rename from packages/stream_feeds/test/test_utils/testers/poll_vote_list_tester.dart rename to packages/stream_feeds_test/lib/src/testers/poll_vote_list_tester.dart index a55a4ebc..b5938455 100644 --- a/packages/stream_feeds/test/test_utils/testers/poll_vote_list_tester.dart +++ b/packages/stream_feeds_test/lib/src/testers/poll_vote_list_tester.dart @@ -4,8 +4,8 @@ import 'package:meta/meta.dart'; import 'package:stream_feeds/stream_feeds.dart'; import 'package:test/test.dart' as test; -import '../fakes.dart'; -import '../mocks.dart'; +import '../helpers/mocks.dart'; +import '../helpers/test_data.dart'; import 'base_tester.dart'; /// Test helper for poll vote list operations. @@ -13,6 +13,8 @@ import 'base_tester.dart'; /// Automatically sets up WebSocket connection, client, and test infrastructure. /// Tests are tagged with 'poll-vote-list' by default for filtering. /// +/// [user] is optional, the authenticated user for the test client (defaults to luke_skywalker). + /// [build] constructs the [PollVoteList] under test using the provided [StreamFeedsClient]. /// [setUp] is optional and runs before [body] for setting up mocks and test state. /// [body] is the test callback that receives a [PollVoteListTester] for interactions. @@ -40,6 +42,7 @@ import 'base_tester.dart'; @isTest void pollVoteListTest( String description, { + User user = const User(id: 'luke_skywalker'), required PollVoteList Function(StreamFeedsClient client) build, FutureOr Function(PollVoteListTester tester)? setUp, required FutureOr Function(PollVoteListTester tester) body, @@ -51,6 +54,7 @@ void pollVoteListTest( }) { return testWithTester( description, + user: user, build: build, createTesterFn: _createPollVoteListTester, setUp: setUp, diff --git a/packages/stream_feeds_test/lib/stream_feeds_test.dart b/packages/stream_feeds_test/lib/stream_feeds_test.dart new file mode 100644 index 00000000..ff013da2 --- /dev/null +++ b/packages/stream_feeds_test/lib/stream_feeds_test.dart @@ -0,0 +1,37 @@ +/// BDD-style test helpers and utilities for Stream Feeds SDK testing. +/// +/// This library provides test utilities including: +/// - Tester classes for state objects (Feed, ActivityList, etc.) +/// - Mock objects for API and WebSocket testing +/// - Helper functions for creating test data +/// - API mocker mixin for clean test setup +/// +/// Re-exports `package:test/test.dart` and `package:mocktail/mocktail.dart` +/// for convenience - only one import needed in test files. +library; + +// Re-export test framework and mocking library +export 'package:mocktail/mocktail.dart'; +export 'package:test/test.dart'; + +// Helpers +export 'src/helpers/api_mocker_mixin.dart'; +export 'src/helpers/event_types.dart'; +export 'src/helpers/mocks.dart'; +export 'src/helpers/test_data.dart'; +export 'src/helpers/web_socket_mocks.dart'; + +// Testers +export 'src/testers/activity_comment_list_tester.dart'; +export 'src/testers/activity_list_tester.dart'; +export 'src/testers/activity_tester.dart'; +export 'src/testers/base_tester.dart'; +export 'src/testers/bookmark_folder_list_tester.dart'; +export 'src/testers/bookmark_list_tester.dart'; +export 'src/testers/comment_list_tester.dart'; +export 'src/testers/comment_reply_list_tester.dart'; +export 'src/testers/feed_list_tester.dart'; +export 'src/testers/feed_tester.dart'; +export 'src/testers/follow_list_tester.dart'; +export 'src/testers/poll_list_tester.dart'; +export 'src/testers/poll_vote_list_tester.dart'; diff --git a/packages/stream_feeds_test/pubspec.yaml b/packages/stream_feeds_test/pubspec.yaml new file mode 100644 index 00000000..a95d1a55 --- /dev/null +++ b/packages/stream_feeds_test/pubspec.yaml @@ -0,0 +1,14 @@ +name: stream_feeds_test +description: Internal BDD-style test helpers and utilities for Stream Feeds SDK testing. +version: 0.1.0 +publish_to: none # This package is not intended for publishing. + +environment: + sdk: ^3.6.2 + +dependencies: + meta: ^1.9.1 + mocktail: ^1.0.4 + stream_feeds: ^0.4.0 + test: ^1.25.8 + web_socket_channel: ^3.0.1 diff --git a/packages/stream_feeds_test/test/stream_feeds_test_test.dart b/packages/stream_feeds_test/test/stream_feeds_test_test.dart new file mode 100644 index 00000000..15a6460f --- /dev/null +++ b/packages/stream_feeds_test/test/stream_feeds_test_test.dart @@ -0,0 +1,24 @@ +import 'package:stream_feeds_test/stream_feeds_test.dart'; + +void main() { + group('stream_feeds_test', () { + test('re-exports test framework', () { + // Verify test framework functions are available + expect(true, isTrue); + expect(1, equals(1)); + }); + + test('re-exports mocktail', () { + // Verify mocktail functions are available + final mock = MockTestClass(); + when(mock.getValue).thenReturn(42); + expect(mock.getValue(), 42); + verify(mock.getValue).called(1); + }); + }); +} + +// Test mock class for verifying mocktail re-export +class MockTestClass extends Mock { + int getValue(); +}