Merge remote-tracking branch 'origin/temp8' into temp8-U4-11220

# Conflicts:
#	src/Umbraco.Web/PublishedCache/NuCache/DataSource/BTree.cs
This commit is contained in:
Shannon
2018-04-26 19:18:14 +10:00
75 changed files with 1361 additions and 841 deletions

View File

@@ -65,6 +65,8 @@ namespace Umbraco.Tests.Models
var propertyType = new PropertyType("editor", ValueStorageType.Nvarchar) { Alias = "prop" };
var prop = new Property(propertyType);
const string langFr = "fr-FR";
// can set value
// and get edited and published value
// because non-publishing
@@ -84,8 +86,8 @@ namespace Umbraco.Tests.Models
Assert.IsNull(prop.GetValue(published: true));
// cannot set non-supported variation value
Assert.Throws<NotSupportedException>(() => prop.SetValue("x", 1));
Assert.IsNull(prop.GetValue(1));
Assert.Throws<NotSupportedException>(() => prop.SetValue("x", langFr));
Assert.IsNull(prop.GetValue(langFr));
// can publish value
// and get edited and published values
@@ -109,41 +111,41 @@ namespace Umbraco.Tests.Models
// can set value
// and get values
prop.SetValue("c", 1);
prop.SetValue("c", langFr);
Assert.AreEqual("b", prop.GetValue());
Assert.IsNull(prop.GetValue(published: true));
Assert.AreEqual("c", prop.GetValue(1));
Assert.IsNull(prop.GetValue(1, published: true));
Assert.AreEqual("c", prop.GetValue(langFr));
Assert.IsNull(prop.GetValue(langFr, published: true));
// can publish value
// and get edited and published values
prop.PublishValue(1);
prop.PublishValue(langFr);
Assert.AreEqual("b", prop.GetValue());
Assert.IsNull(prop.GetValue(published: true));
Assert.AreEqual("c", prop.GetValue(1));
Assert.AreEqual("c", prop.GetValue(1, published: true));
Assert.AreEqual("c", prop.GetValue(langFr));
Assert.AreEqual("c", prop.GetValue(langFr, published: true));
// can clear all
prop.ClearPublishedAllValues();
Assert.AreEqual("b", prop.GetValue());
Assert.IsNull(prop.GetValue(published: true));
Assert.AreEqual("c", prop.GetValue(1));
Assert.IsNull(prop.GetValue(1, published: true));
Assert.AreEqual("c", prop.GetValue(langFr));
Assert.IsNull(prop.GetValue(langFr, published: true));
// can publish all
prop.PublishAllValues();
Assert.AreEqual("b", prop.GetValue());
Assert.AreEqual("b", prop.GetValue(published: true));
Assert.AreEqual("c", prop.GetValue(1));
Assert.AreEqual("c", prop.GetValue(1, published: true));
Assert.AreEqual("c", prop.GetValue(langFr));
Assert.AreEqual("c", prop.GetValue(langFr, published: true));
// same for culture
prop.ClearPublishedCultureValues(1);
Assert.AreEqual("c", prop.GetValue(1));
Assert.IsNull(prop.GetValue(1, published: true));
prop.PublishCultureValues(1);
Assert.AreEqual("c", prop.GetValue(1));
Assert.AreEqual("c", prop.GetValue(1, published: true));
prop.ClearPublishedCultureValues(langFr);
Assert.AreEqual("c", prop.GetValue(langFr));
Assert.IsNull(prop.GetValue(langFr, published: true));
prop.PublishCultureValues(langFr);
Assert.AreEqual("c", prop.GetValue(langFr));
Assert.AreEqual("c", prop.GetValue(langFr, published: true));
prop.ClearPublishedCultureValues();
Assert.AreEqual("b", prop.GetValue());
@@ -159,25 +161,29 @@ namespace Umbraco.Tests.Models
var contentType = new ContentType(-1) { Alias = "contentType" };
var content = new Content("content", -1, contentType) { Id = 1, VersionId = 1 };
const int langFr = 1;
const int langUk = 2;
const string langFr = "fr-FR";
const string langUk = "en-UK";
// throws if the content type does not support the variation
Assert.Throws<NotSupportedException>(() => content.SetName(langFr, "name-fr"));
// now it will work
contentType.Variations = ContentVariation.CultureNeutral;
// invariant name works
content.Name = "name";
Assert.AreEqual("name", content.GetName(null));
content.SetName(null, "name2");
Assert.AreEqual("name2", content.Name);
Assert.AreEqual("name2", content.GetName(null));
// variant names work
content.SetName(langFr, "name-fr");
content.SetName(langUk, "name-uk");
Assert.AreEqual("name-fr", content.GetName(langFr));
Assert.AreEqual("name-uk", content.GetName(langUk));
// variant dictionary of names work
Assert.AreEqual(2, content.Names.Count);
Assert.IsTrue(content.Names.ContainsKey(langFr));
Assert.AreEqual("name-fr", content.Names[langFr]);
@@ -186,8 +192,10 @@ namespace Umbraco.Tests.Models
}
[Test]
public void ContentTests()
public void ContentPublishValues()
{
const string langFr = "fr-FR";
var propertyType = new PropertyType("editor", ValueStorageType.Nvarchar) { Alias = "prop" };
var contentType = new ContentType(-1) { Alias = "contentType" };
contentType.AddPropertyType(propertyType);
@@ -202,8 +210,8 @@ namespace Umbraco.Tests.Models
Assert.IsNull(content.GetValue("prop", published: true));
// cannot set non-supported variation value
Assert.Throws<NotSupportedException>(() => content.SetValue("prop", "x", 1));
Assert.IsNull(content.GetValue("prop", 1));
Assert.Throws<NotSupportedException>(() => content.SetValue("prop", "x", langFr));
Assert.IsNull(content.GetValue("prop", langFr));
// can publish value
// and get edited and published values
@@ -228,43 +236,43 @@ namespace Umbraco.Tests.Models
// can set value
// and get values
content.SetValue("prop", "c", 1);
content.SetValue("prop", "c", langFr);
Assert.AreEqual("b", content.GetValue("prop"));
Assert.IsNull(content.GetValue("prop", published: true));
Assert.AreEqual("c", content.GetValue("prop", 1));
Assert.IsNull(content.GetValue("prop", 1, published: true));
Assert.AreEqual("c", content.GetValue("prop", langFr));
Assert.IsNull(content.GetValue("prop", langFr, published: true));
// can publish value
// and get edited and published values
Assert.Throws<InvalidOperationException>(() => content.PublishValues(1)); // no name
content.SetName(1, "name-fr");
content.PublishValues(1);
Assert.Throws<InvalidOperationException>(() => content.PublishValues(langFr)); // no name
content.SetName(langFr, "name-fr");
content.PublishValues(langFr);
Assert.AreEqual("b", content.GetValue("prop"));
Assert.IsNull(content.GetValue("prop", published: true));
Assert.AreEqual("c", content.GetValue("prop", 1));
Assert.AreEqual("c", content.GetValue("prop", 1, published: true));
Assert.AreEqual("c", content.GetValue("prop", langFr));
Assert.AreEqual("c", content.GetValue("prop", langFr, published: true));
// can clear all
content.ClearAllPublishedValues();
Assert.AreEqual("b", content.GetValue("prop"));
Assert.IsNull(content.GetValue("prop", published: true));
Assert.AreEqual("c", content.GetValue("prop", 1));
Assert.IsNull(content.GetValue("prop", 1, published: true));
Assert.AreEqual("c", content.GetValue("prop", langFr));
Assert.IsNull(content.GetValue("prop", langFr, published: true));
// can publish all
content.PublishAllValues();
Assert.AreEqual("b", content.GetValue("prop"));
Assert.AreEqual("b", content.GetValue("prop", published: true));
Assert.AreEqual("c", content.GetValue("prop", 1));
Assert.AreEqual("c", content.GetValue("prop", 1, published: true));
Assert.AreEqual("c", content.GetValue("prop", langFr));
Assert.AreEqual("c", content.GetValue("prop", langFr, published: true));
// same for culture
content.ClearCulturePublishedValues(1);
Assert.AreEqual("c", content.GetValue("prop", 1));
Assert.IsNull(content.GetValue("prop", 1, published: true));
content.PublishCultureValues(1);
Assert.AreEqual("c", content.GetValue("prop", 1));
Assert.AreEqual("c", content.GetValue("prop", 1, published: true));
content.ClearCulturePublishedValues(langFr);
Assert.AreEqual("c", content.GetValue("prop", langFr));
Assert.IsNull(content.GetValue("prop", langFr, published: true));
content.PublishCultureValues(langFr);
Assert.AreEqual("c", content.GetValue("prop", langFr));
Assert.AreEqual("c", content.GetValue("prop", langFr, published: true));
content.ClearCulturePublishedValues();
Assert.AreEqual("b", content.GetValue("prop"));
@@ -275,21 +283,76 @@ namespace Umbraco.Tests.Models
var other = new Content("other", -1, contentType) { Id = 2, VersionId = 1 };
other.SetValue("prop", "o");
other.SetValue("prop", "o1", 1);
other.SetValue("prop", "o1", langFr);
// can copy other's edited value
content.CopyAllValues(other);
Assert.AreEqual("o", content.GetValue("prop"));
Assert.AreEqual("b", content.GetValue("prop", published: true));
Assert.AreEqual("o1", content.GetValue("prop", 1));
Assert.AreEqual("c", content.GetValue("prop", 1, published: true));
Assert.AreEqual("o1", content.GetValue("prop", langFr));
Assert.AreEqual("c", content.GetValue("prop", langFr, published: true));
// can copy self's published value
content.CopyAllValues(content);
Assert.AreEqual("b", content.GetValue("prop"));
Assert.AreEqual("b", content.GetValue("prop", published: true));
Assert.AreEqual("c", content.GetValue("prop", 1));
Assert.AreEqual("c", content.GetValue("prop", 1, published: true));
Assert.AreEqual("c", content.GetValue("prop", langFr));
Assert.AreEqual("c", content.GetValue("prop", langFr, published: true));
}
[Test]
public void ContentPublishVariations()
{
const string langFr = "fr-FR";
const string langUk = "en-UK";
const string langEs = "es-ES";
var propertyType = new PropertyType("editor", ValueStorageType.Nvarchar) { Alias = "prop" };
var contentType = new ContentType(-1) { Alias = "contentType" };
contentType.AddPropertyType(propertyType);
var content = new Content("content", -1, contentType) { Id = 1, VersionId = 1 };
contentType.Variations |= ContentVariation.CultureNeutral;
propertyType.Variations |= ContentVariation.CultureNeutral;
content.SetValue("prop", "a");
content.SetValue("prop", "a-fr", langFr);
content.SetValue("prop", "a-uk", langUk);
content.SetValue("prop", "a-es", langEs);
// cannot publish without a name
Assert.Throws<InvalidOperationException>(() => content.PublishValues(langFr));
// works with a name
// and then FR is available, and published
content.SetName(langFr, "name-fr");
content.PublishValues(langFr);
// now UK is available too
content.SetName(langUk, "name-uk");
// test available, published
Assert.IsTrue(content.IsCultureAvailable(langFr));
Assert.IsTrue(content.IsCulturePublished(langFr));
Assert.AreEqual("name-fr", content.GetPublishName(langFr));
Assert.AreNotEqual(DateTime.MinValue, content.GetDateCulturePublished(langFr));
Assert.IsFalse(content.IsCultureEdited(langFr)); // once published, edited is *wrong* until saved
Assert.IsTrue(content.IsCultureAvailable(langUk));
Assert.IsFalse(content.IsCulturePublished(langUk));
Assert.IsNull(content.GetPublishName(langUk));
Assert.Throws<InvalidOperationException>(() => content.GetDateCulturePublished(langUk)); // not published!
Assert.IsTrue(content.IsCultureEdited(langEs)); // not published, so... edited
Assert.IsFalse(content.IsCultureAvailable(langEs));
Assert.IsFalse(content.IsCulturePublished(langEs));
Assert.IsNull(content.GetPublishName(langEs));
Assert.Throws<InvalidOperationException>(() => content.GetDateCulturePublished(langEs)); // not published!
Assert.IsTrue(content.IsCultureEdited(langEs)); // not published, so... edited
// cannot test IsCultureEdited here - as that requires the content service and repository
// see: ContentServiceTests.Can_SaveRead_Variations
}
[Test]

View File

@@ -36,7 +36,7 @@ namespace Umbraco.Tests.Persistence.Repositories
mediaTypeRepository = new MediaTypeRepository(scopeAccessor, cacheHelper, Logger);
var tagRepository = new TagRepository(scopeAccessor, cacheHelper, Logger);
var repository = new MediaRepository(scopeAccessor, cacheHelper, Logger, mediaTypeRepository, tagRepository, Mock.Of<IContentSection>());
var repository = new MediaRepository(scopeAccessor, cacheHelper, Logger, mediaTypeRepository, tagRepository, Mock.Of<IContentSection>(), Mock.Of<ILanguageRepository>());
return repository;
}

View File

@@ -31,7 +31,7 @@ namespace Umbraco.Tests.Persistence.Repositories
memberTypeRepository = new MemberTypeRepository(accessor, DisabledCache, Logger);
memberGroupRepository = new MemberGroupRepository(accessor, DisabledCache, Logger);
var tagRepo = new TagRepository(accessor, DisabledCache, Logger);
var repository = new MemberRepository(accessor, DisabledCache, Logger, memberTypeRepository, memberGroupRepository, tagRepo);
var repository = new MemberRepository(accessor, DisabledCache, Logger, memberTypeRepository, memberGroupRepository, tagRepo, Mock.Of<ILanguageRepository>());
return repository;
}

View File

@@ -4,6 +4,7 @@ using NUnit.Framework;
using Umbraco.Core.Configuration.UmbracoSettings;
using Umbraco.Core.IO;
using Umbraco.Core.Models;
using Umbraco.Core.Persistence.Repositories;
using Umbraco.Core.Persistence.Repositories.Implement;
using Umbraco.Core.Scoping;
using Umbraco.Tests.TestHelpers;
@@ -964,7 +965,7 @@ namespace Umbraco.Tests.Persistence.Repositories
var accessor = (IScopeAccessor) provider;
var tagRepository = new TagRepository(accessor, DisabledCache, Logger);
mediaTypeRepository = new MediaTypeRepository(accessor, DisabledCache, Logger);
var repository = new MediaRepository(accessor, DisabledCache, Logger, mediaTypeRepository, tagRepository, Mock.Of<IContentSection>());
var repository = new MediaRepository(accessor, DisabledCache, Logger, mediaTypeRepository, tagRepository, Mock.Of<IContentSection>(), Mock.Of<ILanguageRepository>());
return repository;
}
}

View File

@@ -26,7 +26,7 @@ namespace Umbraco.Tests.Persistence.Repositories
var accessor = (IScopeAccessor) provider;
mediaTypeRepository = new MediaTypeRepository(accessor, CacheHelper, Mock.Of<ILogger>());
var tagRepository = new TagRepository(accessor, CacheHelper, Mock.Of<ILogger>());
var repository = new MediaRepository(accessor, CacheHelper, Mock.Of<ILogger>(), mediaTypeRepository, tagRepository, Mock.Of<IContentSection>());
var repository = new MediaRepository(accessor, CacheHelper, Mock.Of<ILogger>(), mediaTypeRepository, tagRepository, Mock.Of<IContentSection>(), Mock.Of<ILanguageRepository>());
return repository;
}

View File

@@ -242,10 +242,10 @@ namespace Umbraco.Tests.Published
_owner = owner;
}
public override bool HasValue(int? languageId = null, string segment = null) => _hasValue;
public override object GetSourceValue(int? languageId = null, string segment = null) => _sourceValue;
public override object GetValue(int? languageId = null, string segment = null) => PropertyType.ConvertInterToObject(_owner, ReferenceCacheLevel, InterValue, _preview);
public override object GetXPathValue(int? languageId = null, string segment = null) => throw new WontImplementException();
public override bool HasValue(string culture = null, string segment = null) => _hasValue;
public override object GetSourceValue(string culture = null, string segment = null) => _sourceValue;
public override object GetValue(string culture = null, string segment = null) => PropertyType.ConvertInterToObject(_owner, ReferenceCacheLevel, InterValue, _preview);
public override object GetXPathValue(string culture = null, string segment = null) => throw new WontImplementException();
}
class TestPublishedContent : PublishedContentBase

View File

@@ -258,10 +258,10 @@ namespace Umbraco.Tests.PublishedContent
public bool SolidHasValue { get; set; }
public object SolidXPathValue { get; set; }
public object GetSourceValue(int? languageId = null, string segment = null) => SolidSourceValue;
public object GetValue(int? languageId = null, string segment = null) => SolidValue;
public object GetXPathValue(int? languageId = null, string segment = null) => SolidXPathValue;
public bool HasValue(int? languageId = null, string segment = null) => SolidHasValue;
public object GetSourceValue(string culture = null, string segment = null) => SolidSourceValue;
public object GetValue(string culture = null, string segment = null) => SolidValue;
public object GetXPathValue(string culture = null, string segment = null) => SolidXPathValue;
public bool HasValue(string culture = null, string segment = null) => SolidHasValue;
}
[PublishedModel("ContentType2")]

View File

@@ -356,7 +356,7 @@ namespace Umbraco.Tests.PublishedContent
var result = doc.Ancestors().OrderBy(x => x.Level)
.Single()
.Descendants()
.FirstOrDefault(x => x.Value<string>("selectedNodes", "").Split(',').Contains("1173"));
.FirstOrDefault(x => x.Value<string>("selectedNodes", defaultValue: "").Split(',').Contains("1173"));
Assert.IsNotNull(result);
}

View File

@@ -2475,210 +2475,274 @@ namespace Umbraco.Tests.Services
}
[Test]
public void Can_SaveAndRead_Names()
public void Can_SaveRead_Variations()
{
var languageService = ServiceContext.LocalizationService;
var langFr = new Language("fr-FR");
var langUk = new Language("en-UK");
var langDe = new Language("de-DE");
var langDe = new Language("de-DE");
languageService.Save(langFr);
languageService.Save(langUk);
languageService.Save(langDe);
languageService.Save(langDe);
var contentTypeService = ServiceContext.ContentTypeService;
// fixme
// contentType.Variations is InvariantNeutral | CultureNeutral
// propertyType.Variations can only be a subset of contentType.Variations - ie cannot *add* anything
// (at least, we should validate this)
// but then,
// if the contentType supports InvariantNeutral | CultureNeutral,
// the propertyType should support InvariantNeutral, or both, but not solely CultureNeutral?
// but does this mean that CultureNeutral implies InvariantNeutral?
// can a contentType *not* support InvariantNeutral?
var contentType = contentTypeService.Get("umbTextpage");
// fixme
// contentType.Variations is InvariantNeutral | CultureNeutral
// propertyType.Variations can only be a subset of contentType.Variations - ie cannot *add* anything
// (at least, we should validate this)
// but then,
// if the contentType supports InvariantNeutral | CultureNeutral,
// the propertyType should support InvariantNeutral, or both, but not solely CultureNeutral?
// but does this mean that CultureNeutral implies InvariantNeutral?
// can a contentType *not* support InvariantNeutral?
var contentType = contentTypeService.Get("umbTextpage");
contentType.Variations = ContentVariation.InvariantNeutral | ContentVariation.CultureNeutral;
contentType.AddPropertyType(new PropertyType(Constants.PropertyEditors.Aliases.TextBox, ValueStorageType.Nvarchar, "prop") { Variations = ContentVariation.CultureNeutral });
contentTypeService.Save(contentType);
contentTypeService.Save(contentType);
var contentService = ServiceContext.ContentService;
var content = contentService.Create("Home US", - 1, "umbTextpage");
// act
var content = contentService.Create("Home US", - 1, "umbTextpage");
content.SetValue("author", "Barack Obama");
content.SetValue("prop", "value-fr1", langFr.Id);
content.SetValue("prop", "value-uk1", langUk.Id);
content.SetName(langFr.Id, "name-fr");
content.SetName(langUk.Id, "name-uk");
// act
content.SetValue("author", "Barack Obama");
content.SetValue("prop", "value-fr1", langFr.IsoCode);
content.SetValue("prop", "value-uk1", langUk.IsoCode);
content.SetName(langFr.IsoCode, "name-fr");
content.SetName(langUk.IsoCode, "name-uk");
contentService.Save(content);
// content has been saved,
// it has names, but no publishNames, and no published cultures
var content2 = contentService.GetById(content.Id);
Assert.AreEqual("Home US", content2.Name);
Assert.AreEqual("name-fr", content2.GetName(langFr.Id));
Assert.AreEqual("name-uk", content2.GetName(langUk.Id));
Assert.AreEqual("value-fr1", content2.GetValue("prop", langFr.Id));
Assert.AreEqual("value-uk1", content2.GetValue("prop", langUk.Id));
Assert.IsNull(content2.GetValue("prop", langFr.Id, published: true));
Assert.IsNull(content2.GetValue("prop", langUk.Id, published: true));
// content has been saved,
// it has names, but no publishNames, and no published cultures
var content2 = contentService.GetById(content.Id);
Assert.AreEqual("Home US", content2.Name);
Assert.AreEqual("name-fr", content2.GetName(langFr.IsoCode));
Assert.AreEqual("name-uk", content2.GetName(langUk.IsoCode));
Assert.AreEqual("value-fr1", content2.GetValue("prop", langFr.IsoCode));
Assert.AreEqual("value-uk1", content2.GetValue("prop", langUk.IsoCode));
Assert.IsNull(content2.GetValue("prop", langFr.IsoCode, published: true));
Assert.IsNull(content2.GetValue("prop", langUk.IsoCode, published: true));
Assert.IsNull(content2.PublishName);
Assert.IsNull(content2.GetPublishName(langFr.Id));
Assert.IsNull(content2.GetPublishName(langUk.Id));
Assert.IsTrue(content.IsCultureAvailable(langFr.Id));
Assert.IsTrue(content.IsCultureAvailable(langUk.Id));
Assert.IsFalse(content.IsCultureAvailable(langDe.Id));
Assert.IsFalse(content.IsCulturePublished(langFr.Id));
Assert.IsFalse(content.IsCulturePublished(langUk.Id));
// act
Assert.IsNull(content2.GetPublishName(langFr.IsoCode));
Assert.IsNull(content2.GetPublishName(langUk.IsoCode));
content.PublishValues(langFr.Id);
content.PublishValues(langUk.Id);
contentService.SaveAndPublish(content);
// both FR and UK have been published,
// and content has been published,
// only fr and uk have a name, and are available
AssertPerCulture(content, (x, c) => x.IsCultureAvailable(c), (langFr, true), (langUk, true), (langDe, false));
AssertPerCulture(content2, (x, c) => x.IsCultureAvailable(c), (langFr, true), (langUk, true), (langDe, false));
// nothing has been published yet
AssertPerCulture(content, (x, c) => x.IsCulturePublished(c), (langFr, false), (langUk, false), (langDe, false));
AssertPerCulture(content2, (x, c) => x.IsCulturePublished(c), (langFr, false), (langUk, false), (langDe, false));
// not published => must be edited
AssertPerCulture(content, (x, c) => x.IsCultureEdited(c), (langFr, true), (langUk, true), (langDe, true));
AssertPerCulture(content2, (x, c) => x.IsCultureEdited(c), (langFr, true), (langUk, true), (langDe, true));
// act
content.PublishValues(langFr.IsoCode);
content.PublishValues(langUk.IsoCode);
contentService.SaveAndPublish(content);
// both FR and UK have been published,
// and content has been published,
// it has names, publishNames, and published cultures
content2 = contentService.GetById(content.Id);
Assert.AreEqual("Home US", content2.Name);
Assert.AreEqual("name-fr", content2.GetName(langFr.Id));
Assert.AreEqual("name-uk", content2.GetName(langUk.Id));
Assert.AreEqual("name-fr", content2.GetName(langFr.IsoCode));
Assert.AreEqual("name-uk", content2.GetName(langUk.IsoCode));
Assert.IsNull(content2.PublishName); // we haven't published InvariantNeutral
Assert.AreEqual("name-fr", content2.GetPublishName(langFr.Id));
Assert.AreEqual("name-uk", content2.GetPublishName(langUk.Id));
Assert.AreEqual("name-fr", content2.GetPublishName(langFr.IsoCode));
Assert.AreEqual("name-uk", content2.GetPublishName(langUk.IsoCode));
Assert.AreEqual("value-fr1", content2.GetValue("prop", langFr.Id));
Assert.AreEqual("value-uk1", content2.GetValue("prop", langUk.Id));
Assert.AreEqual("value-fr1", content2.GetValue("prop", langFr.Id, published: true));
Assert.AreEqual("value-uk1", content2.GetValue("prop", langUk.Id, published: true));
Assert.AreEqual("value-fr1", content2.GetValue("prop", langFr.IsoCode));
Assert.AreEqual("value-uk1", content2.GetValue("prop", langUk.IsoCode));
Assert.AreEqual("value-fr1", content2.GetValue("prop", langFr.IsoCode, published: true));
Assert.AreEqual("value-uk1", content2.GetValue("prop", langUk.IsoCode, published: true));
// no change
AssertPerCulture(content, (x, c) => x.IsCultureAvailable(c), (langFr, true), (langUk, true), (langDe, false));
AssertPerCulture(content2, (x, c) => x.IsCultureAvailable(c), (langFr, true), (langUk, true), (langDe, false));
// fr and uk have been published now
AssertPerCulture(content, (x, c) => x.IsCulturePublished(c), (langFr, true), (langUk, true), (langDe, false));
AssertPerCulture(content2, (x, c) => x.IsCulturePublished(c), (langFr, true), (langUk, true), (langDe, false));
// fr and uk, published without changes, not edited
AssertPerCulture(content, (x, c) => x.IsCultureEdited(c), (langFr, false), (langUk, false), (langDe, true));
AssertPerCulture(content2, (x, c) => x.IsCultureEdited(c), (langFr, false), (langUk, false), (langDe, true));
Assert.IsTrue(content.IsCulturePublished(langFr.Id));
Assert.IsTrue(content.IsCulturePublished(langUk.Id));
AssertPerCulture(content, (x, c) => x.GetDateCulturePublished(c) == DateTime.MinValue, (langFr, false), (langUk, false)); // DE would throw
AssertPerCulture(content2, (x, c) => x.GetDateCulturePublished(c) == DateTime.MinValue, (langFr, false), (langUk, false)); // DE would throw
// note that content and content2 culture published dates might be slightly different due to roundtrip to database
// act
content.PublishValues();
contentService.SaveAndPublish(content);
contentService.SaveAndPublish(content);
// now it has publish name for invariant neutral
content2 = contentService.GetById(content.Id);
Assert.AreEqual("Home US", content2.PublishName);
Assert.AreEqual("Home US", content2.PublishName);
// act
// act
content.SetName(null, "Home US2");
content.SetName(langFr.Id, "name-fr2");
content.SetName(langUk.Id, "name-uk2");
content.SetName(langFr.IsoCode, "name-fr2");
content.SetName(langUk.IsoCode, "name-uk2");
content.SetValue("author", "Barack Obama2");
content.SetValue("prop", "value-fr2", langFr.Id);
content.SetValue("prop", "value-uk2", langUk.Id);
contentService.Save(content);
// content has been saved,
content.SetValue("prop", "value-fr2", langFr.IsoCode);
content.SetValue("prop", "value-uk2", langUk.IsoCode);
contentService.Save(content);
// content has been saved,
// it has updated names, unchanged publishNames, and published cultures
content2 = contentService.GetById(content.Id);
Assert.AreEqual("Home US2", content2.Name);
Assert.AreEqual("name-fr2", content2.GetName(langFr.Id));
Assert.AreEqual("name-uk2", content2.GetName(langUk.Id));
Assert.AreEqual("name-fr2", content2.GetName(langFr.IsoCode));
Assert.AreEqual("name-uk2", content2.GetName(langUk.IsoCode));
Assert.AreEqual("Home US", content2.PublishName);
Assert.AreEqual("name-fr", content2.GetPublishName(langFr.Id));
Assert.AreEqual("name-uk", content2.GetPublishName(langUk.Id));
Assert.AreEqual("name-fr", content2.GetPublishName(langFr.IsoCode));
Assert.AreEqual("name-uk", content2.GetPublishName(langUk.IsoCode));
Assert.AreEqual("Barack Obama2", content2.GetValue("author"));
Assert.AreEqual("Barack Obama", content2.GetValue("author", published: true));
Assert.AreEqual("value-fr2", content2.GetValue("prop", langFr.Id));
Assert.AreEqual("value-uk2", content2.GetValue("prop", langUk.Id));
Assert.AreEqual("value-fr1", content2.GetValue("prop", langFr.Id, published: true));
Assert.AreEqual("value-uk1", content2.GetValue("prop", langUk.Id, published: true));
Assert.AreEqual("value-fr2", content2.GetValue("prop", langFr.IsoCode));
Assert.AreEqual("value-uk2", content2.GetValue("prop", langUk.IsoCode));
Assert.AreEqual("value-fr1", content2.GetValue("prop", langFr.IsoCode, published: true));
Assert.AreEqual("value-uk1", content2.GetValue("prop", langUk.IsoCode, published: true));
// no change
AssertPerCulture(content, (x, c) => x.IsCultureAvailable(c), (langFr, true), (langUk, true), (langDe, false));
AssertPerCulture(content2, (x, c) => x.IsCultureAvailable(c), (langFr, true), (langUk, true), (langDe, false));
// no change
AssertPerCulture(content, (x, c) => x.IsCulturePublished(c), (langFr, true), (langUk, true), (langDe, false));
AssertPerCulture(content2, (x, c) => x.IsCulturePublished(c), (langFr, true), (langUk, true), (langDe, false));
Assert.IsTrue(content.IsCulturePublished(langFr.Id));
Assert.IsTrue(content.IsCulturePublished(langUk.Id));
// we have changed values so now fr and uk are edited
AssertPerCulture(content, (x, c) => x.IsCultureEdited(c), (langFr, true), (langUk, true), (langDe, true));
AssertPerCulture(content2, (x, c) => x.IsCultureEdited(c), (langFr, true), (langUk, true), (langDe, true));
AssertPerCulture(content, (x, c) => x.GetDateCulturePublished(c) == DateTime.MinValue, (langFr, false), (langUk, false)); // DE would throw
AssertPerCulture(content2, (x, c) => x.GetDateCulturePublished(c) == DateTime.MinValue, (langFr, false), (langUk, false)); // DE would throw
// act
// cannot just 'save' since we are changing what's published!
content.ClearPublishedValues(langFr.Id);
content.ClearPublishedValues(langFr.IsoCode);
contentService.SaveAndPublish(content);
// content has been published,
// the french culture is gone
// content has been published,
// the french culture is gone
content2 = contentService.GetById(content.Id);
Assert.AreEqual("Home US2", content2.Name);
Assert.AreEqual("name-fr2", content2.GetName(langFr.Id));
Assert.AreEqual("name-uk2", content2.GetName(langUk.Id));
Assert.AreEqual("name-fr2", content2.GetName(langFr.IsoCode));
Assert.AreEqual("name-uk2", content2.GetName(langUk.IsoCode));
Assert.AreEqual("Home US", content2.PublishName);
Assert.IsNull(content2.GetPublishName(langFr.Id));
Assert.AreEqual("name-uk", content2.GetPublishName(langUk.Id));
Assert.IsNull(content2.GetPublishName(langFr.IsoCode));
Assert.AreEqual("name-uk", content2.GetPublishName(langUk.IsoCode));
Assert.AreEqual("value-fr2", content2.GetValue("prop", langFr.Id));
Assert.AreEqual("value-uk2", content2.GetValue("prop", langUk.Id));
Assert.IsNull(content2.GetValue("prop", langFr.Id, published: true));
Assert.AreEqual("value-uk1", content2.GetValue("prop", langUk.Id, published: true));
Assert.AreEqual("value-fr2", content2.GetValue("prop", langFr.IsoCode));
Assert.AreEqual("value-uk2", content2.GetValue("prop", langUk.IsoCode));
Assert.IsNull(content2.GetValue("prop", langFr.IsoCode, published: true));
Assert.AreEqual("value-uk1", content2.GetValue("prop", langUk.IsoCode, published: true));
Assert.IsFalse(content.IsCulturePublished(langFr.Id));
Assert.IsTrue(content.IsCulturePublished(langUk.Id));
Assert.IsFalse(content.IsCulturePublished(langFr.IsoCode));
Assert.IsTrue(content.IsCulturePublished(langUk.IsoCode));
// no change
AssertPerCulture(content, (x, c) => x.IsCultureAvailable(c), (langFr, true), (langUk, true), (langDe, false));
AssertPerCulture(content2, (x, c) => x.IsCultureAvailable(c), (langFr, true), (langUk, true), (langDe, false));
// fr is not published anymore
AssertPerCulture(content, (x, c) => x.IsCulturePublished(c), (langFr, false), (langUk, true), (langDe, false));
AssertPerCulture(content2, (x, c) => x.IsCulturePublished(c), (langFr, false), (langUk, true), (langDe, false));
// and so, fr has to be edited
AssertPerCulture(content, (x, c) => x.IsCultureEdited(c), (langFr, true), (langUk, true), (langDe, true));
AssertPerCulture(content2, (x, c) => x.IsCultureEdited(c), (langFr, true), (langUk, true), (langDe, true));
AssertPerCulture(content, (x, c) => x.GetDateCulturePublished(c) == DateTime.MinValue, (langUk, false)); // FR, DE would throw
AssertPerCulture(content2, (x, c) => x.GetDateCulturePublished(c) == DateTime.MinValue, (langUk, false)); // FR, DE would throw
// act
contentService.Unpublish(content);
// content has been unpublished,
// but properties, names, etc. retain their 'published' values so the content
// can be re-published in its exact original state (before being unpublished)
//
// BEWARE!
// in order for a content to be unpublished as a whole, and then republished in
// its exact previous state, properties and names etc. retain their published
// values even though the content is not published - hence many things being
// non-null or true below - always check against content.Published to be sure
// act
contentService.Unpublish(content);
// content has been unpublished,
// but properties, names, etc. retain their 'published' values so the content
// can be re-published in its exact original state (before being unpublished)
//
// BEWARE!
// in order for a content to be unpublished as a whole, and then republished in
// its exact previous state, properties and names etc. retain their published
// values even though the content is not published - hence many things being
// non-null or true below - always check against content.Published to be sure
content2 = contentService.GetById(content.Id);
content2 = contentService.GetById(content.Id);
Assert.IsFalse(content2.Published);
Assert.AreEqual("Home US2", content2.Name);
Assert.AreEqual("name-fr2", content2.GetName(langFr.Id));
Assert.AreEqual("name-uk2", content2.GetName(langUk.Id));
Assert.AreEqual("name-fr2", content2.GetName(langFr.IsoCode));
Assert.AreEqual("name-uk2", content2.GetName(langUk.IsoCode));
Assert.AreEqual("Home US", content2.PublishName); // not null, see note above
Assert.IsNull(content2.GetPublishName(langFr.Id));
Assert.AreEqual("name-uk", content2.GetPublishName(langUk.Id)); // not null, see note above
Assert.IsNull(content2.GetPublishName(langFr.IsoCode));
Assert.AreEqual("name-uk", content2.GetPublishName(langUk.IsoCode)); // not null, see note above
Assert.AreEqual("value-fr2", content2.GetValue("prop", langFr.Id));
Assert.AreEqual("value-uk2", content2.GetValue("prop", langUk.Id));
Assert.IsNull(content2.GetValue("prop", langFr.Id, published: true));
Assert.AreEqual("value-uk1", content2.GetValue("prop", langUk.Id, published: true)); // has value, see note above
Assert.IsFalse(content.IsCulturePublished(langFr.Id));
Assert.IsTrue(content.IsCulturePublished(langUk.Id)); // still true, see note above
// act
Assert.AreEqual("value-fr2", content2.GetValue("prop", langFr.IsoCode));
Assert.AreEqual("value-uk2", content2.GetValue("prop", langUk.IsoCode));
Assert.IsNull(content2.GetValue("prop", langFr.IsoCode, published: true));
Assert.AreEqual("value-uk1", content2.GetValue("prop", langUk.IsoCode, published: true)); // has value, see note above
contentService.SaveAndPublish(content);
// no change
AssertPerCulture(content, (x, c) => x.IsCultureAvailable(c), (langFr, true), (langUk, true), (langDe, false));
AssertPerCulture(content2, (x, c) => x.IsCultureAvailable(c), (langFr, true), (langUk, true), (langDe, false));
// fr is not published anymore - uk still is, see note above
AssertPerCulture(content, (x, c) => x.IsCulturePublished(c), (langFr, false), (langUk, true), (langDe, false));
AssertPerCulture(content2, (x, c) => x.IsCulturePublished(c), (langFr, false), (langUk, true), (langDe, false));
// and so, fr has to be edited - uk still is
AssertPerCulture(content, (x, c) => x.IsCultureEdited(c), (langFr, true), (langUk, true), (langDe, true));
AssertPerCulture(content2, (x, c) => x.IsCultureEdited(c), (langFr, true), (langUk, true), (langDe, true));
AssertPerCulture(content, (x, c) => x.GetDateCulturePublished(c) == DateTime.MinValue, (langUk, false)); // FR, DE would throw
AssertPerCulture(content2, (x, c) => x.GetDateCulturePublished(c) == DateTime.MinValue, (langUk, false)); // FR, DE would throw
// content has been re-published,
// act
contentService.SaveAndPublish(content);
// content has been re-published,
// everything is back to what it was before being unpublished
content2 = contentService.GetById(content.Id);
@@ -2686,20 +2750,76 @@ namespace Umbraco.Tests.Services
Assert.IsTrue(content2.Published);
Assert.AreEqual("Home US2", content2.Name);
Assert.AreEqual("name-fr2", content2.GetName(langFr.Id));
Assert.AreEqual("name-uk2", content2.GetName(langUk.Id));
Assert.AreEqual("name-fr2", content2.GetName(langFr.IsoCode));
Assert.AreEqual("name-uk2", content2.GetName(langUk.IsoCode));
Assert.AreEqual("Home US", content2.PublishName);
Assert.IsNull(content2.GetPublishName(langFr.Id));
Assert.AreEqual("name-uk", content2.GetPublishName(langUk.Id));
Assert.IsNull(content2.GetPublishName(langFr.IsoCode));
Assert.AreEqual("name-uk", content2.GetPublishName(langUk.IsoCode));
Assert.AreEqual("value-fr2", content2.GetValue("prop", langFr.Id));
Assert.AreEqual("value-uk2", content2.GetValue("prop", langUk.Id));
Assert.IsNull(content2.GetValue("prop", langFr.Id, published: true));
Assert.AreEqual("value-uk1", content2.GetValue("prop", langUk.Id, published: true));
Assert.AreEqual("value-fr2", content2.GetValue("prop", langFr.IsoCode));
Assert.AreEqual("value-uk2", content2.GetValue("prop", langUk.IsoCode));
Assert.IsNull(content2.GetValue("prop", langFr.IsoCode, published: true));
Assert.AreEqual("value-uk1", content2.GetValue("prop", langUk.IsoCode, published: true));
// no change
AssertPerCulture(content, (x, c) => x.IsCultureAvailable(c), (langFr, true), (langUk, true), (langDe, false));
AssertPerCulture(content2, (x, c) => x.IsCultureAvailable(c), (langFr, true), (langUk, true), (langDe, false));
// no change, back to published
AssertPerCulture(content, (x, c) => x.IsCulturePublished(c), (langFr, false), (langUk, true), (langDe, false));
AssertPerCulture(content2, (x, c) => x.IsCulturePublished(c), (langFr, false), (langUk, true), (langDe, false));
// no change, back to published
AssertPerCulture(content, (x, c) => x.IsCultureEdited(c), (langFr, true), (langUk, true), (langDe, true));
AssertPerCulture(content2, (x, c) => x.IsCultureEdited(c), (langFr, true), (langUk, true), (langDe, true));
AssertPerCulture(content, (x, c) => x.GetDateCulturePublished(c) == DateTime.MinValue, (langUk, false)); // FR, DE would throw
AssertPerCulture(content2, (x, c) => x.GetDateCulturePublished(c) == DateTime.MinValue, (langUk, false)); // FR, DE would throw
Assert.IsFalse(content.IsCulturePublished(langFr.Id));
Assert.IsTrue(content.IsCulturePublished(langUk.Id));
// act
content.PublishValues(langUk.IsoCode);
contentService.SaveAndPublish(content);
content2 = contentService.GetById(content.Id);
// no change
AssertPerCulture(content, (x, c) => x.IsCultureAvailable(c), (langFr, true), (langUk, true), (langDe, false));
AssertPerCulture(content2, (x, c) => x.IsCultureAvailable(c), (langFr, true), (langUk, true), (langDe, false));
// no change
AssertPerCulture(content, (x, c) => x.IsCulturePublished(c), (langFr, false), (langUk, true), (langDe, false));
AssertPerCulture(content2, (x, c) => x.IsCulturePublished(c), (langFr, false), (langUk, true), (langDe, false));
// now, uk is no more edited
AssertPerCulture(content, (x, c) => x.IsCultureEdited(c), (langFr, true), (langUk, false), (langDe, true));
AssertPerCulture(content2, (x, c) => x.IsCultureEdited(c), (langFr, true), (langUk, false), (langDe, true));
AssertPerCulture(content, (x, c) => x.GetDateCulturePublished(c) == DateTime.MinValue, (langUk, false)); // FR, DE would throw
AssertPerCulture(content2, (x, c) => x.GetDateCulturePublished(c) == DateTime.MinValue, (langUk, false)); // FR, DE would throw
// act
content.SetName(langUk.IsoCode, "name-uk3");
contentService.Save(content);
content2 = contentService.GetById(content.Id);
// changing the name = edited!
Assert.IsTrue(content.IsCultureEdited(langUk.IsoCode));
Assert.IsTrue(content2.IsCultureEdited(langUk.IsoCode));
}
private void AssertPerCulture<T>(IContent item, Func<IContent, string, T> getter, params (ILanguage Language, bool Result)[] testCases)
{
foreach (var testCase in testCases)
{
var value = getter(item, testCase.Language.IsoCode);
Assert.AreEqual(testCase.Result, value, $"Expected {testCase.Result} and got {value} for culture {testCase.Language.IsoCode}.");
}
}
private IEnumerable<IContent> CreateContentHierarchy()

View File

@@ -457,8 +457,8 @@ namespace Umbraco.Tests.Services
ServiceContext.ContentTypeService.Save(contentType);
var c1 = MockedContent.CreateSimpleContent(contentType, "Test", -1);
c1.SetName(_langFr.Id, "Test - FR");
c1.SetName(_langEs.Id, "Test - ES");
c1.SetName(_langFr.IsoCode, "Test - FR");
c1.SetName(_langEs.IsoCode, "Test - ES");
ServiceContext.ContentService.Save(c1);
var result = service.Get(c1.Id, UmbracoObjectTypes.Document);
@@ -486,8 +486,8 @@ namespace Umbraco.Tests.Services
var c1 = MockedContent.CreateSimpleContent(contentType, Guid.NewGuid().ToString(), root);
if (i % 2 == 0)
{
c1.SetName(_langFr.Id, "Test " + i + " - FR");
c1.SetName(_langEs.Id, "Test " + i + " - ES");
c1.SetName(_langFr.IsoCode, "Test " + i + " - FR");
c1.SetName(_langEs.IsoCode, "Test " + i + " - ES");
}
ServiceContext.ContentService.Save(c1);
}

View File

@@ -140,8 +140,8 @@ namespace Umbraco.Tests.TestHelpers
{
// compare values
var actualProperty = (Property) actual;
var expectedPropertyValues = expectedProperty.Values.OrderBy(x => x.LanguageId).ThenBy(x => x.Segment).ToArray();
var actualPropertyValues = actualProperty.Values.OrderBy(x => x.LanguageId).ThenBy(x => x.Segment).ToArray();
var expectedPropertyValues = expectedProperty.Values.OrderBy(x => x.Culture).ThenBy(x => x.Segment).ToArray();
var actualPropertyValues = actualProperty.Values.OrderBy(x => x.Culture).ThenBy(x => x.Segment).ToArray();
if (expectedPropertyValues.Length != actualPropertyValues.Length)
Assert.Fail($"{property.DeclaringType.Name}.{property.Name}: Expected {expectedPropertyValues.Length} but got {actualPropertyValues.Length}.");
for (var i = 0; i < expectedPropertyValues.Length; i++)