import 'dart:async'; import 'package:flutter_test/flutter_test.dart'; import 'package:minstrel/cache/cache_first.dart'; void main() { test('non-empty drift emission passes through toResult', () async { final controller = StreamController>(); final results = cacheFirst( driftStream: controller.stream, fetchAndPopulate: () async => fail('should not fetch when rows present'), toResult: (rows) => rows.fold(0, (a, b) => a + b), isOnline: () async => true, ); final firstFuture = results.first; controller.add([1, 2, 3]); expect(await firstFuture, 6); await controller.close(); }); test('empty drift emission + online triggers fetchAndPopulate', () async { final controller = StreamController>(); var fetchCalled = 0; final results = cacheFirst( driftStream: controller.stream, fetchAndPopulate: () async { fetchCalled++; controller.add([42]); // simulate populate causing re-emission }, toResult: (rows) => rows.fold(0, (a, b) => a + b), isOnline: () async => true, ); // Post-coldFetchAttempted guard, cacheFirst yields the current // (still-empty) rows after the fetch returns, so the stream // never hangs when populate is a no-op for this filter. The // simulated drift re-emit then yields the populated rows. // Capture the Future *before* feeding the controller so the // listener is subscribed when the first add() lands. final emissionsFuture = results.take(2).toList(); controller.add([]); final emissions = await emissionsFuture; expect(emissions, [0, 42]); expect(fetchCalled, 1); await controller.close(); }); test('empty drift + offline yields empty result without fetch', () async { final controller = StreamController>(); var fetchCalled = 0; final results = cacheFirst( driftStream: controller.stream, fetchAndPopulate: () async { fetchCalled++; }, toResult: (rows) => rows.fold(0, (a, b) => a + b), isOnline: () async => false, ); final firstFuture = results.first; controller.add([]); expect(await firstFuture, 0); expect(fetchCalled, 0); await controller.close(); }); test('REST failure falls through to empty result', () async { final controller = StreamController>(); final results = cacheFirst( driftStream: controller.stream, fetchAndPopulate: () async => throw Exception('REST 500'), toResult: (rows) => rows.fold(0, (a, b) => a + b), isOnline: () async => true, ); final firstFuture = results.first; controller.add([]); expect(await firstFuture, 0); await controller.close(); }); }