···
import 'package:coves_flutter/models/post.dart';
2
+
import 'package:coves_flutter/services/streamable_service.dart';
import 'package:coves_flutter/widgets/post_card.dart';
4
+
import 'package:dio/dio.dart';
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
7
+
import 'package:http_mock_adapter/http_mock_adapter.dart';
import 'package:provider/provider.dart';
import '../test_helpers/mock_providers.dart';
···
mockVoteProvider = MockVoteProvider();
18
-
Widget createTestWidget(FeedViewPost post) {
21
+
Widget createTestWidget(
22
+
FeedViewPost post, {
23
+
StreamableService? streamableService,
// ignore: argument_type_not_assignable
ChangeNotifierProvider<MockAuthProvider>.value(value: mockAuthProvider),
// ignore: argument_type_not_assignable
ChangeNotifierProvider<MockVoteProvider>.value(value: mockVoteProvider),
31
+
Provider<StreamableService>.value(
32
+
value: streamableService ?? StreamableService(),
child: MaterialApp(home: Scaffold(body: PostCard(post: post))),
30
-
group('PostCard', skip: 'Provider type compatibility issues - needs mock refactoring', () {
31
-
testWidgets('renders all basic components', (tester) async {
32
-
final post = FeedViewPost(
34
-
uri: 'at://did:example/post/123',
37
-
author: AuthorView(did: 'did:plc:author', handle: 'author.test'),
38
-
community: CommunityRef(
39
-
did: 'did:plc:community',
40
-
name: 'test-community',
42
-
createdAt: DateTime(2024, 1, 1),
43
-
indexedAt: DateTime(2024, 1, 1),
44
-
text: 'Test post content',
45
-
title: 'Test Post Title',
41
+
skip: 'Provider type compatibility issues - needs mock refactoring',
43
+
testWidgets('renders all basic components', (tester) async {
44
+
final post = FeedViewPost(
46
+
uri: 'at://did:example/post/123',
49
+
author: AuthorView(did: 'did:plc:author', handle: 'author.test'),
50
+
community: CommunityRef(
51
+
did: 'did:plc:community',
52
+
name: 'test-community',
54
+
createdAt: DateTime(2024, 1, 1),
55
+
indexedAt: DateTime(2024, 1, 1),
56
+
text: 'Test post content',
57
+
title: 'Test Post Title',
55
-
await tester.pumpWidget(createTestWidget(post));
67
+
await tester.pumpWidget(createTestWidget(post));
57
-
// Verify title is displayed
58
-
expect(find.text('Test Post Title'), findsOneWidget);
69
+
// Verify title is displayed
70
+
expect(find.text('Test Post Title'), findsOneWidget);
60
-
// Verify community name is displayed
61
-
expect(find.text('c/test-community'), findsOneWidget);
72
+
// Verify community name is displayed
73
+
expect(find.text('c/test-community'), findsOneWidget);
63
-
// Verify author handle is displayed
64
-
expect(find.text('@author.test'), findsOneWidget);
75
+
// Verify author handle is displayed
76
+
expect(find.text('@author.test'), findsOneWidget);
66
-
// Verify text content is displayed
67
-
expect(find.text('Test post content'), findsOneWidget);
78
+
// Verify text content is displayed
79
+
expect(find.text('Test post content'), findsOneWidget);
69
-
// Verify stats are displayed
70
-
expect(find.text('8'), findsOneWidget); // score
71
-
expect(find.text('5'), findsOneWidget); // comment count
81
+
// Verify stats are displayed
82
+
expect(find.text('8'), findsOneWidget); // score
83
+
expect(find.text('5'), findsOneWidget); // comment count
74
-
testWidgets('displays community avatar when available', (tester) async {
75
-
final post = FeedViewPost(
77
-
uri: 'at://did:example/post/123',
80
-
author: AuthorView(did: 'did:plc:author', handle: 'author.test'),
81
-
community: CommunityRef(
82
-
did: 'did:plc:community',
83
-
name: 'test-community',
84
-
avatar: 'https://example.com/avatar.jpg',
86
+
testWidgets('displays community avatar when available', (tester) async {
87
+
final post = FeedViewPost(
89
+
uri: 'at://did:example/post/123',
92
+
author: AuthorView(did: 'did:plc:author', handle: 'author.test'),
93
+
community: CommunityRef(
94
+
did: 'did:plc:community',
95
+
name: 'test-community',
96
+
avatar: 'https://example.com/avatar.jpg',
98
+
createdAt: DateTime(2024, 1, 1),
99
+
indexedAt: DateTime(2024, 1, 1),
86
-
createdAt: DateTime(2024, 1, 1),
87
-
indexedAt: DateTime(2024, 1, 1),
89
-
stats: PostStats(upvotes: 0, downvotes: 0, score: 0, commentCount: 0),
93
-
await tester.pumpWidget(createTestWidget(post));
94
-
await tester.pumpAndSettle();
110
+
await tester.pumpWidget(createTestWidget(post));
111
+
await tester.pumpAndSettle();
96
-
// Avatar image should be present
97
-
expect(find.byType(Image), findsWidgets);
113
+
// Avatar image should be present
114
+
expect(find.byType(Image), findsWidgets);
100
-
testWidgets('shows fallback avatar when no avatar URL', (tester) async {
101
-
final post = FeedViewPost(
103
-
uri: 'at://did:example/post/123',
106
-
author: AuthorView(did: 'did:plc:author', handle: 'author.test'),
107
-
community: CommunityRef(
108
-
did: 'did:plc:community',
109
-
name: 'TestCommunity',
117
+
testWidgets('shows fallback avatar when no avatar URL', (tester) async {
118
+
final post = FeedViewPost(
120
+
uri: 'at://did:example/post/123',
123
+
author: AuthorView(did: 'did:plc:author', handle: 'author.test'),
124
+
community: CommunityRef(
125
+
did: 'did:plc:community',
126
+
name: 'TestCommunity',
128
+
createdAt: DateTime(2024, 1, 1),
129
+
indexedAt: DateTime(2024, 1, 1),
111
-
createdAt: DateTime(2024, 1, 1),
112
-
indexedAt: DateTime(2024, 1, 1),
114
-
stats: PostStats(upvotes: 0, downvotes: 0, score: 0, commentCount: 0),
118
-
await tester.pumpWidget(createTestWidget(post));
140
+
await tester.pumpWidget(createTestWidget(post));
120
-
// Verify fallback shows first letter
121
-
expect(find.text('T'), findsOneWidget);
142
+
// Verify fallback shows first letter
143
+
expect(find.text('T'), findsOneWidget);
124
-
testWidgets('displays external link bar when embed present', (
127
-
final post = FeedViewPost(
129
-
uri: 'at://did:example/post/123',
132
-
author: AuthorView(did: 'did:plc:author', handle: 'author.test'),
133
-
community: CommunityRef(
134
-
did: 'did:plc:community',
135
-
name: 'test-community',
137
-
createdAt: DateTime(2024, 1, 1),
138
-
indexedAt: DateTime(2024, 1, 1),
140
-
stats: PostStats(upvotes: 0, downvotes: 0, score: 0, commentCount: 0),
142
-
type: 'social.coves.embed.external',
143
-
external: ExternalEmbed(
144
-
uri: 'https://example.com/article',
145
-
domain: 'example.com',
146
-
title: 'Example Article',
146
+
testWidgets('displays external link bar when embed present', (
149
+
final post = FeedViewPost(
151
+
uri: 'at://did:example/post/123',
154
+
author: AuthorView(did: 'did:plc:author', handle: 'author.test'),
155
+
community: CommunityRef(
156
+
did: 'did:plc:community',
157
+
name: 'test-community',
159
+
createdAt: DateTime(2024, 1, 1),
160
+
indexedAt: DateTime(2024, 1, 1),
169
+
type: 'social.coves.embed.external',
170
+
external: ExternalEmbed(
171
+
uri: 'https://example.com/article',
172
+
domain: 'example.com',
173
+
title: 'Example Article',
153
-
await tester.pumpWidget(createTestWidget(post));
180
+
await tester.pumpWidget(createTestWidget(post));
155
-
// Verify external link bar is present
156
-
expect(find.text('example.com'), findsOneWidget);
157
-
expect(find.byIcon(Icons.open_in_new), findsOneWidget);
182
+
// Verify external link bar is present
183
+
expect(find.text('example.com'), findsOneWidget);
184
+
expect(find.byIcon(Icons.open_in_new), findsOneWidget);
160
-
testWidgets('displays embed image when available', (tester) async {
161
-
final post = FeedViewPost(
163
-
uri: 'at://did:example/post/123',
166
-
author: AuthorView(did: 'did:plc:author', handle: 'author.test'),
167
-
community: CommunityRef(
168
-
did: 'did:plc:community',
169
-
name: 'test-community',
187
+
testWidgets('displays embed image when available', (tester) async {
188
+
final post = FeedViewPost(
190
+
uri: 'at://did:example/post/123',
193
+
author: AuthorView(did: 'did:plc:author', handle: 'author.test'),
194
+
community: CommunityRef(
195
+
did: 'did:plc:community',
196
+
name: 'test-community',
198
+
createdAt: DateTime(2024, 1, 1),
199
+
indexedAt: DateTime(2024, 1, 1),
208
+
type: 'social.coves.embed.external',
209
+
external: ExternalEmbed(
210
+
uri: 'https://example.com/article',
211
+
thumb: 'https://example.com/thumb.jpg',
171
-
createdAt: DateTime(2024, 1, 1),
172
-
indexedAt: DateTime(2024, 1, 1),
174
-
stats: PostStats(upvotes: 0, downvotes: 0, score: 0, commentCount: 0),
176
-
type: 'social.coves.embed.external',
177
-
external: ExternalEmbed(
178
-
uri: 'https://example.com/article',
179
-
thumb: 'https://example.com/thumb.jpg',
218
+
await tester.pumpWidget(createTestWidget(post));
219
+
await tester.pump();
221
+
// Embed image should be loading/present
222
+
expect(find.byType(Image), findsWidgets);
225
+
testWidgets('renders without title', (tester) async {
226
+
final post = FeedViewPost(
228
+
uri: 'at://did:example/post/123',
231
+
author: AuthorView(did: 'did:plc:author', handle: 'author.test'),
232
+
community: CommunityRef(
233
+
did: 'did:plc:community',
234
+
name: 'test-community',
236
+
createdAt: DateTime(2024, 1, 1),
237
+
indexedAt: DateTime(2024, 1, 1),
238
+
text: 'Just body text',
186
-
await tester.pumpWidget(createTestWidget(post));
187
-
await tester.pump();
248
+
await tester.pumpWidget(createTestWidget(post));
189
-
// Embed image should be loading/present
190
-
expect(find.byType(Image), findsWidgets);
250
+
// Should render without errors
251
+
expect(find.text('Just body text'), findsOneWidget);
252
+
expect(find.text('c/test-community'), findsOneWidget);
193
-
testWidgets('renders without title', (tester) async {
194
-
final post = FeedViewPost(
196
-
uri: 'at://did:example/post/123',
199
-
author: AuthorView(did: 'did:plc:author', handle: 'author.test'),
200
-
community: CommunityRef(
201
-
did: 'did:plc:community',
202
-
name: 'test-community',
255
+
testWidgets('has action buttons', (tester) async {
256
+
final post = FeedViewPost(
258
+
uri: 'at://did:example/post/123',
261
+
author: AuthorView(did: 'did:plc:author', handle: 'author.test'),
262
+
community: CommunityRef(
263
+
did: 'did:plc:community',
264
+
name: 'test-community',
266
+
createdAt: DateTime(2024, 1, 1),
267
+
indexedAt: DateTime(2024, 1, 1),
204
-
createdAt: DateTime(2024, 1, 1),
205
-
indexedAt: DateTime(2024, 1, 1),
206
-
text: 'Just body text',
207
-
stats: PostStats(upvotes: 0, downvotes: 0, score: 0, commentCount: 0),
211
-
await tester.pumpWidget(createTestWidget(post));
278
+
await tester.pumpWidget(createTestWidget(post));
213
-
// Should render without errors
214
-
expect(find.text('Just body text'), findsOneWidget);
215
-
expect(find.text('c/test-community'), findsOneWidget);
280
+
// Verify action buttons are present
281
+
expect(find.byIcon(Icons.more_horiz), findsOneWidget); // menu
282
+
// Share, comment, and heart icons are custom widgets, verify by count
283
+
expect(find.byType(InkWell), findsWidgets);
218
-
testWidgets('has action buttons', (tester) async {
219
-
final post = FeedViewPost(
221
-
uri: 'at://did:example/post/123',
224
-
author: AuthorView(did: 'did:plc:author', handle: 'author.test'),
225
-
community: CommunityRef(
226
-
did: 'did:plc:community',
227
-
name: 'test-community',
286
+
testWidgets('displays play button overlay for Streamable videos', (
289
+
final post = FeedViewPost(
291
+
uri: 'at://did:example/post/123',
294
+
author: AuthorView(did: 'did:plc:author', handle: 'author.test'),
295
+
community: CommunityRef(
296
+
did: 'did:plc:community',
297
+
name: 'test-community',
299
+
createdAt: DateTime(2024, 1, 1),
300
+
indexedAt: DateTime(2024, 1, 1),
309
+
type: 'social.coves.embed.external',
310
+
external: ExternalEmbed(
311
+
uri: 'https://streamable.com/abc123',
312
+
thumb: 'https://example.com/thumb.jpg',
313
+
embedType: 'video',
314
+
provider: 'streamable',
229
-
createdAt: DateTime(2024, 1, 1),
230
-
indexedAt: DateTime(2024, 1, 1),
232
-
stats: PostStats(upvotes: 0, downvotes: 0, score: 0, commentCount: 0),
321
+
await tester.pumpWidget(createTestWidget(post));
322
+
await tester.pump();
324
+
// Verify play button is displayed
325
+
expect(find.byIcon(Icons.play_arrow), findsOneWidget);
329
+
'shows loading indicator when fetching video URL for Streamable',
331
+
final dio = Dio(BaseOptions(baseUrl: 'https://api.streamable.com'));
332
+
final dioAdapter = DioAdapter(dio: dio);
333
+
final streamableService = StreamableService(dio: dio);
335
+
// Delay the response to test loading state
338
+
(server) => server.reply(200, {
340
+
'mp4': {'url': '//cdn.streamable.com/video.mp4'},
342
+
}, delay: const Duration(milliseconds: 500)),
345
+
final post = FeedViewPost(
347
+
uri: 'at://did:example/post/123',
350
+
author: AuthorView(did: 'did:plc:author', handle: 'author.test'),
351
+
community: CommunityRef(
352
+
did: 'did:plc:community',
353
+
name: 'test-community',
355
+
createdAt: DateTime(2024, 1, 1),
356
+
indexedAt: DateTime(2024, 1, 1),
365
+
type: 'social.coves.embed.external',
366
+
external: ExternalEmbed(
367
+
uri: 'https://streamable.com/abc123',
368
+
thumb: 'https://example.com/thumb.jpg',
369
+
embedType: 'video',
370
+
provider: 'streamable',
377
+
await tester.pumpWidget(
378
+
createTestWidget(post, streamableService: streamableService),
380
+
await tester.pump();
382
+
// Tap the play button
383
+
await tester.tap(find.byIcon(Icons.play_arrow));
384
+
await tester.pump();
386
+
// Verify loading indicator is displayed
387
+
expect(find.byType(CircularProgressIndicator), findsOneWidget);
236
-
await tester.pumpWidget(createTestWidget(post));
391
+
testWidgets('does not show play button for non-video embeds', (
394
+
final post = FeedViewPost(
396
+
uri: 'at://did:example/post/123',
399
+
author: AuthorView(did: 'did:plc:author', handle: 'author.test'),
400
+
community: CommunityRef(
401
+
did: 'did:plc:community',
402
+
name: 'test-community',
404
+
createdAt: DateTime(2024, 1, 1),
405
+
indexedAt: DateTime(2024, 1, 1),
414
+
type: 'social.coves.embed.external',
415
+
external: ExternalEmbed(
416
+
uri: 'https://example.com/article',
417
+
thumb: 'https://example.com/thumb.jpg',
238
-
// Verify action buttons are present
239
-
expect(find.byIcon(Icons.more_horiz), findsOneWidget); // menu
240
-
// Share, comment, and heart icons are custom widgets, verify by count
241
-
expect(find.byType(InkWell), findsWidgets);
424
+
await tester.pumpWidget(createTestWidget(post));
425
+
await tester.pump();
427
+
// Verify play button is NOT displayed
428
+
expect(find.byIcon(Icons.play_arrow), findsNothing);