22// Use of this source code is governed by a BSD-style license that can be
33// found in the LICENSE file.
44
5+ import 'dart:async' ;
6+
57import 'package:flutter/services.dart' ;
68import 'package:flutter_test/flutter_test.dart' ;
79import 'package:integration_test/integration_test.dart' ;
@@ -13,7 +15,9 @@ void main() {
1315 const String channelName = 'tizen/internal/inputpanel' ;
1416 const StandardMethodCodec codec = StandardMethodCodec ();
1517
16- Future <void > emit (WidgetTester tester, Map <String , Object ?> payload) async {
18+ // Injects an event into the input-panel [EventChannel] the controller
19+ // listens to, simulating a message coming from the flutter-tizen embedder.
20+ Future <void > emit (WidgetTester tester, Object ? payload) async {
1721 final ByteData data = codec.encodeSuccessEnvelope (payload);
1822 await tester.binding.defaultBinaryMessenger.handlePlatformMessage (
1923 channelName,
@@ -22,25 +26,317 @@ void main() {
2226 );
2327 }
2428
25- testWidgets ('reports visible on show event' , (WidgetTester tester) async {
26- final KeyboardDetectionController controller =
27- KeyboardDetectionController ();
28- await emit (tester, < String , Object ? > {'state' : 'show' });
29- await tester.pump ();
30- expect (controller.state, KeyboardState .visible);
31- expect (controller.stateAsBool (), isTrue);
32- await controller.dispose ();
29+ group ('state reporting' , () {
30+ testWidgets ('starts in the unknown state' , (WidgetTester tester) async {
31+ final KeyboardDetectionController controller =
32+ KeyboardDetectionController ();
33+ expect (controller.state, KeyboardState .unknown);
34+ expect (controller.stateAsBool (), isNull);
35+ await controller.dispose ();
36+ });
37+
38+ testWidgets ('reports visibling on will_show event' ,
39+ (WidgetTester tester) async {
40+ final KeyboardDetectionController controller =
41+ KeyboardDetectionController ();
42+ await emit (tester, < String , Object ? > {'state' : 'will_show' });
43+ await tester.pump ();
44+ expect (controller.state, KeyboardState .visibling);
45+ await controller.dispose ();
46+ });
47+
48+ testWidgets ('reports visible on show event' , (WidgetTester tester) async {
49+ final KeyboardDetectionController controller =
50+ KeyboardDetectionController ();
51+ await emit (tester, < String , Object ? > {'state' : 'show' });
52+ await tester.pump ();
53+ expect (controller.state, KeyboardState .visible);
54+ expect (controller.stateAsBool (), isTrue);
55+ await controller.dispose ();
56+ });
57+
58+ testWidgets ('reports hiding on will_hide event' ,
59+ (WidgetTester tester) async {
60+ final KeyboardDetectionController controller =
61+ KeyboardDetectionController ();
62+ await emit (tester, < String , Object ? > {'state' : 'show' });
63+ await tester.pump ();
64+ await emit (tester, < String , Object ? > {'state' : 'will_hide' });
65+ await tester.pump ();
66+ expect (controller.state, KeyboardState .hiding);
67+ await controller.dispose ();
68+ });
69+
70+ testWidgets ('reports hidden on hide event' , (WidgetTester tester) async {
71+ final KeyboardDetectionController controller =
72+ KeyboardDetectionController ();
73+ await emit (tester, < String , Object ? > {'state' : 'show' });
74+ await tester.pump ();
75+ await emit (tester, < String , Object ? > {'state' : 'hide' });
76+ await tester.pump ();
77+ expect (controller.state, KeyboardState .hidden);
78+ expect (controller.stateAsBool (), isFalse);
79+ await controller.dispose ();
80+ });
81+
82+ testWidgets ('falls back to unknown for an unrecognized event' ,
83+ (WidgetTester tester) async {
84+ final KeyboardDetectionController controller =
85+ KeyboardDetectionController ();
86+ await emit (tester, < String , Object ? > {'state' : 'show' });
87+ await tester.pump ();
88+ await emit (tester, < String , Object ? > {'state' : 'something_else' });
89+ await tester.pump ();
90+ expect (controller.state, KeyboardState .unknown);
91+ await controller.dispose ();
92+ });
93+
94+ testWidgets ('ignores events without a valid state field' ,
95+ (WidgetTester tester) async {
96+ final KeyboardDetectionController controller =
97+ KeyboardDetectionController ();
98+ // Reach a known state first, so the assertions verify that the invalid
99+ // events are ignored (state preserved) rather than merely matching the
100+ // initial unknown state.
101+ await emit (tester, < String , Object ? > {'state' : 'show' });
102+ await tester.pump ();
103+ expect (controller.state, KeyboardState .visible);
104+ await emit (tester, < String , Object ? > {'noState' : true });
105+ await tester.pump ();
106+ expect (controller.state, KeyboardState .visible);
107+ await emit (tester, < String , Object ? > {'state' : 123 });
108+ await tester.pump ();
109+ expect (controller.state, KeyboardState .visible);
110+ await controller.dispose ();
111+ });
112+ });
113+
114+ group ('stateAsBool' , () {
115+ testWidgets ('maps the transitional visibling state' ,
116+ (WidgetTester tester) async {
117+ final KeyboardDetectionController controller =
118+ KeyboardDetectionController ();
119+ await emit (tester, < String , Object ? > {'state' : 'will_show' });
120+ await tester.pump ();
121+ expect (controller.stateAsBool (), isFalse);
122+ expect (controller.stateAsBool (true ), isTrue);
123+ await controller.dispose ();
124+ });
125+
126+ testWidgets ('maps the transitional hiding state' ,
127+ (WidgetTester tester) async {
128+ final KeyboardDetectionController controller =
129+ KeyboardDetectionController ();
130+ await emit (tester, < String , Object ? > {'state' : 'will_hide' });
131+ await tester.pump ();
132+ expect (controller.stateAsBool (), isTrue);
133+ expect (controller.stateAsBool (true ), isFalse);
134+ await controller.dispose ();
135+ });
136+ });
137+
138+ group ('keyboard metrics' , () {
139+ testWidgets ('size, width and position are zero before any event' ,
140+ (WidgetTester tester) async {
141+ final KeyboardDetectionController controller =
142+ KeyboardDetectionController ();
143+ expect (controller.size, 0 );
144+ expect (controller.width, 0 );
145+ expect (controller.position, Offset .zero);
146+ expect (controller.isSizeLoaded, isFalse);
147+ await controller.dispose ();
148+ });
149+
150+ testWidgets ('updates metrics from a show event carrying dimensions' ,
151+ (WidgetTester tester) async {
152+ final KeyboardDetectionController controller =
153+ KeyboardDetectionController ();
154+ await emit (tester, < String , Object ? > {
155+ 'state' : 'show' ,
156+ 'width' : 1080.0 ,
157+ 'height' : 420.0 ,
158+ 'x' : 0.0 ,
159+ 'y' : 1500.0 ,
160+ });
161+ await tester.pump ();
162+ expect (controller.width, 1080.0 );
163+ expect (controller.size, 420.0 );
164+ expect (controller.position, const Offset (0 , 1500 ));
165+ expect (controller.isSizeLoaded, isTrue);
166+ await controller.dispose ();
167+ });
168+
169+ testWidgets ('ensureSizeLoaded completes once metrics arrive' ,
170+ (WidgetTester tester) async {
171+ final KeyboardDetectionController controller =
172+ KeyboardDetectionController ();
173+ final Future <void > sizeLoaded = controller.ensureSizeLoaded;
174+ await emit (tester, < String , Object ? > {
175+ 'state' : 'show' ,
176+ 'width' : 1080.0 ,
177+ 'height' : 420.0 ,
178+ });
179+ await tester.pump ();
180+ await expectLater (sizeLoaded, completes);
181+ expect (controller.isSizeLoaded, isTrue);
182+ await controller.dispose ();
183+ });
184+
185+ testWidgets ('resets metrics to zero on hide' , (WidgetTester tester) async {
186+ final KeyboardDetectionController controller =
187+ KeyboardDetectionController ();
188+ await emit (tester, < String , Object ? > {
189+ 'state' : 'show' ,
190+ 'width' : 1080.0 ,
191+ 'height' : 420.0 ,
192+ 'x' : 0.0 ,
193+ 'y' : 1500.0 ,
194+ });
195+ await tester.pump ();
196+ await emit (tester, < String , Object ? > {'state' : 'hide' });
197+ await tester.pump ();
198+ expect (controller.width, 0 );
199+ expect (controller.size, 0 );
200+ expect (controller.position, Offset .zero);
201+ await controller.dispose ();
202+ });
203+ });
204+
205+ group ('notifications' , () {
206+ testWidgets ('stream emits state changes in order' ,
207+ (WidgetTester tester) async {
208+ final KeyboardDetectionController controller =
209+ KeyboardDetectionController ();
210+ final List <KeyboardState > seen = < KeyboardState > [];
211+ final StreamSubscription <KeyboardState > subscription =
212+ controller.stream.listen (seen.add);
213+ await emit (tester, < String , Object ? > {'state' : 'will_show' });
214+ await tester.pump ();
215+ await emit (tester, < String , Object ? > {'state' : 'show' });
216+ await tester.pump ();
217+ await emit (tester, < String , Object ? > {'state' : 'hide' });
218+ await tester.pump ();
219+ expect (seen, < KeyboardState > [
220+ KeyboardState .visibling,
221+ KeyboardState .visible,
222+ KeyboardState .hidden,
223+ ]);
224+ await subscription.cancel ();
225+ await controller.dispose ();
226+ });
227+
228+ testWidgets ('onChanged is invoked on every state change' ,
229+ (WidgetTester tester) async {
230+ final List <KeyboardState > seen = < KeyboardState > [];
231+ final KeyboardDetectionController controller =
232+ KeyboardDetectionController (onChanged: seen.add);
233+ await emit (tester, < String , Object ? > {'state' : 'show' });
234+ await tester.pump ();
235+ await emit (tester, < String , Object ? > {'state' : 'hide' });
236+ await tester.pump ();
237+ expect (seen, < KeyboardState > [
238+ KeyboardState .visible,
239+ KeyboardState .hidden,
240+ ]);
241+ await controller.dispose ();
242+ });
243+ });
244+
245+ group ('registered callbacks' , () {
246+ testWidgets ('a registered callback receives state changes' ,
247+ (WidgetTester tester) async {
248+ final KeyboardDetectionController controller =
249+ KeyboardDetectionController ();
250+ final List <KeyboardState > seen = < KeyboardState > [];
251+ controller.registerCallback ((KeyboardState state) {
252+ seen.add (state);
253+ return true ;
254+ });
255+ await emit (tester, < String , Object ? > {'state' : 'show' });
256+ await tester.pump ();
257+ await emit (tester, < String , Object ? > {'state' : 'hide' });
258+ await tester.pump ();
259+ expect (seen, < KeyboardState > [
260+ KeyboardState .visible,
261+ KeyboardState .hidden,
262+ ]);
263+ await controller.dispose ();
264+ });
265+
266+ testWidgets ('a callback returning false unregisters itself' ,
267+ (WidgetTester tester) async {
268+ final KeyboardDetectionController controller =
269+ KeyboardDetectionController ();
270+ int calls = 0 ;
271+ controller.registerCallback ((KeyboardState state) {
272+ calls++ ;
273+ return false ;
274+ });
275+ await emit (tester, < String , Object ? > {'state' : 'show' });
276+ await tester.pump ();
277+ await emit (tester, < String , Object ? > {'state' : 'hide' });
278+ await tester.pump ();
279+ expect (calls, 1 );
280+ await controller.dispose ();
281+ });
282+
283+ testWidgets ('unregisterCallback stops further invocations' ,
284+ (WidgetTester tester) async {
285+ final KeyboardDetectionController controller =
286+ KeyboardDetectionController ();
287+ final List <KeyboardState > seen = < KeyboardState > [];
288+ bool callback (KeyboardState state) {
289+ seen.add (state);
290+ return true ;
291+ }
292+
293+ controller.registerCallback (callback);
294+ await emit (tester, < String , Object ? > {'state' : 'show' });
295+ await tester.pump ();
296+ controller.unregisterCallback (callback);
297+ await emit (tester, < String , Object ? > {'state' : 'hide' });
298+ await tester.pump ();
299+ expect (seen, < KeyboardState > [KeyboardState .visible]);
300+ await controller.dispose ();
301+ });
302+
303+ testWidgets ('unregisterAllCallbacks removes every callback' ,
304+ (WidgetTester tester) async {
305+ final KeyboardDetectionController controller =
306+ KeyboardDetectionController ();
307+ int first = 0 ;
308+ int second = 0 ;
309+ controller.registerCallback ((KeyboardState state) {
310+ first++ ;
311+ return true ;
312+ });
313+ controller.registerCallback ((KeyboardState state) {
314+ second++ ;
315+ return true ;
316+ });
317+ await emit (tester, < String , Object ? > {'state' : 'show' });
318+ await tester.pump ();
319+ controller.unregisterAllCallbacks ();
320+ await emit (tester, < String , Object ? > {'state' : 'hide' });
321+ await tester.pump ();
322+ expect (first, 1 );
323+ expect (second, 1 );
324+ await controller.dispose ();
325+ });
33326 });
34327
35- testWidgets ('reports hidden on hide event' , (WidgetTester tester) async {
36- final KeyboardDetectionController controller =
37- KeyboardDetectionController ();
38- await emit (tester, < String , Object ? > {'state' : 'show' });
39- await tester.pump ();
40- await emit (tester, < String , Object ? > {'state' : 'hide' });
41- await tester.pump ();
42- expect (controller.state, KeyboardState .hidden);
43- expect (controller.stateAsBool (), isFalse);
44- await controller.dispose ();
328+ group ('lifecycle' , () {
329+ testWidgets ('does not report state changes after dispose' ,
330+ (WidgetTester tester) async {
331+ final KeyboardDetectionController controller =
332+ KeyboardDetectionController ();
333+ await emit (tester, < String , Object ? > {'state' : 'show' });
334+ await tester.pump ();
335+ expect (controller.state, KeyboardState .visible);
336+ await controller.dispose ();
337+ await emit (tester, < String , Object ? > {'state' : 'hide' });
338+ await tester.pump ();
339+ expect (controller.state, KeyboardState .visible);
340+ });
45341 });
46342}
0 commit comments