using System.ComponentModel.DataAnnotations; using e_suite.API.Common; using e_suite.API.Common.exceptions; using e_suite.API.Common.models; using e_suite.API.Common.repository; using e_suite.Database.Audit; using e_suite.Database.Core.Tables.CustomFields; using e_suite.Database.Core.Tables.Domain; using e_suite.Database.Core.Tables.Forms; using e_suite.Database.Core.Tables.Glossaries; using e_suite.Service.CustomFieldValidation; using e_suite.UnitTestCore; using eSuite.Core.CustomFields; using eSuite.Core.Miscellaneous; using Moq; using NUnit.Framework; namespace e_suite.Service.CustomFieldValidationUnitTests; [TestFixture] public class CustomFieldValidatorUnitTests : TestBase { private Mock _customFieldValidatorRepositoryMock = null!; private Mock _sequenceManagerMock = null!; private CustomFieldValidator _customFieldValidator = null!; private AuditUserDetails _auditUserDetails = null!; [SetUp] public override async Task Setup() { await base.Setup(); _auditUserDetails = new() { UserId = 1, UserDisplayName = "Testy McTester", Comment = "I'm testing stuff to see if it works" }; _customFieldValidatorRepositoryMock = new(); _sequenceManagerMock = new(); _customFieldValidator = new(_customFieldValidatorRepositoryMock.Object, _sequenceManagerMock.Object); } [Test] public async Task ValidateFields_CalledWithEmptyValues_ReturnsNothing() { //Arrange var customFieldValues = new List(); var customFields = new List(); //Act var result = (await _customFieldValidator.ValidateFields(_auditUserDetails, customFieldValues, customFields, default)).ToList(); //Assert Assert.That(result.Count, Is.EqualTo(0)); } [Test] public void ValidateFields_CustomFieldsListNull_ThrowsException() { //Arrange var customFieldValues = new List(); List customFields = null!; //Act & Assert Assert.ThrowsAsync(async () => { var result = (await _customFieldValidator.ValidateFields(_auditUserDetails, customFieldValues, customFields, default)).ToList(); }); } [Test] public void ValidateFields_FieldDefinitionNotFound_ThowsExpectedException() { //Arrange var customFieldValues = new List { new() { Id = new GeneralIdRef { Guid = new Guid("{5814570A-7830-4160-9F64-5596A83616EC}") }, Values = [ new () { Value = "TestValue", DisplayValue = "TestValue" } ] } }; var customFields = new List(); //Act & Assert Assert.ThrowsAsync(async () => { var result = (await _customFieldValidator.ValidateFields(_auditUserDetails, customFieldValues, customFields, default)).ToList(); }); } [Test] public async Task ValidateFields_FieldDefinitionFound_ThrowsExpectedException() { //Arrange var customFieldValues = new List { new() { Id = new GeneralIdRef { Guid = new Guid("{5814570A-7830-4160-9F64-5596A83616EC}") }, Values = [new () { Value = "TestValue", DisplayValue = "TestValue"}] } }; var customFields = new List { new() { Id = 1, Guid = new("{5814570A-7830-4160-9F64-5596A83616EC}"), FieldType = FieldType.Text, DefaultValue = string.Empty } }; //Act var result = (await _customFieldValidator.ValidateFields(_auditUserDetails, customFieldValues, customFields, default)).ToList(); //Assert Assert.That(result.Count, Is.EqualTo(1)); Assert.That(result[0].CustomFieldId, Is.EqualTo(1)); Assert.That(result[0].Index, Is.EqualTo(0)); Assert.That(result[0].Value, Is.EqualTo("TestValue")); Assert.That(result[0].DisplayValue, Is.EqualTo("TestValue")); Assert.That(result[0].Valid, Is.True); } [Test] public async Task ValidateFields_FieldContainsDuplicates_ResultsFilterOutDuplicates() { //Arrange var customFieldValues = new List { new() { Id = new GeneralIdRef { Guid = new Guid("{5814570A-7830-4160-9F64-5596A83616EC}") }, Values = [new () {Value = "TestValue", DisplayValue = "TestValue"}, new() { Value = "TestValue", DisplayValue = "TestValue" }] } }; var customFields = new List { new() { Id = 1, Guid = new("{5814570A-7830-4160-9F64-5596A83616EC}"), FieldType = FieldType.Text, DefaultValue = string.Empty } }; //Act var result = (await _customFieldValidator.ValidateFields(_auditUserDetails, customFieldValues, customFields, default)).ToList(); //Assert Assert.That(result.Count, Is.EqualTo(1)); Assert.That(result[0].CustomFieldId, Is.EqualTo(1)); Assert.That(result[0].Index, Is.EqualTo(0)); Assert.That(result[0].Value, Is.EqualTo("TestValue")); Assert.That(result[0].DisplayValue, Is.EqualTo("TestValue")); Assert.That(result[0].Valid, Is.True); } [Test] public async Task ValidateFields_FieldContainsValueMissing_DefaultValueIsCreated() { //Arrange var customFieldValues = new List(); var customFields = new List { new() { Id = 1, Guid = new("{5814570A-7830-4160-9F64-5596A83616EC}"), FieldType = FieldType.Text, DefaultValue = "DefaultValue" } }; //Act var result = (await _customFieldValidator.ValidateFields(_auditUserDetails, customFieldValues, customFields, default)).ToList(); //Assert Assert.That(result.Count, Is.EqualTo(1)); Assert.That(result[0].CustomFieldId, Is.EqualTo(1)); Assert.That(result[0].Index, Is.EqualTo(0)); Assert.That(result[0].Value, Is.EqualTo("DefaultValue")); Assert.That(result[0].DisplayValue, Is.EqualTo("DefaultValue")); Assert.That(result[0].Valid, Is.True); } [Test] public async Task ValidateFields_FieldIsSequence_ValueObtainedFromSequence() { //Arrange var expectedResult = "1"; var customFieldValues = new List(); var customFields = new List { new() { Id = 1, Guid = new("{5814570A-7830-4160-9F64-5596A83616EC}"), FieldType = FieldType.Sequence, DefaultValue = "" } }; var sequenceValues = new List { expectedResult }; _sequenceManagerMock.Setup(x => x.NextValue(It.IsAny(), It.IsAny(), It.IsAny())).Returns(() => Task.FromResult>(sequenceValues)); //Act var result = (await _customFieldValidator.ValidateFields(_auditUserDetails, customFieldValues, customFields, default)).ToList(); //Assert Assert.That(result.Count, Is.EqualTo(1)); Assert.That(result[0].CustomFieldId, Is.EqualTo(1)); Assert.That(result[0].Index, Is.EqualTo(0)); Assert.That(result[0].Value, Is.EqualTo(expectedResult)); Assert.That(result[0].DisplayValue, Is.EqualTo(expectedResult)); Assert.That(result[0].Valid, Is.True); } [Test] public async Task ValidateFields_FieldIsSequenceAndValueAlreadySet_ValueIsNotChanged() { //Arrange var expectedResult = "2"; var customFieldValues = new List { new() { Id = new GeneralIdRef { Guid = new Guid("{5814570A-7830-4160-9F64-5596A83616EC}") }, Values = [new () { Value = expectedResult, DisplayValue = "TestValue"}] } }; var customFields = new List { new() { Id = 1, Guid = new("{5814570A-7830-4160-9F64-5596A83616EC}"), FieldType = FieldType.Sequence, DefaultValue = "" } }; var sequenceValues = new List { "2" }; _sequenceManagerMock.Setup(x => x.NextValue(It.IsAny(), It.IsAny(), It.IsAny())).Returns(() => Task.FromResult>(sequenceValues)); //Act var result = (await _customFieldValidator.ValidateFields(_auditUserDetails, customFieldValues, customFields, default)).ToList(); //Assert Assert.That(result.Count, Is.EqualTo(1)); Assert.That(result[0].CustomFieldId, Is.EqualTo(1)); Assert.That(result[0].Index, Is.EqualTo(0)); Assert.That(result[0].Value, Is.EqualTo(expectedResult)); Assert.That(result[0].DisplayValue, Is.EqualTo(expectedResult)); Assert.That(result[0].Valid, Is.True); } [Test] public void ValidateFields_AtLeastOneEntryRequiredAndNotSupplied_ThrowsMinEntryException() { //Arrange var customFieldValues = new List(); var customFields = new List { new() { Id = 1, Guid = new("{5814570A-7830-4160-9F64-5596A83616EC}"), Name = "TestFieldName", FieldType = FieldType.FormTemplate, DefaultValue = "", MinEntries = 1 } }; //Act var exception = Assert.ThrowsAsync(async () => { var result = (await _customFieldValidator.ValidateFields(_auditUserDetails, customFieldValues, customFields, default)).ToList(); }); //Assert Assert.That(exception?.Message, Is.EqualTo($"TestFieldName Requires at least one entry")); } [Test] public void ValidateFields_AtMostOneEntryRequiredAndTwoSupplied_ThrowsMaxEntryException() { //Arrange var customFieldValues = new List { new() { Id = new GeneralIdRef { Guid = new Guid("{5814570A-7830-4160-9F64-5596A83616EC}") }, Values = [new () { Value = "1", DisplayValue = "TestValue1"}, new() { Value = "2", DisplayValue = "TestValue2" }] } }; var customFields = new List { new() { Id = 1, Guid = new("{5814570A-7830-4160-9F64-5596A83616EC}"), Name = "TestFieldName", FieldType = FieldType.Text, DefaultValue = "", MaxEntries = 1 } }; //Act var exception = Assert.ThrowsAsync(async () => { var result = (await _customFieldValidator.ValidateFields(_auditUserDetails, customFieldValues, customFields, default)).ToList(); }); //Assert Assert.That(exception?.Message, Is.EqualTo($"TestFieldName Can have 1 entries at most")); } [Test] public void ValidateFields_FieldIsFormTemplateAndTemplateNotFound_ThrowsException() { //Arrange var customFieldValues = new List { new() { Id = new() { Guid = new Guid("{5814570A-7830-4160-9F64-5596A83616EC}") }, Values = [new () { Value = "{\"id\":1}", DisplayValue = "TestValue1"}] } }; var customFields = new List { new() { Id = 1, Guid = new("{5814570A-7830-4160-9F64-5596A83616EC}"), FieldType = FieldType.FormTemplate, DefaultValue = "" } }; //Act & Assert Assert.ThrowsAsync(async () => { var result = (await _customFieldValidator.ValidateFields(_auditUserDetails, customFieldValues, customFields, default)).ToList(); }); } [Test] public async Task ValidateFields_FieldIsFormTemplateAndTemplateFound_ReturnsExpectedResult() { //Arrange var customFieldValues = new List { new() { Id = new GeneralIdRef { Guid = new Guid("{5814570A-7830-4160-9F64-5596A83616EC}") }, Values = [new () { Value = "{\"id\":1}", DisplayValue = "TestValue1"}] } }; var customFields = new List { new() { Id = 1, Guid = new("{5814570A-7830-4160-9F64-5596A83616EC}"), FieldType = FieldType.FormTemplate, DefaultValue = "" } }; var formTemplate = new FormTemplate { Id = 1, Name = "TestForm", Guid = new("5D2D337A-EA31-4805-A580-F148D02E5A10") }; _customFieldValidatorRepositoryMock.Setup(x => x.GetTemplateByGeneralRefId(It.IsAny(), It.IsAny())) .Returns(Task.FromResult(formTemplate)!); //Act var result = (await _customFieldValidator.ValidateFields(_auditUserDetails, customFieldValues, customFields, default)).ToList(); //Assert Assert.That(result.Count, Is.EqualTo(1)); Assert.That(result[0].CustomFieldId, Is.EqualTo(1)); Assert.That(result[0].Index, Is.EqualTo(0)); Assert.That(result[0].Value, Is.EqualTo("5D2D337A-EA31-4805-A580-F148D02E5A10".ToLower())); Assert.That(result[0].DisplayValue, Is.EqualTo("TestForm")); Assert.That(result[0].Valid, Is.True); } [Test] public void ValidateFields_FieldIsGlossaryAndItemNotFound_ThrowsException() { //Arrange var customFieldValues = new List { new() { Id = new() { Guid = new Guid("{5814570A-7830-4160-9F64-5596A83616EC}") }, Values = [new () { Value = "{\"id\":1}", DisplayValue = "TestValue1"}] } }; var customFields = new List { new() { Id = 1, Guid = new("{5814570A-7830-4160-9F64-5596A83616EC}"), FieldType = FieldType.Glossary, DefaultValue = "" } }; //Act & Assert Assert.ThrowsAsync(async () => { var result = (await _customFieldValidator.ValidateFields(_auditUserDetails, customFieldValues, customFields, default)).ToList(); }); } [Test] public async Task ValidateFields_FieldIsGlossaryAndItemFound_ReturnsExpectedResult() { //Arrange var customFieldValues = new List { new() { Id = new GeneralIdRef { Guid = new Guid("{5814570A-7830-4160-9F64-5596A83616EC}") }, Values = [new () { Value = "{\"id\":1}", DisplayValue = "TestValue1"}] } }; var customFields = new List { new() { Id = 1, Guid = new("{5814570A-7830-4160-9F64-5596A83616EC}"), FieldType = FieldType.Glossary, DefaultValue = "" } }; var formTemplate = new Glossary { Id = 1, Name = "TestGlossary", Guid = new("2f28ac0a-d681-4ac1-82ff-aa423ca0e8fe") }; _customFieldValidatorRepositoryMock.Setup(x => x.GetGlossaryByGeneralRefId(It.IsAny(), It.IsAny())) .Returns(Task.FromResult(formTemplate)!); //Act var result = (await _customFieldValidator.ValidateFields(_auditUserDetails, customFieldValues, customFields, default)).ToList(); //Assert Assert.That(result.Count, Is.EqualTo(1)); Assert.That(result[0].CustomFieldId, Is.EqualTo(1)); Assert.That(result[0].Index, Is.EqualTo(0)); Assert.That(result[0].Value, Is.EqualTo("2f28ac0a-d681-4ac1-82ff-aa423ca0e8fe")); Assert.That(result[0].DisplayValue, Is.EqualTo("TestGlossary")); Assert.That(result[0].Valid, Is.True); } [Test] public async Task ValidateFields_FieldIsDomainAndItemFound_ReturnsExpectedResult() { //Arrange var customFieldGuid = new Guid("1a0bb5ad-201c-49d5-91f6-6b2326418525"); var customFieldValues = new List { new() { Id = new GeneralIdRef { Guid = customFieldGuid }, Values = [new () { Value = "{\"id\":1}", DisplayValue = "TestValue1"}] } }; var customFields = new List { new() { Id = 1, Guid = customFieldGuid, FieldType = FieldType.Domain, DefaultValue = "" } }; var formTemplate = new Domain { Id = 1, Name = "Test domain", Guid = new("c3856531-cb23-4559-9cb4-5d600c8ab457") }; _customFieldValidatorRepositoryMock.Setup(x => x.GetDomainByGeneralRefId(It.IsAny(), It.IsAny())) .Returns(Task.FromResult(formTemplate)!); //Act var result = (await _customFieldValidator.ValidateFields(_auditUserDetails, customFieldValues, customFields, default)).ToList(); //Assert Assert.That(result.Count, Is.EqualTo(1)); Assert.That(result[0].CustomFieldId, Is.EqualTo(1)); Assert.That(result[0].Index, Is.EqualTo(0)); Assert.That(result[0].Value, Is.EqualTo("c3856531-cb23-4559-9cb4-5d600c8ab457")); Assert.That(result[0].DisplayValue, Is.EqualTo("Test domain")); Assert.That(result[0].Valid, Is.True); } [Test] public async Task ValidateFields_FieldIsDomainGeneralIdRefAndItemFound_ReturnsExpectedResult() { //Arrange var customFieldGuid = new Guid("1a0bb5ad-201c-49d5-91f6-6b2326418525"); var customFieldValues = new List { new() { Id = new GeneralIdRef { Guid = customFieldGuid }, Values = [ new() { Value = new GeneralIdRef { Id = 1 } } ] } }; var customFields = new List { new() { Id = 1, Guid = customFieldGuid, FieldType = FieldType.Domain, DefaultValue = "" } }; var formTemplate = new Domain { Id = 1, Name = "Test domain", Guid = new("c3856531-cb23-4559-9cb4-5d600c8ab457") }; _customFieldValidatorRepositoryMock.Setup(x => x.GetDomainByGeneralRefId(It.IsAny(), It.IsAny())) .Returns(Task.FromResult(formTemplate)!); //Act var result = (await _customFieldValidator.ValidateFields(_auditUserDetails, customFieldValues, customFields, default)).ToList(); //Assert Assert.That(result.Count, Is.EqualTo(1)); Assert.That(result[0].CustomFieldId, Is.EqualTo(1)); Assert.That(result[0].Index, Is.EqualTo(0)); Assert.That(result[0].Value, Is.EqualTo("c3856531-cb23-4559-9cb4-5d600c8ab457")); Assert.That(result[0].DisplayValue, Is.EqualTo("Test domain")); Assert.That(result[0].Valid, Is.True); } [Test] public async Task ValidateFields_FieldIsNumberAndValueIsOptionalAndNoValueSupplied_ReturnsSuccess() { //Arrange var customFieldValues = new List { new() { Id = new() { Guid = new Guid("abe34ee2-f3cc-4968-b2a9-892bdc15192f") }, Values = [ new CustomFieldValue { Value = ""} ] } }; var customFields = new List { new() { Id = 1, Guid = new("abe34ee2-f3cc-4968-b2a9-892bdc15192f"), FieldType = FieldType.Number, DefaultValue = "", MinEntries = 0 } }; //Act var result = (await _customFieldValidator.ValidateFields(_auditUserDetails, customFieldValues, customFields, default)).ToList(); //Assert Assert.That(result.Count, Is.EqualTo(1)); } [Test] public async Task ValidateFields_FieldIsNumberAndValueMinusZero_ReturnsSuccessAndNumberSavedIsZero() { //Arrange var customFieldValues = new List { new() { Id = new GeneralIdRef { Guid = new Guid("abe34ee2-f3cc-4968-b2a9-892bdc15192f") }, Values = [new () { Value = "-0"}] } }; var customField = new CustomField { Id = 1, Guid = new("abe34ee2-f3cc-4968-b2a9-892bdc15192f"), FieldType = FieldType.Number, DefaultValue = "", MinEntries = 0 }; var customFields = new List { customField }; var customFieldNumber = new CustomFieldNumber { CustomField = customField, CustomFieldId = customField.Id, MaximumValue = null, MinimumValue = null, Step = null }; _customFieldValidatorRepositoryMock.Setup(x => x.GetCustomFieldNumbersAsync(1, It.IsAny())) .Returns(Task.FromResult(customFieldNumber)!); //Act var result = (await _customFieldValidator.ValidateFields(_auditUserDetails, customFieldValues, customFields, default)).ToList(); //Assert Assert.That(result.Count, Is.EqualTo(1)); Assert.That(result[0].DisplayValue, Is.EqualTo("0")); Assert.That(result[0].Value, Is.EqualTo("0")); } [Test] public void ValidateFields_FieldIsNumberAndValueIsBelowMinimumValue_ThrowsValidationException() { //Arrange var customFieldValues = new List { new() { Id = new GeneralIdRef { Guid = new Guid("abe34ee2-f3cc-4968-b2a9-892bdc15192f") }, Values = [new () { Value = "2"}] } }; var customField = new CustomField { Id = 1, Guid = new("abe34ee2-f3cc-4968-b2a9-892bdc15192f"), Name = "TestNumberField1", FieldType = FieldType.Number, DefaultValue = "", MinEntries = 0 }; var customFields = new List { customField, }; var customFieldNumber = new CustomFieldNumber { CustomField = customField, CustomFieldId = customField.Id, MaximumValue = null, MinimumValue =10, Step = null }; _customFieldValidatorRepositoryMock.Setup(x => x.GetCustomFieldNumbersAsync(1, It.IsAny())) .Returns(Task.FromResult(customFieldNumber)!); //Assert var exception = Assert.ThrowsAsync(async () => { //Act var result = (await _customFieldValidator.ValidateFields(_auditUserDetails, customFieldValues, customFields, default)).ToList(); }); Assert.That( exception?.Message, Is.EqualTo($"{customField.Name}: 2 must be greater than or equal to 10")); } [Test] public void ValidateFields_FieldIsNumberAndValueIsAboveMaximumValue_ThrowsValidationException() { //Arrange var customFieldValues = new List { new() { Id = new GeneralIdRef { Guid = new Guid("abe34ee2-f3cc-4968-b2a9-892bdc15192f") }, Values = [new () { Value = "300"}] } }; var customField = new CustomField { Id = 1, Guid = new("abe34ee2-f3cc-4968-b2a9-892bdc15192f"), Name = "TestNumberField1", FieldType = FieldType.Number, DefaultValue = "", MinEntries = 0 }; var customFields = new List { customField, }; var customFieldNumber = new CustomFieldNumber { CustomField = customField, CustomFieldId = customField.Id, MaximumValue = 200, MinimumValue = null, Step = null }; _customFieldValidatorRepositoryMock.Setup(x => x.GetCustomFieldNumbersAsync(1, It.IsAny())) .Returns(Task.FromResult(customFieldNumber)!); //Assert var exception = Assert.ThrowsAsync(async () => { //Act var result = (await _customFieldValidator.ValidateFields(_auditUserDetails, customFieldValues, customFields, default)).ToList(); }); Assert.That(exception?.Message, Is.EqualTo($"{customField.Name}: 300 must be less than or equal to 200")); } [Test] public void ValidateFields_FieldIsNumberAndValueRequiredButNotSupplied_ThrowsValidationException() { //Arrange var customFieldValues = new List { new() { Id = new GeneralIdRef { Guid = new Guid("abe34ee2-f3cc-4968-b2a9-892bdc15192f") }, Values = [new () { Value = ""}] } }; var customField = new CustomField { Id = 1, Guid = new("abe34ee2-f3cc-4968-b2a9-892bdc15192f"), Name = "TestNumberField1", FieldType = FieldType.Number, DefaultValue = "", MinEntries = 1 }; var customFields = new List { customField, }; var customFieldNumber = new CustomFieldNumber { CustomField = customField, CustomFieldId = customField.Id, MaximumValue = 200, MinimumValue = null, Step = null }; _customFieldValidatorRepositoryMock.Setup(x => x.GetCustomFieldNumbersAsync(1, It.IsAny())) .Returns(Task.FromResult(customFieldNumber)!); //Assert var exception = Assert.ThrowsAsync(async () => { //Act var result = (await _customFieldValidator.ValidateFields(_auditUserDetails, customFieldValues, customFields, default)).ToList(); }); Assert.That(exception?.Message, Is.EqualTo($"{customField.Name}: Missing required value")); } }