1// Copyright 2014 The Flutter Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5import 'package:flutter/foundation.dart';
6import 'package:flutter/material.dart';
7import 'package:flutter_test/flutter_test.dart';
8
9void main() {
10 test('Typography is defined for all target platforms', () {
11 for (final TargetPlatform platform in TargetPlatform.values) {
12 final Typography typography = Typography.material2018(platform: platform);
13 expect(typography, isNotNull, reason: 'null typography for $platform');
14 expect(typography.black, isNotNull, reason: 'null black typography for $platform');
15 expect(typography.white, isNotNull, reason: 'null white typography for $platform');
16 }
17 });
18
19 test('Typography lerp special cases', () {
20 final Typography typography = Typography();
21 expect(identical(Typography.lerp(typography, typography, 0.5), typography), true);
22 });
23
24 test('Typography on non-Apple platforms defaults to the correct font', () {
25 expect(Typography.material2018().black.titleLarge!.fontFamily, 'Roboto');
26 expect(
27 Typography.material2018(platform: TargetPlatform.fuchsia).black.titleLarge!.fontFamily,
28 'Roboto',
29 );
30 expect(
31 Typography.material2018(platform: TargetPlatform.linux).black.titleLarge!.fontFamily,
32 'Roboto',
33 );
34 expect(
35 Typography.material2018(platform: TargetPlatform.linux).black.titleLarge!.fontFamilyFallback,
36 <String>['Ubuntu', 'Cantarell', 'DejaVu Sans', 'Liberation Sans', 'Arial'],
37 );
38 expect(
39 Typography.material2018(platform: TargetPlatform.windows).black.titleLarge!.fontFamily,
40 'Segoe UI',
41 );
42 expect(Typography.material2018().white.titleLarge!.fontFamily, 'Roboto');
43 expect(
44 Typography.material2018(platform: TargetPlatform.fuchsia).white.titleLarge!.fontFamily,
45 'Roboto',
46 );
47 expect(
48 Typography.material2018(platform: TargetPlatform.linux).white.titleLarge!.fontFamily,
49 'Roboto',
50 );
51 expect(
52 Typography.material2018(platform: TargetPlatform.linux).white.titleLarge!.fontFamilyFallback,
53 <String>['Ubuntu', 'Cantarell', 'DejaVu Sans', 'Liberation Sans', 'Arial'],
54 );
55 expect(
56 Typography.material2018(platform: TargetPlatform.windows).white.titleLarge!.fontFamily,
57 'Segoe UI',
58 );
59 });
60
61 // Ref: https://developer.apple.com/design/human-interface-guidelines/typography/
62 final Matcher isSanFranciscoDisplayFont = predicate((TextStyle s) {
63 return s.fontFamily == 'CupertinoSystemDisplay';
64 }, 'Uses SF Display font');
65
66 final Matcher isSanFranciscoTextFont = predicate((TextStyle s) {
67 return s.fontFamily == 'CupertinoSystemText';
68 }, 'Uses SF Text font');
69
70 final Matcher isMacOSSanFranciscoMetaFont = predicate((TextStyle s) {
71 return s.fontFamily == '.AppleSystemUIFont';
72 }, 'Uses macOS system meta-font');
73
74 test('Typography on iOS defaults to the correct SF font family based on size', () {
75 final Typography typography = Typography.material2018(platform: TargetPlatform.iOS);
76 for (final TextTheme textTheme in <TextTheme>[typography.black, typography.white]) {
77 expect(textTheme.displayLarge, isSanFranciscoDisplayFont);
78 expect(textTheme.displayMedium, isSanFranciscoDisplayFont);
79 expect(textTheme.displaySmall, isSanFranciscoDisplayFont);
80 expect(textTheme.headlineLarge, isSanFranciscoDisplayFont);
81 expect(textTheme.headlineMedium, isSanFranciscoDisplayFont);
82 expect(textTheme.headlineSmall, isSanFranciscoDisplayFont);
83 expect(textTheme.titleLarge, isSanFranciscoDisplayFont);
84 expect(textTheme.titleMedium, isSanFranciscoTextFont);
85 expect(textTheme.titleSmall, isSanFranciscoTextFont);
86 expect(textTheme.bodyLarge, isSanFranciscoTextFont);
87 expect(textTheme.bodyMedium, isSanFranciscoTextFont);
88 expect(textTheme.bodySmall, isSanFranciscoTextFont);
89 expect(textTheme.labelLarge, isSanFranciscoTextFont);
90 expect(textTheme.labelMedium, isSanFranciscoTextFont);
91 expect(textTheme.labelSmall, isSanFranciscoTextFont);
92 }
93 });
94
95 test('Typography on macOS defaults to the system UI meta-font', () {
96 final Typography typography = Typography.material2018(platform: TargetPlatform.macOS);
97 for (final TextTheme textTheme in <TextTheme>[typography.black, typography.white]) {
98 expect(textTheme.displayLarge, isMacOSSanFranciscoMetaFont);
99 expect(textTheme.displayMedium, isMacOSSanFranciscoMetaFont);
100 expect(textTheme.displaySmall, isMacOSSanFranciscoMetaFont);
101 expect(textTheme.headlineLarge, isMacOSSanFranciscoMetaFont);
102 expect(textTheme.headlineMedium, isMacOSSanFranciscoMetaFont);
103 expect(textTheme.headlineSmall, isMacOSSanFranciscoMetaFont);
104 expect(textTheme.titleLarge, isMacOSSanFranciscoMetaFont);
105 expect(textTheme.titleMedium, isMacOSSanFranciscoMetaFont);
106 expect(textTheme.titleSmall, isMacOSSanFranciscoMetaFont);
107 expect(textTheme.bodyLarge, isMacOSSanFranciscoMetaFont);
108 expect(textTheme.bodyMedium, isMacOSSanFranciscoMetaFont);
109 expect(textTheme.bodySmall, isMacOSSanFranciscoMetaFont);
110 expect(textTheme.labelLarge, isMacOSSanFranciscoMetaFont);
111 expect(textTheme.labelMedium, isMacOSSanFranciscoMetaFont);
112 expect(textTheme.labelSmall, isMacOSSanFranciscoMetaFont);
113 }
114 });
115
116 testWidgets('Typography implements debugFillProperties', (WidgetTester tester) async {
117 final DiagnosticPropertiesBuilder builder = DiagnosticPropertiesBuilder();
118 Typography.material2014(
119 black: Typography.blackCupertino,
120 white: Typography.whiteCupertino,
121 englishLike: Typography.englishLike2018,
122 dense: Typography.dense2018,
123 tall: Typography.tall2018,
124 ).debugFillProperties(builder);
125
126 final List<String> nonDefaultPropertyNames =
127 builder.properties
128 .where((DiagnosticsNode node) => !node.isFiltered(DiagnosticLevel.info))
129 .map((DiagnosticsNode node) => node.name!)
130 .toList();
131
132 expect(nonDefaultPropertyNames, <String>['black', 'white', 'englishLike', 'dense', 'tall']);
133 });
134
135 test('Can lerp between different typographies', () {
136 final List<Typography> all = <Typography>[
137 for (final TargetPlatform platform in TargetPlatform.values)
138 Typography.material2014(platform: platform),
139 for (final TargetPlatform platform in TargetPlatform.values)
140 Typography.material2018(platform: platform),
141 for (final TargetPlatform platform in TargetPlatform.values)
142 Typography.material2021(platform: platform),
143 ];
144
145 for (final Typography fromTypography in all) {
146 for (final Typography toTypography in all) {
147 Object? error;
148 try {
149 Typography.lerp(fromTypography, toTypography, 0.5);
150 } catch (e) {
151 error = e;
152 }
153 expect(error, isNull);
154 }
155 }
156 });
157
158 test('englishLike2018 TextTheme matches Material Design spec', () {
159 // Check the default material text theme against the style values
160 // shown https://material.io/design/typography/#type-scale.
161
162 final TextTheme theme = Typography.englishLike2018.merge(Typography.blackMountainView);
163 const FontWeight light = FontWeight.w300;
164 const FontWeight regular = FontWeight.w400;
165 const FontWeight medium = FontWeight.w500;
166
167 // Display Large Roboto light 96 -1.5
168 expect(theme.displayLarge!.fontFamily, 'Roboto');
169 expect(theme.displayLarge!.fontWeight, light);
170 expect(theme.displayLarge!.fontSize, 96);
171 expect(theme.displayLarge!.letterSpacing, -1.5);
172
173 // Display Medium Roboto light 60 -0.5
174 expect(theme.displayMedium!.fontFamily, 'Roboto');
175 expect(theme.displayMedium!.fontWeight, light);
176 expect(theme.displayMedium!.fontSize, 60);
177 expect(theme.displayMedium!.letterSpacing, -0.5);
178
179 // Display Small Roboto regular 48 0
180 expect(theme.displaySmall!.fontFamily, 'Roboto');
181 expect(theme.displaySmall!.fontWeight, regular);
182 expect(theme.displaySmall!.fontSize, 48);
183 expect(theme.displaySmall!.letterSpacing, 0);
184
185 // Headline Large (from Material 3 for backwards compatibility) Roboto regular 40 0.25
186 expect(theme.headlineLarge!.fontFamily, 'Roboto');
187 expect(theme.headlineLarge!.fontWeight, regular);
188 expect(theme.headlineLarge!.fontSize, 40);
189 expect(theme.headlineLarge!.letterSpacing, 0.25);
190
191 // Headline Medium Roboto regular 34 0.25
192 expect(theme.headlineMedium!.fontFamily, 'Roboto');
193 expect(theme.headlineMedium!.fontWeight, regular);
194 expect(theme.headlineMedium!.fontSize, 34);
195 expect(theme.headlineMedium!.letterSpacing, 0.25);
196
197 // Headline Small Roboto regular 24 0
198 expect(theme.headlineSmall!.fontFamily, 'Roboto');
199 expect(theme.headlineSmall!.fontWeight, regular);
200 expect(theme.headlineSmall!.fontSize, 24);
201 expect(theme.headlineSmall!.letterSpacing, 0);
202
203 // Title Large Roboto medium 20 0.15
204 expect(theme.titleLarge!.fontFamily, 'Roboto');
205 expect(theme.titleLarge!.fontWeight, medium);
206 expect(theme.titleLarge!.fontSize, 20);
207 expect(theme.titleLarge!.letterSpacing, 0.15);
208
209 // Title Medium Roboto regular 16 0.15
210 expect(theme.titleMedium!.fontFamily, 'Roboto');
211 expect(theme.titleMedium!.fontWeight, regular);
212 expect(theme.titleMedium!.fontSize, 16);
213 expect(theme.titleMedium!.letterSpacing, 0.15);
214
215 // Title Small Roboto medium 14 0.1
216 expect(theme.titleSmall!.fontFamily, 'Roboto');
217 expect(theme.titleSmall!.fontWeight, medium);
218 expect(theme.titleSmall!.fontSize, 14);
219 expect(theme.titleSmall!.letterSpacing, 0.1);
220
221 // Body Large Roboto regular 16 0.5
222 expect(theme.bodyLarge!.fontFamily, 'Roboto');
223 expect(theme.bodyLarge!.fontWeight, regular);
224 expect(theme.bodyLarge!.fontSize, 16);
225 expect(theme.bodyLarge!.letterSpacing, 0.5);
226
227 // Body Medium Roboto regular 14 0.25
228 expect(theme.bodyMedium!.fontFamily, 'Roboto');
229 expect(theme.bodyMedium!.fontWeight, regular);
230 expect(theme.bodyMedium!.fontSize, 14);
231 expect(theme.bodyMedium!.letterSpacing, 0.25);
232
233 // Body Small Roboto regular 12 0.4
234 expect(theme.bodySmall!.fontFamily, 'Roboto');
235 expect(theme.bodySmall!.fontWeight, regular);
236 expect(theme.bodySmall!.fontSize, 12);
237 expect(theme.bodySmall!.letterSpacing, 0.4);
238
239 // Label Large Roboto medium 14 1.25
240 expect(theme.labelLarge!.fontFamily, 'Roboto');
241 expect(theme.labelLarge!.fontWeight, medium);
242 expect(theme.labelLarge!.fontSize, 14);
243 expect(theme.labelLarge!.letterSpacing, 1.25);
244
245 // Label Medium (from Material 3 for backwards compatibility) Roboto regular 11 1.5
246 expect(theme.labelMedium!.fontFamily, 'Roboto');
247 expect(theme.labelMedium!.fontWeight, regular);
248 expect(theme.labelMedium!.fontSize, 11);
249 expect(theme.labelMedium!.letterSpacing, 1.5);
250
251 // Label Small Roboto regular 10 1.5
252 expect(theme.labelSmall!.fontFamily, 'Roboto');
253 expect(theme.labelSmall!.fontWeight, regular);
254 expect(theme.labelSmall!.fontSize, 10);
255 expect(theme.labelSmall!.letterSpacing, 1.5);
256 });
257
258 test('englishLike2021 TextTheme matches Material Design 3 spec', () {
259 // Check the default material text theme against the style values
260 // shown https://m3.material.io/styles/typography/tokens.
261 //
262 // This may need to be updated if the token values change.
263 final TextTheme theme = Typography.englishLike2021.merge(Typography.blackMountainView);
264
265 // Display large
266 expect(theme.displayLarge!.fontFamily, 'Roboto');
267 expect(theme.displayLarge!.fontSize, 57.0);
268 expect(theme.displayLarge!.fontWeight, FontWeight.w400);
269 expect(theme.displayLarge!.letterSpacing, -0.25);
270 expect(theme.displayLarge!.height, 1.12);
271 expect(theme.displayLarge!.textBaseline, TextBaseline.alphabetic);
272 expect(theme.displayLarge!.leadingDistribution, TextLeadingDistribution.even);
273
274 // Display medium
275 expect(theme.displayMedium!.fontFamily, 'Roboto');
276 expect(theme.displayMedium!.fontSize, 45.0);
277 expect(theme.displayMedium!.fontWeight, FontWeight.w400);
278 expect(theme.displayMedium!.letterSpacing, 0.0);
279 expect(theme.displayMedium!.height, 1.16);
280 expect(theme.displayMedium!.textBaseline, TextBaseline.alphabetic);
281 expect(theme.displayMedium!.leadingDistribution, TextLeadingDistribution.even);
282
283 // Display small
284 expect(theme.displaySmall!.fontFamily, 'Roboto');
285 expect(theme.displaySmall!.fontSize, 36.0);
286 expect(theme.displaySmall!.fontWeight, FontWeight.w400);
287 expect(theme.displaySmall!.letterSpacing, 0.0);
288 expect(theme.displaySmall!.height, 1.22);
289 expect(theme.displaySmall!.textBaseline, TextBaseline.alphabetic);
290 expect(theme.displaySmall!.leadingDistribution, TextLeadingDistribution.even);
291
292 // Headline large
293 expect(theme.headlineLarge!.fontFamily, 'Roboto');
294 expect(theme.headlineLarge!.fontSize, 32.0);
295 expect(theme.headlineLarge!.fontWeight, FontWeight.w400);
296 expect(theme.headlineLarge!.letterSpacing, 0.0);
297 expect(theme.headlineLarge!.height, 1.25);
298 expect(theme.headlineLarge!.textBaseline, TextBaseline.alphabetic);
299 expect(theme.headlineLarge!.leadingDistribution, TextLeadingDistribution.even);
300
301 // Headline medium
302 expect(theme.headlineMedium!.fontFamily, 'Roboto');
303 expect(theme.headlineMedium!.fontSize, 28.0);
304 expect(theme.headlineMedium!.fontWeight, FontWeight.w400);
305 expect(theme.headlineMedium!.letterSpacing, 0.0);
306 expect(theme.headlineMedium!.height, 1.29);
307 expect(theme.headlineMedium!.textBaseline, TextBaseline.alphabetic);
308 expect(theme.headlineMedium!.leadingDistribution, TextLeadingDistribution.even);
309
310 // Headline small
311 expect(theme.headlineSmall!.fontFamily, 'Roboto');
312 expect(theme.headlineSmall!.fontSize, 24.0);
313 expect(theme.headlineSmall!.fontWeight, FontWeight.w400);
314 expect(theme.headlineSmall!.letterSpacing, 0.0);
315 expect(theme.headlineSmall!.height, 1.33);
316 expect(theme.headlineSmall!.textBaseline, TextBaseline.alphabetic);
317 expect(theme.headlineSmall!.leadingDistribution, TextLeadingDistribution.even);
318
319 // Title large
320 expect(theme.titleLarge!.fontFamily, 'Roboto');
321 expect(theme.titleLarge!.fontSize, 22.0);
322 expect(theme.titleLarge!.fontWeight, FontWeight.w400);
323 expect(theme.titleLarge!.letterSpacing, 0.0);
324 expect(theme.titleLarge!.height, 1.27);
325 expect(theme.titleLarge!.textBaseline, TextBaseline.alphabetic);
326 expect(theme.titleLarge!.leadingDistribution, TextLeadingDistribution.even);
327
328 // Title medium
329 expect(theme.titleMedium!.fontFamily, 'Roboto');
330 expect(theme.titleMedium!.fontSize, 16.0);
331 expect(theme.titleMedium!.fontWeight, FontWeight.w500);
332 expect(theme.titleMedium!.letterSpacing, 0.15);
333 expect(theme.titleMedium!.height, 1.50);
334 expect(theme.titleMedium!.textBaseline, TextBaseline.alphabetic);
335 expect(theme.titleMedium!.leadingDistribution, TextLeadingDistribution.even);
336
337 // Title small
338 expect(theme.titleSmall!.fontFamily, 'Roboto');
339 expect(theme.titleSmall!.fontSize, 14.0);
340 expect(theme.titleSmall!.fontWeight, FontWeight.w500);
341 expect(theme.titleSmall!.letterSpacing, 0.1);
342 expect(theme.titleSmall!.height, 1.43);
343 expect(theme.titleSmall!.textBaseline, TextBaseline.alphabetic);
344 expect(theme.titleSmall!.leadingDistribution, TextLeadingDistribution.even);
345
346 // Label large
347 expect(theme.labelLarge!.fontFamily, 'Roboto');
348 expect(theme.labelLarge!.fontSize, 14.0);
349 expect(theme.labelLarge!.fontWeight, FontWeight.w500);
350 expect(theme.labelLarge!.letterSpacing, 0.1);
351 expect(theme.labelLarge!.height, 1.43);
352 expect(theme.labelLarge!.textBaseline, TextBaseline.alphabetic);
353 expect(theme.labelLarge!.leadingDistribution, TextLeadingDistribution.even);
354
355 // Label medium
356 expect(theme.labelMedium!.fontFamily, 'Roboto');
357 expect(theme.labelMedium!.fontSize, 12.0);
358 expect(theme.labelMedium!.fontWeight, FontWeight.w500);
359 expect(theme.labelMedium!.letterSpacing, 0.5);
360 expect(theme.labelMedium!.height, 1.33);
361 expect(theme.labelMedium!.textBaseline, TextBaseline.alphabetic);
362 expect(theme.labelMedium!.leadingDistribution, TextLeadingDistribution.even);
363
364 // Label small
365 expect(theme.labelSmall!.fontFamily, 'Roboto');
366 expect(theme.labelSmall!.fontSize, 11.0);
367 expect(theme.labelSmall!.fontWeight, FontWeight.w500);
368 expect(theme.labelSmall!.letterSpacing, 0.5);
369 expect(theme.labelSmall!.height, 1.45);
370 expect(theme.labelSmall!.textBaseline, TextBaseline.alphabetic);
371 expect(theme.labelSmall!.leadingDistribution, TextLeadingDistribution.even);
372
373 // Body large
374 expect(theme.bodyLarge!.fontFamily, 'Roboto');
375 expect(theme.bodyLarge!.fontSize, 16.0);
376 expect(theme.bodyLarge!.fontWeight, FontWeight.w400);
377 expect(theme.bodyLarge!.letterSpacing, 0.5);
378 expect(theme.bodyLarge!.height, 1.50);
379 expect(theme.bodyLarge!.textBaseline, TextBaseline.alphabetic);
380 expect(theme.bodyLarge!.leadingDistribution, TextLeadingDistribution.even);
381
382 // Body medium
383 expect(theme.bodyMedium!.fontFamily, 'Roboto');
384 expect(theme.bodyMedium!.fontSize, 14.0);
385 expect(theme.bodyMedium!.fontWeight, FontWeight.w400);
386 expect(theme.bodyMedium!.letterSpacing, 0.25);
387 expect(theme.bodyMedium!.height, 1.43);
388 expect(theme.bodyMedium!.textBaseline, TextBaseline.alphabetic);
389 expect(theme.bodyMedium!.leadingDistribution, TextLeadingDistribution.even);
390
391 // Body small
392 expect(theme.bodySmall!.fontFamily, 'Roboto');
393 expect(theme.bodySmall!.fontSize, 12.0);
394 expect(theme.bodySmall!.fontWeight, FontWeight.w400);
395 expect(theme.bodySmall!.letterSpacing, 0.4);
396 expect(theme.bodySmall!.height, 1.33);
397 expect(theme.bodySmall!.textBaseline, TextBaseline.alphabetic);
398 expect(theme.bodySmall!.leadingDistribution, TextLeadingDistribution.even);
399 });
400
401 test('Default M3 light textTheme styles all use onSurface', () {
402 final ThemeData theme = ThemeData();
403 final TextTheme textTheme = theme.textTheme;
404 final Color dark = theme.colorScheme.onSurface;
405 expect(textTheme.displayLarge!.color, dark);
406 expect(textTheme.displayMedium!.color, dark);
407 expect(textTheme.displaySmall!.color, dark);
408 expect(textTheme.headlineLarge!.color, dark);
409 expect(textTheme.headlineMedium!.color, dark);
410 expect(textTheme.headlineSmall!.color, dark);
411 expect(textTheme.titleLarge!.color, dark);
412 expect(textTheme.titleMedium!.color, dark);
413 expect(textTheme.titleSmall!.color, dark);
414 expect(textTheme.bodyLarge!.color, dark);
415 expect(textTheme.bodyMedium!.color, dark);
416 expect(textTheme.bodySmall!.color, dark);
417 expect(textTheme.labelLarge!.color, dark);
418 expect(textTheme.labelMedium!.color, dark);
419 expect(textTheme.labelSmall!.color, dark);
420 });
421
422 test('Default M3 dark textTheme styles all use onSurface', () {
423 final ThemeData theme = ThemeData(brightness: Brightness.dark);
424 final TextTheme textTheme = theme.textTheme;
425 final Color light = theme.colorScheme.onSurface;
426 expect(textTheme.displayLarge!.color, light);
427 expect(textTheme.displayMedium!.color, light);
428 expect(textTheme.displaySmall!.color, light);
429 expect(textTheme.headlineLarge!.color, light);
430 expect(textTheme.headlineMedium!.color, light);
431 expect(textTheme.headlineSmall!.color, light);
432 expect(textTheme.titleLarge!.color, light);
433 expect(textTheme.titleMedium!.color, light);
434 expect(textTheme.titleSmall!.color, light);
435 expect(textTheme.bodyLarge!.color, light);
436 expect(textTheme.bodyMedium!.color, light);
437 expect(textTheme.bodySmall!.color, light);
438 expect(textTheme.labelLarge!.color, light);
439 expect(textTheme.labelMedium!.color, light);
440 expect(textTheme.labelSmall!.color, light);
441 });
442}
443

Provided by KDAB

Privacy Policy
Learn more about Flutter for embedded and desktop on industrialflutter.com