Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Sign in
Toggle navigation
F
Front-End
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
abdullh.alsoleman
Front-End
Commits
af587a15
Commit
af587a15
authored
Feb 07, 2017
by
Hans Muller
Committed by
GitHub
Feb 07, 2017
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Support for tests that respond to text input (#7915)
parent
c08bac83
Changes
6
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
92 additions
and
80 deletions
+92
-80
form_test.dart
packages/flutter/test/widgets/form_test.dart
+10
-29
input_test.dart
packages/flutter/test/widgets/input_test.dart
+18
-45
flutter_test.dart
packages/flutter_test/lib/flutter_test.dart
+1
-0
binding.dart
packages/flutter_test/lib/src/binding.dart
+16
-0
test_text_input.dart
packages/flutter_test/lib/src/test_text_input.dart
+16
-6
widget_tester.dart
packages/flutter_test/lib/src/widget_tester.dart
+31
-0
No files found.
packages/flutter/test/widgets/form_test.dart
View file @
af587a15
...
...
@@ -5,21 +5,7 @@
import
'package:flutter_test/flutter_test.dart'
;
import
'package:flutter/material.dart'
;
import
'mock_text_input.dart'
;
void
main
(
)
{
MockTextInput
mockTextInput
=
new
MockTextInput
()..
register
();
void
enterText
(
String
text
)
{
mockTextInput
.
enterText
(
text
);
}
Future
<
Null
>
showKeyboard
(
WidgetTester
tester
)
async
{
EditableTextState
editable
=
tester
.
state
(
find
.
byType
(
EditableText
).
first
);
editable
.
requestKeyboard
();
await
tester
.
pump
();
}
testWidgets
(
'onSaved callback is called'
,
(
WidgetTester
tester
)
async
{
GlobalKey
<
FormState
>
formKey
=
new
GlobalKey
<
FormState
>();
String
fieldValue
;
...
...
@@ -38,12 +24,11 @@ void main() {
}
await
tester
.
pumpWidget
(
builder
());
await
showKeyboard
(
tester
);
expect
(
fieldValue
,
isNull
);
Future
<
Null
>
checkText
(
String
testValue
)
async
{
enterText
(
testValue
);
await
tester
.
enterText
(
find
.
byType
(
EditableText
),
testValue
);
await
tester
.
idle
();
formKey
.
currentState
.
save
();
// pump'ing is unnecessary because callback happens regardless of frames
...
...
@@ -70,12 +55,11 @@ void main() {
}
await
tester
.
pumpWidget
(
builder
());
await
showKeyboard
(
tester
);
expect
(
fieldValue
,
isNull
);
Future
<
Null
>
checkText
(
String
testValue
)
async
{
enterText
(
testValue
);
await
tester
.
enterText
(
find
.
byType
(
EditableText
),
testValue
);
await
tester
.
idle
();
// pump'ing is unnecessary because callback happens regardless of frames
expect
(
fieldValue
,
equals
(
testValue
));
...
...
@@ -107,11 +91,10 @@ void main() {
// Start off not autovalidating.
await
tester
.
pumpWidget
(
builder
(
false
));
await
showKeyboard
(
tester
);
Future
<
Null
>
checkErrorText
(
String
testValue
)
async
{
formKey
.
currentState
.
reset
();
enterText
(
testValue
);
await
tester
.
enterText
(
find
.
byType
(
EditableText
),
testValue
);
await
tester
.
idle
();
await
tester
.
pumpWidget
(
builder
(
false
));
...
...
@@ -123,7 +106,7 @@ void main() {
// Try again with autovalidation. Should validate immediately.
formKey
.
currentState
.
reset
();
enterText
(
testValue
);
await
tester
.
enterText
(
find
.
byType
(
EditableText
),
testValue
);
await
tester
.
idle
();
await
tester
.
pumpWidget
(
builder
(
true
));
...
...
@@ -166,10 +149,9 @@ void main() {
}
await
tester
.
pumpWidget
(
builder
());
await
showKeyboard
(
tester
);
Future
<
Null
>
checkErrorText
(
String
testValue
)
async
{
enterText
(
testValue
);
await
tester
.
enterText
(
find
.
byType
(
EditableText
).
first
,
testValue
);
await
tester
.
idle
();
await
tester
.
pump
();
...
...
@@ -200,11 +182,11 @@ void main() {
}
await
tester
.
pumpWidget
(
builder
());
await
showKeyboard
(
tester
);
await
tester
.
showKeyboard
(
find
.
byType
(
EditableText
)
);
// initial value should be loaded into keyboard editing state
expect
(
mock
TextInput
.
editingState
,
isNotNull
);
expect
(
mock
TextInput
.
editingState
[
'text'
],
equals
(
initialValue
));
expect
(
tester
.
test
TextInput
.
editingState
,
isNotNull
);
expect
(
tester
.
test
TextInput
.
editingState
[
'text'
],
equals
(
initialValue
));
// initial value should also be visible in the raw input line
EditableTextState
editableText
=
tester
.
state
(
find
.
byType
(
EditableText
));
...
...
@@ -212,7 +194,7 @@ void main() {
// sanity check, make sure we can still edit the text and everything updates
expect
(
inputKey
.
currentState
.
value
.
text
,
equals
(
initialValue
));
enterText
(
'world'
);
await
tester
.
enterText
(
find
.
byType
(
EditableText
),
'world'
);
await
tester
.
idle
();
await
tester
.
pump
();
expect
(
inputKey
.
currentState
.
value
.
text
,
equals
(
'world'
));
...
...
@@ -241,12 +223,11 @@ void main() {
}
await
tester
.
pumpWidget
(
builder
(
false
));
await
showKeyboard
(
tester
);
expect
(
fieldValue
,
isNull
);
expect
(
formKey
.
currentState
.
validate
(),
isTrue
);
enterText
(
'Test'
);
await
tester
.
enterText
(
find
.
byType
(
EditableText
),
'Test'
);
await
tester
.
idle
();
await
tester
.
pumpWidget
(
builder
(
false
));
...
...
packages/flutter/test/widgets/input_test.dart
View file @
af587a15
...
...
@@ -10,8 +10,6 @@ import 'package:flutter/material.dart';
import
'package:flutter/rendering.dart'
;
import
'package:flutter/services.dart'
;
import
'mock_text_input.dart'
;
class
MockClipboard
{
Object
_clipboardData
=
<
String
,
dynamic
>{
'text'
:
null
...
...
@@ -41,7 +39,6 @@ Widget overlay(Widget child) {
}
void
main
(
)
{
MockTextInput
mockTextInput
=
new
MockTextInput
()..
register
();
MockClipboard
mockClipboard
=
new
MockClipboard
();
PlatformMessages
.
setMockJSONMessageHandler
(
'flutter/platform'
,
mockClipboard
.
handleJSONMessage
);
...
...
@@ -53,20 +50,6 @@ void main() {
kThreeLines
+
'Fourth line won
\'
t display and ends at abcdef ghi. '
;
void
updateEditingState
(
TextEditingState
state
)
{
mockTextInput
.
updateEditingState
(
state
);
}
void
enterText
(
String
text
)
{
mockTextInput
.
enterText
(
text
);
}
Future
<
Null
>
showKeyboard
(
WidgetTester
tester
)
async
{
EditableTextState
editable
=
tester
.
state
(
find
.
byType
(
EditableText
).
first
);
editable
.
requestKeyboard
();
await
tester
.
pump
();
}
// Returns the first RenderEditable.
RenderEditable
findRenderEditable
(
WidgetTester
tester
)
{
RenderObject
root
=
tester
.
renderObject
(
find
.
byType
(
EditableText
));
...
...
@@ -101,7 +84,6 @@ void main() {
return
new
Center
(
child:
new
Material
(
child:
new
Input
(
autofocus:
true
,
value:
inputValue
,
key:
inputKey
,
hintText:
'Placeholder'
,
...
...
@@ -119,7 +101,7 @@ void main() {
Size
emptyInputSize
=
inputBox
.
size
;
Future
<
Null
>
checkText
(
String
testValue
)
async
{
enterText
(
testValue
);
await
tester
.
enterText
(
find
.
byType
(
EditableText
),
testValue
);
await
tester
.
idle
();
// Check that the onChanged event handler fired.
...
...
@@ -152,7 +134,7 @@ void main() {
}
await
tester
.
pumpWidget
(
builder
());
await
showKeyboard
(
tester
);
await
tester
.
showKeyboard
(
find
.
byType
(
EditableText
)
);
EditableTextState
editableText
=
tester
.
state
(
find
.
byType
(
EditableText
));
...
...
@@ -172,9 +154,10 @@ void main() {
}
await
checkCursorToggle
();
await
tester
.
showKeyboard
(
find
.
byType
(
EditableText
));
// Try the test again with a nonempty EditableText.
updateEditingState
(
const
TextEditingState
(
tester
.
testTextInput
.
updateEditingState
(
const
TextEditingState
(
text:
'X'
,
selectionBase:
1
,
selectionExtent:
1
,
...
...
@@ -198,10 +181,10 @@ void main() {
}
await
tester
.
pumpWidget
(
builder
());
await
showKeyboard
(
tester
);
await
tester
.
showKeyboard
(
find
.
byType
(
EditableText
)
);
const
String
testValue
=
'ABC'
;
updateEditingState
(
const
TextEditingState
(
tester
.
testTextInput
.
updateEditingState
(
const
TextEditingState
(
text:
testValue
,
selectionBase:
testValue
.
length
,
selectionExtent:
testValue
.
length
,
...
...
@@ -235,10 +218,9 @@ void main() {
}
await
tester
.
pumpWidget
(
builder
());
await
showKeyboard
(
tester
);
String
testValue
=
'abc def ghi'
;
enterText
(
testValue
);
await
tester
.
enterText
(
find
.
byType
(
EditableText
),
testValue
);
await
tester
.
idle
();
expect
(
inputValue
.
text
,
testValue
);
...
...
@@ -283,10 +265,9 @@ void main() {
}
await
tester
.
pumpWidget
(
builder
());
await
showKeyboard
(
tester
);
String
testValue
=
'abc def ghi'
;
enterText
(
testValue
);
await
tester
.
enterText
(
find
.
byType
(
EditableText
),
testValue
);
await
tester
.
idle
();
await
tester
.
pumpWidget
(
builder
());
...
...
@@ -359,10 +340,9 @@ void main() {
}
await
tester
.
pumpWidget
(
builder
());
await
showKeyboard
(
tester
);
String
testValue
=
'abc def ghi'
;
enterText
(
testValue
);
await
tester
.
enterText
(
find
.
byType
(
EditableText
),
testValue
);
await
tester
.
idle
();
await
tester
.
pumpWidget
(
builder
());
...
...
@@ -425,10 +405,9 @@ void main() {
}
await
tester
.
pumpWidget
(
builder
());
await
showKeyboard
(
tester
);
String
testValue
=
'abc def ghi'
;
enterText
(
testValue
);
await
tester
.
enterText
(
find
.
byType
(
EditableText
),
testValue
);
await
tester
.
idle
();
await
tester
.
pumpWidget
(
builder
());
...
...
@@ -476,20 +455,19 @@ void main() {
}
await
tester
.
pumpWidget
(
builder
(
3
));
await
showKeyboard
(
tester
);
RenderBox
findInputBox
()
=>
tester
.
renderObject
(
find
.
byKey
(
inputKey
));
RenderBox
inputBox
=
findInputBox
();
Size
emptyInputSize
=
inputBox
.
size
;
enterText
(
'No wrapping here.'
);
await
tester
.
enterText
(
find
.
byType
(
EditableText
),
'No wrapping here.'
);
await
tester
.
idle
();
await
tester
.
pumpWidget
(
builder
(
3
));
expect
(
findInputBox
(),
equals
(
inputBox
));
expect
(
inputBox
.
size
,
equals
(
emptyInputSize
));
enterText
(
kThreeLines
);
await
tester
.
enterText
(
find
.
byType
(
EditableText
),
kThreeLines
);
await
tester
.
idle
();
await
tester
.
pumpWidget
(
builder
(
3
));
expect
(
findInputBox
(),
equals
(
inputBox
));
...
...
@@ -498,14 +476,14 @@ void main() {
Size
threeLineInputSize
=
inputBox
.
size
;
// An extra line won't increase the size because we max at 3.
enterText
(
kFourLines
);
await
tester
.
enterText
(
find
.
byType
(
EditableText
),
kFourLines
);
await
tester
.
idle
();
await
tester
.
pumpWidget
(
builder
(
3
));
expect
(
findInputBox
(),
equals
(
inputBox
));
expect
(
inputBox
.
size
,
threeLineInputSize
);
// But now it will.
enterText
(
kFourLines
);
await
tester
.
enterText
(
find
.
byType
(
EditableText
),
kFourLines
);
await
tester
.
idle
();
await
tester
.
pumpWidget
(
builder
(
4
));
expect
(
findInputBox
(),
equals
(
inputBox
));
...
...
@@ -539,11 +517,10 @@ void main() {
}
await
tester
.
pumpWidget
(
builder
());
await
showKeyboard
(
tester
);
String
testValue
=
kThreeLines
;
String
cutValue
=
'First line of stuff keeps going until abcdef ghijk. '
;
enterText
(
testValue
);
await
tester
.
enterText
(
find
.
byType
(
EditableText
),
testValue
);
await
tester
.
idle
();
await
tester
.
pumpWidget
(
builder
());
...
...
@@ -632,9 +609,8 @@ void main() {
}
await
tester
.
pumpWidget
(
builder
());
await
showKeyboard
(
tester
);
enterText
(
kFourLines
);
await
tester
.
enterText
(
find
.
byType
(
EditableText
),
kFourLines
);
await
tester
.
idle
();
await
tester
.
pumpWidget
(
builder
());
...
...
@@ -718,10 +694,9 @@ void main() {
}
await
tester
.
pumpWidget
(
builder
());
await
showKeyboard
(
tester
);
Future
<
Null
>
checkText
(
String
testValue
)
async
{
enterText
(
testValue
);
await
tester
.
enterText
(
find
.
byType
(
EditableText
),
testValue
);
await
tester
.
idle
();
// Check that the onChanged event handler fired.
...
...
@@ -751,10 +726,9 @@ void main() {
}
await
tester
.
pumpWidget
(
builder
());
await
showKeyboard
(
tester
);
Future
<
Null
>
checkText
(
String
testValue
)
async
{
enterText
(
testValue
);
await
tester
.
enterText
(
find
.
byType
(
EditableText
),
testValue
);
await
tester
.
idle
();
// Check that the onChanged event handler fired.
...
...
@@ -828,5 +802,4 @@ void main() {
expect
(
iconRight
,
equals
(
tester
.
getTopLeft
(
find
.
text
(
'label'
)).
x
));
expect
(
iconRight
,
equals
(
tester
.
getTopLeft
(
find
.
byType
(
InputField
)).
x
));
});
}
packages/flutter_test/lib/flutter_test.dart
View file @
af587a15
...
...
@@ -15,5 +15,6 @@ export 'src/matchers.dart';
export
'src/test_async_utils.dart'
;
export
'src/stack_manipulation.dart'
;
export
'src/test_pointer.dart'
;
export
'src/test_text_input.dart'
;
export
'src/test_vsync.dart'
;
export
'src/widget_tester.dart'
;
packages/flutter_test/lib/src/binding.dart
View file @
af587a15
...
...
@@ -20,6 +20,7 @@ import 'package:vector_math/vector_math_64.dart';
import
'stack_manipulation.dart'
;
import
'test_async_utils.dart'
;
import
'test_text_input.dart'
;
/// Phases that can be reached by [WidgetTester.pumpWidget] and
/// [TestWidgetsFlutterBinding.pump].
...
...
@@ -125,6 +126,7 @@ abstract class TestWidgetsFlutterBinding extends BindingBase
);
});
};
_testTextInput
=
new
TestTextInput
()..
register
();
super
.
initInstances
();
}
...
...
@@ -188,6 +190,20 @@ abstract class TestWidgetsFlutterBinding extends BindingBase
super
.
dispatchEvent
(
event
,
result
);
}
/// A stub for the system's onscreen keyboard. Callers must set the
/// [focusedEditable] before using this value.
TestTextInput
get
testTextInput
=>
_testTextInput
;
TestTextInput
_testTextInput
;
/// The current client of the onscreen keyboard. Callers must pump
/// an additional frame after setting this property to complete the
/// the focus change.
EditableTextState
get
focusedEditable
=>
_focusedEditable
;
EditableTextState
_focusedEditable
;
set
focusedEditable
(
EditableTextState
editable
)
{
_focusedEditable
=
editable
..
requestKeyboard
();
}
/// Returns the exception most recently caught by the Flutter framework.
///
/// Call this if you expect an exception during a test. If an exception is
...
...
packages/flutter
/test/widgets/mock
_text_input.dart
→
packages/flutter
_test/lib/src/test
_text_input.dart
View file @
af587a15
...
...
@@ -6,17 +6,27 @@ import 'dart:async';
import
'dart:convert'
;
import
'dart:typed_data'
;
import
'package:flutter_test/flutter_test.dart'
;
import
'package:flutter/services.dart'
;
import
'widget_tester.dart'
;
const
String
_kTextInputClientChannel
=
'flutter/textinputclient'
;
class
MockTextInput
{
/// 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
{
void
register
()
{
PlatformMessages
.
setMockJSONMessageHandler
(
'flutter/textinput'
,
handleJSONMessage
);
}
int
client
=
0
;
int
_
client
=
0
;
Map
<
String
,
dynamic
>
editingState
;
Future
<
dynamic
>
handleJSONMessage
(
dynamic
message
)
async
{
...
...
@@ -24,7 +34,7 @@ class MockTextInput {
final
List
<
dynamic
>
args
=
message
[
'args'
];
switch
(
method
)
{
case
'TextInput.setClient'
:
client
=
args
[
0
];
_
client
=
args
[
0
];
break
;
case
'TextInput.setEditingState'
:
editingState
=
args
[
0
];
...
...
@@ -33,10 +43,10 @@ class MockTextInput {
}
void
updateEditingState
(
TextEditingState
state
)
{
expect
(
client
,
isNonZero
);
expect
(
_
client
,
isNonZero
);
String
message
=
JSON
.
encode
(<
String
,
dynamic
>{
'method'
:
'TextInputClient.updateEditingState'
,
'args'
:
<
dynamic
>[
client
,
state
.
toJSON
()],
'args'
:
<
dynamic
>[
_
client
,
state
.
toJSON
()],
});
Uint8List
encoded
=
UTF8
.
encoder
.
convert
(
message
);
PlatformMessages
.
handlePlatformMessage
(
...
...
packages/flutter_test/lib/src/widget_tester.dart
View file @
af587a15
...
...
@@ -15,6 +15,7 @@ import 'binding.dart';
import
'controller.dart'
;
import
'finders.dart'
;
import
'test_async_utils.dart'
;
import
'test_text_input.dart'
;
export
'package:test/test.dart'
hide
expect
;
...
...
@@ -399,6 +400,36 @@ class WidgetTester extends WidgetController implements HitTestDispatcher, Ticker
void
_endOfTestVerifications
()
{
verifyTickersWereDisposed
(
'at the end of the test'
);
}
/// Returns the TestTextInput singleton.
///
/// Typical app tests will not need to use this value. To add text to widgets
/// like [Input] or [TextField], call [enterText].
TestTextInput
get
testTextInput
=>
binding
.
testTextInput
;
/// Give the EditableText widget specified by [finder] the focus, as if the
/// onscreen keyboard had appeared.
///
/// Tests that just need to add text to widgets like [Input] or [TextField]
/// only need to call [enterText].
Future
<
Null
>
showKeyboard
(
Finder
finder
)
async
{
// TODO(hansmuller): Once find.descendant (#7789) lands replace the following
// RHS with state(find.descendant(finder), find.byType(EditableText)).
final
EditableTextState
editable
=
state
(
finder
);
if
(
editable
!=
binding
.
focusedEditable
)
{
binding
.
focusedEditable
=
editable
;
await
pump
();
}
return
null
;
}
/// Give the EditableText widget specified by [finder] the focus and
/// enter [text] as if it been provided by the onscreen keyboard.
Future
<
Null
>
enterText
(
Finder
finder
,
String
text
)
async
{
await
showKeyboard
(
finder
);
testTextInput
.
enterText
(
text
);
return
null
;
}
}
typedef
void
_TickerDisposeCallback
(
_TestTicker
ticker
);
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment