Commit 2a545243 authored by Ian Hickson's avatar Ian Hickson Committed by GitHub

Fix tests to use Ahem, and helpful changes around that (#9332)

* Fix tests to use Ahem, and helpful changes around that

- Fix fonts that had metric-specific behaviours.

- LiveTestWidgetsFlutterBinding.allowAllFrames has been renamed
  to LiveTestWidgetsFlutterBinding.framePolicy.

- LiveTestWidgetsFlutterBinding now defaults to using a frame policy
  that pumps slightly more frames, to animate the pointer crosshairs.

- Added "flutter run --use-test-fonts" to enable Ahem on devices.

- Changed how idle() works to be more effective in live mode.

- Display the test name in live mode (unless ahem fonts are enabled).

- Added a toString to TextSelectionPoint.

- Style nit fixes.

* Roll engine to get Ahem changes.

* Update tests for dartdoc changes.

* Fix flutter_tools tests
parent c12c019b
5d9a6422577d95c242f45f48c47b431f7cf3c548 1fed16fb25f3f7afc8303116d6ef707c4043c127
...@@ -15,7 +15,8 @@ When the exception was thrown, this was the stack: ...@@ -15,7 +15,8 @@ When the exception was thrown, this was the stack:
<<skip until matching line>> <<skip until matching line>>
\(elided .+\) \(elided .+\)
The test description was:
TestAsyncUtils - custom guarded sections
════════════════════════════════════════════════════════════════════════════════════════════════════ ════════════════════════════════════════════════════════════════════════════════════════════════════
.*(this line has more of the test framework's output)? .*(this line has more of the test framework's output)?
Test failed\. See exception logs above\. Test failed\. See exception logs above\.
......
...@@ -14,7 +14,8 @@ When the exception was thrown, this was the stack: ...@@ -14,7 +14,8 @@ When the exception was thrown, this was the stack:
<<skip until matching line>> <<skip until matching line>>
(elided [0-9]+ frames from .+) (elided [0-9]+ frames from .+)
The test description was:
TestAsyncUtils - handling unguarded async helper functions
════════════════════════════════════════════════════════════════════════════════════════════════════ ════════════════════════════════════════════════════════════════════════════════════════════════════
.*..:.. \+0 -1: - TestAsyncUtils - handling unguarded async helper functions * .*..:.. \+0 -1: - TestAsyncUtils - handling unguarded async helper functions *
Test failed. See exception logs above. Test failed. See exception logs above.
......
...@@ -22,7 +22,7 @@ Future<Null> main() async { ...@@ -22,7 +22,7 @@ Future<Null> main() async {
// This allows us to call onBeginFrame even when the engine didn't request it, // This allows us to call onBeginFrame even when the engine didn't request it,
// and have it actually do something: // and have it actually do something:
final LiveTestWidgetsFlutterBinding binding = TestWidgetsFlutterBinding.ensureInitialized(); final LiveTestWidgetsFlutterBinding binding = TestWidgetsFlutterBinding.ensureInitialized();
binding.allowAllFrames = true; binding.framePolicy = LiveTestWidgetsFlutterBindingFramePolicy.fullyLive;
final Stopwatch watch = new Stopwatch(); final Stopwatch watch = new Stopwatch();
int iterations = 0; int iterations = 0;
......
...@@ -21,7 +21,7 @@ Future<Null> main() async { ...@@ -21,7 +21,7 @@ Future<Null> main() async {
// This allows us to call onBeginFrame even when the engine didn't request it, // This allows us to call onBeginFrame even when the engine didn't request it,
// and have it actually do something: // and have it actually do something:
final LiveTestWidgetsFlutterBinding binding = TestWidgetsFlutterBinding.ensureInitialized(); final LiveTestWidgetsFlutterBinding binding = TestWidgetsFlutterBinding.ensureInitialized();
binding.allowAllFrames = true; binding.framePolicy = LiveTestWidgetsFlutterBindingFramePolicy.fullyLive;
final Stopwatch watch = new Stopwatch(); final Stopwatch watch = new Stopwatch();
int iterations = 0; int iterations = 0;
......
...@@ -108,9 +108,9 @@ void createFooter(String footerPath) { ...@@ -108,9 +108,9 @@ void createFooter(String footerPath) {
void sanityCheckDocs() { void sanityCheckDocs() {
final List<String> canaries = <String>[ final List<String> canaries = <String>[
'$kDocRoot/api/dart-io/File-class.html', '$kDocRoot/api/dart.io/File-class.html',
'$kDocRoot/api/dart-ui/Canvas-class.html', '$kDocRoot/api/dart_ui/Canvas-class.html',
'$kDocRoot/api/dart-ui/Canvas/drawRect.html', '$kDocRoot/api/dart_ui/Canvas/drawRect.html',
'$kDocRoot/api/flutter_test/WidgetTester/pumpWidget.html', '$kDocRoot/api/flutter_test/WidgetTester/pumpWidget.html',
'$kDocRoot/api/material/Material-class.html', '$kDocRoot/api/material/Material-class.html',
'$kDocRoot/api/material/Tooltip-class.html', '$kDocRoot/api/material/Tooltip-class.html',
......
...@@ -9,7 +9,7 @@ import 'package:flutter_test/flutter_test.dart'; ...@@ -9,7 +9,7 @@ import 'package:flutter_test/flutter_test.dart';
void main() { void main() {
final TestWidgetsFlutterBinding binding = TestWidgetsFlutterBinding.ensureInitialized(); final TestWidgetsFlutterBinding binding = TestWidgetsFlutterBinding.ensureInitialized();
if (binding is LiveTestWidgetsFlutterBinding) if (binding is LiveTestWidgetsFlutterBinding)
binding.allowAllFrames = true; binding.framePolicy = LiveTestWidgetsFlutterBindingFramePolicy.fullyLive;
// We press the "1" and the "2" buttons and check that the display // We press the "1" and the "2" buttons and check that the display
// reads "12". // reads "12".
......
...@@ -9,7 +9,7 @@ import 'package:flutter_test/flutter_test.dart'; ...@@ -9,7 +9,7 @@ import 'package:flutter_test/flutter_test.dart';
void main() { void main() {
final TestWidgetsFlutterBinding binding = TestWidgetsFlutterBinding.ensureInitialized(); final TestWidgetsFlutterBinding binding = TestWidgetsFlutterBinding.ensureInitialized();
if (binding is LiveTestWidgetsFlutterBinding) if (binding is LiveTestWidgetsFlutterBinding)
binding.allowAllFrames = true; binding.framePolicy = LiveTestWidgetsFlutterBindingFramePolicy.fullyLive;
testWidgets('Flutter gallery button example code displays', (WidgetTester tester) async { testWidgets('Flutter gallery button example code displays', (WidgetTester tester) async {
// Regression test for https://github.com/flutter/flutter/issues/6147 // Regression test for https://github.com/flutter/flutter/issues/6147
......
...@@ -9,7 +9,7 @@ import 'package:flutter_gallery/gallery/app.dart'; ...@@ -9,7 +9,7 @@ import 'package:flutter_gallery/gallery/app.dart';
void main() { void main() {
final TestWidgetsFlutterBinding binding = TestWidgetsFlutterBinding.ensureInitialized(); final TestWidgetsFlutterBinding binding = TestWidgetsFlutterBinding.ensureInitialized();
if (binding is LiveTestWidgetsFlutterBinding) if (binding is LiveTestWidgetsFlutterBinding)
binding.allowAllFrames = true; binding.framePolicy = LiveTestWidgetsFlutterBindingFramePolicy.fullyLive;
// Regression test for https://github.com/flutter/flutter/pull/5168 // Regression test for https://github.com/flutter/flutter/pull/5168
testWidgets('Pesto appbar heroics', (WidgetTester tester) async { testWidgets('Pesto appbar heroics', (WidgetTester tester) async {
......
...@@ -9,7 +9,7 @@ import 'package:flutter_gallery/main.dart' as flutter_gallery_main; ...@@ -9,7 +9,7 @@ import 'package:flutter_gallery/main.dart' as flutter_gallery_main;
void main() { void main() {
final TestWidgetsFlutterBinding binding = TestWidgetsFlutterBinding.ensureInitialized(); final TestWidgetsFlutterBinding binding = TestWidgetsFlutterBinding.ensureInitialized();
if (binding is LiveTestWidgetsFlutterBinding) if (binding is LiveTestWidgetsFlutterBinding)
binding.allowAllFrames = true; binding.framePolicy = LiveTestWidgetsFlutterBindingFramePolicy.fullyLive;
testWidgets('Flutter Gallery app simple smoke test', (WidgetTester tester) async { testWidgets('Flutter Gallery app simple smoke test', (WidgetTester tester) async {
flutter_gallery_main.main(); // builds the app and schedules a frame but doesn't trigger one flutter_gallery_main.main(); // builds the app and schedules a frame but doesn't trigger one
......
...@@ -13,7 +13,7 @@ Future<String> mockUpdateUrlFetcher() { ...@@ -13,7 +13,7 @@ Future<String> mockUpdateUrlFetcher() {
void main() { void main() {
final TestWidgetsFlutterBinding binding = TestWidgetsFlutterBinding.ensureInitialized(); final TestWidgetsFlutterBinding binding = TestWidgetsFlutterBinding.ensureInitialized();
if (binding is LiveTestWidgetsFlutterBinding) if (binding is LiveTestWidgetsFlutterBinding)
binding.allowAllFrames = true; binding.framePolicy = LiveTestWidgetsFlutterBindingFramePolicy.fullyLive;
// Regression test for https://github.com/flutter/flutter/pull/5168 // Regression test for https://github.com/flutter/flutter/pull/5168
testWidgets('update dialog', (WidgetTester tester) async { testWidgets('update dialog', (WidgetTester tester) async {
......
...@@ -40,6 +40,17 @@ class TextSelectionPoint { ...@@ -40,6 +40,17 @@ class TextSelectionPoint {
/// Direction of the text at this edge of the selection. /// Direction of the text at this edge of the selection.
final TextDirection direction; final TextDirection direction;
@override
String toString() {
switch (direction) {
case TextDirection.ltr:
return '$point-ltr';
case TextDirection.rtl:
return '$point-rtl';
}
return '$point';
}
} }
/// A single line of editable text. /// A single line of editable text.
......
...@@ -3,7 +3,6 @@ ...@@ -3,7 +3,6 @@
// found in the LICENSE file. // found in the LICENSE file.
import 'dart:async'; import 'dart:async';
import 'dart:io';
import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_test/flutter_test.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
...@@ -41,12 +40,12 @@ void main() { ...@@ -41,12 +40,12 @@ void main() {
SystemChannels.platform.setMockMethodCallHandler(mockClipboard.handleMethodCall); SystemChannels.platform.setMockMethodCallHandler(mockClipboard.handleMethodCall);
const String kThreeLines = const String kThreeLines =
'First line of text is here abcdef ghijkl mnopqrst. ' + 'First line of text is ' +
'Second line of text goes until abcdef ghijkl mnopq. ' + 'Second line goes until ' +
'Third line of stuff keeps going until abcdef ghijk. '; 'Third line of stuff ';
const String kFourLines = const String kFourLines =
kThreeLines + kThreeLines +
'Fourth line won\'t display and ends at abcdef ghi. '; 'Fourth line won\'t display and ends at';
// Returns the first RenderEditable. // Returns the first RenderEditable.
RenderEditable findRenderEditable(WidgetTester tester) { RenderEditable findRenderEditable(WidgetTester tester) {
...@@ -69,7 +68,8 @@ void main() { ...@@ -69,7 +68,8 @@ void main() {
Point textOffsetToPosition(WidgetTester tester, int offset) { Point textOffsetToPosition(WidgetTester tester, int offset) {
final RenderEditable renderEditable = findRenderEditable(tester); final RenderEditable renderEditable = findRenderEditable(tester);
final List<TextSelectionPoint> endpoints = renderEditable.getEndpointsForSelection( final List<TextSelectionPoint> endpoints = renderEditable.getEndpointsForSelection(
new TextSelection.collapsed(offset: offset)); new TextSelection.collapsed(offset: offset),
);
expect(endpoints.length, 1); expect(endpoints.length, 1);
return endpoints[0].point + const Offset(0.0, -2.0); return endpoints[0].point + const Offset(0.0, -2.0);
} }
...@@ -102,15 +102,18 @@ void main() { ...@@ -102,15 +102,18 @@ void main() {
final Size emptyInputSize = inputBox.size; final Size emptyInputSize = inputBox.size;
Future<Null> checkText(String testValue) async { Future<Null> checkText(String testValue) async {
await tester.enterText(find.byType(EditableText), testValue); return TestAsyncUtils.guard(() async {
await tester.enterText(find.byType(EditableText), testValue);
// Check that the onChanged event handler fired. // Check that the onChanged event handler fired.
expect(textFieldValue, equals(testValue)); expect(textFieldValue, equals(testValue));
return await tester.pumpWidget(builder()); await tester.pumpWidget(builder());
});
} }
await checkText(' '); await checkText(' ');
expect(findTextFieldBox(), equals(inputBox)); expect(findTextFieldBox(), equals(inputBox));
expect(inputBox.size, equals(emptyInputSize)); expect(inputBox.size, equals(emptyInputSize));
...@@ -492,7 +495,7 @@ void main() { ...@@ -492,7 +495,7 @@ void main() {
await tester.pumpWidget(builder()); await tester.pumpWidget(builder());
final String testValue = kThreeLines; final String testValue = kThreeLines;
final String cutValue = 'First line of stuff keeps going until abcdef ghijk. '; final String cutValue = 'First line of stuff ';
await tester.enterText(find.byType(EditableText), testValue); await tester.enterText(find.byType(EditableText), testValue);
await tester.pumpWidget(builder()); await tester.pumpWidget(builder());
...@@ -513,8 +516,8 @@ void main() { ...@@ -513,8 +516,8 @@ void main() {
await gesture.up(); await gesture.up();
await tester.pump(); await tester.pump();
expect(controller.selection.baseOffset, 76); expect(controller.selection.baseOffset, 39);
expect(controller.selection.extentOffset, 81); expect(controller.selection.extentOffset, 44);
final RenderEditable renderEditable = findRenderEditable(tester); final RenderEditable renderEditable = findRenderEditable(tester);
final List<TextSelectionPoint> endpoints = renderEditable.getEndpointsForSelection( final List<TextSelectionPoint> endpoints = renderEditable.getEndpointsForSelection(
...@@ -531,8 +534,8 @@ void main() { ...@@ -531,8 +534,8 @@ void main() {
await gesture.up(); await gesture.up();
await tester.pumpWidget(builder()); await tester.pumpWidget(builder());
expect(controller.selection.baseOffset, 76); expect(controller.selection.baseOffset, 39);
expect(controller.selection.extentOffset, 108); expect(controller.selection.extentOffset, 50);
// Drag the left handle to the first line, just after 'First'. // Drag the left handle to the first line, just after 'First'.
handlePos = endpoints[0].point + const Offset(-1.0, 1.0); handlePos = endpoints[0].point + const Offset(-1.0, 1.0);
...@@ -545,13 +548,13 @@ void main() { ...@@ -545,13 +548,13 @@ void main() {
await tester.pumpWidget(builder()); await tester.pumpWidget(builder());
expect(controller.selection.baseOffset, 5); expect(controller.selection.baseOffset, 5);
expect(controller.selection.extentOffset, 108); expect(controller.selection.extentOffset, 50);
await tester.tap(find.text('CUT')); await tester.tap(find.text('CUT'));
await tester.pumpWidget(builder()); await tester.pumpWidget(builder());
expect(controller.selection.isCollapsed, true); expect(controller.selection.isCollapsed, true);
expect(controller.text, cutValue); expect(controller.text, cutValue);
}, skip: Platform.isMacOS); // Skip due to https://github.com/flutter/flutter/issues/6961 });
testWidgets('Can scroll multiline input', (WidgetTester tester) async { testWidgets('Can scroll multiline input', (WidgetTester tester) async {
final Key textFieldKey = new UniqueKey(); final Key textFieldKey = new UniqueKey();
...@@ -571,10 +574,12 @@ void main() { ...@@ -571,10 +574,12 @@ void main() {
} }
await tester.pumpWidget(builder()); await tester.pumpWidget(builder());
await tester.pump(const Duration(seconds: 1));
await tester.enterText(find.byType(EditableText), kFourLines); await tester.enterText(find.byType(EditableText), kFourLines);
await tester.pumpWidget(builder()); await tester.pumpWidget(builder());
await tester.pump(const Duration(seconds: 1));
RenderBox findInputBox() => tester.renderObject(find.byKey(textFieldKey)); RenderBox findInputBox() => tester.renderObject(find.byKey(textFieldKey));
final RenderBox inputBox = findInputBox(); final RenderBox inputBox = findInputBox();
...@@ -590,11 +595,11 @@ void main() { ...@@ -590,11 +595,11 @@ void main() {
TestGesture gesture = await tester.startGesture(firstPos, pointer: 7); TestGesture gesture = await tester.startGesture(firstPos, pointer: 7);
await tester.pump(); await tester.pump();
await gesture.moveBy(const Offset(0.0, -1000.0)); await gesture.moveBy(const Offset(0.0, -1000.0));
await tester.pump(const Duration(seconds: 2)); await tester.pump(const Duration(seconds: 1));
// Wait and drag again to trigger https://github.com/flutter/flutter/issues/6329 // Wait and drag again to trigger https://github.com/flutter/flutter/issues/6329
// (No idea why this is necessary, but the bug wouldn't repro without it.) // (No idea why this is necessary, but the bug wouldn't repro without it.)
await gesture.moveBy(const Offset(0.0, -1000.0)); await gesture.moveBy(const Offset(0.0, -1000.0));
await tester.pump(const Duration(seconds: 2)); await tester.pump(const Duration(seconds: 1));
await gesture.up(); await gesture.up();
await tester.pump(); await tester.pump();
...@@ -609,27 +614,26 @@ void main() { ...@@ -609,27 +614,26 @@ void main() {
// Now try scrolling by dragging the selection handle. // Now try scrolling by dragging the selection handle.
// Long press the 'i' in 'Fourth line' to select the word. // Long press the 'i' in 'Fourth line' to select the word.
await tester.pump(const Duration(seconds: 2)); await tester.pump(const Duration(seconds: 1));
final Point untilPos = textOffsetToPosition(tester, kFourLines.indexOf('Fourth line')+8); final Point untilPos = textOffsetToPosition(tester, kFourLines.indexOf('Fourth line')+8);
gesture = await tester.startGesture(untilPos, pointer: 7); gesture = await tester.startGesture(untilPos, pointer: 7);
await tester.pump(const Duration(seconds: 2)); await tester.pump(const Duration(seconds: 1));
await gesture.up(); await gesture.up();
await tester.pump(); await tester.pump(const Duration(seconds: 1));
final RenderEditable renderEditable = findRenderEditable(tester); final RenderEditable renderEditable = findRenderEditable(tester);
final List<TextSelectionPoint> endpoints = renderEditable.getEndpointsForSelection( final List<TextSelectionPoint> endpoints = renderEditable.getEndpointsForSelection(controller.selection);
controller.selection);
expect(endpoints.length, 2); expect(endpoints.length, 2);
// Drag the left handle to the first line, just after 'First'. // Drag the left handle to the first line, just after 'First'.
final Point handlePos = endpoints[0].point + const Offset(-1.0, 1.0); final Point handlePos = endpoints[0].point + const Offset(-1.0, 1.0);
final Point newHandlePos = textOffsetToPosition(tester, kFourLines.indexOf('First') + 5); final Point newHandlePos = textOffsetToPosition(tester, kFourLines.indexOf('First') + 5);
gesture = await tester.startGesture(handlePos, pointer: 7); gesture = await tester.startGesture(handlePos, pointer: 7);
await tester.pump(); await tester.pump(const Duration(seconds: 1));
await gesture.moveTo(newHandlePos + const Offset(0.0, -10.0)); await gesture.moveTo(newHandlePos + const Offset(0.0, -10.0));
await tester.pump(); await tester.pump(const Duration(seconds: 1));
await gesture.up(); await gesture.up();
await tester.pump(); await tester.pump(const Duration(seconds: 1));
// The text should have scrolled up with the handle to keep the active // The text should have scrolled up with the handle to keep the active
// cursor visible, back to its original position. // cursor visible, back to its original position.
...@@ -638,7 +642,7 @@ void main() { ...@@ -638,7 +642,7 @@ void main() {
expect(newFirstPos.y, firstPos.y); expect(newFirstPos.y, firstPos.y);
expect(inputBox.hitTest(new HitTestResult(), position: inputBox.globalToLocal(newFirstPos)), isTrue); expect(inputBox.hitTest(new HitTestResult(), position: inputBox.globalToLocal(newFirstPos)), isTrue);
expect(inputBox.hitTest(new HitTestResult(), position: inputBox.globalToLocal(newFourthPos)), isFalse); expect(inputBox.hitTest(new HitTestResult(), position: inputBox.globalToLocal(newFourthPos)), isFalse);
}, skip: Platform.isMacOS); // Skip due to https://github.com/flutter/flutter/issues/6961 });
testWidgets('InputField smoke test', (WidgetTester tester) async { testWidgets('InputField smoke test', (WidgetTester tester) async {
String textFieldValue; String textFieldValue;
...@@ -658,16 +662,18 @@ void main() { ...@@ -658,16 +662,18 @@ void main() {
await tester.pumpWidget(builder()); await tester.pumpWidget(builder());
Future<Null> checkText(String testValue) async { Future<Null> checkText(String testValue) {
await tester.enterText(find.byType(EditableText), testValue); return TestAsyncUtils.guard(() async {
await tester.enterText(find.byType(EditableText), testValue);
// Check that the onChanged event handler fired. // Check that the onChanged event handler fired.
expect(textFieldValue, equals(testValue)); expect(textFieldValue, equals(testValue));
return await tester.pumpWidget(builder()); await tester.pumpWidget(builder());
});
} }
checkText('Hello World'); await checkText('Hello World');
}); });
testWidgets('InputField with global key', (WidgetTester tester) async { testWidgets('InputField with global key', (WidgetTester tester) async {
...@@ -691,15 +697,17 @@ void main() { ...@@ -691,15 +697,17 @@ void main() {
await tester.pumpWidget(builder()); await tester.pumpWidget(builder());
Future<Null> checkText(String testValue) async { Future<Null> checkText(String testValue) async {
await tester.enterText(find.byType(EditableText), testValue); return TestAsyncUtils.guard(() async {
await tester.enterText(find.byType(EditableText), testValue);
// Check that the onChanged event handler fired. // Check that the onChanged event handler fired.
expect(textFieldValue, equals(testValue)); expect(textFieldValue, equals(testValue));
return await tester.pumpWidget(builder()); await tester.pumpWidget(builder());
});
} }
checkText('Hello World'); await checkText('Hello World');
}); });
testWidgets('TextField with default hintStyle', (WidgetTester tester) async { testWidgets('TextField with default hintStyle', (WidgetTester tester) async {
...@@ -929,35 +937,28 @@ void main() { ...@@ -929,35 +937,28 @@ void main() {
), ),
), ),
)); ));
expect(tester.testTextInput.editingState['text'], isEmpty); expect(tester.testTextInput.editingState['text'], isEmpty);
await tester.tap(find.byType(TextField)); await tester.tap(find.byType(TextField));
await tester.pump(); await tester.pump();
expect(tester.testTextInput.editingState['text'], equals('Initial Text')); expect(tester.testTextInput.editingState['text'], equals('Initial Text'));
controller.text = 'Updated Text'; controller.text = 'Updated Text';
await tester.idle(); await tester.idle();
expect(tester.testTextInput.editingState['text'], equals('Updated Text')); expect(tester.testTextInput.editingState['text'], equals('Updated Text'));
setState(() { setState(() {
currentController = controller2; currentController = controller2;
}); });
await tester.pump(); await tester.pump();
expect(tester.testTextInput.editingState['text'], equals('More Text')); expect(tester.testTextInput.editingState['text'], equals('More Text'));
controller.text = 'Ignored Text'; controller.text = 'Ignored Text';
await tester.idle(); await tester.idle();
expect(tester.testTextInput.editingState['text'], equals('More Text')); expect(tester.testTextInput.editingState['text'], equals('More Text'));
controller2.text = 'Final Text'; controller2.text = 'Final Text';
await tester.idle(); await tester.idle();
expect(tester.testTextInput.editingState['text'], equals('Final Text')); expect(tester.testTextInput.editingState['text'], equals('Final Text'));
}); });
} }
...@@ -76,7 +76,10 @@ void main() { ...@@ -76,7 +76,10 @@ void main() {
test('overflow test', () { test('overflow test', () {
final RenderParagraph paragraph = new RenderParagraph( final RenderParagraph paragraph = new RenderParagraph(
const TextSpan(text: 'This is\na wrapping test. It should wrap at manual newlines, and if softWrap is true, also at spaces.'), const TextSpan(
text: 'This\n' // 4 characters * 10px font size = 40px width on the first line
'is a wrapping test. It should wrap at manual newlines, and if softWrap is true, also at spaces.',
style: const TextStyle(fontFamily: 'Ahem', fontSize: 10.0)),
maxLines: 1, maxLines: 1,
softWrap: true, softWrap: true,
); );
...@@ -90,7 +93,7 @@ void main() { ...@@ -90,7 +93,7 @@ void main() {
} }
// Lay out in a narrow box to force wrapping. // Lay out in a narrow box to force wrapping.
layout(paragraph, constraints: const BoxConstraints(maxWidth: 50.0)); layout(paragraph, constraints: const BoxConstraints(maxWidth: 50.0)); // enough to fit "This" but not "This is"
final double lineHeight = paragraph.size.height; final double lineHeight = paragraph.size.height;
relayoutWith(maxLines: 3, softWrap: true, overflow: TextOverflow.clip); relayoutWith(maxLines: 3, softWrap: true, overflow: TextOverflow.clip);
......
...@@ -2,21 +2,27 @@ ...@@ -2,21 +2,27 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
import 'dart:io';
import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_test/flutter_test.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
const TextStyle testFont = const TextStyle(
color: const Color(0xFF00FF00),
fontFamily: 'Ahem',
);
Future<Null> pumpTest(WidgetTester tester, TargetPlatform platform) async { Future<Null> pumpTest(WidgetTester tester, TargetPlatform platform) async {
await tester.pumpWidget(new Container()); await tester.pumpWidget(new Container());
await tester.pumpWidget(new MaterialApp( await tester.pumpWidget(new MaterialApp(
theme: new ThemeData( theme: new ThemeData(
platform: platform platform: platform,
), ),
home: new ListView.builder( home: new Container(
itemBuilder: (BuildContext context, int index) { color: const Color(0xFF111111),
return new Text('$index'); child: new ListView.builder(
}, itemBuilder: (BuildContext context, int index) {
return new Text('$index', style: testFont);
},
),
), ),
)); ));
return null; return null;
...@@ -53,44 +59,44 @@ void main() { ...@@ -53,44 +59,44 @@ void main() {
final List<String> log = <String>[]; final List<String> log = <String>[];
final List<Widget> textWidgets = <Widget>[]; final List<Widget> textWidgets = <Widget>[];
for (int i = 0; i < 250; i++) for (int i = 0; i < 250; i += 1)
textWidgets.add(new GestureDetector(onTap: () { log.add('tap $i'); }, child: new Text('$i'))); textWidgets.add(new GestureDetector(onTap: () { log.add('tap $i'); }, child: new Text('$i', style: testFont)));
await tester.pumpWidget(new ListView(children: textWidgets)); await tester.pumpWidget(new ListView(children: textWidgets));
expect(log, equals(<String>[])); expect(log, equals(<String>[]));
await tester.tap(find.byType(Scrollable)); await tester.tap(find.byType(Scrollable));
await tester.pump(const Duration(milliseconds: 50)); await tester.pump(const Duration(milliseconds: 50));
expect(log, equals(<String>['tap 18'])); expect(log, equals(<String>['tap 21']));
await tester.fling(find.byType(Scrollable), const Offset(0.0, -200.0), 1000.0); await tester.fling(find.byType(Scrollable), const Offset(0.0, -200.0), 1000.0);
await tester.pump(const Duration(milliseconds: 50)); await tester.pump(const Duration(milliseconds: 50));
expect(log, equals(<String>['tap 18'])); expect(log, equals(<String>['tap 21']));
await tester.tap(find.byType(Scrollable)); await tester.tap(find.byType(Scrollable)); // should stop the fling but not tap anything
await tester.pump(const Duration(milliseconds: 50)); await tester.pump(const Duration(milliseconds: 50));
expect(log, equals(<String>['tap 18'])); expect(log, equals(<String>['tap 21']));
await tester.tap(find.byType(Scrollable)); await tester.tap(find.byType(Scrollable));
await tester.pump(const Duration(milliseconds: 50)); await tester.pump(const Duration(milliseconds: 50));
expect(log, equals(<String>['tap 18', 'tap 31'])); expect(log, equals(<String>['tap 21', 'tap 35']));
}, skip: Platform.isMacOS); // Skip due to https://github.com/flutter/flutter/issues/6961 });
testWidgets('fling and wait and tap', (WidgetTester tester) async { testWidgets('fling and wait and tap', (WidgetTester tester) async {
final List<String> log = <String>[]; final List<String> log = <String>[];
final List<Widget> textWidgets = <Widget>[]; final List<Widget> textWidgets = <Widget>[];
for (int i = 0; i < 250; i++) for (int i = 0; i < 250; i += 1)
textWidgets.add(new GestureDetector(onTap: () { log.add('tap $i'); }, child: new Text('$i'))); textWidgets.add(new GestureDetector(onTap: () { log.add('tap $i'); }, child: new Text('$i', style: testFont)));
await tester.pumpWidget(new ListView(children: textWidgets)); await tester.pumpWidget(new ListView(children: textWidgets));
expect(log, equals(<String>[])); expect(log, equals(<String>[]));
await tester.tap(find.byType(Scrollable)); await tester.tap(find.byType(Scrollable));
await tester.pump(const Duration(milliseconds: 50)); await tester.pump(const Duration(milliseconds: 50));
expect(log, equals(<String>['tap 18'])); expect(log, equals(<String>['tap 21']));
await tester.fling(find.byType(Scrollable), const Offset(0.0, -200.0), 1000.0); await tester.fling(find.byType(Scrollable), const Offset(0.0, -200.0), 1000.0);
await tester.pump(const Duration(milliseconds: 50)); await tester.pump(const Duration(milliseconds: 50));
expect(log, equals(<String>['tap 18'])); expect(log, equals(<String>['tap 21']));
await tester.pump(const Duration(seconds: 50)); await tester.pump(const Duration(seconds: 50)); // long wait, so the fling will have ended at the end of it
expect(log, equals(<String>['tap 18'])); expect(log, equals(<String>['tap 21']));
await tester.tap(find.byType(Scrollable)); await tester.tap(find.byType(Scrollable));
await tester.pump(const Duration(milliseconds: 50)); await tester.pump(const Duration(milliseconds: 50));
expect(log, equals(<String>['tap 18', 'tap 42'])); expect(log, equals(<String>['tap 21', 'tap 48']));
}, skip: Platform.isMacOS); // Skip due to https://github.com/flutter/flutter/issues/6961 });
} }
This diff is collapsed.
...@@ -282,9 +282,13 @@ class TestAsyncUtils { ...@@ -282,9 +282,13 @@ class TestAsyncUtils {
} }
} }
static bool _stripAsynchronousSuspensions(String line) {
return line != '<asynchronous suspension>';
}
static _StackEntry _findResponsibleMethod(StackTrace rawStack, String method, StringBuffer errors) { static _StackEntry _findResponsibleMethod(StackTrace rawStack, String method, StringBuffer errors) {
assert(method == 'guard' || method == 'guardSync'); assert(method == 'guard' || method == 'guardSync');
final List<String> stack = rawStack.toString().split('\n'); final List<String> stack = rawStack.toString().split('\n').where(_stripAsynchronousSuspensions).toList();
assert(stack.last == ''); assert(stack.last == '');
stack.removeLast(); stack.removeLast();
final RegExp getClassPattern = new RegExp(r'^#[0-9]+ +([^. ]+)'); final RegExp getClassPattern = new RegExp(r'^#[0-9]+ +([^. ]+)');
......
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
// found in the LICENSE file. // found in the LICENSE file.
import 'dart:async'; import 'dart:async';
import 'dart:typed_data';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
...@@ -48,7 +49,7 @@ class TestTextInput { ...@@ -48,7 +49,7 @@ class TestTextInput {
<dynamic>[_client, value.toJSON()], <dynamic>[_client, value.toJSON()],
), ),
), ),
(_) {}, (ByteData data) { /* response from framework is discarded */ },
); );
} }
......
...@@ -51,7 +51,17 @@ void testWidgets(String description, WidgetTesterCallback callback, { ...@@ -51,7 +51,17 @@ void testWidgets(String description, WidgetTesterCallback callback, {
final WidgetTester tester = new WidgetTester._(binding); final WidgetTester tester = new WidgetTester._(binding);
timeout ??= binding.defaultTestTimeout; timeout ??= binding.defaultTestTimeout;
test_package.group('-', () { test_package.group('-', () {
test_package.test(description, () => binding.runTest(() => callback(tester), tester._endOfTestVerifications), skip: skip); test_package.test(
description,
() {
return binding.runTest(
() => callback(tester),
tester._endOfTestVerifications,
description: description ?? '',
);
},
skip: skip,
);
test_package.tearDown(binding.postTest); test_package.tearDown(binding.postTest);
}, timeout: timeout); }, timeout: timeout);
} }
...@@ -109,7 +119,10 @@ Future<Null> benchmarkWidgets(WidgetTesterCallback callback) { ...@@ -109,7 +119,10 @@ Future<Null> benchmarkWidgets(WidgetTesterCallback callback) {
final TestWidgetsFlutterBinding binding = TestWidgetsFlutterBinding.ensureInitialized(); final TestWidgetsFlutterBinding binding = TestWidgetsFlutterBinding.ensureInitialized();
assert(binding is! AutomatedTestWidgetsFlutterBinding); assert(binding is! AutomatedTestWidgetsFlutterBinding);
final WidgetTester tester = new WidgetTester._(binding); final WidgetTester tester = new WidgetTester._(binding);
return binding.runTest(() => callback(tester), tester._endOfTestVerifications) ?? new Future<Null>.value(); return binding.runTest(
() => callback(tester),
tester._endOfTestVerifications,
) ?? new Future<Null>.value();
} }
/// Assert that `actual` matches `matcher`. /// Assert that `actual` matches `matcher`.
...@@ -163,6 +176,9 @@ class WidgetTester extends WidgetController implements HitTestDispatcher, Ticker ...@@ -163,6 +176,9 @@ class WidgetTester extends WidgetController implements HitTestDispatcher, Ticker
/// Subsequent calls to this is different from [pump] in that it forces a full /// Subsequent calls to this is different from [pump] in that it forces a full
/// rebuild of the tree, even if [widget] is the same as the previous call. /// rebuild of the tree, even if [widget] is the same as the previous call.
/// [pump] will only rebuild the widgets that have changed. /// [pump] will only rebuild the widgets that have changed.
///
/// See also [LiveTestWidgetsFlutterBindingFramePolicy], which affects how
/// this method works when the test is run with `flutter run`.
Future<Null> pumpWidget(Widget widget, [ Future<Null> pumpWidget(Widget widget, [
Duration duration, Duration duration,
EnginePhase phase = EnginePhase.sendSemanticsTree EnginePhase phase = EnginePhase.sendSemanticsTree
...@@ -182,6 +198,9 @@ class WidgetTester extends WidgetController implements HitTestDispatcher, Ticker ...@@ -182,6 +198,9 @@ class WidgetTester extends WidgetController implements HitTestDispatcher, Ticker
/// ///
/// This is a convenience function that just calls /// This is a convenience function that just calls
/// [TestWidgetsFlutterBinding.pump]. /// [TestWidgetsFlutterBinding.pump].
///
/// See also [LiveTestWidgetsFlutterBindingFramePolicy], which affects how
/// this method works when the test is run with `flutter run`.
@override @override
Future<Null> pump([ Future<Null> pump([
Duration duration, Duration duration,
...@@ -426,23 +445,25 @@ class WidgetTester extends WidgetController implements HitTestDispatcher, Ticker ...@@ -426,23 +445,25 @@ class WidgetTester extends WidgetController implements HitTestDispatcher, Ticker
/// Tests that just need to add text to widgets like [Input] or [TextField] /// Tests that just need to add text to widgets like [Input] or [TextField]
/// only need to call [enterText]. /// only need to call [enterText].
Future<Null> showKeyboard(Finder finder) async { Future<Null> showKeyboard(Finder finder) async {
// TODO(hansmuller): Once find.descendant (#7789) lands replace the following return TestAsyncUtils.guard(() async {
// RHS with state(find.descendant(finder), find.byType(EditableText)). // TODO(hansmuller): Once find.descendant (#7789) lands replace the following
final EditableTextState editable = state(finder); // RHS with state(find.descendant(finder), find.byType(EditableText)).
if (editable != binding.focusedEditable) { final EditableTextState editable = state(finder);
binding.focusedEditable = editable; if (editable != binding.focusedEditable) {
await pump(); binding.focusedEditable = editable;
} await pump();
return null; }
});
} }
/// Give the EditableText widget specified by [finder] the focus and /// Give the EditableText widget specified by [finder] the focus and
/// enter [text] as if it been provided by the onscreen keyboard. /// enter [text] as if it been provided by the onscreen keyboard.
Future<Null> enterText(Finder finder, String text) async { Future<Null> enterText(Finder finder, String text) async {
await showKeyboard(finder); return TestAsyncUtils.guard(() async {
testTextInput.enterText(text); await showKeyboard(finder);
await idle(); testTextInput.enterText(text);
return null; await idle();
});
} }
} }
......
...@@ -337,7 +337,7 @@ class AndroidDevice extends Device { ...@@ -337,7 +337,7 @@ class AndroidDevice extends Device {
if (debuggingOptions.debuggingEnabled) { if (debuggingOptions.debuggingEnabled) {
// TODO(devoncarew): Remember the forwarding information (so we can later remove the // TODO(devoncarew): Remember the forwarding information (so we can later remove the
// port forwarding). // port forwarding or set it up again when adb fails on us).
observatoryDiscovery = new ProtocolDiscovery.observatory( observatoryDiscovery = new ProtocolDiscovery.observatory(
getLogReader(), portForwarder: portForwarder, hostPort: debuggingOptions.observatoryPort); getLogReader(), portForwarder: portForwarder, hostPort: debuggingOptions.observatoryPort);
diagnosticDiscovery = new ProtocolDiscovery.diagnosticService( diagnosticDiscovery = new ProtocolDiscovery.diagnosticService(
...@@ -363,6 +363,8 @@ class AndroidDevice extends Device { ...@@ -363,6 +363,8 @@ class AndroidDevice extends Device {
cmd.addAll(<String>['--ez', 'enable-checked-mode', 'true']); cmd.addAll(<String>['--ez', 'enable-checked-mode', 'true']);
if (debuggingOptions.startPaused) if (debuggingOptions.startPaused)
cmd.addAll(<String>['--ez', 'start-paused', 'true']); cmd.addAll(<String>['--ez', 'start-paused', 'true']);
if (debuggingOptions.useTestFonts)
cmd.addAll(<String>['--ez', 'use-test-fonts', 'true']);
} }
cmd.add(apk.launchActivity); cmd.add(apk.launchActivity);
final String result = runCheckedSync(cmd); final String result = runCheckedSync(cmd);
...@@ -372,9 +374,8 @@ class AndroidDevice extends Device { ...@@ -372,9 +374,8 @@ class AndroidDevice extends Device {
return new LaunchResult.failed(); return new LaunchResult.failed();
} }
if (!debuggingOptions.debuggingEnabled) { if (!debuggingOptions.debuggingEnabled)
return new LaunchResult.succeeded(); return new LaunchResult.succeeded();
}
// Wait for the service protocol port here. This will complete once the // Wait for the service protocol port here. This will complete once the
// device has printed "Observatory is listening on...". // device has printed "Observatory is listening on...".
......
...@@ -296,6 +296,7 @@ class AppDomain extends Domain { ...@@ -296,6 +296,7 @@ class AppDomain extends Domain {
final String deviceId = _getStringArg(args, 'deviceId', required: true); final String deviceId = _getStringArg(args, 'deviceId', required: true);
final String projectDirectory = _getStringArg(args, 'projectDirectory', required: true); final String projectDirectory = _getStringArg(args, 'projectDirectory', required: true);
final bool startPaused = _getBoolArg(args, 'startPaused') ?? false; final bool startPaused = _getBoolArg(args, 'startPaused') ?? false;
final bool useTestFonts = _getBoolArg(args, 'useTestFonts') ?? false;
final String route = _getStringArg(args, 'route'); final String route = _getStringArg(args, 'route');
final String mode = _getStringArg(args, 'mode'); final String mode = _getStringArg(args, 'mode');
final String target = _getStringArg(args, 'target'); final String target = _getStringArg(args, 'target');
...@@ -309,10 +310,25 @@ class AppDomain extends Domain { ...@@ -309,10 +310,25 @@ class AppDomain extends Domain {
throw "'$projectDirectory' does not exist"; throw "'$projectDirectory' does not exist";
final BuildMode buildMode = getBuildModeForName(mode) ?? BuildMode.debug; final BuildMode buildMode = getBuildModeForName(mode) ?? BuildMode.debug;
DebuggingOptions options;
if (buildMode == BuildMode.release) {
options = new DebuggingOptions.disabled(buildMode);
} else {
options = new DebuggingOptions.enabled(
buildMode,
startPaused: startPaused,
useTestFonts: useTestFonts,
);
}
final AppInstance app = await startApp( final AppInstance app = await startApp(
device, projectDirectory, target, route, device,
buildMode, startPaused, enableHotReload); projectDirectory,
target,
route,
options,
enableHotReload,
);
return <String, dynamic>{ return <String, dynamic>{
'appId': app.id, 'appId': app.id,
...@@ -324,28 +340,14 @@ class AppDomain extends Domain { ...@@ -324,28 +340,14 @@ class AppDomain extends Domain {
Future<AppInstance> startApp( Future<AppInstance> startApp(
Device device, String projectDirectory, String target, String route, Device device, String projectDirectory, String target, String route,
BuildMode buildMode, bool startPaused, bool enableHotReload, { DebuggingOptions options, bool enableHotReload, {
String applicationBinary, String applicationBinary,
String projectRootPath, String projectRootPath,
String packagesFilePath, String packagesFilePath,
String projectAssets, String projectAssets,
}) async { }) async {
DebuggingOptions options; if (device.isLocalEmulator && !isEmulatorBuildMode(options.buildMode))
throw '${toTitleCase(getModeName(options.buildMode))} mode is not supported for emulators.';
switch (buildMode) {
case BuildMode.debug:
case BuildMode.profile:
options = new DebuggingOptions.enabled(buildMode, startPaused: startPaused);
break;
case BuildMode.release:
options = new DebuggingOptions.disabled(buildMode);
break;
default:
throw 'unhandle build mode: $buildMode';
}
if (device.isLocalEmulator && !isEmulatorBuildMode(buildMode))
throw '${toTitleCase(getModeName(buildMode))} mode is not supported for emulators.';
// We change the current working directory for the duration of the `start` command. // We change the current working directory for the duration of the `start` command.
final Directory cwd = fs.currentDirectory; final Directory cwd = fs.currentDirectory;
......
...@@ -88,6 +88,14 @@ class RunCommand extends RunCommandBase { ...@@ -88,6 +88,14 @@ class RunCommand extends RunCommandBase {
defaultsTo: false, defaultsTo: false,
negatable: false, negatable: false,
help: 'Start in a paused mode and wait for a debugger to connect.'); help: 'Start in a paused mode and wait for a debugger to connect.');
argParser.addFlag('use-test-fonts',
negatable: true,
defaultsTo: false,
help: 'Enable (and default to) the "Ahem" font. This is a special font\n'
'used in tests to remove any dependencies on the font metrics. It\n'
'is enabled when you use "flutter test". Set this flag when running\n'
'a test using "flutter run" for debugging purposes. This flag is\n'
'only available when running in debug mode.');
argParser.addFlag('build', argParser.addFlag('build',
defaultsTo: true, defaultsTo: true,
help: 'If necessary, build the app before running.'); help: 'If necessary, build the app before running.');
...@@ -126,18 +134,19 @@ class RunCommand extends RunCommandBase { ...@@ -126,18 +134,19 @@ class RunCommand extends RunCommandBase {
hide: !verboseHelp, hide: !verboseHelp,
help: 'Stay resident after launching the application.'); help: 'Stay resident after launching the application.');
// Hidden option to enable a benchmarking mode. This will run the given argParser.addFlag('benchmark',
// application, measure the startup time and the app restart time, write the negatable: false,
// results out to 'refresh_benchmark.json', and exit. This flag is intended hide: !verboseHelp,
// for use in generating automated flutter benchmarks. help: 'Enable a benchmarking mode. This will run the given application,\n'
argParser.addFlag('benchmark', negatable: false, hide: !verboseHelp); 'measure the startup time and the app restart time, write the\n'
'results out to "refresh_benchmark.json", and exit. This flag is\n'
'intended for use in generating automated flutter benchmarks.');
commandValidator = () { commandValidator = () {
if (!runningWithPrebuiltApplication)
commonCommandValidator();
// When running with a prebuilt application, no command validation is // When running with a prebuilt application, no command validation is
// necessary. // necessary.
if (!runningWithPrebuiltApplication)
commonCommandValidator();
}; };
} }
...@@ -196,6 +205,20 @@ class RunCommand extends RunCommandBase { ...@@ -196,6 +205,20 @@ class RunCommand extends RunCommandBase {
return super.verifyThenRunCommand(); return super.verifyThenRunCommand();
} }
DebuggingOptions _createDebuggingOptions() {
if (getBuildMode() == BuildMode.release) {
return new DebuggingOptions.disabled(getBuildMode());
} else {
return new DebuggingOptions.enabled(
getBuildMode(),
startPaused: argResults['start-paused'],
useTestFonts: argResults['use-test-fonts'],
observatoryPort: observatoryPort,
diagnosticPort: diagnosticPort,
);
}
}
@override @override
Future<Null> runCommand() async { Future<Null> runCommand() async {
...@@ -212,7 +235,7 @@ class RunCommand extends RunCommandBase { ...@@ -212,7 +235,7 @@ class RunCommand extends RunCommandBase {
try { try {
app = await daemon.appDomain.startApp( app = await daemon.appDomain.startApp(
device, fs.currentDirectory.path, targetFile, route, device, fs.currentDirectory.path, targetFile, route,
getBuildMode(), argResults['start-paused'], hotMode, _createDebuggingOptions(), hotMode,
applicationBinary: argResults['use-application-binary'], applicationBinary: argResults['use-application-binary'],
projectRootPath: argResults['project-root'], projectRootPath: argResults['project-root'],
packagesFilePath: argResults['packages'], packagesFilePath: argResults['packages'],
...@@ -229,19 +252,6 @@ class RunCommand extends RunCommandBase { ...@@ -229,19 +252,6 @@ class RunCommand extends RunCommandBase {
if (device.isLocalEmulator && !isEmulatorBuildMode(getBuildMode())) if (device.isLocalEmulator && !isEmulatorBuildMode(getBuildMode()))
throwToolExit('${toTitleCase(getModeName(getBuildMode()))} mode is not supported for emulators.'); throwToolExit('${toTitleCase(getModeName(getBuildMode()))} mode is not supported for emulators.');
DebuggingOptions options;
if (getBuildMode() == BuildMode.release) {
options = new DebuggingOptions.disabled(getBuildMode());
} else {
options = new DebuggingOptions.enabled(
getBuildMode(),
startPaused: argResults['start-paused'],
observatoryPort: observatoryPort,
diagnosticPort: diagnosticPort,
);
}
if (hotMode) { if (hotMode) {
if (!device.supportsHotMode) if (!device.supportsHotMode)
throwToolExit('Hot mode is not supported by this device. Run with --no-hot.'); throwToolExit('Hot mode is not supported by this device. Run with --no-hot.');
...@@ -258,7 +268,7 @@ class RunCommand extends RunCommandBase { ...@@ -258,7 +268,7 @@ class RunCommand extends RunCommandBase {
runner = new HotRunner( runner = new HotRunner(
device, device,
target: targetFile, target: targetFile,
debuggingOptions: options, debuggingOptions: _createDebuggingOptions(),
benchmarkMode: argResults['benchmark'], benchmarkMode: argResults['benchmark'],
applicationBinary: argResults['use-application-binary'], applicationBinary: argResults['use-application-binary'],
kernelFilePath: argResults['kernel'], kernelFilePath: argResults['kernel'],
...@@ -271,7 +281,7 @@ class RunCommand extends RunCommandBase { ...@@ -271,7 +281,7 @@ class RunCommand extends RunCommandBase {
runner = new ColdRunner( runner = new ColdRunner(
device, device,
target: targetFile, target: targetFile,
debuggingOptions: options, debuggingOptions: _createDebuggingOptions(),
traceStartup: traceStartup, traceStartup: traceStartup,
applicationBinary: argResults['use-application-binary'], applicationBinary: argResults['use-application-binary'],
stayResident: stayResident, stayResident: stayResident,
......
...@@ -279,12 +279,14 @@ abstract class Device { ...@@ -279,12 +279,14 @@ abstract class Device {
class DebuggingOptions { class DebuggingOptions {
DebuggingOptions.enabled(this.buildMode, { DebuggingOptions.enabled(this.buildMode, {
this.startPaused: false, this.startPaused: false,
this.useTestFonts: false,
this.observatoryPort, this.observatoryPort,
this.diagnosticPort this.diagnosticPort
}) : debuggingEnabled = true; }) : debuggingEnabled = true;
DebuggingOptions.disabled(this.buildMode) : DebuggingOptions.disabled(this.buildMode) :
debuggingEnabled = false, debuggingEnabled = false,
useTestFonts = false,
startPaused = false, startPaused = false,
observatoryPort = null, observatoryPort = null,
diagnosticPort = null; diagnosticPort = null;
...@@ -293,6 +295,7 @@ class DebuggingOptions { ...@@ -293,6 +295,7 @@ class DebuggingOptions {
final BuildMode buildMode; final BuildMode buildMode;
final bool startPaused; final bool startPaused;
final bool useTestFonts;
final int observatoryPort; final int observatoryPort;
final int diagnosticPort; final int diagnosticPort;
......
...@@ -228,6 +228,9 @@ class IOSDevice extends Device { ...@@ -228,6 +228,9 @@ class IOSDevice extends Device {
if (debuggingOptions.startPaused) if (debuggingOptions.startPaused)
launchArguments.add("--start-paused"); launchArguments.add("--start-paused");
if (debuggingOptions.useTestFonts)
launchArguments.add("--use-test-fonts");
if (debuggingOptions.debuggingEnabled) { if (debuggingOptions.debuggingEnabled) {
launchArguments.add("--enable-checked-mode"); launchArguments.add("--enable-checked-mode");
......
...@@ -455,6 +455,8 @@ class IOSSimulator extends Device { ...@@ -455,6 +455,8 @@ class IOSSimulator extends Device {
args.add('--enable-checked-mode'); args.add('--enable-checked-mode');
if (debuggingOptions.startPaused) if (debuggingOptions.startPaused)
args.add('--start-paused'); args.add('--start-paused');
if (debuggingOptions.useTestFonts)
args.add('--use-test-fonts');
final int observatoryPort = await debuggingOptions.findBestObservatoryPort(); final int observatoryPort = await debuggingOptions.findBestObservatoryPort();
args.add('--observatory-port=$observatoryPort'); args.add('--observatory-port=$observatoryPort');
......
...@@ -210,9 +210,8 @@ abstract class ResidentRunner { ...@@ -210,9 +210,8 @@ abstract class ResidentRunner {
} }
Future<Null> connectToServiceProtocol(Uri uri, {String isolateFilter}) async { Future<Null> connectToServiceProtocol(Uri uri, {String isolateFilter}) async {
if (!debuggingOptions.debuggingEnabled) { if (!debuggingOptions.debuggingEnabled)
return new Future<Null>.error('Error the service protocol is not enabled.'); return new Future<Null>.error('Error the service protocol is not enabled.');
}
vmService = VMService.connect(uri); vmService = VMService.connect(uri);
printTrace('Connected to service protocol: $uri'); printTrace('Connected to service protocol: $uri');
await vmService.getVM(); await vmService.getVM();
......
...@@ -100,9 +100,8 @@ class ColdRunner extends ResidentRunner { ...@@ -100,9 +100,8 @@ class ColdRunner extends ResidentRunner {
startTime.stop(); startTime.stop();
// Connect to observatory. // Connect to observatory.
if (debuggingOptions.debuggingEnabled) { if (debuggingOptions.debuggingEnabled)
await connectToServiceProtocol(_result.observatoryUri); await connectToServiceProtocol(_result.observatoryUri);
}
if (_result.hasObservatory) { if (_result.hasObservatory) {
connectionInfoCompleter?.complete(new DebugConnectionInfo( connectionInfoCompleter?.complete(new DebugConnectionInfo(
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment