Skip to content

Commit 7d702d0

Browse files
fix(test): fix lifecycle tests timing out on web/JS platform
Two issues fixed: 1. Missing mockAppLink() in setUp — on web, Supabase.initialize() calls _appLinks.getInitialLink() via a platform channel. Without the mock, that call hangs forever, timing out the test. Native tests were unaffected because _handleInitialUri() has a kIsWeb guard. 2. The completeReadyCompleters() helper was async void, so its body ran as a deferred microtask and cleared the list. Replace with settleLifecycle() that loops until all lifecycle operations settle.
1 parent 41a1225 commit 7d702d0

1 file changed

Lines changed: 16 additions & 13 deletions

File tree

packages/supabase_flutter/test/lifecycle_test.dart

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ void main() {
7777
late List<Completer<void>> readyCompleters;
7878

7979
setUp(() async {
80+
mockAppLink();
8081
readyCompleters = [];
8182
await Supabase.initialize(
8283
url: supabaseUrl,
@@ -112,12 +113,18 @@ void main() {
112113
await future;
113114
}
114115

115-
// Helper: complete all pending ready futures to unblock connect()
116-
void completeReadyCompleters() async {
117-
for (final completer in readyCompleters) {
118-
if (!completer.isCompleted) completer.complete();
116+
/// Repeatedly complete pending ready futures and pump the event queue
117+
/// until no new completers appear. This handles the case where lifecycle
118+
/// processing triggers a connect() that creates a new completer.
119+
Future<void> settleLifecycle() async {
120+
var previousCount = -1;
121+
while (readyCompleters.length != previousCount) {
122+
previousCount = readyCompleters.length;
123+
for (final c in readyCompleters) {
124+
if (!c.isCompleted) c.complete();
125+
}
126+
await pumpEventQueue();
119127
}
120-
readyCompleters.clear();
121128
}
122129

123130
test(
@@ -143,8 +150,7 @@ void main() {
143150
binding.handleAppLifecycleStateChanged(AppLifecycleState.resumed);
144151

145152
// Complete any pending ready futures (reconnect)
146-
completeReadyCompleters();
147-
await pumpEventQueue();
153+
await settleLifecycle();
148154

149155
expect(realtime.connState, SocketStates.open);
150156
expect(realtime.conn, isNotNull);
@@ -177,8 +183,7 @@ void main() {
177183
binding.handleAppLifecycleStateChanged(AppLifecycleState.resumed);
178184

179185
// Complete all pending ready futures
180-
completeReadyCompleters();
181-
await pumpEventQueue();
186+
await settleLifecycle();
182187

183188
// Should have reconnected, not stuck disconnecting
184189
expect(realtime.connState, SocketStates.open);
@@ -212,8 +217,7 @@ void main() {
212217
binding.handleAppLifecycleStateChanged(AppLifecycleState.resumed);
213218

214219
// Complete all pending ready futures as they appear
215-
completeReadyCompleters();
216-
await pumpEventQueue();
220+
await settleLifecycle();
217221

218222
expect(realtime.connState, SocketStates.open);
219223
expect(realtime.conn, isNotNull);
@@ -246,8 +250,7 @@ void main() {
246250
binding.handleAppLifecycleStateChanged(AppLifecycleState.paused);
247251

248252
// Complete all pending ready futures
249-
completeReadyCompleters();
250-
await pumpEventQueue();
253+
await settleLifecycle();
251254

252255
// Should be disconnected since the last event was paused
253256
expect(realtime.connState, SocketStates.disconnected);

0 commit comments

Comments
 (0)