diff --git a/material_3_demo/lib/color_box.dart b/material_3_demo/lib/color_box.dart index df81e6d84..06a168fb8 100644 --- a/material_3_demo/lib/color_box.dart +++ b/material_3_demo/lib/color_box.dart @@ -66,14 +66,13 @@ class _ColorBoxState extends State { onPressed: () async { final messenger = ScaffoldMessenger.of(context); // Copy color as hex to clipboard - String hex = '#'; final c = widget.color; - // Will change from int 0-255 to double 0.0-1.0 in 3.26+ - // The properties also change from red/green/blue to r/g/b - // hex += (c.[r g b] * 255.0).round().toRadixString(16).padLeft(2, '0'); - hex += c.r.round().toRadixString(16).padLeft(2, '0'); - hex += c.g.round().toRadixString(16).padLeft(2, '0'); - hex += c.b.round().toRadixString(16).padLeft(2, '0'); + + final hex = + '#${_colorChannelToHex(c.r)}' + '${_colorChannelToHex(c.g)}' + '${_colorChannelToHex(c.b)}'; + final data = ClipboardData(text: hex); await Clipboard.setData(data); messenger.hideCurrentSnackBar(); @@ -90,3 +89,8 @@ class _ColorBoxState extends State { ); } } + +String _colorChannelToHex(double value) { + final intVal = (value * 255).round(); + return intVal.toRadixString(16).padLeft(2, '0'); +} diff --git a/material_3_demo/test/color_screen_test.dart b/material_3_demo/test/color_screen_test.dart index 42418791e..63df10753 100644 --- a/material_3_demo/test/color_screen_test.dart +++ b/material_3_demo/test/color_screen_test.dart @@ -2,8 +2,12 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +import 'dart:ui'; + import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; import 'package:flutter_test/flutter_test.dart'; +import 'package:material_3_demo/color_box.dart'; import 'package:material_3_demo/color_palettes_screen.dart'; import 'package:material_3_demo/main.dart'; import 'package:material_3_demo/scheme.dart'; @@ -88,4 +92,66 @@ void main() { expect(find.text('Dark ColorScheme'), findsOneWidget); expect(find.byType(SchemePreview, skipOffstage: false), findsNWidgets(2)); }); + + testWidgets( + 'ColorBox displays correct info and copies hex color on button tap', + (tester) async { + TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger + .setMockMessageHandler('flutter/platform', (_) async { + // To intercept method calls to 'Clipboard.setData' + return const JSONMethodCodec().encodeSuccessEnvelope(null); + }); + const hexColor = 0xFF3d3d8d; + const testColor = Color(hexColor); + const onTestColor = Colors.white; + const testLabel = 'Test Label'; + const testTone = '50'; + + final gesture = await tester.createGesture(kind: PointerDeviceKind.mouse); + + // Wrap in MaterialApp + Scaffold so we can show SnackBars + await tester.pumpWidget( + MaterialApp( + home: Scaffold( + body: ColorBox( + label: testLabel, + tone: testTone, + color: testColor, + onColor: onTestColor, + height: 100, + width: 100, + displayPaletteInfo: true, + ), + ), + ), + ); + + expect(find.text(testLabel), findsOneWidget); + expect(find.text(testTone), findsOneWidget); + + // The copy icon should NOT be there initially (only appears on hover). + expect(find.byIcon(Icons.copy), findsNothing); + + await gesture.addPointer(location: Offset.zero); + addTearDown(gesture.removePointer); + await tester.pump(); + await gesture.moveTo(tester.getCenter(find.byType(ColorBox))); + await tester.pumpAndSettle(); + + expect(find.byIcon(Icons.copy), findsOneWidget); + + // Tap the copy icon, which copies the hex to clipboard and shows a SnackBar. + await tester.tap(find.byIcon(Icons.copy)); + await tester.pumpAndSettle(); + + expect(find.byType(SnackBar), findsOneWidget); + + expect( + find.text( + 'Copied #${hexColor.toRadixString(16).substring(2)} to clipboard', + ), + findsOneWidget, + ); + }, + ); }