From 0d3c00edd3e320f9da14839b521fa572da7a57a8 Mon Sep 17 00:00:00 2001 From: dshukertjr Date: Tue, 2 Apr 2024 22:16:05 +0900 Subject: [PATCH] adjust gotrue tests --- packages/gotrue/lib/src/gotrue_client.dart | 47 ++++++++++++-------- packages/gotrue/test/client_test.dart | 27 +++++------ packages/gotrue/test/custom_http_client.dart | 6 ++- packages/gotrue/test/utils.dart | 7 +-- 4 files changed, 47 insertions(+), 40 deletions(-) diff --git a/packages/gotrue/lib/src/gotrue_client.dart b/packages/gotrue/lib/src/gotrue_client.dart index a574c0c9..2849e3f5 100644 --- a/packages/gotrue/lib/src/gotrue_client.dart +++ b/packages/gotrue/lib/src/gotrue_client.dart @@ -924,28 +924,37 @@ class GoTrueClient { /// Recover session from stringified [Session]. Future recoverSession(String jsonStr) async { - final session = Session.fromJson(json.decode(jsonStr)); - if (session == null) { - await signOut(); - throw notifyException(AuthException('Current session is missing data.')); - } - - if (session.isExpired) { - final refreshToken = session.refreshToken; - if (_autoRefreshToken && refreshToken != null) { - return await _callRefreshToken(refreshToken); - } else { + try { + final session = Session.fromJson(json.decode(jsonStr)); + if (session == null) { await signOut(); - throw notifyException(AuthException('Session expired.')); + throw notifyException( + AuthException('Current session is missing data.'), + ); } - } else { - final shouldEmitEvent = _currentSession == null || - _currentSession?.user.id != session.user.id; - _saveSession(session); - if (shouldEmitEvent) notifyAllSubscribers(AuthChangeEvent.tokenRefreshed); + if (session.isExpired) { + final refreshToken = session.refreshToken; + if (_autoRefreshToken && refreshToken != null) { + return await _callRefreshToken(refreshToken); + } else { + await signOut(); + throw notifyException(AuthException('Session expired.')); + } + } else { + final shouldEmitEvent = _currentSession == null || + _currentSession?.user.id != session.user.id; + _saveSession(session); - return AuthResponse(session: session); + if (shouldEmitEvent) { + notifyAllSubscribers(AuthChangeEvent.tokenRefreshed); + } + + return AuthResponse(session: session); + } + } catch (error) { + notifyException(error); + rethrow; } } @@ -1164,7 +1173,7 @@ class GoTrueClient { /// For internal use only. @internal - Exception notifyException(Exception exception, [StackTrace? stackTrace]) { + Object notifyException(Object exception, [StackTrace? stackTrace]) { _onAuthStateChangeController.addError( exception, stackTrace ?? StackTrace.current, diff --git a/packages/gotrue/test/client_test.dart b/packages/gotrue/test/client_test.dart index 0b098540..d4f5c181 100644 --- a/packages/gotrue/test/client_test.dart +++ b/packages/gotrue/test/client_test.dart @@ -373,26 +373,19 @@ void main() { final session = '{"access_token":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE2ODAzNDE3MDUsInN1YiI6IjRkMjU4M2RhLThkZTQtNDlkMy05Y2QxLTM3YTlhNzRmNTViZCIsImVtYWlsIjoiZmFrZTE2ODAzMzgxMDVAZW1haWwuY29tIiwicGhvbmUiOiIiLCJhcHBfbWV0YWRhdGEiOnsicHJvdmlkZXIiOiJlbWFpbCIsInByb3ZpZGVycyI6WyJlbWFpbCJdfSwidXNlcl9tZXRhZGF0YSI6eyJIZWxsbyI6IldvcmxkIn0sInJvbGUiOiIiLCJhYWwiOiJhYWwxIiwiYW1yIjpbeyJtZXRob2QiOiJwYXNzd29yZCIsInRpbWVzdGFtcCI6MTY4MDMzODEwNX1dLCJzZXNzaW9uX2lkIjoiYzhiOTg2Y2UtZWJkZC00ZGUxLWI4MjAtZjIyOWYyNjg1OGIwIn0.0x1rFlPKbIU1rZPY1SH_FNSZaXerfkFA1Y-EOlhuzUs","expires_in":3600,"refresh_token":"-yeS4omysFs9tpUYBws9Rg","token_type":"bearer","provider_token":null,"provider_refresh_token":null,"user":{"id":"4d2583da-8de4-49d3-9cd1-37a9a74f55bd","app_metadata":{"provider":"email","providers":["email"]},"user_metadata":{"Hello":"World"},"aud":"","email":"fake1680338105@email.com","phone":"","created_at":"2023-04-01T08:35:05.208586Z","confirmed_at":null,"email_confirmed_at":"2023-04-01T08:35:05.220096086Z","phone_confirmed_at":null,"last_sign_in_at":"2023-04-01T08:35:05.222755878Z","role":"","updated_at":"2023-04-01T08:35:05.226938Z"},"expiresAt":1680341705}'; - ///These 3 are bundled and in sum 4 refresh token requests are made, because the first 3 fail in [RetryTestHttpClient] - final future1 = Future.wait([ - client.recoverSession(session), + ///These 3 are bundled and in sum 1 refresh token requests is made, because the first 3 fail in [RetryTestHttpClient] + final responses = await Future.wait([ client.recoverSession(session), client.recoverSession(session), ]); - await expectLater(future1, throwsA(isA())); - expect(httpClient.retryCount, 1); - - /// Again these 3 are bundled and only one refresh token request is made - final future2 = Future.wait([ - client.recoverSession(session), - client.recoverSession(session), - client.recoverSession(session), - ]); + expect(responses[0].session?.accessToken, isNotNull); + expect( + responses[0].session?.accessToken, + responses[1].session?.accessToken, + ); - await expectLater(future2, throwsA(isA())); - expect(client.onAuthStateChange, emits(isA())); - expect(httpClient.retryCount, 2); + expect(httpClient.retryCount, 4); }); test('Sign out on wrong refresh token', () async { @@ -410,10 +403,10 @@ void main() { ]), ); - final session = + final expiredSession = getSessionData(DateTime.now().subtract(Duration(hours: 1))); - await expectLater(client.recoverSession(session.sessionString), + await expectLater(client.recoverSession(expiredSession.sessionString), throwsA(isA())); expect(stream, emitsError(isA())); diff --git a/packages/gotrue/test/custom_http_client.dart b/packages/gotrue/test/custom_http_client.dart index fe2ed433..fe1f04d1 100644 --- a/packages/gotrue/test/custom_http_client.dart +++ b/packages/gotrue/test/custom_http_client.dart @@ -76,7 +76,11 @@ class RetryTestHttpClient extends BaseClient { throw ClientException('Retry #$retryCount'); } final jwt = JWT( - {'exp': (DateTime.now().millisecondsSinceEpoch / 1000).round() + 60}, + { + 'exp': (DateTime.now().millisecondsSinceEpoch / 1000).round() + 60, + 'retry_count': + retryCount, // Add retryCount so that tokens issued on different retries are different. + }, subject: userId1, ); diff --git a/packages/gotrue/test/utils.dart b/packages/gotrue/test/utils.dart index 2bec283e..10b4f5b9 100644 --- a/packages/gotrue/test/utils.dart +++ b/packages/gotrue/test/utils.dart @@ -51,13 +51,14 @@ String getServiceRoleToken(DotEnv env) { } /// Construct session data for a given expiration date -({String accessToken, String sessionString}) getSessionData(DateTime dateTime) { - final expiresAt = dateTime.millisecondsSinceEpoch ~/ 1000; +({String accessToken, String sessionString}) getSessionData( + DateTime expireDateTime) { + final expiresAt = expireDateTime.millisecondsSinceEpoch ~/ 1000; final accessTokenMid = base64.encode(utf8.encode(json.encode( {'exp': expiresAt, 'sub': '1234567890', 'role': 'authenticated'}))); final accessToken = 'any.$accessTokenMid.any'; final sessionString = - '{"access_token":"$accessToken","expires_in":${dateTime.difference(DateTime.now()).inSeconds},"refresh_token":"-yeS4omysFs9tpUYBws9Rg","token_type":"bearer","provider_token":null,"provider_refresh_token":null,"user":{"id":"4d2583da-8de4-49d3-9cd1-37a9a74f55bd","app_metadata":{"provider":"email","providers":["email"]},"user_metadata":{"Hello":"World"},"aud":"","email":"fake1680338105@email.com","phone":"","created_at":"2023-04-01T08:35:05.208586Z","confirmed_at":null,"email_confirmed_at":"2023-04-01T08:35:05.220096086Z","phone_confirmed_at":null,"last_sign_in_at":"2023-04-01T08:35:05.222755878Z","role":"","updated_at":"2023-04-01T08:35:05.226938Z"}}'; + '{"access_token":"$accessToken","expires_in":${expireDateTime.difference(DateTime.now()).inSeconds},"refresh_token":"-yeS4omysFs9tpUYBws9Rg","token_type":"bearer","provider_token":null,"provider_refresh_token":null,"user":{"id":"4d2583da-8de4-49d3-9cd1-37a9a74f55bd","app_metadata":{"provider":"email","providers":["email"]},"user_metadata":{"Hello":"World"},"aud":"","email":"fake1680338105@email.com","phone":"","created_at":"2023-04-01T08:35:05.208586Z","confirmed_at":null,"email_confirmed_at":"2023-04-01T08:35:05.220096086Z","phone_confirmed_at":null,"last_sign_in_at":"2023-04-01T08:35:05.222755878Z","role":"","updated_at":"2023-04-01T08:35:05.226938Z"}}'; return (accessToken: accessToken, sessionString: sessionString); }