diff --git a/dwds/pubspec.yaml b/dwds/pubspec.yaml index 5e81d22f1..b26b45cf8 100644 --- a/dwds/pubspec.yaml +++ b/dwds/pubspec.yaml @@ -52,7 +52,7 @@ dev_dependencies: js: ^0.6.4 lints: ^2.0.0 pubspec_parse: ^1.2.0 - puppeteer: ^2.17.0 + puppeteer: ^2.18.0 stream_channel: ^2.1.0 test: ^1.21.1 webdriver: ^3.0.0 diff --git a/dwds/test/puppeteer/extension_test.dart b/dwds/test/puppeteer/extension_test.dart index 6985fa0df..9ed7b55a3 100644 --- a/dwds/test/puppeteer/extension_test.dart +++ b/dwds/test/puppeteer/extension_test.dart @@ -23,12 +23,8 @@ import 'test_utils.dart'; final context = TestContext(); -// Note: The following delay is required to reduce flakiness. It makes -// sure the service worker execution context is ready. -const executionContextDelay = 1; - void main() async { - late Target serviceWorkerTarget; + late Worker worker; late Browser browser; late String extensionPath; @@ -58,13 +54,13 @@ void main() async { ], ); - serviceWorkerTarget = await browser + final serviceWorkerTarget = await browser .waitForTarget((target) => target.type == 'service_worker'); + worker = (await serviceWorkerTarget.worker)!; }); tearDown(() async { - final worker = (await serviceWorkerTarget.worker)!; - await Future.delayed(Duration(seconds: executionContextDelay)); + await workerEvalDelay(); await worker.evaluate(_clearStorageJs()); }); @@ -78,17 +74,15 @@ void main() async { // Navigate to the Dart app: final appTab = await navigateToPage(browser, url: appUrl, isNew: true); - final worker = (await serviceWorkerTarget.worker)!; - await Future.delayed(Duration(seconds: executionContextDelay)); // Verify that we have debug info for the Dart app: - final tabIdForAppJs = _tabIdForTabJs(appUrl); - final appTabId = (await worker.evaluate(tabIdForAppJs)) as int; + await workerEvalDelay(); + final appTabId = await _getTabId(appUrl, worker: worker); final debugInfoKey = '$appTabId-debugInfo'; - final storageObj = await worker.evaluate( - _fetchStorageObjJs(debugInfoKey, storageArea: 'session')); - final json = storageObj[debugInfoKey]; - final debugInfo = - serializers.deserialize(jsonDecode(json)) as DebugInfo; + final debugInfo = await _fetchStorageObj( + debugInfoKey, + storageArea: 'session', + worker: worker, + ); expect(debugInfo.appId, isNotNull); expect(debugInfo.appEntrypointPath, isNotNull); expect(debugInfo.appInstanceId, isNotNull); @@ -116,12 +110,11 @@ void main() async { // Close the settings tab: await settingsTab.close(); // Check that is has been saved in local storage: - final worker = (await serviceWorkerTarget.worker)!; - final storageObj = await worker.evaluate( - _fetchStorageObjJs('devToolsOpener', storageArea: 'local')); - final json = storageObj['devToolsOpener']; - final devToolsOpener = - serializers.deserialize(jsonDecode(json)) as DevToolsOpener; + final devToolsOpener = await _fetchStorageObj( + 'devToolsOpener', + storageArea: 'local', + worker: worker, + ); expect(devToolsOpener.newWindow, isTrue); }); @@ -131,22 +124,21 @@ void main() async { final appUrl = context.appUrl; final devToolsUrlFragment = useSse ? 'debugger?uri=sse' : 'debugger?uri=ws'; - final windowIdForAppJs = _windowIdForTabJs(appUrl); // Navigate to the Dart app: final appTab = await navigateToPage(browser, url: appUrl, isNew: true); // Click on the Dart Debug Extension icon: - final worker = (await serviceWorkerTarget.worker)!; - await Future.delayed(Duration(seconds: executionContextDelay)); - await worker.evaluate(clickIconJs); + await workerEvalDelay(); + await clickOnExtensionIcon(worker); // Verify the extension opened the Dart docs in the same window: var devToolsTabTarget = await browser.waitForTarget( (target) => target.url.contains(devToolsUrlFragment)); final devToolsPage = await devToolsTabTarget.page; - final windowIdForDevToolsJs = _windowIdForTabJs(devToolsPage.url!); - var devToolsWindowId = - (await worker.evaluate(windowIdForDevToolsJs)) as int?; - var appWindowId = (await worker.evaluate(windowIdForAppJs)) as int?; + var devToolsWindowId = await _getWindowId( + devToolsPage.url!, + worker: worker, + ); + var appWindowId = await _getWindowId(appUrl, worker: worker); expect(devToolsWindowId == appWindowId, isTrue); // Close the DevTools tab: var devToolsTab = await devToolsTabTarget.page; @@ -168,13 +160,15 @@ void main() async { // Navigate to the Dart app: await navigateToPage(browser, url: appUrl); // Click on the Dart Debug Extension icon: - await worker.evaluate(clickIconJs); + await clickOnExtensionIcon(worker); // Verify the extension opened DevTools in a different window: devToolsTabTarget = await browser.waitForTarget( (target) => target.url.contains(devToolsUrlFragment)); - devToolsWindowId = - (await worker.evaluate(windowIdForDevToolsJs)) as int?; - appWindowId = (await worker.evaluate(windowIdForAppJs)) as int?; + devToolsWindowId = await _getWindowId( + devToolsPage.url!, + worker: worker, + ); + appWindowId = await _getWindowId(appUrl, worker: worker); expect(devToolsWindowId == appWindowId, isFalse); // Close the DevTools tab: devToolsTab = await devToolsTabTarget.page; @@ -186,6 +180,35 @@ void main() async { }); } +Future _getTabId( + String url, { + required Worker worker, +}) async { + final jsExpression = _tabIdForTabJs(url); + return (await worker.evaluate(jsExpression)) as int; +} + +Future _getWindowId( + String url, { + required Worker worker, +}) async { + final jsExpression = _windowIdForTabJs(url); + return (await worker.evaluate(jsExpression)) as int?; +} + +Future _fetchStorageObj( + String storageKey, { + required String storageArea, + required Worker worker, +}) async { + final storageObj = await worker.evaluate(_fetchStorageObjJs( + storageKey, + storageArea: storageArea, + )); + final json = storageObj[storageKey]; + return serializers.deserialize(jsonDecode(json)) as T; +} + String _tabIdForTabJs(String tabUrl) { return ''' async () => { diff --git a/dwds/test/puppeteer/lifeline_test.dart b/dwds/test/puppeteer/lifeline_test.dart index b179a8704..aed47d747 100644 --- a/dwds/test/puppeteer/lifeline_test.dart +++ b/dwds/test/puppeteer/lifeline_test.dart @@ -2,7 +2,7 @@ // 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: 10)) +@Timeout(Duration(minutes: 12)) @Skip('https://github.com/dart-lang/webdev/issues/1788') import 'dart:async'; @@ -15,7 +15,7 @@ import 'test_utils.dart'; final context = TestContext(); void main() async { - late Target serviceWorkerTarget; + late Worker worker; late Browser browser; late String extensionPath; @@ -38,8 +38,9 @@ void main() async { ], ); - serviceWorkerTarget = await browser + final serviceWorkerTarget = await browser .waitForTarget((target) => target.type == 'service_worker'); + worker = (await serviceWorkerTarget.worker)!; }); tearDownAll(() async { @@ -50,14 +51,10 @@ void main() async { // Navigate to the Dart app: final appTab = await navigateToPage(browser, url: context.appUrl, isNew: true); - // Click on the Dart Debug Extension icon: - final worker = (await serviceWorkerTarget.worker)!; - // Note: The following delay is required to reduce flakiness (it makes - // sure the execution context is ready): - await Future.delayed(Duration(seconds: 1)); + await workerEvalDelay(); // Initiate listeners for the port connection event and the subsequent // reconnection logs: - final portConnectionPromise = worker.evaluate(_portConnectionJs); + final portConnectionFuture = _connectToPort(worker); appTab.onConsole.listen((ConsoleMessage message) { final messageText = message.text ?? ''; if (messageText @@ -66,19 +63,28 @@ void main() async { } }); // Click on the Dart Debug Extension icon to intiate a debug session: - await worker.evaluate(clickIconJs); - final connectedToPort = await portConnectionPromise; + await clickOnExtensionIcon(worker); + final connectedToPort = await portConnectionFuture; // Verify that we have connected to the port: expect(connectedToPort, isTrue); expect(connectionCount, equals(1)); // Wait for a little over 5 minutes, and verify that we have reconnected // to the port again: - await Future.delayed(Duration(minutes: 5) + Duration(seconds: 15)); + await _reconnectToPortDelay(); expect(connectionCount, equals(2)); }); }); } +Future _reconnectToPortDelay() async { + await Future.delayed(Duration(minutes: 5) + Duration(seconds: 15)); + return; +} + +Future _connectToPort(Worker worker) async { + return worker.evaluate(_portConnectionJs); +} + final _portConnectionJs = ''' async () => { return new Promise((resolve, reject) => { diff --git a/dwds/test/puppeteer/test_utils.dart b/dwds/test/puppeteer/test_utils.dart index 567aee1b9..7d8c046b1 100644 --- a/dwds/test/puppeteer/test_utils.dart +++ b/dwds/test/puppeteer/test_utils.dart @@ -24,6 +24,17 @@ Future buildDebugExtension() async { return '$extensionDir/compiled'; } +Future clickOnExtensionIcon(Worker worker) async { + return worker.evaluate(_clickIconJs); +} + +// Note: The following delay is required to reduce flakiness. It makes +// sure the service worker execution context is ready. +Future workerEvalDelay() async { + await Future.delayed(Duration(seconds: 1)); + return; +} + Future navigateToPage( Browser browser, { required String url, @@ -60,7 +71,7 @@ Future _getPageForUrl(Browser browser, {required String url}) { return pageTarget.page; } -final clickIconJs = ''' +final _clickIconJs = ''' async () => { const activeTabs = await chrome.tabs.query({ active: true }); const tab = activeTabs[0];