Merge branch 'release/17.0' into v17/dev

# Conflicts:
#	src/Umbraco.Web.UI.Client/src/packages/core/recycle-bin/entity-action/restore-from-recycle-bin/restore-from-recycle-bin.action.ts
#	tests/Umbraco.Tests.AcceptanceTest/package-lock.json
#	tests/Umbraco.Tests.AcceptanceTest/package.json
This commit is contained in:
leekelleher
2025-10-21 16:11:22 +01:00
170 changed files with 2568 additions and 761 deletions

View File

@@ -1,11 +1,7 @@
// Copyright (c) Umbraco.
// See LICENSE for more details.
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Threading;
using Microsoft.Extensions.Primitives;
using NUnit.Framework;
using Umbraco.Cms.Core.PropertyEditors;
@@ -31,6 +27,17 @@ public class ObjectExtensionsTests
private CultureInfo _savedCulture;
[Test]
public void Can_Create_Enumerable_Of_One()
{
var input = "hello";
#pragma warning disable CS0618 // Type or member is obsolete
var result = input.AsEnumerableOfOne<string>();
#pragma warning restore CS0618 // Type or member is obsolete
Assert.AreEqual(1, result.Count());
Assert.AreEqual("hello", result.First());
}
[Test]
public void Can_Convert_List_To_Enumerable()
{

View File

@@ -86,7 +86,7 @@ public class DateTimeUnspecifiedValueConverterTests
private static object[] _dateTimeUnspecifiedConvertToObjectCases =
[
new object[] { null, null },
new object[] { _convertToObjectInputDate, DateTime.Parse("2025-08-20T17:30:00") },
new object[] { _convertToObjectInputDate, DateTime.Parse("2025-08-20T16:30:00") },
];
[TestCaseSource(nameof(_dateTimeUnspecifiedConvertToObjectCases))]

View File

@@ -86,7 +86,7 @@ public class TimeOnlyValueConverterTests
private static object[] _timeOnlyConvertToObjectCases =
[
new object[] { null, null },
new object[] { _convertToObjectInputDate, TimeOnly.Parse("17:30") },
new object[] { _convertToObjectInputDate, TimeOnly.Parse("16:30") },
];
[TestCaseSource(nameof(_timeOnlyConvertToObjectCases))]

View File

@@ -1,3 +1,4 @@
using System;
using Microsoft.Extensions.Caching.Hybrid;
using Moq;
using NUnit.Framework;
@@ -33,15 +34,15 @@ public class HybridCacheExtensionsTests
_cacheMock
.Setup(cache => cache.GetOrCreateAsync(
key,
null!,
It.IsAny<Func<object, CancellationToken, ValueTask<ContentCacheNode>>>(),
It.IsAny<Func<CancellationToken, ValueTask<ContentCacheNode?>>>(),
It.IsAny<Func<Func<CancellationToken, ValueTask<ContentCacheNode?>>, CancellationToken, ValueTask<ContentCacheNode?>>>(),
It.IsAny<HybridCacheEntryOptions>(),
null,
CancellationToken.None))
.ReturnsAsync(expectedValue);
// Act
var exists = await HybridCacheExtensions.ExistsAsync<ContentCacheNode>(_cacheMock.Object, key);
var exists = await HybridCacheExtensions.ExistsAsync<ContentCacheNode?>(_cacheMock.Object, key, CancellationToken.None);
// Assert
Assert.IsTrue(exists);
@@ -56,24 +57,24 @@ public class HybridCacheExtensionsTests
_cacheMock
.Setup(cache => cache.GetOrCreateAsync(
key,
null!,
It.IsAny<Func<object, CancellationToken, ValueTask<ContentCacheNode>>>(),
It.IsAny<Func<CancellationToken, ValueTask<ContentCacheNode?>>>(),
It.IsAny<Func<Func<CancellationToken, ValueTask<ContentCacheNode?>>, CancellationToken, ValueTask<ContentCacheNode?>>>(),
It.IsAny<HybridCacheEntryOptions>(),
null,
CancellationToken.None))
.Returns((
string key,
object? state,
Func<object, CancellationToken, ValueTask<ContentCacheNode>> factory,
Func<CancellationToken, ValueTask<ContentCacheNode?>> state,
Func<Func<CancellationToken, ValueTask<ContentCacheNode?>>, CancellationToken, ValueTask<ContentCacheNode?>> factory,
HybridCacheEntryOptions? options,
IEnumerable<string>? tags,
CancellationToken token) =>
{
return factory(state!, token);
return factory(state, token);
});
// Act
var exists = await HybridCacheExtensions.ExistsAsync<ContentCacheNode>(_cacheMock.Object, key);
var exists = await HybridCacheExtensions.ExistsAsync<ContentCacheNode?>(_cacheMock.Object, key, CancellationToken.None);
// Assert
Assert.IsFalse(exists);
@@ -89,15 +90,15 @@ public class HybridCacheExtensionsTests
_cacheMock
.Setup(cache => cache.GetOrCreateAsync(
key,
null!,
It.IsAny<Func<object, CancellationToken, ValueTask<string>>>(),
It.IsAny<Func<CancellationToken, ValueTask<string>>>(),
It.IsAny<Func<Func<CancellationToken, ValueTask<string>>, CancellationToken, ValueTask<string>>>(),
It.IsAny<HybridCacheEntryOptions>(),
null,
CancellationToken.None))
.ReturnsAsync(expectedValue);
// Act
var (exists, value) = await HybridCacheExtensions.TryGetValueAsync<string>(_cacheMock.Object, key);
var (exists, value) = await HybridCacheExtensions.TryGetValueAsync<string>(_cacheMock.Object, key, CancellationToken.None);
// Assert
Assert.IsTrue(exists);
@@ -114,15 +115,15 @@ public class HybridCacheExtensionsTests
_cacheMock
.Setup(cache => cache.GetOrCreateAsync(
key,
null!,
It.IsAny<Func<object, CancellationToken, ValueTask<int>>>(),
It.IsAny<Func<CancellationToken, ValueTask<int>>>(),
It.IsAny<Func<Func<CancellationToken, ValueTask<int>>, CancellationToken, ValueTask<int>>>(),
It.IsAny<HybridCacheEntryOptions>(),
null,
CancellationToken.None))
.ReturnsAsync(expectedValue);
// Act
var (exists, value) = await HybridCacheExtensions.TryGetValueAsync<int>(_cacheMock.Object, key);
var (exists, value) = await HybridCacheExtensions.TryGetValueAsync<int>(_cacheMock.Object, key, CancellationToken.None);
// Assert
Assert.IsTrue(exists);
@@ -138,15 +139,15 @@ public class HybridCacheExtensionsTests
_cacheMock
.Setup(cache => cache.GetOrCreateAsync(
key,
null!,
It.IsAny<Func<object, CancellationToken, ValueTask<object>>>(),
It.IsAny<Func<CancellationToken, ValueTask<object>>>(),
It.IsAny<Func<Func<CancellationToken, ValueTask<object>>, CancellationToken, ValueTask<object>>>(),
It.IsAny<HybridCacheEntryOptions>(),
null,
CancellationToken.None))
.ReturnsAsync(null!);
// Act
var (exists, value) = await HybridCacheExtensions.TryGetValueAsync<int?>(_cacheMock.Object, key);
var (exists, value) = await HybridCacheExtensions.TryGetValueAsync<int?>(_cacheMock.Object, key, CancellationToken.None);
// Assert
Assert.IsTrue(exists);
@@ -160,16 +161,16 @@ public class HybridCacheExtensionsTests
string key = "test-key";
_cacheMock.Setup(cache => cache.GetOrCreateAsync(
key,
null,
It.IsAny<Func<object?, CancellationToken, ValueTask<string>>>(),
It.IsAny<HybridCacheEntryOptions>(),
null,
CancellationToken.None))
key,
It.IsAny<Func<CancellationToken, ValueTask<object>>>(),
It.IsAny<Func<Func<CancellationToken, ValueTask<object>>, CancellationToken, ValueTask<object>>>(),
It.IsAny<HybridCacheEntryOptions>(),
null,
CancellationToken.None))
.Returns((
string key,
object? state,
Func<object?, CancellationToken, ValueTask<string>> factory,
Func<CancellationToken, ValueTask<object>> state,
Func<Func<CancellationToken, ValueTask<object>>, CancellationToken, ValueTask<object>> factory,
HybridCacheEntryOptions? options,
IEnumerable<string>? tags,
CancellationToken token) =>
@@ -178,7 +179,7 @@ public class HybridCacheExtensionsTests
});
// Act
var (exists, value) = await HybridCacheExtensions.TryGetValueAsync<string>(_cacheMock.Object, key);
var (exists, value) = await HybridCacheExtensions.TryGetValueAsync<object>(_cacheMock.Object, key, CancellationToken.None);
// Assert
Assert.IsFalse(exists);