import 'dart:async'; import 'package:fancake/core/data/shared_stream.dart'; import 'package:flutter_test/flutter_test.dart'; /// 실시간 구독 공유 — 같은 문서를 여러 화면이 볼 때 원본 구독은 하나만 연다. void main() { group('구독 공유 — 여러 화면이 원본 하나를 나눠 본다', () { test('여러 화면이 같은 원본 하나를 나눠 쓴다', () async { // 화면마다 snapshots() 를 열면 한 팬덤에 리스너가 화면 수만큼 붙는다. var opened = 0; final controller = StreamController.broadcast(); addTearDown(controller.close); final shared = SharedStream(() { opened += 1; return controller.stream; }); final a = []; final b = []; final subA = shared.stream.listen(a.add); final subB = shared.stream.listen(b.add); await Future.delayed(Duration.zero); controller.add(7); await Future.delayed(Duration.zero); // 원본은 한 번만 열렸는데 두 화면 모두 값을 받았다. expect(opened, 1); expect(a, [7]); expect(b, [7]); await subA.cancel(); await subB.cancel(); }); test('늦게 붙은 화면이 현재 값을 곧바로 받는다', () async { final controller = StreamController.broadcast(); addTearDown(controller.close); final shared = SharedStream(() => controller.stream); final first = []; final subA = shared.stream.listen(first.add); await Future.delayed(Duration.zero); controller.add(42); await Future.delayed(Duration.zero); // 뒤늦게 열린 화면이 다음 갱신까지 빈 상태로 남으면 안 된다. final late = []; final subB = shared.stream.listen(late.add); await Future.delayed(Duration.zero); expect(late, [42]); await subA.cancel(); await subB.cancel(); }); test('마지막 화면이 떠나면 원본을 닫는다', () async { var cancelled = false; final controller = StreamController( onCancel: () => cancelled = true, ); addTearDown(controller.close); final shared = SharedStream(() => controller.stream); final sub = shared.stream.listen((_) {}); await Future.delayed(Duration.zero); expect(cancelled, isFalse); await sub.cancel(); await Future.delayed(Duration.zero); // 남겨 두면 화면이 없는 동안에도 읽기 비용이 계속 든다. expect(cancelled, isTrue); }); }); }