|
1 | 1 | import 'package:checks/checks.dart';
|
| 2 | +import 'package:flutter/foundation.dart'; |
2 | 3 | import 'package:flutter/material.dart';
|
| 4 | +import 'package:flutter_checks/flutter_checks.dart'; |
3 | 5 | import 'package:flutter_test/flutter_test.dart';
|
4 | 6 | import 'package:zulip/widgets/app_bar.dart';
|
5 | 7 | import 'package:zulip/widgets/profile.dart';
|
@@ -35,4 +37,124 @@ void main() {
|
35 | 37 | check(tester.getRect(find.byType(ZulipAppBar))).equals(rectBefore);
|
36 | 38 | check(finder.evaluate()).single;
|
37 | 39 | });
|
| 40 | + |
| 41 | + group("buildTitle's willCenterTitle agrees with Material AppBar", () { |
| 42 | + /// Build an [AppBar]; inspect and return whether it decided to center. |
| 43 | + Future<bool> material(WidgetTester tester, { |
| 44 | + required bool? paramValue, |
| 45 | + required bool? themeValue, |
| 46 | + required List<Widget>? actions, |
| 47 | + }) async { |
| 48 | + testBinding.reset(); |
| 49 | + |
| 50 | + final themeData = ThemeData(appBarTheme: AppBarTheme(centerTitle: themeValue)); |
| 51 | + final widget = TestZulipApp( |
| 52 | + child: Theme(data: themeData, |
| 53 | + child: AppBar( |
| 54 | + centerTitle: paramValue, |
| 55 | + actions: actions, |
| 56 | + title: const Text('a')))); |
| 57 | + |
| 58 | + await tester.pumpWidget(widget); |
| 59 | + await tester.pump(); |
| 60 | + |
| 61 | + // test assumes LTR text direction |
| 62 | + check(tester.platformDispatcher.locale).equals(const Locale('en', 'US')); |
| 63 | + assert(actions == null || actions.isNotEmpty); |
| 64 | + final titleAreaRightEdgeOffset = actions == null |
| 65 | + ? (tester.view.physicalSize / tester.view.devicePixelRatio).width |
| 66 | + : tester.getTopLeft(find.byWidget(actions.first)).dx; |
| 67 | + final titlePosition = tester.getTopLeft(find.text('a')).dx; |
| 68 | + final isCentered = titlePosition > ((1 / 3) * titleAreaRightEdgeOffset); |
| 69 | + check(titlePosition).isLessThan((2 / 3) * titleAreaRightEdgeOffset); |
| 70 | + |
| 71 | + return isCentered; |
| 72 | + } |
| 73 | + |
| 74 | + /// Build a [ZulipAppBar]; return willCenterTitle from the buildTitle call. |
| 75 | + Future<bool> ours(WidgetTester tester, { |
| 76 | + required bool? paramValue, |
| 77 | + required bool? themeValue, |
| 78 | + required List<Widget>? actions, |
| 79 | + }) async { |
| 80 | + testBinding.reset(); |
| 81 | + await testBinding.globalStore.add(eg.selfAccount, eg.initialSnapshot()); |
| 82 | + |
| 83 | + bool? result; |
| 84 | + |
| 85 | + final widget = TestZulipApp( |
| 86 | + // ZulipAppBar expects a per-account context (for the loading indicator) |
| 87 | + accountId: eg.selfAccount.id, |
| 88 | + child: Builder(builder: (context) => Theme( |
| 89 | + data: Theme.of(context).copyWith(appBarTheme: AppBarTheme(centerTitle: themeValue)), |
| 90 | + child: ZulipAppBar( |
| 91 | + centerTitle: paramValue, |
| 92 | + actions: actions, |
| 93 | + buildTitle: (willCenterTitle) { |
| 94 | + result = willCenterTitle; |
| 95 | + return const Text('a'); |
| 96 | + })))); |
| 97 | + |
| 98 | + await tester.pumpWidget(widget); |
| 99 | + await tester.pump(); // global store |
| 100 | + await tester.pump(); // per-account store |
| 101 | + check(find.widgetWithText(ZulipAppBar, 'a')).findsOne(); |
| 102 | + |
| 103 | + check(result).isNotNull(); |
| 104 | + return result!; |
| 105 | + } |
| 106 | + |
| 107 | + void doTest(String description, bool expectedWillCenter, { |
| 108 | + bool? paramValue, |
| 109 | + bool? themeValue, |
| 110 | + TargetPlatform? platform, |
| 111 | + List<Widget>? actions, |
| 112 | + }) { |
| 113 | + testWidgets(description, (tester) async { |
| 114 | + addTearDown(testBinding.reset); |
| 115 | + debugDefaultTargetPlatformOverride = platform; |
| 116 | + |
| 117 | + check( |
| 118 | + await ours(tester, paramValue: paramValue, themeValue: themeValue, actions: actions) |
| 119 | + )..equals( |
| 120 | + await material(tester, paramValue: paramValue, themeValue: themeValue, actions: actions) |
| 121 | + )..equals(expectedWillCenter); |
| 122 | + |
| 123 | + // TODO(upstream) Do this in an addTearDown, once we can: |
| 124 | + // https://github.com/flutter/flutter/issues/123189 |
| 125 | + debugDefaultTargetPlatformOverride = null; |
| 126 | + }); |
| 127 | + } |
| 128 | + |
| 129 | + const iOS = TargetPlatform.iOS; |
| 130 | + const android = TargetPlatform.android; |
| 131 | + |
| 132 | + Widget button() => IconButton(icon: const Icon(Icons.add), onPressed: () {}); |
| 133 | + final oneButton = [button()]; |
| 134 | + final twoButtons = [button(), button()]; |
| 135 | + final threeButtons = [button(), button(), button()]; |
| 136 | + |
| 137 | + doTest('ios', true, platform: iOS); |
| 138 | + doTest('android', false, platform: android); |
| 139 | + |
| 140 | + doTest('ios, theme false', false, platform: iOS, themeValue: false); |
| 141 | + doTest('android, theme true', true, platform: android, themeValue: true); |
| 142 | + |
| 143 | + doTest('ios, param false', false, platform: iOS, paramValue: false); |
| 144 | + doTest('android, param true', true, platform: android, paramValue: true); |
| 145 | + |
| 146 | + doTest('ios, theme true, param false', false, platform: iOS, themeValue: true, paramValue: false); |
| 147 | + doTest('ios, theme false, param true', true, platform: iOS, themeValue: false, paramValue: true); |
| 148 | + |
| 149 | + doTest('android, theme true, param false', false, platform: android, themeValue: true, paramValue: false); |
| 150 | + doTest('android, theme false, param true', true, platform: android, themeValue: false, paramValue: true); |
| 151 | + |
| 152 | + doTest('ios, no actions', true, platform: iOS, actions: null); |
| 153 | + doTest('ios, one action', true, platform: iOS, actions: oneButton); |
| 154 | + doTest('ios, two actions' , false, platform: iOS, actions: twoButtons); |
| 155 | + doTest('ios, three actions', false, platform: iOS, actions: threeButtons); |
| 156 | + |
| 157 | + doTest('ios, two actions but param true', true, platform: iOS, paramValue: true, actions: twoButtons); |
| 158 | + doTest('ios, two actions but theme true', true, platform: iOS, themeValue: true, actions: twoButtons); |
| 159 | + }); |
38 | 160 | }
|
0 commit comments