[google_sign_in_web] Ensure plugin throws PlatformExceptions (#2943)
Instead of throwing JS objects, or attempting to access undefined properties.
This change also migrates tests to the `integration_test` package.
diff --git a/packages/google_sign_in/google_sign_in_web/CHANGELOG.md b/packages/google_sign_in/google_sign_in_web/CHANGELOG.md
index 35a6934..d71badc 100644
--- a/packages/google_sign_in/google_sign_in_web/CHANGELOG.md
+++ b/packages/google_sign_in/google_sign_in_web/CHANGELOG.md
@@ -1,3 +1,10 @@
+## 0.9.2
+
+* Throw PlatformExceptions from where the GMaps SDK may throw exceptions: `init()` and `signIn()`.
+* Add two new JS-interop types to be able to unwrap JS errors in release mode.
+* Align the fields of the thrown PlatformExceptions with the mobile version.
+* Migrate tests to run with `flutter drive`
+
## 0.9.1+2
* Update package:e2e reference to use the local version in the flutter/plugins
diff --git a/packages/google_sign_in/google_sign_in_web/README.md b/packages/google_sign_in/google_sign_in_web/README.md
index 930212c..7a44e99 100644
--- a/packages/google_sign_in/google_sign_in_web/README.md
+++ b/packages/google_sign_in/google_sign_in_web/README.md
@@ -98,11 +98,7 @@
Tests are a crucial to contributions to this package. All new contributions should be reasonably tested.
-In order to run tests in this package, do:
-
-```
-flutter test --platform chrome -j1
-```
+**Check the [`test/README.md` file](https://github.com/flutter/plugins/blob/master/packages/google_sign_in/google_sign_in_web/test/README.md)** for more information on how to run tests on this package.
Contributions to this package are welcome. Read the [Contributing to Flutter Plugins](https://github.com/flutter/plugins/blob/master/CONTRIBUTING.md) guide to get started.
diff --git a/packages/google_sign_in/google_sign_in_web/lib/google_sign_in_web.dart b/packages/google_sign_in/google_sign_in_web/lib/google_sign_in_web.dart
index bb43ba1..dd82852 100644
--- a/packages/google_sign_in/google_sign_in_web/lib/google_sign_in_web.dart
+++ b/packages/google_sign_in/google_sign_in_web/lib/google_sign_in_web.dart
@@ -105,16 +105,17 @@
// state of the authentication, i.e: if you logout elsewhere...
isAuthInitialized.complete();
- }), allowInterop((dynamic reason) {
+ }), allowInterop((auth2.GoogleAuthInitFailureError reason) {
// onError
- throw PlatformException(
- code: 'google_sign_in',
- message: reason.error,
- details: reason.details,
- );
+ isAuthInitialized.completeError(PlatformException(
+ code: reason.error,
+ message: reason.details,
+ details:
+ 'https://developers.google.com/identity/sign-in/web/reference#error_codes',
+ ));
}));
- return null;
+ return _isAuthInitialized;
}
@override
@@ -128,8 +129,16 @@
@override
Future<GoogleSignInUserData> signIn() async {
await initialized;
-
- return gapiUserToPluginUserData(await auth2.getAuthInstance().signIn());
+ try {
+ return gapiUserToPluginUserData(await auth2.getAuthInstance().signIn());
+ } on auth2.GoogleAuthSignInError catch (reason) {
+ throw PlatformException(
+ code: reason.error,
+ message: 'Exception raised from GoogleAuth.signIn()',
+ details:
+ 'https://developers.google.com/identity/sign-in/web/reference#error_codes_2',
+ );
+ }
}
@override
diff --git a/packages/google_sign_in/google_sign_in_web/lib/src/generated/gapiauth2.dart b/packages/google_sign_in/google_sign_in_web/lib/src/generated/gapiauth2.dart
index e05bedf..ed7a281 100644
--- a/packages/google_sign_in/google_sign_in_web/lib/src/generated/gapiauth2.dart
+++ b/packages/google_sign_in/google_sign_in_web/lib/src/generated/gapiauth2.dart
@@ -16,6 +16,23 @@
/// <reference types="gapi" />
+@anonymous
+@JS()
+class GoogleAuthInitFailureError {
+ external String get error;
+ external set error(String value);
+
+ external String get details;
+ external set details(String value);
+}
+
+@anonymous
+@JS()
+class GoogleAuthSignInError {
+ external String get error;
+ external set error(String value);
+}
+
// Module gapi.auth2
/// GoogleAuth is a singleton class that provides methods to allow the user to sign in with a Google account,
/// get the user's current sign-in status, get specific data from the user's Google profile,
@@ -30,7 +47,7 @@
/// Calls the onInit function when the GoogleAuth object is fully initialized, or calls the onFailure function if
/// initialization fails.
external dynamic then(dynamic onInit(GoogleAuth googleAuth),
- [dynamic onFailure(dynamic /*{error: string, details: string}*/ reason)]);
+ [dynamic onFailure(GoogleAuthInitFailureError reason)]);
/// Signs out all accounts from the application.
external dynamic signOut();
diff --git a/packages/google_sign_in/google_sign_in_web/pubspec.yaml b/packages/google_sign_in/google_sign_in_web/pubspec.yaml
index 8b48d36..70758ac 100644
--- a/packages/google_sign_in/google_sign_in_web/pubspec.yaml
+++ b/packages/google_sign_in/google_sign_in_web/pubspec.yaml
@@ -2,7 +2,7 @@
description: Flutter plugin for Google Sign-In, a secure authentication system
for signing in with a Google account on Android, iOS and Web.
homepage: https://github.com/flutter/plugins/tree/master/packages/google_sign_in/google_sign_in_web
-version: 0.9.1+2
+version: 0.9.2
flutter:
plugin:
@@ -26,6 +26,8 @@
google_sign_in: ^4.0.14
pedantic: ^1.8.0
mockito: ^4.1.1
+ integration_test:
+ path: ../../integration_test
environment:
sdk: ">=2.6.0 <3.0.0"
diff --git a/packages/google_sign_in/google_sign_in_web/test/README.md b/packages/google_sign_in/google_sign_in_web/test/README.md
new file mode 100644
index 0000000..7c48d02
--- /dev/null
+++ b/packages/google_sign_in/google_sign_in_web/test/README.md
@@ -0,0 +1,17 @@
+# Running browser_tests
+
+Make sure you have updated to the latest Flutter master.
+
+1. Check what version of Chrome is running on the machine you're running tests on.
+
+2. Download and install driver for that version from here:
+ * <https://chromedriver.chromium.org/downloads>
+
+3. Start the driver using `chromedriver --port=4444`
+
+4. Change into the `test` directory of your clone.
+
+5. Run tests: `flutter drive -d web-server --browser-name=chrome --target=test_driver/TEST_NAME_integration.dart`, or (in Linux):
+
+ * Single: `./run_test test_driver/TEST_NAME_integration.dart`
+ * All: `./run_test`
diff --git a/packages/google_sign_in/google_sign_in_web/test/auth2_test.dart b/packages/google_sign_in/google_sign_in_web/test/auth2_test.dart
deleted file mode 100644
index 40bc8a4..0000000
--- a/packages/google_sign_in/google_sign_in_web/test/auth2_test.dart
+++ /dev/null
@@ -1,83 +0,0 @@
-// Copyright 2019 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.
-
-@TestOn('browser')
-
-import 'package:flutter_test/flutter_test.dart';
-import 'package:google_sign_in_platform_interface/google_sign_in_platform_interface.dart';
-import 'package:google_sign_in_web/google_sign_in_web.dart';
-import 'gapi_mocks/gapi_mocks.dart' as gapi_mocks;
-import 'utils.dart';
-
-void main() {
- GoogleSignInTokenData expectedTokenData =
- GoogleSignInTokenData(idToken: '70k3n', accessToken: 'access_70k3n');
-
- GoogleSignInUserData expectedUserData = GoogleSignInUserData(
- displayName: 'Foo Bar',
- email: 'foo@example.com',
- id: '123',
- photoUrl: 'http://example.com/img.jpg',
- idToken: expectedTokenData.idToken,
- );
-
- // The pre-configured use case for the instances of the plugin in this test
- gapiUrl = toBase64Url(gapi_mocks.auth2InitSuccess(expectedUserData));
-
- GoogleSignInPlugin plugin;
-
- setUp(() {
- plugin = GoogleSignInPlugin();
- });
-
- test('Init requires clientId', () async {
- expect(plugin.init(hostedDomain: ''), throwsAssertionError);
- });
-
- test('Init doesn\'t accept spaces in scopes', () async {
- expect(
- plugin.init(
- hostedDomain: '',
- clientId: '',
- scopes: <String>['scope with spaces'],
- ),
- throwsAssertionError);
- });
-
- group('Successful .init, then', () {
- setUp(() async {
- await plugin.init(
- hostedDomain: 'foo',
- scopes: <String>['some', 'scope'],
- clientId: '1234',
- );
- await plugin.initialized;
- });
-
- test('signInSilently', () async {
- GoogleSignInUserData actualUser = await plugin.signInSilently();
-
- expect(actualUser, expectedUserData);
- });
-
- test('signIn', () async {
- GoogleSignInUserData actualUser = await plugin.signIn();
-
- expect(actualUser, expectedUserData);
- });
-
- test('getTokens', () async {
- GoogleSignInTokenData actualToken =
- await plugin.getTokens(email: expectedUserData.email);
-
- expect(actualToken, expectedTokenData);
- });
-
- test('requestScopes', () async {
- bool scopeGranted = await plugin.requestScopes(['newScope']);
-
- expect(scopeGranted, isTrue);
- });
- });
-}
diff --git a/packages/google_sign_in/google_sign_in_web/test/gapi_mocks/src/auth2_init.dart b/packages/google_sign_in/google_sign_in_web/test/gapi_mocks/src/auth2_init.dart
deleted file mode 100644
index 1846033..0000000
--- a/packages/google_sign_in/google_sign_in_web/test/gapi_mocks/src/auth2_init.dart
+++ /dev/null
@@ -1,47 +0,0 @@
-// Copyright 2019 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.
-
-part of gapi_mocks;
-
-// JS mock of a gapi.auth2, with a successfully identified user
-String auth2InitSuccess(GoogleSignInUserData userData) => testIife('''
-${gapi()}
-
-var mockUser = ${googleUser(userData)};
-
-function GapiAuth2() {}
-GapiAuth2.prototype.init = function (initOptions) {
- return {
- then: (onSuccess, onError) => {
- window.setTimeout(() => {
- onSuccess(window.gapi.auth2);
- }, 30);
- },
- currentUser: {
- listen: (cb) => {
- window.setTimeout(() => {
- cb(mockUser);
- }, 30);
- }
- }
- }
-};
-
-GapiAuth2.prototype.getAuthInstance = function () {
- return {
- signIn: () => {
- return new Promise((resolve, reject) => {
- window.setTimeout(() => {
- resolve(mockUser);
- }, 30);
- });
- },
- currentUser: {
- get: () => mockUser,
- },
- }
-};
-
-window.gapi.auth2 = new GapiAuth2();
-''');
diff --git a/packages/google_sign_in/google_sign_in_web/test/lib/main.dart b/packages/google_sign_in/google_sign_in_web/test/lib/main.dart
new file mode 100644
index 0000000..1041520
--- /dev/null
+++ b/packages/google_sign_in/google_sign_in_web/test/lib/main.dart
@@ -0,0 +1,22 @@
+// Copyright 2013 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';
+
+void main() {
+ runApp(MyApp());
+}
+
+/// App for testing
+class MyApp extends StatefulWidget {
+ @override
+ _MyAppState createState() => _MyAppState();
+}
+
+class _MyAppState extends State<MyApp> {
+ @override
+ Widget build(BuildContext context) {
+ return Text('Testing... Look at the console output for results!');
+ }
+}
diff --git a/packages/google_sign_in/google_sign_in_web/test/pubspec.yaml b/packages/google_sign_in/google_sign_in_web/test/pubspec.yaml
new file mode 100644
index 0000000..dd0354e
--- /dev/null
+++ b/packages/google_sign_in/google_sign_in_web/test/pubspec.yaml
@@ -0,0 +1,24 @@
+name: regular_integration_tests
+publish_to: none
+
+environment:
+ sdk: ">=2.2.2 <3.0.0"
+
+dependencies:
+ flutter:
+ sdk: flutter
+
+dev_dependencies:
+ google_sign_in: ^4.5.3
+ flutter_driver:
+ sdk: flutter
+ flutter_test:
+ sdk: flutter
+ http: ^0.12.2
+ mockito: ^4.1.1
+ integration_test:
+ path: ../../../integration_test
+
+dependency_overrides:
+ google_sign_in_web:
+ path: ../
diff --git a/packages/google_sign_in/google_sign_in_web/test/run_test b/packages/google_sign_in/google_sign_in_web/test/run_test
new file mode 100755
index 0000000..74a8526
--- /dev/null
+++ b/packages/google_sign_in/google_sign_in_web/test/run_test
@@ -0,0 +1,17 @@
+#!/usr/bin/bash
+if pgrep -lf chromedriver > /dev/null; then
+ echo "chromedriver is running."
+
+ if [ $# -eq 0 ]; then
+ echo "No target specified, running all tests..."
+ find test_driver/ -iname *_integration.dart | xargs -n1 -i -t flutter drive -d web-server --web-port=7357 --browser-name=chrome --target='{}'
+ else
+ echo "Running test target: $1..."
+ set -x
+ flutter drive -d web-server --web-port=7357 --browser-name=chrome --target=$1
+ fi
+
+ else
+ echo "chromedriver is not running."
+fi
+
diff --git a/packages/google_sign_in/google_sign_in_web/test/test_driver/auth2_integration.dart b/packages/google_sign_in/google_sign_in_web/test/test_driver/auth2_integration.dart
new file mode 100644
index 0000000..e2f16f2
--- /dev/null
+++ b/packages/google_sign_in/google_sign_in_web/test/test_driver/auth2_integration.dart
@@ -0,0 +1,192 @@
+// Copyright 2019 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/services.dart';
+import 'package:integration_test/integration_test.dart';
+
+import 'package:flutter_test/flutter_test.dart';
+import 'package:google_sign_in_platform_interface/google_sign_in_platform_interface.dart';
+import 'package:google_sign_in_web/google_sign_in_web.dart';
+import 'gapi_mocks/gapi_mocks.dart' as gapi_mocks;
+import 'src/test_utils.dart';
+
+void main() {
+ IntegrationTestWidgetsFlutterBinding.ensureInitialized();
+
+ GoogleSignInTokenData expectedTokenData =
+ GoogleSignInTokenData(idToken: '70k3n', accessToken: 'access_70k3n');
+
+ GoogleSignInUserData expectedUserData = GoogleSignInUserData(
+ displayName: 'Foo Bar',
+ email: 'foo@example.com',
+ id: '123',
+ photoUrl: 'http://example.com/img.jpg',
+ idToken: expectedTokenData.idToken,
+ );
+
+ GoogleSignInPlugin plugin;
+
+ group('plugin.init() throws a catchable exception', () {
+ setUp(() {
+ // The pre-configured use case for the instances of the plugin in this test
+ gapiUrl = toBase64Url(gapi_mocks.auth2InitError());
+ plugin = GoogleSignInPlugin();
+ });
+
+ testWidgets('init throws PlatformException', (WidgetTester tester) async {
+ await expectLater(
+ plugin.init(
+ hostedDomain: 'foo',
+ scopes: <String>['some', 'scope'],
+ clientId: '1234',
+ ),
+ throwsA(isA<PlatformException>()));
+ });
+
+ testWidgets('init forwards error code from JS',
+ (WidgetTester tester) async {
+ try {
+ await plugin.init(
+ hostedDomain: 'foo',
+ scopes: <String>['some', 'scope'],
+ clientId: '1234',
+ );
+ fail('plugin.init should have thrown an exception!');
+ } catch (e) {
+ expect(e.code, 'idpiframe_initialization_failed');
+ }
+ });
+ });
+
+ group('other methods also throw catchable exceptions on init fail', () {
+ // This function ensures that init gets called, but for some reason, we
+ // ignored that it has thrown stuff...
+ void _discardInit() async {
+ try {
+ await plugin.init(
+ hostedDomain: 'foo',
+ scopes: <String>['some', 'scope'],
+ clientId: '1234',
+ );
+ } catch (e) {
+ // Noop so we can call other stuff
+ }
+ }
+
+ setUp(() {
+ gapiUrl = toBase64Url(gapi_mocks.auth2InitError());
+ plugin = GoogleSignInPlugin();
+ });
+
+ testWidgets('signInSilently throws', (WidgetTester tester) async {
+ await _discardInit();
+ await expectLater(
+ plugin.signInSilently(), throwsA(isA<PlatformException>()));
+ });
+
+ testWidgets('signIn throws', (WidgetTester tester) async {
+ await _discardInit();
+ await expectLater(plugin.signIn(), throwsA(isA<PlatformException>()));
+ });
+
+ testWidgets('getTokens throws', (WidgetTester tester) async {
+ await _discardInit();
+ await expectLater(plugin.getTokens(email: 'test@example.com'),
+ throwsA(isA<PlatformException>()));
+ });
+ testWidgets('requestScopes', (WidgetTester tester) async {
+ await _discardInit();
+ await expectLater(plugin.requestScopes(['newScope']),
+ throwsA(isA<PlatformException>()));
+ });
+ });
+
+ group('auth2 Init Successful', () {
+ setUp(() {
+ // The pre-configured use case for the instances of the plugin in this test
+ gapiUrl = toBase64Url(gapi_mocks.auth2InitSuccess(expectedUserData));
+ plugin = GoogleSignInPlugin();
+ });
+
+ testWidgets('Init requires clientId', (WidgetTester tester) async {
+ expect(plugin.init(hostedDomain: ''), throwsAssertionError);
+ });
+
+ testWidgets('Init doesn\'t accept spaces in scopes',
+ (WidgetTester tester) async {
+ expect(
+ plugin.init(
+ hostedDomain: '',
+ clientId: '',
+ scopes: <String>['scope with spaces'],
+ ),
+ throwsAssertionError);
+ });
+
+ group('Successful .init, then', () {
+ setUp(() async {
+ await plugin.init(
+ hostedDomain: 'foo',
+ scopes: <String>['some', 'scope'],
+ clientId: '1234',
+ );
+ await plugin.initialized;
+ });
+
+ testWidgets('signInSilently', (WidgetTester tester) async {
+ GoogleSignInUserData actualUser = await plugin.signInSilently();
+
+ expect(actualUser, expectedUserData);
+ });
+
+ testWidgets('signIn', (WidgetTester tester) async {
+ GoogleSignInUserData actualUser = await plugin.signIn();
+
+ expect(actualUser, expectedUserData);
+ });
+
+ testWidgets('getTokens', (WidgetTester tester) async {
+ GoogleSignInTokenData actualToken =
+ await plugin.getTokens(email: expectedUserData.email);
+
+ expect(actualToken, expectedTokenData);
+ });
+
+ testWidgets('requestScopes', (WidgetTester tester) async {
+ bool scopeGranted = await plugin.requestScopes(['newScope']);
+
+ expect(scopeGranted, isTrue);
+ });
+ });
+ });
+
+ group('auth2 Init successful, but exception on signIn() method', () {
+ setUp(() async {
+ // The pre-configured use case for the instances of the plugin in this test
+ gapiUrl = toBase64Url(gapi_mocks.auth2SignInError());
+ plugin = GoogleSignInPlugin();
+ await plugin.init(
+ hostedDomain: 'foo',
+ scopes: <String>['some', 'scope'],
+ clientId: '1234',
+ );
+ await plugin.initialized;
+ });
+
+ testWidgets('User aborts sign in flow, throws PlatformException',
+ (WidgetTester tester) async {
+ await expectLater(plugin.signIn(), throwsA(isA<PlatformException>()));
+ });
+
+ testWidgets('User aborts sign in flow, error code is forwarded from JS',
+ (WidgetTester tester) async {
+ try {
+ await plugin.signIn();
+ fail('plugin.signIn() should have thrown an exception!');
+ } catch (e) {
+ expect(e.code, 'popup_closed_by_user');
+ }
+ });
+ });
+}
diff --git a/packages/google_sign_in/google_sign_in_web/test/test_driver/auth2_integration_test.dart b/packages/google_sign_in/google_sign_in_web/test/test_driver/auth2_integration_test.dart
new file mode 100644
index 0000000..39444c0
--- /dev/null
+++ b/packages/google_sign_in/google_sign_in_web/test/test_driver/auth2_integration_test.dart
@@ -0,0 +1,7 @@
+// 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:integration_test/integration_test_driver.dart';
+
+Future<void> main() async => integrationDriver();
diff --git a/packages/google_sign_in/google_sign_in_web/test/gapi_load_test.dart b/packages/google_sign_in/google_sign_in_web/test/test_driver/gapi_load_integration.dart
similarity index 82%
rename from packages/google_sign_in/google_sign_in_web/test/gapi_load_test.dart
rename to packages/google_sign_in/google_sign_in_web/test/test_driver/gapi_load_integration.dart
index 6703bec..540369c 100644
--- a/packages/google_sign_in/google_sign_in_web/test/gapi_load_test.dart
+++ b/packages/google_sign_in/google_sign_in_web/test/test_driver/gapi_load_integration.dart
@@ -2,21 +2,23 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-@TestOn('browser')
-
import 'dart:html' as html;
+import 'package:integration_test/integration_test.dart';
+
import 'package:flutter_test/flutter_test.dart';
import 'package:google_sign_in_platform_interface/google_sign_in_platform_interface.dart';
import 'package:google_sign_in_web/google_sign_in_web.dart';
import 'gapi_mocks/gapi_mocks.dart' as gapi_mocks;
-import 'utils.dart';
+import 'src/test_utils.dart';
void main() {
+ IntegrationTestWidgetsFlutterBinding.ensureInitialized();
+
gapiUrl = toBase64Url(gapi_mocks.auth2InitSuccess(GoogleSignInUserData()));
- test('Plugin is initialized after GAPI fully loads and init is called',
- () async {
+ testWidgets('Plugin is initialized after GAPI fully loads and init is called',
+ (WidgetTester tester) async {
expect(
html.querySelector('script[src^="data:"]'),
isNull,
diff --git a/packages/google_sign_in/google_sign_in_web/test/test_driver/gapi_load_integration_test.dart b/packages/google_sign_in/google_sign_in_web/test/test_driver/gapi_load_integration_test.dart
new file mode 100644
index 0000000..39444c0
--- /dev/null
+++ b/packages/google_sign_in/google_sign_in_web/test/test_driver/gapi_load_integration_test.dart
@@ -0,0 +1,7 @@
+// 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:integration_test/integration_test_driver.dart';
+
+Future<void> main() async => integrationDriver();
diff --git a/packages/google_sign_in/google_sign_in_web/test/gapi_mocks/gapi_mocks.dart b/packages/google_sign_in/google_sign_in_web/test/test_driver/gapi_mocks/gapi_mocks.dart
similarity index 100%
rename from packages/google_sign_in/google_sign_in_web/test/gapi_mocks/gapi_mocks.dart
rename to packages/google_sign_in/google_sign_in_web/test/test_driver/gapi_mocks/gapi_mocks.dart
diff --git a/packages/google_sign_in/google_sign_in_web/test/test_driver/gapi_mocks/src/auth2_init.dart b/packages/google_sign_in/google_sign_in_web/test/test_driver/gapi_mocks/src/auth2_init.dart
new file mode 100644
index 0000000..79d798a
--- /dev/null
+++ b/packages/google_sign_in/google_sign_in_web/test/test_driver/gapi_mocks/src/auth2_init.dart
@@ -0,0 +1,107 @@
+// Copyright 2019 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.
+
+part of gapi_mocks;
+
+// JS mock of a gapi.auth2, with a successfully identified user
+String auth2InitSuccess(GoogleSignInUserData userData) => testIife('''
+${gapi()}
+
+var mockUser = ${googleUser(userData)};
+
+function GapiAuth2() {}
+GapiAuth2.prototype.init = function (initOptions) {
+ return {
+ then: (onSuccess, onError) => {
+ window.setTimeout(() => {
+ onSuccess(window.gapi.auth2);
+ }, 30);
+ },
+ currentUser: {
+ listen: (cb) => {
+ window.setTimeout(() => {
+ cb(mockUser);
+ }, 30);
+ }
+ }
+ }
+};
+
+GapiAuth2.prototype.getAuthInstance = function () {
+ return {
+ signIn: () => {
+ return new Promise((resolve, reject) => {
+ window.setTimeout(() => {
+ resolve(mockUser);
+ }, 30);
+ });
+ },
+ currentUser: {
+ get: () => mockUser,
+ },
+ }
+};
+
+window.gapi.auth2 = new GapiAuth2();
+''');
+
+String auth2InitError() => testIife('''
+${gapi()}
+
+function GapiAuth2() {}
+GapiAuth2.prototype.init = function (initOptions) {
+ return {
+ then: (onSuccess, onError) => {
+ window.setTimeout(() => {
+ onError({
+ error: 'idpiframe_initialization_failed',
+ details: 'This error was raised from a test.',
+ });
+ }, 30);
+ }
+ }
+};
+
+window.gapi.auth2 = new GapiAuth2();
+''');
+
+String auth2SignInError([String error = 'popup_closed_by_user']) => testIife('''
+${gapi()}
+
+var mockUser = null;
+
+function GapiAuth2() {}
+GapiAuth2.prototype.init = function (initOptions) {
+ return {
+ then: (onSuccess, onError) => {
+ window.setTimeout(() => {
+ onSuccess(window.gapi.auth2);
+ }, 30);
+ },
+ currentUser: {
+ listen: (cb) => {
+ window.setTimeout(() => {
+ cb(mockUser);
+ }, 30);
+ }
+ }
+ }
+};
+
+GapiAuth2.prototype.getAuthInstance = function () {
+ return {
+ signIn: () => {
+ return new Promise((resolve, reject) => {
+ window.setTimeout(() => {
+ reject({
+ error: '${error}'
+ });
+ }, 30);
+ });
+ },
+ }
+};
+
+window.gapi.auth2 = new GapiAuth2();
+''');
diff --git a/packages/google_sign_in/google_sign_in_web/test/gapi_mocks/src/gapi.dart b/packages/google_sign_in/google_sign_in_web/test/test_driver/gapi_mocks/src/gapi.dart
similarity index 100%
rename from packages/google_sign_in/google_sign_in_web/test/gapi_mocks/src/gapi.dart
rename to packages/google_sign_in/google_sign_in_web/test/test_driver/gapi_mocks/src/gapi.dart
diff --git a/packages/google_sign_in/google_sign_in_web/test/gapi_mocks/src/google_user.dart b/packages/google_sign_in/google_sign_in_web/test/test_driver/gapi_mocks/src/google_user.dart
similarity index 100%
rename from packages/google_sign_in/google_sign_in_web/test/gapi_mocks/src/google_user.dart
rename to packages/google_sign_in/google_sign_in_web/test/test_driver/gapi_mocks/src/google_user.dart
diff --git a/packages/google_sign_in/google_sign_in_web/test/gapi_mocks/src/test_iife.dart b/packages/google_sign_in/google_sign_in_web/test/test_driver/gapi_mocks/src/test_iife.dart
similarity index 100%
rename from packages/google_sign_in/google_sign_in_web/test/gapi_mocks/src/test_iife.dart
rename to packages/google_sign_in/google_sign_in_web/test/test_driver/gapi_mocks/src/test_iife.dart
diff --git a/packages/google_sign_in/google_sign_in_web/test/gapi_utils_test.dart b/packages/google_sign_in/google_sign_in_web/test/test_driver/gapi_utils_integration.dart
similarity index 70%
rename from packages/google_sign_in/google_sign_in_web/test/gapi_utils_test.dart
rename to packages/google_sign_in/google_sign_in_web/test/test_driver/gapi_utils_integration.dart
index 2dc49fc..55b9428 100644
--- a/packages/google_sign_in/google_sign_in_web/test/gapi_utils_test.dart
+++ b/packages/google_sign_in/google_sign_in_web/test/test_driver/gapi_utils_integration.dart
@@ -1,10 +1,10 @@
// Copyright 2019 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.
-@TestOn('browser')
-
import 'package:flutter_test/flutter_test.dart';
+import 'package:integration_test/integration_test.dart';
+
import 'package:google_sign_in_web/src/generated/gapiauth2.dart' as gapi;
import 'package:google_sign_in_web/src/utils.dart';
import 'package:mockito/mockito.dart';
@@ -15,6 +15,7 @@
void main() {
// The non-null use cases are covered by the auth2_test.dart file.
+ IntegrationTestWidgetsFlutterBinding.ensureInitialized();
group('gapiUserToPluginUserData', () {
var mockUser;
@@ -23,21 +24,24 @@
mockUser = MockGoogleUser();
});
- test('null user -> null response', () {
+ testWidgets('null user -> null response', (WidgetTester tester) async {
expect(gapiUserToPluginUserData(null), isNull);
});
- test('not signed-in user -> null response', () {
+ testWidgets('not signed-in user -> null response',
+ (WidgetTester tester) async {
when(mockUser.isSignedIn()).thenReturn(false);
expect(gapiUserToPluginUserData(mockUser), isNull);
});
- test('signed-in, but null profile user -> null response', () {
+ testWidgets('signed-in, but null profile user -> null response',
+ (WidgetTester tester) async {
when(mockUser.isSignedIn()).thenReturn(true);
expect(gapiUserToPluginUserData(mockUser), isNull);
});
- test('signed-in, null userId in profile user -> null response', () {
+ testWidgets('signed-in, null userId in profile user -> null response',
+ (WidgetTester tester) async {
when(mockUser.isSignedIn()).thenReturn(true);
when(mockUser.getBasicProfile()).thenReturn(MockBasicProfile());
expect(gapiUserToPluginUserData(mockUser), isNull);
diff --git a/packages/google_sign_in/google_sign_in_web/test/test_driver/gapi_utils_integration_test.dart b/packages/google_sign_in/google_sign_in_web/test/test_driver/gapi_utils_integration_test.dart
new file mode 100644
index 0000000..39444c0
--- /dev/null
+++ b/packages/google_sign_in/google_sign_in_web/test/test_driver/gapi_utils_integration_test.dart
@@ -0,0 +1,7 @@
+// 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:integration_test/integration_test_driver.dart';
+
+Future<void> main() async => integrationDriver();
diff --git a/packages/google_sign_in/google_sign_in_web/test/utils.dart b/packages/google_sign_in/google_sign_in_web/test/test_driver/src/test_utils.dart
similarity index 100%
rename from packages/google_sign_in/google_sign_in_web/test/utils.dart
rename to packages/google_sign_in/google_sign_in_web/test/test_driver/src/test_utils.dart
diff --git a/packages/google_sign_in/google_sign_in_web/test/web/index.html b/packages/google_sign_in/google_sign_in_web/test/web/index.html
new file mode 100644
index 0000000..59a832b
--- /dev/null
+++ b/packages/google_sign_in/google_sign_in_web/test/web/index.html
@@ -0,0 +1,13 @@
+<!DOCTYPE HTML>
+<!-- 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. -->
+<html>
+ <head>
+ <title>Browser Tests</title>
+ </head>
+ <body>
+ <script src="main.dart.js"></script>
+ </body>
+</html>
+