|
|
|
@ -11,6 +11,13 @@ using Avalonia.Data; |
|
|
|
using Avalonia.Logging; |
|
|
|
using Avalonia.UnitTests; |
|
|
|
using Xunit; |
|
|
|
using System.Threading.Tasks; |
|
|
|
using Avalonia.Platform; |
|
|
|
using System.Threading; |
|
|
|
using Moq; |
|
|
|
using System.Reactive.Disposables; |
|
|
|
using System.Reactive.Concurrency; |
|
|
|
using Avalonia.Threading; |
|
|
|
|
|
|
|
namespace Avalonia.Base.UnitTests |
|
|
|
{ |
|
|
|
@ -356,6 +363,39 @@ namespace Avalonia.Base.UnitTests |
|
|
|
Assert.True(called); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
[Fact] |
|
|
|
public async void Bind_With_Scheduler_Executes_On_Scheduler() |
|
|
|
{ |
|
|
|
var target = new Class1(); |
|
|
|
var source = new Subject<object>(); |
|
|
|
var currentThreadId = Thread.CurrentThread.ManagedThreadId; |
|
|
|
var calledThreadingInterface = false; |
|
|
|
|
|
|
|
var threadingInterfaceMock = new Mock<IPlatformThreadingInterface>(); |
|
|
|
threadingInterfaceMock.SetupGet(mock => mock.CurrentThreadIsLoopThread) |
|
|
|
.Returns(() => Thread.CurrentThread.ManagedThreadId == currentThreadId); |
|
|
|
threadingInterfaceMock.Setup(mock => mock.StartTimer(TimeSpan.Zero, It.IsAny<Action>())) |
|
|
|
.Returns<TimeSpan, Action>((ts, act) => |
|
|
|
{ |
|
|
|
act(); |
|
|
|
calledThreadingInterface = true; |
|
|
|
return Disposable.Empty; |
|
|
|
}); |
|
|
|
|
|
|
|
using (AvaloniaLocator.EnterScope()) |
|
|
|
{ |
|
|
|
AvaloniaLocator.CurrentMutable.Bind<IPlatformThreadingInterface>().ToConstant(threadingInterfaceMock.Object); |
|
|
|
AvaloniaLocator.CurrentMutable.Bind<IScheduler>().ToConstant(AvaloniaScheduler.Instance); |
|
|
|
|
|
|
|
target.Bind(Class1.QuxProperty, source); |
|
|
|
|
|
|
|
await Task.Run(() => source.OnNext(6.7)); |
|
|
|
|
|
|
|
Assert.True(calledThreadingInterface); |
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Returns an observable that returns a single value but does not complete.
|
|
|
|
|