Skip to content
This repository was archived by the owner on Oct 28, 2024. It is now read-only.

Allow signing into default profile and enabling extensions #29

Merged
merged 6 commits into from
Jan 21, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
## 1.0.1-dev
## 1.1.0-dev

- Add optional `signIn` argument to `startWithDebugPort`.
To be used together with `user-data-dir` to start a chrome
window signed into the default profile with extensions enabled.

## 1.0.0

Expand Down
15 changes: 13 additions & 2 deletions lib/src/chrome.dart
Original file line number Diff line number Diff line change
Expand Up @@ -65,14 +65,25 @@ class Chrome {
/// Starts Chrome with the given arguments and a specific port.
///
/// Each url in [urls] will be loaded in a separate tab.
///
/// If [userDataDir] is `null`, a new temp directory will be
/// passed to chrome as a user data directory. Chrome will
/// start without sign in and with extensions disabled.
///
/// If [userDataDir] is not `null`, it will be passed to chrome
/// as a user data directory. Chrome will start signed into
/// the default profile with extensions enabled if [signIn]
/// is also true.
static Future<Chrome> startWithDebugPort(
List<String> urls, {
int debugPort = 0,
bool headless = false,
String? userDataDir,
bool signIn = false,
}) async {
Directory dataDir;
if (userDataDir == null) {
signIn = false;
dataDir = Directory.systemTemp.createTempSync();
} else {
dataDir = Directory(userDataDir);
Expand All @@ -87,9 +98,9 @@ class Chrome {
'--disable-background-timer-throttling',
// Since we are using a temp profile, disable features that slow the
// Chrome launch.
'--disable-extensions',
if (!signIn) '--disable-extensions',
'--disable-popup-blocking',
'--bwsi',
if (!signIn) '--bwsi',
'--no-first-run',
'--no-default-browser-check',
'--disable-default-apps',
Expand Down
2 changes: 1 addition & 1 deletion pubspec.yaml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name: browser_launcher
description: Provides a standardized way to launch web browsers for testing and tools.

version: 1.0.1-dev
version: 1.1.0-dev

homepage: https://github.com/dart-lang/browser_launcher

Expand Down
148 changes: 119 additions & 29 deletions test/chrome_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

@OnPlatform({'windows': Skip('appveyor is not setup to install Chrome')})
import 'dart:async';
import 'dart:io';

import 'package:browser_launcher/src/chrome.dart';
import 'package:test/test.dart';
Expand All @@ -12,48 +13,137 @@ import 'package:webkit_inspection_protocol/webkit_inspection_protocol.dart';
void main() {
Chrome? chrome;

Future<void> launchChromeWithDebugPort({int port = 0}) async {
chrome = await Chrome.startWithDebugPort([_googleUrl], debugPort: port);
Future<WipConnection> connectToTab(String url) async {
var tab = await chrome!.chromeConnection.getTab((t) => t.url.contains(url));
expect(tab, isNotNull);
return tab!.connect();
}

Future<void> openTab(String url) async {
await chrome!.chromeConnection.getUrl(_openTabUrl(url));
}

Future<void> launchChromeWithDebugPort(
{int port = 0, String? userDataDir, bool signIn = false}) async {
chrome = await Chrome.startWithDebugPort([_googleUrl],
debugPort: port, userDataDir: userDataDir, signIn: signIn);
}

Future<void> launchChrome() async {
await Chrome.start([_googleUrl]);
}

tearDown(() async {
await chrome?.close();
chrome = null;
});
group('chrome with temp data dir', () {
tearDown(() async {
await chrome?.close();
chrome = null;
});

test('can launch chrome', () async {
await launchChrome();
expect(chrome, isNull);
});
test('can launch chrome', () async {
await launchChrome();
expect(chrome, isNull);
});

test('can launch chrome with debug port', () async {
await launchChromeWithDebugPort();
expect(chrome, isNotNull);
});
test('can launch chrome with debug port', () async {
await launchChromeWithDebugPort();
expect(chrome, isNotNull);
});

test('debugger is working', () async {
await launchChromeWithDebugPort();
var tabs = await chrome!.chromeConnection.getTabs();
expect(
tabs,
contains(const TypeMatcher<ChromeTab>()
.having((t) => t.url, 'url', _googleUrl)));
});
test('has a working debugger', () async {
await launchChromeWithDebugPort();
var 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 launchChromeWithDebugPort(port: 0);
expect(chrome!.debugPort, isNot(equals(0)));
});

test('uses open debug port if provided port is 0', () async {
await launchChromeWithDebugPort(port: 0);
expect(chrome!.debugPort, isNot(equals(0)));
test('can provide a specific debug port', () async {
var port = await findUnusedPort();
await launchChromeWithDebugPort(port: port);
expect(chrome!.debugPort, port);
});
});

test('can provide a specific debug port', () async {
var port = await findUnusedPort();
await launchChromeWithDebugPort(port: port);
expect(chrome!.debugPort, port);
group('chrome with user data dir', () {
late Directory dataDir;

for (var signIn in [false, true]) {
group('and signIn = $signIn', () {
setUp(() {
dataDir = Directory.systemTemp.createTempSync(_userDataDirName);
});

tearDown(() async {
await chrome?.close();
chrome = null;

var attempts = 0;
while (true) {
try {
attempts++;
await Future.delayed(const Duration(milliseconds: 100));
dataDir.deleteSync(recursive: true);
break;
} catch (_) {
if (attempts > 3) rethrow;
}
}
});

test('can launch with debug port', () async {
await launchChromeWithDebugPort(
userDataDir: dataDir.path, signIn: signIn);
expect(chrome, isNotNull);
});

test('has a working debugger', () async {
await launchChromeWithDebugPort(
userDataDir: dataDir.path, signIn: signIn);
var tabs = await chrome!.chromeConnection.getTabs();
expect(
tabs,
contains(const TypeMatcher<ChromeTab>()
.having((t) => t.url, 'url', _googleUrl)));
});

test('has correct profile path', () async {
await launchChromeWithDebugPort(
userDataDir: dataDir.path, signIn: signIn);
await openTab(_chromeVersionUrl);

var wipConnection = await connectToTab(_chromeVersionUrl);
var result = await _evaluateExpression(wipConnection.page,
"document.getElementById('profile_path').textContent");

expect(result, contains(_userDataDirName));
});
});
}
});
}

String _openTabUrl(String url) => '/json/new?$url';

Future<String> _evaluateExpression(WipPage page, String expression) async {
var result = '';
while (result.isEmpty) {
await Future.delayed(Duration(milliseconds: 100));
var wipResponse = await page.sendCommand(
'Runtime.evaluate',
params: {'expression': expression},
);
var value = wipResponse.json['result']['result']['value'];
result = (value != null && value is String) ? value : '';
}
return result;
}

const _googleUrl = 'https://www.google.com/';
const _chromeVersionUrl = 'chrome://version/';
const _userDataDirName = 'data dir';