* New backoffice/add system text json configuration attribute (#12998) * Add SystemTextJsonConfigurationAttribute * Fix up formatting * Rename classes for clearer purpose Co-authored-by: Zeegaan <nge@umbraco.dk> * UmbracoPath should no longer be configurable (#13032) * UmbracoPath should no longer be configurable * Remove UmbracoPath configuration from all tests * Only contain style instead of full layout (#13033) * Only contain style instead of full layout (#13033) * Fix CodeQL duplicate "permissions" node and reformat * add an extra check to ensure the pips exist before adding a class to them * improve pip classList add/remove with no intermediary variable * Only contain style instead of full layout (#13033) * Ensure consistent margin on headings in tree root (#12992) * Ensure consistent margin on headings in tree root (#12992) (cherry picked from commit88bfef9e0d) * Bump version to 10.2.1 * Translate "User permissions for languages" feature to dutch (#12971) * Translate 'sectionsHelp' to Dutch * Translate 'selectLanguages' to Dutch * Transkate 'allowAccessToAllLanguages' to Dutch * Translate "User permissions for languages" feature to español (#12975) * Translate 'selectLanguages' to Español * Translate 'languagesHelp' to español * Translate 'allowAccessToAllLanguages' to spanish * Updated project references for Forms and Deploy in the JsonSchema project. (#13047) * Updated project references for Forms and Deploy in the JsonSchema project. (#13047) * UmbracoPath has been removed from the official schema store, remove temporary workaround from our schema generator as well (#13043) * add an extra check to ensure the pips exist before adding a class to them * improve pip classList add/remove with no intermediary variable * pass in parameters needed to member service (#13020) * Missing methods from IMemberService (#13022) * Add back methods to interface * Add default implementations to avoid breaking changes Co-authored-by: Zeegaan <nge@umbraco.dk> * New endpoint for web profiling dashboard (#13038) * Endpoint for web profiling dashboard * Add profiling API contract * New Backoffice: Published cache controller (#13034) * Add published cache controller (endpoints for the Published Status dashboard) * Update OpenAPI contract for published cache endpoints * Fix OpenApi spec Co-authored-by: Zeegaan <nge@umbraco.dk> * Bug fix for datepicker with offset time (#12847) * https://github.com/umbraco/Umbraco-CMS/issues/12844 * remove "X" from ng-attr Doing the test I killed the ng-if attr. But forgot it was there doing the commit Co-authored-by: Lucas Bach Bisgaard <lom@novicell.dk> * Make sure swagger tags and operations are sorted alphabetically (#13055) * Add spellcheck false to password inputs (#13059) * Add null check for variants in Grid Layout (#13060) This fixes a regression from 10.2.0 where the `variants` property was removed. * Add null check for variants in Grid Layout (#13060) This fixes a regression from 10.2.0 where the `variants` property was removed. * Fixes #12972 for validating legacy member passwords (#12973) * Fixes #12972 for validating legacy member passwords * Removed unused variable * removed unused variable * Fix issue toggling boolean between true/false after Save without refreshing * New backoffice: examine management controller (#12981) * Add ExamineManagementControllerBase * Add ExamineIndexModelFactory * Add IndexesExamineManagementController * Add proper attributes * Implement ExamineIndexViewModel.cs * formatting * Add comment about it working in .NET 7 * Add SearchersExamineManagementController.cs * Update comments about why it might throw errors * Add SearchResultViewModel * Add SearchExamineManagementController * Add ExamineSearcherValidationService * Rename ExamineSearcherValidationService.cs to ExamineSearcherFinderService.cs * Rename interface aswell * Add SearchExamineManagementController * Refactor ExamineSearcherFinderService * Add HasIndexRebuiltExamineManagementController.cs * Fix up formatting * Async actions * Add RebuildIndexExamineManagementController.cs * Rename IExamineIndexModelFactory to IExamineIndexViewModelFactory * Refactor HasIndexRebuilt endpoint to Index endpoint * Remove unused usings * Fix up DetailsExplanation * Create dedicated SearchersViewModel * Rename action * Rename RebuildIndex to Rebuild * Dont have changes in ExamineIndexModel * Make values strongly typed instead of generic lists of strings * Rename to non-plural * Rename to non-plural * Rename controller * Introduce ITemporaryIndexingService * Introduce ITemporaryIndexingService * Add SearcherName to view model * Move to new ExamineManagementControllerBase.cs * Refactor ExamineManagerService * Use init instead of setters * Make properties explicitly on models * Add DI * Apply suggestions from code review Co-authored-by: Kenn Jacobsen <kja@umbraco.dk> * Rename to IndexExamineManagementController * Return ViewModel instead of exception * Make view models non-nullable * Add examine management extension point * Rename to IndexingRebuilderService * Move rebuild logic to service * Fix up usages in IIndexingRebuilderService * Fix up DI * Fix OpenApi contract * Implement CanRebuild on IIndexingRebuilderService.cs Co-authored-by: Zeegaan <nge@umbraco.dk> Co-authored-by: Kenn Jacobsen <kja@umbraco.dk> * Update build script * Add BuildProjectReferences=false to dotnet pack * Internalize Umbraco.Cms.ManagementApi references * Make Searchers endpoint return ActionResult (#13068) * New backoffice - trees design (#12963) * Refactor: Add default versioned back office route attribute * Tree controller bases and first draft implementations for document, media and doctype * Move tree item view models to appropriate location * Fix missing parent * Refactor user entity access for testability * A bit of clean-up + handle user start nodes for items endpoint * Implement foldersOnly for folder tree * Items endpoint for document type tree * Strongly typed action results * Content + media recycle bin * Correct return type for swagger * Member type tree * Rename user start node handling to make a little more sense * Revert to faked admin start nodes in document tree * Media type tree * Data type tree * Relation type tree * Remove unused dependency from member type tree * Correct documentation for member type tree endpoint response types * Use icon constants * Add templates tree * Member group tree * Document blueprint tree * Partial views, scripts and stylesheets trees * Static files tree * Clarify "folders only" state * Comments and improved readability * Rename TreeControllerBase and TreeItemViewModel * Move recycle bin controller base to its own namespace * Moved tree base controllers to their own namespace * Common base class for tree view models * Remove ProblemDetails response type declaration from all actions * Add OpenApiTag * Various review comments * Dictionary item tree * Renamed all tree controllers to follow action/feature naming convention * Handle client culture state for document tree * Support "ignore user start nodes" for content and media + refactor how tree states work to make things more explicit * Fix or postpone a few TODOs * Make entity service able to paginate trashed children * Handle sorting explicitly * Re-apply VersionedApiBackOfficeRoute to install and upgrade controllers after merge * Use PagedViewModel instead of PagedResult for all trees * Explain the usage of UmbracoObjectTypes.Unknown * Introduce and apply GetMany pattern for dictionary items * Add a note about relation type caching * Fix broken test build + add unit tests for new localization service methods * Use new management API controller base * Entity repository should build document entities for document blueprints when getting paged entities (same as it does when getting specific entities) * Use Media type for Media recycle bin Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Move shared relation service to concrete implementations * Use inclusive language * Add 401 response type documentation to applicable trees * Refactor entity load for folder tree controller base + ensure that folders are only included in the first result page * Add (in-memory) pagination to dictionary tree * Make file system controller honor paging parameters * Support pagination in relation type tree * Clarify method name a bit for detecting tree root path requests * Update Open API schema to match new trees * Move from page number and page size to skip/take (with temporary workaround for lack of property skip/take pagination in current DB implementation) * Update OpenAPI schema to match skip/take * Update OpenAPI schema * Don't return paginated view models from "items" endpoints * Update OpenApi schema Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Use pattern matching to check if items is not `JArray` * Bump Smidge up to v4.1.1 * Removing X-XSS-Protection healthcheck * Redirect to a return URL if one is present on the querystring when logging into the back office * Fix issue 13023 - Cannot read properties of undefined (reading 'allowedActions') * Implement playwright acceptance tests instead of cypress (#13069) * fix up dependencies in package.json * Change configs to playwright * update types * remove cypress * add playwright * Fix up imports * Move up test files * Fix up scripts * Update user import * Remove allowEditInvariantFromNonDefault=True.spec.ts * Update docker container * Run playwright on pipelines * Install playwright * change urls * change to run playwright * Update reporter * create .env file when installing * update pipelines * Remove @in yml * Update Yaml script to use New-Item * Pipe object to Value * Update yaml to use "" not {} * Update localhost to proper port * Push package-lock.json * include dotenv in package.json * Add back umbraco.config.ts * Dont change launchSettings.json * Fix up pipelines * Change working directory * Add logging * Actually name the file * Remove .env from path * Add working directory * Add working directory to script * check env content * Update more working dir * Try making newline in YAML * add quotes * Try multiline infront of script * Move top statement * use https * Update to localhost 44331 * ignore https in config * Change linux to https * add timeouts for tests * Fix up url for linux * Update docker to use port 44331 -> 5000 * increase timeout * Update yaml * Remove Cypress references and fix URL/port mapping * Update umbraco-linux.docker * Generate ASP.NET HTTPS development certificate * Enable HTTPS development certificate in Docker * Dont run failing tests * Update HTTPS development certificate generation * Copy nuget.config to correct location in Docker file * do not run flaky test * update outputdir * Remove flaky tests * Update to dot reporter * Update to json-models-builders package * Check if results folder exists * Remove logging * Use bash to find folder * Dont use junit to report * only publish if folder exists * Add 5 retries for CI * search correct folder * Remove unused json file * Use line reporter * Remove umbraco.config.ts * Remove more flaky test * Add waits so we dont bombard SQLite * Add page as parameter * add page as parameter * Remove flaky macro test Co-authored-by: Zeegaan <nge@umbraco.dk> Co-authored-by: Ronald Barendse <ronald@barend.se> * Fix comment of view property in `ConfigurationFieldAttribute` (#13077) * Fix comment of view property in `ConfigurationFieldAttribute` * Update description of key property as well * Use char instead of string for DetectJson (#13019) * Use char instead of string for DetectJson * Use faster method * Change DetectIsJon method * Update acceptance test readme & scripts (#13078) * Update readme to reflect the change to playwright * Update test scripts * update README * update pipelines to run new script * update package.json scripts * dont include demo test in package.json * Add creation of blueprint test * Implement create test script Co-authored-by: Zeegaan <nge@umbraco.dk> * Refactor event handler away from keyup to ng-change * Don't use legacy icon for action delete * Added nullability attribute to IsNullOrWhitespace * Fixes umbraco/Umbraco-CMS.Accessibility.Issues #63 and #61 * Revert "Removing X-XSS-Protection healthcheck" (#13096) This reverts commit696475ebf2. Co-authored-by: Zeegaan <nge@umbraco.dk> * New backoffice: New Api controllers (#12983) * Create migrate Language controller to Umbraco.Cms:ManagementApi * Add proper language mapping * Update mapping to handle if language name is null * Uncomment code * Add new language view model * Add LanguageViewModelMapping * Add mapper registration * Fix up AddMappers extension method * Implement mapping IEnumerable of languages * Change action signatures to ViewModel instead of model * Seperate logic from controller into service * Move LanguageService.cs * Register service * Fix up mapping * Add null check to mapping instead of controller * Map to ILanguage instead of implementation * Fix up null check * Implement ProblemDetailsBuilder.cs * Rename duplicate method * Use builder in actions * Implement new Paged models * Create language controller base * Use pagedModel for GetAllLanguages * Create GetAllLanguagesPaged method * Split language controller into single APIs * Fix up controllers with API versions * Map Total property * Fix up route and naming for GetLanguageController.cs * Fix up naming for language controllers * New folder structure * Add culture controllers * Map CultureInfos to paged CultureViewModel * Remove wierd include in csproj * Refactor controller to return pagedViewModel instead of dictionary * Fix up mapping to map single and enumerable * Register mapping * Add apiversion to controller * Add inheritdoc * Create DictionaryControllerBase.cs * Add delete controller * Only use HttpDelete for deletes * Check also if language exists in service * Split Save action into Create & Update actions * Update Http attributes on Create and update controllers * Proper routing for delete controller * Add api version * Make action async * Implement CreateDictionaryController * Create DictionaryViewModel.cs * Use viewmodel instead of values * Create get by int DictionaryController * Add view models * Rename controller * Rename DictionaryViewModel to DictionaryItemViewModel * use created instead of ID * Apply DataContract/Datamember to view model * change to guid instead of Guid * Use proper responses instead of return models when creating/updating * Implement new IDictionaryService * Implement new MoveController * Use new service in mapper * Remove unused method * Add DictionaryViewModelMapDefinition * Create MoveOrCopyViewModel * Proper Http action * Create UpdateDictionary controller * Map IDictionaryItem to DictionaryViewModel * Add JsonPatching * Add UpdateDictionaryController.cs * Map DictionaryTranslationsDisplays properly * ParentId should be nullable * Add new DictionaryTranslationViewModel.cs * Remove translationViewModel * Add Id and Key to DictionaryTranslationDisplay.cs * Implement IDictionaryFactory.cs * Create DictionaryViewModels and do not use IEntity * Map to new view models instead of displays * Register the factiories in the service container * Remove newtonsoft * Add serializing to and from PatchDocs * Use JsonPatchViewModel instead of object type * Add JsonPatch.Net to csproj * Implement JsonPatchService.cs * Register JsonPatchService * Make model non-nullable * Update controllers to use new attributes * Rename MoveViewModel.cs * Remove NameIsDirty as that is legacy from how we used to handle updating * Add GetAllDictionaryController * Add todo to DictionaryControllerBase * Add ExportDictionaryController * Add ImportDictionaryController * Remove unused umbraco mapper * Add upload dictionary controller * Create Dictionary import view models * Update UploadDictionaryController with view models * Remove unused using * Implement pagedviewmodel for GetAllDictionaryController.cs * Add dictionary overview viewmodels * Add mapping for DictionaryOverViewModel * Update Dictionary controller to use new viewmodel * Fix up attributes for UploadDictionaryController * Make actions async * Make controller bases abstract * Fix after merge * New backoffice: Analytics controller (#12957) * Add AnalyticsControllerBase * Add AnalyticsViewModel * Add GetAnalyticsController * Update ViewModel to use System.Text.Json * Add SetAnalyticsController * Add AnalyticsLevelViewModel * Add GetAllAnalyticsController * Add viewmodel factory * Register factory for DI * Use factory for creation of ViewModel * Fix up AnalyticsLevelViewModel.cs * Use analyticsLevelViewModel * Add Enum validation to controller * Add OpenApi attributes * Add routing to GetAllAnalyticsController * Rename IPagedViewModelFactory * use new renamed PagedViewModelFactory * Make actions async * Make controller base abstract * Fix up after merge Co-authored-by: Zeegaan <nge@umbraco.dk> * New backoffice: Help controller (#12958) * Add HelpControllerBase * Add HelpPageViewModel * Add GetHelpController * Add viewmodel factory * Register factory for DI * Use PagedViewModelFactory for controller * Update baseurl to be nullable * Rename IPagedViewModelFactory * Use new renamed IPagedViewModelFactory * Dont use httpclient as field Co-authored-by: Zeegaan <nge@umbraco.dk> * New backoffice: Relation controller (#12961) * Add relation controller base * Add commen about auth * Add GetRelationController * Use mapping to viewmodel * Add RelationViewModel * Add RelationViewModelsMapDefinition.cs * Add viewmodel factory * Register factory for DI * Rename IPagedViewModelFactory * Add RelationViewModelFactory * Remove unused service * Add GetByChildRelationController * Add relationViewModelFactory to DI * Add MappingBuilderExtensions * Add relationViewModelsMapDefinition to DI * Use PagedViewModel for child relations * Add CreateMultiple * Update GetRelationController to use factory instead of direct mapping * Update GetByChildRelationController to use relationViewModelFactory * Fix up after merge Co-authored-by: Zeegaan <nge@umbraco.dk> * New backoffice: Tracked references controller (#12966) * Add TrackedReferencesControllerBase.cs * Add GetTrackedReferencesController * Add relation model * Add ITrackedReferencesRepository.cs * Rename relation to RelationModel * Add RelationMapDefinition.cs * Add TrackedReferencesSkipTakeRepository * Rename RelationModelMapDefinition * Add new services to DI * Rename RelationModel to RelationItemModel * Implement TrackedReferencesSkipTakeService * Formatting * Add RelationItemViewModel.cs * Add mapdefition * Update TrackedReferencesController to use new PagedViewModel * Add service to DI * imlement proper routing * Add async to GetTrackedReferencesController.cs * Rename action to get * Add DescendantTrackedReferencesController * make filterMustBeIsDependency nullable * Use count instead of capacity * Rename controller * Add MultipleTrackedReferencesController.cs * Refactor TrackedReferencesService to not return pagedViewModel * Remove TODO untill consensus on convention * Formatting * Delete old duplicate controller * Fix up naming * Fix up naming and fixed todo * Fix up mapdefinition registrations * Rename controllers * Fix naming * Fix nullable tree * Fix up relation controller & action names * Fix naming * Fix up multiple to not be post * Apply suggestions from code review Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Remove [ApiVersion] from each individual controller and added to base instead * Added missing semi-colon * Update all "non-async async" endpoints to return Task.FromResult * Fixed up LanguageViewModels namespace * Return proper status code * Update xml documentation * Rename GetAllCultureController * Change return type attribute to proper Model * Change return type attribute to correct model * Add clarifying comment * Change return type attribute to proper model * Rename ById to by key * Update DictionaryOverviewViewModel to use Key instead of ID * Implement factory method to create viewModel instead of using services in mapper * Fix up DictionaryItemViewModel to use Parent GUID instead of ID * Update return type attribute to correct model * Update key to actual GUID instead of string * Update route to not include "delete" * Remove redundant IActionResult specification * Update responseType attribute to correct models * Update OpenApiTag for DictionaryControllerBase * Update ResponseType attribute to correct models * update variable name to not be "XD" * Update ResponseType attribute to correct model * Update route to not include "update" as it is redundant * Update produces responsetype attributes to correct models * Use IJsonSerializer abstraction instead of JsonConvert directly * Remove unused field * Change ResponseType attribute to correct model * change TrackedReferencesSkipTakeService to return pagedModels directly * Remove duplicate DI * change to better variable names * Move RelationItemModel to core * Remove empty folder * Remove ITrackedReferencesSkipTakeService and add it to TrackedReferencesService * remove TrackedReferencesSkipTakeRepository and add to TrackedReferencesRepository.cs * Fix up TrackedReferencesService to not use SkipTake repository * Remove AddRepositories from ManagementApiComposer * Transition to ManagementApiBaseController * Fixes ResponseType attribute to correct model * Add loading files to service instead of having logic in controller * Add todo comment * Fix up routing for delete language * Use problem details builder * Add SystemTextJsonSerializer * Add SystemTextJsonSerializer * Remove unused usings * Remove obsolete MoveDictionaryController * Remove CreateDate and UpdateDate from DictionaryViewModel * Change response type to correct model * Remove PagedViewModelFactory.cs * Add obsolete message * Fix installer view models A setter is required for the modelbinder to be able to do its work * Update src/Umbraco.Cms.ManagementApi/Controllers/Analytics/SetAnalyticsController.cs Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> * Update ResponseType to correct Model * Update comment * Add FileUploadService * Add DictionaryFactory.cs to handle creation of viewmodel * Remove unused DI * Rename actions & controllers to reflect eachother * Update OpenApi.json * Add dictionary to openapi * Update in proper alphabetical order * Add trackedReferences to openapi * Fix open api doc Co-authored-by: Nikolaj Geisle <70372949+Zeegaan@users.noreply.github.com> Co-authored-by: Zeegaan <nge@umbraco.dk> * Backport project cleanup from #12907 * Remove empty Directory.Build.props * Fix GenerateAppsettingsSchema target * Re-add empty Directory.Build.props to prevent inheritance * Re-add missing JsonPatch.Net dependency * Fix merge issues (redundant TargetFramework property and appsettings-schema.json generation) * Fix and improve OpenAPI test assertion Co-authored-by: Sebastiaan Janssen <sebastiaan@umbraco.com> Co-authored-by: Nikolaj Geisle <70372949+Zeegaan@users.noreply.github.com> Co-authored-by: Zeegaan <nge@umbraco.dk> Co-authored-by: Kenn Jacobsen <kja@umbraco.dk> Co-authored-by: Mads Rasmussen <madsr@hey.com> Co-authored-by: Jacob Overgaard <752371+iOvergaard@users.noreply.github.com> Co-authored-by: Bjarne Fyrstenborg <bjarne_fyrstenborg@hotmail.com> Co-authored-by: Erik-Jan Westendorp <erikjanwestendorp@outlook.com> Co-authored-by: Andy Butland <abutland73@gmail.com> Co-authored-by: Sean <29239704+Bakersbakebread@users.noreply.github.com> Co-authored-by: Lucas Bach Bisgaard <rammi@rammi.dk> Co-authored-by: Lucas Bach Bisgaard <lom@novicell.dk> Co-authored-by: Mole <nikolajlauridsen@protonmail.ch> Co-authored-by: Busra Sengul <aysebusrasengul@gmail.com> Co-authored-by: Justin Neville <justin@nevitech.co.uk> Co-authored-by: Jeavon Leopold <jeavon@crumpled-dog.com> Co-authored-by: Austin Gilbert <AGilbert@rbaconsulting.com> Co-authored-by: patrickdemooij9 <patrickdemooij98@hotmail.com> Co-authored-by: bakersbakebread <hello@seanthorne.co.uk> Co-authored-by: Karl Butler <kbutler@carbonsix.digital>
479 lines
15 KiB
C#
479 lines
15 KiB
C#
// Copyright (c) Umbraco.
|
|
// See LICENSE for more details.
|
|
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Diagnostics;
|
|
using System.Linq;
|
|
using NUnit.Framework;
|
|
using Umbraco.Cms.Core.Models;
|
|
using Umbraco.Cms.Core.Services;
|
|
using Umbraco.Cms.Infrastructure.Persistence;
|
|
using Umbraco.Cms.Tests.Common.Builders;
|
|
using Umbraco.Cms.Tests.Common.Builders.Extensions;
|
|
using Umbraco.Cms.Tests.Common.Testing;
|
|
using Umbraco.Cms.Tests.Integration.Testing;
|
|
|
|
namespace Umbraco.Cms.Tests.Integration.Umbraco.Infrastructure.Services;
|
|
|
|
/// <summary>
|
|
/// Tests covering all methods in the LocalizationService class.
|
|
/// This is more of an integration test as it involves multiple layers
|
|
/// as well as configuration.
|
|
/// </summary>
|
|
[TestFixture]
|
|
[UmbracoTest(Database = UmbracoTestOptions.Database.NewSchemaPerTest)]
|
|
public class LocalizationServiceTests : UmbracoIntegrationTest
|
|
{
|
|
[SetUp]
|
|
public void SetUp() => CreateTestData();
|
|
|
|
private Guid _parentItemGuidId;
|
|
private int _parentItemIntId;
|
|
private Guid _childItemGuidId;
|
|
private int _childItemIntId;
|
|
private int _danishLangId;
|
|
private int _englishLangId;
|
|
|
|
private ILocalizationService LocalizationService => GetRequiredService<ILocalizationService>();
|
|
|
|
[Test]
|
|
public void Can_Get_Root_Dictionary_Items()
|
|
{
|
|
var rootItems = LocalizationService.GetRootDictionaryItems();
|
|
|
|
Assert.NotNull(rootItems);
|
|
Assert.IsTrue(rootItems.Any());
|
|
}
|
|
|
|
[Test]
|
|
public void Can_Determint_If_DictionaryItem_Exists()
|
|
{
|
|
var exists = LocalizationService.DictionaryItemExists("Parent");
|
|
Assert.IsTrue(exists);
|
|
}
|
|
|
|
[Test]
|
|
public void Can_Get_All_Languages()
|
|
{
|
|
var languages = LocalizationService.GetAllLanguages();
|
|
Assert.NotNull(languages);
|
|
Assert.IsTrue(languages.Any());
|
|
Assert.That(languages.Count(), Is.EqualTo(3));
|
|
}
|
|
|
|
[Test]
|
|
public void Can_Get_Dictionary_Item_By_Int_Id()
|
|
{
|
|
var parentItem = LocalizationService.GetDictionaryItemById(_parentItemIntId);
|
|
Assert.NotNull(parentItem);
|
|
|
|
var childItem = LocalizationService.GetDictionaryItemById(_childItemIntId);
|
|
Assert.NotNull(childItem);
|
|
}
|
|
|
|
[Test]
|
|
public void Can_Get_Dictionary_Item_By_Guid_Id()
|
|
{
|
|
var parentItem = LocalizationService.GetDictionaryItemById(_parentItemGuidId);
|
|
Assert.NotNull(parentItem);
|
|
|
|
var childItem = LocalizationService.GetDictionaryItemById(_childItemGuidId);
|
|
Assert.NotNull(childItem);
|
|
}
|
|
|
|
[Test]
|
|
public void Can_Get_Dictionary_Items_By_Guid_Ids()
|
|
{
|
|
var items = LocalizationService.GetDictionaryItemsByIds(_parentItemGuidId, _childItemGuidId);
|
|
Assert.AreEqual(2, items.Count());
|
|
Assert.NotNull(items.FirstOrDefault(i => i.Key == _parentItemGuidId));
|
|
Assert.NotNull(items.FirstOrDefault(i => i.Key == _childItemGuidId));
|
|
}
|
|
|
|
[Test]
|
|
public void Can_Get_Dictionary_Item_By_Key()
|
|
{
|
|
var parentItem = LocalizationService.GetDictionaryItemByKey("Parent");
|
|
Assert.NotNull(parentItem);
|
|
|
|
var childItem = LocalizationService.GetDictionaryItemByKey("Child");
|
|
Assert.NotNull(childItem);
|
|
}
|
|
|
|
[Test]
|
|
public void Can_Get_Dictionary_Items_By_Keys()
|
|
{
|
|
var items = LocalizationService.GetDictionaryItemsByKeys("Parent", "Child");
|
|
Assert.AreEqual(2, items.Count());
|
|
Assert.NotNull(items.FirstOrDefault(i => i.ItemKey == "Parent"));
|
|
Assert.NotNull(items.FirstOrDefault(i => i.ItemKey == "Child"));
|
|
}
|
|
|
|
[Test]
|
|
public void Can_Get_Dictionary_Item_Children()
|
|
{
|
|
var item = LocalizationService.GetDictionaryItemChildren(_parentItemGuidId);
|
|
Assert.NotNull(item);
|
|
Assert.That(item.Count(), Is.EqualTo(1));
|
|
|
|
foreach (var dictionaryItem in item)
|
|
{
|
|
Assert.AreEqual(_parentItemGuidId, dictionaryItem.ParentId);
|
|
Assert.IsFalse(string.IsNullOrEmpty(dictionaryItem.ItemKey));
|
|
}
|
|
}
|
|
|
|
[Test]
|
|
public void Can_Get_Dictionary_Item_Descendants()
|
|
{
|
|
using (var scope = ScopeProvider.CreateScope())
|
|
{
|
|
var en = LocalizationService.GetLanguageById(_englishLangId);
|
|
var dk = LocalizationService.GetLanguageById(_danishLangId);
|
|
|
|
var currParentId = _childItemGuidId;
|
|
for (var i = 0; i < 25; i++)
|
|
{
|
|
// Create 2 per level
|
|
var desc1 = new DictionaryItem(currParentId, "D1" + i)
|
|
{
|
|
Translations = new List<IDictionaryTranslation>
|
|
{
|
|
new DictionaryTranslation(en, "ChildValue1 " + i),
|
|
new DictionaryTranslation(dk, "BørnVærdi1 " + i)
|
|
}
|
|
};
|
|
var desc2 = new DictionaryItem(currParentId, "D2" + i)
|
|
{
|
|
Translations = new List<IDictionaryTranslation>
|
|
{
|
|
new DictionaryTranslation(en, "ChildValue2 " + i),
|
|
new DictionaryTranslation(dk, "BørnVærdi2 " + i)
|
|
}
|
|
};
|
|
LocalizationService.Save(desc1);
|
|
LocalizationService.Save(desc2);
|
|
|
|
currParentId = desc1.Key;
|
|
}
|
|
|
|
ScopeAccessor.AmbientScope.Database.AsUmbracoDatabase().EnableSqlTrace = true;
|
|
ScopeAccessor.AmbientScope.Database.AsUmbracoDatabase().EnableSqlCount = true;
|
|
|
|
var items = LocalizationService.GetDictionaryItemDescendants(_parentItemGuidId).ToArray();
|
|
|
|
Debug.WriteLine("SQL CALLS: " + ScopeAccessor.AmbientScope.Database.AsUmbracoDatabase().SqlCount);
|
|
|
|
Assert.AreEqual(51, items.Length);
|
|
|
|
// There's a call or two to get languages, so apart from that there should only be one call per level.
|
|
Assert.Less(ScopeAccessor.AmbientScope.Database.AsUmbracoDatabase().SqlCount, 30);
|
|
}
|
|
}
|
|
|
|
[Test]
|
|
public void Can_GetLanguageById()
|
|
{
|
|
var danish = LocalizationService.GetLanguageById(_danishLangId);
|
|
var english = LocalizationService.GetLanguageById(_englishLangId);
|
|
Assert.NotNull(danish);
|
|
Assert.NotNull(english);
|
|
}
|
|
|
|
[Test]
|
|
public void Can_GetLanguageByIsoCode()
|
|
{
|
|
var danish = LocalizationService.GetLanguageByIsoCode("da-DK");
|
|
var english = LocalizationService.GetLanguageByIsoCode("en-GB");
|
|
Assert.NotNull(danish);
|
|
Assert.NotNull(english);
|
|
}
|
|
|
|
[Test]
|
|
public void Does_Not_Fail_When_Language_Doesnt_Exist()
|
|
{
|
|
var language = LocalizationService.GetLanguageByIsoCode("sv-SE");
|
|
Assert.Null(language);
|
|
}
|
|
|
|
[Test]
|
|
public void Does_Not_Fail_When_DictionaryItem_Doesnt_Exist()
|
|
{
|
|
var item = LocalizationService.GetDictionaryItemByKey("RandomKey");
|
|
Assert.Null(item);
|
|
}
|
|
|
|
[Test]
|
|
public void Can_Delete_Language()
|
|
{
|
|
var languageNbNo = new LanguageBuilder()
|
|
.WithCultureInfo("nb-NO")
|
|
.Build();
|
|
LocalizationService.Save(languageNbNo, 0);
|
|
Assert.That(languageNbNo.HasIdentity, Is.True);
|
|
var languageId = languageNbNo.Id;
|
|
|
|
LocalizationService.Delete(languageNbNo);
|
|
|
|
var language = LocalizationService.GetLanguageById(languageId);
|
|
Assert.Null(language);
|
|
}
|
|
|
|
[Test]
|
|
public void Can_Delete_Language_Used_As_Fallback()
|
|
{
|
|
var languageDaDk = LocalizationService.GetLanguageByIsoCode("da-DK");
|
|
var languageNbNo = new LanguageBuilder()
|
|
.WithCultureInfo("nb-NO")
|
|
.WithFallbackLanguageId(languageDaDk.Id)
|
|
.Build();
|
|
LocalizationService.Save(languageNbNo, 0);
|
|
var languageId = languageDaDk.Id;
|
|
|
|
LocalizationService.Delete(languageDaDk);
|
|
|
|
var language = LocalizationService.GetLanguageById(languageId);
|
|
Assert.Null(language);
|
|
}
|
|
|
|
[Test]
|
|
public void Can_Create_DictionaryItem_At_Root()
|
|
{
|
|
var english = LocalizationService.GetLanguageByIsoCode("en-US");
|
|
|
|
var item = (IDictionaryItem)new DictionaryItem("Testing123")
|
|
{
|
|
Translations = new List<IDictionaryTranslation> { new DictionaryTranslation(english, "Hello world") }
|
|
};
|
|
LocalizationService.Save(item);
|
|
|
|
// re-get
|
|
item = LocalizationService.GetDictionaryItemById(item.Id);
|
|
|
|
Assert.Greater(item.Id, 0);
|
|
Assert.IsTrue(item.HasIdentity);
|
|
Assert.IsFalse(item.ParentId.HasValue);
|
|
Assert.AreEqual("Testing123", item.ItemKey);
|
|
Assert.AreEqual(1, item.Translations.Count());
|
|
}
|
|
|
|
[Test]
|
|
public void Can_Create_DictionaryItem_At_Root_With_Identity()
|
|
{
|
|
var item = LocalizationService.CreateDictionaryItemWithIdentity(
|
|
"Testing12345", null, "Hellooooo");
|
|
|
|
// re-get
|
|
item = LocalizationService.GetDictionaryItemById(item.Id);
|
|
|
|
Assert.IsNotNull(item);
|
|
Assert.Greater(item.Id, 0);
|
|
Assert.IsTrue(item.HasIdentity);
|
|
Assert.IsFalse(item.ParentId.HasValue);
|
|
Assert.AreEqual("Testing12345", item.ItemKey);
|
|
var allLangs = LocalizationService.GetAllLanguages();
|
|
Assert.Greater(allLangs.Count(), 0);
|
|
foreach (var language in allLangs)
|
|
{
|
|
Assert.AreEqual("Hellooooo",
|
|
item.Translations.Single(x => x.Language.CultureName == language.CultureName).Value);
|
|
}
|
|
}
|
|
|
|
[Test]
|
|
public void Can_Add_Translation_To_Existing_Dictionary_Item()
|
|
{
|
|
var english = LocalizationService.GetLanguageByIsoCode("en-US");
|
|
|
|
var item = (IDictionaryItem)new DictionaryItem("Testing123");
|
|
LocalizationService.Save(item);
|
|
|
|
// re-get
|
|
item = LocalizationService.GetDictionaryItemById(item.Id);
|
|
|
|
item.Translations = new List<IDictionaryTranslation> { new DictionaryTranslation(english, "Hello world") };
|
|
|
|
LocalizationService.Save(item);
|
|
|
|
Assert.AreEqual(1, item.Translations.Count());
|
|
foreach (var translation in item.Translations)
|
|
{
|
|
Assert.AreEqual("Hello world", translation.Value);
|
|
}
|
|
|
|
item.Translations = new List<IDictionaryTranslation>(item.Translations)
|
|
{
|
|
new DictionaryTranslation(
|
|
LocalizationService.GetLanguageByIsoCode("en-GB"),
|
|
"My new value")
|
|
};
|
|
|
|
LocalizationService.Save(item);
|
|
|
|
// re-get
|
|
item = LocalizationService.GetDictionaryItemById(item.Id);
|
|
|
|
Assert.AreEqual(2, item.Translations.Count());
|
|
Assert.AreEqual("Hello world", item.Translations.First().Value);
|
|
Assert.AreEqual("My new value", item.Translations.Last().Value);
|
|
}
|
|
|
|
[Test]
|
|
public void Can_Delete_DictionaryItem()
|
|
{
|
|
var item = LocalizationService.GetDictionaryItemByKey("Child");
|
|
Assert.NotNull(item);
|
|
|
|
LocalizationService.Delete(item);
|
|
|
|
var deletedItem = LocalizationService.GetDictionaryItemByKey("Child");
|
|
Assert.Null(deletedItem);
|
|
}
|
|
|
|
[Test]
|
|
public void Can_Update_Existing_DictionaryItem()
|
|
{
|
|
var item = LocalizationService.GetDictionaryItemByKey("Child");
|
|
foreach (var translation in item.Translations)
|
|
{
|
|
translation.Value += "UPDATED";
|
|
}
|
|
|
|
LocalizationService.Save(item);
|
|
|
|
var updatedItem = LocalizationService.GetDictionaryItemByKey("Child");
|
|
Assert.NotNull(updatedItem);
|
|
|
|
foreach (var translation in updatedItem.Translations)
|
|
{
|
|
Assert.That(translation.Value.EndsWith("UPDATED"), Is.True);
|
|
}
|
|
}
|
|
|
|
[Test]
|
|
public void Find_BaseData_Language()
|
|
{
|
|
// Act
|
|
var languages = LocalizationService.GetAllLanguages();
|
|
|
|
// Assert
|
|
Assert.That(3, Is.EqualTo(languages.Count()));
|
|
}
|
|
|
|
[Test]
|
|
public void Save_Language_And_GetLanguageByIsoCode()
|
|
{
|
|
// Arrange
|
|
var isoCode = "en-AU";
|
|
var languageEnAu = new LanguageBuilder()
|
|
.WithCultureInfo(isoCode)
|
|
.Build();
|
|
|
|
// Act
|
|
LocalizationService.Save(languageEnAu);
|
|
var result = LocalizationService.GetLanguageByIsoCode(isoCode);
|
|
|
|
// Assert
|
|
Assert.NotNull(result);
|
|
}
|
|
|
|
[Test]
|
|
public void Save_Language_And_GetLanguageById()
|
|
{
|
|
// Arrange
|
|
var languageEnAu = new LanguageBuilder()
|
|
.WithCultureInfo("en-AU")
|
|
.Build();
|
|
|
|
// Act
|
|
LocalizationService.Save(languageEnAu);
|
|
var result = LocalizationService.GetLanguageById(languageEnAu.Id);
|
|
|
|
// Assert
|
|
Assert.NotNull(result);
|
|
}
|
|
|
|
[Test]
|
|
public void Set_Default_Language()
|
|
{
|
|
var languageEnAu = new LanguageBuilder()
|
|
.WithCultureInfo("en-AU")
|
|
.WithIsDefault(true)
|
|
.Build();
|
|
LocalizationService.Save(languageEnAu);
|
|
var result = LocalizationService.GetLanguageById(languageEnAu.Id);
|
|
|
|
Assert.IsTrue(result.IsDefault);
|
|
|
|
var languageEnNz = new LanguageBuilder()
|
|
.WithCultureInfo("en-NZ")
|
|
.WithIsDefault(true)
|
|
.Build();
|
|
LocalizationService.Save(languageEnNz);
|
|
var result2 = LocalizationService.GetLanguageById(languageEnNz.Id);
|
|
|
|
// re-get
|
|
result = LocalizationService.GetLanguageById(languageEnAu.Id);
|
|
|
|
Assert.IsTrue(result2.IsDefault);
|
|
Assert.IsFalse(result.IsDefault);
|
|
}
|
|
|
|
[Test]
|
|
public void Deleted_Language_Should_Not_Exist()
|
|
{
|
|
var isoCode = "en-AU";
|
|
var languageEnAu = new LanguageBuilder()
|
|
.WithCultureInfo(isoCode)
|
|
.Build();
|
|
LocalizationService.Save(languageEnAu);
|
|
|
|
// Act
|
|
LocalizationService.Delete(languageEnAu);
|
|
var result = LocalizationService.GetLanguageByIsoCode(isoCode);
|
|
|
|
// Assert
|
|
Assert.Null(result);
|
|
}
|
|
|
|
public void CreateTestData()
|
|
{
|
|
var languageDaDk = new LanguageBuilder()
|
|
.WithCultureInfo("da-DK")
|
|
.Build();
|
|
var languageEnGb = new LanguageBuilder()
|
|
.WithCultureInfo("en-GB")
|
|
.Build();
|
|
|
|
LocalizationService.Save(languageDaDk, 0);
|
|
LocalizationService.Save(languageEnGb, 0);
|
|
_danishLangId = languageDaDk.Id;
|
|
_englishLangId = languageEnGb.Id;
|
|
|
|
var parentItem = new DictionaryItem("Parent")
|
|
{
|
|
Translations = new List<IDictionaryTranslation>
|
|
{
|
|
new DictionaryTranslation(languageEnGb, "ParentValue"),
|
|
new DictionaryTranslation(languageDaDk, "ForældreVærdi")
|
|
}
|
|
};
|
|
LocalizationService.Save(parentItem);
|
|
_parentItemGuidId = parentItem.Key;
|
|
_parentItemIntId = parentItem.Id;
|
|
|
|
var childItem = new DictionaryItem(parentItem.Key, "Child")
|
|
{
|
|
Translations = new List<IDictionaryTranslation>
|
|
{
|
|
new DictionaryTranslation(languageEnGb, "ChildValue"),
|
|
new DictionaryTranslation(languageDaDk, "BørnVærdi")
|
|
}
|
|
};
|
|
LocalizationService.Save(childItem);
|
|
_childItemGuidId = childItem.Key;
|
|
_childItemIntId = childItem.Id;
|
|
}
|
|
}
|