Skip to content

Commit

Permalink
Golden YaruIconButton test (#294)
Browse files Browse the repository at this point in the history
NOTE: To update golden images, run:
```
flutter test --update-goldens
```
  • Loading branch information
jpnurmi committed Oct 23, 2022
1 parent f381a2d commit c252cd6
Show file tree
Hide file tree
Showing 36 changed files with 203 additions and 6 deletions.
2 changes: 2 additions & 0 deletions dart_test.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
tags:
golden:
12 changes: 6 additions & 6 deletions lib/src/controls/yaru_icon_button.dart
Original file line number Diff line number Diff line change
Expand Up @@ -63,25 +63,25 @@ 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);
}
if (states.contains(MaterialState.focused)) {
return colors.onSurfaceVariant.withOpacity(0.08);
}
if (states.contains(MaterialState.pressed)) {
return colors.onSurfaceVariant.withOpacity(0.12);
}
return null;
}),
);
Expand Down
2 changes: 2 additions & 0 deletions pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
91 changes: 91 additions & 0 deletions test/controls/yaru_icon_button_test.dart
Original file line number Diff line number Diff line change
@@ -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,
}),
});
8 changes: 8 additions & 0 deletions test/flutter_test_config.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import 'dart:async';

import 'package:golden_toolkit/golden_toolkit.dart';

Future<void> testExecutable(FutureOr<void> Function() testMain) async {
await loadAppFonts();
return testMain();
}
94 changes: 94 additions & 0 deletions test/yaru_golden_tester.dart
Original file line number Diff line number Diff line change
@@ -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<void> 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<void> hover(Finder finder) async {
final gesture = await createGesture(kind: PointerDeviceKind.mouse);
await gesture.addPointer();
addTearDown(gesture.removePointer);
await gesture.moveTo(getCenter(finder));
}

Future<void> 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<MaterialState, bool> 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<YaruGoldenVariant> goldenThemeVariants(
String label, [
Map<MaterialState, bool> states = const {},
]) {
return [
YaruGoldenVariant(
label: label,
themeMode: ThemeMode.light,
states: states,
),
YaruGoldenVariant(
label: label,
themeMode: ThemeMode.dark,
states: states,
),
];
}

0 comments on commit c252cd6

Please sign in to comment.