diff --git a/dart_test.yaml b/dart_test.yaml new file mode 100644 index 000000000..f01b9558c --- /dev/null +++ b/dart_test.yaml @@ -0,0 +1,2 @@ +tags: + golden: diff --git a/lib/src/controls/yaru_icon_button.dart b/lib/src/controls/yaru_icon_button.dart index b5191dd2d..15c716500 100644 --- a/lib/src/controls/yaru_icon_button.dart +++ b/lib/src/controls/yaru_icon_button.dart @@ -63,15 +63,18 @@ class YaruIconButton extends StatelessWidget { }), overlayColor: MaterialStateProperty.resolveWith((states) { if (states.contains(MaterialState.selected)) { + if (states.contains(MaterialState.pressed)) { + return colors.onSurface.withOpacity(0.12); + } if (states.contains(MaterialState.hovered)) { return colors.onSurface.withOpacity(0.08); } if (states.contains(MaterialState.focused)) { return colors.onSurface.withOpacity(0.12); } - if (states.contains(MaterialState.pressed)) { - return colors.onSurface.withOpacity(0.12); - } + } + if (states.contains(MaterialState.pressed)) { + return colors.onSurfaceVariant.withOpacity(0.12); } if (states.contains(MaterialState.hovered)) { return colors.onSurfaceVariant.withOpacity(0.08); @@ -79,9 +82,6 @@ class YaruIconButton extends StatelessWidget { if (states.contains(MaterialState.focused)) { return colors.onSurfaceVariant.withOpacity(0.08); } - if (states.contains(MaterialState.pressed)) { - return colors.onSurfaceVariant.withOpacity(0.12); - } return null; }), ); diff --git a/pubspec.yaml b/pubspec.yaml index 6e25f5b52..c5d386bec 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -15,9 +15,11 @@ dependencies: yaru_icons: ^0.2.4 dev_dependencies: + collection: ^1.16.0 flutter_lints: ^1.0.0 flutter_test: sdk: flutter + golden_toolkit: ^0.13.0 test: ^1.21.4 flutter: diff --git a/test/controls/goldens/yaru_icon_button-disabled-dark.png b/test/controls/goldens/yaru_icon_button-disabled-dark.png new file mode 100644 index 000000000..a70bfb28f Binary files /dev/null and b/test/controls/goldens/yaru_icon_button-disabled-dark.png differ diff --git a/test/controls/goldens/yaru_icon_button-disabled-light.png b/test/controls/goldens/yaru_icon_button-disabled-light.png new file mode 100644 index 000000000..367fd171c Binary files /dev/null and b/test/controls/goldens/yaru_icon_button-disabled-light.png differ diff --git a/test/controls/goldens/yaru_icon_button-focused-dark.png b/test/controls/goldens/yaru_icon_button-focused-dark.png new file mode 100644 index 000000000..46e6655c3 Binary files /dev/null and b/test/controls/goldens/yaru_icon_button-focused-dark.png differ diff --git a/test/controls/goldens/yaru_icon_button-focused-light.png b/test/controls/goldens/yaru_icon_button-focused-light.png new file mode 100644 index 000000000..68065d762 Binary files /dev/null and b/test/controls/goldens/yaru_icon_button-focused-light.png differ diff --git a/test/controls/goldens/yaru_icon_button-hovered-dark.png b/test/controls/goldens/yaru_icon_button-hovered-dark.png new file mode 100644 index 000000000..46e6655c3 Binary files /dev/null and b/test/controls/goldens/yaru_icon_button-hovered-dark.png differ diff --git a/test/controls/goldens/yaru_icon_button-hovered-light.png b/test/controls/goldens/yaru_icon_button-hovered-light.png new file mode 100644 index 000000000..68065d762 Binary files /dev/null and b/test/controls/goldens/yaru_icon_button-hovered-light.png differ diff --git a/test/controls/goldens/yaru_icon_button-normal-dark.png b/test/controls/goldens/yaru_icon_button-normal-dark.png new file mode 100644 index 000000000..ee6bfc5ba Binary files /dev/null and b/test/controls/goldens/yaru_icon_button-normal-dark.png differ diff --git a/test/controls/goldens/yaru_icon_button-normal-light.png b/test/controls/goldens/yaru_icon_button-normal-light.png new file mode 100644 index 000000000..12683c8f4 Binary files /dev/null and b/test/controls/goldens/yaru_icon_button-normal-light.png differ diff --git a/test/controls/goldens/yaru_icon_button-pressed-dark.png b/test/controls/goldens/yaru_icon_button-pressed-dark.png new file mode 100644 index 000000000..39067e328 Binary files /dev/null and b/test/controls/goldens/yaru_icon_button-pressed-dark.png differ diff --git a/test/controls/goldens/yaru_icon_button-pressed-light.png b/test/controls/goldens/yaru_icon_button-pressed-light.png new file mode 100644 index 000000000..5dea3b0ec Binary files /dev/null and b/test/controls/goldens/yaru_icon_button-pressed-light.png differ diff --git a/test/controls/goldens/yaru_icon_button-selected-dark.png b/test/controls/goldens/yaru_icon_button-selected-dark.png new file mode 100644 index 000000000..435528b09 Binary files /dev/null and b/test/controls/goldens/yaru_icon_button-selected-dark.png differ diff --git a/test/controls/goldens/yaru_icon_button-selected-disabled-dark.png b/test/controls/goldens/yaru_icon_button-selected-disabled-dark.png new file mode 100644 index 000000000..1c407f04c Binary files /dev/null and b/test/controls/goldens/yaru_icon_button-selected-disabled-dark.png differ diff --git a/test/controls/goldens/yaru_icon_button-selected-disabled-light.png b/test/controls/goldens/yaru_icon_button-selected-disabled-light.png new file mode 100644 index 000000000..03e1cea89 Binary files /dev/null and b/test/controls/goldens/yaru_icon_button-selected-disabled-light.png differ diff --git a/test/controls/goldens/yaru_icon_button-selected-focused-dark.png b/test/controls/goldens/yaru_icon_button-selected-focused-dark.png new file mode 100644 index 000000000..4780cf622 Binary files /dev/null and b/test/controls/goldens/yaru_icon_button-selected-focused-dark.png differ diff --git a/test/controls/goldens/yaru_icon_button-selected-focused-light.png b/test/controls/goldens/yaru_icon_button-selected-focused-light.png new file mode 100644 index 000000000..f994d1235 Binary files /dev/null and b/test/controls/goldens/yaru_icon_button-selected-focused-light.png differ diff --git a/test/controls/goldens/yaru_icon_button-selected-hovered-dark.png b/test/controls/goldens/yaru_icon_button-selected-hovered-dark.png new file mode 100644 index 000000000..c98790056 Binary files /dev/null and b/test/controls/goldens/yaru_icon_button-selected-hovered-dark.png differ diff --git a/test/controls/goldens/yaru_icon_button-selected-hovered-light.png b/test/controls/goldens/yaru_icon_button-selected-hovered-light.png new file mode 100644 index 000000000..ce8d06b14 Binary files /dev/null and b/test/controls/goldens/yaru_icon_button-selected-hovered-light.png differ diff --git a/test/controls/goldens/yaru_icon_button-selected-light.png b/test/controls/goldens/yaru_icon_button-selected-light.png new file mode 100644 index 000000000..714318f67 Binary files /dev/null and b/test/controls/goldens/yaru_icon_button-selected-light.png differ diff --git a/test/controls/goldens/yaru_icon_button-selected-pressed-dark.png b/test/controls/goldens/yaru_icon_button-selected-pressed-dark.png new file mode 100644 index 000000000..f82f02f26 Binary files /dev/null and b/test/controls/goldens/yaru_icon_button-selected-pressed-dark.png differ diff --git a/test/controls/goldens/yaru_icon_button-selected-pressed-light.png b/test/controls/goldens/yaru_icon_button-selected-pressed-light.png new file mode 100644 index 000000000..5af1d26b6 Binary files /dev/null and b/test/controls/goldens/yaru_icon_button-selected-pressed-light.png differ diff --git a/test/controls/goldens/yaru_icon_button-unselected-dark.png b/test/controls/goldens/yaru_icon_button-unselected-dark.png new file mode 100644 index 000000000..ee6bfc5ba Binary files /dev/null and b/test/controls/goldens/yaru_icon_button-unselected-dark.png differ diff --git a/test/controls/goldens/yaru_icon_button-unselected-disabled-dark.png b/test/controls/goldens/yaru_icon_button-unselected-disabled-dark.png new file mode 100644 index 000000000..a70bfb28f Binary files /dev/null and b/test/controls/goldens/yaru_icon_button-unselected-disabled-dark.png differ diff --git a/test/controls/goldens/yaru_icon_button-unselected-disabled-light.png b/test/controls/goldens/yaru_icon_button-unselected-disabled-light.png new file mode 100644 index 000000000..367fd171c Binary files /dev/null and b/test/controls/goldens/yaru_icon_button-unselected-disabled-light.png differ diff --git a/test/controls/goldens/yaru_icon_button-unselected-focused-dark.png b/test/controls/goldens/yaru_icon_button-unselected-focused-dark.png new file mode 100644 index 000000000..46e6655c3 Binary files /dev/null and b/test/controls/goldens/yaru_icon_button-unselected-focused-dark.png differ diff --git a/test/controls/goldens/yaru_icon_button-unselected-focused-light.png b/test/controls/goldens/yaru_icon_button-unselected-focused-light.png new file mode 100644 index 000000000..68065d762 Binary files /dev/null and b/test/controls/goldens/yaru_icon_button-unselected-focused-light.png differ diff --git a/test/controls/goldens/yaru_icon_button-unselected-hovered-dark.png b/test/controls/goldens/yaru_icon_button-unselected-hovered-dark.png new file mode 100644 index 000000000..46e6655c3 Binary files /dev/null and b/test/controls/goldens/yaru_icon_button-unselected-hovered-dark.png differ diff --git a/test/controls/goldens/yaru_icon_button-unselected-hovered-light.png b/test/controls/goldens/yaru_icon_button-unselected-hovered-light.png new file mode 100644 index 000000000..68065d762 Binary files /dev/null and b/test/controls/goldens/yaru_icon_button-unselected-hovered-light.png differ diff --git a/test/controls/goldens/yaru_icon_button-unselected-light.png b/test/controls/goldens/yaru_icon_button-unselected-light.png new file mode 100644 index 000000000..12683c8f4 Binary files /dev/null and b/test/controls/goldens/yaru_icon_button-unselected-light.png differ diff --git a/test/controls/goldens/yaru_icon_button-unselected-pressed-dark.png b/test/controls/goldens/yaru_icon_button-unselected-pressed-dark.png new file mode 100644 index 000000000..39067e328 Binary files /dev/null and b/test/controls/goldens/yaru_icon_button-unselected-pressed-dark.png differ diff --git a/test/controls/goldens/yaru_icon_button-unselected-pressed-light.png b/test/controls/goldens/yaru_icon_button-unselected-pressed-light.png new file mode 100644 index 000000000..5dea3b0ec Binary files /dev/null and b/test/controls/goldens/yaru_icon_button-unselected-pressed-light.png differ diff --git a/test/controls/yaru_icon_button_test.dart b/test/controls/yaru_icon_button_test.dart new file mode 100644 index 000000000..4c3225087 --- /dev/null +++ b/test/controls/yaru_icon_button_test.dart @@ -0,0 +1,91 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:yaru_icons/yaru_icons.dart'; +import 'package:yaru_widgets/yaru_widgets.dart'; + +import '../yaru_golden_tester.dart'; + +void main() { + testWidgets( + 'golden images', + (tester) async { + final variant = goldenVariant.currentValue!; + + // ensure traditional focus highlight + FocusManager.instance.highlightStrategy = + FocusHighlightStrategy.alwaysTraditional; + + await tester.pumpScaffold( + YaruIconButton( + autofocus: variant.hasState(MaterialState.focused), + isSelected: variant.states[MaterialState.selected], + onPressed: variant.hasState(MaterialState.disabled) ? null : () {}, + icon: const Icon(YaruIcons.star_filled), + ), + themeMode: variant.themeMode, + size: const Size(40, 40), + ); + await tester.pumpAndSettle(); + + if (variant.hasState(MaterialState.pressed)) { + await tester.down(find.byType(YaruIconButton)); + await tester.pumpAndSettle(); + } else if (variant.hasState(MaterialState.hovered)) { + await tester.hover(find.byType(YaruIconButton)); + await tester.pumpAndSettle(); + } + + await expectLater( + find.byType(YaruIconButton), + matchesGoldenFile('goldens/yaru_icon_button-${variant.label}.png'), + ); + }, + variant: goldenVariant, + tags: 'golden', + ); +} + +final goldenVariant = ValueVariant({ + // normal (non-toggle) button + ...goldenThemeVariants('normal'), + ...goldenThemeVariants('disabled', {MaterialState.disabled: true}), + ...goldenThemeVariants('focused', {MaterialState.focused: true}), + ...goldenThemeVariants('hovered', {MaterialState.hovered: true}), + ...goldenThemeVariants('pressed', {MaterialState.pressed: true}), + // selected toggle button + ...goldenThemeVariants('selected', {MaterialState.selected: true}), + ...goldenThemeVariants('selected-disabled', { + MaterialState.selected: true, + MaterialState.disabled: true, + }), + ...goldenThemeVariants('selected-focused', { + MaterialState.selected: true, + MaterialState.focused: true, + }), + ...goldenThemeVariants('selected-hovered', { + MaterialState.selected: true, + MaterialState.hovered: true, + }), + ...goldenThemeVariants('selected-pressed', { + MaterialState.selected: true, + MaterialState.pressed: true, + }), + // unselected toggle button + ...goldenThemeVariants('unselected', {MaterialState.selected: false}), + ...goldenThemeVariants('unselected-disabled', { + MaterialState.selected: false, + MaterialState.disabled: true, + }), + ...goldenThemeVariants('unselected-focused', { + MaterialState.selected: false, + MaterialState.focused: true, + }), + ...goldenThemeVariants('unselected-hovered', { + MaterialState.selected: false, + MaterialState.hovered: true, + }), + ...goldenThemeVariants('unselected-pressed', { + MaterialState.selected: false, + MaterialState.pressed: true, + }), +}); diff --git a/test/flutter_test_config.dart b/test/flutter_test_config.dart new file mode 100644 index 000000000..31cf4707b --- /dev/null +++ b/test/flutter_test_config.dart @@ -0,0 +1,8 @@ +import 'dart:async'; + +import 'package:golden_toolkit/golden_toolkit.dart'; + +Future testExecutable(FutureOr Function() testMain) async { + await loadAppFonts(); + return testMain(); +} diff --git a/test/yaru_golden_tester.dart b/test/yaru_golden_tester.dart new file mode 100644 index 000000000..2f3641316 --- /dev/null +++ b/test/yaru_golden_tester.dart @@ -0,0 +1,94 @@ +import 'package:collection/collection.dart'; +import 'package:flutter/gestures.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:yaru/yaru.dart'; + +extension YaruGoldenTester on WidgetTester { + Future pumpScaffold( + Widget widget, { + ThemeMode? themeMode, + ThemeData? theme, + ThemeData? darkTheme, + Size? size, + }) { + binding.window.devicePixelRatioTestValue = 1; + if (size != null) binding.window.physicalSizeTestValue = size; + return pumpWidget( + MaterialApp( + themeMode: themeMode, + theme: theme ?? yaruLight, + darkTheme: darkTheme ?? yaruDark, + home: Scaffold( + body: Center(child: widget), + ), + ), + ); + } + + Future hover(Finder finder) async { + final gesture = await createGesture(kind: PointerDeviceKind.mouse); + await gesture.addPointer(); + addTearDown(gesture.removePointer); + await gesture.moveTo(getCenter(finder)); + } + + Future down(Finder finder) async { + final gesture = await createGesture(kind: PointerDeviceKind.mouse); + await gesture.addPointer(); + addTearDown(gesture.removePointer); + await gesture.down(getCenter(finder)); + } +} + +@immutable +class YaruGoldenVariant { + YaruGoldenVariant({ + required String label, + required this.themeMode, + this.states = const {}, + }) : label = '$label-${themeMode.name}'; + + final String label; + final ThemeMode themeMode; + final Map states; + + bool hasState(MaterialState state) => states[state] == true; + + @override + bool operator ==(Object other) { + if (identical(this, other)) return true; + final mapEquals = const MapEquality().equals; + return other is YaruGoldenVariant && + other.label == label && + other.themeMode == themeMode && + mapEquals(other.states, states); + } + + @override + int get hashCode { + final mapHash = const MapEquality().hash; + return Object.hash(label, themeMode, mapHash(states)); + } + + @override + String toString() => '$label: themeMode: $themeMode, states: $states'; +} + +List goldenThemeVariants( + String label, [ + Map states = const {}, +]) { + return [ + YaruGoldenVariant( + label: label, + themeMode: ThemeMode.light, + states: states, + ), + YaruGoldenVariant( + label: label, + themeMode: ThemeMode.dark, + states: states, + ), + ]; +}