diff --git a/src/Umbraco.Core/Models/Content.cs b/src/Umbraco.Core/Models/Content.cs index b8e96c2793..2b20b68164 100644 --- a/src/Umbraco.Core/Models/Content.cs +++ b/src/Umbraco.Core/Models/Content.cs @@ -1,6 +1,7 @@ using System; using System.Collections; using System.Collections.Generic; +using System.ComponentModel; using System.Linq; using System.Reflection; using System.Runtime.Serialization; @@ -155,6 +156,7 @@ namespace Umbraco.Core.Models /// Language of the data contained within this Content object. /// [Obsolete("This is not used and will be removed from the codebase in future versions")] + [EditorBrowsable(EditorBrowsableState.Never)] public string Language { get { return _language; } diff --git a/src/Umbraco.Core/Models/IContent.cs b/src/Umbraco.Core/Models/IContent.cs index 2715e5fe3a..7caefc1121 100644 --- a/src/Umbraco.Core/Models/IContent.cs +++ b/src/Umbraco.Core/Models/IContent.cs @@ -1,4 +1,5 @@ using System; +using System.ComponentModel; using System.Diagnostics; using Umbraco.Core.Persistence.Mappers; @@ -21,6 +22,7 @@ namespace Umbraco.Core.Models bool Published { get; } [Obsolete("This will be removed in future versions")] + [EditorBrowsable(EditorBrowsableState.Never)] string Language { get; set; } /// diff --git a/src/Umbraco.Core/Models/Rdbms/PropertyTypeReadOnlyDto.cs b/src/Umbraco.Core/Models/Rdbms/PropertyTypeReadOnlyDto.cs index 2f448860b0..d85baa2884 100644 --- a/src/Umbraco.Core/Models/Rdbms/PropertyTypeReadOnlyDto.cs +++ b/src/Umbraco.Core/Models/Rdbms/PropertyTypeReadOnlyDto.cs @@ -51,5 +51,8 @@ namespace Umbraco.Core.Models.Rdbms [Column("dbType")] public string DbType { get; set; } + + [Column("UniqueID")] + public Guid UniqueId { get; set; } } } \ No newline at end of file diff --git a/src/Umbraco.Core/Persistence/Factories/MemberTypeReadOnlyFactory.cs b/src/Umbraco.Core/Persistence/Factories/MemberTypeReadOnlyFactory.cs index eebbc34eda..9e1c09d6d5 100644 --- a/src/Umbraco.Core/Persistence/Factories/MemberTypeReadOnlyFactory.cs +++ b/src/Umbraco.Core/Persistence/Factories/MemberTypeReadOnlyFactory.cs @@ -114,7 +114,8 @@ namespace Umbraco.Core.Persistence.Factories ValidationRegExp = typeDto.ValidationRegExp, PropertyGroupId = new Lazy(() => tempGroupDto.Id.Value), CreateDate = memberType.CreateDate, - UpdateDate = memberType.UpdateDate + UpdateDate = memberType.UpdateDate, + Key = typeDto.UniqueId }; //on initial construction we don't want to have dirty properties tracked // http://issues.umbraco.org/issue/U4-1946 @@ -166,7 +167,8 @@ namespace Umbraco.Core.Persistence.Factories ValidationRegExp = typeDto.ValidationRegExp, PropertyGroupId = null, CreateDate = dto.CreateDate, - UpdateDate = dto.CreateDate + UpdateDate = dto.CreateDate, + Key = typeDto.UniqueId }; propertyTypes.Add(propertyType); diff --git a/src/Umbraco.Core/Persistence/Repositories/MemberTypeRepository.cs b/src/Umbraco.Core/Persistence/Repositories/MemberTypeRepository.cs index b35c793400..5157eec9f0 100644 --- a/src/Umbraco.Core/Persistence/Repositories/MemberTypeRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/MemberTypeRepository.cs @@ -94,7 +94,7 @@ namespace Umbraco.Core.Persistence.Repositories } sql.Select("umbracoNode.*", "cmsContentType.*", "cmsPropertyType.id AS PropertyTypeId", "cmsPropertyType.Alias", - "cmsPropertyType.Name", "cmsPropertyType.Description", "cmsPropertyType.mandatory", + "cmsPropertyType.Name", "cmsPropertyType.Description", "cmsPropertyType.mandatory", "cmsPropertyType.UniqueID", "cmsPropertyType.validationRegExp", "cmsPropertyType.dataTypeId", "cmsPropertyType.sortOrder AS PropertyTypeSortOrder", "cmsPropertyType.propertyTypeGroupId AS PropertyTypesGroupId", "cmsMemberType.memberCanEdit", "cmsMemberType.viewOnProfile", "cmsDataType.propertyEditorAlias", "cmsDataType.dbType", "cmsPropertyTypeGroup.id AS PropertyTypeGroupId", diff --git a/src/Umbraco.Tests/Persistence/Repositories/ContentRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/ContentRepositoryTest.cs index d29b073df7..105793b42c 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/ContentRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/ContentRepositoryTest.cs @@ -21,6 +21,7 @@ using Umbraco.Tests.TestHelpers; using Umbraco.Tests.TestHelpers.Entities; using umbraco.editorControls.tinyMCE3; using umbraco.interfaces; +using Umbraco.Core.Models.EntityBase; using Umbraco.Core.Persistence.DatabaseModelDefinitions; namespace Umbraco.Tests.Persistence.Repositories @@ -266,17 +267,18 @@ namespace Umbraco.Tests.Persistence.Repositories using (var repository = CreateRepository(unitOfWork, out contentTypeRepository)) { ContentType contentType = MockedContentTypes.CreateSimpleContentType("umbTextpage2", "Textpage"); - Content textpage = MockedContent.CreateSimpleContent(contentType); + IContent textpage = MockedContent.CreateSimpleContent(contentType); // Act contentTypeRepository.AddOrUpdate(contentType); repository.AddOrUpdate(textpage); unitOfWork.Commit(); - + // Assert Assert.That(contentType.HasIdentity, Is.True); Assert.That(textpage.HasIdentity, Is.True); + } } @@ -305,9 +307,13 @@ namespace Umbraco.Tests.Persistence.Repositories repository.AddOrUpdate(textpage); unitOfWork.Commit(); + var fetched = repository.Get(textpage.Id); + // Assert Assert.That(textpage.Template, Is.Not.Null); Assert.That(textpage.Template, Is.EqualTo(contentType.DefaultTemplate)); + + TestHelper.AssertAllPropertyValuesAreEquals(textpage, fetched, "yyyy-MM-dd HH:mm:ss"); } } diff --git a/src/Umbraco.Tests/Persistence/Repositories/ContentTypeRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/ContentTypeRepositoryTest.cs index b2fed80f1b..7d8d7659c8 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/ContentTypeRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/ContentTypeRepositoryTest.cs @@ -266,6 +266,8 @@ namespace Umbraco.Tests.Persistence.Repositories repository.AddOrUpdate(contentType); unitOfWork.Commit(); + var fetched = repository.Get(contentType.Id); + // Assert Assert.That(contentType.HasIdentity, Is.True); Assert.That(contentType.PropertyGroups.All(x => x.HasIdentity), Is.True); @@ -281,6 +283,8 @@ namespace Umbraco.Tests.Persistence.Repositories { Assert.AreNotEqual(propertyType.Key, Guid.Empty); } + + TestHelper.AssertAllPropertyValuesAreEquals(contentType, fetched, "yyyy-MM-dd HH:mm:ss", ignoreProperties: new [] { "DefaultTemplate", "AllowedTemplates", "UpdateDate" }); } } diff --git a/src/Umbraco.Tests/Persistence/Repositories/DataTypeDefinitionRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/DataTypeDefinitionRepositoryTest.cs index 2f1c31487c..4db63f6085 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/DataTypeDefinitionRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/DataTypeDefinitionRepositoryTest.cs @@ -355,9 +355,13 @@ namespace Umbraco.Tests.Persistence.Repositories unitOfWork.Commit(); var exists = repository.Exists(dataTypeDefinition.Id); + var fetched = repository.Get(dataTypeDefinition.Id); + // Assert Assert.That(dataTypeDefinition.HasIdentity, Is.True); Assert.That(exists, Is.True); + + TestHelper.AssertAllPropertyValuesAreEquals(dataTypeDefinition, fetched, "yyyy-MM-dd HH:mm:ss"); } } diff --git a/src/Umbraco.Tests/Persistence/Repositories/MediaRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/MediaRepositoryTest.cs index 10256e7dee..a216eaaa45 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/MediaRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/MediaRepositoryTest.cs @@ -127,9 +127,13 @@ namespace Umbraco.Tests.Persistence.Repositories repository.AddOrUpdate(image); unitOfWork.Commit(); + var fetched = repository.Get(image.Id); + // Assert Assert.That(mediaType.HasIdentity, Is.True); Assert.That(image.HasIdentity, Is.True); + + TestHelper.AssertAllPropertyValuesAreEquals(image, fetched, "yyyy-MM-dd HH:mm:ss"); } } diff --git a/src/Umbraco.Tests/Persistence/Repositories/MediaTypeRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/MediaTypeRepositoryTest.cs index eaedef09e4..b9ff045c71 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/MediaTypeRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/MediaTypeRepositoryTest.cs @@ -197,11 +197,15 @@ namespace Umbraco.Tests.Persistence.Repositories repository.AddOrUpdate(contentType); unitOfWork.Commit(); + var fetched = repository.Get(contentType.Id); + // Assert Assert.That(contentType.HasIdentity, Is.True); Assert.That(contentType.PropertyGroups.All(x => x.HasIdentity), Is.True); Assert.That(contentType.Path.Contains(","), Is.True); - Assert.That(contentType.SortOrder, Is.GreaterThan(0)); + Assert.That(contentType.SortOrder, Is.GreaterThan(0)); + + TestHelper.AssertAllPropertyValuesAreEquals(contentType, fetched, "yyyy-MM-dd HH:mm:ss", ignoreProperties: new[] { "UpdateDate" }); } diff --git a/src/Umbraco.Tests/Persistence/Repositories/MemberRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/MemberRepositoryTest.cs index 0d3b4e4e47..c8ffda7aec 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/MemberRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/MemberRepositoryTest.cs @@ -220,7 +220,9 @@ namespace Umbraco.Tests.Persistence.Repositories Assert.That(sut.Name, Is.EqualTo("Johnny Hefty")); Assert.That(sut.Email, Is.EqualTo("johnny@example.com")); Assert.That(sut.RawPasswordValue, Is.EqualTo("123")); - Assert.That(sut.Username, Is.EqualTo("hefty")); + Assert.That(sut.Username, Is.EqualTo("hefty")); + + TestHelper.AssertAllPropertyValuesAreEquals(sut, member, "yyyy-MM-dd HH:mm:ss"); } } diff --git a/src/Umbraco.Tests/Persistence/Repositories/MemberTypeRepositoryTest.cs b/src/Umbraco.Tests/Persistence/Repositories/MemberTypeRepositoryTest.cs index aa4027d8a8..2de69b5071 100644 --- a/src/Umbraco.Tests/Persistence/Repositories/MemberTypeRepositoryTest.cs +++ b/src/Umbraco.Tests/Persistence/Repositories/MemberTypeRepositoryTest.cs @@ -42,7 +42,7 @@ namespace Umbraco.Tests.Persistence.Repositories var unitOfWork = provider.GetUnitOfWork(); using (var repository = CreateRepository(unitOfWork)) { - var memberType = MockedContentTypes.CreateSimpleMemberType(); + var memberType = (IMemberType)MockedContentTypes.CreateSimpleMemberType(); repository.AddOrUpdate(memberType); unitOfWork.Commit(); @@ -56,6 +56,30 @@ namespace Umbraco.Tests.Persistence.Repositories Assert.That(sut.PropertyGroups.Any(x => x.HasIdentity == false || x.Id == 0), Is.False); Assert.That(sut.PropertyTypes.Any(x => x.HasIdentity == false || x.Id == 0), Is.False); + + TestHelper.AssertAllPropertyValuesAreEquals(sut, memberType, "yyyy-MM-dd HH:mm:ss"); + } + } + + [Test] + public void Can_Persist_Member_Type_Same_Property_Keys() + { + var provider = new PetaPocoUnitOfWorkProvider(Logger); + var unitOfWork = provider.GetUnitOfWork(); + using (var repository = CreateRepository(unitOfWork)) + { + var memberType = (IMemberType)MockedContentTypes.CreateSimpleMemberType(); + + repository.AddOrUpdate(memberType); + unitOfWork.Commit(); + + var propertyKeys = memberType.PropertyTypes.Select(x => x.Key).OrderBy(x => x).ToArray(); + + memberType = repository.Get(memberType.Id); + var propertyKeys2 = memberType.PropertyTypes.Select(x => x.Key).OrderBy(x => x).ToArray(); + + Assert.IsTrue(propertyKeys.SequenceEqual(propertyKeys2)); + } } diff --git a/src/Umbraco.Tests/TestHelpers/TestHelper.cs b/src/Umbraco.Tests/TestHelpers/TestHelper.cs index eec71f9a7f..5e362ee1f8 100644 --- a/src/Umbraco.Tests/TestHelpers/TestHelper.cs +++ b/src/Umbraco.Tests/TestHelpers/TestHelper.cs @@ -1,13 +1,17 @@ using System; +using System.Collections; using System.Collections.Generic; +using System.ComponentModel; using System.Configuration; using System.IO; using System.Linq; using System.Reflection; +using NUnit.Framework; using SqlCE4Umbraco; using Umbraco.Core; using Umbraco.Core.IO; using umbraco.DataLayer; +using Umbraco.Core.Models.EntityBase; using GlobalSettings = umbraco.GlobalSettings; namespace Umbraco.Tests.TestHelpers @@ -116,6 +120,83 @@ namespace Umbraco.Tests.TestHelpers File.Delete(umbracoSettingsFile); } + public static void AssertAllPropertyValuesAreEquals(object actual, object expected, string dateTimeFormat = null, Func sorter = null, string[] ignoreProperties = null) + { + var properties = expected.GetType().GetProperties(); + foreach (var property in properties) + { + //ignore properties that are attributed with this + var att = property.GetCustomAttribute(false); + if (att != null && att.State == EditorBrowsableState.Never) + continue; - } + if (ignoreProperties != null && ignoreProperties.Contains(property.Name)) + continue; + + var expectedValue = property.GetValue(expected, null); + var actualValue = property.GetValue(actual, null); + + if (((actualValue is string) == false) && actualValue is IEnumerable) + { + AssertListsAreEquals(property, (IEnumerable)actualValue, (IEnumerable)expectedValue, dateTimeFormat, sorter); + } + else if (dateTimeFormat.IsNullOrWhiteSpace() == false && actualValue is DateTime) + { + Assert.AreEqual(((DateTime) expectedValue).ToString(dateTimeFormat), ((DateTime)actualValue).ToString(dateTimeFormat), "Property {0}.{1} does not match. Expected: {2} but was: {3}", property.DeclaringType.Name, property.Name, expectedValue, actualValue); + } + else + { + Assert.AreEqual(expectedValue, actualValue, "Property {0}.{1} does not match. Expected: {2} but was: {3}", property.DeclaringType.Name, property.Name, expectedValue, actualValue); + } + } + } + + private static void AssertListsAreEquals(PropertyInfo property, IEnumerable actualList, IEnumerable expectedList, string dateTimeFormat, Func sorter) + { + if (sorter == null) + { + //this is pretty hackerific but saves us some code to write + sorter = enumerable => + { + //semi-generic way of ensuring any collection of IEntity are sorted by Ids for comparison + var entities = enumerable.OfType().ToList(); + if (entities.Count > 0) + { + return entities.OrderBy(x => x.Id); + } + else + { + return enumerable; + } + }; + } + + var actualListEx = sorter(actualList).Cast().ToList(); + var expectedListEx = sorter(expectedList).Cast().ToList(); + + if (actualListEx.Count != expectedListEx.Count) + Assert.Fail("Collection {0}.{1} does not match. Expected IEnumerable containing {2} elements but was IEnumerable containing {3} elements", property.PropertyType.Name, property.Name, expectedListEx.Count, actualListEx.Count); + + for (int i = 0; i < actualListEx.Count; i++) + { + var actualValue = actualListEx[i]; + var expectedValue = expectedListEx[i]; + + if (((actualValue is string) == false) && actualValue is IEnumerable) + { + AssertListsAreEquals(property, (IEnumerable)actualValue, (IEnumerable)expectedValue, dateTimeFormat, sorter); + } + else if (dateTimeFormat.IsNullOrWhiteSpace() == false && actualValue is DateTime) + { + Assert.AreEqual(((DateTime)expectedValue).ToString(dateTimeFormat), ((DateTime)actualValue).ToString(dateTimeFormat), "Property {0}.{1} does not match. Expected: {2} but was: {3}", property.DeclaringType.Name, property.Name, expectedValue, actualValue); + } + else + { + Assert.AreEqual(expectedValue, actualValue, "Property {0}.{1} does not match. Expected: {2} but was: {3}", property.DeclaringType.Name, property.Name, expectedValue, actualValue); + } + } + } + + + } } \ No newline at end of file