Repository navigation
Fix Radio's painters - #170321
Fix Radio's painters#170321
Radio's painters#170321Conversation
a9a35c8 to
5d0fd66
Compare
| Material.of(tester.element(find.byType(Radio<int>))), | ||
| paints | ||
| ..rect() | ||
| ..circle(color: Colors.transparent) |
There was a problem hiding this comment.
I don't get why this won't record correctly if reuse paint, looking a the code, it just call renderObject.paint on the TestRecordingPaintingContext which will record all the push layer. Can you explain a bit?
There was a problem hiding this comment.
Sure!
The previous implementation was reusing the same Paint and was something similar to:
// Draw background.
final Paint paint = Paint()..color = Colors.transparent;
canvas.drawCircle(backgroundOffset, backgroundRadius, paint);
// Draw border.
paint..color = Colors.red; // Red for simplicity here
canvas.drawCircle(borderOffset, borderRadius, paint);I wanted to verify the background and the border were painted, for that, I was using mock canvas with:
expect(
radioFinder,
paints
..circle(color: Colors.transparent)
..circle(color: Colors.red),
);But it was failing, it couldn't "find" the ..circle(color: Colors.transparent) part and the reason was because the reuse of the reference of Paint paint.
TestRecordingPaintingContext records the invocations and here is what was happening during a test:
/*
There are no invocations recorded yet:
invocations: []
*/
// Draw background.
final Paint paint = Paint()..color = Colors.transparent;
canvas.drawCircle(backgroundOffset, backgroundRadius, paint);
/*
drawCircle is recorded with the paint reference (#123 here) and the color transparent.
invocations: [MethodInvocation(#drawCircle, Paint#123(Colors.transparent))]
*/
// Draw border.
paint..color = Colors.red; // Red for simplicity here
/*
The paint object is mutated, which ends up modifying the invocation list:
invocations: [MethodInvocation(#drawCircle, Paint#123(Colors.red))]
*/
canvas.drawCircle(borderOffset, borderRadius, paint);
/*
drawCircle is recorded with the same paint reference (#123 here) and the color red.
invocations: [
MethodInvocation(#drawCircle, Paint#123(Colors.red)),
MethodInvocation(#drawCircle, Paint#123(Colors.red)),
]
*/So the test:
expect(
radioFinder,
paints
..circle(color: Colors.transparent)
..circle(color: Colors.red),
);fails and
expect(
radioFinder,
paints
..circle(color: Colors.red)
..circle(color: Colors.red),
);passes.
That's why I changed it to not reuse the same Paint
Having said this, do my changes still make sense? Or was there a better thing to do I missed?
There was a problem hiding this comment.
Thanks for the thorough explanation here! Is the reason why the invocation list changes simply because it is holding a weak reference to the Paint or something like that? I'm just trying to understand the details here. Maybe we can explain this in the docs somewhere.
There was a problem hiding this comment.
Yes, if I apply the same example (using a transparent circle for the background and a red circle for the border) the recorded invocation list was:
// invocations: [
MethodInvocation(#drawCircle, Paint#123(Colors.red)),
MethodInvocation(#drawCircle, Paint#123(Colors.red)),
] The tests
expect(
radioFinder,
paints.circle(color: Colors.red),
);successfully passed.
However, after my modification, the invocation list changed to:
// invocations: [
MethodInvocation(#drawCircle, Paint#123(Colors.transparent)),
MethodInvocation(#drawCircle, Paint#123(Colors.red)),
] Consequently, the tests failed until I updated them to:
expect(
radioFinder,
paints
..circle(color: Colors.transparent)
..circle(color: Colors.red),
);Does that clear your question?
Maybe we can explain this in the docs somewhere.
Sure, where did you picture the doc to be? A comment in paint method in _RadioPainter?
There was a problem hiding this comment.
Hello everyone,
Does my explanation address your questions? How do you envision the documentation?
It seems a bit odd to me to include comments about the tests in the paint method of _RadioPainter. What are your thoughts?
There was a problem hiding this comment.
Sorry for the delay here. I think this PR is fine as-is. I've made a note about this in the docs for paints here: #171180
There was a problem hiding this comment.
I think this pr is fine as-is, but I think we should fix the mock canvas to be able to handle this. we can continue the discussion in other pr
5d0fd66 to
512adb0
Compare
512adb0 to
4876422
Compare
justinmc
left a comment
There was a problem hiding this comment.
LGTM but left a question below. Thanks for improving the codebase 👍
| final Color effectiveInactiveColor = | ||
| inactiveColor ?? defaults.fillColor!.resolve(inactiveStates)!; | ||
| // TODO(ValentinVignal): ADd backgroundColor to RadioThemeData. | ||
| // TODO(ValentinVignal): Add backgroundColor to RadioThemeData. |
| Material.of(tester.element(find.byType(Radio<int>))), | ||
| paints | ||
| ..rect() | ||
| ..circle(color: Colors.transparent) |
There was a problem hiding this comment.
Thanks for the thorough explanation here! Is the reason why the invocation list changes simply because it is holding a weak reference to the Paint or something like that? I'm just trying to understand the details here. Maybe we can explain this in the docs somewhere.
| Material.of(tester.element(find.byType(Radio<int>))), | ||
| paints | ||
| ..rect() | ||
| ..circle(color: Colors.transparent) |
There was a problem hiding this comment.
Sorry for the delay here. I think this PR is fine as-is. I've made a note about this in the docs for paints here: #171180
While working on flutter#168787 as a follow-up of flutter#169415, I noticed that the tests introduced in flutter#169415 were incorrect. However, because of the way the `Radio` implements `paint` and reuses 1 painter, it was not possible to properly assert the paints in the test. This PR fixes it ## Pre-launch Checklist - [x] I read the [Contributor Guide] and followed the process outlined there for submitting PRs. - [x] I read the [Tree Hygiene] wiki page, which explains my responsibilities. - [x] I read and followed the [Flutter Style Guide], including [Features we expect every widget to implement]. - [x] I signed the [CLA]. - [x] I listed at least one issue that this PR fixes in the description above. - [x] I updated/added relevant documentation (doc comments with `///`). - [x] I added new tests to check the change I am making, or this PR is [test-exempt]. - [x] I followed the [breaking change policy] and added [Data Driven Fixes] where supported. - [x] All existing and new tests are passing. If you need help, consider asking for advice on the #hackers-new channel on [Discord]. <!-- Links --> [Contributor Guide]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#overview [Tree Hygiene]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md [test-exempt]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#tests [Flutter Style Guide]: https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md [Features we expect every widget to implement]: https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md#features-we-expect-every-widget-to-implement [CLA]: https://cla.developers.google.com/ [flutter/tests]: https://github.com/flutter/tests [breaking change policy]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#handling-breaking-changes [Discord]: https://github.com/flutter/flutter/blob/main/docs/contributing/Chat.md [Data Driven Fixes]: https://github.com/flutter/flutter/blob/main/docs/contributing/Data-driven-Fixes.md
While working on #168787 as a follow-up of #169415, I noticed that the tests introduced in #169415 were incorrect. However, because of the way the
Radioimplementspaintand reuses 1 painter, it was not possible to properly assert the paints in the test.This PR fixes it
Pre-launch Checklist
///).If you need help, consider asking for advice on the #hackers-new channel on Discord.