gesture_config_regression_test.dart 4.61 KB
Newer Older
1 2 3 4 5 6 7 8 9
// 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 'dart:ui' as ui;

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

10 11
import '../foundation/leak_tracking.dart';

12 13 14 15 16
class TestResult {
  bool dragStarted = false;
  bool dragUpdate = false;
}

17
class NestedScrollableCase extends StatelessWidget {
18
  const NestedScrollableCase({super.key, required this.testResult});
19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35

  final TestResult testResult;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: CustomScrollView(
        slivers: <Widget>[
          SliverFixedExtentList(
            itemExtent: 50.0,
            delegate: SliverChildBuilderDelegate(
              (BuildContext context, int index) {
                return Container(
                  alignment: Alignment.center,
                  child: GestureDetector(
                    behavior: HitTestBehavior.opaque,
                    onVerticalDragDown: (DragDownDetails details) {
36
                      testResult.dragStarted = true;
37 38
                    },
                    onVerticalDragUpdate: (DragUpdateDetails details){
39
                      testResult.dragUpdate = true;
40 41 42 43 44 45 46 47 48 49 50 51 52 53 54
                    },
                    onVerticalDragEnd: (_) {},
                    child: Text('List Item $index', key: ValueKey<int>(index),
                    ),
                  ),
                );
              },
            ),
          ),
        ],
      ),
    );
  }
}

Lioness100's avatar
Lioness100 committed
55 56
class NestedDraggableCase extends StatelessWidget {
  const NestedDraggableCase({super.key, required this.testResult});
57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75

  final TestResult testResult;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: CustomScrollView(
        slivers: <Widget>[
          SliverFixedExtentList(
            itemExtent: 50.0,
            delegate: SliverChildBuilderDelegate(
              (BuildContext context, int index) {
                return Container(
                  alignment: Alignment.center,
                  child: Draggable<Object>(
                    key: ValueKey<int>(index),
                    feedback: const Text('Dragging'),
                    child: Text('List Item $index'),
                    onDragStarted: () {
76
                      testResult.dragStarted = true;
77 78
                    },
                    onDragUpdate: (DragUpdateDetails details){
79
                      testResult.dragUpdate = true;
80 81 82 83 84 85 86 87 88 89 90 91 92
                    },
                    onDragEnd: (_) {},
                  ),
                );
              },
            ),
          ),
        ],
      ),
    );
  }
}

93
void main() {
94
  testWidgetsWithLeakTracking('Scroll Views get the same ScrollConfiguration as GestureDetectors', (WidgetTester tester) async {
95 96 97
    tester.view.gestureSettings = const ui.GestureSettings(physicalTouchSlop: 4);
    addTearDown(tester.view.reset);

98 99 100 101
    final TestResult result = TestResult();

    await tester.pumpWidget(MaterialApp(
      title: 'Scroll Bug',
102 103 104 105 106 107 108 109 110 111 112 113 114 115 116
      home: NestedScrollableCase(testResult: result),
    ));

    // By dragging the scroll view more than the configured touch slop above but less than
    // the framework default value, we demonstrate that this causes gesture detectors
    // that do not receive the same gesture settings to fire at different times than would
    // be expected.
    final Offset start = tester.getCenter(find.byKey(const ValueKey<int>(1)));
    await tester.timedDragFrom(start, const Offset(0, 5), const Duration(milliseconds: 50));
    await tester.pumpAndSettle();

   expect(result.dragStarted, true);
   expect(result.dragUpdate, true);
  });

117
  testWidgetsWithLeakTracking('Scroll Views get the same ScrollConfiguration as Draggables', (WidgetTester tester) async {
118 119
    tester.view.gestureSettings = const ui.GestureSettings(physicalTouchSlop: 4);
    addTearDown(tester.view.reset);
120

121 122 123 124
    final TestResult result = TestResult();

    await tester.pumpWidget(MaterialApp(
      title: 'Scroll Bug',
Lioness100's avatar
Lioness100 committed
125
      home: NestedDraggableCase(testResult: result),
126 127 128 129 130 131 132 133 134 135 136 137 138 139
    ));

    // By dragging the scroll view more than the configured touch slop above but less than
    // the framework default value, we demonstrate that this causes gesture detectors
    // that do not receive the same gesture settings to fire at different times than would
    // be expected.
    final Offset start = tester.getCenter(find.byKey(const ValueKey<int>(1)));
    await tester.timedDragFrom(start, const Offset(0, 5), const Duration(milliseconds: 50));
    await tester.pumpAndSettle();

   expect(result.dragStarted, true);
   expect(result.dragUpdate, true);
  });
}