From 5014b332e577f372206631ef86598bb6ae56e7f9 Mon Sep 17 00:00:00 2001 From: AIlhomov Date: Mon, 9 Nov 2026 21:49:21 +0100 Subject: [PATCH 1/2] Handle network failures when fetching survey metadata --- .../lib/src/shared/managers/survey.dart | 2 + .../release_notes/NEXT_RELEASE_NOTES.md | 3 + .../test/shared/managers/survey_test.dart | 62 ++++++++++++++++++- 3 files changed, 65 insertions(+), 2 deletions(-) diff --git a/packages/devtools_app/lib/src/shared/managers/survey.dart b/packages/devtools_app/lib/src/shared/managers/survey.dart index 271bd95f9de..35757045693 100644 --- a/packages/devtools_app/lib/src/shared/managers/survey.dart +++ b/packages/devtools_app/lib/src/shared/managers/survey.dart @@ -136,6 +136,8 @@ class SurveyService { final contents = json.decode(response.body) as Map; return DevToolsSurvey.fromJson(contents); } + } on ClientException catch (e, st) { + _log.fine('Unable to fetch survey content: $e', e, st); } on Error catch (e, st) { _log.shout('Error fetching survey content: $e', e, st); } diff --git a/packages/devtools_app/release_notes/NEXT_RELEASE_NOTES.md b/packages/devtools_app/release_notes/NEXT_RELEASE_NOTES.md index 3abdfddc6d8..56502dc0d71 100644 --- a/packages/devtools_app/release_notes/NEXT_RELEASE_NOTES.md +++ b/packages/devtools_app/release_notes/NEXT_RELEASE_NOTES.md @@ -15,6 +15,9 @@ To learn more about DevTools, check out the ## General updates +* Handle network failures when fetching survey metadata without an unhandled + exception. [#8562](https://github.com/flutter/devtools/issues/8562) + * Added guidance to run "flutter attach" when a Flutter debug app cannot evaluate expressions and a debug-only screen is unavailable. [#4091](https://github.com/flutter/devtools/issues/4091) diff --git a/packages/devtools_app/test/shared/managers/survey_test.dart b/packages/devtools_app/test/shared/managers/survey_test.dart index 44a5e05ed92..c5e7c002d1f 100644 --- a/packages/devtools_app/test/shared/managers/survey_test.dart +++ b/packages/devtools_app/test/shared/managers/survey_test.dart @@ -6,6 +6,8 @@ import 'package:devtools_app/devtools_app.dart'; import 'package:devtools_app/src/shared/managers/survey.dart'; import 'package:devtools_app/src/shared/primitives/query_parameters.dart'; import 'package:flutter_test/flutter_test.dart'; +import 'package:http/http.dart' as http; +import 'package:http/testing.dart'; void main() { setUp(() { @@ -13,9 +15,65 @@ void main() { }); group('SurveyService', () { + Future fetchWithClient(MockClient client) => + http.runWithClient( + () => SurveyService().fetchSurveyContent(), + () => client, + ); + test('can fetch survey metadata', () async { - final survey = await SurveyService().fetchSurveyContent(); - expect(survey, isNotNull); + final survey = await fetchWithClient( + MockClient( + (_) async => http.Response('{"uniqueId":"test-survey"}', 200), + ), + ); + expect(survey!.id, 'test-survey'); + }); + + test('returns no survey for an unsuccessful response', () async { + final survey = await fetchWithClient( + MockClient((_) async => http.Response('Unavailable', 503)), + ); + expect(survey, isNull); + }); + + test('returns no survey when the network request fails', () async { + final survey = await fetchWithClient( + MockClient( + (request) => Future.error( + http.ClientException('Network unavailable', request.url), + ), + ), + ); + expect(survey, isNull); + }); + + test('can fetch a survey after a network failure', () async { + var requests = 0; + final client = MockClient((request) async { + if (requests++ == 0) { + throw http.ClientException('Network unavailable', request.url); + } + return http.Response('{"uniqueId":"test-survey"}', 200); + }); + + expect(await fetchWithClient(client), isNull); + expect((await fetchWithClient(client))!.id, 'test-survey'); + expect(requests, 2); + }); + + test('preserves error handling for invalid metadata types', () async { + final survey = await fetchWithClient( + MockClient((_) async => http.Response('{"uniqueId":42}', 200)), + ); + expect(survey, isNull); + }); + + test('does not suppress malformed JSON exceptions', () async { + await expectLater( + fetchWithClient(MockClient((_) async => http.Response('{', 200))), + throwsFormatException, + ); }); }); From e5adad65533d6215c597b21f96dc372e427ad515 Mon Sep 17 00:00:00 2001 From: AIlhomov Date: Mon, 9 Nov 2026 22:09:45 +0100 Subject: [PATCH 2/2] Use past tense in survey error release note --- packages/devtools_app/release_notes/NEXT_RELEASE_NOTES.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/devtools_app/release_notes/NEXT_RELEASE_NOTES.md b/packages/devtools_app/release_notes/NEXT_RELEASE_NOTES.md index 56502dc0d71..be3ecf8ec0c 100644 --- a/packages/devtools_app/release_notes/NEXT_RELEASE_NOTES.md +++ b/packages/devtools_app/release_notes/NEXT_RELEASE_NOTES.md @@ -15,7 +15,7 @@ To learn more about DevTools, check out the ## General updates -* Handle network failures when fetching survey metadata without an unhandled +* Handled network failures when fetching survey metadata without an unhandled exception. [#8562](https://github.com/flutter/devtools/issues/8562) * Added guidance to run "flutter attach" when a Flutter debug app cannot