diff --git a/src/ReactiveUI.Fody.Analyzer.Test/ReactiveObjectAnalyzerTest.cs b/src/ReactiveUI.Fody.Analyzer.Test/ReactiveObjectAnalyzerTest.cs index 88340d69f9..f7d0af9396 100644 --- a/src/ReactiveUI.Fody.Analyzer.Test/ReactiveObjectAnalyzerTest.cs +++ b/src/ReactiveUI.Fody.Analyzer.Test/ReactiveObjectAnalyzerTest.cs @@ -32,7 +32,7 @@ public void CheckEmptyFileReturnsNoFailures() [Fact] public void ShouldGiveAnErrorWhenClassDoesNotImplement() { - var test = @" + const string test = @" using System; using System.Collections.Generic; using System.Linq; @@ -68,7 +68,7 @@ public class TypeName [Fact] public void ShouldNotGiveAnErrorWhenClassInherits() { - var test = @" + const string test = @" using System; using System.Collections.Generic; using System.Linq; @@ -95,7 +95,7 @@ public class TypeName : ReactiveObject [Fact] public void ShouldNotGiveAnErrorWhenClassImplements() { - var test = @" + const string test = @" using System; using System.Collections.Generic; using System.Linq; @@ -122,7 +122,7 @@ public class TypeName : IReactiveObject [Fact] public void ShouldGiveErrorForNonAutoProperty() { - var test = @" + const string test = @" using System; using System.Collections.Generic; using System.Linq; diff --git a/src/ReactiveUI.Testing.Tests/TestFixture.cs b/src/ReactiveUI.Testing.Tests/TestFixture.cs index d309a0c83f..0685bafe3c 100644 --- a/src/ReactiveUI.Testing.Tests/TestFixture.cs +++ b/src/ReactiveUI.Testing.Tests/TestFixture.cs @@ -30,7 +30,6 @@ public class TestFixture /// /// Gets or sets the variables. /// - [SuppressMessage("Design", "CA2227: Read only dictionary", Justification = "Used in mock.")] public Dictionary? Variables { get; set; } } } diff --git a/src/ReactiveUI.Testing.Tests/TestSequencerTests.cs b/src/ReactiveUI.Testing.Tests/TestSequencerTests.cs new file mode 100644 index 0000000000..4cad299790 --- /dev/null +++ b/src/ReactiveUI.Testing.Tests/TestSequencerTests.cs @@ -0,0 +1,42 @@ +// Copyright (c) 2023 .NET Foundation and Contributors. All rights reserved. +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for full license information. + +using Xunit; + +namespace ReactiveUI.Testing.Tests +{ + /// + /// TestSequencerTests. + /// + public class TestSequencerTests + { + /// + /// Shoulds the execute tests in order. + /// + /// A representing the asynchronous unit test. + [Fact] + public async Task Should_Execute_Tests_In_Order() + { + using var testSequencer = new TestSequencer(); + var subject = new Subject(); + subject.Subscribe(async _ => await testSequencer.AdvancePhaseAsync()); + + Assert.Equal(0, testSequencer.CurrentPhase); + Assert.Equal(0, testSequencer.CompletedPhases); + subject.OnNext(Unit.Default); + Assert.Equal(1, testSequencer.CurrentPhase); + Assert.Equal(0, testSequencer.CompletedPhases); + await testSequencer.AdvancePhaseAsync("Phase 1"); + Assert.Equal(1, testSequencer.CurrentPhase); + Assert.Equal(1, testSequencer.CompletedPhases); + subject.OnNext(Unit.Default); + Assert.Equal(2, testSequencer.CurrentPhase); + Assert.Equal(1, testSequencer.CompletedPhases); + await testSequencer.AdvancePhaseAsync("Phase 2"); + Assert.Equal(2, testSequencer.CurrentPhase); + Assert.Equal(2, testSequencer.CompletedPhases); + } + } +} diff --git a/src/ReactiveUI.Testing/TestSequencer.cs b/src/ReactiveUI.Testing/TestSequencer.cs new file mode 100644 index 0000000000..7b9a1f0aa4 --- /dev/null +++ b/src/ReactiveUI.Testing/TestSequencer.cs @@ -0,0 +1,84 @@ +// Copyright (c) 2023 .NET Foundation and Contributors. All rights reserved. +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for full license information. + +namespace ReactiveUI.Testing +{ + /// + /// Test Sequencer. + /// + /// + public class TestSequencer : IDisposable + { + private readonly Barrier _phaseSync; + private bool _disposedValue; + + /// + /// Initializes a new instance of the class. + /// + public TestSequencer() => _phaseSync = new(2); + + /// + /// Gets the number of completed phases. + /// + /// + /// The completed phases. + /// + public long CompletedPhases => _phaseSync.CurrentPhaseNumber; + + /// + /// Gets the current phase. + /// + /// + /// The current phase. + /// + public long CurrentPhase { get; private set; } + + /// + /// Advances this phase instance. + /// + /// The comment for Test visual identification Purposes only. + /// + /// A representing the asynchronous operation. + /// +#pragma warning disable RCS1163 // Unused parameter. + public Task AdvancePhaseAsync(string comment = "") +#pragma warning restore RCS1163 // Unused parameter. + { + if (_phaseSync.ParticipantCount == _phaseSync.ParticipantsRemaining) + { + CurrentPhase = CompletedPhases + 1; + } + + return Task.Run(() => _phaseSync?.SignalAndWait(CancellationToken.None)); + } + + /// + /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. + /// + public void Dispose() + { + // Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method + Dispose(disposing: true); + GC.SuppressFinalize(this); + } + + /// + /// Releases unmanaged and - optionally - managed resources. + /// + /// true to release both managed and unmanaged resources; false to release only unmanaged resources. + protected virtual void Dispose(bool disposing) + { + if (!_disposedValue) + { + if (disposing) + { + _phaseSync.Dispose(); + } + + _disposedValue = true; + } + } + } +} diff --git a/src/ReactiveUI.Tests/API/ApiApprovalTests.Testing.DotNet6_0.verified.txt b/src/ReactiveUI.Tests/API/ApiApprovalTests.Testing.DotNet6_0.verified.txt index 0b93a3938a..304564a83e 100644 --- a/src/ReactiveUI.Tests/API/ApiApprovalTests.Testing.DotNet6_0.verified.txt +++ b/src/ReactiveUI.Tests/API/ApiApprovalTests.Testing.DotNet6_0.verified.txt @@ -43,4 +43,13 @@ namespace ReactiveUI.Testing where T : System.Reactive.Concurrency.IScheduler { } public static System.IDisposable WithScheduler(System.Reactive.Concurrency.IScheduler scheduler) { } } + public class TestSequencer : System.IDisposable + { + public TestSequencer() { } + public long CompletedPhases { get; } + public long CurrentPhase { get; } + public System.Threading.Tasks.Task AdvancePhaseAsync(string comment = "") { } + public void Dispose() { } + protected virtual void Dispose(bool disposing) { } + } } \ No newline at end of file diff --git a/src/ReactiveUI.Tests/API/ApiApprovalTests.Testing.DotNet7_0.verified.txt b/src/ReactiveUI.Tests/API/ApiApprovalTests.Testing.DotNet7_0.verified.txt index b1e52d7367..879eba2a36 100644 --- a/src/ReactiveUI.Tests/API/ApiApprovalTests.Testing.DotNet7_0.verified.txt +++ b/src/ReactiveUI.Tests/API/ApiApprovalTests.Testing.DotNet7_0.verified.txt @@ -43,4 +43,13 @@ namespace ReactiveUI.Testing where T : System.Reactive.Concurrency.IScheduler { } public static System.IDisposable WithScheduler(System.Reactive.Concurrency.IScheduler scheduler) { } } + public class TestSequencer : System.IDisposable + { + public TestSequencer() { } + public long CompletedPhases { get; } + public long CurrentPhase { get; } + public System.Threading.Tasks.Task AdvancePhaseAsync(string comment = "") { } + public void Dispose() { } + protected virtual void Dispose(bool disposing) { } + } } \ No newline at end of file diff --git a/src/ReactiveUI.Tests/API/ApiApprovalTests.Testing.Net4_7.verified.txt b/src/ReactiveUI.Tests/API/ApiApprovalTests.Testing.Net4_7.verified.txt index cc7f911bf2..f11db08cc5 100644 --- a/src/ReactiveUI.Tests/API/ApiApprovalTests.Testing.Net4_7.verified.txt +++ b/src/ReactiveUI.Tests/API/ApiApprovalTests.Testing.Net4_7.verified.txt @@ -43,4 +43,13 @@ namespace ReactiveUI.Testing where T : System.Reactive.Concurrency.IScheduler { } public static System.IDisposable WithScheduler(System.Reactive.Concurrency.IScheduler scheduler) { } } + public class TestSequencer : System.IDisposable + { + public TestSequencer() { } + public long CompletedPhases { get; } + public long CurrentPhase { get; } + public System.Threading.Tasks.Task AdvancePhaseAsync(string comment = "") { } + public void Dispose() { } + protected virtual void Dispose(bool disposing) { } + } } \ No newline at end of file diff --git a/src/ReactiveUI.Tests/Activation/ActivatingViewTests.cs b/src/ReactiveUI.Tests/Activation/ActivatingViewTests.cs index 6b3848aba0..78923500ff 100644 --- a/src/ReactiveUI.Tests/Activation/ActivatingViewTests.cs +++ b/src/ReactiveUI.Tests/Activation/ActivatingViewTests.cs @@ -26,9 +26,10 @@ public void ActivatingViewSmokeTest() using (locator.WithResolver()) { var vm = new ActivatingViewModel(); - var fixture = new ActivatingView(); - - fixture.ViewModel = vm; + var fixture = new ActivatingView + { + ViewModel = vm + }; Assert.Equal(0, vm.IsActiveCount); Assert.Equal(0, fixture.IsActiveCount); @@ -56,9 +57,10 @@ public void NullingViewModelDeactivateIt() using (locator.WithResolver()) { var vm = new ActivatingViewModel(); - var fixture = new ActivatingView(); - - fixture.ViewModel = vm; + var fixture = new ActivatingView + { + ViewModel = vm + }; Assert.Equal(0, vm.IsActiveCount); Assert.Equal(0, fixture.IsActiveCount); @@ -151,9 +153,10 @@ public void CanUnloadAndLoadViewAgain() using (locator.WithResolver()) { var vm = new ActivatingViewModel(); - var fixture = new ActivatingView(); - - fixture.ViewModel = vm; + var fixture = new ActivatingView + { + ViewModel = vm + }; Assert.Equal(0, vm.IsActiveCount); Assert.Equal(0, fixture.IsActiveCount); diff --git a/src/ReactiveUI.Tests/BindingTypeConvertersTest.cs b/src/ReactiveUI.Tests/BindingTypeConvertersTest.cs index 9893846927..94d0169091 100644 --- a/src/ReactiveUI.Tests/BindingTypeConvertersTest.cs +++ b/src/ReactiveUI.Tests/BindingTypeConvertersTest.cs @@ -7,8 +7,6 @@ namespace ReactiveUI.Tests { - using System; - /// /// Tests for binding type converters. /// @@ -66,7 +64,7 @@ public void EqualityTypeConverterDoReferenceCastNullableToValueType() [Fact] public void EqualityTypeConverterDoReferenceCastShouldConvertValueTypes() { - var doubleValue = 1.0; + const double doubleValue = 1.0; var result = EqualityTypeConverter.DoReferenceCast(doubleValue, typeof(double)); Assert.Equal(doubleValue, result); } diff --git a/src/ReactiveUI.Tests/Commands/ReactiveCommandTest.cs b/src/ReactiveUI.Tests/Commands/ReactiveCommandTest.cs index c5cb8801fe..fab386afc2 100644 --- a/src/ReactiveUI.Tests/Commands/ReactiveCommandTest.cs +++ b/src/ReactiveUI.Tests/Commands/ReactiveCommandTest.cs @@ -1199,25 +1199,21 @@ public async Task ReactiveCommandCreateFromTaskHandlesTaskExceptionAsync() [Fact] public async Task ReactiveCommandExecutesFromInvokeCommand() { - var semaphore = new SemaphoreSlim(0); - var command = ReactiveCommand.Create(() => semaphore.Release()); + using var testSequencer = new TestSequencer(); + + var command = ReactiveCommand.Create(async () => await testSequencer.AdvancePhaseAsync("Phase 1")); + var result = 0; + + // False, True, False + command.IsExecuting.Subscribe(_ => result++); Observable.Return(Unit.Default) .InvokeCommand(command); - var result = 0; - var task = semaphore.WaitAsync(); - if (await Task.WhenAny(Task.Delay(TimeSpan.FromMilliseconds(100)), task).ConfigureAwait(true) == task) - { - result = 1; - } - else - { - result = -1; - } + await testSequencer.AdvancePhaseAsync("Phase 1"); + Assert.Equal(3, result); - await Task.Delay(200).ConfigureAwait(false); - Assert.Equal(1, result); + testSequencer.Dispose(); } } } diff --git a/src/ReactiveUI.Tests/Locator/DefaultViewLocatorTests.cs b/src/ReactiveUI.Tests/Locator/DefaultViewLocatorTests.cs index 34007010c0..76e1ef4e40 100644 --- a/src/ReactiveUI.Tests/Locator/DefaultViewLocatorTests.cs +++ b/src/ReactiveUI.Tests/Locator/DefaultViewLocatorTests.cs @@ -13,7 +13,7 @@ namespace ReactiveUI.Tests public class DefaultViewLocatorTests { /// - /// Tests that the the default name of the view model is replaced with view when determining the service. + /// Tests that the default name of the view model is replaced with view when determining the service. /// [Fact] public void ByDefaultViewModelIsReplacedWithViewWhenDeterminingTheServiceName() @@ -70,9 +70,11 @@ public void ViewModelToViewNamingConventionCanBeCustomized() using (resolver.WithResolver()) { - var fixture = new DefaultViewLocator(); - fixture.ViewModelToViewFunc = - viewModelName => viewModelName.Replace("ViewModel", "WithWeirdConvention"); + var fixture = new DefaultViewLocator + { + ViewModelToViewFunc = + viewModelName => viewModelName.Replace("ViewModel", "WithWeirdConvention") + }; var vm = new FooViewModel(); var result = fixture.ResolveView(vm); @@ -254,9 +256,11 @@ public void NoErrorIsRaisedIfATypeCannotBeFound() using (resolver.WithResolver()) { - var fixture = new DefaultViewLocator(); - fixture.ViewModelToViewFunc = viewModelName => - "DoesNotExist, " + typeof(DefaultViewLocatorTests).Assembly.FullName; + var fixture = new DefaultViewLocator + { + ViewModelToViewFunc = viewModelName => + "DoesNotExist, " + typeof(DefaultViewLocatorTests).Assembly.FullName + }; var vm = new FooViewModel(); var result = fixture.ResolveView(vm); @@ -386,8 +390,10 @@ public void CanOverrideNameResolutionFunc() using (resolver.WithResolver()) { - var fixture = new DefaultViewLocator(); - fixture.ViewModelToViewFunc = x => x.Replace("ViewModel", "CustomView"); + var fixture = new DefaultViewLocator + { + ViewModelToViewFunc = x => x.Replace("ViewModel", "CustomView") + }; var vm = new RoutableFooViewModel(); var result = fixture.ResolveView(vm); diff --git a/src/ReactiveUI.Tests/MessageBusTest.cs b/src/ReactiveUI.Tests/MessageBusTest.cs index 8ba563d698..217ecaa5e7 100644 --- a/src/ReactiveUI.Tests/MessageBusTest.cs +++ b/src/ReactiveUI.Tests/MessageBusTest.cs @@ -89,7 +89,7 @@ public void GcShouldNotKillMessageService() var bus = new MessageBus(); var receivedMessage = false; - var dispose = bus.Listen().Subscribe(x => receivedMessage = true); + var dispose = bus.Listen().Subscribe(_ => receivedMessage = true); bus.SendMessage(1); Assert.True(receivedMessage); @@ -114,10 +114,10 @@ public void RegisteringSecondMessageSourceShouldMergeBothSources() var receivedMessage2 = false; bus.RegisterMessageSource(source1); - bus.Listen().Subscribe(x => receivedMessage1 = true); + bus.Listen().Subscribe(_ => receivedMessage1 = true); bus.RegisterMessageSource(source2); - bus.Listen().Subscribe(x => receivedMessage2 = true); + bus.Listen().Subscribe(_ => receivedMessage2 = true); source1.OnNext(1); Assert.True(receivedMessage1); @@ -140,12 +140,12 @@ public void MessageBusThreadingTest() var mb = new MessageBus(); int? listenedThreadId = null; int? otherThreadId = null; - var thisThreadId = Thread.CurrentThread.ManagedThreadId; + var thisThreadId = Environment.CurrentManagedThreadId; var otherThread = new Thread(new ThreadStart(() => { - otherThreadId = Thread.CurrentThread.ManagedThreadId; - mb.Listen().Subscribe(_ => listenedThreadId = Thread.CurrentThread.ManagedThreadId); + otherThreadId = Environment.CurrentManagedThreadId; + mb.Listen().Subscribe(_ => listenedThreadId = Environment.CurrentManagedThreadId); mb.SendMessage(42); })); diff --git a/src/ReactiveUI.Tests/ObservableAsPropertyHelper/Mocks/OAPHIndexerTestFixture.cs b/src/ReactiveUI.Tests/ObservableAsPropertyHelper/Mocks/OAPHIndexerTestFixture.cs index 244ac5623a..86c338fb8b 100644 --- a/src/ReactiveUI.Tests/ObservableAsPropertyHelper/Mocks/OAPHIndexerTestFixture.cs +++ b/src/ReactiveUI.Tests/ObservableAsPropertyHelper/Mocks/OAPHIndexerTestFixture.cs @@ -15,25 +15,25 @@ internal class OAPHIndexerTestFixture : ReactiveObject /// /// Initializes a new instance of the class. /// - public OAPHIndexerTestFixture(int test) + public OAPHIndexerTestFixture(int test, IScheduler scheduler) { switch (test) { case 0: var temp = this.WhenAnyValue(f => f.Text) - .ToProperty(this, f => f["Whatever"]) + .ToProperty(this, f => f["Whatever"], scheduler: scheduler) .Value; break; case 1: var temp1 = this.WhenAnyValue(f => f.Text) - .ToProperty(new ReactiveObject(), f => f.ToString()) + .ToProperty(new ReactiveObject(), f => f.ToString(), scheduler: scheduler) .Value; break; case 2: var temp2 = Observable.Return("happy") - .ToProperty(this, string.Empty) + .ToProperty(this, string.Empty, scheduler: scheduler) .Value; break; } diff --git a/src/ReactiveUI.Tests/ObservableAsPropertyHelper/ObservableAsPropertyHelperTest.cs b/src/ReactiveUI.Tests/ObservableAsPropertyHelper/ObservableAsPropertyHelperTest.cs index 5f55a12b98..6febd8b067 100644 --- a/src/ReactiveUI.Tests/ObservableAsPropertyHelper/ObservableAsPropertyHelperTest.cs +++ b/src/ReactiveUI.Tests/ObservableAsPropertyHelper/ObservableAsPropertyHelperTest.cs @@ -32,7 +32,8 @@ public void OAPHShouldFireChangeNotifications() var fixture = new ObservableAsPropertyHelper( input, x => output.Add(x), - -5); + -5, + scheduler: scheduler); scheduler.Start(); @@ -58,7 +59,8 @@ public void OAPHShouldSkipFirstValueIfItMatchesTheInitialValue() var fixture = new ObservableAsPropertyHelper( input, x => output.Add(x), - 1); + 1, + scheduler: scheduler); scheduler.Start(); @@ -81,7 +83,8 @@ public void OAPHShouldProvideInitialValueImmediatelyRegardlessOfScheduler() var fixture = new ObservableAsPropertyHelper( Observable.Never, x => output.Add(x), - 32); + 32, + scheduler: scheduler); Assert.Equal(32, fixture.Value); }); @@ -91,27 +94,27 @@ public void OAPHShouldProvideInitialValueImmediatelyRegardlessOfScheduler() /// Tests that Observable As Property Helpers should provide latest value. /// [Fact] - public void OAPHShouldProvideLatestValue() - { - var scheduler = new TestScheduler(); - var input = new Subject(); + public void OAPHShouldProvideLatestValue() => + new TestScheduler().With(scheduler => + { + var input = new Subject(); - var fixture = new ObservableAsPropertyHelper( - input, - _ => { }, - -5, - scheduler: scheduler); + var fixture = new ObservableAsPropertyHelper( + input, + _ => { }, + -5, + scheduler: scheduler); - Assert.Equal(-5, fixture.Value); - new[] { 1, 2, 3, 4 }.Run(x => input.OnNext(x)); + Assert.Equal(-5, fixture.Value); + new[] { 1, 2, 3, 4 }.Run(x => input.OnNext(x)); - scheduler.Start(); - Assert.Equal(4, fixture.Value); + scheduler.Start(); + Assert.Equal(4, fixture.Value); - input.OnCompleted(); - scheduler.Start(); - Assert.Equal(4, fixture.Value); - } + input.OnCompleted(); + scheduler.Start(); + Assert.Equal(4, fixture.Value); + }); /// /// Tests that Observable As Property Helpers should subscribe immediately to source. @@ -231,9 +234,10 @@ public void OAPHDeferSubscriptionWithInitialValueShouldNotEmitInitialValue(int i public void OAPHDeferSubscriptionWithInitialFuncValueShouldNotEmitInitialValueNorAccessFunc() { var observable = Observable.Empty(); - Func throwIfAccessed = () => throw new Exception(); - var fixture = new ObservableAsPropertyHelper(observable, _ => { }, getInitialValue: throwIfAccessed, deferSubscription: true); + static int ThrowIfAccessed() => throw new Exception(); + + var fixture = new ObservableAsPropertyHelper(observable, _ => { }, getInitialValue: ThrowIfAccessed, deferSubscription: true); Assert.False(fixture.IsSubscribed); @@ -271,13 +275,13 @@ public void OAPHDeferSubscriptionWithInitialFuncValueEmitInitialValueWhenSubscri { var observable = Observable.Empty(); var wasAccessed = false; - Func getInitialValue = () => + int GetInitialValue() { wasAccessed = true; return 42; - }; + } - var fixture = new ObservableAsPropertyHelper(observable, _ => { }, getInitialValue: getInitialValue, deferSubscription: true); + var fixture = new ObservableAsPropertyHelper(observable, _ => { }, getInitialValue: GetInitialValue, deferSubscription: true); Assert.False(fixture.IsSubscribed); Assert.False(wasAccessed); @@ -312,30 +316,30 @@ public void OAPHInitialValueShouldEmitInitialValue(int initialValue) /// Tests that Observable As Property Helpers should rethrow errors. /// [Fact] - public void OAPHShouldRethrowErrors() - { - var input = new Subject(); - var scheduler = new TestScheduler(); + public void OAPHShouldRethrowErrors() => + new TestScheduler().With(scheduler => + { + var input = new Subject(); - var fixture = new ObservableAsPropertyHelper(input, _ => { }, -5, scheduler: scheduler); - var errors = new List(); + var fixture = new ObservableAsPropertyHelper(input, _ => { }, -5, scheduler: scheduler); + var errors = new List(); - Assert.Equal(-5, fixture.Value); - new[] { 1, 2, 3, 4 }.Run(x => input.OnNext(x)); + Assert.Equal(-5, fixture.Value); + new[] { 1, 2, 3, 4 }.Run(x => input.OnNext(x)); - fixture.ThrownExceptions.Subscribe(errors.Add); + fixture.ThrownExceptions.Subscribe(errors.Add); - scheduler.Start(); + scheduler.Start(); - Assert.Equal(4, fixture.Value); + Assert.Equal(4, fixture.Value); - input.OnError(new Exception("Die!")); + input.OnError(new Exception("Die!")); - scheduler.Start(); + scheduler.Start(); - Assert.Equal(4, fixture.Value); - Assert.Equal(1, errors.Count); - } + Assert.Equal(4, fixture.Value); + Assert.Equal(1, errors.Count); + }); /// /// Test that no thrown exceptions subscriber equals Observable As Property Helper death. @@ -481,24 +485,23 @@ public void ToProperty_NameOf_ValidValuesProduced(string[] testWords, string[] f /// Tests to make sure that the ToProperty with a indexer notifies the expected property name. /// [Fact] - public void ToProperty_GivenIndexer_NotifiesOnExpectedPropertyName() => - new TestScheduler().With(scheduler => - { - var fixture = new OAPHIndexerTestFixture(0); - var propertiesChanged = new List(); + public void ToProperty_GivenIndexer_NotifiesOnExpectedPropertyName() + { + var fixture = new OAPHIndexerTestFixture(0, ImmediateScheduler.Instance); + var propertiesChanged = new List(); - fixture.PropertyChanged += (_, args) => + fixture.PropertyChanged += (_, args) => + { + if (args.PropertyName is not null) { - if (args.PropertyName is not null) - { - propertiesChanged.Add(args.PropertyName); - } - }; + propertiesChanged.Add(args.PropertyName); + } + }; - fixture.Text = "awesome"; + fixture.Text = "awesome"; - Assert.Equal(new[] { "Text", "Item[]" }, propertiesChanged); - }); + Assert.Equal(new[] { "Text", "Item[]" }, propertiesChanged); + } /// /// Tests to make sure that the ToProperty with a indexer notifies the expected property name. @@ -506,10 +509,9 @@ public void ToProperty_NameOf_ValidValuesProduced(string[] testWords, string[] f [Fact] public void ToProperty_GivenIndexer_NotifiesOnExpectedPropertyName1() => new TestScheduler().With(scheduler => - { Assert.Throws(() => { - var fixture = new OAPHIndexerTestFixture(1); + var fixture = new OAPHIndexerTestFixture(1, scheduler); var propertiesChanged = new List(); fixture.PropertyChanged += (_, args) => @@ -521,8 +523,7 @@ public void ToProperty_NameOf_ValidValuesProduced(string[] testWords, string[] f }; fixture.Text = "awesome"; - }); - }); + })); /// /// Tests to make sure that the ToProperty with a indexer notifies the expected property name. @@ -530,12 +531,10 @@ public void ToProperty_NameOf_ValidValuesProduced(string[] testWords, string[] f [Fact] public void ToProperty_GivenIndexer_NotifiesOnExpectedPropertyName2() => new TestScheduler().With(scheduler => - { Assert.Throws(() => { - var fixture = new OAPHIndexerTestFixture(2); - }); - }); + var fixture = new OAPHIndexerTestFixture(2, scheduler); + })); /// /// Nullables the types test shouldnt need decorators with toproperty. diff --git a/src/ReactiveUI.Tests/ObservedChanged/ObservedChangedMixinTest.cs b/src/ReactiveUI.Tests/ObservedChanged/ObservedChangedMixinTest.cs index 10325585ac..c0cd17321d 100644 --- a/src/ReactiveUI.Tests/ObservedChanged/ObservedChangedMixinTest.cs +++ b/src/ReactiveUI.Tests/ObservedChanged/ObservedChangedMixinTest.cs @@ -160,18 +160,17 @@ public void SetValuePathSmokeTest() /// Tests to make sure that BindTo can handle Stack Overflow conditions. /// [Fact] - public void BindToStackOverFlowTest() - { - // Before the code changes packed in the same commit - // as this test the test would go into an infinite - // event storm. The critical issue is that the - // property StackOverflowTrigger will clone the - // value before setting it. - // - // If this test executes through without hanging then - // the problem has been fixed. + public void BindToStackOverFlowTest() => new TestScheduler().With(_ => { + // Before the code changes packed in the same commit + // as this test the test would go into an infinite + // event storm. The critical issue is that the + // property StackOverflowTrigger will clone the + // value before setting it. + // + // If this test executes through without hanging then + // the problem has been fixed. var fixtureA = new TestFixture(); var fixtureB = new TestFixture(); @@ -179,6 +178,5 @@ public void BindToStackOverFlowTest() source.BindTo(fixtureA, x => x.StackOverflowTrigger); }); - } } } diff --git a/src/ReactiveUI.Tests/Platforms/windows-xaml/CommandBindingImplementationTests.cs b/src/ReactiveUI.Tests/Platforms/windows-xaml/CommandBindingImplementationTests.cs index fb136fc74a..b5525aeb34 100644 --- a/src/ReactiveUI.Tests/Platforms/windows-xaml/CommandBindingImplementationTests.cs +++ b/src/ReactiveUI.Tests/Platforms/windows-xaml/CommandBindingImplementationTests.cs @@ -215,7 +215,7 @@ public void CommandBindWithParameterObservable() var view = new CommandBindView { ViewModel = new() }; var received = 0; - var cmd = ReactiveCommand.Create(i => { received = i; }); + var cmd = ReactiveCommand.Create(i => received = i); view.ViewModel.Command1 = cmd; view.ViewModel.Value = 10; var value = view.ViewModel.WhenAnyValue(v => v.Value); diff --git a/src/ReactiveUI.Tests/Platforms/windows-xaml/DependencyObjectObservableForPropertyTest.cs b/src/ReactiveUI.Tests/Platforms/windows-xaml/DependencyObjectObservableForPropertyTest.cs index f5c1792597..52897d2a84 100644 --- a/src/ReactiveUI.Tests/Platforms/windows-xaml/DependencyObjectObservableForPropertyTest.cs +++ b/src/ReactiveUI.Tests/Platforms/windows-xaml/DependencyObjectObservableForPropertyTest.cs @@ -34,13 +34,7 @@ public void DependencyObjectObservableForPropertySmokeTest() var results = new List>(); Expression> expression = x => x.TestString; - var propertyName = expression.Body.GetMemberInfo()?.Name; - - if (propertyName is null) - { - throw new InvalidOperationException("There is no valid property name"); - } - + var propertyName = expression.Body.GetMemberInfo()?.Name ?? throw new InvalidOperationException("There is no valid property name"); var disp1 = binder.GetNotificationForProperty(fixture, expression.Body, propertyName).WhereNotNull().Subscribe(results.Add); var disp2 = binder.GetNotificationForProperty(fixture, expression.Body, propertyName).WhereNotNull().Subscribe(results.Add); @@ -66,13 +60,7 @@ public void DerivedDependencyObjectObservableForPropertySmokeTest() var results = new List>(); Expression> expression = x => x.TestString; - var propertyName = expression.Body.GetMemberInfo()?.Name; - - if (propertyName is null) - { - throw new InvalidOperationException("There is no valid property name"); - } - + var propertyName = expression.Body.GetMemberInfo()?.Name ?? throw new InvalidOperationException("There is no valid property name"); var disp1 = binder.GetNotificationForProperty(fixture, expression.Body, propertyName).WhereNotNull().Subscribe(results.Add); var disp2 = binder.GetNotificationForProperty(fixture, expression.Body, propertyName).WhereNotNull().Subscribe(results.Add); diff --git a/src/ReactiveUI.Tests/Platforms/windows-xaml/XamlViewCommandTests.cs b/src/ReactiveUI.Tests/Platforms/windows-xaml/XamlViewCommandTests.cs index b2b16f1bf5..4b0b4fc29b 100644 --- a/src/ReactiveUI.Tests/Platforms/windows-xaml/XamlViewCommandTests.cs +++ b/src/ReactiveUI.Tests/Platforms/windows-xaml/XamlViewCommandTests.cs @@ -33,7 +33,7 @@ public class XamlViewCommandTests public void EventBinderBindsToExplicitInheritedEvent() { var fixture = new FakeView(); - fixture.BindCommand(fixture!.ViewModel!, x => x!.Cmd, x => x.TheTextBox, "MouseDown"); + fixture.BindCommand(fixture!.ViewModel, x => x!.Cmd, x => x.TheTextBox, "MouseDown"); } /// @@ -49,7 +49,7 @@ public void EventBinderBindsToImplicitEvent() Assert.True(fixture.GetAffinityForObject(input.GetType(), false) > 0); var invokeCount = 0; - cmd.Subscribe(_ => invokeCount += 1); + cmd.Subscribe(_ => ++invokeCount); var disp = fixture.BindCommandToObject(cmd, input, Observable.Return((object)5)); Assert.NotNull(disp); diff --git a/src/ReactiveUI.Tests/Platforms/winforms/CommandBindingImplementationTests.cs b/src/ReactiveUI.Tests/Platforms/winforms/CommandBindingImplementationTests.cs index debca7bfb3..62fec631f0 100644 --- a/src/ReactiveUI.Tests/Platforms/winforms/CommandBindingImplementationTests.cs +++ b/src/ReactiveUI.Tests/Platforms/winforms/CommandBindingImplementationTests.cs @@ -4,7 +4,7 @@ // See the LICENSE file in the project root for full license information. using System.Windows.Forms; - +using ReactiveUI.Testing; using Xunit; namespace ReactiveUI.Tests.Winforms @@ -45,15 +45,21 @@ public void CommandBindByNameWireup() /// /// Tests the command bind explicit event wire up. /// + /// A representing the asynchronous unit test. [Fact] - public void CommandBindToExplicitEventWireup() + public async Task CommandBindToExplicitEventWireupAsync() { + using var testSequencer = new TestSequencer(); var vm = new WinformCommandBindViewModel(); var view = new WinformCommandBindView { ViewModel = vm }; var fixture = new CommandBinderImplementation(); var invokeCount = 0; - vm.Command2.Subscribe(_ => ++invokeCount); + vm.Command2.Subscribe(async _ => + { + ++invokeCount; + await testSequencer.AdvancePhaseAsync(); + }); var disp = fixture.BindCommand(vm, view, x => x.Command2, x => x.Command2, "MouseUp"); @@ -62,6 +68,8 @@ public void CommandBindToExplicitEventWireup() disp.Dispose(); view.Command2.RaiseMouseUpEvent(new MouseEventArgs(MouseButtons.Left, 1, 0, 0, 0)); + + await testSequencer.AdvancePhaseAsync(); Assert.Equal(1, invokeCount); } diff --git a/src/ReactiveUI.Tests/Platforms/winforms/CommandBindingTests.cs b/src/ReactiveUI.Tests/Platforms/winforms/CommandBindingTests.cs index 0d90700fdd..ee51b012c1 100644 --- a/src/ReactiveUI.Tests/Platforms/winforms/CommandBindingTests.cs +++ b/src/ReactiveUI.Tests/Platforms/winforms/CommandBindingTests.cs @@ -4,7 +4,7 @@ // See the LICENSE file in the project root for full license information. using System.Windows.Forms; - +using ReactiveUI.Testing; using ReactiveUI.Winforms; using Xunit; @@ -23,6 +23,7 @@ public class CommandBindingTests [Fact] public async Task CommandBinderBindsToButtonAsync() { + using var testSequencer = new TestSequencer(); var fixture = new CreatesWinformsCommandBinding(); var cmd = ReactiveCommand.CreateRunInBackground(_ => { }); var input = new Button(); @@ -31,16 +32,17 @@ public async Task CommandBinderBindsToButtonAsync() Assert.True(fixture.GetAffinityForObject(input.GetType(), false) > 0); var commandExecuted = false; object? ea = null; - cmd.Subscribe(o => + cmd.Subscribe(async o => { ea = o; commandExecuted = true; + await testSequencer.AdvancePhaseAsync("Phase 1"); }); using (fixture.BindCommandToObject(cmd, input, Observable.Return((object)5))) { input.PerformClick(); - await Task.Delay(10); + await testSequencer.AdvancePhaseAsync("Phase 1"); Assert.True(commandExecuted); Assert.NotNull(ea); } diff --git a/src/ReactiveUI.Tests/Platforms/winforms/DefaultPropertyBindingTests.cs b/src/ReactiveUI.Tests/Platforms/winforms/DefaultPropertyBindingTests.cs index 7e0e61b5d3..f181aa066d 100644 --- a/src/ReactiveUI.Tests/Platforms/winforms/DefaultPropertyBindingTests.cs +++ b/src/ReactiveUI.Tests/Platforms/winforms/DefaultPropertyBindingTests.cs @@ -32,13 +32,7 @@ public void WinformsCreatesObservableForPropertyWorksForTextboxes() Expression> expression = x => x.Text; - var propertyName = expression.Body.GetMemberInfo()?.Name; - - if (propertyName is null) - { - throw new InvalidOperationException("propertyName should not be null."); - } - + var propertyName = expression.Body.GetMemberInfo()?.Name ?? throw new InvalidOperationException("propertyName should not be null."); var dispose = fixture.GetNotificationForProperty(input, expression.Body, propertyName).ToObservableChangeSet(scheduler: ImmediateScheduler.Instance).Bind(out var output).Subscribe(); Assert.Equal(0, output.Count); @@ -65,13 +59,7 @@ public void WinformsCreatesObservableForPropertyWorksForComponents() Assert.NotEqual(0, fixture.GetAffinityForObject(typeof(ToolStripButton), "Checked")); Expression> expression = x => x.Checked; - var propertyName = expression.Body.GetMemberInfo()?.Name; - - if (propertyName is null) - { - throw new InvalidOperationException("propertyName should not be null."); - } - + var propertyName = expression.Body.GetMemberInfo()?.Name ?? throw new InvalidOperationException("propertyName should not be null."); var dispose = fixture.GetNotificationForProperty(input, expression.Body, propertyName).ToObservableChangeSet(scheduler: ImmediateScheduler.Instance).Bind(out var output).Subscribe(); Assert.Equal(0, output.Count); @@ -99,13 +87,7 @@ public void WinformsCreatesObservableForPropertyWorksForThirdPartyControls() Assert.NotEqual(0, fixture.GetAffinityForObject(typeof(AThirdPartyNamespace.ThirdPartyControl), "Value")); Expression> expression = x => x.Value; - var propertyName = expression.Body.GetMemberInfo()?.Name; - - if (propertyName is null) - { - throw new InvalidOperationException("propertyName should not be null."); - } - + var propertyName = expression.Body.GetMemberInfo()?.Name ?? throw new InvalidOperationException("propertyName should not be null."); var dispose = fixture.GetNotificationForProperty(input, expression.Body, propertyName).ToObservableChangeSet(scheduler: ImmediateScheduler.Instance).Bind(out var output).Subscribe(); Assert.Equal(0, output.Count); diff --git a/src/ReactiveUI.Tests/Platforms/winforms/WinFormsRoutedViewHostTests.cs b/src/ReactiveUI.Tests/Platforms/winforms/WinFormsRoutedViewHostTests.cs index 0a9dd343b2..bc0beaff97 100644 --- a/src/ReactiveUI.Tests/Platforms/winforms/WinFormsRoutedViewHostTests.cs +++ b/src/ReactiveUI.Tests/Platforms/winforms/WinFormsRoutedViewHostTests.cs @@ -16,7 +16,7 @@ public class WinFormsRoutedViewHostTests [Fact] public void ShouldDisposePreviousView() { - var viewLocator = new FakeViewLocator { LocatorFunc = t => new FakeWinformsView() }; + var viewLocator = new FakeViewLocator { LocatorFunc = _ => new FakeWinformsView() }; var router = new RoutingState(); var target = new WinFormsRoutedViewHost { Router = router, ViewLocator = viewLocator }; router?.Navigate?.Execute(new FakeWinformViewModel()); @@ -50,7 +50,7 @@ public void ShouldSetDefaultContentWhenViewModelIsNull() [Fact] public void WhenRoutedToViewModelItShouldAddViewToControls() { - var viewLocator = new FakeViewLocator { LocatorFunc = t => new FakeWinformsView() }; + var viewLocator = new FakeViewLocator { LocatorFunc = _ => new FakeWinformsView() }; var router = new RoutingState(); var target = new WinFormsRoutedViewHost { Router = router, ViewLocator = viewLocator }; router?.Navigate?.Execute(new FakeWinformViewModel()); diff --git a/src/ReactiveUI.Tests/Platforms/winforms/WinFormsViewModelViewHostTests.cs b/src/ReactiveUI.Tests/Platforms/winforms/WinFormsViewModelViewHostTests.cs index 67ac50e90d..713bb70628 100644 --- a/src/ReactiveUI.Tests/Platforms/winforms/WinFormsViewModelViewHostTests.cs +++ b/src/ReactiveUI.Tests/Platforms/winforms/WinFormsViewModelViewHostTests.cs @@ -18,11 +18,13 @@ public class WinFormsViewModelViewHostTests [Fact] public void SettingViewModelShouldAddTheViewtoItsControls() { - var viewLocator = new FakeViewLocator { LocatorFunc = t => new FakeWinformsView() }; - var target = new WinFormsViewModelViewHost(); - target.ViewLocator = viewLocator; + var viewLocator = new FakeViewLocator { LocatorFunc = _ => new FakeWinformsView() }; + var target = new WinFormsViewModelViewHost + { + ViewLocator = viewLocator, - target.ViewModel = new FakeWinformViewModel(); + ViewModel = new FakeWinformViewModel() + }; Assert.IsType(target.CurrentView); Assert.Equal(1, target.Controls.OfType().Count()); @@ -34,11 +36,11 @@ public void ShouldDisposePreviousView() var viewLocator = new FakeViewLocator { LocatorFunc = _ => new FakeWinformsView() }; var target = new WinFormsViewModelViewHost { - CacheViews = false - }; - target.ViewLocator = viewLocator; + CacheViews = false, + ViewLocator = viewLocator, - target.ViewModel = new FakeWinformViewModel(); + ViewModel = new FakeWinformViewModel() + }; var currentView = target.CurrentView; var isDisposed = false; @@ -66,9 +68,13 @@ public void ShouldCacheViewWhenEnabled() { var viewLocator = new FakeViewLocator { LocatorFunc = _ => new FakeWinformsView() }; var defaultContent = new Control(); - var target = new WinFormsViewModelViewHost { DefaultContent = defaultContent, ViewLocator = viewLocator, CacheViews = true }; - - target.ViewModel = new FakeWinformViewModel(); + var target = new WinFormsViewModelViewHost + { + DefaultContent = defaultContent, + ViewLocator = viewLocator, + CacheViews = true, + ViewModel = new FakeWinformViewModel() + }; var cachedView = target.Content; target.ViewModel = new FakeWinformViewModel(); Assert.True(ReferenceEquals(cachedView, target.Content)); @@ -79,9 +85,13 @@ public void ShouldNotCacheViewWhenDisabled() { var viewLocator = new FakeViewLocator { LocatorFunc = _ => new FakeWinformsView() }; var defaultContent = new Control(); - var target = new WinFormsViewModelViewHost { DefaultContent = defaultContent, ViewLocator = viewLocator, CacheViews = false }; - - target.ViewModel = new FakeWinformViewModel(); + var target = new WinFormsViewModelViewHost + { + DefaultContent = defaultContent, + ViewLocator = viewLocator, + CacheViews = false, + ViewModel = new FakeWinformViewModel() + }; var cachedView = target.CurrentView; target.ViewModel = new FakeWinformViewModel(); Assert.False(ReferenceEquals(cachedView, target.CurrentView)); diff --git a/src/ReactiveUI.Tests/Platforms/wpf/API/WpfApiApprovalTests.Wpf.DotNet6_0.verified.txt b/src/ReactiveUI.Tests/Platforms/wpf/API/WpfApiApprovalTests.Wpf.DotNet6_0.verified.txt new file mode 100644 index 0000000000..cc3c98af59 --- /dev/null +++ b/src/ReactiveUI.Tests/Platforms/wpf/API/WpfApiApprovalTests.Wpf.DotNet6_0.verified.txt @@ -0,0 +1,139 @@ +[assembly: System.Runtime.CompilerServices.InternalsVisibleTo("ReactiveUI.Tests")] +[assembly: System.Runtime.Versioning.SupportedOSPlatform("Windows10.0.17763.0")] +[assembly: System.Runtime.Versioning.TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName=".NET 6.0")] +[assembly: System.Runtime.Versioning.TargetPlatform("Windows10.0.17763.0")] +[assembly: System.Windows.Markup.XmlnsDefinition("http://reactiveui.net", "ReactiveUI")] +[assembly: System.Windows.ThemeInfo(System.Windows.ResourceDictionaryLocation.None, System.Windows.ResourceDictionaryLocation.SourceAssembly)] +namespace ReactiveUI +{ + public class ActivationForViewFetcher : ReactiveUI.IActivationForViewFetcher + { + public ActivationForViewFetcher() { } + public System.IObservable GetActivationForView(ReactiveUI.IActivatableView view) { } + public int GetAffinityForView(System.Type view) { } + } + public class AutoDataTemplateBindingHook : ReactiveUI.IPropertyBindingHook + { + public AutoDataTemplateBindingHook() { } + public static System.Lazy DefaultItemTemplate { get; } + public bool ExecuteHook(object? source, object target, System.Func[]> getCurrentViewModelProperties, System.Func[]> getCurrentViewProperties, ReactiveUI.BindingDirection direction) { } + } + public class AutoSuspendHelper : Splat.IEnableLogger + { + public AutoSuspendHelper(System.Windows.Application app) { } + public System.TimeSpan IdleTimeout { get; set; } + } + [System.Flags] + public enum BooleanToVisibilityHint + { + None = 0, + Inverse = 2, + UseHidden = 4, + } + public class BooleanToVisibilityTypeConverter : ReactiveUI.IBindingTypeConverter, Splat.IEnableLogger + { + public BooleanToVisibilityTypeConverter() { } + public int GetAffinityForObjects(System.Type fromType, System.Type toType) { } + public bool TryConvert(object? from, System.Type toType, object? conversionHint, out object result) { } + } + public class DependencyObjectObservableForProperty : ReactiveUI.ICreatesObservableForProperty, Splat.IEnableLogger + { + public DependencyObjectObservableForProperty() { } + public int GetAffinityForObject(System.Type type, string propertyName, bool beforeChanged = false) { } + public System.IObservable> GetNotificationForProperty(object sender, System.Linq.Expressions.Expression expression, string propertyName, bool beforeChanged = false, bool suppressWarnings = false) { } + } + public class PlatformOperations : ReactiveUI.IPlatformOperations + { + public PlatformOperations() { } + public string? GetOrientation() { } + } + public class ReactivePage : System.Windows.Controls.Page, ReactiveUI.IActivatableView, ReactiveUI.IViewFor, ReactiveUI.IViewFor + where TViewModel : class + { + public static readonly System.Windows.DependencyProperty ViewModelProperty; + public ReactivePage() { } + public TViewModel BindingRoot { get; } + public TViewModel ViewModel { get; set; } + } + public class ReactiveUserControl : System.Windows.Controls.UserControl, ReactiveUI.IActivatableView, ReactiveUI.IViewFor, ReactiveUI.IViewFor + where TViewModel : class + { + public static readonly System.Windows.DependencyProperty ViewModelProperty; + public ReactiveUserControl() { } + public TViewModel BindingRoot { get; } + public TViewModel ViewModel { get; set; } + } + public class ReactiveWindow : System.Windows.Window, ReactiveUI.IActivatableView, ReactiveUI.IViewFor, ReactiveUI.IViewFor + where TViewModel : class + { + public static readonly System.Windows.DependencyProperty ViewModelProperty; + public ReactiveWindow() { } + public TViewModel BindingRoot { get; } + public TViewModel ViewModel { get; set; } + } + public class RoutedViewHost : ReactiveUI.TransitioningContentControl, ReactiveUI.IActivatableView, Splat.IEnableLogger + { + public static readonly System.Windows.DependencyProperty DefaultContentProperty; + public static readonly System.Windows.DependencyProperty RouterProperty; + public static readonly System.Windows.DependencyProperty ViewContractObservableProperty; + public RoutedViewHost() { } + public object DefaultContent { get; set; } + public ReactiveUI.RoutingState Router { get; set; } + public string? ViewContract { get; set; } + public System.IObservable ViewContractObservable { get; set; } + public ReactiveUI.IViewLocator? ViewLocator { get; set; } + } + [System.Windows.TemplatePart(Name="PART_Container", Type=typeof(System.Windows.FrameworkElement?))] + [System.Windows.TemplatePart(Name="PART_CurrentContentPresentationSite", Type=typeof(System.Windows.Controls.ContentPresenter?))] + [System.Windows.TemplatePart(Name="PART_PreviousImageSite", Type=typeof(System.Windows.Controls.Image?))] + [System.Windows.TemplateVisualState(GroupName="PresentationStates", Name="Normal")] + public class TransitioningContentControl : System.Windows.Controls.ContentControl + { + public static readonly System.Windows.DependencyProperty TransitionDirectionProperty; + public static readonly System.Windows.DependencyProperty TransitionDurationProperty; + public static readonly System.Windows.DependencyProperty TransitionProperty; + public TransitioningContentControl() { } + public ReactiveUI.TransitioningContentControl.TransitionDirection Direction { get; set; } + public System.TimeSpan Duration { get; set; } + public ReactiveUI.TransitioningContentControl.TransitionType Transition { get; set; } + public event System.Windows.RoutedEventHandler? TransitionCompleted; + public event System.Windows.RoutedEventHandler? TransitionStarted; + public override void OnApplyTemplate() { } + protected override void OnContentChanged(object oldContent, object newContent) { } + public enum TransitionDirection + { + Up = 0, + Down = 1, + Left = 2, + Right = 3, + } + public enum TransitionType + { + Fade = 0, + Move = 1, + Slide = 2, + Drop = 3, + Bounce = 4, + } + } + public class ViewModelViewHost : ReactiveUI.TransitioningContentControl, ReactiveUI.IActivatableView, ReactiveUI.IViewFor, Splat.IEnableLogger + { + public static readonly System.Windows.DependencyProperty DefaultContentProperty; + public static readonly System.Windows.DependencyProperty ViewContractObservableProperty; + public static readonly System.Windows.DependencyProperty ViewModelProperty; + public ViewModelViewHost() { } + public object DefaultContent { get; set; } + public string? ViewContract { get; set; } + public System.IObservable ViewContractObservable { get; set; } + public ReactiveUI.IViewLocator? ViewLocator { get; set; } + public object? ViewModel { get; set; } + } +} +namespace ReactiveUI.Wpf +{ + public class Registrations + { + public Registrations() { } + public void Register(System.Action, System.Type> registerFunction) { } + } +} \ No newline at end of file diff --git a/src/ReactiveUI.Tests/Platforms/wpf/API/WpfApiApprovalTests.Wpf.DotNet7_0.verified.txt b/src/ReactiveUI.Tests/Platforms/wpf/API/WpfApiApprovalTests.Wpf.DotNet7_0.verified.txt new file mode 100644 index 0000000000..1b219049f1 --- /dev/null +++ b/src/ReactiveUI.Tests/Platforms/wpf/API/WpfApiApprovalTests.Wpf.DotNet7_0.verified.txt @@ -0,0 +1,139 @@ +[assembly: System.Runtime.CompilerServices.InternalsVisibleTo("ReactiveUI.Tests")] +[assembly: System.Runtime.Versioning.SupportedOSPlatform("Windows10.0.17763.0")] +[assembly: System.Runtime.Versioning.TargetFramework(".NETCoreApp,Version=v7.0", FrameworkDisplayName=".NET 7.0")] +[assembly: System.Runtime.Versioning.TargetPlatform("Windows10.0.17763.0")] +[assembly: System.Windows.Markup.XmlnsDefinition("http://reactiveui.net", "ReactiveUI")] +[assembly: System.Windows.ThemeInfo(System.Windows.ResourceDictionaryLocation.None, System.Windows.ResourceDictionaryLocation.SourceAssembly)] +namespace ReactiveUI +{ + public class ActivationForViewFetcher : ReactiveUI.IActivationForViewFetcher + { + public ActivationForViewFetcher() { } + public System.IObservable GetActivationForView(ReactiveUI.IActivatableView view) { } + public int GetAffinityForView(System.Type view) { } + } + public class AutoDataTemplateBindingHook : ReactiveUI.IPropertyBindingHook + { + public AutoDataTemplateBindingHook() { } + public static System.Lazy DefaultItemTemplate { get; } + public bool ExecuteHook(object? source, object target, System.Func[]> getCurrentViewModelProperties, System.Func[]> getCurrentViewProperties, ReactiveUI.BindingDirection direction) { } + } + public class AutoSuspendHelper : Splat.IEnableLogger + { + public AutoSuspendHelper(System.Windows.Application app) { } + public System.TimeSpan IdleTimeout { get; set; } + } + [System.Flags] + public enum BooleanToVisibilityHint + { + None = 0, + Inverse = 2, + UseHidden = 4, + } + public class BooleanToVisibilityTypeConverter : ReactiveUI.IBindingTypeConverter, Splat.IEnableLogger + { + public BooleanToVisibilityTypeConverter() { } + public int GetAffinityForObjects(System.Type fromType, System.Type toType) { } + public bool TryConvert(object? from, System.Type toType, object? conversionHint, out object result) { } + } + public class DependencyObjectObservableForProperty : ReactiveUI.ICreatesObservableForProperty, Splat.IEnableLogger + { + public DependencyObjectObservableForProperty() { } + public int GetAffinityForObject(System.Type type, string propertyName, bool beforeChanged = false) { } + public System.IObservable> GetNotificationForProperty(object sender, System.Linq.Expressions.Expression expression, string propertyName, bool beforeChanged = false, bool suppressWarnings = false) { } + } + public class PlatformOperations : ReactiveUI.IPlatformOperations + { + public PlatformOperations() { } + public string? GetOrientation() { } + } + public class ReactivePage : System.Windows.Controls.Page, ReactiveUI.IActivatableView, ReactiveUI.IViewFor, ReactiveUI.IViewFor + where TViewModel : class + { + public static readonly System.Windows.DependencyProperty ViewModelProperty; + public ReactivePage() { } + public TViewModel BindingRoot { get; } + public TViewModel ViewModel { get; set; } + } + public class ReactiveUserControl : System.Windows.Controls.UserControl, ReactiveUI.IActivatableView, ReactiveUI.IViewFor, ReactiveUI.IViewFor + where TViewModel : class + { + public static readonly System.Windows.DependencyProperty ViewModelProperty; + public ReactiveUserControl() { } + public TViewModel BindingRoot { get; } + public TViewModel ViewModel { get; set; } + } + public class ReactiveWindow : System.Windows.Window, ReactiveUI.IActivatableView, ReactiveUI.IViewFor, ReactiveUI.IViewFor + where TViewModel : class + { + public static readonly System.Windows.DependencyProperty ViewModelProperty; + public ReactiveWindow() { } + public TViewModel BindingRoot { get; } + public TViewModel ViewModel { get; set; } + } + public class RoutedViewHost : ReactiveUI.TransitioningContentControl, ReactiveUI.IActivatableView, Splat.IEnableLogger + { + public static readonly System.Windows.DependencyProperty DefaultContentProperty; + public static readonly System.Windows.DependencyProperty RouterProperty; + public static readonly System.Windows.DependencyProperty ViewContractObservableProperty; + public RoutedViewHost() { } + public object DefaultContent { get; set; } + public ReactiveUI.RoutingState Router { get; set; } + public string? ViewContract { get; set; } + public System.IObservable ViewContractObservable { get; set; } + public ReactiveUI.IViewLocator? ViewLocator { get; set; } + } + [System.Windows.TemplatePart(Name="PART_Container", Type=typeof(System.Windows.FrameworkElement?))] + [System.Windows.TemplatePart(Name="PART_CurrentContentPresentationSite", Type=typeof(System.Windows.Controls.ContentPresenter?))] + [System.Windows.TemplatePart(Name="PART_PreviousImageSite", Type=typeof(System.Windows.Controls.Image?))] + [System.Windows.TemplateVisualState(GroupName="PresentationStates", Name="Normal")] + public class TransitioningContentControl : System.Windows.Controls.ContentControl + { + public static readonly System.Windows.DependencyProperty TransitionDirectionProperty; + public static readonly System.Windows.DependencyProperty TransitionDurationProperty; + public static readonly System.Windows.DependencyProperty TransitionProperty; + public TransitioningContentControl() { } + public ReactiveUI.TransitioningContentControl.TransitionDirection Direction { get; set; } + public System.TimeSpan Duration { get; set; } + public ReactiveUI.TransitioningContentControl.TransitionType Transition { get; set; } + public event System.Windows.RoutedEventHandler? TransitionCompleted; + public event System.Windows.RoutedEventHandler? TransitionStarted; + public override void OnApplyTemplate() { } + protected override void OnContentChanged(object oldContent, object newContent) { } + public enum TransitionDirection + { + Up = 0, + Down = 1, + Left = 2, + Right = 3, + } + public enum TransitionType + { + Fade = 0, + Move = 1, + Slide = 2, + Drop = 3, + Bounce = 4, + } + } + public class ViewModelViewHost : ReactiveUI.TransitioningContentControl, ReactiveUI.IActivatableView, ReactiveUI.IViewFor, Splat.IEnableLogger + { + public static readonly System.Windows.DependencyProperty DefaultContentProperty; + public static readonly System.Windows.DependencyProperty ViewContractObservableProperty; + public static readonly System.Windows.DependencyProperty ViewModelProperty; + public ViewModelViewHost() { } + public object DefaultContent { get; set; } + public string? ViewContract { get; set; } + public System.IObservable ViewContractObservable { get; set; } + public ReactiveUI.IViewLocator? ViewLocator { get; set; } + public object? ViewModel { get; set; } + } +} +namespace ReactiveUI.Wpf +{ + public class Registrations + { + public Registrations() { } + public void Register(System.Action, System.Type> registerFunction) { } + } +} \ No newline at end of file diff --git a/src/ReactiveUI.Tests/Platforms/wpf/API/WpfApiApprovalTests.Wpf.Net4_7.verified.txt b/src/ReactiveUI.Tests/Platforms/wpf/API/WpfApiApprovalTests.Wpf.Net4_7.verified.txt new file mode 100644 index 0000000000..079d7649ed --- /dev/null +++ b/src/ReactiveUI.Tests/Platforms/wpf/API/WpfApiApprovalTests.Wpf.Net4_7.verified.txt @@ -0,0 +1,137 @@ +[assembly: System.Runtime.CompilerServices.InternalsVisibleTo("ReactiveUI.Tests")] +[assembly: System.Runtime.Versioning.TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName=".NET Framework 4.7.2")] +[assembly: System.Windows.Markup.XmlnsDefinition("http://reactiveui.net", "ReactiveUI")] +[assembly: System.Windows.ThemeInfo(System.Windows.ResourceDictionaryLocation.None, System.Windows.ResourceDictionaryLocation.SourceAssembly)] +namespace ReactiveUI +{ + public class ActivationForViewFetcher : ReactiveUI.IActivationForViewFetcher + { + public ActivationForViewFetcher() { } + public System.IObservable GetActivationForView(ReactiveUI.IActivatableView view) { } + public int GetAffinityForView(System.Type view) { } + } + public class AutoDataTemplateBindingHook : ReactiveUI.IPropertyBindingHook + { + public AutoDataTemplateBindingHook() { } + public static System.Lazy DefaultItemTemplate { get; } + public bool ExecuteHook(object? source, object target, System.Func[]> getCurrentViewModelProperties, System.Func[]> getCurrentViewProperties, ReactiveUI.BindingDirection direction) { } + } + public class AutoSuspendHelper : Splat.IEnableLogger + { + public AutoSuspendHelper(System.Windows.Application app) { } + public System.TimeSpan IdleTimeout { get; set; } + } + [System.Flags] + public enum BooleanToVisibilityHint + { + None = 0, + Inverse = 2, + UseHidden = 4, + } + public class BooleanToVisibilityTypeConverter : ReactiveUI.IBindingTypeConverter, Splat.IEnableLogger + { + public BooleanToVisibilityTypeConverter() { } + public int GetAffinityForObjects(System.Type fromType, System.Type toType) { } + public bool TryConvert(object? from, System.Type toType, object? conversionHint, out object result) { } + } + public class DependencyObjectObservableForProperty : ReactiveUI.ICreatesObservableForProperty, Splat.IEnableLogger + { + public DependencyObjectObservableForProperty() { } + public int GetAffinityForObject(System.Type type, string propertyName, bool beforeChanged = false) { } + public System.IObservable> GetNotificationForProperty(object sender, System.Linq.Expressions.Expression expression, string propertyName, bool beforeChanged = false, bool suppressWarnings = false) { } + } + public class PlatformOperations : ReactiveUI.IPlatformOperations + { + public PlatformOperations() { } + public string? GetOrientation() { } + } + public class ReactivePage : System.Windows.Controls.Page, ReactiveUI.IActivatableView, ReactiveUI.IViewFor, ReactiveUI.IViewFor + where TViewModel : class + { + public static readonly System.Windows.DependencyProperty ViewModelProperty; + public ReactivePage() { } + public TViewModel BindingRoot { get; } + public TViewModel ViewModel { get; set; } + } + public class ReactiveUserControl : System.Windows.Controls.UserControl, ReactiveUI.IActivatableView, ReactiveUI.IViewFor, ReactiveUI.IViewFor + where TViewModel : class + { + public static readonly System.Windows.DependencyProperty ViewModelProperty; + public ReactiveUserControl() { } + public TViewModel BindingRoot { get; } + public TViewModel ViewModel { get; set; } + } + public class ReactiveWindow : System.Windows.Window, ReactiveUI.IActivatableView, ReactiveUI.IViewFor, ReactiveUI.IViewFor + where TViewModel : class + { + public static readonly System.Windows.DependencyProperty ViewModelProperty; + public ReactiveWindow() { } + public TViewModel BindingRoot { get; } + public TViewModel ViewModel { get; set; } + } + public class RoutedViewHost : ReactiveUI.TransitioningContentControl, ReactiveUI.IActivatableView, Splat.IEnableLogger + { + public static readonly System.Windows.DependencyProperty DefaultContentProperty; + public static readonly System.Windows.DependencyProperty RouterProperty; + public static readonly System.Windows.DependencyProperty ViewContractObservableProperty; + public RoutedViewHost() { } + public object DefaultContent { get; set; } + public ReactiveUI.RoutingState Router { get; set; } + public string? ViewContract { get; set; } + public System.IObservable ViewContractObservable { get; set; } + public ReactiveUI.IViewLocator? ViewLocator { get; set; } + } + [System.Windows.TemplatePart(Name="PART_Container", Type=typeof(System.Windows.FrameworkElement?))] + [System.Windows.TemplatePart(Name="PART_CurrentContentPresentationSite", Type=typeof(System.Windows.Controls.ContentPresenter?))] + [System.Windows.TemplatePart(Name="PART_PreviousImageSite", Type=typeof(System.Windows.Controls.Image?))] + [System.Windows.TemplateVisualState(GroupName="PresentationStates", Name="Normal")] + public class TransitioningContentControl : System.Windows.Controls.ContentControl + { + public static readonly System.Windows.DependencyProperty TransitionDirectionProperty; + public static readonly System.Windows.DependencyProperty TransitionDurationProperty; + public static readonly System.Windows.DependencyProperty TransitionProperty; + public TransitioningContentControl() { } + public ReactiveUI.TransitioningContentControl.TransitionDirection Direction { get; set; } + public System.TimeSpan Duration { get; set; } + public ReactiveUI.TransitioningContentControl.TransitionType Transition { get; set; } + public event System.Windows.RoutedEventHandler? TransitionCompleted; + public event System.Windows.RoutedEventHandler? TransitionStarted; + public override void OnApplyTemplate() { } + protected override void OnContentChanged(object oldContent, object newContent) { } + public enum TransitionDirection + { + Up = 0, + Down = 1, + Left = 2, + Right = 3, + } + public enum TransitionType + { + Fade = 0, + Move = 1, + Slide = 2, + Drop = 3, + Bounce = 4, + } + } + public class ViewModelViewHost : ReactiveUI.TransitioningContentControl, ReactiveUI.IActivatableView, ReactiveUI.IViewFor, Splat.IEnableLogger + { + public static readonly System.Windows.DependencyProperty DefaultContentProperty; + public static readonly System.Windows.DependencyProperty ViewContractObservableProperty; + public static readonly System.Windows.DependencyProperty ViewModelProperty; + public ViewModelViewHost() { } + public object DefaultContent { get; set; } + public string? ViewContract { get; set; } + public System.IObservable ViewContractObservable { get; set; } + public ReactiveUI.IViewLocator? ViewLocator { get; set; } + public object? ViewModel { get; set; } + } +} +namespace ReactiveUI.Wpf +{ + public class Registrations + { + public Registrations() { } + public void Register(System.Action, System.Type> registerFunction) { } + } +} \ No newline at end of file diff --git a/src/ReactiveUI.Tests/Platforms/wpf/API/WpfApiApprovalTests.cs b/src/ReactiveUI.Tests/Platforms/wpf/API/WpfApiApprovalTests.cs index fcdf40531e..eda570fbf0 100644 --- a/src/ReactiveUI.Tests/Platforms/wpf/API/WpfApiApprovalTests.cs +++ b/src/ReactiveUI.Tests/Platforms/wpf/API/WpfApiApprovalTests.cs @@ -22,7 +22,7 @@ public class WpfApiApprovalTests : ApiApprovalBase /// Checks the approved vs the received API. /// /// A task to monitor the process. - [Fact(Skip = "Need to resolve GeneratedInternalTypeHelper")] + [Fact] public Task Wpf() => CheckApproval(typeof(ReactiveWindow<>).Assembly); } } diff --git a/src/ReactiveUI.Tests/Platforms/wpf/WpfActivationForViewFetcherTest.cs b/src/ReactiveUI.Tests/Platforms/wpf/WpfActivationForViewFetcherTest.cs index 118325193d..87cacb8c7b 100644 --- a/src/ReactiveUI.Tests/Platforms/wpf/WpfActivationForViewFetcherTest.cs +++ b/src/ReactiveUI.Tests/Platforms/wpf/WpfActivationForViewFetcherTest.cs @@ -22,15 +22,19 @@ public void FrameworkElementIsActivatedAndDeactivated() var obs = activation.GetActivationForView(uc); obs.ToObservableChangeSet(scheduler: ImmediateScheduler.Instance).Bind(out var activated).Subscribe(); - var loaded = new RoutedEventArgs(); - loaded.RoutedEvent = FrameworkElement.LoadedEvent; + var loaded = new RoutedEventArgs + { + RoutedEvent = FrameworkElement.LoadedEvent + }; uc.RaiseEvent(loaded); new[] { true }.AssertAreEqual(activated); - var unloaded = new RoutedEventArgs(); - unloaded.RoutedEvent = FrameworkElement.UnloadedEvent; + var unloaded = new RoutedEventArgs + { + RoutedEvent = FrameworkElement.UnloadedEvent + }; uc.RaiseEvent(unloaded); @@ -40,15 +44,19 @@ public void FrameworkElementIsActivatedAndDeactivated() [Fact] public void IsHitTestVisibleActivatesFrameworkElement() { - var uc = new WpfTestUserControl(); - uc.IsHitTestVisible = false; + var uc = new WpfTestUserControl + { + IsHitTestVisible = false + }; var activation = new ActivationForViewFetcher(); var obs = activation.GetActivationForView(uc); obs.ToObservableChangeSet(scheduler: ImmediateScheduler.Instance).Bind(out var activated).Subscribe(); - var loaded = new RoutedEventArgs(); - loaded.RoutedEvent = FrameworkElement.LoadedEvent; + var loaded = new RoutedEventArgs + { + RoutedEvent = FrameworkElement.LoadedEvent + }; uc.RaiseEvent(loaded); @@ -60,8 +68,10 @@ public void IsHitTestVisibleActivatesFrameworkElement() // IsHitTestVisible true, we don't want the event to repeat unnecessarily. new[] { true }.AssertAreEqual(activated); - var unloaded = new RoutedEventArgs(); - unloaded.RoutedEvent = FrameworkElement.UnloadedEvent; + var unloaded = new RoutedEventArgs + { + RoutedEvent = FrameworkElement.UnloadedEvent + }; uc.RaiseEvent(unloaded); @@ -78,8 +88,10 @@ public void IsHitTestVisibleDeactivatesFrameworkElement() var obs = activation.GetActivationForView(uc); obs.ToObservableChangeSet(scheduler: ImmediateScheduler.Instance).Bind(out var activated).Subscribe(); - var loaded = new RoutedEventArgs(); - loaded.RoutedEvent = FrameworkElement.LoadedEvent; + var loaded = new RoutedEventArgs + { + RoutedEvent = FrameworkElement.LoadedEvent + }; uc.RaiseEvent(loaded); @@ -99,8 +111,10 @@ public void FrameworkElementIsActivatedAndDeactivatedWithHitTest() var obs = activation.GetActivationForView(uc); obs.ToObservableChangeSet(scheduler: ImmediateScheduler.Instance).Bind(out var activated).Subscribe(); - var loaded = new RoutedEventArgs(); - loaded.RoutedEvent = FrameworkElement.LoadedEvent; + var loaded = new RoutedEventArgs + { + RoutedEvent = FrameworkElement.LoadedEvent + }; uc.RaiseEvent(loaded); @@ -116,8 +130,10 @@ public void FrameworkElementIsActivatedAndDeactivatedWithHitTest() new[] { true, false, true }.AssertAreEqual(activated); - var unloaded = new RoutedEventArgs(); - unloaded.RoutedEvent = FrameworkElement.UnloadedEvent; + var unloaded = new RoutedEventArgs + { + RoutedEvent = FrameworkElement.UnloadedEvent + }; uc.RaiseEvent(unloaded); diff --git a/src/ReactiveUI.Tests/Platforms/wpf/WpfActiveContentTests.cs b/src/ReactiveUI.Tests/Platforms/wpf/WpfActiveContentTests.cs index a32086f872..8ec52b1ab7 100644 --- a/src/ReactiveUI.Tests/Platforms/wpf/WpfActiveContentTests.cs +++ b/src/ReactiveUI.Tests/Platforms/wpf/WpfActiveContentTests.cs @@ -6,7 +6,7 @@ using System.Windows; using DynamicData; - +using ReactiveUI.Testing; using Xunit; namespace ReactiveUI.Tests.Wpf @@ -18,8 +18,6 @@ namespace ReactiveUI.Tests.Wpf /// public class WpfActiveContentTests : IClassFixture { -#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. - /// /// Initializes a new instance of the class. /// @@ -74,7 +72,7 @@ public void BindListFunctionalTest() public void TransitioningContentControlTest() { var window = Fixture?.App?.MockWindowFactory(); - window!.WhenActivated(async d => + window!.WhenActivated(async _ => { window!.TransitioningContent.Duration = TimeSpan.FromMilliseconds(200); var transitioning = false; @@ -156,41 +154,42 @@ public void DummySuspensionDriverTest() public void TransitioninContentControlDpiTest() { var window = Fixture?.App?.TCMockWindowFactory(); + const int delay = 2000; - window!.WhenActivated(async d => + window!.WhenActivated(async _ => { TransitioningContentControl.OverrideDpi = true; window!.TransitioningContent.Height = 500; window.TransitioningContent.Width = 500; window.TransitioningContent.Content = new FirstView(); - await Task.Delay(5000).ConfigureAwait(true); + await Task.Delay(delay).ConfigureAwait(true); window.TransitioningContent.Content = new SecondView(); - await Task.Delay(5000).ConfigureAwait(true); + await Task.Delay(delay).ConfigureAwait(true); window.TransitioningContent.Height = 300; window.TransitioningContent.Width = 300; window.TransitioningContent.Content = new FirstView(); - await Task.Delay(5000).ConfigureAwait(true); + await Task.Delay(delay).ConfigureAwait(true); window.TransitioningContent.Content = new SecondView(); window.TransitioningContent.Height = 0.25; window.TransitioningContent.Width = 0.25; window.TransitioningContent.Content = new FirstView(); - await Task.Delay(5000).ConfigureAwait(true); + await Task.Delay(delay).ConfigureAwait(true); window.TransitioningContent.Content = new SecondView(); window.TransitioningContent.Height = 500; window.TransitioningContent.Width = 500; window.TransitioningContent.Content = new FirstView(); - await Task.Delay(5000).ConfigureAwait(true); + await Task.Delay(delay).ConfigureAwait(true); window.TransitioningContent.Content = new SecondView(); - await Task.Delay(5000).ConfigureAwait(true); + await Task.Delay(delay).ConfigureAwait(true); window.TransitioningContent.Height = 300; window.TransitioningContent.Width = 300; window.TransitioningContent.Content = new FirstView(); - await Task.Delay(5000).ConfigureAwait(true); + await Task.Delay(delay).ConfigureAwait(true); window.TransitioningContent.Content = new SecondView(); window.TransitioningContent.Height = 0.25; window.TransitioningContent.Width = 0.25; window.TransitioningContent.Content = new FirstView(); - await Task.Delay(5000).ConfigureAwait(true); + await Task.Delay(delay).ConfigureAwait(true); window.TransitioningContent.Content = new SecondView(); window.Close(); }); @@ -206,11 +205,12 @@ public void ReactiveCommandRunningOnTaskThreadAllowsCanExecuteAndExecutingToFire { try { + using var testSequencer = new TestSequencer(); window!.TransitioningContent.VerticalContentAlignment = VerticalAlignment.Stretch; window!.TransitioningContent.HorizontalContentAlignment = HorizontalAlignment.Stretch; var view = new CanExecuteExecutingView(); window!.TransitioningContent.Content = view; - await Task.Delay(5000).ConfigureAwait(true); + await Task.Delay(2000).ConfigureAwait(true); var isExecutingExecuted = false; view!.ViewModel!.Command3.IsExecuting @@ -224,9 +224,13 @@ public void ReactiveCommandRunningOnTaskThreadAllowsCanExecuteAndExecutingToFire }).DisposeWith(d); int? result = null; - view!.ViewModel!.Command3.Subscribe(r => result = r); + view!.ViewModel!.Command3.Subscribe(async r => + { + result = r; + await testSequencer.AdvancePhaseAsync(); + }); await view!.ViewModel!.Command3.Execute(); - await Task.Delay(5000).ConfigureAwait(true); + await testSequencer.AdvancePhaseAsync(); Assert.Equal(100, result); Assert.True(isExecutingExecuted); } @@ -238,7 +242,5 @@ public void ReactiveCommandRunningOnTaskThreadAllowsCanExecuteAndExecutingToFire }); window!.ShowDialog(); } - -#pragma warning restore CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. } } diff --git a/src/ReactiveUI.Tests/Platforms/wpf/WpfCommandBindingImplementationTests.cs b/src/ReactiveUI.Tests/Platforms/wpf/WpfCommandBindingImplementationTests.cs index 6fc01ca3c7..413eada6a6 100644 --- a/src/ReactiveUI.Tests/Platforms/wpf/WpfCommandBindingImplementationTests.cs +++ b/src/ReactiveUI.Tests/Platforms/wpf/WpfCommandBindingImplementationTests.cs @@ -223,10 +223,7 @@ public void CommandBindViewModelToViewWithFunc() var view = new CommandBindingView { ViewModel = vm }; // Create a paramenter feed - vm.Command2.Subscribe(_ => - { - vm.Value++; - }); + vm.Command2.Subscribe(_ => vm.Value++); view.BindCommand(vm, x => x.Command2, x => x.Command2, "MouseUp"); // Bind the command and the Func parameter. diff --git a/src/ReactiveUI.Tests/ReactiveObject/ReactiveObjectTests.cs b/src/ReactiveUI.Tests/ReactiveObject/ReactiveObjectTests.cs index 1c09b393e3..89a1bee503 100644 --- a/src/ReactiveUI.Tests/ReactiveObject/ReactiveObjectTests.cs +++ b/src/ReactiveUI.Tests/ReactiveObject/ReactiveObjectTests.cs @@ -23,8 +23,8 @@ public class ReactiveObjectTests [Fact] public void ChangingShouldAlwaysArriveBeforeChanged() { - var beforeSet = "Foo"; - var afterSet = "Bar"; + const string beforeSet = "Foo"; + const string afterSet = "Bar"; var fixture = new TestFixture { @@ -126,7 +126,7 @@ public void ExceptionsThrownInSubscribersShouldMarshalToThrownExceptions() IsOnlyOneWord = "Foo" }; - fixture.Changed.Subscribe(x => { throw new Exception("Die!"); }); + fixture.Changed.Subscribe(_ => throw new Exception("Die!")); fixture.ThrownExceptions.ToObservableChangeSet(ImmediateScheduler.Instance).Bind(out var exceptionList).Subscribe(); fixture.IsOnlyOneWord = "Bar"; @@ -202,12 +202,7 @@ public void ReactiveObjectShouldntSerializeAnythingExtra() IsNotNullString = "Foo", IsOnlyOneWord = "Baz" }; - var json = JSONHelper.Serialize(fixture); - - if (json is null) - { - throw new InvalidOperationException("JSON string should not be null"); - } + var json = JSONHelper.Serialize(fixture) ?? throw new InvalidOperationException("JSON string should not be null"); // Should look something like: // {"IsNotNullString":"Foo","IsOnlyOneWord":"Baz","NullableInt":null,"PocoProperty":null,"StackOverflowTrigger":null,"TestCollection":[],"UsesExprRaiseSet":null} @@ -257,7 +252,7 @@ public void ReactiveObjectShouldRethrowException() { var fixture = new TestFixture(); var observable = fixture.WhenAnyValue(x => x.IsOnlyOneWord).Skip(1); - observable.Subscribe(x => throw new Exception("This is a test.")); + observable.Subscribe(_ => throw new Exception("This is a test.")); var result = Record.Exception(() => fixture.IsOnlyOneWord = "Two Words"); diff --git a/src/ReactiveUI.Tests/Resolvers/INPCObservableForPropertyTests.cs b/src/ReactiveUI.Tests/Resolvers/INPCObservableForPropertyTests.cs index 612c476880..bac967a938 100644 --- a/src/ReactiveUI.Tests/Resolvers/INPCObservableForPropertyTests.cs +++ b/src/ReactiveUI.Tests/Resolvers/INPCObservableForPropertyTests.cs @@ -38,13 +38,7 @@ public void NotificationOnPropertyChanged() var changes = new List>(); - var propertyName = exp.GetMemberInfo()?.Name; - - if (propertyName is null) - { - throw new InvalidOperationException("propertyName should not be null"); - } - + var propertyName = exp.GetMemberInfo()?.Name ?? throw new InvalidOperationException("propertyName should not be null"); instance.GetNotificationForProperty(testClass, exp, propertyName).WhereNotNull().Subscribe(c => changes.Add(c)); testClass.Property1 = "test1"; @@ -68,13 +62,7 @@ public void NotificationOnPropertyChanging() var changes = new List>(); - var propertyName = exp.GetMemberInfo()?.Name; - - if (propertyName is null) - { - throw new InvalidOperationException("propertyName should not be null"); - } - + var propertyName = exp.GetMemberInfo()?.Name ?? throw new InvalidOperationException("propertyName should not be null"); instance.GetNotificationForProperty(testClass, exp, propertyName, true).WhereNotNull().Subscribe(c => changes.Add(c)); testClass.Property1 = "test1"; @@ -98,13 +86,7 @@ public void NotificationOnWholeObjectChanged() var changes = new List>(); - var propertyName = exp.GetMemberInfo()?.Name; - - if (propertyName is null) - { - throw new InvalidOperationException("propertyName should not be null"); - } - + var propertyName = exp.GetMemberInfo()?.Name ?? throw new InvalidOperationException("propertyName should not be null"); instance.GetNotificationForProperty(testClass, exp, propertyName, false).WhereNotNull().Subscribe(c => changes.Add(c)); testClass.OnPropertyChanged(null); @@ -128,13 +110,7 @@ public void NotificationOnWholeObjectChanging() var changes = new List>(); - var propertyName = exp.GetMemberInfo()?.Name; - - if (propertyName is null) - { - throw new InvalidOperationException("propertyName should not be null"); - } - + var propertyName = exp.GetMemberInfo()?.Name ?? throw new InvalidOperationException("propertyName should not be null"); instance.GetNotificationForProperty(testClass, exp, propertyName, true).WhereNotNull().Subscribe(c => changes.Add(c)); testClass.OnPropertyChanging(null); diff --git a/src/ReactiveUI.Tests/Routing/RoutableViewModelMixinTests.cs b/src/ReactiveUI.Tests/Routing/RoutableViewModelMixinTests.cs index 8002214af5..383b2cc000 100644 --- a/src/ReactiveUI.Tests/Routing/RoutableViewModelMixinTests.cs +++ b/src/ReactiveUI.Tests/Routing/RoutableViewModelMixinTests.cs @@ -73,10 +73,7 @@ public void WhenNavigatedToCallsDisposeWhenViewModelLosesFocus() var vm = new RoutableViewModel(screen); var vm2 = new RoutableViewModel(screen); - vm.WhenNavigatedTo(() => - { - return Disposable.Create(() => count++); - }); + vm.WhenNavigatedTo(() => Disposable.Create(() => count++)); screen.Router.Navigate.Execute(vm); @@ -99,10 +96,7 @@ public void WhenNavigatedToCallsDisposeWhenNavigationStackIsReset() var vm1 = new RoutableViewModel(screen); var vm2 = new RoutableViewModel(screen); - vm1.WhenNavigatedTo(() => - { - return Disposable.Create(() => count++); - }); + vm1.WhenNavigatedTo(() => Disposable.Create(() => count++)); screen.Router.Navigate.Execute(vm1); @@ -124,10 +118,7 @@ public void WhenNavigatedToObservableFiresWhenViewModelAddedToNavigationStack() var screen = new TestScreen(); var vm = new RoutableViewModel(screen); - vm.WhenNavigatedToObservable().Subscribe(_ => - { - count++; - }); + vm.WhenNavigatedToObservable().Subscribe(_ => count++); screen.Router.Navigate.Execute(vm); @@ -146,10 +137,7 @@ public void WhenNavigatedToObservableFiresWhenViewModelReturnsToNavigationStack( var vm = new RoutableViewModel(screen); var vm2 = new RoutableViewModel(screen); - vm.WhenNavigatedToObservable().Subscribe(_ => - { - count++; - }); + vm.WhenNavigatedToObservable().Subscribe(_ => count++); screen.Router.Navigate.Execute(vm); screen.Router.Navigate.Execute(vm2); @@ -171,7 +159,7 @@ public void WhenNavigatedToObservableCompletesWhenViewModelIsRemovedFromNavigati vm.WhenNavigatedToObservable().Subscribe( _ => { }, - () => { count++; }); + () => count++); screen.Router.Navigate.Execute(vm); screen.Router.NavigateBack.Execute(); @@ -193,7 +181,7 @@ public void WhenNavigatedToObservableCompletesWhenNavigationStackIsReset() vm1.WhenNavigatedToObservable().Subscribe( _ => { }, - () => { count++; }); + () => count++); screen.Router.Navigate.Execute(vm1); screen.Router.NavigateAndReset.Execute(vm2); @@ -212,10 +200,7 @@ public void WhenNavigatingFromObservableFiresWhenViewModelLosesFocus() var vm = new RoutableViewModel(screen); var vm2 = new RoutableViewModel(screen); - vm.WhenNavigatingFromObservable().Subscribe(_ => - { - count++; - }); + vm.WhenNavigatingFromObservable().Subscribe(_ => count++); screen.Router.Navigate.Execute(vm); screen.Router.Navigate.Execute(vm2); @@ -236,7 +221,7 @@ public void WhenNavigatingFromObservableCompletesWhenViewModelIsRemovedFromNavig vm.WhenNavigatingFromObservable().Subscribe( _ => { }, - () => { count++; }); + () => count++); screen.Router.Navigate.Execute(vm); screen.Router.NavigateBack.Execute(); @@ -258,7 +243,7 @@ public void WhenNavigatingFromObservableCompletesWhenNavigationStackIsReset() vm1.WhenNavigatingFromObservable().Subscribe( _ => { }, - () => { count++; }); + () => count++); screen.Router.Navigate.Execute(vm1); screen.Router.NavigateAndReset.Execute(vm2); diff --git a/src/ReactiveUI.Tests/WhenAny/ReactiveNotifyPropertyChangedMixinTest.cs b/src/ReactiveUI.Tests/WhenAny/ReactiveNotifyPropertyChangedMixinTest.cs index 7f873bb690..af7774ce17 100644 --- a/src/ReactiveUI.Tests/WhenAny/ReactiveNotifyPropertyChangedMixinTest.cs +++ b/src/ReactiveUI.Tests/WhenAny/ReactiveNotifyPropertyChangedMixinTest.cs @@ -438,7 +438,7 @@ public void SubscriptionToWhenAnyShouldReturnCurrentValue() [Fact] public void WhenAnyShouldRunInContext() { - var tid = Thread.CurrentThread.ManagedThreadId; + var tid = Environment.CurrentManagedThreadId; TaskPoolScheduler.Default.With( _ => @@ -451,7 +451,7 @@ public void WhenAnyShouldRunInContext() PocoProperty = "Bamf" }; - fixture.WhenAnyValue(x => x.IsNotNullString).Subscribe(__ => whenAnyTid = Thread.CurrentThread.ManagedThreadId); + fixture.WhenAnyValue(x => x.IsNotNullString).Subscribe(__ => whenAnyTid = Environment.CurrentManagedThreadId); var timeout = 10; fixture.IsNotNullString = "Bar"; @@ -570,11 +570,11 @@ public void ChangingShouldHaveValidData() new TestScheduler().With( scheduler => { - var fixture = new HostTestFixture() + var fixture = new HostTestFixture { - Child = new TestFixture() + Child = new TestFixture(), + SomeOtherParam = 5 }; - fixture.SomeOtherParam = 5; fixture.Child.IsNotNullString = "Foo"; var output1 = new List>(); @@ -646,11 +646,11 @@ public void WhenAnyValueShouldWorkEvenWithNormalProperties() new TestScheduler().With( scheduler => { - var fixture = new HostTestFixture() + var fixture = new HostTestFixture { - Child = new TestFixture() + Child = new TestFixture(), + SomeOtherParam = 5 }; - fixture.SomeOtherParam = 5; fixture.Child.IsNotNullString = "Foo"; var output1 = new List(); @@ -1329,8 +1329,10 @@ public void WhenAnyValueWithToProperty() Assert.Equal(null, fixture.Owner); Assert.Equal(null, fixture.OwnerName); - fixture.Owner = new(); - fixture.Owner.Name = "Fred"; + fixture.Owner = new() + { + Name = "Fred" + }; Assert.NotNull(fixture.Owner); Assert.Equal("Fred", fixture.OwnerName); diff --git a/src/ReactiveUI.Tests/WhenAny/WhenAnyObservableTests.cs b/src/ReactiveUI.Tests/WhenAny/WhenAnyObservableTests.cs index 645d99be33..e367a39089 100644 --- a/src/ReactiveUI.Tests/WhenAny/WhenAnyObservableTests.cs +++ b/src/ReactiveUI.Tests/WhenAny/WhenAnyObservableTests.cs @@ -21,8 +21,10 @@ public class WhenAnyObservableTests [Fact] public void NullObservablesDoNotCauseExceptions() { - var fixture = new TestWhenAnyObsViewModel(); - fixture.Command1 = null; + var fixture = new TestWhenAnyObsViewModel + { + Command1 = null + }; // these are the overloads of WhenAnyObservable that perform a Merge fixture.WhenAnyObservable(x => x.Command1).Subscribe(); diff --git a/src/ReactiveUI.XamForms.Tests/RoutedViewHostTest.cs b/src/ReactiveUI.XamForms.Tests/RoutedViewHostTest.cs index 6781870b71..625ffbb296 100644 --- a/src/ReactiveUI.XamForms.Tests/RoutedViewHostTest.cs +++ b/src/ReactiveUI.XamForms.Tests/RoutedViewHostTest.cs @@ -359,13 +359,7 @@ private RoutedViewHost CreateRoutedViewHost(string? initialViewModel = nameof(Ma { if (initialViewModel is not null) { - var mainViewModel = Locator.Current.GetService(initialViewModel); - - if (mainViewModel is null) - { - throw new InvalidOperationException("There should be a valid view model."); - } - + var mainViewModel = Locator.Current.GetService(initialViewModel) ?? throw new InvalidOperationException("There should be a valid view model."); _navigationViewModel.Router.NavigationStack.Add(mainViewModel); }