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

ci(passkit_ui): add workflow #26

Merged
merged 13 commits into from
Jun 26, 2024
Merged

ci(passkit_ui): add workflow #26

merged 13 commits into from
Jun 26, 2024

Conversation

marcossevilla
Copy link
Contributor

No description provided.

@marcossevilla marcossevilla self-assigned this Jun 24, 2024
@marcossevilla marcossevilla marked this pull request as ready for review June 24, 2024 11:23
@marcossevilla marcossevilla added the package: passkit_ui Issues relevant for the "passkit_ui" package label Jun 24, 2024
Copy link
Owner

@ueman ueman left a comment

Choose a reason for hiding this comment

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

Wohooo, this is super cool 🚀

Do you have by chance an example for how Pull Requests should look like according to VeryGoodOpenSource/very_good_workflows/.github/workflows/semantic_pull_request.yml@v1?

Would it make sense to provide a template for such a PR?

@marcossevilla
Copy link
Contributor Author

Do you have by chance an example for how Pull Requests should look like according to VeryGoodOpenSource/very_good_workflows/.github/workflows/semantic_pull_request.yml@v1?

You can take a look at this part of the docs 👍

Would it make sense to provide a template for such a PR?

Yeah I think that would be super useful

@marcossevilla marcossevilla requested a review from ueman June 24, 2024 14:09
Copy link
Owner

@ueman ueman left a comment

Choose a reason for hiding this comment

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

Why don't you write golden image tests? The widgets do not have state and are non-interactive, so a golden image test would cover probably even more lines of code while being easier to write and maintain:

void main() {
  // Arrange
  testWidgets('boarding pass gets rendered correctly', (WidgetTester tester) async {
    final bytes = await File('test/sample_passes/BoardingPass.pkpass').readAsBytes();
    final pkPass = PkPass.fromBytes(bytes);

    // Act
    await tester.pumpWidget(MaterialApp(home: PkPassWidget(pass: pkPass)));

    // Assert
    await expectLater(find.byType(PkPassWidget), matchesGoldenFile('boarding_pass.png'));
  });
}

To test the various branches (e.g. for choosing the resolution appropriate image), you just supply different pkpass files. Assuming the tests are exhaustive, each uncovered line is dead code and can be removed. This also keeps basically of the code an implementation detail and it just tests the actual API surface of the library. That's also why PkPassWidget is the only exposed class from the library (yet). That way we can change the whole implementation, without breaking users nor tests, while still having a high confidence in the code being correct, since it always looks correct thanks to the golden images.

A concrete example for this implementation detail argument is that, in particular, I view the PkPassTheme class as an implementation detail. It should probably be an individual ThemeExtension per pass type instead (different pass types have different font styles for example). I don't really want to rewrite the tests you just wrote for the PkPassTheme, but I really want to keep the look (aka the golden image) the same.

That being said, I very much appreciate your effort :D

Comment on lines +5 to +10
extension PkPassImageX on PkPassImage {
Uint8List forCorrectPixelRatio(double devicePixelRatio) {
// It just looks better when using images a step higher.
return fromMultiplier(devicePixelRatio.toInt() + 1);
}
}
Copy link
Owner

Choose a reason for hiding this comment

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

While I understand your reason for changing this, I think it's more important to make it easy to use here, especially now that you made it public facing. After all, that's what libraries for, to make the life of the consumer of the library easier. Also, a pass has at max like 3 or 4 images and one or three calls to the MediaQuery isn't really anything that makes or breaks the performance.

By keeping the BuildContext as parameter, we can also change how the correct image is retrieved later ta a different property of the MediaQuery instead, so it future-proofes the API in a way that doesn't break consumers.
Keeping the BuildContext as a parameter also makes the API more Flutter-like, since Flutter also always just takes a context as a parameter.

If it was just an internal API I wouldn't mind this change at all though.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

BuildContext shouldn't be a parameter for external methods, it should be used exclusively on the widgets' build method to avoid passing the whole context object as a function parameter and also causing context issues. It's even easier to test methods by passing a devicePixelRatio in this case than a mock build context. I think breaking changes are inevitable on packages and in this case it's a small one so it shouldn't be an issue!

Comment on lines +10 to +13
PkTextAlignment.natural when textDirection == TextDirection.ltr =>
TextAlign.left,
PkTextAlignment.natural when textDirection == TextDirection.rtl =>
TextAlign.right,
Copy link
Owner

Choose a reason for hiding this comment

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

Huh, that's a nice change.

import 'package:passkit/passkit.dart';

extension PkTextAlignmentX on PkTextAlignment {
TextAlign toFlutterTextAlign({TextDirection? textDirection}) {
Copy link
Owner

Choose a reason for hiding this comment

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

Same as above. If it's public facing, it should take a context instead.

flutter_version: 3.22.2
working_directory: passkit_ui
# TODO: Increase minimum coverage to 100% gradually.
min_coverage: 50
Copy link
Owner

Choose a reason for hiding this comment

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

That's already higher than I expected :D

Comment on lines 1 to 8
export 'src/widgets/widgets.dart';
export 'src/extensions/extensions.dart';
export 'src/theme/theme.dart';
export 'src/boarding_pass.dart';
export 'src/coupon.dart';
export 'src/event_ticket.dart';
export 'src/generic.dart';
export 'src/store_card.dart';
Copy link
Owner

Choose a reason for hiding this comment

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

I would, at least for now, keep the PkPassWidget as the only exposed class. That makes iterating a bit easier, while ensuring that no consumer of the library gets broken due to API changes.

In particular, the PkPassTheme is something that's not yet ready to be public facing, since it probably should be a ThemeExtension instead.

Copy link
Owner

@ueman ueman left a comment

Choose a reason for hiding this comment

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

You know what, consumers of the lib have been warned that it may contain breaking changes 🤷

@marcossevilla
Copy link
Contributor Author

Merging this but keeping in mind:

  • Future refactor to widget tests into golden tests (specially the transit types since they're custom painters).
  • Make PkPassTheme a ThemeExtension.

@marcossevilla marcossevilla merged commit c285c5a into master Jun 26, 2024
2 checks passed
@marcossevilla marcossevilla deleted the ci/add-workflows branch June 26, 2024 08:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
package: passkit_ui Issues relevant for the "passkit_ui" package
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants