network: Fix bad HAR data (#9900)
diff --git a/packages/devtools_app/lib/src/screens/network/har_data_entry.dart b/packages/devtools_app/lib/src/screens/network/har_data_entry.dart
index bd9316d..0176d96 100644
--- a/packages/devtools_app/lib/src/screens/network/har_data_entry.dart
+++ b/packages/devtools_app/lib/src/screens/network/har_data_entry.dart
@@ -6,6 +6,7 @@
 import 'dart:typed_data';
 
 import '../../screens/network/utils/http_utils.dart';
+import '../../shared/http/constants.dart' as shared_http;
 import '../../shared/http/http_request_data.dart';
 import 'constants.dart';
 
@@ -45,6 +46,15 @@
     final requestPostData = responseData[NetworkEventKeys.postData.name];
     final responseContent = responseData[NetworkEventKeys.content.name];
 
+    final statusValue = responseData[NetworkEventKeys.status.name];
+    final statusCode = switch (statusValue) {
+      int() => statusValue,
+      String() => int.tryParse(statusValue),
+      _ => null,
+    };
+    responseData[shared_http.HttpRequestDataKeys.statusCode.name] =
+        statusCode ?? -1;
+
     return HarDataEntry(
       DartIOHttpRequestData.fromJson(
         modifiedRequestData,
@@ -148,7 +158,7 @@
       },
       // Response
       NetworkEventKeys.response.name: <String, Object?>{
-        NetworkEventKeys.status.name: e.status,
+        NetworkEventKeys.status.name: int.tryParse(e.status ?? '') ?? -1,
         NetworkEventKeys.statusText.name:
             e.general[NetworkEventKeys.reasonPhrase.name] ?? '',
         NetworkEventKeys.httpVersion.name:
diff --git a/packages/devtools_app/release_notes/NEXT_RELEASE_NOTES.md b/packages/devtools_app/release_notes/NEXT_RELEASE_NOTES.md
index d428e86..381298f 100644
--- a/packages/devtools_app/release_notes/NEXT_RELEASE_NOTES.md
+++ b/packages/devtools_app/release_notes/NEXT_RELEASE_NOTES.md
@@ -40,7 +40,8 @@
 
 ## Network profiler updates
 
-TODO: Remove this section if there are not any updates.
+- Fixed exported response status in HAR files so that they parse as integers
+  instead of strings. [#9900](https://github.com/flutter/devtools/pull/9900)
 
 ## Logging updates
 
diff --git a/packages/devtools_app/test/screens/network/har_network_test.dart b/packages/devtools_app/test/screens/network/har_network_test.dart
index 98a8a78..a1c735f 100644
--- a/packages/devtools_app/test/screens/network/har_network_test.dart
+++ b/packages/devtools_app/test/screens/network/har_network_test.dart
@@ -8,7 +8,6 @@
 import 'package:devtools_app/src/screens/network/constants.dart';
 import 'package:devtools_app/src/screens/network/har_data_entry.dart';
 import 'package:devtools_app/src/screens/network/har_network_data.dart';
-
 import 'package:flutter_test/flutter_test.dart';
 
 void main() {
@@ -58,10 +57,25 @@
   });
 
   group('HarDataEntry', () {
+    final entryJson =
+        ((jsonData['log'] as Map<String, Object?>)['entries'] as List).first
+            as Map<String, Object?>;
+
+    Map<String, Object?> copyWithStatus(Object? status) {
+      final copy = jsonDecode(jsonEncode(entryJson)) as Map<String, Object?>;
+      final response = copy['response'] as Map<String, Object?>;
+      response['status'] = status;
+      return copy;
+    }
+
+    Map<String, Object?> copyWithRequestError(String error) {
+      final copy = jsonDecode(jsonEncode(entryJson)) as Map<String, Object?>;
+      final request = copy['request'] as Map<String, Object?>;
+      request['error'] = error;
+      return copy;
+    }
+
     test('fromJson parses correctly', () {
-      final entryJson =
-          ((jsonData['log'] as Map<String, Object?>)['entries'] as List).first
-              as Map<String, Object?>;
       final harDataEntry = HarDataEntry.fromJson(entryJson);
 
       expect(
@@ -71,12 +85,10 @@
       expect(harDataEntry.request.method, 'GET');
       expect(harDataEntry.request.requestHeaders, isNotEmpty);
       expect(harDataEntry.request.requestCookies, isEmpty);
+      expect(harDataEntry.request.status, '200');
     });
 
     test('toJson serializes correctly', () {
-      final entryJson =
-          ((jsonData['log'] as Map<String, Object?>)['entries'] as List).first
-              as Map<String, Object?>;
       final harDataEntry = HarDataEntry.fromJson(entryJson);
       final json = HarDataEntry.toJson(harDataEntry.request);
 
@@ -89,6 +101,11 @@
       expect(request?['cookies'], isEmpty);
 
       expect(json['cache'], isEmpty);
+      final response = json['response'] as Map<String, Object?>?;
+      expect(response, isNotNull);
+      expect(response?['status'], 200);
+      expect(response?['statusText'], '');
+
       final timings = json['timings'] as Map<String, Object?>?;
       expect(timings?['blocked'], NetworkEventDefaults.blocked);
       expect(timings?['dns'], NetworkEventDefaults.dns);
@@ -98,5 +115,68 @@
       expect(timings?['ssl'], NetworkEventDefaults.ssl);
       expect(json['comment'], '');
     });
+
+    test('handles "Error" status in JSON', () {
+      final errorJson = copyWithStatus('Error');
+      final harDataEntry = HarDataEntry.fromJson(errorJson);
+      expect(harDataEntry.request.status, '-1');
+
+      final serialized = HarDataEntry.toJson(harDataEntry.request);
+      expect((serialized['response'] as Map)['status'], -1);
+    });
+
+    test('handles "Cancelled" status in JSON', () {
+      final cancelledJson = copyWithStatus('Cancelled');
+      final harDataEntry = HarDataEntry.fromJson(cancelledJson);
+      expect(harDataEntry.request.status, '-1');
+
+      final serialized = HarDataEntry.toJson(harDataEntry.request);
+      expect((serialized['response'] as Map)['status'], -1);
+    });
+
+    test('handles -1 integer status in JSON', () {
+      final minusOneJson = copyWithStatus(-1);
+      final harDataEntry = HarDataEntry.fromJson(minusOneJson);
+      expect(harDataEntry.request.status, '-1');
+
+      final serialized = HarDataEntry.toJson(harDataEntry.request);
+      expect((serialized['response'] as Map)['status'], -1);
+    });
+
+    test('handles invalid string status in JSON', () {
+      final invalidJson = copyWithStatus('foo');
+      final harDataEntry = HarDataEntry.fromJson(invalidJson);
+      expect(harDataEntry.request.status, '-1');
+
+      final serialized = HarDataEntry.toJson(harDataEntry.request);
+      expect((serialized['response'] as Map)['status'], -1);
+    });
+
+    test('handles null status in JSON', () {
+      final nullJson = copyWithStatus(null);
+      final harDataEntry = HarDataEntry.fromJson(nullJson);
+      expect(harDataEntry.request.status, '-1');
+
+      final serialized = HarDataEntry.toJson(harDataEntry.request);
+      expect((serialized['response'] as Map)['status'], -1);
+    });
+
+    test('handles request connection error', () {
+      final errorJson = copyWithRequestError('connection failed');
+      final harDataEntry = HarDataEntry.fromJson(errorJson);
+      expect(harDataEntry.request.status, 'Error');
+
+      final serialized = HarDataEntry.toJson(harDataEntry.request);
+      expect((serialized['response'] as Map)['status'], -1);
+    });
+
+    test('handles request cancellation error', () {
+      final cancelledJson = copyWithRequestError('cancelled');
+      final harDataEntry = HarDataEntry.fromJson(cancelledJson);
+      expect(harDataEntry.request.status, 'Cancelled');
+
+      final serialized = HarDataEntry.toJson(harDataEntry.request);
+      expect((serialized['response'] as Map)['status'], -1);
+    });
   });
 }