2020-12-23 11:35:49 +01:00
|
|
|
// Copyright (c) Umbraco.
|
|
|
|
|
// See LICENSE for more details.
|
|
|
|
|
|
2018-06-29 19:52:40 +02:00
|
|
|
using System.Collections.Generic;
|
|
|
|
|
using System.Linq;
|
2020-09-17 10:35:11 +02:00
|
|
|
using Microsoft.Extensions.Logging;
|
2020-12-23 11:35:49 +01:00
|
|
|
using Microsoft.Extensions.Options;
|
2021-04-20 12:17:11 +02:00
|
|
|
using Moq;
|
2018-06-29 19:52:40 +02:00
|
|
|
using NUnit.Framework;
|
2021-02-09 10:22:42 +01:00
|
|
|
using Umbraco.Cms.Core;
|
|
|
|
|
using Umbraco.Cms.Core.Cache;
|
|
|
|
|
using Umbraco.Cms.Core.Configuration.Models;
|
2021-04-20 12:17:11 +02:00
|
|
|
using Umbraco.Cms.Core.Events;
|
2021-02-09 10:22:42 +01:00
|
|
|
using Umbraco.Cms.Core.IO;
|
|
|
|
|
using Umbraco.Cms.Core.Models;
|
|
|
|
|
using Umbraco.Cms.Core.Persistence;
|
|
|
|
|
using Umbraco.Cms.Core.PropertyEditors;
|
|
|
|
|
using Umbraco.Cms.Core.Serialization;
|
|
|
|
|
using Umbraco.Cms.Core.Services;
|
2021-02-12 13:36:50 +01:00
|
|
|
using Umbraco.Cms.Infrastructure.Persistence;
|
|
|
|
|
using Umbraco.Cms.Infrastructure.Persistence.Repositories.Implement;
|
2022-01-13 17:44:11 +00:00
|
|
|
using Umbraco.Cms.Infrastructure.Scoping;
|
v10 SQLite support + distributed locking abstractions (#11922)
* Created Persistence.SQLite project skeleton.
* SQLite database initialization
* Various changes and hacks to make things work.
* WIP integration tests
* Fix thread safety tests
* Fix tests that relied on tie breaker sorting.
Spent a fair amount of time looking for a less lazy fix but gave up.
* Convert right join to left join ContentTypeRepository.PerformGetByQuery
SQLite doesn't support right join
* Fix test Can_Generate_Delete_SubQuery_Statement
Worth noting that NPoco.DatabaseTypes.SQLiteDatabaseType doesn't override
EscapeSqlIdentifier so NPoco will escape with [].
SQLite docs say > "A keyword enclosed in square brackets is an identifier.
This is not standard SQL.
This quoting mechanism is used by MS Access and SQL Server and is
included in SQLite for compatibility."
Also could have updated SqliteSyntaxProvider to match npoco but
decided against it.
* Fixes for paginated custom order by
* Fix tests broken by lack of unique indexes.
* Fix SqlServerTableByTableTest tests.
These tests didn't actually do anything as the tables already exist so schema creator just returned.
Did however point out that the default implementation for DoesTableExist just returns false so added a default naive implementation.
* Fix ValidateLoginSession - SelectTop must come later
* dry up database cleanup
* Fix up db migration tests.
We can't drop pk in sqlite without recreating table.
Test looks to be testing that add column works as intended which we can test.
* Prevent schema creation errors.
* SQLite ignore lock tests, WAL back on.
* Fix package schema tests
* Fix NPocoFetchTests - case sensitivity not under test
* Fix AdvancedMigrationTests (where possible)
Migrations probably need a good look later.
Maybe nuke old migrations and only support moving to v10 from v9.
If we do that can do some cleanup.
* Cleanup test database configuration
* Run integration tests against SQLite on build agent.
* Drop MS.Data.SQLite
System.Data.SQLite was quicker to roll out due to more CLR type mapping
* YAML
* Skip Umbraco.Tests.Integration.SqlCe
* Drop SqlServerTableByTable tests.
Until this week they did nothing anyway as they with NewSchemaPerTest
so the tests all passed as CreateTable was no op (already exists).
Also all of the tables are created in an empty database by SchemaValidationTest.cs
DatabaseSchemaCreation_Produces_DatabaseSchemaResult_With_Zero_Errors
* Might aswell run against macOS also.
* Copy azure pipelines task header layout
* Delete SQLCe projects
* Remove SQL CE specific code.
* Remove SQL CE NuSpec, template params, build script setup
* Delete umbraco-netcore-only.sln
* Add SkipTests solution configuration and use for codeql
* Remove reference to deleted nuspec file.
* Refactor ConnectionStrings WRT DataDirectory placeholder & ProviderName.
At this point you can try out SQLite support by setting the following
in appsettings.json and then completing the install process.
"ConnectionStrings": {
"umbracoDbDSN": "Data Source=|DataDirectory|/umbraco.sqlite",
"umbracoDbDSN_ProviderName": "System.Data.SQLite"
},
Not currently possible via installer UI without provider name pre-set in
configuration.
* Switch to Microsoft.Data.Sqlite
Some gross hacks but will be good to find out if this works
with apple silicon.
* Enable selection of SQLite via installer UI (also quick install)
* Remove SqlServerDbProviderFactoryCreator to cleanup a TODO
* Move SQL Server support to its own class library
* Add persistence dependencies to Umbraco.CMS metapackage
* Bugfix packages delete query
Created invalid query for SQLite.
* Try out cypress tests Linux + SQLite
* Prevent cypress test artifact upload failure on attempt 2+
* LocalDb bugfixes
* Drop redundant enum
* Move SqlClient constant
* Misc whitespace
* Remove IsSqlCe extension (TODO: drop non 9->10 migrations later).
* Umbraco.Persistence.* -> Umbraco.Cms.Persistence.*
* Display quick install defaults and per provider default database name.
* Misc remove old comment
* little re-arrange
* Remove almost all usages of IsSqlite extension.
* visual adjustments
* Custom Database Configuration is last step and should then say Install.
* use text instead of disabled inputs
* move legend, rename to Install
* Update SqlMainDomLock to work without distributed locks.
* Added IDistributedLockingMechanism interface and in memory impl.
* Drop locking from ISqlSyntaxProvider & wire up scope to abstraction.
* Added SqlServerDistributedLockingMechanism
* Move distributed locking interfaces and exceptions to Core + xmldocs.
* Fix tests, Misc cleanup, Add SQL distributed locking integration tests
* Provide mechanism to specify DistributedLockingMechanism in config
(even if added by composer)
* Nomplementation -> NoImplementation
* Fix misleading comment
* Integration tests use SqlServerDistributedLockingMechanism when possible
* Handle up-gradable locks SqlServerDistributedLockingMechanism.
TODO: InMemoryDistributedLockingMechanism.
Note: Nuked SqlServerDistributedLockingMechanismTests, will still sleep
at night.
Is covered by Umbraco.Cms.Tests.Integration.Umbraco.Infrastructure.Persistence.LockTests
* Make tests pass for InMemoryDistributedLockingMechanism, pretty hacky.
* Tweak constraints on WithCollectionBuilder so i can drop bad constructor
* Added SqliteDistributedLockingMechanism
* Dropped InMemoryDistributedMechanism + magic
InMemoryDistributedMechanism was pretty rubbish and now we have
a decent implementation for SQLite as we no longer block readers
see 8d1f42b.
Also drop the CollectionBuilder setup, instead do the same as we do
for syntax providers etc, it's more automagical so we never require an
explicit selection although we are allowing for it.
However keeping the optional IUmbracoBuilder constructor param for
CollectionBuilders as it's extremely useful.
* Fix quick install "" database name.
* Hide Database Configuration section when a connection string is pre-set.
Doesn't seem worth it to extract db name from connection string.
* Ensure wal test 2+
* Fix logging inconsistencies.
* Ensure in transaction when obtaining locks + no-op the SQLite read lock.
There's no point in running the query just to make a single test pass.
* Fix installer database display names
* Allow SQLite shared cache without losing deferred transactions
* Opt into shared cache for new SQLite databases + fix filename
* Fix misc inconsistency in .gitignore
* Prefer our interceptor interface
* Restore DEBUG_DATABASES code OnConnectionOpened in case it's used.
* Back to private cache.
* Added retry strategy for SQLite + refactor out SQL server specific stuff
* Fix SQL server tests.
* Misc - Orphaned comment, incorrect casing.
* InMemory SQLite test database & turn shared cache back on everywhere.
Co-authored-by: Niels Lyngsø <niels.lyngso@gmail.com>
2022-03-11 16:14:20 +00:00
|
|
|
using Umbraco.Cms.Persistence.SqlServer.Services;
|
2023-09-12 14:16:27 +02:00
|
|
|
using Umbraco.Cms.Tests.Common.Attributes;
|
2021-02-10 14:45:44 +01:00
|
|
|
using Umbraco.Cms.Tests.Common.Builders;
|
|
|
|
|
using Umbraco.Cms.Tests.Common.Testing;
|
2021-02-11 08:30:27 +01:00
|
|
|
using Umbraco.Cms.Tests.Integration.Testing;
|
2021-02-09 11:26:22 +01:00
|
|
|
using Umbraco.Extensions;
|
2018-06-29 19:52:40 +02:00
|
|
|
|
2022-06-21 08:09:38 +02:00
|
|
|
namespace Umbraco.Cms.Tests.Integration.Umbraco.Infrastructure.Persistence.Repositories;
|
2022-04-26 10:22:37 +01:00
|
|
|
|
2022-06-21 08:09:38 +02:00
|
|
|
[TestFixture]
|
|
|
|
|
[UmbracoTest(Database = UmbracoTestOptions.Database.NewSchemaPerTest)]
|
|
|
|
|
public class DocumentRepositoryTest : UmbracoIntegrationTest
|
2018-06-29 19:52:40 +02:00
|
|
|
{
|
2022-06-21 08:09:38 +02:00
|
|
|
[SetUp]
|
|
|
|
|
public void SetUpData()
|
2018-06-29 19:52:40 +02:00
|
|
|
{
|
2022-06-21 08:09:38 +02:00
|
|
|
CreateTestData();
|
2020-10-09 13:08:23 +02:00
|
|
|
|
2022-06-21 08:09:38 +02:00
|
|
|
ContentRepositoryBase.ThrowOnWarning = true;
|
|
|
|
|
}
|
2020-12-23 11:35:49 +01:00
|
|
|
|
2022-06-21 08:09:38 +02:00
|
|
|
[TearDown]
|
|
|
|
|
public void Teardown() => ContentRepositoryBase.ThrowOnWarning = false;
|
2020-12-23 11:35:49 +01:00
|
|
|
|
2022-06-21 08:09:38 +02:00
|
|
|
private ContentType _contentType;
|
|
|
|
|
private Content _textpage;
|
|
|
|
|
private Content _subpage;
|
|
|
|
|
private Content _subpage2;
|
|
|
|
|
private Content _trashed;
|
2020-12-23 11:35:49 +01:00
|
|
|
|
2022-06-21 08:09:38 +02:00
|
|
|
private IContentService ContentService => GetRequiredService<IContentService>();
|
2020-12-23 11:35:49 +01:00
|
|
|
|
2022-06-21 08:09:38 +02:00
|
|
|
private IContentTypeService ContentTypeService => GetRequiredService<IContentTypeService>();
|
2020-10-09 13:08:23 +02:00
|
|
|
|
2022-06-21 08:09:38 +02:00
|
|
|
private IFileService FileService => GetRequiredService<IFileService>();
|
2018-06-29 19:52:40 +02:00
|
|
|
|
2022-06-21 08:09:38 +02:00
|
|
|
private IDataTypeService DataTypeService => GetRequiredService<IDataTypeService>();
|
2018-06-29 19:52:40 +02:00
|
|
|
|
2022-06-21 08:09:38 +02:00
|
|
|
private FileSystems FileSystems => GetRequiredService<FileSystems>();
|
2018-06-29 19:52:40 +02:00
|
|
|
|
2022-06-21 08:09:38 +02:00
|
|
|
private IConfigurationEditorJsonSerializer ConfigurationEditorJsonSerializer =>
|
|
|
|
|
GetRequiredService<IConfigurationEditorJsonSerializer>();
|
2020-10-09 13:08:23 +02:00
|
|
|
|
2022-06-21 08:09:38 +02:00
|
|
|
public void CreateTestData()
|
|
|
|
|
{
|
|
|
|
|
var template = TemplateBuilder.CreateTextPageTemplate();
|
|
|
|
|
FileService.SaveTemplate(template);
|
|
|
|
|
|
|
|
|
|
// Create and Save ContentType "umbTextpage" -> (_contentType.Id)
|
|
|
|
|
_contentType =
|
|
|
|
|
ContentTypeBuilder.CreateSimpleContentType("umbTextpage", "Textpage", defaultTemplateId: template.Id);
|
|
|
|
|
_contentType.Key = new Guid("1D3A8E6E-2EA9-4CC1-B229-1AEE19821522");
|
|
|
|
|
ContentTypeService.Save(_contentType);
|
|
|
|
|
|
|
|
|
|
// Create and Save Content "Homepage" based on "umbTextpage" -> (_textpage.Id)
|
|
|
|
|
_textpage = ContentBuilder.CreateSimpleContent(_contentType);
|
|
|
|
|
_textpage.Key = new Guid("B58B3AD4-62C2-4E27-B1BE-837BD7C533E0");
|
2023-08-16 23:37:10 +02:00
|
|
|
ContentService.Save(_textpage, -1);
|
2022-06-21 08:09:38 +02:00
|
|
|
|
|
|
|
|
// Create and Save Content "Text Page 1" based on "umbTextpage" -> (_subpage.Id)
|
|
|
|
|
_subpage = ContentBuilder.CreateSimpleContent(_contentType, "Text Page 1", _textpage.Id);
|
|
|
|
|
_subpage.Key = new Guid("FF11402B-7E53-4654-81A7-462AC2108059");
|
2023-08-16 23:37:10 +02:00
|
|
|
ContentService.Save(_subpage, -1);
|
2022-06-21 08:09:38 +02:00
|
|
|
|
|
|
|
|
// Create and Save Content "Text Page 1" based on "umbTextpage" -> (_subpage2.Id)
|
|
|
|
|
_subpage2 = ContentBuilder.CreateSimpleContent(_contentType, "Text Page 2", _textpage.Id);
|
2023-08-16 23:37:10 +02:00
|
|
|
ContentService.Save(_subpage2, -1);
|
2022-06-21 08:09:38 +02:00
|
|
|
|
|
|
|
|
// Create and Save Content "Text Page Deleted" based on "umbTextpage" -> (_trashed.Id)
|
|
|
|
|
_trashed = ContentBuilder.CreateSimpleContent(_contentType, "Text Page Deleted", -20);
|
|
|
|
|
_trashed.Trashed = true;
|
2023-08-16 23:37:10 +02:00
|
|
|
ContentService.Save(_trashed, -1);
|
2022-06-21 08:09:38 +02:00
|
|
|
}
|
2020-10-09 13:08:23 +02:00
|
|
|
|
2022-06-21 08:09:38 +02:00
|
|
|
private DocumentRepository CreateRepository(IScopeAccessor scopeAccessor, out ContentTypeRepository contentTypeRepository, out DataTypeRepository dtdRepository, AppCaches appCaches = null)
|
|
|
|
|
{
|
|
|
|
|
appCaches ??= AppCaches;
|
2018-06-29 19:52:40 +02:00
|
|
|
|
2022-06-21 08:09:38 +02:00
|
|
|
var ctRepository = CreateRepository(scopeAccessor, out contentTypeRepository, out TemplateRepository tr);
|
|
|
|
|
var editors = new PropertyEditorCollection(new DataEditorCollection(() => Enumerable.Empty<IDataEditor>()));
|
|
|
|
|
dtdRepository = new DataTypeRepository(scopeAccessor, appCaches, editors, LoggerFactory.CreateLogger<DataTypeRepository>(), LoggerFactory, ConfigurationEditorJsonSerializer);
|
|
|
|
|
return ctRepository;
|
|
|
|
|
}
|
2018-06-29 19:52:40 +02:00
|
|
|
|
2022-06-21 08:09:38 +02:00
|
|
|
private DocumentRepository CreateRepository(IScopeAccessor scopeAccessor, out ContentTypeRepository contentTypeRepository, AppCaches appCaches = null) =>
|
|
|
|
|
CreateRepository(scopeAccessor, out contentTypeRepository, out TemplateRepository tr, appCaches);
|
2018-06-29 19:52:40 +02:00
|
|
|
|
2022-06-21 08:09:38 +02:00
|
|
|
private DocumentRepository CreateRepository(IScopeAccessor scopeAccessor, out ContentTypeRepository contentTypeRepository, out TemplateRepository templateRepository, AppCaches appCaches = null)
|
|
|
|
|
{
|
|
|
|
|
appCaches ??= AppCaches;
|
|
|
|
|
|
2022-07-15 14:17:45 +02:00
|
|
|
var runtimeSettingsMock = new Mock<IOptionsMonitor<RuntimeSettings>>();
|
|
|
|
|
runtimeSettingsMock.Setup(x => x.CurrentValue).Returns(new RuntimeSettings());
|
|
|
|
|
|
|
|
|
|
templateRepository = new TemplateRepository(scopeAccessor, appCaches, LoggerFactory.CreateLogger<TemplateRepository>(), FileSystems, IOHelper, ShortStringHelper, Mock.Of<IViewHelper>(), runtimeSettingsMock.Object);
|
2022-06-21 08:09:38 +02:00
|
|
|
var tagRepository = new TagRepository(scopeAccessor, appCaches, LoggerFactory.CreateLogger<TagRepository>());
|
|
|
|
|
var commonRepository =
|
|
|
|
|
new ContentTypeCommonRepository(scopeAccessor, templateRepository, appCaches, ShortStringHelper);
|
|
|
|
|
var languageRepository =
|
|
|
|
|
new LanguageRepository(scopeAccessor, appCaches, LoggerFactory.CreateLogger<LanguageRepository>());
|
|
|
|
|
contentTypeRepository = new ContentTypeRepository(scopeAccessor, appCaches, LoggerFactory.CreateLogger<ContentTypeRepository>(), commonRepository, languageRepository, ShortStringHelper);
|
|
|
|
|
var relationTypeRepository = new RelationTypeRepository(scopeAccessor, AppCaches.Disabled, LoggerFactory.CreateLogger<RelationTypeRepository>());
|
|
|
|
|
var entityRepository = new EntityRepository(scopeAccessor, AppCaches.Disabled);
|
|
|
|
|
var relationRepository = new RelationRepository(scopeAccessor, LoggerFactory.CreateLogger<RelationRepository>(), relationTypeRepository, entityRepository);
|
|
|
|
|
var propertyEditors =
|
|
|
|
|
new PropertyEditorCollection(new DataEditorCollection(() => Enumerable.Empty<IDataEditor>()));
|
|
|
|
|
var dataValueReferences =
|
|
|
|
|
new DataValueReferenceFactoryCollection(() => Enumerable.Empty<IDataValueReferenceFactory>());
|
|
|
|
|
var repository = new DocumentRepository(
|
|
|
|
|
scopeAccessor,
|
|
|
|
|
appCaches,
|
|
|
|
|
LoggerFactory.CreateLogger<DocumentRepository>(),
|
|
|
|
|
LoggerFactory,
|
|
|
|
|
contentTypeRepository,
|
|
|
|
|
templateRepository,
|
|
|
|
|
tagRepository,
|
|
|
|
|
languageRepository,
|
|
|
|
|
relationRepository,
|
|
|
|
|
relationTypeRepository,
|
|
|
|
|
propertyEditors,
|
|
|
|
|
dataValueReferences,
|
|
|
|
|
DataTypeService,
|
|
|
|
|
ConfigurationEditorJsonSerializer,
|
|
|
|
|
Mock.Of<IEventAggregator>());
|
|
|
|
|
return repository;
|
|
|
|
|
}
|
2018-06-29 19:52:40 +02:00
|
|
|
|
2022-06-21 08:09:38 +02:00
|
|
|
[Test]
|
|
|
|
|
public void CacheActiveForIntsAndGuids()
|
|
|
|
|
{
|
|
|
|
|
var realCache = new AppCaches(
|
|
|
|
|
new ObjectCacheAppCache(),
|
|
|
|
|
new DictionaryAppCache(),
|
|
|
|
|
new IsolatedCaches(t => new ObjectCacheAppCache()));
|
2018-06-29 19:52:40 +02:00
|
|
|
|
2022-06-21 08:09:38 +02:00
|
|
|
var provider = ScopeProvider;
|
|
|
|
|
var scopeAccessor = ScopeAccessor;
|
2022-01-13 17:44:11 +00:00
|
|
|
|
2022-06-21 08:09:38 +02:00
|
|
|
using (var scope = provider.CreateScope())
|
|
|
|
|
{
|
|
|
|
|
var repository = CreateRepository((IScopeAccessor)provider, out var contentTypeRepository, realCache);
|
2018-06-29 19:52:40 +02:00
|
|
|
|
2022-06-21 08:09:38 +02:00
|
|
|
var udb = scopeAccessor.AmbientScope.Database;
|
2018-06-29 19:52:40 +02:00
|
|
|
|
2022-06-21 08:09:38 +02:00
|
|
|
udb.EnableSqlCount = false;
|
2018-06-29 19:52:40 +02:00
|
|
|
|
2022-06-21 08:09:38 +02:00
|
|
|
var template = TemplateBuilder.CreateTextPageTemplate();
|
|
|
|
|
FileService.SaveTemplate(template);
|
|
|
|
|
var contentType =
|
|
|
|
|
ContentTypeBuilder.CreateSimpleContentType("umbTextpage1", "Textpage", defaultTemplateId: template.Id);
|
2020-10-09 13:08:23 +02:00
|
|
|
|
2022-06-21 08:09:38 +02:00
|
|
|
contentTypeRepository.Save(contentType);
|
|
|
|
|
var content = ContentBuilder.CreateSimpleContent(contentType);
|
|
|
|
|
repository.Save(content);
|
2018-06-29 19:52:40 +02:00
|
|
|
|
2022-06-21 08:09:38 +02:00
|
|
|
udb.EnableSqlCount = true;
|
2018-06-29 19:52:40 +02:00
|
|
|
|
2022-06-21 08:09:38 +02:00
|
|
|
// go get it, this should already be cached since the default repository key is the INT
|
|
|
|
|
repository.Get(content.Id);
|
|
|
|
|
Assert.AreEqual(0, udb.SqlCount);
|
2020-12-23 11:35:49 +01:00
|
|
|
|
2022-06-21 08:09:38 +02:00
|
|
|
// retrieve again, this should use cache
|
|
|
|
|
repository.Get(content.Id);
|
|
|
|
|
Assert.AreEqual(0, udb.SqlCount);
|
2018-06-29 19:52:40 +02:00
|
|
|
|
2022-06-21 08:09:38 +02:00
|
|
|
// reset counter
|
|
|
|
|
udb.EnableSqlCount = false;
|
|
|
|
|
udb.EnableSqlCount = true;
|
2018-06-29 19:52:40 +02:00
|
|
|
|
2022-06-21 08:09:38 +02:00
|
|
|
// now get by GUID, this won't be cached yet because the default repo key is not a GUID
|
|
|
|
|
repository.Get(content.Key);
|
|
|
|
|
var sqlCount = udb.SqlCount;
|
|
|
|
|
Assert.Greater(sqlCount, 0);
|
2020-12-23 11:35:49 +01:00
|
|
|
|
2022-06-21 08:09:38 +02:00
|
|
|
// retrieve again, this should use cache now
|
|
|
|
|
repository.Get(content.Key);
|
|
|
|
|
Assert.AreEqual(sqlCount, udb.SqlCount);
|
2018-06-29 19:52:40 +02:00
|
|
|
}
|
2022-06-21 08:09:38 +02:00
|
|
|
}
|
2018-06-29 19:52:40 +02:00
|
|
|
|
2022-06-21 08:09:38 +02:00
|
|
|
[Test]
|
|
|
|
|
public void CreateVersions()
|
|
|
|
|
{
|
|
|
|
|
var provider = ScopeProvider;
|
|
|
|
|
using (var scope = provider.CreateScope())
|
2018-06-29 19:52:40 +02:00
|
|
|
{
|
2022-06-21 08:09:38 +02:00
|
|
|
var repository = CreateRepository((IScopeAccessor)provider, out var contentTypeRepository, out DataTypeRepository _);
|
|
|
|
|
var versions = new List<int>();
|
|
|
|
|
var template = TemplateBuilder.CreateTextPageTemplate();
|
|
|
|
|
FileService.SaveTemplate(template);
|
|
|
|
|
var hasPropertiesContentType =
|
|
|
|
|
ContentTypeBuilder.CreateSimpleContentType("umbTextpage1", "Textpage", defaultTemplateId: template.Id);
|
|
|
|
|
|
|
|
|
|
contentTypeRepository.Save(hasPropertiesContentType);
|
|
|
|
|
|
|
|
|
|
IContent content1 = ContentBuilder.CreateSimpleContent(hasPropertiesContentType);
|
|
|
|
|
|
|
|
|
|
// save = create the initial version
|
|
|
|
|
repository.Save(content1);
|
|
|
|
|
|
|
|
|
|
versions.Add(content1.VersionId); // the first version
|
|
|
|
|
|
|
|
|
|
// publish = new edit version
|
|
|
|
|
content1.SetValue("title", "title");
|
|
|
|
|
content1.PublishCulture(CultureImpact.Invariant);
|
|
|
|
|
content1.PublishedState = PublishedState.Publishing;
|
|
|
|
|
repository.Save(content1);
|
|
|
|
|
|
|
|
|
|
versions.Add(content1.VersionId); // NEW VERSION
|
|
|
|
|
|
|
|
|
|
// new edit version has been created
|
|
|
|
|
Assert.AreNotEqual(versions[^2], versions[^1]);
|
|
|
|
|
Assert.IsTrue(content1.Published);
|
|
|
|
|
Assert.AreEqual(PublishedState.Published, ((Content)content1).PublishedState);
|
|
|
|
|
Assert.AreEqual(versions[^1], repository.Get(content1.Id).VersionId);
|
|
|
|
|
|
|
|
|
|
// misc checks
|
|
|
|
|
Assert.AreEqual(true, ScopeAccessor.AmbientScope.Database.ExecuteScalar<bool>(
|
|
|
|
|
$"SELECT published FROM {Constants.DatabaseSchema.Tables.Document} WHERE nodeId=@id",
|
|
|
|
|
new { id = content1.Id }));
|
|
|
|
|
|
|
|
|
|
// change something
|
|
|
|
|
// save = update the current (draft) version
|
|
|
|
|
content1.Name = "name-1";
|
|
|
|
|
content1.SetValue("title", "title-1");
|
|
|
|
|
repository.Save(content1);
|
|
|
|
|
|
|
|
|
|
versions.Add(content1.VersionId); // the same version
|
|
|
|
|
|
|
|
|
|
// no new version has been created
|
|
|
|
|
Assert.AreEqual(versions[^2], versions[^1]);
|
|
|
|
|
Assert.IsTrue(content1.Published);
|
|
|
|
|
Assert.AreEqual(versions[^1], repository.Get(content1.Id).VersionId);
|
|
|
|
|
|
|
|
|
|
// misc checks
|
|
|
|
|
Assert.AreEqual(
|
|
|
|
|
true,
|
|
|
|
|
ScopeAccessor.AmbientScope.Database.ExecuteScalar<bool>(
|
|
|
|
|
$"SELECT published FROM {Constants.DatabaseSchema.Tables.Document} WHERE nodeId=@id",
|
|
|
|
|
new { id = content1.Id }));
|
|
|
|
|
|
|
|
|
|
// unpublish = no impact on versions
|
|
|
|
|
((Content)content1).PublishedState = PublishedState.Unpublishing;
|
|
|
|
|
repository.Save(content1);
|
|
|
|
|
|
|
|
|
|
versions.Add(content1.VersionId); // the same version
|
|
|
|
|
|
|
|
|
|
// no new version has been created
|
|
|
|
|
Assert.AreEqual(versions[^2], versions[^1]);
|
|
|
|
|
Assert.IsFalse(content1.Published);
|
|
|
|
|
Assert.AreEqual(PublishedState.Unpublished, ((Content)content1).PublishedState);
|
|
|
|
|
Assert.AreEqual(versions[^1], repository.Get(content1.Id).VersionId);
|
|
|
|
|
|
|
|
|
|
// misc checks
|
|
|
|
|
Assert.AreEqual(
|
|
|
|
|
false,
|
|
|
|
|
ScopeAccessor.AmbientScope.Database.ExecuteScalar<bool>(
|
|
|
|
|
$"SELECT published FROM {Constants.DatabaseSchema.Tables.Document} WHERE nodeId=@id",
|
|
|
|
|
new { id = content1.Id }));
|
|
|
|
|
|
|
|
|
|
// change something
|
|
|
|
|
// save = update the current (draft) version
|
|
|
|
|
content1.Name = "name-2";
|
|
|
|
|
content1.SetValue("title", "title-2");
|
|
|
|
|
repository.Save(content1);
|
|
|
|
|
|
|
|
|
|
versions.Add(content1.VersionId); // the same version
|
|
|
|
|
|
|
|
|
|
// no new version has been created
|
|
|
|
|
Assert.AreEqual(versions[^2], versions[^1]);
|
|
|
|
|
Assert.AreEqual(versions[^1], repository.Get(content1.Id).VersionId);
|
|
|
|
|
|
|
|
|
|
// misc checks
|
|
|
|
|
Assert.AreEqual(
|
|
|
|
|
false,
|
|
|
|
|
ScopeAccessor.AmbientScope.Database.ExecuteScalar<bool>(
|
|
|
|
|
$"SELECT published FROM {Constants.DatabaseSchema.Tables.Document} WHERE nodeId=@id",
|
|
|
|
|
new { id = content1.Id }));
|
|
|
|
|
|
|
|
|
|
// publish = version
|
|
|
|
|
content1.PublishCulture(CultureImpact.Invariant);
|
|
|
|
|
content1.PublishedState = PublishedState.Publishing;
|
|
|
|
|
repository.Save(content1);
|
|
|
|
|
|
|
|
|
|
versions.Add(content1.VersionId); // NEW VERSION
|
|
|
|
|
|
|
|
|
|
// new version has been created
|
|
|
|
|
Assert.AreNotEqual(versions[^2], versions[^1]);
|
|
|
|
|
Assert.IsTrue(content1.Published);
|
|
|
|
|
Assert.AreEqual(PublishedState.Published, ((Content)content1).PublishedState);
|
|
|
|
|
Assert.AreEqual(versions[^1], repository.Get(content1.Id).VersionId);
|
|
|
|
|
|
|
|
|
|
// misc checks
|
|
|
|
|
Assert.AreEqual(
|
|
|
|
|
true,
|
|
|
|
|
ScopeAccessor.AmbientScope.Database.ExecuteScalar<bool>(
|
|
|
|
|
$"SELECT published FROM {Constants.DatabaseSchema.Tables.Document} WHERE nodeId=@id",
|
|
|
|
|
new { id = content1.Id }));
|
|
|
|
|
|
|
|
|
|
// change something
|
|
|
|
|
// save = update the current (draft) version
|
|
|
|
|
content1.Name = "name-3";
|
|
|
|
|
content1.SetValue("title", "title-3");
|
|
|
|
|
|
|
|
|
|
//// Thread.Sleep(2000); // force date change
|
|
|
|
|
|
|
|
|
|
repository.Save(content1);
|
|
|
|
|
|
|
|
|
|
versions.Add(content1.VersionId); // the same version
|
|
|
|
|
|
|
|
|
|
// no new version has been created
|
|
|
|
|
Assert.AreEqual(versions[^2], versions[^1]);
|
|
|
|
|
Assert.AreEqual(versions[^1], repository.Get(content1.Id).VersionId);
|
|
|
|
|
|
|
|
|
|
// misc checks
|
|
|
|
|
Assert.AreEqual(
|
|
|
|
|
true,
|
|
|
|
|
ScopeAccessor.AmbientScope.Database.ExecuteScalar<bool>(
|
|
|
|
|
$"SELECT published FROM {Constants.DatabaseSchema.Tables.Document} WHERE nodeId=@id",
|
|
|
|
|
new { id = content1.Id }));
|
|
|
|
|
|
|
|
|
|
// publish = new version
|
|
|
|
|
content1.Name = "name-4";
|
|
|
|
|
content1.SetValue("title", "title-4");
|
|
|
|
|
content1.PublishCulture(CultureImpact.Invariant);
|
|
|
|
|
content1.PublishedState = PublishedState.Publishing;
|
|
|
|
|
repository.Save(content1);
|
|
|
|
|
|
|
|
|
|
versions.Add(content1.VersionId); // NEW VERSION
|
|
|
|
|
|
|
|
|
|
// a new version has been created
|
|
|
|
|
Assert.AreNotEqual(versions[^2], versions[^1]);
|
|
|
|
|
Assert.IsTrue(content1.Published);
|
|
|
|
|
Assert.AreEqual(PublishedState.Published, ((Content)content1).PublishedState);
|
|
|
|
|
Assert.AreEqual(versions[^1], repository.Get(content1.Id).VersionId);
|
|
|
|
|
|
|
|
|
|
// misc checks
|
|
|
|
|
Assert.AreEqual(
|
|
|
|
|
true,
|
|
|
|
|
ScopeAccessor.AmbientScope.Database.ExecuteScalar<bool>(
|
|
|
|
|
$"SELECT published FROM {Constants.DatabaseSchema.Tables.Document} WHERE nodeId=@id",
|
|
|
|
|
new { id = content1.Id }));
|
|
|
|
|
|
|
|
|
|
// all versions
|
|
|
|
|
var allVersions = repository.GetAllVersions(content1.Id).ToArray();
|
|
|
|
|
Console.WriteLine();
|
|
|
|
|
foreach (var v in versions)
|
2018-06-29 19:52:40 +02:00
|
|
|
{
|
2022-06-21 08:09:38 +02:00
|
|
|
Console.WriteLine(v);
|
|
|
|
|
}
|
2020-12-23 11:35:49 +01:00
|
|
|
|
2022-06-21 08:09:38 +02:00
|
|
|
Console.WriteLine();
|
|
|
|
|
foreach (var v in allVersions)
|
|
|
|
|
{
|
|
|
|
|
var c = (Content)v;
|
|
|
|
|
Console.WriteLine(
|
|
|
|
|
$"{c.Id} {c.VersionId} {(c.Published ? "+" : "-")}pub pk={c.VersionId} ppk={c.PublishedVersionId} name=\"{c.Name}\" pname=\"{c.PublishName}\"");
|
|
|
|
|
}
|
2018-06-29 19:52:40 +02:00
|
|
|
|
2022-06-21 08:09:38 +02:00
|
|
|
// get older version
|
|
|
|
|
var content = repository.GetVersion(versions[^4]);
|
|
|
|
|
Assert.AreNotEqual(0, content.VersionId);
|
|
|
|
|
Assert.AreEqual(versions[^4], content.VersionId);
|
|
|
|
|
Assert.AreEqual("name-4", content1.Name);
|
|
|
|
|
Assert.AreEqual("title-4", content1.GetValue("title"));
|
|
|
|
|
Assert.AreEqual("name-2", content.Name);
|
|
|
|
|
Assert.AreEqual("title-2", content.GetValue("title"));
|
|
|
|
|
|
|
|
|
|
// get all versions - most recent first
|
|
|
|
|
allVersions = repository.GetAllVersions(content1.Id).ToArray();
|
|
|
|
|
var expVersions = versions.Distinct().Reverse().ToArray();
|
|
|
|
|
Assert.AreEqual(expVersions.Length, allVersions.Length);
|
|
|
|
|
for (var i = 0; i < expVersions.Length; i++)
|
|
|
|
|
{
|
|
|
|
|
Assert.AreEqual(expVersions[i], allVersions[i].VersionId);
|
2018-06-29 19:52:40 +02:00
|
|
|
}
|
|
|
|
|
}
|
2022-06-21 08:09:38 +02:00
|
|
|
}
|
2018-06-29 19:52:40 +02:00
|
|
|
|
2022-06-21 08:09:38 +02:00
|
|
|
/// <summary>
|
|
|
|
|
/// This tests the regression issue of U4-9438
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <remarks>
|
|
|
|
|
/// The problem was the iteration of the property data in VersionableRepositoryBase when a content item
|
|
|
|
|
/// in the list actually doesn't have any property types, it would still skip over a property row.
|
|
|
|
|
/// To test, we have 3 content items, the first has properties, the second doesn't and the third does.
|
|
|
|
|
/// </remarks>
|
|
|
|
|
[Test]
|
|
|
|
|
public void PropertyDataAssignedCorrectly()
|
|
|
|
|
{
|
|
|
|
|
var provider = ScopeProvider;
|
|
|
|
|
using (var scope = provider.CreateScope())
|
2018-06-29 19:52:40 +02:00
|
|
|
{
|
2022-06-21 08:09:38 +02:00
|
|
|
var template = TemplateBuilder.CreateTextPageTemplate();
|
|
|
|
|
FileService.SaveTemplate(template);
|
|
|
|
|
|
|
|
|
|
var repository = CreateRepository((IScopeAccessor)provider, out var contentTypeRepository, out DataTypeRepository _);
|
|
|
|
|
|
|
|
|
|
var emptyContentType = ContentTypeBuilder.CreateBasicContentType();
|
|
|
|
|
var hasPropertiesContentType =
|
|
|
|
|
ContentTypeBuilder.CreateSimpleContentType("umbTextpage1", "Textpage", defaultTemplateId: template.Id);
|
|
|
|
|
contentTypeRepository.Save(emptyContentType);
|
|
|
|
|
contentTypeRepository.Save(hasPropertiesContentType);
|
|
|
|
|
|
|
|
|
|
var content1 = ContentBuilder.CreateSimpleContent(hasPropertiesContentType);
|
|
|
|
|
var content2 = ContentBuilder.CreateBasicContent(emptyContentType);
|
|
|
|
|
var content3 = ContentBuilder.CreateSimpleContent(hasPropertiesContentType);
|
|
|
|
|
|
|
|
|
|
repository.Save(content1);
|
|
|
|
|
repository.Save(content2);
|
|
|
|
|
repository.Save(content3);
|
|
|
|
|
|
|
|
|
|
// this will cause the GetPropertyCollection to execute and we need to ensure that
|
|
|
|
|
// all of the properties and property types are all correct
|
|
|
|
|
var result = repository.GetMany(content1.Id, content2.Id, content3.Id).ToArray();
|
|
|
|
|
var n1 = result[0];
|
|
|
|
|
var n2 = result[1];
|
|
|
|
|
var n3 = result[2];
|
|
|
|
|
|
|
|
|
|
Assert.AreEqual(content1.Id, n1.Id);
|
|
|
|
|
Assert.AreEqual(content2.Id, n2.Id);
|
|
|
|
|
Assert.AreEqual(content3.Id, n3.Id);
|
|
|
|
|
|
|
|
|
|
// compare everything including properties and their values
|
|
|
|
|
// this ensures that they have been properly retrieved
|
|
|
|
|
TestHelper.AssertPropertyValuesAreEqual(content1, n1);
|
|
|
|
|
TestHelper.AssertPropertyValuesAreEqual(content2, n2);
|
|
|
|
|
TestHelper.AssertPropertyValuesAreEqual(content3, n3);
|
2018-06-29 19:52:40 +02:00
|
|
|
}
|
2022-06-21 08:09:38 +02:00
|
|
|
}
|
2018-06-29 19:52:40 +02:00
|
|
|
|
2022-06-21 08:09:38 +02:00
|
|
|
//// /// <summary>
|
|
|
|
|
//// /// This test ensures that when property values using special database fields are saved, the actual data in the
|
|
|
|
|
//// /// object being stored is also transformed in the same way as the data being stored in the database is.
|
|
|
|
|
//// /// Before you would see that ex: a decimal value being saved as 100 or "100", would be that exact value in the
|
|
|
|
|
//// /// object, but the value saved to the database was actually 100.000000.
|
|
|
|
|
//// /// When querying the database for the value again - the value would then differ from what is in the object.
|
|
|
|
|
//// /// This caused inconsistencies between saving+publishing and simply saving and then publishing, due to the former
|
|
|
|
|
//// /// sending the non-transformed data directly on to publishing.
|
|
|
|
|
//// /// </summary>
|
|
|
|
|
//// [Test]
|
|
|
|
|
//// public void PropertyValuesWithSpecialTypes()
|
|
|
|
|
//// {
|
|
|
|
|
//// var provider = ScopeProvider;
|
|
|
|
|
//// using (var scope = provider.CreateScope())
|
|
|
|
|
//// {
|
|
|
|
|
//// var repository = CreateRepository((IScopeAccessor)provider, out var contentTypeRepository, out DataTypeRepository dataTypeDefinitionRepository);
|
|
|
|
|
////
|
|
|
|
|
//// var editor = new DecimalPropertyEditor(LoggerFactory, DataTypeService, LocalizationService, LocalizedTextService, ShortStringHelper);
|
|
|
|
|
//// var dtd = new DataType(editor) { Name = "test", DatabaseType = ValueStorageType.Decimal };
|
|
|
|
|
//// dataTypeDefinitionRepository.Save(dtd);
|
|
|
|
|
////
|
|
|
|
|
//// const string decimalPropertyAlias = "decimalProperty";
|
|
|
|
|
//// const string intPropertyAlias = "intProperty";
|
|
|
|
|
//// const string dateTimePropertyAlias = "datetimeProperty";
|
|
|
|
|
//// var dateValue = new DateTime(2016, 1, 6);
|
|
|
|
|
////
|
|
|
|
|
//// var propertyTypeCollection = new PropertyTypeCollection(true,
|
|
|
|
|
//// new List<PropertyType>
|
|
|
|
|
//// {
|
|
|
|
|
//// MockedPropertyTypes.CreateDecimalProperty(decimalPropertyAlias, "Decimal property", dtd.Id),
|
|
|
|
|
//// MockedPropertyTypes.CreateIntegerProperty(intPropertyAlias, "Integer property"),
|
|
|
|
|
//// MockedPropertyTypes.CreateDateTimeProperty(dateTimePropertyAlias, "DateTime property")
|
|
|
|
|
//// });
|
|
|
|
|
//// var contentType = ContentTypeBuilder.CreateSimpleContentType("umbTextpage1", "Textpage", propertyTypeCollection);
|
|
|
|
|
//// contentTypeRepository.Save(contentType);
|
|
|
|
|
////
|
|
|
|
|
//// // int and decimal values are passed in as strings as they would be from the backoffice UI
|
|
|
|
|
//// var textpage = ContentBuilder.CreateSimpleContentWithSpecialDatabaseTypes(contentType, "test@umbraco.org", -1, "100", "150", dateValue);
|
|
|
|
|
////
|
|
|
|
|
//// repository.Save(textpage);
|
|
|
|
|
//// scope.Complete();
|
|
|
|
|
////
|
|
|
|
|
//// Assert.That(contentType.HasIdentity, Is.True);
|
|
|
|
|
//// Assert.That(textpage.HasIdentity, Is.True);
|
|
|
|
|
////
|
|
|
|
|
//// var persistedTextpage = repository.Get(textpage.Id);
|
|
|
|
|
//// Assert.That(persistedTextpage.Name, Is.EqualTo(textpage.Name));
|
|
|
|
|
//// Assert.AreEqual(100m, persistedTextpage.GetValue(decimalPropertyAlias));
|
|
|
|
|
//// Assert.AreEqual(persistedTextpage.GetValue(decimalPropertyAlias), textpage.GetValue(decimalPropertyAlias));
|
|
|
|
|
//// Assert.AreEqual(150, persistedTextpage.GetValue(intPropertyAlias));
|
|
|
|
|
//// Assert.AreEqual(persistedTextpage.GetValue(intPropertyAlias), textpage.GetValue(intPropertyAlias));
|
|
|
|
|
//// Assert.AreEqual(dateValue, persistedTextpage.GetValue(dateTimePropertyAlias));
|
|
|
|
|
//// Assert.AreEqual(persistedTextpage.GetValue(dateTimePropertyAlias), textpage.GetValue(dateTimePropertyAlias));
|
|
|
|
|
//// }
|
|
|
|
|
//// }
|
|
|
|
|
|
|
|
|
|
[Test]
|
|
|
|
|
public void SaveContent()
|
|
|
|
|
{
|
|
|
|
|
var provider = ScopeProvider;
|
|
|
|
|
using (var scope = provider.CreateScope())
|
2018-06-29 19:52:40 +02:00
|
|
|
{
|
2022-06-21 08:09:38 +02:00
|
|
|
var template = TemplateBuilder.CreateTextPageTemplate();
|
|
|
|
|
FileService.SaveTemplate(template);
|
|
|
|
|
var repository = CreateRepository((IScopeAccessor)provider, out var contentTypeRepository);
|
|
|
|
|
var contentType =
|
|
|
|
|
ContentTypeBuilder.CreateSimpleContentType("umbTextpage2", "Textpage", defaultTemplateId: template.Id);
|
|
|
|
|
contentTypeRepository.Save(contentType);
|
2019-02-05 19:58:33 +01:00
|
|
|
|
2022-06-21 08:09:38 +02:00
|
|
|
IContent textpage = ContentBuilder.CreateSimpleContent(contentType);
|
2018-06-29 19:52:40 +02:00
|
|
|
|
2022-06-21 08:09:38 +02:00
|
|
|
repository.Save(textpage);
|
|
|
|
|
scope.Complete();
|
2018-06-29 19:52:40 +02:00
|
|
|
|
2022-06-21 08:09:38 +02:00
|
|
|
Assert.That(contentType.HasIdentity, Is.True);
|
|
|
|
|
Assert.That(textpage.HasIdentity, Is.True);
|
2018-06-01 15:20:16 +10:00
|
|
|
}
|
2022-06-21 08:09:38 +02:00
|
|
|
}
|
2018-06-29 19:52:40 +02:00
|
|
|
|
2022-06-21 08:09:38 +02:00
|
|
|
[Test]
|
|
|
|
|
public void SaveContentWithDefaultTemplate()
|
|
|
|
|
{
|
|
|
|
|
var provider = ScopeProvider;
|
|
|
|
|
using (var scope = provider.CreateScope())
|
2018-06-29 19:52:40 +02:00
|
|
|
{
|
2022-06-21 08:09:38 +02:00
|
|
|
var repository = CreateRepository((IScopeAccessor)provider, out var contentTypeRepository, out TemplateRepository templateRepository);
|
2018-06-29 19:52:40 +02:00
|
|
|
|
2022-06-21 08:09:38 +02:00
|
|
|
var template = new Template(ShortStringHelper, "hello", "hello");
|
|
|
|
|
templateRepository.Save(template);
|
2018-05-01 13:43:27 +10:00
|
|
|
|
2022-06-21 08:09:38 +02:00
|
|
|
var contentType = ContentTypeBuilder.CreateSimpleContentType("umbTextpage2", "Textpage");
|
|
|
|
|
contentType.AllowedTemplates =
|
|
|
|
|
Enumerable.Empty<ITemplate>(); // because CreateSimpleContentType assigns one already
|
|
|
|
|
contentType.SetDefaultTemplate(template);
|
|
|
|
|
contentTypeRepository.Save(contentType);
|
2019-01-03 09:27:52 +01:00
|
|
|
|
2022-06-21 08:09:38 +02:00
|
|
|
var textpage = ContentBuilder.CreateSimpleContent(contentType);
|
|
|
|
|
repository.Save(textpage);
|
2018-05-01 13:43:27 +10:00
|
|
|
|
2022-06-21 08:09:38 +02:00
|
|
|
var fetched = repository.Get(textpage.Id);
|
2018-06-29 19:52:40 +02:00
|
|
|
|
2022-06-21 08:09:38 +02:00
|
|
|
Assert.True(textpage.TemplateId.HasValue);
|
|
|
|
|
Assert.NotZero(textpage.TemplateId.Value);
|
|
|
|
|
Assert.AreEqual(textpage.TemplateId, contentType.DefaultTemplate.Id);
|
2018-06-29 19:52:40 +02:00
|
|
|
|
2022-06-21 08:09:38 +02:00
|
|
|
scope.Complete();
|
2018-06-29 19:52:40 +02:00
|
|
|
|
2022-06-21 08:09:38 +02:00
|
|
|
TestHelper.AssertPropertyValuesAreEqual(textpage, fetched);
|
2018-06-29 19:52:40 +02:00
|
|
|
}
|
2022-06-21 08:09:38 +02:00
|
|
|
}
|
2018-06-29 19:52:40 +02:00
|
|
|
|
2022-06-21 08:09:38 +02:00
|
|
|
// Covers issue U4-2791 and U4-2607
|
|
|
|
|
[Test]
|
|
|
|
|
public void SaveContentWithAtSignInName()
|
|
|
|
|
{
|
|
|
|
|
// Arrange
|
|
|
|
|
var provider = ScopeProvider;
|
|
|
|
|
using (var scope = provider.CreateScope())
|
2018-06-29 19:52:40 +02:00
|
|
|
{
|
2022-06-21 08:09:38 +02:00
|
|
|
var template = TemplateBuilder.CreateTextPageTemplate();
|
|
|
|
|
FileService.SaveTemplate(template);
|
|
|
|
|
var repository = CreateRepository((IScopeAccessor)provider, out var contentTypeRepository);
|
|
|
|
|
var contentType =
|
|
|
|
|
ContentTypeBuilder.CreateSimpleContentType("umbTextpage1", "Textpage", defaultTemplateId: template.Id);
|
|
|
|
|
contentTypeRepository.Save(contentType);
|
2018-05-01 13:43:27 +10:00
|
|
|
|
2022-06-21 08:09:38 +02:00
|
|
|
var textpage = ContentBuilder.CreateSimpleContent(contentType, "test@umbraco.org");
|
|
|
|
|
var anotherTextpage = ContentBuilder.CreateSimpleContent(contentType, "@lightgiants");
|
2018-06-29 19:52:40 +02:00
|
|
|
|
2022-06-21 08:09:38 +02:00
|
|
|
repository.Save(textpage);
|
|
|
|
|
repository.Save(anotherTextpage);
|
2018-05-01 13:43:27 +10:00
|
|
|
|
2022-06-21 08:09:38 +02:00
|
|
|
Assert.That(contentType.HasIdentity, Is.True);
|
|
|
|
|
Assert.That(textpage.HasIdentity, Is.True);
|
2018-06-29 19:52:40 +02:00
|
|
|
|
2022-06-21 08:09:38 +02:00
|
|
|
var content = repository.Get(textpage.Id);
|
|
|
|
|
Assert.That(content.Name, Is.EqualTo(textpage.Name));
|
2018-06-29 19:52:40 +02:00
|
|
|
|
2022-06-21 08:09:38 +02:00
|
|
|
var content2 = repository.Get(anotherTextpage.Id);
|
|
|
|
|
Assert.That(content2.Name, Is.EqualTo(anotherTextpage.Name));
|
2018-06-29 19:52:40 +02:00
|
|
|
|
2022-06-21 08:09:38 +02:00
|
|
|
scope.Complete();
|
2018-06-29 19:52:40 +02:00
|
|
|
}
|
2022-06-21 08:09:38 +02:00
|
|
|
}
|
2018-06-29 19:52:40 +02:00
|
|
|
|
2022-06-21 08:09:38 +02:00
|
|
|
[Test]
|
|
|
|
|
public void SaveContentMultiple()
|
|
|
|
|
{
|
|
|
|
|
var provider = ScopeProvider;
|
|
|
|
|
using (var scope = provider.CreateScope())
|
2018-06-29 19:52:40 +02:00
|
|
|
{
|
2022-06-21 08:09:38 +02:00
|
|
|
var template = TemplateBuilder.CreateTextPageTemplate();
|
|
|
|
|
FileService.SaveTemplate(template);
|
|
|
|
|
var repository = CreateRepository((IScopeAccessor)provider, out var contentTypeRepository);
|
|
|
|
|
var contentType =
|
|
|
|
|
ContentTypeBuilder.CreateSimpleContentType("umbTextpage1", "Textpage", defaultTemplateId: template.Id);
|
|
|
|
|
contentTypeRepository.Save(contentType);
|
2019-02-05 19:58:33 +01:00
|
|
|
|
2022-06-21 08:09:38 +02:00
|
|
|
var textpage = ContentBuilder.CreateSimpleContent(contentType);
|
2018-06-29 19:52:40 +02:00
|
|
|
|
2022-06-21 08:09:38 +02:00
|
|
|
repository.Save(textpage);
|
2018-05-01 13:43:27 +10:00
|
|
|
|
2022-06-21 08:09:38 +02:00
|
|
|
var subpage = ContentBuilder.CreateSimpleContent(contentType, "Text Page 1", textpage.Id);
|
|
|
|
|
repository.Save(subpage);
|
2018-05-01 13:43:27 +10:00
|
|
|
|
2022-06-21 08:09:38 +02:00
|
|
|
Assert.That(contentType.HasIdentity, Is.True);
|
|
|
|
|
Assert.That(textpage.HasIdentity, Is.True);
|
|
|
|
|
Assert.That(subpage.HasIdentity, Is.True);
|
|
|
|
|
Assert.That(textpage.Id, Is.EqualTo(subpage.ParentId));
|
2018-06-29 19:52:40 +02:00
|
|
|
}
|
2022-06-21 08:09:38 +02:00
|
|
|
}
|
2018-06-29 19:52:40 +02:00
|
|
|
|
2022-06-21 08:09:38 +02:00
|
|
|
[Test]
|
|
|
|
|
public void GetContentIsNotDirty()
|
|
|
|
|
{
|
|
|
|
|
var provider = ScopeProvider;
|
|
|
|
|
using (var scope = provider.CreateScope())
|
2018-06-29 19:52:40 +02:00
|
|
|
{
|
2022-06-21 08:09:38 +02:00
|
|
|
var repository = CreateRepository((IScopeAccessor)provider, out _);
|
2018-06-29 19:52:40 +02:00
|
|
|
|
2022-06-21 08:09:38 +02:00
|
|
|
var content = repository.Get(_subpage2.Id);
|
|
|
|
|
var dirty = ((Content)content).IsDirty();
|
2018-06-29 19:52:40 +02:00
|
|
|
|
2022-06-21 08:09:38 +02:00
|
|
|
Assert.That(dirty, Is.False);
|
2018-06-29 19:52:40 +02:00
|
|
|
}
|
2022-06-21 08:09:38 +02:00
|
|
|
}
|
2018-06-29 19:52:40 +02:00
|
|
|
|
2022-06-21 08:09:38 +02:00
|
|
|
[Test]
|
|
|
|
|
public void UpdateContent()
|
|
|
|
|
{
|
|
|
|
|
var provider = ScopeProvider;
|
|
|
|
|
using (var scope = provider.CreateScope())
|
2018-06-29 19:52:40 +02:00
|
|
|
{
|
2022-06-21 08:09:38 +02:00
|
|
|
var repository = CreateRepository((IScopeAccessor)provider, out _);
|
2018-06-29 19:52:40 +02:00
|
|
|
|
2022-06-21 08:09:38 +02:00
|
|
|
var content = repository.Get(_subpage.Id);
|
|
|
|
|
content.Name = "About 2";
|
|
|
|
|
repository.Save(content);
|
2018-05-01 13:43:27 +10:00
|
|
|
|
2022-06-21 08:09:38 +02:00
|
|
|
var updatedContent = repository.Get(_subpage.Id);
|
2018-06-29 19:52:40 +02:00
|
|
|
|
2022-06-21 08:09:38 +02:00
|
|
|
Assert.AreEqual(content.Id, updatedContent.Id);
|
|
|
|
|
Assert.AreEqual(content.Name, updatedContent.Name);
|
|
|
|
|
Assert.AreEqual(content.VersionId, updatedContent.VersionId);
|
2018-06-29 19:52:40 +02:00
|
|
|
|
2022-06-21 08:09:38 +02:00
|
|
|
Assert.AreEqual(content.GetValue("title"), "Welcome to our Home page");
|
|
|
|
|
content.SetValue("title", "toot");
|
|
|
|
|
repository.Save(content);
|
2018-05-01 13:43:27 +10:00
|
|
|
|
2022-06-21 08:09:38 +02:00
|
|
|
updatedContent = repository.Get(_subpage.Id);
|
2018-06-29 19:52:40 +02:00
|
|
|
|
2022-06-21 08:09:38 +02:00
|
|
|
Assert.AreEqual("toot", updatedContent.GetValue("title"));
|
|
|
|
|
Assert.AreEqual(content.VersionId, updatedContent.VersionId);
|
2018-06-29 19:52:40 +02:00
|
|
|
}
|
2022-06-21 08:09:38 +02:00
|
|
|
}
|
2018-06-29 19:52:40 +02:00
|
|
|
|
2022-06-21 08:09:38 +02:00
|
|
|
[Test]
|
|
|
|
|
public void UpdateContentWithNullTemplate()
|
|
|
|
|
{
|
|
|
|
|
var provider = ScopeProvider;
|
|
|
|
|
using (var scope = provider.CreateScope())
|
2018-06-29 19:52:40 +02:00
|
|
|
{
|
2022-06-21 08:09:38 +02:00
|
|
|
var repository = CreateRepository((IScopeAccessor)provider, out _);
|
2018-06-29 19:52:40 +02:00
|
|
|
|
2022-06-21 08:09:38 +02:00
|
|
|
var content = repository.Get(_subpage.Id);
|
|
|
|
|
content.TemplateId = null;
|
|
|
|
|
repository.Save(content);
|
2018-05-01 13:43:27 +10:00
|
|
|
|
2022-06-21 08:09:38 +02:00
|
|
|
var updatedContent = repository.Get(_subpage.Id);
|
2018-06-29 19:52:40 +02:00
|
|
|
|
2022-06-21 08:09:38 +02:00
|
|
|
Assert.False(updatedContent.TemplateId.HasValue);
|
2018-06-29 19:52:40 +02:00
|
|
|
}
|
2022-06-21 08:09:38 +02:00
|
|
|
}
|
2018-06-29 19:52:40 +02:00
|
|
|
|
2022-06-21 08:09:38 +02:00
|
|
|
[Test]
|
|
|
|
|
public void DeleteContent()
|
|
|
|
|
{
|
|
|
|
|
var provider = ScopeProvider;
|
|
|
|
|
using (var scope = provider.CreateScope())
|
2018-06-29 19:52:40 +02:00
|
|
|
{
|
2022-06-21 08:09:38 +02:00
|
|
|
var repository = CreateRepository((IScopeAccessor)provider, out var contentTypeRepository);
|
|
|
|
|
var contentType = contentTypeRepository.Get(_contentType.Id);
|
|
|
|
|
var content = new Content("Textpage 2 Child Node", _trashed.Id, contentType) { CreatorId = 0, WriterId = 0 };
|
2018-06-29 19:52:40 +02:00
|
|
|
|
2022-06-21 08:09:38 +02:00
|
|
|
repository.Save(content);
|
2018-05-01 13:43:27 +10:00
|
|
|
|
2022-06-21 08:09:38 +02:00
|
|
|
var id = content.Id;
|
2018-06-29 19:52:40 +02:00
|
|
|
|
2022-06-21 08:09:38 +02:00
|
|
|
repository.Delete(content);
|
2018-05-01 13:43:27 +10:00
|
|
|
|
2022-06-21 08:09:38 +02:00
|
|
|
var content1 = repository.Get(id);
|
|
|
|
|
Assert.IsNull(content1);
|
2018-06-29 19:52:40 +02:00
|
|
|
}
|
2022-06-21 08:09:38 +02:00
|
|
|
}
|
2018-06-29 19:52:40 +02:00
|
|
|
|
2022-06-21 08:09:38 +02:00
|
|
|
[Test]
|
|
|
|
|
public void GetContent()
|
|
|
|
|
{
|
|
|
|
|
var provider = ScopeProvider;
|
|
|
|
|
using (var scope = provider.CreateScope())
|
2018-06-29 19:52:40 +02:00
|
|
|
{
|
2022-06-21 08:09:38 +02:00
|
|
|
var repository = CreateRepository((IScopeAccessor)provider, out _);
|
|
|
|
|
var content = repository.Get(_subpage2.Id);
|
|
|
|
|
|
|
|
|
|
Assert.AreEqual(_subpage2.Id, content.Id);
|
|
|
|
|
Assert.That(content.CreateDate, Is.GreaterThan(DateTime.MinValue));
|
|
|
|
|
Assert.That(content.UpdateDate, Is.GreaterThan(DateTime.MinValue));
|
|
|
|
|
Assert.AreNotEqual(0, content.ParentId);
|
|
|
|
|
Assert.AreEqual("Text Page 2", content.Name);
|
|
|
|
|
Assert.AreNotEqual(0, content.VersionId);
|
|
|
|
|
Assert.AreEqual(_contentType.Id, content.ContentTypeId);
|
|
|
|
|
Assert.That(content.Path, Is.Not.Empty);
|
|
|
|
|
Assert.That(content.Properties.Any(), Is.True);
|
2018-06-29 19:52:40 +02:00
|
|
|
}
|
2022-06-21 08:09:38 +02:00
|
|
|
}
|
2018-06-29 19:52:40 +02:00
|
|
|
|
2022-06-21 08:09:38 +02:00
|
|
|
[Test]
|
|
|
|
|
public void QueryContent()
|
|
|
|
|
{
|
|
|
|
|
var provider = ScopeProvider;
|
|
|
|
|
using (var scope = provider.CreateScope())
|
2018-06-29 19:52:40 +02:00
|
|
|
{
|
2022-06-21 08:09:38 +02:00
|
|
|
var repository = CreateRepository((IScopeAccessor)provider, out _);
|
2018-06-29 19:52:40 +02:00
|
|
|
|
2022-06-21 08:09:38 +02:00
|
|
|
var query = ScopeProvider.CreateQuery<IContent>().Where(x => x.Level == 2);
|
|
|
|
|
var result = repository.Get(query);
|
2018-06-29 19:52:40 +02:00
|
|
|
|
2022-06-21 08:09:38 +02:00
|
|
|
Assert.GreaterOrEqual(2, result.Count());
|
2018-06-29 19:52:40 +02:00
|
|
|
}
|
2022-06-21 08:09:38 +02:00
|
|
|
}
|
2018-06-29 19:52:40 +02:00
|
|
|
|
2022-06-21 08:09:38 +02:00
|
|
|
[Test]
|
2023-09-12 14:16:27 +02:00
|
|
|
[LongRunning]
|
2022-06-21 08:09:38 +02:00
|
|
|
public void GetAllContentManyVersions()
|
|
|
|
|
{
|
|
|
|
|
IContent[] result;
|
|
|
|
|
|
|
|
|
|
var provider = ScopeProvider;
|
|
|
|
|
using (var scope = provider.CreateScope())
|
2018-06-29 19:52:40 +02:00
|
|
|
{
|
2022-06-21 08:09:38 +02:00
|
|
|
var repository = CreateRepository((IScopeAccessor)provider, out _);
|
|
|
|
|
result = repository.GetMany().ToArray();
|
2018-06-29 19:52:40 +02:00
|
|
|
|
2022-06-21 08:09:38 +02:00
|
|
|
// save them all
|
|
|
|
|
foreach (var content in result)
|
2018-06-29 19:52:40 +02:00
|
|
|
{
|
2022-06-21 08:09:38 +02:00
|
|
|
content.SetValue("title", content.GetValue<string>("title") + "x");
|
|
|
|
|
repository.Save(content);
|
2018-06-29 19:52:40 +02:00
|
|
|
}
|
|
|
|
|
|
2022-06-21 08:09:38 +02:00
|
|
|
// publish them all
|
|
|
|
|
foreach (var content in result)
|
2018-06-29 19:52:40 +02:00
|
|
|
{
|
2022-06-21 08:09:38 +02:00
|
|
|
content.PublishCulture(CultureImpact.Invariant);
|
|
|
|
|
repository.Save(content);
|
2018-06-29 19:52:40 +02:00
|
|
|
}
|
2022-06-21 08:09:38 +02:00
|
|
|
|
|
|
|
|
scope.Complete();
|
2018-06-29 19:52:40 +02:00
|
|
|
}
|
|
|
|
|
|
2022-06-21 08:09:38 +02:00
|
|
|
// get them all again
|
|
|
|
|
using (var scope = provider.CreateScope())
|
2018-06-29 19:52:40 +02:00
|
|
|
{
|
2022-06-21 08:09:38 +02:00
|
|
|
var repository = CreateRepository((IScopeAccessor)provider, out _);
|
|
|
|
|
var result2 = repository.GetMany().ToArray();
|
|
|
|
|
|
|
|
|
|
Assert.AreEqual(result.Length, result2.Length);
|
2018-06-29 19:52:40 +02:00
|
|
|
}
|
2022-06-21 08:09:38 +02:00
|
|
|
}
|
2018-06-29 19:52:40 +02:00
|
|
|
|
2022-06-21 08:09:38 +02:00
|
|
|
[Test]
|
|
|
|
|
public void AliasRegexTest()
|
|
|
|
|
{
|
|
|
|
|
var regex = new SqlServerSyntaxProvider(Options.Create(new GlobalSettings())).AliasRegex;
|
|
|
|
|
Assert.AreEqual(@"(\[\w+]\.\[\w+])\s+AS\s+(\[\w+])", regex.ToString());
|
|
|
|
|
const string sql = "SELECT [table].[column1] AS [alias1], [table].[column2] AS [alias2] FROM [table];";
|
|
|
|
|
var matches = regex.Matches(sql);
|
|
|
|
|
Assert.AreEqual(2, matches.Count);
|
|
|
|
|
Assert.AreEqual("[table].[column1]", matches[0].Groups[1].Value);
|
|
|
|
|
Assert.AreEqual("[alias1]", matches[0].Groups[2].Value);
|
|
|
|
|
Assert.AreEqual("[table].[column2]", matches[1].Groups[1].Value);
|
|
|
|
|
Assert.AreEqual("[alias2]", matches[1].Groups[2].Value);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[Test]
|
|
|
|
|
public void GetPagedResultsByQuery_With_Variant_Names()
|
|
|
|
|
{
|
|
|
|
|
// One invariant content type named "umbInvariantTextPage"
|
|
|
|
|
var template = TemplateBuilder.CreateTextPageTemplate();
|
|
|
|
|
FileService.SaveTemplate(template);
|
|
|
|
|
var invariantCt = ContentTypeBuilder.CreateSimpleContentType("umbInvariantTextpage", "Invariant Textpage", defaultTemplateId: template.Id);
|
|
|
|
|
invariantCt.Variations = ContentVariation.Nothing;
|
|
|
|
|
foreach (var p in invariantCt.PropertyTypes)
|
2018-05-01 13:30:25 +10:00
|
|
|
{
|
2022-06-21 08:09:38 +02:00
|
|
|
p.Variations = ContentVariation.Nothing;
|
|
|
|
|
}
|
2020-12-23 11:35:49 +01:00
|
|
|
|
2022-06-21 08:09:38 +02:00
|
|
|
ContentTypeService.Save(invariantCt);
|
2018-06-29 19:52:40 +02:00
|
|
|
|
2022-06-21 08:09:38 +02:00
|
|
|
// One variant (by culture) content type named "umbVariantTextPage"
|
|
|
|
|
// with properties, every 2nd one being variant (by culture), the other being invariant
|
|
|
|
|
var variantCt = ContentTypeBuilder.CreateSimpleContentType("umbVariantTextpage", "Variant Textpage", defaultTemplateId: template.Id);
|
|
|
|
|
variantCt.Variations = ContentVariation.Culture;
|
|
|
|
|
var propTypes = variantCt.PropertyTypes.ToList();
|
|
|
|
|
for (var i = 0; i < propTypes.Count; i++)
|
|
|
|
|
{
|
|
|
|
|
var p = propTypes[i];
|
|
|
|
|
p.Variations = i % 2 == 0 ? ContentVariation.Culture : ContentVariation.Nothing;
|
|
|
|
|
}
|
2020-10-09 13:08:23 +02:00
|
|
|
|
2022-06-21 08:09:38 +02:00
|
|
|
ContentTypeService.Save(variantCt);
|
2018-05-01 13:30:25 +10:00
|
|
|
|
2022-06-21 08:09:38 +02:00
|
|
|
invariantCt.AllowedContentTypes =
|
|
|
|
|
new[] { new ContentTypeSort(invariantCt.Id, 0), new ContentTypeSort(variantCt.Id, 1) };
|
|
|
|
|
ContentTypeService.Save(invariantCt);
|
2018-05-01 13:30:25 +10:00
|
|
|
|
2022-06-21 08:09:38 +02:00
|
|
|
// Create content
|
|
|
|
|
var root = ContentBuilder.CreateSimpleContent(invariantCt);
|
|
|
|
|
ContentService.Save(root);
|
2018-05-01 13:30:25 +10:00
|
|
|
|
2022-06-21 08:09:38 +02:00
|
|
|
var children = new List<IContent>();
|
2018-06-20 14:18:57 +02:00
|
|
|
|
2022-06-21 08:09:38 +02:00
|
|
|
for (var i = 0; i < 25; i++)
|
|
|
|
|
{
|
|
|
|
|
var isInvariant = i % 2 == 0;
|
|
|
|
|
var name = (isInvariant ? "INV" : "VAR") + "_" + Guid.NewGuid();
|
|
|
|
|
var culture = isInvariant ? null : "en-US";
|
|
|
|
|
|
|
|
|
|
var child = ContentBuilder.CreateSimpleContent(
|
|
|
|
|
isInvariant ? invariantCt : variantCt,
|
|
|
|
|
name,
|
|
|
|
|
root,
|
|
|
|
|
culture,
|
|
|
|
|
setPropertyValues: isInvariant);
|
|
|
|
|
|
|
|
|
|
if (!isInvariant)
|
2018-05-01 13:30:25 +10:00
|
|
|
{
|
2022-06-21 08:09:38 +02:00
|
|
|
// manually set the property values since we have mixed variant/invariant property types
|
|
|
|
|
child.SetValue("title", name + " Subpage", culture);
|
|
|
|
|
child.SetValue("bodyText", "This is a subpage"); // this one is invariant
|
|
|
|
|
child.SetValue("author", "John Doe", culture);
|
2018-05-01 13:30:25 +10:00
|
|
|
}
|
2018-06-29 19:52:40 +02:00
|
|
|
|
2022-06-21 08:09:38 +02:00
|
|
|
ContentService.Save(child);
|
|
|
|
|
children.Add(child);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var child1 = children[1];
|
|
|
|
|
Assert.IsTrue(child1.ContentType.VariesByCulture());
|
|
|
|
|
Assert.IsTrue(child1.Name.StartsWith("VAR"));
|
|
|
|
|
Assert.IsTrue(child1.GetCultureName("en-US").StartsWith("VAR"));
|
2018-06-20 14:18:57 +02:00
|
|
|
|
2022-06-21 08:09:38 +02:00
|
|
|
var provider = ScopeProvider;
|
|
|
|
|
using (var scope = provider.CreateScope())
|
|
|
|
|
{
|
|
|
|
|
var repository = CreateRepository((IScopeAccessor)provider, out _);
|
|
|
|
|
|
|
|
|
|
var child = repository.Get(children[1].Id); // 1 is variant
|
|
|
|
|
Assert.IsTrue(child.ContentType.VariesByCulture());
|
|
|
|
|
Assert.IsTrue(child.Name.StartsWith("VAR"));
|
|
|
|
|
Assert.IsTrue(child.GetCultureName("en-US").StartsWith("VAR"));
|
|
|
|
|
|
|
|
|
|
try
|
2018-06-29 19:52:40 +02:00
|
|
|
{
|
2022-06-21 08:09:38 +02:00
|
|
|
ScopeAccessor.AmbientScope.Database.AsUmbracoDatabase().EnableSqlTrace = true;
|
|
|
|
|
ScopeAccessor.AmbientScope.Database.AsUmbracoDatabase().EnableSqlCount = true;
|
2018-06-29 19:52:40 +02:00
|
|
|
|
2022-06-21 08:09:38 +02:00
|
|
|
var query = ScopeProvider.CreateQuery<IContent>().Where(x => x.ParentId == root.Id);
|
|
|
|
|
var result = repository.GetPage(query, 0, 20, out var totalRecords, null, Ordering.By("UpdateDate"));
|
2018-06-29 19:52:40 +02:00
|
|
|
|
2022-06-21 08:09:38 +02:00
|
|
|
Assert.AreEqual(25, totalRecords);
|
|
|
|
|
foreach (var r in result)
|
2018-06-29 19:52:40 +02:00
|
|
|
{
|
2022-06-21 08:09:38 +02:00
|
|
|
var isInvariant = r.ContentType.Alias == "umbInvariantTextpage";
|
|
|
|
|
var name = isInvariant ? r.Name : r.CultureInfos["en-US"].Name;
|
|
|
|
|
var namePrefix = isInvariant ? "INV" : "VAR";
|
2018-06-29 19:52:40 +02:00
|
|
|
|
2022-06-21 08:09:38 +02:00
|
|
|
// ensure the correct name (invariant vs variant) is in the result
|
|
|
|
|
Assert.IsTrue(name.StartsWith(namePrefix));
|
2018-05-01 13:30:25 +10:00
|
|
|
|
2022-06-21 08:09:38 +02:00
|
|
|
foreach (var p in r.Properties)
|
2018-05-01 13:30:25 +10:00
|
|
|
{
|
2022-06-21 08:09:38 +02:00
|
|
|
// ensure there is a value for the correct variant/invariant property
|
|
|
|
|
var value = p.GetValue(p.PropertyType.Variations.VariesByNothing() ? null : "en-US");
|
|
|
|
|
Assert.IsNotNull(value);
|
2018-06-29 19:52:40 +02:00
|
|
|
}
|
|
|
|
|
}
|
2022-06-21 08:09:38 +02:00
|
|
|
}
|
|
|
|
|
finally
|
|
|
|
|
{
|
|
|
|
|
ScopeAccessor.AmbientScope.Database.AsUmbracoDatabase().EnableSqlTrace = false;
|
|
|
|
|
ScopeAccessor.AmbientScope.Database.AsUmbracoDatabase().EnableSqlCount = false;
|
2018-06-29 19:52:40 +02:00
|
|
|
}
|
|
|
|
|
}
|
2022-06-21 08:09:38 +02:00
|
|
|
}
|
2018-06-29 19:52:40 +02:00
|
|
|
|
2022-06-21 08:09:38 +02:00
|
|
|
[Test]
|
|
|
|
|
public void GetPagedResultsByQuery_CustomPropertySort()
|
|
|
|
|
{
|
|
|
|
|
var provider = ScopeProvider;
|
|
|
|
|
using (var scope = provider.CreateScope())
|
2018-06-29 19:52:40 +02:00
|
|
|
{
|
2022-06-21 08:09:38 +02:00
|
|
|
var repository = CreateRepository((IScopeAccessor)provider, out _);
|
2018-06-29 19:52:40 +02:00
|
|
|
|
2022-06-21 08:09:38 +02:00
|
|
|
var query = ScopeProvider.CreateQuery<IContent>().Where(x => x.Name.Contains("Text"));
|
2018-06-29 19:52:40 +02:00
|
|
|
|
2022-06-21 08:09:38 +02:00
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
ScopeAccessor.AmbientScope.Database.AsUmbracoDatabase().EnableSqlTrace = true;
|
|
|
|
|
ScopeAccessor.AmbientScope.Database.AsUmbracoDatabase().EnableSqlCount = true;
|
2018-06-29 19:52:40 +02:00
|
|
|
|
2022-06-21 08:09:38 +02:00
|
|
|
var result = repository.GetPage(query, 0, 2, out var totalRecords, null, Ordering.By("title", isCustomField: true));
|
2018-06-29 19:52:40 +02:00
|
|
|
|
2022-06-21 08:09:38 +02:00
|
|
|
Assert.AreEqual(3, totalRecords);
|
|
|
|
|
Assert.AreEqual(2, result.Count());
|
2018-06-29 19:52:40 +02:00
|
|
|
|
2022-06-21 08:09:38 +02:00
|
|
|
result = repository.GetPage(query, 1, 2, out totalRecords, null, Ordering.By("title", isCustomField: true));
|
2018-06-29 19:52:40 +02:00
|
|
|
|
2022-06-21 08:09:38 +02:00
|
|
|
Assert.AreEqual(1, result.Count());
|
|
|
|
|
}
|
|
|
|
|
finally
|
|
|
|
|
{
|
|
|
|
|
ScopeAccessor.AmbientScope.Database.AsUmbracoDatabase().EnableSqlTrace = false;
|
|
|
|
|
ScopeAccessor.AmbientScope.Database.AsUmbracoDatabase().EnableSqlCount = false;
|
2018-06-29 19:52:40 +02:00
|
|
|
}
|
|
|
|
|
}
|
2022-06-21 08:09:38 +02:00
|
|
|
}
|
2018-06-29 19:52:40 +02:00
|
|
|
|
2022-06-21 08:09:38 +02:00
|
|
|
[Test]
|
|
|
|
|
public void GetPagedResultsByQuery_FirstPage()
|
|
|
|
|
{
|
|
|
|
|
var provider = ScopeProvider;
|
|
|
|
|
using (var scope = provider.CreateScope())
|
2018-06-29 19:52:40 +02:00
|
|
|
{
|
2022-06-21 08:09:38 +02:00
|
|
|
var repository = CreateRepository((IScopeAccessor)provider, out _);
|
2018-06-29 19:52:40 +02:00
|
|
|
|
2022-06-21 08:09:38 +02:00
|
|
|
var query = ScopeProvider.CreateQuery<IContent>().Where(x => x.Level == 2);
|
2018-06-29 19:52:40 +02:00
|
|
|
|
2022-06-21 08:09:38 +02:00
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
ScopeAccessor.AmbientScope.Database.AsUmbracoDatabase().EnableSqlTrace = true;
|
|
|
|
|
ScopeAccessor.AmbientScope.Database.AsUmbracoDatabase().EnableSqlCount = true;
|
2018-06-29 19:52:40 +02:00
|
|
|
|
2022-06-21 08:09:38 +02:00
|
|
|
var result = repository.GetPage(query, 0, 1, out var totalRecords, null, Ordering.By("Name"));
|
2018-06-29 19:52:40 +02:00
|
|
|
|
2022-06-21 08:09:38 +02:00
|
|
|
Assert.That(totalRecords, Is.GreaterThanOrEqualTo(2));
|
|
|
|
|
Assert.That(result.Count(), Is.EqualTo(1));
|
|
|
|
|
Assert.That(result.First().Name, Is.EqualTo("Text Page 1"));
|
|
|
|
|
}
|
|
|
|
|
finally
|
|
|
|
|
{
|
|
|
|
|
ScopeAccessor.AmbientScope.Database.AsUmbracoDatabase().EnableSqlTrace = false;
|
|
|
|
|
ScopeAccessor.AmbientScope.Database.AsUmbracoDatabase().EnableSqlCount = false;
|
2018-06-29 19:52:40 +02:00
|
|
|
}
|
|
|
|
|
}
|
2022-06-21 08:09:38 +02:00
|
|
|
}
|
2018-06-29 19:52:40 +02:00
|
|
|
|
2022-06-21 08:09:38 +02:00
|
|
|
[Test]
|
|
|
|
|
public void GetPagedResultsByQuery_SecondPage()
|
|
|
|
|
{
|
|
|
|
|
var provider = ScopeProvider;
|
|
|
|
|
using (var scope = provider.CreateScope())
|
2018-06-29 19:52:40 +02:00
|
|
|
{
|
2022-06-21 08:09:38 +02:00
|
|
|
var repository = CreateRepository((IScopeAccessor)provider, out _);
|
2018-06-29 19:52:40 +02:00
|
|
|
|
2022-06-21 08:09:38 +02:00
|
|
|
var query = ScopeProvider.CreateQuery<IContent>().Where(x => x.Level == 2);
|
|
|
|
|
var result = repository.GetPage(query, 1, 1, out var totalRecords, null, Ordering.By("Name")).ToArray();
|
2018-06-29 19:52:40 +02:00
|
|
|
|
2022-06-21 08:09:38 +02:00
|
|
|
Assert.That(totalRecords, Is.GreaterThanOrEqualTo(2));
|
|
|
|
|
Assert.That(result.Count(), Is.EqualTo(1));
|
|
|
|
|
Assert.That(result.First().Name, Is.EqualTo("Text Page 2"));
|
2018-06-29 19:52:40 +02:00
|
|
|
}
|
2022-06-21 08:09:38 +02:00
|
|
|
}
|
2018-06-29 19:52:40 +02:00
|
|
|
|
2022-06-21 08:09:38 +02:00
|
|
|
[Test]
|
|
|
|
|
public void GetPagedResultsByQuery_SinglePage()
|
|
|
|
|
{
|
|
|
|
|
var provider = ScopeProvider;
|
|
|
|
|
using (var scope = provider.CreateScope())
|
2018-06-29 19:52:40 +02:00
|
|
|
{
|
2022-06-21 08:09:38 +02:00
|
|
|
var repository = CreateRepository((IScopeAccessor)provider, out _);
|
2018-06-29 19:52:40 +02:00
|
|
|
|
2022-06-21 08:09:38 +02:00
|
|
|
var query = ScopeProvider.CreateQuery<IContent>().Where(x => x.Level == 2);
|
|
|
|
|
var result = repository.GetPage(query, 0, 2, out var totalRecords, null, Ordering.By("Name")).ToArray();
|
2018-06-29 19:52:40 +02:00
|
|
|
|
2022-06-21 08:09:38 +02:00
|
|
|
Assert.That(totalRecords, Is.GreaterThanOrEqualTo(2));
|
|
|
|
|
Assert.That(result.Count(), Is.EqualTo(2));
|
|
|
|
|
Assert.That(result.First().Name, Is.EqualTo("Text Page 1"));
|
2018-06-29 19:52:40 +02:00
|
|
|
}
|
2022-06-21 08:09:38 +02:00
|
|
|
}
|
2018-06-29 19:52:40 +02:00
|
|
|
|
2022-06-21 08:09:38 +02:00
|
|
|
[Test]
|
|
|
|
|
public void GetPagedResultsByQuery_DescendingOrder()
|
|
|
|
|
{
|
|
|
|
|
var provider = ScopeProvider;
|
|
|
|
|
using (var scope = provider.CreateScope())
|
2018-06-29 19:52:40 +02:00
|
|
|
{
|
2022-06-21 08:09:38 +02:00
|
|
|
var repository = CreateRepository((IScopeAccessor)provider, out _);
|
2018-06-29 19:52:40 +02:00
|
|
|
|
2022-06-21 08:09:38 +02:00
|
|
|
var query = ScopeProvider.CreateQuery<IContent>().Where(x => x.Level == 2);
|
|
|
|
|
var result = repository.GetPage(query, 0, 1, out var totalRecords, null, Ordering.By("Name", Direction.Descending)).ToArray();
|
2018-06-29 19:52:40 +02:00
|
|
|
|
2022-06-21 08:09:38 +02:00
|
|
|
Assert.That(totalRecords, Is.GreaterThanOrEqualTo(2));
|
|
|
|
|
Assert.That(result.Count(), Is.EqualTo(1));
|
|
|
|
|
Assert.That(result.First().Name, Is.EqualTo("Text Page 2"));
|
2018-06-29 19:52:40 +02:00
|
|
|
}
|
2022-06-21 08:09:38 +02:00
|
|
|
}
|
2018-06-29 19:52:40 +02:00
|
|
|
|
2022-06-21 08:09:38 +02:00
|
|
|
[Test]
|
|
|
|
|
public void GetPagedResultsByQuery_FilterMatchingSome()
|
|
|
|
|
{
|
|
|
|
|
var provider = ScopeProvider;
|
|
|
|
|
using (var scope = provider.CreateScope())
|
2018-06-29 19:52:40 +02:00
|
|
|
{
|
2022-06-21 08:09:38 +02:00
|
|
|
var repository = CreateRepository((IScopeAccessor)provider, out _);
|
2018-06-29 19:52:40 +02:00
|
|
|
|
2022-06-21 08:09:38 +02:00
|
|
|
var query = ScopeProvider.CreateQuery<IContent>().Where(x => x.Level == 2);
|
2018-06-29 19:52:40 +02:00
|
|
|
|
2022-06-21 08:09:38 +02:00
|
|
|
var filterQuery = ScopeProvider.CreateQuery<IContent>().Where(x => x.Name.Contains("Page 2"));
|
|
|
|
|
var result = repository.GetPage(query, 0, 1, out var totalRecords, filterQuery, Ordering.By("Name")).ToArray();
|
2018-06-29 19:52:40 +02:00
|
|
|
|
2022-06-21 08:09:38 +02:00
|
|
|
Assert.That(totalRecords, Is.EqualTo(1));
|
|
|
|
|
Assert.That(result.Count(), Is.EqualTo(1));
|
|
|
|
|
Assert.That(result.First().Name, Is.EqualTo("Text Page 2"));
|
2018-06-29 19:52:40 +02:00
|
|
|
}
|
2022-06-21 08:09:38 +02:00
|
|
|
}
|
2018-06-29 19:52:40 +02:00
|
|
|
|
2022-06-21 08:09:38 +02:00
|
|
|
[Test]
|
|
|
|
|
public void GetPagedResultsByQuery_FilterMatchingAll()
|
|
|
|
|
{
|
|
|
|
|
var provider = ScopeProvider;
|
|
|
|
|
using (var scope = provider.CreateScope())
|
2018-06-29 19:52:40 +02:00
|
|
|
{
|
2022-06-21 08:09:38 +02:00
|
|
|
var repository = CreateRepository((IScopeAccessor)provider, out _);
|
2018-06-29 19:52:40 +02:00
|
|
|
|
2022-06-21 08:09:38 +02:00
|
|
|
var query = ScopeProvider.CreateQuery<IContent>().Where(x => x.Level == 2);
|
2018-06-29 19:52:40 +02:00
|
|
|
|
2022-06-21 08:09:38 +02:00
|
|
|
var filterQuery = ScopeProvider.CreateQuery<IContent>().Where(x => x.Name.Contains("text"));
|
|
|
|
|
var result = repository.GetPage(query, 0, 1, out var totalRecords, filterQuery, Ordering.By("Name")).ToArray();
|
2018-06-29 19:52:40 +02:00
|
|
|
|
2022-06-21 08:09:38 +02:00
|
|
|
Assert.That(totalRecords, Is.EqualTo(2));
|
|
|
|
|
Assert.That(result.Count(), Is.EqualTo(1));
|
|
|
|
|
Assert.That(result.First().Name, Is.EqualTo("Text Page 1"));
|
2018-06-29 19:52:40 +02:00
|
|
|
}
|
2022-06-21 08:09:38 +02:00
|
|
|
}
|
2018-06-29 19:52:40 +02:00
|
|
|
|
2022-06-21 08:09:38 +02:00
|
|
|
[Test]
|
|
|
|
|
public void GetAllContentByIds()
|
|
|
|
|
{
|
|
|
|
|
var provider = ScopeProvider;
|
|
|
|
|
using (var scope = provider.CreateScope())
|
2018-06-29 19:52:40 +02:00
|
|
|
{
|
2022-06-21 08:09:38 +02:00
|
|
|
var repository = CreateRepository((IScopeAccessor)provider, out _);
|
2018-06-29 19:52:40 +02:00
|
|
|
|
2022-06-21 08:09:38 +02:00
|
|
|
var contents = repository.GetMany(_subpage.Id, _subpage2.Id).ToArray();
|
2018-06-29 19:52:40 +02:00
|
|
|
|
2022-06-21 08:09:38 +02:00
|
|
|
Assert.That(contents, Is.Not.Null);
|
|
|
|
|
Assert.That(contents.Any(), Is.True);
|
|
|
|
|
Assert.That(contents.Count(), Is.EqualTo(2));
|
2018-06-29 19:52:40 +02:00
|
|
|
}
|
2022-06-21 08:09:38 +02:00
|
|
|
}
|
2018-06-29 19:52:40 +02:00
|
|
|
|
2022-06-21 08:09:38 +02:00
|
|
|
[Test]
|
|
|
|
|
public void GetAllContent()
|
|
|
|
|
{
|
|
|
|
|
var provider = ScopeProvider;
|
|
|
|
|
using (var scope = provider.CreateScope())
|
2018-06-29 19:52:40 +02:00
|
|
|
{
|
2022-06-21 08:09:38 +02:00
|
|
|
var repository = CreateRepository((IScopeAccessor)provider, out _);
|
2018-06-29 19:52:40 +02:00
|
|
|
|
2022-06-21 08:09:38 +02:00
|
|
|
var contents = repository.GetMany().ToArray();
|
2018-06-29 19:52:40 +02:00
|
|
|
|
2022-06-21 08:09:38 +02:00
|
|
|
Assert.That(contents, Is.Not.Null);
|
|
|
|
|
Assert.That(contents.Any(), Is.True);
|
|
|
|
|
Assert.That(contents.Count(), Is.GreaterThanOrEqualTo(4));
|
2018-06-29 19:52:40 +02:00
|
|
|
|
2022-06-21 08:09:38 +02:00
|
|
|
contents = repository.GetMany(contents.Select(x => x.Id).ToArray()).ToArray();
|
|
|
|
|
Assert.That(contents, Is.Not.Null);
|
|
|
|
|
Assert.That(contents.Any(), Is.True);
|
|
|
|
|
Assert.That(contents.Count(), Is.GreaterThanOrEqualTo(4));
|
2018-06-29 19:52:40 +02:00
|
|
|
|
2022-06-21 08:09:38 +02:00
|
|
|
contents = ((IReadRepository<Guid, IContent>)repository).GetMany(contents.Select(x => x.Key).ToArray()).ToArray();
|
|
|
|
|
Assert.That(contents, Is.Not.Null);
|
|
|
|
|
Assert.That(contents.Any(), Is.True);
|
|
|
|
|
Assert.That(contents.Count(), Is.GreaterThanOrEqualTo(4));
|
2018-06-29 19:52:40 +02:00
|
|
|
}
|
2022-06-21 08:09:38 +02:00
|
|
|
}
|
2018-06-29 19:52:40 +02:00
|
|
|
|
2022-06-21 08:09:38 +02:00
|
|
|
[Test]
|
|
|
|
|
public void ExistContent()
|
|
|
|
|
{
|
|
|
|
|
var provider = ScopeProvider;
|
|
|
|
|
using (var scope = provider.CreateScope())
|
2018-06-29 19:52:40 +02:00
|
|
|
{
|
2022-06-21 08:09:38 +02:00
|
|
|
var repository = CreateRepository((IScopeAccessor)provider, out _);
|
2018-06-29 19:52:40 +02:00
|
|
|
|
2022-06-21 08:09:38 +02:00
|
|
|
var exists = repository.Exists(_subpage.Id);
|
2018-06-29 19:52:40 +02:00
|
|
|
|
2022-06-21 08:09:38 +02:00
|
|
|
Assert.That(exists, Is.True);
|
2018-06-29 19:52:40 +02:00
|
|
|
}
|
2022-06-21 08:09:38 +02:00
|
|
|
}
|
2018-06-29 19:52:40 +02:00
|
|
|
|
2022-06-21 08:09:38 +02:00
|
|
|
[Test]
|
|
|
|
|
public void CountContent()
|
|
|
|
|
{
|
|
|
|
|
var provider = ScopeProvider;
|
|
|
|
|
using (var scope = provider.CreateScope())
|
2018-06-29 19:52:40 +02:00
|
|
|
{
|
2022-06-21 08:09:38 +02:00
|
|
|
var repository = CreateRepository((IScopeAccessor)provider, out _);
|
2018-06-29 19:52:40 +02:00
|
|
|
|
2022-06-21 08:09:38 +02:00
|
|
|
var query = ScopeProvider.CreateQuery<IContent>().Where(x => x.Level == 2);
|
|
|
|
|
var result = repository.Count(query);
|
2018-06-29 19:52:40 +02:00
|
|
|
|
2022-06-21 08:09:38 +02:00
|
|
|
Assert.That(result, Is.GreaterThanOrEqualTo(2));
|
2018-06-29 19:52:40 +02:00
|
|
|
}
|
2022-06-21 08:09:38 +02:00
|
|
|
}
|
2018-06-29 19:52:40 +02:00
|
|
|
|
2022-06-21 08:09:38 +02:00
|
|
|
[Test]
|
|
|
|
|
public void QueryContentByUniqueId()
|
|
|
|
|
{
|
|
|
|
|
var provider = ScopeProvider;
|
|
|
|
|
using (var scope = provider.CreateScope())
|
2018-06-29 19:52:40 +02:00
|
|
|
{
|
2022-06-21 08:09:38 +02:00
|
|
|
var repository = CreateRepository((IScopeAccessor)provider, out _);
|
2018-06-29 19:52:40 +02:00
|
|
|
|
2022-06-21 08:09:38 +02:00
|
|
|
var query = ScopeProvider.CreateQuery<IContent>()
|
|
|
|
|
.Where(x => x.Key == new Guid("B58B3AD4-62C2-4E27-B1BE-837BD7C533E0"));
|
|
|
|
|
var content = repository.Get(query).SingleOrDefault();
|
2018-06-29 19:52:40 +02:00
|
|
|
|
2022-06-21 08:09:38 +02:00
|
|
|
Assert.IsNotNull(content);
|
|
|
|
|
Assert.AreEqual(_textpage.Id, content.Id);
|
2018-06-29 19:52:40 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|