From 7d056305adb5fee3cd9b1a91c7488fc90cf4fc1f Mon Sep 17 00:00:00 2001 From: Elliott Brooks <21270878+elliette@users.noreply.github.com> Date: Thu, 4 Sep 2025 15:19:23 -0700 Subject: [PATCH 1/5] Add test for compiler query param --- .../test_infra/run/run_test.dart | 122 ++++++++++++------ packages/devtools_app/pubspec.yaml | 1 + .../webdriver_test/web_compiler_test.dart | 86 ++++++++++++ .../lib/src/test/chrome_driver.dart | 4 +- .../devtools_test/lib/src/helpers/utils.dart | 18 +++ tool/lib/commands/serve.dart | 57 ++++---- 6 files changed, 220 insertions(+), 68 deletions(-) create mode 100644 packages/devtools_app/webdriver_test/web_compiler_test.dart diff --git a/packages/devtools_app/integration_test/test_infra/run/run_test.dart b/packages/devtools_app/integration_test/test_infra/run/run_test.dart index 5f7cba5846b..b4e3162e7f9 100644 --- a/packages/devtools_app/integration_test/test_infra/run/run_test.dart +++ b/packages/devtools_app/integration_test/test_infra/run/run_test.dart @@ -8,6 +8,7 @@ import 'dart:io'; import 'package:args/args.dart'; import 'package:devtools_shared/devtools_test_utils.dart'; +import 'package:path/path.dart' as p; import '_in_file_args.dart'; import '_test_app_driver.dart'; @@ -35,50 +36,10 @@ Future runFlutterIntegrationTest( // TODO(https://github.com/flutter/devtools/issues/9196): support starting // DTD and passing the URI to DevTools server. Workspace roots should be set // on the DTD instance based on the connected test app. - - // Start the DevTools server. This will use the DevTools server that is - // shipped with the Dart SDK. - // TODO(https://github.com/flutter/devtools/issues/9197): launch the - // DevTools server from source so that end to end changes (server + app) can - // be tested. - devToolsServerProcess = await Process.start('dart', [ - 'devtools', - // Do not launch DevTools app in the browser. This DevTools server - // instance will be used to connect to the DevTools app that is run from - // Flutter driver from the integration test runner. - '--no-launch-browser', - // Disable CORS restrictions so that we can connect to the server from - // DevTools app that is served on a different origin. - '--disable-cors', - ]); - - final addressCompleter = Completer(); - final sub = devToolsServerProcess.stdout.transform(utf8.decoder).listen(( - line, - ) { - if (line.startsWith(_devToolsServerAddressLine)) { - // This will pull the server address from a String like: - // "Serving DevTools at http://127.0.0.1:9104.". - final regexp = RegExp( - r'http:\/\/\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}:\d+', - ); - final match = regexp.firstMatch(line); - if (match != null) { - devToolsServerAddress = match.group(0); - addressCompleter.complete(); - } - } - }); - - await addressCompleter.future.timeout( - const Duration(seconds: 10), - onTimeout: () async { - await sub.cancel(); - devToolsServerProcess?.kill(); - throw Exception('Timed out waiting for DevTools server to start.'); - }, + devToolsServerProcess = await startDevToolsServer(); + devToolsServerAddress = await listenForDevToolsAddress( + devToolsServerProcess, ); - await sub.cancel(); } if (!offline) { @@ -195,3 +156,78 @@ class DevToolsAppTestRunnerArgs extends IntegrationTestRunnerArgs { ); } } + +Future startDevToolsServer({bool useLocalServer = false}) async { + // Start the DevTools server from source. + if (useLocalServer) { + return _startLocalDevToolsServer(); + } + + // Start the DevTools server. This will use the DevTools server that is + // shipped with the Dart SDK. + final devToolsServerProcess = await Process.start('dart', [ + 'devtools', + // Do not launch DevTools app in the browser. This DevTools server + // instance will be used to connect to the DevTools app that is run from + // Flutter driver from the integration test runner. + '--no-launch-browser', + // Disable CORS restrictions so that we can connect to the server from + // DevTools app that is served on a different origin. + '--disable-cors', + ]); + return devToolsServerProcess; +} + +Future listenForDevToolsAddress( + Process devToolsServerProcess, { + Duration timeout = const Duration(seconds: 10), +}) async { + final devToolsAddressCompleter = Completer(); + + final sub = devToolsServerProcess.stdout.transform(utf8.decoder).listen(( + line, + ) { + if (line.contains(_devToolsServerAddressLine)) { + // This will pull the server address from a String like: + // "Serving DevTools at http://127.0.0.1:9104.". + final regexp = RegExp(r'http:\/\/\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}:\d+'); + final match = regexp.firstMatch(line); + if (match != null) { + final devToolsServerAddress = match.group(0); + devToolsAddressCompleter.complete(devToolsServerAddress); + } + } + }); + + await devToolsAddressCompleter.future.timeout( + timeout, + onTimeout: () async { + await sub.cancel(); + devToolsServerProcess.kill(); + throw Exception('Timed out waiting for DevTools server to start.'); + }, + ); + await sub.cancel(); + + return devToolsAddressCompleter.future; +} + +Future _startLocalDevToolsServer() async { + final devtoolsProcess = await Process.start('dart', [ + 'run', + 'bin/dt.dart', + 'serve', + '--no-launch-browser', + ], workingDirectory: _toolPath()); + return devtoolsProcess; +} + +String _toolPath() { + final dir = Directory.current; + final pathParts = p.split(dir.path); + if (!pathParts.contains('packages')) { + throw StateError('Expected to be in a package, instead in ${dir.path}'); + } + final root = pathParts.sublist(0, pathParts.indexOf('packages')); + return p.joinAll([...root, 'tool']); +} diff --git a/packages/devtools_app/pubspec.yaml b/packages/devtools_app/pubspec.yaml index e82e795726e..7a74eaac6d0 100644 --- a/packages/devtools_app/pubspec.yaml +++ b/packages/devtools_app/pubspec.yaml @@ -77,6 +77,7 @@ dev_dependencies: stream_channel: ^2.1.1 test: ^1.21.0 web_benchmarks: ^4.0.0 + webdriver: ^3.1.0 webkit_inspection_protocol: ">=0.5.0 <2.0.0" dependency_overrides: diff --git a/packages/devtools_app/webdriver_test/web_compiler_test.dart b/packages/devtools_app/webdriver_test/web_compiler_test.dart new file mode 100644 index 00000000000..dcd2730a9d8 --- /dev/null +++ b/packages/devtools_app/webdriver_test/web_compiler_test.dart @@ -0,0 +1,86 @@ +// Copyright 2025 The Flutter Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file or at https://developers.google.com/open-source/licenses/bsd. + +@Timeout(Duration(minutes: 4)) +library; + +import 'dart:async'; +import 'dart:io'; + +import 'package:devtools_shared/devtools_test_utils.dart'; +import 'package:devtools_test/helpers.dart'; +import 'package:test/test.dart'; +import 'package:webdriver/async_io.dart'; + +import '../integration_test/test_infra/run/run_test.dart'; + +void main() { + late Process devtoolsProcess; + late WebDriver driver; + late String devToolsServerAddress; + + const serverStartupTimeout = Duration(minutes: 3); + + setUp(() async { + // Start ChromeDriver. + await ChromeDriver().start(debugLogging: true); + + // Start the DevTools server. + devtoolsProcess = await startDevToolsServer(useLocalServer: true); + devToolsServerAddress = await listenForDevToolsAddress( + devtoolsProcess, + timeout: serverStartupTimeout, + ); + + // Create a WebDriver instance. + driver = await createDriver( + uri: Uri.parse('http://127.0.0.1:${ChromeDriver.port}'), + desired: { + ...Capabilities.chrome, + Capabilities.chromeOptions: { + 'args': ['--headless'], + }, + }, + ); + }); + + tearDown(() async { + await driver.quit(); + devtoolsProcess.kill(); + }); + + Future getRendererAttribute() => retryUntilNotNull(() async { + final body = await driver.findElement(const By.tagName('body')); + return body.attributes['flt-renderer']; + }); + + group('compilation', () { + test('compiler query param determines skwasm/canvaskit renderer', () async { + // Open the DevTools URL with ?compiler=wasm. + await driver.get( + _addQueryParam(devToolsServerAddress, param: 'compiler', value: 'wasm'), + ); + // Verify we are using the skwasm renderer. + expect(await getRendererAttribute(), equals('skwasm')); + + // Open the DevTools URL with ?compiler=js. + await driver.get( + _addQueryParam(devToolsServerAddress, param: 'compiler', value: 'js'), + ); + // Verify we are using the canvaskit renderer. + expect(await getRendererAttribute(), equals('canvaskit')); + }, retry: 1); + }); +} + +String _addQueryParam( + String url, { + required String param, + required String value, +}) { + final uri = Uri.parse(url); + final newQueryParameters = Map.from(uri.queryParameters); + newQueryParameters[param] = value; + return uri.replace(queryParameters: newQueryParameters).toString(); +} diff --git a/packages/devtools_shared/lib/src/test/chrome_driver.dart b/packages/devtools_shared/lib/src/test/chrome_driver.dart index be78cc97985..21b4bba4749 100644 --- a/packages/devtools_shared/lib/src/test/chrome_driver.dart +++ b/packages/devtools_shared/lib/src/test/chrome_driver.dart @@ -9,6 +9,8 @@ import 'dart:io'; import 'io_utils.dart'; class ChromeDriver with IOMixin { + static const port = 4444; + Process? _process; // TODO(kenz): add error messaging if the chromedriver executable is not @@ -17,7 +19,7 @@ class ChromeDriver with IOMixin { Future start({bool debugLogging = false}) async { try { const chromedriverExe = 'chromedriver'; - const chromedriverArgs = ['--port=4444']; + const chromedriverArgs = ['--port=$port']; if (debugLogging) { print('${DateTime.now()}: starting the chromedriver process'); print('${DateTime.now()}: > $chromedriverExe ' diff --git a/packages/devtools_test/lib/src/helpers/utils.dart b/packages/devtools_test/lib/src/helpers/utils.dart index 2ff7fe58caf..c7a18b76c02 100644 --- a/packages/devtools_test/lib/src/helpers/utils.dart +++ b/packages/devtools_test/lib/src/helpers/utils.dart @@ -30,6 +30,7 @@ const includeForCustomerTestsTag = 'include-for-flutter-customer-tests'; /// since the library containing the test case is already excluded. const skipForCustomerTestsTag = 'skip-for-flutter-customer-tests'; +const extraShortPumpDuration = Duration(milliseconds: 250); const shortPumpDuration = Duration(seconds: 1); const safePumpDuration = Duration(seconds: 3); const longPumpDuration = Duration(seconds: 6); @@ -240,6 +241,23 @@ Future retryUntilFound( return retryUntilFound(finder, tester: tester, retries: retries - 1); } + +/// Retries the [callback] until the result is not null. +/// +/// This will retry the [callback] up to [retries] times, with an +/// [extraShortPumpDuration] delay between each attempt. +Future retryUntilNotNull( + Future Function() callback, { + int retries = 3, +}) async { + final result = await callback(); + if (retries == 0 || result != null) return result; + + await Future.delayed(extraShortPumpDuration); + return retryUntilNotNull(callback, retries: retries - 1); +} + + void logStatus(String message) { // ignore: avoid_print, intentional print for test output print('${DateTime.now()}: TEST STATUS: $message'); diff --git a/tool/lib/commands/serve.dart b/tool/lib/commands/serve.dart index 722229c36f3..54924444637 100644 --- a/tool/lib/commands/serve.dart +++ b/tool/lib/commands/serve.dart @@ -21,6 +21,7 @@ const _machineFlag = 'machine'; const _dtdUriFlag = 'dtd-uri'; const _dtdExposedUriFlag = 'dtd-exposed-uri'; const _allowEmbeddingFlag = 'allow-embedding'; +const _launchBrowserFlag = 'launch-browser'; /// This command builds DevTools in release mode by running the /// `dt build` command and then serves DevTools with a locally @@ -85,6 +86,13 @@ class ServeCommand extends Command { ' of building it using `flutter build web` and serving the assets' ' directly from the DevTools server.', ) + ..addFlag( + _launchBrowserFlag, + negatable: true, + defaultsTo: true, + help: + 'Whether to automatically open a browser and load DevTools in it. Defaults to true, pass --no-launch-browser to disable.', + ) ..addDebugServerFlag() ..addServeWithSdkOption() ..addUpdateFlutterFlag() @@ -146,6 +154,7 @@ class ServeCommand extends Command { final results = argResults!; final buildApp = results[_buildAppFlag] as bool; + final launchBrowser = results[_launchBrowserFlag] as bool; final runApp = results[SharedCommandArgs.runApp.flagName] as bool; final debugServer = results[SharedCommandArgs.debugServer.flagName] as bool; final updateFlutter = @@ -175,27 +184,27 @@ class ServeCommand extends Command { // Any flag that we aren't removing here is intended to be passed through. final remainingArguments = List.of(results.arguments) - ..remove(SharedCommandArgs.updateFlutter.asArg()) - ..remove(SharedCommandArgs.updateFlutter.asArg(negated: true)) - ..remove(SharedCommandArgs.updatePerfetto.asArg()) - ..remove(SharedCommandArgs.wasm.asArg()) - ..remove(SharedCommandArgs.noStripWasm.asArg()) - ..remove(SharedCommandArgs.noMinifyWasm.asArg()) - ..remove(valueAsArg(_buildAppFlag)) - ..remove(valueAsArg(_buildAppFlag, negated: true)) - ..remove(SharedCommandArgs.runApp.asArg()) - ..remove(SharedCommandArgs.debugServer.asArg()) - ..remove(SharedCommandArgs.pubGet.asArg()) - ..remove(SharedCommandArgs.pubGet.asArg(negated: true)) - ..removeWhere( + ..remove(SharedCommandArgs.updateFlutter.asArg()) + ..remove(SharedCommandArgs.updateFlutter.asArg(negated: true)) + ..remove(SharedCommandArgs.updatePerfetto.asArg()) + ..remove(SharedCommandArgs.wasm.asArg()) + ..remove(SharedCommandArgs.noStripWasm.asArg()) + ..remove(SharedCommandArgs.noMinifyWasm.asArg()) + ..remove(valueAsArg(_buildAppFlag)) + ..remove(valueAsArg(_buildAppFlag, negated: true)) + ..remove(SharedCommandArgs.runApp.asArg()) + ..remove(SharedCommandArgs.debugServer.asArg()) + ..remove(SharedCommandArgs.pubGet.asArg()) + ..remove(SharedCommandArgs.pubGet.asArg(negated: true)) + ..removeWhere( (element) => element.startsWith(SharedCommandArgs.buildMode.asArg()), - ) - ..removeWhere( - (element) => element.startsWith( - valueAsArg(SharedCommandArgs.serveWithDartSdk.flagName), - ), - ); + ) + ..removeWhere( + (element) => element.startsWith( + valueAsArg(SharedCommandArgs.serveWithDartSdk.flagName), + ), + ); final localDartSdkLocation = Platform.environment['LOCAL_DART_SDK']; if (localDartSdkLocation == null) { @@ -292,11 +301,11 @@ class ServeCommand extends Command { final cliCommand = CliCommand.dart([ if (debugServer) ...['run', '--observe=0'], ddsServeLocalScriptPath, - if (runApp) + if (!launchBrowser || runApp) // When running DevTools via `flutter run`, the [flutterRunProcess] // below will launch DevTools in the browser. - '--no-launch-browser' - else + '--no-launch-browser', + if (!runApp) // Only pass a build location if the server is serving the web assets // (i.e. not when DevTools app is ran via `flutter run`). '--devtools-build=$devToolsBuildLocation', @@ -372,11 +381,11 @@ class ServeCommand extends Command { // Consolidate important stdout content for easy access. final debugServerContent = debugServer - ? ''' + ? ''' - VM Service URI: $debugServerVmServiceUri - DevTools URI for debugging the DevTools server: $debugServerDevToolsConnection ''' - : ''; + : ''; print(''' ------------------------------------------------------------------- From cd0c8a20b547732970e0ab25b35a46a20e1573db Mon Sep 17 00:00:00 2001 From: Elliott Brooks <21270878+elliette@users.noreply.github.com> Date: Fri, 5 Sep 2025 09:49:37 -0700 Subject: [PATCH 2/5] Fix DCM errors --- .../benchmark/devtools_benchmarks_test.dart | 2 +- .../screens/profiler/cpu_profile_model.dart | 4 +- .../src/shared/http/http_request_data.dart | 2 +- .../webdriver_test/web_compiler_test.dart | 43 +++++++++++-------- .../integration_test_utils.dart | 6 +-- 5 files changed, 32 insertions(+), 25 deletions(-) diff --git a/packages/devtools_app/benchmark/devtools_benchmarks_test.dart b/packages/devtools_app/benchmark/devtools_benchmarks_test.dart index 60819df5198..7febc95b064 100644 --- a/packages/devtools_app/benchmark/devtools_benchmarks_test.dart +++ b/packages/devtools_app/benchmark/devtools_benchmarks_test.dart @@ -272,7 +272,7 @@ Future _findAvailablePort({required int startingAt}) async { Future _isPortAvailable(int port) async { try { - final RawSocket socket = await RawSocket.connect('localhost', port); + final socket = await RawSocket.connect('localhost', port); socket.shutdown(SocketDirection.both); await socket.close(); return false; diff --git a/packages/devtools_app/lib/src/screens/profiler/cpu_profile_model.dart b/packages/devtools_app/lib/src/screens/profiler/cpu_profile_model.dart index 6ea11c6d4c4..719d2e9108d 100644 --- a/packages/devtools_app/lib/src/screens/profiler/cpu_profile_model.dart +++ b/packages/devtools_app/lib/src/screens/profiler/cpu_profile_model.dart @@ -744,12 +744,12 @@ class CpuProfileData with Serializable { List? _bottomUpRoots; - late final Iterable userTags = { + late final userTags = { for (final cpuSample in cpuSamples) if (cpuSample.userTag case final userTag?) userTag, }; - late final Iterable vmTags = { + late final vmTags = { for (final cpuSample in cpuSamples) if (cpuSample.vmTag case final vmTag?) vmTag, }; diff --git a/packages/devtools_app/lib/src/shared/http/http_request_data.dart b/packages/devtools_app/lib/src/shared/http/http_request_data.dart index 8be9458d23f..aeb478e44bb 100644 --- a/packages/devtools_app/lib/src/shared/http/http_request_data.dart +++ b/packages/devtools_app/lib/src/shared/http/http_request_data.dart @@ -33,7 +33,7 @@ class DartIOHttpInstantEvent { TimeRange get timeRange => _timeRangeBuilder.build(); // This is modified from within HttpRequestData. - final TimeRangeBuilder _timeRangeBuilder = TimeRangeBuilder(); + final _timeRangeBuilder = TimeRangeBuilder(); } /// An abstraction of an HTTP request made through dart:io. diff --git a/packages/devtools_app/webdriver_test/web_compiler_test.dart b/packages/devtools_app/webdriver_test/web_compiler_test.dart index dcd2730a9d8..fe83e2aaa35 100644 --- a/packages/devtools_app/webdriver_test/web_compiler_test.dart +++ b/packages/devtools_app/webdriver_test/web_compiler_test.dart @@ -2,14 +2,12 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file or at https://developers.google.com/open-source/licenses/bsd. -@Timeout(Duration(minutes: 4)) -library; - import 'dart:async'; import 'dart:io'; import 'package:devtools_shared/devtools_test_utils.dart'; import 'package:devtools_test/helpers.dart'; +import 'package:devtools_test/integration_test.dart'; import 'package:test/test.dart'; import 'package:webdriver/async_io.dart'; @@ -56,21 +54,30 @@ void main() { }); group('compilation', () { - test('compiler query param determines skwasm/canvaskit renderer', () async { - // Open the DevTools URL with ?compiler=wasm. - await driver.get( - _addQueryParam(devToolsServerAddress, param: 'compiler', value: 'wasm'), - ); - // Verify we are using the skwasm renderer. - expect(await getRendererAttribute(), equals('skwasm')); + test( + 'compiler query param determines skwasm/canvaskit renderer', + timeout: longTimeout, + () async { + // Open the DevTools URL with ?compiler=wasm. + await driver.get( + _addQueryParam( + devToolsServerAddress, + param: 'compiler', + value: 'wasm', + ), + ); + // Verify we are using the skwasm renderer. + expect(await getRendererAttribute(), equals('skwasm')); - // Open the DevTools URL with ?compiler=js. - await driver.get( - _addQueryParam(devToolsServerAddress, param: 'compiler', value: 'js'), - ); - // Verify we are using the canvaskit renderer. - expect(await getRendererAttribute(), equals('canvaskit')); - }, retry: 1); + // Open the DevTools URL with ?compiler=js. + await driver.get( + _addQueryParam(devToolsServerAddress, param: 'compiler', value: 'js'), + ); + // Verify we are using the canvaskit renderer. + expect(await getRendererAttribute(), equals('canvaskit')); + }, + retry: 1, + ); }); } @@ -80,7 +87,7 @@ String _addQueryParam( required String value, }) { final uri = Uri.parse(url); - final newQueryParameters = Map.from(uri.queryParameters); + final newQueryParameters = Map.of(uri.queryParameters); newQueryParameters[param] = value; return uri.replace(queryParameters: newQueryParameters).toString(); } diff --git a/packages/devtools_test/lib/src/integration_test/integration_test_utils.dart b/packages/devtools_test/lib/src/integration_test/integration_test_utils.dart index 6187893ad20..605df1e5e47 100644 --- a/packages/devtools_test/lib/src/integration_test/integration_test_utils.dart +++ b/packages/devtools_test/lib/src/integration_test/integration_test_utils.dart @@ -156,16 +156,16 @@ Future verifyScreenshot( /// /// Adjust as needed; this is used to override the 10-minute or infinite timeout /// in [testWidgets]. -const Timeout shortTimeout = Timeout(Duration(minutes: 2)); +const shortTimeout = Timeout(Duration(minutes: 2)); /// A timeout for a "medium" integration test. /// /// Adjust as needed; this is used to override the 10-minute or infinite timeout /// in [testWidgets]. -const Timeout mediumTimeout = Timeout(Duration(minutes: 3)); +const mediumTimeout = Timeout(Duration(minutes: 3)); /// A timeout for a "long" integration test. /// /// Adjust as needed; this is used to override the 10-minute or infinite timeout /// in [testWidgets]. -const Timeout longTimeout = Timeout(Duration(minutes: 4)); +const longTimeout = Timeout(Duration(minutes: 4)); From 6432fdce20b100dbf6f350bbefdc8d5c34c71cca Mon Sep 17 00:00:00 2001 From: Elliott Brooks <21270878+elliette@users.noreply.github.com> Date: Fri, 5 Sep 2025 10:09:10 -0700 Subject: [PATCH 3/5] Maybe add test to Github CI --- .github/workflows/build.yaml | 25 +++++++++++++++++++++++++ tool/ci/bots.sh | 3 +++ 2 files changed, 28 insertions(+) diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 38cedc3da9a..5c89fd841f8 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -157,6 +157,31 @@ jobs: PLATFORM: vm run: ./tool/ci/bots.sh + webdriver_test: + name: ${{ matrix.os }} Webdriver test + needs: flutter-prep + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + bot: + - test_webdriver + os: [ubuntu-latest, windows-latest] + steps: + - name: git clone + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 + - name: Load Cached Flutter SDK + uses: actions/cache@d4323d4df104b026a6aa633fdb11d772146be0bf + with: + path: | + ./tool/flutter-sdk + key: flutter-sdk-${{ runner.os }}-${{ needs.flutter-prep.outputs.latest_flutter_candidate }} + - name: tool/ci/bots.sh + env: + BOT: ${{ matrix.bot }} + PLATFORM: vm + run: ./tool/ci/bots.sh + macos-test: needs: flutter-prep name: macos goldens ${{ matrix.bot }} diff --git a/tool/ci/bots.sh b/tool/ci/bots.sh index c4eda2d2c81..60ed7763025 100755 --- a/tool/ci/bots.sh +++ b/tool/ci/bots.sh @@ -64,6 +64,9 @@ elif [[ "$BOT" == "test_ddc" || "$BOT" == "test_dart2js" ]]; then exit 1 fi +elif [ "$BOT" = "test_webdriver" ]; then + flutter test webdriver_test + # TODO(https://github.com/flutter/devtools/issues/1987): consider running integration tests # for a DDC build of DevTools # elif [ "$BOT" = "integration_ddc" ]; then From 35e7a701d4bdd40c0c0412dd092991e31b3e997d Mon Sep 17 00:00:00 2001 From: Elliott Brooks <21270878+elliette@users.noreply.github.com> Date: Fri, 5 Sep 2025 10:38:36 -0700 Subject: [PATCH 4/5] Add print statement to debug CI failure --- .../devtools_app/integration_test/test_infra/run/run_test.dart | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/devtools_app/integration_test/test_infra/run/run_test.dart b/packages/devtools_app/integration_test/test_infra/run/run_test.dart index b4e3162e7f9..01090dc63ba 100644 --- a/packages/devtools_app/integration_test/test_infra/run/run_test.dart +++ b/packages/devtools_app/integration_test/test_infra/run/run_test.dart @@ -187,6 +187,7 @@ Future listenForDevToolsAddress( final sub = devToolsServerProcess.stdout.transform(utf8.decoder).listen(( line, ) { + print('[Server start-up] $line'); if (line.contains(_devToolsServerAddressLine)) { // This will pull the server address from a String like: // "Serving DevTools at http://127.0.0.1:9104.". From 6ad7058d414c11a2eefd9a5fd8c6078abdf7eb84 Mon Sep 17 00:00:00 2001 From: Elliott Brooks <21270878+elliette@users.noreply.github.com> Date: Fri, 5 Sep 2025 15:51:12 -0700 Subject: [PATCH 5/5] more debugging --- .../integration_test/test_infra/run/run_test.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/devtools_app/integration_test/test_infra/run/run_test.dart b/packages/devtools_app/integration_test/test_infra/run/run_test.dart index 01090dc63ba..2a7577440f3 100644 --- a/packages/devtools_app/integration_test/test_infra/run/run_test.dart +++ b/packages/devtools_app/integration_test/test_infra/run/run_test.dart @@ -180,14 +180,14 @@ Future startDevToolsServer({bool useLocalServer = false}) async { Future listenForDevToolsAddress( Process devToolsServerProcess, { - Duration timeout = const Duration(seconds: 10), + Duration timeout = const Duration(minutes: 3), }) async { final devToolsAddressCompleter = Completer(); final sub = devToolsServerProcess.stdout.transform(utf8.decoder).listen(( line, ) { - print('[Server start-up] $line'); + print('[Server - ${DateTime.now()}] $line'); if (line.contains(_devToolsServerAddressLine)) { // This will pull the server address from a String like: // "Serving DevTools at http://127.0.0.1:9104.".