Skip to content

Commit

Permalink
Merge pull request #641 from camunda-community-hub/dimasm61-main
Browse files Browse the repository at this point in the history
Add ModifyProcessInstance to client
  • Loading branch information
ChrisKujawa authored Jan 29, 2024
2 parents b28ac1f + 3281d3f commit c315aff
Show file tree
Hide file tree
Showing 9 changed files with 528 additions and 1 deletion.
2 changes: 1 addition & 1 deletion Client.UnitTests/Client.UnitTests.csproj
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFrameworks>net6.0;net7.0</TargetFrameworks>
<TargetFrameworks>net6.0;net7.0;net8.0</TargetFrameworks>
<RootNamespace>Zeebe.Client</RootNamespace>
</PropertyGroup>

Expand Down
6 changes: 6 additions & 0 deletions Client.UnitTests/GatewayTestService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ public GatewayTestService()
typedRequestHandler.Add(typeof(ResolveIncidentRequest), request => new ResolveIncidentResponse());
typedRequestHandler.Add(typeof(CreateProcessInstanceWithResultRequest), request => new CreateProcessInstanceWithResultResponse());
typedRequestHandler.Add(typeof(EvaluateDecisionRequest), request => new EvaluateDecisionResponse());
typedRequestHandler.Add(typeof(ModifyProcessInstanceRequest), request => new ModifyProcessInstanceResponse());

foreach (var pair in typedRequestHandler)
{
Expand Down Expand Up @@ -150,6 +151,11 @@ public override Task<EvaluateDecisionResponse> EvaluateDecision(EvaluateDecision
return Task.FromResult((EvaluateDecisionResponse)HandleRequest(request, context));
}

public override Task<ModifyProcessInstanceResponse> ModifyProcessInstance(ModifyProcessInstanceRequest request, ServerCallContext context)
{
return Task.FromResult((ModifyProcessInstanceResponse)HandleRequest(request, context));
}

public delegate void ConsumeMetadata(Metadata metadata);

public void ConsumeRequestHeaders(ConsumeMetadata consumer)
Expand Down
276 changes: 276 additions & 0 deletions Client.UnitTests/ModifyProcessInstanceTest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,276 @@
using System.Collections.Generic;
using System.Threading.Tasks;
using GatewayProtocol;
using NUnit.Framework;

namespace Zeebe.Client;

[TestFixture]
public class ModifyProcessInstanceTest : BaseZeebeTest
{
private const long TestProcessInstanceKey = 1234567890;
private const long TestAncestorElementInstanceKey = 2345678900;
private const long TestElementInstanceKey = 3456789000;
private const string TestElementId = "element1";
private const string TestVariables = "variable1";
private const string TestScopeId = "scope1";

[Test]
public async Task ShouldSendRequestAsExpectedWithActivateElement()
{
// given
var expectedRequest = new ModifyProcessInstanceRequest
{
ProcessInstanceKey = TestProcessInstanceKey,
ActivateInstructions =
{
new ModifyProcessInstanceRequest.Types.ActivateInstruction
{
ElementId = TestElementId,
AncestorElementInstanceKey = 0
}
}
};

// when
await ZeebeClient.NewModifyProcessInstanceCommand(processInstanceKey: TestProcessInstanceKey)
.ActivateElement(elementId: TestElementId)
.Send();

// then
var request = TestService.Requests[typeof(ModifyProcessInstanceRequest)][0];
var typedRequest = request as ModifyProcessInstanceRequest;
Assert.NotNull(typedRequest);
Assert.AreEqual(expectedRequest, typedRequest);
}

[Test]
public async Task ShouldSendRequestAsExpectedWithActivateElementWithAncestor()
{
// given
var expectedRequest = new ModifyProcessInstanceRequest
{
ProcessInstanceKey = TestProcessInstanceKey,
ActivateInstructions =
{
new ModifyProcessInstanceRequest.Types.ActivateInstruction
{
ElementId = TestElementId,
AncestorElementInstanceKey = TestAncestorElementInstanceKey
}
}
};

// when
await ZeebeClient.NewModifyProcessInstanceCommand(processInstanceKey: TestProcessInstanceKey)
.ActivateElement(elementId: TestElementId, ancestorElementInstanceKey: TestAncestorElementInstanceKey)
.Send();

// then
var request = TestService.Requests[typeof(ModifyProcessInstanceRequest)][0];
var typedRequest = request as ModifyProcessInstanceRequest;
Assert.NotNull(typedRequest);
Assert.AreEqual(expectedRequest, typedRequest);
}

[Test]
public async Task ShouldSendRequestAsExpectedWithTerminateElement()
{
// given
var expectedRequest = new ModifyProcessInstanceRequest
{
ProcessInstanceKey = TestProcessInstanceKey,
TerminateInstructions =
{
new ModifyProcessInstanceRequest.Types.TerminateInstruction()
{
ElementInstanceKey = TestElementInstanceKey
}
}
};

// when
await ZeebeClient.NewModifyProcessInstanceCommand(processInstanceKey: TestProcessInstanceKey)
.TerminateElement(TestElementInstanceKey)
.Send();

// then
var request = TestService.Requests[typeof(ModifyProcessInstanceRequest)][0];
var typedRequest = request as ModifyProcessInstanceRequest;
Assert.NotNull(typedRequest);
Assert.AreEqual(expectedRequest, typedRequest);
}

[Test]
public async Task ShouldSendRequestWithActivateAndTerminate()
{
// given
var expectedRequest = new ModifyProcessInstanceRequest
{
ProcessInstanceKey = TestProcessInstanceKey,
ActivateInstructions =
{
new ModifyProcessInstanceRequest.Types.ActivateInstruction
{
ElementId = TestElementId,
AncestorElementInstanceKey = TestAncestorElementInstanceKey
}
},
TerminateInstructions =
{
new ModifyProcessInstanceRequest.Types.TerminateInstruction()
{
ElementInstanceKey = TestElementInstanceKey
}
}
};

// when
await ZeebeClient.NewModifyProcessInstanceCommand(processInstanceKey: TestProcessInstanceKey)
.ActivateElement(elementId: TestElementId, ancestorElementInstanceKey: TestAncestorElementInstanceKey)
.And()
.TerminateElement(elementInstanceKey: TestElementInstanceKey)
.Send();

// then
var request = TestService.Requests[typeof(ModifyProcessInstanceRequest)][0];
var typedRequest = request as ModifyProcessInstanceRequest;
Assert.NotNull(typedRequest);
Assert.AreEqual(expectedRequest, typedRequest);
}

[Test]
public async Task ShouldSendRequestWithActivateAndTerminateMultiple()
{
// given
var expectedRequest = new ModifyProcessInstanceRequest
{
ProcessInstanceKey = TestProcessInstanceKey,
ActivateInstructions =
{
new ModifyProcessInstanceRequest.Types.ActivateInstruction
{
ElementId = TestElementId,
AncestorElementInstanceKey = TestAncestorElementInstanceKey
},
new ModifyProcessInstanceRequest.Types.ActivateInstruction
{
ElementId = TestElementId + "2",
AncestorElementInstanceKey = TestAncestorElementInstanceKey + 1
}
},
TerminateInstructions =
{
new ModifyProcessInstanceRequest.Types.TerminateInstruction()
{
ElementInstanceKey = TestElementInstanceKey
},
new ModifyProcessInstanceRequest.Types.TerminateInstruction()
{
ElementInstanceKey = TestElementInstanceKey + 1
}
}
};

// when
await ZeebeClient.NewModifyProcessInstanceCommand(processInstanceKey: TestProcessInstanceKey)
.ActivateElement(elementId: TestElementId, ancestorElementInstanceKey: TestAncestorElementInstanceKey)
.And()
.TerminateElement(elementInstanceKey: TestElementInstanceKey)
.And()
.ActivateElement(elementId: TestElementId + "2",
ancestorElementInstanceKey: TestAncestorElementInstanceKey + 1)
.And()
.TerminateElement(TestElementInstanceKey + 1)
.Send();

// then
var request = TestService.Requests[typeof(ModifyProcessInstanceRequest)][0];
var typedRequest = request as ModifyProcessInstanceRequest;
Assert.NotNull(typedRequest);
Assert.AreEqual(expectedRequest, typedRequest);
}

[Test]
public async Task ShouldSendRequestWithActivateElementIdAndVariableInstructions()
{
// given
var expectedRequest = new ModifyProcessInstanceRequest
{
ProcessInstanceKey = TestProcessInstanceKey,
ActivateInstructions =
{
new ModifyProcessInstanceRequest.Types.ActivateInstruction
{
ElementId = TestElementId,
AncestorElementInstanceKey = 0,
VariableInstructions =
{
new List<ModifyProcessInstanceRequest.Types.VariableInstruction>
{
new () { Variables = TestVariables, ScopeId = TestScopeId }
}
}
}
}
};

// when
await ZeebeClient.NewModifyProcessInstanceCommand(processInstanceKey: TestProcessInstanceKey)
.ActivateElement(elementId: TestElementId)
.WithVariables(TestVariables, TestScopeId)
.Send();

// then
var request = TestService.Requests[typeof(ModifyProcessInstanceRequest)][0];
var typedRequest = request as ModifyProcessInstanceRequest;
Assert.NotNull(typedRequest);
Assert.AreEqual(expectedRequest, typedRequest);
}

[Test]
public async Task ShouldSendRequestWithActivateElementIdVariableAndTerminateInstructions()
{
// given
var expectedRequest = new ModifyProcessInstanceRequest
{
ProcessInstanceKey = TestProcessInstanceKey,
ActivateInstructions =
{
new ModifyProcessInstanceRequest.Types.ActivateInstruction
{
ElementId = TestElementId,
AncestorElementInstanceKey = TestAncestorElementInstanceKey,
VariableInstructions =
{
new List<ModifyProcessInstanceRequest.Types.VariableInstruction>
{
new () { Variables = TestVariables, ScopeId = TestScopeId }
}
}
}
},
TerminateInstructions =
{
new ModifyProcessInstanceRequest.Types.TerminateInstruction()
{
ElementInstanceKey = TestElementInstanceKey
}
}
};

// when
await ZeebeClient.NewModifyProcessInstanceCommand(processInstanceKey: TestProcessInstanceKey)
.ActivateElement(TestElementId, TestAncestorElementInstanceKey)
.WithVariables(TestVariables, TestScopeId)
.And()
.TerminateElement(elementInstanceKey: TestElementInstanceKey)
.Send();

// then
var request = TestService.Requests[typeof(ModifyProcessInstanceRequest)][0];
var typedRequest = request as ModifyProcessInstanceRequest;
Assert.NotNull(typedRequest);
Assert.AreEqual(expectedRequest, typedRequest);
}
}
75 changes: 75 additions & 0 deletions Client/Api/Commands/IModifyProcessInstanceCommandStep1.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
using Zeebe.Client.Api.Responses;

namespace Zeebe.Client.Api.Commands;

/// <summary>
/// Command to modify a process instance.
/// </summary>
public interface IModifyProcessInstanceCommandStep1
{
/// <summary>
/// Create an activate Instruction
/// for the given element id. The element will be created within an existing element instance of
/// the flow scope. When activating an element inside a multi-instance element the element instance
/// key of the ancestor must be defined. For this use <see cref="ActivateElement(string, long)"/>.
/// </summary>
/// <param name="elementId">The id of the element to activate.</param>
/// <returns>The builder for this command.</returns>
IModifyProcessInstanceCommandStep3 ActivateElement(string elementId);

/// <summary>
/// Create an activate Instruction
/// for the given element id. The element will be created within the scope that is passed. This
/// scope must be an ancestor of the element that's getting activated.
/// </summary>
/// <param name="elementId">The id of the element to activate.</param>
/// <param name="ancestorElementInstanceKey">The element instance key in which the element will be created.</param>
/// <returns>The builder for this command.</returns>
IModifyProcessInstanceCommandStep3 ActivateElement(string elementId, long ancestorElementInstanceKey);


/// <summary>
/// Create a terminate instruction for the given element id.
/// </summary>
/// <param name="elementInstanceKey">The element instance key of the element to terminate.</param>
/// <returns>the builder for this command.</returns>
IModifyProcessInstanceCommandStep2 TerminateElement(long elementInstanceKey);
}

/// <summary>
/// Second command step, to optional add more instructions to activate or terminate.
/// </summary>
public interface IModifyProcessInstanceCommandStep2 :
IFinalCommandWithRetryStep<IModifyProcessInstanceResponse>
{
/// <summary>
/// Acts as a boundary between the different activate and terminate instructions. Use this if you
/// want to activate or terminate another element.
/// Otherwise, use <see cref="IFinalCommandWithRetryStep{T}.SendWithRetry"/> to send the command.
/// </summary>
/// <returns>The builder for this command.</returns>
IModifyProcessInstanceCommandStep1 And();
}

/// <summary>
/// Third command step, to optionally add variables to the element which should be activated.
/// </summary>
public interface IModifyProcessInstanceCommandStep3 : IModifyProcessInstanceCommandStep2
{
/// <summary>
/// Create a variable instruction for the element that's getting activated.
/// These variables will be created in the global scope of the process instance.
/// </summary>
/// <param name="variables">The variables JSON document as String.</param>
/// <returns>The builder for this command.</returns>
IModifyProcessInstanceCommandStep3 WithVariables(string variables);

/// <summary>
/// Create a variable instruction for the element that's getting activated.
/// These variables will be created in the scope of the passed element.
/// </summary>
/// <param name="variables">The variables JSON document as String.</param>
/// <param name="scopeId">The id of the element in which scope the variables should be created.</param>
/// <returns>The builder for this command.</returns>
IModifyProcessInstanceCommandStep3 WithVariables(string variables, string scopeId);
}
8 changes: 8 additions & 0 deletions Client/Api/Responses/IModifyProcessInstanceResponse.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
namespace Zeebe.Client.Api.Responses;

/// <summary>
/// Response on a process instance to modification.
/// </summary>
public interface IModifyProcessInstanceResponse
{
}
Loading

0 comments on commit c315aff

Please sign in to comment.