Skip to content

Commit a064534

Browse files
committed
chore: add a basic test suite
1 parent d3d8df0 commit a064534

File tree

1 file changed

+127
-0
lines changed

1 file changed

+127
-0
lines changed

test/modular_widget_test.dart

Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
import 'dart:async';
2+
3+
import 'package:flutter/widgets.dart';
4+
import 'package:flutter_modular/flutter_modular.dart';
5+
import 'package:flutter_modular_widget/flutter_modular_widget.dart';
6+
import 'package:flutter_test/flutter_test.dart';
7+
import 'package:mcquenji_core/mcquenji_core.dart';
8+
9+
void main() {
10+
TestWidgetsFlutterBinding.ensureInitialized();
11+
12+
late TestRepository repository;
13+
14+
setUp(() {
15+
Modular.init(_TestModule());
16+
repository = Modular.get<TestRepository>();
17+
});
18+
19+
tearDown(() {
20+
cleanGlobals();
21+
});
22+
23+
Future<void> pumpHarness(
24+
WidgetTester tester, {
25+
void Function(TestRepository repo)? onContentBuild,
26+
}) async {
27+
await tester.pumpWidget(
28+
Directionality(
29+
textDirection: TextDirection.ltr,
30+
child: _TestHarness(onContentBuild: onContentBuild),
31+
),
32+
);
33+
await tester.pump();
34+
}
35+
36+
testWidgets('shows loader while watched repository is loading', (
37+
tester,
38+
) async {
39+
await pumpHarness(tester);
40+
41+
expect(find.text('loader'), findsOneWidget);
42+
});
43+
44+
testWidgets('renders derived content once repository provides data', (
45+
tester,
46+
) async {
47+
await pumpHarness(tester);
48+
repository.setData(7);
49+
await tester.pump(Duration(milliseconds: 1000));
50+
51+
expect(find.text('content: 7'), findsOneWidget);
52+
});
53+
54+
testWidgets('renders error UI when repository enters error state', (
55+
tester,
56+
) async {
57+
await pumpHarness(tester);
58+
repository.setData(1);
59+
await tester.pump();
60+
await tester.pump();
61+
62+
repository.setError(Exception('boom'));
63+
await tester.pump();
64+
await tester.pump();
65+
66+
expect(find.text('error: Exception: boom'), findsOneWidget);
67+
});
68+
69+
testWidgets('exposes non-reactive repository access via get callback', (
70+
tester,
71+
) async {
72+
TestRepository? repoSeenInContent;
73+
74+
await pumpHarness(
75+
tester,
76+
onContentBuild: (repo) => repoSeenInContent = repo,
77+
);
78+
79+
repository.setData(42);
80+
await tester.pump(Duration(milliseconds: 100));
81+
82+
expect(repoSeenInContent, same(repository));
83+
});
84+
}
85+
86+
class _TestHarness extends ModularWidget<int> {
87+
const _TestHarness({this.onContentBuild});
88+
89+
final void Function(TestRepository repo)? onContentBuild;
90+
91+
@override
92+
Widget buildLoader(BuildContext context) => const Text('loader');
93+
94+
@override
95+
Widget buildError(
96+
BuildContext context,
97+
Object error,
98+
StackTrace? stackTrace,
99+
) => Text('error: $error');
100+
101+
@override
102+
Widget buildContent(BuildContext context, int data, RepoAccessor get) {
103+
onContentBuild?.call(get<TestRepository>());
104+
return Text('content: $data');
105+
}
106+
107+
@override
108+
FutureOr<int> query(RepoAccessor watch) {
109+
final repo = watch<TestRepository>();
110+
return repo.state.requireData;
111+
}
112+
}
113+
114+
class _TestModule extends Module {
115+
@override
116+
void binds(Injector i) {
117+
i.addRepository<TestRepository>(TestRepository.new);
118+
}
119+
}
120+
121+
class TestRepository extends Repository<AsyncValue<int>> {
122+
TestRepository() : super(AsyncValue.loading());
123+
124+
void setData(int value) => emit(AsyncValue.data(value));
125+
126+
void setError(Object error) => emit(AsyncValue.error(error));
127+
}

0 commit comments

Comments
 (0)