syncing_test.dart 5.57 KB
Newer Older
Ian Hickson's avatar
Ian Hickson committed
1
// Copyright 2014 The Flutter Authors. All rights reserved.
Hixie's avatar
Hixie committed
2 3 4
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

5
import 'package:flutter/material.dart';
Adam Barth's avatar
Adam Barth committed
6
import 'package:flutter_test/flutter_test.dart';
7
import 'package:leak_tracker_flutter_testing/leak_tracker_flutter_testing.dart';
8

9
class TestWidget extends StatefulWidget {
10
  const TestWidget({
11
    super.key,
12 13 14
    required this.child,
    required this.persistentState,
    required this.syncedState,
15
  });
16 17 18 19 20

  final Widget child;
  final int persistentState;
  final int syncedState;

21
  @override
22
  TestWidgetState createState() => TestWidgetState();
23 24 25
}

class TestWidgetState extends State<TestWidget> {
26 27
  late int persistentState;
  late int syncedState;
28 29
  int updates = 0;

30
  @override
31 32
  void initState() {
    super.initState();
33 34
    persistentState = widget.persistentState;
    syncedState = widget.syncedState;
35 36
  }

37
  @override
38
  void didUpdateWidget(TestWidget oldWidget) {
39
    super.didUpdateWidget(oldWidget);
40
    syncedState = widget.syncedState;
41
    // we explicitly do NOT sync the persistentState from the new instance
42
    // because we're using that to track whether we got recreated
43
    updates += 1;
44
  }
45

46
  @override
47
  Widget build(BuildContext context) => widget.child;
48 49 50 51
}

void main() {

52
  testWidgetsWithLeakTracking('no change', (WidgetTester tester) async {
53
    await tester.pumpWidget(
54
      ColoredBox(
55
        color: Colors.blue,
56
        child: ColoredBox(
57
          color: Colors.blue,
58
          child: TestWidget(
59
            persistentState: 1,
60
            syncedState: 0,
61 62 63
            child: Container(),
          ),
        ),
64
      ),
65
    );
66

67
    final TestWidgetState state = tester.state(find.byType(TestWidget));
68

69 70
    expect(state.persistentState, equals(1));
    expect(state.updates, equals(0));
71

72
    await tester.pumpWidget(
73
      ColoredBox(
74
        color: Colors.blue,
75
        child: ColoredBox(
76
          color: Colors.blue,
77
          child: TestWidget(
78
            persistentState: 2,
79
            syncedState: 0,
80 81 82
            child: Container(),
          ),
        ),
83
      ),
84
    );
85

86 87
    expect(state.persistentState, equals(1));
    expect(state.updates, equals(1));
88

89
    await tester.pumpWidget(Container());
90 91
  });

92
  testWidgetsWithLeakTracking('remove one', (WidgetTester tester) async {
93
    await tester.pumpWidget(
94
      ColoredBox(
95
        color: Colors.blue,
96
        child: ColoredBox(
97
          color: Colors.blue,
98
          child: TestWidget(
99
            persistentState: 10,
100
            syncedState: 0,
101 102 103
            child: Container(),
          ),
        ),
104
      ),
105
    );
106

107
    TestWidgetState state = tester.state(find.byType(TestWidget));
108

109 110
    expect(state.persistentState, equals(10));
    expect(state.updates, equals(0));
111

112
    await tester.pumpWidget(
113
      ColoredBox(
114
        color: Colors.green,
115
        child: TestWidget(
116
          persistentState: 11,
117
          syncedState: 0,
118 119
          child: Container(),
        ),
120
      ),
121
    );
122

123
    state = tester.state(find.byType(TestWidget));
124

125 126
    expect(state.persistentState, equals(11));
    expect(state.updates, equals(0));
127

128
    await tester.pumpWidget(Container());
129
  });
130

131
  testWidgetsWithLeakTracking('swap instances around', (WidgetTester tester) async {
132 133
    const Widget a = TestWidget(persistentState: 0x61, syncedState: 0x41, child: Text('apple', textDirection: TextDirection.ltr));
    const Widget b = TestWidget(persistentState: 0x62, syncedState: 0x42, child: Text('banana', textDirection: TextDirection.ltr));
134
    await tester.pumpWidget(const Column());
135

136 137
    final GlobalKey keyA = GlobalKey();
    final GlobalKey keyB = GlobalKey();
138

139
    await tester.pumpWidget(
140
      Column(
141
        children: <Widget>[
142
          Container(
143
            key: keyA,
144
            child: a,
145
          ),
146
          Container(
147
            key: keyB,
148 149 150
            child: b,
          ),
        ],
151
      ),
152 153 154 155
    );

    TestWidgetState first, second;

156 157
    first = tester.state(find.byWidget(a));
    second = tester.state(find.byWidget(b));
158

159
    expect(first.widget, equals(a));
160 161
    expect(first.persistentState, equals(0x61));
    expect(first.syncedState, equals(0x41));
162
    expect(second.widget, equals(b));
163 164 165
    expect(second.persistentState, equals(0x62));
    expect(second.syncedState, equals(0x42));

166
    await tester.pumpWidget(
167
      Column(
168
        children: <Widget>[
169
          Container(
170
            key: keyA,
171
            child: a,
172
          ),
173
          Container(
174
            key: keyB,
175 176 177
            child: b,
          ),
        ],
178
      ),
179 180
    );

181 182
    first = tester.state(find.byWidget(a));
    second = tester.state(find.byWidget(b));
183 184

    // same as before
185
    expect(first.widget, equals(a));
186 187
    expect(first.persistentState, equals(0x61));
    expect(first.syncedState, equals(0x41));
188
    expect(second.widget, equals(b));
189 190 191 192 193 194
    expect(second.persistentState, equals(0x62));
    expect(second.syncedState, equals(0x42));

    // now we swap the nodes over
    // since they are both "old" nodes, they shouldn't sync with each other even though they look alike

195
    await tester.pumpWidget(
196
      Column(
197
        children: <Widget>[
198
          Container(
199
            key: keyA,
200
            child: b,
201
          ),
202
          Container(
203
            key: keyB,
204 205 206
            child: a,
          ),
        ],
207
      ),
208 209
    );

210 211
    first = tester.state(find.byWidget(b));
    second = tester.state(find.byWidget(a));
212

213
    expect(first.widget, equals(b));
214 215
    expect(first.persistentState, equals(0x61));
    expect(first.syncedState, equals(0x42));
216
    expect(second.widget, equals(a));
217 218
    expect(second.persistentState, equals(0x62));
    expect(second.syncedState, equals(0x41));
219
  });
220
}