diff --git a/packages/google_identity_services_web/CHANGELOG.md b/packages/google_identity_services_web/CHANGELOG.md index 74323f88c30..1f8f8b4c2c7 100644 --- a/packages/google_identity_services_web/CHANGELOG.md +++ b/packages/google_identity_services_web/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.3.3+1 + +* Handles potential exceptions gracefully while fetching `Moment*Reason` for invalid value. + ## 0.3.3 * Moves all the JavaScript types to extend `JSObject`. diff --git a/packages/google_identity_services_web/README.md b/packages/google_identity_services_web/README.md index 733644af5ba..f82eeb9b372 100644 --- a/packages/google_identity_services_web/README.md +++ b/packages/google_identity_services_web/README.md @@ -93,10 +93,3 @@ Refer to the official documentation site for the latest browser compatibility information of the underlying JS SDK: * **Sign In With Google > [Supported browsers and platforms](https://developers.google.com/identity/gsi/web/guides/supported-browsers)** - -## Testing - -This web-only package uses `dart:test` to test its features. They can be run -with `dart test -p chrome`. - -_(Look at `test/README.md` and `tool/run_tests.dart` for more info.)_ diff --git a/packages/google_identity_services_web/example/integration_test/js_interop_id_test.dart b/packages/google_identity_services_web/example/integration_test/js_interop_id_test.dart index 6c5da4bcd14..c49ed40cf3c 100644 --- a/packages/google_identity_services_web/example/integration_test/js_interop_id_test.dart +++ b/packages/google_identity_services_web/example/integration_test/js_interop_id_test.dart @@ -83,8 +83,11 @@ void main() async { }); group('prompt', () { - testWidgets('supports a moment notification callback', (_) async { + testWidgets( + 'supports a moment notification callback with correct type and reason', + (_) async { id.initialize(IdConfiguration(client_id: 'testing_1-2-3')); + utils.setMockMomentNotification('skipped', 'user_cancel'); final StreamController controller = StreamController(); @@ -93,11 +96,27 @@ void main() async { final PromptMomentNotification moment = await controller.stream.first; - // These defaults are set in mock-gis.js expect(moment.getMomentType(), MomentType.skipped); expect(moment.getSkippedReason(), MomentSkippedReason.user_cancel); }); + testWidgets( + 'supports a moment notification callback while handling invalid reason ' + 'value gracefully', (_) async { + id.initialize(IdConfiguration(client_id: 'testing_1-2-3')); + utils.setMockMomentNotification('skipped', 'random_invalid_reason'); + + final StreamController controller = + StreamController(); + + id.prompt(controller.add); + + final PromptMomentNotification moment = await controller.stream.first; + + expect(moment.getMomentType(), MomentType.skipped); + expect(moment.getSkippedReason(), isNull); + }); + testWidgets('calls config callback with credential response', (_) async { const String expected = 'should_be_a_proper_jwt_token'; utils.setMockCredentialResponse(expected); diff --git a/packages/google_identity_services_web/example/integration_test/utils.dart b/packages/google_identity_services_web/example/integration_test/utils.dart index a75d2d9e9ee..a27cce2f405 100644 --- a/packages/google_identity_services_web/example/integration_test/utils.dart +++ b/packages/google_identity_services_web/example/integration_test/utils.dart @@ -90,12 +90,18 @@ void setMockTokenResponse(TokenClient client, [String? authToken]) { client.setMockTokenResponse(authToken?.toJS); } -/// Allows calling a `setMockCredentialResponse` method (set by mock-gis.js) +/// Allows calling `setMockCredentialResponse` and `setMockMomentNotification` +/// methods (set by mock-gis.js). extension on GoogleAccountsId { external void setMockCredentialResponse( JSString credential, JSString select_by, //ignore: non_constant_identifier_names ); + + external void setMockMomentNotification( + JSString momentType, + JSString reason, + ); } /// Sets a mock credential response in `google.accounts.id`. @@ -103,6 +109,12 @@ void setMockCredentialResponse([String value = 'default_value']) { _getGoogleAccountsId().setMockCredentialResponse(value.toJS, 'auto'.toJS); } +/// Sets a mock moment notification in `google.accounts.id`. +void setMockMomentNotification(String momentType, String reason) { + _getGoogleAccountsId() + .setMockMomentNotification(momentType.toJS, reason.toJS); +} + GoogleAccountsId _getGoogleAccountsId() { return _getDeepProperty( web.window as JSObject, 'google.accounts.id'); diff --git a/packages/google_identity_services_web/example/web/mock-gis.js b/packages/google_identity_services_web/example/web/mock-gis.js index 5921c5eb89f..e99ac6347ee 100644 --- a/packages/google_identity_services_web/example/web/mock-gis.js +++ b/packages/google_identity_services_web/example/web/mock-gis.js @@ -22,9 +22,6 @@ class PromptMomentNotification { isNotDisplayed() { return this.isDisplayMoment() && this.reason; } } -const CREDENTIAL_RETURNED = new PromptMomentNotification("dismissed", "credential_returned"); -const USER_CANCEL = new PromptMomentNotification("skipped", "user_cancel"); - function callAsync(func, timeout = 100) { window.setTimeout(func, timeout) } @@ -47,11 +44,11 @@ class Id { if (callback) { callback(this.mockCredentialResponse); } - if (momentListener) { - momentListener(CREDENTIAL_RETURNED); + } + if (momentListener) { + if (this.mockMomentNotification) { + momentListener(this.mockMomentNotification); } - } else if (momentListener) { - momentListener(USER_CANCEL); } }); } @@ -61,11 +58,15 @@ class Id { select_by: select_by, }; } + setMockMomentNotification(momentType, reason) { + this.mockMomentNotification = new PromptMomentNotification(momentType, reason); + } disableAutoSelect() {} storeCredential() {} cancel() {} revoke(hint, callback) { this.mockCredentialResponse = null; + this.mockMomentNotification = null; if (!callback) { return; } diff --git a/packages/google_identity_services_web/lib/src/js_interop/shared.dart b/packages/google_identity_services_web/lib/src/js_interop/shared.dart index a5645038326..ea762b457fb 100644 --- a/packages/google_identity_services_web/lib/src/js_interop/shared.dart +++ b/packages/google_identity_services_web/lib/src/js_interop/shared.dart @@ -3,11 +3,18 @@ // found in the LICENSE file. /// Attempts to retrieve an enum value from [haystack] if [needle] is not null. +/// +/// Returns `null` if no enum value in [haystack] matches [needle]. T? maybeEnum(String? needle, List haystack) { if (needle == null) { return null; } - return haystack.byName(needle); + for (final T value in haystack) { + if (value.name == needle) { + return value; + } + } + return null; } /// The type of several functions from the library, that don't receive diff --git a/packages/google_identity_services_web/pubspec.yaml b/packages/google_identity_services_web/pubspec.yaml index cedb0e5b194..4433fc6c6e0 100644 --- a/packages/google_identity_services_web/pubspec.yaml +++ b/packages/google_identity_services_web/pubspec.yaml @@ -2,7 +2,7 @@ name: google_identity_services_web description: A Dart JS-interop layer for Google Identity Services. Google's new sign-in SDK for Web that supports multiple types of credentials. repository: https://github.com/flutter/packages/tree/main/packages/google_identity_services_web issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+google_identiy_services_web%22 -version: 0.3.3 +version: 0.3.3+1 environment: sdk: ^3.4.0 diff --git a/packages/google_identity_services_web/test/README.md b/packages/google_identity_services_web/test/README.md index 38faf114033..5166f0e2459 100644 --- a/packages/google_identity_services_web/test/README.md +++ b/packages/google_identity_services_web/test/README.md @@ -1,6 +1,6 @@ # Tests -Use `dart run tool/run_tests.dart` to run tests in this package. +Use `dart test -p chrome .dart` to run tests in this package. ## Failed to run Chrome: No such file or directory