Fix tristate checkbox false to null transition, test ALL transitions (#26199)
diff --git a/packages/flutter/lib/src/material/checkbox.dart b/packages/flutter/lib/src/material/checkbox.dart index 87c0196..d471735 100644 --- a/packages/flutter/lib/src/material/checkbox.dart +++ b/packages/flutter/lib/src/material/checkbox.dart
@@ -342,7 +342,7 @@ _initStrokePaint(paint); final double tShrink = (t - 0.5) * 2.0; - if (_oldValue == null) + if (_oldValue == null || value == null) _drawDash(canvas, origin, tShrink, paint); else _drawCheck(canvas, origin, tShrink, paint);
diff --git a/packages/flutter/test/material/checkbox_test.dart b/packages/flutter/test/material/checkbox_test.dart index eba2aee..58945d1 100644 --- a/packages/flutter/test/material/checkbox_test.dart +++ b/packages/flutter/test/material/checkbox_test.dart
@@ -9,6 +9,7 @@ import 'package:flutter_test/flutter_test.dart'; import 'package:flutter/material.dart'; +import '../rendering/mock_canvas.dart'; import '../widgets/semantics_tester.dart'; void main() { @@ -286,4 +287,53 @@ SystemChannels.accessibility.setMockMessageHandler(null); semanticsTester.dispose(); }); + + testWidgets('CheckBox tristate rendering, programmatic transitions', (WidgetTester tester) async { + Widget buildFrame(bool checkboxValue) { + return Material( + child: StatefulBuilder( + builder: (BuildContext context, StateSetter setState) { + return Checkbox( + tristate: true, + value: checkboxValue, + onChanged: (bool value) { }, + ); + }, + ), + ); + } + + RenderToggleable getCheckboxRenderer() { + return tester.renderObject<RenderToggleable>(find.byType(Checkbox)); + } + + await tester.pumpWidget(buildFrame(false)); + await tester.pumpAndSettle(); + expect(getCheckboxRenderer(), isNot(paints..path())); // checkmark is rendered as a path + expect(getCheckboxRenderer(), isNot(paints..line())); // null is rendered as a line (a "dash") + expect(getCheckboxRenderer(), paints..drrect()); // empty checkbox + + await tester.pumpWidget(buildFrame(true)); + await tester.pumpAndSettle(); + expect(getCheckboxRenderer(), paints..path()); // checkmark is rendered as a path + + await tester.pumpWidget(buildFrame(false)); + await tester.pumpAndSettle(); + expect(getCheckboxRenderer(), isNot(paints..path())); // checkmark is rendered as a path + expect(getCheckboxRenderer(), isNot(paints..line())); // null is rendered as a line (a "dash") + expect(getCheckboxRenderer(), paints..drrect()); // empty checkbox + + await tester.pumpWidget(buildFrame(null)); + await tester.pumpAndSettle(); + expect(getCheckboxRenderer(), paints..line()); // null is rendered as a line (a "dash") + + await tester.pumpWidget(buildFrame(true)); + await tester.pumpAndSettle(); + expect(getCheckboxRenderer(), paints..path()); // checkmark is rendered as a path + + await tester.pumpWidget(buildFrame(null)); + await tester.pumpAndSettle(); + expect(getCheckboxRenderer(), paints..line()); // null is rendered as a line (a "dash") + }); + }