Implement frameData for TestWindow (#105537)

diff --git a/packages/flutter_test/lib/src/binding.dart b/packages/flutter_test/lib/src/binding.dart
index 238af86..9f2f391 100644
--- a/packages/flutter_test/lib/src/binding.dart
+++ b/packages/flutter_test/lib/src/binding.dart
@@ -157,6 +157,12 @@
   }
 
   @override
+  void handleBeginFrame(Duration? rawTimeStamp) {
+    _window.incrementFrameNumber();
+    super.handleBeginFrame(rawTimeStamp);
+  }
+
+  @override
   TestWindow get window => _window;
   final TestWindow _window;
 
@@ -1048,7 +1054,6 @@
       }
       _phase = newPhase;
       if (hasScheduledFrame) {
-        addTime(const Duration(milliseconds: 500));
         _currentFakeAsync!.flushMicrotasks();
         handleBeginFrame(Duration(
           milliseconds: _clock!.now().millisecondsSinceEpoch,
@@ -1093,8 +1098,6 @@
       ),
     );
 
-    addTime(additionalTime);
-
     return realAsyncZone.run<Future<T?>>(() async {
       _pendingAsyncTasks = Completer<void>();
       T? result;
diff --git a/packages/flutter_test/lib/src/window.dart b/packages/flutter_test/lib/src/window.dart
index e82bc80..c8cc714 100644
--- a/packages/flutter_test/lib/src/window.dart
+++ b/packages/flutter_test/lib/src/window.dart
@@ -59,6 +59,14 @@
   }) : _window = window,
        platformDispatcher = TestPlatformDispatcher(platformDispatcher: window.platformDispatcher);
 
+
+  int _frameNumber = 0;
+  /// Indicates that the test binding has pumped a frame.
+  void incrementFrameNumber() {
+    _frameNumber += 1;
+    platformDispatcher.frameData = _TestFrameData(_frameNumber);
+  }
+
   /// The [dart:ui.SingletonFlutterWindow] that is wrapped by this [TestWindow].
   final ui.SingletonFlutterWindow _window;
 
@@ -491,6 +499,9 @@
     platformDispatcher.onPlatformMessage = callback;
   }
 
+  @override
+  ui.FrameData get frameData => platformDispatcher.frameData;
+
   /// Delete any test value properties that have been set on this [TestWindow]
   /// as well as its [platformDispatcher].
   ///
@@ -505,6 +516,7 @@
     clearDisplayFeaturesTestValue();
     clearPhysicalSizeTestValue();
     clearViewInsetsTestValue();
+    _frameNumber = 0;
     platformDispatcher.clearAllTestValues();
   }
 
@@ -882,6 +894,7 @@
     clearLocalesTestValue();
     clearSemanticsEnabledTestValue();
     clearTextScaleFactorTestValue();
+    frameData = const _TestFrameData(0);
   }
 
   @override
@@ -914,7 +927,7 @@
   ui.PlatformConfiguration get configuration => _platformDispatcher.configuration;
 
   @override
-  ui.FrameData get frameData => _platformDispatcher.frameData;
+  ui.FrameData frameData = const _TestFrameData(0);
 
   @override
   ByteData? getPersistentIsolateData() => _platformDispatcher.getPersistentIsolateData();
@@ -930,3 +943,10 @@
     return null;
   }
 }
+
+class _TestFrameData implements ui.FrameData {
+  const _TestFrameData(this.frameNumber);
+
+  @override
+  final int frameNumber;
+}
diff --git a/packages/flutter_test/test/bindings_test.dart b/packages/flutter_test/test/bindings_test.dart
index c5a4b92..7816cda 100644
--- a/packages/flutter_test/test/bindings_test.dart
+++ b/packages/flutter_test/test/bindings_test.dart
@@ -33,6 +33,35 @@
     });
   });
 
+  test('frameNumber', () async {
+    binding.window.clearAllTestValues();
+    expect(binding.window.frameData.frameNumber, 0);
+    await binding.runTest(() async {
+      // runTest pumps a frame.
+      expect(binding.window.frameData.frameNumber, 1);
+
+      // Scheduling should not pump
+      binding.scheduleFrame();
+      expect(binding.window.frameData.frameNumber, 1);
+      binding.handleBeginFrame(null);
+      expect(binding.window.frameData.frameNumber, 2);
+      binding.handleDrawFrame();
+      expect(binding.window.frameData.frameNumber, 2);
+
+      // Pump with no scheduled frame.
+      await binding.pump();
+      expect(binding.window.frameData.frameNumber, 2);
+
+      // Schedule and pump, similar to handleBeginFrame.
+      binding.scheduleFrame();
+      await binding.pump();
+      expect(binding.window.frameData.frameNumber, 3);
+    }, () {});
+    binding.postTest();
+    binding.window.clearAllTestValues();
+    expect(binding.window.frameData.frameNumber, 0);
+  });
+
   // The next three tests must run in order -- first using `test`, then `testWidgets`, then `test` again.
 
   int order = 0;