Skip to content

implement app state getter for web #509

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 20 commits into from
Apr 15, 2025

Conversation

navaronbracke
Copy link
Contributor

Fixes #486
Replaces #485 (I had an issue with signing the commits during the interactive rebase, so I started over)

  • All new/changed/fixed functionality is covered by tests (or N/A)
  • I have added documentation for all new/changed functionality (or N/A)

📋 Changes

This PR adds support for the appState parameter to loginWithRedirect() for the web.
See https://github.com/auth0/auth0-spa-js/blob/f2e566849efa398ca599daf9ebdfbbd62fcb1894/src/global.ts#L298

There is prior art in auth0/auth0-angular#168

🎯 Testing

Added several unit tests. This can be tested end-to-end by setting up a login with redirect, that uses the app state argument as parameter, and then validating that the app state is returned when the user is redirected back.
I did verify end-to-end using an internal application that uses the SDK integration.

To run the unit tests locally, use flutter test test/web/auth0_flutter_web_test.dart --platform=chrome

@navaronbracke navaronbracke requested a review from a team as a code owner February 11, 2025 12:01
@navaronbracke
Copy link
Contributor Author

@Widcket Apologies, I had an issue during the interactive rebase when trying to fix the commit signing, so I had to start over. I also applied your comments from the previous PR into this one.

/// Get the app state that was provided during a previous call
/// to [loginWithRedirect].
///
/// This method should be called after calling [onLoad].
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The note about second access returning null is now removed.

/// Thus clearing this object is not needed,
/// as the actual state is managed across reloads,
/// using the transaction manager.
// TODO: move the `appState` to the result of `onLoad/initialize`
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please let me know if I need to update this new TODO

Object? _appState;

@override
Future<Object?> get appState => Future<Object?>.value(_appState);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Per your request, the getter now returns the value as-is

@@ -21,6 +21,7 @@ dependency_overrides:

dev_dependencies:
build_runner: ^2.1.8
collection: ^1.18.0
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is for the MapEquality in tests.

@@ -15,6 +15,10 @@ abstract class Auth0FlutterWebPlatform extends PlatformInterface {
_instance = instance;
}

Future<Object?> get appState {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Previously there was also an @override that duplicated this implementation. I removed that one.
Maybe that is why the code coverage report was reporting the uncovered lines?


when(mockClientProxy.isAuthenticated())
.thenAnswer((final _) => Future.value(false));
when(mockClientProxy.handleRedirectCallback())
Copy link
Contributor Author

@navaronbracke navaronbracke Feb 11, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This test was updated to verify the redirect callback as well. (since it now returns a value)

);
});

test('appState getter returns value when accessed more than once', () async {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This test was added to prevent regressing the behavior of the new getter. (it should always return the same value)

Copy link

codecov bot commented Feb 11, 2025

Codecov Report

Attention: Patch coverage is 80.00000% with 1 line in your changes missing coverage. Please review.

Project coverage is 84.16%. Comparing base (253209a) to head (3326ae1).
Report is 147 commits behind head on main.

Files with missing lines Patch % Lines
...PI/AuthAPIPhoneNumberPasswordlessLoginMethod.swift 0.00% 1 Missing ⚠️
Additional details and impacted files
@@              Coverage Diff              @@
##               main     #509       +/-   ##
=============================================
- Coverage     96.08%   84.16%   -11.93%     
=============================================
  Files            97      108       +11     
  Lines          1611     1907      +296     
  Branches        331      424       +93     
=============================================
+ Hits           1548     1605       +57     
- Misses           49      289      +240     
+ Partials         14       13        -1     
Flag Coverage Δ
auth0_flutter 91.72% <ø> (-8.28%) ⬇️
auth0_flutter_android 80.65% <ø> (-15.91%) ⬇️
auth0_flutter_ios 83.78% <0.00%> (-16.07%) ⬇️
auth0_flutter_platform_interface 87.00% <100.00%> (-0.04%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@navaronbracke
Copy link
Contributor Author

I don't understand why the Sentry report might still be reporting the getter as uncovered?
The Auth0FlutterWebPlatform class in which it is defined is abstract, so cannot be instantiated.
The StubAuth0FlutterWeb class, which implements Auth0FlutterWebPlatform tests the getter in
https://github.com/auth0/auth0-flutter/pull/509/files#diff-b6191cf5b6dc7f251d6af466701eb8de71f4bb8fdebb1bfb2cfdbbf865bec83eR121

@navaronbracke
Copy link
Contributor Author

It seems that the upstream iOS & MacOS tests are broken currently? This prevents new test reports from being made.

final key = objKeys[i];
for (var i = 0; i < objKeys.arrayLength; i++) {
// TODO: replace w/ `final key = objKeys[i];` when updating to Dart 3.6.0
final key = objKeys.elementAt.callAsFunction(objKeys, i.toJS)!;
Copy link
Contributor

@pmathew92 pmathew92 Mar 6, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why do we need this change ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The [] operator and the length getter on JSArray are only available from Dart 3.6.0 onwards.
However, requiring to go from Dart 3.5.0 to Dart 3.6.0 would imply a switch from Flutter 3.24 to 3.27.
Therefor I opted to use a backwards compatible fix for now.

/// that do not fit into a static interop definition.
///
/// See https://api.dart.dev/dart-js_interop/NullableObjectUtilExtension/jsify.html
static JSAny? jsifyObject(final Object? obj) => obj.jsify();
Copy link
Contributor

@pmathew92 pmathew92 Mar 6, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@navaronbracke Do we need these helper methods ? Wouldn't be much easier if we call .jsify() and .dartify() directly on the corresponding objects

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

@navaronbracke
Copy link
Contributor Author

@pmathew92 PTAL. I updated the JS interop to call dartify/jsify directly and moved the polyfill for JSArray to the correct file.

As for the appState argument, I think that that is working as intended? Named arguments can be written anywhere in the argument list of a function call. (as opposed to positional arguments, which do have a fixed order). And since the appState is nullable users can just omit the argument if it is not needed.

For the switch to Dart 3.6.0, that is up to you, as this would mean that users that are on Flutter 3.24 (for WASM support) will need to migrate to Flutter 3.27 for this change.

@navaronbracke navaronbracke requested a review from pmathew92 March 6, 2025 13:41
@pmathew92
Copy link
Contributor

Thankyou @navaronbracke

@navaronbracke
Copy link
Contributor Author

Any ideas why the code coverage check is failing? The indirect diff seems to be unrelated to this PR?

@Widcket Widcket merged commit ab020b5 into auth0:main Apr 15, 2025
14 of 16 checks passed
@Widcket
Copy link
Contributor

Widcket commented Apr 15, 2025

Thanks @navaronbracke! Appreciate the patience, and the thorough PR.

@navaronbracke navaronbracke deleted the app_state_argument_addition branch April 15, 2025 22:29
@navaronbracke
Copy link
Contributor Author

Thanks for getting this landed!

This was referenced Apr 29, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

The appState parameter is missing for login with redirect on the web
3 participants