Commit f1f5d4f3 authored by Sarah Zakarias's avatar Sarah Zakarias Committed by GitHub

Add integration test for platform interaction (#11580)

parent 4f610617
// 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_devicelab/framework/adb.dart';
import 'package:flutter_devicelab/framework/framework.dart';
import 'package:flutter_devicelab/tasks/integration_tests.dart';
Future<Null> main() async {
deviceOperatingSystem = DeviceOperatingSystem.android;
await task(createPlatformInteractionTest());
}
// 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_devicelab/framework/adb.dart';
import 'package:flutter_devicelab/framework/framework.dart';
import 'package:flutter_devicelab/tasks/integration_tests.dart';
Future<Null> main() async {
deviceOperatingSystem = DeviceOperatingSystem.ios;
await task(createPlatformInteractionTest());
}
...@@ -16,6 +16,13 @@ TaskFunction createChannelsIntegrationTest() { ...@@ -16,6 +16,13 @@ TaskFunction createChannelsIntegrationTest() {
); );
} }
TaskFunction createPlatformInteractionTest() {
return new DriverTest(
'${flutterDirectory.path}/dev/integration_tests/platform_interaction',
'lib/main.dart',
);
}
TaskFunction createPlatformChannelSampleTest() { TaskFunction createPlatformChannelSampleTest() {
return new DriverTest( return new DriverTest(
'${flutterDirectory.path}/examples/platform_channel', '${flutterDirectory.path}/examples/platform_channel',
......
...@@ -65,6 +65,12 @@ tasks: ...@@ -65,6 +65,12 @@ tasks:
stage: devicelab stage: devicelab
required_agent_capabilities: ["has-android-device"] required_agent_capabilities: ["has-android-device"]
platform_interaction_test:
description: >
Checks platform interaction on Android.
stage: devicelab
required_agent_capabilities: ["has-android-device"]
platform_channel_sample_test: platform_channel_sample_test:
description: > description: >
Runs a driver test on the Platform Channel sample app on Android. Runs a driver test on the Platform Channel sample app on Android.
...@@ -161,6 +167,12 @@ tasks: ...@@ -161,6 +167,12 @@ tasks:
stage: devicelab_ios stage: devicelab_ios
required_agent_capabilities: ["has-ios-device"] required_agent_capabilities: ["has-ios-device"]
platform_interaction_test_ios:
description: >
Checks platform interaction on iOS.
stage: devicelab_ios
required_agent_capabilities: ["has-ios-device"]
platform_channel_sample_test_ios: platform_channel_sample_test_ios:
description: > description: >
Runs a driver test on the Platform Channel sample app on iOS. Runs a driver test on the Platform Channel sample app on iOS.
......
...@@ -91,7 +91,6 @@ ...@@ -91,7 +91,6 @@
9740EEB11CF90186004384FC /* Flutter */, 9740EEB11CF90186004384FC /* Flutter */,
97C146F01CF9000F007C117D /* Runner */, 97C146F01CF9000F007C117D /* Runner */,
97C146EF1CF9000F007C117D /* Products */, 97C146EF1CF9000F007C117D /* Products */,
CF3B75C9A7D2FA2A4C99F110 /* Frameworks */,
); );
sourceTree = "<group>"; sourceTree = "<group>";
}; };
......
.DS_Store
.atom/
.idea
.packages
.pub/
build/
ios/.generated/
packages
pubspec.lock
.flutter-plugins
# platform_interaction
Integration test of platform interaction.
*.iml
.gradle
/local.properties
/.idea/workspace.xml
/.idea/libraries
.DS_Store
/build
/captures
GeneratedPluginRegistrant.java
gradle-wrapper.jar
/gradlew
/gradlew.bat
def localProperties = new Properties()
def localPropertiesFile = rootProject.file('local.properties')
if (localPropertiesFile.exists()) {
localPropertiesFile.withInputStream { stream ->
localProperties.load(stream)
}
}
def flutterRoot = localProperties.getProperty('flutter.sdk')
if (flutterRoot == null) {
throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.")
}
apply plugin: 'com.android.application'
apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
android {
compileSdkVersion 25
buildToolsVersion '25.0.3'
lintOptions {
disable 'InvalidPackage'
}
defaultConfig {
minSdkVersion 16
targetSdkVersion 25
versionCode 1
versionName "0.0.1"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
// TODO: Add your own signing config for the release build.
// Signing with the debug keys for now, so `flutter run --release` works.
signingConfig signingConfigs.debug
}
}
aaptOptions {
// TODO(goderbauer): remove when https://github.com/flutter/flutter/issues/8986 is resolved.
if(System.getenv("FLUTTER_CI_WIN")) {
println "AAPT cruncher disabled when running on Win CI."
cruncherEnabled false
}
}
}
flutter {
source '../..'
}
dependencies {
androidTestCompile 'com.android.support:support-annotations:25.4.0'
androidTestCompile 'com.android.support.test:runner:0.5'
androidTestCompile 'com.android.support.test:rules:0.5'
}
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.yourcompany.platforminteraction">
<!-- The INTERNET permission is required for development. Specifically,
flutter needs it to communicate with the running application
to allow setting breakpoints, to provide hot reload, etc.
-->
<uses-permission android:name="android.permission.INTERNET"/>
<!-- io.flutter.app.FlutterApplication is an android.app.Application that
calls FlutterMain.startInitialization(this); in its onCreate method.
In most cases you can leave this as-is, but you if you want to provide
additional functionality it is fine to subclass or reimplement
FlutterApplication and put your custom class here. -->
<application android:name="io.flutter.app.FlutterApplication" android:label="Platform Interaction" android:icon="@mipmap/ic_launcher">
<activity android:name="com.yourcompany.platforminteraction.MainActivity"
android:launchMode="singleTop"
android:theme="@android:style/Theme.Black.NoTitleBar"
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection"
android:hardwareAccelerated="true"
android:windowSoftInputMode="adjustResize">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
</application>
</manifest>
// 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.
package com.yourcompany.platforminteraction;
import android.os.Bundle;
import io.flutter.app.FlutterActivity;
import io.flutter.plugin.common.*;
import io.flutter.plugins.GeneratedPluginRegistrant;
public class MainActivity extends FlutterActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
GeneratedPluginRegistrant.registerWith(this);
}
public void finish() {
BasicMessageChannel channel =
new BasicMessageChannel<>(getFlutterView(), "navigation-test", StringCodec.INSTANCE);
channel.send("ping");
}
}
buildscript {
repositories {
jcenter()
maven {
url "https://maven.google.com"
}
}
dependencies {
classpath 'com.android.tools.build:gradle:2.3.3'
}
}
allprojects {
repositories {
jcenter()
maven {
url "https://maven.google.com"
}
}
}
rootProject.buildDir = '../build'
subprojects {
project.buildDir = "${rootProject.buildDir}/${project.name}"
project.evaluationDependsOn(':app')
}
task clean(type: Delete) {
delete rootProject.buildDir
}
#Fri Jun 23 08:50:38 CEST 2017
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-3.3-all.zip
include ':app'
def flutterProjectRoot = rootProject.projectDir.parentFile.toPath()
def plugins = new Properties()
def pluginsFile = new File(flutterProjectRoot.toFile(), '.flutter-plugins')
if (pluginsFile.exists()) {
pluginsFile.withInputStream { stream -> plugins.load(stream) }
}
plugins.each { name, path ->
def pluginDirectory = flutterProjectRoot.resolve(path).resolve('android').toFile()
include ":$name"
project(":$name").projectDir = pluginDirectory
}
.idea/
.vagrant/
.sconsign.dblite
.svn/
.DS_Store
*.swp
profile
DerivedData/
build/
GeneratedPluginRegistrant.h
GeneratedPluginRegistrant.m
*.pbxuser
*.mode1v3
*.mode2v3
*.perspectivev3
!default.pbxuser
!default.mode1v3
!default.mode2v3
!default.perspectivev3
xcuserdata
*.moved-aside
*.pyc
*sync/
Icon?
.tags*
/Flutter/app.flx
/Flutter/app.zip
/Flutter/App.framework
/Flutter/Flutter.framework
/Flutter/Generated.xcconfig
/ServiceDefinitions.json
Pods/
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
<string>App</string>
<key>CFBundleIdentifier</key>
<string>io.flutter.flutter.app</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>App</string>
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>1.0</string>
<key>UIRequiredDeviceCapabilities</key>
<array>
<string>arm64</string>
</array>
<key>MinimumOSVersion</key>
<string>8.0</string>
</dict>
</plist>
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "group:Runner.xcodeproj">
</FileRef>
</Workspace>
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0830"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "97C146ED1CF9000F007C117D"
BuildableName = "Runner.app"
BlueprintName = "Runner"
ReferencedContainer = "container:Runner.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
</Testables>
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "97C146ED1CF9000F007C117D"
BuildableName = "Runner.app"
BlueprintName = "Runner"
ReferencedContainer = "container:Runner.xcodeproj">
</BuildableReference>
</MacroExpansion>
<AdditionalOptions>
</AdditionalOptions>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "97C146ED1CF9000F007C117D"
BuildableName = "Runner.app"
BlueprintName = "Runner"
ReferencedContainer = "container:Runner.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
<AdditionalOptions>
</AdditionalOptions>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "97C146ED1CF9000F007C117D"
BuildableName = "Runner.app"
BlueprintName = "Runner"
ReferencedContainer = "container:Runner.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "group:Runner.xcodeproj">
</FileRef>
</Workspace>
// 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 <UIKit/UIKit.h>
#import <Flutter/Flutter.h>
@interface AppDelegate : FlutterAppDelegate
@end
// 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.
#include "AppDelegate.h"
#include "GeneratedPluginRegistrant.h"
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
[GeneratedPluginRegistrant registerWithRegistry:self];
return [super application:application didFinishLaunchingWithOptions:launchOptions];
}
@end
{
"images" : [
{
"size" : "20x20",
"idiom" : "iphone",
"filename" : "Icon-App-20x20@2x.png",
"scale" : "2x"
},
{
"size" : "20x20",
"idiom" : "iphone",
"filename" : "Icon-App-20x20@3x.png",
"scale" : "3x"
},
{
"size" : "29x29",
"idiom" : "iphone",
"filename" : "Icon-App-29x29@1x.png",
"scale" : "1x"
},
{
"size" : "29x29",
"idiom" : "iphone",
"filename" : "Icon-App-29x29@2x.png",
"scale" : "2x"
},
{
"size" : "29x29",
"idiom" : "iphone",
"filename" : "Icon-App-29x29@3x.png",
"scale" : "3x"
},
{
"size" : "40x40",
"idiom" : "iphone",
"filename" : "Icon-App-40x40@2x.png",
"scale" : "2x"
},
{
"size" : "40x40",
"idiom" : "iphone",
"filename" : "Icon-App-40x40@3x.png",
"scale" : "3x"
},
{
"size" : "60x60",
"idiom" : "iphone",
"filename" : "Icon-App-60x60@2x.png",
"scale" : "2x"
},
{
"size" : "60x60",
"idiom" : "iphone",
"filename" : "Icon-App-60x60@3x.png",
"scale" : "3x"
},
{
"size" : "20x20",
"idiom" : "ipad",
"filename" : "Icon-App-20x20@1x.png",
"scale" : "1x"
},
{
"size" : "20x20",
"idiom" : "ipad",
"filename" : "Icon-App-20x20@2x.png",
"scale" : "2x"
},
{
"size" : "29x29",
"idiom" : "ipad",
"filename" : "Icon-App-29x29@1x.png",
"scale" : "1x"
},
{
"size" : "29x29",
"idiom" : "ipad",
"filename" : "Icon-App-29x29@2x.png",
"scale" : "2x"
},
{
"size" : "40x40",
"idiom" : "ipad",
"filename" : "Icon-App-40x40@1x.png",
"scale" : "1x"
},
{
"size" : "40x40",
"idiom" : "ipad",
"filename" : "Icon-App-40x40@2x.png",
"scale" : "2x"
},
{
"size" : "76x76",
"idiom" : "ipad",
"filename" : "Icon-App-76x76@1x.png",
"scale" : "1x"
},
{
"size" : "76x76",
"idiom" : "ipad",
"filename" : "Icon-App-76x76@2x.png",
"scale" : "2x"
},
{
"size" : "83.5x83.5",
"idiom" : "ipad",
"filename" : "Icon-App-83.5x83.5@2x.png",
"scale" : "2x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="10117" systemVersion="15F34" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" initialViewController="01J-lp-oVM">
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="10085"/>
</dependencies>
<scenes>
<!--View Controller-->
<scene sceneID="EHf-IW-A2E">
<objects>
<viewController id="01J-lp-oVM" sceneMemberID="viewController">
<layoutGuides>
<viewControllerLayoutGuide type="top" id="Llm-lL-Icb"/>
<viewControllerLayoutGuide type="bottom" id="xb3-aO-Qok"/>
</layoutGuides>
<view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3">
<rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
</view>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="53" y="375"/>
</scene>
</scenes>
</document>
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="12121" systemVersion="16G29" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="hIq-15-ITu">
<device id="retina4_7" orientation="portrait">
<adaptation id="fullscreen"/>
</device>
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="12089"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<scenes>
<!--Flutter View Controller-->
<scene sceneID="tne-QT-ifu">
<objects>
<viewController id="BYZ-38-t0r" customClass="FlutterViewController" sceneMemberID="viewController">
<layoutGuides>
<viewControllerLayoutGuide type="top" id="y3c-jy-aDJ"/>
<viewControllerLayoutGuide type="bottom" id="wfy-db-euE"/>
</layoutGuides>
<view key="view" contentMode="scaleToFill" id="8bC-Xf-vdC">
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</view>
<navigationItem key="navigationItem" id="GUu-dA-3Cs"/>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="1055.2" y="123.68815592203899"/>
</scene>
<!--Test Navigation Controller-->
<scene sceneID="dG3-WE-vKQ">
<objects>
<navigationController automaticallyAdjustsScrollViewInsets="NO" id="hIq-15-ITu" customClass="TestNavigationController" sceneMemberID="viewController">
<toolbarItems/>
<navigationBar key="navigationBar" contentMode="scaleToFill" id="Tam-uN-fcI">
<rect key="frame" x="0.0" y="0.0" width="375" height="44"/>
<autoresizingMask key="autoresizingMask"/>
</navigationBar>
<nil name="viewControllers"/>
<connections>
<segue destination="BYZ-38-t0r" kind="relationship" relationship="rootViewController" id="0aD-1I-Wci"/>
</connections>
</navigationController>
<placeholder placeholderIdentifier="IBFirstResponder" id="8XK-Xi-qiO" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="189.59999999999999" y="777.66116941529242"/>
</scene>
</scenes>
</document>
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>platforminteraction</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>1</string>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>UILaunchStoryboardName</key>
<string>LaunchScreen</string>
<key>UIMainStoryboardFile</key>
<string>Main</string>
<key>UIRequiredDeviceCapabilities</key>
<array>
<string>arm64</string>
</array>
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>UISupportedInterfaceOrientations~ipad</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationPortraitUpsideDown</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>UIViewControllerBasedStatusBarAppearance</key>
<false/>
</dict>
</plist>
// 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 <UIKit/UIKit.h>
@interface TestNavigationController: UINavigationController
@end
// 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 <Foundation/Foundation.h>
#import "TestNavigationController.h"
#import <Flutter/Flutter.h>
@implementation TestNavigationController
- (void) viewWillAppear:(BOOL)animated {
[self setNavigationBarHidden:YES animated:NO];
[super viewWillAppear:animated];
}
- (nullable UIViewController *)popViewControllerAnimated:(BOOL)animated {
FlutterViewController* root = (FlutterViewController*)[self.viewControllers objectAtIndex:0];
FlutterBasicMessageChannel* messageChannel =
[FlutterBasicMessageChannel messageChannelWithName:@"navigation-test"
binaryMessenger:root
codec:[FlutterStringCodec sharedInstance]];
[messageChannel sendMessage:@"ping"];
return root;
}
@end
// 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 <UIKit/UIKit.h>
#import <Flutter/Flutter.h>
#import "AppDelegate.h"
int main(int argc, char * argv[]) {
@autoreleasepool {
return UIApplicationMain(argc, argv, nil,
NSStringFromClass([AppDelegate class]));
}
}
// 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/material.dart';
import 'package:flutter_driver/driver_extension.dart';
import 'src/system_navigation.dart';
import 'src/test_step.dart';
void main() {
enableFlutterDriverExtension();
runApp(new TestApp());
}
class TestApp extends StatefulWidget {
@override
_TestAppState createState() => new _TestAppState();
}
class _TestAppState extends State<TestApp> {
static final List<TestStep> steps = <TestStep>[
() => systemNavigatorPop(),
];
Future<TestStepResult> _result;
int _step = 0;
@override
void initState() {
super.initState();
}
void _executeNextStep() {
setState(() {
if (_step < steps.length)
_result = steps[_step++]();
else
_result = new Future<TestStepResult>.value(TestStepResult.complete);
});
}
Widget _buildTestResultWidget(
BuildContext context,
AsyncSnapshot<TestStepResult> snapshot,
) {
return new TestStepResult.fromSnapshot(snapshot).asWidget(context);
}
@override
Widget build(BuildContext context) {
return new MaterialApp(
title: 'Platform Interaction Test',
home: new Scaffold(
appBar: new AppBar(
title: const Text('Platform Interaction Test'),
),
body: new Padding(
padding: const EdgeInsets.all(20.0),
child: new FutureBuilder<TestStepResult>(
future: _result,
builder: _buildTestResultWidget,
),
),
floatingActionButton: new FloatingActionButton(
key: const ValueKey<String>('step'),
onPressed: _executeNextStep,
child: const Icon(Icons.navigate_next),
),
),
);
}
}
// 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 'test_step.dart';
Future<TestStepResult> systemNavigatorPop() {
const BasicMessageChannel<String> channel = const BasicMessageChannel<String>(
'navigation-test',
const StringCodec(),
);
final Completer<TestStepResult> completer = new Completer<TestStepResult>();
channel.setMessageHandler((String message) async {
completer.complete(
new TestStepResult('System navigation pop', '', TestStatus.ok));
return '';
});
SystemNavigator.pop();
return completer.future;
}
// 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/material.dart';
enum TestStatus { ok, pending, failed, complete }
typedef Future<TestStepResult> TestStep();
const String nothing = '-';
class TestStepResult {
static const TextStyle bold = const TextStyle(fontWeight: FontWeight.bold);
static const TestStepResult complete = const TestStepResult(
'Test complete',
nothing,
TestStatus.complete,
);
const TestStepResult(this.name, this.description, this.status);
factory TestStepResult.fromSnapshot(AsyncSnapshot<TestStepResult> snapshot) {
switch (snapshot.connectionState) {
case ConnectionState.none:
return const TestStepResult('Not started', nothing, TestStatus.ok);
case ConnectionState.waiting:
return const TestStepResult('Executing', nothing, TestStatus.pending);
case ConnectionState.done:
if (snapshot.hasData) {
return snapshot.data;
} else {
final TestStepResult result = snapshot.error;
return result;
}
break;
default:
throw 'Unsupported state ${snapshot.connectionState}';
}
}
final String name;
final String description;
final TestStatus status;
Widget asWidget(BuildContext context) {
return new Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
new Text('Step: $name', style: bold),
new Text(description),
const Text(' '),
new Text(
status.toString().substring('TestStatus.'.length),
key: new ValueKey<String>(
status == TestStatus.pending ? 'nostatus' : 'status'),
style: bold,
),
],
);
}
}
name: platform_interaction
description: Integration test for platform interactions.
dependencies:
flutter:
sdk: flutter
flutter_driver:
sdk: flutter
flutter:
uses-material-design: true
// 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 'package:flutter_driver/flutter_driver.dart';
import 'package:test/test.dart';
void main() {
group('channel suite', () {
FlutterDriver driver;
setUpAll(() async {
driver = await FlutterDriver.connect();
});
test('step through', () async {
final SerializableFinder stepButton = find.byValueKey('step');
final SerializableFinder statusField = find.byValueKey('status');
int step = 0;
while (await driver.getText(statusField) == 'ok') {
await driver.tap(stepButton);
step++;
}
final String status = await driver.getText(statusField);
if (status != 'complete') {
fail('Failed at step $step with status $status');
}
});
tearDownAll(() async {
driver?.close();
});
});
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment