mirror of https://github.com/Squidex/squidex.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
229 lines
9.2 KiB
229 lines
9.2 KiB
// ==========================================================================
|
|
// Squidex Headless CMS
|
|
// ==========================================================================
|
|
// Copyright (c) Squidex UG (haftungsbeschraenkt)
|
|
// All rights reserved. Licensed under the MIT license.
|
|
// ==========================================================================
|
|
|
|
using System.Reflection;
|
|
using System.Security.Claims;
|
|
using System.Text.Json;
|
|
using System.Text.Json.Serialization;
|
|
using System.Text.Json.Serialization.Metadata;
|
|
using Microsoft.Extensions.Options;
|
|
using NetTopologySuite.IO.Converters;
|
|
using NodaTime;
|
|
using NodaTime.Serialization.SystemTextJson;
|
|
using Squidex.Domain.Apps.Core.Apps;
|
|
using Squidex.Domain.Apps.Core.Apps.Json;
|
|
using Squidex.Domain.Apps.Core.Contents;
|
|
using Squidex.Domain.Apps.Core.Contents.Json;
|
|
using Squidex.Domain.Apps.Core.HandleRules;
|
|
using Squidex.Domain.Apps.Core.Rules;
|
|
using Squidex.Domain.Apps.Core.Rules.Deprecated;
|
|
using Squidex.Domain.Apps.Core.Rules.Json;
|
|
using Squidex.Domain.Apps.Core.Schemas;
|
|
using Squidex.Domain.Apps.Core.Schemas.Json;
|
|
using Squidex.Domain.Apps.Events;
|
|
using Squidex.Events.Utils;
|
|
using Squidex.Flows;
|
|
using Squidex.Infrastructure;
|
|
using Squidex.Infrastructure.Commands;
|
|
using Squidex.Infrastructure.EventSourcing;
|
|
using Squidex.Infrastructure.Json;
|
|
using Squidex.Infrastructure.Json.Objects;
|
|
using Squidex.Infrastructure.Json.System;
|
|
using Squidex.Infrastructure.Queries;
|
|
using Squidex.Infrastructure.Queries.Json;
|
|
using Squidex.Infrastructure.Reflection;
|
|
|
|
#pragma warning disable SYSLIB0011 // Type or member is obsolete
|
|
|
|
namespace Squidex.Domain.Apps.Core.TestHelpers;
|
|
|
|
public static class TestUtils
|
|
{
|
|
public static readonly TypeRegistry TypeRegistry = CreateTypeRegistry(typeof(TestUtils).Assembly);
|
|
|
|
public static readonly IJsonSerializer DefaultSerializer = CreateSerializer();
|
|
|
|
private sealed class ObjectHolder<T>
|
|
{
|
|
public T Value1 { get; set; }
|
|
|
|
public T Value2 { get; set; }
|
|
}
|
|
|
|
public static TypeRegistry CreateTypeRegistry(Assembly assembly)
|
|
{
|
|
#pragma warning disable CS0618 // Type or member is obsolete
|
|
var typeRegistry =
|
|
new TypeRegistry()
|
|
.Map(new FieldTypeProvider())
|
|
.Map(new AssemblyTypeProvider<IEvent>(assembly))
|
|
.Map(new AssemblyTypeProvider<IEvent>(SquidexEvents.Assembly))
|
|
.Map(new AssemblyTypeProvider<RuleAction>(assembly))
|
|
.Map(new AssemblyTypeProvider<RuleTrigger>(assembly))
|
|
.Map(new AssemblyTypeProvider<FlowStep>(assembly))
|
|
.Map(new RuleTypeProvider(A.Fake<IFlowStepRegistry>(), Options.Create(new RulesOptions())));
|
|
#pragma warning restore CS0618 // Type or member is obsolete
|
|
|
|
return typeRegistry;
|
|
}
|
|
|
|
public static IJsonSerializer CreateSerializer(Action<JsonSerializerOptions>? configure = null)
|
|
{
|
|
return CreateSerializer(TypeRegistry, configure);
|
|
}
|
|
|
|
public static IJsonSerializer CreateSerializer(TypeRegistry typeRegistry, Action<JsonSerializerOptions>? configure = null)
|
|
{
|
|
var serializerSettings = DefaultOptions(typeRegistry, configure);
|
|
|
|
return new SystemJsonSerializer(serializerSettings);
|
|
}
|
|
|
|
public static JsonSerializerOptions DefaultOptions(Action<JsonSerializerOptions>? configure = null)
|
|
{
|
|
return DefaultOptions(TypeRegistry, configure);
|
|
}
|
|
|
|
public static JsonSerializerOptions DefaultOptions(TypeRegistry typeRegistry, Action<JsonSerializerOptions>? configure = null)
|
|
{
|
|
var options = new JsonSerializerOptions(JsonSerializerDefaults.Web);
|
|
|
|
// It is also a readonly list, so we have to register it first, so that other converters do not pick this up.
|
|
options.Converters.Add(new StringConverter<PropertyPath>(x => x));
|
|
|
|
options.ConfigureForNodaTime(DateTimeZoneProviders.Tzdb);
|
|
options.Converters.Add(new GeoJsonConverterFactory());
|
|
options.Converters.Add(new HeaderValueConverter());
|
|
options.Converters.Add(new JsonValueConverter());
|
|
options.Converters.Add(new PolymorphicConverter<FieldProperties>(typeRegistry));
|
|
options.Converters.Add(new PolymorphicConverter<FlowStep>(typeRegistry));
|
|
options.Converters.Add(new PolymorphicConverter<IEvent>(typeRegistry));
|
|
options.Converters.Add(new PolymorphicConverter<RuleTrigger>(typeRegistry));
|
|
options.Converters.Add(new ReadonlyDictionaryConverterFactory());
|
|
options.Converters.Add(new ReadonlyListConverterFactory());
|
|
options.Converters.Add(new StringConverter<CompareOperator>());
|
|
options.Converters.Add(new StringConverter<DomainId>());
|
|
options.Converters.Add(new StringConverter<Language>());
|
|
options.Converters.Add(new StringConverter<NamedId<DomainId>>());
|
|
options.Converters.Add(new StringConverter<NamedId<Guid>>());
|
|
options.Converters.Add(new StringConverter<NamedId<long>>());
|
|
options.Converters.Add(new StringConverter<NamedId<string>>());
|
|
options.Converters.Add(new StringConverter<RefToken>());
|
|
options.Converters.Add(new StringConverter<Status>());
|
|
options.Converters.Add(new SurrogateJsonConverter<ClaimsPrincipal, ClaimsPrincipalSurrogate>());
|
|
options.Converters.Add(new SurrogateJsonConverter<FieldCollection<RootField>, FieldsSurrogate>());
|
|
options.Converters.Add(new SurrogateJsonConverter<FilterNode<JsonValue>, JsonFilterSurrogate>());
|
|
options.Converters.Add(new SurrogateJsonConverter<LanguageConfig, LanguageConfigSurrogate>());
|
|
options.Converters.Add(new SurrogateJsonConverter<LanguagesConfig, LanguagesConfigSurrogate>());
|
|
options.Converters.Add(new SurrogateJsonConverter<Roles, RolesSurrogate>());
|
|
options.Converters.Add(new SurrogateJsonConverter<Rule, RuleSorrgate>());
|
|
options.Converters.Add(new SurrogateJsonConverter<Schema, SchemaSurrogate>());
|
|
options.Converters.Add(new SurrogateJsonConverter<WorkflowStep, WorkflowStepSurrogate>());
|
|
options.Converters.Add(new SurrogateJsonConverter<WorkflowTransition, WorkflowTransitionSurrogate>());
|
|
options.Converters.Add(new JsonStringEnumConverter());
|
|
options.IncludeFields = true;
|
|
options.TypeInfoResolver = new DefaultJsonTypeInfoResolver()
|
|
.WithAddedModifier(PolymorphicConverter<None>.Modifier(typeRegistry))
|
|
.WithAddedModifier(JsonIgnoreReadonlyProperties.Modifier<Entity>())
|
|
.WithAddedModifier(JsonRenameAttribute.Modifier);
|
|
#pragma warning disable CS0618 // Type or member is obsolete
|
|
options.Converters.Add(new PolymorphicConverter<RuleAction>(typeRegistry));
|
|
#pragma warning restore CS0618 // Type or member is obsolete
|
|
configure?.Invoke(options);
|
|
|
|
return options;
|
|
}
|
|
|
|
public static T SerializeAndDeserializeAsJson<T>(this T value)
|
|
{
|
|
return SerializeAndDeserializeAsJson<T, T>(value);
|
|
}
|
|
|
|
public static TOut SerializeAndDeserializeAsJson<TOut, TIn>(this TIn value)
|
|
{
|
|
var json = DefaultSerializer.Serialize(new ObjectHolder<TIn> { Value1 = value, Value2 = value });
|
|
|
|
return DefaultSerializer.Deserialize<ObjectHolder<TOut>>(json).Value1;
|
|
}
|
|
|
|
public static T DeserializeJson<T>(string value)
|
|
{
|
|
var json = DefaultSerializer.Serialize(new ObjectHolder<string> { Value1 = value, Value2 = value });
|
|
|
|
return DefaultSerializer.Deserialize<ObjectHolder<T>>(json).Value1;
|
|
}
|
|
|
|
public static string SerializeWithoutNullsAsJson<T>(this T value)
|
|
{
|
|
var options = DefaultOptions(options =>
|
|
{
|
|
options.DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull;
|
|
});
|
|
|
|
return new SystemJsonSerializer(options).Serialize(value, true).CleanJson();
|
|
}
|
|
|
|
public static string CleanJson(this string json)
|
|
{
|
|
var document = System.Text.Json.Nodes.JsonNode.Parse(json);
|
|
|
|
static void Handle(System.Text.Json.Nodes.JsonNode? node)
|
|
{
|
|
if (node is System.Text.Json.Nodes.JsonArray array)
|
|
{
|
|
foreach (var item in array)
|
|
{
|
|
Handle(item);
|
|
}
|
|
}
|
|
else if (node is System.Text.Json.Nodes.JsonObject obj)
|
|
{
|
|
var properties = obj.ToList();
|
|
|
|
foreach (var (key, _) in properties)
|
|
{
|
|
obj.Remove(key);
|
|
}
|
|
|
|
foreach (var (key, value) in properties.OrderBy(x => x.Key))
|
|
{
|
|
Handle(value);
|
|
|
|
obj.Add(key, value);
|
|
}
|
|
}
|
|
}
|
|
|
|
Handle(document?.Root);
|
|
|
|
return DefaultSerializer.Serialize(document, true);
|
|
}
|
|
|
|
public static TEvent CreateEvent<TEvent>(Action<TEvent>? init = null) where TEvent : IEvent, new()
|
|
{
|
|
var actual = new TEvent();
|
|
|
|
if (actual is SquidexEvent squidexEvent)
|
|
{
|
|
squidexEvent.Actor = RefToken.Client("my-client");
|
|
}
|
|
|
|
if (actual is AppEvent appEvent)
|
|
{
|
|
appEvent.AppId = NamedId.Of(DomainId.NewGuid(), "my-app");
|
|
}
|
|
|
|
if (actual is SchemaEvent schemaEvent)
|
|
{
|
|
schemaEvent.SchemaId = NamedId.Of(DomainId.NewGuid(), "my-schema");
|
|
}
|
|
|
|
init?.Invoke(actual);
|
|
|
|
return actual;
|
|
}
|
|
}
|
|
|