* Remove nucache reference from Web.Common * Get tests building-ish * Move ReservedFieldNamesService to the right project * Remove IPublishedSnapshotStatus * Added functionality to the INavigationQueryService to get root keys * Fixed issue with navigation * Remove IPublishedSnapshot from UmbracoContext * Begin removing usage of IPublishedSnapshot from PublishedContentExtensions * Fix PublishedContentExtensions.cs * Don't use snapshots in delivery media api * Use IPublishedMediaCache in QueryMediaApiController * Remove more usages of IPublishedSnapshotAccessor * Comment out tests * Remove more usages of PublishedSnapshotAccessor * Remove PublishedSnapshot from property * Fixed test build * Fix errors * Fix some tests * Delete NuCache 🎉 * Implement DatabaseCacheRebuilder * Remove usage of IPublishedSnapshotService * Remove IPublishedSnapshotService * Remove TestPublishedSnapshotAccessor and make tests build * Don't test Snapshot cachelevel It's no longer supported * Fix BlockEditorConverter Element != Element document type * Remember to set cachemanager * Fix RichTextParserTests * Implement TryGetLevel on INavigationQueryService * Fake level and obsolete it in PublishedContent * Remove ChildrenForAllCultures * Hack Path property on PublishedContent * Remove usages of IPublishedSnapshot in tests * More ConvertersTests * Add hybrid cache to integration tests We can actually do this now because we no longer save files on disk * Rename IPublishedSnapshotRebuilder to ICacheRebuilder * Comment out tests * V15: Replacing the usages of Parent (navigation data) from IPublishedContent (#17125) * Fix .Parent references in PublishedContentExtensions * Add missing methods to FriendlyPublishedContentExtensions (ones that you were able to call on the content directly as they now require extra params) * Fix references from the extension methods * Fix dependencies in tests * Replace IPublishedSnapshotAccessor with the content cache in tests * Resolving more .Parent references * Fix unit tests * Obsolete and use extension methods * Remove private method and use extension instead * Moving code around * Fix tests * Fix more references * Cleanup * Fix more usages * Resolve merge conflict * Fix tests * Cleanup * Fix more tests * Fixed unit tests * Cleanup * Replace last usages --------- Co-authored-by: Bjarke Berg <mail@bergmania.dk> * Remove usage of IPublishedSnapshotAccessor from IRequestItemProvider * Post merge fixup * Remo IPublishedSnapshot * Add HasAny to IDocumentUrlService * Fix TextBuilder * Fix modelsbuilder tests * Use explicit types * Implement GetByContentType * Support element types in PublishedContentTypeCache * Run enlistments before publishing notifications * Fix elements cache refreshing * Implement GetByUdi * Implement GetAtRoot * Implement GetByRoute * Reimplement GetRouteById * Fix blocks unit tests * Initialize domain cache on boot * Only return routes with domains on non default lanauges * V15: Replacing the usages of `Children` (navigation data) from `IPublishedContent` (#17159) * Update params in PublishedContentExtensions to the general interfaces for the published cache and navigation service, so that we can use the extension methods on both documents and media * Introduce GetParent() which uses the right services * Fix obsolete message on .Parent * Obsolete .Children * Fix usages of Children for ApiMediaQueryService * Fix usage in internal * Fix usages in views * Fix indentation * Fix issue with delete language * Update nuget pacakges * Clear elements cache when content is deleted instead of trying to update it * Reset publishedModelFactory * Fixed publishing --------- Co-authored-by: Bjarke Berg <mail@bergmania.dk> Co-authored-by: Elitsa Marinovska <21998037+elit0451@users.noreply.github.com> Co-authored-by: kjac <kja@umbraco.dk>
256 lines
7.7 KiB
C#
256 lines
7.7 KiB
C#
// Copyright (c) Umbraco.
|
|
// See LICENSE for more details.
|
|
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using Microsoft.Extensions.DependencyInjection;
|
|
using Microsoft.Extensions.Logging.Abstractions;
|
|
using Microsoft.Extensions.Options;
|
|
using Moq;
|
|
using NPoco;
|
|
using NUnit.Framework;
|
|
using Umbraco.Cms.Core.Cache;
|
|
using Umbraco.Cms.Core.Configuration.Models;
|
|
using Umbraco.Cms.Core.Events;
|
|
using Umbraco.Cms.Core.PublishedCache;
|
|
using Umbraco.Cms.Core.Services;
|
|
using Umbraco.Cms.Core.Sync;
|
|
using Umbraco.Cms.Infrastructure.Migrations;
|
|
using Umbraco.Cms.Infrastructure.Migrations.Upgrade;
|
|
using Umbraco.Cms.Infrastructure.Persistence;
|
|
using Umbraco.Cms.Infrastructure.Scoping;
|
|
using Umbraco.Cms.Persistence.SqlServer.Services;
|
|
using Umbraco.Cms.Tests.Common.TestHelpers;
|
|
using Umbraco.Cms.Tests.UnitTests.TestHelpers;
|
|
using Umbraco.Extensions;
|
|
|
|
namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Infrastructure.Migrations;
|
|
|
|
[TestFixture]
|
|
public class MigrationPlanTests
|
|
{
|
|
[Test]
|
|
public void CanExecute()
|
|
{
|
|
var loggerFactory = NullLoggerFactory.Instance;
|
|
|
|
var database = new TestDatabase();
|
|
var scope = Mock.Of<IScope>(x => x.Notifications == Mock.Of<IScopedNotificationPublisher>());
|
|
Mock.Get(scope)
|
|
.Setup(x => x.Database)
|
|
.Returns(database);
|
|
|
|
var databaseFactory = Mock.Of<IUmbracoDatabaseFactory>();
|
|
Mock.Get(databaseFactory)
|
|
.Setup(x => x.CreateDatabase())
|
|
.Returns(database);
|
|
|
|
var sqlContext = new SqlContext(
|
|
new SqlServerSyntaxProvider(Options.Create(new GlobalSettings())),
|
|
DatabaseType.SQLCe,
|
|
Mock.Of<IPocoDataFactory>());
|
|
var scopeProvider = new MigrationTests.TestScopeProvider(scope) { SqlContext = sqlContext };
|
|
|
|
var migrationBuilder = Mock.Of<IMigrationBuilder>();
|
|
Mock.Get(migrationBuilder)
|
|
.Setup(x => x.Build(It.IsAny<Type>(), It.IsAny<IMigrationContext>()))
|
|
.Returns<Type, IMigrationContext>((t, c) =>
|
|
{
|
|
switch (t.Name)
|
|
{
|
|
case "DeleteRedirectUrlTable":
|
|
return new DeleteRedirectUrlTable(c);
|
|
case "NoopMigration":
|
|
return new NoopMigration(c);
|
|
default:
|
|
throw new NotSupportedException();
|
|
}
|
|
});
|
|
|
|
var distributedCache = new DistributedCache(
|
|
Mock.Of<IServerMessenger>(),
|
|
new CacheRefresherCollection(() => Enumerable.Empty<ICacheRefresher>()));
|
|
|
|
var executor = new MigrationPlanExecutor(
|
|
scopeProvider,
|
|
scopeProvider,
|
|
loggerFactory,
|
|
migrationBuilder,
|
|
databaseFactory,
|
|
Mock.Of<IDatabaseCacheRebuilder>(), distributedCache, Mock.Of<IKeyValueService>(), Mock.Of<IServiceScopeFactory>());
|
|
|
|
var plan = new MigrationPlan("default")
|
|
.From(string.Empty)
|
|
.To<DeleteRedirectUrlTable>("{4A9A1A8F-0DA1-4BCF-AD06-C19D79152E35}")
|
|
.To<NoopMigration>("VERSION.33");
|
|
|
|
var kvs = Mock.Of<IKeyValueService>();
|
|
Mock.Get(kvs).Setup(x => x.GetValue(It.IsAny<string>()))
|
|
.Returns<string>(k => k == "Umbraco.Tests.MigrationPlan" ? string.Empty : null);
|
|
|
|
string state;
|
|
using (var s = scopeProvider.CreateScope())
|
|
{
|
|
// read current state
|
|
var sourceState = kvs.GetValue("Umbraco.Tests.MigrationPlan") ?? string.Empty;
|
|
|
|
// execute plan
|
|
var result = executor.ExecutePlan(plan, sourceState);
|
|
state = result.FinalState;
|
|
|
|
// save new state
|
|
kvs.SetValue("Umbraco.Tests.MigrationPlan", sourceState, state);
|
|
|
|
s.Complete();
|
|
}
|
|
|
|
Assert.AreEqual("VERSION.33", state);
|
|
Assert.AreEqual(1, database.Operations.Count);
|
|
Assert.AreEqual("DROP TABLE [umbracoRedirectUrl]", database.Operations[0].Sql);
|
|
}
|
|
|
|
[Test]
|
|
public void CanAddMigrations()
|
|
{
|
|
var plan = new MigrationPlan("default");
|
|
plan
|
|
.From(string.Empty)
|
|
.To("aaa")
|
|
.To("bbb")
|
|
.To("ccc");
|
|
}
|
|
|
|
[Test]
|
|
public void CannotTransitionToSameState()
|
|
{
|
|
var plan = new MigrationPlan("default");
|
|
Assert.Throws<ArgumentException>(() => plan.From("aaa").To("aaa"));
|
|
}
|
|
|
|
[Test]
|
|
public void OnlyOneTransitionPerState()
|
|
{
|
|
var plan = new MigrationPlan("default");
|
|
plan.From("aaa").To("bbb");
|
|
Assert.Throws<InvalidOperationException>(() => plan.From("aaa").To("ccc"));
|
|
}
|
|
|
|
[Test]
|
|
public void CannotContainTwoMoreHeads()
|
|
{
|
|
var plan = new MigrationPlan("default");
|
|
plan
|
|
.From(string.Empty)
|
|
.To("aaa")
|
|
.To("bbb")
|
|
.From("ccc")
|
|
.To("ddd");
|
|
Assert.Throws<InvalidOperationException>(() => plan.Validate());
|
|
}
|
|
|
|
[Test]
|
|
public void CannotContainLoops()
|
|
{
|
|
var plan = new MigrationPlan("default");
|
|
plan
|
|
.From("aaa")
|
|
.To("bbb")
|
|
.To("ccc")
|
|
.To("aaa");
|
|
Assert.Throws<InvalidOperationException>(() => plan.Validate());
|
|
}
|
|
|
|
[Test]
|
|
public void ValidateUmbracoPlan()
|
|
{
|
|
var plan = new UmbracoPlan(TestHelper.GetUmbracoVersion());
|
|
plan.Validate();
|
|
Console.WriteLine(plan.FinalState);
|
|
Assert.IsFalse(plan.FinalState.IsNullOrWhiteSpace());
|
|
}
|
|
|
|
[Test]
|
|
public void CanClone()
|
|
{
|
|
var plan = new MigrationPlan("default");
|
|
plan
|
|
.From(string.Empty)
|
|
.To("aaa")
|
|
.To("bbb")
|
|
.To("ccc")
|
|
.To("ddd")
|
|
.To("eee");
|
|
|
|
plan
|
|
.From("xxx")
|
|
.ToWithClone("bbb", "ddd", "yyy")
|
|
.To("eee");
|
|
|
|
WritePlanToConsole(plan);
|
|
|
|
plan.Validate();
|
|
Assert.AreEqual("eee", plan.FollowPath("xxx").Last());
|
|
Assert.AreEqual("yyy", plan.FollowPath("xxx", "yyy").Last());
|
|
}
|
|
|
|
[Test]
|
|
public void CanMerge()
|
|
{
|
|
var plan = new MigrationPlan("default");
|
|
plan
|
|
.From(string.Empty)
|
|
.To("aaa")
|
|
.Merge()
|
|
.To("bbb")
|
|
.To("ccc")
|
|
.With()
|
|
.To("ddd")
|
|
.To("eee")
|
|
.As("fff")
|
|
.To("ggg");
|
|
|
|
WritePlanToConsole(plan);
|
|
|
|
plan.Validate();
|
|
AssertList(plan.FollowPath(), string.Empty, "aaa", "bbb", "ccc", "*", "*", "fff", "ggg");
|
|
AssertList(plan.FollowPath("ccc"), "ccc", "*", "*", "fff", "ggg");
|
|
AssertList(plan.FollowPath("eee"), "eee", "*", "*", "fff", "ggg");
|
|
}
|
|
|
|
private void AssertList(IReadOnlyList<string> states, params string[] expected)
|
|
{
|
|
Assert.AreEqual(expected.Length, states.Count, string.Join(", ", states));
|
|
for (var i = 0; i < expected.Length; i++)
|
|
{
|
|
if (expected[i] != "*")
|
|
{
|
|
Assert.AreEqual(expected[i], states[i], "at:" + i);
|
|
}
|
|
}
|
|
}
|
|
|
|
private void WritePlanToConsole(MigrationPlan plan)
|
|
{
|
|
var final = plan.Transitions.First(x => x.Value == null).Key;
|
|
|
|
Console.WriteLine("plan \"{0}\" to final state \"{1}\":", plan.Name, final);
|
|
foreach ((var _, var transition) in plan.Transitions)
|
|
{
|
|
if (transition != null)
|
|
{
|
|
Console.WriteLine(transition);
|
|
}
|
|
}
|
|
}
|
|
|
|
public class DeleteRedirectUrlTable : MigrationBase
|
|
{
|
|
public DeleteRedirectUrlTable(IMigrationContext context)
|
|
: base(context)
|
|
{
|
|
}
|
|
|
|
protected override void Migrate() => Delete.Table("umbracoRedirectUrl").Do();
|
|
}
|
|
}
|