| // Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file |
| // for details. All rights reserved. Use of this source code is governed by a |
| // BSD-style license that can be found in the LICENSE file. |
| |
| @Timeout(Duration(seconds: 60)) |
| library; |
| |
| import 'dart:async'; |
| import 'dart:io'; |
| |
| import 'package:logging/logging.dart'; |
| import 'package:test/test.dart'; |
| import 'package:webdev/src/logging.dart'; |
| import 'package:webdev/src/serve/chrome.dart'; |
| import 'package:webkit_inspection_protocol/webkit_inspection_protocol.dart'; |
| |
| void main() { |
| Chrome? chrome; |
| |
| Future<void> launchChrome({int? port, String? userDataDir}) async { |
| chrome = await Chrome.start([_googleUrl], |
| port: port ?? 0, userDataDir: userDataDir); |
| } |
| |
| Future<void> openTab(String url) => |
| chrome!.chromeConnection.getUrl(_openTabUrl(url)); |
| |
| Future<void> closeTab(ChromeTab tab) => |
| chrome!.chromeConnection.getUrl(_closeTabUrl(tab.id)); |
| |
| Future<WipConnection> connectToTab(String url) async { |
| final tab = await chrome!.chromeConnection.getTab( |
| (t) => t.url.contains(url), |
| retryFor: const Duration(milliseconds: 60)); |
| expect(tab, isNotNull); |
| return tab!.connect(); |
| } |
| |
| group('chrome with temp data dir', () { |
| tearDown(() async { |
| final tabs = await chrome?.chromeConnection.getTabs(); |
| if (tabs != null) { |
| for (final tab in tabs) { |
| await closeTab(tab); |
| } |
| } |
| await chrome?.close(); |
| chrome = null; |
| }); |
| |
| test('can launch chrome', () async { |
| await launchChrome(); |
| expect(chrome, isNotNull); |
| }); |
| |
| test('has a working debugger', () async { |
| await launchChrome(); |
| final tabs = await chrome!.chromeConnection.getTabs(); |
| expect( |
| tabs, |
| contains(const TypeMatcher<ChromeTab>() |
| .having((t) => t.url, 'url', _googleUrl))); |
| }); |
| |
| test('uses open debug port if provided port is 0', () async { |
| await launchChrome(port: 0); |
| expect(chrome!.debugPort, isNot(equals(0))); |
| }); |
| |
| test('has correct profile path', () async { |
| await launchChrome(); |
| await openTab(_chromeVersionUrl); |
| |
| final wipConnection = await connectToTab(_chromeVersionUrl); |
| final result = await _evaluateExpression(wipConnection.page, |
| "document.getElementById('profile_path').textContent"); |
| |
| if (Platform.isWindows) { |
| // --user-data-dir is not supported on Windows yet |
| // Issue: https://github.com/dart-lang/webdev/issues/1545 |
| expect(result, isNot(contains('chrome_user_data'))); |
| } else { |
| expect(result, contains('chrome_user_data')); |
| } |
| }, skip: 'https://github.com/dart-lang/webdev/issues/2030'); |
| }); |
| |
| group('chrome with user data dir', () { |
| late Directory dataDir; |
| late StreamController<String> logController; |
| late Stream<String> logStream; |
| |
| setUp(() { |
| logController = StreamController<String>(); |
| logStream = logController.stream; |
| |
| void logWriter(Level level, String message, |
| {String? error, String? loggerName, String? stackTrace}) { |
| if (level >= Level.INFO) { |
| logController.add('[$level] $loggerName: $message'); |
| } |
| } |
| |
| configureLogWriter(true, customLogWriter: logWriter); |
| dataDir = Directory.systemTemp.createTempSync(_userDataDirName); |
| }); |
| |
| tearDown(() async { |
| final tabs = await chrome?.chromeConnection.getTabs(); |
| if (tabs != null) { |
| for (final tab in tabs) { |
| await closeTab(tab); |
| } |
| } |
| await chrome?.close(); |
| chrome = null; |
| |
| // Issue: https://github.com/dart-lang/webdev/issues/1545 |
| if (!Platform.isWindows) { |
| expect( |
| logStream, |
| emitsThrough(matches('Starting chrome with user data directory:' |
| '.*chrome_user_data_copy'))); |
| await logController.close(); |
| } |
| dataDir.deleteSync(recursive: true); |
| }); |
| |
| test('works with debug port', () async { |
| await launchChrome(userDataDir: dataDir.path); |
| expect(chrome, isNotNull); |
| }); |
| |
| test('has a working debugger', () async { |
| await launchChrome(userDataDir: dataDir.path); |
| |
| final tabs = await chrome!.chromeConnection.getTabs(); |
| expect( |
| tabs, |
| contains(const TypeMatcher<ChromeTab>() |
| .having((t) => t.url, 'url', _googleUrl))); |
| }); |
| |
| test('has correct profile path', () async { |
| await launchChrome(userDataDir: dataDir.path); |
| await openTab(_chromeVersionUrl); |
| |
| final wipConnection = await connectToTab(_chromeVersionUrl); |
| final result = await _evaluateExpression(wipConnection.page, |
| "document.getElementById('profile_path').textContent"); |
| |
| if (Platform.isWindows) { |
| // --user-data-dir is not supported on Windows yet |
| // Issue: https://github.com/dart-lang/webdev/issues/1545 |
| expect(result, isNot(contains('chrome_user_data_copy'))); |
| } else { |
| expect(result, contains('chrome_user_data_copy')); |
| } |
| }, skip: 'https://github.com/dart-lang/webdev/issues/2030'); |
| |
| test('can auto detect default chrome directory', () async { |
| final userDataDir = autoDetectChromeUserDataDirectory(); |
| expect(userDataDir, isNotNull); |
| |
| expect(Directory(userDataDir!).existsSync(), isTrue); |
| |
| await launchChrome(userDataDir: userDataDir); |
| await openTab(_chromeVersionUrl); |
| |
| final wipConnection = await connectToTab(_chromeVersionUrl); |
| final result = await _evaluateExpression(wipConnection.page, |
| "document.getElementById('profile_path').textContent"); |
| |
| expect(result, contains('chrome_user_data_copy')); |
| }, onPlatform: { |
| 'windows': const Skip('https://github.com/dart-lang/webdev/issues/1545') |
| }, skip: 'https://github.com/dart-lang/webdev/issues/2030'); |
| |
| test('cannot auto detect default chrome directory on windows', () async { |
| final userDataDir = autoDetectChromeUserDataDirectory(); |
| expect(userDataDir, isNull); |
| }, onPlatform: { |
| 'linux': const Skip('https://github.com/dart-lang/webdev/issues/1545'), |
| 'mac-os': const Skip('https://github.com/dart-lang/webdev/issues/1545'), |
| }); |
| }); |
| } |
| |
| String _openTabUrl(String url) => '/json/new?$url'; |
| String _closeTabUrl(String id) => '/json/close/$id'; |
| |
| Future<String> _evaluateExpression(WipPage page, String expression) async { |
| String? result = ''; |
| while (result == null || result.isEmpty) { |
| await Future.delayed(const Duration(milliseconds: 100)); |
| final wipResponse = await page.sendCommand( |
| 'Runtime.evaluate', |
| params: {'expression': expression}, |
| ); |
| result = wipResponse.json['result']['result']['value'] as String?; |
| } |
| return result; |
| } |
| |
| const _googleUrl = 'https://www.google.com/'; |
| const _chromeVersionUrl = 'chrome://version/'; |
| const _userDataDirName = 'data dir'; |