blob: b7e1ddf1b9fbc4e5b0f6abaad1267e0c21dfb9ea [file] [log] [blame] [edit]
// 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(minutes: 5))
@TestOn('vm')
import 'dart:io';
import 'package:test/test.dart';
import 'package:test_common/test_sdk_configuration.dart';
import 'package:vm_service/vm_service.dart';
// ignore: deprecated_member_use
import 'package:webdriver/io.dart';
import 'fixtures/context.dart';
import 'fixtures/project.dart';
import 'fixtures/utilities.dart';
Future<void> _waitForPageReady(TestContext context) async {
var attempt = 100;
while (attempt-- > 0) {
final content = await context.webDriver.pageSource;
if (content.contains('hello_world')) return;
await Future.delayed(const Duration(milliseconds: 100));
}
throw StateError('Page never initialized');
}
void main() {
final provider = TestSdkConfigurationProvider();
tearDownAll(provider.dispose);
final context = TestContext(TestProject.testWithSoundNullSafety, provider);
group('Injected client', () {
setUp(() async {
await context.setUp(
debugSettings: TestDebugSettings.withDevTools(context),
);
await context.webDriver.driver.keyboard.sendChord([Keyboard.alt, 'd']);
// Wait for DevTools to actually open.
await Future.delayed(const Duration(seconds: 2));
});
tearDown(() async {
await context.tearDown();
});
test(
'can launch devtools',
() async {
final windows = await context.webDriver.windows.toList();
await context.webDriver.driver.switchTo.window(windows.last);
expect(await context.webDriver.pageSource, contains('DevTools'));
expect(await context.webDriver.currentUrl, contains('ide=Dwds'));
// TODO(https://github.com/dart-lang/webdev/issues/1888): Re-enable.
},
skip: Platform.isWindows,
);
test('can not launch devtools for the same app in multiple tabs', () async {
final appUrl = await context.webDriver.currentUrl;
// Open a new tab, select it, and navigate to the app
await context.webDriver.driver
.execute("window.open('$appUrl', '_blank');", []);
await Future.delayed(const Duration(seconds: 2));
final newAppWindow = await context.webDriver.windows.last;
await newAppWindow.setAsActive();
// Wait for the page to be ready before trying to open DevTools again.
await _waitForPageReady(context);
// Try to open devtools and check for the alert.
await context.webDriver.driver.keyboard.sendChord([Keyboard.alt, 'd']);
await Future.delayed(const Duration(seconds: 2));
final alert = context.webDriver.driver.switchTo.alert;
expect(alert, isNotNull);
expect(
await alert.text,
contains('This app is already being debugged in a different tab'),
);
await alert.accept();
var windows = await context.webDriver.windows.toList();
for (final window in windows) {
if (window.id != newAppWindow.id) {
await window.setAsActive();
await window.close();
}
}
await newAppWindow.setAsActive();
await context.webDriver.driver.keyboard.sendChord([Keyboard.alt, 'd']);
await Future.delayed(const Duration(seconds: 2));
windows = await context.webDriver.windows.toList();
final devToolsWindow =
windows.firstWhere((window) => window != newAppWindow);
await devToolsWindow.setAsActive();
expect(await context.webDriver.pageSource, contains('DevTools'));
});
test(
'destroys and recreates the isolate during a page refresh',
() async {
// This test is the same as one in reload_test, but runs here when there
// is a connected client (DevTools) since it can behave differently.
// https://github.com/dart-lang/webdev/pull/901#issuecomment-586438132
final client = context.debugConnection.vmService;
await client.streamListen('Isolate');
context.makeEditToDartEntryFile(
toReplace: 'Hello World!',
replaceWith: 'Bonjour le monde!',
);
await context.waitForSuccessfulBuild(propagateToBrowser: true);
final eventsDone = expectLater(
client.onIsolateEvent,
emitsThrough(
emitsInOrder([
_hasKind(EventKind.kIsolateExit),
_hasKind(EventKind.kIsolateStart),
_hasKind(EventKind.kIsolateRunnable),
]),
),
);
await context.webDriver.driver.refresh();
await eventsDone;
// Re-set the edited file:
context.makeEditToDartEntryFile(
toReplace: 'Bonjour le monde!',
replaceWith: 'Hello World!',
);
},
skip: 'https://github.com/dart-lang/webdev/issues/1888',
);
});
group('Injected client without a DevTools server', () {
setUp(() async {
await context.setUp(
debugSettings: TestDebugSettings.noDevTools().copyWith(
enableDevToolsLaunch: true,
),
);
});
tearDown(() async {
await context.tearDown();
});
test('gives a good error if devtools is not served', () async {
// Try to open devtools and check for the alert.
await context.webDriver.driver.keyboard.sendChord([Keyboard.alt, 'd']);
await Future.delayed(const Duration(seconds: 2));
final alert = context.webDriver.driver.switchTo.alert;
expect(alert, isNotNull);
expect(await alert.text, contains('--debug'));
await alert.accept();
});
});
group(
'Injected client with debug extension and without DevTools',
() {
setUp(() async {
await context.setUp(
debugSettings: TestDebugSettings.noDevTools()
.copyWith(enableDebugExtension: true),
);
});
tearDown(() async {
await context.tearDown();
});
test('gives a good error if devtools is not served', () async {
// Click on extension
await context.extensionConnection.sendCommand('Runtime.evaluate', {
'expression': 'fakeClick()',
});
// Try to open devtools and check for the alert.
await context.webDriver.driver.keyboard.sendChord([Keyboard.alt, 'd']);
await Future.delayed(const Duration(seconds: 2));
final alert = context.webDriver.driver.switchTo.alert;
expect(alert, isNotNull);
expect(await alert.text, contains('--debug'));
await alert.accept();
});
// TODO(https://github.com/dart-lang/webdev/issues/1724): Re-enable debug
// extension tests on Windows.
},
tags: ['extension'],
skip: 'https://github.com/dart-lang/webdev/issues/2114',
);
}
TypeMatcher<Event> _hasKind(String kind) =>
isA<Event>().having((e) => e.kind, 'kind', kind);