test_text_input.dart 4.41 KB
Newer Older
1 2 3 4 5
// Copyright 2015 The Chromium 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:async';
6
import 'dart:typed_data';
7 8 9

import 'package:flutter/services.dart';

10 11 12 13 14 15 16 17 18 19 20 21
import 'widget_tester.dart';

/// A testing stub for the system's onscreen keyboard.
///
/// Typical app tests will not need to use this class directly.
///
/// See also:
///
/// * [WidgetTester.enterText], which uses this class to simulate keyboard input.
/// * [WidgetTester.showKeyboard], which uses this class to simulate showing the
///   popup keyboard and initializing its text.
class TestTextInput {
22
  /// Installs this object as a mock handler for [SystemChannels.textInput].
23
  void register() {
24
    SystemChannels.textInput.setMockMethodCallHandler(_handleTextInputCall);
25
    _isRegistered = true;
26 27
  }

28 29 30 31 32 33 34
  /// Removes this object as a mock handler for [SystemChannels.textInput].
  ///
  /// After calling this method, the channel will exchange messages with the
  /// Flutter engine. Use this with [FlutterDriver] tests that need to display
  /// on-screen keyboard provided by the operating system.
  void unregister() {
    SystemChannels.textInput.setMockMethodCallHandler(null);
35
    _isRegistered = false;
36 37
  }

38 39 40 41 42 43
  /// Whether this [TestTextInput] is registered with [SystemChannels.textInput].
  ///
  /// Use [register] and [unregister] methods to control this value.
  bool get isRegistered => _isRegistered;
  bool _isRegistered = false;

44
  int _client = 0;
45

46 47 48
  /// Arguments supplied to the TextInput.setClient method call.
  Map<String, dynamic> setClientArgs;

49 50 51 52 53 54
  /// The last set of arguments that [TextInputConnection.setEditingState] sent
  /// to the embedder.
  ///
  /// This is a map representation of a [TextEditingValue] object. For example,
  /// it will have a `text` entry whose value matches the most recent
  /// [TextEditingValue.text] that was sent to the embedder.
55 56
  Map<String, dynamic> editingState;

57
  Future<dynamic> _handleTextInputCall(MethodCall methodCall) async {
58
    switch (methodCall.method) {
59
      case 'TextInput.setClient':
60
        _client = methodCall.arguments[0];
61
        setClientArgs = methodCall.arguments[1];
62
        break;
63 64 65 66
      case 'TextInput.clearClient':
        _client = 0;
        _isVisible = false;
        break;
67
      case 'TextInput.setEditingState':
68
        editingState = methodCall.arguments;
69
        break;
70 71 72 73 74 75
      case 'TextInput.show':
        _isVisible = true;
        break;
      case 'TextInput.hide':
        _isVisible = false;
        break;
76 77 78
    }
  }

79 80 81 82 83
  /// Whether the onscreen keyboard is visible to the user.
  bool get isVisible => _isVisible;
  bool _isVisible = false;

  /// Simulates the user changing the [TextEditingValue] to the given value.
84
  void updateEditingValue(TextEditingValue value) {
85 86 87 88 89
    // Not using the `expect` function because in the case of a FlutterDriver
    // test this code does not run in a package:test test zone.
    if (_client == 0) {
      throw new TestFailure('_client must be non-zero');
    }
90
    BinaryMessages.handlePlatformMessage(
91 92 93 94
      SystemChannels.textInput.name,
      SystemChannels.textInput.codec.encodeMethodCall(
        new MethodCall(
          'TextInputClient.updateEditingState',
95
          <dynamic>[_client, value.toJSON()],
96 97
        ),
      ),
98
      (ByteData data) { /* response from framework is discarded */ },
99
    );
100 101
  }

102
  /// Simulates the user typing the given text.
103
  void enterText(String text) {
104
    updateEditingValue(new TextEditingValue(
105 106 107
      text: text,
    ));
  }
108

109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129
  /// Simulates the user pressing one of the [TextInputAction] buttons.
  /// Does not check that the [TextInputAction] performed is an acceptable one
  /// based on the `inputAction` [setClientArgs].
  void receiveAction(TextInputAction action) {
    // Not using the `expect` function because in the case of a FlutterDriver
    // test this code does not run in a package:test test zone.
    if (_client == 0) {
      throw new TestFailure('_client must be non-zero');
    }
    BinaryMessages.handlePlatformMessage(
      SystemChannels.textInput.name,
      SystemChannels.textInput.codec.encodeMethodCall(
        new MethodCall(
          'TextInputClient.performAction',
          <dynamic>[_client, action.toString()],
        ),
      ),
      (ByteData data) { /* response from framework is discarded */ },
    );
  }

130 131 132 133
  /// Simulates the user hiding the onscreen keyboard.
  void hide() {
    _isVisible = false;
  }
134
}