Skip to content

selectable_region_test.dart failure when switching to M3 #129626

@bleroux

Description

@bleroux

Is there an existing issue for this?

Steps to reproduce

When switching to Material 3 the following existing test fails:

testWidgets(
'can select word when a selectables rect is completely inside of another selectables rect', (WidgetTester tester) async {
// Regression test for https://github.com/flutter/flutter/issues/127076.
final UniqueKey outerText = UniqueKey();
await tester.pumpWidget(
MaterialApp(
home: SelectableRegion(
focusNode: FocusNode(),
selectionControls: materialTextSelectionControls,
child: Scaffold(
body: Center(
child: Text.rich(
const TextSpan(
children: <InlineSpan>[
TextSpan(
text:
'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.',
),
WidgetSpan(child: Text('Some text in a WidgetSpan. ')),
TextSpan(text: 'Hello, world.'),
],
),
key: outerText,
),
),
),
),
),
);
final RenderParagraph paragraph = tester.renderObject<RenderParagraph>(find.descendant(of: find.byKey(outerText), matching: find.byType(RichText)).first);
// Right click to select word at position.
final TestGesture gesture = await tester.startGesture(textOffsetToPosition(paragraph, 125), kind: PointerDeviceKind.mouse, buttons: kSecondaryMouseButton);
addTearDown(gesture.removePointer);
await tester.pump();
await gesture.up();
await tester.pump();
// Should select "Hello".
expect(paragraph.selections[0], const TextSelection(baseOffset: 124, extentOffset: 129));
},
variant: TargetPlatformVariant.only(TargetPlatform.macOS),
skip: isBrowser, // https://github.com/flutter/flutter/issues/61020
);

(This test was introduced in #127478).

M3 typography (Typography.material2021) sets TextStyle.height to 1.43, M2 typography does not set line height.

This particular test is broken because textOffsetToPosition returns the wrong vertical position (probably related to line height).

Visually the line height also affects the rendering (issue is described in #97262).

Expected results

Test succeeds

Actual results

Test fails

Code sample

Code sample
// 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/gestures.dart';
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter_test/flutter_test.dart';

Offset textOffsetToPosition(RenderParagraph paragraph, int offset) {
  const Rect caret = Rect.fromLTWH(0.0, 0.0, 2.0, 20.0);
  final Offset localOffset =
      paragraph.getOffsetForCaret(TextPosition(offset: offset), caret);
  return paragraph.localToGlobal(localOffset);
}

void main() {
  testWidgets(
    'can select word when a selectables rect is completely inside of another selectables rect',
    (WidgetTester tester) async {
      // Regression test for https://github.com/flutter/flutter/issues/127076.
      final UniqueKey outerText = UniqueKey();
      await tester.pumpWidget(
        MaterialApp(
          theme: ThemeData(useMaterial3: true),
          home: SelectableRegion(
            focusNode: FocusNode(),
            selectionControls: materialTextSelectionControls,
            child: Scaffold(
              body: Center(
                child: Text.rich(
                  const TextSpan(
                    children: <InlineSpan>[
                      TextSpan(
                        text:
                            'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.',
                      ),
                      WidgetSpan(child: Text('Some text in a WidgetSpan. ')),
                      TextSpan(text: 'Hello, world.'),
                    ],
                  ),
                  key: outerText,
                ),
              ),
            ),
          ),
        ),
      );
      final RenderParagraph paragraph = tester.renderObject<RenderParagraph>(
          find
              .descendant(
                  of: find.byKey(outerText), matching: find.byType(RichText))
              .first);
      // Right click to select word at position.
      final TestGesture gesture = await tester.startGesture(
          textOffsetToPosition(paragraph, 125),
          kind: PointerDeviceKind.mouse,
          buttons: kSecondaryMouseButton);
      addTearDown(gesture.removePointer);
      await tester.pump();
      await gesture.up();
      await tester.pump();
      // Should select "Hello".
      expect(paragraph.selections[0],
          const TextSelection(baseOffset: 124, extentOffset: 129));
    },
    variant: TargetPlatformVariant.only(TargetPlatform.macOS),
    skip: isBrowser, // https://github.com/flutter/flutter/issues/61020
  );
}

Screenshots or Video

Screenshots / Video demonstration

[Upload media here]

Logs

Logs
══╡ EXCEPTION CAUGHT BY GESTURE ╞═══════════════════════════════════════════════════════════════════
The following assertion was thrown while handling a gesture:
'package:flutter/src/widgets/selectable_region.dart': Failed assertion: line 2003 pos 12:
'lastSelectionResult == null': is not true.

Either the assertion indicates an error in the framework itself, or we should provide substantially
more information in this error message to help you determine and fix the underlying cause.
In either case, please report this assertion by filing a bug on GitHub:
  https://github.com/flutter/flutter/issues/new?template=2_bug.yml

When the exception was thrown, this was the stack:
#2      MultiSelectableSelectionContainerDelegate.handleSelectWord (package:flutter/src/widgets/selectable_region.dart:2003:12)
#3      _SelectableRegionContainerDelegate.handleSelectWord (package:flutter/src/widgets/selectable_region.dart:1384:42)
#4      MultiSelectableSelectionContainerDelegate.dispatchSelectionEvent (package:flutter/src/widgets/selectable_region.dart:2139:18)
#5      _SelectionContainerState.dispatchSelectionEvent (package:flutter/src/widgets/selection_container.dart:187:29)
#6      SelectableRegionState._selectWordAt (package:flutter/src/widgets/selectable_region.dart:913:18)
#7      SelectableRegionState._handleRightClickDown (package:flutter/src/widgets/selectable_region.dart:529:9)
#8      TapGestureRecognizer.handleTapDown.<anonymous closure> (package:flutter/src/gestures/tap.dart:630:79)
#9      GestureRecognizer.invokeCallback (package:flutter/src/gestures/recognizer.dart:275:24)
#10     TapGestureRecognizer.handleTapDown (package:flutter/src/gestures/tap.dart:630:11)
#11     BaseTapGestureRecognizer._checkDown (package:flutter/src/gestures/tap.dart:302:5)
#12     BaseTapGestureRecognizer.acceptGesture (package:flutter/src/gestures/tap.dart:279:7)
#13     GestureArenaManager._resolveByDefault (package:flutter/src/gestures/arena.dart:268:25)
#14     GestureArenaManager._tryToResolveArena.<anonymous closure> (package:flutter/src/gestures/arena.dart:248:31)
#21     FakeAsync.flushMicrotasks (package:fake_async/fake_async.dart:197:32)
#22     AutomatedTestWidgetsFlutterBinding.runTest.<anonymous closure> (package:flutter_test/src/binding.dart:1493:17)
(elided 23 frames from class _AssertionError, dart:async, and package:stack_trace)

Handler: "onSecondaryTapDown"
Recognizer:
  TapGestureRecognizer#d7829
════════════════════════════════════════════════════════════════════════════════════════════════════
══╡ EXCEPTION CAUGHT BY FLUTTER TEST FRAMEWORK ╞════════════════════════════════════════════════════
The following RangeError was thrown running a test:
RangeError (index): Invalid value: Valid value range is empty: 0

When the exception was thrown, this was the stack:
#0      List.[] (dart:core-patch/growable_array.dart:264:36)
#1      main.<anonymous closure>.<anonymous closure> (file:///home/bruno/Nevercode/flutter/packages/flutter/test/widgets/selectable_region_test.dart:1282:34)
<asynchronous suspension>
<asynchronous suspension>
(elided one frame from package:stack_trace)

The test description was:
  can select word when a selectables rect is completely inside of another selectables rect (variant:
  TargetPlatform.macOS)
════════════════════════════════════════════════════════════════════════════════════════════════════
══╡ EXCEPTION CAUGHT BY FLUTTER TEST FRAMEWORK ╞════════════════════════════════════════════════════
The following message was thrown:
Multiple exceptions (2) were detected during the running of the current test, and at least one was
unexpected.
════════════════════════════════════════════════════════════════════════════════════════════════════
Test failed. See exception logs above.
The test description was: can select word when a selectables rect is completely inside of another selectables rect (variant: TargetPlatform.macOS)


✖ SelectionArea integration can select word when a selectables rect is completely inside of another selectables rect (variant: TargetPlatform.macOS)

Exited (1).

Flutter Doctor output

Doctor output
[!] Flutter (Channel [user-branch], 3.11.0-2.0.pre.803, on Ubuntu 22.10 5.19.0-45-generic, locale fr_FR.UTF-8)
    ! Flutter version 3.11.0-2.0.pre.803 on channel [user-branch] at /home/bruno/Nevercode/flutter
      Currently on an unknown channel. Run `flutter channel` to switch to an official channel.
      If that doesn't fix the issue, reinstall Flutter by following instructions at https://flutter.dev/docs/get-started/install.
    • Upstream repository git@github.com:NevercodeHQ/flutter.git
    • FLUTTER_GIT_URL = git@github.com:NevercodeHQ/flutter.git
    • Framework revision 7dbdacff46 (il y a 11 heures), 2023-06-26 22:05:23 -0400
    • Engine revision f320b8c36f
    • Dart version 3.1.0 (build 3.1.0-246.0.dev)
    • DevTools version 2.24.0
    • If those were intentional, you can disregard the above warnings; however it is recommended to use "git" directly to perform update checks and
      upgrades.

[✓] Android toolchain - develop for Android devices (Android SDK version 33.0.2)
    • Android SDK at /media/oldhome/Android/Sdk
    • Platform android-33-ext5, build-tools 33.0.2
    • ANDROID_HOME = /media/oldhome/Android/Sdk
    • Java binary at: /media/oldhome/Produits/android-studio/jre/bin/java
    • Java version OpenJDK Runtime Environment (build 11.0.13+0-b1751.21-8125866)
    • All Android licenses accepted.

[✓] Chrome - develop for the web
    • Chrome at google-chrome

[✓] Linux toolchain - develop for Linux desktop
    • Ubuntu clang version 15.0.7
    • cmake version 3.24.2
    • ninja version 1.11.0
    • pkg-config version 0.29.2

[✓] Android Studio (version 2021.3)
    • Android Studio at /media/oldhome/Produits/android-studio
    • Flutter plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/9212-flutter
    • Dart plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/6351-dart
    • Java version OpenJDK Runtime Environment (build 11.0.13+0-b1751.21-8125866)

[✓] VS Code (version unknown)
    • VS Code at /snap/code/current
    • Flutter extension version 3.66.0
    ✗ Unable to determine VS Code version.

[✓] Connected device (2 available)
    • Linux (desktop) • linux  • linux-x64      • Ubuntu 22.10 5.19.0-45-generic
    • Chrome (web)    • chrome • web-javascript • Google Chrome 114.0.5735.133

[✓] Network resources
    • All expected network resources are available.

! Doctor found issues in 1 category.```

</details>

Metadata

Metadata

Assignees

Labels

P2Important issues not at the top of the work listf: material designflutter/packages/flutter/material repository.f: selectionSelectableRegion, SelectionArea, SelectionContainer, Selectable, and related APIsfound in release: 3.12Found to occur in 3.12frameworkflutter/packages/flutter repository. See also f: labels.has reproducible stepsThe issue has been confirmed reproducible and is ready to work onr: fixedIssue is closed as already fixed in a newer versionteam-designOwned by Design Languages teamtriaged-designTriaged by Design Languages team

Type

No type

Projects

Status

Done (PR merged)

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions