Skip to content

Commit 6af95b5

Browse files
committed
Add tests for class-level attributes
1 parent 4d8630b commit 6af95b5

File tree

2 files changed

+162
-0
lines changed

2 files changed

+162
-0
lines changed

tests/CommunityToolkit.Mvvm.SourceGenerators.UnitTests/Test_SourceGeneratorsDiagnostics.cs

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1258,6 +1258,46 @@ public partial class SampleViewModel : ObservableValidator
12581258
VerifyGeneratedDiagnostics<ObservablePropertyGenerator>(source, "MVVMTK0026");
12591259
}
12601260

1261+
[TestMethod]
1262+
public void InvalidTypeForNotifyRecipientsError()
1263+
{
1264+
string source = @"
1265+
using CommunityToolkit.Mvvm.ComponentModel;
1266+
1267+
namespace MyApp
1268+
{
1269+
[NotifyRecipients]
1270+
public partial class MyViewModel : ObservableObject
1271+
{
1272+
[ObservableProperty]
1273+
public int number;
1274+
}
1275+
}";
1276+
1277+
VerifyGeneratedDiagnostics<ObservablePropertyGenerator>(source, "MVVMTK0027");
1278+
}
1279+
1280+
[TestMethod]
1281+
public void InvalidTypeForNotifyDataErrorInfoError()
1282+
{
1283+
string source = @"
1284+
using System.ComponentModel.DataAnnotations;
1285+
using CommunityToolkit.Mvvm.ComponentModel;
1286+
1287+
namespace MyApp
1288+
{
1289+
[NotifyDataErrorInfo]
1290+
public partial class SampleViewModel : ObservableObject
1291+
{
1292+
[ObservableProperty]
1293+
[Required]
1294+
private string name;
1295+
}
1296+
}";
1297+
1298+
VerifyGeneratedDiagnostics<ObservablePropertyGenerator>(source, "MVVMTK0006", "MVVMTK0028");
1299+
}
1300+
12611301
/// <summary>
12621302
/// Verifies the output of a source generator.
12631303
/// </summary>

tests/CommunityToolkit.Mvvm.UnitTests/Test_ObservablePropertyAttribute.cs

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -264,6 +264,32 @@ public void Test_ObservablePropertyWithValueNamedField_WithValidationAttributesA
264264
Assert.AreEqual(errors[1].PropertyName, nameof(ModelWithValuePropertyWithAutomaticValidation.Value));
265265
}
266266

267+
[TestMethod]
268+
public void Test_ObservablePropertyWithValueNamedField_WithValidationAttributesAndValidation_WithClassLevelAttribute()
269+
{
270+
ModelWithValuePropertyWithAutomaticValidationWithClassLevelAttribute model = new();
271+
272+
List<string?> propertyNames = new();
273+
274+
model.PropertyChanged += (s, e) => propertyNames.Add(e.PropertyName);
275+
276+
List<DataErrorsChangedEventArgs> errors = new();
277+
278+
model.ErrorsChanged += (s, e) => errors.Add(e);
279+
280+
model.Value = "Bo";
281+
282+
Assert.IsTrue(model.HasErrors);
283+
Assert.AreEqual(errors.Count, 1);
284+
Assert.AreEqual(errors[0].PropertyName, nameof(ModelWithValuePropertyWithAutomaticValidationWithClassLevelAttribute.Value));
285+
286+
model.Value = "Hello world";
287+
288+
Assert.IsFalse(model.HasErrors);
289+
Assert.AreEqual(errors.Count, 2);
290+
Assert.AreEqual(errors[1].PropertyName, nameof(ModelWithValuePropertyWithAutomaticValidationWithClassLevelAttribute.Value));
291+
}
292+
267293
// See https://github.com/CommunityToolkit/WindowsCommunityToolkit/issues/4184
268294
[TestMethod]
269295
public void Test_GeneratedPropertiesWithValidationAttributesOverFields()
@@ -424,6 +450,33 @@ public void Test_NotifyRecipients_WithInheritedObservableRecipientAttribute()
424450
propertyName: nameof(BroadcastingViewModelWithInheritedAttribute.Name2));
425451
}
426452

453+
[TestMethod]
454+
public void Test_NotifyRecipients_WithObservableObject_WithClassLevelAttribute()
455+
{
456+
Test_NotifyRecipients_Test(
457+
factory: static messenger => new BroadcastingViewModelWithClassLevelAttribute(messenger),
458+
setter: static (model, value) => model.Name = value,
459+
propertyName: nameof(BroadcastingViewModelWithClassLevelAttribute.Name));
460+
}
461+
462+
[TestMethod]
463+
public void Test_NotifyRecipients_WithObservableRecipientAttribute_WithClassLevelAttribute()
464+
{
465+
Test_NotifyRecipients_Test(
466+
factory: static messenger => new BroadcastingViewModelWithAttributeAndClassLevelAttribute(messenger),
467+
setter: static (model, value) => model.Name = value,
468+
propertyName: nameof(BroadcastingViewModelWithAttributeAndClassLevelAttribute.Name));
469+
}
470+
471+
[TestMethod]
472+
public void Test_NotifyRecipients_WithInheritedObservableRecipientAttribute_WithClassLevelAttribute()
473+
{
474+
Test_NotifyRecipients_Test(
475+
factory: static messenger => new BroadcastingViewModelWithInheritedAttributeAndClassLevelAttribute(messenger),
476+
setter: static (model, value) => model.Name2 = value,
477+
propertyName: nameof(BroadcastingViewModelWithInheritedAttributeAndClassLevelAttribute.Name2));
478+
}
479+
427480
private void Test_NotifyRecipients_Test<T>(Func<IMessenger, T> factory, Action<T, string?> setter, string propertyName)
428481
where T : notnull
429482
{
@@ -452,6 +505,24 @@ private void Test_NotifyRecipients_Test<T>(Func<IMessenger, T> factory, Action<T
452505
Assert.AreEqual(propertyName, messages[0].Message.PropertyName);
453506
}
454507

508+
[TestMethod]
509+
public void Test_ObservableProperty_ObservableRecipientDoesNotBroadcastByDefault()
510+
{
511+
IMessenger messenger = new StrongReferenceMessenger();
512+
RecipientWithNonBroadcastingProperty model = new(messenger);
513+
514+
List<(object Sender, PropertyChangedMessage<string?> Message)> messages = new();
515+
516+
messenger.Register<PropertyChangedMessage<string?>>(model, (r, m) => messages.Add((r, m)));
517+
518+
model.Name = "Bob";
519+
model.Name = "Alice";
520+
model.Name = null;
521+
522+
// The [NotifyRecipients] attribute wasn't used, so no messages should have been sent
523+
Assert.AreEqual(messages.Count, 0);
524+
}
525+
455526
#if NET6_0_OR_GREATER
456527
// See https://github.com/CommunityToolkit/dotnet/issues/155
457528
[TestMethod]
@@ -969,6 +1040,15 @@ public partial class ModelWithValuePropertyWithAutomaticValidation : ObservableV
9691040
private string? value;
9701041
}
9711042

1043+
[NotifyDataErrorInfo]
1044+
public partial class ModelWithValuePropertyWithAutomaticValidationWithClassLevelAttribute : ObservableValidator
1045+
{
1046+
[ObservableProperty]
1047+
[Required]
1048+
[MinLength(5)]
1049+
private string? value;
1050+
}
1051+
9721052
public partial class ViewModelWithValidatableGeneratedProperties : ObservableValidator
9731053
{
9741054
[Required]
@@ -1080,6 +1160,17 @@ public BroadcastingViewModel(IMessenger messenger)
10801160
private string? name;
10811161
}
10821162

1163+
partial class RecipientWithNonBroadcastingProperty : ObservableRecipient
1164+
{
1165+
public RecipientWithNonBroadcastingProperty(IMessenger messenger)
1166+
: base(messenger)
1167+
{
1168+
}
1169+
1170+
[ObservableProperty]
1171+
private string? name;
1172+
}
1173+
10831174
[ObservableRecipient]
10841175
partial class BroadcastingViewModelWithAttribute : ObservableObject
10851176
{
@@ -1100,6 +1191,37 @@ public BroadcastingViewModelWithInheritedAttribute(IMessenger messenger)
11001191
private string? name2;
11011192
}
11021193

1194+
[NotifyRecipients]
1195+
partial class BroadcastingViewModelWithClassLevelAttribute : ObservableRecipient
1196+
{
1197+
public BroadcastingViewModelWithClassLevelAttribute(IMessenger messenger)
1198+
: base(messenger)
1199+
{
1200+
}
1201+
1202+
[ObservableProperty]
1203+
private string? name;
1204+
}
1205+
1206+
[ObservableRecipient]
1207+
[NotifyRecipients]
1208+
partial class BroadcastingViewModelWithAttributeAndClassLevelAttribute : ObservableObject
1209+
{
1210+
[ObservableProperty]
1211+
private string? name;
1212+
}
1213+
1214+
partial class BroadcastingViewModelWithInheritedAttributeAndClassLevelAttribute : BroadcastingViewModelWithClassLevelAttribute
1215+
{
1216+
public BroadcastingViewModelWithInheritedAttributeAndClassLevelAttribute(IMessenger messenger)
1217+
: base(messenger)
1218+
{
1219+
}
1220+
1221+
[ObservableProperty]
1222+
private string? name2;
1223+
}
1224+
11031225
#if NET6_0_OR_GREATER
11041226
private partial class NullableRepro : ObservableObject
11051227
{

0 commit comments

Comments
 (0)