From d116366b283bde323997008696fe15f0ec155a26 Mon Sep 17 00:00:00 2001 From: Nikolaj Geisle <70372949+Zeegaan@users.noreply.github.com> Date: Fri, 7 Jul 2023 11:12:04 +0200 Subject: [PATCH 01/13] V12: Deprecate XPath (#14372) * Deprecate all outward facing methods that uses XPath * Add more obsolete messages --------- Co-authored-by: Zeegaan --- .../Configuration/Models/ContentErrorPage.cs | 3 +++ src/Umbraco.Core/Extensions/XmlExtensions.cs | 8 ++++++++ .../Models/PublishedContent/IPublishedProperty.cs | 2 ++ .../Models/PublishedContent/IPublishedPropertyType.cs | 1 + .../Models/PublishedContent/PublishedPropertyBase.cs | 1 + .../Models/PublishedContent/PublishedPropertyType.cs | 1 + .../Models/PublishedContent/RawValueProperty.cs | 1 + .../PropertyEditors/IPropertyValueConverter.cs | 1 + .../PropertyEditors/PropertyValueConverterBase.cs | 1 + .../PropertyEditors/TextStringValueConverter.cs | 1 + .../ValueConverters/ContentPickerValueConverter.cs | 1 + .../ValueConverters/DatePickerValueConverter.cs | 1 + .../MultipleTextStringValueConverter.cs | 1 + .../ValueConverters/SimpleTinyMceValueConverter.cs | 1 + .../ValueConverters/YesNoValueConverter.cs | 1 + src/Umbraco.Core/PublishedCache/IPublishedCache.cs | 10 ++++++++++ .../Internal/InternalPublishedContentCache.cs | 6 ++++++ .../Internal/InternalPublishedProperty.cs | 2 ++ src/Umbraco.Core/PublishedCache/PublishedCacheBase.cs | 11 +++++++++++ .../PublishedCache/PublishedElementPropertyBase.cs | 1 + src/Umbraco.Core/Xml/DynamicContext.cs | 3 +++ src/Umbraco.Core/Xml/UmbracoXPathPathSyntaxParser.cs | 1 + src/Umbraco.Core/Xml/XPath/INavigableContent.cs | 1 + src/Umbraco.Core/Xml/XPath/INavigableContentType.cs | 1 + src/Umbraco.Core/Xml/XPath/INavigableFieldType.cs | 1 + src/Umbraco.Core/Xml/XPath/INavigableSource.cs | 1 + src/Umbraco.Core/Xml/XPath/MacroNavigator.cs | 1 + src/Umbraco.Core/Xml/XPath/NavigableNavigator.cs | 2 ++ src/Umbraco.Core/Xml/XPath/RenamedRootNavigator.cs | 1 + src/Umbraco.Core/Xml/XPathNavigatorExtensions.cs | 2 ++ src/Umbraco.Core/Xml/XPathVariable.cs | 1 + src/Umbraco.Core/Xml/XmlHelper.cs | 5 +++++ src/Umbraco.Core/Xml/XmlNodeListFactory.cs | 1 + src/Umbraco.Infrastructure/IPublishedContentQuery.cs | 3 +++ .../ValueConverters/MarkdownEditorValueConverter.cs | 1 + src/Umbraco.Infrastructure/PublishedContentQuery.cs | 3 +++ src/Umbraco.PublishedCache.NuCache/ContentCache.cs | 6 ++++++ src/Umbraco.PublishedCache.NuCache/MediaCache.cs | 3 +++ src/Umbraco.PublishedCache.NuCache/Property.cs | 1 + .../Controllers/EntityController.cs | 1 + src/Umbraco.Web.Common/UmbracoHelper.cs | 3 +++ 41 files changed, 97 insertions(+) diff --git a/src/Umbraco.Core/Configuration/Models/ContentErrorPage.cs b/src/Umbraco.Core/Configuration/Models/ContentErrorPage.cs index 415240e017..e5424fb636 100644 --- a/src/Umbraco.Core/Configuration/Models/ContentErrorPage.cs +++ b/src/Umbraco.Core/Configuration/Models/ContentErrorPage.cs @@ -24,6 +24,8 @@ public class ContentErrorPage : ValidatableEntryBase /// /// Gets or sets a value for the content XPath. /// + + [Obsolete("The current implementation of XPath is suboptimal and will be removed entirely in a future version. Scheduled for removal in v14")] public string? ContentXPath { get; set; } /// @@ -39,6 +41,7 @@ public class ContentErrorPage : ValidatableEntryBase /// /// Gets a value indicating whether the field is populated. /// + [Obsolete("The current implementation of XPath is suboptimal and will be removed entirely in a future version. Scheduled for removal in v14")] public bool HasContentXPath => !string.IsNullOrEmpty(ContentXPath); /// diff --git a/src/Umbraco.Core/Extensions/XmlExtensions.cs b/src/Umbraco.Core/Extensions/XmlExtensions.cs index 34e2b7b2aa..bb9e6c69b5 100644 --- a/src/Umbraco.Core/Extensions/XmlExtensions.cs +++ b/src/Umbraco.Core/Extensions/XmlExtensions.cs @@ -34,6 +34,7 @@ public static class XmlExtensions /// /// The XPath expression should reference variables as $var. /// + [Obsolete("The current implementation of XPath is suboptimal and will be removed entirely in a future version. Scheduled for removal in v14")] public static XmlNodeList? SelectNodes(this XmlNode source, string expression, IEnumerable? variables) { XPathVariable[]? av = variables?.ToArray(); @@ -56,6 +57,7 @@ public static class XmlExtensions /// /// The XPath expression should reference variables as $var. /// + [Obsolete("The current implementation of XPath is suboptimal and will be removed entirely in a future version. Scheduled for removal in v14")] public static XmlNodeList? SelectNodes(this XmlNode source, XPathExpression expression, IEnumerable? variables) { XPathVariable[]? av = variables?.ToArray(); @@ -78,6 +80,7 @@ public static class XmlExtensions /// /// The XPath expression should reference variables as $var. /// + [Obsolete("The current implementation of XPath is suboptimal and will be removed entirely in a future version. Scheduled for removal in v14")] public static XmlNodeList? SelectNodes(this XmlNode source, string? expression, params XPathVariable[]? variables) { if (variables == null || variables.Length == 0 || variables[0] == null) @@ -105,6 +108,7 @@ public static class XmlExtensions /// /// The XPath expression should reference variables as $var. /// + [Obsolete("The current implementation of XPath is suboptimal and will be removed entirely in a future version. Scheduled for removal in v14")] public static XmlNodeList SelectNodes(this XmlNode source, XPathExpression expression, params XPathVariable[]? variables) { if (variables == null || variables.Length == 0 || variables[0] == null) @@ -132,6 +136,7 @@ public static class XmlExtensions /// /// The XPath expression should reference variables as $var. /// + [Obsolete("The current implementation of XPath is suboptimal and will be removed entirely in a future version. Scheduled for removal in v14")] public static XmlNode? SelectSingleNode(this XmlNode source, string expression, IEnumerable? variables) { XPathVariable[]? av = variables?.ToArray(); @@ -154,6 +159,7 @@ public static class XmlExtensions /// /// The XPath expression should reference variables as $var. /// + [Obsolete("The current implementation of XPath is suboptimal and will be removed entirely in a future version. Scheduled for removal in v14")] public static XmlNode? SelectSingleNode(this XmlNode source, XPathExpression expression, IEnumerable? variables) { XPathVariable[]? av = variables?.ToArray(); @@ -176,6 +182,7 @@ public static class XmlExtensions /// /// The XPath expression should reference variables as $var. /// + [Obsolete("The current implementation of XPath is suboptimal and will be removed entirely in a future version. Scheduled for removal in v14")] public static XmlNode? SelectSingleNode(this XmlNode source, string expression, params XPathVariable[]? variables) { if (variables == null || variables.Length == 0 || variables[0] == null) @@ -202,6 +209,7 @@ public static class XmlExtensions /// /// The XPath expression should reference variables as $var. /// + [Obsolete("The current implementation of XPath is suboptimal and will be removed entirely in a future version. Scheduled for removal in v14")] public static XmlNode? SelectSingleNode(this XmlNode source, XPathExpression expression, params XPathVariable[]? variables) { if (variables == null || variables.Length == 0 || variables[0] == null) diff --git a/src/Umbraco.Core/Models/PublishedContent/IPublishedProperty.cs b/src/Umbraco.Core/Models/PublishedContent/IPublishedProperty.cs index a7bff33ba4..ed175e418d 100644 --- a/src/Umbraco.Core/Models/PublishedContent/IPublishedProperty.cs +++ b/src/Umbraco.Core/Models/PublishedContent/IPublishedProperty.cs @@ -69,6 +69,8 @@ public interface IPublishedProperty /// It must be either null, or a string, or an XPathNavigator. /// It has been fully prepared and processed by the appropriate converter. /// + + [Obsolete("The current implementation of XPath is suboptimal and will be removed entirely in a future version. Scheduled for removal in v14")] object? GetXPathValue(string? culture = null, string? segment = null); /// diff --git a/src/Umbraco.Core/Models/PublishedContent/IPublishedPropertyType.cs b/src/Umbraco.Core/Models/PublishedContent/IPublishedPropertyType.cs index 83ca0c49df..45d36abb6a 100644 --- a/src/Umbraco.Core/Models/PublishedContent/IPublishedPropertyType.cs +++ b/src/Umbraco.Core/Models/PublishedContent/IPublishedPropertyType.cs @@ -113,6 +113,7 @@ public interface IPublishedPropertyType /// /// The XPath value can be either a string or an XPathNavigator. /// + [Obsolete("The current implementation of XPath is suboptimal and will be removed entirely in a future version. Scheduled for removal in v14")] object? ConvertInterToXPath(IPublishedElement owner, PropertyCacheLevel referenceCacheLevel, object? inter, bool preview); /// diff --git a/src/Umbraco.Core/Models/PublishedContent/PublishedPropertyBase.cs b/src/Umbraco.Core/Models/PublishedContent/PublishedPropertyBase.cs index a06d2006ba..c36809600b 100644 --- a/src/Umbraco.Core/Models/PublishedContent/PublishedPropertyBase.cs +++ b/src/Umbraco.Core/Models/PublishedContent/PublishedPropertyBase.cs @@ -46,6 +46,7 @@ public abstract class PublishedPropertyBase : IPublishedProperty public abstract object? GetValue(string? culture = null, string? segment = null); /// + [Obsolete("The current implementation of XPath is suboptimal and will be removed entirely in a future version. Scheduled for removal in v14")] public abstract object? GetXPathValue(string? culture = null, string? segment = null); /// diff --git a/src/Umbraco.Core/Models/PublishedContent/PublishedPropertyType.cs b/src/Umbraco.Core/Models/PublishedContent/PublishedPropertyType.cs index 0efa4e7653..848e961d0b 100644 --- a/src/Umbraco.Core/Models/PublishedContent/PublishedPropertyType.cs +++ b/src/Umbraco.Core/Models/PublishedContent/PublishedPropertyType.cs @@ -273,6 +273,7 @@ namespace Umbraco.Cms.Core.Models.PublishedContent } /// + [Obsolete("The current implementation of XPath is suboptimal and will be removed entirely in a future version. Scheduled for removal in v14")] public object? ConvertInterToXPath(IPublishedElement owner, PropertyCacheLevel referenceCacheLevel, object? inter, bool preview) { if (!_initialized) diff --git a/src/Umbraco.Core/Models/PublishedContent/RawValueProperty.cs b/src/Umbraco.Core/Models/PublishedContent/RawValueProperty.cs index 3d29744bac..013f969805 100644 --- a/src/Umbraco.Core/Models/PublishedContent/RawValueProperty.cs +++ b/src/Umbraco.Core/Models/PublishedContent/RawValueProperty.cs @@ -58,6 +58,7 @@ public class RawValueProperty : PublishedPropertyBase public override object? GetValue(string? culture = null, string? segment = null) => string.IsNullOrEmpty(culture) & string.IsNullOrEmpty(segment) ? _objectValue.Value : null; + [Obsolete("The current implementation of XPath is suboptimal and will be removed entirely in a future version. Scheduled for removal in v14")] public override object? GetXPathValue(string? culture = null, string? segment = null) => string.IsNullOrEmpty(culture) & string.IsNullOrEmpty(segment) ? _xpathValue.Value : null; diff --git a/src/Umbraco.Core/PropertyEditors/IPropertyValueConverter.cs b/src/Umbraco.Core/PropertyEditors/IPropertyValueConverter.cs index 37d6b82475..74dbeaebae 100644 --- a/src/Umbraco.Core/PropertyEditors/IPropertyValueConverter.cs +++ b/src/Umbraco.Core/PropertyEditors/IPropertyValueConverter.cs @@ -128,5 +128,6 @@ public interface IPropertyValueConverter : IDiscoverable /// the cache levels of property values. It is not meant to be used by the converter. /// /// + [Obsolete("The current implementation of XPath is suboptimal and will be removed entirely in a future version. Scheduled for removal in v14")] object? ConvertIntermediateToXPath(IPublishedElement owner, IPublishedPropertyType propertyType, PropertyCacheLevel referenceCacheLevel, object? inter, bool preview); } diff --git a/src/Umbraco.Core/PropertyEditors/PropertyValueConverterBase.cs b/src/Umbraco.Core/PropertyEditors/PropertyValueConverterBase.cs index 3066086e7b..33c86f3ef4 100644 --- a/src/Umbraco.Core/PropertyEditors/PropertyValueConverterBase.cs +++ b/src/Umbraco.Core/PropertyEditors/PropertyValueConverterBase.cs @@ -49,6 +49,7 @@ public abstract class PropertyValueConverterBase : IPropertyValueConverter => inter; /// + [Obsolete("The current implementation of XPath is suboptimal and will be removed entirely in a future version. Scheduled for removal in v14")] public virtual object? ConvertIntermediateToXPath(IPublishedElement owner, IPublishedPropertyType propertyType, PropertyCacheLevel referenceCacheLevel, object? inter, bool preview) { var d = new XmlDocument(); diff --git a/src/Umbraco.Core/PropertyEditors/TextStringValueConverter.cs b/src/Umbraco.Core/PropertyEditors/TextStringValueConverter.cs index 6c9c80ce81..fc7651b801 100644 --- a/src/Umbraco.Core/PropertyEditors/TextStringValueConverter.cs +++ b/src/Umbraco.Core/PropertyEditors/TextStringValueConverter.cs @@ -51,6 +51,7 @@ public class TextStringValueConverter : PropertyValueConverterBase, IDeliveryApi // source should come from ConvertSource and be a string (or null) already inter ?? string.Empty; + [Obsolete("The current implementation of XPath is suboptimal and will be removed entirely in a future version. Scheduled for removal in v14")] public override object? ConvertIntermediateToXPath(IPublishedElement owner, IPublishedPropertyType propertyType, PropertyCacheLevel referenceCacheLevel, object? inter, bool preview) => // source should come from ConvertSource and be a string (or null) already diff --git a/src/Umbraco.Core/PropertyEditors/ValueConverters/ContentPickerValueConverter.cs b/src/Umbraco.Core/PropertyEditors/ValueConverters/ContentPickerValueConverter.cs index 06bfd1b1f2..94f2533548 100644 --- a/src/Umbraco.Core/PropertyEditors/ValueConverters/ContentPickerValueConverter.cs +++ b/src/Umbraco.Core/PropertyEditors/ValueConverters/ContentPickerValueConverter.cs @@ -86,6 +86,7 @@ public class ContentPickerValueConverter : PropertyValueConverterBase, IDelivery return content ?? inter; } + [Obsolete("The current implementation of XPath is suboptimal and will be removed entirely in a future version. Scheduled for removal in v14")] public override object? ConvertIntermediateToXPath(IPublishedElement owner, IPublishedPropertyType propertyType, PropertyCacheLevel referenceCacheLevel, object? inter, bool preview) { if (inter == null) diff --git a/src/Umbraco.Core/PropertyEditors/ValueConverters/DatePickerValueConverter.cs b/src/Umbraco.Core/PropertyEditors/ValueConverters/DatePickerValueConverter.cs index 7941946964..73ef424ba4 100644 --- a/src/Umbraco.Core/PropertyEditors/ValueConverters/DatePickerValueConverter.cs +++ b/src/Umbraco.Core/PropertyEditors/ValueConverters/DatePickerValueConverter.cs @@ -39,6 +39,7 @@ public class DatePickerValueConverter : PropertyValueConverterBase } // default ConvertSourceToObject just returns source ie a DateTime value + [Obsolete("The current implementation of XPath is suboptimal and will be removed entirely in a future version. Scheduled for removal in v14")] public override object? ConvertIntermediateToXPath( IPublishedElement owner, IPublishedPropertyType propertyType, diff --git a/src/Umbraco.Core/PropertyEditors/ValueConverters/MultipleTextStringValueConverter.cs b/src/Umbraco.Core/PropertyEditors/ValueConverters/MultipleTextStringValueConverter.cs index 3d631afead..e3dcd6ae78 100644 --- a/src/Umbraco.Core/PropertyEditors/ValueConverters/MultipleTextStringValueConverter.cs +++ b/src/Umbraco.Core/PropertyEditors/ValueConverters/MultipleTextStringValueConverter.cs @@ -57,6 +57,7 @@ public class MultipleTextStringValueConverter : PropertyValueConverterBase : values.ToArray(); } + [Obsolete("The current implementation of XPath is suboptimal and will be removed entirely in a future version. Scheduled for removal in v14")] public override object? ConvertIntermediateToXPath(IPublishedElement owner, IPublishedPropertyType propertyType, PropertyCacheLevel referenceCacheLevel, object? inter, bool preview) { var d = new XmlDocument(); diff --git a/src/Umbraco.Core/PropertyEditors/ValueConverters/SimpleTinyMceValueConverter.cs b/src/Umbraco.Core/PropertyEditors/ValueConverters/SimpleTinyMceValueConverter.cs index 7503e6711f..8e0aa50acf 100644 --- a/src/Umbraco.Core/PropertyEditors/ValueConverters/SimpleTinyMceValueConverter.cs +++ b/src/Umbraco.Core/PropertyEditors/ValueConverters/SimpleTinyMceValueConverter.cs @@ -31,6 +31,7 @@ public class SimpleTinyMceValueConverter : PropertyValueConverterBase // source should come from ConvertSource and be a string (or null) already new HtmlEncodedString(inter == null ? string.Empty : (string)inter); + [Obsolete("The current implementation of XPath is suboptimal and will be removed entirely in a future version. Scheduled for removal in v14")] public override object? ConvertIntermediateToXPath(IPublishedElement owner, IPublishedPropertyType propertyType, PropertyCacheLevel referenceCacheLevel, object? inter, bool preview) => // source should come from ConvertSource and be a string (or null) already diff --git a/src/Umbraco.Core/PropertyEditors/ValueConverters/YesNoValueConverter.cs b/src/Umbraco.Core/PropertyEditors/ValueConverters/YesNoValueConverter.cs index ab7f99e7f8..7bc940f90f 100644 --- a/src/Umbraco.Core/PropertyEditors/ValueConverters/YesNoValueConverter.cs +++ b/src/Umbraco.Core/PropertyEditors/ValueConverters/YesNoValueConverter.cs @@ -56,6 +56,7 @@ public class YesNoValueConverter : PropertyValueConverterBase } // default ConvertSourceToObject just returns source ie a boolean value + [Obsolete("The current implementation of XPath is suboptimal and will be removed entirely in a future version. Scheduled for removal in v14")] public override object ConvertIntermediateToXPath(IPublishedElement owner, IPublishedPropertyType propertyType, PropertyCacheLevel referenceCacheLevel, object? inter, bool preview) => // source should come from ConvertSource and be a boolean already diff --git a/src/Umbraco.Core/PublishedCache/IPublishedCache.cs b/src/Umbraco.Core/PublishedCache/IPublishedCache.cs index 0ee2ca38ed..78ebd19d6a 100644 --- a/src/Umbraco.Core/PublishedCache/IPublishedCache.cs +++ b/src/Umbraco.Core/PublishedCache/IPublishedCache.cs @@ -102,6 +102,7 @@ public interface IPublishedCache : IXPathNavigable /// Optional XPath variables. /// The content, or null. /// The value of overrides defaults. + [Obsolete("The current implementation of this method is suboptimal and will be removed entirely in a future version. Scheduled for removal in v14")] IPublishedContent? GetSingleByXPath(bool preview, string xpath, params XPathVariable[] vars); /// @@ -111,6 +112,7 @@ public interface IPublishedCache : IXPathNavigable /// Optional XPath variables. /// The content, or null. /// Considers published or unpublished content depending on defaults. + [Obsolete("The current implementation of this method is suboptimal and will be removed entirely in a future version. Scheduled for removal in v14")] IPublishedContent? GetSingleByXPath(string xpath, params XPathVariable[] vars); /// @@ -121,6 +123,7 @@ public interface IPublishedCache : IXPathNavigable /// Optional XPath variables. /// The content, or null. /// The value of overrides defaults. + [Obsolete("The current implementation of this method is suboptimal and will be removed entirely in a future version. Scheduled for removal in v14")] IPublishedContent? GetSingleByXPath(bool preview, XPathExpression xpath, params XPathVariable[] vars); /// @@ -130,6 +133,7 @@ public interface IPublishedCache : IXPathNavigable /// Optional XPath variables. /// The content, or null. /// Considers published or unpublished content depending on defaults. + [Obsolete("The current implementation of this method is suboptimal and will be removed entirely in a future version. Scheduled for removal in v14")] IPublishedContent? GetSingleByXPath(XPathExpression xpath, params XPathVariable[] vars); /// @@ -140,6 +144,7 @@ public interface IPublishedCache : IXPathNavigable /// Optional XPath variables. /// The contents. /// The value of overrides defaults. + [Obsolete("The current implementation of this method is suboptimal and will be removed entirely in a future version. Scheduled for removal in v14")] IEnumerable GetByXPath(bool preview, string xpath, params XPathVariable[] vars); /// @@ -149,6 +154,7 @@ public interface IPublishedCache : IXPathNavigable /// Optional XPath variables. /// The contents. /// Considers published or unpublished content depending on defaults. + [Obsolete("The current implementation of this method is suboptimal and will be removed entirely in a future version. Scheduled for removal in v14")] IEnumerable GetByXPath(string xpath, params XPathVariable[] vars); /// @@ -159,6 +165,7 @@ public interface IPublishedCache : IXPathNavigable /// Optional XPath variables. /// The contents. /// The value of overrides defaults. + [Obsolete("The current implementation of this method is suboptimal and will be removed entirely in a future version. Scheduled for removal in v14")] IEnumerable GetByXPath(bool preview, XPathExpression xpath, params XPathVariable[] vars); /// @@ -168,6 +175,7 @@ public interface IPublishedCache : IXPathNavigable /// Optional XPath variables. /// The contents. /// Considers published or unpublished content depending on defaults. + [Obsolete("The current implementation of this method is suboptimal and will be removed entirely in a future version. Scheduled for removal in v14")] IEnumerable GetByXPath(XPathExpression xpath, params XPathVariable[] vars); /// @@ -179,6 +187,7 @@ public interface IPublishedCache : IXPathNavigable /// The value of overrides the context. /// The navigator is already a safe clone (no need to clone it again). /// + [Obsolete("The current implementation of this method is suboptimal and will be removed entirely in a future version. Scheduled for removal in v14")] XPathNavigator CreateNavigator(bool preview); /// @@ -196,6 +205,7 @@ public interface IPublishedCache : IXPathNavigable /// /// If the node does not exist, returns null. /// + [Obsolete("The current implementation of this method is suboptimal and will be removed entirely in a future version. Scheduled for removal in v14")] XPathNavigator? CreateNodeNavigator(int id, bool preview); /// diff --git a/src/Umbraco.Core/PublishedCache/Internal/InternalPublishedContentCache.cs b/src/Umbraco.Core/PublishedCache/Internal/InternalPublishedContentCache.cs index e4e9010f5b..315136612a 100644 --- a/src/Umbraco.Core/PublishedCache/Internal/InternalPublishedContentCache.cs +++ b/src/Umbraco.Core/PublishedCache/Internal/InternalPublishedContentCache.cs @@ -38,20 +38,26 @@ public sealed class InternalPublishedContentCache : PublishedCacheBase, IPublish public override IEnumerable GetAtRoot(bool preview, string? culture = null) => _content.Values.Where(x => x.Parent == null); + [Obsolete("The current implementation of this method is suboptimal and will be removed entirely in a future version. Scheduled for removal in v14")] public override IPublishedContent GetSingleByXPath(bool preview, string xpath, XPathVariable[] vars) => throw new NotImplementedException(); + [Obsolete("The current implementation of this method is suboptimal and will be removed entirely in a future version. Scheduled for removal in v14")] public override IPublishedContent GetSingleByXPath(bool preview, XPathExpression xpath, XPathVariable[] vars) => throw new NotImplementedException(); + [Obsolete("The current implementation of this method is suboptimal and will be removed entirely in a future version. Scheduled for removal in v14")] public override IEnumerable GetByXPath(bool preview, string xpath, XPathVariable[] vars) => throw new NotImplementedException(); + [Obsolete("The current implementation of this method is suboptimal and will be removed entirely in a future version. Scheduled for removal in v14")] public override IEnumerable GetByXPath(bool preview, XPathExpression xpath, XPathVariable[] vars) => throw new NotImplementedException(); + [Obsolete("The current implementation of this method is suboptimal and will be removed entirely in a future version. Scheduled for removal in v14")] public override XPathNavigator CreateNavigator(bool preview) => throw new NotImplementedException(); + [Obsolete("The current implementation of this method is suboptimal and will be removed entirely in a future version. Scheduled for removal in v14")] public override XPathNavigator CreateNodeNavigator(int id, bool preview) => throw new NotImplementedException(); public override bool HasContent(bool preview) => _content.Count > 0; diff --git a/src/Umbraco.Core/PublishedCache/Internal/InternalPublishedProperty.cs b/src/Umbraco.Core/PublishedCache/Internal/InternalPublishedProperty.cs index a90897e221..c0d76aceb8 100644 --- a/src/Umbraco.Core/PublishedCache/Internal/InternalPublishedProperty.cs +++ b/src/Umbraco.Core/PublishedCache/Internal/InternalPublishedProperty.cs @@ -13,6 +13,7 @@ public class InternalPublishedProperty : IPublishedProperty public bool SolidHasValue { get; set; } + [Obsolete("The current implementation of XPath is suboptimal and will be removed entirely in a future version. Scheduled for removal in v14")] public object? SolidXPathValue { get; set; } public object? SolidDeliveryApiValue { get; set; } @@ -25,6 +26,7 @@ public class InternalPublishedProperty : IPublishedProperty public virtual object? GetValue(string? culture = null, string? segment = null) => SolidValue; + [Obsolete("The current implementation of XPath is suboptimal and will be removed entirely in a future version. Scheduled for removal in v14")] public virtual object? GetXPathValue(string? culture = null, string? segment = null) => SolidXPathValue; public virtual object? GetDeliveryApiValue(bool expanding, string? culture = null, string? segment = null) => SolidDeliveryApiValue; diff --git a/src/Umbraco.Core/PublishedCache/PublishedCacheBase.cs b/src/Umbraco.Core/PublishedCache/PublishedCacheBase.cs index 3e961ce434..c20ebf9284 100644 --- a/src/Umbraco.Core/PublishedCache/PublishedCacheBase.cs +++ b/src/Umbraco.Core/PublishedCache/PublishedCacheBase.cs @@ -40,31 +40,42 @@ public abstract class PublishedCacheBase : IPublishedCache public IEnumerable GetAtRoot(string? culture = null) => GetAtRoot(PreviewDefault, culture); + [Obsolete("The current implementation of this method is suboptimal and will be removed entirely in a future version. Scheduled for removal in v14")] public abstract IPublishedContent? GetSingleByXPath(bool preview, string xpath, XPathVariable[] vars); + [Obsolete("The current implementation of this method is suboptimal and will be removed entirely in a future version. Scheduled for removal in v14")] public IPublishedContent? GetSingleByXPath(string xpath, XPathVariable[] vars) => GetSingleByXPath(PreviewDefault, xpath, vars); + [Obsolete("The current implementation of this method is suboptimal and will be removed entirely in a future version. Scheduled for removal in v14")] public abstract IPublishedContent? GetSingleByXPath(bool preview, XPathExpression xpath, XPathVariable[] vars); + [Obsolete("The current implementation of this method is suboptimal and will be removed entirely in a future version. Scheduled for removal in v14")] public IPublishedContent? GetSingleByXPath(XPathExpression xpath, XPathVariable[] vars) => GetSingleByXPath(PreviewDefault, xpath, vars); + [Obsolete("The current implementation of this method is suboptimal and will be removed entirely in a future version. Scheduled for removal in v14")] public abstract IEnumerable GetByXPath(bool preview, string xpath, XPathVariable[] vars); + [Obsolete("The current implementation of this method is suboptimal and will be removed entirely in a future version. Scheduled for removal in v14")] public IEnumerable GetByXPath(string xpath, XPathVariable[] vars) => GetByXPath(PreviewDefault, xpath, vars); + [Obsolete("The current implementation of this method is suboptimal and will be removed entirely in a future version. Scheduled for removal in v14")] public abstract IEnumerable GetByXPath(bool preview, XPathExpression xpath, XPathVariable[] vars); + [Obsolete("The current implementation of this method is suboptimal and will be removed entirely in a future version. Scheduled for removal in v14")] public IEnumerable GetByXPath(XPathExpression xpath, XPathVariable[] vars) => GetByXPath(PreviewDefault, xpath, vars); + [Obsolete("The current implementation of this method is suboptimal and will be removed entirely in a future version. Scheduled for removal in v14")] public abstract XPathNavigator CreateNavigator(bool preview); + [Obsolete("The current implementation of this method is suboptimal and will be removed entirely in a future version. Scheduled for removal in v14")] public XPathNavigator CreateNavigator() => CreateNavigator(PreviewDefault); + [Obsolete("The current implementation of this method is suboptimal and will be removed entirely in a future version. Scheduled for removal in v14")] public abstract XPathNavigator? CreateNodeNavigator(int id, bool preview); public abstract bool HasContent(bool preview); diff --git a/src/Umbraco.Core/PublishedCache/PublishedElementPropertyBase.cs b/src/Umbraco.Core/PublishedCache/PublishedElementPropertyBase.cs index b4e56897a7..05348a138c 100644 --- a/src/Umbraco.Core/PublishedCache/PublishedElementPropertyBase.cs +++ b/src/Umbraco.Core/PublishedCache/PublishedElementPropertyBase.cs @@ -201,6 +201,7 @@ internal class PublishedElementPropertyBase : PublishedPropertyBase } } + [Obsolete("The current implementation of XPath is suboptimal and will be removed entirely in a future version. Scheduled for removal in v14")] public override object? GetXPathValue(string? culture = null, string? segment = null) { GetCacheLevels(out PropertyCacheLevel cacheLevel, out PropertyCacheLevel referenceCacheLevel); diff --git a/src/Umbraco.Core/Xml/DynamicContext.cs b/src/Umbraco.Core/Xml/DynamicContext.cs index fd86866348..321024f486 100644 --- a/src/Umbraco.Core/Xml/DynamicContext.cs +++ b/src/Umbraco.Core/Xml/DynamicContext.cs @@ -118,6 +118,7 @@ namespace Umbraco.Cms.Core.Xml /// /// Same as . /// + [Obsolete("The current implementation of XPath is suboptimal and will be removed entirely in a future version. Scheduled for removal in v14")] public override bool PreserveWhitespace(XPathNavigator node) { return true; @@ -140,6 +141,7 @@ namespace Umbraco.Cms.Core.Xml /// /// The expression to compile /// A compiled . + [Obsolete("The current implementation of XPath is suboptimal and will be removed entirely in a future version. Scheduled for removal in v14")] public static XPathExpression? Compile(string xpath) { return new XmlDocument().CreateNavigator()?.Compile(xpath); @@ -203,6 +205,7 @@ namespace Umbraco.Cms.Core.Xml /// /// See . Not used in our implementation. /// + [Obsolete("The current implementation of XPath is suboptimal and will be removed entirely in a future version. Scheduled for removal in v14")] public override IXsltContextFunction ResolveFunction(string prefix, string name, XPathResultType[] argTypes) => throw new NotImplementedException(); /// diff --git a/src/Umbraco.Core/Xml/UmbracoXPathPathSyntaxParser.cs b/src/Umbraco.Core/Xml/UmbracoXPathPathSyntaxParser.cs index 2a01d42dc7..87d4d459fa 100644 --- a/src/Umbraco.Core/Xml/UmbracoXPathPathSyntaxParser.cs +++ b/src/Umbraco.Core/Xml/UmbracoXPathPathSyntaxParser.cs @@ -6,6 +6,7 @@ namespace Umbraco.Cms.Core.Xml; /// This is used to parse our customize Umbraco XPath expressions (i.e. that include special tokens like $site) into /// a real XPath statement /// +[Obsolete("The current implementation of XPath is suboptimal and will be removed entirely in a future version. Scheduled for removal in v14")] public class UmbracoXPathPathSyntaxParser { [Obsolete("This will be removed in Umbraco 13. Use ParseXPathQuery which accepts a parentId instead")] diff --git a/src/Umbraco.Core/Xml/XPath/INavigableContent.cs b/src/Umbraco.Core/Xml/XPath/INavigableContent.cs index b9359b4fef..8d9d48a0a0 100644 --- a/src/Umbraco.Core/Xml/XPath/INavigableContent.cs +++ b/src/Umbraco.Core/Xml/XPath/INavigableContent.cs @@ -3,6 +3,7 @@ namespace Umbraco.Cms.Core.Xml.XPath; /// /// Represents a content that can be navigated via XPath. /// +[Obsolete("The current implementation of XPath is suboptimal and will be removed entirely in a future version. Scheduled for removal in v14")] public interface INavigableContent { /// diff --git a/src/Umbraco.Core/Xml/XPath/INavigableContentType.cs b/src/Umbraco.Core/Xml/XPath/INavigableContentType.cs index 08a7c1a0f6..eeb775e07b 100644 --- a/src/Umbraco.Core/Xml/XPath/INavigableContentType.cs +++ b/src/Umbraco.Core/Xml/XPath/INavigableContentType.cs @@ -3,6 +3,7 @@ namespace Umbraco.Cms.Core.Xml.XPath; /// /// Represents the type of a content that can be navigated via XPath. /// +[Obsolete("The current implementation of XPath is suboptimal and will be removed entirely in a future version. Scheduled for removal in v14")] public interface INavigableContentType { /// diff --git a/src/Umbraco.Core/Xml/XPath/INavigableFieldType.cs b/src/Umbraco.Core/Xml/XPath/INavigableFieldType.cs index 28fa46e84b..faaa612474 100644 --- a/src/Umbraco.Core/Xml/XPath/INavigableFieldType.cs +++ b/src/Umbraco.Core/Xml/XPath/INavigableFieldType.cs @@ -4,6 +4,7 @@ namespace Umbraco.Cms.Core.Xml.XPath; /// Represents the type of a field of a content that can be navigated via XPath. /// /// A field can be an attribute or a property. +[Obsolete("The current implementation of XPath is suboptimal and will be removed entirely in a future version. Scheduled for removal in v14")] public interface INavigableFieldType { /// diff --git a/src/Umbraco.Core/Xml/XPath/INavigableSource.cs b/src/Umbraco.Core/Xml/XPath/INavigableSource.cs index 1f8500725b..459f1bf606 100644 --- a/src/Umbraco.Core/Xml/XPath/INavigableSource.cs +++ b/src/Umbraco.Core/Xml/XPath/INavigableSource.cs @@ -3,6 +3,7 @@ namespace Umbraco.Cms.Core.Xml.XPath; /// /// Represents a source of content that can be navigated via XPath. /// +[Obsolete("The current implementation of XPath is suboptimal and will be removed entirely in a future version. Scheduled for removal in v14")] public interface INavigableSource { /// diff --git a/src/Umbraco.Core/Xml/XPath/MacroNavigator.cs b/src/Umbraco.Core/Xml/XPath/MacroNavigator.cs index dd27e6124c..3d706eed80 100644 --- a/src/Umbraco.Core/Xml/XPath/MacroNavigator.cs +++ b/src/Umbraco.Core/Xml/XPath/MacroNavigator.cs @@ -7,6 +7,7 @@ namespace Umbraco.Cms.Core.Xml.XPath /// /// Provides a cursor model for navigating {macro /} as if it were XML. /// + [Obsolete("The current implementation of XPath is suboptimal and will be removed entirely in a future version. Scheduled for removal in v14")] public class MacroNavigator : XPathNavigator { private readonly XmlNameTable _nameTable; diff --git a/src/Umbraco.Core/Xml/XPath/NavigableNavigator.cs b/src/Umbraco.Core/Xml/XPath/NavigableNavigator.cs index 3529f55922..020f753165 100644 --- a/src/Umbraco.Core/Xml/XPath/NavigableNavigator.cs +++ b/src/Umbraco.Core/Xml/XPath/NavigableNavigator.cs @@ -21,6 +21,8 @@ namespace Umbraco.Cms.Core.Xml.XPath; /// /// Provides a cursor model for navigating Umbraco data as if it were XML. /// + +[Obsolete("The current implementation of XPath is suboptimal and will be removed entirely in a future version. Scheduled for removal in v14")] public class NavigableNavigator : XPathNavigator { // "The XmlNameTable stores atomized strings of any local name, namespace URI, diff --git a/src/Umbraco.Core/Xml/XPath/RenamedRootNavigator.cs b/src/Umbraco.Core/Xml/XPath/RenamedRootNavigator.cs index 1b710c8db5..63fa9ef263 100644 --- a/src/Umbraco.Core/Xml/XPath/RenamedRootNavigator.cs +++ b/src/Umbraco.Core/Xml/XPath/RenamedRootNavigator.cs @@ -3,6 +3,7 @@ using System.Xml.XPath; namespace Umbraco.Cms.Core.Xml.XPath; +[Obsolete("The current implementation of XPath is suboptimal and will be removed entirely in a future version. Scheduled for removal in v14")] public class RenamedRootNavigator : XPathNavigator { private readonly XPathNavigator _navigator; diff --git a/src/Umbraco.Core/Xml/XPathNavigatorExtensions.cs b/src/Umbraco.Core/Xml/XPathNavigatorExtensions.cs index 44cda2c691..09bd34f692 100644 --- a/src/Umbraco.Core/Xml/XPathNavigatorExtensions.cs +++ b/src/Umbraco.Core/Xml/XPathNavigatorExtensions.cs @@ -18,6 +18,7 @@ public static class XPathNavigatorExtensions /// An XPath expression. /// A set of XPathVariables. /// An iterator over the nodes matching the specified expression. + [Obsolete("The current implementation of XPath is suboptimal and will be removed entirely in a future version. Scheduled for removal in v14")] public static XPathNodeIterator Select(this XPathNavigator navigator, string expression, params XPathVariable[] variables) { if (variables == null || variables.Length == 0 || variables[0] == null) @@ -50,6 +51,7 @@ public static class XPathNavigatorExtensions /// An XPath expression. /// A set of XPathVariables. /// An iterator over the nodes matching the specified expression. + [Obsolete("The current implementation of XPath is suboptimal and will be removed entirely in a future version. Scheduled for removal in v14")] public static XPathNodeIterator Select(this XPathNavigator navigator, XPathExpression expression, params XPathVariable[] variables) { if (variables == null || variables.Length == 0 || variables[0] == null) diff --git a/src/Umbraco.Core/Xml/XPathVariable.cs b/src/Umbraco.Core/Xml/XPathVariable.cs index 4c2d2d0f4e..675485e551 100644 --- a/src/Umbraco.Core/Xml/XPathVariable.cs +++ b/src/Umbraco.Core/Xml/XPathVariable.cs @@ -6,6 +6,7 @@ namespace Umbraco.Cms.Core.Xml; /// Represents a variable in an XPath query. /// /// The name must be foo in the constructor and $foo in the XPath query. +[Obsolete("The current implementation of XPath is suboptimal and will be removed entirely in a future version. Scheduled for removal in v14")] public class XPathVariable { /// diff --git a/src/Umbraco.Core/Xml/XmlHelper.cs b/src/Umbraco.Core/Xml/XmlHelper.cs index ad97120c93..a2165fdd39 100644 --- a/src/Umbraco.Core/Xml/XmlHelper.cs +++ b/src/Umbraco.Core/Xml/XmlHelper.cs @@ -76,6 +76,7 @@ public class XmlHelper /// /// The xml string. /// An XPathDocument created from the xml string. + [Obsolete("The current implementation of XPath is suboptimal and will be removed entirely in a future version. Scheduled for removal in v14")] public static XPathDocument CreateXPathDocument(string xml) => new XPathDocument(new XmlTextReader(new StringReader(xml))); @@ -85,6 +86,7 @@ public class XmlHelper /// The xml string. /// The XPath document. /// A value indicating whether it has been possible to create the document. + [Obsolete("The current implementation of XPath is suboptimal and will be removed entirely in a future version. Scheduled for removal in v14")] public static bool TryCreateXPathDocument(string xml, out XPathDocument? doc) { try @@ -106,6 +108,7 @@ public class XmlHelper /// The XPath document. /// A value indicating whether it has been possible to create the document. /// The value can be anything... Performance-wise, this is bad. + [Obsolete("The current implementation of XPath is suboptimal and will be removed entirely in a future version. Scheduled for removal in v14")] public static bool TryCreateXPathDocumentFromPropertyValue(object value, out XPathDocument? doc) { // DynamicNode.ConvertPropertyValueByDataType first cleans the value by calling @@ -155,6 +158,7 @@ public class XmlHelper /// The parent node. /// An XPath expression to select children of to sort. /// A function returning the value to order the nodes by. + [Obsolete("The current implementation of XPath is suboptimal and will be removed entirely in a future version. Scheduled for removal in v14")] public static void SortNodes( XmlNode parentNode, string childNodesXPath, @@ -187,6 +191,7 @@ public class XmlHelper /// Assuming all nodes but are sorted, this will move the node to /// the right position without moving all the nodes (as SortNodes would do) - should improve perfs. /// + [Obsolete("The current implementation of XPath is suboptimal and will be removed entirely in a future version. Scheduled for removal in v14")] public static bool SortNode( XmlNode parentNode, string childNodesXPath, diff --git a/src/Umbraco.Core/Xml/XmlNodeListFactory.cs b/src/Umbraco.Core/Xml/XmlNodeListFactory.cs index 17c2f41843..8031ca0bf0 100644 --- a/src/Umbraco.Core/Xml/XmlNodeListFactory.cs +++ b/src/Umbraco.Core/Xml/XmlNodeListFactory.cs @@ -27,6 +27,7 @@ public class XmlNodeListFactory /// an object inheriting , such as /// . /// + [Obsolete("The current implementation of XPath is suboptimal and will be removed entirely in a future version. Scheduled for removal in v14")] public static XmlNodeList CreateNodeList(XPathNodeIterator? iterator) => new XmlNodeListIterator(iterator); #endregion Public members diff --git a/src/Umbraco.Infrastructure/IPublishedContentQuery.cs b/src/Umbraco.Infrastructure/IPublishedContentQuery.cs index cc034e5768..6e82239dac 100644 --- a/src/Umbraco.Infrastructure/IPublishedContentQuery.cs +++ b/src/Umbraco.Infrastructure/IPublishedContentQuery.cs @@ -18,6 +18,7 @@ public interface IPublishedContentQuery IPublishedContent? Content(object id); + [Obsolete("The current implementation of this method is suboptimal and will be removed entirely in a future version. Scheduled for removal in v14")] IPublishedContent? ContentSingleAtXPath(string xpath, params XPathVariable[] vars); IEnumerable Content(IEnumerable ids); @@ -26,8 +27,10 @@ public interface IPublishedContentQuery IEnumerable Content(IEnumerable ids); + [Obsolete("The current implementation of this method is suboptimal and will be removed entirely in a future version. Scheduled for removal in v14")] IEnumerable ContentAtXPath(string xpath, params XPathVariable[] vars); + [Obsolete("The current implementation of this method is suboptimal and will be removed entirely in a future version. Scheduled for removal in v14")] IEnumerable ContentAtXPath(XPathExpression xpath, params XPathVariable[] vars); IEnumerable ContentAtRoot(); diff --git a/src/Umbraco.Infrastructure/PropertyEditors/ValueConverters/MarkdownEditorValueConverter.cs b/src/Umbraco.Infrastructure/PropertyEditors/ValueConverters/MarkdownEditorValueConverter.cs index 9aeeb02d92..178778483d 100644 --- a/src/Umbraco.Infrastructure/PropertyEditors/ValueConverters/MarkdownEditorValueConverter.cs +++ b/src/Umbraco.Infrastructure/PropertyEditors/ValueConverters/MarkdownEditorValueConverter.cs @@ -56,6 +56,7 @@ public class MarkdownEditorValueConverter : PropertyValueConverterBase, IDeliver return new HtmlEncodedString(inter == null ? string.Empty : mark.Transform((string)inter)); } + [Obsolete("The current implementation of XPath is suboptimal and will be removed entirely in a future version. Scheduled for removal in v14")] public override object ConvertIntermediateToXPath(IPublishedElement owner, IPublishedPropertyType propertyType, PropertyCacheLevel referenceCacheLevel, object? inter, bool preview) => // source should come from ConvertSource and be a string (or null) already diff --git a/src/Umbraco.Infrastructure/PublishedContentQuery.cs b/src/Umbraco.Infrastructure/PublishedContentQuery.cs index ef16aeccc6..d075e8b9d2 100644 --- a/src/Umbraco.Infrastructure/PublishedContentQuery.cs +++ b/src/Umbraco.Infrastructure/PublishedContentQuery.cs @@ -129,6 +129,7 @@ public class PublishedContentQuery : IPublishedContentQuery return null; } + [Obsolete("The current implementation of this method is suboptimal and will be removed entirely in a future version. Scheduled for removal in v14")] public IPublishedContent? ContentSingleAtXPath(string xpath, params XPathVariable[] vars) => ItemByXPath(xpath, vars, _publishedSnapshot.Content); @@ -141,9 +142,11 @@ public class PublishedContentQuery : IPublishedContentQuery public IEnumerable Content(IEnumerable ids) => ids.Select(Content).WhereNotNull(); + [Obsolete("The current implementation of this method is suboptimal and will be removed entirely in a future version. Scheduled for removal in v14")] public IEnumerable ContentAtXPath(string xpath, params XPathVariable[] vars) => ItemsByXPath(xpath, vars, _publishedSnapshot.Content); + [Obsolete("The current implementation of this method is suboptimal and will be removed entirely in a future version. Scheduled for removal in v14")] public IEnumerable ContentAtXPath(XPathExpression xpath, params XPathVariable[] vars) => ItemsByXPath(xpath, vars, _publishedSnapshot.Content); diff --git a/src/Umbraco.PublishedCache.NuCache/ContentCache.cs b/src/Umbraco.PublishedCache.NuCache/ContentCache.cs index d8a5c0bc04..d854de4b95 100644 --- a/src/Umbraco.PublishedCache.NuCache/ContentCache.cs +++ b/src/Umbraco.PublishedCache.NuCache/ContentCache.cs @@ -360,6 +360,7 @@ public class ContentCache : PublishedCacheBase, IPublishedContentCache, INavigab ? _snapshot.IsEmpty == false : _snapshot.GetAtRoot().Any(x => x.PublishedModel != null); + [Obsolete("The current implementation of this method is suboptimal and will be removed entirely in a future version. Scheduled for removal in v14")] public override IPublishedContent? GetSingleByXPath(bool preview, string xpath, XPathVariable[] vars) { XPathNavigator navigator = CreateNavigator(preview); @@ -367,6 +368,7 @@ public class ContentCache : PublishedCacheBase, IPublishedContentCache, INavigab return GetSingleByXPath(iterator); } + [Obsolete("The current implementation of this method is suboptimal and will be removed entirely in a future version. Scheduled for removal in v14")] public override IPublishedContent? GetSingleByXPath(bool preview, XPathExpression xpath, XPathVariable[] vars) { XPathNavigator navigator = CreateNavigator(preview); @@ -386,6 +388,7 @@ public class ContentCache : PublishedCacheBase, IPublishedContentCache, INavigab return xcontent?.InnerContent; } + [Obsolete("The current implementation of this method is suboptimal and will be removed entirely in a future version. Scheduled for removal in v14")] public override IEnumerable GetByXPath(bool preview, string xpath, XPathVariable[] vars) { XPathNavigator navigator = CreateNavigator(preview); @@ -393,6 +396,7 @@ public class ContentCache : PublishedCacheBase, IPublishedContentCache, INavigab return GetByXPath(iterator); } + [Obsolete("The current implementation of this method is suboptimal and will be removed entirely in a future version. Scheduled for removal in v14")] public override IEnumerable GetByXPath(bool preview, XPathExpression xpath, XPathVariable[] vars) { XPathNavigator navigator = CreateNavigator(preview); @@ -416,6 +420,7 @@ public class ContentCache : PublishedCacheBase, IPublishedContentCache, INavigab } } + [Obsolete("The current implementation of this method is suboptimal and will be removed entirely in a future version. Scheduled for removal in v14")] public override XPathNavigator CreateNavigator(bool preview) { var source = new Source(this, preview); @@ -423,6 +428,7 @@ public class ContentCache : PublishedCacheBase, IPublishedContentCache, INavigab return navigator; } + [Obsolete("The current implementation of this method is suboptimal and will be removed entirely in a future version. Scheduled for removal in v14")] public override XPathNavigator? CreateNodeNavigator(int id, bool preview) { var source = new Source(this, preview); diff --git a/src/Umbraco.PublishedCache.NuCache/MediaCache.cs b/src/Umbraco.PublishedCache.NuCache/MediaCache.cs index 626e2fe36c..014140e884 100644 --- a/src/Umbraco.PublishedCache.NuCache/MediaCache.cs +++ b/src/Umbraco.PublishedCache.NuCache/MediaCache.cs @@ -95,6 +95,7 @@ public class MediaCache : PublishedCacheBase, IPublishedMediaCache, INavigableDa #region XPath + [Obsolete("The current implementation of this method is suboptimal and will be removed entirely in a future version. Scheduled for removal in v14")] public override IPublishedContent? GetSingleByXPath(bool preview, string xpath, XPathVariable[] vars) { XPathNavigator navigator = CreateNavigator(preview); @@ -102,6 +103,7 @@ public class MediaCache : PublishedCacheBase, IPublishedMediaCache, INavigableDa return GetSingleByXPath(iterator); } + [Obsolete("The current implementation of this method is suboptimal and will be removed entirely in a future version. Scheduled for removal in v14")] public override IPublishedContent? GetSingleByXPath(bool preview, XPathExpression xpath, XPathVariable[] vars) { XPathNavigator navigator = CreateNavigator(preview); @@ -109,6 +111,7 @@ public class MediaCache : PublishedCacheBase, IPublishedMediaCache, INavigableDa return GetSingleByXPath(iterator); } + [Obsolete("The current implementation of this method is suboptimal and will be removed entirely in a future version. Scheduled for removal in v14")] public override IEnumerable GetByXPath(bool preview, string xpath, XPathVariable[] vars) { XPathNavigator navigator = CreateNavigator(preview); diff --git a/src/Umbraco.PublishedCache.NuCache/Property.cs b/src/Umbraco.PublishedCache.NuCache/Property.cs index d50553d95f..e86f6f4ad9 100644 --- a/src/Umbraco.PublishedCache.NuCache/Property.cs +++ b/src/Umbraco.PublishedCache.NuCache/Property.cs @@ -288,6 +288,7 @@ internal class Property : PublishedPropertyBase return value; } + [Obsolete("The current implementation of XPath is suboptimal and will be removed entirely in a future version. Scheduled for removal in v14")] public override object? GetXPathValue(string? culture = null, string? segment = null) { _content.VariationContextAccessor.ContextualizeVariation(_variations, _content.Id, ref culture, ref segment); diff --git a/src/Umbraco.Web.BackOffice/Controllers/EntityController.cs b/src/Umbraco.Web.BackOffice/Controllers/EntityController.cs index 750d60d67e..036397cb4d 100644 --- a/src/Umbraco.Web.BackOffice/Controllers/EntityController.cs +++ b/src/Umbraco.Web.BackOffice/Controllers/EntityController.cs @@ -533,6 +533,7 @@ public class EntityController : UmbracoAuthorizedJsonController /// /// /// + [Obsolete("The current implementation of this method is suboptimal and will be removed entirely in a future version. Scheduled for removal in v14")] public ActionResult? GetByXPath(string query, int nodeContextId, int? parentId, UmbracoEntityTypes type) { if (type != UmbracoEntityTypes.Document) diff --git a/src/Umbraco.Web.Common/UmbracoHelper.cs b/src/Umbraco.Web.Common/UmbracoHelper.cs index 56181b29da..17729f3364 100644 --- a/src/Umbraco.Web.Common/UmbracoHelper.cs +++ b/src/Umbraco.Web.Common/UmbracoHelper.cs @@ -174,6 +174,7 @@ public class UmbracoHelper private IPublishedContent? ContentForObject(object id) => _publishedContentQuery.Content(id); + [Obsolete("The current implementation of XPath is suboptimal and will be removed entirely in a future version. Scheduled for removal in v14")] public IPublishedContent? ContentSingleAtXPath(string xpath, params XPathVariable[] vars) => _publishedContentQuery.ContentSingleAtXPath(xpath, vars); @@ -286,9 +287,11 @@ public class UmbracoHelper /// If an identifier does not match an existing content, it will be missing in the returned value. public IEnumerable Content(IEnumerable ids) => _publishedContentQuery.Content(ids); + [Obsolete("The current implementation of this method is suboptimal and will be removed entirely in a future version. Scheduled for removal in v14")] public IEnumerable ContentAtXPath(string xpath, params XPathVariable[] vars) => _publishedContentQuery.ContentAtXPath(xpath, vars); + [Obsolete("The current implementation of this method is suboptimal and will be removed entirely in a future version. Scheduled for removal in v14")] public IEnumerable ContentAtXPath(XPathExpression xpath, params XPathVariable[] vars) => _publishedContentQuery.ContentAtXPath(xpath, vars); From a5ba32bfd7478f44a0aff3c9c0fcdad08fe51d96 Mon Sep 17 00:00:00 2001 From: Elitsa Marinovska <21998037+elit0451@users.noreply.github.com> Date: Fri, 7 Jul 2023 15:23:32 +0300 Subject: [PATCH 02/13] Store tags as text (instead of nvarchar) (#14510) * Migrate tags from NVarchar To NText * Cleanup --- .../Migrations/Upgrade/UmbracoPlan.cs | 4 ++ .../MigrateTagsFromNVarcharToNText.cs | 46 +++++++++++++++++++ .../PropertyEditors/TagsPropertyEditor.cs | 3 +- 3 files changed, 52 insertions(+), 1 deletion(-) create mode 100644 src/Umbraco.Infrastructure/Migrations/Upgrade/V_10_7_0/MigrateTagsFromNVarcharToNText.cs diff --git a/src/Umbraco.Infrastructure/Migrations/Upgrade/UmbracoPlan.cs b/src/Umbraco.Infrastructure/Migrations/Upgrade/UmbracoPlan.cs index 62a37a8e98..aaffb07839 100644 --- a/src/Umbraco.Infrastructure/Migrations/Upgrade/UmbracoPlan.cs +++ b/src/Umbraco.Infrastructure/Migrations/Upgrade/UmbracoPlan.cs @@ -6,6 +6,7 @@ using Umbraco.Cms.Infrastructure.Migrations.Upgrade.Common; using Umbraco.Cms.Infrastructure.Migrations.Upgrade.V_10_0_0; using Umbraco.Cms.Infrastructure.Migrations.Upgrade.V_10_2_0; using Umbraco.Cms.Infrastructure.Migrations.Upgrade.V_10_5_0; +using Umbraco.Cms.Infrastructure.Migrations.Upgrade.V_10_7_0; using Umbraco.Cms.Infrastructure.Migrations.Upgrade.V_8_0_0; using Umbraco.Cms.Infrastructure.Migrations.Upgrade.V_8_0_1; using Umbraco.Cms.Infrastructure.Migrations.Upgrade.V_8_1_0; @@ -303,5 +304,8 @@ public class UmbracoPlan : MigrationPlan // to 10.5.0 To("{83AF7945-DADE-4A02-9041-F3F6EBFAC319}"); + + // to 10.7.0 + To("{EF93F398-1385-4F07-808A-D3C518984442}"); } } diff --git a/src/Umbraco.Infrastructure/Migrations/Upgrade/V_10_7_0/MigrateTagsFromNVarcharToNText.cs b/src/Umbraco.Infrastructure/Migrations/Upgrade/V_10_7_0/MigrateTagsFromNVarcharToNText.cs new file mode 100644 index 0000000000..462e3772fa --- /dev/null +++ b/src/Umbraco.Infrastructure/Migrations/Upgrade/V_10_7_0/MigrateTagsFromNVarcharToNText.cs @@ -0,0 +1,46 @@ +using NPoco; +using Umbraco.Cms.Core; +using Umbraco.Cms.Core.Models; +using Umbraco.Cms.Infrastructure.Persistence; +using Umbraco.Cms.Infrastructure.Persistence.Dtos; +using Umbraco.Extensions; + +namespace Umbraco.Cms.Infrastructure.Migrations.Upgrade.V_10_7_0; + +public class MigrateTagsFromNVarcharToNText : MigrationBase +{ + public MigrateTagsFromNVarcharToNText(IMigrationContext context) + : base(context) + { + } + + protected override void Migrate() + { + // Firstly change the storage type for the Umbraco.Tags property editor + Sql updateDbTypeForTagsQuery = Database.SqlContext.Sql() + .Update(x => x.Set(dt => dt.DbType, ValueStorageType.Ntext.ToString())) + .Where(dt => dt.EditorAlias == Constants.PropertyEditors.Aliases.Tags); + + Database.Execute(updateDbTypeForTagsQuery); + + // Then migrate the data from "varcharValue" column to "textValue" + Sql tagsDataTypeIdQuery = Database.SqlContext.Sql() + .Select(dt => dt.NodeId) + .From() + .Where(dt => dt.EditorAlias == Constants.PropertyEditors.Aliases.Tags); + + Sql tagsPropertyTypeIdQuery = Database.SqlContext.Sql() + .Select(pt => pt.Id) + .From() + .WhereIn(pt => pt.DataTypeId, tagsDataTypeIdQuery); + + Sql updatePropertyDataColumnsQuery = Database.SqlContext.Sql() + .Update() + .Append("SET textValue = varcharValue, varcharValue = null") + .WhereIn(pd => pd.PropertyTypeId, tagsPropertyTypeIdQuery) + .Where(pd => pd.TextValue == null) + .Where(pd => pd.VarcharValue != null); + + Database.Execute(updatePropertyDataColumnsQuery); + } +} diff --git a/src/Umbraco.Infrastructure/PropertyEditors/TagsPropertyEditor.cs b/src/Umbraco.Infrastructure/PropertyEditors/TagsPropertyEditor.cs index 6f82c8ab3c..99ae8f378a 100644 --- a/src/Umbraco.Infrastructure/PropertyEditors/TagsPropertyEditor.cs +++ b/src/Umbraco.Infrastructure/PropertyEditors/TagsPropertyEditor.cs @@ -25,7 +25,8 @@ namespace Umbraco.Cms.Core.PropertyEditors; "Tags", "tags", Icon = "icon-tags", - ValueEditorIsReusable = true)] + ValueEditorIsReusable = true, + ValueType = ValueTypes.Text)] public class TagsPropertyEditor : DataEditor { private readonly IEditorConfigurationParser _editorConfigurationParser; From 45083b673596f83d063d27f843af8ecd4a2fd6e6 Mon Sep 17 00:00:00 2001 From: Andreas Zerbst <73799582+andr317c@users.noreply.github.com> Date: Fri, 7 Jul 2023 14:49:08 +0200 Subject: [PATCH 03/13] Removed usage of sending umbracoApi to our testHelpers (#14526) * Cleaned up in Advanced * Cleaned up in Areas * Cleaned up in Content * Cleaned up in Rendering * Cleaned up in Settings * Updated the timeout to 40 seconds, 30 seconds is not always enough anymore. * Bumped version of testhelpers and builders --- .../package-lock.json | 18 ++-- .../Umbraco.Tests.AcceptanceTest/package.json | 4 +- .../playwright.config.ts | 10 +- .../Content/blockGridEditorAdvanced.spec.ts | 16 +-- .../blockGridEditorAreasContent.spec.ts | 98 +++++++++---------- .../Content/blockGridEditorContent.spec.ts | 54 +++++----- .../Content/blockGridEditorRendering.spec.ts | 60 ++++++------ .../Content/blockGridEditorSettings.spec.ts | 38 +++---- 8 files changed, 149 insertions(+), 149 deletions(-) diff --git a/tests/Umbraco.Tests.AcceptanceTest/package-lock.json b/tests/Umbraco.Tests.AcceptanceTest/package-lock.json index e4feabc9ae..3eca295aac 100644 --- a/tests/Umbraco.Tests.AcceptanceTest/package-lock.json +++ b/tests/Umbraco.Tests.AcceptanceTest/package-lock.json @@ -7,8 +7,8 @@ "name": "acceptancetest", "hasInstallScript": true, "dependencies": { - "@umbraco/json-models-builders": "^1.0.5", - "@umbraco/playwright-testhelpers": "^1.0.22", + "@umbraco/json-models-builders": "^1.0.6", + "@umbraco/playwright-testhelpers": "^1.0.24", "camelize": "^1.0.0", "dotenv": "^16.0.2", "faker": "^4.1.0", @@ -132,20 +132,20 @@ "dev": true }, "node_modules/@umbraco/json-models-builders": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/@umbraco/json-models-builders/-/json-models-builders-1.0.5.tgz", - "integrity": "sha512-14xowT8oiW9+DQVOoundRPvcvnNrU0Ey+06G/q/iZyUnqaNRu/i5nUqcbUZGdv6VBCdxaxq2H3WwtSET3gtneA==", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/@umbraco/json-models-builders/-/json-models-builders-1.0.6.tgz", + "integrity": "sha512-bXwfXcpuqG1Ye714L9KJEGXuSzJfckysE/6CuPjdG8FqHWTE1brv28teR2oMw+ih8ca2u2zUboRgdzLEU/1D3Q==", "dependencies": { "camelize": "^1.0.0", "faker": "^4.1.0" } }, "node_modules/@umbraco/playwright-testhelpers": { - "version": "1.0.22", - "resolved": "https://registry.npmjs.org/@umbraco/playwright-testhelpers/-/playwright-testhelpers-1.0.22.tgz", - "integrity": "sha512-hFqqQvEIylagfqFyhQ2rSyYlUP+xpWA5lkhJjkpb2qpxkIISxjwC/FYJTJGvcoBHuUaZrjsSv4lM2aJy2ZWHMA==", + "version": "1.0.24", + "resolved": "https://registry.npmjs.org/@umbraco/playwright-testhelpers/-/playwright-testhelpers-1.0.24.tgz", + "integrity": "sha512-xYOgcnyvcEywgC9DT4Q3OhQDTfdtF1zXLQIXdjNtwr6a4j3SUab1RI/tGxlF01fX+8Ttw3edlV4l+HIrY0hM1Q==", "dependencies": { - "@umbraco/json-models-builders": "^1.0.5", + "@umbraco/json-models-builders": "^1.0.6", "camelize": "^1.0.0", "faker": "^4.1.0", "form-data": "^4.0.0", diff --git a/tests/Umbraco.Tests.AcceptanceTest/package.json b/tests/Umbraco.Tests.AcceptanceTest/package.json index f651f799ae..e6e4c264ff 100644 --- a/tests/Umbraco.Tests.AcceptanceTest/package.json +++ b/tests/Umbraco.Tests.AcceptanceTest/package.json @@ -19,8 +19,8 @@ "wait-on": "^6.0.1" }, "dependencies": { - "@umbraco/json-models-builders": "^1.0.5", - "@umbraco/playwright-testhelpers": "^1.0.22", + "@umbraco/json-models-builders": "^1.0.6", + "@umbraco/playwright-testhelpers": "^1.0.24", "camelize": "^1.0.0", "faker": "^4.1.0", "form-data": "^4.0.0", diff --git a/tests/Umbraco.Tests.AcceptanceTest/playwright.config.ts b/tests/Umbraco.Tests.AcceptanceTest/playwright.config.ts index d084cd69ba..f3d94a05f7 100644 --- a/tests/Umbraco.Tests.AcceptanceTest/playwright.config.ts +++ b/tests/Umbraco.Tests.AcceptanceTest/playwright.config.ts @@ -10,7 +10,7 @@ dotenv.config(); const config: PlaywrightTestConfig = { testDir: './tests/', /* Maximum time one test can run for. */ - timeout: 30 * 1000, + timeout: 40 * 1000, expect: { /** * Maximum time expect() should wait for the condition to be met. @@ -27,18 +27,18 @@ const config: PlaywrightTestConfig = { /* Reporter to use. See https://playwright.dev/docs/test-reporters */ reporter: process.env.CI ? 'line' : 'html', outputDir : "./results", - + /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */ use: { /* Maximum time each action such as `click()` can take. Defaults to 0 (no limit). */ actionTimeout: 0, /* Base URL to use in actions like `await page.goto('/')`. */ // baseURL: 'http://localhost:44332', - + /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */ - // When working locally it can be a good idea to use trace: 'on-first-retry' instead of 'retain-on-failure', it can cut the local test times in half. + // When working locally it can be a good idea to use trace: 'on-first-retry' instead of 'retain-on-failure', it can cut the local test times in half. trace: 'retain-on-failure', - ignoreHTTPSErrors: true, + ignoreHTTPSErrors: true, }, /* Configure projects for major browsers */ diff --git a/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/BlockGridEditor/Content/blockGridEditorAdvanced.spec.ts b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/BlockGridEditor/Content/blockGridEditorAdvanced.spec.ts index 8db631019b..0e18826781 100644 --- a/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/BlockGridEditor/Content/blockGridEditorAdvanced.spec.ts +++ b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/BlockGridEditor/Content/blockGridEditorAdvanced.spec.ts @@ -72,7 +72,7 @@ test.describe('BlockGridEditorAdvancedContent', () => { .build(); const dataType = await umbracoApi.dataTypes.save(dataTypeBlockGrid); - await umbracoApi.documentTypes.createDefaultDocumentWithBlockGridEditor(umbracoApi, element, dataType); + await umbracoApi.documentTypes.createDefaultDocumentWithBlockGridEditor(element, dataType); const rootContentNode = new ContentBuilder() .withContentTypeAlias(documentAlias) @@ -134,7 +134,7 @@ test.describe('BlockGridEditorAdvancedContent', () => { .build(); const dataType = await umbracoApi.dataTypes.save(dataTypeBlockGrid); - await umbracoApi.content.createDefaultContentWithABlockGridEditor(umbracoApi, element, dataType, null); + await umbracoApi.content.createDefaultContentWithABlockGridEditor(element, dataType, null); await umbracoUi.navigateToContent(blockGridName); @@ -160,7 +160,7 @@ test.describe('BlockGridEditorAdvancedContent', () => { .build(); const dataType = await umbracoApi.dataTypes.save(dataTypeBlockGrid); - await umbracoApi.content.createDefaultContentWithABlockGridEditor(umbracoApi, element, dataType, null); + await umbracoApi.content.createDefaultContentWithABlockGridEditor(element, dataType, null); await umbracoUi.navigateToContent(blockGridName); @@ -186,7 +186,7 @@ test.describe('BlockGridEditorAdvancedContent', () => { .build(); const dataType = await umbracoApi.dataTypes.save(dataTypeBlockGrid); - await umbracoApi.content.createDefaultContentWithABlockGridEditor(umbracoApi, element, dataType, null); + await umbracoApi.content.createDefaultContentWithABlockGridEditor(element, dataType, null); await umbracoUi.navigateToContent(blockGridName); @@ -213,7 +213,7 @@ test.describe('BlockGridEditorAdvancedContent', () => { .build(); const dataType = await umbracoApi.dataTypes.save(dataTypeBlockGrid); - await umbracoApi.content.createDefaultContentWithABlockGridEditor(umbracoApi, element, dataType, null); + await umbracoApi.content.createDefaultContentWithABlockGridEditor(element, dataType, null); await umbracoUi.navigateToContent(blockGridName); @@ -250,7 +250,7 @@ test.describe('BlockGridEditorAdvancedContent', () => { .build(); const dataType = await umbracoApi.dataTypes.save(dataTypeBlockGrid); - await umbracoApi.content.createDefaultContentWithABlockGridEditor(umbracoApi, element, dataType, null); + await umbracoApi.content.createDefaultContentWithABlockGridEditor(element, dataType, null); await umbracoUi.navigateToContent(blockGridName); @@ -288,7 +288,7 @@ test.describe('BlockGridEditorAdvancedContent', () => { .build(); const dataType = await umbracoApi.dataTypes.save(dataTypeBlockGrid); - await umbracoApi.content.createDefaultContentWithABlockGridEditor(umbracoApi, element, dataType, null); + await umbracoApi.content.createDefaultContentWithABlockGridEditor(element, dataType, null); await umbracoUi.navigateToContent(blockGridName); @@ -336,7 +336,7 @@ test.describe('BlockGridEditorAdvancedContent', () => { .build(); const dataType = await umbracoApi.dataTypes.save(dataTypeBlockGrid); - await umbracoApi.content.createDefaultContentWithABlockGridEditor(umbracoApi, element, dataType, null); + await umbracoApi.content.createDefaultContentWithABlockGridEditor(element, dataType, null); await umbracoUi.navigateToContent(blockGridName); diff --git a/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/BlockGridEditor/Content/blockGridEditorAreasContent.spec.ts b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/BlockGridEditor/Content/blockGridEditorAreasContent.spec.ts index a55c12a7d9..7c5b407786 100644 --- a/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/BlockGridEditor/Content/blockGridEditorAreasContent.spec.ts +++ b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/BlockGridEditor/Content/blockGridEditorAreasContent.spec.ts @@ -6,26 +6,26 @@ import {expect} from "@playwright/test"; test.describe('BlockGridEditorAreasContent', () => { const documentName = 'DocumentTest'; const blockGridName = 'BlockGridTest'; - const elementTitleName = 'ElementTitle'; + const elementTitleName = 'ElementTitle'; const titleText = 'ElementTitle'; const titleArea = 'AreaTitle'; const elementBodyName = 'ElementBody'; const bodyText = 'Lorem ipsum dolor sit amet'; - + const elementBodyAlias = AliasHelper.toAlias(elementBodyName); const documentAlias = AliasHelper.toAlias(documentName); const blockGridAlias = AliasHelper.toAlias(blockGridName); const elementTitleAlias = AliasHelper.toAlias(elementTitleName); - - async function createContentWithABlockInAnotherBlock(umbracoApi,elementParent, elementChild, dataType?, document?) { + + async function createContentWithABlockInAnotherBlock(umbracoApi, elementParent, elementChild, dataType?, document?) { if (dataType == null) { - dataType = await umbracoApi.dataTypes.createBlockGridDataTypeWithArea(umbracoApi, elementParent, elementChild, blockGridName, titleArea); + dataType = await umbracoApi.dataTypes.createBlockGridDataTypeWithArea(elementParent, elementChild, blockGridName, titleArea); } if (document == null) { - await umbracoApi.documentTypes.createDefaultDocumentWithBlockGridEditor(umbracoApi, elementParent, dataType); + await umbracoApi.documentTypes.createDefaultDocumentWithBlockGridEditor(elementParent, dataType); } - + const rootContentNode = new ContentBuilder() .withContentTypeAlias(documentAlias) .withAction(ConstantHelper.actions.save) @@ -58,7 +58,7 @@ test.describe('BlockGridEditorAreasContent', () => { .build(); return await umbracoApi.content.save(rootContentNode); } - + test.beforeEach(async ({page, umbracoApi, umbracoUi}, testInfo) => { await umbracoApi.report.report(testInfo); await umbracoApi.login(); @@ -80,12 +80,12 @@ test.describe('BlockGridEditorAreasContent', () => { const element = await umbracoApi.documentTypes.createDefaultElementType(elementTitleName, elementTitleAlias); const elementBody = await umbracoApi.documentTypes.createDefaultElementType(elementBodyName, elementBodyAlias); - const dataType = await umbracoApi.dataTypes.createBlockGridDataTypeWithArea(umbracoApi, element, elementBody, blockGridName, titleArea); - - await umbracoApi.content.createDefaultContentWithABlockGridEditor(umbracoApi, element, dataType, null); + const dataType = await umbracoApi.dataTypes.createBlockGridDataTypeWithArea(element, elementBody, blockGridName, titleArea); + + await umbracoApi.content.createDefaultContentWithABlockGridEditor(element, dataType, null); await umbracoUi.navigateToContent(blockGridName); - + // Adds a body to the area await page.locator('[data-content-element-type-key="' + element['key'] + '"] >> [data-area-alias="' + titleArea + '"]').click(); await page.locator('[name="infiniteEditorForm"]').locator('[data-element="editor-container"]').getByRole('button', {name: elementBodyName}).click(); @@ -166,9 +166,9 @@ test.describe('BlockGridEditorAreasContent', () => { .done() .build(); const dataType = await umbracoApi.dataTypes.save(dataTypeBlockGrid); - + await createContentWithABlockInAnotherBlock(umbracoApi, element, elementBody, dataType); - + await umbracoUi.navigateToContent(blockGridName); // Adds another body to the area @@ -204,7 +204,7 @@ test.describe('BlockGridEditorAreasContent', () => { .build(); const dataType = await umbracoApi.dataTypes.save(dataTypeBlockGrid); - await umbracoApi.content.createDefaultContentWithABlockGridEditor(umbracoApi, element, dataType, null); + await umbracoApi.content.createDefaultContentWithABlockGridEditor(element, dataType, null); await umbracoUi.navigateToContent(blockGridName); @@ -212,12 +212,12 @@ test.describe('BlockGridEditorAreasContent', () => { // Checks if the area in content has the value that is defined in the block grid editor await expect(page.locator('[data-content-element-type-key="' + element['key'] + '"]').locator('[data-area-alias="' + titleArea + '"]')).toHaveAttribute('data-area-col-span', '6'); }); - + test('can add two different blocks in a area with different grid columns', async ({page, umbracoApi, umbracoUi}) => { const secondArea = 'AreaFour'; const columnSpanEight = "8"; const columnSpanFour = "4"; - + const element = await umbracoApi.documentTypes.createDefaultElementType(elementTitleName, elementTitleAlias); const elementBody = await umbracoApi.documentTypes.createDefaultElementType(elementBodyName, elementBodyAlias); @@ -239,8 +239,8 @@ test.describe('BlockGridEditorAreasContent', () => { .done() .build(); const dataType = await umbracoApi.dataTypes.save(dataTypeBlockGrid); - - await umbracoApi.documentTypes.createDefaultDocumentWithBlockGridEditor(umbracoApi, element, dataType); + + await umbracoApi.documentTypes.createDefaultDocumentWithBlockGridEditor(element, dataType); const rootContentNode = new ContentBuilder() .withContentTypeAlias(documentAlias) @@ -275,14 +275,14 @@ test.describe('BlockGridEditorAreasContent', () => { await umbracoApi.content.save(rootContentNode); await umbracoUi.navigateToContent(blockGridName); - + // Adds a block to the area with a different column span await page.locator('[data-content-element-type-key="' + element['key'] + '"]').locator('[data-area-alias="' + secondArea + '"]').getByRole('button', {name: 'Add content'}).click(); await page.locator('[name="infiniteEditorForm"]').locator('[data-element="editor-container"]').getByRole('button', {name: elementBodyName}).click(); await page.locator('[id="sub-view-0"]').locator('[id="title"]').fill('BodyTwoText'); await page.locator('[label="Create"]').click(); await umbracoUi.clickElement(umbracoUi.getButtonByLabelKey(ConstantHelper.buttons.saveAndPublish)); - + // Assert await umbracoUi.isSuccessNotificationVisible(); // Checks if there are two block in the ElementTitle Area @@ -311,14 +311,14 @@ test.describe('BlockGridEditorAreasContent', () => { .done() .build(); const dataType = await umbracoApi.dataTypes.save(dataTypeBlockGrid); - - await umbracoApi.content.createDefaultContentWithABlockGridEditor(umbracoApi, element, dataType, false); + + await umbracoApi.content.createDefaultContentWithABlockGridEditor(element, dataType, false); await umbracoUi.navigateToContent(blockGridName); // Checks if the button has the correct row span await expect(page.locator('[data-content-element-type-key="' + element['key'] + '"]').locator('[data-area-row-span="3"]').getByRole('button', {name: 'Add content'})).toBeVisible(); - + // Adds a block to the area await page.locator('[data-content-element-type-key="' + element['key'] + '"]').locator('[data-area-alias="' + titleArea + '"]').getByRole('button', {name: 'Add content'}).click(); await page.locator('[name="infiniteEditorForm"]').locator('[data-element="editor-container"]').getByRole('button', {name: elementBodyName}).click(); @@ -336,7 +336,7 @@ test.describe('BlockGridEditorAreasContent', () => { await expect(page.locator('[data-content-element-type-key="' + element['key'] + '"]').locator('[data-content-element-type-alias="' + elementBodyAlias + '"]')).toHaveAttribute('data-row-span', '3'); }); }); - + test.describe('Create Button Label', () => { test('can add a create button label for an area in block grid editor', async ({page, umbracoApi, umbracoUi}) => { const newButtonLabel = 'NewAreaBlock'; @@ -358,9 +358,9 @@ test.describe('BlockGridEditorAreasContent', () => { .done() .build(); const dataType = await umbracoApi.dataTypes.save(dataTypeBlockGrid); - - await umbracoApi.content.createDefaultContentWithABlockGridEditor(umbracoApi, element, dataType, false); - + + await umbracoApi.content.createDefaultContentWithABlockGridEditor( element, dataType, false); + await umbracoUi.navigateToContent(blockGridName); // Assert @@ -371,7 +371,7 @@ test.describe('BlockGridEditorAreasContent', () => { await createButtonLocator.click(); }); }); - + test.describe('Number of blocks', () => { test('can add a minimum number of blocks for a block grid editor', async ({page, umbracoApi, umbracoUi}) => { const element = await umbracoApi.documentTypes.createDefaultElementType(elementTitleName, elementTitleAlias); @@ -418,7 +418,7 @@ test.describe('BlockGridEditorAreasContent', () => { test('can add a maximum number of blocks for a block grid editor', async ({page, umbracoApi, umbracoUi}) => { const bodyTextTwo = 'AnotherBody'; - + const element = await umbracoApi.documentTypes.createDefaultElementType(elementTitleName, elementTitleAlias); const elementBody = await umbracoApi.documentTypes.createDefaultElementType(elementBodyName, elementBodyAlias); @@ -437,7 +437,7 @@ test.describe('BlockGridEditorAreasContent', () => { .build(); const dataType = await umbracoApi.dataTypes.save(dataTypeBlockGrid); - await umbracoApi.documentTypes.createDefaultDocumentWithBlockGridEditor(umbracoApi, element, dataType); + await umbracoApi.documentTypes.createDefaultDocumentWithBlockGridEditor(element, dataType); const rootContentNode = new ContentBuilder() .withContentTypeAlias(documentAlias) @@ -522,7 +522,7 @@ test.describe('BlockGridEditorAreasContent', () => { .build(); const dataType = await umbracoApi.dataTypes.save(dataTypeBlockGrid); - await umbracoApi.documentTypes.createDefaultDocumentWithBlockGridEditor(umbracoApi, element, dataType); + await umbracoApi.documentTypes.createDefaultDocumentWithBlockGridEditor(element, dataType); const rootContentNode = new ContentBuilder() .withContentTypeAlias(documentAlias) @@ -551,7 +551,7 @@ test.describe('BlockGridEditorAreasContent', () => { await umbracoApi.content.save(rootContentNode); await umbracoUi.navigateToContent(blockGridName); - + // Adds a ElementBody await page.locator('[data-content-element-type-key="' + element['key'] + '"]').locator('[data-area-alias="' + titleArea + '"]').click(); // Since the ElementBody is added as the only Specified Allowance for the area of the Element, then we should be instantly directed to it, instead of having to pick it. @@ -586,7 +586,7 @@ test.describe('BlockGridEditorAreasContent', () => { const dataType = await umbracoApi.dataTypes.save(dataTypeBlockGrid); await createContentWithABlockInAnotherBlock(umbracoApi, element, elementBody, dataType, null); - + await umbracoUi.navigateToContent(blockGridName); // Checks if a validation error is visible @@ -630,7 +630,7 @@ test.describe('BlockGridEditorAreasContent', () => { .build(); const dataType = await umbracoApi.dataTypes.save(dataTypeBlockGrid); - await umbracoApi.documentTypes.createDefaultDocumentWithBlockGridEditor(umbracoApi, element, dataType); + await umbracoApi.documentTypes.createDefaultDocumentWithBlockGridEditor(element, dataType); const rootContentNode = new ContentBuilder() .withContentTypeAlias(documentAlias) @@ -736,7 +736,7 @@ test.describe('BlockGridEditorAreasContent', () => { .build(); const dataType = await umbracoApi.dataTypes.save(dataTypeBlockGrid); - await umbracoApi.documentTypes.createDefaultDocumentWithBlockGridEditor(umbracoApi, element, dataType); + await umbracoApi.documentTypes.createDefaultDocumentWithBlockGridEditor( element, dataType); const rootContentNode = new ContentBuilder() .withContentTypeAlias(documentAlias) @@ -778,7 +778,7 @@ test.describe('BlockGridEditorAreasContent', () => { await umbracoApi.content.save(rootContentNode); await umbracoUi.navigateToContent(blockGridName); - + // Checks if there is validation error for both blocks await expect(page.locator('[key="blockEditor_areaValidationEntriesExceed"]', {hasText: elementBodyName})).toBeVisible(); await expect(page.locator('[key="blockEditor_areaValidationEntriesShort"]', {hasText: elementFooterName})).toBeVisible(); @@ -808,7 +808,7 @@ test.describe('BlockGridEditorAreasContent', () => { await expect(page.locator('[data-content-element-type-key="' + element['key'] + '"]').locator('[data-content-element-type-alias="' + elementBodyAlias + '"]')).toHaveCount(1); await expect(page.locator('[data-content-element-type-key="' + element['key'] + '"]').locator('[data-content-element-type-alias="' + elementFooterAlias + '"]')).toHaveCount(1); - // Clean + // Clean await umbracoApi.documentTypes.ensureNameNotExists(elementFooterName); }); }); @@ -818,9 +818,9 @@ test.describe('BlockGridEditorAreasContent', () => { const element = await umbracoApi.documentTypes.createDefaultElementType(elementTitleName, elementTitleAlias); const elementBody = await umbracoApi.documentTypes.createDefaultElementType(elementBodyName, elementBodyAlias); - const dataType = await umbracoApi.dataTypes.createBlockGridDataTypeWithArea(umbracoApi, element, elementBody, blockGridName, titleArea); + const dataType = await umbracoApi.dataTypes.createBlockGridDataTypeWithArea(element, elementBody, blockGridName, titleArea); - await umbracoApi.documentTypes.createDefaultDocumentWithBlockGridEditor(umbracoApi, element, dataType); + await umbracoApi.documentTypes.createDefaultDocumentWithBlockGridEditor(element, dataType); const rootContentNode = new ContentBuilder() .withContentTypeAlias(documentAlias) @@ -869,9 +869,9 @@ test.describe('BlockGridEditorAreasContent', () => { const element = await umbracoApi.documentTypes.createDefaultElementType(elementTitleName, elementTitleAlias); const elementBody = await umbracoApi.documentTypes.createDefaultElementType(elementBodyName, elementBodyAlias); - const dataType = await umbracoApi.dataTypes.createBlockGridDataTypeWithArea(umbracoApi, element, elementBody, blockGridName, titleArea); + const dataType = await umbracoApi.dataTypes.createBlockGridDataTypeWithArea(element, elementBody, blockGridName, titleArea); - await umbracoApi.documentTypes.createDefaultDocumentWithBlockGridEditor(umbracoApi, element, dataType); + await umbracoApi.documentTypes.createDefaultDocumentWithBlockGridEditor(element, dataType); const rootContentNode = new ContentBuilder() .withContentTypeAlias(documentAlias) @@ -935,9 +935,9 @@ test.describe('BlockGridEditorAreasContent', () => { const element = await umbracoApi.documentTypes.createDefaultElementType(elementTitleName, elementTitleAlias); const elementBody = await umbracoApi.documentTypes.createDefaultElementType(elementBodyName, elementBodyAlias); - const dataType = await umbracoApi.dataTypes.createBlockGridDataTypeWithArea(umbracoApi, element, elementBody, blockGridName, titleArea); + const dataType = await umbracoApi.dataTypes.createBlockGridDataTypeWithArea(element, elementBody, blockGridName, titleArea); - await umbracoApi.documentTypes.createDefaultDocumentWithBlockGridEditor(umbracoApi, element, dataType); + await umbracoApi.documentTypes.createDefaultDocumentWithBlockGridEditor(element, dataType); const rootContentNode = new ContentBuilder() .withContentTypeAlias(documentAlias) @@ -1002,9 +1002,9 @@ test.describe('BlockGridEditorAreasContent', () => { const element = await umbracoApi.documentTypes.createDefaultElementType(elementTitleName, elementTitleAlias); const elementBody = await umbracoApi.documentTypes.createDefaultElementType(elementBodyName, elementBodyAlias); - const dataType = await umbracoApi.dataTypes.createBlockGridDataTypeWithArea(umbracoApi, element, elementBody, blockGridName, titleArea); + const dataType = await umbracoApi.dataTypes.createBlockGridDataTypeWithArea(element, elementBody, blockGridName, titleArea); - await umbracoApi.documentTypes.createDefaultDocumentWithBlockGridEditor(umbracoApi, element, dataType); + await umbracoApi.documentTypes.createDefaultDocumentWithBlockGridEditor(element, dataType); const rootContentNode = new ContentBuilder() .withContentTypeAlias(documentAlias) @@ -1041,14 +1041,14 @@ test.describe('BlockGridEditorAreasContent', () => { const blockParentUdi = rootContentNode.variants[0].properties[0].value.contentData[1].udi; await umbracoUi.navigateToContent(blockGridName); - + // Copies and pastes the block into another block await page.locator('[data-element-udi="' + blockParentUdi + '"]').getByRole('button', {name: 'Copy'}).nth(1).click(); await page.locator('[data-element="property-' + blockGridAlias + '"]').getByRole('button', {name: 'Clipboard'}).click(); await page.locator('[data-element="editor-container"]').locator('umb-block-card', {hasText: elementTitleName}).click(); - + // Checks if the blocks were copied await expect(page.locator('[data-content-element-type-alias="' + elementTitleAlias + '"]')).toHaveCount(2); }); }); -}); \ No newline at end of file +}); diff --git a/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/BlockGridEditor/Content/blockGridEditorContent.spec.ts b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/BlockGridEditor/Content/blockGridEditorContent.spec.ts index 9eb4d75e92..9c610da191 100644 --- a/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/BlockGridEditor/Content/blockGridEditorContent.spec.ts +++ b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/BlockGridEditor/Content/blockGridEditorContent.spec.ts @@ -27,8 +27,8 @@ test.describe('BlockGridEditorContent', () => { }); test('can create content with a block grid editor', async ({page, umbracoApi, umbracoUi}) => { - await umbracoApi.documentTypes.createDefaultDocumentWithBlockGridEditor(umbracoApi, null, null); - + await umbracoApi.documentTypes.createDefaultDocumentWithBlockGridEditor(null, null); + const rootContentNode = new ContentBuilder() .withContentTypeAlias(documentAlias) .withAction(ConstantHelper.actions.save) @@ -58,11 +58,11 @@ test.describe('BlockGridEditorContent', () => { const newContentValue = 'UpdatedTitle'; const newSettingValue = 'UpdatedSetting'; - const element = await umbracoApi.content.createDefaultContentWithABlockGridEditor(umbracoApi, null, null, null); + const element = await umbracoApi.content.createDefaultContentWithABlockGridEditor(null, null, null); await umbracoUi.navigateToContent(blockGridName); - // Updates the already created content text + // Updates the already created content text await page.locator('[data-content-element-type-key="' + element['key'] + '"]', {hasText: elementName}).click(); await page.locator('[id="sub-view-0"]').locator('[id="title"]').fill(newContentValue); await umbracoUi.clickDataElementByElementName('sub-view-settings'); @@ -71,7 +71,7 @@ test.describe('BlockGridEditorContent', () => { await page.locator('[label="Submit"]').click(); await umbracoUi.clickElement(umbracoUi.getButtonByLabelKey(ConstantHelper.buttons.saveAndPublish)); - // Assert + // Assert await umbracoUi.isSuccessNotificationVisible(); // Checks if the Content and Setting were updated after it was saved await page.locator('[data-content-element-type-key="' + element['key'] + '"]', {hasText: elementName}).click(); @@ -81,13 +81,13 @@ test.describe('BlockGridEditorContent', () => { }); test('can delete a block grid editor in content', async ({page, umbracoApi, umbracoUi}) => { - const element = await umbracoApi.content.createDefaultContentWithABlockGridEditor(umbracoApi, null, null, null); + const element = await umbracoApi.content.createDefaultContentWithABlockGridEditor(null, null, null); await umbracoUi.navigateToContent(blockGridName); // Deletes the block grid editor inside of the content await page.getByTitle("Delete").click(); - + // Can't use our constant helper because the action for delete does not contain an s. The correct way is 'action-delete' await umbracoUi.clickElement(umbracoUi.getButtonByLabelKey('actions_delete')); @@ -101,7 +101,7 @@ test.describe('BlockGridEditorContent', () => { }); test('can copy block grid content and paste it', async ({page, umbracoApi, umbracoUi}) => { - await umbracoApi.content.createDefaultContentWithABlockGridEditor(umbracoApi, null, null, null); + await umbracoApi.content.createDefaultContentWithABlockGridEditor(null, null, null); await umbracoUi.navigateToContent(blockGridName); // Checks to make sure that there is only one item @@ -134,7 +134,7 @@ test.describe('BlockGridEditorContent', () => { const element = await umbracoApi.documentTypes.createDefaultElementType(elementName, elementAlias); - const dataType = await umbracoApi.dataTypes.createDefaultBlockGrid(umbracoApi, blockGridName, element); + const dataType = await umbracoApi.dataTypes.createDefaultBlockGrid(blockGridName, element); const docType = new DocumentTypeBuilder() .withName(documentName) @@ -157,7 +157,7 @@ test.describe('BlockGridEditorContent', () => { .build(); await umbracoApi.documentTypes.save(docType); - await umbracoApi.content.createDefaultContentWithABlockGridEditor(umbracoApi, element, dataType, true); + await umbracoApi.content.createDefaultContentWithABlockGridEditor(element, dataType, true); await umbracoUi.navigateToContent(blockGridName); @@ -192,9 +192,9 @@ test.describe('BlockGridEditorContent', () => { const element = await umbracoApi.documentTypes.createDefaultElementType(elementName, elementAlias); // We give the dataType a label so we can differentiate between the top and bottom block in the content editor. - const dataType = await umbracoApi.dataTypes.createDefaultBlockGrid(umbracoApi, blockGridName, element, '{{' + element.groups[0].properties[0].alias + '}}'); + const dataType = await umbracoApi.dataTypes.createDefaultBlockGrid(blockGridName, element, '{{' + element.groups[0].properties[0].alias + '}}'); - await umbracoApi.documentTypes.createDefaultDocumentWithBlockGridEditor(umbracoApi, element, dataType); + await umbracoApi.documentTypes.createDefaultDocumentWithBlockGridEditor(element, dataType); const rootContentNode = new ContentBuilder() .withContentTypeAlias(documentAlias) @@ -226,7 +226,7 @@ test.describe('BlockGridEditorContent', () => { await umbracoApi.content.save(rootContentNode); await umbracoUi.navigateToContent(blockGridName); - + // Drag and Drop const dragFromLocator = await page.locator('[data-content-element-type-key="' + element['key'] + '"]', {hasText: bottomBlock}); const dragToLocator = await page.locator('[data-content-element-type-key="' + element['key'] + '"]', {hasText: topBlock}); @@ -253,7 +253,7 @@ test.describe('BlockGridEditorContent', () => { .build(); const dataType = await umbracoApi.dataTypes.save(dataTypeBlockGrid); - await umbracoApi.documentTypes.createDefaultDocumentWithBlockGridEditor(umbracoApi, element, dataType); + await umbracoApi.documentTypes.createDefaultDocumentWithBlockGridEditor(element, dataType); const rootContentNode = new ContentBuilder() .withContentTypeAlias(documentAlias) @@ -319,7 +319,7 @@ test.describe('BlockGridEditorContent', () => { await umbracoApi.media.createDefaultImage(imageName); - await umbracoApi.documentTypes.createDefaultDocumentWithBlockGridEditor(umbracoApi, element, null); + await umbracoApi.documentTypes.createDefaultDocumentWithBlockGridEditor(element, null); const rootContentNode = new ContentBuilder() .withContentTypeAlias(documentAlias) @@ -374,7 +374,7 @@ test.describe('BlockGridEditorContent', () => { .build(); const dataType = await umbracoApi.dataTypes.save(dataTypeBlockGrid); - await umbracoApi.content.createDefaultContentWithABlockGridEditor(umbracoApi, element, dataType, false); + await umbracoApi.content.createDefaultContentWithABlockGridEditor(element, dataType, false); await umbracoUi.navigateToContent(blockGridName); // Checks if there is validation for needing 2 entries or more @@ -408,7 +408,7 @@ test.describe('BlockGridEditorContent', () => { .build(); const dataType = await umbracoApi.dataTypes.save(dataTypeBlockGrid); - await umbracoApi.documentTypes.createDefaultDocumentWithBlockGridEditor(umbracoApi, element, dataType); + await umbracoApi.documentTypes.createDefaultDocumentWithBlockGridEditor(element, dataType); const rootContentNode = new ContentBuilder() .withContentTypeAlias(documentAlias) @@ -470,7 +470,7 @@ test.describe('BlockGridEditorContent', () => { test.describe('Live editing mode', () => { test('can use live editing mode in content with a block grid editor', async ({page, umbracoApi, umbracoUi}) => { const newText = 'LiveUpdatedContent'; - + const element = await umbracoApi.documentTypes.createDefaultElementType(elementName, elementAlias); const dataTypeBlockGrid = new BlockGridDataTypeBuilder() @@ -485,17 +485,17 @@ test.describe('BlockGridEditorContent', () => { .build(); const dataType = await umbracoApi.dataTypes.save(dataTypeBlockGrid); - await umbracoApi.content.createDefaultContentWithABlockGridEditor(umbracoApi, element, dataType, false); + await umbracoApi.content.createDefaultContentWithABlockGridEditor(element, dataType, false); await umbracoUi.navigateToContent(blockGridName); // Checks if the block contains the correct text before being edited await expect(page.locator('[data-content-element-type-alias="'+elementAlias +'"]')).toContainText('aliasTest'); - + // Updates the text without saving the changes. await page.locator('[data-content-element-type-key="' + element['key'] + '"]').click(); await page.locator('[id="sub-view-0"]').locator('[id="title"]').fill(newText); - + // Checks if the block is being live updated as the content is being updated. await expect(page.locator('[data-content-element-type-alias="'+elementAlias +'"]')).toContainText(newText); }); @@ -515,7 +515,7 @@ test.describe('BlockGridEditorContent', () => { .build(); const dataType = await umbracoApi.dataTypes.save(dataTypeBlockGrid); - await umbracoApi.content.createDefaultContentWithABlockGridEditor(umbracoApi, element, dataType, false); + await umbracoApi.content.createDefaultContentWithABlockGridEditor(element, dataType, false); await umbracoUi.navigateToContent(blockGridName); @@ -540,7 +540,7 @@ test.describe('BlockGridEditorContent', () => { .build(); const dataType = await umbracoApi.dataTypes.save(dataTypeBlockGrid); - await umbracoApi.content.createDefaultContentWithABlockGridEditor(umbracoApi, element, dataType, false); + await umbracoApi.content.createDefaultContentWithABlockGridEditor(element, dataType, false); await umbracoUi.navigateToContent(blockGridName); @@ -571,8 +571,8 @@ test.describe('BlockGridEditorContent', () => { .withLayoutStylesheet(stylesheetDataPath) .build(); const dataType = await umbracoApi.dataTypes.save(dataTypeBlockGrid); - - await umbracoApi.content.createDefaultContentWithABlockGridEditor(umbracoApi, element, dataType, null); + + await umbracoApi.content.createDefaultContentWithABlockGridEditor(element, dataType, null); await umbracoUi.navigateToContent(blockGridName); @@ -600,7 +600,7 @@ test.describe('BlockGridEditorContent', () => { .build(); const dataType = await umbracoApi.dataTypes.save(dataTypeBlockGrid); - await umbracoApi.content.createDefaultContentWithABlockGridEditor(umbracoApi, element, dataType, false); + await umbracoApi.content.createDefaultContentWithABlockGridEditor(element, dataType, false); // Goes to the created Content await umbracoUi.goToSection(ConstantHelper.sections.content); @@ -614,4 +614,4 @@ test.describe('BlockGridEditorContent', () => { await page.locator('[data-element="property-' + blockGridAlias + '"] >> .umb-block-grid__actions', {hasText: newButtonLabel}).click(); }); }); -}); \ No newline at end of file +}); diff --git a/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/BlockGridEditor/Content/blockGridEditorRendering.spec.ts b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/BlockGridEditor/Content/blockGridEditorRendering.spec.ts index d95d39ccaa..0d8bdd58ac 100644 --- a/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/BlockGridEditor/Content/blockGridEditorRendering.spec.ts +++ b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/BlockGridEditor/Content/blockGridEditorRendering.spec.ts @@ -9,14 +9,14 @@ test.describe('BlockGridEditorRending', () => { const blockGridName = 'BlockGridTest'; const elementTitleName = 'ElementTitle'; const contentText = "ContentTest"; - + const documentAlias = 'documentTest'; const blockGridAlias = 'blockGridTest'; const elementTitleAlias = "elementTitle"; const elementTitleLabel = 'Title'; const elementTitleLabelAlias = AliasHelper.toAlias(elementTitleLabel); - + test.beforeEach(async ({page, umbracoApi, umbracoUi}, testInfo) => { await umbracoApi.report.report(testInfo); await umbracoApi.login(); @@ -51,7 +51,7 @@ test.describe('BlockGridEditorRending', () => { .build(); return await umbracoApi.documentTypes.save(element); } - + async function createDocumentWithTemplateAndDataType(umbracoApi, dataType){ const docType = new DocumentTypeBuilder() .withName(documentName) @@ -69,14 +69,14 @@ test.describe('BlockGridEditorRending', () => { .build(); return await umbracoApi.documentTypes.save(docType); } - + async function editDefaultTemplate(umbracoApi){ await umbracoApi.templates.edit(documentName, '@using Umbraco.Cms.Web.Common.PublishedModels;\n' + '@inherits Umbraco.Cms.Web.Common.Views.UmbracoViewPage\n' + '@using ContentModels = Umbraco.Cms.Web.Common.PublishedModels;' + '\n' + '@await Html.GetBlockGridHtmlAsync(Model.' + blockGridName + ')'); } - + async function createPartialViewWithArea(umbracoApi, elementAlias, elementLabelAlias){ const partialViewElementTitle = new PartialViewBuilder() .withName(elementAlias) @@ -91,7 +91,7 @@ test.describe('BlockGridEditorRending', () => { partialViewElementTitle.virtualPath = "/Views/Partials/blockgrid/Components/"; return await umbracoApi.partialViews.save(partialViewElementTitle); } - + async function createPartialViewWithBlock(umbracoApi,elementAlias, elementLabelAlias){ const partialViewElementBody = new PartialViewBuilder() .withName(elementAlias) @@ -105,11 +105,11 @@ test.describe('BlockGridEditorRending', () => { partialViewElementBody.virtualPath = "/Views/Partials/blockgrid/Components/"; await umbracoApi.partialViews.save(partialViewElementBody); } - + test('can render content with a block grid editor', async ({page, umbracoApi, umbracoUi}) => { const element = await createElementWithRTE(umbracoApi, elementTitleName, elementTitleAlias, elementTitleLabel, elementTitleLabelAlias); - const dataType = await umbracoApi.dataTypes.createDefaultBlockGrid(umbracoApi, blockGridName, element); + const dataType = await umbracoApi.dataTypes.createDefaultBlockGrid(blockGridName, element); await createDocumentWithTemplateAndDataType(umbracoApi, dataType); @@ -140,7 +140,7 @@ test.describe('BlockGridEditorRending', () => { .withTemplateAlias(documentName) .build(); await umbracoApi.content.save(rootContentNode); - + // Assert await page.goto(umbracoConfig.environment.baseUrl); await expect(page).toHaveScreenshot('Block-grid-editor.png'); @@ -158,7 +158,7 @@ test.describe('BlockGridEditorRending', () => { const element = await createElementWithRTE(umbracoApi, elementTitleName, elementTitleAlias, elementTitleLabel, elementTitleLabelAlias); const elementBody = await createElementWithRTE(umbracoApi, elementBodyName, elementBodyAlias, elementBodyLabel, elementBodyLabelAlias); - + const dataTypeBlockGrid = new BlockGridDataTypeBuilder() .withName(blockGridName) .addBlock() @@ -179,7 +179,7 @@ test.describe('BlockGridEditorRending', () => { // Creates partial view for the ElementBody await createPartialViewWithBlock(umbracoApi, elementBodyAlias, elementBodyLabelAlias); - + const rootContentNode = new ContentBuilder() .withContentTypeAlias(documentAlias) .withAction(ConstantHelper.actions.publish) @@ -210,12 +210,12 @@ test.describe('BlockGridEditorRending', () => { .withTemplateAlias(documentName) .build(); await umbracoApi.content.save(rootContentNode); - + // Assert await page.goto(umbracoConfig.environment.baseUrl); await expect(page).toHaveScreenshot('Block-grid-editor-with-two-elements.png'); - // Clean + // Clean await umbracoApi.documentTypes.ensureNameNotExists(elementBodyName); await umbracoApi.partialViews.ensureNameNotExists('blockgrid/Components', elementBodyAlias + '.cshtml'); }); @@ -257,7 +257,7 @@ test.describe('BlockGridEditorRending', () => { // Creates partial view for the ElementBody await createPartialViewWithBlock(umbracoApi, elementBodyAlias, elementBodyLabelAlias); - + const rootContentNode = new ContentBuilder() .withContentTypeAlias(documentAlias) .withAction(ConstantHelper.actions.publish) @@ -291,12 +291,12 @@ test.describe('BlockGridEditorRending', () => { .withTemplateAlias(documentName) .build(); await umbracoApi.content.save(rootContentNode); - + // Assert await page.goto(umbracoConfig.environment.baseUrl); await expect(page).toHaveScreenshot('Block-grid-editor-with-area.png'); - - // Clean + + // Clean await umbracoApi.documentTypes.ensureNameNotExists(elementBodyName); await umbracoApi.partialViews.ensureNameNotExists('blockgrid/Components', elementBodyAlias + '.cshtml'); }) @@ -392,7 +392,7 @@ test.describe('BlockGridEditorRending', () => { .withTemplateAlias(documentName) .build(); await umbracoApi.content.save(rootContentNode); - + // Assert await page.goto(umbracoConfig.environment.baseUrl); await expect(page).toHaveScreenshot('Block-grid-editor-with-multiple-areas.png'); @@ -433,7 +433,7 @@ test.describe('BlockGridEditorRending', () => { .done() .done() .addBlock() - .withContentElementTypeKey(elementBody['key']) + .withContentElementTypeKey(elementBody['key']) .addArea() .withAlias('bodyArea') .done() @@ -551,7 +551,7 @@ test.describe('BlockGridEditorRending', () => { .build(); partialViewElement.virtualPath = "/Views/Partials/blockgrid/Components/"; await umbracoApi.partialViews.save(partialViewElement); - + const rootContentNode = new ContentBuilder() .withContentTypeAlias(documentAlias) .withAction(ConstantHelper.actions.publish) @@ -595,7 +595,7 @@ test.describe('BlockGridEditorRending', () => { // ElementBody const elementBodyName = "ElementBody"; const elementBodyAlias = AliasHelper.toAlias(elementBodyName); - + await umbracoApi.documentTypes.ensureNameNotExists(elementBodyName); await umbracoApi.media.ensureNameNotExists(stylesheetTitleName); await umbracoApi.media.ensureNameNotExists(stylesheetBodyName); @@ -695,7 +695,7 @@ test.describe('BlockGridEditorRending', () => { // Assert await page.goto(umbracoConfig.environment.baseUrl); await expect(page).toHaveScreenshot('Block-grid-editor-with-two-custom-stylesheets.png'); - + // Clean await umbracoApi.documentTypes.ensureNameNotExists(elementBodyName); await umbracoApi.media.ensureNameNotExists(stylesheetTitleName); @@ -703,7 +703,7 @@ test.describe('BlockGridEditorRending', () => { await umbracoApi.partialViews.ensureNameNotExists('blockgrid/Components', elementBodyAlias + '.cshtml'); }); }); - + test.describe('Image', () => { test('can render a block grid with an image', async ({page, umbracoApi, umbracoUi}) => { // Image @@ -714,9 +714,9 @@ test.describe('BlockGridEditorRending', () => { const imageMimeType = "image/png"; await umbracoApi.media.ensureNameNotExists(imageName); - + const imageData = await umbracoApi.media.createImageWithFile(imageName, umbracoFileValue, imageFileName, imagePath, imageMimeType); - + const element = new DocumentTypeBuilder() .withName(elementTitleName) .withAlias(elementTitleAlias) @@ -756,7 +756,7 @@ test.describe('BlockGridEditorRending', () => { .build(); partialViewImage.virtualPath = "/Views/Partials/blockgrid/Components/"; await umbracoApi.partialViews.save(partialViewImage); - + const rootContentNode = new ContentBuilder() .withContentTypeAlias(documentAlias) .withAction(ConstantHelper.actions.publish) @@ -771,7 +771,7 @@ test.describe('BlockGridEditorRending', () => { .addImage() .withMediaKey(imageData.key) .done() - .done() + .done() .addLayout() .withContentUdi(element['key']) .done() @@ -780,12 +780,12 @@ test.describe('BlockGridEditorRending', () => { .done() .build(); await umbracoApi.content.save(rootContentNode); - + // Assert await page.goto(umbracoConfig.environment.baseUrl); await expect(page).toHaveScreenshot('Block-grid-editor-with-image.png'); - - // Clean + + // Clean await umbracoApi.media.ensureNameNotExists(imageName); }); }); diff --git a/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/BlockGridEditor/Content/blockGridEditorSettings.spec.ts b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/BlockGridEditor/Content/blockGridEditorSettings.spec.ts index 358a979a43..0f5773ba04 100644 --- a/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/BlockGridEditor/Content/blockGridEditorSettings.spec.ts +++ b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/BlockGridEditor/Content/blockGridEditorSettings.spec.ts @@ -29,7 +29,7 @@ test.describe('BlockGridEditorSettings', () => { test.describe('General', () => { test('can see label in content for a block grid editor', async ({page, umbracoApi, umbracoUi}) => { const newLabel = "New Label"; - + const element = await umbracoApi.documentTypes.createDefaultElementType(elementName, elementAlias); const dataTypeBlockGrid = new BlockGridDataTypeBuilder() @@ -41,14 +41,14 @@ test.describe('BlockGridEditorSettings', () => { .build(); const dataType = await umbracoApi.dataTypes.save(dataTypeBlockGrid); - await umbracoApi.content.createDefaultContentWithABlockGridEditor(umbracoApi, element, dataType, null); + await umbracoApi.content.createDefaultContentWithABlockGridEditor(element, dataType, null); await umbracoUi.navigateToContent(blockGridName); - + // Assert // Checks if the element contains the correct label await expect(page.locator('[data-content-element-type-alias="' + elementAlias + '"]')).toContainText(newLabel); - // Checks if the element is clickable + // Checks if the element is clickable await page.locator('[data-content-element-type-alias="' + elementAlias + '"]').click(); }); }); @@ -65,9 +65,9 @@ test.describe('BlockGridEditorSettings', () => { .done() .build(); const dataType = await umbracoApi.dataTypes.save(dataTypeBlockGrid); - - await umbracoApi.documentTypes.createDefaultDocumentWithBlockGridEditor(umbracoApi, element, dataType); - + + await umbracoApi.documentTypes.createDefaultDocumentWithBlockGridEditor(element, dataType); + const rootContentNode = new ContentBuilder() .withContentTypeAlias(documentAlias) .withAction(ConstantHelper.actions.save) @@ -77,21 +77,21 @@ test.describe('BlockGridEditorSettings', () => { .done() .build(); await umbracoApi.content.save(rootContentNode); - + await umbracoUi.navigateToContent(blockGridName); - + // Checks if adding a block is disabled await expect(page.locator('[data-element="property-'+blockGridAlias+'"]').locator('umb-block-grid-root').locator('[disabled="disabled"]')).toBeDisabled(); // Checks if the button is not clickable await expect(page.locator('[data-element="property-' + blockGridAlias + '"]').locator('[key="blockEditor_addBlock"]')).not.toBeEnabled(); }); - + test('can set allow in areas to false for an element in a block grid editor', async ({page, umbracoApi, umbracoUi}) => { const elementBodyName = 'BodyElement'; const elementBodyAlias = AliasHelper.toAlias(elementBodyName); - + await umbracoApi.documentTypes.ensureNameNotExists(elementBodyName); - + const element = await umbracoApi.documentTypes.createDefaultElementType(elementName, elementAlias); const elementBody = await umbracoApi.documentTypes.createDefaultElementType(elementBodyName, elementBodyAlias); @@ -110,14 +110,14 @@ test.describe('BlockGridEditorSettings', () => { .build(); const dataType = await umbracoApi.dataTypes.save(dataTypeBlockGrid); - await umbracoApi.content.createDefaultContentWithABlockGridEditor(umbracoApi,element,dataType,false); + await umbracoApi.content.createDefaultContentWithABlockGridEditor(element, dataType, false); await umbracoUi.navigateToContent(blockGridName); - + // Assert // Checks if the elementTitle is the only element selectable to be in a area await expect(page.locator('[data-area-alias="titleArea"]').locator('[key="blockEditor_addThis"]')).toContainText('Add ' + elementName); - + // Clean await umbracoApi.documentTypes.ensureNameNotExists(elementBodyName); }); @@ -136,20 +136,20 @@ test.describe('BlockGridEditorSettings', () => { .build(); const dataType = await umbracoApi.dataTypes.save(dataTypeBlockGrid); - await umbracoApi.content.createDefaultContentWithABlockGridEditor(umbracoApi, element, dataType, null); + await umbracoApi.content.createDefaultContentWithABlockGridEditor(element, dataType, null); await umbracoUi.navigateToContent(blockGridName); - + // Drags the blocks from a columnSpan of 12 to 6 const dragFrom = await page.locator('[data-content-element-type-key="' + element['key'] + '"]', {hasText: elementName}).locator('[title="Drag to scale"]'); const dragTo = await page.locator('[data-content-element-type-key="' + element['key'] + '"]', {hasText: elementName}); await umbracoUi.dragAndDrop(dragFrom,dragTo, 0, 0 ,10); await umbracoUi.clickElement(umbracoUi.getButtonByLabelKey(ConstantHelper.buttons.saveAndPublish)); - // Assert + // Assert await umbracoUi.isSuccessNotificationVisible(); // Checks if the block is resized to a column span of 6 await expect(page.locator('[data-content-element-type-key="' + element['key'] + '"], [data-col-span="6"]', {hasText: elementName})).toBeVisible(); }); }); -}); \ No newline at end of file +}); From 313fdf79fecf4f53977463fc83bc9b46fc113f10 Mon Sep 17 00:00:00 2001 From: Andreas Zerbst <73799582+andr317c@users.noreply.github.com> Date: Mon, 10 Jul 2023 10:38:43 +0200 Subject: [PATCH 04/13] Added test for checking if settings model contains default value (#14513) * Added test for checking if a settings model contains default value. Fixed tests * Bumped version * Moved createSliderWithDefaultValue function to our testHelpers. Removed the use of count in test since there was only one --- .../blockListEditorContent.spec.ts | 248 ++++++++++++------ 1 file changed, 172 insertions(+), 76 deletions(-) diff --git a/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/BlockListEditor/blockListEditorContent.spec.ts b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/BlockListEditor/blockListEditorContent.spec.ts index 8dcadef04d..0c99d46ab5 100644 --- a/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/BlockListEditor/blockListEditorContent.spec.ts +++ b/tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/BlockListEditor/blockListEditorContent.spec.ts @@ -6,24 +6,26 @@ import {BlockListDataTypeBuilder} from "@umbraco/json-models-builders/dist/lib/b test.describe('BlockListEditorContent', () => { const documentName = 'DocumentTestName'; const blockListName = 'BlockListTest'; - const elementName = 'TestElement'; + const contentElementName = 'ContentElement'; + const settingElementName = 'SettingsElement'; const documentAlias = AliasHelper.toAlias(documentName); const blockListAlias = AliasHelper.toAlias(blockListName); - // Won't work if I use the to alias for the elementAlias - const elementAlias = 'testElement'; - + // Won't work if we use the to alias for the elementAliases + const contentElementAlias = 'contentElement'; + const settingsElementAlias = 'settingsElement'; + test.beforeEach(async ({page, umbracoApi, umbracoUi}, testInfo) => { await umbracoApi.report.report(testInfo); await umbracoApi.login(); await umbracoApi.documentTypes.ensureNameNotExists(documentName); - await umbracoApi.documentTypes.ensureNameNotExists(elementName); + await umbracoApi.documentTypes.ensureNameNotExists(contentElementName); await umbracoApi.dataTypes.ensureNameNotExists(blockListName); }); - + test.afterEach(async ({page, umbracoApi, umbracoUi}) => { await umbracoApi.documentTypes.ensureNameNotExists(documentName); - await umbracoApi.documentTypes.ensureNameNotExists(elementName); + await umbracoApi.documentTypes.ensureNameNotExists(contentElementName); await umbracoApi.dataTypes.ensureNameNotExists(blockListName); }); @@ -31,23 +33,22 @@ test.describe('BlockListEditorContent', () => { const dataTypeBlockList = new BlockListDataTypeBuilder() .withName(blockListName) .addBlock() - .withContentElementTypeKey(element['key']) - .withSettingsElementTypeKey(element['key']) + .withContentElementTypeKey(element['key']) + .withSettingsElementTypeKey(element['key']) .done() .build(); return await umbracoApi.dataTypes.save(dataTypeBlockList); } - - async function createDocumentWithOneBlockListEditor(umbracoApi, element, dataType){ - + + async function createDocumentWithOneBlockListEditor(umbracoApi, element, dataType, elementName?, elementAlias?){ if(element == null) { element = await umbracoApi.documentTypes.createDefaultElementType(elementName, elementAlias); } - + if(dataType == null) { dataType = await createDefaultBlockList(umbracoApi, blockListName, element); } - + const docType = new DocumentTypeBuilder() .withName(documentName) .withAlias(documentAlias) @@ -61,16 +62,15 @@ test.describe('BlockListEditorContent', () => { .done() .build(); await umbracoApi.documentTypes.save(docType); - + return element; } - - async function createContentWithOneBlockListEditor(umbracoApi, element) { - + + async function createContentWithOneBlockListEditor(umbracoApi, element, datatype?, elementName?, elementAlias?) { if(element == null) { - element = await createDocumentWithOneBlockListEditor(umbracoApi, null, null); + element = await createDocumentWithOneBlockListEditor(umbracoApi, null, datatype, elementName, elementAlias); } - + const rootContentNode = new ContentBuilder() .withContentTypeAlias(documentAlias) .withAction(ConstantHelper.actions.save) @@ -89,13 +89,35 @@ test.describe('BlockListEditorContent', () => { .done() .build(); await umbracoApi.content.save(rootContentNode); - + return element; } + async function createElementWithSlider(umbracoApi, name, alias, sliderId, sliderName?, sliderDefaultValue?) { + if (sliderId == null) { + const sliderData = await umbracoApi.dataTypes.createSliderWithDefaultValue(sliderName, sliderDefaultValue); + sliderId = sliderData.id; + } + + const contentElement = new DocumentTypeBuilder() + .withName(name) + .withAlias(alias) + .AsElementType() + .addGroup() + .withName('Content') + .withAlias('content') + .addCustomProperty(sliderId) + .withLabel('Slider') + .withAlias('slider') + .done() + .done() + .build(); + return await umbracoApi.documentTypes.save(contentElement); + } + test('can create content with a block list editor', async ({page, umbracoApi, umbracoUi}) => { - await createDocumentWithOneBlockListEditor(umbracoApi, null, null); - + await createDocumentWithOneBlockListEditor(umbracoApi, null, null, contentElementName, contentElementAlias); + const rootContentNode = new ContentBuilder() .withContentTypeAlias(documentAlias) .withAction(ConstantHelper.actions.save) @@ -113,7 +135,7 @@ test.describe('BlockListEditorContent', () => { await umbracoUi.clickDataElementByElementName('tree-item-' + blockListName); // Adds TestElement - await page.locator('[key="blockEditor_addThis"]', {hasText: elementName}).click(); + await page.locator('[key="blockEditor_addThis"]', {hasText: contentElementName}).click(); await page.locator('[id="sub-view-0"]').locator('[id="title"]').fill('Testing...'); await page.locator('[label="Create"]').click(); @@ -121,17 +143,17 @@ test.describe('BlockListEditorContent', () => { // Assert await umbracoUi.isSuccessNotificationVisible(); - + // Checks if the content was created await expect(page.locator('.umb-block-list__block--view')).toHaveCount(1); - await expect(page.locator('.umb-block-list__block--view').nth(0)).toHaveText(elementName); + await expect(page.locator('.umb-block-list__block--view')).toHaveText(contentElementName); // Checks if the content contains the correct value - await page.locator('.umb-block-list__block--view').nth(0).click(); + await page.locator('.umb-block-list__block--view', {hasText: contentElementName}).click(); await expect(page.locator('[id="sub-view-0"]').locator('[id="title"]')).toHaveValue('Testing...'); }); test('can update content with a block list editor', async ({page, umbracoApi, umbracoUi}) => { - await createContentWithOneBlockListEditor(umbracoApi, null); + await createContentWithOneBlockListEditor(umbracoApi, null, null, contentElementName, contentElementAlias); await umbracoUi.goToSection(ConstantHelper.sections.content); await umbracoUi.refreshContentTree(); @@ -154,7 +176,7 @@ test.describe('BlockListEditorContent', () => { }); test('can delete a block list editor in content', async ({page, umbracoApi, umbracoUi}) => { - await createContentWithOneBlockListEditor(umbracoApi, null); + await createContentWithOneBlockListEditor(umbracoApi, null, null, contentElementName, contentElementAlias); await umbracoUi.goToSection(ConstantHelper.sections.content); await umbracoUi.refreshContentTree(); @@ -172,13 +194,13 @@ test.describe('BlockListEditorContent', () => { // Assert await umbracoUi.isSuccessNotificationVisible(); - + // Checks if the content is actually deleted await expect(page.locator('[ui-sortable="vm.sortableOptions"]').nth(0)).not.toBeVisible(); }); test('can copy block list content and paste it', async ({page, umbracoApi, umbracoUi}) => { - await createContentWithOneBlockListEditor(umbracoApi, null); + await createContentWithOneBlockListEditor(umbracoApi, null, null, contentElementName, contentElementAlias); await umbracoUi.goToSection(ConstantHelper.sections.content); await umbracoUi.refreshContentTree(); @@ -194,7 +216,7 @@ test.describe('BlockListEditorContent', () => { await expect(page.locator('.alert-success', {hasText: 'Copied to clipboard'})).toBeVisible(); // Pastes block list content await page.locator('[title="Clipboard"]').click(); - await page.locator('umb-block-card', {hasText: elementName}).click(); + await page.locator('umb-block-card', {hasText: contentElementName}).click(); await umbracoUi.clickElement(umbracoUi.getButtonByLabelKey(ConstantHelper.buttons.saveAndPublish)); // Assert @@ -204,9 +226,9 @@ test.describe('BlockListEditorContent', () => { }); test('can copy block list content and paste it into another group with the same block list editor', async ({page, umbracoApi, umbracoUi}) => { - const element = await umbracoApi.documentTypes.createDefaultElementType(elementName, elementAlias); + const contentElement = await umbracoApi.documentTypes.createDefaultElementType(contentElementName, contentElementAlias); - const dataType = await createDefaultBlockList(umbracoApi, blockListName, element); + const dataType = await createDefaultBlockList(umbracoApi, blockListName, contentElement); const docType = new DocumentTypeBuilder() .withName(documentName) @@ -227,7 +249,7 @@ test.describe('BlockListEditorContent', () => { .build(); await umbracoApi.documentTypes.save(docType); - await createContentWithOneBlockListEditor(umbracoApi, element); + await createContentWithOneBlockListEditor(umbracoApi, contentElement); await umbracoUi.goToSection(ConstantHelper.sections.content); await umbracoUi.refreshContentTree(); @@ -245,7 +267,7 @@ test.describe('BlockListEditorContent', () => { await expect(page.locator('.alert-success', {hasText: 'Copied to clipboard'})).toBeVisible(); // Pastes into the second group await page.locator('[title="Clipboard"]').nth(1).click(); - await page.locator('umb-block-card', {hasText: elementName}).click(); + await page.locator('umb-block-card', {hasText: contentElementName}).click(); await umbracoUi.clickElement(umbracoUi.getButtonByLabelKey(ConstantHelper.buttons.saveAndPublish)); await expect(page.locator('.alert-success', {hasText: 'Content Published'})).toBeVisible(); @@ -257,20 +279,20 @@ test.describe('BlockListEditorContent', () => { }); test('can set a minimum of required blocks in content with a block list editor', async ({page, umbracoApi, umbracoUi}) => { - const element = await umbracoApi.documentTypes.createDefaultElementType(elementName, elementAlias); + const contentElement = await umbracoApi.documentTypes.createDefaultElementType(contentElementName, contentElementAlias); const dataTypeBlockList = new BlockListDataTypeBuilder() .withName(blockListName) .withMin(2) .addBlock() - .withContentElementTypeKey(element['key']) + .withContentElementTypeKey(contentElement['key']) .done() .build(); const dataType = await umbracoApi.dataTypes.save(dataTypeBlockList); - await createDocumentWithOneBlockListEditor(umbracoApi, element, dataType); - - await createContentWithOneBlockListEditor(umbracoApi, element); + await createDocumentWithOneBlockListEditor(umbracoApi, contentElement, dataType); + + await createContentWithOneBlockListEditor(umbracoApi, contentElement); await umbracoUi.goToSection(ConstantHelper.sections.content); await umbracoUi.refreshContentTree(); @@ -294,18 +316,18 @@ test.describe('BlockListEditorContent', () => { }); test('can set a maximum of required blocks in content with a block list editor', async ({page, umbracoApi, umbracoUi}) => { - const element = await umbracoApi.documentTypes.createDefaultElementType(elementName, elementAlias); + const contentElement = await umbracoApi.documentTypes.createDefaultElementType(contentElementName, contentElementAlias); const dataTypeBlockList = new BlockListDataTypeBuilder() .withName(blockListName) .withMax(2) .addBlock() - .withContentElementTypeKey(element['key']) + .withContentElementTypeKey(contentElement['key']) .done() .build(); const dataType = await umbracoApi.dataTypes.save(dataTypeBlockList); - await createDocumentWithOneBlockListEditor(umbracoApi, element, dataType); + await createDocumentWithOneBlockListEditor(umbracoApi, contentElement, dataType); const rootContentNode = new ContentBuilder() .withContentTypeAlias(documentAlias) @@ -317,16 +339,16 @@ test.describe('BlockListEditorContent', () => { .withAlias(blockListAlias) .addBlockListValue() .addBlockListEntry() - .withContentTypeKey(element['key']) - .appendContentProperties(element.groups[0].properties[0].alias, "aliasTest") + .withContentTypeKey(contentElement['key']) + .appendContentProperties(contentElement.groups[0].properties[0].alias, "aliasTest") .done() .addBlockListEntry() - .withContentTypeKey(element['key']) - .appendContentProperties(element.groups[0].properties[0].alias, "aliasTests") + .withContentTypeKey(contentElement['key']) + .appendContentProperties(contentElement.groups[0].properties[0].alias, "aliasTests") .done() .addBlockListEntry() - .withContentTypeKey(element['key']) - .appendContentProperties(element.groups[0].properties[0].alias, "aliasTester") + .withContentTypeKey(contentElement['key']) + .appendContentProperties(contentElement.groups[0].properties[0].alias, "aliasTester") .done() .done() .done() @@ -357,20 +379,20 @@ test.describe('BlockListEditorContent', () => { }); test('can use inline editing mode in content with a block list editor', async ({page, umbracoApi, umbracoUi}) => { - const element = await umbracoApi.documentTypes.createDefaultElementType(elementName, elementAlias); + const contentElement = await umbracoApi.documentTypes.createDefaultElementType(contentElementName, contentElementAlias); const dataTypeBlockList = new BlockListDataTypeBuilder() .withName(blockListName) .withUseInlineEditingAsDefault(true) .addBlock() - .withContentElementTypeKey(element['key']) + .withContentElementTypeKey(contentElement['key']) .done() .build(); const dataType = await umbracoApi.dataTypes.save(dataTypeBlockList); - await createDocumentWithOneBlockListEditor(umbracoApi, element, dataType); - - await createContentWithOneBlockListEditor(umbracoApi, element); + await createDocumentWithOneBlockListEditor(umbracoApi, contentElement, dataType); + + await createContentWithOneBlockListEditor(umbracoApi, contentElement); await umbracoUi.goToSection(ConstantHelper.sections.content); await umbracoUi.refreshContentTree(); @@ -387,11 +409,11 @@ test.describe('BlockListEditorContent', () => { test('can see rendered content with a block list editor', async ({page, umbracoApi, umbracoUi}) => { await umbracoApi.templates.ensureNameNotExists(documentName); - await umbracoApi.partialViews.ensureNameNotExists('blocklist/Components',elementAlias + '.cshtml'); + await umbracoApi.partialViews.ensureNameNotExists('blocklist/Components',contentElementAlias + '.cshtml'); - const element = new DocumentTypeBuilder() - .withName(elementName) - .withAlias(elementAlias) + const contentElement = new DocumentTypeBuilder() + .withName(contentElementName) + .withAlias(contentElementAlias) .AsElementType() .addGroup() .withName("TestString") @@ -406,9 +428,9 @@ test.describe('BlockListEditorContent', () => { .done() .done() .build(); - await umbracoApi.documentTypes.save(element); + await umbracoApi.documentTypes.save(contentElement); - const dataType = await createDefaultBlockList(umbracoApi, blockListName, element); + const dataType = await createDefaultBlockList(umbracoApi, blockListName, contentElement); const docType = new DocumentTypeBuilder() .withName(documentName) @@ -418,7 +440,7 @@ test.describe('BlockListEditorContent', () => { .addGroup() .withName('BlockListGroup') .addCustomProperty(dataType['id']) - .withAlias(elementAlias) + .withAlias(contentElementAlias) .done() .done() .build(); @@ -431,15 +453,15 @@ test.describe('BlockListEditorContent', () => { '\n Layout = null;' + '\n}' + '\n' + - '@Html.GetBlockListHtml(Model.' + elementName + ')'); + '@Html.GetBlockListHtml(Model.' + contentElementName + ')'); const partialView = new PartialViewBuilder() - .withName(elementAlias) + .withName(contentElementAlias) .withContent("@inherits Umbraco.Cms.Web.Common.Views.UmbracoViewPage;\n" + "@using ContentModels = Umbraco.Cms.Web.Common.PublishedModels;\n" + "@{\n" + - "var content = (ContentModels." + elementName + ")Model.Content;\n" + - "var settings = (ContentModels." + elementName + ")Model.Settings;\n" + + "var content = (ContentModels." + contentElementName + ")Model.Content;\n" + + "var settings = (ContentModels." + contentElementName + ")Model.Settings;\n" + "}\n" + "\n" + "

@content.Title

" + @@ -459,15 +481,15 @@ test.describe('BlockListEditorContent', () => { .withSave(true) .withPublish(true) .addProperty() - .withAlias(elementAlias) + .withAlias(contentElementAlias) .addBlockListValue() .addBlockListEntry() - .withContentTypeKey(element['key']) - .appendContentProperties(element.groups[0].properties[0].alias, "ContentTest") - .appendContentProperties(element.groups[0].properties[1].alias, "RTEContent") - .withSettingsTypeKey(element['key']) - .appendSettingsProperties(element.groups[0].properties[0].alias, "SettingTest") - .appendSettingsProperties(element.groups[0].properties[1].alias, "RTESetting") + .withContentTypeKey(contentElement['key']) + .appendContentProperties(contentElement.groups[0].properties[0].alias, "ContentTest") + .appendContentProperties(contentElement.groups[0].properties[1].alias, "RTEContent") + .withSettingsTypeKey(contentElement['key']) + .appendSettingsProperties(contentElement.groups[0].properties[0].alias, "SettingTest") + .appendSettingsProperties(contentElement.groups[0].properties[1].alias, "RTESetting") .done() .done() .done() @@ -479,9 +501,83 @@ test.describe('BlockListEditorContent', () => { // Ensure that the view gets rendered correctly const expected = `

ContentTest

RTEContent

SettingTest

RTESetting

`; await expect(await umbracoApi.content.verifyRenderedContent('/', expected, true)).toBeTruthy(); - + // Clean await umbracoApi.templates.ensureNameNotExists(documentName); - await umbracoApi.partialViews.ensureNameNotExists('blocklist/Components',elementAlias + '.cshtml'); + await umbracoApi.partialViews.ensureNameNotExists('blocklist/Components',contentElementAlias + '.cshtml'); }); -}); \ No newline at end of file + + test('Checks if the settings content model contains a default value when created', async ({page, umbracoApi, umbracoUi}) => { + const contentSliderName = 'ContentSlider'; + const contentSliderDefaultValue = 5; + const settingsSliderName = 'SettingsSlider'; + const settingsSliderDefaultValue = 9; + + await umbracoApi.documentTypes.ensureNameNotExists(settingElementName); + await umbracoApi.dataTypes.ensureNameNotExists(contentSliderName); + await umbracoApi.dataTypes.ensureNameNotExists(settingsSliderName); + + const contentElement = await createElementWithSlider(umbracoApi, contentElementName, contentElementAlias, null, contentSliderName, contentSliderDefaultValue); + + const settingsElement = await createElementWithSlider(umbracoApi, settingElementName, settingsElementAlias, null, settingsSliderName, settingsSliderDefaultValue); + + const blockList = new BlockListDataTypeBuilder() + .withName(blockListName) + .addBlock() + .withContentElementTypeKey(contentElement['key']) + .withSettingsElementTypeKey(settingsElement['key']) + .done() + .build(); + const blockListDataType = await umbracoApi.dataTypes.save(blockList); + + const document = new DocumentTypeBuilder() + .withName(documentName) + .withAlias(documentAlias) + .withAllowAsRoot(true) + .addGroup() + .withName('Content') + .withAlias('content') + .addCustomProperty(blockListDataType['id']) + .withLabel('BlockListTest') + .withAlias('blockListTest') + .done() + .done() + .build(); + await umbracoApi.documentTypes.save(document); + + const content = new ContentBuilder() + .withContentTypeAlias(documentAlias) + .withAction(ConstantHelper.actions.publish) + .addVariant() + .withName(blockListName) + .withSave(true) + .withPublish(true) + .done() + .build(); + const contentNode = await umbracoApi.content.save(content); + + await umbracoUi.goToSection(ConstantHelper.sections.content); + await umbracoUi.refreshContentTree(); + await umbracoUi.clickDataElementByElementName('tree-item-' + blockListName); + await page.locator('[key="blockEditor_addThis"]', {hasText: contentElementName}).click(); + await page.locator('[label="Create"]').click(); + await umbracoUi.clickElement(umbracoUi.getButtonByLabelKey(ConstantHelper.buttons.saveAndPublish)); + + // Assert + // Checks if the content contains the BlockListEditor block + await umbracoUi.clickDataElementByElementName("tree-root"); + await umbracoUi.refreshContentTree(); + await umbracoUi.clickDataElementByElementName('tree-item-' + blockListName); + await expect(page.locator('.umb-block-list__block--view')).toHaveCount(1); + + // Checks if both the content and settings have been assigned their DefaultValues + const contentData = await umbracoApi.content.getContent(contentNode.id); + await expect(contentData.variants[0].tabs[0].properties[0].value.contentData[0].slider).toEqual(contentSliderDefaultValue.toString()); + await expect(contentData.variants[0].tabs[0].properties[0].value.settingsData[0].slider).toEqual(settingsSliderDefaultValue.toString()); + + // Clean + await umbracoApi.documentTypes.ensureNameNotExists(settingElementName); + await umbracoApi.dataTypes.ensureNameNotExists(contentSliderName); + await umbracoApi.dataTypes.ensureNameNotExists(settingsSliderName); + }); +}); From 82eae48d098b9deecbdf86cf288b2b18020e1fed Mon Sep 17 00:00:00 2001 From: Nikolaj Geisle <70372949+Zeegaan@users.noreply.github.com> Date: Thu, 13 Jul 2023 06:03:39 +0200 Subject: [PATCH 05/13] Merge pull request from GHSA-h8wc-r4jh-mg7m * Don't login after install * Fail the install if database is not created --------- Co-authored-by: Zeegaan Co-authored-by: Nikolaj --- .../Runtime/RuntimeState.cs | 2 +- .../Install/InstallApiController.cs | 27 ++++++++++--------- 2 files changed, 16 insertions(+), 13 deletions(-) diff --git a/src/Umbraco.Infrastructure/Runtime/RuntimeState.cs b/src/Umbraco.Infrastructure/Runtime/RuntimeState.cs index ec1cfc5d6e..8731f7acc8 100644 --- a/src/Umbraco.Infrastructure/Runtime/RuntimeState.cs +++ b/src/Umbraco.Infrastructure/Runtime/RuntimeState.cs @@ -213,7 +213,7 @@ public class RuntimeState : IRuntimeState if (_globalSettings.Value.InstallMissingDatabase || _databaseProviderMetadata.CanForceCreateDatabase(_databaseFactory)) { // ok to install on a configured but missing database - Level = RuntimeLevel.Install; + Level = RuntimeLevel.BootFailed; Reason = RuntimeLevelReason.InstallMissingDatabase; return; } diff --git a/src/Umbraco.Web.BackOffice/Install/InstallApiController.cs b/src/Umbraco.Web.BackOffice/Install/InstallApiController.cs index 555c14ff96..b710933791 100644 --- a/src/Umbraco.Web.BackOffice/Install/InstallApiController.cs +++ b/src/Umbraco.Web.BackOffice/Install/InstallApiController.cs @@ -1,5 +1,6 @@ using System.Reflection; using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using Newtonsoft.Json.Linq; using Umbraco.Cms.Core; @@ -25,8 +26,6 @@ namespace Umbraco.Cms.Web.BackOffice.Install; [Area(Constants.Web.Mvc.InstallArea)] public class InstallApiController : ControllerBase { - private readonly IBackOfficeSignInManager _backOfficeSignInManager; - private readonly IBackOfficeUserManager _backOfficeUserManager; private readonly DatabaseBuilder _databaseBuilder; private readonly InstallStatusTracker _installStatusTracker; private readonly InstallStepCollection _installSteps; @@ -34,6 +33,7 @@ public class InstallApiController : ControllerBase private readonly IProfilingLogger _proflog; private readonly IRuntime _runtime; + [Obsolete("Use the constructor without IBackOfficeUserManager & IBackOfficeSignInManager instead, scheduled for removal in v14")] public InstallApiController( DatabaseBuilder databaseBuilder, IProfilingLogger proflog, @@ -44,14 +44,25 @@ public class InstallApiController : ControllerBase IRuntime runtime, IBackOfficeUserManager backOfficeUserManager, IBackOfficeSignInManager backOfficeSignInManager) + : this(databaseBuilder, proflog, logger, installHelper, installSteps, installStatusTracker, runtime) + { + } + + [ActivatorUtilitiesConstructor] + public InstallApiController( + DatabaseBuilder databaseBuilder, + IProfilingLogger proflog, + ILogger logger, + InstallHelper installHelper, + InstallStepCollection installSteps, + InstallStatusTracker installStatusTracker, + IRuntime runtime) { _databaseBuilder = databaseBuilder ?? throw new ArgumentNullException(nameof(databaseBuilder)); _proflog = proflog ?? throw new ArgumentNullException(nameof(proflog)); _installSteps = installSteps; _installStatusTracker = installStatusTracker; _runtime = runtime; - _backOfficeUserManager = backOfficeUserManager; - _backOfficeSignInManager = backOfficeSignInManager; InstallHelper = installHelper; _logger = logger; } @@ -88,16 +99,8 @@ public class InstallApiController : ControllerBase [HttpPost] public async Task CompleteInstall() { - RuntimeLevel levelBeforeRestart = _runtime.State.Level; - await _runtime.RestartAsync(); - if (levelBeforeRestart == RuntimeLevel.Install) - { - BackOfficeIdentityUser identityUser = await _backOfficeUserManager.FindByIdAsync(Core.Constants.Security.SuperUserIdAsString); - _backOfficeSignInManager.SignInAsync(identityUser, false); - } - return NoContent(); } From 596284f32dace3b50f0ad54b1ca94ecd51aaa0a7 Mon Sep 17 00:00:00 2001 From: nikolajlauridsen Date: Thu, 13 Jul 2023 06:07:59 +0200 Subject: [PATCH 06/13] Bump version --- version.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.json b/version.json index f64e6fe584..f621eed7fd 100644 --- a/version.json +++ b/version.json @@ -1,6 +1,6 @@ { "$schema": "https://raw.githubusercontent.com/dotnet/Nerdbank.GitVersioning/master/src/NerdBank.GitVersioning/version.schema.json", - "version": "11.4.1", + "version": "11.4.2", "assemblyVersion": { "precision": "build" }, From 1f26f2c6f3428833892cde5c6d8441fb041e410e Mon Sep 17 00:00:00 2001 From: Nikolaj Geisle <70372949+zeegaan@users.noreply.github.com> Date: Thu, 13 Jul 2023 06:03:39 +0200 Subject: [PATCH 07/13] Merge pull request from GHSA-h8wc-r4jh-mg7m * Don't login after install * Fail the install if database is not created --------- Co-authored-by: Zeegaan Co-authored-by: Nikolaj --- .../Runtime/RuntimeState.cs | 2 +- .../Install/InstallApiController.cs | 31 +++++++++---------- 2 files changed, 16 insertions(+), 17 deletions(-) diff --git a/src/Umbraco.Infrastructure/Runtime/RuntimeState.cs b/src/Umbraco.Infrastructure/Runtime/RuntimeState.cs index 6597fadf61..2e2e5dbe59 100644 --- a/src/Umbraco.Infrastructure/Runtime/RuntimeState.cs +++ b/src/Umbraco.Infrastructure/Runtime/RuntimeState.cs @@ -212,7 +212,7 @@ public class RuntimeState : IRuntimeState if (_globalSettings.Value.InstallMissingDatabase || _databaseProviderMetadata.CanForceCreateDatabase(_databaseFactory)) { // ok to install on a configured but missing database - Level = RuntimeLevel.Install; + Level = RuntimeLevel.BootFailed; Reason = RuntimeLevelReason.InstallMissingDatabase; return; } diff --git a/src/Umbraco.Web.BackOffice/Install/InstallApiController.cs b/src/Umbraco.Web.BackOffice/Install/InstallApiController.cs index 52068c6f8d..b710933791 100644 --- a/src/Umbraco.Web.BackOffice/Install/InstallApiController.cs +++ b/src/Umbraco.Web.BackOffice/Install/InstallApiController.cs @@ -1,5 +1,6 @@ using System.Reflection; using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using Newtonsoft.Json.Linq; using Umbraco.Cms.Core; @@ -25,8 +26,6 @@ namespace Umbraco.Cms.Web.BackOffice.Install; [Area(Constants.Web.Mvc.InstallArea)] public class InstallApiController : ControllerBase { - private readonly IBackOfficeSignInManager _backOfficeSignInManager; - private readonly IBackOfficeUserManager _backOfficeUserManager; private readonly DatabaseBuilder _databaseBuilder; private readonly InstallStatusTracker _installStatusTracker; private readonly InstallStepCollection _installSteps; @@ -34,6 +33,7 @@ public class InstallApiController : ControllerBase private readonly IProfilingLogger _proflog; private readonly IRuntime _runtime; + [Obsolete("Use the constructor without IBackOfficeUserManager & IBackOfficeSignInManager instead, scheduled for removal in v14")] public InstallApiController( DatabaseBuilder databaseBuilder, IProfilingLogger proflog, @@ -44,14 +44,25 @@ public class InstallApiController : ControllerBase IRuntime runtime, IBackOfficeUserManager backOfficeUserManager, IBackOfficeSignInManager backOfficeSignInManager) + : this(databaseBuilder, proflog, logger, installHelper, installSteps, installStatusTracker, runtime) + { + } + + [ActivatorUtilitiesConstructor] + public InstallApiController( + DatabaseBuilder databaseBuilder, + IProfilingLogger proflog, + ILogger logger, + InstallHelper installHelper, + InstallStepCollection installSteps, + InstallStatusTracker installStatusTracker, + IRuntime runtime) { _databaseBuilder = databaseBuilder ?? throw new ArgumentNullException(nameof(databaseBuilder)); _proflog = proflog ?? throw new ArgumentNullException(nameof(proflog)); _installSteps = installSteps; _installStatusTracker = installStatusTracker; _runtime = runtime; - _backOfficeUserManager = backOfficeUserManager; - _backOfficeSignInManager = backOfficeSignInManager; InstallHelper = installHelper; _logger = logger; } @@ -88,20 +99,8 @@ public class InstallApiController : ControllerBase [HttpPost] public async Task CompleteInstall() { - RuntimeLevel levelBeforeRestart = _runtime.State.Level; - await _runtime.RestartAsync(); - if (levelBeforeRestart == RuntimeLevel.Install) - { - BackOfficeIdentityUser? identityUser = - await _backOfficeUserManager.FindByIdAsync(Core.Constants.Security.SuperUserIdAsString); - if (identityUser is not null) - { - _backOfficeSignInManager.SignInAsync(identityUser, false); - } - } - return NoContent(); } From 2a601ae0d0682737d6c12f6d2e6c641b51bda717 Mon Sep 17 00:00:00 2001 From: nikolajlauridsen Date: Thu, 13 Jul 2023 06:17:34 +0200 Subject: [PATCH 08/13] Bump version --- version.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.json b/version.json index 531f830eba..222a809220 100644 --- a/version.json +++ b/version.json @@ -1,6 +1,6 @@ { "$schema": "https://raw.githubusercontent.com/dotnet/Nerdbank.GitVersioning/master/src/NerdBank.GitVersioning/version.schema.json", - "version": "12.0.0", + "version": "12.0.1", "assemblyVersion": { "precision": "build" }, From 20a4e475c8d7b91d263e4e103ef19f3644e7b569 Mon Sep 17 00:00:00 2001 From: Nikolaj Geisle <70372949+zeegaan@users.noreply.github.com> Date: Thu, 13 Jul 2023 06:03:39 +0200 Subject: [PATCH 09/13] Merge pull request from GHSA-h8wc-r4jh-mg7m * Don't login after install * Fail the install if database is not created --------- Co-authored-by: Zeegaan Co-authored-by: Nikolaj --- .../Runtime/RuntimeState.cs | 2 +- .../Install/InstallApiController.cs | 31 +++++++++---------- 2 files changed, 16 insertions(+), 17 deletions(-) diff --git a/src/Umbraco.Infrastructure/Runtime/RuntimeState.cs b/src/Umbraco.Infrastructure/Runtime/RuntimeState.cs index 6597fadf61..2e2e5dbe59 100644 --- a/src/Umbraco.Infrastructure/Runtime/RuntimeState.cs +++ b/src/Umbraco.Infrastructure/Runtime/RuntimeState.cs @@ -212,7 +212,7 @@ public class RuntimeState : IRuntimeState if (_globalSettings.Value.InstallMissingDatabase || _databaseProviderMetadata.CanForceCreateDatabase(_databaseFactory)) { // ok to install on a configured but missing database - Level = RuntimeLevel.Install; + Level = RuntimeLevel.BootFailed; Reason = RuntimeLevelReason.InstallMissingDatabase; return; } diff --git a/src/Umbraco.Web.BackOffice/Install/InstallApiController.cs b/src/Umbraco.Web.BackOffice/Install/InstallApiController.cs index 52068c6f8d..b710933791 100644 --- a/src/Umbraco.Web.BackOffice/Install/InstallApiController.cs +++ b/src/Umbraco.Web.BackOffice/Install/InstallApiController.cs @@ -1,5 +1,6 @@ using System.Reflection; using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using Newtonsoft.Json.Linq; using Umbraco.Cms.Core; @@ -25,8 +26,6 @@ namespace Umbraco.Cms.Web.BackOffice.Install; [Area(Constants.Web.Mvc.InstallArea)] public class InstallApiController : ControllerBase { - private readonly IBackOfficeSignInManager _backOfficeSignInManager; - private readonly IBackOfficeUserManager _backOfficeUserManager; private readonly DatabaseBuilder _databaseBuilder; private readonly InstallStatusTracker _installStatusTracker; private readonly InstallStepCollection _installSteps; @@ -34,6 +33,7 @@ public class InstallApiController : ControllerBase private readonly IProfilingLogger _proflog; private readonly IRuntime _runtime; + [Obsolete("Use the constructor without IBackOfficeUserManager & IBackOfficeSignInManager instead, scheduled for removal in v14")] public InstallApiController( DatabaseBuilder databaseBuilder, IProfilingLogger proflog, @@ -44,14 +44,25 @@ public class InstallApiController : ControllerBase IRuntime runtime, IBackOfficeUserManager backOfficeUserManager, IBackOfficeSignInManager backOfficeSignInManager) + : this(databaseBuilder, proflog, logger, installHelper, installSteps, installStatusTracker, runtime) + { + } + + [ActivatorUtilitiesConstructor] + public InstallApiController( + DatabaseBuilder databaseBuilder, + IProfilingLogger proflog, + ILogger logger, + InstallHelper installHelper, + InstallStepCollection installSteps, + InstallStatusTracker installStatusTracker, + IRuntime runtime) { _databaseBuilder = databaseBuilder ?? throw new ArgumentNullException(nameof(databaseBuilder)); _proflog = proflog ?? throw new ArgumentNullException(nameof(proflog)); _installSteps = installSteps; _installStatusTracker = installStatusTracker; _runtime = runtime; - _backOfficeUserManager = backOfficeUserManager; - _backOfficeSignInManager = backOfficeSignInManager; InstallHelper = installHelper; _logger = logger; } @@ -88,20 +99,8 @@ public class InstallApiController : ControllerBase [HttpPost] public async Task CompleteInstall() { - RuntimeLevel levelBeforeRestart = _runtime.State.Level; - await _runtime.RestartAsync(); - if (levelBeforeRestart == RuntimeLevel.Install) - { - BackOfficeIdentityUser? identityUser = - await _backOfficeUserManager.FindByIdAsync(Core.Constants.Security.SuperUserIdAsString); - if (identityUser is not null) - { - _backOfficeSignInManager.SignInAsync(identityUser, false); - } - } - return NoContent(); } From 291f90d03dc0da21f3b0b64468bdf43cddf4b1f3 Mon Sep 17 00:00:00 2001 From: nikolajlauridsen Date: Thu, 13 Jul 2023 10:48:43 +0200 Subject: [PATCH 10/13] Bump version --- version.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.json b/version.json index f621eed7fd..fe28088e74 100644 --- a/version.json +++ b/version.json @@ -1,6 +1,6 @@ { "$schema": "https://raw.githubusercontent.com/dotnet/Nerdbank.GitVersioning/master/src/NerdBank.GitVersioning/version.schema.json", - "version": "11.4.2", + "version": "11.4.3", "assemblyVersion": { "precision": "build" }, From c12cce6d8c077f49a2ecde4f879ed42f6567f072 Mon Sep 17 00:00:00 2001 From: Andy Butland Date: Fri, 14 Jul 2023 09:27:02 +0200 Subject: [PATCH 11/13] Fixes an incorrect property name used for generating JSON schema. (#14542) --- src/JsonSchema/AppSettings.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/JsonSchema/AppSettings.cs b/src/JsonSchema/AppSettings.cs index e1a6d619ec..717f826859 100644 --- a/src/JsonSchema/AppSettings.cs +++ b/src/JsonSchema/AppSettings.cs @@ -88,7 +88,7 @@ namespace JsonSchema public HelpPageSettings? HelpPage { get; set; } - public InstallDefaultDataSettings? DefaultDataCreation { get; set; } + public InstallDefaultDataSettings? InstallDefaultData { get; set; } public DataTypesSettings? DataTypes { get; set; } From af44f7f59da7ea68576b747a42286c7983b699f9 Mon Sep 17 00:00:00 2001 From: nikolajlauridsen Date: Fri, 14 Jul 2023 09:38:16 +0200 Subject: [PATCH 12/13] Fix migration plan --- src/Umbraco.Infrastructure/Migrations/Upgrade/UmbracoPlan.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Umbraco.Infrastructure/Migrations/Upgrade/UmbracoPlan.cs b/src/Umbraco.Infrastructure/Migrations/Upgrade/UmbracoPlan.cs index e739d61744..cade3369f8 100644 --- a/src/Umbraco.Infrastructure/Migrations/Upgrade/UmbracoPlan.cs +++ b/src/Umbraco.Infrastructure/Migrations/Upgrade/UmbracoPlan.cs @@ -1,5 +1,6 @@ using Umbraco.Cms.Core; using Umbraco.Cms.Core.Configuration; +using Umbraco.Cms.Infrastructure.Migrations.Upgrade.V_10_7_0; namespace Umbraco.Cms.Infrastructure.Migrations.Upgrade; @@ -77,6 +78,7 @@ public class UmbracoPlan : MigrationPlan // to 11.4.3 // This is here twice since it was added in 10, so if you had already upgraded you wouldn't get it // But we still need the first once, since if you upgraded to 10.7.0 then the "From" state would be unknown otherwise. - To("{EF93F398-1385-4F07-808A-D3C518984442}"); + // This has it's own key, we essentially consider it a separate migration. + To("{2CA0C5BB-170B-45E5-8179-E73DA4B41A46}"); } } From f902b839404c68919500d1ab129c8d61deaef6d7 Mon Sep 17 00:00:00 2001 From: nikolajlauridsen Date: Fri, 14 Jul 2023 09:59:56 +0200 Subject: [PATCH 13/13] Fix version --- version.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.json b/version.json index 829112f0e2..8f4e1d83d5 100644 --- a/version.json +++ b/version.json @@ -1,6 +1,6 @@ { "$schema": "https://raw.githubusercontent.com/dotnet/Nerdbank.GitVersioning/master/src/NerdBank.GitVersioning/version.schema.json", - "version": "12.1.0-rc", + "version": "13.0.0-rc", "assemblyVersion": { "precision": "build" },