Add integration test for the Platform Services app (#8826)

diff --git a/dev/devicelab/bin/tasks/platform_services_test.dart b/dev/devicelab/bin/tasks/platform_services_test.dart
new file mode 100644
index 0000000..d1afc67
--- /dev/null
+++ b/dev/devicelab/bin/tasks/platform_services_test.dart
@@ -0,0 +1,14 @@
+// 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/tasks/perf_tests.dart';
+import 'package:flutter_devicelab/framework/adb.dart';
+import 'package:flutter_devicelab/framework/framework.dart';
+
+Future<Null> main() async {
+  deviceOperatingSystem = DeviceOperatingSystem.android;
+  await task(createPlatformServiceDriverTest());
+}
diff --git a/dev/devicelab/bin/tasks/platform_services_test_ios.dart b/dev/devicelab/bin/tasks/platform_services_test_ios.dart
new file mode 100644
index 0000000..07760fb
--- /dev/null
+++ b/dev/devicelab/bin/tasks/platform_services_test_ios.dart
@@ -0,0 +1,14 @@
+// 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/tasks/perf_tests.dart';
+import 'package:flutter_devicelab/framework/adb.dart';
+import 'package:flutter_devicelab/framework/framework.dart';
+
+Future<Null> main() async {
+  deviceOperatingSystem = DeviceOperatingSystem.ios;
+  await task(createPlatformServiceDriverTest());
+}
diff --git a/dev/devicelab/lib/tasks/perf_tests.dart b/dev/devicelab/lib/tasks/perf_tests.dart
index d8c18f3..440f78b 100644
--- a/dev/devicelab/lib/tasks/perf_tests.dart
+++ b/dev/devicelab/lib/tasks/perf_tests.dart
@@ -9,6 +9,14 @@
 import '../framework/framework.dart';
 import '../framework/utils.dart';
 
+
+TaskFunction createPlatformServiceDriverTest() {
+  return new DriverTest(
+      '${flutterDirectory.path}/examples/platform_services',
+      'test_driver/button_tap.dart',
+  );
+}
+
 TaskFunction createComplexLayoutScrollPerfTest() {
   return new PerfTest(
     '${flutterDirectory.path}/dev/benchmarks/complex_layout',
@@ -152,6 +160,39 @@
   }
 }
 
+
+class DriverTest {
+
+  DriverTest(this.testDirectory, this.testTarget);
+
+  final String testDirectory;
+  final String testTarget;
+
+  Future<TaskResult> call() {
+    return inDirectory(testDirectory, () async {
+      final Device device = await devices.workingDevice;
+      await device.unlock();
+      final String deviceId = device.deviceId;
+      await flutter('packages', options: <String>['get']);
+
+      if (deviceOperatingSystem == DeviceOperatingSystem.ios) {
+        // This causes an Xcode project to be created.
+        await flutter('build', options: <String>['ios', '--profile']);
+      }
+
+      await flutter('drive', options: <String>[
+        '-v',
+        '-t',
+        testTarget,
+        '-d',
+        deviceId,
+      ]);
+
+      return new TaskResult.success(null);
+    });
+  }
+}
+
 class BuildTest {
 
   BuildTest(this.testDirectory);
diff --git a/dev/devicelab/manifest.yaml b/dev/devicelab/manifest.yaml
index 8830c5c..8561cf2 100644
--- a/dev/devicelab/manifest.yaml
+++ b/dev/devicelab/manifest.yaml
@@ -83,6 +83,12 @@
     stage: devicelab
     required_agent_capabilities: ["has-android-device"]
 
+  platform_services_test:
+    description: >
+     Runs a driver test on the Platform Services sample app on Android.
+    stage: devicelab
+    required_agent_capabilities: ["has-android-device"]
+
   flutter_gallery__start_up:
     description: >
       Measures the startup time of the Flutter Gallery app on Android.
@@ -138,9 +144,14 @@
     stage: devicelab
     required_agent_capabilities: ["has-android-device"]
 
-
   # iOS on-device tests
 
+  platform_services_test_ios:
+    description: >
+      Runs a driver test on the Platform Services sample app on iOS.
+    stage: devicelab_ios
+    required_agent_capabilities: ["has-ios-device"]
+
   complex_layout_scroll_perf_ios__timeline_summary:
     description: >
       Measures the runtime performance of the Complex Layout sample app on
diff --git a/examples/platform_services/lib/main.dart b/examples/platform_services/lib/main.dart
index 3109791..63f15c5 100644
--- a/examples/platform_services/lib/main.dart
+++ b/examples/platform_services/lib/main.dart
@@ -14,7 +14,7 @@
 
 class _PlatformServicesState extends State<PlatformServices> {
   static const PlatformMethodChannel platform = const PlatformMethodChannel('battery');
-  String _batteryLevel = 'Unknown battery level.';
+  String _batteryLevel = '';
 
   Future<Null> _getBatteryLevel() async {
     String batteryLevel;
@@ -40,7 +40,7 @@
               child: new Text('Get Battery Level'),
               onPressed: _getBatteryLevel,
             ),
-            new Text(_batteryLevel),
+            new Text(_batteryLevel, key: new Key('Battery level label')),
           ],
         ),
       ),
diff --git a/examples/platform_services/pubspec.yaml b/examples/platform_services/pubspec.yaml
index a889233..fd42143 100644
--- a/examples/platform_services/pubspec.yaml
+++ b/examples/platform_services/pubspec.yaml
@@ -7,6 +7,8 @@
 dev_dependencies:
   flutter_test:
     sdk: flutter
+  flutter_driver:
+    path: ../../packages/flutter_driver
 
 flutter:
   uses-material-design: true
diff --git a/examples/platform_services/test_driver/button_tap.dart b/examples/platform_services/test_driver/button_tap.dart
new file mode 100644
index 0000000..35b7d82
--- /dev/null
+++ b/examples/platform_services/test_driver/button_tap.dart
@@ -0,0 +1,11 @@
+// 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/driver_extension.dart';
+import 'package:platform_services/main.dart' as app;
+
+void main() {
+  enableFlutterDriverExtension();
+  app.main();
+}
diff --git a/examples/platform_services/test_driver/button_tap_test.dart b/examples/platform_services/test_driver/button_tap_test.dart
new file mode 100644
index 0000000..cf6601e
--- /dev/null
+++ b/examples/platform_services/test_driver/button_tap_test.dart
@@ -0,0 +1,36 @@
+// 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('button tap test', () {
+    FlutterDriver driver;
+
+    setUpAll(() async {
+      driver = await FlutterDriver.connect();
+    });
+
+    tearDownAll(() async {
+      if (driver != null)
+        driver.close();
+    });
+
+    test('tap on the button, verify result', () async {
+        final SerializableFinder batteryLevelLabel = find.byValueKey('Battery level label');
+        expect(batteryLevelLabel, isNotNull);
+
+        final SerializableFinder button = find.text('Get Battery Level');
+        await driver.waitFor(button);
+        await driver.tap(button);
+
+        String batteryLevel;
+        while(batteryLevel == null || batteryLevel.isEmpty) {
+          batteryLevel = await driver.getText(batteryLevelLabel);
+        }
+        expect(batteryLevel, isNotEmpty);
+    });
+  });
+}
\ No newline at end of file