widget_inspector_test_utils.dart 3.53 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
  final Map<String, ServiceExtensionCallback> extensions = <String, ServiceExtensionCallback>{};
41

42 43 44
  final Map<DispatchedEventKey, List<Map<Object, Object?>>> eventsDispatched =
      <DispatchedEventKey, List<Map<Object, Object?>>>{};
  final  List<Object?> objectsInspected = <Object?>[];
45 46 47

  @override
  void registerServiceExtension({
48 49
    required String name,
    required ServiceExtensionCallback callback,
50 51 52 53 54 55
  }) {
    assert(!extensions.containsKey(name));
    extensions[name] = callback;
  }

  @override
56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76
  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?>>[],
    );
77 78
  }

79 80
  List<Object?> inspectedObjects(){
    return objectsInspected;
81 82
  }

83
  Iterable<Map<Object, Object?>> getServiceExtensionStateChangedEvents(String extensionName) {
84
    return dispatchedEvents('Flutter.ServiceExtensionStateChanged')
85
      .where((Map<Object, Object?> event) => event['extension'] == extensionName);
86 87
  }

88
  Future<Object?> testExtension(String name, Map<String, String> arguments) async {
89 90 91
    expect(extensions, contains(name));
    // Encode and decode to JSON to match behavior using a real service
    // extension where only JSON is allowed.
92
    return (json.decode(json.encode(await extensions[name]!(arguments))) as Map<String, dynamic>)['result'];
93 94 95 96 97 98
  }

  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.
99
    return (json.decode(json.encode(await extensions[name]!(arguments))) as Map<String, dynamic>)['enabled'] as String;
100 101 102 103 104 105 106
  }

  int rebuildCount = 0;

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

109 110
    if (binding.rootElement != null) {
      binding.buildOwner!.reassemble(binding.rootElement!, null);
111 112
    }
  }
113 114 115 116 117

  @override
  void resetAllState() {
    super.resetAllState();
    eventsDispatched.clear();
118
    objectsInspected.clear();
119 120
    rebuildCount = 0;
  }
121
}