Skip to content

Commit

Permalink
ci: add coverage to pr action
Browse files Browse the repository at this point in the history
  • Loading branch information
thelukewalton committed Jun 19, 2024
1 parent 9659e70 commit c5a1d71
Show file tree
Hide file tree
Showing 18 changed files with 166 additions and 10 deletions.
21 changes: 21 additions & 0 deletions .github/scripts/parse_coverage.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@

lcov --capture --directory coverage --output-file coverage/lcov.info &> /dev/null

# Remove unnecessary files from the report
lcov --remove coverage/lcov.info 'lib/*/*.g.dart' 'lib/*/*.freezed.dart' -o coverage/lcov.info &> /dev/null

# Generate the HTML report
genhtml coverage/lcov.info --output-directory coverage/html &> /dev/null

# Save output of coverage
output="$(lcov --summary coverage/lcov.info )"

# Trim to only return what we want
IFS=':';
output=($output);
output=${output[3]};
output=${output%'functions...'};

unset IFS;

echo $output
16 changes: 12 additions & 4 deletions .github/workflows/code-quality.yml
Original file line number Diff line number Diff line change
Expand Up @@ -43,20 +43,22 @@ jobs:
id: test
run: |
cd example
# Allows code to run after an error.
set -e
# Runs flutter test; saves output and if it fails.
out=$(flutter test) || failed='true'
out=$(flutter test --coverage) || failed='true'
echo "$out"
# Saves output to either success or failure variables.
if [ "$failed" == "true" ]; then
echo "FAILURE=true" >> $GITHUB_OUTPUT
exit 1
fi
- name: Check test coverage
id: coverage
run: echo "coverage=$(sh .github/scripts/parse_coverage.sh)" >> $GITHUB_OUTPUT
- name: Check for modified files
id: git-check
run: echo "modified=$(if [ -n "$(git status --porcelain)" ]; then echo "true"; else echo "false"; fi)" >> $GITHUB_ENV
Expand All @@ -68,8 +70,8 @@ jobs:
git add -A
git commit -m '[automated commit] lint format and import sort'
git push
- name: Print outputs
if: always()
env:
GH_TOKEN: ${{ github.token }}
run: |
Expand All @@ -87,6 +89,12 @@ jobs:
template="$template ✅ - All tests passed</br>"
fi
if [ -n "${{steps.coverage.outputs.coverage}}" ]; then
echo 'Coverage does not work'
else
template="$template 🧪 ${{steps.coverage.outputs.coverage}}</br>"
fi
# Add / amend comment on PR.
gh pr comment ${{github.event.pull_request.number}} --body="${template}" --edit-last -R ${{github.repository}} || gh pr comment ${{github.event.pull_request.number}} --body="${template}" -R ${{github.repository}} || echo 'Token not working'
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/pull-request.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
name: CI - Pull Request
on:
pull_request_target:
pull_request:

jobs:
up-to-date:
Expand Down
1 change: 0 additions & 1 deletion example/lib/pages/components/button_example.dart
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ class ButtonExample extends StatefulWidget {
class _ButtonExampleState extends State<ButtonExample> {
Widget? fab;
late ScrollController _scrollController;
bool expanded = false;

@override
void initState() {
Expand Down
8 changes: 4 additions & 4 deletions lib/src/components/fabs/fab.dart
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ class ZetaFAB extends StatefulWidget {
class _ZetaFABState extends State<ZetaFAB> {
@override
Widget build(BuildContext context) {
bool _isExpanded = (widget.initiallyExpanded != null ? widget.initiallyExpanded! : widget.label != null);
final bool isExpanded = (widget.initiallyExpanded != null ? widget.initiallyExpanded! : widget.label != null);
final colors = widget.type.colors(context);
final backgroundColor = widget.type == ZetaFabType.inverse ? colors.shade80 : colors.shade60;

Expand All @@ -115,7 +115,7 @@ class _ZetaFABState extends State<ZetaFAB> {
focusNode: widget.focusNode,
style: ButtonStyle(
padding: const WidgetStatePropertyAll(EdgeInsets.zero),
shape: WidgetStatePropertyAll(widget.shape.buttonShape(isExpanded: _isExpanded, size: widget.size)),
shape: WidgetStatePropertyAll(widget.shape.buttonShape(isExpanded: isExpanded, size: widget.size)),
backgroundColor: WidgetStateProperty.resolveWith((states) {
if (states.contains(WidgetState.disabled)) return Zeta.of(context).colors.surfaceDisabled;
if (states.contains(WidgetState.hovered)) return colors.hover;
Expand All @@ -135,14 +135,14 @@ class _ZetaFABState extends State<ZetaFAB> {
child: AnimatedContainer(
duration: ZetaAnimationLength.normal,
child: Padding(
padding: _isExpanded
padding: isExpanded
? const EdgeInsets.symmetric(horizontal: ZetaSpacingBase.x3_5, vertical: ZetaSpacing.medium)
: EdgeInsets.all(widget.size.padding),
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
Icon(widget.icon, size: widget.size.iconSize),
if (_isExpanded && widget.label != null)
if (isExpanded && widget.label != null)
Row(
mainAxisSize: MainAxisSize.min,
children: [Text(widget.label!, style: ZetaTextStyles.labelLarge)],
Expand Down
5 changes: 5 additions & 0 deletions test/src/components/badge/indicator_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,14 @@ import 'package:flutter_test/flutter_test.dart';
import 'package:path/path.dart';
import 'package:zeta_flutter/zeta_flutter.dart';
import '../../../test_utils/test_app.dart';
import '../../../test_utils/tolerant_comparator.dart';
import '../../../test_utils/utils.dart';

void main() {
setUpAll(() {
final testUri = Uri.parse(getCurrentPath('badge'));
goldenFileComparator = TolerantComparator(testUri, tolerance: 0.01);
});
testWidgets('Default constructor initializes with correct parameters', (WidgetTester tester) async {
await tester.pumpWidget(const TestApp(home: ZetaIndicator()));

Expand Down
5 changes: 5 additions & 0 deletions test/src/components/badge/label_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,14 @@ import 'package:flutter_test/flutter_test.dart';
import 'package:path/path.dart';
import 'package:zeta_flutter/zeta_flutter.dart';
import '../../../test_utils/test_app.dart';
import '../../../test_utils/tolerant_comparator.dart';
import '../../../test_utils/utils.dart';

void main() {
setUpAll(() {
final testUri = Uri.parse(getCurrentPath('badge'));
goldenFileComparator = TolerantComparator(testUri, tolerance: 0.01);
});
testWidgets('Initializes with correct parameters', (WidgetTester tester) async {
await tester.pumpWidget(const TestApp(home: ZetaLabel(label: 'Test Label')));

Expand Down
5 changes: 5 additions & 0 deletions test/src/components/badge/priority_pill_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,14 @@ import 'package:path/path.dart';
import 'package:zeta_flutter/zeta_flutter.dart';

import '../../../test_utils/test_app.dart';
import '../../../test_utils/tolerant_comparator.dart';
import '../../../test_utils/utils.dart';

void main() {
setUpAll(() {
final testUri = Uri.parse(getCurrentPath('badge'));
goldenFileComparator = TolerantComparator(testUri, tolerance: 0.01);
});
testWidgets('Initializes with correct label and index', (WidgetTester tester) async {
await tester.pumpWidget(
const TestApp(
Expand Down
5 changes: 5 additions & 0 deletions test/src/components/badge/status_label_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,14 @@ import 'package:path/path.dart';
import 'package:zeta_flutter/zeta_flutter.dart';

import '../../../test_utils/test_app.dart';
import '../../../test_utils/tolerant_comparator.dart';
import '../../../test_utils/utils.dart';

void main() {
setUpAll(() {
final testUri = Uri.parse(getCurrentPath('badge'));
goldenFileComparator = TolerantComparator(testUri, tolerance: 0.01);
});
group('ZetaStatusLabel Tests', () {
testWidgets('Initializes with correct properties', (WidgetTester tester) async {
await tester.pumpWidget(
Expand Down
5 changes: 5 additions & 0 deletions test/src/components/badge/tag_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,14 @@ import 'package:path/path.dart';
import 'package:zeta_flutter/zeta_flutter.dart';

import '../../../test_utils/test_app.dart';
import '../../../test_utils/tolerant_comparator.dart';
import '../../../test_utils/utils.dart';

void main() {
setUpAll(() {
final testUri = Uri.parse(getCurrentPath('badge'));
goldenFileComparator = TolerantComparator(testUri, tolerance: 0.01);
});
group('ZetaTag', () {
testWidgets('Initializes right with correct parameters', (WidgetTester tester) async {
await tester.pumpWidget(
Expand Down
6 changes: 6 additions & 0 deletions test/src/components/button/button_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,15 @@ import 'package:path/path.dart';
import 'package:zeta_flutter/zeta_flutter.dart';

import '../../../test_utils/test_app.dart';
import '../../../test_utils/tolerant_comparator.dart';
import '../../../test_utils/utils.dart';

void main() {
setUpAll(() {
final testUri = Uri.parse(getCurrentPath('button'));
goldenFileComparator = TolerantComparator(testUri, tolerance: 0.01);
});

group('ZetaButton Tests', () {
testWidgets('Initializes with correct Label', (WidgetTester tester) async {
await tester.pumpWidget(
Expand Down
6 changes: 6 additions & 0 deletions test/src/components/checkbox/checkbox_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,15 @@ import 'package:path/path.dart';
import 'package:zeta_flutter/zeta_flutter.dart';

import '../../../test_utils/test_app.dart';
import '../../../test_utils/tolerant_comparator.dart';
import '../../../test_utils/utils.dart';

void main() {
setUpAll(() {
final testUri = Uri.parse(getCurrentPath('checkbox'));
goldenFileComparator = TolerantComparator(testUri, tolerance: 0.01);
});

group('ZetaCheckbox Tests', () {
testWidgets('Initializes with correct parameters', (WidgetTester tester) async {
await tester.pumpWidget(
Expand Down
6 changes: 6 additions & 0 deletions test/src/components/dialpad/dialpad_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,15 @@ import 'package:path/path.dart';
import 'package:zeta_flutter/zeta_flutter.dart';

import '../../../test_utils/test_app.dart';
import '../../../test_utils/tolerant_comparator.dart';
import '../../../test_utils/utils.dart';

void main() {
setUpAll(() {
final testUri = Uri.parse(getCurrentPath('dialpad'));
goldenFileComparator = TolerantComparator(testUri, tolerance: 0.01);
});

group('ZetaDialPad Tests', () {
testWidgets('Initializes with correct parameters and is enabled', (WidgetTester tester) async {
String number = '';
Expand Down
6 changes: 6 additions & 0 deletions test/src/components/fabs/fab_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,15 @@ import 'package:flutter_test/flutter_test.dart';
import 'package:path/path.dart';
import 'package:zeta_flutter/zeta_flutter.dart';
import '../../../test_utils/test_app.dart';
import '../../../test_utils/tolerant_comparator.dart';
import '../../../test_utils/utils.dart';

void main() {
setUpAll(() {
final testUri = Uri.parse(getCurrentPath('fabs'));
goldenFileComparator = TolerantComparator(testUri, tolerance: 0.01);
});

group('ZetaFAB Tests', () {
testWidgets('Initializes with correct parameters', (WidgetTester tester) async {
final scrollController = ScrollController();
Expand Down
6 changes: 6 additions & 0 deletions test/src/components/in_page_banner/in_page_banner_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,15 @@ import 'package:flutter_test/flutter_test.dart';
import 'package:path/path.dart';
import 'package:zeta_flutter/zeta_flutter.dart';
import '../../../test_utils/test_app.dart';
import '../../../test_utils/tolerant_comparator.dart';
import '../../../test_utils/utils.dart';

void main() {
setUpAll(() {
final testUri = Uri.parse(getCurrentPath('in_page_banner'));
goldenFileComparator = TolerantComparator(testUri, tolerance: 0.01);
});

group('ZetaInPageBanner Tests', () {
testWidgets('ZetaInPageBanner creation', (WidgetTester tester) async {
await tester.pumpWidget(
Expand Down
6 changes: 6 additions & 0 deletions test/src/components/tooltip/tooltip_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,15 @@ import 'package:path/path.dart';
import 'package:zeta_flutter/zeta_flutter.dart';

import '../../../test_utils/test_app.dart';
import '../../../test_utils/tolerant_comparator.dart';
import '../../../test_utils/utils.dart';

void main() {
setUpAll(() {
final testUri = Uri.parse(getCurrentPath('tooltip'));
goldenFileComparator = TolerantComparator(testUri, tolerance: 0.01);
});

group('ZetaTooltip Widget Tests', () {
testWidgets('renders with default properties', (WidgetTester tester) async {
await tester.pumpWidget(
Expand Down
1 change: 0 additions & 1 deletion test/test_utils/test_app.dart
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ class TestApp extends StatelessWidget {
initialThemeData: ZetaThemeData(rounded: rounded ?? true),
builder: (context, themeData, themeMode) {
return MaterialApp(
// debugShowCheckedModeBanner: false,
theme: ThemeData(
fontFamily: themeData.fontFamily,
colorScheme: themeData.colorsLight.toScheme(),
Expand Down
67 changes: 67 additions & 0 deletions test/test_utils/tolerant_comparator.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import 'dart:io';
import 'dart:typed_data';

import 'package:flutter_test/flutter_test.dart';
import 'package:image/image.dart' as img;

class TolerantComparator extends LocalFileComparator {
TolerantComparator(super.testFile, {this.tolerance = 0.0});

final double tolerance;

@override
Future<bool> compare(Uint8List imageBytes, Uri golden) async {
final goldenFile = File.fromUri(golden);
if (!goldenFile.existsSync()) {
goldenFile
..createSync(recursive: true)
..writeAsBytesSync(imageBytes);
return true;
}

final goldenBytes = goldenFile.readAsBytesSync();
final testImage = img.decodeImage(imageBytes);
final goldenImage = img.decodeImage(goldenBytes);

if (testImage == null || goldenImage == null) {
return false;
}

return _compareImages(testImage, goldenImage);
}

bool _compareImages(img.Image testImage, img.Image goldenImage) {
if (testImage.width != goldenImage.width || testImage.height != goldenImage.height) {
return false;
}

int diffPixels = 0;
for (int y = 0; y < testImage.height; y++) {
for (int x = 0; x < testImage.width; x++) {
final testPixel = testImage.getPixel(x, y);
final goldenPixel = goldenImage.getPixel(x, y);

if (!_isPixelWithinTolerance(testPixel, goldenPixel)) {
diffPixels++;
}
}
}

final diffPercentage = diffPixels / (testImage.width * testImage.height);
return diffPercentage <= tolerance;
}

bool _isPixelWithinTolerance(img.Pixel testPixel, img.Pixel goldenPixel) {
final tr = testPixel.r;
final tg = testPixel.g;
final tb = testPixel.b;

final gr = goldenPixel.r;
final gg = goldenPixel.g;
final gb = goldenPixel.b;

return (tr - gr).abs() <= 255 * tolerance &&
(tg - gg).abs() <= 255 * tolerance &&
(tb - gb).abs() <= 255 * tolerance;
}
}

0 comments on commit c5a1d71

Please sign in to comment.