From bd3b41440a3b784491fa633ad9549cfe9db35a65 Mon Sep 17 00:00:00 2001 From: Sipke Schoorstra Date: Mon, 19 Oct 2020 22:12:11 +0200 Subject: [PATCH] Incremental work on tests and QA --- .editorconfig | 3 + Elsa.sln | 16 +-- Samples.sln | 40 +++--- Samples.sln.DotSettings | 3 +- .../Activities/ReadLine/ReadLine.cs | 4 +- .../Activities/WriteLine/WriteLine.cs | 2 +- .../WriteLine/WriteLineExtensions.cs | 17 +++ .../Elsa.Activities.Console.csproj | 1 + .../Extensions/ServiceCollectionExtensions.cs | 3 +- .../Elsa.Activities.Dropbox.csproj | 2 +- .../Activities/UserTask.cs | 4 +- .../Elsa.Abstractions.csproj | 2 +- .../Extensions/VariablesExtensions.cs | 2 +- .../Models/ActivityDefinitionPropertyValue.cs | 15 +++ ...sonSerializer.cs => IContentSerializer.cs} | 2 +- .../Services/IWorkflowHost.cs | 25 +++- .../Models/WorkflowExecutionContext.cs | 3 +- .../Elsa.Core/Builders/WorkflowBuilder.cs | 4 +- .../RunWorkflowConsumer.cs} | 6 +- src/core/Elsa.Core/Elsa.Core.csproj | 3 +- src/core/Elsa.Core/ElsaOptions.cs | 2 +- .../ActivityCollectionExtensions.cs | 15 --- .../ElsaServiceCollectionExtensions.cs | 23 ++-- .../AppendExecutionLog.cs} | 6 +- .../PersistWorkflow.cs} | 8 +- .../Serialization/ActivitySerializer.cs | 4 +- ...JsonSerializer.cs => ContentSerializer.cs} | 8 +- .../ServiceCollectionExtensions.cs | 2 +- src/core/Elsa.Core/Services/WorkflowHost.cs | 26 +++- .../Properties/launchSettings.json | 27 ++++ .../Properties/launchSettings.json | 27 ++++ .../Elsa.Samples.Serialization/Program.cs | 2 +- .../Elsa.Samples.Timers.csproj | 2 +- .../Elsa.Server.Api/Elsa.Server.Api.csproj | 29 +++++ .../Endpoints/WorkflowDefinitions/Get.cs | 25 ++++ .../WorkflowDefinitions/Post.Request.cs | 20 +++ .../Endpoints/WorkflowDefinitions/Post.cs | 45 +++++++ .../Extensions/JsonMvcBuilderExtensions.cs | 18 +++ .../Extensions/ServiceCollectionExtensions.cs | 25 ++++ .../Extensions/ServiceCollectionExtensions.cs | 3 +- src/server/Elsa.Server.GraphQL/Mutation.cs | 2 +- .../Elsa.Server.Host/Elsa.Server.Host.csproj | 5 +- src/server/Elsa.Server.Host/Startup.cs | 8 +- .../Assets/hello-world-workflow.json | 37 ++++++ .../Elsa.ComponentTests.csproj | 39 ++++++ .../WorkflowDefinitions/PostTests.cs | 75 +++++++++++ .../Helpers/AssetHelper.cs | 13 ++ .../Helpers/ComponentTestsCollection.cs | 10 ++ .../Helpers/ElsaHostApplicationFactory.cs | 23 ++++ .../Helpers/FakeConfiguration.cs | 15 +++ .../Helpers/HttpClientExtensions.cs | 18 +++ .../Helpers/HttpContentExtensions.cs | 15 +++ .../Helpers/JsonContent.cs | 29 +++++ .../BasicWorkflowUnitTests.cs | 25 ++++ .../Elsa.Core.IntegrationTests.csproj} | 8 +- ...a.Core.IntegrationTests.xunit.runner.json} | 0 .../ForLoopWorkflowUnitTests.cs | 28 ++++ .../Workflows/BasicWorkflow.cs | 13 ++ .../Workflows/ForLoopWorkflow.cs | 26 ++++ .../Abstractions/SpecimenBuilderBase.cs | 2 +- .../NodaTimeCustomization.cs | 4 +- .../SpecimenBuilders/DurationGenerator.cs | 4 +- .../SpecimenBuilders/InstantGenerator.cs | 4 +- .../SpecimenBuilders/LocalDateGenerator.cs | 4 +- .../SpecimenBuilders/PeriodGenerator.cs | 4 +- .../Elsa.Testing.Shared.csproj | 9 +- .../Helpers}/TemporaryFolder.cs | 2 +- .../Helpers/WorkflowsUnitTestBase.cs | 54 ++++++++ .../Helpers/XunitConsoleForwarder.cs | 44 +++++++ .../Elsa.Core.UnitTests/WorkflowHostTests.cs | 120 ------------------ 70 files changed, 869 insertions(+), 245 deletions(-) create mode 100644 src/activities/Elsa.Activities.Console/Activities/WriteLine/WriteLineExtensions.cs rename src/core/Elsa.Abstractions/Serialization/{IJsonSerializer.cs => IContentSerializer.cs} (82%) rename src/core/Elsa.Core/{Messaging/Distributed/Handlers/RunWorkflowHandler.cs => Consumers/RunWorkflowConsumer.cs} (80%) delete mode 100644 src/core/Elsa.Core/Extensions/ActivityCollectionExtensions.cs rename src/core/Elsa.Core/{Messaging/Domain/Handlers/WorkflowExecutionLogEventHandler.cs => Handlers/AppendExecutionLog.cs} (69%) rename src/core/Elsa.Core/{Messaging/Domain/Handlers/PersistenceWorkflowEventHandler.cs => Handlers/PersistWorkflow.cs} (93%) rename src/core/Elsa.Core/Serialization/{DefaultJsonSerializer.cs => ContentSerializer.cs} (87%) rename src/core/Elsa.Core/{Messaging => ServiceBus}/ServiceCollectionExtensions.cs (95%) create mode 100644 src/samples/Elsa.Samples.CustomActivities/Properties/launchSettings.json create mode 100644 src/samples/Elsa.Samples.HelloWorldHttp/Properties/launchSettings.json create mode 100644 src/server/Elsa.Server.Api/Elsa.Server.Api.csproj create mode 100644 src/server/Elsa.Server.Api/Endpoints/WorkflowDefinitions/Get.cs create mode 100644 src/server/Elsa.Server.Api/Endpoints/WorkflowDefinitions/Post.Request.cs create mode 100644 src/server/Elsa.Server.Api/Endpoints/WorkflowDefinitions/Post.cs create mode 100644 src/server/Elsa.Server.Api/Extensions/JsonMvcBuilderExtensions.cs create mode 100644 src/server/Elsa.Server.Api/Extensions/ServiceCollectionExtensions.cs create mode 100644 test/component/Elsa.ComponentTests/Assets/hello-world-workflow.json create mode 100644 test/component/Elsa.ComponentTests/Elsa.ComponentTests.csproj create mode 100644 test/component/Elsa.ComponentTests/Endpoints/WorkflowDefinitions/PostTests.cs create mode 100644 test/component/Elsa.ComponentTests/Helpers/AssetHelper.cs create mode 100644 test/component/Elsa.ComponentTests/Helpers/ComponentTestsCollection.cs create mode 100644 test/component/Elsa.ComponentTests/Helpers/ElsaHostApplicationFactory.cs create mode 100644 test/component/Elsa.ComponentTests/Helpers/FakeConfiguration.cs create mode 100644 test/component/Elsa.ComponentTests/Helpers/HttpClientExtensions.cs create mode 100644 test/component/Elsa.ComponentTests/Helpers/HttpContentExtensions.cs create mode 100644 test/component/Elsa.ComponentTests/Helpers/JsonContent.cs create mode 100644 test/integration/Elsa.Core.IntegrationTests/BasicWorkflowUnitTests.cs rename test/{unit/Elsa.Core.UnitTests/Elsa.Core.UnitTests.csproj => integration/Elsa.Core.IntegrationTests/Elsa.Core.IntegrationTests.csproj} (91%) rename test/{unit/Elsa.Core.UnitTests/Elsa.Core.UnitTests.xunit.runner.json => integration/Elsa.Core.IntegrationTests/Elsa.Core.IntegrationTests.xunit.runner.json} (100%) create mode 100644 test/integration/Elsa.Core.IntegrationTests/ForLoopWorkflowUnitTests.cs create mode 100644 test/integration/Elsa.Core.IntegrationTests/Workflows/BasicWorkflow.cs create mode 100644 test/integration/Elsa.Core.IntegrationTests/Workflows/ForLoopWorkflow.cs rename test/shared/Elsa.Testing.Shared/{Autofixture => AutoFixture}/Abstractions/SpecimenBuilderBase.cs (90%) rename test/shared/Elsa.Testing.Shared/{Autofixture => AutoFixture}/NodaTimeCustomization.cs (80%) rename test/shared/Elsa.Testing.Shared/{Autofixture => AutoFixture}/SpecimenBuilders/DurationGenerator.cs (73%) rename test/shared/Elsa.Testing.Shared/{Autofixture => AutoFixture}/SpecimenBuilders/InstantGenerator.cs (78%) rename test/shared/Elsa.Testing.Shared/{Autofixture => AutoFixture}/SpecimenBuilders/LocalDateGenerator.cs (72%) rename test/shared/Elsa.Testing.Shared/{Autofixture => AutoFixture}/SpecimenBuilders/PeriodGenerator.cs (73%) rename test/{unit/Elsa.Core.UnitTests => shared/Elsa.Testing.Shared/Helpers}/TemporaryFolder.cs (93%) create mode 100644 test/shared/Elsa.Testing.Shared/Helpers/WorkflowsUnitTestBase.cs create mode 100644 test/shared/Elsa.Testing.Shared/Helpers/XunitConsoleForwarder.cs delete mode 100644 test/unit/Elsa.Core.UnitTests/WorkflowHostTests.cs diff --git a/.editorconfig b/.editorconfig index 593f45591e..5cc8f95ea0 100644 --- a/.editorconfig +++ b/.editorconfig @@ -10,3 +10,6 @@ indent_size=4 resharper_csharp_max_line_length=240 resharper_keep_user_linebreaks=true +# Microsoft .NET properties +csharp_new_line_before_members_in_object_initializers=false + diff --git a/Elsa.sln b/Elsa.sln index 2bf1d48d74..ded392a585 100644 --- a/Elsa.sln +++ b/Elsa.sln @@ -52,9 +52,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Elsa.Server.Core", "src\ser EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{AB1AE008-6FD6-414C-8E88-D735F42E1FA6}" EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "unit", "unit", "{0A3C36AB-2ACF-4175-A512-66B4C3DB9371}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Elsa.Core.UnitTests", "test\unit\Elsa.Core.UnitTests\Elsa.Core.UnitTests.csproj", "{475EEB95-ED27-4366-88EA-97C5000AC8E8}" +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "integration", "integration", "{0A3C36AB-2ACF-4175-A512-66B4C3DB9371}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "shared", "shared", "{0A6747EA-7AC6-4B6F-BC0C-C40C8A80C44D}" EndProject @@ -72,6 +70,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "locking", "locking", "{7CD5 EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Elsa.YesSql.Provider.Sqlite.InMemory", "src\core\Elsa.YesSql.Provider.Sqlite.InMemory\Elsa.YesSql.Provider.Sqlite.InMemory.csproj", "{E2D63391-1986-45C8-A18F-4D58F3D71057}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Elsa.Core.IntegrationTests", "test\integration\Elsa.Core.IntegrationTests\Elsa.Core.IntegrationTests.csproj", "{3C43CC9B-E64F-4481-9B27-3E868AD95CE9}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -130,10 +130,6 @@ Global {D91E2F7B-D5B7-4D1C-A3F0-B0475C33F539}.Debug|Any CPU.Build.0 = Debug|Any CPU {D91E2F7B-D5B7-4D1C-A3F0-B0475C33F539}.Release|Any CPU.ActiveCfg = Release|Any CPU {D91E2F7B-D5B7-4D1C-A3F0-B0475C33F539}.Release|Any CPU.Build.0 = Release|Any CPU - {475EEB95-ED27-4366-88EA-97C5000AC8E8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {475EEB95-ED27-4366-88EA-97C5000AC8E8}.Debug|Any CPU.Build.0 = Debug|Any CPU - {475EEB95-ED27-4366-88EA-97C5000AC8E8}.Release|Any CPU.ActiveCfg = Release|Any CPU - {475EEB95-ED27-4366-88EA-97C5000AC8E8}.Release|Any CPU.Build.0 = Release|Any CPU {E7C689EB-5AD6-4E91-A007-6116EEA702FC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {E7C689EB-5AD6-4E91-A007-6116EEA702FC}.Debug|Any CPU.Build.0 = Debug|Any CPU {E7C689EB-5AD6-4E91-A007-6116EEA702FC}.Release|Any CPU.ActiveCfg = Release|Any CPU @@ -159,6 +155,10 @@ Global {E2D63391-1986-45C8-A18F-4D58F3D71057}.Debug|Any CPU.Build.0 = Debug|Any CPU {E2D63391-1986-45C8-A18F-4D58F3D71057}.Release|Any CPU.ActiveCfg = Release|Any CPU {E2D63391-1986-45C8-A18F-4D58F3D71057}.Release|Any CPU.Build.0 = Release|Any CPU + {3C43CC9B-E64F-4481-9B27-3E868AD95CE9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3C43CC9B-E64F-4481-9B27-3E868AD95CE9}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3C43CC9B-E64F-4481-9B27-3E868AD95CE9}.Release|Any CPU.ActiveCfg = Release|Any CPU + {3C43CC9B-E64F-4481-9B27-3E868AD95CE9}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -182,7 +182,6 @@ Global {468E498C-59DB-4541-8D8A-0D89DE9083AB} = {DA71CDAA-8DD3-4D5F-9FBD-8E4B37A2D925} {D91E2F7B-D5B7-4D1C-A3F0-B0475C33F539} = {468E498C-59DB-4541-8D8A-0D89DE9083AB} {0A3C36AB-2ACF-4175-A512-66B4C3DB9371} = {AB1AE008-6FD6-414C-8E88-D735F42E1FA6} - {475EEB95-ED27-4366-88EA-97C5000AC8E8} = {0A3C36AB-2ACF-4175-A512-66B4C3DB9371} {0A6747EA-7AC6-4B6F-BC0C-C40C8A80C44D} = {AB1AE008-6FD6-414C-8E88-D735F42E1FA6} {E7C689EB-5AD6-4E91-A007-6116EEA702FC} = {0A6747EA-7AC6-4B6F-BC0C-C40C8A80C44D} {12D29DDC-A885-4CAA-908C-106D845B10C0} = {468E498C-59DB-4541-8D8A-0D89DE9083AB} @@ -191,6 +190,7 @@ Global {EBD49CCA-5400-4C36-B5DF-7B28190AA323} = {7CD5C8D5-EC78-4A99-A514-F01CA7197AC8} {150EF356-E8BC-4922-91C2-362017479409} = {7CD5C8D5-EC78-4A99-A514-F01CA7197AC8} {E2D63391-1986-45C8-A18F-4D58F3D71057} = {35F44BE9-13D0-417C-A01A-F0787BEE6DC3} + {3C43CC9B-E64F-4481-9B27-3E868AD95CE9} = {0A3C36AB-2ACF-4175-A512-66B4C3DB9371} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {8B0975FD-7050-48B0-88C5-48C33378E158} diff --git a/Samples.sln b/Samples.sln index ffd9941c72..30ed6028f7 100644 --- a/Samples.sln +++ b/Samples.sln @@ -56,9 +56,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Elsa.Server.Host", "src\ser EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{AB1AE008-6FD6-414C-8E88-D735F42E1FA6}" EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "unit", "unit", "{0A3C36AB-2ACF-4175-A512-66B4C3DB9371}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Elsa.Core.UnitTests", "test\unit\Elsa.Core.UnitTests\Elsa.Core.UnitTests.csproj", "{475EEB95-ED27-4366-88EA-97C5000AC8E8}" +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "integration", "integration", "{0A3C36AB-2ACF-4175-A512-66B4C3DB9371}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "shared", "shared", "{0A6747EA-7AC6-4B6F-BC0C-C40C8A80C44D}" EndProject @@ -68,8 +66,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Elsa.Samples.Timers", "src\ EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Elsa.DistributedLocking.SqlServer", "src\providers\Elsa.DistributedLocking.SqlServer\Elsa.DistributedLocking.SqlServer.csproj", "{150EF356-E8BC-4922-91C2-362017479409}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Elsa.Server.GraphQL", "src\server\Elsa.Server.GraphQL\Elsa.Server.GraphQL.csproj", "{12D29DDC-A885-4CAA-908C-106D845B10C0}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Elsa.Samples.Serialization", "src\samples\Elsa.Samples.Serialization\Elsa.Samples.Serialization.csproj", "{DF47517F-9029-44DF-A29F-F2DE15041473}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Elsa.Samples.HelloWorldConsole", "src\samples\Elsa.Samples.HelloWorldConsole\Elsa.Samples.HelloWorldConsole.csproj", "{E224F8CF-F9F5-4E99-B405-758F3C02C47A}" @@ -94,6 +90,14 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Elsa.Samples.ReadLineEchoCo EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Elsa.YesSql.Provider.Sqlite.InMemory", "src\core\Elsa.YesSql.Provider.Sqlite.InMemory\Elsa.YesSql.Provider.Sqlite.InMemory.csproj", "{D0364288-3072-44F4-877C-7721C20BC27F}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Elsa.Core.IntegrationTests", "test\integration\Elsa.Core.IntegrationTests\Elsa.Core.IntegrationTests.csproj", "{4CB34AB3-01C9-4911-8914-EABAA744EAD3}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "component", "component", "{FC47A50F-03B2-47D8-AAFB-075314FBA186}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Elsa.ComponentTests", "test\component\Elsa.ComponentTests\Elsa.ComponentTests.csproj", "{BB5819C7-434A-4AC5-8B0E-6C4FA672EBD5}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Elsa.Server.Api", "src\server\Elsa.Server.Api\Elsa.Server.Api.csproj", "{44E0B699-A140-4551-A0E9-9FD9F171A9C2}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -156,10 +160,6 @@ Global {FC54EDBA-71FB-4A87-8FD5-54759DF77CCE}.Debug|Any CPU.Build.0 = Debug|Any CPU {FC54EDBA-71FB-4A87-8FD5-54759DF77CCE}.Release|Any CPU.ActiveCfg = Release|Any CPU {FC54EDBA-71FB-4A87-8FD5-54759DF77CCE}.Release|Any CPU.Build.0 = Release|Any CPU - {475EEB95-ED27-4366-88EA-97C5000AC8E8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {475EEB95-ED27-4366-88EA-97C5000AC8E8}.Debug|Any CPU.Build.0 = Debug|Any CPU - {475EEB95-ED27-4366-88EA-97C5000AC8E8}.Release|Any CPU.ActiveCfg = Release|Any CPU - {475EEB95-ED27-4366-88EA-97C5000AC8E8}.Release|Any CPU.Build.0 = Release|Any CPU {E7C689EB-5AD6-4E91-A007-6116EEA702FC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {E7C689EB-5AD6-4E91-A007-6116EEA702FC}.Debug|Any CPU.Build.0 = Debug|Any CPU {E7C689EB-5AD6-4E91-A007-6116EEA702FC}.Release|Any CPU.ActiveCfg = Release|Any CPU @@ -172,10 +172,6 @@ Global {150EF356-E8BC-4922-91C2-362017479409}.Debug|Any CPU.Build.0 = Debug|Any CPU {150EF356-E8BC-4922-91C2-362017479409}.Release|Any CPU.ActiveCfg = Release|Any CPU {150EF356-E8BC-4922-91C2-362017479409}.Release|Any CPU.Build.0 = Release|Any CPU - {12D29DDC-A885-4CAA-908C-106D845B10C0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {12D29DDC-A885-4CAA-908C-106D845B10C0}.Debug|Any CPU.Build.0 = Debug|Any CPU - {12D29DDC-A885-4CAA-908C-106D845B10C0}.Release|Any CPU.ActiveCfg = Release|Any CPU - {12D29DDC-A885-4CAA-908C-106D845B10C0}.Release|Any CPU.Build.0 = Release|Any CPU {DF47517F-9029-44DF-A29F-F2DE15041473}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {DF47517F-9029-44DF-A29F-F2DE15041473}.Debug|Any CPU.Build.0 = Debug|Any CPU {DF47517F-9029-44DF-A29F-F2DE15041473}.Release|Any CPU.ActiveCfg = Release|Any CPU @@ -221,6 +217,18 @@ Global {D0364288-3072-44F4-877C-7721C20BC27F}.Debug|Any CPU.Build.0 = Debug|Any CPU {D0364288-3072-44F4-877C-7721C20BC27F}.Release|Any CPU.ActiveCfg = Release|Any CPU {D0364288-3072-44F4-877C-7721C20BC27F}.Release|Any CPU.Build.0 = Release|Any CPU + {4CB34AB3-01C9-4911-8914-EABAA744EAD3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {4CB34AB3-01C9-4911-8914-EABAA744EAD3}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4CB34AB3-01C9-4911-8914-EABAA744EAD3}.Release|Any CPU.ActiveCfg = Release|Any CPU + {4CB34AB3-01C9-4911-8914-EABAA744EAD3}.Release|Any CPU.Build.0 = Release|Any CPU + {BB5819C7-434A-4AC5-8B0E-6C4FA672EBD5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {BB5819C7-434A-4AC5-8B0E-6C4FA672EBD5}.Debug|Any CPU.Build.0 = Debug|Any CPU + {BB5819C7-434A-4AC5-8B0E-6C4FA672EBD5}.Release|Any CPU.ActiveCfg = Release|Any CPU + {BB5819C7-434A-4AC5-8B0E-6C4FA672EBD5}.Release|Any CPU.Build.0 = Release|Any CPU + {44E0B699-A140-4551-A0E9-9FD9F171A9C2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {44E0B699-A140-4551-A0E9-9FD9F171A9C2}.Debug|Any CPU.Build.0 = Debug|Any CPU + {44E0B699-A140-4551-A0E9-9FD9F171A9C2}.Release|Any CPU.ActiveCfg = Release|Any CPU + {44E0B699-A140-4551-A0E9-9FD9F171A9C2}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -246,11 +254,9 @@ Global {D91E2F7B-D5B7-4D1C-A3F0-B0475C33F539} = {468E498C-59DB-4541-8D8A-0D89DE9083AB} {FC54EDBA-71FB-4A87-8FD5-54759DF77CCE} = {468E498C-59DB-4541-8D8A-0D89DE9083AB} {0A3C36AB-2ACF-4175-A512-66B4C3DB9371} = {AB1AE008-6FD6-414C-8E88-D735F42E1FA6} - {475EEB95-ED27-4366-88EA-97C5000AC8E8} = {0A3C36AB-2ACF-4175-A512-66B4C3DB9371} {0A6747EA-7AC6-4B6F-BC0C-C40C8A80C44D} = {AB1AE008-6FD6-414C-8E88-D735F42E1FA6} {E7C689EB-5AD6-4E91-A007-6116EEA702FC} = {0A6747EA-7AC6-4B6F-BC0C-C40C8A80C44D} {071DD6EC-D00C-4513-82B6-3FE8438061E3} = {5E5E1E84-DDBC-40D6-B891-0D563A15A44A} - {12D29DDC-A885-4CAA-908C-106D845B10C0} = {468E498C-59DB-4541-8D8A-0D89DE9083AB} {DF47517F-9029-44DF-A29F-F2DE15041473} = {5E5E1E84-DDBC-40D6-B891-0D563A15A44A} {E224F8CF-F9F5-4E99-B405-758F3C02C47A} = {5E5E1E84-DDBC-40D6-B891-0D563A15A44A} {A11D79AE-F4C9-4595-9B73-0E0AB221B90D} = {5E5E1E84-DDBC-40D6-B891-0D563A15A44A} @@ -264,6 +270,10 @@ Global {F755FB1F-72FB-4F7B-8270-F5F40F4D6952} = {5E5E1E84-DDBC-40D6-B891-0D563A15A44A} {867CB845-B803-4D40-9360-3D11ADBD9CE9} = {5E5E1E84-DDBC-40D6-B891-0D563A15A44A} {D0364288-3072-44F4-877C-7721C20BC27F} = {35F44BE9-13D0-417C-A01A-F0787BEE6DC3} + {4CB34AB3-01C9-4911-8914-EABAA744EAD3} = {0A3C36AB-2ACF-4175-A512-66B4C3DB9371} + {FC47A50F-03B2-47D8-AAFB-075314FBA186} = {AB1AE008-6FD6-414C-8E88-D735F42E1FA6} + {BB5819C7-434A-4AC5-8B0E-6C4FA672EBD5} = {FC47A50F-03B2-47D8-AAFB-075314FBA186} + {44E0B699-A140-4551-A0E9-9FD9F171A9C2} = {468E498C-59DB-4541-8D8A-0D89DE9083AB} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {8B0975FD-7050-48B0-88C5-48C33378E158} diff --git a/Samples.sln.DotSettings b/Samples.sln.DotSettings index 1e636e30a1..ba2138f0cb 100644 --- a/Samples.sln.DotSettings +++ b/Samples.sln.DotSettings @@ -8,4 +8,5 @@ True True True - True \ No newline at end of file + True + True \ No newline at end of file diff --git a/src/activities/Elsa.Activities.Console/Activities/ReadLine/ReadLine.cs b/src/activities/Elsa.Activities.Console/Activities/ReadLine/ReadLine.cs index 8ca4ef24dd..8a02f5e26b 100644 --- a/src/activities/Elsa.Activities.Console/Activities/ReadLine/ReadLine.cs +++ b/src/activities/Elsa.Activities.Console/Activities/ReadLine/ReadLine.cs @@ -22,7 +22,7 @@ namespace Elsa.Activities.Console )] public class ReadLine : Activity { - private readonly TextReader _input; + private readonly TextReader? _input; public ReadLine() { @@ -46,7 +46,7 @@ protected override async ValueTask OnExecuteAsync( protected override IActivityExecutionResult OnResume(ActivityExecutionContext context) { - var receivedInput = (string)context.Input; + var receivedInput = (string)context.Input!; return Execute(receivedInput); } diff --git a/src/activities/Elsa.Activities.Console/Activities/WriteLine/WriteLine.cs b/src/activities/Elsa.Activities.Console/Activities/WriteLine/WriteLine.cs index 911de62abf..681a8c5301 100644 --- a/src/activities/Elsa.Activities.Console/Activities/WriteLine/WriteLine.cs +++ b/src/activities/Elsa.Activities.Console/Activities/WriteLine/WriteLine.cs @@ -30,7 +30,7 @@ public WriteLine(TextWriter output) } [ActivityProperty(Hint = "The text to write.")] - public string Text { get; set; } + public string? Text { get; set; } private readonly TextWriter _output; diff --git a/src/activities/Elsa.Activities.Console/Activities/WriteLine/WriteLineExtensions.cs b/src/activities/Elsa.Activities.Console/Activities/WriteLine/WriteLineExtensions.cs new file mode 100644 index 0000000000..2ea67a0a38 --- /dev/null +++ b/src/activities/Elsa.Activities.Console/Activities/WriteLine/WriteLineExtensions.cs @@ -0,0 +1,17 @@ +using System; +using System.Threading.Tasks; +using Elsa.Builders; +using Elsa.Services.Models; + +// ReSharper disable once CheckNamespace +namespace Elsa.Activities.Console +{ + public static class WriteLineExtensions + { + public static ISetupActivity WithText(this ISetupActivity writeLine, Func> text) => writeLine.Set(x => x.Text, text); + public static ISetupActivity WithText(this ISetupActivity writeLine, Func text) => writeLine.Set(x => x.Text, text); + public static ISetupActivity WithText(this ISetupActivity writeLine, Func> text) => writeLine.Set(x => x.Text, text); + public static ISetupActivity WithText(this ISetupActivity writeLine, Func text) => writeLine.Set(x => x.Text, text); + public static ISetupActivity WithText(this ISetupActivity writeLine, string? text) => writeLine.Set(x => x.Text, text); + } +} \ No newline at end of file diff --git a/src/activities/Elsa.Activities.Console/Elsa.Activities.Console.csproj b/src/activities/Elsa.Activities.Console/Elsa.Activities.Console.csproj index b6b7bc2866..0e5c0b10da 100644 --- a/src/activities/Elsa.Activities.Console/Elsa.Activities.Console.csproj +++ b/src/activities/Elsa.Activities.Console/Elsa.Activities.Console.csproj @@ -18,6 +18,7 @@ GitHub elsa, workflows icon.png + enable diff --git a/src/activities/Elsa.Activities.Console/Extensions/ServiceCollectionExtensions.cs b/src/activities/Elsa.Activities.Console/Extensions/ServiceCollectionExtensions.cs index 03b8941af7..a2621f4d6b 100644 --- a/src/activities/Elsa.Activities.Console/Extensions/ServiceCollectionExtensions.cs +++ b/src/activities/Elsa.Activities.Console/Extensions/ServiceCollectionExtensions.cs @@ -7,10 +7,11 @@ namespace Microsoft.Extensions.DependencyInjection { public static class ServiceCollectionExtensions { - public static IServiceCollection AddConsoleActivities(this IServiceCollection services, TextReader standardIn = default) + public static IServiceCollection AddConsoleActivities(this IServiceCollection services, TextReader? standardIn = default, TextWriter? standardOut = default) { return services .AddSingleton(standardIn ?? Console.In) + .AddSingleton(standardOut ?? Console.Out) .AddActivity() .AddActivity(); } diff --git a/src/activities/Elsa.Activities.Dropbox/Elsa.Activities.Dropbox.csproj b/src/activities/Elsa.Activities.Dropbox/Elsa.Activities.Dropbox.csproj index 59b8d8ee99..67939b7312 100644 --- a/src/activities/Elsa.Activities.Dropbox/Elsa.Activities.Dropbox.csproj +++ b/src/activities/Elsa.Activities.Dropbox/Elsa.Activities.Dropbox.csproj @@ -33,7 +33,7 @@ - + diff --git a/src/activities/Elsa.Activities.UserTask/Activities/UserTask.cs b/src/activities/Elsa.Activities.UserTask/Activities/UserTask.cs index bf362d92b7..7530c9e03a 100644 --- a/src/activities/Elsa.Activities.UserTask/Activities/UserTask.cs +++ b/src/activities/Elsa.Activities.UserTask/Activities/UserTask.cs @@ -20,7 +20,7 @@ namespace Elsa.Activities.UserTask.Activities )] public class UserTask : Activity { - private readonly IJsonSerializer _serializer; + private readonly IContentSerializer _serializer; [ActivityProperty( Type = ActivityPropertyTypes.List, @@ -28,7 +28,7 @@ public class UserTask : Activity )] public ICollection Actions { get; set; } = new List(); - public UserTask(IJsonSerializer serializer) + public UserTask(IContentSerializer serializer) { _serializer = serializer; } diff --git a/src/core/Elsa.Abstractions/Elsa.Abstractions.csproj b/src/core/Elsa.Abstractions/Elsa.Abstractions.csproj index b5f5d9ac72..3fd2078abc 100644 --- a/src/core/Elsa.Abstractions/Elsa.Abstractions.csproj +++ b/src/core/Elsa.Abstractions/Elsa.Abstractions.csproj @@ -32,7 +32,7 @@ - + diff --git a/src/core/Elsa.Abstractions/Extensions/VariablesExtensions.cs b/src/core/Elsa.Abstractions/Extensions/VariablesExtensions.cs index 7fb4123489..dbf4b80f54 100644 --- a/src/core/Elsa.Abstractions/Extensions/VariablesExtensions.cs +++ b/src/core/Elsa.Abstractions/Extensions/VariablesExtensions.cs @@ -5,7 +5,7 @@ namespace Elsa { public static class VariablesExtensions { - public static T Get(this Variables variables, string name, IJsonSerializer serializer) + public static T Get(this Variables variables, string name, IContentSerializer serializer) { var value = variables.Get(name); return value != null ? serializer.Deserialize(value) : default!; diff --git a/src/core/Elsa.Abstractions/Models/ActivityDefinitionPropertyValue.cs b/src/core/Elsa.Abstractions/Models/ActivityDefinitionPropertyValue.cs index e05c26d883..fad658632f 100644 --- a/src/core/Elsa.Abstractions/Models/ActivityDefinitionPropertyValue.cs +++ b/src/core/Elsa.Abstractions/Models/ActivityDefinitionPropertyValue.cs @@ -4,6 +4,21 @@ namespace Elsa.Models { public class ActivityDefinitionPropertyValue { + public static ActivityDefinitionPropertyValue Literal(T value) => new ActivityDefinitionPropertyValue(value!.ToString(), "Literal", typeof(T)); + public static ActivityDefinitionPropertyValue Liquid(string expression) => new ActivityDefinitionPropertyValue(expression, "Liquid", typeof(T)); + public static ActivityDefinitionPropertyValue JavaScript(string expression) => new ActivityDefinitionPropertyValue(expression, "JavaScript", typeof(T)); + + public ActivityDefinitionPropertyValue() + { + } + + public ActivityDefinitionPropertyValue(string expression, string syntax, Type type) + { + Expression = expression; + Syntax = syntax; + Type = type; + } + public Type Type { get; set; } = default!; public string Syntax { get; set; } = default!; public string Expression { get; set; } = default!; diff --git a/src/core/Elsa.Abstractions/Serialization/IJsonSerializer.cs b/src/core/Elsa.Abstractions/Serialization/IContentSerializer.cs similarity index 82% rename from src/core/Elsa.Abstractions/Serialization/IJsonSerializer.cs rename to src/core/Elsa.Abstractions/Serialization/IContentSerializer.cs index 0f30a168bf..851168e75a 100644 --- a/src/core/Elsa.Abstractions/Serialization/IJsonSerializer.cs +++ b/src/core/Elsa.Abstractions/Serialization/IContentSerializer.cs @@ -2,7 +2,7 @@ namespace Elsa.Serialization { - public interface IJsonSerializer + public interface IContentSerializer { JObject Serialize(T value); T Deserialize(JToken token); diff --git a/src/core/Elsa.Abstractions/Services/IWorkflowHost.cs b/src/core/Elsa.Abstractions/Services/IWorkflowHost.cs index cd8245aa2d..7fbcf1d645 100644 --- a/src/core/Elsa.Abstractions/Services/IWorkflowHost.cs +++ b/src/core/Elsa.Abstractions/Services/IWorkflowHost.cs @@ -13,7 +13,7 @@ ValueTask RunWorkflowAsync( string? activityId = default, object? input = default, CancellationToken cancellationToken = default); - + ValueTask RunWorkflowAsync( IWorkflowBlueprint workflowDefinition, WorkflowInstance workflowInstance, @@ -27,17 +27,32 @@ ValueTask RunWorkflowAsync( object? input = default, string? correlationId = default, CancellationToken cancellationToken = default); - + ValueTask RunWorkflowAsync( string? activityId = default, object? input = default, string? correlationId = default, - CancellationToken cancellationToken = default) where T:IWorkflow; - + CancellationToken cancellationToken = default) where T : IWorkflow; + ValueTask RunWorkflowAsync( WorkflowInstance workflowInstance, string? activityId = default, object? input = default, - CancellationToken cancellationToken = default) where T:IWorkflow; + CancellationToken cancellationToken = default) where T : IWorkflow; + + ValueTask RunWorkflowAsync( + IWorkflow workflow, + string? activityId = default, + object? input = default, + string? correlationId = default, + CancellationToken cancellationToken = default); + + ValueTask RunWorkflowAsync( + IWorkflow workflow, + WorkflowInstance workflowInstance, + string? activityId = default, + object? input = default, + string? correlationId = default, + CancellationToken cancellationToken = default); } } \ No newline at end of file diff --git a/src/core/Elsa.Abstractions/Services/Models/WorkflowExecutionContext.cs b/src/core/Elsa.Abstractions/Services/Models/WorkflowExecutionContext.cs index 57d9215c0d..2be947aca7 100644 --- a/src/core/Elsa.Abstractions/Services/Models/WorkflowExecutionContext.cs +++ b/src/core/Elsa.Abstractions/Services/Models/WorkflowExecutionContext.cs @@ -18,7 +18,6 @@ WorkflowInstance workflowInstance ServiceProvider = serviceProvider; WorkflowBlueprint = workflowBlueprint; WorkflowInstance = workflowInstance; - ExecutionLog = new List(workflowInstance.ExecutionLog); IsFirstPass = true; } @@ -47,7 +46,7 @@ public void ScheduleActivities(IEnumerable activities) public ScheduledActivity PeekScheduledActivity() => WorkflowInstance.ScheduledActivities.Peek(); public string? CorrelationId { get; set; } public bool DeleteCompletedInstances { get; set; } - public ICollection ExecutionLog { get; } + public ICollection ExecutionLog => WorkflowInstance.ExecutionLog; public WorkflowStatus Status => WorkflowInstance.Status; public void SetVariable(string name, object? value) => WorkflowInstance.Variables.Set(name, JToken.FromObject(value!)); diff --git a/src/core/Elsa.Core/Builders/WorkflowBuilder.cs b/src/core/Elsa.Core/Builders/WorkflowBuilder.cs index 87ea6c1ca6..1825120495 100644 --- a/src/core/Elsa.Core/Builders/WorkflowBuilder.cs +++ b/src/core/Elsa.Core/Builders/WorkflowBuilder.cs @@ -93,11 +93,9 @@ public IWorkflowBuilder WithDeleteCompletedInstances(bool value) public IActivityBuilder New( Type activityType, - Action? branch = default, IDictionary? propertyValueProviders = default) { var activityBuilder = new ActivityBuilder(activityType, this, propertyValueProviders); - branch?.Invoke(activityBuilder); return activityBuilder; } @@ -105,7 +103,7 @@ public IActivityBuilder New( Action? branch = default, IDictionary? propertyValueProviders = default) where T : class, IActivity => - New(typeof(T), branch, propertyValueProviders); + New(typeof(T), propertyValueProviders); public IActivityBuilder New( Action>? setup = default, diff --git a/src/core/Elsa.Core/Messaging/Distributed/Handlers/RunWorkflowHandler.cs b/src/core/Elsa.Core/Consumers/RunWorkflowConsumer.cs similarity index 80% rename from src/core/Elsa.Core/Messaging/Distributed/Handlers/RunWorkflowHandler.cs rename to src/core/Elsa.Core/Consumers/RunWorkflowConsumer.cs index 6c62e0b00b..309c4cf61c 100644 --- a/src/core/Elsa.Core/Messaging/Distributed/Handlers/RunWorkflowHandler.cs +++ b/src/core/Elsa.Core/Consumers/RunWorkflowConsumer.cs @@ -5,14 +5,14 @@ using Elsa.Services; using Rebus.Handlers; -namespace Elsa.Messaging.Distributed.Handlers +namespace Elsa.Consumers { - public class RunWorkflowHandler : IHandleMessages + public class RunWorkflowConsumer : IHandleMessages { private readonly IWorkflowHost _workflowHost; private readonly IWorkflowInstanceManager _workflowInstanceManager; - public RunWorkflowHandler(IWorkflowHost workflowHost, IWorkflowInstanceManager workflowInstanceManager) + public RunWorkflowConsumer(IWorkflowHost workflowHost, IWorkflowInstanceManager workflowInstanceManager) { _workflowHost = workflowHost; _workflowInstanceManager = workflowInstanceManager; diff --git a/src/core/Elsa.Core/Elsa.Core.csproj b/src/core/Elsa.Core/Elsa.Core.csproj index ad94b2aa5c..fd98a0a819 100644 --- a/src/core/Elsa.Core/Elsa.Core.csproj +++ b/src/core/Elsa.Core/Elsa.Core.csproj @@ -46,7 +46,7 @@ - + @@ -69,7 +69,6 @@ - \ No newline at end of file diff --git a/src/core/Elsa.Core/ElsaOptions.cs b/src/core/Elsa.Core/ElsaOptions.cs index 33dfa43198..7549faef21 100644 --- a/src/core/Elsa.Core/ElsaOptions.cs +++ b/src/core/Elsa.Core/ElsaOptions.cs @@ -29,7 +29,7 @@ public ElsaOptions(IServiceCollection services) CreateJsonSerializer = sp => { - var serializer = DefaultJsonSerializer.CreateDefaultJsonSerializer(); + var serializer = ContentSerializer.CreateDefaultJsonSerializer(); JsonSerializerConfigurer(sp, serializer); return serializer; }; diff --git a/src/core/Elsa.Core/Extensions/ActivityCollectionExtensions.cs b/src/core/Elsa.Core/Extensions/ActivityCollectionExtensions.cs deleted file mode 100644 index f3028b28bf..0000000000 --- a/src/core/Elsa.Core/Extensions/ActivityCollectionExtensions.cs +++ /dev/null @@ -1,15 +0,0 @@ -using System.Collections.Generic; -using System.Linq; -using Elsa.Services; - -namespace Elsa.Extensions -{ - public static class ActivityCollectionExtensions - { - public static IEnumerable Find(this IEnumerable collection, IEnumerable ids) - { - var idList = ids?.ToList(); - return idList != null ? collection.Where(x => idList.Contains(x.Id)) : default; - } - } -} \ No newline at end of file diff --git a/src/core/Elsa.Core/Extensions/ElsaServiceCollectionExtensions.cs b/src/core/Elsa.Core/Extensions/ElsaServiceCollectionExtensions.cs index bac7236a44..2c869f5c79 100644 --- a/src/core/Elsa.Core/Extensions/ElsaServiceCollectionExtensions.cs +++ b/src/core/Elsa.Core/Extensions/ElsaServiceCollectionExtensions.cs @@ -1,22 +1,26 @@ using System; using System.Collections.Generic; +using System.Linq; using Elsa; using Elsa.Activities.ControlFlow; using Elsa.Activities.Primitives; using Elsa.Activities.Signaling; using Elsa.Builders; +using Elsa.Consumers; using Elsa.Converters; using Elsa.Data; using Elsa.Data.Extensions; +using Elsa.Events; using Elsa.Expressions; +using Elsa.Extensions; +using Elsa.Handlers; using Elsa.Indexes; using Elsa.Messages; -using Elsa.Messaging; -using Elsa.Messaging.Distributed.Handlers; using Elsa.Metadata; using Elsa.Metadata.Handlers; using Elsa.Runtime; using Elsa.Serialization; +using Elsa.ServiceBus; using Elsa.Services; using Elsa.StartupTasks; using Elsa.Triggers; @@ -67,13 +71,7 @@ public static IServiceCollection AddWorkflow(this IServiceCollection services } public static IServiceCollection AddConsumer(this IServiceCollection services) where TConsumer : class, IHandleMessages => services.AddTransient, TConsumer>(); - - private static IServiceCollection AddMediatR(this ElsaOptions options) - { - return options.Services.AddMediatR( - mediatr => mediatr.AsScoped(), - typeof(ElsaServiceCollectionExtensions)); - } + private static IServiceCollection AddMediatR(this ElsaOptions options) => options.Services.AddMediatR(mediatr => mediatr.AsScoped(), typeof(IActivity)); private static ElsaOptions AddWorkflowsCore(this ElsaOptions configuration) { @@ -87,7 +85,7 @@ private static ElsaOptions AddWorkflowsCore(this ElsaOptions configuration) .AddTransient>>(sp => sp.GetServices) .AddSingleton() .AddSingleton(sp => sp.GetRequiredService().CreateJsonSerializer(sp)) - .AddSingleton() + .AddSingleton() .AddSingleton() .AddSingleton() .TryAddProvider(ServiceLifetime.Singleton) @@ -99,7 +97,7 @@ private static ElsaOptions AddWorkflowsCore(this ElsaOptions configuration) .AddScoped() .AddSingleton() .AddSingleton() - .AddSingleton() + .AddScoped() .AddScoped() .AddScoped() .AddIndexProvider() @@ -109,8 +107,9 @@ private static ElsaOptions AddWorkflowsCore(this ElsaOptions configuration) .AddWorkflowProvider() .AddTransient() .AddTransient>(sp => sp.GetRequiredService) + .AddNotificationHandlers(typeof(ElsaServiceCollectionExtensions)) .AddStartupTask() - .AddConsumer() + .AddConsumer() .AddMetadataHandlers() .AddPrimitiveActivities(); diff --git a/src/core/Elsa.Core/Messaging/Domain/Handlers/WorkflowExecutionLogEventHandler.cs b/src/core/Elsa.Core/Handlers/AppendExecutionLog.cs similarity index 69% rename from src/core/Elsa.Core/Messaging/Domain/Handlers/WorkflowExecutionLogEventHandler.cs rename to src/core/Elsa.Core/Handlers/AppendExecutionLog.cs index 4b338900bb..dd4e314175 100644 --- a/src/core/Elsa.Core/Messaging/Domain/Handlers/WorkflowExecutionLogEventHandler.cs +++ b/src/core/Elsa.Core/Handlers/AppendExecutionLog.cs @@ -5,12 +5,12 @@ using MediatR; using NodaTime; -namespace Elsa.Messaging.Domain.Handlers +namespace Elsa.Handlers { - public class WorkflowExecutionLogEventHandler : INotificationHandler + public class AppendExecutionLog : INotificationHandler { private readonly IClock _clock; - public WorkflowExecutionLogEventHandler(IClock clock) => _clock = clock; + public AppendExecutionLog(IClock clock) => _clock = clock; public Task Handle(ActivityExecuted notification, CancellationToken cancellationToken) { diff --git a/src/core/Elsa.Core/Messaging/Domain/Handlers/PersistenceWorkflowEventHandler.cs b/src/core/Elsa.Core/Handlers/PersistWorkflow.cs similarity index 93% rename from src/core/Elsa.Core/Messaging/Domain/Handlers/PersistenceWorkflowEventHandler.cs rename to src/core/Elsa.Core/Handlers/PersistWorkflow.cs index 718b3230af..9692342810 100644 --- a/src/core/Elsa.Core/Messaging/Domain/Handlers/PersistenceWorkflowEventHandler.cs +++ b/src/core/Elsa.Core/Handlers/PersistWorkflow.cs @@ -7,9 +7,9 @@ using MediatR; using Microsoft.Extensions.Logging; -namespace Elsa.Messaging.Domain.Handlers +namespace Elsa.Handlers { - public class PersistenceWorkflowEventHandler : + public class PersistWorkflow : INotificationHandler, INotificationHandler, INotificationHandler, @@ -18,9 +18,9 @@ public class PersistenceWorkflowEventHandler : private readonly IWorkflowInstanceManager _workflowInstanceManager; private readonly ILogger _logger; - public PersistenceWorkflowEventHandler( + public PersistWorkflow( IWorkflowInstanceManager workflowInstanceManager, - ILogger logger) + ILogger logger) { _workflowInstanceManager = workflowInstanceManager; _logger = logger; diff --git a/src/core/Elsa.Core/Serialization/ActivitySerializer.cs b/src/core/Elsa.Core/Serialization/ActivitySerializer.cs index 1363c20980..ff6df1c002 100644 --- a/src/core/Elsa.Core/Serialization/ActivitySerializer.cs +++ b/src/core/Elsa.Core/Serialization/ActivitySerializer.cs @@ -5,8 +5,8 @@ namespace Elsa.Serialization { public class ActivitySerializer : IActivitySerializer { - private readonly IJsonSerializer _ijSerializer; - public ActivitySerializer(IJsonSerializer ijSerializer) => _ijSerializer = ijSerializer; + private readonly IContentSerializer _ijSerializer; + public ActivitySerializer(IContentSerializer ijSerializer) => _ijSerializer = ijSerializer; public JObject Serialize(T activity) where T : IActivity => _ijSerializer.Serialize(activity); public T Deserialize(JObject data) where T : IActivity => _ijSerializer.Deserialize(data); } diff --git a/src/core/Elsa.Core/Serialization/DefaultJsonSerializer.cs b/src/core/Elsa.Core/Serialization/ContentSerializer.cs similarity index 87% rename from src/core/Elsa.Core/Serialization/DefaultJsonSerializer.cs rename to src/core/Elsa.Core/Serialization/ContentSerializer.cs index 16cdc1e8d7..104c895d99 100644 --- a/src/core/Elsa.Core/Serialization/DefaultJsonSerializer.cs +++ b/src/core/Elsa.Core/Serialization/ContentSerializer.cs @@ -7,9 +7,9 @@ namespace Elsa.Serialization { - public class DefaultJsonSerializer : IJsonSerializer + public class ContentSerializer : IContentSerializer { - public DefaultJsonSerializer(JsonSerializer serializer) + public ContentSerializer(JsonSerializer serializer) { Serializer = serializer; } @@ -30,9 +30,9 @@ public static JsonSerializer CreateDefaultJsonSerializer() jsonSerializer.ConfigureForNodaTime(DateTimeZoneProviders.Tzdb); jsonSerializer.NullValueHandling = NullValueHandling.Ignore; jsonSerializer.ReferenceLoopHandling = ReferenceLoopHandling.Serialize; - jsonSerializer.PreserveReferencesHandling = PreserveReferencesHandling.Objects; + jsonSerializer.PreserveReferencesHandling = PreserveReferencesHandling.All; jsonSerializer.TypeNameAssemblyFormatHandling = TypeNameAssemblyFormatHandling.Simple; - jsonSerializer.TypeNameHandling = TypeNameHandling.Objects; + jsonSerializer.TypeNameHandling = TypeNameHandling.None; jsonSerializer.ContractResolver = new CamelCasePropertyNamesContractResolver { NamingStrategy = new CamelCaseNamingStrategy diff --git a/src/core/Elsa.Core/Messaging/ServiceCollectionExtensions.cs b/src/core/Elsa.Core/ServiceBus/ServiceCollectionExtensions.cs similarity index 95% rename from src/core/Elsa.Core/Messaging/ServiceCollectionExtensions.cs rename to src/core/Elsa.Core/ServiceBus/ServiceCollectionExtensions.cs index 6201058717..3e7b3badcd 100644 --- a/src/core/Elsa.Core/Messaging/ServiceCollectionExtensions.cs +++ b/src/core/Elsa.Core/ServiceBus/ServiceCollectionExtensions.cs @@ -3,7 +3,7 @@ using Rebus.Config; using Rebus.ServiceProvider; -namespace Elsa.Messaging +namespace Elsa.ServiceBus { public static class ServiceCollectionExtensions { diff --git a/src/core/Elsa.Core/Services/WorkflowHost.cs b/src/core/Elsa.Core/Services/WorkflowHost.cs index 5c8fcef779..5727d64505 100644 --- a/src/core/Elsa.Core/Services/WorkflowHost.cs +++ b/src/core/Elsa.Core/Services/WorkflowHost.cs @@ -27,7 +27,6 @@ public class WorkflowHost : IWorkflowHost private readonly IWorkflowBuilder _workflowBuilder; private readonly IMediator _mediator; private readonly IServiceProvider _serviceProvider; - private readonly IEnumerable _triggerProviders; private readonly ILogger _logger; public WorkflowHost( @@ -36,7 +35,6 @@ public WorkflowHost( IWorkflowBuilder workflowBuilder, IMediator mediator, IServiceProvider serviceProvider, - IEnumerable triggerProviders, ILogger logger) { _workflowRegistry = workflowRegistry; @@ -44,7 +42,6 @@ public WorkflowHost( _workflowBuilder = workflowBuilder; _mediator = mediator; _serviceProvider = serviceProvider; - _triggerProviders = triggerProviders; _logger = logger; } @@ -79,6 +76,29 @@ public async ValueTask RunWorkflowAsync( where T : IWorkflow => await RunWorkflowAsync(_workflowBuilder.Build(), workflowInstance, activityId, input, cancellationToken); + public async ValueTask RunWorkflowAsync( + IWorkflow workflow, + string? activityId = default, + object? input = default, + string? correlationId = default, + CancellationToken cancellationToken = default) + { + var workflowBlueprint = _workflowBuilder.Build(workflow); + return await RunWorkflowAsync(workflowBlueprint, activityId, input, correlationId, cancellationToken); + } + + public async ValueTask RunWorkflowAsync( + IWorkflow workflow, + WorkflowInstance workflowInstance, + string? activityId = default, + object? input = default, + string? correlationId = default, + CancellationToken cancellationToken = default) + { + var workflowBlueprint = _workflowBuilder.Build(workflow); + return await RunWorkflowAsync(workflowBlueprint, workflowInstance, activityId, input, cancellationToken); + } + public async ValueTask RunWorkflowAsync( WorkflowInstance workflowInstance, string? activityId = default, diff --git a/src/samples/Elsa.Samples.CustomActivities/Properties/launchSettings.json b/src/samples/Elsa.Samples.CustomActivities/Properties/launchSettings.json new file mode 100644 index 0000000000..86fb7527a5 --- /dev/null +++ b/src/samples/Elsa.Samples.CustomActivities/Properties/launchSettings.json @@ -0,0 +1,27 @@ +{ + "iisSettings": { + "windowsAuthentication": false, + "anonymousAuthentication": true, + "iisExpress": { + "applicationUrl": "http://localhost:62840/", + "sslPort": 44305 + } + }, + "profiles": { + "IIS Express": { + "commandName": "IISExpress", + "launchBrowser": true, + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "Elsa.Samples.CustomActivities": { + "commandName": "Project", + "launchBrowser": true, + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + }, + "applicationUrl": "https://localhost:5001;http://localhost:5000" + } + } +} \ No newline at end of file diff --git a/src/samples/Elsa.Samples.HelloWorldHttp/Properties/launchSettings.json b/src/samples/Elsa.Samples.HelloWorldHttp/Properties/launchSettings.json new file mode 100644 index 0000000000..e85d335207 --- /dev/null +++ b/src/samples/Elsa.Samples.HelloWorldHttp/Properties/launchSettings.json @@ -0,0 +1,27 @@ +{ + "iisSettings": { + "windowsAuthentication": false, + "anonymousAuthentication": true, + "iisExpress": { + "applicationUrl": "http://localhost:62841/", + "sslPort": 44336 + } + }, + "profiles": { + "IIS Express": { + "commandName": "IISExpress", + "launchBrowser": true, + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "Elsa.Samples.HelloWorldHttp": { + "commandName": "Project", + "launchBrowser": true, + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + }, + "applicationUrl": "https://localhost:5001;http://localhost:5000" + } + } +} \ No newline at end of file diff --git a/src/samples/Elsa.Samples.Serialization/Program.cs b/src/samples/Elsa.Samples.Serialization/Program.cs index 66dc0a6c85..e932a2914d 100644 --- a/src/samples/Elsa.Samples.Serialization/Program.cs +++ b/src/samples/Elsa.Samples.Serialization/Program.cs @@ -60,7 +60,7 @@ static async Task Main(string[] args) }; // Serialize workflow definition to JSON. - var serializer = services.GetRequiredService(); + var serializer = services.GetRequiredService(); var json = serializer.Serialize(workflowDefinition); Console.WriteLine(json); diff --git a/src/samples/Elsa.Samples.Timers/Elsa.Samples.Timers.csproj b/src/samples/Elsa.Samples.Timers/Elsa.Samples.Timers.csproj index b34c1de28d..f09b267644 100644 --- a/src/samples/Elsa.Samples.Timers/Elsa.Samples.Timers.csproj +++ b/src/samples/Elsa.Samples.Timers/Elsa.Samples.Timers.csproj @@ -7,7 +7,7 @@ - + diff --git a/src/server/Elsa.Server.Api/Elsa.Server.Api.csproj b/src/server/Elsa.Server.Api/Elsa.Server.Api.csproj new file mode 100644 index 0000000000..59ba1be57a --- /dev/null +++ b/src/server/Elsa.Server.Api/Elsa.Server.Api.csproj @@ -0,0 +1,29 @@ + + + + netcoreapp3.1 + enable + + + + + + + + + + + + + + + + + + + + + Post.cs + + + diff --git a/src/server/Elsa.Server.Api/Endpoints/WorkflowDefinitions/Get.cs b/src/server/Elsa.Server.Api/Endpoints/WorkflowDefinitions/Get.cs new file mode 100644 index 0000000000..208c36de9f --- /dev/null +++ b/src/server/Elsa.Server.Api/Endpoints/WorkflowDefinitions/Get.cs @@ -0,0 +1,25 @@ +using System.Threading; +using System.Threading.Tasks; +using Elsa.Models; +using Elsa.Queries; +using Elsa.Services; +using Microsoft.AspNetCore.Mvc; + +namespace Elsa.Server.Api.Endpoints.WorkflowDefinitions +{ + [ApiController] + [ApiVersion("1")] + [Route("v{version:apiVersion}/workflow-definitions/{id}")] + public class Get : ControllerBase + { + private readonly IWorkflowDefinitionManager _workflowDefinitionManager; + public Get(IWorkflowDefinitionManager workflowDefinitionManager) => _workflowDefinitionManager = workflowDefinitionManager; + + [HttpGet] + public async Task Handle([FromRoute(Name = "id")] string workflowDefinitionId, CancellationToken cancellationToken) + { + var workflowDefinition = await _workflowDefinitionManager.GetAsync(workflowDefinitionId, VersionOptions.Latest, cancellationToken); + return workflowDefinition == null ? (IActionResult)NotFound() : Ok(workflowDefinition); + } + } +} \ No newline at end of file diff --git a/src/server/Elsa.Server.Api/Endpoints/WorkflowDefinitions/Post.Request.cs b/src/server/Elsa.Server.Api/Endpoints/WorkflowDefinitions/Post.Request.cs new file mode 100644 index 0000000000..3984c541d4 --- /dev/null +++ b/src/server/Elsa.Server.Api/Endpoints/WorkflowDefinitions/Post.Request.cs @@ -0,0 +1,20 @@ +using System.Collections.Generic; +using Elsa.Models; + +namespace Elsa.Server.Api.Endpoints.WorkflowDefinitions +{ + public class CreateWorkflowDefinitionRequest + { + public string WorkflowDefinitionId { get; set; } = default!; + public string? Name { get; set; } + public string? Description { get; set; } + public Variables? Variables { get; set; } + public bool IsSingleton { get; set; } + public WorkflowPersistenceBehavior PersistenceBehavior { get; set; } + public bool DeleteCompletedInstances { get; set; } + public bool Enabled { get; set; } + public bool Publish { get; set; } + public ICollection Activities { get; set; } = new List(); + public ICollection Connections { get; set; } = new List(); + } +} \ No newline at end of file diff --git a/src/server/Elsa.Server.Api/Endpoints/WorkflowDefinitions/Post.cs b/src/server/Elsa.Server.Api/Endpoints/WorkflowDefinitions/Post.cs new file mode 100644 index 0000000000..b6c40a2a60 --- /dev/null +++ b/src/server/Elsa.Server.Api/Endpoints/WorkflowDefinitions/Post.cs @@ -0,0 +1,45 @@ +using System.Threading; +using System.Threading.Tasks; +using Elsa.Models; +using Elsa.Services; +using Microsoft.AspNetCore.Mvc; + +namespace Elsa.Server.Api.Endpoints.WorkflowDefinitions +{ + [ApiController] + [ApiVersion("1")] + [Route("v{version:apiVersion}/workflow-definitions")] + public class Post : ControllerBase + { + private readonly IWorkflowDefinitionManager _workflowDefinitionManager; + + public Post(IWorkflowDefinitionManager workflowDefinitionManager) + { + _workflowDefinitionManager = workflowDefinitionManager; + } + + [HttpPost] + public async Task Handle(CreateWorkflowDefinitionRequest request, ApiVersion apiVersion, CancellationToken cancellationToken) + { + var workflowDefinition = new WorkflowDefinition + { + WorkflowDefinitionId = request.WorkflowDefinitionId.Trim(), + Activities = request.Activities, + Connections = request.Connections, + Description = request.Description?.Trim(), + Name = request.Name?.Trim(), + Variables = request.Variables, + IsEnabled = request.Enabled, + IsLatest = true, + IsPublished = request.Publish, + Version = 1, + IsSingleton = request.IsSingleton, + PersistenceBehavior = request.PersistenceBehavior, + DeleteCompletedInstances = request.DeleteCompletedInstances + }; + + await _workflowDefinitionManager.SaveAsync(workflowDefinition, cancellationToken); + return CreatedAtAction("Handle", "Get", new { version = apiVersion.ToString() }, workflowDefinition); + } + } +} \ No newline at end of file diff --git a/src/server/Elsa.Server.Api/Extensions/JsonMvcBuilderExtensions.cs b/src/server/Elsa.Server.Api/Extensions/JsonMvcBuilderExtensions.cs new file mode 100644 index 0000000000..f99b465f67 --- /dev/null +++ b/src/server/Elsa.Server.Api/Extensions/JsonMvcBuilderExtensions.cs @@ -0,0 +1,18 @@ +using System.Text.Json; +using Microsoft.Extensions.DependencyInjection; +using NodaTime; +using NodaTime.Serialization.SystemTextJson; + +namespace Elsa.Server.Api.Extensions +{ + public static class JsonMvcBuilderExtensions + { + public static IMvcBuilder AddJsonSerialization(this IMvcBuilder builder) => + builder.AddJsonOptions( + options => + { + options.JsonSerializerOptions.PropertyNamingPolicy = JsonNamingPolicy.CamelCase; + options.JsonSerializerOptions.ConfigureForNodaTime(DateTimeZoneProviders.Tzdb); + }); + } +} \ No newline at end of file diff --git a/src/server/Elsa.Server.Api/Extensions/ServiceCollectionExtensions.cs b/src/server/Elsa.Server.Api/Extensions/ServiceCollectionExtensions.cs new file mode 100644 index 0000000000..4b8639c1a2 --- /dev/null +++ b/src/server/Elsa.Server.Api/Extensions/ServiceCollectionExtensions.cs @@ -0,0 +1,25 @@ +using Elsa.Server.Api.Extensions; +using Microsoft.AspNetCore.Mvc; + +// ReSharper disable once CheckNamespace +namespace Microsoft.Extensions.DependencyInjection +{ + public static class ServiceCollectionExtensions + { + public static IServiceCollection AddElsaApiEndpoints(this IServiceCollection services) + { + services.AddControllers().SetCompatibilityVersion(CompatibilityVersion.Latest).AddJsonSerialization(); + services.AddRouting(options => options.LowercaseUrls = true); + + services.AddApiVersioning( + options => + { + options.ReportApiVersions = true; + options.DefaultApiVersion = ApiVersion.Default; + options.AssumeDefaultVersionWhenUnspecified = true; + }); + + return services; + } + } +} \ No newline at end of file diff --git a/src/server/Elsa.Server.GraphQL/Extensions/ServiceCollectionExtensions.cs b/src/server/Elsa.Server.GraphQL/Extensions/ServiceCollectionExtensions.cs index 9180249865..f841aee7be 100644 --- a/src/server/Elsa.Server.GraphQL/Extensions/ServiceCollectionExtensions.cs +++ b/src/server/Elsa.Server.GraphQL/Extensions/ServiceCollectionExtensions.cs @@ -6,7 +6,8 @@ using HotChocolate; using Microsoft.Extensions.DependencyInjection; -namespace Elsa.Server.GraphQL.Extensions +// ReSharper disable once CheckNamespace +namespace Microsoft.Extensions.DependencyInjection { public static class ServiceCollectionExtensions { diff --git a/src/server/Elsa.Server.GraphQL/Mutation.cs b/src/server/Elsa.Server.GraphQL/Mutation.cs index ed2be0d71b..f028ea0048 100644 --- a/src/server/Elsa.Server.GraphQL/Mutation.cs +++ b/src/server/Elsa.Server.GraphQL/Mutation.cs @@ -29,7 +29,7 @@ public async Task SaveWorkflowDefinition( WorkflowInput workflowInput, [Service] IWorkflowDefinitionManager manager, [Service] IIdGenerator idGenerator, - [Service] IJsonSerializer serializer, + [Service] IContentSerializer serializer, [Service] IWorkflowPublisher publisher, CancellationToken cancellationToken) { diff --git a/src/server/Elsa.Server.Host/Elsa.Server.Host.csproj b/src/server/Elsa.Server.Host/Elsa.Server.Host.csproj index d117e9cd83..f53bd35ae6 100644 --- a/src/server/Elsa.Server.Host/Elsa.Server.Host.csproj +++ b/src/server/Elsa.Server.Host/Elsa.Server.Host.csproj @@ -5,14 +5,11 @@ + - - - - diff --git a/src/server/Elsa.Server.Host/Startup.cs b/src/server/Elsa.Server.Host/Startup.cs index e9bdbce2d2..0ccf5e0d64 100644 --- a/src/server/Elsa.Server.Host/Startup.cs +++ b/src/server/Elsa.Server.Host/Startup.cs @@ -1,8 +1,5 @@ using Elsa.Runtime; -using Elsa.Server.GraphQL.Extensions; using Elsa.StartupTasks; -using HotChocolate.AspNetCore; -using HotChocolate.AspNetCore.Voyager; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.Configuration; @@ -34,7 +31,7 @@ public void ConfigureServices(IServiceCollection services) services .AddElsaServer() - .AddElsaGraphQL() + .AddElsaApiEndpoints() .AddCors(options => options.AddDefaultPolicy(cors => cors .AllowAnyOrigin() @@ -57,9 +54,6 @@ public void Configure(IApplicationBuilder app) app .UseCors() - .UseGraphQL("/graphql") - .UsePlayground("/graphql") - .UseVoyager("/graphql") .UseHttpActivities(); } } diff --git a/test/component/Elsa.ComponentTests/Assets/hello-world-workflow.json b/test/component/Elsa.ComponentTests/Assets/hello-world-workflow.json new file mode 100644 index 0000000000..59672ec5a7 --- /dev/null +++ b/test/component/Elsa.ComponentTests/Assets/hello-world-workflow.json @@ -0,0 +1,37 @@ +{ + "$id": "1", + "workflowDefinitionId": "SampleWorkflow", + "workflowDefinitionVersionId": "1", + "version": 1, + "variables": { + "$id": "2", + "data": {} + }, + "isEnabled": true, + "isPublished": true, + "isLatest": true, + "activities": { + "$id": "3", + "$values": [ + { + "$id": "4", + "id": "activity-1", + "type": "WriteLine", + "properties": { + "$id": "5", + "Text": { + "$id": "6", + "type": "System.String, mscorlib", + "syntax": "Liquid", + "expression": "Hello World!" + } + } + } + ] + }, + "connections": { + "$id": "7", + "$values": [] + } + } + \ No newline at end of file diff --git a/test/component/Elsa.ComponentTests/Elsa.ComponentTests.csproj b/test/component/Elsa.ComponentTests/Elsa.ComponentTests.csproj new file mode 100644 index 0000000000..d94d17cf71 --- /dev/null +++ b/test/component/Elsa.ComponentTests/Elsa.ComponentTests.csproj @@ -0,0 +1,39 @@ + + + + netcoreapp3.1 + false + enable + + + + + + + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + + + + + + + + + + + + + PreserveNewest + + + + diff --git a/test/component/Elsa.ComponentTests/Endpoints/WorkflowDefinitions/PostTests.cs b/test/component/Elsa.ComponentTests/Endpoints/WorkflowDefinitions/PostTests.cs new file mode 100644 index 0000000000..d520c617e3 --- /dev/null +++ b/test/component/Elsa.ComponentTests/Endpoints/WorkflowDefinitions/PostTests.cs @@ -0,0 +1,75 @@ +using System; +using System.Net; +using System.Net.Http; +using System.Threading.Tasks; +using AutoFixture; +using Elsa.Activities.Console; +using Elsa.ComponentTests.Helpers; +using Elsa.Core.IntegrationTests.Helpers; +using Elsa.Models; +using Elsa.Server.Api.Endpoints.WorkflowDefinitions; +using Elsa.Testing.Shared.AutoFixture; +using Xunit; + +namespace Elsa.ComponentTests.Endpoints.WorkflowDefinitions +{ + [Collection(ComponentTestsCollection.Name)] + public class PostTests : IDisposable + { + private readonly IFixture _fixture; + private readonly TemporaryFolder _tempFolder; + private readonly ElsaHostApplicationFactory _hostApplicationFactory; + private readonly HttpClient _httpClient; + + public PostTests(ElsaHostApplicationFactory hostApplicationFactory) + { + _fixture = new Fixture().Customize(new NodaTimeCustomization()); + _tempFolder = new TemporaryFolder(); + _hostApplicationFactory = hostApplicationFactory; + hostApplicationFactory.SetDbConnectionString($@"Data Source={_tempFolder.Folder}elsa.db;Cache=Shared"); + _httpClient = hostApplicationFactory.CreateClient(); + } + + [Fact(DisplayName = "Posting a new workflow definition returns HTTP 201.")] + public async Task Post01() + { + var request = CreateWorkflowDefinitionRequest(); + var response = await _httpClient.PostJsonAsync("/v1/workflow-definitions", request); + + Assert.Equal(HttpStatusCode.Created, response.StatusCode); + } + + private CreateWorkflowDefinitionRequest CreateWorkflowDefinitionRequest() + { + var writeLine = new ActivityDefinition + { + Id = _fixture.Create(), + Type = nameof(WriteLine), + Properties = new ActivityDefinitionProperties + { + [nameof(WriteLine.Text)] = ActivityDefinitionPropertyValue.Literal("Hello World!") + } + }; + + var readLine = new ActivityDefinition { Id = _fixture.Create(), Type = nameof(ReadLine) }; + var activities = new[] { writeLine, readLine }; + var connections = new[] { new ConnectionDefinition(writeLine.Id, readLine.Id, OutcomeNames.Done) }; + + return _fixture.Build() + .With(x => x.Activities, activities) + .With(x => x.Connections, connections) + .Create(); + } + + private string CreateWorkflowDefinitionJson() + { + throw new NotImplementedException(); + } + + public void Dispose() + { + _hostApplicationFactory.Dispose(); + _tempFolder.Dispose(); + } + } +} \ No newline at end of file diff --git a/test/component/Elsa.ComponentTests/Helpers/AssetHelper.cs b/test/component/Elsa.ComponentTests/Helpers/AssetHelper.cs new file mode 100644 index 0000000000..0d42d86879 --- /dev/null +++ b/test/component/Elsa.ComponentTests/Helpers/AssetHelper.cs @@ -0,0 +1,13 @@ +using System.IO; +using System.Threading.Tasks; + +namespace Elsa.ComponentTests.Helpers +{ + public static class AssetHelper + { + private static readonly string AssetsDirectory; + static AssetHelper() => AssetsDirectory = Path.Combine(Path.GetDirectoryName(typeof(AssetHelper).Assembly.Location)!, "Assets"); + public static string GetAssetPath(string filename) => Path.Combine(AssetsDirectory, filename); + public static Task ReadAsset(string filename) => File.ReadAllTextAsync(Path.Combine(AssetsDirectory, filename)); + } +} \ No newline at end of file diff --git a/test/component/Elsa.ComponentTests/Helpers/ComponentTestsCollection.cs b/test/component/Elsa.ComponentTests/Helpers/ComponentTestsCollection.cs new file mode 100644 index 0000000000..c09ea8693b --- /dev/null +++ b/test/component/Elsa.ComponentTests/Helpers/ComponentTestsCollection.cs @@ -0,0 +1,10 @@ +using Xunit; + +namespace Elsa.ComponentTests.Helpers +{ + [CollectionDefinition(Name)] + public class ComponentTestsCollection : ICollectionFixture + { + public const string Name = "Component Tests"; + } +} diff --git a/test/component/Elsa.ComponentTests/Helpers/ElsaHostApplicationFactory.cs b/test/component/Elsa.ComponentTests/Helpers/ElsaHostApplicationFactory.cs new file mode 100644 index 0000000000..ca12aaaf80 --- /dev/null +++ b/test/component/Elsa.ComponentTests/Helpers/ElsaHostApplicationFactory.cs @@ -0,0 +1,23 @@ +using Elsa.Server.Host; +using Microsoft.AspNetCore.Hosting; +using Microsoft.AspNetCore.Mvc.Testing; +using Microsoft.Extensions.Configuration; + +namespace Elsa.ComponentTests.Helpers +{ + public class ElsaHostApplicationFactory : WebApplicationFactory + { + private string _dbConnectionString; + + public void SetDbConnectionString(string connectionString) + { + _dbConnectionString = connectionString; + } + + protected override void ConfigureWebHost(IWebHostBuilder builder) + { + builder + .ConfigureAppConfiguration(config => config.AddInMemoryCollection(FakeConfiguration.Create(_dbConnectionString))); + } + } +} \ No newline at end of file diff --git a/test/component/Elsa.ComponentTests/Helpers/FakeConfiguration.cs b/test/component/Elsa.ComponentTests/Helpers/FakeConfiguration.cs new file mode 100644 index 0000000000..0432ea7b80 --- /dev/null +++ b/test/component/Elsa.ComponentTests/Helpers/FakeConfiguration.cs @@ -0,0 +1,15 @@ +using System.Collections.Generic; + +namespace Elsa.ComponentTests.Helpers +{ + public static class FakeConfiguration + { + public static IEnumerable> Create(string dbConnectionString) + { + return new Dictionary + { + ["ConnectionStrings:Sqlite"] = dbConnectionString, + }; + } + } +} diff --git a/test/component/Elsa.ComponentTests/Helpers/HttpClientExtensions.cs b/test/component/Elsa.ComponentTests/Helpers/HttpClientExtensions.cs new file mode 100644 index 0000000000..5137c401db --- /dev/null +++ b/test/component/Elsa.ComponentTests/Helpers/HttpClientExtensions.cs @@ -0,0 +1,18 @@ +using System.Net.Http; +using System.Threading.Tasks; + +namespace Elsa.ComponentTests.Helpers +{ + public static class HttpClientExtensions + { + public static async Task GetJsonAsync(this HttpClient httpClient, string requestUri) + { + using var response = await httpClient.GetAsync(requestUri); + response.EnsureSuccessStatusCode(); + + return await response.Content.ReadJsonAsync(); + } + + public static async Task PostJsonAsync(this HttpClient httpClient, string requestUri, T value) => await httpClient.PostAsync(requestUri, new JsonContent(value!)); + } +} \ No newline at end of file diff --git a/test/component/Elsa.ComponentTests/Helpers/HttpContentExtensions.cs b/test/component/Elsa.ComponentTests/Helpers/HttpContentExtensions.cs new file mode 100644 index 0000000000..5524f1d71a --- /dev/null +++ b/test/component/Elsa.ComponentTests/Helpers/HttpContentExtensions.cs @@ -0,0 +1,15 @@ +using System.Net.Http; +using System.Threading.Tasks; +using Newtonsoft.Json; + +namespace Elsa.ComponentTests.Helpers +{ + public static class HttpContentExtensions + { + public static async Task ReadJsonAsync(this HttpContent content) + { + var json = await content.ReadAsStringAsync(); + return JsonConvert.DeserializeObject(json, JsonContent.SerializerSettings)!; + } + } +} \ No newline at end of file diff --git a/test/component/Elsa.ComponentTests/Helpers/JsonContent.cs b/test/component/Elsa.ComponentTests/Helpers/JsonContent.cs new file mode 100644 index 0000000000..afabf756fa --- /dev/null +++ b/test/component/Elsa.ComponentTests/Helpers/JsonContent.cs @@ -0,0 +1,29 @@ +using System.Net.Http; +using System.Text; +using Newtonsoft.Json; +using Newtonsoft.Json.Converters; +using Newtonsoft.Json.Serialization; +using NodaTime; +using NodaTime.Serialization.JsonNet; + +namespace Elsa.ComponentTests.Helpers +{ + public class JsonContent : StringContent + { + public static readonly JsonSerializerSettings SerializerSettings; + + static JsonContent() + { + SerializerSettings = new JsonSerializerSettings { ContractResolver = new CamelCasePropertyNamesContractResolver() }.ConfigureForNodaTime(DateTimeZoneProviders.Tzdb); + SerializerSettings.Converters.Add(new StringEnumConverter()); + } + + public JsonContent(string content) : base(content, Encoding.UTF8, "application/json") + { + } + + public JsonContent(object content) : this(JsonConvert.SerializeObject(content, SerializerSettings)) + { + } + } +} \ No newline at end of file diff --git a/test/integration/Elsa.Core.IntegrationTests/BasicWorkflowUnitTests.cs b/test/integration/Elsa.Core.IntegrationTests/BasicWorkflowUnitTests.cs new file mode 100644 index 0000000000..b88392c848 --- /dev/null +++ b/test/integration/Elsa.Core.IntegrationTests/BasicWorkflowUnitTests.cs @@ -0,0 +1,25 @@ +using System.Threading.Tasks; +using Elsa.Core.IntegrationTests.Helpers; +using Elsa.Core.IntegrationTests.Workflows; +using Elsa.Models; +using Elsa.Testing.Shared.Helpers; +using Xunit; +using Xunit.Abstractions; + +namespace Elsa.Core.IntegrationTests +{ + public class BasicWorkflowUnitTests : WorkflowsUnitTestBase + { + public BasicWorkflowUnitTests(ITestOutputHelper testOutputHelper) : base(testOutputHelper) + { + } + + [Fact(DisplayName = "Runs simple workflow.")] + public async Task Test01() + { + var workflowInstance = await WorkflowHost.RunWorkflowAsync(); + + Assert.Equal(WorkflowStatus.Completed, workflowInstance.Status); + } + } +} \ No newline at end of file diff --git a/test/unit/Elsa.Core.UnitTests/Elsa.Core.UnitTests.csproj b/test/integration/Elsa.Core.IntegrationTests/Elsa.Core.IntegrationTests.csproj similarity index 91% rename from test/unit/Elsa.Core.UnitTests/Elsa.Core.UnitTests.csproj rename to test/integration/Elsa.Core.IntegrationTests/Elsa.Core.IntegrationTests.csproj index 01220f4799..87bea58a84 100644 --- a/test/unit/Elsa.Core.UnitTests/Elsa.Core.UnitTests.csproj +++ b/test/integration/Elsa.Core.IntegrationTests/Elsa.Core.IntegrationTests.csproj @@ -2,9 +2,7 @@ netcoreapp3.1 - false - enable @@ -33,8 +31,12 @@ - + + + + + diff --git a/test/unit/Elsa.Core.UnitTests/Elsa.Core.UnitTests.xunit.runner.json b/test/integration/Elsa.Core.IntegrationTests/Elsa.Core.IntegrationTests.xunit.runner.json similarity index 100% rename from test/unit/Elsa.Core.UnitTests/Elsa.Core.UnitTests.xunit.runner.json rename to test/integration/Elsa.Core.IntegrationTests/Elsa.Core.IntegrationTests.xunit.runner.json diff --git a/test/integration/Elsa.Core.IntegrationTests/ForLoopWorkflowUnitTests.cs b/test/integration/Elsa.Core.IntegrationTests/ForLoopWorkflowUnitTests.cs new file mode 100644 index 0000000000..186bf40e8c --- /dev/null +++ b/test/integration/Elsa.Core.IntegrationTests/ForLoopWorkflowUnitTests.cs @@ -0,0 +1,28 @@ +using System.Linq; +using System.Threading.Tasks; +using Elsa.Core.IntegrationTests.Helpers; +using Elsa.Core.IntegrationTests.Workflows; +using Elsa.Testing.Shared.Helpers; +using Xunit; +using Xunit.Abstractions; + +namespace Elsa.Core.IntegrationTests +{ + public class ForLoopWorkflowUnitTests : WorkflowsUnitTestBase + { + public ForLoopWorkflowUnitTests(ITestOutputHelper testOutputHelper) : base(testOutputHelper) + { + } + + [Fact(DisplayName = "Runs For loop workflow.")] + public async Task Test01() + { + const int loopCount = 10; + var workflow = new ForLoopWorkflow(loopCount); + var workflowInstance = await WorkflowHost.RunWorkflowAsync(workflow); + var iterationLogs = workflowInstance.ExecutionLog.Where(x => x.ActivityId == "WriteLine").ToList(); + + Assert.Equal(loopCount, iterationLogs.Count); + } + } +} \ No newline at end of file diff --git a/test/integration/Elsa.Core.IntegrationTests/Workflows/BasicWorkflow.cs b/test/integration/Elsa.Core.IntegrationTests/Workflows/BasicWorkflow.cs new file mode 100644 index 0000000000..ad10171ea3 --- /dev/null +++ b/test/integration/Elsa.Core.IntegrationTests/Workflows/BasicWorkflow.cs @@ -0,0 +1,13 @@ +using Elsa.Activities.Console; +using Elsa.Builders; + +namespace Elsa.Core.IntegrationTests.Workflows +{ + public class BasicWorkflow : IWorkflow + { + public void Build(IWorkflowBuilder builder) + { + builder.WriteLine("Hello xUnit!"); + } + } +} \ No newline at end of file diff --git a/test/integration/Elsa.Core.IntegrationTests/Workflows/ForLoopWorkflow.cs b/test/integration/Elsa.Core.IntegrationTests/Workflows/ForLoopWorkflow.cs new file mode 100644 index 0000000000..a7157843e8 --- /dev/null +++ b/test/integration/Elsa.Core.IntegrationTests/Workflows/ForLoopWorkflow.cs @@ -0,0 +1,26 @@ +using Elsa.Activities.Console; +using Elsa.Activities.ControlFlow; +using Elsa.Builders; + +namespace Elsa.Core.IntegrationTests.Workflows +{ + public class ForLoopWorkflow : IWorkflow + { + private readonly int _loopCount; + + public ForLoopWorkflow(int loopCount) + { + _loopCount = loopCount; + } + + public void Build(IWorkflowBuilder builder) + { + builder.For( + 0, + _loopCount, + iterate => iterate + .Then(activity => activity.Set(x => x.Text, context => $"Iteration {context.Input}")) + .WithId("WriteLine")); + } + } +} \ No newline at end of file diff --git a/test/shared/Elsa.Testing.Shared/Autofixture/Abstractions/SpecimenBuilderBase.cs b/test/shared/Elsa.Testing.Shared/AutoFixture/Abstractions/SpecimenBuilderBase.cs similarity index 90% rename from test/shared/Elsa.Testing.Shared/Autofixture/Abstractions/SpecimenBuilderBase.cs rename to test/shared/Elsa.Testing.Shared/AutoFixture/Abstractions/SpecimenBuilderBase.cs index c74526c0ae..41ad09993e 100644 --- a/test/shared/Elsa.Testing.Shared/Autofixture/Abstractions/SpecimenBuilderBase.cs +++ b/test/shared/Elsa.Testing.Shared/AutoFixture/Abstractions/SpecimenBuilderBase.cs @@ -1,7 +1,7 @@ using System; using AutoFixture.Kernel; -namespace Elsa.Testing.Shared.Autofixture.Abstractions +namespace Elsa.Testing.Shared.AutoFixture.Abstractions { public abstract class SpecimenBuilderBase : ISpecimenBuilder { diff --git a/test/shared/Elsa.Testing.Shared/Autofixture/NodaTimeCustomization.cs b/test/shared/Elsa.Testing.Shared/AutoFixture/NodaTimeCustomization.cs similarity index 80% rename from test/shared/Elsa.Testing.Shared/Autofixture/NodaTimeCustomization.cs rename to test/shared/Elsa.Testing.Shared/AutoFixture/NodaTimeCustomization.cs index 753120a0c4..c169a39738 100644 --- a/test/shared/Elsa.Testing.Shared/Autofixture/NodaTimeCustomization.cs +++ b/test/shared/Elsa.Testing.Shared/AutoFixture/NodaTimeCustomization.cs @@ -1,7 +1,7 @@ using AutoFixture; -using Elsa.Testing.Shared.Autofixture.SpecimenBuilders; +using Elsa.Testing.Shared.AutoFixture.SpecimenBuilders; -namespace Elsa.Testing.Shared.Autofixture +namespace Elsa.Testing.Shared.AutoFixture { public class NodaTimeCustomization : ICustomization { diff --git a/test/shared/Elsa.Testing.Shared/Autofixture/SpecimenBuilders/DurationGenerator.cs b/test/shared/Elsa.Testing.Shared/AutoFixture/SpecimenBuilders/DurationGenerator.cs similarity index 73% rename from test/shared/Elsa.Testing.Shared/Autofixture/SpecimenBuilders/DurationGenerator.cs rename to test/shared/Elsa.Testing.Shared/AutoFixture/SpecimenBuilders/DurationGenerator.cs index 5e237f3401..d1be8f8200 100644 --- a/test/shared/Elsa.Testing.Shared/Autofixture/SpecimenBuilders/DurationGenerator.cs +++ b/test/shared/Elsa.Testing.Shared/AutoFixture/SpecimenBuilders/DurationGenerator.cs @@ -1,10 +1,10 @@ using System; using AutoFixture; using AutoFixture.Kernel; -using Elsa.Testing.Shared.Autofixture.Abstractions; +using Elsa.Testing.Shared.AutoFixture.Abstractions; using NodaTime; -namespace Elsa.Testing.Shared.Autofixture.SpecimenBuilders +namespace Elsa.Testing.Shared.AutoFixture.SpecimenBuilders { public class DurationGenerator : SpecimenBuilderBase { diff --git a/test/shared/Elsa.Testing.Shared/Autofixture/SpecimenBuilders/InstantGenerator.cs b/test/shared/Elsa.Testing.Shared/AutoFixture/SpecimenBuilders/InstantGenerator.cs similarity index 78% rename from test/shared/Elsa.Testing.Shared/Autofixture/SpecimenBuilders/InstantGenerator.cs rename to test/shared/Elsa.Testing.Shared/AutoFixture/SpecimenBuilders/InstantGenerator.cs index dc9db61eea..d2b77ecada 100644 --- a/test/shared/Elsa.Testing.Shared/Autofixture/SpecimenBuilders/InstantGenerator.cs +++ b/test/shared/Elsa.Testing.Shared/AutoFixture/SpecimenBuilders/InstantGenerator.cs @@ -1,10 +1,10 @@ using System; using AutoFixture; using AutoFixture.Kernel; -using Elsa.Testing.Shared.Autofixture.Abstractions; +using Elsa.Testing.Shared.AutoFixture.Abstractions; using NodaTime; -namespace Elsa.Testing.Shared.Autofixture.SpecimenBuilders +namespace Elsa.Testing.Shared.AutoFixture.SpecimenBuilders { public class InstantGenerator : SpecimenBuilderBase { diff --git a/test/shared/Elsa.Testing.Shared/Autofixture/SpecimenBuilders/LocalDateGenerator.cs b/test/shared/Elsa.Testing.Shared/AutoFixture/SpecimenBuilders/LocalDateGenerator.cs similarity index 72% rename from test/shared/Elsa.Testing.Shared/Autofixture/SpecimenBuilders/LocalDateGenerator.cs rename to test/shared/Elsa.Testing.Shared/AutoFixture/SpecimenBuilders/LocalDateGenerator.cs index 635dfcbbf9..136c246e96 100644 --- a/test/shared/Elsa.Testing.Shared/Autofixture/SpecimenBuilders/LocalDateGenerator.cs +++ b/test/shared/Elsa.Testing.Shared/AutoFixture/SpecimenBuilders/LocalDateGenerator.cs @@ -1,9 +1,9 @@ using System; using AutoFixture.Kernel; -using Elsa.Testing.Shared.Autofixture.Abstractions; +using Elsa.Testing.Shared.AutoFixture.Abstractions; using NodaTime; -namespace Elsa.Testing.Shared.Autofixture.SpecimenBuilders +namespace Elsa.Testing.Shared.AutoFixture.SpecimenBuilders { public class LocalDateGenerator : SpecimenBuilderBase { diff --git a/test/shared/Elsa.Testing.Shared/Autofixture/SpecimenBuilders/PeriodGenerator.cs b/test/shared/Elsa.Testing.Shared/AutoFixture/SpecimenBuilders/PeriodGenerator.cs similarity index 73% rename from test/shared/Elsa.Testing.Shared/Autofixture/SpecimenBuilders/PeriodGenerator.cs rename to test/shared/Elsa.Testing.Shared/AutoFixture/SpecimenBuilders/PeriodGenerator.cs index fa5279160b..9a1c2d4542 100644 --- a/test/shared/Elsa.Testing.Shared/Autofixture/SpecimenBuilders/PeriodGenerator.cs +++ b/test/shared/Elsa.Testing.Shared/AutoFixture/SpecimenBuilders/PeriodGenerator.cs @@ -1,10 +1,10 @@ using System; using AutoFixture; using AutoFixture.Kernel; -using Elsa.Testing.Shared.Autofixture.Abstractions; +using Elsa.Testing.Shared.AutoFixture.Abstractions; using NodaTime; -namespace Elsa.Testing.Shared.Autofixture.SpecimenBuilders +namespace Elsa.Testing.Shared.AutoFixture.SpecimenBuilders { public class PeriodGenerator : SpecimenBuilderBase { diff --git a/test/shared/Elsa.Testing.Shared/Elsa.Testing.Shared.csproj b/test/shared/Elsa.Testing.Shared/Elsa.Testing.Shared.csproj index 67a1408a27..483854b89b 100644 --- a/test/shared/Elsa.Testing.Shared/Elsa.Testing.Shared.csproj +++ b/test/shared/Elsa.Testing.Shared/Elsa.Testing.Shared.csproj @@ -1,7 +1,7 @@  - netstandard2.0 + netstandard2.1 latest 1.0.0 Elsa Contributors @@ -19,7 +19,10 @@ + + + @@ -29,4 +32,8 @@ + + + + diff --git a/test/unit/Elsa.Core.UnitTests/TemporaryFolder.cs b/test/shared/Elsa.Testing.Shared/Helpers/TemporaryFolder.cs similarity index 93% rename from test/unit/Elsa.Core.UnitTests/TemporaryFolder.cs rename to test/shared/Elsa.Testing.Shared/Helpers/TemporaryFolder.cs index b93355aa89..513e60145e 100644 --- a/test/unit/Elsa.Core.UnitTests/TemporaryFolder.cs +++ b/test/shared/Elsa.Testing.Shared/Helpers/TemporaryFolder.cs @@ -1,7 +1,7 @@ using System; using System.IO; -namespace Elsa.Core.UnitTests +namespace Elsa.Core.IntegrationTests.Helpers { public class TemporaryFolder : IDisposable { diff --git a/test/shared/Elsa.Testing.Shared/Helpers/WorkflowsUnitTestBase.cs b/test/shared/Elsa.Testing.Shared/Helpers/WorkflowsUnitTestBase.cs new file mode 100644 index 0000000000..e3bd8494a6 --- /dev/null +++ b/test/shared/Elsa.Testing.Shared/Helpers/WorkflowsUnitTestBase.cs @@ -0,0 +1,54 @@ +using System; +using System.Threading.Tasks; +using Elsa.Core.IntegrationTests.Helpers; +using Elsa.Services; +using Microsoft.Extensions.DependencyInjection; +using Xunit; +using Xunit.Abstractions; +using YesSql; +using YesSql.Provider.Sqlite; + +namespace Elsa.Testing.Shared.Helpers +{ + public abstract class WorkflowsUnitTestBase : IAsyncLifetime, IDisposable + { + private readonly TemporaryFolder _tempFolder; + + protected WorkflowsUnitTestBase(ITestOutputHelper testOutputHelper, Action? configureServices = default) + { + _tempFolder = new TemporaryFolder(); + TestOutputHelper = testOutputHelper; + + var services = new ServiceCollection() + .AddElsa(options => options.UsePersistence(config => ConfigurePersistence(config, _tempFolder.Folder))) + .AddConsoleActivities(Console.In, new XunitConsoleForwarder(testOutputHelper)); + + configureServices?.Invoke(services); + ServiceProvider = services.BuildServiceProvider(); + WorkflowHost = ServiceProvider.GetRequiredService(); + } + + protected ITestOutputHelper TestOutputHelper { get; } + protected ServiceProvider ServiceProvider { get; } + protected IWorkflowHost WorkflowHost { get; } + public virtual void Dispose() => _tempFolder.Dispose(); + + public virtual async Task InitializeAsync() + { + var startupRunner = ServiceProvider.GetRequiredService(); + await startupRunner.StartupAsync(); + } + + public virtual async Task DisposeAsync() + { + await ServiceProvider.DisposeAsync(); + Dispose(); + } + + private void ConfigurePersistence(IConfiguration configuration, string folder) + { + var connectionString = $@"Data Source={folder}elsa.db;Cache=Shared"; + configuration.UseSqLite(connectionString).UseDefaultIdGenerator(); + } + } +} \ No newline at end of file diff --git a/test/shared/Elsa.Testing.Shared/Helpers/XunitConsoleForwarder.cs b/test/shared/Elsa.Testing.Shared/Helpers/XunitConsoleForwarder.cs new file mode 100644 index 0000000000..6bf20f9666 --- /dev/null +++ b/test/shared/Elsa.Testing.Shared/Helpers/XunitConsoleForwarder.cs @@ -0,0 +1,44 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using Xunit.Abstractions; + +namespace Elsa.Core.IntegrationTests.Helpers +{ + public class XunitConsoleForwarder : TextWriter + { + private readonly ITestOutputHelper _output; + private IList _line = new List(); + public XunitConsoleForwarder(ITestOutputHelper output) => _output = output; + public override Encoding Encoding => Console.Out.Encoding; + + public override void Write(char value) + { + if (value == '\n') + { + FlushLine(); + _line = new List(); + return; + } + + _line.Add(value); + } + + protected override void Dispose(bool disposing) + { + if (_line.Count > 0) + FlushLine(); + base.Dispose(disposing); + } + + private void FlushLine() + { + if (_line.Count > 0 && _line.Last() == '\r') + _line.RemoveAt(_line.Count - 1); + + _output.WriteLine(new string(_line.ToArray())); + } + } +} \ No newline at end of file diff --git a/test/unit/Elsa.Core.UnitTests/WorkflowHostTests.cs b/test/unit/Elsa.Core.UnitTests/WorkflowHostTests.cs deleted file mode 100644 index 7b981619fa..0000000000 --- a/test/unit/Elsa.Core.UnitTests/WorkflowHostTests.cs +++ /dev/null @@ -1,120 +0,0 @@ -// using System; -// using System.Threading; -// using System.Threading.Tasks; -// using AutoFixture; -// using Elsa.ActivityResults; -// using Elsa.Expressions; -// using Elsa.Models; -// using Elsa.Services; -// using Elsa.Services.Models; -// using Elsa.Testing.Shared.Autofixture; -// using MediatR; -// using Microsoft.Extensions.DependencyInjection; -// using Microsoft.Extensions.Logging.Abstractions; -// using Moq; -// using NodaTime; -// using NodaTime.Testing; -// using Xunit; -// using YesSql; -// using YesSql.Provider.Sqlite; -// -// namespace Elsa.Core.UnitTests -// { -// public class WorkflowHostTests : IDisposable -// { -// private readonly IFixture _fixture; -// private readonly WorkflowHost _workflowHost; -// private TemporaryFolder _tempFolder; -// private ISession _session; -// -// public WorkflowHostTests() -// { -// _fixture = new Fixture().Customize(new NodaTimeCustomization()); -// _session = CreateSession(); -// -// var workflowActivatorMock = new Mock(); -// var workflowRegistryMock = new Mock(); -// var workflowInstanceManager = new WorkflowInstanceManager(_session); -// var workflowExpressionEvaluatorMock = new Mock(); -// var mediatorMock = new Mock(); -// var now = _fixture.Create(); -// var clock = new FakeClock(now); -// var logger = new NullLogger(); -// var serviceProvider = new ServiceCollection().BuildServiceProvider(); -// -// workflowActivatorMock -// .Setup(x => x.InstantiateAsync(It.IsAny(), It.IsAny(), It.IsAny())) -// .ReturnsAsync((WorkflowBlueprint workflow, string? correlationId, CancellationToken cancellationToken) => new WorkflowInstance()); -// -// _workflowHost = new WorkflowHost( -// workflowInstanceManager, -// workflowRegistryMock.Object, -// workflowActivatorMock.Object, -// workflowExpressionEvaluatorMock.Object, -// clock, -// mediatorMock.Object, -// serviceProvider, -// logger); -// } -// -// public void Dispose() => _session.Dispose(); -// -// private ISession CreateSession() -// { -// _tempFolder = new TemporaryFolder(); -// var connectionString = $@"Data Source={_tempFolder.Folder}elsa.db;Cache=Shared"; -// var config = new Configuration().UseSqLite(connectionString).UseDefaultIdGenerator(); -// var store = StoreFactory.CreateAndInitializeAsync(config).GetAwaiter().GetResult(); -// return store.CreateSession(); -// } -// -// [Fact(DisplayName = "Can run simple workflow to completed state.")] -// public async Task RunAsync01() -// { -// var activityExecutionResultMock = new Mock(); -// var activity = CreateActivity(activityExecutionResult: activityExecutionResultMock.Object); -// var workflow = CreateWorkflow(activity); -// var executionContext = await _workflowHost.RunWorkflowAsync(workflow); -// -// Assert.Equal(WorkflowStatus.Completed, executionContext.UpdateWorkflowInstance().Status); -// } -// -// [Fact(DisplayName = "Invokes returned activity execution result.")] -// public async Task RunAsync02() -// { -// var activityExecutionResultMock = new Mock(); -// var activity = CreateActivity(true, activityExecutionResultMock.Object); -// var workflow = CreateWorkflow(activity); -// var executionContext = await _workflowHost.RunWorkflowAsync(workflow); -// -// activityExecutionResultMock -// .Verify(x => x.ExecuteAsync(It.IsAny(), It.IsAny()), Times.Once); -// } -// -// private IActivity CreateActivity(bool canExecute = true, IActivityExecutionResult? activityExecutionResult = null) -// { -// var activityMock = new Mock(); -// var activityId = _fixture.Create(); -// -// activityMock.Setup(x => x.Id).Returns(activityId); -// -// activityMock -// .Setup(x => x.CanExecuteAsync(It.IsAny(), It.IsAny())) -// .ReturnsAsync(canExecute); -// -// if (activityExecutionResult != null) -// activityMock -// .Setup(x => x.ExecuteAsync(It.IsAny(), It.IsAny())) -// .ReturnsAsync(activityExecutionResult); -// -// return activityMock.Object; -// } -// -// private WorkflowBlueprint CreateWorkflow(IActivity activity) -// { -// var workflow = new WorkflowBlueprint(); -// workflow.Activities.Add(activity); -// return workflow; -// } -// } -// } \ No newline at end of file