Add a flutter app that can resize itself as integration test app. (#112297)
diff --git a/.ci.yaml b/.ci.yaml
index 031f7a5..e647fd5 100644
--- a/.ci.yaml
+++ b/.ci.yaml
@@ -2642,6 +2642,16 @@
["devicelab", "hostonly"]
task_name: hello_world_macos__compile
+ - name: Mac integration_ui_test_test_macos
+ bringup: true
+ recipe: devicelab/devicelab_drone
+ presubmit: false
+ timeout: 60
+ properties:
+ tags: >
+ ["devicelab", "mac"]
+ task_name: integration_ui_test_test_macos
+
- name: Mac module_custom_host_app_name_test
recipe: devicelab/devicelab_drone
timeout: 60
diff --git a/TESTOWNERS b/TESTOWNERS
index f30f239..9ae5008 100644
--- a/TESTOWNERS
+++ b/TESTOWNERS
@@ -219,10 +219,10 @@
/dev/devicelab/bin/tasks/flutter_gallery_macos__start_up.dart @a-wallen @flutter/desktop
/dev/devicelab/bin/tasks/flutter_gallery_win_desktop__compile.dart @yaakovschectman @flutter/desktop
/dev/devicelab/bin/tasks/flutter_gallery_win_desktop__start_up.dart @yaakovschectman @flutter/desktop
-/dev/devicelab/bin/tasks/flutter_view_macos__start_up.dart @a-wallen @flutter/desktop
-/dev/devicelab/bin/tasks/flutter_tool_startup__windows.dart @jensjoha @flutter/tool
/dev/devicelab/bin/tasks/flutter_tool_startup__linux.dart @jensjoha @flutter/tool
/dev/devicelab/bin/tasks/flutter_tool_startup__macos.dart @jensjoha @flutter/tool
+/dev/devicelab/bin/tasks/flutter_tool_startup__windows.dart @jensjoha @flutter/tool
+/dev/devicelab/bin/tasks/flutter_view_macos__start_up.dart @a-wallen @flutter/desktop
/dev/devicelab/bin/tasks/flutter_view_win_desktop__start_up.dart @yaakovschectman @flutter/desktop
/dev/devicelab/bin/tasks/gradle_desugar_classes_test.dart @zanderso @flutter/tool
/dev/devicelab/bin/tasks/gradle_non_android_plugin_test.dart @stuartmorgan @flutter/plugin
@@ -236,6 +236,7 @@
/dev/devicelab/bin/tasks/hello_world_macos__compile.dart @a-wallen @flutter/desktop
/dev/devicelab/bin/tasks/hello_world_win_desktop__compile.dart @yaakovschectman @flutter/desktop
/dev/devicelab/bin/tasks/hot_mode_dev_cycle_win_target__benchmark.dart @cbracken @flutter/desktop
+/dev/devicelab/bin/tasks/integration_ui_test_test_macos.dart @a-wallen @flutter/desktop
/dev/devicelab/bin/tasks/module_custom_host_app_name_test.dart @zanderso @flutter/tool
/dev/devicelab/bin/tasks/module_host_with_custom_build_test.dart @zanderso @flutter/tool
/dev/devicelab/bin/tasks/module_test_ios.dart @jmagman @flutter/tool
diff --git a/dev/devicelab/bin/tasks/integration_ui_test_test_macos.dart b/dev/devicelab/bin/tasks/integration_ui_test_test_macos.dart
new file mode 100644
index 0000000..0026817
--- /dev/null
+++ b/dev/devicelab/bin/tasks/integration_ui_test_test_macos.dart
@@ -0,0 +1,12 @@
+// Copyright 2014 The Flutter Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import 'package:flutter_devicelab/framework/devices.dart';
+import 'package:flutter_devicelab/framework/framework.dart';
+import 'package:flutter_devicelab/tasks/integration_tests.dart';
+
+Future<void> main() async {
+ deviceOperatingSystem = DeviceOperatingSystem.macos;
+ await task(createEndToEndIntegrationTest());
+}
diff --git a/dev/integration_tests/ui/integration_test/resize_integration_test.dart b/dev/integration_tests/ui/integration_test/resize_integration_test.dart
new file mode 100644
index 0000000..6dedbc1
--- /dev/null
+++ b/dev/integration_tests/ui/integration_test/resize_integration_test.dart
@@ -0,0 +1,57 @@
+// Copyright 2014 The Flutter Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import 'package:flutter/widgets.dart' as widgets show Container, Size, runApp;
+import 'package:flutter_test/flutter_test.dart';
+import 'package:integration_test/integration_test.dart';
+import 'package:integration_ui/resize.dart' as app;
+
+void main() {
+ IntegrationTestWidgetsFlutterBinding.ensureInitialized();
+
+ group('end-to-end test', () {
+ testWidgets('Use button to resize window',
+ timeout: const Timeout(Duration(seconds: 5)),
+ (WidgetTester tester) async {
+ const app.ResizeApp resizeApp = app.ResizeApp();
+
+ widgets.runApp(resizeApp);
+ await tester.pumpAndSettle();
+
+ final Finder fab = find.byKey(app.ResizeApp.extendedFab);
+ expect(fab, findsOneWidget);
+
+ final Finder root = find.byWidget(resizeApp);
+ final widgets.Size sizeBefore = tester.getSize(root);
+
+ await tester.tap(fab);
+ await tester.pumpAndSettle();
+
+ final widgets.Size sizeAfter = tester.getSize(root);
+ expect(sizeAfter.width, equals(sizeBefore.width + app.ResizeApp.resizeBy));
+ expect(sizeAfter.height, equals(sizeBefore.height + app.ResizeApp.resizeBy));
+
+ final Finder widthLabel = find.byKey(app.ResizeApp.widthLabel);
+ expect(widthLabel, findsOneWidget);
+ expect(find.text('width: ${sizeAfter.width}'), findsOneWidget);
+
+ final Finder heightLabel = find.byKey(app.ResizeApp.heightLabel);
+ expect(heightLabel, findsOneWidget);
+ expect(find.text('height: ${sizeAfter.height}'), findsOneWidget);
+ });
+ });
+
+ testWidgets('resize window after calling runApp twice, the second with no content',
+ timeout: const Timeout(Duration(seconds: 5)),
+ (WidgetTester tester) async {
+ const app.ResizeApp root = app.ResizeApp();
+ widgets.runApp(root);
+ widgets.runApp(widgets.Container());
+
+ await tester.pumpAndSettle();
+
+ const widgets.Size expectedSize = widgets.Size(100, 100);
+ await app.ResizeApp.resize(expectedSize);
+ });
+}
diff --git a/dev/integration_tests/ui/lib/resize.dart b/dev/integration_tests/ui/lib/resize.dart
new file mode 100644
index 0000000..86359cf
--- /dev/null
+++ b/dev/integration_tests/ui/lib/resize.dart
@@ -0,0 +1,76 @@
+// Copyright 2014 The Flutter Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import 'package:flutter/material.dart';
+import 'package:flutter/services.dart';
+
+void main() async {
+ runApp(const ResizeApp());
+}
+
+class ResizeApp extends StatefulWidget {
+ const ResizeApp({super.key});
+
+ static const double resizeBy = 10.0;
+ static const Key heightLabel = Key('height label');
+ static const Key widthLabel = Key('width label');
+ static const Key extendedFab = Key('extended FAB');
+
+ static const MethodChannel platform =
+ MethodChannel('samples.flutter.dev/resize');
+
+ static Future<void> resize(Size size) async {
+ await ResizeApp.platform.invokeMethod<void>(
+ 'resize',
+ <String, dynamic>{
+ 'width': size.width,
+ 'height': size.height,
+ }
+ );
+ }
+
+ @override
+ State<ResizeApp> createState() => _ResizeAppState();
+}
+
+class _ResizeAppState extends State<ResizeApp> {
+ @override
+ Widget build(BuildContext context) {
+ return MaterialApp(
+ home: Builder(
+ builder: (BuildContext context) {
+ final Size currentSize = MediaQuery.of(context).size;
+ return Scaffold(
+ floatingActionButton: FloatingActionButton.extended(
+ key: ResizeApp.extendedFab,
+ label: const Text('Resize'),
+ onPressed: () {
+ final Size nextSize = Size(
+ currentSize.width + ResizeApp.resizeBy,
+ currentSize.height + ResizeApp.resizeBy,
+ );
+ ResizeApp.resize(nextSize);
+ },
+ ),
+ body: Center(
+ child: Column(
+ mainAxisAlignment: MainAxisAlignment.center,
+ children: <Widget>[
+ Text(
+ key: ResizeApp.widthLabel,
+ 'width: ${currentSize.width}'
+ ),
+ Text(
+ key: ResizeApp.heightLabel,
+ 'height: ${currentSize.height}',
+ ),
+ ],
+ ),
+ ),
+ );
+ }
+ ),
+ );
+ }
+}
diff --git a/dev/integration_tests/ui/macos/Runner/MainFlutterWindow.swift b/dev/integration_tests/ui/macos/Runner/MainFlutterWindow.swift
index a97a962..a52288a 100644
--- a/dev/integration_tests/ui/macos/Runner/MainFlutterWindow.swift
+++ b/dev/integration_tests/ui/macos/Runner/MainFlutterWindow.swift
@@ -5,6 +5,12 @@
import Cocoa
import FlutterMacOS
+extension NSWindow {
+ var titlebarHeight: CGFloat {
+ frame.height - contentRect(forFrameRect: frame).height
+ }
+}
+
class MainFlutterWindow: NSWindow {
override func awakeFromNib() {
let flutterViewController = FlutterViewController.init()
@@ -12,8 +18,35 @@
self.contentViewController = flutterViewController
self.setFrame(windowFrame, display: true)
+ RegisterMethodChannel(registry: flutterViewController)
RegisterGeneratedPlugins(registry: flutterViewController)
super.awakeFromNib()
}
+
+ func RegisterMethodChannel(registry: FlutterPluginRegistry) {
+ let registrar = registry.registrar(forPlugin: "resize")
+ let channel = FlutterMethodChannel(name: "samples.flutter.dev/resize",
+ binaryMessenger: registrar.messenger)
+ channel.setMethodCallHandler({ (call, result) in
+ if call.method == "resize" {
+ if let args = call.arguments as? Dictionary<String, Any>,
+ let width = args["width"] as? Double,
+ var height = args["height"] as? Double {
+ height += self.titlebarHeight
+ let currentFrame: NSRect = self.frame
+ let nextFrame: NSRect = NSMakeRect(
+ currentFrame.minX - (width - currentFrame.width) / 2,
+ currentFrame.minY - (height - currentFrame.height) / 2,
+ width,
+ height
+ )
+ self.setFrame(nextFrame, display: true, animate: false)
+ result(true)
+ } else {
+ result(FlutterError.init(code: "bad args", message: nil, details: nil))
+ }
+ }
+ })
+ }
}