18

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: Maybe the widget is actually off-screen, or another widget is obscuring it, or the widget cannot receive pointer events.

The tap is never executed so the next part of the test fails. 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);
  });
}
Lee Mordell
  • 473
  • 5
  • 16

3 Answers3

12

Try to set ensureVisible() before 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();
  • 4
    Thanks for the suggestion. [ensureVisible](https://docs-flutter-io.firebaseapp.com/flutter/flutter_test/WidgetTester/ensureVisible.html) is great when a widget is off-screen and you want to scroll to it; however, in my case the widget is clearly visible on the screen. – Lee Mordell Jul 15 '21 at 16:30
  • I am currently having the same issue @LeeMordell , but when I run the test on the simulator, it is visible as you mentioned in your comment. Did you manage to find a solution to this issue? – Emir Bostancı Nov 22 '21 at 09:30
  • 1
    ensureVisible is not about not being visible in real simulator, is about this specific component being visible on screen on test emulator. So, it simulates a scroll on emulator screen till the related component is visible – William Cunha Cardoso Nov 23 '21 at 18:21
1

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. The fix is to call await tester.pumpAndSettle(); which flushes out all pending animations.

I believe a side effect of ensureVisible() is something similar which is why it works.

Jstuff
  • 1,266
  • 2
  • 16
  • 27
0

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. When I'd run the test on chrome it would pass, but would fail when run heedlessly.

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.

  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;
Lee Mordell
  • 473
  • 5
  • 16