1 | // Copyright 2014 The Flutter Authors. All rights reserved. |
2 | // Use of this source code is governed by a BSD-style license that can be |
3 | // found in the LICENSE file. |
4 | |
5 | import 'dart:ui_web' as ui_web; |
6 | |
7 | import 'package:collection/collection.dart' ; |
8 | import 'package:flutter/services.dart'; |
9 | import 'package:flutter_test/flutter_test.dart'; |
10 | |
11 | typedef FakeViewFactory = ({String viewType, bool isVisible, Function viewFactory}); |
12 | |
13 | typedef FakePlatformView = ({int id, String viewType, Object? params, Object htmlElement}); |
14 | |
15 | class FakePlatformViewRegistry implements ui_web.PlatformViewRegistry { |
16 | FakePlatformViewRegistry() { |
17 | TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger.setMockMethodCallHandler( |
18 | SystemChannels.platform_views, |
19 | _onMethodCall, |
20 | ); |
21 | } |
22 | |
23 | Set<FakePlatformView> get views => Set<FakePlatformView>.unmodifiable(_views); |
24 | final Set<FakePlatformView> _views = <FakePlatformView>{}; |
25 | |
26 | final Set<FakeViewFactory> _registeredViewTypes = <FakeViewFactory>{}; |
27 | |
28 | @override |
29 | bool registerViewFactory(String viewType, Function viewFactory, {bool isVisible = true}) { |
30 | if (_findRegisteredViewFactory(viewType) != null) { |
31 | return false; |
32 | } |
33 | _registeredViewTypes.add((viewType: viewType, isVisible: isVisible, viewFactory: viewFactory)); |
34 | return true; |
35 | } |
36 | |
37 | @override |
38 | Object getViewById(int viewId) { |
39 | return _findViewById(viewId)!.htmlElement; |
40 | } |
41 | |
42 | FakeViewFactory? _findRegisteredViewFactory(String viewType) { |
43 | return _registeredViewTypes.singleWhereOrNull( |
44 | (FakeViewFactory registered) => registered.viewType == viewType, |
45 | ); |
46 | } |
47 | |
48 | FakePlatformView? _findViewById(int viewId) { |
49 | return _views.singleWhereOrNull((FakePlatformView view) => view.id == viewId); |
50 | } |
51 | |
52 | Future<dynamic> _onMethodCall(MethodCall call) { |
53 | return switch (call.method) { |
54 | 'create' => _create(call), |
55 | 'dispose' => _dispose(call), |
56 | _ => Future<dynamic>.sync(() => null), |
57 | }; |
58 | } |
59 | |
60 | Future<dynamic> _create(MethodCall call) async { |
61 | final Map<dynamic, dynamic> args = call.arguments as Map<dynamic, dynamic>; |
62 | final int id = args['id' ] as int; |
63 | final String viewType = args['viewType' ] as String; |
64 | final Object? params = args['params' ]; |
65 | |
66 | if (_findViewById(id) != null) { |
67 | throw PlatformException( |
68 | code: 'error' , |
69 | message: 'Trying to create an already created platform view, view id: $id' , |
70 | ); |
71 | } |
72 | |
73 | final FakeViewFactory? registered = _findRegisteredViewFactory(viewType); |
74 | if (registered == null) { |
75 | throw PlatformException( |
76 | code: 'error' , |
77 | message: 'Trying to create a platform view of unregistered type: $viewType' , |
78 | ); |
79 | } |
80 | |
81 | final ui_web.ParameterizedPlatformViewFactory viewFactory = |
82 | registered.viewFactory as ui_web.ParameterizedPlatformViewFactory; |
83 | |
84 | _views.add(( |
85 | id: id, |
86 | viewType: viewType, |
87 | params: params, |
88 | htmlElement: viewFactory(id, params: params), |
89 | )); |
90 | return null; |
91 | } |
92 | |
93 | Future<dynamic> _dispose(MethodCall call) async { |
94 | final int id = call.arguments as int; |
95 | |
96 | final FakePlatformView? view = _findViewById(id); |
97 | if (view == null) { |
98 | throw PlatformException( |
99 | code: 'error' , |
100 | message: 'Trying to dispose a platform view with unknown id: $id' , |
101 | ); |
102 | } |
103 | |
104 | _views.remove(view); |
105 | return null; |
106 | } |
107 | } |
108 | |