Skip to content

feat: Easy way to retrieve InteractiveRequestOptions#867

Merged
linkdotnet merged 8 commits intomainfrom
feature/interactive-request-options
Oct 12, 2022
Merged

feat: Easy way to retrieve InteractiveRequestOptions#867
linkdotnet merged 8 commits intomainfrom
feature/interactive-request-options

Conversation

@linkdotnet
Copy link
Collaborator

Pull request description

This PR relates and directly closes #859 .
It gives the user an easy way of retrieving the InteractiveRequestOptions from the NavigationHistoryEntry.

PR meta checklist

  • Pull request is targeted at main branch for code
    or targeted at stable branch for documentation that is live on bunit.dev.
  • Pull request is linked to all related issues, if any.
  • I have read the CONTRIBUTING.md document.

Code PR specific checklist

  • My code follows the code style of this project and AspNetCore coding guidelines.
  • My change requires a change to the documentation.
    • I have updated the documentation accordingly.
  • I have updated the appropriate sub section in the CHANGELOG.md.
  • I have added, updated or removed tests to according to my changes.
    • All tests passed.

@egil
Copy link
Member

egil commented Sep 25, 2022

Humor me for a second here. I still think we should consider adding a FromJson<T>(JsonSerializerOptions? options = null) to NavigationHistory. While there are no other current solution that uses JSON right now, its a pattern I suspect we'll see being used more, and then a FromJson method is more generalized.

As for whether it should throw or not, I think it is fine if it does. If a user expects that a navigation history entry is deserializeable from JSON and its not, then its completely fine to it throw an exception and thus have the test fail. Test assertions also work by throwing exceptions when things are not as expected.

The code would look something like this:

var actualInteractiveRequestOptions = navigationManager.History.Last().FromJson<InteractiveRequestOptions>();

If the FromJson method throws, then things are really incompatible. If it returns null, then thats also OK.

The implementation could look something like this:

public T? FromJson<T>(JsonSerializerOptions? options = null)
{
  options = options ?? JsonSerializerDefaults.Web; 
  return JsonSerializer.Deserialize<T>(Options.HistoryEntryState, options);
}

@linkdotnet
Copy link
Collaborator Author

linkdotnet commented Sep 25, 2022

The code would look something like this:

var actualInteractiveRequestOptions = navigationManager.History.Last().FromJson<InteractiveRequestOptions>();

I guess I know what you mean. As far as I am concerned I even would like that API, but (as always there is a but :D) FromJson would be an extension method on string, right?

This bid navigationManager.History.Last() is of type NavigationOptions, so the extension method wouldn't work.
Sure the user could do this: navigationManager.History.Last().State.FromJson<InteractiveRequestOptions>(...) but I see two main issues here:

  1. This one-liner can be done by the user. Not sure where we would bring much to the table.
  2. The user has to know a lot of internal stuff here (Blazor structure as well as bUnit structure to pull that off).

Right now the docu of the TryGet... method indicates that it is specifically designed for NavigateToLogin. My way of thinking is that I want to help the user out, because of Blazor knowledge (does he has to care that it is JSON?) as well as bUnit knowledge. I know that is a wacky argument at best, as I could literally use that argumentation for almost every API.

We can also put this back into the shelf and wait until users ask for help and depending on how they might expect an API, they get help. Or if you still think it would be viable to have the generic from the getgo, then I am more than happy to make that work. I just wanted to present my thoughts around that topic.

EDIT: I also see the danger that if the Blazor teams introduces more stuff, we are stuck with this very API I am proposing right now. Do we then want to have specific helper methods for every JSON-related call? Personally I would still argue in favor of that but I see that it might not be the way you want to go.

@linkdotnet linkdotnet requested a review from egil October 1, 2022 16:10
@egil
Copy link
Member

egil commented Oct 3, 2022

The code would look something like this:

var actualInteractiveRequestOptions = navigationManager.History.Last().FromJson<InteractiveRequestOptions>();

I guess I know what you mean. As far as I am concerned I even would like that API, but (as always there is a but :D) FromJson would be an extension method on string, right?

My plan was to have it on NavigationHistory, but it could also be an extension method on NavigationOptions. Perhaps the name should be StateFromJson<T> to make it more explicit where data will come from. The inspiration is the FromJson pattern used on HttpClient responses.

...

The general design approach i'm trying to take with bUnit is to enable more generic low level APIs that make it easy to do things, instead of of adding a whole bunch of very specific APIs, even if those are more discoverable.

The "fist party support" bUnit includes I like to expose through extension methods, since that is what 3rd parties will have to do, if they want to add support in bUnit for their stuff. Using the same approach for 1st party stuff allows us to eat our own dog food, as it were.

Hope this makes sense.

@linkdotnet
Copy link
Collaborator Author

My plan was to have it on NavigationHistory, but it could also be an extension method on NavigationOptions. Perhaps the name should be StateFromJson to make it more explicit where data will come from. The inspiration is the FromJson pattern used on HttpClient responses.

I do understand that part. Applying StateFromJson on a specific object bound to a use-case will anyway lead to the fact that we have to main multiple StateFromJson objects. Unlikely that we can re-use that besides on NavigationOptionsor NavigationHistory. So if we have to maintain multiple of those (depending on the type), then naming it according to the use-case would be better in my opinion.

Also StateFromJson could be misleading. Which State do we mean? Here the string State or the whole state or something else?

The inspiration is the FromJson pattern used on HttpClient responses.

Good input. But even that thing is bound to HttpClient and isn't generally available. So I guess we will find ourselves somewhere in the middle as I understand you!? We use a generic term, we might introduce in other places of bUnit, but they are always bound to that specific use-case. Ergo we don't have one StateFromJson method but multiple, depending where we need it.

@egil
Copy link
Member

egil commented Oct 3, 2022

As far as I can see, we can make due with one generic FromJson<T> method, where T would be whatever type has been stored as JSON in the NavigationOptions type, right?

If other types are stored as JSON in the NavigationOptions.State field, e.g. a custom type the user might be using in their own code, or something from a 3rd party lib, then they can reuse the same FromJson<T> method, as far as I can see. Ill see if I can get some time later today or tomorrow to prototype this.

@egil
Copy link
Member

egil commented Oct 9, 2022

Added my suggestion here. I like the more generic approach. Did forget to update the docs though.

@linkdotnet
Copy link
Collaborator Author

Added my suggestion here. I like the more generic approach. Did forget to update the docs though.

Okay as I wrote you some days ago. I misunderstood what you meant with generic.
That approach works for me ... will update all the docs

@linkdotnet
Copy link
Collaborator Author

I adopted some additional documentation as well (see last commit)

@linkdotnet linkdotnet requested a review from egil October 9, 2022 19:02
@egil
Copy link
Member

egil commented Oct 12, 2022

Looks good to me. Added a few changes. If you like them, squash merge at will :)

@linkdotnet linkdotnet merged commit 100ea01 into main Oct 12, 2022
@linkdotnet linkdotnet deleted the feature/interactive-request-options branch October 12, 2022 16:19
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.

Explicit support for NavigationManager.NavigateToLogin and InteractiveRequestOptions needed?

2 participants