Platform agnostic gallery smoke test (#23423)

diff --git a/examples/flutter_gallery/test/live_smoketest.dart b/examples/flutter_gallery/test/live_smoketest.dart
index c64be04..8f2977c 100644
--- a/examples/flutter_gallery/test/live_smoketest.dart
+++ b/examples/flutter_gallery/test/live_smoketest.dart
@@ -10,10 +10,11 @@
 
 import 'dart:async';
 
-import 'package:flutter/services.dart';
-import 'package:flutter/widgets.dart';
+import 'package:flutter/cupertino.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter/scheduler.dart';
+import 'package:flutter/services.dart';
+import 'package:flutter/widgets.dart';
 import 'package:flutter_test/flutter_test.dart';
 
 import 'package:flutter_gallery/gallery/demos.dart';
@@ -33,12 +34,19 @@
 // These demos can't be backed out of by tapping a button whose
 // tooltip is 'Back'.
 const List<String> _kSkippedDemoTitles = <String>[
-  'Pull to refresh',
   'Progress indicators',
   'Activity Indicator',
   'Video',
 ];
 
+// There are 3 places where the Gallery demos are traversed.
+// 1- In widget tests such as examples/flutter_gallery/test/smoke_test.dart
+// 2- In driver tests such as examples/flutter_gallery/test_driver/transitions_perf_test.dart
+// 3- In on-device instrumentation tests such as examples/flutter_gallery/test/live_smoketest.dart
+//
+// If you change navigation behavior in the Gallery or in the framework, make
+// sure all 3 are covered.
+
 Future<void> main() async {
   try {
     // Verify that _kUnsynchronizedDemos and _kSkippedDemos identify
@@ -66,7 +74,7 @@
           await controller.tap(demoItem); // Launch the demo
           controller.frameSync = !_kUnsynchronizedDemoTitles.contains(demo.title);
           print('Going back to demo list...');
-          await controller.tap(find.byTooltip('Back'));
+          await controller.tap(backFinder);
           controller.frameSync = true;
         }
       }
@@ -81,6 +89,18 @@
   }
 }
 
+final Finder backFinder = find.byElementPredicate(
+  (Element element) {
+    final Widget widget = element.widget;
+    if (widget is Tooltip)
+      return widget.message == 'Back';
+    if (widget is CupertinoNavigationBarBackButton)
+      return true;
+    return false;
+  },
+  description: 'Material or Cupertino back button',
+);
+
 class _LiveWidgetController extends LiveWidgetController {
   _LiveWidgetController(WidgetsBinding binding) : super(binding);
 
diff --git a/examples/flutter_gallery/test/smoke_test.dart b/examples/flutter_gallery/test/smoke_test.dart
index 9eb65f5..284ee0f 100644
--- a/examples/flutter_gallery/test/smoke_test.dart
+++ b/examples/flutter_gallery/test/smoke_test.dart
@@ -18,6 +18,14 @@
 // values approved by verityToStringOutput().
 int toStringErrors = 0;
 
+// There are 3 places where the Gallery demos are traversed.
+// 1- In widget tests such as examples/flutter_gallery/test/smoke_test.dart
+// 2- In driver tests such as examples/flutter_gallery/test_driver/transitions_perf_test.dart
+// 3- In on-device instrumentation tests such as examples/flutter_gallery/test/live_smoketest.dart
+//
+// If you change navigation behavior in the Gallery or in the framework, make
+// sure all 3 are covered.
+
 void reportToStringError(String name, String route, int lineNumber, List<String> lines, String message) {
   // If you're on line 12, then it has index 11.
   // If you want 1 line before and 1 line after, then you want lines with index 10, 11, and 12.
diff --git a/examples/flutter_gallery/test_driver/transitions_perf_test.dart b/examples/flutter_gallery/test_driver/transitions_perf_test.dart
index 440e332..c8fcd7e 100644
--- a/examples/flutter_gallery/test_driver/transitions_perf_test.dart
+++ b/examples/flutter_gallery/test_driver/transitions_perf_test.dart
@@ -35,6 +35,14 @@
   'Pickers@Material',
 ];
 
+// There are 3 places where the Gallery demos are traversed.
+// 1- In widget tests such as examples/flutter_gallery/test/smoke_test.dart
+// 2- In driver tests such as examples/flutter_gallery/test_driver/transitions_perf_test.dart
+// 3- In on-device instrumentation tests such as examples/flutter_gallery/test/live_smoketest.dart
+//
+// If you change navigation behavior in the Gallery or in the framework, make
+// sure all 3 are covered.
+
 // Demos that will be backed out of within FlutterDriver.runUnsynchronized();
 //
 // These names must match GalleryItem titles from kAllGalleryDemos