Merge remote-tracking branch 'origin/v13/dev' into v14/dev
# Conflicts: # tests/Umbraco.Tests.AcceptanceTest/package-lock.json # tests/Umbraco.Tests.AcceptanceTest/package.json # tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/BlockGridEditor/Content/blockGridEditorAdvanced.spec.ts # tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/BlockGridEditor/Content/blockGridEditorAreasContent.spec.ts # tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/BlockGridEditor/Content/blockGridEditorSettings.spec.ts # tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/BlockGridEditor/Datatype/BlockGridEditorDataTypeBlocks.spec.ts # tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/BlockListEditor/blockListEditorDocument.spec.ts # tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Content/content.spec.ts # tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Content/routing.spec.ts # tests/Umbraco.Tests.AcceptanceTest/tests/DefaultConfig/Settings/partialViews.spec.ts
This commit is contained in:
@@ -372,7 +372,7 @@ public class ContentService : RepositoryService, IContentService
|
||||
public IContent CreateAndSave(string name, int parentId, string contentTypeAlias, int userId = Constants.Security.SuperUserId)
|
||||
{
|
||||
// TODO: what about culture?
|
||||
using (ICoreScope scope = ScopeProvider.CreateCoreScope(autoComplete: true))
|
||||
using (ICoreScope scope = ScopeProvider.CreateCoreScope())
|
||||
{
|
||||
// locking the content tree secures content types too
|
||||
scope.WriteLock(Constants.Locks.ContentTree);
|
||||
@@ -395,6 +395,8 @@ public class ContentService : RepositoryService, IContentService
|
||||
|
||||
Save(content, userId);
|
||||
|
||||
scope.Complete();
|
||||
|
||||
return content;
|
||||
}
|
||||
}
|
||||
@@ -416,7 +418,7 @@ public class ContentService : RepositoryService, IContentService
|
||||
throw new ArgumentNullException(nameof(parent));
|
||||
}
|
||||
|
||||
using (ICoreScope scope = ScopeProvider.CreateCoreScope(autoComplete: true))
|
||||
using (ICoreScope scope = ScopeProvider.CreateCoreScope())
|
||||
{
|
||||
// locking the content tree secures content types too
|
||||
scope.WriteLock(Constants.Locks.ContentTree);
|
||||
@@ -431,6 +433,7 @@ public class ContentService : RepositoryService, IContentService
|
||||
|
||||
Save(content, userId);
|
||||
|
||||
scope.Complete();
|
||||
return content;
|
||||
}
|
||||
}
|
||||
@@ -508,10 +511,11 @@ public class ContentService : RepositoryService, IContentService
|
||||
/// <inheritdoc />
|
||||
public void PersistContentSchedule(IContent content, ContentScheduleCollection contentSchedule)
|
||||
{
|
||||
using (ICoreScope scope = ScopeProvider.CreateCoreScope(autoComplete: true))
|
||||
using (ICoreScope scope = ScopeProvider.CreateCoreScope())
|
||||
{
|
||||
scope.WriteLock(Constants.Locks.ContentTree);
|
||||
_documentRepository.PersistContentSchedule(content, contentSchedule);
|
||||
scope.Complete();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1951,7 +1955,7 @@ public class ContentService : RepositoryService, IContentService
|
||||
cultures = new HashSet<string>(); // empty means 'already published'
|
||||
}
|
||||
|
||||
if (isRoot || edited)
|
||||
if (edited)
|
||||
{
|
||||
cultures.Add(c); // <culture> means 'republish this culture'
|
||||
}
|
||||
@@ -2106,13 +2110,11 @@ public class ContentService : RepositoryService, IContentService
|
||||
}
|
||||
|
||||
// deal with the branch root - if it fails, abort
|
||||
var rootPublishNotificationState = new Dictionary<string, object?>();
|
||||
PublishResult? rootResult = SaveAndPublishBranchItem(scope, document, shouldPublish, publishCultures, true,
|
||||
publishedDocuments, eventMessages, userId, allLangs, rootPublishNotificationState);
|
||||
if (rootResult != null)
|
||||
PublishResult? result = SaveAndPublishBranchItem(scope, document, shouldPublish, publishCultures, true, publishedDocuments, eventMessages, userId, allLangs, out IDictionary<string, object?> notificationState);
|
||||
if (result != null)
|
||||
{
|
||||
results.Add(rootResult);
|
||||
if (!rootResult.Success)
|
||||
results.Add(result);
|
||||
if (!result.Success)
|
||||
{
|
||||
return results;
|
||||
}
|
||||
@@ -2125,7 +2127,6 @@ public class ContentService : RepositoryService, IContentService
|
||||
int count;
|
||||
var page = 0;
|
||||
const int pageSize = 100;
|
||||
PublishResult? result = null;
|
||||
do
|
||||
{
|
||||
count = 0;
|
||||
@@ -2144,8 +2145,7 @@ public class ContentService : RepositoryService, IContentService
|
||||
}
|
||||
|
||||
// no need to check path here, parent has to be published here
|
||||
result = SaveAndPublishBranchItem(scope, d, shouldPublish, publishCultures, false,
|
||||
publishedDocuments, eventMessages, userId, allLangs,null);
|
||||
result = SaveAndPublishBranchItem(scope, d, shouldPublish, publishCultures, false, publishedDocuments, eventMessages, userId, allLangs, out _);
|
||||
if (result != null)
|
||||
{
|
||||
results.Add(result);
|
||||
@@ -2169,12 +2169,7 @@ public class ContentService : RepositoryService, IContentService
|
||||
// (SaveAndPublishBranchOne does *not* do it)
|
||||
scope.Notifications.Publish(
|
||||
new ContentTreeChangeNotification(document, TreeChangeTypes.RefreshBranch, eventMessages));
|
||||
if (rootResult?.Success is true)
|
||||
{
|
||||
scope.Notifications.Publish(
|
||||
new ContentPublishedNotification(rootResult!.Content!.Yield(), eventMessages, true)
|
||||
.WithState(rootPublishNotificationState));
|
||||
}
|
||||
scope.Notifications.Publish(new ContentPublishedNotification(publishedDocuments, eventMessages).WithState(notificationState));
|
||||
|
||||
scope.Complete();
|
||||
}
|
||||
@@ -2185,9 +2180,6 @@ public class ContentService : RepositoryService, IContentService
|
||||
// shouldPublish: a function determining whether the document has changes that need to be published
|
||||
// note - 'force' is handled by 'editing'
|
||||
// publishValues: a function publishing values (using the appropriate PublishCulture calls)
|
||||
/// <param name="rootPublishingNotificationState">Only set this when processing a the root of the branch
|
||||
/// Published notification will not be send when this property is set</param>
|
||||
/// <returns></returns>
|
||||
private PublishResult? SaveAndPublishBranchItem(
|
||||
ICoreScope scope,
|
||||
IContent document,
|
||||
@@ -2199,8 +2191,9 @@ public class ContentService : RepositoryService, IContentService
|
||||
EventMessages evtMsgs,
|
||||
int userId,
|
||||
IReadOnlyCollection<ILanguage> allLangs,
|
||||
IDictionary<string, object?>? rootPublishingNotificationState)
|
||||
out IDictionary<string, object?> notificationState)
|
||||
{
|
||||
notificationState = new Dictionary<string, object?>();
|
||||
HashSet<string>? culturesToPublish = shouldPublish(document);
|
||||
|
||||
// null = do not include
|
||||
@@ -2228,17 +2221,11 @@ public class ContentService : RepositoryService, IContentService
|
||||
return new PublishResult(PublishResultType.FailedPublishContentInvalid, evtMsgs, document);
|
||||
}
|
||||
|
||||
var notificationState = rootPublishingNotificationState ?? new Dictionary<string, object?>();
|
||||
PublishResult result = CommitDocumentChangesInternal(scope, document, evtMsgs, allLangs, notificationState, userId, true, isRoot);
|
||||
if (!result.Success)
|
||||
PublishResult result = CommitDocumentChangesInternal(scope, document, evtMsgs, allLangs, savingNotification.State, userId, true, isRoot);
|
||||
if (result.Success)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
publishedDocuments.Add(document);
|
||||
if (rootPublishingNotificationState == null)
|
||||
{
|
||||
scope.Notifications.Publish(new ContentPublishedNotification(result.Content!, evtMsgs).WithState(notificationState));
|
||||
publishedDocuments.Add(document);
|
||||
notificationState = savingNotification.State;
|
||||
}
|
||||
|
||||
return result;
|
||||
@@ -2982,7 +2969,7 @@ public class ContentService : RepositoryService, IContentService
|
||||
|
||||
public ContentDataIntegrityReport CheckDataIntegrity(ContentDataIntegrityReportOptions options)
|
||||
{
|
||||
using (ICoreScope scope = ScopeProvider.CreateCoreScope(autoComplete: true))
|
||||
using (ICoreScope scope = ScopeProvider.CreateCoreScope())
|
||||
{
|
||||
scope.WriteLock(Constants.Locks.ContentTree);
|
||||
|
||||
@@ -2995,6 +2982,8 @@ public class ContentService : RepositoryService, IContentService
|
||||
scope.Notifications.Publish(new ContentTreeChangeNotification(root, TreeChangeTypes.RefreshAll, EventMessagesFactory.Get()));
|
||||
}
|
||||
|
||||
scope.Complete();
|
||||
|
||||
return report;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -354,7 +354,6 @@ public abstract class ContentTypeServiceBase<TRepository, TItem> : ContentTypeSe
|
||||
}
|
||||
|
||||
using (ICoreScope scope = ScopeProvider.CreateCoreScope(autoComplete: true))
|
||||
|
||||
{
|
||||
scope.ReadLock(ReadLockIds);
|
||||
return Repository.GetMany(ids.ToArray());
|
||||
|
||||
@@ -68,7 +68,7 @@ internal class ContentVersionService : IContentVersionService
|
||||
/// <inheritdoc />
|
||||
public void SetPreventCleanup(int versionId, bool preventCleanup, int userId = Constants.Security.SuperUserId)
|
||||
{
|
||||
using (ICoreScope scope = _scopeProvider.CreateCoreScope(autoComplete: true))
|
||||
using (ICoreScope scope = _scopeProvider.CreateCoreScope())
|
||||
{
|
||||
scope.WriteLock(Constants.Locks.ContentTree);
|
||||
_documentVersionRepository.SetPreventCleanup(versionId, preventCleanup);
|
||||
@@ -87,6 +87,7 @@ internal class ContentVersionService : IContentVersionService
|
||||
var message = $"set preventCleanup = '{preventCleanup}' for version '{versionId}'";
|
||||
|
||||
Audit(auditType, userId, version.ContentId, message, $"{version.VersionDate}");
|
||||
scope.Complete();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -120,7 +121,7 @@ internal class ContentVersionService : IContentVersionService
|
||||
*
|
||||
* tl;dr lots of scopes to enable other connections to use the DB whilst we work.
|
||||
*/
|
||||
using (ICoreScope scope = _scopeProvider.CreateCoreScope(autoComplete: true))
|
||||
using (ICoreScope scope = _scopeProvider.CreateCoreScope())
|
||||
{
|
||||
IReadOnlyCollection<ContentVersionMeta>? allHistoricVersions =
|
||||
_documentVersionRepository.GetDocumentVersionsEligibleForCleanup();
|
||||
@@ -154,6 +155,8 @@ internal class ContentVersionService : IContentVersionService
|
||||
|
||||
versionsToDelete.Add(version);
|
||||
}
|
||||
|
||||
scope.Complete();
|
||||
}
|
||||
|
||||
if (!versionsToDelete.Any())
|
||||
@@ -169,7 +172,7 @@ internal class ContentVersionService : IContentVersionService
|
||||
|
||||
foreach (IEnumerable<ContentVersionMeta> group in versionsToDelete.InGroupsOf(Constants.Sql.MaxParameterCount))
|
||||
{
|
||||
using (ICoreScope scope = _scopeProvider.CreateCoreScope(autoComplete: true))
|
||||
using (ICoreScope scope = _scopeProvider.CreateCoreScope())
|
||||
{
|
||||
scope.WriteLock(Constants.Locks.ContentTree);
|
||||
var groupEnumerated = group.ToList();
|
||||
@@ -182,12 +185,16 @@ internal class ContentVersionService : IContentVersionService
|
||||
scope.Notifications.Publish(
|
||||
new ContentDeletedVersionsNotification(version.ContentId, messages, version.VersionId));
|
||||
}
|
||||
|
||||
scope.Complete();
|
||||
}
|
||||
}
|
||||
|
||||
using (_scopeProvider.CreateCoreScope(autoComplete: true))
|
||||
using (ICoreScope scope = _scopeProvider.CreateCoreScope())
|
||||
{
|
||||
Audit(AuditType.Delete, Constants.Security.SuperUserId, -1, $"Removed {versionsToDelete.Count} ContentVersion(s) according to cleanup policy");
|
||||
|
||||
scope.Complete();
|
||||
}
|
||||
|
||||
return versionsToDelete;
|
||||
|
||||
@@ -680,7 +680,7 @@ namespace Umbraco.Cms.Core.Services.Implement
|
||||
[Obsolete("Please use GetReferencesAsync. Will be deleted in V15.")]
|
||||
public IReadOnlyDictionary<Udi, IEnumerable<string>> GetReferences(int id)
|
||||
{
|
||||
using ICoreScope scope = ScopeProvider.CreateCoreScope(autoComplete:true);
|
||||
using ICoreScope scope = ScopeProvider.CreateCoreScope(autoComplete: true);
|
||||
return _dataTypeRepository.FindUsages(id);
|
||||
}
|
||||
|
||||
|
||||
@@ -33,7 +33,7 @@ public class DefaultContentVersionCleanupPolicy : IContentVersionCleanupPolicy
|
||||
|
||||
var theRest = new List<ContentVersionMeta>();
|
||||
|
||||
using (_scopeProvider.CreateCoreScope(autoComplete: true))
|
||||
using (ICoreScope scope = _scopeProvider.CreateCoreScope())
|
||||
{
|
||||
var policyOverrides = _documentVersionRepository.GetCleanupPolicies()?
|
||||
.ToDictionary(x => x.ContentTypeId);
|
||||
@@ -77,6 +77,8 @@ public class DefaultContentVersionCleanupPolicy : IContentVersionCleanupPolicy
|
||||
yield return version;
|
||||
}
|
||||
}
|
||||
|
||||
scope.Complete();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1199,7 +1199,7 @@ namespace Umbraco.Cms.Core.Services
|
||||
|
||||
public ContentDataIntegrityReport CheckDataIntegrity(ContentDataIntegrityReportOptions options)
|
||||
{
|
||||
using (ICoreScope scope = ScopeProvider.CreateCoreScope(autoComplete: true))
|
||||
using (ICoreScope scope = ScopeProvider.CreateCoreScope())
|
||||
{
|
||||
scope.WriteLock(Constants.Locks.MediaTree);
|
||||
|
||||
@@ -1212,6 +1212,7 @@ namespace Umbraco.Cms.Core.Services
|
||||
scope.Notifications.Publish(new MediaTreeChangeNotification(root, TreeChangeTypes.RefreshAll, EventMessagesFactory.Get()));
|
||||
}
|
||||
|
||||
scope.Complete();
|
||||
return report;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,8 +42,10 @@ public class TwoFactorLoginService : ITwoFactorLoginService
|
||||
/// <inheritdoc />
|
||||
public async Task DeleteUserLoginsAsync(Guid userOrMemberKey)
|
||||
{
|
||||
using ICoreScope scope = _scopeProvider.CreateCoreScope(autoComplete: true);
|
||||
using ICoreScope scope = _scopeProvider.CreateCoreScope();
|
||||
await _twoFactorLoginRepository.DeleteUserLoginsAsync(userOrMemberKey);
|
||||
|
||||
scope.Complete();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
@@ -138,8 +140,12 @@ public class TwoFactorLoginService : ITwoFactorLoginService
|
||||
/// <inheritdoc />
|
||||
public async Task<bool> DisableAsync(Guid userOrMemberKey, string providerName)
|
||||
{
|
||||
using ICoreScope scope = _scopeProvider.CreateCoreScope(autoComplete: true);
|
||||
return await _twoFactorLoginRepository.DeleteUserLoginsAsync(userOrMemberKey, providerName);
|
||||
using ICoreScope scope = _scopeProvider.CreateCoreScope();
|
||||
var result = await _twoFactorLoginRepository.DeleteUserLoginsAsync(userOrMemberKey, providerName);
|
||||
|
||||
scope.Complete();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
@@ -156,9 +162,10 @@ public class TwoFactorLoginService : ITwoFactorLoginService
|
||||
/// <inheritdoc />
|
||||
public Task SaveAsync(TwoFactorLogin twoFactorLogin)
|
||||
{
|
||||
using ICoreScope scope = _scopeProvider.CreateCoreScope(autoComplete: true);
|
||||
using ICoreScope scope = _scopeProvider.CreateCoreScope();
|
||||
_twoFactorLoginRepository.Save(twoFactorLogin);
|
||||
|
||||
scope.Complete();
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
|
||||
@@ -106,7 +106,7 @@ public class ScheduledPublishing : RecurringHostedServiceBase
|
||||
// but then what should be its "scope"? could we attach it to scopes?
|
||||
// - and we should definitively *not* have to flush it here (should be auto)
|
||||
using UmbracoContextReference contextReference = _umbracoContextFactory.EnsureUmbracoContext();
|
||||
using ICoreScope scope = _scopeProvider.CreateCoreScope(autoComplete: true);
|
||||
using ICoreScope scope = _scopeProvider.CreateCoreScope();
|
||||
|
||||
/* We used to assume that there will never be two instances running concurrently where (IsMainDom && ServerRole == SchedulingPublisher)
|
||||
* However this is possible during an azure deployment slot swap for the SchedulingPublisher instance when trying to achieve zero downtime deployments.
|
||||
@@ -125,6 +125,8 @@ public class ScheduledPublishing : RecurringHostedServiceBase
|
||||
grouped.Count(),
|
||||
grouped.Key);
|
||||
}
|
||||
|
||||
scope.Complete();
|
||||
}
|
||||
finally
|
||||
{
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Umbraco.Cms.Core.DependencyInjection;
|
||||
using Umbraco.Cms.Core.Models;
|
||||
using Umbraco.Cms.Core.Persistence.Repositories;
|
||||
using Umbraco.Cms.Core.Scoping;
|
||||
using Umbraco.Cms.Infrastructure.Scoping;
|
||||
using IScope = Umbraco.Cms.Infrastructure.Scoping.IScope;
|
||||
|
||||
namespace Umbraco.Cms.Core.Logging.Viewer;
|
||||
@@ -10,6 +12,21 @@ public class LogViewerConfig : ILogViewerConfig
|
||||
private readonly ILogViewerQueryRepository _logViewerQueryRepository;
|
||||
private readonly IScopeProvider _scopeProvider;
|
||||
|
||||
[Obsolete("Use non-obsolete ctor. This will be removed in Umbraco 14.")]
|
||||
public LogViewerConfig(ILogViewerQueryRepository logViewerQueryRepository, Umbraco.Cms.Core.Scoping.IScopeProvider scopeProvider)
|
||||
: this(logViewerQueryRepository, StaticServiceProvider.Instance.GetRequiredService<IScopeProvider>())
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
//Temp ctor used by MSDI (Greedy)
|
||||
[Obsolete("Use non-obsolete ctor. This will be removed in Umbraco 14.")]
|
||||
public LogViewerConfig(ILogViewerQueryRepository logViewerQueryRepository, Umbraco.Cms.Core.Scoping.IScopeProvider coreScopeProvider, IScopeProvider scopeProvider)
|
||||
: this(logViewerQueryRepository, scopeProvider)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public LogViewerConfig(ILogViewerQueryRepository logViewerQueryRepository, IScopeProvider scopeProvider)
|
||||
{
|
||||
_logViewerQueryRepository = logViewerQueryRepository;
|
||||
@@ -28,9 +45,10 @@ public class LogViewerConfig : ILogViewerConfig
|
||||
[Obsolete("Use ILogViewerService.AddSavedLogQueryAsync instead. Scheduled for removal in Umbraco 15.")]
|
||||
public IReadOnlyList<SavedLogSearch> AddSavedSearch(string name, string query)
|
||||
{
|
||||
using IScope scope = _scopeProvider.CreateScope(autoComplete: true);
|
||||
using IScope scope = _scopeProvider.CreateScope();
|
||||
_logViewerQueryRepository.Save(new LogViewerQuery(name, query));
|
||||
|
||||
scope.Complete();
|
||||
return GetSavedSearches();
|
||||
}
|
||||
|
||||
@@ -40,7 +58,7 @@ public class LogViewerConfig : ILogViewerConfig
|
||||
[Obsolete("Use ILogViewerService.DeleteSavedLogQueryAsync instead. Scheduled for removal in Umbraco 15.")]
|
||||
public IReadOnlyList<SavedLogSearch> DeleteSavedSearch(string name)
|
||||
{
|
||||
using IScope scope = _scopeProvider.CreateScope(autoComplete: true);
|
||||
using IScope scope = _scopeProvider.CreateScope();
|
||||
ILogViewerQuery? item = _logViewerQueryRepository.GetByName(name);
|
||||
|
||||
if (item is not null)
|
||||
@@ -49,6 +67,8 @@ public class LogViewerConfig : ILogViewerConfig
|
||||
}
|
||||
|
||||
// Return the updated object - so we can instantly reset the entire array from the API response
|
||||
return GetSavedSearches();
|
||||
IReadOnlyList<SavedLogSearch> result = GetSavedSearches();
|
||||
scope.Complete();
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -96,7 +96,7 @@ public class MemberUserStore : UmbracoUserStore<MemberIdentityUser, UmbracoIdent
|
||||
throw new ArgumentNullException(nameof(user));
|
||||
}
|
||||
|
||||
using ICoreScope scope = _scopeProvider.CreateCoreScope(autoComplete: true);
|
||||
using ICoreScope scope = _scopeProvider.CreateCoreScope();
|
||||
|
||||
// create member
|
||||
IMember memberEntity = _memberService.CreateMember(
|
||||
@@ -150,6 +150,7 @@ public class MemberUserStore : UmbracoUserStore<MemberIdentityUser, UmbracoIdent
|
||||
x.Value)));
|
||||
}
|
||||
|
||||
scope.Complete();
|
||||
return Task.FromResult(IdentityResult.Success);
|
||||
}
|
||||
catch (Exception ex)
|
||||
@@ -179,7 +180,7 @@ public class MemberUserStore : UmbracoUserStore<MemberIdentityUser, UmbracoIdent
|
||||
throw new InvalidOperationException("The user id must be an integer to work with the Umbraco");
|
||||
}
|
||||
|
||||
using ICoreScope scope = _scopeProvider.CreateCoreScope(autoComplete: true);
|
||||
using ICoreScope scope = _scopeProvider.CreateCoreScope();
|
||||
|
||||
IMember? found = _memberService.GetById(asInt);
|
||||
if (found != null)
|
||||
@@ -220,6 +221,7 @@ public class MemberUserStore : UmbracoUserStore<MemberIdentityUser, UmbracoIdent
|
||||
}
|
||||
}
|
||||
|
||||
scope.Complete();
|
||||
return Task.FromResult(IdentityResult.Success);
|
||||
}
|
||||
catch (Exception ex)
|
||||
|
||||
@@ -86,7 +86,9 @@ internal class Property : PublishedPropertyBase
|
||||
_isPreviewing = content.IsPreviewing;
|
||||
_isMember = content.ContentType.ItemType == PublishedItemType.Member;
|
||||
_publishedSnapshotAccessor = publishedSnapshotAccessor;
|
||||
_variations = propertyType.Variations;
|
||||
// this variable is used for contextualizing the variation level when calculating property values.
|
||||
// it must be set to the union of variance (the combination of content type and property type variance).
|
||||
_variations = propertyType.Variations | content.ContentType.Variations;
|
||||
}
|
||||
|
||||
// clone for previewing as draft a published content that is published and has no draft
|
||||
|
||||
@@ -573,6 +573,11 @@ public class BackOfficeController : UmbracoController
|
||||
|
||||
if (errors.Count > 0)
|
||||
{
|
||||
// the external user might actually be signed in at this point, but certain errors (i.e. missing claims)
|
||||
// prevents us from applying said user to a back-office session. make sure the sign-in manager does not
|
||||
// report the user as being signed in for subsequent requests.
|
||||
await _signInManager.SignOutAsync();
|
||||
|
||||
ViewData.SetExternalSignInProviderErrors(
|
||||
new BackOfficeExternalLoginProviderErrors(
|
||||
loginInfo.LoginProvider,
|
||||
|
||||
@@ -188,15 +188,41 @@ public class ExamineManagementController : UmbracoAuthorizedJsonController
|
||||
private ExamineIndexModel CreateModel(IIndex index)
|
||||
{
|
||||
var indexName = index.Name;
|
||||
|
||||
IIndexDiagnostics indexDiag = _indexDiagnosticsFactory.Create(index);
|
||||
|
||||
Attempt<string?> isHealth = indexDiag.IsHealthy();
|
||||
var healthResult = isHealth.Result;
|
||||
|
||||
long documentCount;
|
||||
int fieldCount;
|
||||
|
||||
try
|
||||
{
|
||||
// This will throw if the index is corrupted - i.e. a file in the index folder cannot be found
|
||||
// Which will break the UI and not give the possibility to rebuild the index
|
||||
documentCount = indexDiag.GetDocumentCount();
|
||||
fieldCount = indexDiag.GetFieldNames().Count();
|
||||
}
|
||||
catch (FileNotFoundException ex)
|
||||
{
|
||||
// Safe catch that will allow to rebuild a corrupted index
|
||||
documentCount = 0;
|
||||
fieldCount = 0;
|
||||
|
||||
_logger.LogWarning(ex, "{name} is corrupted.", indexName);
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(healthResult))
|
||||
{
|
||||
healthResult += " ";
|
||||
}
|
||||
|
||||
// Provide a useful message in the Examine dashboard
|
||||
healthResult += $"It may not be possible to rebuild the index. Please try deleting the entire {indexName} folder and then attempt to rebuild it again.";
|
||||
}
|
||||
|
||||
var properties = new Dictionary<string, object?>
|
||||
{
|
||||
["DocumentCount"] = indexDiag.GetDocumentCount(),
|
||||
["FieldCount"] = indexDiag.GetFieldNames().Count()
|
||||
["DocumentCount"] = documentCount,
|
||||
["FieldCount"] = fieldCount
|
||||
};
|
||||
|
||||
foreach (KeyValuePair<string, object?> p in indexDiag.Metadata)
|
||||
@@ -207,7 +233,7 @@ public class ExamineManagementController : UmbracoAuthorizedJsonController
|
||||
var indexerModel = new ExamineIndexModel
|
||||
{
|
||||
Name = indexName,
|
||||
HealthStatus = isHealth.Success ? isHealth.Result ?? "Healthy" : isHealth.Result ?? "Unhealthy",
|
||||
HealthStatus = isHealth.Success ? healthResult ?? "Healthy" : healthResult ?? "Unhealthy",
|
||||
ProviderProperties = properties,
|
||||
CanRebuild = _indexRebuilder.CanRebuild(index.Name)
|
||||
};
|
||||
|
||||
@@ -102,7 +102,7 @@ public class UmbProfileController : SurfaceController
|
||||
|
||||
private async Task<IdentityResult> UpdateMemberAsync(ProfileModel model, MemberIdentityUser currentMember)
|
||||
{
|
||||
using ICoreScope scope = _scopeProvider.CreateCoreScope(autoComplete: true);
|
||||
using ICoreScope scope = _scopeProvider.CreateCoreScope();
|
||||
|
||||
currentMember.Email = model.Email;
|
||||
currentMember.Name = model.Name;
|
||||
@@ -140,6 +140,7 @@ public class UmbProfileController : SurfaceController
|
||||
|
||||
_memberService.Save(member);
|
||||
|
||||
scope.Complete();
|
||||
return saveResult;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -118,7 +118,7 @@ public class UmbRegisterController : SurfaceController
|
||||
/// <returns>Result of registration operation.</returns>
|
||||
private async Task<IdentityResult> RegisterMemberAsync(RegisterModel model)
|
||||
{
|
||||
using ICoreScope scope = _scopeProvider.CreateCoreScope(autoComplete: true);
|
||||
using ICoreScope scope = _scopeProvider.CreateCoreScope();
|
||||
|
||||
// U4-10762 Server error with "Register Member" snippet (Cannot save member with empty name)
|
||||
// If name field is empty, add the email address instead.
|
||||
@@ -160,6 +160,8 @@ public class UmbRegisterController : SurfaceController
|
||||
}
|
||||
}
|
||||
|
||||
scope.Complete();
|
||||
|
||||
return identityResult;
|
||||
}
|
||||
}
|
||||
|
||||
751
tests/Umbraco.Tests.AcceptanceTest/package-lock.json
generated
751
tests/Umbraco.Tests.AcceptanceTest/package-lock.json
generated
@@ -17,7 +17,7 @@
|
||||
"xhr2": "^0.2.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@playwright/test": "^1.35",
|
||||
"@playwright/test": "^1.38",
|
||||
"del": "^6.0.0",
|
||||
"ncp": "^2.0.0",
|
||||
"prompt": "^1.2.0",
|
||||
@@ -86,22 +86,18 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@playwright/test": {
|
||||
"version": "1.35.1",
|
||||
"resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.35.1.tgz",
|
||||
"integrity": "sha512-b5YoFe6J9exsMYg0pQAobNDR85T1nLumUYgUTtKm4d21iX2L7WqKq9dW8NGJ+2vX0etZd+Y7UeuqsxDXm9+5ZA==",
|
||||
"version": "1.38.0",
|
||||
"resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.38.0.tgz",
|
||||
"integrity": "sha512-xis/RXXsLxwThKnlIXouxmIvvT3zvQj1JE39GsNieMUrMpb3/GySHDh2j8itCG22qKVD4MYLBp7xB73cUW/UUw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@types/node": "*",
|
||||
"playwright-core": "1.35.1"
|
||||
"playwright": "1.38.0"
|
||||
},
|
||||
"bin": {
|
||||
"playwright": "cli.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=16"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"fsevents": "2.3.2"
|
||||
}
|
||||
},
|
||||
"node_modules/@sideway/address": {
|
||||
@@ -744,10 +740,28 @@
|
||||
"url": "https://github.com/sponsors/jonschlinkert"
|
||||
}
|
||||
},
|
||||
"node_modules/playwright": {
|
||||
"version": "1.38.0",
|
||||
"resolved": "https://registry.npmjs.org/playwright/-/playwright-1.38.0.tgz",
|
||||
"integrity": "sha512-fJGw+HO0YY+fU/F1N57DMO+TmXHTrmr905J05zwAQE9xkuwP/QLDk63rVhmyxh03dYnEhnRbsdbH9B0UVVRB3A==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"playwright-core": "1.38.0"
|
||||
},
|
||||
"bin": {
|
||||
"playwright-core": "cli.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=16"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"fsevents": "2.3.2"
|
||||
}
|
||||
},
|
||||
"node_modules/playwright-core": {
|
||||
"version": "1.35.1",
|
||||
"resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.35.1.tgz",
|
||||
"integrity": "sha512-pNXb6CQ7OqmGDRspEjlxE49w+4YtR6a3X6mT1hZXeJHWmsEz7SunmvZeiG/+y1yyMZdHnnn73WKYdtV1er0Xyg==",
|
||||
"version": "1.38.0",
|
||||
"resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.38.0.tgz",
|
||||
"integrity": "sha512-f8z1y8J9zvmHoEhKgspmCvOExF2XdcxMW8jNRuX4vkQFrzV4MlZ55iwb5QeyiFQgOFCUolXiRHgpjSEnqvO48g==",
|
||||
"dev": true,
|
||||
"bin": {
|
||||
"playwright-core": "cli.js"
|
||||
@@ -988,5 +1002,718 @@
|
||||
"node": ">= 6"
|
||||
}
|
||||
}
|
||||
},
|
||||
"dependencies": {
|
||||
"@colors/colors": {
|
||||
"version": "1.5.0",
|
||||
"resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz",
|
||||
"integrity": "sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==",
|
||||
"dev": true
|
||||
},
|
||||
"@hapi/hoek": {
|
||||
"version": "9.3.0",
|
||||
"resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-9.3.0.tgz",
|
||||
"integrity": "sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ==",
|
||||
"dev": true
|
||||
},
|
||||
"@hapi/topo": {
|
||||
"version": "5.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@hapi/topo/-/topo-5.1.0.tgz",
|
||||
"integrity": "sha512-foQZKJig7Ob0BMAYBfcJk8d77QtOe7Wo4ox7ff1lQYoNNAb6jwcY1ncdoy2e9wQZzvNy7ODZCYJkK8kzmcAnAg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@hapi/hoek": "^9.0.0"
|
||||
}
|
||||
},
|
||||
"@nodelib/fs.scandir": {
|
||||
"version": "2.1.5",
|
||||
"resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
|
||||
"integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@nodelib/fs.stat": "2.0.5",
|
||||
"run-parallel": "^1.1.9"
|
||||
}
|
||||
},
|
||||
"@nodelib/fs.stat": {
|
||||
"version": "2.0.5",
|
||||
"resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz",
|
||||
"integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==",
|
||||
"dev": true
|
||||
},
|
||||
"@nodelib/fs.walk": {
|
||||
"version": "1.2.8",
|
||||
"resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz",
|
||||
"integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@nodelib/fs.scandir": "2.1.5",
|
||||
"fastq": "^1.6.0"
|
||||
}
|
||||
},
|
||||
"@playwright/test": {
|
||||
"version": "1.38.0",
|
||||
"resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.38.0.tgz",
|
||||
"integrity": "sha512-xis/RXXsLxwThKnlIXouxmIvvT3zvQj1JE39GsNieMUrMpb3/GySHDh2j8itCG22qKVD4MYLBp7xB73cUW/UUw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"playwright": "1.38.0"
|
||||
}
|
||||
},
|
||||
"@sideway/address": {
|
||||
"version": "4.1.4",
|
||||
"resolved": "https://registry.npmjs.org/@sideway/address/-/address-4.1.4.tgz",
|
||||
"integrity": "sha512-7vwq+rOHVWjyXxVlR76Agnvhy8I9rpzjosTESvmhNeXOXdZZB15Fl+TI9x1SiHZH5Jv2wTGduSxFDIaq0m3DUw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@hapi/hoek": "^9.0.0"
|
||||
}
|
||||
},
|
||||
"@sideway/formula": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@sideway/formula/-/formula-3.0.1.tgz",
|
||||
"integrity": "sha512-/poHZJJVjx3L+zVD6g9KgHfYnb443oi7wLu/XKojDviHy6HOEOA6z1Trk5aR1dGcmPenJEgb2sK2I80LeS3MIg==",
|
||||
"dev": true
|
||||
},
|
||||
"@sideway/pinpoint": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@sideway/pinpoint/-/pinpoint-2.0.0.tgz",
|
||||
"integrity": "sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ==",
|
||||
"dev": true
|
||||
},
|
||||
"@types/node": {
|
||||
"version": "14.17.33",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-14.17.33.tgz",
|
||||
"integrity": "sha512-noEeJ06zbn3lOh4gqe2v7NMGS33jrulfNqYFDjjEbhpDEHR5VTxgYNQSBqBlJIsBJW3uEYDgD6kvMnrrhGzq8g==",
|
||||
"dev": true
|
||||
},
|
||||
"@umbraco/json-models-builders": {
|
||||
"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==",
|
||||
"requires": {
|
||||
"camelize": "^1.0.0",
|
||||
"faker": "^4.1.0"
|
||||
}
|
||||
},
|
||||
"@umbraco/playwright-testhelpers": {
|
||||
"version": "1.0.25",
|
||||
"resolved": "https://registry.npmjs.org/@umbraco/playwright-testhelpers/-/playwright-testhelpers-1.0.25.tgz",
|
||||
"integrity": "sha512-6H452J6LhP0EHjF4jR7V7i0U8WPTiAbSyhN1J459BbbYEJ4QX1A2ZlCdA6VSBAsK1xYdMXD+yxsVJq7AAwiy9A==",
|
||||
"requires": {
|
||||
"@umbraco/json-models-builders": "^1.0.6",
|
||||
"camelize": "^1.0.0",
|
||||
"faker": "^4.1.0",
|
||||
"form-data": "^4.0.0",
|
||||
"node-fetch": "^2.6.7",
|
||||
"xhr2": "^0.2.1"
|
||||
}
|
||||
},
|
||||
"aggregate-error": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz",
|
||||
"integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"clean-stack": "^2.0.0",
|
||||
"indent-string": "^4.0.0"
|
||||
}
|
||||
},
|
||||
"array-union": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz",
|
||||
"integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==",
|
||||
"dev": true
|
||||
},
|
||||
"async": {
|
||||
"version": "3.2.3",
|
||||
"resolved": "https://registry.npmjs.org/async/-/async-3.2.3.tgz",
|
||||
"integrity": "sha512-spZRyzKL5l5BZQrr/6m/SqFdBN0q3OCI0f9rjfBzCMBIP4p75P620rR3gTmaksNOhmzgdxcaxdNfMy6anrbM0g==",
|
||||
"dev": true
|
||||
},
|
||||
"asynckit": {
|
||||
"version": "0.4.0",
|
||||
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
|
||||
"integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k="
|
||||
},
|
||||
"axios": {
|
||||
"version": "0.25.0",
|
||||
"resolved": "https://registry.npmjs.org/axios/-/axios-0.25.0.tgz",
|
||||
"integrity": "sha512-cD8FOb0tRH3uuEe6+evtAbgJtfxr7ly3fQjYcMcuPlgkwVS9xboaVIpcDV+cYQe+yGykgwZCs1pzjntcGa6l5g==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"follow-redirects": "^1.14.7"
|
||||
}
|
||||
},
|
||||
"balanced-match": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
|
||||
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
|
||||
"dev": true
|
||||
},
|
||||
"brace-expansion": {
|
||||
"version": "1.1.11",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
|
||||
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"balanced-match": "^1.0.0",
|
||||
"concat-map": "0.0.1"
|
||||
}
|
||||
},
|
||||
"braces": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
|
||||
"integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"fill-range": "^7.0.1"
|
||||
}
|
||||
},
|
||||
"camelize": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/camelize/-/camelize-1.0.0.tgz",
|
||||
"integrity": "sha1-FkpUg+Yw+kMh5a8HAg5TGDGyYJs="
|
||||
},
|
||||
"clean-stack": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz",
|
||||
"integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==",
|
||||
"dev": true
|
||||
},
|
||||
"colors": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/colors/-/colors-1.0.3.tgz",
|
||||
"integrity": "sha512-pFGrxThWcWQ2MsAz6RtgeWe4NK2kUE1WfsrvvlctdII745EW9I0yflqhe7++M5LEc7bV2c/9/5zc8sFcpL0Drw==",
|
||||
"dev": true
|
||||
},
|
||||
"combined-stream": {
|
||||
"version": "1.0.8",
|
||||
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
|
||||
"integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
|
||||
"requires": {
|
||||
"delayed-stream": "~1.0.0"
|
||||
}
|
||||
},
|
||||
"concat-map": {
|
||||
"version": "0.0.1",
|
||||
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
|
||||
"integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
|
||||
"dev": true
|
||||
},
|
||||
"cycle": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/cycle/-/cycle-1.0.3.tgz",
|
||||
"integrity": "sha512-TVF6svNzeQCOpjCqsy0/CSy8VgObG3wXusJ73xW2GbG5rGx7lC8zxDSURicsXI2UsGdi2L0QNRCi745/wUDvsA==",
|
||||
"dev": true
|
||||
},
|
||||
"del": {
|
||||
"version": "6.1.1",
|
||||
"resolved": "https://registry.npmjs.org/del/-/del-6.1.1.tgz",
|
||||
"integrity": "sha512-ua8BhapfP0JUJKC/zV9yHHDW/rDoDxP4Zhn3AkA6/xT6gY7jYXJiaeyBZznYVujhZZET+UgcbZiQ7sN3WqcImg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"globby": "^11.0.1",
|
||||
"graceful-fs": "^4.2.4",
|
||||
"is-glob": "^4.0.1",
|
||||
"is-path-cwd": "^2.2.0",
|
||||
"is-path-inside": "^3.0.2",
|
||||
"p-map": "^4.0.0",
|
||||
"rimraf": "^3.0.2",
|
||||
"slash": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"delayed-stream": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
|
||||
"integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk="
|
||||
},
|
||||
"dir-glob": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz",
|
||||
"integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"path-type": "^4.0.0"
|
||||
}
|
||||
},
|
||||
"dotenv": {
|
||||
"version": "16.0.2",
|
||||
"resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.0.2.tgz",
|
||||
"integrity": "sha512-JvpYKUmzQhYoIFgK2MOnF3bciIZoItIIoryihy0rIA+H4Jy0FmgyKYAHCTN98P5ybGSJcIFbh6QKeJdtZd1qhA=="
|
||||
},
|
||||
"eyes": {
|
||||
"version": "0.1.8",
|
||||
"resolved": "https://registry.npmjs.org/eyes/-/eyes-0.1.8.tgz",
|
||||
"integrity": "sha512-GipyPsXO1anza0AOZdy69Im7hGFCNB7Y/NGjDlZGJ3GJJLtwNSb2vrzYrTYJRrRloVx7pl+bhUaTB8yiccPvFQ==",
|
||||
"dev": true
|
||||
},
|
||||
"faker": {
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/faker/-/faker-4.1.0.tgz",
|
||||
"integrity": "sha1-HkW7vsxndLPBlfrSg1EJxtdIzD8="
|
||||
},
|
||||
"fast-glob": {
|
||||
"version": "3.2.12",
|
||||
"resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.12.tgz",
|
||||
"integrity": "sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@nodelib/fs.stat": "^2.0.2",
|
||||
"@nodelib/fs.walk": "^1.2.3",
|
||||
"glob-parent": "^5.1.2",
|
||||
"merge2": "^1.3.0",
|
||||
"micromatch": "^4.0.4"
|
||||
}
|
||||
},
|
||||
"fastq": {
|
||||
"version": "1.13.0",
|
||||
"resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz",
|
||||
"integrity": "sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"reusify": "^1.0.4"
|
||||
}
|
||||
},
|
||||
"fill-range": {
|
||||
"version": "7.0.1",
|
||||
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
|
||||
"integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"to-regex-range": "^5.0.1"
|
||||
}
|
||||
},
|
||||
"follow-redirects": {
|
||||
"version": "1.15.2",
|
||||
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz",
|
||||
"integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==",
|
||||
"dev": true
|
||||
},
|
||||
"form-data": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz",
|
||||
"integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==",
|
||||
"requires": {
|
||||
"asynckit": "^0.4.0",
|
||||
"combined-stream": "^1.0.8",
|
||||
"mime-types": "^2.1.12"
|
||||
}
|
||||
},
|
||||
"fs.realpath": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
|
||||
"integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==",
|
||||
"dev": true
|
||||
},
|
||||
"fsevents": {
|
||||
"version": "2.3.2",
|
||||
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
|
||||
"integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"glob": {
|
||||
"version": "7.2.3",
|
||||
"resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
|
||||
"integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"fs.realpath": "^1.0.0",
|
||||
"inflight": "^1.0.4",
|
||||
"inherits": "2",
|
||||
"minimatch": "^3.1.1",
|
||||
"once": "^1.3.0",
|
||||
"path-is-absolute": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"glob-parent": {
|
||||
"version": "5.1.2",
|
||||
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
|
||||
"integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"is-glob": "^4.0.1"
|
||||
}
|
||||
},
|
||||
"globby": {
|
||||
"version": "11.1.0",
|
||||
"resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz",
|
||||
"integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"array-union": "^2.1.0",
|
||||
"dir-glob": "^3.0.1",
|
||||
"fast-glob": "^3.2.9",
|
||||
"ignore": "^5.2.0",
|
||||
"merge2": "^1.4.1",
|
||||
"slash": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"graceful-fs": {
|
||||
"version": "4.2.10",
|
||||
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz",
|
||||
"integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==",
|
||||
"dev": true
|
||||
},
|
||||
"ignore": {
|
||||
"version": "5.2.0",
|
||||
"resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz",
|
||||
"integrity": "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==",
|
||||
"dev": true
|
||||
},
|
||||
"indent-string": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz",
|
||||
"integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==",
|
||||
"dev": true
|
||||
},
|
||||
"inflight": {
|
||||
"version": "1.0.6",
|
||||
"resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
|
||||
"integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"once": "^1.3.0",
|
||||
"wrappy": "1"
|
||||
}
|
||||
},
|
||||
"inherits": {
|
||||
"version": "2.0.4",
|
||||
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
|
||||
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
|
||||
"dev": true
|
||||
},
|
||||
"is-extglob": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
|
||||
"integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
|
||||
"dev": true
|
||||
},
|
||||
"is-glob": {
|
||||
"version": "4.0.3",
|
||||
"resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
|
||||
"integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"is-extglob": "^2.1.1"
|
||||
}
|
||||
},
|
||||
"is-number": {
|
||||
"version": "7.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
|
||||
"integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
|
||||
"dev": true
|
||||
},
|
||||
"is-path-cwd": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-2.2.0.tgz",
|
||||
"integrity": "sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ==",
|
||||
"dev": true
|
||||
},
|
||||
"is-path-inside": {
|
||||
"version": "3.0.3",
|
||||
"resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz",
|
||||
"integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==",
|
||||
"dev": true
|
||||
},
|
||||
"isstream": {
|
||||
"version": "0.1.2",
|
||||
"resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz",
|
||||
"integrity": "sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==",
|
||||
"dev": true
|
||||
},
|
||||
"joi": {
|
||||
"version": "17.6.3",
|
||||
"resolved": "https://registry.npmjs.org/joi/-/joi-17.6.3.tgz",
|
||||
"integrity": "sha512-YlQsIaS9MHYekzf1Qe11LjTkNzx9qhYluK3172z38RxYoAUf82XMX1p1DG1H4Wtk2ED/vPdSn9OggqtDu+aTow==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@hapi/hoek": "^9.0.0",
|
||||
"@hapi/topo": "^5.0.0",
|
||||
"@sideway/address": "^4.1.3",
|
||||
"@sideway/formula": "^3.0.0",
|
||||
"@sideway/pinpoint": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"lodash": {
|
||||
"version": "4.17.21",
|
||||
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
|
||||
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==",
|
||||
"dev": true
|
||||
},
|
||||
"merge2": {
|
||||
"version": "1.4.1",
|
||||
"resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
|
||||
"integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==",
|
||||
"dev": true
|
||||
},
|
||||
"micromatch": {
|
||||
"version": "4.0.5",
|
||||
"resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz",
|
||||
"integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"braces": "^3.0.2",
|
||||
"picomatch": "^2.3.1"
|
||||
}
|
||||
},
|
||||
"mime-db": {
|
||||
"version": "1.51.0",
|
||||
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.51.0.tgz",
|
||||
"integrity": "sha512-5y8A56jg7XVQx2mbv1lu49NR4dokRnhZYTtL+KGfaa27uq4pSTXkwQkFJl4pkRMyNFz/EtYDSkiiEHx3F7UN6g=="
|
||||
},
|
||||
"mime-types": {
|
||||
"version": "2.1.34",
|
||||
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.34.tgz",
|
||||
"integrity": "sha512-6cP692WwGIs9XXdOO4++N+7qjqv0rqxxVvJ3VHPh/Sc9mVZcQP+ZGhkKiTvWMQRr2tbHkJP/Yn7Y0npb3ZBs4A==",
|
||||
"requires": {
|
||||
"mime-db": "1.51.0"
|
||||
}
|
||||
},
|
||||
"minimatch": {
|
||||
"version": "3.1.2",
|
||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
|
||||
"integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"brace-expansion": "^1.1.7"
|
||||
}
|
||||
},
|
||||
"minimist": {
|
||||
"version": "1.2.7",
|
||||
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.7.tgz",
|
||||
"integrity": "sha512-bzfL1YUZsP41gmu/qjrEk0Q6i2ix/cVeAhbCbqH9u3zYutS1cLg00qhrD0M2MVdCcx4Sc0UpP2eBWo9rotpq6g==",
|
||||
"dev": true
|
||||
},
|
||||
"mute-stream": {
|
||||
"version": "0.0.8",
|
||||
"resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz",
|
||||
"integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==",
|
||||
"dev": true
|
||||
},
|
||||
"ncp": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/ncp/-/ncp-2.0.0.tgz",
|
||||
"integrity": "sha512-zIdGUrPRFTUELUvr3Gmc7KZ2Sw/h1PiVM0Af/oHB6zgnV1ikqSfRk+TOufi79aHYCW3NiOXmr1BP5nWbzojLaA==",
|
||||
"dev": true
|
||||
},
|
||||
"node-fetch": {
|
||||
"version": "2.6.7",
|
||||
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz",
|
||||
"integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==",
|
||||
"requires": {
|
||||
"whatwg-url": "^5.0.0"
|
||||
}
|
||||
},
|
||||
"once": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
|
||||
"integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"wrappy": "1"
|
||||
}
|
||||
},
|
||||
"p-map": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz",
|
||||
"integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"aggregate-error": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"path-is-absolute": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
|
||||
"integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==",
|
||||
"dev": true
|
||||
},
|
||||
"path-type": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz",
|
||||
"integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==",
|
||||
"dev": true
|
||||
},
|
||||
"picomatch": {
|
||||
"version": "2.3.1",
|
||||
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
|
||||
"integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
|
||||
"dev": true
|
||||
},
|
||||
"playwright": {
|
||||
"version": "1.38.0",
|
||||
"resolved": "https://registry.npmjs.org/playwright/-/playwright-1.38.0.tgz",
|
||||
"integrity": "sha512-fJGw+HO0YY+fU/F1N57DMO+TmXHTrmr905J05zwAQE9xkuwP/QLDk63rVhmyxh03dYnEhnRbsdbH9B0UVVRB3A==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"fsevents": "2.3.2",
|
||||
"playwright-core": "1.38.0"
|
||||
}
|
||||
},
|
||||
"playwright-core": {
|
||||
"version": "1.38.0",
|
||||
"resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.38.0.tgz",
|
||||
"integrity": "sha512-f8z1y8J9zvmHoEhKgspmCvOExF2XdcxMW8jNRuX4vkQFrzV4MlZ55iwb5QeyiFQgOFCUolXiRHgpjSEnqvO48g==",
|
||||
"dev": true
|
||||
},
|
||||
"prompt": {
|
||||
"version": "1.3.0",
|
||||
"resolved": "https://registry.npmjs.org/prompt/-/prompt-1.3.0.tgz",
|
||||
"integrity": "sha512-ZkaRWtaLBZl7KKAKndKYUL8WqNT+cQHKRZnT4RYYms48jQkFw3rrBL+/N5K/KtdEveHkxs982MX2BkDKub2ZMg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@colors/colors": "1.5.0",
|
||||
"async": "3.2.3",
|
||||
"read": "1.0.x",
|
||||
"revalidator": "0.1.x",
|
||||
"winston": "2.x"
|
||||
}
|
||||
},
|
||||
"queue-microtask": {
|
||||
"version": "1.2.3",
|
||||
"resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
|
||||
"integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==",
|
||||
"dev": true
|
||||
},
|
||||
"read": {
|
||||
"version": "1.0.7",
|
||||
"resolved": "https://registry.npmjs.org/read/-/read-1.0.7.tgz",
|
||||
"integrity": "sha512-rSOKNYUmaxy0om1BNjMN4ezNT6VKK+2xF4GBhc81mkH7L60i6dp8qPYrkndNLT3QPphoII3maL9PVC9XmhHwVQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"mute-stream": "~0.0.4"
|
||||
}
|
||||
},
|
||||
"reusify": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz",
|
||||
"integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==",
|
||||
"dev": true
|
||||
},
|
||||
"revalidator": {
|
||||
"version": "0.1.8",
|
||||
"resolved": "https://registry.npmjs.org/revalidator/-/revalidator-0.1.8.tgz",
|
||||
"integrity": "sha512-xcBILK2pA9oh4SiinPEZfhP8HfrB/ha+a2fTMyl7Om2WjlDVrOQy99N2MXXlUHqGJz4qEu2duXxHJjDWuK/0xg==",
|
||||
"dev": true
|
||||
},
|
||||
"rimraf": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
|
||||
"integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"glob": "^7.1.3"
|
||||
}
|
||||
},
|
||||
"run-parallel": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
|
||||
"integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"queue-microtask": "^1.2.2"
|
||||
}
|
||||
},
|
||||
"rxjs": {
|
||||
"version": "7.5.7",
|
||||
"resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.5.7.tgz",
|
||||
"integrity": "sha512-z9MzKh/UcOqB3i20H6rtrlaE/CgjLOvheWK/9ILrbhROGTweAi1BaFsTT9FbwZi5Trr1qNRs+MXkhmR06awzQA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"tslib": "^2.1.0"
|
||||
}
|
||||
},
|
||||
"slash": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz",
|
||||
"integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==",
|
||||
"dev": true
|
||||
},
|
||||
"stack-trace": {
|
||||
"version": "0.0.10",
|
||||
"resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz",
|
||||
"integrity": "sha512-KGzahc7puUKkzyMt+IqAep+TVNbKP+k2Lmwhub39m1AsTSkaDutx56aDCo+HLDzf/D26BIHTJWNiTG1KAJiQCg==",
|
||||
"dev": true
|
||||
},
|
||||
"to-regex-range": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
|
||||
"integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"is-number": "^7.0.0"
|
||||
}
|
||||
},
|
||||
"tr46": {
|
||||
"version": "0.0.3",
|
||||
"resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
|
||||
"integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw=="
|
||||
},
|
||||
"tslib": {
|
||||
"version": "2.4.0",
|
||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz",
|
||||
"integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==",
|
||||
"dev": true
|
||||
},
|
||||
"typescript": {
|
||||
"version": "4.8.3",
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.8.3.tgz",
|
||||
"integrity": "sha512-goMHfm00nWPa8UvR/CPSvykqf6dVV8x/dp0c5mFTMTIu0u0FlGWRioyy7Nn0PGAdHxpJZnuO/ut+PpQ8UiHAig==",
|
||||
"dev": true
|
||||
},
|
||||
"wait-on": {
|
||||
"version": "6.0.1",
|
||||
"resolved": "https://registry.npmjs.org/wait-on/-/wait-on-6.0.1.tgz",
|
||||
"integrity": "sha512-zht+KASY3usTY5u2LgaNqn/Cd8MukxLGjdcZxT2ns5QzDmTFc4XoWBgC+C/na+sMRZTuVygQoMYwdcVjHnYIVw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"axios": "^0.25.0",
|
||||
"joi": "^17.6.0",
|
||||
"lodash": "^4.17.21",
|
||||
"minimist": "^1.2.5",
|
||||
"rxjs": "^7.5.4"
|
||||
}
|
||||
},
|
||||
"webidl-conversions": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
|
||||
"integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ=="
|
||||
},
|
||||
"whatwg-url": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz",
|
||||
"integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==",
|
||||
"requires": {
|
||||
"tr46": "~0.0.3",
|
||||
"webidl-conversions": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"winston": {
|
||||
"version": "2.4.6",
|
||||
"resolved": "https://registry.npmjs.org/winston/-/winston-2.4.6.tgz",
|
||||
"integrity": "sha512-J5Zu4p0tojLde8mIOyDSsmLmcP8I3Z6wtwpTDHx1+hGcdhxcJaAmG4CFtagkb+NiN1M9Ek4b42pzMWqfc9jm8w==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"async": "^3.2.3",
|
||||
"colors": "1.0.x",
|
||||
"cycle": "1.0.x",
|
||||
"eyes": "0.1.x",
|
||||
"isstream": "0.1.x",
|
||||
"stack-trace": "0.0.x"
|
||||
}
|
||||
},
|
||||
"wrappy": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
|
||||
"integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
|
||||
"dev": true
|
||||
},
|
||||
"xhr2": {
|
||||
"version": "0.2.1",
|
||||
"resolved": "https://registry.npmjs.org/xhr2/-/xhr2-0.2.1.tgz",
|
||||
"integrity": "sha512-sID0rrVCqkVNUn8t6xuv9+6FViXjUVXq8H5rWOH2rz9fDNQEd4g0EA2XlcEdJXRz5BMEn4O1pJFdT+z4YHhoWw=="
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,7 +10,9 @@
|
||||
"createTest": "node createTest.js"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@playwright/test": "^1.35",
|
||||
"@playwright/test": "^1.38",
|
||||
"typescript": "^4.8.3",
|
||||
"tslib": "^2.4.0",
|
||||
"del": "^6.0.0",
|
||||
"ncp": "^2.0.0",
|
||||
"prompt": "^1.2.0",
|
||||
|
||||
@@ -7,6 +7,7 @@ using System.Reflection;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Logging.Abstractions;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Moq;
|
||||
using Umbraco.Cms.Core;
|
||||
using Umbraco.Cms.Core.Cache;
|
||||
@@ -14,6 +15,8 @@ using Umbraco.Cms.Core.Composing;
|
||||
using Umbraco.Cms.Core.Configuration;
|
||||
using Umbraco.Cms.Core.Configuration.Models;
|
||||
using Umbraco.Cms.Core.Diagnostics;
|
||||
using Umbraco.Cms.Core.DistributedLocking;
|
||||
using Umbraco.Cms.Core.Events;
|
||||
using Umbraco.Cms.Core.Hosting;
|
||||
using Umbraco.Cms.Core.IO;
|
||||
using Umbraco.Cms.Core.Logging;
|
||||
@@ -24,6 +27,8 @@ using Umbraco.Cms.Core.Runtime;
|
||||
using Umbraco.Cms.Core.Serialization;
|
||||
using Umbraco.Cms.Core.Strings;
|
||||
using Umbraco.Cms.Infrastructure.Persistence;
|
||||
using Umbraco.Cms.Infrastructure.Persistence.SqlSyntax;
|
||||
using Umbraco.Cms.Infrastructure.Scoping;
|
||||
using Umbraco.Cms.Infrastructure.Serialization;
|
||||
using Umbraco.Cms.Tests.Common.TestHelpers;
|
||||
using Umbraco.Extensions;
|
||||
@@ -76,6 +81,61 @@ public abstract class TestHelperBase
|
||||
|
||||
public IShortStringHelper ShortStringHelper { get; } =
|
||||
new DefaultShortStringHelper(new DefaultShortStringHelperConfig());
|
||||
public IScopeProvider ScopeProvider
|
||||
{
|
||||
get
|
||||
{
|
||||
var loggerFactory = NullLoggerFactory.Instance;
|
||||
var fileSystems = new FileSystems(
|
||||
loggerFactory,
|
||||
Mock.Of<IIOHelper>(),
|
||||
Mock.Of<IOptions<GlobalSettings>>(),
|
||||
Mock.Of<IHostingEnvironment>());
|
||||
var mediaFileManager = new MediaFileManager(
|
||||
Mock.Of<IFileSystem>(),
|
||||
Mock.Of<IMediaPathScheme>(),
|
||||
loggerFactory.CreateLogger<MediaFileManager>(),
|
||||
Mock.Of<IShortStringHelper>(),
|
||||
Mock.Of<IServiceProvider>(),
|
||||
Options.Create(new ContentSettings()));
|
||||
var databaseFactory = new Mock<IUmbracoDatabaseFactory>();
|
||||
var database = new Mock<IUmbracoDatabase>();
|
||||
var sqlContext = new Mock<ISqlContext>();
|
||||
|
||||
var lockingMechanism = new Mock<IDistributedLockingMechanism>();
|
||||
lockingMechanism.Setup(x => x.ReadLock(It.IsAny<int>(), It.IsAny<TimeSpan?>()))
|
||||
.Returns(Mock.Of<IDistributedLock>());
|
||||
lockingMechanism.Setup(x => x.WriteLock(It.IsAny<int>(), It.IsAny<TimeSpan?>()))
|
||||
.Returns(Mock.Of<IDistributedLock>());
|
||||
|
||||
var lockingMechanismFactory = new Mock<IDistributedLockingMechanismFactory>();
|
||||
lockingMechanismFactory.Setup(x => x.DistributedLockingMechanism)
|
||||
.Returns(lockingMechanism.Object);
|
||||
|
||||
// Setup mock of database factory to return mock of database.
|
||||
databaseFactory.Setup(x => x.CreateDatabase()).Returns(database.Object);
|
||||
databaseFactory.Setup(x => x.SqlContext).Returns(sqlContext.Object);
|
||||
|
||||
// Setup mock of database to return mock of sql SqlContext
|
||||
database.Setup(x => x.SqlContext).Returns(sqlContext.Object);
|
||||
|
||||
var syntaxProviderMock = new Mock<ISqlSyntaxProvider>();
|
||||
|
||||
// Setup mock of ISqlContext to return syntaxProviderMock
|
||||
sqlContext.Setup(x => x.SqlSyntax).Returns(syntaxProviderMock.Object);
|
||||
|
||||
return new ScopeProvider(
|
||||
new AmbientScopeStack(),
|
||||
new AmbientScopeContextStack(),
|
||||
lockingMechanismFactory.Object,
|
||||
databaseFactory.Object,
|
||||
fileSystems,
|
||||
new TestOptionsMonitor<CoreDebugSettings>(new CoreDebugSettings()),
|
||||
mediaFileManager,
|
||||
loggerFactory,
|
||||
Mock.Of<IEventAggregator>());
|
||||
}
|
||||
}
|
||||
|
||||
public IJsonSerializer JsonSerializer { get; } = new JsonNetSerializer();
|
||||
|
||||
|
||||
@@ -92,7 +92,7 @@ public class ContentServicePublishBranchTests : UmbracoIntegrationTest
|
||||
AssertPublishResults(
|
||||
r,
|
||||
x => x.Result,
|
||||
PublishResultType.SuccessPublish, // During branch publishing, the change detection of the root branch runs AFTER the check to process the branchItem => root is always saved&Published as the intent requires it.
|
||||
PublishResultType.SuccessPublishAlready,
|
||||
PublishResultType.SuccessPublishAlready,
|
||||
PublishResultType.SuccessPublishAlready);
|
||||
|
||||
@@ -139,7 +139,7 @@ public class ContentServicePublishBranchTests : UmbracoIntegrationTest
|
||||
AssertPublishResults(
|
||||
r,
|
||||
x => x.Result,
|
||||
PublishResultType.SuccessPublish, // During branch publishing, the change detection of the root branch runs AFTER the check to process the branchItem => root is always saved&Published as the intent requires it.
|
||||
PublishResultType.SuccessPublishAlready,
|
||||
PublishResultType.SuccessPublishAlready,
|
||||
PublishResultType.SuccessPublishAlready,
|
||||
PublishResultType.SuccessPublish,
|
||||
@@ -184,7 +184,7 @@ public class ContentServicePublishBranchTests : UmbracoIntegrationTest
|
||||
|
||||
var r = ContentService.SaveAndPublishBranch(vRoot, false)
|
||||
.ToArray(); // no culture specified so "*" is used, so all cultures
|
||||
Assert.AreEqual(PublishResultType.SuccessPublishCulture, r[0].Result); // During branch publishing, the change detection of the root branch runs AFTER the check to process the branchItem => root is always saved&Published as the intent requires it.
|
||||
Assert.AreEqual(PublishResultType.SuccessPublishAlready, r[0].Result);
|
||||
Assert.AreEqual(PublishResultType.SuccessPublishCulture, r[1].Result);
|
||||
}
|
||||
|
||||
@@ -220,7 +220,7 @@ public class ContentServicePublishBranchTests : UmbracoIntegrationTest
|
||||
var saveResult = ContentService.Save(iv1);
|
||||
|
||||
var r = ContentService.SaveAndPublishBranch(vRoot, false, "de").ToArray();
|
||||
Assert.AreEqual(PublishResultType.SuccessPublishCulture, r[0].Result); // During branch publishing, the change detection of the root branch runs AFTER the check to process the branchItem => root is always saved&Published as the intent requires it.
|
||||
Assert.AreEqual(PublishResultType.SuccessPublishAlready, r[0].Result);
|
||||
Assert.AreEqual(PublishResultType.SuccessPublishCulture, r[1].Result);
|
||||
}
|
||||
|
||||
@@ -380,7 +380,7 @@ public class ContentServicePublishBranchTests : UmbracoIntegrationTest
|
||||
AssertPublishResults(
|
||||
r,
|
||||
x => x.Result,
|
||||
PublishResultType.SuccessPublish, // During branch publishing, the change detection of the root branch runs AFTER the check to process the branchItem => root is always saved&Published as the intent requires it.
|
||||
PublishResultType.SuccessPublishAlready,
|
||||
PublishResultType.SuccessPublish,
|
||||
PublishResultType.SuccessPublishCulture);
|
||||
|
||||
@@ -406,7 +406,7 @@ public class ContentServicePublishBranchTests : UmbracoIntegrationTest
|
||||
AssertPublishResults(
|
||||
r,
|
||||
x => x.Result,
|
||||
PublishResultType.SuccessPublish, // During branch publishing, the change detection of the root branch runs AFTER the check to process the branchItem => root is always saved&Published as the intent requires it.
|
||||
PublishResultType.SuccessPublishAlready,
|
||||
PublishResultType.SuccessPublish,
|
||||
PublishResultType.SuccessPublishCulture);
|
||||
|
||||
|
||||
@@ -31,6 +31,7 @@ using Umbraco.Cms.Core.Net;
|
||||
using Umbraco.Cms.Core.PropertyEditors;
|
||||
using Umbraco.Cms.Core.Routing;
|
||||
using Umbraco.Cms.Core.Runtime;
|
||||
using Umbraco.Cms.Core.Scoping;
|
||||
using Umbraco.Cms.Core.Serialization;
|
||||
using Umbraco.Cms.Core.Strings;
|
||||
using Umbraco.Cms.Infrastructure.Mail;
|
||||
@@ -42,6 +43,7 @@ using Umbraco.Cms.Tests.Common.Testing;
|
||||
using Umbraco.Extensions;
|
||||
using File = System.IO.File;
|
||||
using IHostingEnvironment = Umbraco.Cms.Core.Hosting.IHostingEnvironment;
|
||||
using IScopeProvider = Umbraco.Cms.Infrastructure.Scoping.IScopeProvider;
|
||||
|
||||
namespace Umbraco.Cms.Tests.UnitTests.TestHelpers;
|
||||
|
||||
@@ -58,6 +60,8 @@ public static class TestHelper
|
||||
/// <value>The assembly directory.</value>
|
||||
public static string WorkingDirectory => s_testHelperInternal.WorkingDirectory;
|
||||
|
||||
public static IScopeProvider ScopeProvider => s_testHelperInternal.ScopeProvider;
|
||||
public static ICoreScopeProvider CoreScopeProvider => s_testHelperInternal.ScopeProvider;
|
||||
public static IShortStringHelper ShortStringHelper => s_testHelperInternal.ShortStringHelper;
|
||||
|
||||
public static IJsonSerializer JsonSerializer => s_testHelperInternal.JsonSerializer;
|
||||
|
||||
@@ -0,0 +1,381 @@
|
||||
using Moq;
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Cms.Core.Cache;
|
||||
using Umbraco.Cms.Core.Models;
|
||||
using Umbraco.Cms.Core.Models.PublishedContent;
|
||||
using Umbraco.Cms.Core.PropertyEditors;
|
||||
using Umbraco.Cms.Core.PublishedCache;
|
||||
using Umbraco.Cms.Infrastructure.PublishedCache;
|
||||
using Umbraco.Cms.Infrastructure.PublishedCache.DataSource;
|
||||
using Property = Umbraco.Cms.Infrastructure.PublishedCache.Property;
|
||||
|
||||
namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Core.Published;
|
||||
|
||||
[TestFixture]
|
||||
public class PropertyCacheVarianceTests
|
||||
{
|
||||
// This class tests various permutations of property value calculation across variance types and cache levels.
|
||||
//
|
||||
// Properties contain different "value levels", all of which are cached:
|
||||
// 1. The source value => the "raw" value from the client side editor (it can be different, but it's easiest to think of it like that).
|
||||
// 2. The intermediate value => a "temporary" value that is used to calculate the various "final" values.
|
||||
// 3. The object value => the "final" object value that is exposed in an IPublishedElement output.
|
||||
// 4. The XPath value => a legacy "final" value, don't think too hard on it.
|
||||
// 3. The delivery API object value => the "final" object value that is exposed in the Delivery API.
|
||||
//
|
||||
// Property values are cached based on a few rules:
|
||||
// 1. The property type variation and the parent content type variation determines how the intermediate value is cached.
|
||||
// The effective property variation is a product of both variations, meaning the property type and the content type
|
||||
// variations are combined in an OR.
|
||||
// The rules are as follows:
|
||||
// - ContentVariation.Nothing => the intermediate value is calculated once and reused across all variants (cultures and segments).
|
||||
// - ContentVariation.Culture => the intermediate value is calculated per culture and reused across all segments.
|
||||
// - ContentVariation.Segment => the intermediate value is calculated per segment and reused across all cultures.
|
||||
// - ContentVariation.CultureAndSegment => the intermediate value is calculated for all invoked culture and segment combinations.
|
||||
// 2. The property type cache level (which is usually derived from the property value converter).
|
||||
// - PropertyCacheLevel.Element => the final values are cached until the parent content item is updated.
|
||||
// - PropertyCacheLevel.Elements => the final values are cached until the _any_ content item is updated.
|
||||
// - PropertyCacheLevel.Snapshot => the final values are cached for the duration of the active cache snapshot (i.e. until the end of the current request).
|
||||
// - PropertyCacheLevel.None => the final values are never cached and will be re-calculated each time they're requested.
|
||||
|
||||
// ### Invariant content type + invariant property type ###
|
||||
[TestCase(
|
||||
ContentVariation.Nothing,
|
||||
ContentVariation.Nothing,
|
||||
PropertyCacheLevel.Element,
|
||||
// no variation => the intermediate value is calculated only once
|
||||
// cache level => the final value is calculated only once
|
||||
"da-DK:segment1 (da-DK:segment1)",
|
||||
"da-DK:segment1 (da-DK:segment1)",
|
||||
"da-DK:segment1 (da-DK:segment1)",
|
||||
"da-DK:segment1 (da-DK:segment1)")]
|
||||
[TestCase(
|
||||
ContentVariation.Nothing,
|
||||
ContentVariation.Nothing,
|
||||
PropertyCacheLevel.Elements,
|
||||
"da-DK:segment1 (da-DK:segment1)",
|
||||
"da-DK:segment1 (da-DK:segment1)",
|
||||
"da-DK:segment1 (da-DK:segment1)",
|
||||
"da-DK:segment1 (da-DK:segment1)")]
|
||||
[TestCase(
|
||||
ContentVariation.Nothing,
|
||||
ContentVariation.Nothing,
|
||||
PropertyCacheLevel.Snapshot,
|
||||
"da-DK:segment1 (da-DK:segment1)",
|
||||
"da-DK:segment1 (da-DK:segment1)",
|
||||
"da-DK:segment1 (da-DK:segment1)",
|
||||
"da-DK:segment1 (da-DK:segment1)")]
|
||||
[TestCase(
|
||||
ContentVariation.Nothing,
|
||||
ContentVariation.Nothing,
|
||||
PropertyCacheLevel.None,
|
||||
// no variation => the intermediate value is calculated once
|
||||
// no cache => the final value is calculated for each request (reflects both changes in culture and segments)
|
||||
"da-DK:segment1 (da-DK:segment1)",
|
||||
"en-US:segment1 (da-DK:segment1)",
|
||||
"en-US:segment2 (da-DK:segment1)",
|
||||
"da-DK:segment2 (da-DK:segment1)")]
|
||||
// ### Culture variant content type + invariant property type ###
|
||||
[TestCase(
|
||||
ContentVariation.Culture,
|
||||
ContentVariation.Nothing,
|
||||
PropertyCacheLevel.Element,
|
||||
// culture variation => the intermediate value is calculated per culture (ignores segment changes until a culture changes)
|
||||
// cache level => the final value is calculated only once per culture (ignores segment changes until a culture changes)
|
||||
// NOTE: in this test, culture changes before segment, so the updated segment is never reflected here
|
||||
"da-DK:segment1 (da-DK:segment1)",
|
||||
"en-US:segment1 (en-US:segment1)",
|
||||
"en-US:segment1 (en-US:segment1)",
|
||||
"da-DK:segment1 (da-DK:segment1)")]
|
||||
[TestCase(
|
||||
ContentVariation.Culture,
|
||||
ContentVariation.Nothing,
|
||||
PropertyCacheLevel.Elements,
|
||||
"da-DK:segment1 (da-DK:segment1)",
|
||||
"en-US:segment1 (en-US:segment1)",
|
||||
"en-US:segment1 (en-US:segment1)",
|
||||
"da-DK:segment1 (da-DK:segment1)")]
|
||||
[TestCase(
|
||||
ContentVariation.Culture,
|
||||
ContentVariation.Nothing,
|
||||
PropertyCacheLevel.Snapshot,
|
||||
"da-DK:segment1 (da-DK:segment1)",
|
||||
"en-US:segment1 (en-US:segment1)",
|
||||
"en-US:segment1 (en-US:segment1)",
|
||||
"da-DK:segment1 (da-DK:segment1)")]
|
||||
[TestCase(
|
||||
ContentVariation.Culture,
|
||||
ContentVariation.Nothing,
|
||||
PropertyCacheLevel.None,
|
||||
// culture variation => the intermediate value is calculated per culture (ignores segment changes until a culture changes)
|
||||
// no cache => the final value is calculated for each request (reflects both changes in culture and segments)
|
||||
// NOTE: in this test, culture changes before segment, so the updated segment is never reflected in the intermediate value here
|
||||
"da-DK:segment1 (da-DK:segment1)",
|
||||
"en-US:segment1 (en-US:segment1)",
|
||||
"en-US:segment2 (en-US:segment1)",
|
||||
"da-DK:segment2 (da-DK:segment1)")]
|
||||
// NOTE: As the tests above show, cache levels Element, Elements and Snapshot all yield the same values in this
|
||||
// test, because we are efficiently executing the test in a snapshot. From here on out we're only building
|
||||
// test cases for Element and None.
|
||||
// ### Segment variant content type + invariant property type ###
|
||||
[TestCase(
|
||||
ContentVariation.Segment,
|
||||
ContentVariation.Nothing,
|
||||
PropertyCacheLevel.Element,
|
||||
// segment variation => the intermediate value is calculated per segment (ignores culture changes until a segment changes)
|
||||
// cache level => the final value is calculated only once per segment (ignores culture changes until a segment changes)
|
||||
"da-DK:segment1 (da-DK:segment1)",
|
||||
"da-DK:segment1 (da-DK:segment1)",
|
||||
"en-US:segment2 (en-US:segment2)",
|
||||
"en-US:segment2 (en-US:segment2)")]
|
||||
[TestCase(
|
||||
ContentVariation.Segment,
|
||||
ContentVariation.Nothing,
|
||||
PropertyCacheLevel.None,
|
||||
// segment variation => the intermediate value is calculated per segment (ignores culture changes until a segment changes)
|
||||
// no cache => the final value is calculated for each request (reflects both changes in culture and segments)
|
||||
"da-DK:segment1 (da-DK:segment1)",
|
||||
"en-US:segment1 (da-DK:segment1)",
|
||||
"en-US:segment2 (en-US:segment2)",
|
||||
"da-DK:segment2 (en-US:segment2)")]
|
||||
// ### Culture and segment variant content type + invariant property type ###
|
||||
[TestCase(
|
||||
ContentVariation.CultureAndSegment,
|
||||
ContentVariation.Nothing,
|
||||
PropertyCacheLevel.Element,
|
||||
// culture and segment variation => the intermediate value is calculated per culture and segment
|
||||
// cache level => the final value is calculated only once per culture and segment (efficiently on every request in this test)
|
||||
"da-DK:segment1 (da-DK:segment1)",
|
||||
"en-US:segment1 (en-US:segment1)",
|
||||
"en-US:segment2 (en-US:segment2)",
|
||||
"da-DK:segment2 (da-DK:segment2)")]
|
||||
[TestCase(
|
||||
ContentVariation.CultureAndSegment,
|
||||
ContentVariation.Nothing,
|
||||
PropertyCacheLevel.None,
|
||||
// culture and segment variation => the intermediate value is calculated per culture and segment
|
||||
// no cache => the final value is calculated for each request
|
||||
"da-DK:segment1 (da-DK:segment1)",
|
||||
"en-US:segment1 (en-US:segment1)",
|
||||
"en-US:segment2 (en-US:segment2)",
|
||||
"da-DK:segment2 (da-DK:segment2)")]
|
||||
// ### Invariant content type + culture variant property type ###
|
||||
[TestCase(
|
||||
ContentVariation.Nothing,
|
||||
ContentVariation.Culture,
|
||||
PropertyCacheLevel.Element,
|
||||
// same behaviour as culture variation on content type + no variation on property type, see comments above
|
||||
"da-DK:segment1 (da-DK:segment1)",
|
||||
"en-US:segment1 (en-US:segment1)",
|
||||
"en-US:segment1 (en-US:segment1)",
|
||||
"da-DK:segment1 (da-DK:segment1)")]
|
||||
[TestCase(
|
||||
ContentVariation.Nothing,
|
||||
ContentVariation.Culture,
|
||||
PropertyCacheLevel.None,
|
||||
// same behaviour as culture variation on content type + no variation on property type, see comments above
|
||||
"da-DK:segment1 (da-DK:segment1)",
|
||||
"en-US:segment1 (en-US:segment1)",
|
||||
"en-US:segment2 (en-US:segment1)",
|
||||
"da-DK:segment2 (da-DK:segment1)")]
|
||||
// ### Invariant content type + segment variant property type ###
|
||||
[TestCase(
|
||||
ContentVariation.Nothing,
|
||||
ContentVariation.Segment,
|
||||
PropertyCacheLevel.Element,
|
||||
// same behaviour as segment variation on content type + no variation on property type, see comments above
|
||||
"da-DK:segment1 (da-DK:segment1)",
|
||||
"da-DK:segment1 (da-DK:segment1)",
|
||||
"en-US:segment2 (en-US:segment2)",
|
||||
"en-US:segment2 (en-US:segment2)")]
|
||||
[TestCase(
|
||||
ContentVariation.Nothing,
|
||||
ContentVariation.Segment,
|
||||
PropertyCacheLevel.None,
|
||||
// same behaviour as segment variation on content type + no variation on property type, see comments above
|
||||
"da-DK:segment1 (da-DK:segment1)",
|
||||
"en-US:segment1 (da-DK:segment1)",
|
||||
"en-US:segment2 (en-US:segment2)",
|
||||
"da-DK:segment2 (en-US:segment2)")]
|
||||
// ### Invariant content type + culture and segment variant property type ###
|
||||
[TestCase(
|
||||
ContentVariation.Nothing,
|
||||
ContentVariation.CultureAndSegment,
|
||||
PropertyCacheLevel.Element,
|
||||
// same behaviour as culture and segment variation on content type + no variation on property type, see comments above
|
||||
"da-DK:segment1 (da-DK:segment1)",
|
||||
"en-US:segment1 (en-US:segment1)",
|
||||
"en-US:segment2 (en-US:segment2)",
|
||||
"da-DK:segment2 (da-DK:segment2)")]
|
||||
[TestCase(
|
||||
ContentVariation.Nothing,
|
||||
ContentVariation.CultureAndSegment,
|
||||
PropertyCacheLevel.None,
|
||||
// same behaviour as culture and segment variation on content type + no variation on property type, see comments above
|
||||
"da-DK:segment1 (da-DK:segment1)",
|
||||
"en-US:segment1 (en-US:segment1)",
|
||||
"en-US:segment2 (en-US:segment2)",
|
||||
"da-DK:segment2 (da-DK:segment2)")]
|
||||
// ### Culture variant content type + segment variant property type ###
|
||||
[TestCase(
|
||||
ContentVariation.Culture,
|
||||
ContentVariation.Segment,
|
||||
PropertyCacheLevel.Element,
|
||||
// same behaviour as culture and segment variation on content type + no variation on property type, see comments above
|
||||
"da-DK:segment1 (da-DK:segment1)",
|
||||
"en-US:segment1 (en-US:segment1)",
|
||||
"en-US:segment2 (en-US:segment2)",
|
||||
"da-DK:segment2 (da-DK:segment2)")]
|
||||
[TestCase(
|
||||
ContentVariation.Culture,
|
||||
ContentVariation.Segment,
|
||||
PropertyCacheLevel.None,
|
||||
// same behaviour as culture and segment variation on content type + no variation on property type, see comments above
|
||||
"da-DK:segment1 (da-DK:segment1)",
|
||||
"en-US:segment1 (en-US:segment1)",
|
||||
"en-US:segment2 (en-US:segment2)",
|
||||
"da-DK:segment2 (da-DK:segment2)")]
|
||||
public void ContentType_PropertyType_Variation_Cache_Values(
|
||||
ContentVariation contentTypeVariation,
|
||||
ContentVariation propertyTypeVariation,
|
||||
PropertyCacheLevel propertyCacheLevel,
|
||||
string expectedValue1DaDkSegment1,
|
||||
string expectedValue2EnUsSegment1,
|
||||
string expectedValue3EnUsSegment2,
|
||||
string expectedValue4DaDkSegment2)
|
||||
{
|
||||
var variationContextCulture = "da-DK";
|
||||
var variationContextSegment = "segment1";
|
||||
var property = CreateProperty(
|
||||
contentTypeVariation,
|
||||
propertyTypeVariation,
|
||||
propertyCacheLevel,
|
||||
() => variationContextCulture,
|
||||
() => variationContextSegment);
|
||||
|
||||
Assert.AreEqual(expectedValue1DaDkSegment1, property.GetValue());
|
||||
|
||||
variationContextCulture = "en-US";
|
||||
Assert.AreEqual(expectedValue2EnUsSegment1, property.GetValue());
|
||||
|
||||
variationContextSegment = "segment2";
|
||||
Assert.AreEqual(expectedValue3EnUsSegment2, property.GetValue());
|
||||
|
||||
variationContextCulture = "da-DK";
|
||||
Assert.AreEqual(expectedValue4DaDkSegment2, property.GetValue());
|
||||
}
|
||||
|
||||
[TestCase(
|
||||
ContentVariation.Culture,
|
||||
ContentVariation.Nothing,
|
||||
"da-DK:segment1 (da-DK:segment1)",
|
||||
"en-US:segment1 (en-US:segment1)",
|
||||
"en-US:segment1 (en-US:segment1)",
|
||||
"da-DK:segment1 (da-DK:segment1)")]
|
||||
[TestCase(
|
||||
ContentVariation.Segment,
|
||||
ContentVariation.Nothing,
|
||||
"da-DK:segment1 (da-DK:segment1)",
|
||||
"da-DK:segment1 (da-DK:segment1)",
|
||||
"en-US:segment2 (en-US:segment2)",
|
||||
"en-US:segment2 (en-US:segment2)")]
|
||||
[TestCase(
|
||||
ContentVariation.Culture,
|
||||
ContentVariation.Segment,
|
||||
"da-DK:segment1 (da-DK:segment1)",
|
||||
"en-US:segment1 (en-US:segment1)",
|
||||
"en-US:segment2 (en-US:segment2)",
|
||||
"da-DK:segment2 (da-DK:segment2)")]
|
||||
[TestCase(
|
||||
ContentVariation.CultureAndSegment,
|
||||
ContentVariation.Nothing,
|
||||
"da-DK:segment1 (da-DK:segment1)",
|
||||
"en-US:segment1 (en-US:segment1)",
|
||||
"en-US:segment2 (en-US:segment2)",
|
||||
"da-DK:segment2 (da-DK:segment2)")]
|
||||
public void ContentType_PropertyType_Variation_Are_Interchangeable(
|
||||
ContentVariation variation1,
|
||||
ContentVariation variation2,
|
||||
string expectedValue1DaDkSegment1,
|
||||
string expectedValue2EnUsSegment1,
|
||||
string expectedValue3EnUsSegment2,
|
||||
string expectedValue4DaDkSegment2)
|
||||
{
|
||||
var scenarios = new[]
|
||||
{
|
||||
new { ContentTypeVariation = variation1, PropertyTypeVariation = variation2 },
|
||||
new { ContentTypeVariation = variation2, PropertyTypeVariation = variation1 }
|
||||
};
|
||||
|
||||
foreach (var scenario in scenarios)
|
||||
{
|
||||
var variationContextCulture = "da-DK";
|
||||
var variationContextSegment = "segment1";
|
||||
var property = CreateProperty(
|
||||
scenario.ContentTypeVariation,
|
||||
scenario.PropertyTypeVariation,
|
||||
PropertyCacheLevel.Element,
|
||||
() => variationContextCulture,
|
||||
() => variationContextSegment);
|
||||
|
||||
Assert.AreEqual(expectedValue1DaDkSegment1, property.GetValue());
|
||||
|
||||
variationContextCulture = "en-US";
|
||||
Assert.AreEqual(expectedValue2EnUsSegment1, property.GetValue());
|
||||
|
||||
variationContextSegment = "segment2";
|
||||
Assert.AreEqual(expectedValue3EnUsSegment2, property.GetValue());
|
||||
|
||||
variationContextCulture = "da-DK";
|
||||
Assert.AreEqual(expectedValue4DaDkSegment2, property.GetValue());
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new property with a mocked publishedSnapshotAccessor that uses a VariationContext that reads culture and segment information from the passed in functions.
|
||||
/// </summary>
|
||||
private Property CreateProperty(ContentVariation contentTypeVariation, ContentVariation propertyTypeVariation, PropertyCacheLevel propertyTypeCacheLevel, Func<string> getCulture, Func<string> getSegment)
|
||||
{
|
||||
var contentType = new Mock<IPublishedContentType>();
|
||||
contentType.SetupGet(c => c.PropertyTypes).Returns(Array.Empty<IPublishedPropertyType>());
|
||||
contentType.SetupGet(c => c.Variations).Returns(contentTypeVariation);
|
||||
|
||||
var contentNode = new ContentNode(123, Guid.NewGuid(), contentType.Object, 1, string.Empty, 1, 1, DateTime.Now, 1);
|
||||
var contentData = new ContentData("bla", "bla", 1, DateTime.Now, 1, 1, true, new Dictionary<string, PropertyData[]>(), null);
|
||||
|
||||
var elementCache = new FastDictionaryAppCache();
|
||||
var snapshotCache = new FastDictionaryAppCache();
|
||||
var publishedSnapshotMock = new Mock<IPublishedSnapshot>();
|
||||
publishedSnapshotMock.SetupGet(p => p.ElementsCache).Returns(elementCache);
|
||||
publishedSnapshotMock.SetupGet(p => p.SnapshotCache).Returns(snapshotCache);
|
||||
|
||||
var publishedSnapshot = publishedSnapshotMock.Object;
|
||||
var publishedSnapshotAccessor = new Mock<IPublishedSnapshotAccessor>();
|
||||
publishedSnapshotAccessor.Setup(p => p.TryGetPublishedSnapshot(out publishedSnapshot)).Returns(true);
|
||||
|
||||
var variationContextAccessorMock = new Mock<IVariationContextAccessor>();
|
||||
variationContextAccessorMock
|
||||
.SetupGet(mock => mock.VariationContext)
|
||||
.Returns(() => new VariationContext(getCulture(), getSegment()));
|
||||
|
||||
var content = new PublishedContent(
|
||||
contentNode,
|
||||
contentData,
|
||||
publishedSnapshotAccessor.Object,
|
||||
variationContextAccessorMock.Object,
|
||||
Mock.Of<IPublishedModelFactory>());
|
||||
|
||||
var propertyType = new Mock<IPublishedPropertyType>();
|
||||
propertyType.SetupGet(p => p.CacheLevel).Returns(propertyTypeCacheLevel);
|
||||
propertyType.SetupGet(p => p.DeliveryApiCacheLevel).Returns(propertyTypeCacheLevel);
|
||||
propertyType.SetupGet(p => p.Variations).Returns(propertyTypeVariation);
|
||||
propertyType
|
||||
.Setup(p => p.ConvertSourceToInter(It.IsAny<IPublishedElement>(), It.IsAny<object?>(), It.IsAny<bool>()))
|
||||
.Returns(() => $"{getCulture()}:{getSegment()}");
|
||||
propertyType
|
||||
.Setup(p => p.ConvertInterToObject(It.IsAny<IPublishedElement>(), It.IsAny<PropertyCacheLevel>(), It.IsAny<object?>(), It.IsAny<bool>()))
|
||||
.Returns((IPublishedElement _, PropertyCacheLevel _, object? inter, bool _) => $"{getCulture()}:{getSegment()} ({inter})" );
|
||||
|
||||
return new Property(propertyType.Object, content, publishedSnapshotAccessor.Object);
|
||||
}
|
||||
}
|
||||
@@ -48,7 +48,7 @@ public class LogviewerTests
|
||||
File.Copy(exampleLogfilePath, _newLogfilePath, true);
|
||||
|
||||
var logger = Mock.Of<ILogger<SerilogJsonLogViewer>>();
|
||||
var logViewerConfig = new LogViewerConfig(LogViewerQueryRepository, Mock.Of<IScopeProvider>());
|
||||
var logViewerConfig = new LogViewerConfig(LogViewerQueryRepository, TestHelper.ScopeProvider);
|
||||
var logLevelLoader = Mock.Of<ILogLevelLoader>();
|
||||
_logViewer =
|
||||
new SerilogJsonLogViewer(logger, logViewerConfig, loggingConfiguration, logLevelLoader, Log.Logger);
|
||||
|
||||
@@ -17,6 +17,7 @@ using Umbraco.Cms.Infrastructure.Scoping;
|
||||
using Umbraco.Cms.Tests.Common;
|
||||
using Umbraco.Cms.Tests.Common.Builders;
|
||||
using Umbraco.Cms.Tests.Common.Builders.Extensions;
|
||||
using Umbraco.Cms.Tests.UnitTests.TestHelpers;
|
||||
using Umbraco.Cms.Web.Common.Security;
|
||||
|
||||
namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Infrastructure.Security;
|
||||
@@ -33,7 +34,7 @@ public class MemberManagerTests
|
||||
|
||||
public MemberManager CreateSut()
|
||||
{
|
||||
var scopeProvider = new Mock<IScopeProvider>().Object;
|
||||
var scopeProvider = TestHelper.ScopeProvider;
|
||||
_mockMemberService = new Mock<IMemberService>();
|
||||
|
||||
var mapDefinitions = new List<IMapDefinition>
|
||||
|
||||
@@ -14,6 +14,7 @@ using Umbraco.Cms.Core.PublishedCache;
|
||||
using Umbraco.Cms.Core.Scoping;
|
||||
using Umbraco.Cms.Core.Security;
|
||||
using Umbraco.Cms.Core.Services;
|
||||
using Umbraco.Cms.Tests.UnitTests.TestHelpers;
|
||||
using Umbraco.Cms.Tests.UnitTests.Umbraco.Core.ShortStringHelper;
|
||||
using IScopeProvider = Umbraco.Cms.Infrastructure.Scoping.IScopeProvider;
|
||||
|
||||
@@ -27,23 +28,12 @@ public class MemberUserStoreTests
|
||||
public MemberUserStore CreateSut()
|
||||
{
|
||||
_mockMemberService = new Mock<IMemberService>();
|
||||
var mockScope = new Mock<IScope>();
|
||||
var mockScopeProvider = new Mock<IScopeProvider>();
|
||||
mockScopeProvider
|
||||
.Setup(x => x.CreateScope(
|
||||
It.IsAny<IsolationLevel>(),
|
||||
It.IsAny<RepositoryCacheMode>(),
|
||||
It.IsAny<IEventDispatcher>(),
|
||||
It.IsAny<IScopedNotificationPublisher>(),
|
||||
It.IsAny<bool?>(),
|
||||
It.IsAny<bool>(),
|
||||
It.IsAny<bool>()))
|
||||
.Returns(mockScope.Object);
|
||||
var mockScopeProvider = TestHelper.ScopeProvider;
|
||||
|
||||
return new MemberUserStore(
|
||||
_mockMemberService.Object,
|
||||
new UmbracoMapper(new MapDefinitionCollection(() => new List<IMapDefinition>()), mockScopeProvider.Object, NullLogger<UmbracoMapper>.Instance),
|
||||
mockScopeProvider.Object,
|
||||
new UmbracoMapper(new MapDefinitionCollection(() => new List<IMapDefinition>()), mockScopeProvider, NullLogger<UmbracoMapper>.Instance),
|
||||
mockScopeProvider,
|
||||
new IdentityErrorDescriber(),
|
||||
Mock.Of<IPublishedSnapshotAccessor>(),
|
||||
Mock.Of<IExternalLoginWithKeyService>(),
|
||||
|
||||
Reference in New Issue
Block a user