Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: break out smoke test goldens into directories based on flutter version #126

Merged
merged 34 commits into from
Sep 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
ac32272
feat: break smoke test goldens into dirs for each flutter version
btrautmann Sep 16, 2024
93a0a75
add failures/**/*.png files to .gitignore
btrautmann Sep 16, 2024
04c9d7e
update workflows
btrautmann Sep 16, 2024
6bcefde
Disable fail-fast
btrautmann Sep 16, 2024
3ca757b
correct fail-fast spec
btrautmann Sep 16, 2024
96d7c0e
formatter
btrautmann Sep 16, 2024
0ebd209
run pub get
btrautmann Sep 16, 2024
e02234e
fix input for update goldens workflow
btrautmann Sep 16, 2024
b05e713
chore: Updating Goldens
btrautmann Sep 16, 2024
75dacfc
Re-run CI after updating goldens
btrautmann Sep 16, 2024
bce22e5
chore: Updating Goldens
btrautmann Sep 16, 2024
65aa116
fix logic in test config
btrautmann Sep 16, 2024
77a1ea8
Revert "chore: Updating Goldens"
btrautmann Sep 16, 2024
d0293b6
chore: Updating Goldens
btrautmann Sep 16, 2024
d1c6c37
Re-run CI after updating goldens
btrautmann Sep 16, 2024
3d1543a
debug logging
btrautmann Sep 16, 2024
b9bcf5d
remove scaffold from test
btrautmann Sep 16, 2024
ac1d7cb
use Scaffold with white background
btrautmann Sep 16, 2024
50d9edb
delete 3.22.3 goldens for now
btrautmann Sep 16, 2024
3dfc88d
chore: Updating Goldens
btrautmann Sep 16, 2024
1e3f231
Merge branch 'bt/flutter-version-dirs' of https://github.com/Betterme…
btrautmann Sep 16, 2024
748a889
chore: Updating Goldens
btrautmann Sep 16, 2024
a69fd05
Re-run CI after updating goldens
btrautmann Sep 16, 2024
6ae9b0b
delete old goldens dirs
btrautmann Sep 16, 2024
e8eedc8
update interactions smoke test colors
btrautmann Sep 16, 2024
b8ba873
chore: Updating Goldens
btrautmann Sep 16, 2024
f12c9c4
Re-run CI after updating goldens
btrautmann Sep 16, 2024
e3be414
more colors
btrautmann Sep 16, 2024
32f33be
chore: Updating Goldens
btrautmann Sep 16, 2024
6fd9a3c
Re-run CI after updating goldens
btrautmann Sep 16, 2024
574506b
formatter
btrautmann Sep 16, 2024
1d0fa87
clean up logic
btrautmann Sep 16, 2024
d6fe44c
use Jays process.run logic
btrautmann Sep 16, 2024
2d6dd9f
one last change, do not run directories code on every file path resol…
btrautmann Sep 16, 2024
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
35 changes: 29 additions & 6 deletions .github/workflows/main.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,19 @@ name: alchemist

on: [pull_request]

env:
FLUTTER_VERSION: 3.16.0

jobs:
build:
analyze:
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We'll analyze against the lowest version we support. This means that contributors should be using that version (fvm is helpful here). We can/should probably add something that details that in our CONTRIBUTING.md.

runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v3

- uses: subosito/flutter-action@v2
with:
flutter-version: '3.16.0'
flutter-version: ${{ env.FLUTTER_VERSION }}
channel: 'stable'
cache: true

Expand All @@ -24,20 +27,40 @@ jobs:
- name: Analyze project source
uses: invertase/github-action-dart-analyzer@v1

- uses: codecov/codecov-action@v2
with:
files: coverage/lcov.info

test:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
flutter-version: ['3.16.9', '3.19.6', '3.22.3', '3.24.3']
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Test against all supported versions of flutter, up to latest stable version. This will take some manual work to keep this up to date; I'll noodle on how to make this more dynamic as a follow-up.

steps:
- uses: actions/checkout@v3

- uses: subosito/flutter-action@v2
with:
flutter-version: ${{ matrix.flutter-version }}
channel: 'stable'
cache: true

- name: Install Dependencies
run: flutter packages get

- name: Run tests
run: flutter test --no-pub --coverage --test-randomize-ordering-seed=random

- name: Upload failures
if: failure()
uses: actions/upload-artifact@50769540e7f4bd5e21e526ee35c689e35e0d6874 # v4.4.0
with:
name: "golden_failures"
name: "golden_failures_${{ matrix.flutter-version }}"
path: |
**/failures/**/*.png


- uses: codecov/codecov-action@v2
with:
files: coverage/lcov.info

pana:
runs-on: ubuntu-latest
Expand Down
5 changes: 4 additions & 1 deletion .github/workflows/post_merge.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ on:
branches:
- 'main'

env:
FLUTTER_VERSION: 3.16.0

jobs:
upload_coverage:
runs-on: ubuntu-latest
Expand All @@ -14,7 +17,7 @@ jobs:

- uses: subosito/flutter-action@v2
with:
flutter-version: '3.16.0'
flutter-version: ${{ env.FLUTTER_VERSION }}
cache: true

- name: Install Dependencies
Expand Down
25 changes: 24 additions & 1 deletion .github/workflows/update_goldens.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@ on:
branch:
description: 'Branch to generate goldens from'
required: true
flutter_version:
description: 'Flutter version to use'
required: true
default: '3.16.0'
permissions:
contents: write

Expand All @@ -14,6 +18,7 @@ jobs:
steps:
- name: Checkout repo
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1

- name: Validate branch input
run: |
BRANCH_PATTERN="^[a-zA-Z0-9/_.-]+$"
Expand All @@ -32,6 +37,24 @@ jobs:
exit 1
fi

- name: Validate Flutter version input
run: |
VERSION_PATTERN="^[0-9]+\.[0-9]+\.[0-9]+$"

# Input string (branch name) to be validated
VERSION_INPUT=${{ inputs.flutter_version}}

echo "Checking version input: $VERSION_INPUT"

# Validate branch name against the regex pattern
if [[ $VERSION_INPUT =~ $VERSION_PATTERN ]]; then
echo "Version input is valid."
exit 0
else
echo "Version input is invalid."
exit 1
fi

- name: Ensure branch is not main
if: ${{ github.event.inputs.branch == 'main' || github.event.inputs.branch == 'origin/main'}}
run: exit 1
Expand All @@ -43,7 +66,7 @@ jobs:

- uses: subosito/flutter-action@v2
with:
flutter-version: '3.16.0'
flutter-version: ${{ github.event.inputs.flutter_version }}
channel: 'stable'
cache: true

Expand Down
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
# Alchemist

**/failures/**/*.png

# Miscellaneous
*.class
*.log
Expand Down
2 changes: 2 additions & 0 deletions pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,9 @@ dependencies:
dev_dependencies:
mocktail: ^0.3.0
mocktail_image_network: ^0.3.1
path: ^1.8.3
test: ^1.21.1
version: ^3.0.2
very_good_analysis: ^3.1.0

flutter:
Expand Down
128 changes: 122 additions & 6 deletions test/flutter_test_config.dart
Original file line number Diff line number Diff line change
@@ -1,24 +1,140 @@
import 'dart:async';
import 'dart:convert';
import 'dart:io';

import 'package:alchemist/alchemist.dart';
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:path/path.dart' as path;
import 'package:version/version.dart';

Future<void> testExecutable(FutureOr<void> Function() testMain) async {
final enablePlatformTests =
!Platform.environment.containsKey('GITHUB_ACTIONS');
final runningOnCi = Platform.environment.containsKey('GITHUB_ACTIONS');

// Grab the flutter version from the current environment.
final versionResult = await Process.run(
'flutter',
['--version', '--machine'],
);

if (versionResult.exitCode != 0) {
throw const ProcessException(
'flutter',
['--version', '--machine'],
'Failed to get flutter version',
);
}

final versionJson = versionResult.stdout.toString().trim();
final flutterData = json.decode(versionJson) as Map<String, dynamic>;
final version = flutterData['flutterVersion'] as String;

if (!version.isValidVersion()) {
throw ProcessException(
'flutter',
['--version', '--machine'],
'Invalid flutter version returned by `flutter version`: $version',
);
}

final parsedVersion = Version.parse(version);
final subDirectories = Directory(
path.join(
Directory.current.path,
'test',
'smoke_tests',
'goldens',
),
).listSync().whereType<Directory>().toList();

final candidates = subDirectories.where((dir) {
try {
final dirVersion = Version.parse(path.basename(dir.path));
return dirVersion <= parsedVersion;
} on FormatException {
return false;
}
});

/// Returns the goldens directory for the provided flutter version.
///
/// In order, this attempts to find:
/// - A directory that matches the provided flutter version exactly.
/// - If no exact match is found, the highest version directory that is less
/// than or equal to the provided flutter version.
/// - If no directories are found, an error is thrown.
///
/// If `autoUpdateGoldenFiles` is true (meaning we've passed
/// --update-goldens), a directory matching the provided flutter version will
/// be created if it does not already exist.
///
/// Doing this supports running our smoke tests against specific versions of
/// Flutter, allowing us to maintain goldens for each version when necessary.
Directory goldensDirectory() {
// If we're updating golden files, always return the associated directory.
if (autoUpdateGoldenFiles) {
return Directory(path.join('goldens', parsedVersion.toString()));
}

if (candidates.isEmpty) {
throw ArgumentError(
'No valid directories found in `goldens` for the current '
'flutter version: $parsedVersion',
);
}

// If we have multiple candidates, we want to find the highest version
// directory that is less than or equal to the provided flutter version.
return candidates.reduce((a, b) {
final aVersion = Version.parse(path.basename(a.path));
final bVersion = Version.parse(path.basename(b.path));
return aVersion > bVersion ? a : b;
});
}

final directory = goldensDirectory();

Future<String> filePathResolver(
String fileName,
String environmentName,
) async {
return path.join(
directory.path,
environmentName.toLowerCase(),
'$fileName.png',
);
}

return AlchemistConfig.runWithConfig(
config: AlchemistConfig(
theme: ThemeData(
useMaterial3: false,
textTheme: const TextTheme().apply(fontFamily: 'Roboto'),
),
platformGoldensConfig:
AlchemistConfig.current().platformGoldensConfig.copyWith(
enabled: enablePlatformTests,
),
ciGoldensConfig: AlchemistConfig.current()
.ciGoldensConfig //
.copyWith(
filePathResolver: filePathResolver,
enabled: runningOnCi,
),
platformGoldensConfig: AlchemistConfig.current()
.platformGoldensConfig //
.copyWith(
filePathResolver: filePathResolver,
enabled: !runningOnCi,
),
),
run: testMain,
);
}

extension on String {
bool isValidVersion() {
try {
Version.parse(this);
return true;
} on FormatException {
return false;
}
}
}
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.
Binary file not shown.
Binary file not shown.
Binary file not shown.
17 changes: 17 additions & 0 deletions test/smoke_tests/interactions_smoke_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,23 @@ void main() {
GoldenTestScenario(
name: 'scenario_button',
child: ElevatedButton(
style: ButtonStyle(
backgroundColor: MaterialStateProperty.all(
const Color(0xFF2196F3),
),
foregroundColor: MaterialStateProperty.all(
const Color(0xFFFFFFFF),
),
shadowColor: MaterialStateProperty.all(
const Color(0xFFFF0000),
),
surfaceTintColor: MaterialStateProperty.all(
const Color(0xFF00FF00),
),
overlayColor: MaterialStateProperty.all(
const Color(0xFF0000FF),
),
),
onPressed: () {},
onLongPress: () {},
child: const Text('button'),
Expand Down
Binary file modified test/src/blocked_text_image_reference.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions test/src/blocked_text_painting_context_golden_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ void main() {
key: key,
debugShowCheckedModeBanner: false,
home: const Scaffold(
backgroundColor: Color(0x0f000000),
body: Padding(
padding: EdgeInsets.all(8),
child: Column(
Expand Down
Loading