// Copyright 2014 The Flutter Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. import 'package:flutter/material.dart'; import 'package:flutter/rendering.dart'; import 'package:flutter_test/flutter_test.dart'; import '../rendering/mock_canvas.dart'; void main() { test('TextSelectionThemeData copyWith, ==, hashCode basics', () { expect(const TextSelectionThemeData(), const TextSelectionThemeData().copyWith()); expect(const TextSelectionThemeData().hashCode, const TextSelectionThemeData().copyWith().hashCode); }); test('TextSelectionThemeData null fields by default', () { const TextSelectionThemeData theme = TextSelectionThemeData(); expect(theme.cursorColor, null); expect(theme.selectionColor, null); expect(theme.selectionHandleColor, null); }); testWidgets('Default TextSelectionThemeData debugFillProperties', (WidgetTester tester) async { final DiagnosticPropertiesBuilder builder = DiagnosticPropertiesBuilder(); const TextSelectionThemeData().debugFillProperties(builder); final List<String> description = builder.properties .where((DiagnosticsNode node) => !node.isFiltered(DiagnosticLevel.info)) .map((DiagnosticsNode node) => node.toString()) .toList(); expect(description, <String>[]); }); testWidgets('TextSelectionThemeData implements debugFillProperties', (WidgetTester tester) async { final DiagnosticPropertiesBuilder builder = DiagnosticPropertiesBuilder(); const TextSelectionThemeData( cursorColor: Color(0xffeeffaa), selectionColor: Color(0x88888888), selectionHandleColor: Color(0xaabbccdd), ).debugFillProperties(builder); final List<String> description = builder.properties .where((DiagnosticsNode node) => !node.isFiltered(DiagnosticLevel.info)) .map((DiagnosticsNode node) => node.toString()) .toList(); expect(description, <String>[ 'cursorColor: Color(0xffeeffaa)', 'selectionColor: Color(0x88888888)', 'selectionHandleColor: Color(0xaabbccdd)', ]); }); testWidgets('Empty textSelectionTheme will use defaults', (WidgetTester tester) async { const Color defaultCursorColor = Color(0xff2196f3); const Color defaultSelectionColor = Color(0x662196f3); const Color defaultSelectionHandleColor = Color(0xff2196f3); EditableText.debugDeterministicCursor = true; addTearDown(() { EditableText.debugDeterministicCursor = false; }); // Test TextField's cursor & selection color. await tester.pumpWidget( const MaterialApp( home: Material( child: TextField(autofocus: true), ), ), ); await tester.pump(); await tester.pumpAndSettle(); final EditableTextState editableTextState = tester.firstState(find.byType(EditableText)); final RenderEditable renderEditable = editableTextState.renderEditable; expect(renderEditable.cursorColor, defaultCursorColor); expect(renderEditable.selectionColor?.value, defaultSelectionColor.value); // Test the selection handle color. await tester.pumpWidget( MaterialApp( home: Material( child: Builder( builder: (BuildContext context) { return materialTextSelectionControls.buildHandle( context, TextSelectionHandleType.left, 10.0, ); }, ), ), ), ); await tester.pumpAndSettle(); final RenderBox handle = tester.firstRenderObject<RenderBox>(find.byType(CustomPaint)); expect(handle, paints..path(color: defaultSelectionHandleColor)); }); testWidgets('ThemeData.textSelectionTheme will be used if provided', (WidgetTester tester) async { const TextSelectionThemeData textSelectionTheme = TextSelectionThemeData( cursorColor: Color(0xffaabbcc), selectionColor: Color(0x88888888), selectionHandleColor: Color(0x00ccbbaa), ); final ThemeData theme = ThemeData.fallback().copyWith( textSelectionTheme: textSelectionTheme, ); EditableText.debugDeterministicCursor = true; addTearDown(() { EditableText.debugDeterministicCursor = false; }); // Test TextField's cursor & selection color. await tester.pumpWidget( MaterialApp( theme: theme, home: const Material( child: TextField(autofocus: true), ), ), ); await tester.pump(); final EditableTextState editableTextState = tester.firstState(find.byType(EditableText)); final RenderEditable renderEditable = editableTextState.renderEditable; expect(renderEditable.cursorColor, textSelectionTheme.cursorColor); expect(renderEditable.selectionColor, textSelectionTheme.selectionColor); // Test the selection handle color. await tester.pumpWidget( MaterialApp( theme: theme, home: Material( child: Builder( builder: (BuildContext context) { return materialTextSelectionControls.buildHandle( context, TextSelectionHandleType.left, 10.0, ); }, ), ), ), ); await tester.pumpAndSettle(); final RenderBox handle = tester.firstRenderObject<RenderBox>(find.byType(CustomPaint)); expect(handle, paints..path(color: textSelectionTheme.selectionHandleColor)); }); testWidgets('TextSelectionTheme widget will override ThemeData.textSelectionTheme', (WidgetTester tester) async { const TextSelectionThemeData defaultTextSelectionTheme = TextSelectionThemeData( cursorColor: Color(0xffaabbcc), selectionColor: Color(0x88888888), selectionHandleColor: Color(0x00ccbbaa), ); final ThemeData theme = ThemeData.fallback().copyWith( textSelectionTheme: defaultTextSelectionTheme, ); const TextSelectionThemeData widgetTextSelectionTheme = TextSelectionThemeData( cursorColor: Color(0xffddeeff), selectionColor: Color(0x44444444), selectionHandleColor: Color(0x00ffeedd), ); EditableText.debugDeterministicCursor = true; addTearDown(() { EditableText.debugDeterministicCursor = false; }); // Test TextField's cursor & selection color. await tester.pumpWidget( MaterialApp( theme: theme, home: const Material( child: TextSelectionTheme( data: widgetTextSelectionTheme, child: TextField(autofocus: true), ), ), ), ); await tester.pump(); final EditableTextState editableTextState = tester.firstState(find.byType(EditableText)); final RenderEditable renderEditable = editableTextState.renderEditable; expect(renderEditable.cursorColor, widgetTextSelectionTheme.cursorColor); expect(renderEditable.selectionColor, widgetTextSelectionTheme.selectionColor); // Test the selection handle color. await tester.pumpWidget( MaterialApp( theme: theme, home: Material( child: TextSelectionTheme( data: widgetTextSelectionTheme, child: Builder( builder: (BuildContext context) { return materialTextSelectionControls.buildHandle( context, TextSelectionHandleType.left, 10.0, ); }, ), ), ), ), ); await tester.pumpAndSettle(); final RenderBox handle = tester.firstRenderObject<RenderBox>(find.byType(CustomPaint)); expect(handle, paints..path(color: widgetTextSelectionTheme.selectionHandleColor)); }); testWidgets('TextField parameters will override theme settings', (WidgetTester tester) async { const TextSelectionThemeData defaultTextSelectionTheme = TextSelectionThemeData( cursorColor: Color(0xffaabbcc), selectionHandleColor: Color(0x00ccbbaa), ); final ThemeData theme = ThemeData.fallback().copyWith( textSelectionTheme: defaultTextSelectionTheme, ); const TextSelectionThemeData widgetTextSelectionTheme = TextSelectionThemeData( cursorColor: Color(0xffddeeff), selectionHandleColor: Color(0x00ffeedd), ); const Color cursorColor = Color(0x88888888); // Test TextField's cursor color. await tester.pumpWidget( MaterialApp( theme: theme, home: const Material( child: TextSelectionTheme( data: widgetTextSelectionTheme, child: TextField(cursorColor: cursorColor), ), ), ), ); await tester.pumpAndSettle(); final EditableTextState editableTextState = tester.firstState(find.byType(EditableText)); final RenderEditable renderEditable = editableTextState.renderEditable; expect(renderEditable.cursorColor, cursorColor.withAlpha(0)); // Test SelectableText's cursor color. await tester.pumpWidget( MaterialApp( theme: theme, home: const Material( child: TextSelectionTheme( data: widgetTextSelectionTheme, child: SelectableText('foobar', cursorColor: cursorColor), ), ), ), ); await tester.pumpAndSettle(); final EditableTextState selectableTextState = tester.firstState(find.byType(EditableText)); final RenderEditable renderSelectable = selectableTextState.renderEditable; expect(renderSelectable.cursorColor, cursorColor.withAlpha(0)); }); testWidgets('TextSelectionThem overrides DefaultSelectionStyle', (WidgetTester tester) async { const Color themeSelectionColor = Color(0xffaabbcc); const Color themeCursorColor = Color(0x00ccbbaa); const Color defaultSelectionColor = Color(0xffaa1111); const Color defaultCursorColor = Color(0x00cc2222); final Key defaultSelectionStyle = UniqueKey(); final Key themeStyle = UniqueKey(); // Test TextField's cursor color. await tester.pumpWidget( MaterialApp( home: DefaultSelectionStyle( selectionColor: defaultSelectionColor, cursorColor: defaultCursorColor, child: Container( key: defaultSelectionStyle, child: TextSelectionTheme( data: const TextSelectionThemeData( selectionColor: themeSelectionColor, cursorColor: themeCursorColor, ), child: Placeholder( key: themeStyle, ), ), ) ), ), ); final BuildContext defaultSelectionStyleContext = tester.element(find.byKey(defaultSelectionStyle)); DefaultSelectionStyle style = DefaultSelectionStyle.of(defaultSelectionStyleContext); expect(style.selectionColor, defaultSelectionColor); expect(style.cursorColor, defaultCursorColor); final BuildContext themeStyleContext = tester.element(find.byKey(themeStyle)); style = DefaultSelectionStyle.of(themeStyleContext); expect(style.selectionColor, themeSelectionColor); expect(style.cursorColor, themeCursorColor); }); }