public async Task BuildFullDynamicDto_HasNoSideEffect_Test() { var entityConfigCacheMock = new Mock <IEntityConfigCache>(); entityConfigCacheMock.Setup(x => x.GetEntityPropertiesAsync(It.IsAny <Type>())) .Returns(() => { var result = new EntityPropertyDtoList(); var r = result as List <EntityPropertyDto>; return(Task.FromResult(r)); }); var entityConfigStore = LocalIocManager.Resolve <IEntityConfigurationStore>(); var cacheManager = LocalIocManager.Resolve <ICacheManager>(); var builder = new DynamicDtoTypeBuilder(entityConfigCacheMock.Object, entityConfigStore, cacheManager); var baseDtoType = typeof(DynamicDto <Person, Guid>); var proxyType1 = await builder.BuildDtoFullProxyTypeAsync(baseDtoType, new DynamicDtoTypeBuildingContext() { ModelType = baseDtoType, AddFormFieldsProperty = true, }); var proxyType2 = await builder.BuildDtoFullProxyTypeAsync(baseDtoType, new DynamicDtoTypeBuildingContext() { ModelType = baseDtoType, AddFormFieldsProperty = false, }); proxyType1.GetProperties().ShouldContain(p => p.Name == nameof(IHasFormFieldsList._formFields)); proxyType2.GetProperties().ShouldNotContain(p => p.Name == nameof(IHasFormFieldsList._formFields), $"Check internal cache in the '{nameof(DynamicDtoTypeBuilder)}'. Looks like property `{nameof(IHasFormFieldsList._formFields)}` exists in the result type because of caching"); }
public async Task BuildDynamicDto_WidthDtoReferences_Test() { var entityConfigCacheMock = new Mock <IEntityConfigCache>(); const string area1PropName = nameof(Person.AreaLevel1); entityConfigCacheMock.Setup(x => x.GetEntityPropertiesAsync(It.IsAny <Type>())) .Returns(() => { var result = new EntityPropertyDtoList(); result.Add(new EntityPropertyDto { Name = area1PropName, DataType = DataTypes.EntityReference, EntityType = "Shesha.Core.Area", }); var r = result as List <EntityPropertyDto>; return(Task.FromResult(r)); }); var entityConfigStore = LocalIocManager.Resolve <IEntityConfigurationStore>(); var cacheManager = LocalIocManager.Resolve <ICacheManager>(); var builder = new DynamicDtoTypeBuilder(entityConfigCacheMock.Object, entityConfigStore, cacheManager); var baseDtoType = typeof(DynamicDto <Person, Guid>); var context = new DynamicDtoTypeBuildingContext() { ModelType = baseDtoType, UseDtoForEntityReferences = true, // AddFormFieldsProperty = false // note: false is a default value for AddFormFieldsProperty. Leave it blank to test default value }; var proxyType = await builder.BuildDtoFullProxyTypeAsync(baseDtoType, context); proxyType.Assembly.IsDynamic.ShouldBeTrue(); var properties = proxyType.GetProperties(); properties.ShouldContain(p => p.Name == area1PropName); proxyType.ShouldNotBeAssignableTo(typeof(IHasFormFieldsList)); var area1Prop = properties.FirstOrDefault(p => p.Name == area1PropName); area1Prop.ShouldNotBeNull($"{area1PropName} property is missing in the created DTO"); var area1IsDto = area1Prop.PropertyType == typeof(EntityWithDisplayNameDto <Guid>); area1IsDto.ShouldBeTrue($"{area1PropName} is not mapped as '{nameof(EntityWithDisplayNameDto<Guid>)}'"); }
public async Task BuildFullDynamicDto_Test() { var entityConfigCacheMock = new Mock <IEntityConfigCache>(); entityConfigCacheMock.Setup(x => x.GetEntityPropertiesAsync(It.IsAny <Type>())) .Returns(() => { var result = new EntityPropertyDtoList(); result.AddString("Name", "Name..."); result.AddString("Description", "Description..."); var r = result as List <EntityPropertyDto>; return(Task.FromResult(r)); }); var entityConfigStore = LocalIocManager.Resolve <IEntityConfigurationStore>(); var cacheManager = LocalIocManager.Resolve <ICacheManager>(); var builder = new DynamicDtoTypeBuilder(entityConfigCacheMock.Object, entityConfigStore, cacheManager); var baseDtoType = typeof(DynamicDto <Person, Guid>); var context = new DynamicDtoTypeBuildingContext() { ModelType = baseDtoType, AddFormFieldsProperty = true, }; var proxyType = await builder.BuildDtoFullProxyTypeAsync(baseDtoType, context); var properties = proxyType.GetProperties(); properties.ShouldContain(p => p.Name == "Name"); properties.ShouldContain(p => p.Name == "Description"); properties.ShouldContain(p => p.Name == nameof(IHasFormFieldsList._formFields)); proxyType.ShouldNotBeAssignableTo(typeof(IHasFormFieldsList)); }
public async Task BuildDynamicDto_Test() { var entityConfigCacheMock = new Mock <IEntityConfigCache>(); const string supervisorPropName = "Supervisor"; const string supervisorFirstNamePropName = "FirstName"; const string supervisorLastNamePropName = "LastName"; entityConfigCacheMock.Setup(x => x.GetEntityPropertiesAsync(It.IsAny <Type>())) .Returns(() => { var result = new EntityPropertyDtoList(); result.AddString("Name", "Name..."); result.AddString("Description", "Description..."); var nested = new EntityPropertyDto { Name = supervisorPropName, DataType = DataTypes.Object, Properties = new List <EntityPropertyDto>(), }; nested.Properties.Add(new EntityPropertyDto { Name = supervisorFirstNamePropName, DataType = DataTypes.String }); nested.Properties.Add(new EntityPropertyDto { Name = supervisorLastNamePropName, DataType = DataTypes.String }); result.Add(nested); var r = result as List <EntityPropertyDto>; return(Task.FromResult(r)); }); var entityConfigStore = LocalIocManager.Resolve <IEntityConfigurationStore>(); var cacheManager = LocalIocManager.Resolve <ICacheManager>(); var builder = new DynamicDtoTypeBuilder(entityConfigCacheMock.Object, entityConfigStore, cacheManager); var baseDtoType = typeof(DynamicDto <Person, Guid>); var context = new DynamicDtoTypeBuildingContext() { ModelType = baseDtoType, // AddFormFieldsProperty = false // note: false is a default value for AddFormFieldsProperty. Leave it blank to test default value }; var proxyType = await builder.BuildDtoFullProxyTypeAsync(baseDtoType, context); proxyType.Assembly.IsDynamic.ShouldBeTrue(); var properties = proxyType.GetProperties(); properties.ShouldContain(p => p.Name == "Name"); properties.ShouldContain(p => p.Name == "Description"); properties.ShouldNotContain(p => p.Name == nameof(IHasFormFieldsList._formFields)); proxyType.ShouldNotBeAssignableTo(typeof(IHasFormFieldsList)); var supervisorProp = properties.FirstOrDefault(p => p.Name == supervisorPropName); supervisorProp.ShouldNotBeNull($"{supervisorPropName} property is missing in the created DTO"); // nested object should be dynamic supervisorProp.PropertyType.Assembly.IsDynamic.ShouldBeTrue(); typeof(IDynamicNestedObject).IsAssignableFrom(supervisorProp.PropertyType).ShouldBeTrue($"Dynamic nested object must implement {nameof(IDynamicNestedObject)}"); var nestedProperties = supervisorProp.PropertyType.GetProperties(); nestedProperties.ShouldContain(p => p.Name == supervisorFirstNamePropName); nestedProperties.ShouldContain(p => p.Name == supervisorLastNamePropName); }
public async Task SaveLoad_Test() { LoginAsHostAdmin(); // test data var props = new Dictionary <EntityPropertyDto, object> { { new EntityPropertyDto { Name = "UnitTestDynamicString", DataType = DataTypes.String, Source = MetadataSourceType.UserDefined }, "testString" }, { new EntityPropertyDto { Name = "UnitTestDynamicDate", DataType = DataTypes.Date, Source = MetadataSourceType.UserDefined }, DateTime.Today }, { new EntityPropertyDto { Name = "UnitTestDynamicDateTime", DataType = DataTypes.DateTime, Source = MetadataSourceType.UserDefined }, DateTime.Now }, { new EntityPropertyDto { Name = "UnitTestDynamicBoolean", DataType = DataTypes.Boolean, Source = MetadataSourceType.UserDefined }, true }, { new EntityPropertyDto { Name = "UnitTestDynamicNumber", DataType = DataTypes.Number, Source = MetadataSourceType.UserDefined }, (decimal)123.45 }, { new EntityPropertyDto { Name = "UnitTestDynamicObject", DataType = DataTypes.Object, Source = MetadataSourceType.UserDefined, Properties = new List <EntityPropertyDto>() { new EntityPropertyDto { Name = "UnitTestObjectProperty1", DataType = DataTypes.String, Source = MetadataSourceType.UserDefined }, new EntityPropertyDto { Name = "UnitTestObjectProperty2", DataType = DataTypes.String, Source = MetadataSourceType.UserDefined } } }, new { UnitTestObjectProperty1 = "testObjectProperty1", UnitTestObjectProperty2 = "testObjectProperty2" } } }; // configure DTO var entityConfigCacheMock = new Mock <IEntityConfigCache>(); entityConfigCacheMock.Setup(x => x.GetEntityPropertiesAsync(It.IsAny <Type>())) .Returns(() => { var result = new List <EntityPropertyDto>(); foreach (var prop in props) { result.Add(prop.Key); } return(Task.FromResult(result)); }); var entityConfigStore = LocalIocManager.Resolve <IEntityConfigurationStore>(); var cacheManager = LocalIocManager.Resolve <ICacheManager>(); var builder = new DynamicDtoTypeBuilder(entityConfigCacheMock.Object, entityConfigStore, cacheManager); var baseDtoType = typeof(DynamicDto <Person, Guid>); var context = new DynamicDtoTypeBuildingContext() { ModelType = baseDtoType }; var dtoType = await builder.BuildDtoFullProxyTypeAsync(baseDtoType, context); var dto = Activator.CreateInstance(dtoType) as DynamicDto <Person, Guid>; var properties = dto?.GetType().GetProperties(); var serializationManager = Resolve <ISerializationManager>(); // Update DTO properties values with test data foreach (var prop in props) { var p = properties?.FirstOrDefault(x => prop.Key.Name.ToLower() == x.Name.ToLower()); var val = prop.Value; if (prop.Key.DataType == DataTypes.Object) { val = serializationManager.DeserializeProperty(p?.PropertyType, serializationManager.SerializeProperty(prop.Key, val)); } p?.SetValue(dto, val); } using (var uow = _unitOfWorkManager.Begin()) { var nhuow = uow as NhUnitOfWork; var session = nhuow?.GetSession(); // Create temporary Entity Properties configs var entityConfigRepo = Resolve <IRepository <EntityConfig, Guid> >(); var entityPropRepo = Resolve <IRepository <EntityProperty, Guid> >(); var config = entityConfigRepo.GetAll().FirstOrDefault(x => x.TypeShortAlias == typeof(Person).GetEntityConfiguration().TypeShortAlias); foreach (var prop in props) { var propConf = new EntityProperty() { EntityConfig = config, Name = prop.Key.Name, DataType = prop.Key.DataType, Source = MetadataSourceType.UserDefined }; prop.Key.Id = entityPropRepo.Insert(propConf).Id; foreach (var childProp in prop.Key.Properties) { var childPropConf = new EntityProperty() { ParentProperty = propConf, EntityConfig = config, Name = prop.Key.Name, DataType = prop.Key.DataType, Source = MetadataSourceType.UserDefined }; childProp.Id = entityPropRepo.Insert(childPropConf).Id; } } session?.Flush(); try { var personRepo = Resolve <IRepository <Person, Guid> >(); var dynamicPropertyManager = new DynamicPropertyManager( Resolve <IRepository <EntityProperty, Guid> >(), Resolve <IRepository <EntityPropertyValue, Guid> >(), Resolve <IEntityConfigurationStore>(), Resolve <IDynamicRepository>() ) { DtoTypeBuilder = builder, SerializationManager = serializationManager }; // Create temporary entity var entity = new Person(); var id = personRepo.Insert(entity).Id; try { // Save dynamic properties to DB await dynamicPropertyManager.MapDtoToEntityAsync <DynamicDto <Person, Guid>, Person, Guid>(dto, entity); session?.Flush(); session?.Clear(); // Get entity from DB var newEntity = personRepo.Get(id); // Create new DTO and map values from entity to DTO var newDto = Activator.CreateInstance(dtoType) as DynamicDto <Person, Guid>; await dynamicPropertyManager.MapEntityToDtoAsync <DynamicDto <Person, Guid>, Person, Guid>(newEntity, newDto); // Check values. Values from the DB should be the same as from the test list var newProperties = newDto?.GetType().GetProperties(); foreach (var prop in props) { var p = newProperties?.FirstOrDefault(x => prop.Key.Name.ToLower() == x.Name.ToLower()); var dtoValue = p?.GetValue(newDto); if (prop.Key.DataType == DataTypes.Object) { var childProperties = dtoValue.GetType().GetProperties(); foreach (var childProp in prop.Key.Properties) { var childP = childProperties.FirstOrDefault(x => childProp.Name.ToLower() == x.Name.ToLower()); var dtoChildValue = childP.GetValue(dtoValue); dtoChildValue.ShouldBe(prop.Value.GetType().GetProperty(childProp.Name).GetValue(prop.Value)); } } else { dtoValue.ShouldBe(prop.Value); } } } finally { // delete temporary entity session.CreateSQLQuery($"delete from Core_Persons where id = '{id}'").ExecuteUpdate(); } } finally { // delete temporary values and properties configs foreach (var prop in props) { session.CreateSQLQuery($"delete from Frwk_EntityPropertyValues where EntityPropertyId = '{prop.Key.Id}'").ExecuteUpdate(); if (prop.Key.DataType == DataTypes.Object) { foreach (var childProp in prop.Key.Properties) { session.CreateSQLQuery($"delete from Frwk_EntityProperties where Id = '{childProp.Id}'").ExecuteUpdate(); } } session.CreateSQLQuery($"delete from Frwk_EntityProperties where Id = '{prop.Key.Id}'").ExecuteUpdate(); } } } }