Skip to content

Commit e763d1b

Browse files
fix(test): fix lifecycle tests timing out on web/JS platform
The completeReadyCompleters() helper was async void, so its body ran as a deferred microtask and cleared the list. When lifecycle processing later called connect() (creating a new readyCompleter), that completer was never completed, causing tests to hang on web/JS where microtask scheduling differs from native Dart. Replace with settleLifecycle() that loops: complete all pending completers → pump event queue → repeat until no new completers appear.
1 parent 41a1225 commit e763d1b

1 file changed

Lines changed: 15 additions & 13 deletions

File tree

packages/supabase_flutter/test/lifecycle_test.dart

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -112,12 +112,18 @@ void main() {
112112
await future;
113113
}
114114

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();
115+
/// Repeatedly complete pending ready futures and pump the event queue
116+
/// until no new completers appear. This handles the case where lifecycle
117+
/// processing triggers a connect() that creates a new completer.
118+
Future<void> settleLifecycle() async {
119+
var previousCount = -1;
120+
while (readyCompleters.length != previousCount) {
121+
previousCount = readyCompleters.length;
122+
for (final c in readyCompleters) {
123+
if (!c.isCompleted) c.complete();
124+
}
125+
await pumpEventQueue();
119126
}
120-
readyCompleters.clear();
121127
}
122128

123129
test(
@@ -143,8 +149,7 @@ void main() {
143149
binding.handleAppLifecycleStateChanged(AppLifecycleState.resumed);
144150

145151
// Complete any pending ready futures (reconnect)
146-
completeReadyCompleters();
147-
await pumpEventQueue();
152+
await settleLifecycle();
148153

149154
expect(realtime.connState, SocketStates.open);
150155
expect(realtime.conn, isNotNull);
@@ -177,8 +182,7 @@ void main() {
177182
binding.handleAppLifecycleStateChanged(AppLifecycleState.resumed);
178183

179184
// Complete all pending ready futures
180-
completeReadyCompleters();
181-
await pumpEventQueue();
185+
await settleLifecycle();
182186

183187
// Should have reconnected, not stuck disconnecting
184188
expect(realtime.connState, SocketStates.open);
@@ -212,8 +216,7 @@ void main() {
212216
binding.handleAppLifecycleStateChanged(AppLifecycleState.resumed);
213217

214218
// Complete all pending ready futures as they appear
215-
completeReadyCompleters();
216-
await pumpEventQueue();
219+
await settleLifecycle();
217220

218221
expect(realtime.connState, SocketStates.open);
219222
expect(realtime.conn, isNotNull);
@@ -246,8 +249,7 @@ void main() {
246249
binding.handleAppLifecycleStateChanged(AppLifecycleState.paused);
247250

248251
// Complete all pending ready futures
249-
completeReadyCompleters();
250-
await pumpEventQueue();
252+
await settleLifecycle();
251253

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

0 commit comments

Comments
 (0)