Main coves client
1import 'package:coves_flutter/models/post.dart';
2import 'package:coves_flutter/widgets/external_link_bar.dart';
3import 'package:flutter/material.dart';
4import 'package:flutter_test/flutter_test.dart';
5import 'package:url_launcher_platform_interface/url_launcher_platform_interface.dart';
6
7import '../test_helpers/mock_url_launcher_platform.dart';
8
9void main() {
10 TestWidgetsFlutterBinding.ensureInitialized();
11
12 late MockUrlLauncherPlatform mockPlatform;
13
14 setUp(() {
15 mockPlatform = MockUrlLauncherPlatform();
16 UrlLauncherPlatform.instance = mockPlatform;
17 });
18
19 group('ExternalLinkBar', () {
20 testWidgets('renders with domain and favicon', (tester) async {
21 final embed = ExternalEmbed(
22 uri: 'https://example.com/article',
23 domain: 'example.com',
24 title: 'Test Article',
25 description: 'A test article',
26 thumb: 'https://example.com/thumb.jpg',
27 );
28
29 await tester.pumpWidget(
30 MaterialApp(home: Scaffold(body: ExternalLinkBar(embed: embed))),
31 );
32
33 // Verify domain is displayed
34 expect(find.text('example.com'), findsOneWidget);
35
36 // Verify external link icon is present
37 expect(find.byIcon(Icons.open_in_new), findsOneWidget);
38 });
39
40 testWidgets('handles missing domain field by extracting from URI', (
41 tester,
42 ) async {
43 final embed = ExternalEmbed(uri: 'https://test.example.com/path');
44
45 await tester.pumpWidget(
46 MaterialApp(home: Scaffold(body: ExternalLinkBar(embed: embed))),
47 );
48
49 // Should extract domain from URI
50 expect(find.text('test.example.com'), findsOneWidget);
51 });
52
53 testWidgets('handles invalid URI gracefully', (tester) async {
54 final embed = ExternalEmbed(uri: 'not a valid url');
55
56 await tester.pumpWidget(
57 MaterialApp(home: Scaffold(body: ExternalLinkBar(embed: embed))),
58 );
59
60 // Should fallback to showing full URI
61 expect(find.text('not a valid url'), findsOneWidget);
62 });
63
64 testWidgets('launches URL when tapped', (tester) async {
65 final embed = ExternalEmbed(
66 uri: 'https://example.com/article',
67 domain: 'example.com',
68 );
69
70 await tester.pumpWidget(
71 MaterialApp(home: Scaffold(body: ExternalLinkBar(embed: embed))),
72 );
73
74 // Tap the link bar
75 await tester.tap(find.byType(ExternalLinkBar));
76 await tester.pumpAndSettle();
77
78 // Verify URL was launched
79 expect(
80 mockPlatform.launchedUrls,
81 contains('https://example.com/article'),
82 );
83 });
84
85 testWidgets('has proper accessibility label', (tester) async {
86 final embed = ExternalEmbed(
87 uri: 'https://example.com',
88 domain: 'example.com',
89 );
90
91 await tester.pumpWidget(
92 MaterialApp(home: Scaffold(body: ExternalLinkBar(embed: embed))),
93 );
94
95 // Verify Semantics widget is present
96 expect(find.byType(Semantics), findsWidgets);
97
98 // Verify link renders
99 expect(find.text('example.com'), findsOneWidget);
100 });
101
102 testWidgets('displays favicon from Google service', (tester) async {
103 final embed = ExternalEmbed(
104 uri: 'https://github.com/user/repo',
105 domain: 'github.com',
106 );
107
108 await tester.pumpWidget(
109 MaterialApp(home: Scaffold(body: ExternalLinkBar(embed: embed))),
110 );
111
112 // Let images load
113 await tester.pumpAndSettle();
114
115 // Verify CachedNetworkImage is present (favicon)
116 expect(find.byType(Image), findsOneWidget);
117 });
118
119 group('Domain Extraction Edge Cases', () {
120 testWidgets('handles empty domain field', (tester) async {
121 final embed = ExternalEmbed(uri: 'https://example.com', domain: '');
122
123 await tester.pumpWidget(
124 MaterialApp(home: Scaffold(body: ExternalLinkBar(embed: embed))),
125 );
126
127 // Should extract from URI
128 expect(find.text('example.com'), findsOneWidget);
129 });
130
131 testWidgets('handles URL with path and query', (tester) async {
132 final embed = ExternalEmbed(
133 uri: 'https://example.com/path?query=value',
134 );
135
136 await tester.pumpWidget(
137 MaterialApp(home: Scaffold(body: ExternalLinkBar(embed: embed))),
138 );
139
140 // Should show just domain
141 expect(find.text('example.com'), findsOneWidget);
142 });
143
144 testWidgets('handles URL with subdomain', (tester) async {
145 final embed = ExternalEmbed(uri: 'https://sub.example.com/article');
146
147 await tester.pumpWidget(
148 MaterialApp(home: Scaffold(body: ExternalLinkBar(embed: embed))),
149 );
150
151 // Should show full host
152 expect(find.text('sub.example.com'), findsOneWidget);
153 });
154
155 testWidgets('handles URL with port', (tester) async {
156 final embed = ExternalEmbed(uri: 'https://example.com:8080/path');
157
158 await tester.pumpWidget(
159 MaterialApp(home: Scaffold(body: ExternalLinkBar(embed: embed))),
160 );
161
162 // Should show host with port
163 expect(find.text('example.com'), findsOneWidget);
164 });
165 });
166 });
167}