diff --git a/.github/release-notes.yml b/.github/release-notes.yml new file mode 100644 index 0000000..1686110 --- /dev/null +++ b/.github/release-notes.yml @@ -0,0 +1,14 @@ +changelog: + sections: + - title: ":rocket: Enhancements & Features" + labels: [ "Type: enhancement", "Type: documentation", "Type: example" ] + - title: ":bug: Bug Fixes" + labels: [ "Type: bug" ] + - title: ":hammer_and_wrench: Chore" + labels: [ "Type: dependencies" ] + issues: + exclude: + labels: [ "Type: Incorrect Repository", "Type: question" ] + contributors: + exclude: + names: [ "dependabot[bot]", "codacy-badger" ] diff --git a/.github/workflows/default.yml b/.github/workflows/default.yml index b1ba557..9533dd1 100644 --- a/.github/workflows/default.yml +++ b/.github/workflows/default.yml @@ -38,7 +38,3 @@ jobs: - name: Build with Maven run: ./mvnw clean verify -U -B -T4 - - name: Upolad coverage information - uses: codecov/codecov-action@v1 - with: - token: ${{ secrets.CODECOV_TOKEN }} diff --git a/.github/workflows/master.yml b/.github/workflows/master.yml index 7da8d23..9b710ec 100644 --- a/.github/workflows/master.yml +++ b/.github/workflows/master.yml @@ -46,8 +46,3 @@ jobs: env: OSS_CENTRAL_USERNAME: ${{ secrets.SONATYPE_USERNAME }} OSS_CENTRAL_PASSWORD: ${{ secrets.SONATYPE_PASSWORD }} - - - name: Upolad coverage information - uses: codecov/codecov-action@v1 - with: - token: ${{ secrets.CODECOV_TOKEN }} diff --git a/.github/workflows/release-notes.yml b/.github/workflows/release-notes.yml new file mode 100644 index 0000000..5e7360d --- /dev/null +++ b/.github/workflows/release-notes.yml @@ -0,0 +1,33 @@ +# Trigger the workflow on milestone events +on: + milestone: + types: [closed] +name: Milestone Closure +jobs: + create-release-notes: + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@master + - name: Create Release Notes Markdown + uses: docker://decathlon/release-notes-generator-action:3.1.5 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # This token is provided by Actions, you do not need to create your own token + OUTPUT_FOLDER: temp_release_notes + USE_MILESTONE_TITLE: "true" + - name: Get the name of the created Release Notes file and extract Version + run: | + RELEASE_NOTES_FILE=$(ls temp_release_notes/*.md | head -n 1) + echo "RELEASE_NOTES_FILE=$RELEASE_NOTES_FILE" >> $GITHUB_ENV + VERSION=$(echo ${{ github.event.milestone.title }} | cut -d' ' -f2) + echo "VERSION=$VERSION" >> $GITHUB_ENV + - name: Create a Draft Release Notes on GitHub + id: create_release + uses: actions/create-release@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # This token is provided by Actions, you do not need to create your own token + with: + tag_name: ${{ env.VERSION }} + release_name: ${{ env.VERSION }} + body_path: ${{ env.RELEASE_NOTES_FILE }} + draft: true diff --git a/README.md b/README.md index d5c7f91..bf10486 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,6 @@ Camunda specific stages and scenarios for the BDD testing tool JGiven written in [![Development braches](https://github.com/holunda-io/camunda-bpm-jgiven/workflows/Development%20braches/badge.svg)](https://github.com/holunda-io/camunda-bpm-jgiven/workflows) [![Maven Central](https://maven-badges.herokuapp.com/maven-central/io.holunda.testing/camunda-bpm-jgiven/badge.svg)](https://maven-badges.herokuapp.com/maven-central/io.holunda.testing/camunda-bpm-jgiven) -[![codecov](https://codecov.io/gh/holunda-io/camunda-bpm-jgiven/branch/master/graph/badge.svg)](https://codecov.io/gh/holunda-io/camunda-bpm-jgiven) [![Project Stats](https://www.openhub.net/p/camunda-bpm-jgiven/widgets/project_thin_badge.gif)](https://www.openhub.net/p/camunda-bpm-jgiven) @@ -14,24 +13,25 @@ Starting from 2012, we are preaching that processes are no units. Behavior-drive underlying testing methodology of scenario-based testing is a way more adequate and convenient for writing process (model) tests. -Our first attempts addressed testing frameworks Cucumber and JBehave. For JBehave we were even able to release -an official [Camunda BPM extension](https://github.com/camunda/camunda-bpm-jbehave). It turned out that the main problem -in using it, was error-prone writing of the test specifications in Gherkin and glue code in Java. +Our first attempts addressed testing frameworks Cucumber and JBehave. For JBehave we were able to release +an official [Camunda BPM extension](https://github.com/camunda/camunda-bpm-jbehave), but it turned out that the main problem +in using it, was error-prone writing of the test specifications in Gherkin (text files) and glue code them with Java. This is, where [JGiven](http://jgiven.org/) comes on the scene, allowing to write both in Java or any other JVM language -by providing a nice API and later generating reports which are human readable. +by providing a nice API and later generating reports which are human-readable. ## Usage Add the following dependency to your Maven pom: - - io.holunda.testing - camunda-bpm-jgiven - 0.0.7 - test - - +```xml + + io.holunda.testing + camunda-bpm-jgiven + 0.2.0 + test + +``` ## Features JGiven supports separation of the glue code (application driver) into so-called [stages](http://jgiven.org/userguide/#_stages_and_state_sharing). @@ -39,60 +39,113 @@ Stages contain assert and action methods and may be subclassed. This library pro `ProcessStage` for building your process testing stages. Here is how the test then looks like (written in Kotlin): +### JUnit4 + +```kotlin +@Deployment(resources = [ApprovalProcessBean.RESOURCE]) +open class ApprovalProcessTest : ScenarioTest() { + + @get: Rule + val rule: ProcessEngineRule = StandaloneInMemoryTestConfiguration().rule() + + @ScenarioState + val camunda = rule.processEngine + @Test - fun `should automatically approve`() { - - val approvalRequestId = UUID.randomUUID().toString() - - given() - .process_is_deployed(ApprovalProcessBean.KEY) - .and() - .process_is_started_for_request(approvalRequestId) - .and() - .approval_strategy_can_be_applied(Expressions.ApprovalStrategy.AUTOMATIC) - .and() - .automatic_approval_returns(Expressions.ApprovalDecision.APPROVE) - - whenever() - .process_continues() - - then() - .process_is_finished() - .and() - .process_has_passed(Elements.SERVICE_AUTO_APPROVE, Elements.END_APPROVED) - + internal fun `should automatically approve`() { + + val approvalRequestId = UUID.randomUUID().toString() + + GIVEN + .process_is_deployed(ApprovalProcessBean.KEY) + .AND + .process_is_started_for_request(approvalRequestId) + .AND + .approval_strategy_can_be_applied(Expressions.ApprovalStrategy.AUTOMATIC) + .AND + .automatic_approval_returns(Expressions.ApprovalDecision.APPROVE) + + WHEN + .process_continues() + + THEN + .process_is_finished() + .AND + .process_has_passed(Elements.SERVICE_AUTO_APPROVE, Elements.END_APPROVED) + } +} +``` + +### JUnit5 + +```kotlin +@ExtendWith(ProcessEngineExtension::class) +@Deployment(resources = [ApprovalProcessBean.RESOURCE]) +internal class ApprovalProcessTest : + ScenarioTest() { + + @RegisterExtension + val extension = TestProcessEngine.DEFAULT + + @ScenarioState + val camunda = extension.processEngine + + @Test + internal fun `should automatically approve`() { + + val approvalRequestId = UUID.randomUUID().toString() + + GIVEN + .process_is_deployed(ApprovalProcessBean.KEY) + .AND + .process_is_started_for_request(approvalRequestId) + .AND + .approval_strategy_can_be_applied(Expressions.ApprovalStrategy.AUTOMATIC) + .AND + .automatic_approval_returns(Expressions.ApprovalDecision.APPROVE) + + WHEN + .process_continues() + + THEN + .process_is_finished() + .AND + .process_has_passed(Elements.SERVICE_AUTO_APPROVE, Elements.END_APPROVED) -And here is the corresponding stage: - - open class ApprovalProcessActionStage : ProcessStage() { - - @BeforeStage - open fun `automock all delegates`() { - CamundaMockito.registerJavaDelegateMock(DETERMINE_APPROVAL_STRATEGY) - CamundaMockito.registerJavaDelegateMock(AUTOMATICALLY_APPROVE_REQUEST) - CamundaMockito.registerJavaDelegateMock(ApprovalProcessBean.Expressions.LOAD_APPROVAL_REQUEST) - } - - open fun process_is_started_for_request(approvalRequestId: String): ApprovalProcessActionStage { - processInstanceSupplier = ApprovalProcessBean(camunda.processEngine) - processInstanceSupplier.start(approvalRequestId) - assertThat(processInstanceSupplier.processInstance).isNotNull - assertThat(processInstanceSupplier.processInstance).isStarted - return self() - } - - fun approval_strategy_can_be_applied(approvalStrategy: String): ApprovalProcessActionStage { - getJavaDelegateMock(DETERMINE_APPROVAL_STRATEGY).onExecutionSetVariables(Variables.putValue(APPROVAL_STRATEGY, approvalStrategy)) - return self() - } - - fun automatic_approval_returns(approvalDecision: String): ApprovalProcessActionStage { - getJavaDelegateMock(AUTOMATICALLY_APPROVE_REQUEST).onExecutionSetVariables(Variables.putValue(APPROVAL_DECISION, approvalDecision)) - return self() - } } - +} +``` + +Here is the corresponding stage, providing the steps used in the test: + +```kotlin +class ApprovalProcessActionStage : ProcessStage() { + + @BeforeStage + fun `automock all delegates`() { + CamundaMockito.registerJavaDelegateMock(DETERMINE_APPROVAL_STRATEGY) + CamundaMockito.registerJavaDelegateMock(AUTOMATICALLY_APPROVE_REQUEST) + CamundaMockito.registerJavaDelegateMock(ApprovalProcessBean.Expressions.LOAD_APPROVAL_REQUEST) + } + + fun process_is_started_for_request(approvalRequestId: String) = step { + processInstanceSupplier = ApprovalProcessBean(camunda.processEngine) + processInstanceSupplier.start(approvalRequestId) + assertThat(processInstanceSupplier.processInstance).isNotNull + assertThat(processInstanceSupplier.processInstance).isStarted + } + + fun approval_strategy_can_be_applied(approvalStrategy: String) = step { + getJavaDelegateMock(DETERMINE_APPROVAL_STRATEGY).onExecutionSetVariables(Variables.putValue(APPROVAL_STRATEGY, approvalStrategy)) + } + + fun automatic_approval_returns(approvalDecision: String) = step { + getJavaDelegateMock(AUTOMATICALLY_APPROVE_REQUEST).onExecutionSetVariables(Variables.putValue(APPROVAL_DECISION, approvalDecision)) + } +} +``` + The resulting report: ![JGiven Process Report](docs/report.png) @@ -115,12 +168,8 @@ If you have permissions to release, make sure all branches are fetched and run: ./mvnw gitflow:release-start ./mvnw gitflow:release-finish -from cli. This will update the poms of `develop` and `master` branches. -If you want to publish to central and have sufficient permissions, run - - ./mvnw clean deploy -Prelease -DskipExamples - -on `master` branch. Don't forget to close and release repository on https://oss.sonatype.org/#stagingRepositories. +from cli. This will update the poms of `develop` and `master` branches +and start GitHub actions producing a new release. ### Current maintainers @@ -130,5 +179,3 @@ on `master` branch. Don't forget to close and release repository on https://oss. * [Jan Galinski](https://github.com/jangalinski) * [Andre Hegerath](https://github.com/a-hegerath) * [Stefan Zilske](https://github.com/stefanzilske) - - diff --git a/examples/basic-junit5/pom.xml b/examples/basic-junit5/pom.xml new file mode 100644 index 0000000..6a4bf44 --- /dev/null +++ b/examples/basic-junit5/pom.xml @@ -0,0 +1,81 @@ + + + 4.0.0 + + + io.holunda.testing + camunda-bpm-jgiven-examples + 0.2.0 + + + camunda-bpm-jgiven-examples-basic-junit5 + jar + + + + org.camunda.bpm.springboot + camunda-bpm-spring-boot-starter-webapp + + + com.h2database + h2 + + + org.camunda.bpm.extension.mockito + camunda-bpm-mockito + 5.16.0 + test + + + org.camunda.bpm.springboot + camunda-bpm-spring-boot-starter-test + test + + + org.camunda.bpm.assert + camunda-bpm-assert-assertj3-11-1 + + + + + org.camunda.bpm.assert + camunda-bpm-assert + test + + + org.camunda.bpm.extension + camunda-bpm-junit5 + 1.1.0 + test + + + io.holunda.testing + camunda-bpm-jgiven + test + + + org.camunda.bpm.extension + camunda-bpm-process-test-coverage + 0.4.0 + test + + + + + + + + kotlin-maven-plugin + org.jetbrains.kotlin + + + + com.tngtech.jgiven + jgiven-maven-plugin + + + + + + diff --git a/examples/basic-junit5/src/main/kotlin/io/holunda/testing/examples/basic/ApprovalProcessBean.kt b/examples/basic-junit5/src/main/kotlin/io/holunda/testing/examples/basic/ApprovalProcessBean.kt new file mode 100644 index 0000000..6b3ef0f --- /dev/null +++ b/examples/basic-junit5/src/main/kotlin/io/holunda/testing/examples/basic/ApprovalProcessBean.kt @@ -0,0 +1,69 @@ +package io.holunda.testing.examples.basic + +import org.camunda.bpm.engine.ProcessEngine +import org.camunda.bpm.engine.runtime.ProcessInstance +import java.util.function.Supplier + +class ApprovalProcessBean(private val processEngine: ProcessEngine) : Supplier { + + companion object { + const val KEY = "approval" + const val RESOURCE = "approval.bpmn" + } + + lateinit var processInstance: ProcessInstance + + override fun get(): ProcessInstance = this.processInstance + + object Elements { + const val START = "start" + const val END_CANCELLED = "end_cancelled" + const val END_APPROVED = "end_approved" + const val END_REJECTED = "end_rejected" + const val USER_APPROVE_REQUEST = "user_approve_request" + const val USER_AMEND_REQUEST = "user_amend_request" + const val SERVICE_AUTO_APPROVE = "service_auto_approve_request" + } + + object Variables { + const val APPROVAL_REQUEST_ID = "approvalRequestId" + const val APPROVAL_STRATEGY = "approvalStrategy" + const val APPROVAL_DECISION = "approvalDecision" + const val AMEND_ACTION = "ammendAction" + const val ORIGINATOR = "originator" + } + + object Expressions { + const val LOAD_APPROVAL_REQUEST = "loadApprovalRequest" + const val DETERMINE_APPROVAL_STRATEGY = "determineApprovalStrategy" + const val AUTOMATICALLY_APPROVE_REQUEST = "automaticallyApproveRequest" + const val AUTOMATIC_APPROVAL_FAILED = "automaticApprovalFailed" + const val APPROVE_REQUEST_TASK_LISTENER = "approveRequestTaskListener" + + object ApprovalStrategy { + const val AUTOMATIC = "AUTOMATIC" + const val MANUAL = "MANUAL" + } + + object ApprovalDecision { + const val APPROVE = "APPROVE" + const val REJECT = "REJECT" + const val RETURN = "RETURN" + } + + object AmendAction { + const val RESUBMIT = "RESUBMIT" + const val CANCEL = "CANCEL" + } + } + + fun start(approvalRequestId: String) { + this.processInstance = this.processEngine.runtimeService.startProcessInstanceByKey( + KEY, + approvalRequestId, + org.camunda.bpm.engine.variable.Variables + .putValue(Variables.ORIGINATOR, "kermit") + .putValue(Variables.APPROVAL_REQUEST_ID, approvalRequestId) + ) + } +} diff --git a/examples/basic-junit5/src/main/kotlin/io/holunda/testing/examples/basic/BasicProcessApplication.kt b/examples/basic-junit5/src/main/kotlin/io/holunda/testing/examples/basic/BasicProcessApplication.kt new file mode 100644 index 0000000..99f8a84 --- /dev/null +++ b/examples/basic-junit5/src/main/kotlin/io/holunda/testing/examples/basic/BasicProcessApplication.kt @@ -0,0 +1,20 @@ +package io.holunda.testing.examples.basic + +import io.holunda.testing.examples.basic.ApprovalProcessBean.Expressions.APPROVE_REQUEST_TASK_LISTENER +import org.camunda.bpm.engine.delegate.TaskListener +import org.camunda.bpm.spring.boot.starter.annotation.EnableProcessApplication +import org.springframework.boot.runApplication +import org.springframework.context.annotation.Bean +import java.time.temporal.ChronoUnit +import java.util.* + +@EnableProcessApplication +class BasicProcessApplication { + fun main(args: Array) = runApplication(*args).let { Unit } + + @Bean(APPROVE_REQUEST_TASK_LISTENER) + fun approveRequestTaskListener() = TaskListener { + it.followUpDate = Date.from(it.createTime.toInstant().plus(1, ChronoUnit.DAYS)) + } + +} diff --git a/examples/basic-junit5/src/main/resources/META-INF/processes.xml b/examples/basic-junit5/src/main/resources/META-INF/processes.xml new file mode 100644 index 0000000..e69de29 diff --git a/examples/basic-junit5/src/main/resources/approval.bpmn b/examples/basic-junit5/src/main/resources/approval.bpmn new file mode 100644 index 0000000..506d402 --- /dev/null +++ b/examples/basic-junit5/src/main/resources/approval.bpmn @@ -0,0 +1,313 @@ + + + + + flow1 + + + + SequenceFlow_1p4jixi + SequenceFlow_1aallpn + + + + SequenceFlow_1eaf9ol + SequenceFlow_064ef2y + SequenceFlow_0n52bjk + + + + ${approvalStrategy == "AUTOMATIC"} + + + SequenceFlow_1wtga4h + SequenceFlow_1ccqf4c + SequenceFlow_0gcf7ty + + + + SequenceFlow_0gcf7ty + SequenceFlow_0jqf4xj + SequenceFlow_1i81jsh + SequenceFlow_0kbwukz + + + + SequenceFlow_0jqf4xj + + + ${approvalDecision == "APPROVE"} + + + SequenceFlow_1i81jsh + + + ${approvalDecision == "REJECT"} + + + flow1 + SequenceFlow_0on165o + SequenceFlow_1p4jixi + + + + SequenceFlow_064ef2y + SequenceFlow_1wtga4h + + + + + + + + SequenceFlow_0eqlrvy + SequenceFlow_1ccqf4c + + + SequenceFlow_0n52bjk + SequenceFlow_0a86c0j + SequenceFlow_0eqlrvy + + + + + SequenceFlow_0a86c0j + + + + ${approvalDecision == "RETURN"} + + + SequenceFlow_0kbwukz + SequenceFlow_1wcuegh + + + SequenceFlow_1wcuegh + SequenceFlow_0on165o + SequenceFlow_142t3uc + + + + ${amendAction == "RESUBMIT"} + + + SequenceFlow_132n50r + + + ${amendAction == "CANCEL"} + + + SequenceFlow_1aallpn + SequenceFlow_1eaf9ol + + + SequenceFlow_142t3uc + SequenceFlow_07zwntx + SequenceFlow_132n50r + + + + + SequenceFlow_07zwntx + + PT5D + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/basic-junit5/src/test/kotlin/io/holunda/testing/examples/basic/junit5/ApprovalProcessStages.kt b/examples/basic-junit5/src/test/kotlin/io/holunda/testing/examples/basic/junit5/ApprovalProcessStages.kt new file mode 100644 index 0000000..fb5a922 --- /dev/null +++ b/examples/basic-junit5/src/test/kotlin/io/holunda/testing/examples/basic/junit5/ApprovalProcessStages.kt @@ -0,0 +1,54 @@ +package io.holunda.testing.examples.basic.junit5 + +import com.tngtech.jgiven.annotation.As +import com.tngtech.jgiven.annotation.BeforeStage +import com.tngtech.jgiven.annotation.Quoted +import io.holunda.camunda.bpm.extension.jgiven.JGivenProcessStage +import io.holunda.camunda.bpm.extension.jgiven.ProcessStage +import io.holunda.testing.examples.basic.ApprovalProcessBean +import io.holunda.testing.examples.basic.ApprovalProcessBean.Expressions.APPROVE_REQUEST_TASK_LISTENER +import io.holunda.testing.examples.basic.ApprovalProcessBean.Expressions.DETERMINE_APPROVAL_STRATEGY +import io.holunda.testing.examples.basic.ApprovalProcessBean.Expressions.LOAD_APPROVAL_REQUEST +import io.holunda.testing.examples.basic.ApprovalProcessBean.Variables.APPROVAL_DECISION +import io.holunda.testing.examples.basic.ApprovalProcessBean.Variables.APPROVAL_STRATEGY +import io.holunda.testing.examples.basic.BasicProcessApplication +import io.toolisticon.testing.jgiven.step +import org.camunda.bpm.engine.test.assertions.bpmn.BpmnAwareTests.assertThat +import org.camunda.bpm.engine.test.assertions.bpmn.BpmnAwareTests.externalTask +import org.camunda.bpm.engine.test.mock.Mocks +import org.camunda.bpm.engine.variable.Variables +import org.camunda.bpm.engine.variable.Variables.putValue +import org.camunda.bpm.extension.mockito.CamundaMockito.getJavaDelegateMock +import org.camunda.bpm.extension.mockito.CamundaMockito.registerJavaDelegateMock + +@JGivenProcessStage +class ApprovalProcessActionStage : ProcessStage() { + + @BeforeStage + fun mock_all_delegates() { + registerJavaDelegateMock(DETERMINE_APPROVAL_STRATEGY) + registerJavaDelegateMock(LOAD_APPROVAL_REQUEST) + // register a real listener + Mocks.register(APPROVE_REQUEST_TASK_LISTENER, BasicProcessApplication().approveRequestTaskListener()) + } + + fun process_is_started_for_request(@Quoted approvalRequestId: String) = step { + processInstanceSupplier = ApprovalProcessBean(camunda) + processInstanceSupplier.start(approvalRequestId) + assertThat(processInstanceSupplier.processInstance).isNotNull + assertThat(processInstanceSupplier.processInstance).isStarted + } + + @As("\$approvalStrategy approval strategy can be applied") + fun approval_strategy_can_be_applied(@Quoted approvalStrategy: String) = step { + getJavaDelegateMock(DETERMINE_APPROVAL_STRATEGY).onExecutionSetVariables(Variables.putValue(APPROVAL_STRATEGY, approvalStrategy)) + } + + fun automatic_approval_returns(approvalResult: String) = step { + external_task_is_completed(externalTask().topicName, putValue(APPROVAL_DECISION, approvalResult)) + } + +} + +@JGivenProcessStage +class ApprovalProcessThenStage : ProcessStage() diff --git a/examples/basic-junit5/src/test/kotlin/io/holunda/testing/examples/basic/junit5/ApprovalProcessTest.kt b/examples/basic-junit5/src/test/kotlin/io/holunda/testing/examples/basic/junit5/ApprovalProcessTest.kt new file mode 100644 index 0000000..8b3d6c2 --- /dev/null +++ b/examples/basic-junit5/src/test/kotlin/io/holunda/testing/examples/basic/junit5/ApprovalProcessTest.kt @@ -0,0 +1,183 @@ +package io.holunda.testing.examples.basic.junit5 + +import com.tngtech.jgiven.annotation.ScenarioState +import com.tngtech.jgiven.junit5.ScenarioTest +import io.holunda.testing.examples.basic.ApprovalProcessBean +import io.holunda.testing.examples.basic.ApprovalProcessBean.Elements +import io.holunda.testing.examples.basic.ApprovalProcessBean.Expressions +import io.toolisticon.testing.jgiven.AND +import io.toolisticon.testing.jgiven.GIVEN +import io.toolisticon.testing.jgiven.THEN +import io.toolisticon.testing.jgiven.WHEN +import org.camunda.bpm.engine.test.Deployment +import org.camunda.bpm.engine.variable.Variables.putValue +import org.camunda.bpm.extension.junit5.test.ProcessEngineExtension +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.extension.ExtendWith +import org.junit.jupiter.api.extension.RegisterExtension +import java.time.Period +import java.util.* + +@ExtendWith(ProcessEngineExtension::class) +@Deployment(resources = [ApprovalProcessBean.RESOURCE]) +internal class ApprovalProcessTest : + ScenarioTest() { + + @RegisterExtension + val extension = TestProcessEngine.DEFAULT + + @ScenarioState + val camunda = extension.processEngine + + @Test + internal fun `should deploy`() { + THEN + .process_is_deployed(ApprovalProcessBean.KEY) + } + + @Test + internal fun `should start asynchronously`() { + + val approvalRequestId = UUID.randomUUID().toString() + + GIVEN + .process_is_deployed(ApprovalProcessBean.KEY) + WHEN + .process_is_started_for_request(approvalRequestId) + THEN + .process_waits_in(Elements.START) + } + + @Test + internal fun `should wait for automatic approve`() { + + val approvalRequestId = UUID.randomUUID().toString() + + GIVEN + .process_is_deployed(ApprovalProcessBean.KEY) + .AND + .process_is_started_for_request(approvalRequestId) + .AND + .approval_strategy_can_be_applied(Expressions.ApprovalStrategy.AUTOMATIC) + + WHEN + .process_continues() + + THEN + .process_waits_in(Elements.SERVICE_AUTO_APPROVE) + .AND + .external_task_exists("approve-request") + + } + + @Test + internal fun `should automatic approve`() { + + val approvalRequestId = UUID.randomUUID().toString() + + GIVEN + .process_is_deployed(ApprovalProcessBean.KEY) + .AND + .process_is_started_for_request(approvalRequestId) + .AND + .approval_strategy_can_be_applied(Expressions.ApprovalStrategy.AUTOMATIC) + .AND + .process_continues() + + WHEN + .automatic_approval_returns(Expressions.ApprovalDecision.APPROVE) + + THEN + .process_is_finished() + .AND + .process_has_passed(Elements.SERVICE_AUTO_APPROVE, Elements.END_APPROVED) + + } + + + @Test + internal fun `should automatically reject`() { + + val approvalRequestId = UUID.randomUUID().toString() + + GIVEN + .process_is_deployed(ApprovalProcessBean.KEY) + .AND + .process_is_started_for_request(approvalRequestId) + .AND + .approval_strategy_can_be_applied(Expressions.ApprovalStrategy.AUTOMATIC) + .AND + .process_continues() + + WHEN + .automatic_approval_returns(Expressions.ApprovalDecision.REJECT) + + THEN + .process_is_finished() + .AND + .process_has_passed(Elements.SERVICE_AUTO_APPROVE, Elements.END_REJECTED) + + } + + @Test + internal fun `should manually reject`() { + + val approvalRequestId = UUID.randomUUID().toString() + + GIVEN + .process_is_deployed(ApprovalProcessBean.KEY) + .AND + .process_is_started_for_request(approvalRequestId) + .AND + .approval_strategy_can_be_applied(Expressions.ApprovalStrategy.MANUAL) + .AND + .process_continues() + .AND + .process_waits_in(Elements.USER_APPROVE_REQUEST) + .AND + .task_priority_is_between(10, 30) + .AND + .task_has_follow_up_date_after(Period.ofDays(1)) + + WHEN + .task_is_completed_with_variables( + putValue(ApprovalProcessBean.Variables.APPROVAL_DECISION, Expressions.ApprovalDecision.REJECT), + isAsyncAfter = true + ) + + THEN + .process_is_finished() + .AND + .process_has_passed(Elements.END_REJECTED) + + } + + @Test + internal fun `should manually approve`() { + + val approvalRequestId = UUID.randomUUID().toString() + + GIVEN + .process_is_deployed(ApprovalProcessBean.KEY) + .AND + .process_is_started_for_request(approvalRequestId) + .AND + .approval_strategy_can_be_applied(Expressions.ApprovalStrategy.MANUAL) + .AND + .process_continues() + .AND + .process_waits_in(Elements.USER_APPROVE_REQUEST) + + WHEN + .task_is_completed_with_variables( + putValue(ApprovalProcessBean.Variables.APPROVAL_DECISION, Expressions.ApprovalDecision.APPROVE), + isAsyncAfter = true + ) + + THEN + .process_is_finished() + .AND + .process_has_passed(Elements.END_APPROVED) + + } +} diff --git a/examples/basic-junit5/src/test/kotlin/io/holunda/testing/examples/basic/junit5/TestProcessEngine.kt b/examples/basic-junit5/src/test/kotlin/io/holunda/testing/examples/basic/junit5/TestProcessEngine.kt new file mode 100644 index 0000000..cd62f9f --- /dev/null +++ b/examples/basic-junit5/src/test/kotlin/io/holunda/testing/examples/basic/junit5/TestProcessEngine.kt @@ -0,0 +1,126 @@ +package io.holunda.testing.examples.basic.junit5 + +import org.camunda.bpm.engine.ProcessEngine +import org.camunda.bpm.engine.ProcessEngineConfiguration +import org.camunda.bpm.engine.impl.ProcessEngineImpl +import org.camunda.bpm.engine.impl.cfg.AbstractProcessEnginePlugin +import org.camunda.bpm.engine.impl.cfg.ProcessEngineConfigurationImpl +import org.camunda.bpm.engine.impl.cfg.ProcessEnginePlugin +import org.camunda.bpm.engine.impl.cfg.StandaloneInMemProcessEngineConfiguration +import org.camunda.bpm.engine.impl.history.HistoryLevel +import org.camunda.bpm.engine.test.mock.MockExpressionManager +import org.camunda.bpm.extension.junit5.test.ProcessEngineExtension +import java.util.* +import java.util.function.Consumer +import java.util.stream.Collectors +import java.util.stream.Stream + + +enum class TestProcessEngine { + ; + + class Builder internal constructor() { + private val configuration: ProcessEngineConfigurationImpl + + init { + configuration = StandaloneInMemProcessEngineConfiguration() + configuration.historyLevel = HistoryLevel.HISTORY_LEVEL_FULL + configuration.databaseSchemaUpdate = ProcessEngineConfiguration.DB_SCHEMA_UPDATE_TRUE + configuration.isJobExecutorActivate = false + configuration.isDbMetricsReporterActivate = false + configuration.expressionManager = MockExpressionManager() + configuration.isTelemetryReporterActivate = false + configuration.isInitializeTelemetry = false + } + + fun preInit(preInit: Consumer): Builder { + plugin(createPlugin(preInit, null, null)) + return this + } + + fun postInit(postInit: Consumer): Builder { + plugin(createPlugin(null, postInit, null)) + return this + } + + fun postProcessEngineBuild(postProcessEngineBuild: Consumer): Builder { + plugin(createPlugin(null, null, postProcessEngineBuild)) + return this + } + + fun withDefaultSerializationFormat(defaultSerializationFormat: String): Builder { + configuration.defaultSerializationFormat = defaultSerializationFormat + return this + } + + fun plugin(plugin: ProcessEnginePlugin): Builder { + configuration.processEnginePlugins.add(plugin) + return this + } + + fun withH2MemNameDefault(): Builder { + return withH2MemName("camunda") + } + + fun withH2MemName(databaseName: String): Builder { + preInit { + it.jdbcUrl = String.format( + "jdbc:h2:mem:%s;DB_CLOSE_ON_EXIT=FALSE;MODE=PostgreSQL;DATABASE_TO_LOWER=TRUE", + databaseName + ) + } + return this + } + + fun engine(): ProcessEngineImpl { + return configuration.buildProcessEngine() as ProcessEngineImpl + } + + fun extension(): ProcessEngineExtension { + return ProcessEngineExtension.builder().useProcessEngine(engine()).build() + } + + companion object { + private fun createPlugin( + preInit: Consumer?, + postInit: Consumer?, + postProcessEngineBuild: Consumer? + ): ProcessEnginePlugin { + return object : AbstractProcessEnginePlugin() { + override fun preInit(processEngineConfiguration: ProcessEngineConfigurationImpl) { + preInit?.accept(processEngineConfiguration) + } + + override fun postInit(processEngineConfiguration: ProcessEngineConfigurationImpl) { + postInit?.accept(processEngineConfiguration) + } + + override fun postProcessEngineBuild(processEngine: ProcessEngine) { + postProcessEngineBuild?.accept(processEngine) + } + + override fun toString(): String { + return Stream.of(preInit, postInit, postProcessEngineBuild).map(Objects::nonNull) + .map { obj: Any -> obj.toString() } + .collect(Collectors.joining("-")) + } + } + } + } + } + + companion object { + // util class, final, no instance + val DEFAULT = builder() + .withDefaultSerializationFormat("application/json") + .extension() + + fun builder(): Builder { + return Builder() + } + + fun extension(): ProcessEngineExtension { + return builder().extension() + } + } +} diff --git a/examples/basic-junit5/src/test/resources/logback.xml b/examples/basic-junit5/src/test/resources/logback.xml new file mode 100644 index 0000000..9e068a6 --- /dev/null +++ b/examples/basic-junit5/src/test/resources/logback.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/examples/basic/jgiven-reports/io.holunda.testing.examples.basic.ApprovalProcessTest.json b/examples/basic/jgiven-reports/io.holunda.testing.examples.basic.ApprovalProcessTest.json deleted file mode 100644 index 9a89c68..0000000 --- a/examples/basic/jgiven-reports/io.holunda.testing.examples.basic.ApprovalProcessTest.json +++ /dev/null @@ -1,241 +0,0 @@ -{ - "className": "io.holunda.testing.examples.basic.ApprovalProcessTest", - "name": "Approval Process", - "scenarios": [ - { - "className": "io.holunda.testing.examples.basic.ApprovalProcessTest", - "testMethodName": "should manually reject", - "description": "should manually reject", - "tagIds": [], - "explicitParameters": [], - "derivedParameters": [], - "casesAsTable": false, - "scenarioCases": [ - { - "caseNr": 1, - "steps": [ - { - "name": "process $ is deployed", - "words": [ - { - "value": "Given", - "isIntroWord": true - }, - { - "value": "process" - }, - { - "value": "approval", - "argumentInfo": { - "argumentName": "processDefinitionKey", - "formattedValue": "\"approval\"" - } - }, - { - "value": "is deployed" - } - ], - "status": "PASSED", - "durationInNanos": 14548485 - }, - { - "name": "process is started for request", - "words": [ - { - "value": "and", - "isIntroWord": true - }, - { - "value": "process is started for request" - }, - { - "value": "d22b5b69-98a2-45ab-95e3-d21b18918872", - "argumentInfo": { - "argumentName": "approvalRequestId", - "formattedValue": "\"d22b5b69-98a2-45ab-95e3-d21b18918872\"" - } - } - ], - "status": "PASSED", - "durationInNanos": 82380 - }, - { - "name": "$approvalStrategy approval strategy can be applied", - "words": [ - { - "value": "and", - "isIntroWord": true - }, - { - "value": "MANUAL", - "argumentInfo": { - "argumentName": "approvalStrategy", - "formattedValue": "\"MANUAL\"" - } - }, - { - "value": "approval strategy can be applied" - } - ], - "status": "PASSED", - "durationInNanos": 55716 - }, - { - "name": "process continues", - "words": [ - { - "value": "and", - "isIntroWord": true - }, - { - "value": "process continues" - } - ], - "status": "PASSED", - "durationInNanos": 47752 - }, - { - "name": "process waits in $", - "words": [ - { - "value": "and", - "isIntroWord": true - }, - { - "value": "process waits in" - }, - { - "value": "user_approve_request", - "argumentInfo": { - "argumentName": "activityId", - "formattedValue": "\"user_approve_request\"" - } - } - ], - "status": "PASSED", - "durationInNanos": 46041 - }, - { - "name": "task\u0027s priority is between $lower and $upper", - "words": [ - { - "value": "and", - "isIntroWord": true - }, - { - "value": "task\u0027s priority is between" - }, - { - "value": "10", - "argumentInfo": { - "argumentName": "lower", - "formattedValue": "10" - } - }, - { - "value": "and" - }, - { - "value": "30", - "argumentInfo": { - "argumentName": "upper", - "formattedValue": "30" - } - } - ], - "status": "PASSED", - "durationInNanos": 49904 - }, - { - "name": "task\u0027s follow-up date is $ after its creation", - "words": [ - { - "value": "and", - "isIntroWord": true - }, - { - "value": "task\u0027s follow-up date is" - }, - { - "value": "P1D", - "argumentInfo": { - "argumentName": "followUpDatePeriod", - "formattedValue": "P1D" - } - }, - { - "value": "after its creation" - } - ], - "status": "PASSED", - "durationInNanos": 17661886 - }, - { - "name": "task is completed with variables $", - "words": [ - { - "value": "When", - "isIntroWord": true - }, - { - "value": "task is completed with variables" - }, - { - "value": "{\n approvalDecision \u003d\u003e Untyped value \u0027REJECT\u0027, isTransient \u003d false\n}", - "argumentInfo": { - "argumentName": "variables", - "formattedValue": "{\n approvalDecision \u003d\u003e Untyped value \u0027REJECT\u0027, isTransient \u003d false\n}" - } - } - ], - "status": "PASSED", - "durationInNanos": 67949846 - }, - { - "name": "process is finished", - "words": [ - { - "value": "Then", - "isIntroWord": true - }, - { - "value": "process is finished" - } - ], - "status": "PASSED", - "durationInNanos": 63320 - }, - { - "name": "process has passed element(s) $", - "words": [ - { - "value": "and", - "isIntroWord": true - }, - { - "value": "process has passed element(s)" - }, - { - "value": "end_rejected", - "argumentInfo": { - "argumentName": "elements", - "formattedValue": "\"end_rejected\"" - } - } - ], - "status": "PASSED", - "durationInNanos": 51938513 - } - ], - "explicitArguments": [], - "derivedArguments": [], - "status": "SUCCESS", - "durationInNanos": 994767867 - } - ], - "durationInNanos": 994767867, - "executionStatus": "SUCCESS" - } - ], - "tagMap": {} -} \ No newline at end of file diff --git a/examples/basic/pom.xml b/examples/basic/pom.xml index 02a7822..1a22d76 100644 --- a/examples/basic/pom.xml +++ b/examples/basic/pom.xml @@ -6,7 +6,7 @@ io.holunda.testing camunda-bpm-jgiven-examples - 0.0.8 + 0.2.0 camunda-bpm-jgiven-examples-basic @@ -24,7 +24,7 @@ org.camunda.bpm.extension.mockito camunda-bpm-mockito - 5.15.0 + 5.16.0 test @@ -36,6 +36,12 @@ org.camunda.bpm.springboot camunda-bpm-spring-boot-starter-test test + + + org.camunda.bpm.assert + camunda-bpm-assert-assertj3-11-1 + + org.camunda.bpm.assert diff --git a/examples/basic/src/test/kotlin/io/holunda/testing/examples/basic/ApprovalProcessStages.kt b/examples/basic/src/test/kotlin/io/holunda/testing/examples/basic/ApprovalProcessStages.kt index 6b2fe7c..4dc95c0 100644 --- a/examples/basic/src/test/kotlin/io/holunda/testing/examples/basic/ApprovalProcessStages.kt +++ b/examples/basic/src/test/kotlin/io/holunda/testing/examples/basic/ApprovalProcessStages.kt @@ -31,7 +31,7 @@ class ApprovalProcessActionStage : ProcessStage() { - companion object { - val processEngineRule: ProcessEngineRule = StandaloneInMemoryTestConfiguration().rule() - } - @get: Rule - @ScenarioState - val camunda: ProcessEngineRule = processEngineRule + val rule: ProcessEngineRule = StandaloneInMemoryTestConfiguration().rule() + @ScenarioState + val camunda = rule.processEngine @Test fun `should deploy`() { diff --git a/examples/pom.xml b/examples/pom.xml index 5b35fda..15dcd52 100644 --- a/examples/pom.xml +++ b/examples/pom.xml @@ -6,18 +6,19 @@ io.holunda.testing camunda-bpm-jgiven-parent - 0.0.8 + 0.2.0 camunda-bpm-jgiven-examples pom - 2.4.5 + 2.6.4 basic + basic-junit5 diff --git a/extension/pom.xml b/extension/pom.xml index 7735834..9713fc7 100644 --- a/extension/pom.xml +++ b/extension/pom.xml @@ -6,7 +6,7 @@ io.holunda.testing camunda-bpm-jgiven-parent - 0.0.8 + 0.2.0 camunda-bpm-jgiven @@ -18,6 +18,11 @@ jgiven-junit ${jgiven.version} + + com.tngtech.jgiven + jgiven-junit5 + ${jgiven.version} + com.tngtech.jgiven jgiven-spring diff --git a/extension/src/main/kotlin/io/holunda/camunda/bpm/extension/jgiven/ProcessStage.kt b/extension/src/main/kotlin/io/holunda/camunda/bpm/extension/jgiven/ProcessStage.kt index 123903f..455c8dc 100644 --- a/extension/src/main/kotlin/io/holunda/camunda/bpm/extension/jgiven/ProcessStage.kt +++ b/extension/src/main/kotlin/io/holunda/camunda/bpm/extension/jgiven/ProcessStage.kt @@ -7,12 +7,15 @@ import io.holunda.camunda.bpm.extension.jgiven.formatter.QuotedVarargs import io.holunda.camunda.bpm.extension.jgiven.formatter.VariableMapFormat import io.toolisticon.testing.jgiven.step import org.assertj.core.api.Assertions.* +import org.camunda.bpm.engine.ProcessEngine +import org.camunda.bpm.engine.impl.persistence.entity.TimerEntity +import org.camunda.bpm.engine.impl.util.ClockUtil import org.camunda.bpm.engine.runtime.ProcessInstance -import org.camunda.bpm.engine.test.ProcessEngineRule import org.camunda.bpm.engine.test.assertions.bpmn.BpmnAwareTests.* import org.camunda.bpm.engine.variable.VariableMap import org.camunda.bpm.engine.variable.Variables.createVariables import java.time.Period +import java.time.temporal.ChronoUnit import java.util.* import java.util.function.Supplier @@ -56,7 +59,7 @@ class ProcessStage, PROCESS_BEAN : Suppl * Process engine to work on. */ @ExpectedScenarioState(required = true) - lateinit var camunda: ProcessEngineRule + lateinit var camunda: ProcessEngine /** * Instance supplier. @@ -74,6 +77,58 @@ class ProcessStage, PROCESS_BEAN : Suppl assertThat(processInstanceSupplier.get()).isWaitingAt(activityId) } + /** + * Checks if the process instance is waiting in all activities with specified ids. + * @param activityId definition id. + * @return fluent stage. + */ + @As("process waits in activities $") + fun process_waits_in(@QuotedVarargs vararg activityId: String) = step { + require(activityId.isNotEmpty()) { "At least one activity id must be provided" } + activityId.map { + val job = job(it) + assertThat(job).`as`("Expecting the process to be waiting in activity '$it', but it was not.").isNotNull + } + } + + /** + * Checks if the process instance is waiting to receive all events in activities with specified ids. + * @param activityId definition id. + * @return fluent stage. + */ + fun process_waits_for(@QuotedVarargs vararg activityId: String) = step { + require(activityId.isNotEmpty()) { "At least one activity id must be provided" } + val activityIdOfActiveEventSubscriptions = + runtimeService().createEventSubscriptionQuery().list().map { it.activityId } + assertThat(activityIdOfActiveEventSubscriptions) + .`as`( + "Expecting the process to wait for events in activity ${ + activityId.joinToString(", ") + }, but it was waiting in ${ + activityIdOfActiveEventSubscriptions.joinToString(", ") + }" + ) + .containsExactlyInAnyOrder(*activityId) + } + + /** + * Executes current job. + * @return fluent stage. + */ + @As("process continues") + fun process_continues(): SELF = step { + job_is_executed() + } + + /** + * Executes jobs named by the activities the current execution is waiting at. + * @param activityId activities the execution is waiting at. + * @return fluent stage. + */ + @As("process continues") + fun process_continues(vararg activityId: String) = job_is_executed(*activityId) + + /** * Asserts that the process is deployed. * @param processDefinitionKey process definition key. @@ -88,7 +143,6 @@ class ProcessStage, PROCESS_BEAN : Suppl .latestVersion() .singleResult() ).isNotNull - } /** @@ -240,11 +294,23 @@ class ProcessStage, PROCESS_BEAN : Suppl * @param variableName name of the variable. * @return fluent stage. */ - @As("variables $ are not present") - fun variable_is_not_present(@QuotedVarargs vararg variableName: String): SELF = step { + @As("variable $ is not present") + fun variable_is_not_present(@QuotedVarargs variableName: String): SELF = step { assertThat(processInstanceSupplier.get()) .`as`("variable $variableName should not be present") - .variables().doesNotContainKeys(*variableName) + .variables().doesNotContainKeys(variableName) + } + + /** + * Asserts that variable are not set. + * @param variableNames names of the variables. + * @return fluent stage. + */ + @As("variables $ are not present") + fun variables_are_not_present(@QuotedVarargs variableNames: Array): SELF = step { + assertThat(processInstanceSupplier.get()) + .`as`("variables ${variableNames.joinToString(", ")} should not be present") + .variables().doesNotContainKeys(*variableNames) } /** @@ -275,7 +341,7 @@ class ProcessStage, PROCESS_BEAN : Suppl assertThat(processInstanceSupplier.get()) .`as`("Expecting the task to be marked as async after and continue on complete.") .isWaitingAt(taskDefinitionKey) - execute(job()) + job_is_executed(taskDefinitionKey) } } @@ -289,6 +355,7 @@ class ProcessStage, PROCESS_BEAN : Suppl /** * Executes current job. + * Be careful, this method will fail if more than one job is in place. * @return fluent stage. */ fun job_is_executed(): SELF = step { @@ -297,13 +364,65 @@ class ProcessStage, PROCESS_BEAN : Suppl } /** - * Executes current job. + * Executes the jobs waiting in activities provided. + * @param activityId id of the activity the job is waiting in. * @return fluent stage. */ - @As("process continues") - fun process_continues(): SELF = step { - assertThat(processInstanceSupplier.get()).isNotNull - execute(job()) + fun job_is_executed(vararg activityId: String) = step { + require(activityId.isNotEmpty()) { "At least one activity id must be provided" } + activityId.map { + val job = job(it) + assertThat(job).`as`("Expecting the process to be waiting in activity '$it', but it was not.").isNotNull + execute(job) + } + } + + /** + * Asserts that the instance is waiting for the timer to be executed on the expected time. + * @param timerActivityId activity id of the timer. + * @param expectedDate expected data truncated to minute. + * @return fluent stage. + */ + fun timer_is_waiting_until(timerActivityId: String, expectedDate: Date) = step { + + val truncatedToMinutes = Date.from(expectedDate.toInstant().truncatedTo(ChronoUnit.MINUTES)) + + val timerJobs = managementService() + .createJobDefinitionQuery() + .activityIdIn(timerActivityId) + .list() + .mapNotNull { jobDefinition -> + managementService() + .createJobQuery() + .jobDefinitionId(jobDefinition.id) + .singleResult() + }.filterIsInstance() + + assertThat(timerJobs).`as`("Expected one instance waiting in $timerActivityId, but found ${timerJobs.size}.").hasSize(1) + assertThat(timerJobs[0]).hasDueDate(truncatedToMinutes) + } + + /** + * Sets engine time to new value and triggers the timer job execution. + * @param timerActivityId activity id of timer event. + * @param targetTime time to set engine time to. + * @return fluent stage. + */ + fun time_passes(timerActivityId: String, targetTime: Date) = step { + ClockUtil.setCurrentTime(targetTime) + + val timerJobs = managementService() + .createJobDefinitionQuery() + .activityIdIn(timerActivityId) + .list() + .mapNotNull { jobDefinition -> + managementService() + .createJobQuery() + .jobDefinitionId(jobDefinition.id) + .singleResult() + }.filterIsInstance() + assertThat(timerJobs).`as`("Expected one instance waiting in $timerActivityId, but found ${timerJobs.size}.").hasSize(1) + job_is_executed(timerActivityId) } /** @@ -376,14 +495,14 @@ class ProcessStage, PROCESS_BEAN : Suppl // exactly one subscription assertThat( - camunda.processEngine.runtimeService + camunda.runtimeService .createEventSubscriptionQuery() .processInstanceId(processInstanceSupplier.get().processInstanceId) .eventType("message") .eventName(messageName).count() ).isEqualTo(1) - camunda.processEngine.runtimeService + camunda.runtimeService .createMessageCorrelation(messageName) .setVariables(variables) .correlate() diff --git a/pom.xml b/pom.xml index 908ff53..11e5693 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ io.holunda.testing camunda-bpm-jgiven-parent - 0.0.8 + 0.2.0 pom @@ -15,17 +15,16 @@ - 7.15.0 - 1.0.0 + 7.16.0 + 1.2.0 4.13.2 3.19.0 - 10.0.0 - 1.0.0 + 13.0.0 + 1.0.1 11 - 1.5.0 + 1.6.10 true - 2.0.3 ${java.version} ${java.version} ${java.version} @@ -124,7 +123,7 @@ org.apache.maven.plugins maven-enforcer-plugin - 3.0.0-M3 + 3.0.0 enforce-maven @@ -156,7 +155,7 @@ org.apache.maven.plugins maven-compiler-plugin - 3.8.1 + 3.10.0 UTF-8 ${java.version} @@ -204,7 +203,7 @@ com.amashchenko.maven.plugin gitflow-maven-plugin - 1.16.0 + 1.18.0 master @@ -227,6 +226,9 @@ org.jetbrains.kotlin ${kotlin.version} + ${java.version} + 1.5 + 1.5 spring jpa @@ -237,7 +239,6 @@ - ${java.version} @@ -298,7 +299,7 @@ org.jetbrains.dokka dokka-maven-plugin - 1.4.32 + 1.6.10 test @@ -314,7 +315,7 @@ org.codehaus.mojo build-helper-maven-plugin - 3.2.0 + 3.3.0 generate-sources @@ -377,7 +378,7 @@ maven-deploy-plugin - 3.0.0-M1 + 3.0.0-M2 true @@ -385,7 +386,7 @@ org.sonatype.plugins nexus-staging-maven-plugin - 1.6.8 + 1.6.12 default-deploy