Skip to content

Commit 15584a3

Browse files
authored
[gis_web] Migrate to package:web. (#5581)
* Migrates package to use `package:web` so it can be compiled with WASM. * **Breaking change**: Addresses API mismatches with the latest JS SDK changes. * Adds some tests to client configuration objects. (See CHANGELOG.md for a more thorough list of changes) ## Issues * Fixes: flutter/flutter#138202 * Fixes: flutter/flutter#139167 * Part of: flutter/flutter#139170 ## Tests * Ran unit/integration tests locally, added a couple more. * Tested example apps with `flutter run`, both seem to work. * Tested example apps with `--wasm`, both seem to work.
1 parent 57b7d33 commit 15584a3

21 files changed

+784
-518
lines changed

packages/google_identity_services_web/CHANGELOG.md

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,39 @@
1-
## NEXT
1+
## 0.3.0
22

33
* Updates minimum supported SDK version to Flutter 3.10/Dart 3.0.
4+
* Migrates from `package:js`/`dart:html` to `package:web` so this package can
5+
compile to WASM.
6+
* Performs the following **breaking API changes (in bold)** and other fixes to
7+
align with the published GIS SDK:
8+
* **Removes the need to explicitly `allowInterop` in all callbacks.**
9+
* `id`:
10+
* **Changes type:**
11+
* `IdConfiguration.intermediate_iframe_close_callback` to
12+
`VoidFn?`.
13+
* Adds: `fedcm` to `CredentialSelectBy` enum.
14+
* Fixes typo in `storeCredential` `callback` positional parameter name.
15+
* `oauth2`:
16+
* **Removes:**
17+
* `CodeClientConfig.auto_select`, `hint` (now `login_hint`), and `hosted_domain` (now `hd`).
18+
* `TokenClientConfig.hint` (now `login_hint`) and `hosted_domain` (now `hd`).
19+
* `OverridableTokenClientConfig.hint` (now `login_hint`).
20+
* **Changes types:**
21+
* `CodeClientConfig.redirect_uri` to `Uri?`.
22+
* `scope` in `CodeClientConfig` and `CodeResponse` to `List<String>`.
23+
* `CodeResponse.code` and `state` to `String?` (now nullable).
24+
* `scope` in `TokenClientConfig`, `OverridableTokenClientConfig`, and `TokenResponse` to `List<String>`.
25+
* The following `TokenResponse` getters are now nullable: `access_token`,
26+
`expires_in`, `hd`, `prompt`, `token_type`, and `state`.
27+
* The `error_callback` functions now receive a `GoogleIdentityServicesError` parameter, instead of `Object`.
28+
* Adds:
29+
* `include_granted_scopes` and `enable_granular_consent` to `CodeClientConfig`.
30+
* `include_granted_scopes` and `enable_granular_consent` to `TokenClientConfig`.
31+
* `enable_granular_consent` to `OverridableTokenClientConfig`.
32+
* `message` to `GoogleIdentityServicesError`.
33+
* Fixes:
34+
* Assert that `scope` is not empty when used to create `CodeClientConfig`,
35+
`TokenClientConfig`, and `OverridableTokenClientConfig` instances.
36+
* Deprecated `enable_serial_consent`.
437

538
## 0.2.2
639

packages/google_identity_services_web/example/integration_test/js_interop_id_test.dart

Lines changed: 30 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,17 @@
22
// Use of this source code is governed by a BSD-style license that can be
33
// found in the LICENSE file.
44

5+
// the following ignore is needed for downgraded analyzer (casts to JSObject).
6+
// ignore_for_file: unnecessary_cast
7+
58
import 'dart:async';
9+
import 'dart:js_interop';
610

711
import 'package:flutter_test/flutter_test.dart';
812
import 'package:google_identity_services_web/id.dart';
913
import 'package:integration_test/integration_test.dart';
10-
import 'package:js/js.dart';
11-
import 'package:js/js_util.dart' as js_util show getProperty;
14+
import 'package:web/web.dart' as web;
1215

13-
import 'src/dom.dart';
1416
import 'utils.dart' as utils;
1517

1618
void main() async {
@@ -23,11 +25,12 @@ void main() async {
2325

2426
group('renderButton', () {
2527
testWidgets('supports a js-interop target from any library', (_) async {
26-
final DomElement target = createDomElement('div');
28+
final web.HTMLDivElement target =
29+
web.document.createElement('div') as web.HTMLDivElement;
2730

2831
id.renderButton(target);
2932

30-
final DomElement? button = target.querySelector('button');
33+
final web.Element? button = target.querySelector('button');
3134
expect(button, isNotNull);
3235
});
3336
});
@@ -37,45 +40,46 @@ void main() async {
3740
final IdConfiguration config = IdConfiguration(
3841
client_id: 'testing_1-2-3',
3942
auto_select: false,
40-
callback: allowInterop((_) {}),
43+
callback: (_) {},
4144
login_uri: Uri.parse('https://www.example.com/login'),
42-
native_callback: allowInterop((_) {}),
45+
native_callback: (_) {},
4346
cancel_on_tap_outside: false,
4447
prompt_parent_id: 'some_dom_id',
4548
nonce: 's0m3_r4ndOM_vALu3',
4649
context: OneTapContext.signin,
4750
state_cookie_domain: 'subdomain.example.com',
4851
ux_mode: UxMode.popup,
4952
allowed_parent_origin: <String>['allowed', 'another'],
50-
intermediate_iframe_close_callback: allowInterop((_) {}),
53+
intermediate_iframe_close_callback: () {},
5154
itp_support: true,
5255
login_hint: 'login-hint@example.com',
5356
hd: 'hd_value',
5457
use_fedcm_for_prompt: true,
5558
);
5659

57-
// Save some keystrokes below by partially applying to the 'config' above.
58-
void expectConfigValue(String name, Object? matcher) {
59-
expect(js_util.getProperty(config, name), matcher, reason: name);
60-
}
60+
final utils.ExpectConfigValueFn expectConfigValue =
61+
utils.createExpectConfigValue(config as JSObject);
6162

62-
expectConfigValue('allowed_parent_origin', hasLength(2));
63+
expectConfigValue('client_id', 'testing_1-2-3');
6364
expectConfigValue('auto_select', isFalse);
64-
expectConfigValue('callback', isA<Function>());
65+
expectConfigValue('callback', utils.isAJs('function'));
66+
expectConfigValue('login_uri', 'https://www.example.com/login');
67+
expectConfigValue('native_callback', utils.isAJs('function'));
6568
expectConfigValue('cancel_on_tap_outside', isFalse);
66-
expectConfigValue('client_id', 'testing_1-2-3');
67-
expectConfigValue('context', isA<OneTapContext>());
68-
expectConfigValue('hd', 'hd_value');
69-
expectConfigValue('intermediate_iframe_close_callback', isA<Function>());
70-
expectConfigValue('itp_support', isTrue);
71-
expectConfigValue('login_hint', 'login-hint@example.com');
72-
expectConfigValue('login_uri', isA<Uri>());
73-
expectConfigValue('native_callback', isA<Function>());
74-
expectConfigValue('nonce', 's0m3_r4ndOM_vALu3');
69+
expectConfigValue('allowed_parent_origin', isA<JSArray>());
7570
expectConfigValue('prompt_parent_id', 'some_dom_id');
71+
expectConfigValue('nonce', 's0m3_r4ndOM_vALu3');
72+
expectConfigValue('context', 'signin');
7673
expectConfigValue('state_cookie_domain', 'subdomain.example.com');
74+
expectConfigValue('ux_mode', 'popup');
75+
expectConfigValue(
76+
'allowed_parent_origin', <String>['allowed', 'another']);
77+
expectConfigValue(
78+
'intermediate_iframe_close_callback', utils.isAJs('function'));
79+
expectConfigValue('itp_support', isTrue);
80+
expectConfigValue('login_hint', 'login-hint@example.com');
81+
expectConfigValue('hd', 'hd_value');
7782
expectConfigValue('use_fedcm_for_prompt', isTrue);
78-
expectConfigValue('ux_mode', isA<UxMode>());
7983
});
8084
});
8185

@@ -86,7 +90,7 @@ void main() async {
8690
final StreamController<PromptMomentNotification> controller =
8791
StreamController<PromptMomentNotification>();
8892

89-
id.prompt(allowInterop(controller.add));
93+
id.prompt(controller.add);
9094

9195
final PromptMomentNotification moment = await controller.stream.first;
9296

@@ -104,7 +108,7 @@ void main() async {
104108

105109
id.initialize(IdConfiguration(
106110
client_id: 'testing_1-2-3',
107-
callback: allowInterop(controller.add),
111+
callback: controller.add,
108112
));
109113

110114
id.prompt();

packages/google_identity_services_web/example/integration_test/js_interop_oauth_test.dart

Lines changed: 97 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,15 @@
22
// Use of this source code is governed by a BSD-style license that can be
33
// found in the LICENSE file.
44

5+
// the following ignore is needed for downgraded analyzer (casts to JSObject).
6+
// ignore_for_file: unnecessary_cast
7+
58
import 'dart:async';
9+
import 'dart:js_interop';
610

711
import 'package:flutter_test/flutter_test.dart';
812
import 'package:google_identity_services_web/oauth2.dart';
913
import 'package:integration_test/integration_test.dart';
10-
import 'package:js/js.dart';
1114

1215
import 'utils.dart' as utils;
1316

@@ -19,12 +22,96 @@ void main() async {
1922
await utils.installGisMock();
2023
});
2124

25+
group('Config objects pass values from Dart to JS - ', () {
26+
testWidgets('TokenClientConfig', (_) async {
27+
final TokenClientConfig config = TokenClientConfig(
28+
client_id: 'testing_1-2-3',
29+
callback: (_) {},
30+
scope: <String>['one', 'two', 'three'],
31+
include_granted_scopes: true,
32+
prompt: 'some-prompt',
33+
enable_granular_consent: true,
34+
login_hint: 'login-hint@example.com',
35+
hd: 'hd_value',
36+
state: 'some-state',
37+
error_callback: (_) {},
38+
);
39+
40+
final utils.ExpectConfigValueFn expectConfigValue =
41+
utils.createExpectConfigValue(config as JSObject);
42+
43+
expectConfigValue('client_id', 'testing_1-2-3');
44+
expectConfigValue('callback', utils.isAJs('function'));
45+
expectConfigValue('scope', 'one two three');
46+
expectConfigValue('include_granted_scopes', isTrue);
47+
expectConfigValue('prompt', 'some-prompt');
48+
expectConfigValue('enable_granular_consent', isTrue);
49+
expectConfigValue('login_hint', 'login-hint@example.com');
50+
expectConfigValue('hd', 'hd_value');
51+
expectConfigValue('state', 'some-state');
52+
expectConfigValue('error_callback', utils.isAJs('function'));
53+
});
54+
55+
testWidgets('OverridableTokenClientConfig', (_) async {
56+
final OverridableTokenClientConfig config = OverridableTokenClientConfig(
57+
scope: <String>['one', 'two', 'three'],
58+
include_granted_scopes: true,
59+
prompt: 'some-prompt',
60+
enable_granular_consent: true,
61+
login_hint: 'login-hint@example.com',
62+
state: 'some-state',
63+
);
64+
65+
final utils.ExpectConfigValueFn expectConfigValue =
66+
utils.createExpectConfigValue(config as JSObject);
67+
68+
expectConfigValue('scope', 'one two three');
69+
expectConfigValue('include_granted_scopes', isTrue);
70+
expectConfigValue('prompt', 'some-prompt');
71+
expectConfigValue('enable_granular_consent', isTrue);
72+
expectConfigValue('login_hint', 'login-hint@example.com');
73+
expectConfigValue('state', 'some-state');
74+
});
75+
76+
testWidgets('CodeClientConfig', (_) async {
77+
final CodeClientConfig config = CodeClientConfig(
78+
client_id: 'testing_1-2-3',
79+
scope: <String>['one', 'two', 'three'],
80+
include_granted_scopes: true,
81+
redirect_uri: Uri.parse('https://www.example.com/login'),
82+
callback: (_) {},
83+
state: 'some-state',
84+
enable_granular_consent: true,
85+
login_hint: 'login-hint@example.com',
86+
hd: 'hd_value',
87+
ux_mode: UxMode.popup,
88+
select_account: true,
89+
error_callback: (_) {},
90+
);
91+
92+
final utils.ExpectConfigValueFn expectConfigValue =
93+
utils.createExpectConfigValue(config as JSObject);
94+
95+
expectConfigValue('scope', 'one two three');
96+
expectConfigValue('include_granted_scopes', isTrue);
97+
expectConfigValue('redirect_uri', 'https://www.example.com/login');
98+
expectConfigValue('callback', utils.isAJs('function'));
99+
expectConfigValue('state', 'some-state');
100+
expectConfigValue('enable_granular_consent', isTrue);
101+
expectConfigValue('login_hint', 'login-hint@example.com');
102+
expectConfigValue('hd', 'hd_value');
103+
expectConfigValue('ux_mode', 'popup');
104+
expectConfigValue('select_account', isTrue);
105+
expectConfigValue('error_callback', utils.isAJs('function'));
106+
});
107+
});
108+
22109
group('initTokenClient', () {
23110
testWidgets('returns a tokenClient', (_) async {
24111
final TokenClient client = oauth2.initTokenClient(TokenClientConfig(
25112
client_id: 'for-tests',
26-
callback: null,
27-
scope: 'some_scope for_tests not_real',
113+
callback: (_) {},
114+
scope: <String>['some_scope', 'for_tests', 'not_real'],
28115
));
29116

30117
expect(client, isNotNull);
@@ -40,8 +127,8 @@ void main() async {
40127

41128
final TokenClient client = oauth2.initTokenClient(TokenClientConfig(
42129
client_id: 'for-tests',
43-
callback: allowInterop(controller.add),
44-
scope: scopes.join(' '),
130+
callback: controller.add,
131+
scope: scopes,
45132
));
46133

47134
utils.setMockTokenResponse(client, 'some-non-null-auth-token-value');
@@ -52,7 +139,7 @@ void main() async {
52139

53140
expect(response, isNotNull);
54141
expect(response.error, isNull);
55-
expect(response.scope, scopes.join(' '));
142+
expect(response.scope, scopes);
56143
});
57144

58145
testWidgets('configuration can be overridden', (_) async {
@@ -63,21 +150,21 @@ void main() async {
63150

64151
final TokenClient client = oauth2.initTokenClient(TokenClientConfig(
65152
client_id: 'for-tests',
66-
callback: allowInterop(controller.add),
67-
scope: 'blank',
153+
callback: controller.add,
154+
scope: <String>['blank'],
68155
));
69156

70157
utils.setMockTokenResponse(client, 'some-non-null-auth-token-value');
71158

72159
client.requestAccessToken(OverridableTokenClientConfig(
73-
scope: scopes.join(' '),
160+
scope: scopes,
74161
));
75162

76163
final TokenResponse response = await controller.stream.first;
77164

78165
expect(response, isNotNull);
79166
expect(response.error, isNull);
80-
expect(response.scope, scopes.join(' '));
167+
expect(response.scope, scopes);
81168
});
82169
});
83170

packages/google_identity_services_web/example/integration_test/src/dom.dart

Lines changed: 0 additions & 31 deletions
This file was deleted.

0 commit comments

Comments
 (0)