yjbanov | a2b1bd4 | 2016-02-19 16:31:34 -0800 | [diff] [blame] | 1 | // Copyright 2016 The Chromium Authors. All rights reserved. |
| 2 | // Use of this source code is governed by a BSD-style license that can be |
| 3 | // found in the LICENSE file. |
| 4 | |
| 5 | import 'dart:async'; |
| 6 | |
| 7 | import 'package:file/file.dart'; |
Yegor Jbanov | 677e63b | 2016-02-25 15:58:09 -0800 | [diff] [blame] | 8 | import 'package:flutter_tools/src/android/android_device.dart'; |
yjbanov | a2b1bd4 | 2016-02-19 16:31:34 -0800 | [diff] [blame] | 9 | import 'package:flutter_tools/src/base/file_system.dart'; |
| 10 | import 'package:flutter_tools/src/base/logger.dart'; |
Yegor Jbanov | 677e63b | 2016-02-25 15:58:09 -0800 | [diff] [blame] | 11 | import 'package:flutter_tools/src/base/os.dart'; |
| 12 | import 'package:flutter_tools/src/commands/drive.dart'; |
| 13 | import 'package:flutter_tools/src/device.dart'; |
yjbanov | a2b1bd4 | 2016-02-19 16:31:34 -0800 | [diff] [blame] | 14 | import 'package:flutter_tools/src/globals.dart'; |
Yegor Jbanov | 677e63b | 2016-02-25 15:58:09 -0800 | [diff] [blame] | 15 | import 'package:flutter_tools/src/ios/simulators.dart'; |
| 16 | import 'package:mockito/mockito.dart'; |
yjbanov | a2b1bd4 | 2016-02-19 16:31:34 -0800 | [diff] [blame] | 17 | import 'package:test/test.dart'; |
| 18 | |
| 19 | import 'src/common.dart'; |
| 20 | import 'src/context.dart'; |
| 21 | import 'src/mocks.dart'; |
| 22 | |
Hixie | c7339de | 2016-03-09 17:43:14 -0800 | [diff] [blame^] | 23 | void main() { |
yjbanov | a2b1bd4 | 2016-02-19 16:31:34 -0800 | [diff] [blame] | 24 | group('drive', () { |
Yegor Jbanov | 677e63b | 2016-02-25 15:58:09 -0800 | [diff] [blame] | 25 | DriveCommand command; |
| 26 | Device mockDevice; |
| 27 | |
| 28 | void withMockDevice([Device mock]) { |
| 29 | mockDevice = mock ?? new MockDevice(); |
| 30 | targetDeviceFinder = () async => mockDevice; |
| 31 | testDeviceManager.addDevice(mockDevice); |
| 32 | } |
| 33 | |
yjbanov | a2b1bd4 | 2016-02-19 16:31:34 -0800 | [diff] [blame] | 34 | setUp(() { |
Yegor Jbanov | 677e63b | 2016-02-25 15:58:09 -0800 | [diff] [blame] | 35 | command = new DriveCommand(); |
| 36 | applyMocksToCommand(command); |
yjbanov | 278630e | 2016-02-22 14:55:17 -0800 | [diff] [blame] | 37 | useInMemoryFileSystem(cwd: '/some/app'); |
Yegor Jbanov | 677e63b | 2016-02-25 15:58:09 -0800 | [diff] [blame] | 38 | toolchainDownloader = (_) async { }; |
| 39 | targetDeviceFinder = () { |
| 40 | throw 'Unexpected call to targetDeviceFinder'; |
| 41 | }; |
| 42 | appStarter = (_) { |
| 43 | throw 'Unexpected call to appStarter'; |
| 44 | }; |
| 45 | testRunner = (_) { |
| 46 | throw 'Unexpected call to testRunner'; |
| 47 | }; |
| 48 | appStopper = (_) { |
| 49 | throw 'Unexpected call to appStopper'; |
| 50 | }; |
yjbanov | a2b1bd4 | 2016-02-19 16:31:34 -0800 | [diff] [blame] | 51 | }); |
| 52 | |
| 53 | tearDown(() { |
Yegor Jbanov | 677e63b | 2016-02-25 15:58:09 -0800 | [diff] [blame] | 54 | command = null; |
yjbanov | a2b1bd4 | 2016-02-19 16:31:34 -0800 | [diff] [blame] | 55 | restoreFileSystem(); |
Yegor Jbanov | 677e63b | 2016-02-25 15:58:09 -0800 | [diff] [blame] | 56 | restoreAppStarter(); |
| 57 | restoreAppStopper(); |
| 58 | restoreTestRunner(); |
| 59 | restoreTargetDeviceFinder(); |
yjbanov | a2b1bd4 | 2016-02-19 16:31:34 -0800 | [diff] [blame] | 60 | }); |
| 61 | |
| 62 | testUsingContext('returns 1 when test file is not found', () { |
Yegor Jbanov | 677e63b | 2016-02-25 15:58:09 -0800 | [diff] [blame] | 63 | withMockDevice(); |
yjbanov | a2b1bd4 | 2016-02-19 16:31:34 -0800 | [diff] [blame] | 64 | List<String> args = [ |
| 65 | 'drive', |
| 66 | '--target=/some/app/test/e2e.dart', |
| 67 | ]; |
| 68 | return createTestCommandRunner(command).run(args).then((int code) { |
| 69 | expect(code, equals(1)); |
| 70 | BufferLogger buffer = logger; |
| 71 | expect(buffer.errorText, |
yjbanov | 278630e | 2016-02-22 14:55:17 -0800 | [diff] [blame] | 72 | contains('Test file not found: /some/app/test_driver/e2e_test.dart')); |
yjbanov | a2b1bd4 | 2016-02-19 16:31:34 -0800 | [diff] [blame] | 73 | }); |
| 74 | }); |
| 75 | |
| 76 | testUsingContext('returns 1 when app fails to run', () async { |
Yegor Jbanov | 677e63b | 2016-02-25 15:58:09 -0800 | [diff] [blame] | 77 | withMockDevice(); |
| 78 | appStarter = expectAsync((_) async => 1); |
yjbanov | a2b1bd4 | 2016-02-19 16:31:34 -0800 | [diff] [blame] | 79 | |
yjbanov | 278630e | 2016-02-22 14:55:17 -0800 | [diff] [blame] | 80 | String testApp = '/some/app/test_driver/e2e.dart'; |
| 81 | String testFile = '/some/app/test_driver/e2e_test.dart'; |
yjbanov | a2b1bd4 | 2016-02-19 16:31:34 -0800 | [diff] [blame] | 82 | |
| 83 | MemoryFileSystem memFs = fs; |
| 84 | await memFs.file(testApp).writeAsString('main() {}'); |
| 85 | await memFs.file(testFile).writeAsString('main() {}'); |
| 86 | |
| 87 | List<String> args = [ |
| 88 | 'drive', |
| 89 | '--target=$testApp', |
| 90 | ]; |
| 91 | return createTestCommandRunner(command).run(args).then((int code) { |
| 92 | expect(code, equals(1)); |
| 93 | BufferLogger buffer = logger; |
| 94 | expect(buffer.errorText, contains( |
| 95 | 'Application failed to start. Will not run test. Quitting.' |
| 96 | )); |
| 97 | }); |
| 98 | }); |
| 99 | |
yjbanov | 278630e | 2016-02-22 14:55:17 -0800 | [diff] [blame] | 100 | testUsingContext('returns 1 when app file is outside package', () async { |
| 101 | String packageDir = '/my/app'; |
| 102 | useInMemoryFileSystem(cwd: packageDir); |
yjbanov | 278630e | 2016-02-22 14:55:17 -0800 | [diff] [blame] | 103 | |
| 104 | String appFile = '/not/in/my/app.dart'; |
| 105 | List<String> args = [ |
| 106 | 'drive', |
| 107 | '--target=$appFile', |
| 108 | ]; |
| 109 | return createTestCommandRunner(command).run(args).then((int code) { |
| 110 | expect(code, equals(1)); |
| 111 | BufferLogger buffer = logger; |
| 112 | expect(buffer.errorText, contains( |
| 113 | 'Application file $appFile is outside the package directory $packageDir' |
| 114 | )); |
| 115 | }); |
| 116 | }); |
| 117 | |
| 118 | testUsingContext('returns 1 when app file is in the root dir', () async { |
| 119 | String packageDir = '/my/app'; |
| 120 | useInMemoryFileSystem(cwd: packageDir); |
yjbanov | 278630e | 2016-02-22 14:55:17 -0800 | [diff] [blame] | 121 | |
| 122 | String appFile = '/my/app/main.dart'; |
| 123 | List<String> args = [ |
| 124 | 'drive', |
| 125 | '--target=$appFile', |
| 126 | ]; |
| 127 | return createTestCommandRunner(command).run(args).then((int code) { |
| 128 | expect(code, equals(1)); |
| 129 | BufferLogger buffer = logger; |
| 130 | expect(buffer.errorText, contains( |
| 131 | 'Application file main.dart must reside in one of the ' |
| 132 | 'sub-directories of the package structure, not in the root directory.' |
| 133 | )); |
| 134 | }); |
| 135 | }); |
| 136 | |
yjbanov | a2b1bd4 | 2016-02-19 16:31:34 -0800 | [diff] [blame] | 137 | testUsingContext('returns 0 when test ends successfully', () async { |
Yegor Jbanov | 677e63b | 2016-02-25 15:58:09 -0800 | [diff] [blame] | 138 | withMockDevice(); |
| 139 | |
yjbanov | a2b1bd4 | 2016-02-19 16:31:34 -0800 | [diff] [blame] | 140 | String testApp = '/some/app/test/e2e.dart'; |
yjbanov | 278630e | 2016-02-22 14:55:17 -0800 | [diff] [blame] | 141 | String testFile = '/some/app/test_driver/e2e_test.dart'; |
yjbanov | a2b1bd4 | 2016-02-19 16:31:34 -0800 | [diff] [blame] | 142 | |
Yegor Jbanov | 677e63b | 2016-02-25 15:58:09 -0800 | [diff] [blame] | 143 | appStarter = expectAsync((_) { |
| 144 | return new Future<int>.value(0); |
| 145 | }); |
| 146 | testRunner = expectAsync((List<String> testArgs) { |
| 147 | expect(testArgs, [testFile]); |
| 148 | return new Future<Null>.value(); |
| 149 | }); |
| 150 | appStopper = expectAsync((_) { |
| 151 | return new Future<int>.value(0); |
| 152 | }); |
yjbanov | a2b1bd4 | 2016-02-19 16:31:34 -0800 | [diff] [blame] | 153 | |
| 154 | MemoryFileSystem memFs = fs; |
| 155 | await memFs.file(testApp).writeAsString('main() {}'); |
| 156 | await memFs.file(testFile).writeAsString('main() {}'); |
| 157 | |
| 158 | List<String> args = [ |
| 159 | 'drive', |
| 160 | '--target=$testApp', |
| 161 | ]; |
| 162 | return createTestCommandRunner(command).run(args).then((int code) { |
| 163 | expect(code, equals(0)); |
| 164 | BufferLogger buffer = logger; |
| 165 | expect(buffer.errorText, isEmpty); |
| 166 | }); |
| 167 | }); |
Yegor Jbanov | 677e63b | 2016-02-25 15:58:09 -0800 | [diff] [blame] | 168 | |
| 169 | |
| 170 | group('findTargetDevice', () { |
| 171 | testUsingContext('uses specified device', () async { |
| 172 | testDeviceManager.specifiedDeviceId = '123'; |
| 173 | withMockDevice(); |
| 174 | when(mockDevice.name).thenReturn('specified-device'); |
| 175 | when(mockDevice.id).thenReturn('123'); |
| 176 | |
| 177 | Device device = await findTargetDevice(); |
| 178 | expect(device.name, 'specified-device'); |
| 179 | }); |
| 180 | }); |
| 181 | |
| 182 | group('findTargetDevice on iOS', () { |
Hixie | c7339de | 2016-03-09 17:43:14 -0800 | [diff] [blame^] | 183 | void setOs() { |
Yegor Jbanov | 677e63b | 2016-02-25 15:58:09 -0800 | [diff] [blame] | 184 | when(os.isMacOS).thenReturn(true); |
| 185 | when(os.isLinux).thenReturn(false); |
| 186 | } |
| 187 | |
| 188 | testUsingContext('uses existing emulator', () async { |
| 189 | setOs(); |
| 190 | withMockDevice(); |
| 191 | when(mockDevice.name).thenReturn('mock-simulator'); |
| 192 | when(mockDevice.isLocalEmulator).thenReturn(true); |
| 193 | |
| 194 | Device device = await findTargetDevice(); |
| 195 | expect(device.name, 'mock-simulator'); |
| 196 | }); |
| 197 | |
| 198 | testUsingContext('uses existing Android device if and there are no simulators', () async { |
| 199 | setOs(); |
| 200 | mockDevice = new MockAndroidDevice(); |
| 201 | when(mockDevice.name).thenReturn('mock-android-device'); |
| 202 | when(mockDevice.isLocalEmulator).thenReturn(false); |
| 203 | withMockDevice(mockDevice); |
| 204 | |
| 205 | Device device = await findTargetDevice(); |
| 206 | expect(device.name, 'mock-android-device'); |
| 207 | }); |
| 208 | |
| 209 | testUsingContext('launches emulator', () async { |
| 210 | setOs(); |
| 211 | when(SimControl.instance.boot()).thenReturn(true); |
| 212 | Device emulator = new MockDevice(); |
| 213 | when(emulator.name).thenReturn('new-simulator'); |
| 214 | when(IOSSimulatorUtils.instance.getAttachedDevices()) |
| 215 | .thenReturn([emulator]); |
| 216 | |
| 217 | Device device = await findTargetDevice(); |
| 218 | expect(device.name, 'new-simulator'); |
| 219 | }); |
| 220 | }); |
| 221 | |
| 222 | group('findTargetDevice on Linux', () { |
Hixie | c7339de | 2016-03-09 17:43:14 -0800 | [diff] [blame^] | 223 | void setOs() { |
Yegor Jbanov | 677e63b | 2016-02-25 15:58:09 -0800 | [diff] [blame] | 224 | when(os.isMacOS).thenReturn(false); |
| 225 | when(os.isLinux).thenReturn(true); |
| 226 | } |
| 227 | |
| 228 | testUsingContext('returns null if no devices found', () async { |
| 229 | setOs(); |
| 230 | expect(await findTargetDevice(), isNull); |
| 231 | }); |
| 232 | |
| 233 | testUsingContext('uses existing Android device', () async { |
| 234 | setOs(); |
| 235 | mockDevice = new MockAndroidDevice(); |
| 236 | when(mockDevice.name).thenReturn('mock-android-device'); |
| 237 | withMockDevice(mockDevice); |
| 238 | |
| 239 | Device device = await findTargetDevice(); |
| 240 | expect(device.name, 'mock-android-device'); |
| 241 | }); |
| 242 | }); |
yjbanov | a2b1bd4 | 2016-02-19 16:31:34 -0800 | [diff] [blame] | 243 | }); |
| 244 | } |
Yegor Jbanov | 677e63b | 2016-02-25 15:58:09 -0800 | [diff] [blame] | 245 | |
| 246 | class MockDevice extends Mock implements Device { |
| 247 | MockDevice() { |
| 248 | when(this.isSupported()).thenReturn(true); |
| 249 | } |
| 250 | } |
| 251 | |
| 252 | class MockAndroidDevice extends Mock implements AndroidDevice { } |