// Copyright 2016 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'; import 'package:file/file.dart'; import 'package:flutter_tools/src/android/android_device.dart'; import 'package:flutter_tools/src/base/file_system.dart'; import 'package:flutter_tools/src/base/logger.dart'; import 'package:flutter_tools/src/base/os.dart'; import 'package:flutter_tools/src/commands/drive.dart'; import 'package:flutter_tools/src/device.dart'; import 'package:flutter_tools/src/globals.dart'; import 'package:flutter_tools/src/ios/simulators.dart'; import 'package:mockito/mockito.dart'; import 'package:test/test.dart'; import 'src/common.dart'; import 'src/context.dart'; import 'src/mocks.dart'; void main() { group('drive', () { DriveCommand command; Device mockDevice; void withMockDevice([Device mock]) { mockDevice = mock ?? new MockDevice(); targetDeviceFinder = () async => mockDevice; testDeviceManager.addDevice(mockDevice); } setUp(() { command = new DriveCommand(); applyMocksToCommand(command); useInMemoryFileSystem(cwd: '/some/app'); targetDeviceFinder = () { throw 'Unexpected call to targetDeviceFinder'; }; appStarter = (_) { throw 'Unexpected call to appStarter'; }; testRunner = (_) { throw 'Unexpected call to testRunner'; }; appStopper = (_) { throw 'Unexpected call to appStopper'; }; }); tearDown(() { command = null; restoreFileSystem(); restoreAppStarter(); restoreAppStopper(); restoreTestRunner(); restoreTargetDeviceFinder(); }); testUsingContext('returns 1 when test file is not found', () { withMockDevice(); List<String> args = <String>[ 'drive', '--target=/some/app/test/e2e.dart', ]; return createTestCommandRunner(command).run(args).then((int code) { expect(code, 1); BufferLogger buffer = logger; expect(buffer.errorText, contains( 'Test file not found: /some/app/test_driver/e2e_test.dart' )); }); }); testUsingContext('returns 1 when app fails to run', () async { withMockDevice(); appStarter = expectAsync((_) async => 1); String testApp = '/some/app/test_driver/e2e.dart'; String testFile = '/some/app/test_driver/e2e_test.dart'; MemoryFileSystem memFs = fs; await memFs.file(testApp).writeAsString('main() {}'); await memFs.file(testFile).writeAsString('main() {}'); List<String> args = <String>[ 'drive', '--target=$testApp', ]; return createTestCommandRunner(command).run(args).then((int code) { expect(code, 1); BufferLogger buffer = logger; expect(buffer.errorText, contains( 'Application failed to start. Will not run test. Quitting.' )); }); }); testUsingContext('returns 1 when app file is outside package', () async { String packageDir = '/my/app'; useInMemoryFileSystem(cwd: packageDir); String appFile = '/not/in/my/app.dart'; List<String> args = <String>[ 'drive', '--target=$appFile', ]; return createTestCommandRunner(command).run(args).then((int code) { expect(code, 1); BufferLogger buffer = logger; expect(buffer.errorText, contains( 'Application file $appFile is outside the package directory $packageDir' )); }); }); testUsingContext('returns 1 when app file is in the root dir', () async { String packageDir = '/my/app'; useInMemoryFileSystem(cwd: packageDir); String appFile = '/my/app/main.dart'; List<String> args = <String>[ 'drive', '--target=$appFile', ]; return createTestCommandRunner(command).run(args).then((int code) { expect(code, 1); BufferLogger buffer = logger; expect(buffer.errorText, contains( 'Application file main.dart must reside in one of the ' 'sub-directories of the package structure, not in the root directory.' )); }); }); testUsingContext('returns 0 when test ends successfully', () async { withMockDevice(); String testApp = '/some/app/test/e2e.dart'; String testFile = '/some/app/test_driver/e2e_test.dart'; appStarter = expectAsync((_) { return new Future<int>.value(0); }); testRunner = expectAsync((List<String> testArgs) { expect(testArgs, <String>[testFile]); return new Future<int>.value(0); }); appStopper = expectAsync((_) { return new Future<int>.value(0); }); MemoryFileSystem memFs = fs; await memFs.file(testApp).writeAsString('main() {}'); await memFs.file(testFile).writeAsString('main() {}'); List<String> args = <String>[ 'drive', '--target=$testApp', ]; return createTestCommandRunner(command).run(args).then((int code) { expect(code, 0); BufferLogger buffer = logger; expect(buffer.errorText, isEmpty); }); }); testUsingContext('returns exitCode set by test runner', () async { withMockDevice(); String testApp = '/some/app/test/e2e.dart'; String testFile = '/some/app/test_driver/e2e_test.dart'; appStarter = expectAsync((_) { return new Future<int>.value(0); }); testRunner = expectAsync((_) { return new Future<int>.value(123); }); appStopper = expectAsync((_) { return new Future<int>.value(0); }); MemoryFileSystem memFs = fs; await memFs.file(testApp).writeAsString('main() {}'); await memFs.file(testFile).writeAsString('main() {}'); List<String> args = <String>[ 'drive', '--target=$testApp', ]; return createTestCommandRunner(command).run(args).then((int code) { expect(code, 123); BufferLogger buffer = logger; expect(buffer.errorText, isEmpty); }); }); group('findTargetDevice', () { testUsingContext('uses specified device', () async { testDeviceManager.specifiedDeviceId = '123'; withMockDevice(); when(mockDevice.name).thenReturn('specified-device'); when(mockDevice.id).thenReturn('123'); Device device = await findTargetDevice(); expect(device.name, 'specified-device'); }); }); group('findTargetDevice on iOS', () { void setOs() { when(os.isMacOS).thenReturn(true); when(os.isLinux).thenReturn(false); } testUsingContext('uses existing emulator', () async { setOs(); withMockDevice(); when(mockDevice.name).thenReturn('mock-simulator'); when(mockDevice.isLocalEmulator).thenReturn(true); Device device = await findTargetDevice(); expect(device.name, 'mock-simulator'); }); testUsingContext('uses existing Android device if and there are no simulators', () async { setOs(); mockDevice = new MockAndroidDevice(); when(mockDevice.name).thenReturn('mock-android-device'); when(mockDevice.isLocalEmulator).thenReturn(false); withMockDevice(mockDevice); Device device = await findTargetDevice(); expect(device.name, 'mock-android-device'); }); testUsingContext('launches emulator', () async { setOs(); when(SimControl.instance.boot()).thenReturn(true); Device emulator = new MockDevice(); when(emulator.name).thenReturn('new-simulator'); when(IOSSimulatorUtils.instance.getAttachedDevices()) .thenReturn(<Device>[emulator]); Device device = await findTargetDevice(); expect(device.name, 'new-simulator'); }); }); group('findTargetDevice on Linux', () { void setOs() { when(os.isMacOS).thenReturn(false); when(os.isLinux).thenReturn(true); } testUsingContext('returns null if no devices found', () async { setOs(); expect(await findTargetDevice(), isNull); }); testUsingContext('uses existing Android device', () async { setOs(); mockDevice = new MockAndroidDevice(); when(mockDevice.name).thenReturn('mock-android-device'); withMockDevice(mockDevice); Device device = await findTargetDevice(); expect(device.name, 'mock-android-device'); }); }); }); } class MockDevice extends Mock implements Device { MockDevice() { when(this.isSupported()).thenReturn(true); } } class MockAndroidDevice extends Mock implements AndroidDevice { }