public void NotifiesValidationStateChangedAfterObjectValidation() { // Arrange var model = new TestModel { IntFrom1To100 = 101 }; var editContext = new EditContext(model); editContext.EnableDataAnnotationsValidation(); var onValidationStateChangedCount = 0; editContext.OnValidationStateChanged += (sender, eventArgs) => onValidationStateChangedCount++; // Act/Assert 1: Notifies after invalid results Assert.False(editContext.Validate()); Assert.Equal(1, onValidationStateChangedCount); // Act/Assert 2: Notifies after valid results model.RequiredString = "Hello"; model.IntFrom1To100 = 100; Assert.True(editContext.Validate()); Assert.Equal(2, onValidationStateChangedCount); // Act/Assert 3: Notifies even if results haven't changed. Later we might change the // logic to track the previous results and compare with the new ones, but that's just // an optimization. It's legal to notify regardless. Assert.True(editContext.Validate()); Assert.Equal(3, onValidationStateChangedCount); }
public void GetsValidationMessagesFromDataAnnotations() { // Arrange var model = new TestModel { IntFrom1To100 = 101 }; var editContext = new EditContext(model); editContext.EnableDataAnnotationsValidation(); // Act var isValid = editContext.Validate(); // Assert Assert.False(isValid); Assert.Equal(new string[] { "RequiredString:required", "IntFrom1To100:range" }, editContext.GetValidationMessages()); Assert.Equal(new string[] { "RequiredString:required" }, editContext.GetValidationMessages(editContext.Field(nameof(TestModel.RequiredString)))); // This shows we're including non-[Required] properties in the validation results, i.e, // that we're correctly passing "validateAllProperties: true" to DataAnnotations Assert.Equal(new string[] { "IntFrom1To100:range" }, editContext.GetValidationMessages(editContext.Field(nameof(TestModel.IntFrom1To100)))); }
public void ClearsExistingValidationMessagesOnFurtherRuns() { // Arrange var model = new TestModel { IntFrom1To100 = 101 }; var editContext = new EditContext(model); editContext.EnableDataAnnotationsValidation(); // Act/Assert 1: Initially invalid Assert.False(editContext.Validate()); // Act/Assert 2: Can become valid model.RequiredString = "Hello"; model.IntFrom1To100 = 100; Assert.True(editContext.Validate()); }
public void CanDetachFromEditContext() { // Arrange var model = new TestModel { IntFrom1To100 = 101 }; var editContext = new EditContext(model); var subscription = editContext.EnableDataAnnotationsValidation(); // Act/Assert 1: when we're attached Assert.False(editContext.Validate()); Assert.NotEmpty(editContext.GetValidationMessages()); // Act/Assert 2: when we're detached subscription.Dispose(); Assert.True(editContext.Validate()); Assert.Empty(editContext.GetValidationMessages()); }
public void IgnoresFieldChangesThatDoNotCorrespondToAValidatableProperty(string fieldName) { // Arrange var editContext = new EditContext(new TestModel()); editContext.EnableDataAnnotationsValidation(); var onValidationStateChangedCount = 0; editContext.OnValidationStateChanged += (sender, eventArgs) => onValidationStateChangedCount++; // Act/Assert: Ignores field changes that don't correspond to a validatable property editContext.NotifyFieldChanged(editContext.Field(fieldName)); Assert.Equal(0, onValidationStateChangedCount); // Act/Assert: For sanity, observe that we would have validated if it was a validatable property editContext.NotifyFieldChanged(editContext.Field(nameof(TestModel.RequiredString))); Assert.Equal(1, onValidationStateChangedCount); }
public void PerformsPerPropertyValidationOnFieldChange() { // Arrange var model = new TestModel { IntFrom1To100 = 101 }; var independentTopLevelModel = new object(); // To show we can validate things on any model, not just the top-level one var editContext = new EditContext(independentTopLevelModel); editContext.EnableDataAnnotationsValidation(); var onValidationStateChangedCount = 0; var requiredStringIdentifier = new FieldIdentifier(model, nameof(TestModel.RequiredString)); var intFrom1To100Identifier = new FieldIdentifier(model, nameof(TestModel.IntFrom1To100)); editContext.OnValidationStateChanged += (sender, eventArgs) => onValidationStateChangedCount++; // Act/Assert 1: Notify about RequiredString // Only RequiredString gets validated, even though IntFrom1To100 also holds an invalid value editContext.NotifyFieldChanged(requiredStringIdentifier); Assert.Equal(1, onValidationStateChangedCount); Assert.Equal(new[] { "RequiredString:required" }, editContext.GetValidationMessages()); // Act/Assert 2: Fix RequiredString, but only notify about IntFrom1To100 // Only IntFrom1To100 gets validated; messages for RequiredString are left unchanged model.RequiredString = "This string is very cool and very legal"; editContext.NotifyFieldChanged(intFrom1To100Identifier); Assert.Equal(2, onValidationStateChangedCount); Assert.Equal(new string[] { "RequiredString:required", "IntFrom1To100:range" }, editContext.GetValidationMessages()); // Act/Assert 3: Notify about RequiredString editContext.NotifyFieldChanged(requiredStringIdentifier); Assert.Equal(3, onValidationStateChangedCount); Assert.Equal(new[] { "IntFrom1To100:range" }, editContext.GetValidationMessages()); }