Skip to content

Commit 410c688

Browse files
committed
test: Add TestZulipApp; replace uses of ZulipApp
Greg noticed an instance where using ZulipApp directly was causing tests to slow down by some 75%: zulip#805 (comment) Specifically, that was when we converted the emoji-reaction widget tests over to use ZulipApp instead of mimicking it with a MaterialApp, etc. It's helpful to use something approaching the real ZulipApp. But we'd like to avoid that slowdown, especially if it's happening in code that most tests don't need to exercise. So, here's a stripped-down version that does that. It takes roughly the same time as the MaterialApp approach in those emoji-reaction tests. (11s on my machine, vs. 16s with ZulipApp.) This commit just converts the tests that were using ZulipApp. Next, we'll sweep through and treat the ones using the ad hoc MaterialApp approach.
1 parent ab139f7 commit 410c688

File tree

7 files changed

+63
-28
lines changed

7 files changed

+63
-28
lines changed

test/notifications/display_test.dart

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -340,6 +340,8 @@ void main() {
340340
pushedRoutes = [];
341341
final testNavObserver = TestNavigatorObserver()
342342
..onPushed = (route, prevRoute) => pushedRoutes.add(route);
343+
// This uses [ZulipApp] instead of [TestZulipApp] because notification
344+
// logic uses `await ZulipApp.navigator`.
343345
await tester.pumpWidget(ZulipApp(navigatorObservers: [testNavObserver]));
344346
if (early) {
345347
check(pushedRoutes).isEmpty();

test/widgets/code_block_test.dart

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
11
import 'package:checks/checks.dart';
22
import 'package:flutter/material.dart';
33
import 'package:flutter_test/flutter_test.dart';
4-
import 'package:zulip/widgets/app.dart';
54
import 'package:zulip/widgets/code_block.dart';
6-
import 'package:zulip/widgets/page.dart';
75

86
import '../model/binding.dart';
7+
import 'test_app.dart';
98

109
void main() {
1110
TestZulipBinding.ensureInitialized();
@@ -14,12 +13,8 @@ void main() {
1413
group('lerp', () {
1514
Future<BuildContext> contextWithZulipTheme(WidgetTester tester) async {
1615
addTearDown(testBinding.reset);
17-
await tester.pumpWidget(const ZulipApp());
16+
await tester.pumpWidget(const TestZulipApp());
1817
await tester.pump();
19-
final navigator = await ZulipApp.navigator;
20-
navigator.push(MaterialWidgetRoute(page: Builder(
21-
builder: (context) => const Placeholder())));
22-
await tester.pumpAndSettle();
2318
return tester.element(find.byType(Placeholder));
2419
}
2520

test/widgets/inbox_test.dart

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import 'package:flutter_test/flutter_test.dart';
44
import 'package:zulip/api/model/events.dart';
55
import 'package:zulip/api/model/model.dart';
66
import 'package:zulip/model/store.dart';
7-
import 'package:zulip/widgets/app.dart';
87
import 'package:zulip/widgets/icons.dart';
98
import 'package:zulip/widgets/inbox.dart';
109
import 'package:zulip/widgets/stream_colors.dart';
@@ -13,6 +12,7 @@ import '../example_data.dart' as eg;
1312
import '../flutter_checks.dart';
1413
import '../model/binding.dart';
1514
import '../model/test_store.dart';
15+
import 'test_app.dart';
1616

1717
/// Repeatedly drags `view` by `moveStep` until `finder` is invisible.
1818
///
@@ -71,11 +71,12 @@ void main() {
7171
await store.handleEvent(MessageEvent(id: 1, message: message));
7272
}
7373

74-
await tester.pumpWidget(
75-
ZulipApp(navigatorObservers: [if (navigatorObserver != null) navigatorObserver]));
74+
await tester.pumpWidget(TestZulipApp(
75+
accountId: eg.selfAccount.id,
76+
navigatorObservers: [if (navigatorObserver != null) navigatorObserver],
77+
child: const InboxPage(),
78+
));
7679
await tester.pump();
77-
final navigator = await ZulipApp.navigator;
78-
navigator.push(InboxPage.buildRoute(accountId: eg.selfAccount.id));
7980

8081
// global store and per-account store get loaded
8182
await tester.pumpAndSettle();

test/widgets/lightbox_test.dart

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,9 @@ void main() {
208208
addTearDown(testBinding.reset);
209209
await testBinding.globalStore.add(eg.selfAccount, eg.initialSnapshot());
210210

211+
// ZulipApp instead of TestZulipApp because we need the navigator to push
212+
// the lightbox route. The lightbox page works together with the route;
213+
// it takes the route's entrance animation.
211214
await tester.pumpWidget(const ZulipApp());
212215
await tester.pump();
213216
final navigator = await ZulipApp.navigator;

test/widgets/test_app.dart

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
import 'package:flutter/material.dart';
2+
import 'package:flutter_gen/gen_l10n/zulip_localizations.dart';
3+
4+
import 'package:zulip/widgets/store.dart';
5+
import 'package:zulip/widgets/theme.dart';
6+
7+
/// A lightweight mock of [ZulipApp], suitable for most widget tests.
8+
class TestZulipApp extends StatelessWidget {
9+
const TestZulipApp({
10+
super.key,
11+
this.accountId,
12+
this.navigatorObservers,
13+
this.child = const Placeholder(),
14+
});
15+
16+
final int? accountId;
17+
18+
/// A list to pass through to [MaterialApp.navigatorObservers].
19+
final List<NavigatorObserver>? navigatorObservers;
20+
21+
/// A [Widget] to render on the home page.
22+
///
23+
/// If [accountId] is provided, this is wrapped in a [PerAccountStoreWidget].
24+
///
25+
/// Defaults to `Placeholder()`.
26+
final Widget child;
27+
28+
@override
29+
Widget build(BuildContext context) {
30+
return GlobalStoreWidget(
31+
child: MaterialApp(
32+
title: 'Zulip',
33+
localizationsDelegates: ZulipLocalizations.localizationsDelegates,
34+
supportedLocales: ZulipLocalizations.supportedLocales,
35+
theme: zulipThemeData(context),
36+
37+
navigatorObservers: navigatorObservers ?? const [],
38+
39+
home: accountId != null
40+
? PerAccountStoreWidget(accountId: accountId!, child: child)
41+
: child,
42+
));
43+
}
44+
}

test/widgets/text_test.dart

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,11 @@ import 'package:checks/checks.dart';
22
import 'package:collection/collection.dart';
33
import 'package:flutter/material.dart';
44
import 'package:flutter_test/flutter_test.dart';
5-
import 'package:zulip/widgets/app.dart';
6-
import 'package:zulip/widgets/page.dart';
75
import 'package:zulip/widgets/text.dart';
86

97
import '../flutter_checks.dart';
108
import '../model/binding.dart';
9+
import 'test_app.dart';
1110

1211
// From trying the options on an iPhone 13 Pro running iOS 16.6.1:
1312
const kTextScaleFactors = <double>[
@@ -397,14 +396,11 @@ void main() {
397396
addTearDown(tester.platformDispatcher.clearLocaleTestValue);
398397
addTearDown(tester.platformDispatcher.clearLocalesTestValue);
399398

400-
await tester.pumpWidget(const ZulipApp());
399+
await tester.pumpWidget(TestZulipApp(
400+
child: Builder(builder: (context) =>
401+
Text('123', style: TextStyle(textBaseline: localizedTextBaseline(context))))));
401402
await tester.pump();
402403

403-
final navigator = await ZulipApp.navigator;
404-
navigator.push(MaterialWidgetRoute(page: Builder(builder: (context) =>
405-
Text('123', style: TextStyle(textBaseline: localizedTextBaseline(context))))));
406-
await tester.pumpAndSettle();
407-
408404
final TextStyle? style = tester.widget<Text>(find.text('123')).style;
409405
final actualTextBaseline = style!.textBaseline!;
410406
check(actualTextBaseline).equals(expected);

test/widgets/theme_test.dart

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,14 @@ import 'package:checks/checks.dart';
22
import 'package:flutter/material.dart';
33
import 'package:flutter/rendering.dart';
44
import 'package:flutter_test/flutter_test.dart';
5-
import 'package:zulip/widgets/app.dart';
6-
import 'package:zulip/widgets/page.dart';
75
import 'package:zulip/widgets/stream_colors.dart';
86
import 'package:zulip/widgets/text.dart';
97
import 'package:zulip/widgets/theme.dart';
108

119
import '../example_data.dart' as eg;
1210
import '../flutter_checks.dart';
1311
import '../model/binding.dart';
12+
import 'test_app.dart';
1413

1514
void main() {
1615
TestZulipBinding.ensureInitialized();
@@ -118,14 +117,9 @@ void main() {
118117
tester.platformDispatcher.platformBrightnessTestValue = Brightness.light;
119118
addTearDown(tester.platformDispatcher.clearPlatformBrightnessTestValue);
120119

121-
await tester.pumpWidget(const ZulipApp());
120+
await tester.pumpWidget(const TestZulipApp());
122121
await tester.pump();
123122

124-
final navigator = await ZulipApp.navigator;
125-
navigator.push(MaterialWidgetRoute(page: Builder(builder: (context) =>
126-
const Placeholder())));
127-
await tester.pumpAndSettle();
128-
129123
final element = tester.element(find.byType(Placeholder));
130124
// Compares all the swatch's members; see [ColorSwatch]'s `operator ==`.
131125
check(colorSwatchFor(element, subscription))

0 commit comments

Comments
 (0)