From 1ed6695872e953b4eb804082c331eb53681c5a49 Mon Sep 17 00:00:00 2001 From: Sipke Schoorstra Date: Thu, 21 Nov 2024 16:44:25 +0100 Subject: [PATCH] Add ExecuteWorkflow activity (#6134) * Add ExecuteWorkflow activity and enable multitenancy Introduced the ExecuteWorkflow activity to create and execute workflow instances, and updated runtime settings to use ProtoActor for distributed caching transport. Enabled multitenancy for the Elsa Server Web application. * Namespace renames (#6135) * Create ExecuteWorkflows tests and workflows Add unit tests for executing workflows, including MainWorkflow and SubroutineWorkflow. Also, rename ExecutedWorkflowResult to ExecuteWorkflowResult in the runtime module for consistency. * Add output definitions to WorkflowBuilder Refactored the `WithInput` method for clarity and added multiple `WithOutput` methods to support different ways of defining workflow outputs. These changes enhance the flexibility and readability of the workflow configuration process by providing a consistent API for input and output definitions. * Refactor namespaces in component tests Updated namespaces from Helpers to specific contexts like Fixtures, Abstractions, Consumers, Decorators, etc., to improve code organization and readability. This change affects multiple files across different test scenarios and modules. * Disable RabbitMQ and multitenancy, rename test class Commented out RabbitMQ usage in WorkflowServer.cs to focus on other transports. Changed multitenancy flag to false in Program.cs. Renamed DispatchWorkflowsTests to ExecuteWorkflowsTests for clarity. --- src/apps/Elsa.Server.Web/Program.cs | 2 +- .../Builders/WorkflowBuilder.cs | 49 ++++++++-- .../Contracts/IWorkflowBuilder.cs | 25 ++++++ .../Models/ArgumentDefinition.cs | 6 +- .../Activities/ExecuteWorkflow.cs | 90 +++++++++++++++++++ .../Models/ExecuteWorkflowResult.cs | 14 +++ .../Helpers/Abstractions/AppComponentTest.cs | 3 +- .../WorkflowDefinitionEventConsumer.cs | 2 +- .../EventPublishingChangeTokenSignaler.cs | 2 +- .../Helpers/Fixtures/App.cs | 2 +- .../Helpers/Fixtures/AppCollection.cs | 2 +- .../Helpers/Fixtures/Cluster.cs | 2 +- .../Helpers/Fixtures/Infrastructure.cs | 2 +- .../Helpers/Fixtures/WorkflowServer.cs | 9 +- .../Materializers/TestWorkflowMaterializer.cs | 3 +- .../WorkflowProviders/TestWorkflowProvider.cs | 2 +- .../Scenarios/Activities/FlowJoins/Tests.cs | 3 +- .../BasicWorkflows/HelloWorldTests.cs | 3 +- .../BulkDispatchWorkflowsTests.cs | 3 +- .../WorkflowDefinitionActivityTests.cs | 3 +- .../ActivityRegistrySyncTests.cs | 3 +- .../DispatchWorkflowsTests.cs | 3 +- .../ExecuteWorkflows/ExecuteWorkflowsTests.cs | 31 +++++++ .../Workflows/MainWorkflow.cs | 33 +++++++ .../Workflows/SubroutineWorkflow.cs | 31 +++++++ .../HttpWorkflows/HttpHelloWorldTests.cs | 3 +- ...ResumeSpecificHttpWorkflowInstanceTests.cs | 3 +- .../InputOutputLoggingTests.cs | 3 +- .../Multitenancy/MultitenancyTests.cs | 3 +- .../Variables/CountdownWorkflowTests.cs | 3 +- .../WorkflowActivities/AutoUpdateTests.cs | 3 +- .../WorkflowActivities/DeleteWorkflowTests.cs | 3 +- .../WorkflowActivities/SaveWorkflowTests.cs | 3 +- .../WorkflowCompletionTests.cs | 3 +- .../DynamicEndpointTests.cs | 3 +- .../ReloadWorkflowTests.cs | 5 +- .../WorkflowJsonStructureTests.cs | 3 +- 37 files changed, 324 insertions(+), 42 deletions(-) create mode 100644 src/modules/Elsa.Workflows.Runtime/Activities/ExecuteWorkflow.cs create mode 100644 src/modules/Elsa.Workflows.Runtime/Models/ExecuteWorkflowResult.cs create mode 100644 test/component/Elsa.Workflows.ComponentTests/Scenarios/ExecuteWorkflows/ExecuteWorkflowsTests.cs create mode 100644 test/component/Elsa.Workflows.ComponentTests/Scenarios/ExecuteWorkflows/Workflows/MainWorkflow.cs create mode 100644 test/component/Elsa.Workflows.ComponentTests/Scenarios/ExecuteWorkflows/Workflows/SubroutineWorkflow.cs diff --git a/src/apps/Elsa.Server.Web/Program.cs b/src/apps/Elsa.Server.Web/Program.cs index 764309636..0fe6f4bca 100644 --- a/src/apps/Elsa.Server.Web/Program.cs +++ b/src/apps/Elsa.Server.Web/Program.cs @@ -69,7 +69,7 @@ const bool useKafka = false; const bool useReadOnlyMode = false; const bool useSignalR = false; // Disabled until Elsa Studio sends authenticated requests. const WorkflowRuntime workflowRuntime = WorkflowRuntime.ProtoActor; -const DistributedCachingTransport distributedCachingTransport = DistributedCachingTransport.MassTransit; +const DistributedCachingTransport distributedCachingTransport = DistributedCachingTransport.ProtoActor; const MassTransitBroker massTransitBroker = MassTransitBroker.Memory; const bool useMultitenancy = false; const bool useAgents = false; diff --git a/src/modules/Elsa.Workflows.Core/Builders/WorkflowBuilder.cs b/src/modules/Elsa.Workflows.Core/Builders/WorkflowBuilder.cs index 68b14ac0f..c813ada31 100644 --- a/src/modules/Elsa.Workflows.Core/Builders/WorkflowBuilder.cs +++ b/src/modules/Elsa.Workflows.Core/Builders/WorkflowBuilder.cs @@ -123,14 +123,7 @@ public class WorkflowBuilder(IActivityVisitor activityVisitor, IIdentityGraphSer /// public InputDefinition WithInput(string name, string? description = default) { - return WithInput(inputDefinition => - { - inputDefinition.Name = name; - inputDefinition.Type = typeof(T); - - if (description != null) - inputDefinition.Description = description; - }); + return WithInput(name, typeof(T), description); } /// @@ -173,6 +166,46 @@ public class WorkflowBuilder(IActivityVisitor activityVisitor, IIdentityGraphSer return this; } + public OutputDefinition WithOutput(string name, string? description = default) + { + return WithOutput(name, typeof(T), description); + } + + public OutputDefinition WithOutput(string name, Type type, string? description = default) + { + return WithOutput(outputDefinition => + { + outputDefinition.Name = name; + outputDefinition.Type = type; + + if (description != null) + outputDefinition.Description = description; + }); + } + + public OutputDefinition WithOutput(string name, Type type, Action? setup = default) + { + return WithOutput(outputDefinition => + { + outputDefinition.Name = name; + outputDefinition.Type = type; + setup?.Invoke(outputDefinition); + }); + } + + public OutputDefinition WithOutput(Action setup) + { + var outputDefinition = new OutputDefinition(); + setup(outputDefinition); + return WithOutput(outputDefinition); + } + + public OutputDefinition WithOutput(OutputDefinition outputDefinition) + { + Outputs.Add(outputDefinition); + return outputDefinition; + } + /// public IWorkflowBuilder WithCustomProperty(string name, object value) { diff --git a/src/modules/Elsa.Workflows.Core/Contracts/IWorkflowBuilder.cs b/src/modules/Elsa.Workflows.Core/Contracts/IWorkflowBuilder.cs index 3272ec422..363fcbf11 100644 --- a/src/modules/Elsa.Workflows.Core/Contracts/IWorkflowBuilder.cs +++ b/src/modules/Elsa.Workflows.Core/Contracts/IWorkflowBuilder.cs @@ -156,6 +156,31 @@ public interface IWorkflowBuilder /// A fluent method for adding an input to . /// IWorkflowBuilder WithInput(InputDefinition inputDefinition); + + /// + /// A fluent method for adding an output to . + /// + OutputDefinition WithOutput(string name, string? description = default); + + /// + /// A fluent method for adding an output to . + /// + OutputDefinition WithOutput(string name, Type type, string? description = default); + + /// + /// A fluent method for adding an output to . + /// + OutputDefinition WithOutput(string name, Type type, Action? setup = default); + + /// + /// A fluent method for adding an output to . + /// + OutputDefinition WithOutput(Action setup); + + /// + /// A fluent method for adding an output to . + /// + OutputDefinition WithOutput(OutputDefinition outputDefinition); /// /// A fluent method for adding a property to . diff --git a/src/modules/Elsa.Workflows.Core/Models/ArgumentDefinition.cs b/src/modules/Elsa.Workflows.Core/Models/ArgumentDefinition.cs index 0239d0400..afd6b5516 100644 --- a/src/modules/Elsa.Workflows.Core/Models/ArgumentDefinition.cs +++ b/src/modules/Elsa.Workflows.Core/Models/ArgumentDefinition.cs @@ -18,15 +18,15 @@ public abstract class ArgumentDefinition /// /// A user friendly name of the input. /// - public string DisplayName { get; set; } = default!; + public string DisplayName { get; set; } = string.Empty; /// /// A description of the input. /// - public string Description { get; set; } = default!; + public string Description { get; set; } = string.Empty; /// /// The category to which this input belongs. /// - public string Category { get; set; } = default!; + public string Category { get; set; } = string.Empty; } \ No newline at end of file diff --git a/src/modules/Elsa.Workflows.Runtime/Activities/ExecuteWorkflow.cs b/src/modules/Elsa.Workflows.Runtime/Activities/ExecuteWorkflow.cs new file mode 100644 index 000000000..bc23ea78a --- /dev/null +++ b/src/modules/Elsa.Workflows.Runtime/Activities/ExecuteWorkflow.cs @@ -0,0 +1,90 @@ +using System.Runtime.CompilerServices; +using Elsa.Common.Models; +using Elsa.Extensions; +using Elsa.Workflows.Attributes; +using Elsa.Workflows.Management; +using Elsa.Workflows.Models; +using Elsa.Workflows.Options; +using Elsa.Workflows.UIHints; +using JetBrains.Annotations; + +namespace Elsa.Workflows.Runtime.Activities; + +/// +/// Creates a new workflow instance of the specified workflow and dispatches it for execution. +/// +[Activity("Elsa", "Composition", "Create a new workflow instance of the specified workflow and execute it.", Kind = ActivityKind.Task)] +[UsedImplicitly] +public class ExecuteWorkflow : Activity +{ + /// + public ExecuteWorkflow([CallerFilePath] string? source = default, [CallerLineNumber] int? line = default) : base(source, line) + { + } + + /// + /// The definition ID of the workflow to execute. + /// + [Input( + DisplayName = "Workflow Definition", + Description = "The definition ID of the workflow to execute.", + UIHint = InputUIHints.WorkflowDefinitionPicker + )] + public Input WorkflowDefinitionId { get; set; } = default!; + + /// + /// The correlation ID to associate the workflow with. + /// + [Input( + DisplayName = "Correlation ID", + Description = "The correlation ID to associate the workflow with." + )] + public Input CorrelationId { get; set; } = default!; + + /// + /// The input to send to the workflow. + /// + [Input(Description = "The input to send to the workflow.")] + public Input?> Input { get; set; } = default!; + + /// + protected override async ValueTask ExecuteAsync(ActivityExecutionContext context) + { + var result = await ExecuteWorkflowAsync(context); + context.SetResult(result); + await context.CompleteActivityAsync(); + } + + private async ValueTask ExecuteWorkflowAsync(ActivityExecutionContext context) + { + var workflowDefinitionId = WorkflowDefinitionId.Get(context); + var input = Input.GetOrDefault(context) ?? new Dictionary(); + var correlationId = CorrelationId.GetOrDefault(context); + var workflowInvoker = context.GetRequiredService(); + var identityGenerator = context.GetRequiredService(); + var workflowDefinitionService = context.GetRequiredService(); + var workflowGraph = await workflowDefinitionService.FindWorkflowGraphAsync(workflowDefinitionId, VersionOptions.Published, context.CancellationToken); + + if (workflowGraph == null) + throw new Exception($"No published version of workflow definition with ID {workflowDefinitionId} found."); + + var options = new RunWorkflowOptions + { + ParentWorkflowInstanceId = context.WorkflowExecutionContext.Id, + Input = input, + CorrelationId = correlationId, + WorkflowInstanceId = identityGenerator.GenerateId() + }; + + var workflowResult = await workflowInvoker.InvokeAsync(workflowGraph, options, context.CancellationToken); + var info = new ExecuteWorkflowResult + { + WorkflowInstanceId = options.WorkflowInstanceId, + Status = workflowResult.WorkflowState.Status, + SubStatus = workflowResult.WorkflowState.SubStatus, + Output = workflowResult.WorkflowState.Output + }; + + return info; + } +} \ No newline at end of file diff --git a/src/modules/Elsa.Workflows.Runtime/Models/ExecuteWorkflowResult.cs b/src/modules/Elsa.Workflows.Runtime/Models/ExecuteWorkflowResult.cs new file mode 100644 index 000000000..b2bcd36e7 --- /dev/null +++ b/src/modules/Elsa.Workflows.Runtime/Models/ExecuteWorkflowResult.cs @@ -0,0 +1,14 @@ +namespace Elsa.Workflows.Runtime; + +/// +/// Represents the result of executing a workflow. +/// +public class ExecuteWorkflowResult +{ + public string WorkflowDefinitionVersionId { get; set; } = default!; + public string WorkflowInstanceId { get; set; } = default!; + public string? CorrelationId { get; set; } + public WorkflowStatus Status { get; set; } + public WorkflowSubStatus SubStatus { get; set; } + public IDictionary? Output { get; set; } +} \ No newline at end of file diff --git a/test/component/Elsa.Workflows.ComponentTests/Helpers/Abstractions/AppComponentTest.cs b/test/component/Elsa.Workflows.ComponentTests/Helpers/Abstractions/AppComponentTest.cs index e69423a11..b0db161d7 100644 --- a/test/component/Elsa.Workflows.ComponentTests/Helpers/Abstractions/AppComponentTest.cs +++ b/test/component/Elsa.Workflows.ComponentTests/Helpers/Abstractions/AppComponentTest.cs @@ -1,6 +1,7 @@ +using Elsa.Workflows.ComponentTests.Fixtures; using Microsoft.Extensions.DependencyInjection; -namespace Elsa.Workflows.ComponentTests.Helpers; +namespace Elsa.Workflows.ComponentTests.Abstractions; [Collection(nameof(AppCollection))] public abstract class AppComponentTest(App app) : IDisposable diff --git a/test/component/Elsa.Workflows.ComponentTests/Helpers/Consumers/WorkflowDefinitionEventConsumer.cs b/test/component/Elsa.Workflows.ComponentTests/Helpers/Consumers/WorkflowDefinitionEventConsumer.cs index 0418129a4..9a637faff 100644 --- a/test/component/Elsa.Workflows.ComponentTests/Helpers/Consumers/WorkflowDefinitionEventConsumer.cs +++ b/test/component/Elsa.Workflows.ComponentTests/Helpers/Consumers/WorkflowDefinitionEventConsumer.cs @@ -4,7 +4,7 @@ using Elsa.Testing.Shared.Services; using Hangfire.Annotations; using MassTransit; -namespace Elsa.Workflows.ComponentTests.Helpers; +namespace Elsa.Workflows.ComponentTests.Consumers; [UsedImplicitly] public class WorkflowDefinitionEventConsumer(WorkflowDefinitionEvents workflowDefinitionEvents) : IConsumer diff --git a/test/component/Elsa.Workflows.ComponentTests/Helpers/Decorators/EventPublishingChangeTokenSignaler.cs b/test/component/Elsa.Workflows.ComponentTests/Helpers/Decorators/EventPublishingChangeTokenSignaler.cs index 835331052..daac22ba1 100644 --- a/test/component/Elsa.Workflows.ComponentTests/Helpers/Decorators/EventPublishingChangeTokenSignaler.cs +++ b/test/component/Elsa.Workflows.ComponentTests/Helpers/Decorators/EventPublishingChangeTokenSignaler.cs @@ -4,7 +4,7 @@ using Elsa.Testing.Shared.Services; using Hangfire.Annotations; using Microsoft.Extensions.Primitives; -namespace Elsa.Workflows.ComponentTests.Helpers; +namespace Elsa.Workflows.ComponentTests.Decorators; /// /// Provides a decorator for the `IChangeTokenSignaler` interface that triggers change token events. diff --git a/test/component/Elsa.Workflows.ComponentTests/Helpers/Fixtures/App.cs b/test/component/Elsa.Workflows.ComponentTests/Helpers/Fixtures/App.cs index 094a8e784..bcf1d377a 100644 --- a/test/component/Elsa.Workflows.ComponentTests/Helpers/Fixtures/App.cs +++ b/test/component/Elsa.Workflows.ComponentTests/Helpers/Fixtures/App.cs @@ -1,6 +1,6 @@ using Hangfire.Annotations; -namespace Elsa.Workflows.ComponentTests.Helpers; +namespace Elsa.Workflows.ComponentTests.Fixtures; [UsedImplicitly] public class App : IAsyncLifetime diff --git a/test/component/Elsa.Workflows.ComponentTests/Helpers/Fixtures/AppCollection.cs b/test/component/Elsa.Workflows.ComponentTests/Helpers/Fixtures/AppCollection.cs index f83071692..81f27ed3f 100644 --- a/test/component/Elsa.Workflows.ComponentTests/Helpers/Fixtures/AppCollection.cs +++ b/test/component/Elsa.Workflows.ComponentTests/Helpers/Fixtures/AppCollection.cs @@ -1,4 +1,4 @@ -namespace Elsa.Workflows.ComponentTests.Helpers; +namespace Elsa.Workflows.ComponentTests.Fixtures; [CollectionDefinition(nameof(AppCollection))] public class AppCollection : ICollectionFixture diff --git a/test/component/Elsa.Workflows.ComponentTests/Helpers/Fixtures/Cluster.cs b/test/component/Elsa.Workflows.ComponentTests/Helpers/Fixtures/Cluster.cs index e07388593..6ef20f1a5 100644 --- a/test/component/Elsa.Workflows.ComponentTests/Helpers/Fixtures/Cluster.cs +++ b/test/component/Elsa.Workflows.ComponentTests/Helpers/Fixtures/Cluster.cs @@ -1,6 +1,6 @@ using Hangfire.Annotations; -namespace Elsa.Workflows.ComponentTests.Helpers; +namespace Elsa.Workflows.ComponentTests.Fixtures; [UsedImplicitly] public class Cluster(Infrastructure infrastructure) : IAsyncDisposable diff --git a/test/component/Elsa.Workflows.ComponentTests/Helpers/Fixtures/Infrastructure.cs b/test/component/Elsa.Workflows.ComponentTests/Helpers/Fixtures/Infrastructure.cs index 5ce02bc31..81f2682e9 100644 --- a/test/component/Elsa.Workflows.ComponentTests/Helpers/Fixtures/Infrastructure.cs +++ b/test/component/Elsa.Workflows.ComponentTests/Helpers/Fixtures/Infrastructure.cs @@ -1,7 +1,7 @@ using Testcontainers.PostgreSql; using Testcontainers.RabbitMq; -namespace Elsa.Workflows.ComponentTests.Helpers; +namespace Elsa.Workflows.ComponentTests.Fixtures; public class Infrastructure : IAsyncLifetime { diff --git a/test/component/Elsa.Workflows.ComponentTests/Helpers/Fixtures/WorkflowServer.cs b/test/component/Elsa.Workflows.ComponentTests/Helpers/Fixtures/WorkflowServer.cs index cec02baaf..f589d8237 100644 --- a/test/component/Elsa.Workflows.ComponentTests/Helpers/Fixtures/WorkflowServer.cs +++ b/test/component/Elsa.Workflows.ComponentTests/Helpers/Fixtures/WorkflowServer.cs @@ -3,7 +3,6 @@ using System.Reflection; using Elsa.Agents; using Elsa.Alterations.Extensions; using Elsa.Caching; -using Elsa.EntityFrameworkCore; using Elsa.EntityFrameworkCore.Extensions; using Elsa.EntityFrameworkCore.Modules.Alterations; using Elsa.EntityFrameworkCore.Modules.Identity; @@ -14,6 +13,10 @@ using Elsa.Identity.Providers; using Elsa.MassTransit.Extensions; using Elsa.Testing.Shared.Handlers; using Elsa.Testing.Shared.Services; +using Elsa.Workflows.ComponentTests.Consumers; +using Elsa.Workflows.ComponentTests.Decorators; +using Elsa.Workflows.ComponentTests.Materializers; +using Elsa.Workflows.ComponentTests.WorkflowProviders; using Elsa.Workflows.Management; using Elsa.Workflows.Runtime.Distributed.Extensions; using FluentStorage; @@ -25,7 +28,7 @@ using Microsoft.Extensions.DependencyInjection; using Refit; using static Elsa.Api.Client.RefitSettingsHelper; -namespace Elsa.Workflows.ComponentTests.Helpers; +namespace Elsa.Workflows.ComponentTests.Fixtures; [UsedImplicitly] public class WorkflowServer(Infrastructure infrastructure, string url) : WebApplicationFactory @@ -73,7 +76,7 @@ public class WorkflowServer(Infrastructure infrastructure, string url) : WebAppl }); elsa.UseMassTransit(massTransit => { - massTransit.UseRabbitMq(rabbitMqConnectionString); + //massTransit.UseRabbitMq(rabbitMqConnectionString); massTransit.AddConsumer("elsa-test-workflow-definition-updates", true); }); elsa.UseIdentity(identity => identity.UseEntityFrameworkCore(ef => ef.UsePostgreSql(dbConnectionString))); diff --git a/test/component/Elsa.Workflows.ComponentTests/Helpers/Materializers/TestWorkflowMaterializer.cs b/test/component/Elsa.Workflows.ComponentTests/Helpers/Materializers/TestWorkflowMaterializer.cs index ea1f04758..c3756cd0f 100644 --- a/test/component/Elsa.Workflows.ComponentTests/Helpers/Materializers/TestWorkflowMaterializer.cs +++ b/test/component/Elsa.Workflows.ComponentTests/Helpers/Materializers/TestWorkflowMaterializer.cs @@ -1,9 +1,10 @@ using Elsa.Workflows.Activities; +using Elsa.Workflows.ComponentTests.WorkflowProviders; using Elsa.Workflows.Management; using Elsa.Workflows.Management.Entities; using Elsa.Workflows.Runtime; -namespace Elsa.Workflows.ComponentTests.Helpers; +namespace Elsa.Workflows.ComponentTests.Materializers; /// /// A workflow materializer that deserializes workflows created from . diff --git a/test/component/Elsa.Workflows.ComponentTests/Helpers/WorkflowProviders/TestWorkflowProvider.cs b/test/component/Elsa.Workflows.ComponentTests/Helpers/WorkflowProviders/TestWorkflowProvider.cs index 147f163d7..b7ecadb32 100644 --- a/test/component/Elsa.Workflows.ComponentTests/Helpers/WorkflowProviders/TestWorkflowProvider.cs +++ b/test/component/Elsa.Workflows.ComponentTests/Helpers/WorkflowProviders/TestWorkflowProvider.cs @@ -1,6 +1,6 @@ using Elsa.Workflows.Runtime; -namespace Elsa.Workflows.ComponentTests.Helpers; +namespace Elsa.Workflows.ComponentTests.WorkflowProviders; public class TestWorkflowProvider : IWorkflowsProvider { diff --git a/test/component/Elsa.Workflows.ComponentTests/Scenarios/Activities/FlowJoins/Tests.cs b/test/component/Elsa.Workflows.ComponentTests/Scenarios/Activities/FlowJoins/Tests.cs index 3e207352a..605e2da56 100644 --- a/test/component/Elsa.Workflows.ComponentTests/Scenarios/Activities/FlowJoins/Tests.cs +++ b/test/component/Elsa.Workflows.ComponentTests/Scenarios/Activities/FlowJoins/Tests.cs @@ -1,4 +1,5 @@ -using Elsa.Workflows.ComponentTests.Helpers; +using Elsa.Workflows.ComponentTests.Abstractions; +using Elsa.Workflows.ComponentTests.Fixtures; using Microsoft.Extensions.DependencyInjection; namespace Elsa.Workflows.ComponentTests.Scenarios.Activities.FlowJoins; diff --git a/test/component/Elsa.Workflows.ComponentTests/Scenarios/BasicWorkflows/HelloWorldTests.cs b/test/component/Elsa.Workflows.ComponentTests/Scenarios/BasicWorkflows/HelloWorldTests.cs index 4ad364963..7d02e82f2 100644 --- a/test/component/Elsa.Workflows.ComponentTests/Scenarios/BasicWorkflows/HelloWorldTests.cs +++ b/test/component/Elsa.Workflows.ComponentTests/Scenarios/BasicWorkflows/HelloWorldTests.cs @@ -2,7 +2,8 @@ using Elsa.Api.Client.Resources.WorkflowDefinitions.Contracts; using Elsa.Testing.Shared.Extensions; using Elsa.Workflows.Api.Endpoints.WorkflowDefinitions.Execute; -using Elsa.Workflows.ComponentTests.Helpers; +using Elsa.Workflows.ComponentTests.Abstractions; +using Elsa.Workflows.ComponentTests.Fixtures; namespace Elsa.Workflows.ComponentTests.Scenarios.BasicWorkflows; diff --git a/test/component/Elsa.Workflows.ComponentTests/Scenarios/BulkDispatchWorkflows/BulkDispatchWorkflowsTests.cs b/test/component/Elsa.Workflows.ComponentTests/Scenarios/BulkDispatchWorkflows/BulkDispatchWorkflowsTests.cs index 9696a0543..e279acaf2 100644 --- a/test/component/Elsa.Workflows.ComponentTests/Scenarios/BulkDispatchWorkflows/BulkDispatchWorkflowsTests.cs +++ b/test/component/Elsa.Workflows.ComponentTests/Scenarios/BulkDispatchWorkflows/BulkDispatchWorkflowsTests.cs @@ -1,7 +1,8 @@ using Elsa.Common.Models; using Elsa.Testing.Shared; using Elsa.Testing.Shared.Services; -using Elsa.Workflows.ComponentTests.Helpers; +using Elsa.Workflows.ComponentTests.Abstractions; +using Elsa.Workflows.ComponentTests.Fixtures; using Elsa.Workflows.ComponentTests.Scenarios.BulkDispatchWorkflows.Workflows; using Elsa.Workflows.Models; using Elsa.Workflows.Runtime; diff --git a/test/component/Elsa.Workflows.ComponentTests/Scenarios/CachingAndWorkflowDefinitionActivity/WorkflowDefinitionActivityTests.cs b/test/component/Elsa.Workflows.ComponentTests/Scenarios/CachingAndWorkflowDefinitionActivity/WorkflowDefinitionActivityTests.cs index fdc54ee61..e25763ef5 100644 --- a/test/component/Elsa.Workflows.ComponentTests/Scenarios/CachingAndWorkflowDefinitionActivity/WorkflowDefinitionActivityTests.cs +++ b/test/component/Elsa.Workflows.ComponentTests/Scenarios/CachingAndWorkflowDefinitionActivity/WorkflowDefinitionActivityTests.cs @@ -1,4 +1,5 @@ -using Elsa.Workflows.ComponentTests.Helpers; +using Elsa.Workflows.ComponentTests.Abstractions; +using Elsa.Workflows.ComponentTests.Fixtures; using Elsa.Workflows.Management; using Elsa.Workflows.Management.Filters; using Microsoft.Extensions.DependencyInjection; diff --git a/test/component/Elsa.Workflows.ComponentTests/Scenarios/ClusteredHosting/ActivityRegistrySyncTests.cs b/test/component/Elsa.Workflows.ComponentTests/Scenarios/ClusteredHosting/ActivityRegistrySyncTests.cs index 005e85fce..b19d54767 100644 --- a/test/component/Elsa.Workflows.ComponentTests/Scenarios/ClusteredHosting/ActivityRegistrySyncTests.cs +++ b/test/component/Elsa.Workflows.ComponentTests/Scenarios/ClusteredHosting/ActivityRegistrySyncTests.cs @@ -1,4 +1,5 @@ -using Elsa.Workflows.ComponentTests.Helpers; +using Elsa.Workflows.ComponentTests.Abstractions; +using Elsa.Workflows.ComponentTests.Fixtures; using Elsa.Workflows.Management; using Elsa.Workflows.Management.Models; using Elsa.Workflows.Models; diff --git a/test/component/Elsa.Workflows.ComponentTests/Scenarios/DispatchWorkflows/DispatchWorkflowsTests.cs b/test/component/Elsa.Workflows.ComponentTests/Scenarios/DispatchWorkflows/DispatchWorkflowsTests.cs index 050b1a1c5..1b3de1d37 100644 --- a/test/component/Elsa.Workflows.ComponentTests/Scenarios/DispatchWorkflows/DispatchWorkflowsTests.cs +++ b/test/component/Elsa.Workflows.ComponentTests/Scenarios/DispatchWorkflows/DispatchWorkflowsTests.cs @@ -1,7 +1,8 @@ using Elsa.Common.Models; using Elsa.Testing.Shared; using Elsa.Testing.Shared.Services; -using Elsa.Workflows.ComponentTests.Helpers; +using Elsa.Workflows.ComponentTests.Abstractions; +using Elsa.Workflows.ComponentTests.Fixtures; using Elsa.Workflows.ComponentTests.Scenarios.DispatchWorkflows.Workflows; using Elsa.Workflows.Models; using Elsa.Workflows.Runtime; diff --git a/test/component/Elsa.Workflows.ComponentTests/Scenarios/ExecuteWorkflows/ExecuteWorkflowsTests.cs b/test/component/Elsa.Workflows.ComponentTests/Scenarios/ExecuteWorkflows/ExecuteWorkflowsTests.cs new file mode 100644 index 000000000..c47025d46 --- /dev/null +++ b/test/component/Elsa.Workflows.ComponentTests/Scenarios/ExecuteWorkflows/ExecuteWorkflowsTests.cs @@ -0,0 +1,31 @@ +using Elsa.Common.Models; +using Elsa.Workflows.ComponentTests.Abstractions; +using Elsa.Workflows.ComponentTests.Fixtures; +using Elsa.Workflows.ComponentTests.Scenarios.ExecuteWorkflows.Workflows; +using Elsa.Workflows.Models; +using Elsa.Workflows.Runtime; +using Elsa.Workflows.Runtime.Messages; +using Microsoft.Extensions.DependencyInjection; + +namespace Elsa.Workflows.ComponentTests.Scenarios.ExecuteWorkflows; + +public class ExecuteWorkflowsTests : AppComponentTest +{ + private readonly IWorkflowRuntime _workflowRuntime; + + public ExecuteWorkflowsTests(App app) : base(app) + { + _workflowRuntime = Scope.ServiceProvider.GetRequiredService(); + } + + [Fact] + public async Task ExecuteWorkflow_ShouldExecuteWorkflow() + { + var workflowClient = await _workflowRuntime.CreateClientAsync(); + await workflowClient.CreateInstanceAsync(new CreateWorkflowInstanceRequest + { + WorkflowDefinitionHandle = WorkflowDefinitionHandle.ByDefinitionId(MainWorkflow.DefinitionId, VersionOptions.Published) + }); + await workflowClient.RunInstanceAsync(RunWorkflowInstanceRequest.Empty); + } +} \ No newline at end of file diff --git a/test/component/Elsa.Workflows.ComponentTests/Scenarios/ExecuteWorkflows/Workflows/MainWorkflow.cs b/test/component/Elsa.Workflows.ComponentTests/Scenarios/ExecuteWorkflows/Workflows/MainWorkflow.cs new file mode 100644 index 000000000..754fb81df --- /dev/null +++ b/test/component/Elsa.Workflows.ComponentTests/Scenarios/ExecuteWorkflows/Workflows/MainWorkflow.cs @@ -0,0 +1,33 @@ +using System.Text.Json; +using Elsa.Workflows.Activities; +using Elsa.Workflows.Runtime; +using Elsa.Workflows.Runtime.Activities; + +namespace Elsa.Workflows.ComponentTests.Scenarios.ExecuteWorkflows.Workflows; + +public class MainWorkflow : WorkflowBase +{ + public static readonly string DefinitionId = Guid.NewGuid().ToString(); + + protected override void Build(IWorkflowBuilder builder) + { + builder.WithDefinitionId(DefinitionId); + var workflowResult = builder.WithVariable(); + builder.Root = new Sequence + { + Activities = + { + new ExecuteWorkflow + { + WorkflowDefinitionId = new(SubroutineWorkflow.DefinitionId), + Input = new(new Dictionary + { + ["Value"] = 21 + }), + Result = new(workflowResult) + }, + new WriteLine(context => $"Subroutine output: {JsonSerializer.Serialize(workflowResult.Get(context))}") + } + }; + } +} \ No newline at end of file diff --git a/test/component/Elsa.Workflows.ComponentTests/Scenarios/ExecuteWorkflows/Workflows/SubroutineWorkflow.cs b/test/component/Elsa.Workflows.ComponentTests/Scenarios/ExecuteWorkflows/Workflows/SubroutineWorkflow.cs new file mode 100644 index 000000000..531c6cfda --- /dev/null +++ b/test/component/Elsa.Workflows.ComponentTests/Scenarios/ExecuteWorkflows/Workflows/SubroutineWorkflow.cs @@ -0,0 +1,31 @@ +using Elsa.Extensions; +using Elsa.Workflows.Activities; +using Elsa.Workflows.Management.Activities.SetOutput; +using Hangfire.Annotations; + +namespace Elsa.Workflows.ComponentTests.Scenarios.ExecuteWorkflows.Workflows; + +[UsedImplicitly] +public class SubroutineWorkflow : WorkflowBase +{ + public static readonly string DefinitionId = Guid.NewGuid().ToString(); + protected override void Build(IWorkflowBuilder builder) + { + builder.WithDefinitionId(DefinitionId); + var valueInput = builder.WithInput("Value"); + var output = builder.WithOutput("Output"); + + builder.Root = new Sequence + { + Activities = + { + new WriteLine(context => $"Running subroutine on value {context.GetInput(valueInput)}..."), + new SetOutput + { + OutputName = new(output.Name), + OutputValue = new(context => context.GetInput(valueInput) * 2) + } + } + }; + } +} \ No newline at end of file diff --git a/test/component/Elsa.Workflows.ComponentTests/Scenarios/HttpWorkflows/HttpHelloWorldTests.cs b/test/component/Elsa.Workflows.ComponentTests/Scenarios/HttpWorkflows/HttpHelloWorldTests.cs index 930f2b31e..dc27db6f3 100644 --- a/test/component/Elsa.Workflows.ComponentTests/Scenarios/HttpWorkflows/HttpHelloWorldTests.cs +++ b/test/component/Elsa.Workflows.ComponentTests/Scenarios/HttpWorkflows/HttpHelloWorldTests.cs @@ -1,4 +1,5 @@ -using Elsa.Workflows.ComponentTests.Helpers; +using Elsa.Workflows.ComponentTests.Abstractions; +using Elsa.Workflows.ComponentTests.Fixtures; namespace Elsa.Workflows.ComponentTests.Scenarios.HttpWorkflows; diff --git a/test/component/Elsa.Workflows.ComponentTests/Scenarios/HttpWorkflows/ResumeSpecificHttpWorkflowInstanceTests.cs b/test/component/Elsa.Workflows.ComponentTests/Scenarios/HttpWorkflows/ResumeSpecificHttpWorkflowInstanceTests.cs index 77d696f0e..30d46e43c 100644 --- a/test/component/Elsa.Workflows.ComponentTests/Scenarios/HttpWorkflows/ResumeSpecificHttpWorkflowInstanceTests.cs +++ b/test/component/Elsa.Workflows.ComponentTests/Scenarios/HttpWorkflows/ResumeSpecificHttpWorkflowInstanceTests.cs @@ -1,5 +1,6 @@ using System.Net; -using Elsa.Workflows.ComponentTests.Helpers; +using Elsa.Workflows.ComponentTests.Abstractions; +using Elsa.Workflows.ComponentTests.Fixtures; using Microsoft.Extensions.DependencyInjection; namespace Elsa.Workflows.ComponentTests.Scenarios.HttpWorkflows; diff --git a/test/component/Elsa.Workflows.ComponentTests/Scenarios/LogPersistenceModes/InputOutputLoggingTests.cs b/test/component/Elsa.Workflows.ComponentTests/Scenarios/LogPersistenceModes/InputOutputLoggingTests.cs index 68d1171e5..4d2a5629e 100644 --- a/test/component/Elsa.Workflows.ComponentTests/Scenarios/LogPersistenceModes/InputOutputLoggingTests.cs +++ b/test/component/Elsa.Workflows.ComponentTests/Scenarios/LogPersistenceModes/InputOutputLoggingTests.cs @@ -4,7 +4,8 @@ using Elsa.Api.Client.Resources.WorkflowInstances.Models; using Elsa.Common.Entities; using Elsa.Testing.Shared.Extensions; using Elsa.Workflows.Activities; -using Elsa.Workflows.ComponentTests.Helpers; +using Elsa.Workflows.ComponentTests.Abstractions; +using Elsa.Workflows.ComponentTests.Fixtures; using Elsa.Workflows.Helpers; using Elsa.Workflows.Runtime; using Elsa.Workflows.Runtime.Entities; diff --git a/test/component/Elsa.Workflows.ComponentTests/Scenarios/Multitenancy/MultitenancyTests.cs b/test/component/Elsa.Workflows.ComponentTests/Scenarios/Multitenancy/MultitenancyTests.cs index a8f6c05b6..06b5d600c 100644 --- a/test/component/Elsa.Workflows.ComponentTests/Scenarios/Multitenancy/MultitenancyTests.cs +++ b/test/component/Elsa.Workflows.ComponentTests/Scenarios/Multitenancy/MultitenancyTests.cs @@ -1,5 +1,6 @@ using Elsa.Common.Models; -using Elsa.Workflows.ComponentTests.Helpers; +using Elsa.Workflows.ComponentTests.Abstractions; +using Elsa.Workflows.ComponentTests.Fixtures; using Elsa.Workflows.Management; using Elsa.Workflows.Management.Filters; using Microsoft.Extensions.DependencyInjection; diff --git a/test/component/Elsa.Workflows.ComponentTests/Scenarios/Variables/CountdownWorkflowTests.cs b/test/component/Elsa.Workflows.ComponentTests/Scenarios/Variables/CountdownWorkflowTests.cs index 428c28a7b..a09a46863 100644 --- a/test/component/Elsa.Workflows.ComponentTests/Scenarios/Variables/CountdownWorkflowTests.cs +++ b/test/component/Elsa.Workflows.ComponentTests/Scenarios/Variables/CountdownWorkflowTests.cs @@ -1,6 +1,7 @@ using Elsa.Expressions.Helpers; using Elsa.Extensions; -using Elsa.Workflows.ComponentTests.Helpers; +using Elsa.Workflows.ComponentTests.Abstractions; +using Elsa.Workflows.ComponentTests.Fixtures; using Elsa.Workflows.ComponentTests.Scenarios.Variables.Workflows; using Elsa.Workflows.Management; using Elsa.Workflows.Models; diff --git a/test/component/Elsa.Workflows.ComponentTests/Scenarios/WorkflowActivities/AutoUpdateTests.cs b/test/component/Elsa.Workflows.ComponentTests/Scenarios/WorkflowActivities/AutoUpdateTests.cs index 8d25b686a..fdd30c25e 100644 --- a/test/component/Elsa.Workflows.ComponentTests/Scenarios/WorkflowActivities/AutoUpdateTests.cs +++ b/test/component/Elsa.Workflows.ComponentTests/Scenarios/WorkflowActivities/AutoUpdateTests.cs @@ -1,7 +1,8 @@ using Elsa.Http; using Elsa.Testing.Shared; using Elsa.Testing.Shared.Services; -using Elsa.Workflows.ComponentTests.Helpers; +using Elsa.Workflows.ComponentTests.Abstractions; +using Elsa.Workflows.ComponentTests.Fixtures; using Elsa.Workflows.Management; using Elsa.Workflows.Management.Filters; using Elsa.Workflows.Runtime.Filters; diff --git a/test/component/Elsa.Workflows.ComponentTests/Scenarios/WorkflowActivities/DeleteWorkflowTests.cs b/test/component/Elsa.Workflows.ComponentTests/Scenarios/WorkflowActivities/DeleteWorkflowTests.cs index 2068a3812..96fb810be 100644 --- a/test/component/Elsa.Workflows.ComponentTests/Scenarios/WorkflowActivities/DeleteWorkflowTests.cs +++ b/test/component/Elsa.Workflows.ComponentTests/Scenarios/WorkflowActivities/DeleteWorkflowTests.cs @@ -1,6 +1,7 @@ using Elsa.Testing.Shared; using Elsa.Testing.Shared.Services; -using Elsa.Workflows.ComponentTests.Helpers; +using Elsa.Workflows.ComponentTests.Abstractions; +using Elsa.Workflows.ComponentTests.Fixtures; using Elsa.Workflows.ComponentTests.Scenarios.WorkflowActivities.Workflows; using Elsa.Workflows.Management; using Microsoft.Extensions.DependencyInjection; diff --git a/test/component/Elsa.Workflows.ComponentTests/Scenarios/WorkflowActivities/SaveWorkflowTests.cs b/test/component/Elsa.Workflows.ComponentTests/Scenarios/WorkflowActivities/SaveWorkflowTests.cs index e6e09fc88..ff84ede43 100644 --- a/test/component/Elsa.Workflows.ComponentTests/Scenarios/WorkflowActivities/SaveWorkflowTests.cs +++ b/test/component/Elsa.Workflows.ComponentTests/Scenarios/WorkflowActivities/SaveWorkflowTests.cs @@ -1,4 +1,5 @@ -using Elsa.Workflows.ComponentTests.Helpers; +using Elsa.Workflows.ComponentTests.Abstractions; +using Elsa.Workflows.ComponentTests.Fixtures; using Elsa.Workflows.Management; using Elsa.Workflows.Management.Activities.WorkflowDefinitionActivity; using Elsa.Workflows.Management.Models; diff --git a/test/component/Elsa.Workflows.ComponentTests/Scenarios/WorkflowCompletion/WorkflowCompletionTests.cs b/test/component/Elsa.Workflows.ComponentTests/Scenarios/WorkflowCompletion/WorkflowCompletionTests.cs index 7dc704d0c..08a4d7710 100644 --- a/test/component/Elsa.Workflows.ComponentTests/Scenarios/WorkflowCompletion/WorkflowCompletionTests.cs +++ b/test/component/Elsa.Workflows.ComponentTests/Scenarios/WorkflowCompletion/WorkflowCompletionTests.cs @@ -2,7 +2,8 @@ using Elsa.Api.Client.Resources.WorkflowDefinitions.Contracts; using Elsa.Testing.Shared.Extensions; using Elsa.Workflows.Api.Endpoints.WorkflowDefinitions.Execute; -using Elsa.Workflows.ComponentTests.Helpers; +using Elsa.Workflows.ComponentTests.Abstractions; +using Elsa.Workflows.ComponentTests.Fixtures; namespace Elsa.Workflows.ComponentTests.Scenarios.WorkflowCompletion; diff --git a/test/component/Elsa.Workflows.ComponentTests/Scenarios/WorkflowDefinitionRefresh/DynamicEndpointTests.cs b/test/component/Elsa.Workflows.ComponentTests/Scenarios/WorkflowDefinitionRefresh/DynamicEndpointTests.cs index a21b5ab36..32484c686 100644 --- a/test/component/Elsa.Workflows.ComponentTests/Scenarios/WorkflowDefinitionRefresh/DynamicEndpointTests.cs +++ b/test/component/Elsa.Workflows.ComponentTests/Scenarios/WorkflowDefinitionRefresh/DynamicEndpointTests.cs @@ -1,6 +1,7 @@ using System.Net; using Elsa.Testing.Shared.Services; -using Elsa.Workflows.ComponentTests.Helpers; +using Elsa.Workflows.ComponentTests.Abstractions; +using Elsa.Workflows.ComponentTests.Fixtures; using Elsa.Workflows.Runtime; using Microsoft.Extensions.DependencyInjection; diff --git a/test/component/Elsa.Workflows.ComponentTests/Scenarios/WorkflowDefinitionReload/ReloadWorkflowTests.cs b/test/component/Elsa.Workflows.ComponentTests/Scenarios/WorkflowDefinitionReload/ReloadWorkflowTests.cs index 3fb61269b..3f96d9dbb 100644 --- a/test/component/Elsa.Workflows.ComponentTests/Scenarios/WorkflowDefinitionReload/ReloadWorkflowTests.cs +++ b/test/component/Elsa.Workflows.ComponentTests/Scenarios/WorkflowDefinitionReload/ReloadWorkflowTests.cs @@ -1,7 +1,10 @@ using System.Net; using Elsa.Common.Models; using Elsa.Workflows.Activities; -using Elsa.Workflows.ComponentTests.Helpers; +using Elsa.Workflows.ComponentTests.Abstractions; +using Elsa.Workflows.ComponentTests.Fixtures; +using Elsa.Workflows.ComponentTests.Materializers; +using Elsa.Workflows.ComponentTests.WorkflowProviders; using Elsa.Workflows.Management; using Elsa.Workflows.Runtime; using Humanizer; diff --git a/test/component/Elsa.Workflows.ComponentTests/Scenarios/WorkflowJsonStructures/WorkflowJsonStructureTests.cs b/test/component/Elsa.Workflows.ComponentTests/Scenarios/WorkflowJsonStructures/WorkflowJsonStructureTests.cs index bd8514f77..f1ac96583 100644 --- a/test/component/Elsa.Workflows.ComponentTests/Scenarios/WorkflowJsonStructures/WorkflowJsonStructureTests.cs +++ b/test/component/Elsa.Workflows.ComponentTests/Scenarios/WorkflowJsonStructures/WorkflowJsonStructureTests.cs @@ -1,5 +1,6 @@ using Elsa.Api.Client.Resources.WorkflowDefinitions.Contracts; -using Elsa.Workflows.ComponentTests.Helpers; +using Elsa.Workflows.ComponentTests.Abstractions; +using Elsa.Workflows.ComponentTests.Fixtures; namespace Elsa.Workflows.ComponentTests.Scenarios.WorkflowJsonStructures;