blob: 562b4301f260dc0b593e797821e5e6d3234eff8d [file] [log] [blame] [edit]
// 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);
});
}