mirror of
https://github.com/chylex/.NET-Community-Toolkit.git
synced 2025-04-10 11:15:45 +02:00
Add unit tests for cancel commands
This commit is contained in:
parent
5afbbdf6f8
commit
1371da130a
tests
CommunityToolkit.Mvvm.SourceGenerators.UnitTests
CommunityToolkit.Mvvm.UnitTests
@ -554,6 +554,68 @@ private void GreetUser(User user)
|
||||
VerifyGeneratedDiagnostics<ICommandGenerator>(source, "MVVMTK0012");
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void InvalidICommandIncludeCancelCommandSettings_SynchronousMethod()
|
||||
{
|
||||
string source = @"
|
||||
using CommunityToolkit.Mvvm.Input;
|
||||
|
||||
namespace MyApp
|
||||
{
|
||||
public partial class SampleViewModel
|
||||
{
|
||||
[ICommand(IncludeCancelCommand = true)]
|
||||
private void GreetUser(User user)
|
||||
{
|
||||
}
|
||||
}
|
||||
}";
|
||||
|
||||
VerifyGeneratedDiagnostics<ICommandGenerator>(source, "MVVMTK0013");
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void InvalidICommandIncludeCancelCommandSettings_AsynchronousMethodWithNoCancellationToken()
|
||||
{
|
||||
string source = @"
|
||||
using System.Threading.Tasks;
|
||||
using CommunityToolkit.Mvvm.Input;
|
||||
|
||||
namespace MyApp
|
||||
{
|
||||
public partial class SampleViewModel
|
||||
{
|
||||
[ICommand(IncludeCancelCommand = true)]
|
||||
private async Task DoWorkAsync()
|
||||
{
|
||||
}
|
||||
}
|
||||
}";
|
||||
|
||||
VerifyGeneratedDiagnostics<ICommandGenerator>(source, "MVVMTK0013");
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void InvalidICommandIncludeCancelCommandSettings_AsynchronousMethodWithParameterAndNoCancellationToken()
|
||||
{
|
||||
string source = @"
|
||||
using System.Threading.Tasks;
|
||||
using CommunityToolkit.Mvvm.Input;
|
||||
|
||||
namespace MyApp
|
||||
{
|
||||
public partial class SampleViewModel
|
||||
{
|
||||
[ICommand(IncludeCancelCommand = true)]
|
||||
private async Task GreetUserAsync(User user)
|
||||
{
|
||||
}
|
||||
}
|
||||
}";
|
||||
|
||||
VerifyGeneratedDiagnostics<ICommandGenerator>(source, "MVVMTK0013");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies the output of a source generator.
|
||||
/// </summary>
|
||||
|
@ -6,6 +6,7 @@
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Input;
|
||||
using CommunityToolkit.Mvvm.Input;
|
||||
using CommunityToolkit.Mvvm.UnitTests.Helpers;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
@ -418,4 +419,68 @@ public void Test_AsyncRelayCommand_ExecuteWithoutConcurrencyRaisesCanExecuteChan
|
||||
|
||||
tcs.SetResult(null);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Test_AsyncRelayCommand_GetCancelCommand_DisabledCommand()
|
||||
{
|
||||
TaskCompletionSource<object?> tcs = new();
|
||||
|
||||
AsyncRelayCommand command = new(() => tcs.Task);
|
||||
|
||||
ICommand cancelCommand = command.CreateCancelCommand();
|
||||
|
||||
Assert.IsNotNull(cancelCommand);
|
||||
Assert.IsFalse(cancelCommand.CanExecute(null));
|
||||
|
||||
// No-op
|
||||
cancelCommand.Execute(null);
|
||||
|
||||
Assert.AreEqual("CommunityToolkit.Mvvm.Input.Internals.DisabledCommand", cancelCommand.GetType().ToString());
|
||||
|
||||
ICommand cancelCommand2 = command.CreateCancelCommand();
|
||||
|
||||
Assert.IsNotNull(cancelCommand2);
|
||||
Assert.IsFalse(cancelCommand2.CanExecute(null));
|
||||
|
||||
Assert.AreSame(cancelCommand, cancelCommand2);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Test_AsyncRelayCommand_GetCancelCommand_WithToken()
|
||||
{
|
||||
TaskCompletionSource<object?> tcs = new();
|
||||
|
||||
AsyncRelayCommand command = new(token => tcs.Task);
|
||||
|
||||
ICommand cancelCommand = command.CreateCancelCommand();
|
||||
|
||||
Assert.IsNotNull(cancelCommand);
|
||||
Assert.IsFalse(cancelCommand.CanExecute(null));
|
||||
|
||||
// No-op
|
||||
cancelCommand.Execute(null);
|
||||
|
||||
Assert.AreEqual("CommunityToolkit.Mvvm.Input.Internals.CancelCommand", cancelCommand.GetType().ToString());
|
||||
|
||||
List<(object? Sender, EventArgs Args)> cancelCommandCanExecuteChangedArgs = new();
|
||||
|
||||
cancelCommand.CanExecuteChanged += (s, e) => cancelCommandCanExecuteChangedArgs.Add((s, e));
|
||||
|
||||
command.Execute(null);
|
||||
|
||||
Assert.AreEqual(1, cancelCommandCanExecuteChangedArgs.Count);
|
||||
Assert.AreSame(cancelCommand, cancelCommandCanExecuteChangedArgs[0].Sender);
|
||||
Assert.AreSame(EventArgs.Empty, cancelCommandCanExecuteChangedArgs[0].Args);
|
||||
|
||||
Assert.IsTrue(cancelCommand.CanExecute(null));
|
||||
|
||||
cancelCommand.Execute(null);
|
||||
|
||||
Assert.IsFalse(cancelCommand.CanExecute(null));
|
||||
Assert.AreEqual(2, cancelCommandCanExecuteChangedArgs.Count);
|
||||
Assert.AreSame(cancelCommand, cancelCommandCanExecuteChangedArgs[1].Sender);
|
||||
Assert.AreSame(EventArgs.Empty, cancelCommandCanExecuteChangedArgs[1].Args);
|
||||
Assert.IsFalse(command.CanBeCanceled);
|
||||
Assert.IsTrue(command.IsCancellationRequested);
|
||||
}
|
||||
}
|
||||
|
@ -6,6 +6,7 @@
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Input;
|
||||
using CommunityToolkit.Mvvm.Input;
|
||||
using CommunityToolkit.Mvvm.UnitTests.Helpers;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
@ -360,4 +361,68 @@ public void Test_AsyncRelayCommand_ExecuteWithoutConcurrencyRaisesCanExecuteChan
|
||||
|
||||
tcs.SetResult(null);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Test_AsyncRelayCommandOfT_GetCancelCommand_DisabledCommand()
|
||||
{
|
||||
TaskCompletionSource<object?> tcs = new();
|
||||
|
||||
AsyncRelayCommand<string> command = new(s => tcs.Task);
|
||||
|
||||
ICommand cancelCommand = command.CreateCancelCommand();
|
||||
|
||||
Assert.IsNotNull(cancelCommand);
|
||||
Assert.IsFalse(cancelCommand.CanExecute(null));
|
||||
|
||||
// No-op
|
||||
cancelCommand.Execute(null);
|
||||
|
||||
Assert.AreEqual("CommunityToolkit.Mvvm.Input.Internals.DisabledCommand", cancelCommand.GetType().ToString());
|
||||
|
||||
ICommand cancelCommand2 = command.CreateCancelCommand();
|
||||
|
||||
Assert.IsNotNull(cancelCommand2);
|
||||
Assert.IsFalse(cancelCommand2.CanExecute(null));
|
||||
|
||||
Assert.AreSame(cancelCommand, cancelCommand2);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Test_AsyncRelayCommandOfT_GetCancelCommand_WithToken()
|
||||
{
|
||||
TaskCompletionSource<object?> tcs = new();
|
||||
|
||||
AsyncRelayCommand<string> command = new((s, token) => tcs.Task);
|
||||
|
||||
ICommand cancelCommand = command.CreateCancelCommand();
|
||||
|
||||
Assert.IsNotNull(cancelCommand);
|
||||
Assert.IsFalse(cancelCommand.CanExecute(null));
|
||||
|
||||
// No-op
|
||||
cancelCommand.Execute(null);
|
||||
|
||||
Assert.AreEqual("CommunityToolkit.Mvvm.Input.Internals.CancelCommand", cancelCommand.GetType().ToString());
|
||||
|
||||
List<(object? Sender, EventArgs Args)> cancelCommandCanExecuteChangedArgs = new();
|
||||
|
||||
cancelCommand.CanExecuteChanged += (s, e) => cancelCommandCanExecuteChangedArgs.Add((s, e));
|
||||
|
||||
command.Execute(null);
|
||||
|
||||
Assert.AreEqual(1, cancelCommandCanExecuteChangedArgs.Count);
|
||||
Assert.AreSame(cancelCommand, cancelCommandCanExecuteChangedArgs[0].Sender);
|
||||
Assert.AreSame(EventArgs.Empty, cancelCommandCanExecuteChangedArgs[0].Args);
|
||||
|
||||
Assert.IsTrue(cancelCommand.CanExecute(null));
|
||||
|
||||
cancelCommand.Execute(null);
|
||||
|
||||
Assert.IsFalse(cancelCommand.CanExecute(null));
|
||||
Assert.AreEqual(2, cancelCommandCanExecuteChangedArgs.Count);
|
||||
Assert.AreSame(cancelCommand, cancelCommandCanExecuteChangedArgs[1].Sender);
|
||||
Assert.AreSame(EventArgs.Empty, cancelCommandCanExecuteChangedArgs[1].Args);
|
||||
Assert.IsFalse(command.CanBeCanceled);
|
||||
Assert.IsTrue(command.IsCancellationRequested);
|
||||
}
|
||||
}
|
||||
|
@ -2,6 +2,7 @@
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
@ -74,6 +75,18 @@ public async Task Test_ICommandAttribute_RelayCommand()
|
||||
{
|
||||
Assert.AreSame(Task.CompletedTask, tasks[i]);
|
||||
}
|
||||
|
||||
tasks.Clear();
|
||||
|
||||
for (int i = 11; i < 21; i++)
|
||||
{
|
||||
tasks.Add(model.AddValueToListAndDelayWithDefaultConcurrencyAsync_WithCancelCommandCommand.ExecuteAsync(i));
|
||||
}
|
||||
|
||||
Assert.AreEqual(10, tasks.Count);
|
||||
|
||||
// Only the first item should have been added, like the previous case
|
||||
CollectionAssert.AreEqual(model.Values, Enumerable.Range(0, 12).ToArray());
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
@ -334,6 +347,34 @@ public void Test_ICommandAttribute_ViewModelRightAfterRegion()
|
||||
Assert.IsInstanceOfType(model.GreetCommand, typeof(RelayCommand));
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async void Test_ICommandAttribute_CancelCommands()
|
||||
{
|
||||
CancelCommandViewModel model = new();
|
||||
|
||||
model.DoWorkCommand.Execute(null);
|
||||
|
||||
Assert.IsTrue(model.DoWorkCancelCommand.CanExecute(null));
|
||||
|
||||
model.DoWorkCancelCommand.Execute(null);
|
||||
|
||||
await Task.Yield();
|
||||
|
||||
Assert.IsTrue(model.Tcs1.Task.IsCompleted);
|
||||
Assert.IsTrue(model.Tcs1.Task.Result is OperationCanceledException);
|
||||
|
||||
model.DoWorkWithParameterCommand.Execute(null);
|
||||
|
||||
Assert.IsTrue(model.DoWorkWithParameterCancelCommand.CanExecute(null));
|
||||
|
||||
model.DoWorkWithParameterCancelCommand.Execute(42);
|
||||
|
||||
await Task.Yield();
|
||||
|
||||
Assert.IsTrue(model.Tcs2.Task.IsCompleted);
|
||||
Assert.IsTrue(model.Tcs2.Task.Result is 42);
|
||||
}
|
||||
|
||||
#region Region
|
||||
public class Region
|
||||
{
|
||||
@ -399,6 +440,14 @@ private async Task AddValueToListAndDelayWithDefaultConcurrencyAsync(int value)
|
||||
await Task.Delay(1000);
|
||||
}
|
||||
|
||||
[ICommand(IncludeCancelCommand = true)]
|
||||
private async Task AddValueToListAndDelayWithDefaultConcurrencyAsync_WithCancelCommand(int value, CancellationToken token)
|
||||
{
|
||||
Values.Add(value);
|
||||
|
||||
await Task.Delay(1000);
|
||||
}
|
||||
|
||||
#region Test region
|
||||
|
||||
/// <summary>
|
||||
@ -567,4 +616,45 @@ public sealed class User
|
||||
{
|
||||
public string? Name { get; set; }
|
||||
}
|
||||
|
||||
public partial class CancelCommandViewModel
|
||||
{
|
||||
public TaskCompletionSource<object?> Tcs1 { get; } = new();
|
||||
|
||||
public TaskCompletionSource<object?> Tcs2 { get; } = new();
|
||||
|
||||
[ICommand(IncludeCancelCommand = true)]
|
||||
private async Task DoWorkAsync(CancellationToken token)
|
||||
{
|
||||
using CancellationTokenRegistration registration = token.Register(static state => ((TaskCompletionSource<object?>)state!).TrySetCanceled(), Tcs1);
|
||||
|
||||
try
|
||||
{
|
||||
_ = await Tcs1.Task;
|
||||
|
||||
_ = Tcs1.TrySetResult(null);
|
||||
}
|
||||
catch (OperationCanceledException e)
|
||||
{
|
||||
_ = Tcs1.TrySetResult(e);
|
||||
}
|
||||
}
|
||||
|
||||
[ICommand(IncludeCancelCommand = true)]
|
||||
private async Task DoWorkWithParameterAsync(int number, CancellationToken token)
|
||||
{
|
||||
using CancellationTokenRegistration registration = token.Register(static state => ((TaskCompletionSource<object?>)state!).TrySetCanceled(), Tcs2);
|
||||
|
||||
try
|
||||
{
|
||||
_ = await Tcs2.Task;
|
||||
|
||||
_ = Tcs2.TrySetResult(null);
|
||||
}
|
||||
catch (OperationCanceledException)
|
||||
{
|
||||
_ = Tcs2.TrySetResult(number);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user