@@ -6,14 +6,16 @@ import 'package:flutter_modular_widget/flutter_modular_widget.dart';
66import 'package:flutter_test/flutter_test.dart' ;
77import 'package:mcquenji_core/mcquenji_core.dart' ;
88
9+ import 'support/test_repositories.dart' ;
10+
911void main () {
1012 TestWidgetsFlutterBinding .ensureInitialized ();
1113
12- late TestRepository repository;
14+ late TestRepository < int > repository;
1315
1416 setUp (() {
1517 Modular .init (_TestModule ());
16- repository = Modular .get <TestRepository >();
18+ repository = Modular .get <TestRepository < int > >();
1719 });
1820
1921 tearDown (() {
@@ -22,7 +24,7 @@ void main() {
2224
2325 Future <void > pumpHarness (
2426 WidgetTester tester, {
25- void Function (TestRepository repo)? onContentBuild,
27+ void Function (TestRepository < int > repo)? onContentBuild,
2628 }) async {
2729 await tester.pumpWidget (
2830 Directionality (
@@ -46,7 +48,7 @@ void main() {
4648 ) async {
4749 await pumpHarness (tester);
4850 repository.setData (7 );
49- await tester.pump (Duration (milliseconds: 1000 ));
51+ await tester.pump (const Duration (milliseconds: 1000 ));
5052
5153 expect (find.text ('content: 7' ), findsOneWidget);
5254 });
@@ -69,24 +71,106 @@ void main() {
6971 testWidgets ('exposes non-reactive repository access via get callback' , (
7072 tester,
7173 ) async {
72- TestRepository ? repoSeenInContent;
74+ TestRepository < int > ? repoSeenInContent;
7375
7476 await pumpHarness (
7577 tester,
7678 onContentBuild: (repo) => repoSeenInContent = repo,
7779 );
7880
7981 repository.setData (42 );
80- await tester.pump (Duration (milliseconds: 100 ));
82+ await tester.pump (const Duration (milliseconds: 100 ));
8183
8284 expect (repoSeenInContent, same (repository));
8385 });
86+
87+ group ('ModularWidget with multiple repositories' , () {
88+ late FirstRepository firstRepository;
89+ late SecondRepository secondRepository;
90+
91+ setUp (() {
92+ cleanGlobals ();
93+ Modular .init (_MultiRepoModule ());
94+ firstRepository = Modular .get <FirstRepository >();
95+ secondRepository = Modular .get <SecondRepository >();
96+ });
97+
98+ Future <void > pumpMultiHarness (
99+ WidgetTester tester, {
100+ void Function (FirstRepository first, SecondRepository second)?
101+ onContentBuild,
102+ }) async {
103+ await tester.pumpWidget (
104+ Directionality (
105+ textDirection: TextDirection .ltr,
106+ child: _MultiRepoHarness (onContentBuild: onContentBuild),
107+ ),
108+ );
109+ await tester.pump ();
110+ }
111+
112+ testWidgets ('stays loading until all watched repositories resolve' , (
113+ tester,
114+ ) async {
115+ await pumpMultiHarness (tester);
116+
117+ expect (find.text ('multi-loader' ), findsOneWidget);
118+
119+ firstRepository.setData (1 );
120+ await tester.pump ();
121+ expect (find.text ('multi-loader' ), findsOneWidget);
122+
123+ secondRepository.setData (2 );
124+ await tester.pump (const Duration (milliseconds: 100 ));
125+
126+ expect (find.text ('multi-content: 1 + 2' ), findsOneWidget);
127+ });
128+
129+ testWidgets ('shows error when any repository enters error state' , (
130+ tester,
131+ ) async {
132+ await pumpMultiHarness (tester);
133+
134+ firstRepository.setData (5 );
135+ secondRepository.setData (9 );
136+ await tester.pump (const Duration (milliseconds: 100 ));
137+ expect (find.text ('multi-content: 5 + 9' ), findsOneWidget);
138+
139+ secondRepository.setError (Exception ('multi boom' ));
140+ await tester.pump ();
141+ await tester.pump ();
142+
143+ expect (find.text ('multi-error: Exception: multi boom' ), findsOneWidget);
144+ });
145+
146+ testWidgets ('provides get accessor for each repository in content' , (
147+ tester,
148+ ) async {
149+ FirstRepository ? firstSeen;
150+ SecondRepository ? secondSeen;
151+
152+ await pumpMultiHarness (
153+ tester,
154+ onContentBuild: (first, second) {
155+ firstSeen = first;
156+ secondSeen = second;
157+ },
158+ );
159+
160+ firstRepository.setData (3 );
161+ secondRepository.setData (4 );
162+ await tester.pump (const Duration (milliseconds: 100 ));
163+
164+ expect (firstSeen, same (firstRepository));
165+ expect (secondSeen, same (secondRepository));
166+ });
167+ });
84168}
85169
86170class _TestHarness extends ModularWidget <int > {
87171 const _TestHarness ({this .onContentBuild});
88172
89- final void Function (TestRepository repo)? onContentBuild;
173+ final void Function (TestRepository < int > repo)? onContentBuild;
90174
91175 @override
92176 Widget buildLoader (BuildContext context) => const Text ('loader' );
@@ -100,28 +184,63 @@ class _TestHarness extends ModularWidget<int> {
100184
101185 @override
102186 Widget buildContent (BuildContext context, int data, RepoAccessor get ) {
103- onContentBuild? .call (get <TestRepository >());
187+ onContentBuild? .call (get <TestRepository < int > >());
104188 return Text ('content: $data ' );
105189 }
106190
107191 @override
108192 FutureOr <int > query (RepoAccessor watch) {
109- final repo = watch <TestRepository >();
193+ final repo = watch <TestRepository < int > >();
110194 return repo.state.requireData;
111195 }
112196}
113197
114198class _TestModule extends Module {
115199 @override
116200 void binds (Injector i) {
117- i.addRepository <TestRepository > (TestRepository .new );
201+ i.addRepository <TestRepository < int >> (TestRepository < int > .new );
118202 }
119203}
120204
121- class TestRepository extends Repository <AsyncValue <int >> {
122- TestRepository () : super (AsyncValue .loading ());
205+ class _MultiRepoHarness extends ModularWidget <String > {
206+ const _MultiRepoHarness ({this .onContentBuild});
207+
208+ final void Function (FirstRepository first, SecondRepository second)?
209+ onContentBuild;
123210
124- void setData (int value) => emit (AsyncValue .data (value));
211+ @override
212+ Widget buildLoader (BuildContext context) => const Text ('multi-loader' );
125213
126- void setError (Object error) => emit (AsyncValue .error (error));
214+ @override
215+ Widget buildError (
216+ BuildContext context,
217+ Object error,
218+ StackTrace ? stackTrace,
219+ ) => Text ('multi-error: $error ' );
220+
221+ @override
222+ Widget buildContent (BuildContext context, String data, RepoAccessor get ) {
223+ onContentBuild? .call (get <FirstRepository >(), get <SecondRepository >());
224+ return Text (data);
225+ }
226+
227+ @override
228+ FutureOr <String > query (RepoAccessor watch) {
229+ final first = watch <FirstRepository >().state.requireData;
230+ final second = watch <SecondRepository >().state.requireData;
231+ return 'multi-content: $first + $second ' ;
232+ }
233+ }
234+
235+ class _MultiRepoModule extends Module {
236+ @override
237+ void binds (Injector i) {
238+ i
239+ ..addRepository <FirstRepository >(FirstRepository .new )
240+ ..addRepository <SecondRepository >(SecondRepository .new );
241+ }
127242}
243+
244+ class FirstRepository extends TestRepository <int > {}
245+
246+ class SecondRepository extends TestRepository <int > {}
0 commit comments