Files
gopeed/ui/flutter/test/shared/theme/app_component_themes_test.dart
T

121 lines
4.2 KiB
Dart

import 'package:flutter/widgets.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:gopeed/shared/theme/app_component_themes.dart';
import 'package:gopeed/shared/theme/app_design_tokens.dart';
import 'package:gopeed/shared/theme/app_palette.dart';
import 'package:gopeed/shared/theme/app_theme.dart';
import 'package:shadcn_flutter/shadcn_flutter.dart' as shad;
void main() {
testWidgets('provides the standard text field appearance', (tester) async {
late shad.TextFieldTheme textFieldTheme;
await tester.pumpWidget(
shad.ShadcnApp(
theme: AppTheme.light(),
materialTheme: AppTheme.materialLight(),
home: AppComponentThemes(
child: Builder(
builder: (context) {
textFieldTheme = shad.ComponentTheme.of<shad.TextFieldTheme>(context);
return const SizedBox();
},
),
),
),
);
expect(textFieldTheme.filled, isTrue);
expect(textFieldTheme.border, Border.all(color: AppPalette.light.border));
expect(textFieldTheme.borderRadius, BorderRadius.circular(AppDesignTokens.controlRadius));
expect(textFieldTheme.padding, AppDesignTokens.textFieldPadding);
});
testWidgets('provides the standard checkbox metrics', (tester) async {
late shad.CheckboxTheme checkboxTheme;
await tester.pumpWidget(
shad.ShadcnApp(
theme: AppTheme.light(),
materialTheme: AppTheme.materialLight(),
home: AppComponentThemes(
child: Builder(
builder: (context) {
checkboxTheme = shad.ComponentTheme.of<shad.CheckboxTheme>(context);
return const SizedBox();
},
),
),
),
);
expect(checkboxTheme.size, AppDesignTokens.checkboxSize);
expect(checkboxTheme.gap, AppDesignTokens.checkboxLabelGap);
});
testWidgets('uses a high-contrast checkbox border in the dark theme', (tester) async {
late shad.CheckboxTheme checkboxTheme;
await tester.pumpWidget(
shad.ShadcnApp(
theme: AppTheme.dark(),
materialTheme: AppTheme.materialDark(),
home: AppComponentThemes(
child: Builder(
builder: (context) {
checkboxTheme = shad.ComponentTheme.of<shad.CheckboxTheme>(context);
return const SizedBox();
},
),
),
),
);
expect(checkboxTheme.borderColor, AppPalette.dark.textMuted);
expect(_contrastRatio(checkboxTheme.borderColor!, AppPalette.dark.bg), greaterThanOrEqualTo(3));
});
testWidgets('uses distinct borderless secondary button fills in the light theme', (tester) async {
late shad.SecondaryButtonTheme buttonTheme;
late BuildContext themedContext;
await tester.pumpWidget(
shad.ShadcnApp(
theme: AppTheme.light(),
materialTheme: AppTheme.materialLight(),
home: AppComponentThemes(
child: Builder(
builder: (context) {
themedContext = context;
buttonTheme = shad.ComponentTheme.of<shad.SecondaryButtonTheme>(context);
return const SizedBox();
},
),
),
),
);
final decoration =
buttonTheme.decoration!(themedContext, const <WidgetState>{}, const BoxDecoration()) as BoxDecoration;
final hoveredDecoration =
buttonTheme.decoration!(themedContext, const <WidgetState>{WidgetState.hovered}, const BoxDecoration())
as BoxDecoration;
final disabledDecoration =
buttonTheme.decoration!(themedContext, const <WidgetState>{WidgetState.disabled}, const BoxDecoration())
as BoxDecoration;
expect(decoration.border, isNull);
expect(hoveredDecoration.border, isNull);
expect(disabledDecoration.border, isNull);
expect(decoration.color, isNot(AppPalette.light.surfaceSoft));
expect(hoveredDecoration.color, isNot(decoration.color));
});
}
double _contrastRatio(Color first, Color second) {
final firstLuminance = first.computeLuminance();
final secondLuminance = second.computeLuminance();
final lighter = firstLuminance > secondLuminance ? firstLuminance : secondLuminance;
final darker = firstLuminance > secondLuminance ? secondLuminance : firstLuminance;
return (lighter + 0.05) / (darker + 0.05);
}