Added logic to search for workflow-as-activities based on DefinitionId (not only versionId) (#7149)
* Inital commit: 1. Fixed problem: (re-)added logic to search for workflow-as-activities based on DefinitionId (not only versionId) 2. Added tests for Deserialiazation so this logic cannot disappear "unnoticed" in the future. * Found one flaw: workflowDefinitionId is also used in other activities. Therefore, we must make sure to only search by workflowDefinitionId when the value is a string (e.g. when workflow used as activity, the value will always be a constant string, because the workflowDefinitionId cannot be resolved using expressions) * Final attempt: 1) First try to find the activity by type name 2) Even if a descriptor is found by its type name, there might be multiple versions of a workflow-as-activity, hence; if the workflowDefinitionVersionId is specified, then this can override the initially found activity descriptor by type name. 3) Lastly, only when no activity descriptor is found by type name AND the activity JSON contains the property "workflowDeftinitionId", then we can search by workflowDefinitionId * Add `net8.0` and `net9.0` targets, update package versions for resilience libraries. * Exclude `net10.0` target framework from MySQL EF Core project due to Pomelo compatibility constraints. * Remove unnecessary whitespace in MySQL EF Core project file * Refactor `ActivityJsonConverterTests` to streamline registry setup and improve readability. * Adds null activity descriptor lookup mock Ensures the custom property lookup path is tested by mocking type name lookups to return null when searching for ActivityDescriptors. * Fix activity descriptor override assignment in `ActivityJsonConverter` Corrects the assignment logic for `activityDescriptor` and ensures `activityTypeVersion` uses the overridden descriptor's version when a custom property match is found. * Apply suggestion from @Copilot Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Refactor `ActivityJsonConverter` for readability and logic improvements - Adjust null-check handling for `activityDescriptor` overrides. - Improve comment clarity and consolidate lambda expressions. - Remove unnecessary whitespace. * Add blob extension handling to `BlobStorageWorkflowsProvider` - Introduce `BlobExtensions` for extracting blob file extensions. - Add `SupportsExtension` to `IBlobWorkflowFormatHandler` to filter handlers by supported extensions. * Remove unused workflow files and references in `Elsa.Server.Web` - Deleted `flowchart-test.elsa` and `multi-workflow-example.elsa`. - Removed corresponding references from the project file. --------- Co-authored-by: Joey Barten - Founder Orbyss <joey.barten@unfussiness.io> Co-authored-by: Sipke Schoorstra <sipkeschoorstra@outlook.com> Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
This commit is contained in:
parent
4bbdd6f3a7
commit
48b574a411
|
|
@ -30,10 +30,10 @@
|
|||
<PackageVersion Include="Microsoft.Extensions.Hosting.Abstractions" Version="9.0.11"/>
|
||||
<PackageVersion Include="Microsoft.Extensions.Http" Version="9.0.11"/>
|
||||
<PackageVersion Include="Microsoft.Extensions.Http.Polly" Version="9.0.11"/>
|
||||
<PackageVersion Include="Microsoft.Extensions.Http.Resilience" Version="9.0.11"/>
|
||||
<PackageVersion Include="Microsoft.Extensions.Http.Resilience" Version="9.10.0"/>
|
||||
<PackageVersion Include="Microsoft.Extensions.Options" Version="9.0.11"/>
|
||||
<PackageVersion Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="9.0.11"/>
|
||||
<PackageVersion Include="Microsoft.Extensions.Resilience" Version="9.0.11"/>
|
||||
<PackageVersion Include="Microsoft.Extensions.Resilience" Version="9.10.0"/>
|
||||
<PackageVersion Include="Microsoft.Extensions.Logging" Version="9.0.11"/>
|
||||
<PackageVersion Include="Microsoft.Extensions.Logging.Abstractions" Version="9.0.11"/>
|
||||
<PackageVersion Include="Microsoft.Extensions.Logging.Console" Version="9.0.11"/>
|
||||
|
|
|
|||
|
|
@ -37,9 +37,6 @@
|
|||
<None Update="Workflows\for-loop.elsa">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Update="Workflows\flowchart-test.elsa">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
|
|||
|
|
@ -1,16 +0,0 @@
|
|||
use Elsa.Activities.Console;
|
||||
|
||||
workflow FlowchartTest {
|
||||
flowchart {
|
||||
var counter = 0;
|
||||
|
||||
entry Start;
|
||||
|
||||
Start: WriteLine("Starting flowchart");
|
||||
CheckCondition: WriteLine("Checking condition");
|
||||
EndNode: WriteLine("Done!");
|
||||
|
||||
Start -> CheckCondition;
|
||||
CheckCondition.Done -> EndNode;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,29 +0,0 @@
|
|||
use Elsa.Activities.Console;
|
||||
|
||||
workflow HelloWorldDsl(
|
||||
DisplayName: "Hello World DSL",
|
||||
Description: "Demonstrates a simple ElsaScript workflow with metadata.",
|
||||
DefinitionId: "hello-world-dsl",
|
||||
DefinitionVersionId: "hello-world-dsl-v1",
|
||||
Version: 1,
|
||||
UsableAsActivity: true
|
||||
)
|
||||
{
|
||||
use expressions js;
|
||||
|
||||
WriteLine("Hello World from Elsa DSL!");
|
||||
}
|
||||
|
||||
workflow HelloWorldAsActivity(
|
||||
DisplayName: "Hello World as Activity",
|
||||
Description: "Can be embedded as an activity in other workflows.",
|
||||
DefinitionId: "hello-world-activity",
|
||||
DefinitionVersionId: "hello-world-activity-v1",
|
||||
Version: 1,
|
||||
UsableAsActivity: true
|
||||
)
|
||||
{
|
||||
use expressions js;
|
||||
|
||||
WriteLine(`Inner hello at ${Date.now()}`);
|
||||
}
|
||||
|
|
@ -1,6 +1,7 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<!-- Pomelo targets EF Core up to 9.x, so exclude MySQL provider for net10.0. -->
|
||||
<TargetFrameworks>net8.0;net9.0</TargetFrameworks>
|
||||
<Description>
|
||||
Provides MySQL EF Core migrations for various modules.
|
||||
</Description>
|
||||
|
|
@ -8,12 +9,12 @@
|
|||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" PrivateAssets="all" />
|
||||
<PackageReference Include="Pomelo.EntityFrameworkCore.MySql" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" PrivateAssets="all"/>
|
||||
<PackageReference Include="Pomelo.EntityFrameworkCore.MySql"/>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Elsa.Persistence.EFCore\Elsa.Persistence.EFCore.csproj" />
|
||||
<ProjectReference Include="..\Elsa.Persistence.EFCore\Elsa.Persistence.EFCore.csproj"/>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
using FluentStorage.Blobs;
|
||||
|
||||
namespace Elsa.Extensions;
|
||||
|
||||
public static class BlobExtensions
|
||||
{
|
||||
public static string GetExtension(this Blob blob) => Path.GetExtension(blob.Name).TrimStart('.');
|
||||
}
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
using Elsa.WorkflowProviders.BlobStorage.Contracts;
|
||||
|
||||
namespace Elsa.Extensions;
|
||||
|
||||
public static class BlobWorkflowFormatHandlerExtensions
|
||||
{
|
||||
public static bool SupportsExtension(this IBlobWorkflowFormatHandler handler, string extension) => handler.SupportedExtensions.Contains(extension, StringComparer.OrdinalIgnoreCase);
|
||||
}
|
||||
|
|
@ -1,4 +1,5 @@
|
|||
using Elsa.WorkflowProviders.BlobStorage.Contracts;
|
||||
using Elsa.Extensions;
|
||||
using Elsa.WorkflowProviders.BlobStorage.Contracts;
|
||||
using Elsa.Workflows.Runtime;
|
||||
using FluentStorage.Blobs;
|
||||
using JetBrains.Annotations;
|
||||
|
|
@ -71,11 +72,13 @@ public class BlobStorageWorkflowsProvider : IWorkflowsProvider
|
|||
{
|
||||
var blobStorage = _blobStorageProvider.GetBlobStorage();
|
||||
var content = await blobStorage.ReadTextAsync(blob.FullPath, cancellationToken: cancellationToken);
|
||||
|
||||
var contentType = blob.Properties.TryGetValue("ContentType", out var ct) ? ct?.ToString() : null;
|
||||
|
||||
foreach (var handler in _handlers)
|
||||
{
|
||||
if (!handler.SupportsExtension(blob.GetExtension()))
|
||||
continue;
|
||||
|
||||
if (!handler.CanHandle(blob, contentType))
|
||||
continue;
|
||||
|
||||
|
|
|
|||
|
|
@ -81,32 +81,53 @@ public class ActivityJsonConverter(
|
|||
activityDescriptor = null;
|
||||
activityTypeVersion = 0;
|
||||
|
||||
// First try and find the activity by its workflow definition version id. This is a special case when working with the WorkflowDefinitionActivity.
|
||||
if (activityRoot.TryGetProperty("workflowDefinitionVersionId", out var workflowDefinitionVersionIdElement))
|
||||
{
|
||||
var workflowDefinitionVersionId = workflowDefinitionVersionIdElement.GetString();
|
||||
activityDescriptor = activityRegistry.Find(x =>
|
||||
x.CustomProperties.TryGetValue("WorkflowDefinitionVersionId", out var value) && (string?)value == workflowDefinitionVersionId);
|
||||
activityTypeVersion = activityDescriptor?.Version ?? 0;
|
||||
}
|
||||
// First, we check whether the activity type name is a 'well-known' activity; not a workflow-as-activity
|
||||
|
||||
// If the activity type version is specified, use that to find the activity descriptor.
|
||||
if (activityDescriptor == null && activityRoot.TryGetProperty("version", out var activityVersionElement))
|
||||
if (activityRoot.TryGetProperty("version", out var activityVersionElement))
|
||||
{
|
||||
activityTypeVersion = activityVersionElement.GetInt32();
|
||||
activityDescriptor = activityRegistry.Find(activityTypeName, activityTypeVersion);
|
||||
}
|
||||
|
||||
// If the activity type version is not specified, use the latest version of the activity descriptor.
|
||||
// If a version is not specified, or activity with specified version is not found: use the latest version of the activity descriptor.
|
||||
if (activityDescriptor == null)
|
||||
{
|
||||
activityDescriptor = activityRegistry.Find(activityTypeName);
|
||||
activityTypeVersion = activityDescriptor?.Version ?? 0;
|
||||
}
|
||||
|
||||
// This is a special case when working with the WorkflowDefinitionActivity: workflowDefinitionVersionId should be used to find the workflow-as-activity.
|
||||
if (activityRoot.TryGetProperty("workflowDefinitionVersionId", out var workflowDefinitionVersionIdElement))
|
||||
{
|
||||
var activityDescriptorOverride = FindActivityDescriptorByCustomProperty("WorkflowDefinitionVersionId", workflowDefinitionVersionIdElement);
|
||||
if (activityDescriptorOverride is null)
|
||||
return activityTypeName;
|
||||
|
||||
activityDescriptor = activityDescriptorOverride;
|
||||
activityTypeVersion = activityDescriptor.Version;
|
||||
}
|
||||
// This is also a special case when working with the WorkflowDefinitionActivity: if no 'well-known' activity could be found, it might be a workflow-as-activity with a workflowDefinitionId
|
||||
else if (activityDescriptor is null
|
||||
&& activityRoot.TryGetProperty("workflowDefinitionId", out var workflowDefinitionIdElement)
|
||||
&& workflowDefinitionIdElement.ValueKind == JsonValueKind.String)
|
||||
{
|
||||
activityDescriptor = FindActivityDescriptorByCustomProperty("WorkflowDefinitionId", workflowDefinitionIdElement);
|
||||
activityTypeVersion = activityDescriptor?.Version ?? 0;
|
||||
}
|
||||
|
||||
return activityTypeName;
|
||||
}
|
||||
|
||||
private ActivityDescriptor? FindActivityDescriptorByCustomProperty(string customPropertyName, JsonElement valueElement)
|
||||
{
|
||||
if (valueElement.ValueKind != JsonValueKind.String)
|
||||
return null;
|
||||
|
||||
var searchValue = valueElement.GetString();
|
||||
return activityRegistry.Find(x => x.CustomProperties.TryGetValue(customPropertyName, out var value) && (string?)value == searchValue);
|
||||
}
|
||||
|
||||
private JsonSerializerOptions GetClonedOptions(JsonSerializerOptions options)
|
||||
{
|
||||
var clonedOptions = new JsonSerializerOptions(options);
|
||||
|
|
@ -115,7 +136,7 @@ public class ActivityJsonConverter(
|
|||
clonedOptions.Converters.Add(new ExpressionJsonConverterFactory(expressionDescriptorRegistry));
|
||||
return clonedOptions;
|
||||
}
|
||||
|
||||
|
||||
private JsonSerializerOptions GetClonedWriterOptions(JsonSerializerOptions options)
|
||||
{
|
||||
var clonedOptions = GetClonedOptions(options);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,350 @@
|
|||
using System.Text.Json;
|
||||
using Elsa.Common.Serialization;
|
||||
using Elsa.Expressions.Services;
|
||||
using Elsa.Workflows.Activities;
|
||||
using Elsa.Workflows.Helpers;
|
||||
using Elsa.Workflows.Management.Activities.WorkflowDefinitionActivity;
|
||||
using Elsa.Workflows.Management.Services;
|
||||
using Elsa.Workflows.Models;
|
||||
using Elsa.Workflows.Serialization.Configurators;
|
||||
using Elsa.Workflows.Serialization.Converters;
|
||||
using Elsa.Workflows.Serialization.Helpers;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using NSubstitute;
|
||||
|
||||
namespace Elsa.Workflows.Core.UnitTests.Serialization.Converters;
|
||||
|
||||
public sealed class ActivityJsonConverterTests
|
||||
{
|
||||
[Fact]
|
||||
public void When_DeserializeKnownActivity_And_TypeNameSpecified_Then_FindsAndInstantiatesActivity()
|
||||
{
|
||||
// Arrange
|
||||
var activityRegistry = CreateActivityRegistry(WriteLineActivityTypeName, WriteLineActivity);
|
||||
var sut = CreateSut(activityRegistry);
|
||||
|
||||
// Act
|
||||
var result = Execute(sut, WriteLineActivityJson_WithoutVersion);
|
||||
|
||||
// Assert
|
||||
Assert.Same(WriteLineActivity, result);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void When_DeserializeKnownActivity_And_TypeNameSpecified_And_VersionSpecified_Then_FindsAndInstantiatesActivity()
|
||||
{
|
||||
// Arrange
|
||||
var activityRegistry = CreateActivityRegistry(WriteLineActivityTypeName, WriteLineActivity, version: 1);
|
||||
var sut = CreateSut(activityRegistry);
|
||||
|
||||
// Act
|
||||
var result = Execute(sut, WriteLineActivityJson_WithVersion);
|
||||
|
||||
// Assert
|
||||
Assert.Same(WriteLineActivity, result);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void When_DeserializeUnknownActivity_Then_ReturnsNotFoundActivity()
|
||||
{
|
||||
// Arrange
|
||||
var activityRegistry = Substitute.For<IActivityRegistry>();
|
||||
activityRegistry
|
||||
.Find(NotFoundActivityTypeName)
|
||||
.Returns(new ActivityDescriptor());
|
||||
|
||||
var sut = CreateSut(activityRegistry);
|
||||
|
||||
// Act
|
||||
var result = Execute(sut, UnknownActivityJson);
|
||||
|
||||
// Assert
|
||||
Assert.IsType<NotFoundActivity>(result);
|
||||
var notFoundActivity = (NotFoundActivity)result;
|
||||
Assert.Equal(UnknownActivityTypeName, notFoundActivity.MissingTypeName);
|
||||
Assert.Equal(0, notFoundActivity.MissingTypeVersion);
|
||||
|
||||
var expectedJsonDoc = JsonDocument.Parse(UnknownActivityJson);
|
||||
var actualJsonDoc = JsonDocument.Parse(notFoundActivity.OriginalActivityJson);
|
||||
Assert.Equal(expectedJsonDoc.RootElement.ToString(), actualJsonDoc.RootElement.ToString());
|
||||
Assert.True(notFoundActivity.Metadata.ContainsKey("displayText"));
|
||||
Assert.True(notFoundActivity.Metadata.ContainsKey("description"));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void When_DeserializeWorkflowAsActivity_And_WorkflowDefinitionIdSpecified_Then_FindsAndInstantiatesActivity()
|
||||
{
|
||||
// Arrange
|
||||
var activityRegistry = CreateActivityRegistry_FindByCustomProperty(
|
||||
WorkflowDefinitionIdCustomPropertyName,
|
||||
WorkflowAsActivityDefinitionId
|
||||
);
|
||||
|
||||
var sut = CreateSut(activityRegistry);
|
||||
|
||||
// Act
|
||||
var result = Execute(sut, WorkflowAsActivityJson_WithDefinitionId);
|
||||
|
||||
// Assert
|
||||
Assert.Same(WorkflowAsActivity, result);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void When_DeserializeWorkflowAsActivity_And_WorkflowDefinitionVersionIdSpecified_Then_FindsAndInstantiatesActivity()
|
||||
{
|
||||
// Arrange
|
||||
var activityRegistry = CreateActivityRegistry_FindByCustomProperty(
|
||||
WorkflowDefinitionVersionIdCustomPropertyName,
|
||||
WorkflowAsActivityDefinitionVersionId
|
||||
);
|
||||
var sut = CreateSut(activityRegistry);
|
||||
|
||||
// Act
|
||||
var result = Execute(sut, WorkflowAsActivityJson_WithVersionId);
|
||||
|
||||
// Assert
|
||||
Assert.Same(WorkflowAsActivity, result);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void When_DeserializeWorkflowAsActivity_And_TypeNameSpecified_Then_FindsAndInstantiatesActivity()
|
||||
{
|
||||
// Arrange
|
||||
var activityRegistry = CreateActivityRegistry(WorkflowAsActivityTypeName, WorkflowAsActivity);
|
||||
var sut = CreateSut(activityRegistry);
|
||||
|
||||
// Act
|
||||
var result = Execute(sut, WorkflowAsActivityJson_WithTypeNameOnly);
|
||||
|
||||
// Assert
|
||||
Assert.Same(WorkflowAsActivity, result);
|
||||
}
|
||||
|
||||
static IActivity? Execute(ActivityJsonConverter sut, string json) =>
|
||||
JsonSerializer.Deserialize<IActivity>(json, GetSerializerOptions(sut));
|
||||
|
||||
static IActivityRegistry CreateActivityRegistry(string typeName, IActivity activity, int? version = null)
|
||||
{
|
||||
var descriptor = new ActivityDescriptor { Constructor = _ => activity };
|
||||
var activityRegistry = Substitute.For<IActivityRegistry>();
|
||||
|
||||
if (version.HasValue)
|
||||
activityRegistry.Find(typeName, version.Value).Returns(descriptor);
|
||||
else
|
||||
activityRegistry.Find(typeName).Returns(descriptor);
|
||||
|
||||
return activityRegistry;
|
||||
}
|
||||
|
||||
static IActivityRegistry CreateActivityRegistry_FindByCustomProperty(string customPropertyName, string customPropertyValue)
|
||||
{
|
||||
var descriptor = new ActivityDescriptor
|
||||
{
|
||||
Constructor = _ => WorkflowAsActivity,
|
||||
CustomProperties = { [customPropertyName] = customPropertyValue }
|
||||
};
|
||||
|
||||
var activityRegistry = Substitute.For<IActivityRegistry>();
|
||||
|
||||
// Mock type name lookups to return null, ensuring the custom property lookup path is tested
|
||||
activityRegistry.Find(Arg.Any<string>()).Returns((ActivityDescriptor?)null);
|
||||
activityRegistry.Find(Arg.Any<string>(), Arg.Any<int>()).Returns((ActivityDescriptor?)null);
|
||||
|
||||
activityRegistry
|
||||
.Find(Arg.Any<Func<ActivityDescriptor, bool>>())
|
||||
.Returns(callInfo => callInfo.Arg<Func<ActivityDescriptor, bool>>()(descriptor) ? descriptor : null);
|
||||
|
||||
return activityRegistry;
|
||||
}
|
||||
|
||||
static JsonSerializerOptions GetSerializerOptions(ActivityJsonConverter sut) => new()
|
||||
{
|
||||
Converters =
|
||||
{
|
||||
sut,
|
||||
new TypeJsonConverter(WellKnownTypeRegistry.CreateDefault()),
|
||||
new PolymorphicObjectConverterFactory()
|
||||
},
|
||||
TypeInfoResolver = new ModifiableJsonTypeInfoResolver(new CustomConstructorConfigurator().GetModifiers())
|
||||
};
|
||||
|
||||
private const string UnknownActivityTypeName = "Some.Unknown.Activity";
|
||||
private const string WorkflowAsActivityTypeName = "Test-SubWorkflow";
|
||||
private const string WorkflowDefinitionIdCustomPropertyName = "WorkflowDefinitionId";
|
||||
private const string WorkflowDefinitionVersionIdCustomPropertyName = "WorkflowDefinitionVersionId";
|
||||
private const string WorkflowAsActivityDefinitionId = "bd94124913202141";
|
||||
private const string WorkflowAsActivityDefinitionVersionId = "aaa1112fff2443";
|
||||
private static readonly WriteLine WriteLineActivity = new("Hello world!");
|
||||
private static readonly string WriteLineActivityTypeName = ActivityTypeNameHelper.GenerateTypeName<WriteLine>();
|
||||
private static readonly string NotFoundActivityTypeName = ActivityTypeNameHelper.GenerateTypeName<NotFoundActivity>();
|
||||
|
||||
private const string WriteLineActivityJson_WithVersion =
|
||||
"""
|
||||
{
|
||||
"text": {
|
||||
"typeName": "String",
|
||||
"expression": {
|
||||
"type": "Literal",
|
||||
"value": "Hello world!"
|
||||
}
|
||||
},
|
||||
"id": "b54b024aa7469287",
|
||||
"nodeId": "Workflow1:51139b0cc83d3b07:b54b024aa7469287",
|
||||
"name": "WriteLine1",
|
||||
"type": "Elsa.WriteLine",
|
||||
"version": 1,
|
||||
"customProperties": {
|
||||
"canStartWorkflow": false,
|
||||
"runAsynchronously": false
|
||||
},
|
||||
"metadata": {}
|
||||
}
|
||||
""";
|
||||
|
||||
private const string UnknownActivityJson =
|
||||
"""
|
||||
{
|
||||
"text": {
|
||||
"typeName": "String",
|
||||
"expression": {
|
||||
"type": "Literal",
|
||||
"value": "Hello world!"
|
||||
}
|
||||
},
|
||||
"id": "b54b024aa7469287",
|
||||
"nodeId": "Workflow1:51139b0cc83d3b07:b54b024aa7469287",
|
||||
"name": "Unknown1",
|
||||
"type": "Some.Unknown.Activity",
|
||||
"customProperties": {
|
||||
"canStartWorkflow": false,
|
||||
"runAsynchronously": false
|
||||
},
|
||||
"metadata": {}
|
||||
}
|
||||
""";
|
||||
|
||||
private const string WriteLineActivityJson_WithoutVersion =
|
||||
"""
|
||||
{
|
||||
"text": {
|
||||
"typeName": "String",
|
||||
"expression": {
|
||||
"type": "Literal",
|
||||
"value": "Hello world!"
|
||||
}
|
||||
},
|
||||
"id": "b54b024aa7469287",
|
||||
"nodeId": "Workflow1:51139b0cc83d3b07:b54b024aa7469287",
|
||||
"name": "WriteLine1",
|
||||
"type": "Elsa.WriteLine",
|
||||
"customProperties": {
|
||||
"canStartWorkflow": false,
|
||||
"runAsynchronously": false
|
||||
},
|
||||
"metadata": {}
|
||||
}
|
||||
""";
|
||||
|
||||
private const string WorkflowAsActivityJson_WithVersionId =
|
||||
"""
|
||||
{
|
||||
"workflowDefinitionVersionId": "aaa1112fff2443",
|
||||
"id": "5fc551ed366fe9fd",
|
||||
"nodeId": "Workflow2:cad9d2186550a8d7:5fc551ed366fe9fd",
|
||||
"name": "Test-SubWorkflow1",
|
||||
"type": "Test-SubWorkflow",
|
||||
"customProperties": {
|
||||
"canStartWorkflow": false,
|
||||
"runAsynchronously": false,
|
||||
"logPersistenceMode": {
|
||||
"default": "Inherit",
|
||||
"inputs": {},
|
||||
"outputs": {}
|
||||
},
|
||||
"logPersistenceConfig": {
|
||||
"default": null,
|
||||
"internalState": null,
|
||||
"inputs": {},
|
||||
"outputs": {}
|
||||
}
|
||||
},
|
||||
"metadata": {}
|
||||
}
|
||||
""";
|
||||
|
||||
private const string WorkflowAsActivityJson_WithDefinitionId =
|
||||
"""
|
||||
{
|
||||
"workflowDefinitionId": "bd94124913202141",
|
||||
"id": "5fc551ed366fe9fd",
|
||||
"nodeId": "Workflow2:cad9d2186550a8d7:5fc551ed366fe9fd",
|
||||
"name": "Test-SubWorkflow1",
|
||||
"type": "Test-SubWorkflow",
|
||||
"customProperties": {
|
||||
"canStartWorkflow": false,
|
||||
"runAsynchronously": false,
|
||||
"logPersistenceMode": {
|
||||
"default": "Inherit",
|
||||
"inputs": {},
|
||||
"outputs": {}
|
||||
},
|
||||
"logPersistenceConfig": {
|
||||
"default": null,
|
||||
"internalState": null,
|
||||
"inputs": {},
|
||||
"outputs": {}
|
||||
}
|
||||
},
|
||||
"metadata": {}
|
||||
}
|
||||
""";
|
||||
|
||||
private const string WorkflowAsActivityJson_WithTypeNameOnly =
|
||||
"""
|
||||
{
|
||||
"id": "5fc551ed366fe9fd",
|
||||
"nodeId": "Workflow2:cad9d2186550a8d7:5fc551ed366fe9fd",
|
||||
"name": "Test-SubWorkflow1",
|
||||
"type": "Test-SubWorkflow",
|
||||
"customProperties": {
|
||||
"canStartWorkflow": false,
|
||||
"runAsynchronously": false,
|
||||
"logPersistenceMode": {
|
||||
"default": "Inherit",
|
||||
"inputs": {},
|
||||
"outputs": {}
|
||||
},
|
||||
"logPersistenceConfig": {
|
||||
"default": null,
|
||||
"internalState": null,
|
||||
"inputs": {},
|
||||
"outputs": {}
|
||||
}
|
||||
},
|
||||
"metadata": {}
|
||||
}
|
||||
""";
|
||||
|
||||
private static readonly IActivity WorkflowAsActivity = new WorkflowDefinitionActivity
|
||||
{
|
||||
WorkflowDefinitionId = WorkflowAsActivityDefinitionId,
|
||||
WorkflowDefinitionVersionId = WorkflowAsActivityDefinitionVersionId
|
||||
};
|
||||
|
||||
private static ActivityJsonConverter CreateSut(IActivityRegistry activityRegistry)
|
||||
{
|
||||
var expressionDescriptorRegistry = new ExpressionDescriptorRegistry([]);
|
||||
return new(
|
||||
activityRegistry,
|
||||
expressionDescriptorRegistry,
|
||||
new(
|
||||
activityRegistry,
|
||||
new(expressionDescriptorRegistry),
|
||||
CreateLogger<ActivityWriter>()
|
||||
),
|
||||
Substitute.For<IServiceProvider>()
|
||||
);
|
||||
}
|
||||
|
||||
private static ILogger<T> CreateLogger<T>() => LoggerFactory.Create(_ => { }).CreateLogger<T>();
|
||||
}
|
||||
Loading…
Reference in a new issue