private WorkflowInstanceAssert hasPayload( final Record<WorkflowInstanceRecordValue> record, String key, Object expectedValue) { final Map<String, Object> payload = record.getValue().getPayloadAsMap(); if (payload.containsKey(key)) { final Object value = payload.get(key); if (!expectedValue.equals(value)) { failWithMessage( "Expected payload value of <%s> to be <%s> but was <%s>", key, expectedValue, value); } } else { failWithMessage( "Expected payload <%s> to contain <%s> but could not find entry", payload, key); } return this; }
private WorkflowInstanceAssert hasPayload( final Record<WorkflowInstanceRecordValue> record, String key, Object expectedValue) { final Map<String, Object> payload = record.getValue().getPayloadAsMap(); if (payload.containsKey(key)) { final Object value = payload.get(key); if (!expectedValue.equals(value)) { failWithMessage( "Expected payload value of <%s> to be <%s> but was <%s>", key, expectedValue, value); } } else { failWithMessage( "Expected payload <%s> to contain <%s> but could not find entry", payload, key); } return this; }
@Test public void shouldApplyInputMappingOnReady() { // given testClient.deploy(WITHOUT_BOUNDARY_EVENTS); testClient.createWorkflowInstance(PROCESS_ID, "{ \"foo\": 1, \"boo\": 2 }"); // when final Record<WorkflowInstanceRecordValue> record = testClient.receiveElementInState("task", WorkflowInstanceIntent.ELEMENT_ACTIVATED); // then assertThat(record.getValue().getPayloadAsMap()).containsOnly(entry("bar", 1)); }
@Test public void shouldApplyInputMappingOnReady() { // given testClient.deploy(WITHOUT_BOUNDARY_EVENTS); testClient.createWorkflowInstance(PROCESS_ID, "{ \"foo\": 1, \"boo\": 2 }"); // when final Record<WorkflowInstanceRecordValue> record = testClient.receiveElementInState("task", WorkflowInstanceIntent.ELEMENT_ACTIVATED); // then assertThat(record.getValue().getPayloadAsMap()).containsOnly(entry("bar", 1)); }
@Test public void shouldCreateInstanceOnMessage() { // given final ExecuteCommandResponse response = testClient.deployWithResponse(createWorkflowWithOneMessageStartEvent()); final long workflowKey = getFirstDeployedWorkflowKey(response); // wait until subscription is opened assertThat( messageStartEventSubscriptionRecords(MessageStartEventSubscriptionIntent.OPENED) .exists()) .isTrue(); // when testClient.publishMessage(MESSAGE_NAME1, "order-123", asMsgPack("foo", "bar")); // then final List<Record<WorkflowInstanceRecordValue>> records = RecordingExporter.workflowInstanceRecords().limit(5).asList(); assertThat(records) .extracting(r -> r.getMetadata().getIntent()) .containsExactly( WorkflowInstanceIntent.EVENT_OCCURRED, // message WorkflowInstanceIntent.ELEMENT_READY, // workflow instance WorkflowInstanceIntent.ELEMENT_ACTIVATED, WorkflowInstanceIntent.EVENT_TRIGGERING, // start event WorkflowInstanceIntent.EVENT_TRIGGERED); assertThat(records).allMatch(r -> r.getValue().getWorkflowKey() == workflowKey); assertThat(records.get(3).getValue()).hasElementId(EVENT_ID1); final WorkflowInstanceRecordValue eventTriggeredRecord = records.get(4).getValue(); assertThat(eventTriggeredRecord.getPayloadAsMap()).containsEntry("foo", "bar"); }
@Test public void shouldApplyOutputMappingOnCompleting() { // given testClient.deploy(WITHOUT_BOUNDARY_EVENTS); testClient.createWorkflowInstance(PROCESS_ID, "{ \"foo\": 1, \"boo\": 2 }"); // when final Record<JobRecordValue> jobRecord = testClient.receiveFirstJobEvent(JobIntent.CREATED); testClient.completeJob(jobRecord.getKey(), jobRecord.getValue().getPayload()); // then final Record<WorkflowInstanceRecordValue> record = testClient.receiveElementInState("task", WorkflowInstanceIntent.ELEMENT_COMPLETED); assertThat(record.getValue().getPayloadAsMap()).contains(entry("oof", 1)); }
@Test public void shouldApplyOutputMappingOnCompleting() { // given testClient.deploy(WITHOUT_BOUNDARY_EVENTS); testClient.createWorkflowInstance(PROCESS_ID, "{ \"foo\": 1, \"boo\": 2 }"); // when final Record<JobRecordValue> jobRecord = testClient.receiveFirstJobEvent(JobIntent.CREATED); testClient.completeJob(jobRecord.getKey(), jobRecord.getValue().getPayload()); // then final Record<WorkflowInstanceRecordValue> record = testClient.receiveElementInState("task", WorkflowInstanceIntent.ELEMENT_COMPLETED); assertThat(record.getValue().getPayloadAsMap()).contains(entry("oof", 1)); }
@Test public void shouldCreateInstanceOnMessage() { // given final ExecuteCommandResponse response = testClient.deployWithResponse(createWorkflowWithOneMessageStartEvent()); final long workflowKey = getFirstDeployedWorkflowKey(response); // wait until subscription is opened assertThat( messageStartEventSubscriptionRecords(MessageStartEventSubscriptionIntent.OPENED) .exists()) .isTrue(); // when testClient.publishMessage(MESSAGE_NAME1, "order-123", asMsgPack("foo", "bar")); // then final List<Record<WorkflowInstanceRecordValue>> records = RecordingExporter.workflowInstanceRecords().limit(5).asList(); assertThat(records) .extracting(r -> r.getMetadata().getIntent()) .containsExactly( WorkflowInstanceIntent.EVENT_OCCURRED, // message WorkflowInstanceIntent.ELEMENT_ACTIVATING, // workflow instance WorkflowInstanceIntent.ELEMENT_ACTIVATED, WorkflowInstanceIntent.ELEMENT_ACTIVATING, // start event WorkflowInstanceIntent.ELEMENT_ACTIVATED); assertThat(records).allMatch(r -> r.getValue().getWorkflowKey() == workflowKey); assertThat(records.get(3).getValue()).hasElementId(EVENT_ID1); final WorkflowInstanceRecordValue eventTriggeredRecord = records.get(4).getValue(); assertThat(eventTriggeredRecord.getPayloadAsMap()).containsEntry("foo", "bar"); }
@Test public void shouldCorrelateMessageOnlyOnceIfEnteredBefore() { // given testClient.deploy(TWO_MESSAGES_WORKFLOW); testClient.createWorkflowInstance(PROCESS_ID, asMsgPack("key", "123")); // when assertThat( RecordingExporter.workflowInstanceSubscriptionRecords( WorkflowInstanceSubscriptionIntent.OPENED) .exists()) .isTrue(); testClient.publishMessage("ping", "123", asMsgPack("nr", 1)); assertThat( RecordingExporter.workflowInstanceSubscriptionRecords( WorkflowInstanceSubscriptionIntent.OPENED) .limit(2) .count()) .isEqualTo(2); testClient.publishMessage("ping", "123", asMsgPack("nr", 2)); // then assertThat( RecordingExporter.workflowInstanceRecords(WorkflowInstanceIntent.ELEMENT_COMPLETED) .filter(r -> r.getValue().getElementId().startsWith("message")) .limit(2) .asList()) .extracting( r -> tuple(r.getValue().getElementId(), r.getValue().getPayloadAsMap().get("nr"))) .contains(tuple("message1", 1), tuple("message2", 2)); }
@Test public void shouldCorrelateOnlyOneMessagePerCatchElement() { // given testClient.deploy(TWO_MESSAGES_WORKFLOW); testClient.createWorkflowInstance(PROCESS_ID, asMsgPack("key", "123")); assertThat( RecordingExporter.workflowInstanceSubscriptionRecords( WorkflowInstanceSubscriptionIntent.OPENED) .exists()) .isTrue(); // when testClient.publishMessage("ping", "123", asMsgPack("nr", 1)); testClient.publishMessage("ping", "123", asMsgPack("nr", 2)); // then assertThat( RecordingExporter.workflowInstanceRecords(WorkflowInstanceIntent.ELEMENT_COMPLETED) .filter(r -> r.getValue().getElementId().startsWith("message")) .limit(2) .asList()) .extracting( r -> tuple(r.getValue().getElementId(), r.getValue().getPayloadAsMap().get("nr"))) .contains(tuple("message1", 1), tuple("message2", 2)); }
@Test public void shouldCorrelateMessageOnlyOnceIfEnteredBefore() { // given testClient.deploy(TWO_MESSAGES_WORKFLOW); testClient.createWorkflowInstance(PROCESS_ID, asMsgPack("key", "123")); // when assertThat( RecordingExporter.workflowInstanceSubscriptionRecords( WorkflowInstanceSubscriptionIntent.OPENED) .exists()) .isTrue(); testClient.publishMessage("ping", "123", asMsgPack("nr", 1)); assertThat( RecordingExporter.workflowInstanceSubscriptionRecords( WorkflowInstanceSubscriptionIntent.OPENED) .limit(2) .count()) .isEqualTo(2); testClient.publishMessage("ping", "123", asMsgPack("nr", 2)); // then assertThat( RecordingExporter.workflowInstanceRecords(WorkflowInstanceIntent.EVENT_TRIGGERED) .filter(r -> r.getValue().getElementId().startsWith("message")) .limit(2) .asList()) .extracting( r -> tuple(r.getValue().getElementId(), r.getValue().getPayloadAsMap().get("nr"))) .contains(tuple("message1", 1), tuple("message2", 2)); }
@Test public void shouldCorrelateOnlyOneMessagePerCatchElement() { // given testClient.deploy(TWO_MESSAGES_WORKFLOW); testClient.createWorkflowInstance(PROCESS_ID, asMsgPack("key", "123")); assertThat( RecordingExporter.workflowInstanceSubscriptionRecords( WorkflowInstanceSubscriptionIntent.OPENED) .exists()) .isTrue(); // when testClient.publishMessage("ping", "123", asMsgPack("nr", 1)); testClient.publishMessage("ping", "123", asMsgPack("nr", 2)); // then assertThat( RecordingExporter.workflowInstanceRecords(WorkflowInstanceIntent.EVENT_TRIGGERED) .filter(r -> r.getValue().getElementId().startsWith("message")) .limit(2) .asList()) .extracting( r -> tuple(r.getValue().getElementId(), r.getValue().getPayloadAsMap().get("nr"))) .contains(tuple("message1", 1), tuple("message2", 2)); }
@Test public void shouldCorrelateMessageOnlyOnceIfPublishedBefore() { // given testClient.deploy(TWO_MESSAGES_WORKFLOW); testClient.publishMessage("ping", "123", asMsgPack("nr", 1)); testClient.publishMessage("ping", "123", asMsgPack("nr", 2)); // when testClient.createWorkflowInstance(PROCESS_ID, asMsgPack("key", "123")); // then assertThat( RecordingExporter.workflowInstanceRecords(WorkflowInstanceIntent.EVENT_TRIGGERED) .filter(r -> r.getValue().getElementId().startsWith("message")) .limit(2) .asList()) .extracting( r -> tuple(r.getValue().getElementId(), r.getValue().getPayloadAsMap().get("nr"))) .contains(tuple("message1", 1), tuple("message2", 2)); }
@Test public void shouldCorrelateMessageOnlyOnceIfPublishedBefore() { // given testClient.deploy(TWO_MESSAGES_WORKFLOW); testClient.publishMessage("ping", "123", asMsgPack("nr", 1)); testClient.publishMessage("ping", "123", asMsgPack("nr", 2)); // when testClient.createWorkflowInstance(PROCESS_ID, asMsgPack("key", "123")); // then assertThat( RecordingExporter.workflowInstanceRecords(WorkflowInstanceIntent.ELEMENT_COMPLETED) .filter(r -> r.getValue().getElementId().startsWith("message")) .limit(2) .asList()) .extracting( r -> tuple(r.getValue().getElementId(), r.getValue().getPayloadAsMap().get("nr"))) .contains(tuple("message1", 1), tuple("message2", 2)); }
@Test public void shouldCorrelateMessageOnDifferentPartitions() { // given apiRule .partitionClient(0) .publishMessage("message", CORRELATION_KEY_PARTITION_0, asMsgPack("p", "p0")); apiRule .partitionClient(1) .publishMessage("message", CORRELATION_KEY_PARTITION_1, asMsgPack("p", "p1")); apiRule .partitionClient(2) .publishMessage("message", CORRELATION_KEY_PARTITION_2, asMsgPack("p", "p2")); // when testClient.createWorkflowInstance(PROCESS_ID, asMsgPack("key", CORRELATION_KEY_PARTITION_0)); testClient.createWorkflowInstance(PROCESS_ID, asMsgPack("key", CORRELATION_KEY_PARTITION_1)); testClient.createWorkflowInstance(PROCESS_ID, asMsgPack("key", CORRELATION_KEY_PARTITION_2)); // then final List<Record<WorkflowInstanceRecordValue>> events = RecordingExporter.workflowInstanceRecords(WorkflowInstanceIntent.ELEMENT_COMPLETED) .withElementId("receive-message") .limit(3) .collect(Collectors.toList()); assertThat(events) .extracting(r -> r.getValue().getPayloadAsMap().get("p")) .contains("p0", "p1", "p2"); }
.limit(2) .asList()) .extracting(r -> r.getValue().getPayloadAsMap().get("nr")) .contains(1, 2);
.extracting(e -> e.getValue().getPayloadAsMap().get("foo")) .contains("0", "1", "2");
@Test public void shouldCorrelateMessageOnDifferentPartitions() { // given apiRule .partitionClient(0) .publishMessage("message", CORRELATION_KEY_PARTITION_0, asMsgPack("p", "p0")); apiRule .partitionClient(1) .publishMessage("message", CORRELATION_KEY_PARTITION_1, asMsgPack("p", "p1")); apiRule .partitionClient(2) .publishMessage("message", CORRELATION_KEY_PARTITION_2, asMsgPack("p", "p2")); // when testClient.createWorkflowInstance(PROCESS_ID, asMsgPack("key", CORRELATION_KEY_PARTITION_0)); testClient.createWorkflowInstance(PROCESS_ID, asMsgPack("key", CORRELATION_KEY_PARTITION_1)); testClient.createWorkflowInstance(PROCESS_ID, asMsgPack("key", CORRELATION_KEY_PARTITION_2)); // then assertThat( RecordingExporter.workflowInstanceRecords(WorkflowInstanceIntent.EVENT_TRIGGERED) .withElementId("receive-message") .limit(3)) .extracting(r -> r.getValue().getPayloadAsMap().get("p")) .contains("p0", "p1", "p2"); }
@Test public void shouldUseScopePayloadWhenApplyingOutputMappings() { // given final BpmnModelInstance workflow = Bpmn.createExecutableProcess(PROCESS_ID) .startEvent() .serviceTask("task", b -> b.zeebeTaskType("type").zeebeInput("$.oof", "$.baz")) .boundaryEvent("timer") .cancelActivity(true) .timerWithDuration("PT1S") .zeebeOutputBehavior(ZeebeOutputBehavior.merge) .endEvent("endTimer") .moveToActivity("task") .endEvent() .done(); testClient.deploy(workflow); testClient.createWorkflowInstance(PROCESS_ID, "{\"foo\": 1, \"oof\": 2}"); // when testClient.receiveTimerRecord("timer", TimerIntent.CREATED); brokerRule.getClock().addTime(Duration.ofMinutes(1)); awaitProcessCompleted(); // then final Record<WorkflowInstanceRecordValue> boundaryTriggered = testClient.receiveElementInState("timer", WorkflowInstanceIntent.EVENT_TRIGGERED); assertThat(boundaryTriggered.getValue().getPayloadAsMap()) .contains(entry("foo", 1), entry("oof", 2)); }
@Test public void shouldUseScopePayloadWhenApplyingOutputMappings() { // given final BpmnModelInstance workflow = Bpmn.createExecutableProcess(PROCESS_ID) .startEvent() .serviceTask("task", b -> b.zeebeTaskType("type").zeebeInput("$.oof", "$.baz")) .boundaryEvent("timer") .cancelActivity(true) .timerWithDuration("PT1S") .zeebeOutputBehavior(ZeebeOutputBehavior.merge) .endEvent("endTimer") .moveToActivity("task") .endEvent() .done(); testClient.deploy(workflow); testClient.createWorkflowInstance(PROCESS_ID, "{\"foo\": 1, \"oof\": 2}"); // when testClient.receiveTimerRecord("timer", TimerIntent.CREATED); brokerRule.getClock().addTime(Duration.ofMinutes(1)); awaitProcessCompleted(); // then final Record<WorkflowInstanceRecordValue> boundaryTriggered = testClient.receiveElementInState("timer", WorkflowInstanceIntent.ELEMENT_COMPLETED); assertThat(boundaryTriggered.getValue().getPayloadAsMap()) .contains(entry("foo", 1), entry("oof", 2)); }