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

import 'dart:convert';

import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter_test/flutter_test.dart';

12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
/// Tuple-like test class for storing a [stream] and [eventKind].
///
/// Used to store the [stream] and [eventKind] that a dispatched event would be
/// sent on.
@immutable
class DispatchedEventKey {
  const DispatchedEventKey({required this.stream, required this.eventKind});

  final String stream;
  final String eventKind;

  @override
  String toString() {
    return '[DispatchedEventKey]($stream, $eventKind)';
  }

  @override
  bool operator ==(Object other) {
    return other is DispatchedEventKey &&
        stream == other.stream &&
        eventKind == other.eventKind;
  }

  @override
  int get hashCode => Object.hash(stream, eventKind);
}

39
class TestWidgetInspectorService extends Object with WidgetInspectorService {
40 41 42 43 44 45 46
    TestWidgetInspectorService() {
    selection.addListener(() {
      if (selectionChangedCallback != null) {
        selectionChangedCallback!();
      }
    });
  }
47
  final Map<String, ServiceExtensionCallback> extensions = <String, ServiceExtensionCallback>{};
48

49 50 51
  final Map<DispatchedEventKey, List<Map<Object, Object?>>> eventsDispatched =
      <DispatchedEventKey, List<Map<Object, Object?>>>{};
  final  List<Object?> objectsInspected = <Object?>[];
52 53 54

  @override
  void registerServiceExtension({
55 56
    required String name,
    required ServiceExtensionCallback callback,
57
    required RegisterServiceExtensionCallback registerExtension,
58 59 60 61 62 63
  }) {
    assert(!extensions.containsKey(name));
    extensions[name] = callback;
  }

  @override
64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84
  void postEvent(
    String eventKind,
    Map<Object, Object?> eventData, {
    String stream = 'Extension',
  }) {
    dispatchedEvents(eventKind, stream: stream).add(eventData);
  }

  @override
  void inspect(Object? object) {
    objectsInspected.add(object);
  }

  List<Map<Object, Object?>> dispatchedEvents(
    String eventKind, {
    String stream = 'Extension',
  }) {
    return eventsDispatched.putIfAbsent(
      DispatchedEventKey(stream: stream, eventKind: eventKind),
      () => <Map<Object, Object?>>[],
    );
85 86
  }

87 88
  List<Object?> inspectedObjects(){
    return objectsInspected;
89 90
  }

91
  Iterable<Map<Object, Object?>> getServiceExtensionStateChangedEvents(String extensionName) {
92
    return dispatchedEvents('Flutter.ServiceExtensionStateChanged')
93
      .where((Map<Object, Object?> event) => event['extension'] == extensionName);
94 95
  }

96
  Future<Object?> testExtension(String name, Map<String, String> arguments) async {
97 98 99
    expect(extensions, contains(name));
    // Encode and decode to JSON to match behavior using a real service
    // extension where only JSON is allowed.
100
    return (json.decode(json.encode(await extensions[name]!(arguments))) as Map<String, dynamic>)['result'];
101 102 103 104 105 106
  }

  Future<String> testBoolExtension(String name, Map<String, String> arguments) async {
    expect(extensions, contains(name));
    // Encode and decode to JSON to match behavior using a real service
    // extension where only JSON is allowed.
107
    return (json.decode(json.encode(await extensions[name]!(arguments))) as Map<String, dynamic>)['enabled'] as String;
108 109 110 111 112 113 114
  }

  int rebuildCount = 0;

  @override
  Future<void> forceRebuild() async {
    rebuildCount++;
115
    final WidgetsBinding binding = WidgetsBinding.instance;
116

117
    if (binding.rootElement != null) {
118
      binding.buildOwner!.reassemble(binding.rootElement!);
119 120
    }
  }
121 122 123 124 125

  @override
  void resetAllState() {
    super.resetAllState();
    eventsDispatched.clear();
126
    objectsInspected.clear();
127 128
    rebuildCount = 0;
  }
129
}