mirror of
https://github.com/flutter/flutter.git
synced 2025-06-03 00:51:18 +00:00

* add Android instrumentation test * add devicelab test * add to manifest.yaml * rename _smoke_test.dart to _smoketest.dart to prevent flutter test from picking it up * volatile fields; style fixes * use ConditionVariable; fix sh script
151 lines
4.6 KiB
Dart
151 lines
4.6 KiB
Dart
// Copyright 2017 The Chromium 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 'dart:async';
|
|
|
|
import 'package:flutter/services.dart';
|
|
import 'package:flutter/widgets.dart';
|
|
import 'package:flutter/material.dart';
|
|
import 'package:flutter/scheduler.dart';
|
|
import 'package:flutter_test/flutter_test.dart';
|
|
|
|
import 'package:flutter_gallery/gallery/app.dart';
|
|
|
|
/// Reports success or failure to the native code.
|
|
const MethodChannel _kTestChannel = const MethodChannel('io.flutter.examples.gallery/TestLifecycleListener');
|
|
|
|
Future<Null> main() async {
|
|
try {
|
|
runApp(const GalleryApp());
|
|
|
|
const Duration kWaitBetweenActions = const Duration(milliseconds: 250);
|
|
final _LiveWidgetController controller = new _LiveWidgetController();
|
|
|
|
for (Demo demo in demos) {
|
|
print('Testing "${demo.title}" demo');
|
|
final Finder menuItem = find.text(demo.title);
|
|
await controller.scrollIntoView(menuItem, alignment: 0.5);
|
|
await new Future<Null>.delayed(kWaitBetweenActions);
|
|
|
|
for (int i = 0; i < 2; i += 1) {
|
|
await controller.tap(menuItem); // Launch the demo
|
|
await new Future<Null>.delayed(kWaitBetweenActions);
|
|
controller.frameSync = demo.synchronized;
|
|
await controller.tap(find.byTooltip('Back'));
|
|
controller.frameSync = true;
|
|
await new Future<Null>.delayed(kWaitBetweenActions);
|
|
}
|
|
print('Success');
|
|
}
|
|
|
|
_kTestChannel.invokeMethod('success');
|
|
} catch (error) {
|
|
_kTestChannel.invokeMethod('failure');
|
|
}
|
|
}
|
|
|
|
class Demo {
|
|
const Demo(this.title, {this.synchronized = true});
|
|
|
|
/// The title of the demo.
|
|
final String title;
|
|
|
|
/// True if frameSync should be enabled for this test.
|
|
final bool synchronized;
|
|
}
|
|
|
|
// Warning: this list must be kept in sync with the value of
|
|
// kAllGalleryItems.map((GalleryItem item) => item.title).toList();
|
|
const List<Demo> demos = const <Demo>[
|
|
// Demos
|
|
const Demo('Shrine'),
|
|
const Demo('Contact profile'),
|
|
const Demo('Animation'),
|
|
|
|
// Material Components
|
|
const Demo('Bottom navigation'),
|
|
const Demo('Buttons'),
|
|
const Demo('Cards'),
|
|
const Demo('Chips'),
|
|
const Demo('Date and time pickers'),
|
|
const Demo('Dialog'),
|
|
const Demo('Drawer'),
|
|
const Demo('Expand/collapse list control'),
|
|
const Demo('Expansion panels'),
|
|
const Demo('Floating action button'),
|
|
const Demo('Grid'),
|
|
const Demo('Icons'),
|
|
const Demo('Leave-behind list items'),
|
|
const Demo('List'),
|
|
const Demo('Menus'),
|
|
const Demo('Modal bottom sheet'),
|
|
const Demo('Page selector'),
|
|
const Demo('Persistent bottom sheet'),
|
|
const Demo('Progress indicators', synchronized: false),
|
|
const Demo('Pull to refresh'),
|
|
const Demo('Scrollable tabs'),
|
|
const Demo('Selection controls'),
|
|
const Demo('Sliders'),
|
|
const Demo('Snackbar'),
|
|
const Demo('Tabs'),
|
|
const Demo('Text fields'),
|
|
const Demo('Tooltips'),
|
|
|
|
// Cupertino Components
|
|
const Demo('Activity Indicator', synchronized: false),
|
|
const Demo('Buttons'),
|
|
const Demo('Dialogs'),
|
|
const Demo('Sliders'),
|
|
const Demo('Switches'),
|
|
|
|
// Style
|
|
const Demo('Colors'),
|
|
const Demo('Typography'),
|
|
];
|
|
|
|
|
|
class _LiveWidgetController {
|
|
|
|
final WidgetController _controller = new WidgetController(WidgetsBinding.instance);
|
|
|
|
/// With [frameSync] enabled, Flutter Driver will wait to perform an action
|
|
/// until there are no pending frames in the app under test.
|
|
bool frameSync = true;
|
|
|
|
/// Waits until at the end of a frame the provided [condition] is [true].
|
|
Future<Null> _waitUntilFrame(bool condition(), [Completer<Null> completer]) {
|
|
completer ??= new Completer<Null>();
|
|
if (!condition()) {
|
|
SchedulerBinding.instance.addPostFrameCallback((Duration timestamp) {
|
|
_waitUntilFrame(condition, completer);
|
|
});
|
|
} else {
|
|
completer.complete();
|
|
}
|
|
return completer.future;
|
|
}
|
|
|
|
/// Runs `finder` repeatedly until it finds one or more [Element]s.
|
|
Future<Finder> _waitForElement(Finder finder) async {
|
|
if (frameSync)
|
|
await _waitUntilFrame(() => SchedulerBinding.instance.transientCallbackCount == 0);
|
|
|
|
await _waitUntilFrame(() => finder.precache());
|
|
|
|
if (frameSync)
|
|
await _waitUntilFrame(() => SchedulerBinding.instance.transientCallbackCount == 0);
|
|
|
|
return finder;
|
|
}
|
|
|
|
Future<Null> tap(Finder finder) async {
|
|
await _controller.tap(await _waitForElement(finder));
|
|
}
|
|
|
|
Future<Null> scrollIntoView(Finder finder, {double alignment}) async {
|
|
final Finder target = await _waitForElement(finder);
|
|
await Scrollable.ensureVisible(target.evaluate().single, duration: const Duration(milliseconds: 100), alignment: alignment);
|
|
}
|
|
}
|