@@ -30,6 +30,120 @@ void main() {
30
30
Future <void > sendUndo (WidgetTester tester) => sendUndoRedo (tester);
31
31
Future <void > sendRedo (WidgetTester tester) => sendUndoRedo (tester, true );
32
32
33
+ testWidgets ('UndoHistory widget registers as global undo/redo client' , (WidgetTester tester) async {
34
+ final FocusNode focusNode = FocusNode (debugLabel: 'UndoHistory Node' );
35
+ final GlobalKey undoHistoryGlobalKey = GlobalKey ();
36
+ final ValueNotifier <int > value = ValueNotifier <int >(0 );
37
+ addTearDown (value.dispose);
38
+
39
+ await tester.pumpWidget (
40
+ MaterialApp (
41
+ home: UndoHistory <int >(
42
+ key: undoHistoryGlobalKey,
43
+ value: value,
44
+ onTriggered: (_) {},
45
+ focusNode: focusNode,
46
+ child: Focus (
47
+ focusNode: focusNode,
48
+ child: Container (),
49
+ ),
50
+ ),
51
+ ),
52
+ );
53
+
54
+ // Initially the UndoHistory doesn't have focus, therefore it should
55
+ // not be the global undo/redo client. Ensure that's the case.
56
+ expect (UndoManager .client, isNull);
57
+
58
+ // Give focus to the UndoHistory widget.
59
+ focusNode.requestFocus ();
60
+ await tester.pump ();
61
+
62
+ // Now that the UndoHistory widget has focus, it should have registered
63
+ // itself as the global undo/redo client.
64
+ final State ? undoHistoryState = undoHistoryGlobalKey.currentState;
65
+ expect (UndoManager .client, undoHistoryState);
66
+ });
67
+
68
+ testWidgets ('UndoHistory widget deregisters as global undo/redo client when it loses focus' ,
69
+ (WidgetTester tester) async {
70
+ final FocusNode focusNode = FocusNode (debugLabel: 'UndoHistory Node' );
71
+ final GlobalKey undoHistoryGlobalKey = GlobalKey ();
72
+ final ValueNotifier <int > value = ValueNotifier <int >(0 );
73
+ addTearDown (value.dispose);
74
+
75
+ await tester.pumpWidget (
76
+ MaterialApp (
77
+ home: UndoHistory <int >(
78
+ key: undoHistoryGlobalKey,
79
+ value: value,
80
+ onTriggered: (_) {},
81
+ focusNode: focusNode,
82
+ child: Focus (
83
+ focusNode: focusNode,
84
+ child: Container (),
85
+ ),
86
+ ),
87
+ ),
88
+ );
89
+
90
+ // Give focus to the UndoHistory widget.
91
+ focusNode.requestFocus ();
92
+ await tester.pump ();
93
+
94
+ // Ensure that UndoHistory is the global undo/redo client.
95
+ final State ? undoHistoryState = undoHistoryGlobalKey.currentState;
96
+ expect (UndoManager .client, undoHistoryState);
97
+
98
+ // Remove focus from UndoHistory widget.
99
+ focusNode.unfocus ();
100
+ await tester.pump ();
101
+
102
+ // Ensure the UndoHistory widget is no longer the global client
103
+ expect (UndoManager .client, null );
104
+ });
105
+
106
+ testWidgets ('UndoHistory widget deregisters as global undo/redo client when disposed' , (WidgetTester tester) async {
107
+ final FocusNode focusNode = FocusNode (debugLabel: 'UndoHistory Node' );
108
+ final GlobalKey undoHistoryGlobalKey = GlobalKey ();
109
+ final ValueNotifier <int > value = ValueNotifier <int >(0 );
110
+ addTearDown (value.dispose);
111
+
112
+ await tester.pumpWidget (
113
+ MaterialApp (
114
+ home: UndoHistory <int >(
115
+ key: undoHistoryGlobalKey,
116
+ value: value,
117
+ onTriggered: (_) {},
118
+ focusNode: focusNode,
119
+ child: Focus (
120
+ focusNode: focusNode,
121
+ child: Container (),
122
+ ),
123
+ ),
124
+ ),
125
+ );
126
+
127
+ // Give focus to the UndoHistory widget.
128
+ focusNode.requestFocus ();
129
+ await tester.pump ();
130
+
131
+ // Ensure that UndoHistory is the global undo/redo client.
132
+ final State ? undoHistoryState = undoHistoryGlobalKey.currentState;
133
+ expect (UndoManager .client, undoHistoryState);
134
+
135
+ // Cause the UndoHistory widget to dispose its state.
136
+ await tester.pumpWidget (
137
+ const MaterialApp (
138
+ home: SizedBox (),
139
+ ),
140
+ );
141
+
142
+ // Ensure that the disposed UndoHistory state is not still the global
143
+ // undo/redo history client.
144
+ expect (UndoManager .client, isNull);
145
+ });
146
+
33
147
testWidgets ('allows undo and redo to be called programmatically from the UndoHistoryController' , (WidgetTester tester) async {
34
148
final ValueNotifier <int > value = ValueNotifier <int >(0 );
35
149
addTearDown (value.dispose);
0 commit comments