From b22388ee687333adba5f6b21a2684f29981a611e Mon Sep 17 00:00:00 2001 From: Alex Wallen Date: Mon, 26 Sep 2022 07:45:19 -1000 Subject: [PATCH] Add a flutter app that can resize itself as integration test app. (#112297) --- .ci.yaml | 10 +++ TESTOWNERS | 5 +- .../tasks/integration_ui_test_test_macos.dart | 12 +++ .../resize_integration_test.dart | 57 ++++++++++++++ dev/integration_tests/ui/lib/resize.dart | 76 +++++++++++++++++++ .../ui/macos/Runner/MainFlutterWindow.swift | 33 ++++++++ 6 files changed, 191 insertions(+), 2 deletions(-) create mode 100644 dev/devicelab/bin/tasks/integration_ui_test_test_macos.dart create mode 100644 dev/integration_tests/ui/integration_test/resize_integration_test.dart create mode 100644 dev/integration_tests/ui/lib/resize.dart diff --git a/.ci.yaml b/.ci.yaml index 031f7a5577f..e647fd5ae96 100644 --- a/.ci.yaml +++ b/.ci.yaml @@ -2642,6 +2642,16 @@ targets: ["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 f30f239cb36..9ae50083fcc 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 00000000000..0026817db14 --- /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 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 00000000000..6dedbc17d53 --- /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 00000000000..86359cff96f --- /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 resize(Size size) async { + await ResizeApp.platform.invokeMethod( + 'resize', + { + 'width': size.width, + 'height': size.height, + } + ); + } + + @override + State createState() => _ResizeAppState(); +} + +class _ResizeAppState extends State { + @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: [ + 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 a97a96274ee..a52288a4c68 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 @@ class MainFlutterWindow: NSWindow { 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, + 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)) + } + } + }) + } }