From d52ca7cd984491a1b5ad44f39ccbdaf2acf1d2f2 Mon Sep 17 00:00:00 2001 From: Ragin666 Date: Sat, 13 Mar 2021 16:13:58 +0100 Subject: [PATCH 1/2] Polling Signed-off-by: Ragin666 --- CHANGELOG.md | 71 ++++++++++++ README.md | 73 +++++++++++++ gradle.properties | 4 +- .../bdd/cucumber/core/ScenarioStateContext.kt | 7 ++ .../bdd/cucumber/glue/GivenRESTStateGlue.kt | 16 +++ .../cucumber/glue/ThenRESTValidationGlue.kt | 1 + .../cucumber/glue/WhenRESTExecutionGlue.kt | 101 ++++++++++++++++++ .../cucumbertests/library/test/Polling.java | 69 ++++++++++++ .../features/polling/polling.feature | 51 +++++++++ .../features/polling/responses/expected.json | 3 + 10 files changed, 394 insertions(+), 2 deletions(-) create mode 100644 src/test/java/com/ragin/bdd/cucumbertests/library/test/Polling.java create mode 100644 src/test/resources/features/polling/polling.feature create mode 100644 src/test/resources/features/polling/responses/expected.json diff --git a/CHANGELOG.md b/CHANGELOG.md index a414602..04168c7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,74 @@ +# Release 1.30.0 +## Support for polling APIs +The polling configuration is automatically reset before each scenario. +It can be configured via the background or directly in the scenario. + +When the expected HTTP status code and JSON structure has been sent as a response, polling will stop. +This allows an endpoint to be polled until it changes state or fail if the state has not changed during the specified time and retry configuration. + +The configuration can be done in to ways. + +As a single line configuration: +```gherkin +Scenario: Single line configuration + Given that a request polls every 1 seconds for 5 times +``` + +Or as a multiline configuration that supports to specify one of the configurations in the `Background` and the other in the `Scenario` (or to have it more readable). + +```gherkin +Scenario: Multiline configuration + Given that a requests polls every 1 seconds + And that a requests polls for 5 times +``` + +The `URL`/`URI` and (if required) body have to be preconfigured. Polling itself does simply use previous set body and path definition. +To execute a request it supports the well known authorized and unauthorized phrases and it supports direct JSON or JSON from file: + +Authorized request with JSON response file: +```gherkin +Scenario: Authorized request with JSON response file + Given that a request polls every 1 seconds for 5 times + And that the API path is "/api/v1/polling" + When executing an authorized GET poll request until the response code is 200 and the body is equal to file "expected.json" +``` + +Unauthorized request with JSON response file: +```gherkin +Scenario: Unauthorized request with JSON response file + Given that a request polls every 1 seconds for 5 times + And that the API path is "/api/v1/polling" + When executing a GET poll request until the response code is 200 and the body is equal to file "expected.json" +``` + +Authorized request with direct JSON response: +```gherkin +Scenario: Authorized request with JSON response file + Given that a request polls every 1 seconds for 5 times + And that the API path is "/api/v1/polling" + When executing an authorized GET poll request until the response code is 200 and the body is equal to + """ + { + "message": "SUCCESSFUL" + } + """ +``` + +Unauthorized request with direct JSON response: +```gherkin +Scenario: Unauthorized request with JSON response file + Given that a request polls every 1 seconds for 5 times + And that the API path is "/api/v1/polling" + When executing a GET poll request until the response code is 200 and the body is equal to + """ + { + "message": "SUCCESSFUL" + } + """ +``` + +Examples can be found at [src/test/resources/features/polling/](src/test/resources/features/polling/). + # Release 1.29.1 ## Support for database-less applications diff --git a/README.md b/README.md index dd5baea..0bde12b 100644 --- a/README.md +++ b/README.md @@ -60,6 +60,7 @@ dependencies { - [REST](#rest) - [JSON-Unit](#json-unit) - [Adding own pattern for `${json-unit.matches:isValidDate}`](#adding-own-pattern-for-json-unitmatchesisvaliddate) + - [Polling](#polling) - [Given](#given-1) - [Define user(s)](#define-users) - [Set path base directory for request/result/database files](#set-path-base-directory-for-requestresultdatabase-files) @@ -376,6 +377,78 @@ Example: - [Configuration context](src/test/java/com/ragin/bdd/cucumbertests/hooks/CreateContextHooks.java) - [Test feature](src/test/resources/features/body_validation/field_compare.feature) +### Polling +Polling support combines some `Given` and `When` definitions. For this reason it has its own chapter. + +The polling configuration is automatically reset before each scenario. +It can be configured via the background or directly in the scenario. + +When the expected HTTP status code and JSON structure has been sent as a response, polling will stop. +This allows an endpoint to be polled until it changes state or fail if the state has not changed during the specified time and retry configuration. + +The configuration can be done in to ways. + +As a single line configuration: +```gherkin +Scenario: Single line configuration + Given that a request polls every 1 seconds for 5 times +``` + +Or as a multiline configuration that supports to specify one of the configurations in the `Background` and the other in the `Scenario` (or to have it more readable). + +```gherkin +Scenario: Multiline configuration + Given that a requests polls every 1 seconds + And that a requests polls for 5 times +``` + +The `URL`/`URI` and (if required) body have to be preconfigured. Polling itself does simply use previous set body and path definition. +To execute a request it supports the well known authorized and unauthorized phrases and it supports direct JSON or JSON from file: + +Authorized request with JSON response file: +```gherkin +Scenario: Authorized request with JSON response file + Given that a request polls every 1 seconds for 5 times + And that the API path is "/api/v1/polling" + When executing an authorized GET poll request until the response code is 200 and the body is equal to file "expected.json" +``` + +Unauthorized request with JSON response file: +```gherkin +Scenario: Unauthorized request with JSON response file + Given that a request polls every 1 seconds for 5 times + And that the API path is "/api/v1/polling" + When executing a GET poll request until the response code is 200 and the body is equal to file "expected.json" +``` + +Authorized request with direct JSON response: +```gherkin +Scenario: Authorized request with JSON response file + Given that a request polls every 1 seconds for 5 times + And that the API path is "/api/v1/polling" + When executing an authorized GET poll request until the response code is 200 and the body is equal to + """ + { + "message": "SUCCESSFUL" + } + """ +``` + +Unauthorized request with direct JSON response: +```gherkin +Scenario: Unauthorized request with JSON response file + Given that a request polls every 1 seconds for 5 times + And that the API path is "/api/v1/polling" + When executing a GET poll request until the response code is 200 and the body is equal to + """ + { + "message": "SUCCESSFUL" + } + """ +``` + +Examples can be found at [src/test/resources/features/polling/](src/test/resources/features/polling/). + ### Given diff --git a/gradle.properties b/gradle.properties index e0c0966..826d3ca 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,5 +1,5 @@ group=com.ragin.bdd -version=1.29.2 +version=1.30.0 systemProp.sonar.host.url=https://sonarcloud.io/ systemProp.sonar.organization=ragin-lundf-github @@ -7,7 +7,7 @@ systemProp.sonar.projectKey=Ragin-LundF_bbd-cucumber-gherkin-lib versionJavaxJson=1.1.4 versionJsonUnit=2.24.0 -versionCucumber=6.9.1 +versionCucumber=6.10.1 versionValidationApi=2.0.1.Final versionCommonsText=1.9 versionCommonsIo=2.8.0 diff --git a/src/main/kotlin/com/ragin/bdd/cucumber/core/ScenarioStateContext.kt b/src/main/kotlin/com/ragin/bdd/cucumber/core/ScenarioStateContext.kt index 5382a63..f912dd9 100644 --- a/src/main/kotlin/com/ragin/bdd/cucumber/core/ScenarioStateContext.kt +++ b/src/main/kotlin/com/ragin/bdd/cucumber/core/ScenarioStateContext.kt @@ -17,6 +17,7 @@ object ScenarioStateContext { var userTokenMap: HashMap = HashMap() private var jsonPathOptions: MutableList