简体   繁体   English

Flutter 小部件测试点击 - 不会在指定的小部件上进行测试

[英]Flutter widget test tap - would not hit test on the specified widget

My widget test is failing after the following warning is outputted:输出以下警告后,我的小部件测试失败:

flutter: Warning: A call to tap() with finder "exactly one widget with text "Tab 2" (ignoring offstage widgets): Text("Tab 2", softWrap: no wrapping except at line break characters, overflow: fade, dependencies: [MediaQuery, DefaultTextStyle])" derived an Offset (Offset(600.0, 23.0)) that would not hit test on the specified widget. flutter:警告:使用 finder 调用 tap() “恰好是一个带有文本“Tab 2”的小部件(忽略后台小部件):文本(“Tab 2”,softWrap:除换行符外没有换行,溢出:淡入淡出,依赖性: [MediaQuery, DefaultTextStyle])" 派生了一个不会在指定小部件上进行测试的偏移量 (Offset(600.0, 23.0))。 flutter: Maybe the widget is actually off-screen, or another widget is obscuring it, or the widget cannot receive pointer events. flutter:可能是widget实际上在屏幕外,或者其他widget遮挡了它,或者widget无法接收指针事件。

The tap is never executed so the next part of the test fails. tap 永远不会执行,因此测试的下一部分失败。 I put some delays in the test and it appears that the test is attempting to tap the correct widget - it is not offscreen, not obscured, and was able to receive pointer events in the past - not sure why it's currently failing.我在测试中设置了一些延迟,看起来测试正在尝试点击正确的小部件 - 它没有在屏幕外,没有被遮挡,并且过去能够接收指针事件 - 不确定为什么它目前失败了。

Here is a minimal reproducible example:这是一个最小的可重现示例:

import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: DefaultTabController(
        length: 2,
        child: Scaffold(
          appBar: TabBar(
            labelColor: Color(0xff8391e4),
            tabs: [
              Tab(text: 'Tab 1'),
              Tab(text: 'Tab 2'),
            ],
          ),
          body: TabBarView(
            children: <Widget>[
              Text('Tab 1 Text'),
              Text('Tab 2 Text'),
            ],
          ),
        ),
      ),
    );
  }
}

void main() {
  TestWidgetsFlutterBinding.ensureInitialized();

  testWidgets('My Test', (WidgetTester tester) async {
    await tester.pumpWidget(MyApp());
    await tester.pumpAndSettle();

    // Warning thrown on this tap - tap never executed
    await tester.tap(find.text('Tab 2'));
    await tester.pumpAndSettle();

    // Test fails here
    expect(find.text('Tab 2 Text'), findsOneWidget);
  });
}

In my case, when I have modal screen, this works:就我而言,当我有模态屏幕时,这有效:

await tester.tap(find.byKey(Key('some_key')), warnIfMissed: false);

Try to set ensureVisible() before tap() :尝试在ensureVisible()之前设置ensureVisible() tap()

// Warning thrown on this tap - tap never executed
await tester.ensureVisible(find.text('Tab 2'));
await tester.tap(find.text('Tab 2'));
await tester.pumpAndSettle();

I found a solution to my problem, but it may not be a universal solution.我找到了解决我的问题的方法,但它可能不是通用的解决方案。 The app that this test is for is exclusively a web app so it's designed to run on larger screen sizes.此测试所针对的应用程序完全是一个 Web 应用程序,因此它旨在在更大的屏幕尺寸上运行。 When I'd run the test on chrome it would pass, but would fail when run heedlessly.当我在 chrome 上运行测试时,它会通过,但在粗心运行时会失败。

To fix, I run the test at a larger screen size and it now passes heedlessly.为了解决这个问题,我在更大的屏幕尺寸下运行测试,现在它漫不经心地通过了。 So if you run into the A call to tap() ... that would not hit test on the specified widget error, adjusting the screen size might fix the issue.因此,如果您遇到A call to tap() ... that would not hit test on the specified widgetA call to tap() ... that would not hit test on the specified widget错误进行A call to tap() ... that would not hit test on the specified widget ,则调整屏幕大小可能会解决该问题。

  testWidgets('My test', (WidgetTester tester) async {
      // Here we use physicalSizeTestValue to adjust the test screen size to
      // simulate running on a desktop computer which the app was designed for
      tester.binding.window.physicalSizeTestValue = Size(1080, 1920);
      tester.binding.window.devicePixelRatioTestValue = 1.0;

Incase, anyone comes across this question in the future.以防万一,以后有人会遇到这个问题。

I had this same problem it was because I had animation still running in the background.我遇到了同样的问题,因为我的 animation 仍在后台运行。 The fix is to call await tester.pumpAndSettle();解决方法是调用await tester.pumpAndSettle(); which flushes out all pending animations.这会清除所有挂起的动画。

I believe a side effect of ensureVisible() is something similar which is why it works.我相信ensureVisible()的副作用是类似的,这就是它起作用的原因。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM