slivers_block_global_key_test.dart 4.7 KB
Newer Older
Ian Hickson's avatar
Ian Hickson committed
1
// Copyright 2014 The Flutter Authors. All rights reserved.
Ian Hickson's avatar
Ian Hickson committed
2 3 4 5 6 7 8 9 10 11
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import 'package:flutter_test/flutter_test.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter/widgets.dart';

int globalGeneration = 0;

class GenerationText extends StatefulWidget {
12
  const GenerationText(this.value, { Key key }) : super(key: key);
Ian Hickson's avatar
Ian Hickson committed
13 14
  final int value;
  @override
15
  _GenerationTextState createState() => _GenerationTextState();
Ian Hickson's avatar
Ian Hickson committed
16 17 18 19 20 21
}

class _GenerationTextState extends State<GenerationText> {
  _GenerationTextState() : generation = globalGeneration;
  final int generation;
  @override
22
  Widget build(BuildContext context) => Text('${widget.value}:$generation ', textDirection: TextDirection.ltr);
Ian Hickson's avatar
Ian Hickson committed
23 24
}

25 26
// Creates a SliverList with `keys.length` children and each child having a key from `keys` and a text of `key:generation`.
// The generation is increased with every call to this method.
27
Future<void> test(WidgetTester tester, double offset, List<int> keys) {
Ian Hickson's avatar
Ian Hickson committed
28
  globalGeneration += 1;
29
  return tester.pumpWidget(
30
    Directionality(
31
      textDirection: TextDirection.ltr,
32
      child: Viewport(
33
        cacheExtent: 0.0,
34
        offset: ViewportOffset.fixed(offset),
35
        slivers: <Widget>[
36
          SliverList(
37
            delegate: SliverChildListDelegate(keys.map<Widget>((int key) {
38
              return SizedBox(key: GlobalObjectKey(key), height: 100.0, child: GenerationText(key));
39 40 41
            }).toList()),
          ),
        ],
Ian Hickson's avatar
Ian Hickson committed
42
      ),
43 44
    ),
  );
Ian Hickson's avatar
Ian Hickson committed
45 46
}

47 48
// `answerKey`: Expected offsets of visible SliverList children in global coordinate system.
// `text`: A space-separated list of expected `key:generation` pairs for the visible SliverList children.
49 50 51
void verify(WidgetTester tester, List<Offset> answerKey, String text) {
  final List<Offset> testAnswers = tester.renderObjectList<RenderBox>(find.byType(SizedBox)).map<Offset>(
    (RenderBox target) => target.localToGlobal(const Offset(0.0, 0.0))
Ian Hickson's avatar
Ian Hickson committed
52 53 54
  ).toList();
  expect(testAnswers, equals(answerKey));
  final String foundText =
Ian Hickson's avatar
Ian Hickson committed
55
    tester.widgetList<Text>(find.byType(Text))
56 57
        .map<String>((Text widget) => widget.data)
        .reduce((String value, String element) => value + element);
Ian Hickson's avatar
Ian Hickson committed
58 59 60 61
  expect(foundText, equals(text));
}

void main() {
Adam Barth's avatar
Adam Barth committed
62
  testWidgets('Viewport+SliverBlock with GlobalKey reparenting', (WidgetTester tester) async {
Ian Hickson's avatar
Ian Hickson committed
63
    await test(tester, 0.0, <int>[1,2,3,4,5,6,7,8,9]);
64 65 66 67 68 69 70
    verify(tester, <Offset>[
      const Offset(0.0, 0.0),
      const Offset(0.0, 100.0),
      const Offset(0.0, 200.0),
      const Offset(0.0, 300.0),
      const Offset(0.0, 400.0),
      const Offset(0.0, 500.0),
Ian Hickson's avatar
Ian Hickson committed
71 72 73
    ], '1:1 2:1 3:1 4:1 5:1 6:1 ');
    // gen 2 - flipping the order:
    await test(tester, 0.0, <int>[9,8,7,6,5,4,3,2,1]);
74 75 76 77 78 79 80
    verify(tester, <Offset>[
      const Offset(0.0, 0.0),
      const Offset(0.0, 100.0),
      const Offset(0.0, 200.0),
      const Offset(0.0, 300.0),
      const Offset(0.0, 400.0),
      const Offset(0.0, 500.0),
Ian Hickson's avatar
Ian Hickson committed
81 82 83
    ], '9:2 8:2 7:2 6:1 5:1 4:1 ');
    // gen 3 - flipping the order back:
    await test(tester, 0.0, <int>[1,2,3,4,5,6,7,8,9]);
84 85 86 87 88 89 90
    verify(tester, <Offset>[
      const Offset(0.0, 0.0),
      const Offset(0.0, 100.0),
      const Offset(0.0, 200.0),
      const Offset(0.0, 300.0),
      const Offset(0.0, 400.0),
      const Offset(0.0, 500.0),
Ian Hickson's avatar
Ian Hickson committed
91 92 93
    ], '1:3 2:3 3:3 4:1 5:1 6:1 ');
    // gen 4 - removal:
    await test(tester, 0.0, <int>[1,2,3,5,6,7,8,9]);
94 95 96 97 98 99 100
    verify(tester, <Offset>[
      const Offset(0.0, 0.0),
      const Offset(0.0, 100.0),
      const Offset(0.0, 200.0),
      const Offset(0.0, 300.0),
      const Offset(0.0, 400.0),
      const Offset(0.0, 500.0),
Ian Hickson's avatar
Ian Hickson committed
101 102 103
    ], '1:3 2:3 3:3 5:1 6:1 7:4 ');
    // gen 5 - insertion:
    await test(tester, 0.0, <int>[1,2,3,4,5,6,7,8,9]);
104 105 106 107 108 109 110
    verify(tester, <Offset>[
      const Offset(0.0, 0.0),
      const Offset(0.0, 100.0),
      const Offset(0.0, 200.0),
      const Offset(0.0, 300.0),
      const Offset(0.0, 400.0),
      const Offset(0.0, 500.0),
Ian Hickson's avatar
Ian Hickson committed
111 112 113
    ], '1:3 2:3 3:3 4:5 5:1 6:1 ');
    // gen 6 - adjacent reordering:
    await test(tester, 0.0, <int>[1,2,3,5,4,6,7,8,9]);
114 115 116 117 118 119 120
    verify(tester, <Offset>[
      const Offset(0.0, 0.0),
      const Offset(0.0, 100.0),
      const Offset(0.0, 200.0),
      const Offset(0.0, 300.0),
      const Offset(0.0, 400.0),
      const Offset(0.0, 500.0),
Ian Hickson's avatar
Ian Hickson committed
121 122 123
    ], '1:3 2:3 3:3 5:1 4:5 6:1 ');
    // gen 7 - scrolling:
    await test(tester, 120.0, <int>[1,2,3,5,4,6,7,8,9]);
124 125 126 127 128 129 130 131
    verify(tester, <Offset>[
      const Offset(0.0, -20.0),
      const Offset(0.0, 80.0),
      const Offset(0.0, 180.0),
      const Offset(0.0, 280.0),
      const Offset(0.0, 380.0),
      const Offset(0.0, 480.0),
      const Offset(0.0, 580.0),
Ian Hickson's avatar
Ian Hickson committed
132 133 134
    ], '2:3 3:3 5:1 4:5 6:1 7:7 8:7 ');
  });
}