diff --git a/pkg/pub_integration/lib/src/pub_puppeteer_helpers.dart b/pkg/pub_integration/lib/src/pub_puppeteer_helpers.dart index 556a1e63a5..45849a9378 100644 --- a/pkg/pub_integration/lib/src/pub_puppeteer_helpers.dart +++ b/pkg/pub_integration/lib/src/pub_puppeteer_helpers.dart @@ -2,6 +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. import 'dart:async'; +import 'dart:io'; import 'package:puppeteer/puppeteer.dart'; @@ -45,6 +46,10 @@ Future listingPageInfo(Page page) async { } extension PubPageExt on Page { + Future saveScreenshot(String path) async { + await File(path).writeAsBytes(await screenshot()); + } + Future waitFocusAndType(String selector, String text) async { await waitForSelector(selector, timeout: Duration(seconds: 5)); await focus(selector); @@ -187,6 +192,39 @@ extension PubPageExt on Page { await _waitForModelHidden(); } + /// Waits until the given selectors are visible and their UI top-left position + /// differs. + Future waitForLayout( + List selectors, { + Duration timeout = const Duration(seconds: 5), + }) async { + final sw = Stopwatch()..start(); + final handles = await Future.wait( + selectors.map((e) => waitForSelector(e, timeout: timeout))); + while (sw.elapsed < timeout) { + final positions = + await Future.wait(handles.map((e) async => (await e!.boundingBox)!)); + bool hasSamePosition = false; + for (var i = 0; i < positions.length; i++) { + for (var j = i + 1; j < positions.length; j++) { + if (positions[i].topLeft == positions[j].topLeft) { + hasSamePosition = true; + break; + } + } + if (hasSamePosition) break; + } + if (hasSamePosition) { + await Future.delayed(Duration(milliseconds: 25)); + continue; + } else { + return; + } + } + await saveScreenshot('layout-timeout.png'); + throw TimeoutException('Did not have a stable layout in $timeout.'); + } + Future waitAndClick( String selector, { bool? waitForOneResponse, diff --git a/pkg/pub_integration/pubspec.lock b/pkg/pub_integration/pubspec.lock index f0d9c42ca2..0e38991d12 100644 --- a/pkg/pub_integration/pubspec.lock +++ b/pkg/pub_integration/pubspec.lock @@ -91,10 +91,10 @@ packages: dependency: transitive description: name: built_value - sha256: "723b4021e903217dfc445ec4cf5b42e27975aece1fc4ebbc1ca6329c2d9fb54e" + sha256: "69acb7007eb2a31dc901512bfe0f7b767168be34cb734835d54c070bfa74c1b2" url: "https://pub.dev" source: hosted - version: "8.7.0" + version: "8.8.0" checked_yaml: dependency: transitive description: @@ -107,10 +107,10 @@ packages: dependency: transitive description: name: code_builder - sha256: "1be9be30396d7e4c0db42c35ea6ccd7cc6a1e19916b5dc64d6ac216b5544d677" + sha256: b2151ce26a06171005b379ecff6e08d34c470180ffe16b8e14b6d52be292b55f url: "https://pub.dev" source: hosted - version: "4.7.0" + version: "4.8.0" collection: dependency: transitive description: @@ -155,10 +155,10 @@ packages: dependency: transitive description: name: dart_style - sha256: abd7625e16f51f554ea244d090292945ec4d4be7bfbaf2ec8cccea568919d334 + sha256: "40ae61a5d43feea6d24bd22c0537a6629db858963b99b4bc1c3db80676f32368" url: "https://pub.dev" source: hosted - version: "2.3.3" + version: "2.3.4" file: dependency: transitive description: @@ -203,10 +203,10 @@ packages: dependency: "direct main" description: name: http - sha256: "759d1a329847dd0f39226c688d3e06a6b8679668e350e2891a6474f8b4bb8525" + sha256: d4872660c46d929f6b8a9ef4e7a7eff7e49bbf0c4ec3f385ee32df5119175139 url: "https://pub.dev" source: hosted - version: "1.1.0" + version: "1.1.2" http_methods: dependency: transitive description: @@ -323,10 +323,10 @@ packages: dependency: transitive description: name: petitparser - sha256: cb3798bef7fc021ac45b308f4b51208a152792445cce0448c9a4ba5879dd8750 + sha256: eeb2d1428ee7f4170e2bd498827296a18d4e7fc462b71727d111c0ac7707cfa6 url: "https://pub.dev" source: hosted - version: "5.4.0" + version: "6.0.1" pointycastle: dependency: transitive description: @@ -363,10 +363,10 @@ packages: dependency: "direct main" description: name: puppeteer - sha256: dd49117259867d0ce0de33ddd95628fb70cff94581a6432c08272447b8dd1d27 + sha256: eedeaae6ec5d2e54f9ae22ab4d6b3dda2e8791c356cc783046d06c287ffe11d8 url: "https://pub.dev" source: hosted - version: "2.24.0" + version: "3.6.0" sanitize_html: dependency: transitive description: @@ -543,6 +543,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.1.0" + web: + dependency: transitive + description: + name: web + sha256: edc8a9573dd8c5a83a183dae1af2b6fd4131377404706ca4e5420474784906fa + url: "https://pub.dev" + source: hosted + version: "0.4.0" web_socket_channel: dependency: transitive description: @@ -568,4 +576,4 @@ packages: source: hosted version: "3.1.2" sdks: - dart: ">=3.0.0 <4.0.0" + dart: ">=3.2.0 <4.0.0" diff --git a/pkg/pub_integration/pubspec.yaml b/pkg/pub_integration/pubspec.yaml index 99c415c9e7..51f10c8a5e 100644 --- a/pkg/pub_integration/pubspec.yaml +++ b/pkg/pub_integration/pubspec.yaml @@ -12,12 +12,9 @@ dependencies: http: ^1.0.0 path: ^1.8.0 pub_semver: ^2.0.0 - puppeteer: ^2.24.0 + puppeteer: ^3.6.0 oauth2: ^2.0.0 dev_dependencies: coverage: any # test already depends on it test: ^1.16.5 - -dependency_overrides: - http: ^1.0.0 diff --git a/pkg/pub_integration/test/pkg_admin_page_test.dart b/pkg/pub_integration/test/pkg_admin_page_test.dart index d1adb36bed..8c50f536a6 100644 --- a/pkg/pub_integration/test/pkg_admin_page_test.dart +++ b/pkg/pub_integration/test/pkg_admin_page_test.dart @@ -49,6 +49,10 @@ void main() { await page.gotoOrigin('/packages/test_pkg/admin'); await page.waitAndClick('#-pkg-admin-automated-github-enabled'); + await page.waitForLayout([ + '#-pkg-admin-automated-github-repository', + '#-pkg-admin-automated-github-tagpattern', + ]); await page.waitFocusAndType( '#-pkg-admin-automated-github-repository', 'dart-lang/pub-dev'); await page.waitAndClick('#-pkg-admin-automated-button', diff --git a/pkg/pub_integration/test/search_update_test.dart b/pkg/pub_integration/test/search_update_test.dart index 937aaf6f10..8a5ce5d5a5 100644 --- a/pkg/pub_integration/test/search_update_test.dart +++ b/pkg/pub_integration/test/search_update_test.dart @@ -160,7 +160,11 @@ void main() { // show hidden await page.click('.search-form-section[data-section-tag="advanced"]'); - await page.waitAndClick('#search-form-checkbox-show-unlisted'); + await page.waitForLayout([ + '#search-form-checkbox-is-flutter-favorite', + '#search-form-checkbox-show-unlisted' + ]); + await page.click('#search-form-checkbox-show-unlisted'); await page.waitForNavigation(wait: Until.networkIdle); final i7 = await listingPageInfo(page); expect(i7.totalCount, i6.totalCount);