| // Copyright 2014 The Flutter Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| import 'package:flutter/foundation.dart'; |
| import 'package:flutter/material.dart'; |
| import 'package:flutter_test/flutter_test.dart'; |
| |
| void main() { |
| test('Typography is defined for all target platforms', () { |
| for (final TargetPlatform platform in TargetPlatform.values) { |
| final Typography typography = Typography.material2018(platform: platform); |
| expect(typography, isNotNull, reason: 'null typography for $platform'); |
| expect(typography.black, isNotNull, reason: 'null black typography for $platform'); |
| expect(typography.white, isNotNull, reason: 'null white typography for $platform'); |
| } |
| }); |
| |
| test('Typography on non-Apple platforms defaults to the correct font', () { |
| expect(Typography.material2018().black.titleLarge!.fontFamily, 'Roboto'); |
| expect(Typography.material2018(platform: TargetPlatform.fuchsia).black.titleLarge!.fontFamily, 'Roboto'); |
| expect(Typography.material2018(platform: TargetPlatform.linux).black.titleLarge!.fontFamily, 'Roboto'); |
| expect(Typography.material2018(platform: TargetPlatform.linux).black.titleLarge!.fontFamilyFallback, <String>['Ubuntu', 'Cantarell', 'DejaVu Sans', 'Liberation Sans', 'Arial']); |
| expect(Typography.material2018(platform: TargetPlatform.windows).black.titleLarge!.fontFamily, 'Segoe UI'); |
| expect(Typography.material2018().white.titleLarge!.fontFamily, 'Roboto'); |
| expect(Typography.material2018(platform: TargetPlatform.fuchsia).white.titleLarge!.fontFamily, 'Roboto'); |
| expect(Typography.material2018(platform: TargetPlatform.linux).white.titleLarge!.fontFamily, 'Roboto'); |
| expect(Typography.material2018(platform: TargetPlatform.linux).white.titleLarge!.fontFamilyFallback, <String>['Ubuntu', 'Cantarell', 'DejaVu Sans', 'Liberation Sans', 'Arial']); |
| expect(Typography.material2018(platform: TargetPlatform.windows).white.titleLarge!.fontFamily, 'Segoe UI'); |
| }); |
| |
| // Ref: https://developer.apple.com/ios/human-interface-guidelines/visual-design/typography/ |
| final Matcher isSanFranciscoDisplayFont = predicate((TextStyle s) { |
| return s.fontFamily == '.SF UI Display'; |
| }, 'Uses SF Display font'); |
| |
| final Matcher isSanFranciscoTextFont = predicate((TextStyle s) { |
| return s.fontFamily == '.SF UI Text'; |
| }, 'Uses SF Text font'); |
| |
| final Matcher isMacOSSanFranciscoMetaFont = predicate((TextStyle s) { |
| return s.fontFamily == '.AppleSystemUIFont'; |
| }, 'Uses macOS system meta-font'); |
| |
| test('Typography on iOS defaults to the correct SF font family based on size', () { |
| final Typography typography = Typography.material2018(platform: TargetPlatform.iOS); |
| for (final TextTheme textTheme in <TextTheme>[typography.black, typography.white]) { |
| expect(textTheme.displayLarge, isSanFranciscoDisplayFont); |
| expect(textTheme.displayMedium, isSanFranciscoDisplayFont); |
| expect(textTheme.displaySmall, isSanFranciscoDisplayFont); |
| expect(textTheme.headlineLarge, isSanFranciscoDisplayFont); |
| expect(textTheme.headlineMedium, isSanFranciscoDisplayFont); |
| expect(textTheme.headlineSmall, isSanFranciscoDisplayFont); |
| expect(textTheme.titleLarge, isSanFranciscoDisplayFont); |
| expect(textTheme.titleMedium, isSanFranciscoTextFont); |
| expect(textTheme.titleSmall, isSanFranciscoTextFont); |
| expect(textTheme.bodyLarge, isSanFranciscoTextFont); |
| expect(textTheme.bodyMedium, isSanFranciscoTextFont); |
| expect(textTheme.bodySmall, isSanFranciscoTextFont); |
| expect(textTheme.labelLarge, isSanFranciscoTextFont); |
| expect(textTheme.labelMedium, isSanFranciscoTextFont); |
| expect(textTheme.labelSmall, isSanFranciscoTextFont); |
| } |
| }); |
| |
| test('Typography on macOS defaults to the system UI meta-font', () { |
| final Typography typography = Typography.material2018(platform: TargetPlatform.macOS); |
| for (final TextTheme textTheme in <TextTheme>[typography.black, typography.white]) { |
| expect(textTheme.displayLarge, isMacOSSanFranciscoMetaFont); |
| expect(textTheme.displayMedium, isMacOSSanFranciscoMetaFont); |
| expect(textTheme.displaySmall, isMacOSSanFranciscoMetaFont); |
| expect(textTheme.headlineLarge, isMacOSSanFranciscoMetaFont); |
| expect(textTheme.headlineMedium, isMacOSSanFranciscoMetaFont); |
| expect(textTheme.headlineSmall, isMacOSSanFranciscoMetaFont); |
| expect(textTheme.titleLarge, isMacOSSanFranciscoMetaFont); |
| expect(textTheme.titleMedium, isMacOSSanFranciscoMetaFont); |
| expect(textTheme.titleSmall, isMacOSSanFranciscoMetaFont); |
| expect(textTheme.bodyLarge, isMacOSSanFranciscoMetaFont); |
| expect(textTheme.bodyMedium, isMacOSSanFranciscoMetaFont); |
| expect(textTheme.bodySmall, isMacOSSanFranciscoMetaFont); |
| expect(textTheme.labelLarge, isMacOSSanFranciscoMetaFont); |
| expect(textTheme.labelMedium, isMacOSSanFranciscoMetaFont); |
| expect(textTheme.labelSmall, isMacOSSanFranciscoMetaFont); |
| } |
| }); |
| |
| testWidgets('Typography implements debugFillProperties', (WidgetTester tester) async { |
| final DiagnosticPropertiesBuilder builder = DiagnosticPropertiesBuilder(); |
| Typography.material2014( |
| black: Typography.blackCupertino, |
| white: Typography.whiteCupertino, |
| englishLike: Typography.englishLike2018, |
| dense: Typography.dense2018, |
| tall: Typography.tall2018, |
| ).debugFillProperties(builder); |
| |
| final List<String> nonDefaultPropertyNames = builder.properties |
| .where((DiagnosticsNode node) => !node.isFiltered(DiagnosticLevel.info)) |
| .map((DiagnosticsNode node) => node.name!).toList(); |
| |
| expect(nonDefaultPropertyNames, <String>['black', 'white', 'englishLike', 'dense', 'tall']); |
| }); |
| |
| test('Can lerp between different typographies', () { |
| final List<Typography> all = <Typography>[ |
| for (final TargetPlatform platform in TargetPlatform.values) Typography.material2014(platform: platform), |
| for (final TargetPlatform platform in TargetPlatform.values) Typography.material2018(platform: platform), |
| for (final TargetPlatform platform in TargetPlatform.values) Typography.material2021(platform: platform), |
| ]; |
| |
| for (final Typography fromTypography in all) { |
| for (final Typography toTypegraphy in all) { |
| Object? error; |
| try { |
| Typography.lerp(fromTypography, toTypegraphy, 0.5); |
| } catch (e) { |
| error = e; |
| } |
| expect(error, isNull); |
| } |
| } |
| }); |
| |
| test('englishLike2018 TextTheme matches Material Design spec', () { |
| // Check the default material text theme against the style values |
| // shown https://material.io/design/typography/#type-scale. |
| |
| final TextTheme theme = Typography.englishLike2018.merge(Typography.blackMountainView); |
| const FontWeight light = FontWeight.w300; |
| const FontWeight regular = FontWeight.w400; |
| const FontWeight medium = FontWeight.w500; |
| |
| // H1 Roboto light 96 -1.5 |
| expect(theme.displayLarge!.fontFamily, 'Roboto'); |
| expect(theme.displayLarge!.fontWeight, light); |
| expect(theme.displayLarge!.fontSize, 96); |
| expect(theme.displayLarge!.letterSpacing, -1.5); |
| |
| // H2 Roboto light 60 -0.5 |
| expect(theme.displayMedium!.fontFamily, 'Roboto'); |
| expect(theme.displayMedium!.fontWeight, light); |
| expect(theme.displayMedium!.fontSize, 60); |
| expect(theme.displayMedium!.letterSpacing, -0.5); |
| |
| // H3 Roboto regular 48 0 |
| expect(theme.displaySmall!.fontFamily, 'Roboto'); |
| expect(theme.displaySmall!.fontWeight, regular); |
| expect(theme.displaySmall!.fontSize, 48); |
| expect(theme.displaySmall!.letterSpacing, 0); |
| |
| // Headline Large (from Material 3 for backwards compatibility) Roboto regular 40 0.25 |
| expect(theme.headlineLarge!.fontFamily, 'Roboto'); |
| expect(theme.headlineLarge!.fontWeight, regular); |
| expect(theme.headlineLarge!.fontSize, 40); |
| expect(theme.headlineLarge!.letterSpacing, 0.25); |
| |
| // H4 Roboto regular 34 0.25 |
| expect(theme.headlineMedium!.fontFamily, 'Roboto'); |
| expect(theme.headlineMedium!.fontWeight, regular); |
| expect(theme.headlineMedium!.fontSize, 34); |
| expect(theme.headlineMedium!.letterSpacing, 0.25); |
| |
| // H5 Roboto regular 24 0 |
| expect(theme.headlineSmall!.fontFamily, 'Roboto'); |
| expect(theme.headlineSmall!.fontWeight, regular); |
| expect(theme.headlineSmall!.fontSize, 24); |
| expect(theme.headlineSmall!.letterSpacing, 0); |
| |
| // H6 Roboto medium 20 0.15 |
| expect(theme.titleLarge!.fontFamily, 'Roboto'); |
| expect(theme.titleLarge!.fontWeight, medium); |
| expect(theme.titleLarge!.fontSize, 20); |
| expect(theme.titleLarge!.letterSpacing, 0.15); |
| |
| // Subtitle1 Roboto regular 16 0.15 |
| expect(theme.titleMedium!.fontFamily, 'Roboto'); |
| expect(theme.titleMedium!.fontWeight, regular); |
| expect(theme.titleMedium!.fontSize, 16); |
| expect(theme.titleMedium!.letterSpacing, 0.15); |
| |
| // Subtitle2 Roboto medium 14 0.1 |
| expect(theme.titleSmall!.fontFamily, 'Roboto'); |
| expect(theme.titleSmall!.fontWeight, medium); |
| expect(theme.titleSmall!.fontSize, 14); |
| expect(theme.titleSmall!.letterSpacing, 0.1); |
| |
| // Body1 Roboto regular 16 0.5 |
| expect(theme.bodyLarge!.fontFamily, 'Roboto'); |
| expect(theme.bodyLarge!.fontWeight, regular); |
| expect(theme.bodyLarge!.fontSize, 16); |
| expect(theme.bodyLarge!.letterSpacing, 0.5); |
| |
| // Body2 Roboto regular 14 0.25 |
| expect(theme.bodyMedium!.fontFamily, 'Roboto'); |
| expect(theme.bodyMedium!.fontWeight, regular); |
| expect(theme.bodyMedium!.fontSize, 14); |
| expect(theme.bodyMedium!.letterSpacing, 0.25); |
| |
| // Caption Roboto regular 12 0.4 |
| expect(theme.bodySmall!.fontFamily, 'Roboto'); |
| expect(theme.bodySmall!.fontWeight, regular); |
| expect(theme.bodySmall!.fontSize, 12); |
| expect(theme.bodySmall!.letterSpacing, 0.4); |
| |
| // BUTTON Roboto medium 14 1.25 |
| expect(theme.labelLarge!.fontFamily, 'Roboto'); |
| expect(theme.labelLarge!.fontWeight, medium); |
| expect(theme.labelLarge!.fontSize, 14); |
| expect(theme.labelLarge!.letterSpacing, 1.25); |
| |
| // Label Medium (from Material 3 for backwards compatibility) Roboto regular 11 1.5 |
| expect(theme.labelMedium!.fontFamily, 'Roboto'); |
| expect(theme.labelMedium!.fontWeight, regular); |
| expect(theme.labelMedium!.fontSize, 11); |
| expect(theme.labelMedium!.letterSpacing, 1.5); |
| |
| // OVERLINE Roboto regular 10 1.5 |
| expect(theme.labelSmall!.fontFamily, 'Roboto'); |
| expect(theme.labelSmall!.fontWeight, regular); |
| expect(theme.labelSmall!.fontSize, 10); |
| expect(theme.labelSmall!.letterSpacing, 1.5); |
| }); |
| |
| test('englishLike2021 TextTheme matches Material Design 3 spec', () { |
| // Check the default material text theme against the style values |
| // shown https://m3.material.io/styles/typography/tokens. |
| // |
| // This may need to be updated if the token values change. |
| final TextTheme theme = Typography.englishLike2021.merge(Typography.blackMountainView); |
| |
| // Display large |
| expect(theme.displayLarge!.fontFamily, 'Roboto'); |
| expect(theme.displayLarge!.fontSize, 57.0); |
| expect(theme.displayLarge!.fontWeight, FontWeight.w400); |
| expect(theme.displayLarge!.letterSpacing, -0.25); |
| expect(theme.displayLarge!.height, 1.12); |
| expect(theme.displayLarge!.textBaseline, TextBaseline.alphabetic); |
| expect(theme.displayLarge!.leadingDistribution, TextLeadingDistribution.even); |
| |
| // Display medium |
| expect(theme.displayMedium!.fontFamily, 'Roboto'); |
| expect(theme.displayMedium!.fontSize, 45.0); |
| expect(theme.displayMedium!.fontWeight, FontWeight.w400); |
| expect(theme.displayMedium!.letterSpacing, 0.0); |
| expect(theme.displayMedium!.height, 1.16); |
| expect(theme.displayMedium!.textBaseline, TextBaseline.alphabetic); |
| expect(theme.displayMedium!.leadingDistribution, TextLeadingDistribution.even); |
| |
| // Display small |
| expect(theme.displaySmall!.fontFamily, 'Roboto'); |
| expect(theme.displaySmall!.fontSize, 36.0); |
| expect(theme.displaySmall!.fontWeight, FontWeight.w400); |
| expect(theme.displaySmall!.letterSpacing, 0.0); |
| expect(theme.displaySmall!.height, 1.22); |
| expect(theme.displaySmall!.textBaseline, TextBaseline.alphabetic); |
| expect(theme.displaySmall!.leadingDistribution, TextLeadingDistribution.even); |
| |
| // Headline large |
| expect(theme.headlineLarge!.fontFamily, 'Roboto'); |
| expect(theme.headlineLarge!.fontSize, 32.0); |
| expect(theme.headlineLarge!.fontWeight, FontWeight.w400); |
| expect(theme.headlineLarge!.letterSpacing, 0.0); |
| expect(theme.headlineLarge!.height, 1.25); |
| expect(theme.headlineLarge!.textBaseline, TextBaseline.alphabetic); |
| expect(theme.headlineLarge!.leadingDistribution, TextLeadingDistribution.even); |
| |
| // Headline medium |
| expect(theme.headlineMedium!.fontFamily, 'Roboto'); |
| expect(theme.headlineMedium!.fontSize, 28.0); |
| expect(theme.headlineMedium!.fontWeight, FontWeight.w400); |
| expect(theme.headlineMedium!.letterSpacing, 0.0); |
| expect(theme.headlineMedium!.height, 1.29); |
| expect(theme.headlineMedium!.textBaseline, TextBaseline.alphabetic); |
| expect(theme.headlineMedium!.leadingDistribution, TextLeadingDistribution.even); |
| |
| // Headline small |
| expect(theme.headlineSmall!.fontFamily, 'Roboto'); |
| expect(theme.headlineSmall!.fontSize, 24.0); |
| expect(theme.headlineSmall!.fontWeight, FontWeight.w400); |
| expect(theme.headlineSmall!.letterSpacing, 0.0); |
| expect(theme.headlineSmall!.height, 1.33); |
| expect(theme.headlineSmall!.textBaseline, TextBaseline.alphabetic); |
| expect(theme.headlineSmall!.leadingDistribution, TextLeadingDistribution.even); |
| |
| // Title large |
| expect(theme.titleLarge!.fontFamily, 'Roboto'); |
| expect(theme.titleLarge!.fontSize, 22.0); |
| expect(theme.titleLarge!.fontWeight, FontWeight.w400); |
| expect(theme.titleLarge!.letterSpacing, 0.0); |
| expect(theme.titleLarge!.height, 1.27); |
| expect(theme.titleLarge!.textBaseline, TextBaseline.alphabetic); |
| expect(theme.titleLarge!.leadingDistribution, TextLeadingDistribution.even); |
| |
| // Title medium |
| expect(theme.titleMedium!.fontFamily, 'Roboto'); |
| expect(theme.titleMedium!.fontSize, 16.0); |
| expect(theme.titleMedium!.fontWeight, FontWeight.w500); |
| expect(theme.titleMedium!.letterSpacing, 0.15); |
| expect(theme.titleMedium!.height, 1.50); |
| expect(theme.titleMedium!.textBaseline, TextBaseline.alphabetic); |
| expect(theme.titleMedium!.leadingDistribution, TextLeadingDistribution.even); |
| |
| // Title small |
| expect(theme.titleSmall!.fontFamily, 'Roboto'); |
| expect(theme.titleSmall!.fontSize, 14.0); |
| expect(theme.titleSmall!.fontWeight, FontWeight.w500); |
| expect(theme.titleSmall!.letterSpacing, 0.1); |
| expect(theme.titleSmall!.height, 1.43); |
| expect(theme.titleSmall!.textBaseline, TextBaseline.alphabetic); |
| expect(theme.titleSmall!.leadingDistribution, TextLeadingDistribution.even); |
| |
| // Label large |
| expect(theme.labelLarge!.fontFamily, 'Roboto'); |
| expect(theme.labelLarge!.fontSize, 14.0); |
| expect(theme.labelLarge!.fontWeight, FontWeight.w500); |
| expect(theme.labelLarge!.letterSpacing, 0.1); |
| expect(theme.labelLarge!.height, 1.43); |
| expect(theme.labelLarge!.textBaseline, TextBaseline.alphabetic); |
| expect(theme.labelLarge!.leadingDistribution, TextLeadingDistribution.even); |
| |
| // Label medium |
| expect(theme.labelMedium!.fontFamily, 'Roboto'); |
| expect(theme.labelMedium!.fontSize, 12.0); |
| expect(theme.labelMedium!.fontWeight, FontWeight.w500); |
| expect(theme.labelMedium!.letterSpacing, 0.5); |
| expect(theme.labelMedium!.height, 1.33); |
| expect(theme.labelMedium!.textBaseline, TextBaseline.alphabetic); |
| expect(theme.labelMedium!.leadingDistribution, TextLeadingDistribution.even); |
| |
| // Label small |
| expect(theme.labelSmall!.fontFamily, 'Roboto'); |
| expect(theme.labelSmall!.fontSize, 11.0); |
| expect(theme.labelSmall!.fontWeight, FontWeight.w500); |
| expect(theme.labelSmall!.letterSpacing, 0.5); |
| expect(theme.labelSmall!.height, 1.45); |
| expect(theme.labelSmall!.textBaseline, TextBaseline.alphabetic); |
| expect(theme.labelSmall!.leadingDistribution, TextLeadingDistribution.even); |
| |
| // Body large |
| expect(theme.bodyLarge!.fontFamily, 'Roboto'); |
| expect(theme.bodyLarge!.fontSize, 16.0); |
| expect(theme.bodyLarge!.fontWeight, FontWeight.w400); |
| expect(theme.bodyLarge!.letterSpacing, 0.5); |
| expect(theme.bodyLarge!.height, 1.50); |
| expect(theme.bodyLarge!.textBaseline, TextBaseline.alphabetic); |
| expect(theme.bodyLarge!.leadingDistribution, TextLeadingDistribution.even); |
| |
| // Body medium |
| expect(theme.bodyMedium!.fontFamily, 'Roboto'); |
| expect(theme.bodyMedium!.fontSize, 14.0); |
| expect(theme.bodyMedium!.fontWeight, FontWeight.w400); |
| expect(theme.bodyMedium!.letterSpacing, 0.25); |
| expect(theme.bodyMedium!.height, 1.43); |
| expect(theme.bodyMedium!.textBaseline, TextBaseline.alphabetic); |
| expect(theme.bodyMedium!.leadingDistribution, TextLeadingDistribution.even); |
| |
| // Body small |
| expect(theme.bodySmall!.fontFamily, 'Roboto'); |
| expect(theme.bodySmall!.fontSize, 12.0); |
| expect(theme.bodySmall!.fontWeight, FontWeight.w400); |
| expect(theme.bodySmall!.letterSpacing, 0.4); |
| expect(theme.bodySmall!.height, 1.33); |
| expect(theme.bodySmall!.textBaseline, TextBaseline.alphabetic); |
| expect(theme.bodySmall!.leadingDistribution, TextLeadingDistribution.even); |
| }); |
| |
| test('Default M3 light textTheme styles all use onSurface', () { |
| final ThemeData theme = ThemeData(useMaterial3: true); |
| final TextTheme textTheme = theme.textTheme; |
| final Color dark = theme.colorScheme.onSurface; |
| expect(textTheme.displayLarge!.color, dark); |
| expect(textTheme.displayMedium!.color, dark); |
| expect(textTheme.displaySmall!.color, dark); |
| expect(textTheme.headlineLarge!.color, dark); |
| expect(textTheme.headlineMedium!.color, dark); |
| expect(textTheme.headlineSmall!.color, dark); |
| expect(textTheme.titleLarge!.color, dark); |
| expect(textTheme.titleMedium!.color, dark); |
| expect(textTheme.titleSmall!.color, dark); |
| expect(textTheme.bodyLarge!.color, dark); |
| expect(textTheme.bodyMedium!.color, dark); |
| expect(textTheme.bodySmall!.color, dark); |
| expect(textTheme.labelLarge!.color, dark); |
| expect(textTheme.labelMedium!.color, dark); |
| expect(textTheme.labelSmall!.color, dark); |
| }); |
| |
| test('Default M3 dark textTheme styles all use onSurface', () { |
| final ThemeData theme = ThemeData(useMaterial3: true, brightness: Brightness.dark); |
| final TextTheme textTheme = theme.textTheme; |
| final Color light = theme.colorScheme.onSurface; |
| expect(textTheme.displayLarge!.color, light); |
| expect(textTheme.displayMedium!.color, light); |
| expect(textTheme.displaySmall!.color, light); |
| expect(textTheme.headlineLarge!.color, light); |
| expect(textTheme.headlineMedium!.color, light); |
| expect(textTheme.headlineSmall!.color, light); |
| expect(textTheme.titleLarge!.color, light); |
| expect(textTheme.titleMedium!.color, light); |
| expect(textTheme.titleSmall!.color, light); |
| expect(textTheme.bodyLarge!.color, light); |
| expect(textTheme.bodyMedium!.color, light); |
| expect(textTheme.bodySmall!.color, light); |
| expect(textTheme.labelLarge!.color, light); |
| expect(textTheme.labelMedium!.color, light); |
| expect(textTheme.labelSmall!.color, light); |
| }); |
| } |