Skip to content
This repository was archived by the owner on Feb 25, 2024. It is now read-only.

Add golden test #320

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 29 additions & 0 deletions .github/workflows/flutter-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,35 @@ jobs:
- name: Check for any formatting issues
run: dart format --set-exit-if-changed .

goldens:
runs-on: ubuntu-22.04
steps:

- uses: actions/checkout@v2
- uses: subosito/flutter-action@v2
with:
channel: 'stable'
flutter-version: '3.10.x'

- name: Install apt dependencies
run: |
sudo apt update
sudo apt -y install clang cmake curl libgtk-3-dev ninja-build pkg-config unzip xvfb
sudo apt -y install fonts-noto-cjk fonts-ubuntu fonts-tibetan-machine

- name: Get pub dependencies
run: flutter pub get

- name: Run golden tests
run: xvfb-run -a -s '-screen 0 1280x800x24 +extension GLX' flutter test integration_test/golden_test.dart -d linux
working-directory: example/

- uses: actions/upload-artifact@v3
if: failure()
with:
name: failures
path: example/integration_test/failures

pub:
runs-on: ubuntu-20.04
steps:
Expand Down
3 changes: 3 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
.PHONY: goldens
goldens:
cd example && GDK_BACKEND=x11 GDK_SCALE=1 flutter test integration_test/golden_test.dart -d linux --update-goldens
158 changes: 158 additions & 0 deletions example/integration_test/golden_test.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
import 'dart:typed_data';

import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:integration_test/integration_test.dart';
import 'package:path/path.dart' as path;
import 'package:yaru/yaru.dart';
import 'package:yaru_example/main.dart' as app;
import 'package:yaru_example/main.dart';
import 'package:yaru_example/view/home_page.dart';

// NOTE: run `make goldens` to update golden images

const _kGoldenDiffTolerance = 0.005;

Future<void> main() async {
IntegrationTestWidgetsFlutterBinding.ensureInitialized();

goldenFileComparator = GoldenDiffComparator(
path.join(
path.fromUri((goldenFileComparator as LocalFileComparator).basedir),
'yaru.dart',
),
tolerance: _kGoldenDiffTolerance,
);

testWidgets('fonts', (tester) async {
tester.runApp();
await tester.pumpAndSettle();
await tester.takeScreenshots('fonts');
});

testWidgets('buttons', (tester) async {
tester.runApp();
await tester.pumpAndSettle();
await tester.tap(find.text('Controls'));
await tester.pump();
await tester.takeScreenshots('buttons');
});

testWidgets('checks', (tester) async {
tester.runApp();
await tester.pumpAndSettle();
await tester.tap(find.text('Controls'));
await tester.pump();
await tester.tap(find.text('Checks'));
await tester.pump();
await tester.takeScreenshots('checks');
});

testWidgets('switches', (tester) async {
tester.runApp();
await tester.pumpAndSettle();
await tester.tap(find.text('Controls'));
await tester.pump();
await tester.tap(find.text('Switches'));
await tester.pump();
await tester.takeScreenshots('switches');
});

testWidgets('text fields', (tester) async {
tester.runApp();
await tester.pumpAndSettle();
await tester.tap(find.text('Text Fields'));
await tester.pump();
primaryFocus?.unfocus();
await tester.pump();
await tester.takeScreenshots('text-fields');
});

testWidgets('containers', (tester) async {
tester.runApp();
await tester.pumpAndSettle();
await tester.tap(find.text('Containers'));
await tester.pump();
await tester.takeScreenshots('containers');
});
}

extension on WidgetTester {
void runApp() {
view.devicePixelRatio = 1;
view.physicalSize = const Size(600, 700);
app.main();
}

void selectTheme({
YaruVariant? variant,
bool? highContrast,
ThemeMode? themeMode,
}) async {
final context = element(find.byType(HomePage));
AppTheme.apply(
context,
variant: variant,
highContrast: highContrast,
themeMode: themeMode,
);
}

Future<void> takeScreenshots(String screen) async {
for (final themeMode in [ThemeMode.light, ThemeMode.dark]) {
selectTheme(
variant: YaruVariant.orange,
themeMode: themeMode,
highContrast: false,
);
await pumpAndSettle();
await takeScreenshot(screen);

selectTheme(themeMode: themeMode, highContrast: true);
await pumpAndSettle();
await takeScreenshot(screen);
}
}

Future<void> takeScreenshot(String screen) async {
final context = element(find.byType(HomePage));
final theme = AppTheme.of(context);
final suffix = [
if (theme.highContrast == true) 'high-contrast' else theme.variant?.name,
theme.themeMode?.name,
].join('-');

await expectLater(
find.byType(MaterialApp),
matchesGoldenFile('goldens/$screen-$suffix.png'),
);
}
}

class GoldenDiffComparator extends LocalFileComparator {
GoldenDiffComparator(
String testFile, {
required this.tolerance,
}) : super(Uri.parse(testFile));

final double tolerance;

@override
Future<bool> compare(Uint8List imageBytes, Uri golden) async {
final ComparisonResult result = await GoldenFileComparator.compareLists(
imageBytes,
await getGoldenBytes(golden),
);

if (!result.passed && result.diffPercent > tolerance) {
final error = await generateFailureOutput(result, golden, basedir);
throw FlutterError(error);
}
if (!result.passed) {
debugPrint(
'A tolerable difference of ${result.diffPercent * 100}% was found when comparing $golden.',
);
}
return result.passed || result.diffPercent <= tolerance;
}
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions example/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ dev_dependencies:
flutter_lints: ^2.0.1
flutter_test:
sdk: flutter
integration_test:
sdk: flutter
path: ^1.8.3

flutter:
uses-material-design: true
Loading