mirror of
https://github.com/chylex/.NET-Community-Toolkit.git
synced 2024-11-23 22:42:47 +01:00
285 lines
8.3 KiB
C#
285 lines
8.3 KiB
C#
// 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 more information.
|
|
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.ComponentModel;
|
|
using System.ComponentModel.DataAnnotations;
|
|
using System.Linq;
|
|
using System.Reflection;
|
|
using CommunityToolkit.Mvvm.ComponentModel;
|
|
using CommunityToolkit.Mvvm.Messaging;
|
|
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
|
|
|
namespace CommunityToolkit.Mvvm.UnitTests;
|
|
|
|
[TestClass]
|
|
public partial class Test_ObservableRecipientAttribute
|
|
{
|
|
[TestMethod]
|
|
public void Test_ObservableRecipientAttribute_Events()
|
|
{
|
|
Person? model = new();
|
|
List<PropertyChangedEventArgs>? args = new();
|
|
|
|
model.PropertyChanged += (s, e) => args.Add(e);
|
|
|
|
Assert.IsFalse(model.HasErrors);
|
|
|
|
model.Name = "No";
|
|
|
|
Assert.IsTrue(model.HasErrors);
|
|
Assert.AreEqual(args.Count, 2);
|
|
Assert.AreEqual(args[0].PropertyName, nameof(Person.Name));
|
|
Assert.AreEqual(args[1].PropertyName, nameof(INotifyDataErrorInfo.HasErrors));
|
|
|
|
model.Name = "Valid";
|
|
|
|
Assert.IsFalse(model.HasErrors);
|
|
Assert.AreEqual(args.Count, 4);
|
|
Assert.AreEqual(args[2].PropertyName, nameof(Person.Name));
|
|
Assert.AreEqual(args[3].PropertyName, nameof(INotifyDataErrorInfo.HasErrors));
|
|
|
|
Assert.IsNotNull(typeof(Person).GetProperty("Messenger", BindingFlags.Instance | BindingFlags.NonPublic));
|
|
Assert.AreEqual(typeof(Person).GetConstructors(BindingFlags.Instance | BindingFlags.NonPublic).Length, 0);
|
|
}
|
|
|
|
[ObservableRecipient]
|
|
public partial class Person : ObservableValidator
|
|
{
|
|
public Person()
|
|
{
|
|
Messenger = WeakReferenceMessenger.Default;
|
|
}
|
|
|
|
private string? name;
|
|
|
|
[MinLength(4)]
|
|
[MaxLength(20)]
|
|
[Required]
|
|
public string? Name
|
|
{
|
|
get => this.name;
|
|
set => SetProperty(ref this.name, value, true);
|
|
}
|
|
|
|
public void TestCompile()
|
|
{
|
|
// Validates that the method Broadcast is correctly being generated
|
|
Broadcast(0, 1, nameof(TestCompile));
|
|
}
|
|
}
|
|
|
|
[TestMethod]
|
|
public void Test_ObservableRecipientAttribute_AbstractConstructors()
|
|
{
|
|
ConstructorInfo[]? ctors = typeof(AbstractPerson).GetConstructors(BindingFlags.Instance | BindingFlags.NonPublic);
|
|
|
|
Assert.AreEqual(ctors.Length, 2);
|
|
Assert.IsTrue(ctors.All(static ctor => ctor.IsFamily));
|
|
}
|
|
|
|
[ObservableRecipient]
|
|
public abstract partial class AbstractPerson : ObservableObject
|
|
{
|
|
}
|
|
|
|
[TestMethod]
|
|
public void Test_ObservableRecipientAttribute_NonAbstractConstructors()
|
|
{
|
|
ConstructorInfo[]? ctors = typeof(NonAbstractPerson).GetConstructors(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
|
|
|
|
Assert.AreEqual(ctors.Length, 2);
|
|
Assert.IsTrue(ctors.All(static ctor => ctor.IsPublic));
|
|
}
|
|
|
|
[ObservableRecipient]
|
|
public partial class NonAbstractPerson : ObservableObject
|
|
{
|
|
}
|
|
|
|
[TestMethod]
|
|
public void Test_ObservableRecipientAttribute_TrimmingAnnoations_IsActive()
|
|
{
|
|
bool shouldHaveTrimmingAnnotations =
|
|
#if NET6_0_OR_GREATER
|
|
true;
|
|
#else
|
|
false;
|
|
#endif
|
|
|
|
MethodInfo isActivePropertySetter = typeof(TestRecipient).GetProperty(nameof(TestRecipient.IsActive))!.SetMethod!;
|
|
|
|
if (shouldHaveTrimmingAnnotations)
|
|
{
|
|
Attribute[] attributes = isActivePropertySetter.GetCustomAttributes().ToArray();
|
|
|
|
Assert.AreEqual(1, attributes.Length);
|
|
Assert.AreEqual("System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute", attributes[0].GetType().ToString());
|
|
}
|
|
else
|
|
{
|
|
Attribute[] attributes = isActivePropertySetter.GetCustomAttributes().ToArray();
|
|
|
|
Assert.AreEqual(0, attributes.Length);
|
|
}
|
|
}
|
|
|
|
[TestMethod]
|
|
public void Test_ObservableRecipientAttribute_TrimmingAnnoations_OnActivated()
|
|
{
|
|
bool shouldHaveTrimmingAnnotations =
|
|
#if NET6_0_OR_GREATER
|
|
true;
|
|
#else
|
|
false;
|
|
#endif
|
|
|
|
MethodInfo onActivatedMethod = typeof(TestRecipient).GetMethod("OnActivated", BindingFlags.Instance | BindingFlags.NonPublic)!;
|
|
IEnumerable<Attribute> attributes = onActivatedMethod.GetCustomAttributes();
|
|
|
|
if (shouldHaveTrimmingAnnotations)
|
|
{
|
|
Assert.IsTrue(attributes.Any(static a => a.GetType().ToString() == "System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute"));
|
|
}
|
|
else
|
|
{
|
|
Assert.IsFalse(attributes.Any(static a => a.GetType().ToString() == "System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute"));
|
|
}
|
|
}
|
|
|
|
[ObservableRecipient]
|
|
public abstract partial class TestRecipient : ObservableObject
|
|
{
|
|
}
|
|
|
|
[TestMethod]
|
|
public void Test_ObservableRecipientAttribute_PersonWithCustomOnActivated()
|
|
{
|
|
PersonWithCustomOnActivated model = new();
|
|
|
|
model.IsActive = true;
|
|
|
|
Assert.IsTrue(model.Result);
|
|
}
|
|
|
|
[ObservableRecipient]
|
|
public partial class PersonWithCustomOnActivated : ObservableObject
|
|
{
|
|
public bool Result { get; private set; }
|
|
|
|
protected virtual partial void OnActivated()
|
|
{
|
|
Result = true;
|
|
}
|
|
}
|
|
|
|
[TestMethod]
|
|
public void Test_ObservableRecipientAttribute_PersonWithCustomOnDeactivated()
|
|
{
|
|
PersonWithCustomOnDeactivated model = new();
|
|
|
|
model.IsActive = true;
|
|
model.IsActive = false;
|
|
|
|
Assert.IsTrue(model.Result);
|
|
}
|
|
|
|
[ObservableRecipient]
|
|
public partial class PersonWithCustomOnDeactivated : ObservableObject
|
|
{
|
|
public bool Result { get; private set; }
|
|
|
|
protected virtual partial void OnDeactivated()
|
|
{
|
|
Result = true;
|
|
}
|
|
}
|
|
|
|
[TestMethod]
|
|
public void Test_ObservableRecipientAttribute_PersonWithCustomOnActivatedAndOnDeactivated()
|
|
{
|
|
PersonWithCustomOnActivatedAndOnDeactivated model = new();
|
|
|
|
model.IsActive = true;
|
|
|
|
Assert.IsTrue(model.OnActivatedResult);
|
|
|
|
model.IsActive = false;
|
|
|
|
Assert.IsTrue(model.OnDeactivatedResult);
|
|
}
|
|
|
|
[ObservableRecipient]
|
|
public partial class PersonWithCustomOnActivatedAndOnDeactivated : ObservableObject
|
|
{
|
|
public bool OnActivatedResult { get; private set; }
|
|
|
|
public bool OnDeactivatedResult { get; private set; }
|
|
|
|
protected virtual partial void OnActivated()
|
|
{
|
|
OnActivatedResult = true;
|
|
}
|
|
|
|
protected virtual partial void OnDeactivated()
|
|
{
|
|
OnDeactivatedResult = true;
|
|
}
|
|
}
|
|
|
|
[TestMethod]
|
|
public void Test_ObservableRecipientAttribute_SealedPersonWithCustomOnActivatedAndOnDeactivated()
|
|
{
|
|
SealedPersonWithCustomOnActivatedAndOnDeactivated model = new();
|
|
|
|
model.IsActive = true;
|
|
|
|
Assert.IsTrue(model.OnActivatedResult);
|
|
|
|
model.IsActive = false;
|
|
|
|
Assert.IsTrue(model.OnDeactivatedResult);
|
|
}
|
|
|
|
[ObservableRecipient]
|
|
public sealed partial class SealedPersonWithCustomOnActivatedAndOnDeactivated : ObservableObject
|
|
{
|
|
public bool OnActivatedResult { get; private set; }
|
|
|
|
public bool OnDeactivatedResult { get; private set; }
|
|
|
|
private partial void OnActivated()
|
|
{
|
|
OnActivatedResult = true;
|
|
}
|
|
|
|
private partial void OnDeactivated()
|
|
{
|
|
OnDeactivatedResult = true;
|
|
}
|
|
}
|
|
|
|
// See https://github.com/CommunityToolkit/dotnet/issues/109
|
|
[TestMethod]
|
|
public void Test_ObservableRecipientAttribute_WorksWithBaseClassWithObservableObjectAttribute()
|
|
{
|
|
ViewModelWithOnlyObservableRecipientAttribute model = new();
|
|
|
|
// This test method really only needs the two classes below to compile at all
|
|
Assert.IsTrue(model is INotifyPropertyChanged); // From [ObservableObject]
|
|
Assert.IsFalse(model.IsActive); // From [ObservableRecipient]
|
|
}
|
|
|
|
[ObservableObject]
|
|
public partial class BaseViewModelWithObservableObjectAttribute
|
|
{
|
|
}
|
|
|
|
[ObservableRecipient]
|
|
public partial class ViewModelWithOnlyObservableRecipientAttribute : BaseViewModelWithObservableObjectAttribute
|
|
{
|
|
}
|
|
}
|