resident_web_runner_cold_test.dart 8.13 KB
Newer Older
Ian Hickson's avatar
Ian Hickson committed
1
// Copyright 2014 The Flutter Authors. All rights reserved.
2 3 4
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

5 6
// @dart = 2.8

7 8
import 'dart:async';

9
import 'package:file/memory.dart';
10
import 'package:flutter_tools/src/base/common.dart';
11
import 'package:flutter_tools/src/base/file_system.dart';
12
import 'package:flutter_tools/src/base/logger.dart';
13
import 'package:flutter_tools/src/build_info.dart';
14 15
import 'package:flutter_tools/src/isolated/devfs_web.dart';
import 'package:flutter_tools/src/isolated/resident_web_runner.dart';
16
import 'package:flutter_tools/src/build_system/build_system.dart';
17
import 'package:flutter_tools/src/device.dart';
18
import 'package:flutter_tools/src/globals.dart' as globals;
19 20
import 'package:flutter_tools/src/project.dart';
import 'package:flutter_tools/src/resident_runner.dart';
21 22
import 'package:flutter_tools/src/web/chrome.dart';
import 'package:flutter_tools/src/web/web_device.dart';
23
import 'package:mockito/mockito.dart';
24
import 'package:webkit_inspection_protocol/webkit_inspection_protocol.dart';
25 26

import '../src/common.dart';
27
import '../src/context.dart';
28
import '../src/fakes.dart';
29
import '../src/test_build_system.dart';
30 31 32

void main() {
  ResidentWebRunner residentWebRunner;
33
  MockFlutterDevice mockFlutterDevice;
34
  MockWebDevFS mockWebDevFS;
35 36

  setUp(() {
37
    mockWebDevFS = MockWebDevFS();
38
    final MockWebDevice mockWebDevice = MockWebDevice();
39 40
    mockFlutterDevice = MockFlutterDevice();
    when(mockFlutterDevice.device).thenReturn(mockWebDevice);
41 42
    when(mockFlutterDevice.devFS).thenReturn(mockWebDevFS);
    when(mockWebDevFS.sources).thenReturn(<Uri>[]);
43 44
  });

45
  void _setupMocks() {
46
    globals.fs.file('.packages').writeAsStringSync('\n');
47 48 49
    globals.fs.file('pubspec.yaml').createSync();
    globals.fs.file(globals.fs.path.join('lib', 'main.dart')).createSync(recursive: true);
    globals.fs.file(globals.fs.path.join('web', 'index.html')).createSync(recursive: true);
50
    final FlutterProject project = FlutterProject.fromDirectoryTest(globals.fs.currentDirectory);
51
    residentWebRunner = ResidentWebRunner(
52 53 54 55 56 57
      mockFlutterDevice,
      flutterProject: project,
      debuggingOptions: DebuggingOptions.disabled(BuildInfo.release),
      ipv6: true,
      stayResident: true,
      urlTunneller: null,
58 59 60 61 62 63
      featureFlags: TestFeatureFlags(),
      fileSystem: globals.fs,
      logger: globals.logger,
      systemClock: globals.systemClock,
      usage: globals.flutterUsage,
    );
64 65
  }

66
  testUsingContext('Can successfully run and connect without vmservice', () async {
67
    _setupMocks();
68
    final FakeStatusLogger fakeStatusLogger = globals.logger as FakeStatusLogger;
69
    final MockStatus mockStatus = MockStatus();
70
    fakeStatusLogger.status = mockStatus;
71 72 73 74 75 76 77
    final Completer<DebugConnectionInfo> connectionInfoCompleter = Completer<DebugConnectionInfo>();
    unawaited(residentWebRunner.run(
      connectionInfoCompleter: connectionInfoCompleter,
    ));
    final DebugConnectionInfo debugConnectionInfo = await connectionInfoCompleter.future;

    expect(debugConnectionInfo.wsUri, null);
78 79
    verify(mockStatus.stop()).called(1);
  }, overrides: <Type, Generator>{
80 81 82 83 84
    BuildSystem: () => TestBuildSystem.all(BuildResult(success: true)),
    Logger: () => FakeStatusLogger(BufferLogger.test()),
    FileSystem: () => MemoryFileSystem.test(),
    ProcessManager: () => FakeProcessManager.any(),
  });
85

86
  // Regression test for https://github.com/flutter/flutter/issues/60613
87
  testUsingContext('ResidentWebRunner calls appFailedToStart if initial compilation fails', () async {
88
    _setupMocks();
89

90
    expect(() async => residentWebRunner.run(), throwsToolExit());
91 92
    expect(await residentWebRunner.waitForAppToFinish(), 1);
  }, overrides: <Type, Generator>{
93 94 95 96
    BuildSystem: () => TestBuildSystem.all(BuildResult(success: false)),
    FileSystem: () => MemoryFileSystem.test(),
    ProcessManager: () => FakeProcessManager.any(),
  });
97 98

  // Regression test for https://github.com/flutter/flutter/issues/60613
99
  testUsingContext('ResidentWebRunner calls appFailedToStart if error is thrown during startup', () async {
100
    _setupMocks();
101

102
    expect(() async => residentWebRunner.run(), throwsA(isA<Exception>()));
103 104
    expect(await residentWebRunner.waitForAppToFinish(), 1);
  }, overrides: <Type, Generator>{
105 106 107 108
    BuildSystem: () => TestBuildSystem.error(Exception('foo')),
    FileSystem: () => MemoryFileSystem.test(),
    ProcessManager: () => FakeProcessManager.any(),
  });
109

110
  testUsingContext('Can full restart after attaching', () async {
111 112
    _setupMocks();
    final Completer<DebugConnectionInfo> connectionInfoCompleter = Completer<DebugConnectionInfo>();
113
    unawaited(residentWebRunner.run(
114 115 116 117 118 119
      connectionInfoCompleter: connectionInfoCompleter,
    ));
    await connectionInfoCompleter.future;
    final OperationResult result = await residentWebRunner.restart(fullRestart: true);

    expect(result.code, 0);
120
  }, overrides: <Type, Generator>{
121 122 123 124
    BuildSystem: () => TestBuildSystem.all(BuildResult(success: true)),
    FileSystem: () => MemoryFileSystem.test(),
    ProcessManager: () => FakeProcessManager.any(),
  });
125

126
  testUsingContext('Fails on compilation errors in hot restart', () async {
127 128
    _setupMocks();
    final Completer<DebugConnectionInfo> connectionInfoCompleter = Completer<DebugConnectionInfo>();
129
    unawaited(residentWebRunner.run(
130 131 132 133 134 135 136
      connectionInfoCompleter: connectionInfoCompleter,
    ));
    await connectionInfoCompleter.future;
    final OperationResult result = await residentWebRunner.restart(fullRestart: true);

    expect(result.code, 1);
    expect(result.message, contains('Failed to recompile application.'));
137
  }, overrides: <Type, Generator>{
138 139 140 141 142 143 144
    BuildSystem: () => TestBuildSystem.list(<BuildResult>[
      BuildResult(success: true),
      BuildResult(success: false),
    ]),
    FileSystem: () => MemoryFileSystem.test(),
    ProcessManager: () => FakeProcessManager.any(),
  });
145

146
  testUsingContext('Correctly performs a full refresh on attached chrome device.', () async {
147 148 149 150 151 152
    _setupMocks();
    final MockChromeDevice chromeDevice = MockChromeDevice();
    final MockChrome chrome = MockChrome();
    final MockChromeConnection mockChromeConnection = MockChromeConnection();
    final MockChromeTab mockChromeTab = MockChromeTab();
    final MockWipConnection mockWipConnection = MockWipConnection();
153
    final MockChromiumLauncher chromiumLauncher = MockChromiumLauncher();
154 155 156 157 158 159
    when(mockChromeConnection.getTab(any)).thenAnswer((Invocation invocation) async {
      return mockChromeTab;
    });
    when(mockChromeTab.connect()).thenAnswer((Invocation invocation) async {
      return mockWipConnection;
    });
160 161 162
    when(chromiumLauncher.connectedInstance).thenAnswer((Invocation invocation) async {
      return chrome;
    });
163
    when(chrome.chromeConnection).thenReturn(mockChromeConnection);
164
    when(chromeDevice.chromeLauncher).thenReturn(chromiumLauncher);
165 166 167 168 169 170 171 172 173 174 175 176
    when(mockFlutterDevice.device).thenReturn(chromeDevice);
    final Completer<DebugConnectionInfo> connectionInfoCompleter = Completer<DebugConnectionInfo>();
    unawaited(residentWebRunner.run(
      connectionInfoCompleter: connectionInfoCompleter,
    ));
    await connectionInfoCompleter.future;
    final OperationResult result = await residentWebRunner.restart(fullRestart: true);

    expect(result.code, 0);
    verify(mockWipConnection.sendCommand('Page.reload', <String, Object>{
      'ignoreCache': true,
    })).called(1);
177
  }, overrides: <Type, Generator>{
178 179 180 181
    BuildSystem: () => TestBuildSystem.all(BuildResult(success: true)),
    FileSystem: () => MemoryFileSystem.test(),
    ProcessManager: () => FakeProcessManager.any(),
  });
182 183
}

184
class MockWebDevFS extends Mock implements WebDevFS {}
185
class MockWebDevice extends Mock implements Device {}
186
class MockStatus extends Mock implements Status {}
187
class MockFlutterDevice extends Mock implements FlutterDevice {}
188 189
class MockChromeDevice extends Mock implements ChromiumDevice {}
class MockChrome extends Mock implements Chromium {}
190 191 192
class MockChromeConnection extends Mock implements ChromeConnection {}
class MockChromeTab extends Mock implements ChromeTab {}
class MockWipConnection extends Mock implements WipConnection {}
193
class MockChromiumLauncher extends Mock implements ChromiumLauncher {}