Unverified Commit 1957c663 authored by Jonah Williams's avatar Jonah Williams Committed by GitHub

add testing to screenshot and printDetails method (#36418)

parent b7a49c4a
...@@ -679,7 +679,14 @@ abstract class ResidentRunner { ...@@ -679,7 +679,14 @@ abstract class ResidentRunner {
} }
} }
/// Take a screenshot on the provided [device].
///
/// If the device has a connected vmservice, this method will attempt to hide
/// and restore the debug banner before taking the screenshot.
///
/// Throws an [AssertionError] if [Devce.supportsScreenshot] is not true.
Future<void> screenshot(FlutterDevice device) async { Future<void> screenshot(FlutterDevice device) async {
assert(device.device.supportsScreenshot);
final Status status = logger.startProgress('Taking screenshot for ${device.device.name}...', timeout: timeoutConfiguration.fastOperation); final Status status = logger.startProgress('Taking screenshot for ${device.device.name}...', timeout: timeoutConfiguration.fastOperation);
final File outputFile = getUniqueFile(fs.currentDirectory, 'flutter', 'png'); final File outputFile = getUniqueFile(fs.currentDirectory, 'flutter', 'png');
try { try {
......
...@@ -5,6 +5,9 @@ ...@@ -5,6 +5,9 @@
import 'dart:async'; import 'dart:async';
import 'package:flutter_tools/src/base/common.dart'; import 'package:flutter_tools/src/base/common.dart';
import 'package:flutter_tools/src/base/context.dart';
import 'package:flutter_tools/src/base/file_system.dart';
import 'package:flutter_tools/src/base/logger.dart';
import 'package:flutter_tools/src/build_info.dart'; import 'package:flutter_tools/src/build_info.dart';
import 'package:flutter_tools/src/devfs.dart'; import 'package:flutter_tools/src/devfs.dart';
import 'package:flutter_tools/src/device.dart'; import 'package:flutter_tools/src/device.dart';
...@@ -19,7 +22,6 @@ import '../src/common.dart'; ...@@ -19,7 +22,6 @@ import '../src/common.dart';
import '../src/testbed.dart'; import '../src/testbed.dart';
void main() { void main() {
group('ResidentRunner', () {
final Uri testUri = Uri.parse('foo://bar'); final Uri testUri = Uri.parse('foo://bar');
Testbed testbed; Testbed testbed;
MockFlutterDevice mockFlutterDevice; MockFlutterDevice mockFlutterDevice;
...@@ -107,7 +109,7 @@ void main() { ...@@ -107,7 +109,7 @@ void main() {
}); });
}); });
test('Can attach to device successfully', () => testbed.run(() async { test('ResidentRunner can attach to device successfully', () => testbed.run(() async {
final Completer<DebugConnectionInfo> onConnectionInfo = Completer<DebugConnectionInfo>.sync(); final Completer<DebugConnectionInfo> onConnectionInfo = Completer<DebugConnectionInfo>.sync();
final Completer<void> onAppStart = Completer<void>.sync(); final Completer<void> onAppStart = Completer<void>.sync();
final Future<int> result = residentRunner.attach( final Future<int> result = residentRunner.attach(
...@@ -125,7 +127,7 @@ void main() { ...@@ -125,7 +127,7 @@ void main() {
expect(onAppStart.isCompleted, true); expect(onAppStart.isCompleted, true);
})); }));
test('Can handle an RPC exception from hot reload', () => testbed.run(() async { test('ResidentRunner can handle an RPC exception from hot reload', () => testbed.run(() async {
when(mockDevice.sdkNameAndVersion).thenAnswer((Invocation invocation) async { when(mockDevice.sdkNameAndVersion).thenAnswer((Invocation invocation) async {
return 'Example'; return 'Example';
}); });
...@@ -168,7 +170,7 @@ void main() { ...@@ -168,7 +170,7 @@ void main() {
Usage: () => MockUsage(), Usage: () => MockUsage(),
})); }));
test('Can handle an RPC exception from hot restart', () => testbed.run(() async { test('ResidentRunner Can handle an RPC exception from hot restart', () => testbed.run(() async {
when(mockDevice.sdkNameAndVersion).thenAnswer((Invocation invocation) async { when(mockDevice.sdkNameAndVersion).thenAnswer((Invocation invocation) async {
return 'Example'; return 'Example';
}); });
...@@ -212,8 +214,113 @@ void main() { ...@@ -212,8 +214,113 @@ void main() {
Usage: () => MockUsage(), Usage: () => MockUsage(),
})); }));
group('FlutterDevice' , () { test('ResidentRunner printHelpDetails', () => testbed.run(() {
test('Will not exit a paused isolate', () => testbed.run(() async { when(mockDevice.supportsHotRestart).thenReturn(true);
when(mockDevice.supportsScreenshot).thenReturn(true);
residentRunner.printHelp(details: true);
final BufferLogger bufferLogger = context.get<Logger>();
// supports service protocol
expect(residentRunner.supportsServiceProtocol, true);
expect(bufferLogger.statusText, contains('"w"'));
expect(bufferLogger.statusText, contains('"t"'));
expect(bufferLogger.statusText, contains('"P"'));
expect(bufferLogger.statusText, contains('"a"'));
// isRunningDebug
expect(residentRunner.isRunningDebug, true);
expect(bufferLogger.statusText, contains('"L"'));
expect(bufferLogger.statusText, contains('"S"'));
expect(bufferLogger.statusText, contains('"U"'));
expect(bufferLogger.statusText, contains('"i"'));
expect(bufferLogger.statusText, contains('"p"'));
expect(bufferLogger.statusText, contains('"o"'));
expect(bufferLogger.statusText, contains('"z"'));
// screenshot
expect(bufferLogger.statusText, contains('"s"'));
}));
test('ResidentRunner can take screenshot on debug device', () => testbed.run(() async {
when(mockDevice.supportsScreenshot).thenReturn(true);
when(mockDevice.takeScreenshot(any))
.thenAnswer((Invocation invocation) async {
final File file = invocation.positionalArguments.first;
file.writeAsBytesSync(List<int>.generate(1024, (int i) => i));
});
final BufferLogger bufferLogger = context.get<Logger>();
await residentRunner.screenshot(mockFlutterDevice);
// disables debug banner.
verify(mockIsolate.flutterDebugAllowBanner(false)).called(1);
// Enables debug banner.
verify(mockIsolate.flutterDebugAllowBanner(true)).called(1);
expect(bufferLogger.statusText, contains('1kB'));
}));
test('ResidentRunner bails taking screenshot on debug device if debugAllowBanner throws pre', () => testbed.run(() async {
when(mockDevice.supportsScreenshot).thenReturn(true);
when(mockIsolate.flutterDebugAllowBanner(false)).thenThrow(Exception());
final BufferLogger bufferLogger = context.get<Logger>();
await residentRunner.screenshot(mockFlutterDevice);
expect(bufferLogger.errorText, contains('Error'));
}));
test('ResidentRunner bails taking screenshot on debug device if debugAllowBanner throws post', () => testbed.run(() async {
when(mockDevice.supportsScreenshot).thenReturn(true);
when(mockIsolate.flutterDebugAllowBanner(true)).thenThrow(Exception());
final BufferLogger bufferLogger = context.get<Logger>();
await residentRunner.screenshot(mockFlutterDevice);
expect(bufferLogger.errorText, contains('Error'));
}));
test('ResidentRunner bails taking screenshot on debug device if takeScreenshot throws', () => testbed.run(() async {
when(mockDevice.supportsScreenshot).thenReturn(true);
when(mockDevice.takeScreenshot(any)).thenThrow(Exception());
final BufferLogger bufferLogger = context.get<Logger>();
await residentRunner.screenshot(mockFlutterDevice);
expect(bufferLogger.errorText, contains('Error'));
}));
test('ResidentRunner can\'t take screenshot on device without support', () => testbed.run(() {
when(mockDevice.supportsScreenshot).thenReturn(false);
expect(() => residentRunner.screenshot(mockFlutterDevice),
throwsA(isInstanceOf<AssertionError>()));
}));
test('ResidentRunner does not toggle banner in non-debug mode', () => testbed.run(() async {
residentRunner = HotRunner(
<FlutterDevice>[
mockFlutterDevice,
],
stayResident: false,
debuggingOptions: DebuggingOptions.disabled(BuildInfo.release),
);
when(mockDevice.supportsScreenshot).thenReturn(true);
when(mockDevice.takeScreenshot(any))
.thenAnswer((Invocation invocation) async {
final File file = invocation.positionalArguments.first;
file.writeAsBytesSync(List<int>.generate(1024, (int i) => i));
});
final BufferLogger bufferLogger = context.get<Logger>();
await residentRunner.screenshot(mockFlutterDevice);
// doesn't disabled debug banner.
verifyNever(mockIsolate.flutterDebugAllowBanner(false));
// doesn't enable debug banner.
verifyNever(mockIsolate.flutterDebugAllowBanner(true));
expect(bufferLogger.statusText, contains('1kB'));
}));
test('FlutterDevice will not exit a paused isolate', () => testbed.run(() async {
final TestFlutterDevice flutterDevice = TestFlutterDevice( final TestFlutterDevice flutterDevice = TestFlutterDevice(
mockDevice, mockDevice,
<FlutterView>[ mockFlutterView ], <FlutterView>[ mockFlutterView ],
...@@ -229,7 +336,7 @@ void main() { ...@@ -229,7 +336,7 @@ void main() {
verify(mockDevice.stopApp(any)).called(1); verify(mockDevice.stopApp(any)).called(1);
})); }));
test('Will exit an un-paused isolate', () => testbed.run(() async { test('FlutterDevice will exit an un-paused isolate', () => testbed.run(() async {
final TestFlutterDevice flutterDevice = TestFlutterDevice( final TestFlutterDevice flutterDevice = TestFlutterDevice(
mockDevice, mockDevice,
<FlutterView> [mockFlutterView ], <FlutterView> [mockFlutterView ],
...@@ -244,8 +351,6 @@ void main() { ...@@ -244,8 +351,6 @@ void main() {
verify(mockIsolate.flutterExit()).called(1); verify(mockIsolate.flutterExit()).called(1);
})); }));
});
});
} }
class MockFlutterDevice extends Mock implements FlutterDevice {} class MockFlutterDevice extends Mock implements FlutterDevice {}
......
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