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, ); final firstFuture = results.first; controller.add([]); expect(await firstFuture, 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(); }); }