Open zamzowd opened 3 years ago
So blazor app. Are you running the state update method on the form?
Also mind updating this is for blazor earlier on?
If you mean StateHasChanged
, then yes. I am using ReactiveInjectableComponentBase, which does that.
Running the actual blazor app seems to work as expected. It's the unit test in which the mocked task includes an await scheduler.Sleep(...)
where the IsExecuting
becomes silent. I didn't specify blazor in the description since it seemed like the ViewModel and the unit testing class didn't use anything from ReactiveUI.Blazor
.
I think it's a scheduling problem. I am having a similar error in a Visual Studio Extension project where a command opens a WPF window. I this window I have a button with binding on a ReactiveCommand:
Save = ReactiveCommand.CreateFromTask(async () =>
{
if (!ItemVM.Modified || await Interactions.RequestConfirm.Handle("Are you sure you want to save the changes?"))
{
var newAppInfo = ItemVM.ToAppInfo();
await Task.Run( () => throw new Exception("EXXXX"));
return newAppInfo;
}
return null;
}, ItemVM.IsValid()
);
ThrownExcpetions kick an interaction
Save.ThrownExceptions.SelectMany(x => Interactions.Errors.Handle(x)).Subscribe();
And I have an interaction handler
Interactions.Errors.RegisterHandler(i =>
{
MessageBox.Show($"Something went wrong\n{i.Input.Message}\n{i.Input.InnerException?.Message}", "Agrolab Apps Management", MessageBoxButton.OK, MessageBoxImage.Error);
i.SetOutput(Unit.Default);
}
);
Everything works properly and the messagebox appears, but the button remains grayed as if the command were still running.
PS
In order to avoid errors in creating the RxApp I had to manually set the scheduler:
RxApp.MainThreadScheduler = Scheduler.Immediate;
Is this still an issue?
Unit tests for a ReactiveCommand normally require you to set the Scheduler to
ImmediateScheduler.Instance
for both Schedulers that now exist, execution Scheduler and canExecute Scheduler
I just checked against the repo posted and this is still not functioning as per the test in the repo with the latest build as of today. I have a thought that its to do with Observable.FromAsync and the way its working but will dig deeper and try to find out.
Thanks for following up.
I updated the repo with latest Blazor and ReactiveUI nuget packages. As you said, it doesn't address this issue.
I also created an override-scheduler branch, following the guidance in ReactiveUI - Testing (and also setting canExecuteScheduler
, unspecified in the article).
It does have an impact on the LoadTodos_UpdatesLoading
test, but not to the desired result.
In master branch:
In override-scheduler branch:
I'm not sure where I would reference Scheduler.Immediate
or ImmediateScheduler.Instance
, and couldn't find guidance on it.
@zamzowd It's part of the ReactiveX/System.Reactive that ReactiveUI is based on.
We are trying to come up with a resolve for this but the root cause is in the System.Reactive
code
https://github.com/dotnet/reactive/issues/1256
This issue has been outstanding for quite some time.
Describe the bug When unit testing with a TestScheduler to control timing, the IsExecuting of a ReactiveCommand created from a task does not emit new values after awaiting
scheduler.Sleep(...)
.Using the
VirtualTimeSchedulerBase
override ofscheduler.Sleep(...)
misaligns the expected timing.Steps To Reproduce An example can be seen here: https://github.com/zamzowd/ZamzowD.ExampleBlazor
.IsExecuting.ToProperty(...)
from the command.await scheduler.Sleep(TimeSpan.FromTicks(50))
.IsExecuting
observable or changes to the property fromPropertyChanged
events.Expected The IsExecuting and PropertyChanged indicate an update to
true
when the ReactiveCommand starts andfalse
when the ReactiveCommand completes.Actual The IsExecuting and PropertyChanged indicate an update to
true
once, but never an update tofalse
nor subsequent updates totrue
.With
await scheduler.Sleep(TimeSpan.FromTicks(50))
:With
scheduler.Sleep(50)
:Breakpoints are still hit through each scheduled execution. Running the Blazor application normally demonstrates the expected behavior. Properties updated in the command (
Todo
in the example project) have the expected timing inPropertyChanged
events. It is onlyIsExecuting
that falls silent, and only in unit tests.