diff --git a/dev/integration_tests/web_e2e_tests/lib/image_loading_main.dart b/dev/integration_tests/web_e2e_tests/lib/image_loading_main.dart index 16a624be4d..a0cced1a3e 100644 --- a/dev/integration_tests/web_e2e_tests/lib/image_loading_main.dart +++ b/dev/integration_tests/web_e2e_tests/lib/image_loading_main.dart @@ -2,9 +2,20 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +import 'dart:async'; + import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; +final Completer _assetImageCompleter = Completer(); +final Completer _networkImageCompleter = Completer(); + +/// Notifies that Image.asset used in the test app loaded the image. +Future get whenAssetImageLoads => _assetImageCompleter.future; + +/// Notifies that Image.network used in the test app loaded the image. +Future get whenNetworkImageLoads => _networkImageCompleter.future; + Future main() async { WidgetsFlutterBinding.ensureInitialized(); const MethodChannel channel = @@ -30,9 +41,36 @@ class MyAppState extends State { title: 'Integration Test App', home: Column(children: [ const Text('Asset image:'), - RepaintBoundary(child: Image.asset('assets/icons/material/material.png', package: 'flutter_gallery_assets')), + RepaintBoundary(child: Image.asset( + 'assets/icons/material/material.png', + package: 'flutter_gallery_assets', + frameBuilder: ( + BuildContext context, + Widget child, + int? frame, + bool wasSynchronouslyLoaded, + ) { + if (frame != null) { + _assetImageCompleter.complete(); + } + return child; + }, + )), const Text('Network image:'), - RepaintBoundary(child: Image.network('assets/packages/flutter_gallery_assets/assets/icons/material/material.png')), + RepaintBoundary(child: Image.network( + 'assets/packages/flutter_gallery_assets/assets/icons/material/material.png', + frameBuilder: ( + BuildContext context, + Widget child, + int? frame, + bool wasSynchronouslyLoaded, + ) { + if (frame != null) { + _networkImageCompleter.complete(); + } + return child; + }, + )), ]) ); } diff --git a/dev/integration_tests/web_e2e_tests/test_driver/image_loading_integration.dart b/dev/integration_tests/web_e2e_tests/test_driver/image_loading_integration.dart index 00a73ef47c..d81d18c75c 100644 --- a/dev/integration_tests/web_e2e_tests/test_driver/image_loading_integration.dart +++ b/dev/integration_tests/web_e2e_tests/test_driver/image_loading_integration.dart @@ -15,6 +15,17 @@ void main() { (WidgetTester tester) async { await app.main(); await tester.pumpAndSettle(); + + // `pumpAndSettle` only waits until no more frames are scheduled, but the + // test must wait for the image network requests to finish. + await app.whenAssetImageLoads; + await app.whenNetworkImageLoads; + + // At the time the network requests are finished the engine may not have + // updated the DOM yet. Delay checking the DOM until the next event, which + // will guarantee that the current frame is done rendering. + await Future.delayed(Duration.zero); + final List imageElements = findElements('img').cast(); expect(imageElements.length, 2); expect(imageElements[0].naturalWidth, 1.5 * 64);