diff --git a/REGRESSION/resources/config-ci-regression-mobile.xml b/REGRESSION/resources/config-ci-regression-mobile.xml
index 6cd3473..74efde5 100644
--- a/REGRESSION/resources/config-ci-regression-mobile.xml
+++ b/REGRESSION/resources/config-ci-regression-mobile.xml
@@ -8,6 +8,11 @@
+
+
+
+
+
@@ -27,8 +32,6 @@
-
-
diff --git a/REGRESSION/resources/config-ci-regression-windows.xml b/REGRESSION/resources/config-ci-regression-windows.xml
index a4226e0..a83525d 100644
--- a/REGRESSION/resources/config-ci-regression-windows.xml
+++ b/REGRESSION/resources/config-ci-regression-windows.xml
@@ -8,6 +8,11 @@
+
+
+
+
+
@@ -27,8 +32,6 @@
-
-
diff --git a/REGRESSION/resources/config-ci-regression.xml b/REGRESSION/resources/config-ci-regression.xml
index d57141a..09e85a9 100644
--- a/REGRESSION/resources/config-ci-regression.xml
+++ b/REGRESSION/resources/config-ci-regression.xml
@@ -8,6 +8,11 @@
+
+
+
+
+
@@ -27,8 +32,6 @@
-
-
diff --git a/REGRESSION/resources/config-local.xml b/REGRESSION/resources/config-local.xml
index fc7fd2e..a3c15f6 100644
--- a/REGRESSION/resources/config-local.xml
+++ b/REGRESSION/resources/config-local.xml
@@ -8,6 +8,11 @@
+
+
+
+
+
@@ -34,8 +39,6 @@
-
-
@@ -66,9 +69,9 @@
-
+
-
+
diff --git a/REGRESSION/resources/config/ci-windows/integration.xml b/REGRESSION/resources/config/ci-windows/integration.xml
index b7bef3d..391768a 100644
--- a/REGRESSION/resources/config/ci-windows/integration.xml
+++ b/REGRESSION/resources/config/ci-windows/integration.xml
@@ -6,15 +6,32 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/REGRESSION/resources/config/ci/integration.xml b/REGRESSION/resources/config/ci/integration.xml
index c718fb0..d36a95e 100644
--- a/REGRESSION/resources/config/ci/integration.xml
+++ b/REGRESSION/resources/config/ci/integration.xml
@@ -6,15 +6,32 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/REGRESSION/resources/config/local/static/integration.xml b/REGRESSION/resources/config/local/static/integration.xml
index 6825d98..9aa6952 100644
--- a/REGRESSION/resources/config/local/static/integration.xml
+++ b/REGRESSION/resources/config/local/static/integration.xml
@@ -6,14 +6,31 @@
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
diff --git a/REGRESSION/resources/config/local/vault/integration.xml b/REGRESSION/resources/config/local/vault/integration.xml
index d712f2b..305646b 100644
--- a/REGRESSION/resources/config/local/vault/integration.xml
+++ b/REGRESSION/resources/config/local/vault/integration.xml
@@ -6,14 +6,31 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/REGRESSION/resources/data/credentials/auth/basic/http-auth-user-basic.json b/REGRESSION/resources/data/credentials/auth/basic/http-auth-user-basic.json
new file mode 100644
index 0000000..71910eb
--- /dev/null
+++ b/REGRESSION/resources/data/credentials/auth/basic/http-auth-user-basic.json
@@ -0,0 +1,4 @@
+{
+ "username": "testlum",
+ "password": "123456"
+}
\ No newline at end of file
diff --git a/REGRESSION/resources/data/credentials/auth/custom/http-auth-user-custom.json b/REGRESSION/resources/data/credentials/auth/custom/http-auth-user-custom.json
new file mode 100644
index 0000000..92a1264
--- /dev/null
+++ b/REGRESSION/resources/data/credentials/auth/custom/http-auth-user-custom.json
@@ -0,0 +1,4 @@
+{
+ "clientId": "testlum-client",
+ "clientSecret": "super-secret"
+}
\ No newline at end of file
diff --git a/REGRESSION/resources/data/credentials/auth/jwt/http-auth-user-jwt.json b/REGRESSION/resources/data/credentials/auth/jwt/http-auth-user-jwt.json
new file mode 100644
index 0000000..71910eb
--- /dev/null
+++ b/REGRESSION/resources/data/credentials/auth/jwt/http-auth-user-jwt.json
@@ -0,0 +1,4 @@
+{
+ "username": "testlum",
+ "password": "123456"
+}
\ No newline at end of file
diff --git a/REGRESSION/resources/data/credentials/auth/jwt/invalid-http-auth-user-jwt.json b/REGRESSION/resources/data/credentials/auth/jwt/invalid-http-auth-user-jwt.json
new file mode 100644
index 0000000..4d57c0e
--- /dev/null
+++ b/REGRESSION/resources/data/credentials/auth/jwt/invalid-http-auth-user-jwt.json
@@ -0,0 +1,4 @@
+{
+ "username": "username",
+ "password": "password"
+}
\ No newline at end of file
diff --git a/REGRESSION/resources/data/variations/auth/authRepeatVariations.csv b/REGRESSION/resources/data/variations/auth/authRepeatVariations.csv
new file mode 100644
index 0000000..662ab10
--- /dev/null
+++ b/REGRESSION/resources/data/variations/auth/authRepeatVariations.csv
@@ -0,0 +1,4 @@
+value
+repeat-resource-1
+repeat-resource-2
+repeat-resource-3
\ No newline at end of file
diff --git a/REGRESSION/resources/data/variations/auth/authVariations.csv b/REGRESSION/resources/data/variations/auth/authVariations.csv
new file mode 100644
index 0000000..a902f6a
--- /dev/null
+++ b/REGRESSION/resources/data/variations/auth/authVariations.csv
@@ -0,0 +1,3 @@
+authComment,authLoginEndpoint,httpComment,httpEndpoint,expected_2,value
+Authenticate first JWT variation,api/test/auth/jwt/login,Create first protected variation resource,api/test/auth/jwt/resource,expected_2_1,repeat-resource-1
+Authenticate second JWT variation,api/test/auth/jwt/login,Create second protected variation resource,api/test/auth/jwt/resource,expected_2_2,repeat-resource-2
\ No newline at end of file
diff --git a/REGRESSION/resources/data/variations/graphql/graphqlRepeat.csv b/REGRESSION/resources/data/variations/graphql/graphqlRepeat.csv
new file mode 100644
index 0000000..116ea2d
--- /dev/null
+++ b/REGRESSION/resources/data/variations/graphql/graphqlRepeat.csv
@@ -0,0 +1,4 @@
+title,author,number,expected_1
+Repeat Book 1,Vadym,1,expected_2_1
+Repeat Book 2,Taras,2,expected_2_2
+Repeat Book 3,Knubisoft,3,expected_2_3
\ No newline at end of file
diff --git a/REGRESSION/resources/data/variations/graphql/graphqlRepeatVariations.csv b/REGRESSION/resources/data/variations/graphql/graphqlRepeatVariations.csv
new file mode 100644
index 0000000..e82f778
--- /dev/null
+++ b/REGRESSION/resources/data/variations/graphql/graphqlRepeatVariations.csv
@@ -0,0 +1,4 @@
+title,author,number,expected_file
+Repeat Book One,Vadym,1,expected_2
+Repeat Book Two,Taras,2,expected_3
+Repeat Book Three,Knubisoft,3,expected_4
\ No newline at end of file
diff --git a/REGRESSION/resources/data/variations/graphql/graphqlVariations.csv b/REGRESSION/resources/data/variations/graphql/graphqlVariations.csv
new file mode 100644
index 0000000..5c00ea8
--- /dev/null
+++ b/REGRESSION/resources/data/variations/graphql/graphqlVariations.csv
@@ -0,0 +1,3 @@
+comment,title,author,number,expected_1
+Step 1-4. Create first GraphQL book using first variation row,Variation Book One,Vadym,1,expected_1_1
+Step 1-4. Create second GraphQL book using second variation row,Variation Book Two,Taras,2,expected_1_2
\ No newline at end of file
diff --git a/REGRESSION/resources/data/variations/http/httpRepeatVariations.csv b/REGRESSION/resources/data/variations/http/httpRepeatVariations.csv
new file mode 100644
index 0000000..ed1e7c9
--- /dev/null
+++ b/REGRESSION/resources/data/variations/http/httpRepeatVariations.csv
@@ -0,0 +1,4 @@
+name,description,status,category
+Repeat Variation One,Created from first repeat variation,NEW,REPEAT_ONE
+Repeat Variation Two,Created from second repeat variation,ACTIVE,REPEAT_TWO
+Repeat Variation Three,Created from third repeat variation,ARCHIVED,REPEAT_THREE
\ No newline at end of file
diff --git a/REGRESSION/resources/data/variations/http/httpVariations.csv b/REGRESSION/resources/data/variations/http/httpVariations.csv
new file mode 100644
index 0000000..d396da6
--- /dev/null
+++ b/REGRESSION/resources/data/variations/http/httpVariations.csv
@@ -0,0 +1,3 @@
+comment,endpoint,name,description,status,category,expected_1
+Step 1-4. Create first entity using first variation row,api/test/entities,Variation Entity One,Created from first variation,NEW,VARIATION_ONE,expected_1_1
+Step 1-4. Create second entity using second variation row,api/test/entities,Variation Entity Two,Created from second variation,ACTIVE,VARIATION_TWO,expected_1_2
\ No newline at end of file
diff --git a/REGRESSION/resources/data/variations/websocket/websocketStandardVariations.csv b/REGRESSION/resources/data/variations/websocket/websocketStandardVariations.csv
new file mode 100644
index 0000000..6b7a274
--- /dev/null
+++ b/REGRESSION/resources/data/variations/websocket/websocketStandardVariations.csv
@@ -0,0 +1,3 @@
+wsComment,sendComment,receiveComment,message,expected_2
+WS variation 1,Send hello message,Receive hello echo,hello websocket,expected_2_1
+WS variation 2,Send ping message,Receive ping echo,ping,expected_2_2
diff --git a/REGRESSION/resources/data/variations/websocket/websocketStompVariations.csv b/REGRESSION/resources/data/variations/websocket/websocketStompVariations.csv
new file mode 100644
index 0000000..a311031
--- /dev/null
+++ b/REGRESSION/resources/data/variations/websocket/websocketStompVariations.csv
@@ -0,0 +1,3 @@
+comment,subscribeComment,sendComment,receiveComment,endpoint,topic,message,expected_2
+STOMP variation 1,Subscribe to ping,Send ping,Receive ping,app/ping,topic/ping,hello stomp,expected_2_1
+STOMP variation 2,Subscribe to ping,Send test,Receive test,app/ping,topic/ping,test message,expected_2_2
\ No newline at end of file
diff --git a/REGRESSION/resources/scenarios/auth/basic/autoLogout/disable/expected_1.json b/REGRESSION/resources/scenarios/auth/basic/autoLogout/disable/expected_1.json
new file mode 100644
index 0000000..b0cb1c5
--- /dev/null
+++ b/REGRESSION/resources/scenarios/auth/basic/autoLogout/disable/expected_1.json
@@ -0,0 +1,5 @@
+{
+ "status": "UNAUTHORIZED",
+ "message": "Missing Authorization header",
+ "timestamp": "p(any)"
+}
\ No newline at end of file
diff --git a/REGRESSION/resources/scenarios/auth/basic/autoLogout/disable/expected_3.json b/REGRESSION/resources/scenarios/auth/basic/autoLogout/disable/expected_3.json
new file mode 100644
index 0000000..277bac5
--- /dev/null
+++ b/REGRESSION/resources/scenarios/auth/basic/autoLogout/disable/expected_3.json
@@ -0,0 +1,6 @@
+[
+ {
+ "username": "testlum",
+ "role": "ADMIN"
+ }
+]
\ No newline at end of file
diff --git a/REGRESSION/resources/scenarios/auth/basic/autoLogout/disable/expected_4.json b/REGRESSION/resources/scenarios/auth/basic/autoLogout/disable/expected_4.json
new file mode 100644
index 0000000..d6aed63
--- /dev/null
+++ b/REGRESSION/resources/scenarios/auth/basic/autoLogout/disable/expected_4.json
@@ -0,0 +1,4 @@
+[ {
+ "username" : "testlum",
+ "role" : "ADMIN"
+} ]
\ No newline at end of file
diff --git a/REGRESSION/resources/scenarios/auth/basic/autoLogout/disable/scenario.xml b/REGRESSION/resources/scenarios/auth/basic/autoLogout/disable/scenario.xml
new file mode 100644
index 0000000..4e695af
--- /dev/null
+++ b/REGRESSION/resources/scenarios/auth/basic/autoLogout/disable/scenario.xml
@@ -0,0 +1,69 @@
+
+
+
+
+ This scenario verifies Basic Authentication behavior when autoLogout is disabled.
+
+ Test flow includes:
+ 1. Send request without Authorization header → expect 401.
+ 2. Apply Basic Auth via auth tag.
+ 3. Send GET request → expect 200.
+ 4. Create new user → expect 200.
+ 5. Verify updated user list.
+ 6. Exit auth block.
+ 7. Send request again outside auth block → expect 200 because autoLogout=false.
+ 8. Reset test data.
+
+ This scenario validates:
+ - Basic Auth header injection inside auth block
+ - Protected endpoint access with valid credentials
+ - Authorization header persistence after auth block
+ - Continued authorized access after leaving auth block when autoLogout is disabled
+
+ Auth Basic AutoLogout Disabled
+ Vadym Kostenko
+
+
+
+ auth
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/REGRESSION/resources/scenarios/auth/basic/autoLogout/enable/expected_1.json b/REGRESSION/resources/scenarios/auth/basic/autoLogout/enable/expected_1.json
new file mode 100644
index 0000000..b0cb1c5
--- /dev/null
+++ b/REGRESSION/resources/scenarios/auth/basic/autoLogout/enable/expected_1.json
@@ -0,0 +1,5 @@
+{
+ "status": "UNAUTHORIZED",
+ "message": "Missing Authorization header",
+ "timestamp": "p(any)"
+}
\ No newline at end of file
diff --git a/REGRESSION/resources/scenarios/auth/basic/autoLogout/enable/expected_3.json b/REGRESSION/resources/scenarios/auth/basic/autoLogout/enable/expected_3.json
new file mode 100644
index 0000000..277bac5
--- /dev/null
+++ b/REGRESSION/resources/scenarios/auth/basic/autoLogout/enable/expected_3.json
@@ -0,0 +1,6 @@
+[
+ {
+ "username": "testlum",
+ "role": "ADMIN"
+ }
+]
\ No newline at end of file
diff --git a/REGRESSION/resources/scenarios/auth/basic/autoLogout/enable/expected_5.json b/REGRESSION/resources/scenarios/auth/basic/autoLogout/enable/expected_5.json
new file mode 100644
index 0000000..b0cb1c5
--- /dev/null
+++ b/REGRESSION/resources/scenarios/auth/basic/autoLogout/enable/expected_5.json
@@ -0,0 +1,5 @@
+{
+ "status": "UNAUTHORIZED",
+ "message": "Missing Authorization header",
+ "timestamp": "p(any)"
+}
\ No newline at end of file
diff --git a/REGRESSION/resources/scenarios/auth/basic/autoLogout/enable/scenario.xml b/REGRESSION/resources/scenarios/auth/basic/autoLogout/enable/scenario.xml
new file mode 100644
index 0000000..e520f1b
--- /dev/null
+++ b/REGRESSION/resources/scenarios/auth/basic/autoLogout/enable/scenario.xml
@@ -0,0 +1,67 @@
+
+
+
+
+ This scenario verifies Basic Authentication behavior when autoLogout is enabled.
+
+ Test flow includes:
+ 1. Send request without Authorization header → expect 401.
+ 2. Apply Basic Auth via auth tag.
+ 3. Send GET request → expect 200.
+ 4. Create new user → expect 200.
+ 5. Verify updated user list.
+ 6. Exit auth block.
+ 7. Send request again without Authorization header → expect 401 because autoLogout=true.
+ 8. Reset test data.
+
+ This scenario validates:
+ - Basic Auth header injection inside auth block
+ - Protected endpoint access with valid credentials
+ - Automatic Authorization header cleanup after auth block
+ - Unauthorized access after leaving auth block when autoLogout is enabled
+
+ Auth Basic AutoLogout Enabled
+ Vadym Kostenko
+
+
+
+ auth
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/REGRESSION/resources/scenarios/auth/condition/expected_3.json b/REGRESSION/resources/scenarios/auth/condition/expected_3.json
new file mode 100644
index 0000000..38e056b
--- /dev/null
+++ b/REGRESSION/resources/scenarios/auth/condition/expected_3.json
@@ -0,0 +1,5 @@
+{
+ "values": [
+ "secure-resource"
+ ]
+}
\ No newline at end of file
diff --git a/REGRESSION/resources/scenarios/auth/condition/expected_7.json b/REGRESSION/resources/scenarios/auth/condition/expected_7.json
new file mode 100644
index 0000000..e69de29
diff --git a/REGRESSION/resources/scenarios/auth/condition/scenario.xml b/REGRESSION/resources/scenarios/auth/condition/scenario.xml
new file mode 100644
index 0000000..13388d0
--- /dev/null
+++ b/REGRESSION/resources/scenarios/auth/condition/scenario.xml
@@ -0,0 +1,79 @@
+
+
+
+ Auth JWT Condition
+
+ This scenario verifies interaction between JWT authentication flow and condition command using auth tag.
+
+ Test flow includes:
+ 1. Create true condition.
+ 2. Authenticate using auth command with condition=true.
+ 3. Execute protected request inside auth block.
+ 4. Verify authenticated access works correctly.
+ 5. Create false condition.
+ 6. Try to execute second auth block with invalid credentials and condition=false.
+ 7. Verify false-condition auth block is skipped completely.
+ 8. Reset JWT auth state after test.
+
+ This scenario validates:
+ - JWT auth integration via auth tag
+ - Condition-based auth block execution
+ - Skipped auth execution for false condition
+ - Safe skipping of invalid auth block
+
+ Vadym Kostenko
+
+
+
+ auth
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/REGRESSION/resources/scenarios/auth/customAuth/autoLogout/disable/expected_1.json b/REGRESSION/resources/scenarios/auth/customAuth/autoLogout/disable/expected_1.json
new file mode 100644
index 0000000..c2e0af3
--- /dev/null
+++ b/REGRESSION/resources/scenarios/auth/customAuth/autoLogout/disable/expected_1.json
@@ -0,0 +1,5 @@
+{
+ "status" : "UNAUTHORIZED",
+ "message" : "Missing Authorization header",
+ "timestamp" : "p(any)"
+}
\ No newline at end of file
diff --git a/REGRESSION/resources/scenarios/auth/customAuth/autoLogout/disable/expected_3.json b/REGRESSION/resources/scenarios/auth/customAuth/autoLogout/disable/expected_3.json
new file mode 100644
index 0000000..ed8b2c9
--- /dev/null
+++ b/REGRESSION/resources/scenarios/auth/customAuth/autoLogout/disable/expected_3.json
@@ -0,0 +1,4 @@
+{
+ "message" : "Custom auth access granted",
+ "authType" : "CUSTOM"
+}
\ No newline at end of file
diff --git a/REGRESSION/resources/scenarios/auth/customAuth/autoLogout/disable/expected_4.json b/REGRESSION/resources/scenarios/auth/customAuth/autoLogout/disable/expected_4.json
new file mode 100644
index 0000000..ed8b2c9
--- /dev/null
+++ b/REGRESSION/resources/scenarios/auth/customAuth/autoLogout/disable/expected_4.json
@@ -0,0 +1,4 @@
+{
+ "message" : "Custom auth access granted",
+ "authType" : "CUSTOM"
+}
\ No newline at end of file
diff --git a/REGRESSION/resources/scenarios/auth/customAuth/autoLogout/disable/scenario.xml b/REGRESSION/resources/scenarios/auth/customAuth/autoLogout/disable/scenario.xml
new file mode 100644
index 0000000..3622547
--- /dev/null
+++ b/REGRESSION/resources/scenarios/auth/customAuth/autoLogout/disable/scenario.xml
@@ -0,0 +1,68 @@
+
+
+
+ Auth Custom AutoLogout Disabled
+
+ This scenario verifies Custom Authentication behavior when autoLogout is disabled.
+
+ Test flow includes:
+ 1. Send request without Authorization header → expect 401.
+ 2. Apply Custom Auth via auth tag.
+ 3. Send GET request inside auth block → expect 200.
+ 4. Verify protected response body and X-Auth-Type header.
+ 5. Exit auth block.
+ 6. Send request again outside auth block → expect 200 because autoLogout=false.
+ 7. Reset test data.
+
+ This scenario validates:
+ - Custom auth login flow via auth command
+ - Custom Authorization header injection inside auth block
+ - Protected endpoint access with valid custom token
+ - Authorization persistence after leaving auth block
+ - Continued authorized access when autoLogout is disabled
+
+ Vadym Kostenko
+
+
+
+ auth
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/REGRESSION/resources/scenarios/auth/customAuth/autoLogout/enable/expected_1.json b/REGRESSION/resources/scenarios/auth/customAuth/autoLogout/enable/expected_1.json
new file mode 100644
index 0000000..c2e0af3
--- /dev/null
+++ b/REGRESSION/resources/scenarios/auth/customAuth/autoLogout/enable/expected_1.json
@@ -0,0 +1,5 @@
+{
+ "status" : "UNAUTHORIZED",
+ "message" : "Missing Authorization header",
+ "timestamp" : "p(any)"
+}
\ No newline at end of file
diff --git a/REGRESSION/resources/scenarios/auth/customAuth/autoLogout/enable/expected_3.json b/REGRESSION/resources/scenarios/auth/customAuth/autoLogout/enable/expected_3.json
new file mode 100644
index 0000000..ed8b2c9
--- /dev/null
+++ b/REGRESSION/resources/scenarios/auth/customAuth/autoLogout/enable/expected_3.json
@@ -0,0 +1,4 @@
+{
+ "message" : "Custom auth access granted",
+ "authType" : "CUSTOM"
+}
\ No newline at end of file
diff --git a/REGRESSION/resources/scenarios/auth/customAuth/autoLogout/enable/expected_5.json b/REGRESSION/resources/scenarios/auth/customAuth/autoLogout/enable/expected_5.json
new file mode 100644
index 0000000..c2e0af3
--- /dev/null
+++ b/REGRESSION/resources/scenarios/auth/customAuth/autoLogout/enable/expected_5.json
@@ -0,0 +1,5 @@
+{
+ "status" : "UNAUTHORIZED",
+ "message" : "Missing Authorization header",
+ "timestamp" : "p(any)"
+}
\ No newline at end of file
diff --git a/REGRESSION/resources/scenarios/auth/customAuth/autoLogout/enable/scenario.xml b/REGRESSION/resources/scenarios/auth/customAuth/autoLogout/enable/scenario.xml
new file mode 100644
index 0000000..ad257fd
--- /dev/null
+++ b/REGRESSION/resources/scenarios/auth/customAuth/autoLogout/enable/scenario.xml
@@ -0,0 +1,68 @@
+
+
+
+ Auth Custom AutoLogout Enabled
+
+ This scenario verifies Custom Authentication behavior when autoLogout is enabled.
+
+ Test flow includes:
+ 1. Send request without Authorization header → expect 401.
+ 2. Apply Custom Auth via auth tag.
+ 3. Send GET request inside auth block → expect 200.
+ 4. Verify protected response body and X-Auth-Type header.
+ 5. Exit auth block.
+ 6. Send request again without Authorization header → expect 401 because autoLogout=true.
+ 7. Reset test data.
+
+ This scenario validates:
+ - Custom auth login flow via auth command
+ - Custom Authorization header injection inside auth block
+ - Protected endpoint access with valid custom token
+ - Automatic Authorization cleanup after leaving auth block
+ - Unauthorized access after auth block when autoLogout is enabled
+
+ Vadym Kostenko
+
+
+
+ auth
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/REGRESSION/resources/scenarios/auth/jwt/autoLogout/disable/expected_1.json b/REGRESSION/resources/scenarios/auth/jwt/autoLogout/disable/expected_1.json
new file mode 100644
index 0000000..b0cb1c5
--- /dev/null
+++ b/REGRESSION/resources/scenarios/auth/jwt/autoLogout/disable/expected_1.json
@@ -0,0 +1,5 @@
+{
+ "status": "UNAUTHORIZED",
+ "message": "Missing Authorization header",
+ "timestamp": "p(any)"
+}
\ No newline at end of file
diff --git a/REGRESSION/resources/scenarios/auth/jwt/autoLogout/disable/expected_3.json b/REGRESSION/resources/scenarios/auth/jwt/autoLogout/disable/expected_3.json
new file mode 100644
index 0000000..c7a597a
--- /dev/null
+++ b/REGRESSION/resources/scenarios/auth/jwt/autoLogout/disable/expected_3.json
@@ -0,0 +1,3 @@
+{
+ "values" : [ ]
+}
\ No newline at end of file
diff --git a/REGRESSION/resources/scenarios/auth/jwt/autoLogout/disable/expected_4.json b/REGRESSION/resources/scenarios/auth/jwt/autoLogout/disable/expected_4.json
new file mode 100644
index 0000000..c7a597a
--- /dev/null
+++ b/REGRESSION/resources/scenarios/auth/jwt/autoLogout/disable/expected_4.json
@@ -0,0 +1,3 @@
+{
+ "values" : [ ]
+}
\ No newline at end of file
diff --git a/REGRESSION/resources/scenarios/auth/jwt/autoLogout/disable/scenario.xml b/REGRESSION/resources/scenarios/auth/jwt/autoLogout/disable/scenario.xml
new file mode 100644
index 0000000..df41672
--- /dev/null
+++ b/REGRESSION/resources/scenarios/auth/jwt/autoLogout/disable/scenario.xml
@@ -0,0 +1,68 @@
+
+
+
+ Auth JWT AutoLogout Disabled
+
+ This scenario verifies JWT Authentication behavior when autoLogout is disabled.
+
+ Test flow includes:
+ 1. Send request without Authorization header → expect 401.
+ 2. Authenticate via auth tag using JWT login flow.
+ 3. Send GET request inside auth block → expect 200.
+ 4. Verify protected response body and X-Auth-Type header.
+ 5. Exit auth block.
+ 6. Send request again outside auth block → expect 200 because autoLogout=false.
+ 7. Reset JWT auth state.
+
+ This scenario validates:
+ - JWT token retrieval via auth command
+ - Automatic Bearer token injection inside auth block
+ - Protected endpoint access with valid JWT token
+ - Authorization persistence after leaving auth block
+ - Continued authorized access when autoLogout is disabled
+
+ Vadym Kostenko
+
+
+
+ auth
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/REGRESSION/resources/scenarios/auth/jwt/autoLogout/enable/expected_1.json b/REGRESSION/resources/scenarios/auth/jwt/autoLogout/enable/expected_1.json
new file mode 100644
index 0000000..b0cb1c5
--- /dev/null
+++ b/REGRESSION/resources/scenarios/auth/jwt/autoLogout/enable/expected_1.json
@@ -0,0 +1,5 @@
+{
+ "status": "UNAUTHORIZED",
+ "message": "Missing Authorization header",
+ "timestamp": "p(any)"
+}
\ No newline at end of file
diff --git a/REGRESSION/resources/scenarios/auth/jwt/autoLogout/enable/expected_3.json b/REGRESSION/resources/scenarios/auth/jwt/autoLogout/enable/expected_3.json
new file mode 100644
index 0000000..c7a597a
--- /dev/null
+++ b/REGRESSION/resources/scenarios/auth/jwt/autoLogout/enable/expected_3.json
@@ -0,0 +1,3 @@
+{
+ "values" : [ ]
+}
\ No newline at end of file
diff --git a/REGRESSION/resources/scenarios/auth/jwt/autoLogout/enable/expected_5.json b/REGRESSION/resources/scenarios/auth/jwt/autoLogout/enable/expected_5.json
new file mode 100644
index 0000000..b0cb1c5
--- /dev/null
+++ b/REGRESSION/resources/scenarios/auth/jwt/autoLogout/enable/expected_5.json
@@ -0,0 +1,5 @@
+{
+ "status": "UNAUTHORIZED",
+ "message": "Missing Authorization header",
+ "timestamp": "p(any)"
+}
\ No newline at end of file
diff --git a/REGRESSION/resources/scenarios/auth/jwt/autoLogout/enable/scenario.xml b/REGRESSION/resources/scenarios/auth/jwt/autoLogout/enable/scenario.xml
new file mode 100644
index 0000000..5925d98
--- /dev/null
+++ b/REGRESSION/resources/scenarios/auth/jwt/autoLogout/enable/scenario.xml
@@ -0,0 +1,68 @@
+
+
+
+ Auth JWT AutoLogout Enabled
+
+ This scenario verifies JWT Authentication behavior when autoLogout is enabled.
+
+ Test flow includes:
+ 1. Send request without Authorization header → expect 401.
+ 2. Authenticate via auth tag using JWT login flow.
+ 3. Send GET request inside auth block → expect 200.
+ 4. Verify protected response body and X-Auth-Type header.
+ 5. Exit auth block.
+ 6. Send request again without Authorization header → expect 401 because autoLogout=true.
+ 7. Reset JWT auth state.
+
+ This scenario validates:
+ - JWT token retrieval via auth command
+ - Automatic Bearer token injection inside auth block
+ - Protected endpoint access with valid JWT token
+ - Automatic Authorization cleanup after leaving auth block
+ - Unauthorized access after auth block when autoLogout is enabled
+
+ Vadym Kostenko
+
+
+
+ auth
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/REGRESSION/resources/scenarios/auth/repeat/time/expected_6.json b/REGRESSION/resources/scenarios/auth/repeat/time/expected_6.json
new file mode 100644
index 0000000..6d43f49
--- /dev/null
+++ b/REGRESSION/resources/scenarios/auth/repeat/time/expected_6.json
@@ -0,0 +1,7 @@
+{
+ "values": [
+ "repeat-resource",
+ "repeat-resource",
+ "repeat-resource"
+ ]
+}
\ No newline at end of file
diff --git a/REGRESSION/resources/scenarios/auth/repeat/time/scenario.xml b/REGRESSION/resources/scenarios/auth/repeat/time/scenario.xml
new file mode 100644
index 0000000..a0b4472
--- /dev/null
+++ b/REGRESSION/resources/scenarios/auth/repeat/time/scenario.xml
@@ -0,0 +1,71 @@
+
+
+
+ Auth JWT Repeat Times
+
+ This scenario verifies JWT authentication flow inside repeat block using times.
+
+ Test flow includes:
+ 1. Authenticate via auth tag.
+ 2. Execute repeat block 3 times inside authenticated context.
+ 3. Create protected resource on each iteration.
+ 4. Verify each create response = 200.
+ 5. After repeat, retrieve all protected resources.
+ 6. Verify that 3 resources were created.
+ 7. Reset JWT auth state.
+
+ This scenario validates:
+ - JWT authentication wrapping repeat command
+ - Repeated resource creation inside auth context
+ - Stable token reuse across iterations
+ - Correct accumulation of repeated executions
+
+ Vadym Kostenko
+
+
+
+ auth
+
+
+
+
+
+
+
+
+
+
+ {
+ "value": "repeat-resource"
+ }
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/REGRESSION/resources/scenarios/auth/repeat/variations/expected_6.json b/REGRESSION/resources/scenarios/auth/repeat/variations/expected_6.json
new file mode 100644
index 0000000..f6aa594
--- /dev/null
+++ b/REGRESSION/resources/scenarios/auth/repeat/variations/expected_6.json
@@ -0,0 +1,7 @@
+{
+ "values": [
+ "repeat-resource-1",
+ "repeat-resource-2",
+ "repeat-resource-3"
+ ]
+}
\ No newline at end of file
diff --git a/REGRESSION/resources/scenarios/auth/repeat/variations/scenario.xml b/REGRESSION/resources/scenarios/auth/repeat/variations/scenario.xml
new file mode 100644
index 0000000..1e2d9d5
--- /dev/null
+++ b/REGRESSION/resources/scenarios/auth/repeat/variations/scenario.xml
@@ -0,0 +1,73 @@
+
+
+
+ Auth JWT Repeat Variations
+
+ This scenario verifies JWT authentication flow inside repeat block using variations.
+
+ Test flow includes:
+ 1. Authenticate via auth tag.
+ 2. Execute repeat block for each variation row.
+ 3. Create protected resource using variation values.
+ 4. Verify create response = 200 for each iteration.
+ 5. Retrieve all protected resources after repeat execution.
+ 6. Verify that all variation resources were created.
+ 7. Reset JWT auth state.
+
+ This scenario validates:
+ - JWT authentication wrapping repeat command
+ - Repeated execution with variation data
+ - Correct interpolation of variation values
+ - Resource accumulation across all iterations
+ - Stable repeated auth execution
+
+ Vadym Kostenko
+
+
+
+ auth
+
+
+
+
+
+
+
+
+
+
+
+ {
+ "value": "{{value}}"
+ }
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/REGRESSION/resources/scenarios/auth/variable/expected_7.json b/REGRESSION/resources/scenarios/auth/variable/expected_7.json
new file mode 100644
index 0000000..15f9c4b
--- /dev/null
+++ b/REGRESSION/resources/scenarios/auth/variable/expected_7.json
@@ -0,0 +1,5 @@
+{
+ "values": [
+ "{{resourceValue}}"
+ ]
+}
\ No newline at end of file
diff --git a/REGRESSION/resources/scenarios/auth/variable/expected_8.json b/REGRESSION/resources/scenarios/auth/variable/expected_8.json
new file mode 100644
index 0000000..15f9c4b
--- /dev/null
+++ b/REGRESSION/resources/scenarios/auth/variable/expected_8.json
@@ -0,0 +1,5 @@
+{
+ "values": [
+ "{{resourceValue}}"
+ ]
+}
\ No newline at end of file
diff --git a/REGRESSION/resources/scenarios/auth/variable/scenario.xml b/REGRESSION/resources/scenarios/auth/variable/scenario.xml
new file mode 100644
index 0000000..86f4469
--- /dev/null
+++ b/REGRESSION/resources/scenarios/auth/variable/scenario.xml
@@ -0,0 +1,108 @@
+
+
+
+ Auth JWT Variable
+
+ This scenario verifies JWT authentication flow using variables.
+
+ Test flow includes:
+ 1. Create variables for comments, login endpoint, protected endpoint, reset endpoint, condition and request values.
+ 2. Authenticate via auth tag using variable-based login endpoint.
+ 3. Create protected resource using variable-based endpoint and body.
+ 4. Verify create response = 200 using expected file with injected variables.
+ 5. Reset JWT auth state using variable-based endpoint.
+
+ This scenario validates:
+ - Variable injection into auth tag attributes
+ - Variable injection into auth and http comments
+ - Variable injection into condition
+ - Variable injection into HTTP endpoints
+ - Variable injection into request body
+ - Variable injection into expected file content
+ - Variable reuse across authenticated JWT flow
+
+ Vadym Kostenko
+
+
+
+ auth
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {
+ "value": "{{resourceValue}}"
+ }
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/REGRESSION/resources/scenarios/auth/variations/expected_2_1.json b/REGRESSION/resources/scenarios/auth/variations/expected_2_1.json
new file mode 100644
index 0000000..caabe93
--- /dev/null
+++ b/REGRESSION/resources/scenarios/auth/variations/expected_2_1.json
@@ -0,0 +1,3 @@
+{
+ "values" : [ "{{value}}" ]
+}
\ No newline at end of file
diff --git a/REGRESSION/resources/scenarios/auth/variations/expected_2_2.json b/REGRESSION/resources/scenarios/auth/variations/expected_2_2.json
new file mode 100644
index 0000000..caabe93
--- /dev/null
+++ b/REGRESSION/resources/scenarios/auth/variations/expected_2_2.json
@@ -0,0 +1,3 @@
+{
+ "values" : [ "{{value}}" ]
+}
\ No newline at end of file
diff --git a/REGRESSION/resources/scenarios/auth/variations/scenario.xml b/REGRESSION/resources/scenarios/auth/variations/scenario.xml
new file mode 100644
index 0000000..782c56a
--- /dev/null
+++ b/REGRESSION/resources/scenarios/auth/variations/scenario.xml
@@ -0,0 +1,62 @@
+
+
+
+ Auth JWT Variations
+
+ This scenario verifies JWT authentication flow using variation data.
+
+ Test flow includes:
+ 1. Load variation data from CSV file.
+ 2. Authenticate via auth tag using variation-based auth attributes.
+ 3. Create protected resource using variation-based request data.
+ 4. Verify create response = 200 using variation-based expected file.
+ 5. Reset JWT auth state after all variation executions.
+
+ This scenario validates:
+ - Variation injection into auth comment
+ - Variation injection into auth login endpoint
+ - Variation injection into nested http comment
+ - Variation injection into nested http endpoint
+ - Variation injection into request body
+ - Variation injection into expected file names
+ - Stable repeated authenticated execution
+
+ Vadym Kostenko
+
+
+
+ authVariations.csv
+ auth
+
+
+
+
+
+
+
+
+
+ {
+ "value": "{{value}}"
+ }
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/REGRESSION/resources/scenarios/http/auth/basic/mixed/expected_1.json b/REGRESSION/resources/scenarios/end2end/http/auth/basic/mixed/expected_1.json
similarity index 100%
rename from REGRESSION/resources/scenarios/http/auth/basic/mixed/expected_1.json
rename to REGRESSION/resources/scenarios/end2end/http/auth/basic/mixed/expected_1.json
diff --git a/REGRESSION/resources/scenarios/http/auth/basic/mixed/expected_10.json b/REGRESSION/resources/scenarios/end2end/http/auth/basic/mixed/expected_10.json
similarity index 100%
rename from REGRESSION/resources/scenarios/http/auth/basic/mixed/expected_10.json
rename to REGRESSION/resources/scenarios/end2end/http/auth/basic/mixed/expected_10.json
diff --git a/REGRESSION/resources/scenarios/http/auth/basic/mixed/expected_11.json b/REGRESSION/resources/scenarios/end2end/http/auth/basic/mixed/expected_11.json
similarity index 100%
rename from REGRESSION/resources/scenarios/http/auth/basic/mixed/expected_11.json
rename to REGRESSION/resources/scenarios/end2end/http/auth/basic/mixed/expected_11.json
diff --git a/REGRESSION/resources/scenarios/http/auth/basic/mixed/expected_13.json b/REGRESSION/resources/scenarios/end2end/http/auth/basic/mixed/expected_13.json
similarity index 100%
rename from REGRESSION/resources/scenarios/http/auth/basic/mixed/expected_13.json
rename to REGRESSION/resources/scenarios/end2end/http/auth/basic/mixed/expected_13.json
diff --git a/REGRESSION/resources/scenarios/http/auth/basic/mixed/expected_2.json b/REGRESSION/resources/scenarios/end2end/http/auth/basic/mixed/expected_2.json
similarity index 100%
rename from REGRESSION/resources/scenarios/http/auth/basic/mixed/expected_2.json
rename to REGRESSION/resources/scenarios/end2end/http/auth/basic/mixed/expected_2.json
diff --git a/REGRESSION/resources/scenarios/http/auth/basic/mixed/expected_3.json b/REGRESSION/resources/scenarios/end2end/http/auth/basic/mixed/expected_3.json
similarity index 100%
rename from REGRESSION/resources/scenarios/http/auth/basic/mixed/expected_3.json
rename to REGRESSION/resources/scenarios/end2end/http/auth/basic/mixed/expected_3.json
diff --git a/REGRESSION/resources/scenarios/http/auth/basic/mixed/expected_4.json b/REGRESSION/resources/scenarios/end2end/http/auth/basic/mixed/expected_4.json
similarity index 100%
rename from REGRESSION/resources/scenarios/http/auth/basic/mixed/expected_4.json
rename to REGRESSION/resources/scenarios/end2end/http/auth/basic/mixed/expected_4.json
diff --git a/REGRESSION/resources/scenarios/http/auth/basic/mixed/expected_5.json b/REGRESSION/resources/scenarios/end2end/http/auth/basic/mixed/expected_5.json
similarity index 100%
rename from REGRESSION/resources/scenarios/http/auth/basic/mixed/expected_5.json
rename to REGRESSION/resources/scenarios/end2end/http/auth/basic/mixed/expected_5.json
diff --git a/REGRESSION/resources/scenarios/http/auth/basic/mixed/expected_7.json b/REGRESSION/resources/scenarios/end2end/http/auth/basic/mixed/expected_7.json
similarity index 100%
rename from REGRESSION/resources/scenarios/http/auth/basic/mixed/expected_7.json
rename to REGRESSION/resources/scenarios/end2end/http/auth/basic/mixed/expected_7.json
diff --git a/REGRESSION/resources/scenarios/http/auth/basic/mixed/expected_8.json b/REGRESSION/resources/scenarios/end2end/http/auth/basic/mixed/expected_8.json
similarity index 100%
rename from REGRESSION/resources/scenarios/http/auth/basic/mixed/expected_8.json
rename to REGRESSION/resources/scenarios/end2end/http/auth/basic/mixed/expected_8.json
diff --git a/REGRESSION/resources/scenarios/http/auth/basic/mixed/scenario.xml b/REGRESSION/resources/scenarios/end2end/http/auth/basic/mixed/scenario.xml
similarity index 100%
rename from REGRESSION/resources/scenarios/http/auth/basic/mixed/scenario.xml
rename to REGRESSION/resources/scenarios/end2end/http/auth/basic/mixed/scenario.xml
diff --git a/REGRESSION/resources/scenarios/http/auth/jwt/mixed/expected_10.json b/REGRESSION/resources/scenarios/end2end/http/auth/jwt/mixed/expected_10.json
similarity index 100%
rename from REGRESSION/resources/scenarios/http/auth/jwt/mixed/expected_10.json
rename to REGRESSION/resources/scenarios/end2end/http/auth/jwt/mixed/expected_10.json
diff --git a/REGRESSION/resources/scenarios/http/auth/jwt/mixed/expected_12.json b/REGRESSION/resources/scenarios/end2end/http/auth/jwt/mixed/expected_12.json
similarity index 100%
rename from REGRESSION/resources/scenarios/http/auth/jwt/mixed/expected_12.json
rename to REGRESSION/resources/scenarios/end2end/http/auth/jwt/mixed/expected_12.json
diff --git a/REGRESSION/resources/scenarios/http/auth/jwt/mixed/expected_13.json b/REGRESSION/resources/scenarios/end2end/http/auth/jwt/mixed/expected_13.json
similarity index 100%
rename from REGRESSION/resources/scenarios/http/auth/jwt/mixed/expected_13.json
rename to REGRESSION/resources/scenarios/end2end/http/auth/jwt/mixed/expected_13.json
diff --git a/REGRESSION/resources/scenarios/http/auth/jwt/mixed/expected_14.json b/REGRESSION/resources/scenarios/end2end/http/auth/jwt/mixed/expected_14.json
similarity index 100%
rename from REGRESSION/resources/scenarios/http/auth/jwt/mixed/expected_14.json
rename to REGRESSION/resources/scenarios/end2end/http/auth/jwt/mixed/expected_14.json
diff --git a/REGRESSION/resources/scenarios/http/auth/jwt/mixed/expected_16.json b/REGRESSION/resources/scenarios/end2end/http/auth/jwt/mixed/expected_16.json
similarity index 100%
rename from REGRESSION/resources/scenarios/http/auth/jwt/mixed/expected_16.json
rename to REGRESSION/resources/scenarios/end2end/http/auth/jwt/mixed/expected_16.json
diff --git a/REGRESSION/resources/scenarios/http/auth/jwt/mixed/expected_2.json b/REGRESSION/resources/scenarios/end2end/http/auth/jwt/mixed/expected_2.json
similarity index 100%
rename from REGRESSION/resources/scenarios/http/auth/jwt/mixed/expected_2.json
rename to REGRESSION/resources/scenarios/end2end/http/auth/jwt/mixed/expected_2.json
diff --git a/REGRESSION/resources/scenarios/http/auth/jwt/mixed/expected_3.json b/REGRESSION/resources/scenarios/end2end/http/auth/jwt/mixed/expected_3.json
similarity index 100%
rename from REGRESSION/resources/scenarios/http/auth/jwt/mixed/expected_3.json
rename to REGRESSION/resources/scenarios/end2end/http/auth/jwt/mixed/expected_3.json
diff --git a/REGRESSION/resources/scenarios/http/auth/jwt/mixed/expected_5.json b/REGRESSION/resources/scenarios/end2end/http/auth/jwt/mixed/expected_5.json
similarity index 100%
rename from REGRESSION/resources/scenarios/http/auth/jwt/mixed/expected_5.json
rename to REGRESSION/resources/scenarios/end2end/http/auth/jwt/mixed/expected_5.json
diff --git a/REGRESSION/resources/scenarios/http/auth/jwt/mixed/expected_6.json b/REGRESSION/resources/scenarios/end2end/http/auth/jwt/mixed/expected_6.json
similarity index 100%
rename from REGRESSION/resources/scenarios/http/auth/jwt/mixed/expected_6.json
rename to REGRESSION/resources/scenarios/end2end/http/auth/jwt/mixed/expected_6.json
diff --git a/REGRESSION/resources/scenarios/http/auth/jwt/mixed/expected_7.json b/REGRESSION/resources/scenarios/end2end/http/auth/jwt/mixed/expected_7.json
similarity index 100%
rename from REGRESSION/resources/scenarios/http/auth/jwt/mixed/expected_7.json
rename to REGRESSION/resources/scenarios/end2end/http/auth/jwt/mixed/expected_7.json
diff --git a/REGRESSION/resources/scenarios/http/auth/jwt/mixed/expected_8.json b/REGRESSION/resources/scenarios/end2end/http/auth/jwt/mixed/expected_8.json
similarity index 100%
rename from REGRESSION/resources/scenarios/http/auth/jwt/mixed/expected_8.json
rename to REGRESSION/resources/scenarios/end2end/http/auth/jwt/mixed/expected_8.json
diff --git a/REGRESSION/resources/scenarios/http/auth/jwt/mixed/expected_9.json b/REGRESSION/resources/scenarios/end2end/http/auth/jwt/mixed/expected_9.json
similarity index 100%
rename from REGRESSION/resources/scenarios/http/auth/jwt/mixed/expected_9.json
rename to REGRESSION/resources/scenarios/end2end/http/auth/jwt/mixed/expected_9.json
diff --git a/REGRESSION/resources/scenarios/http/auth/jwt/mixed/scenario.xml b/REGRESSION/resources/scenarios/end2end/http/auth/jwt/mixed/scenario.xml
similarity index 100%
rename from REGRESSION/resources/scenarios/http/auth/jwt/mixed/scenario.xml
rename to REGRESSION/resources/scenarios/end2end/http/auth/jwt/mixed/scenario.xml
diff --git a/REGRESSION/resources/scenarios/http/elasticsearch/mixed/expected_1.json b/REGRESSION/resources/scenarios/end2end/http/elasticsearch/mixed/expected_1.json
similarity index 100%
rename from REGRESSION/resources/scenarios/http/elasticsearch/mixed/expected_1.json
rename to REGRESSION/resources/scenarios/end2end/http/elasticsearch/mixed/expected_1.json
diff --git a/REGRESSION/resources/scenarios/http/elasticsearch/mixed/expected_10.json b/REGRESSION/resources/scenarios/end2end/http/elasticsearch/mixed/expected_10.json
similarity index 100%
rename from REGRESSION/resources/scenarios/http/elasticsearch/mixed/expected_10.json
rename to REGRESSION/resources/scenarios/end2end/http/elasticsearch/mixed/expected_10.json
diff --git a/REGRESSION/resources/scenarios/http/elasticsearch/mixed/expected_11.json b/REGRESSION/resources/scenarios/end2end/http/elasticsearch/mixed/expected_11.json
similarity index 100%
rename from REGRESSION/resources/scenarios/http/elasticsearch/mixed/expected_11.json
rename to REGRESSION/resources/scenarios/end2end/http/elasticsearch/mixed/expected_11.json
diff --git a/REGRESSION/resources/scenarios/http/elasticsearch/mixed/expected_12.json b/REGRESSION/resources/scenarios/end2end/http/elasticsearch/mixed/expected_12.json
similarity index 100%
rename from REGRESSION/resources/scenarios/http/elasticsearch/mixed/expected_12.json
rename to REGRESSION/resources/scenarios/end2end/http/elasticsearch/mixed/expected_12.json
diff --git a/REGRESSION/resources/scenarios/http/elasticsearch/mixed/expected_14.json b/REGRESSION/resources/scenarios/end2end/http/elasticsearch/mixed/expected_14.json
similarity index 100%
rename from REGRESSION/resources/scenarios/http/elasticsearch/mixed/expected_14.json
rename to REGRESSION/resources/scenarios/end2end/http/elasticsearch/mixed/expected_14.json
diff --git a/REGRESSION/resources/scenarios/http/elasticsearch/mixed/expected_2.json b/REGRESSION/resources/scenarios/end2end/http/elasticsearch/mixed/expected_2.json
similarity index 100%
rename from REGRESSION/resources/scenarios/http/elasticsearch/mixed/expected_2.json
rename to REGRESSION/resources/scenarios/end2end/http/elasticsearch/mixed/expected_2.json
diff --git a/REGRESSION/resources/scenarios/http/elasticsearch/mixed/expected_4.json b/REGRESSION/resources/scenarios/end2end/http/elasticsearch/mixed/expected_4.json
similarity index 100%
rename from REGRESSION/resources/scenarios/http/elasticsearch/mixed/expected_4.json
rename to REGRESSION/resources/scenarios/end2end/http/elasticsearch/mixed/expected_4.json
diff --git a/REGRESSION/resources/scenarios/http/elasticsearch/mixed/expected_5.json b/REGRESSION/resources/scenarios/end2end/http/elasticsearch/mixed/expected_5.json
similarity index 100%
rename from REGRESSION/resources/scenarios/http/elasticsearch/mixed/expected_5.json
rename to REGRESSION/resources/scenarios/end2end/http/elasticsearch/mixed/expected_5.json
diff --git a/REGRESSION/resources/scenarios/http/elasticsearch/mixed/expected_6.json b/REGRESSION/resources/scenarios/end2end/http/elasticsearch/mixed/expected_6.json
similarity index 100%
rename from REGRESSION/resources/scenarios/http/elasticsearch/mixed/expected_6.json
rename to REGRESSION/resources/scenarios/end2end/http/elasticsearch/mixed/expected_6.json
diff --git a/REGRESSION/resources/scenarios/http/elasticsearch/mixed/expected_7.json b/REGRESSION/resources/scenarios/end2end/http/elasticsearch/mixed/expected_7.json
similarity index 100%
rename from REGRESSION/resources/scenarios/http/elasticsearch/mixed/expected_7.json
rename to REGRESSION/resources/scenarios/end2end/http/elasticsearch/mixed/expected_7.json
diff --git a/REGRESSION/resources/scenarios/http/elasticsearch/mixed/expected_9.json b/REGRESSION/resources/scenarios/end2end/http/elasticsearch/mixed/expected_9.json
similarity index 100%
rename from REGRESSION/resources/scenarios/http/elasticsearch/mixed/expected_9.json
rename to REGRESSION/resources/scenarios/end2end/http/elasticsearch/mixed/expected_9.json
diff --git a/REGRESSION/resources/scenarios/http/elasticsearch/mixed/request_11.json b/REGRESSION/resources/scenarios/end2end/http/elasticsearch/mixed/request_11.json
similarity index 100%
rename from REGRESSION/resources/scenarios/http/elasticsearch/mixed/request_11.json
rename to REGRESSION/resources/scenarios/end2end/http/elasticsearch/mixed/request_11.json
diff --git a/REGRESSION/resources/scenarios/http/elasticsearch/mixed/request_2.json b/REGRESSION/resources/scenarios/end2end/http/elasticsearch/mixed/request_2.json
similarity index 100%
rename from REGRESSION/resources/scenarios/http/elasticsearch/mixed/request_2.json
rename to REGRESSION/resources/scenarios/end2end/http/elasticsearch/mixed/request_2.json
diff --git a/REGRESSION/resources/scenarios/http/elasticsearch/mixed/scenario.xml b/REGRESSION/resources/scenarios/end2end/http/elasticsearch/mixed/scenario.xml
similarity index 100%
rename from REGRESSION/resources/scenarios/http/elasticsearch/mixed/scenario.xml
rename to REGRESSION/resources/scenarios/end2end/http/elasticsearch/mixed/scenario.xml
diff --git a/REGRESSION/resources/scenarios/http/elasticsearch/self/expected_1.json b/REGRESSION/resources/scenarios/end2end/http/elasticsearch/self/expected_1.json
similarity index 100%
rename from REGRESSION/resources/scenarios/http/elasticsearch/self/expected_1.json
rename to REGRESSION/resources/scenarios/end2end/http/elasticsearch/self/expected_1.json
diff --git a/REGRESSION/resources/scenarios/http/elasticsearch/self/expected_11.json b/REGRESSION/resources/scenarios/end2end/http/elasticsearch/self/expected_11.json
similarity index 100%
rename from REGRESSION/resources/scenarios/http/elasticsearch/self/expected_11.json
rename to REGRESSION/resources/scenarios/end2end/http/elasticsearch/self/expected_11.json
diff --git a/REGRESSION/resources/scenarios/http/elasticsearch/self/expected_2.json b/REGRESSION/resources/scenarios/end2end/http/elasticsearch/self/expected_2.json
similarity index 100%
rename from REGRESSION/resources/scenarios/http/elasticsearch/self/expected_2.json
rename to REGRESSION/resources/scenarios/end2end/http/elasticsearch/self/expected_2.json
diff --git a/REGRESSION/resources/scenarios/http/elasticsearch/self/expected_4.json b/REGRESSION/resources/scenarios/end2end/http/elasticsearch/self/expected_4.json
similarity index 100%
rename from REGRESSION/resources/scenarios/http/elasticsearch/self/expected_4.json
rename to REGRESSION/resources/scenarios/end2end/http/elasticsearch/self/expected_4.json
diff --git a/REGRESSION/resources/scenarios/http/elasticsearch/self/expected_5.json b/REGRESSION/resources/scenarios/end2end/http/elasticsearch/self/expected_5.json
similarity index 100%
rename from REGRESSION/resources/scenarios/http/elasticsearch/self/expected_5.json
rename to REGRESSION/resources/scenarios/end2end/http/elasticsearch/self/expected_5.json
diff --git a/REGRESSION/resources/scenarios/http/elasticsearch/self/expected_7.json b/REGRESSION/resources/scenarios/end2end/http/elasticsearch/self/expected_7.json
similarity index 100%
rename from REGRESSION/resources/scenarios/http/elasticsearch/self/expected_7.json
rename to REGRESSION/resources/scenarios/end2end/http/elasticsearch/self/expected_7.json
diff --git a/REGRESSION/resources/scenarios/http/elasticsearch/self/expected_8.json b/REGRESSION/resources/scenarios/end2end/http/elasticsearch/self/expected_8.json
similarity index 100%
rename from REGRESSION/resources/scenarios/http/elasticsearch/self/expected_8.json
rename to REGRESSION/resources/scenarios/end2end/http/elasticsearch/self/expected_8.json
diff --git a/REGRESSION/resources/scenarios/http/elasticsearch/self/expected_9.json b/REGRESSION/resources/scenarios/end2end/http/elasticsearch/self/expected_9.json
similarity index 100%
rename from REGRESSION/resources/scenarios/http/elasticsearch/self/expected_9.json
rename to REGRESSION/resources/scenarios/end2end/http/elasticsearch/self/expected_9.json
diff --git a/REGRESSION/resources/scenarios/http/elasticsearch/self/request_2.json b/REGRESSION/resources/scenarios/end2end/http/elasticsearch/self/request_2.json
similarity index 100%
rename from REGRESSION/resources/scenarios/http/elasticsearch/self/request_2.json
rename to REGRESSION/resources/scenarios/end2end/http/elasticsearch/self/request_2.json
diff --git a/REGRESSION/resources/scenarios/http/elasticsearch/self/request_8.json b/REGRESSION/resources/scenarios/end2end/http/elasticsearch/self/request_8.json
similarity index 100%
rename from REGRESSION/resources/scenarios/http/elasticsearch/self/request_8.json
rename to REGRESSION/resources/scenarios/end2end/http/elasticsearch/self/request_8.json
diff --git a/REGRESSION/resources/scenarios/http/elasticsearch/self/scenario.xml b/REGRESSION/resources/scenarios/end2end/http/elasticsearch/self/scenario.xml
similarity index 100%
rename from REGRESSION/resources/scenarios/http/elasticsearch/self/scenario.xml
rename to REGRESSION/resources/scenarios/end2end/http/elasticsearch/self/scenario.xml
diff --git a/REGRESSION/resources/scenarios/http/graphql/expected_2.json b/REGRESSION/resources/scenarios/end2end/http/graphql/expected_2.json
similarity index 100%
rename from REGRESSION/resources/scenarios/http/graphql/expected_2.json
rename to REGRESSION/resources/scenarios/end2end/http/graphql/expected_2.json
diff --git a/REGRESSION/resources/scenarios/http/graphql/expected_3.json b/REGRESSION/resources/scenarios/end2end/http/graphql/expected_3.json
similarity index 100%
rename from REGRESSION/resources/scenarios/http/graphql/expected_3.json
rename to REGRESSION/resources/scenarios/end2end/http/graphql/expected_3.json
diff --git a/REGRESSION/resources/scenarios/http/graphql/expected_4.json b/REGRESSION/resources/scenarios/end2end/http/graphql/expected_4.json
similarity index 100%
rename from REGRESSION/resources/scenarios/http/graphql/expected_4.json
rename to REGRESSION/resources/scenarios/end2end/http/graphql/expected_4.json
diff --git a/REGRESSION/resources/scenarios/http/graphql/expected_5.json b/REGRESSION/resources/scenarios/end2end/http/graphql/expected_5.json
similarity index 100%
rename from REGRESSION/resources/scenarios/http/graphql/expected_5.json
rename to REGRESSION/resources/scenarios/end2end/http/graphql/expected_5.json
diff --git a/REGRESSION/resources/scenarios/http/graphql/expected_6.json b/REGRESSION/resources/scenarios/end2end/http/graphql/expected_6.json
similarity index 100%
rename from REGRESSION/resources/scenarios/http/graphql/expected_6.json
rename to REGRESSION/resources/scenarios/end2end/http/graphql/expected_6.json
diff --git a/REGRESSION/resources/scenarios/http/graphql/expected_7.json b/REGRESSION/resources/scenarios/end2end/http/graphql/expected_7.json
similarity index 100%
rename from REGRESSION/resources/scenarios/http/graphql/expected_7.json
rename to REGRESSION/resources/scenarios/end2end/http/graphql/expected_7.json
diff --git a/REGRESSION/resources/scenarios/http/graphql/expected_8.json b/REGRESSION/resources/scenarios/end2end/http/graphql/expected_8.json
similarity index 100%
rename from REGRESSION/resources/scenarios/http/graphql/expected_8.json
rename to REGRESSION/resources/scenarios/end2end/http/graphql/expected_8.json
diff --git a/REGRESSION/resources/scenarios/http/graphql/expected_9.json b/REGRESSION/resources/scenarios/end2end/http/graphql/expected_9.json
similarity index 100%
rename from REGRESSION/resources/scenarios/http/graphql/expected_9.json
rename to REGRESSION/resources/scenarios/end2end/http/graphql/expected_9.json
diff --git a/REGRESSION/resources/scenarios/http/graphql/request_2.json b/REGRESSION/resources/scenarios/end2end/http/graphql/request_2.json
similarity index 100%
rename from REGRESSION/resources/scenarios/http/graphql/request_2.json
rename to REGRESSION/resources/scenarios/end2end/http/graphql/request_2.json
diff --git a/REGRESSION/resources/scenarios/http/graphql/request_5.json b/REGRESSION/resources/scenarios/end2end/http/graphql/request_5.json
similarity index 100%
rename from REGRESSION/resources/scenarios/http/graphql/request_5.json
rename to REGRESSION/resources/scenarios/end2end/http/graphql/request_5.json
diff --git a/REGRESSION/resources/scenarios/http/graphql/request_9.json b/REGRESSION/resources/scenarios/end2end/http/graphql/request_9.json
similarity index 100%
rename from REGRESSION/resources/scenarios/http/graphql/request_9.json
rename to REGRESSION/resources/scenarios/end2end/http/graphql/request_9.json
diff --git a/REGRESSION/resources/scenarios/http/graphql/scenario.xml b/REGRESSION/resources/scenarios/end2end/http/graphql/scenario.xml
similarity index 100%
rename from REGRESSION/resources/scenarios/http/graphql/scenario.xml
rename to REGRESSION/resources/scenarios/end2end/http/graphql/scenario.xml
diff --git a/REGRESSION/resources/scenarios/http/lambda/body_2.json b/REGRESSION/resources/scenarios/end2end/http/lambda/body_2.json
similarity index 100%
rename from REGRESSION/resources/scenarios/http/lambda/body_2.json
rename to REGRESSION/resources/scenarios/end2end/http/lambda/body_2.json
diff --git a/REGRESSION/resources/scenarios/http/lambda/expected_2.json b/REGRESSION/resources/scenarios/end2end/http/lambda/expected_2.json
similarity index 100%
rename from REGRESSION/resources/scenarios/http/lambda/expected_2.json
rename to REGRESSION/resources/scenarios/end2end/http/lambda/expected_2.json
diff --git a/REGRESSION/resources/scenarios/http/lambda/expected_3.json b/REGRESSION/resources/scenarios/end2end/http/lambda/expected_3.json
similarity index 100%
rename from REGRESSION/resources/scenarios/http/lambda/expected_3.json
rename to REGRESSION/resources/scenarios/end2end/http/lambda/expected_3.json
diff --git a/REGRESSION/resources/scenarios/http/lambda/expected_4.json b/REGRESSION/resources/scenarios/end2end/http/lambda/expected_4.json
similarity index 100%
rename from REGRESSION/resources/scenarios/http/lambda/expected_4.json
rename to REGRESSION/resources/scenarios/end2end/http/lambda/expected_4.json
diff --git a/REGRESSION/resources/scenarios/http/lambda/expected_5.json b/REGRESSION/resources/scenarios/end2end/http/lambda/expected_5.json
similarity index 100%
rename from REGRESSION/resources/scenarios/http/lambda/expected_5.json
rename to REGRESSION/resources/scenarios/end2end/http/lambda/expected_5.json
diff --git a/REGRESSION/resources/scenarios/http/lambda/expected_6.json b/REGRESSION/resources/scenarios/end2end/http/lambda/expected_6.json
similarity index 100%
rename from REGRESSION/resources/scenarios/http/lambda/expected_6.json
rename to REGRESSION/resources/scenarios/end2end/http/lambda/expected_6.json
diff --git a/REGRESSION/resources/scenarios/http/lambda/expected_7.json b/REGRESSION/resources/scenarios/end2end/http/lambda/expected_7.json
similarity index 100%
rename from REGRESSION/resources/scenarios/http/lambda/expected_7.json
rename to REGRESSION/resources/scenarios/end2end/http/lambda/expected_7.json
diff --git a/REGRESSION/resources/scenarios/http/lambda/expected_8.json b/REGRESSION/resources/scenarios/end2end/http/lambda/expected_8.json
similarity index 100%
rename from REGRESSION/resources/scenarios/http/lambda/expected_8.json
rename to REGRESSION/resources/scenarios/end2end/http/lambda/expected_8.json
diff --git a/REGRESSION/resources/scenarios/http/lambda/request_3.json b/REGRESSION/resources/scenarios/end2end/http/lambda/request_3.json
similarity index 100%
rename from REGRESSION/resources/scenarios/http/lambda/request_3.json
rename to REGRESSION/resources/scenarios/end2end/http/lambda/request_3.json
diff --git a/REGRESSION/resources/scenarios/http/lambda/scenario.xml b/REGRESSION/resources/scenarios/end2end/http/lambda/scenario.xml
similarity index 100%
rename from REGRESSION/resources/scenarios/http/lambda/scenario.xml
rename to REGRESSION/resources/scenarios/end2end/http/lambda/scenario.xml
diff --git a/REGRESSION/resources/scenarios/http/multipart/animalsList.json b/REGRESSION/resources/scenarios/end2end/http/multipart/animalsList.json
similarity index 100%
rename from REGRESSION/resources/scenarios/http/multipart/animalsList.json
rename to REGRESSION/resources/scenarios/end2end/http/multipart/animalsList.json
diff --git a/REGRESSION/resources/scenarios/http/multipart/download.jpeg b/REGRESSION/resources/scenarios/end2end/http/multipart/download.jpeg
similarity index 100%
rename from REGRESSION/resources/scenarios/http/multipart/download.jpeg
rename to REGRESSION/resources/scenarios/end2end/http/multipart/download.jpeg
diff --git a/REGRESSION/resources/scenarios/http/multipart/expected_1.json b/REGRESSION/resources/scenarios/end2end/http/multipart/expected_1.json
similarity index 100%
rename from REGRESSION/resources/scenarios/http/multipart/expected_1.json
rename to REGRESSION/resources/scenarios/end2end/http/multipart/expected_1.json
diff --git a/REGRESSION/resources/scenarios/http/multipart/expected_2.json b/REGRESSION/resources/scenarios/end2end/http/multipart/expected_2.json
similarity index 100%
rename from REGRESSION/resources/scenarios/http/multipart/expected_2.json
rename to REGRESSION/resources/scenarios/end2end/http/multipart/expected_2.json
diff --git a/REGRESSION/resources/scenarios/http/multipart/expected_3.json b/REGRESSION/resources/scenarios/end2end/http/multipart/expected_3.json
similarity index 100%
rename from REGRESSION/resources/scenarios/http/multipart/expected_3.json
rename to REGRESSION/resources/scenarios/end2end/http/multipart/expected_3.json
diff --git a/REGRESSION/resources/scenarios/http/multipart/expected_4.json b/REGRESSION/resources/scenarios/end2end/http/multipart/expected_4.json
similarity index 100%
rename from REGRESSION/resources/scenarios/http/multipart/expected_4.json
rename to REGRESSION/resources/scenarios/end2end/http/multipart/expected_4.json
diff --git a/REGRESSION/resources/scenarios/http/multipart/expected_5.json b/REGRESSION/resources/scenarios/end2end/http/multipart/expected_5.json
similarity index 100%
rename from REGRESSION/resources/scenarios/http/multipart/expected_5.json
rename to REGRESSION/resources/scenarios/end2end/http/multipart/expected_5.json
diff --git a/REGRESSION/resources/scenarios/http/multipart/expected_6.json b/REGRESSION/resources/scenarios/end2end/http/multipart/expected_6.json
similarity index 100%
rename from REGRESSION/resources/scenarios/http/multipart/expected_6.json
rename to REGRESSION/resources/scenarios/end2end/http/multipart/expected_6.json
diff --git a/REGRESSION/resources/scenarios/http/multipart/image.jpg b/REGRESSION/resources/scenarios/end2end/http/multipart/image.jpg
similarity index 100%
rename from REGRESSION/resources/scenarios/http/multipart/image.jpg
rename to REGRESSION/resources/scenarios/end2end/http/multipart/image.jpg
diff --git a/REGRESSION/resources/scenarios/http/multipart/scenario.xml b/REGRESSION/resources/scenarios/end2end/http/multipart/scenario.xml
similarity index 98%
rename from REGRESSION/resources/scenarios/http/multipart/scenario.xml
rename to REGRESSION/resources/scenarios/end2end/http/multipart/scenario.xml
index 8337342..4b6db4a 100644
--- a/REGRESSION/resources/scenarios/http/multipart/scenario.xml
+++ b/REGRESSION/resources/scenarios/end2end/http/multipart/scenario.xml
@@ -7,7 +7,7 @@
Multipart
-
+
api
diff --git a/REGRESSION/resources/scenarios/http/multipart/text.txt b/REGRESSION/resources/scenarios/end2end/http/multipart/text.txt
similarity index 100%
rename from REGRESSION/resources/scenarios/http/multipart/text.txt
rename to REGRESSION/resources/scenarios/end2end/http/multipart/text.txt
diff --git a/REGRESSION/resources/scenarios/http/websocket/all/body_9.json b/REGRESSION/resources/scenarios/end2end/http/websocket/all/body_9.json
similarity index 100%
rename from REGRESSION/resources/scenarios/http/websocket/all/body_9.json
rename to REGRESSION/resources/scenarios/end2end/http/websocket/all/body_9.json
diff --git a/REGRESSION/resources/scenarios/http/websocket/all/expected_13.json b/REGRESSION/resources/scenarios/end2end/http/websocket/all/expected_13.json
similarity index 100%
rename from REGRESSION/resources/scenarios/http/websocket/all/expected_13.json
rename to REGRESSION/resources/scenarios/end2end/http/websocket/all/expected_13.json
diff --git a/REGRESSION/resources/scenarios/http/websocket/all/expected_14.json b/REGRESSION/resources/scenarios/end2end/http/websocket/all/expected_14.json
similarity index 100%
rename from REGRESSION/resources/scenarios/http/websocket/all/expected_14.json
rename to REGRESSION/resources/scenarios/end2end/http/websocket/all/expected_14.json
diff --git a/REGRESSION/resources/scenarios/end2end/http/websocket/all/expected_15.json b/REGRESSION/resources/scenarios/end2end/http/websocket/all/expected_15.json
new file mode 100644
index 0000000..dee3839
--- /dev/null
+++ b/REGRESSION/resources/scenarios/end2end/http/websocket/all/expected_15.json
@@ -0,0 +1,105 @@
+{
+ "per_page" : 10,
+ "data" : [ {
+ "fact" : "Unlike dogs, cats do not have a sweet tooth. Scientists believe this is due to a mutation in a key taste receptor.",
+ "length" : 114
+ }, {
+ "fact" : "When a cat chases its prey, it keeps its head level. Dogs and humans bob their heads up and down.",
+ "length" : 97
+ }, {
+ "fact" : "The technical term for a cat’s hairball is a “bezoar.”",
+ "length" : 54
+ }, {
+ "fact" : "A group of cats is called a “clowder.”",
+ "length" : 38
+ }, {
+ "fact" : "A cat can’t climb head first down a tree because every claw on a cat’s paw points the same way. To get down from a tree, a cat must back down.",
+ "length" : 142
+ }, {
+ "fact" : "Cats make about 100 different sounds. Dogs make only about 10.",
+ "length" : 62
+ }, {
+ "fact" : "Every year, nearly four million cats are eaten in Asia.",
+ "length" : 55
+ }, {
+ "fact" : "There are more than 500 million domestic cats in the world, with approximately 40 recognized breeds.",
+ "length" : 100
+ }, {
+ "fact" : "Approximately 24 cat skins can make a coat.",
+ "length" : 43
+ }, {
+ "fact" : "While it is commonly thought that the ancient Egyptians were the first to domesticate cats, the oldest known pet cat was recently found in a 9,500-year-old grave on the Mediterranean island of Cyprus. This grave predates early Egyptian art depicting cats by 4,000 years or more.",
+ "length" : 278
+ } ],
+ "last_page" : 34,
+ "next_page_url" : "https://catfact.ninja/facts?page=2",
+ "prev_page_url" : null,
+ "first_page_url" : "https://catfact.ninja/facts?page=1",
+ "path" : "https://catfact.ninja/facts",
+ "total" : 332,
+ "last_page_url" : "https://catfact.ninja/facts?page=34",
+ "from" : 1,
+ "links" : [ {
+ "active" : false,
+ "label" : "Previous",
+ "url" : null
+ }, {
+ "active" : true,
+ "label" : "1",
+ "url" : "https://catfact.ninja/facts?page=1"
+ }, {
+ "active" : false,
+ "label" : "2",
+ "url" : "https://catfact.ninja/facts?page=2"
+ }, {
+ "active" : false,
+ "label" : "3",
+ "url" : "https://catfact.ninja/facts?page=3"
+ }, {
+ "active" : false,
+ "label" : "4",
+ "url" : "https://catfact.ninja/facts?page=4"
+ }, {
+ "active" : false,
+ "label" : "5",
+ "url" : "https://catfact.ninja/facts?page=5"
+ }, {
+ "active" : false,
+ "label" : "6",
+ "url" : "https://catfact.ninja/facts?page=6"
+ }, {
+ "active" : false,
+ "label" : "7",
+ "url" : "https://catfact.ninja/facts?page=7"
+ }, {
+ "active" : false,
+ "label" : "8",
+ "url" : "https://catfact.ninja/facts?page=8"
+ }, {
+ "active" : false,
+ "label" : "9",
+ "url" : "https://catfact.ninja/facts?page=9"
+ }, {
+ "active" : false,
+ "label" : "10",
+ "url" : "https://catfact.ninja/facts?page=10"
+ }, {
+ "active" : false,
+ "label" : "...",
+ "url" : null
+ }, {
+ "active" : false,
+ "label" : "33",
+ "url" : "https://catfact.ninja/facts?page=33"
+ }, {
+ "active" : false,
+ "label" : "34",
+ "url" : "https://catfact.ninja/facts?page=34"
+ }, {
+ "active" : false,
+ "label" : "Next",
+ "url" : "https://catfact.ninja/facts?page=2"
+ } ],
+ "to" : 10,
+ "current_page" : 1
+}
\ No newline at end of file
diff --git a/REGRESSION/resources/scenarios/http/websocket/all/expected_17.json b/REGRESSION/resources/scenarios/end2end/http/websocket/all/expected_17.json
similarity index 100%
rename from REGRESSION/resources/scenarios/http/websocket/all/expected_17.json
rename to REGRESSION/resources/scenarios/end2end/http/websocket/all/expected_17.json
diff --git a/REGRESSION/resources/scenarios/http/websocket/all/expected_18.json b/REGRESSION/resources/scenarios/end2end/http/websocket/all/expected_18.json
similarity index 100%
rename from REGRESSION/resources/scenarios/http/websocket/all/expected_18.json
rename to REGRESSION/resources/scenarios/end2end/http/websocket/all/expected_18.json
diff --git a/REGRESSION/resources/scenarios/end2end/http/websocket/all/expected_19.json b/REGRESSION/resources/scenarios/end2end/http/websocket/all/expected_19.json
new file mode 100644
index 0000000..84c0668
--- /dev/null
+++ b/REGRESSION/resources/scenarios/end2end/http/websocket/all/expected_19.json
@@ -0,0 +1,5 @@
+[
+ "server periodic message",
+ "server periodic message",
+ "server periodic message"
+]
\ No newline at end of file
diff --git a/REGRESSION/resources/scenarios/http/websocket/all/expected_5.json b/REGRESSION/resources/scenarios/end2end/http/websocket/all/expected_5.json
similarity index 100%
rename from REGRESSION/resources/scenarios/http/websocket/all/expected_5.json
rename to REGRESSION/resources/scenarios/end2end/http/websocket/all/expected_5.json
diff --git a/REGRESSION/resources/scenarios/http/websocket/all/scenario.xml b/REGRESSION/resources/scenarios/end2end/http/websocket/all/scenario.xml
similarity index 100%
rename from REGRESSION/resources/scenarios/http/websocket/all/scenario.xml
rename to REGRESSION/resources/scenarios/end2end/http/websocket/all/scenario.xml
diff --git a/REGRESSION/resources/scenarios/http/websocket/subscribe/scenario.xml b/REGRESSION/resources/scenarios/end2end/http/websocket/subscribe/scenario.xml
similarity index 100%
rename from REGRESSION/resources/scenarios/http/websocket/subscribe/scenario.xml
rename to REGRESSION/resources/scenarios/end2end/http/websocket/subscribe/scenario.xml
diff --git a/REGRESSION/resources/scenarios/graphql/body/file/expected_1.json b/REGRESSION/resources/scenarios/graphql/body/file/expected_1.json
new file mode 100644
index 0000000..bfb7792
--- /dev/null
+++ b/REGRESSION/resources/scenarios/graphql/body/file/expected_1.json
@@ -0,0 +1,9 @@
+{
+ "data" : {
+ "addSelfBook" : {
+ "title" : "File Book",
+ "author" : "File Author",
+ "number" : 2
+ }
+ }
+}
\ No newline at end of file
diff --git a/REGRESSION/resources/scenarios/graphql/body/file/expected_2.json b/REGRESSION/resources/scenarios/graphql/body/file/expected_2.json
new file mode 100644
index 0000000..ba3d419
--- /dev/null
+++ b/REGRESSION/resources/scenarios/graphql/body/file/expected_2.json
@@ -0,0 +1,5 @@
+{
+ "data" : {
+ "resetSelfBooks" : true
+ }
+}
\ No newline at end of file
diff --git a/REGRESSION/resources/scenarios/graphql/body/file/request_1.json b/REGRESSION/resources/scenarios/graphql/body/file/request_1.json
new file mode 100644
index 0000000..7f0ffc7
--- /dev/null
+++ b/REGRESSION/resources/scenarios/graphql/body/file/request_1.json
@@ -0,0 +1,3 @@
+{
+ "query": "mutation { addSelfBook(newBook: { title: \"File Book\", author: \"File Author\", number: 2 }) { title author number } }"
+}
\ No newline at end of file
diff --git a/REGRESSION/resources/scenarios/graphql/body/file/request_2.json b/REGRESSION/resources/scenarios/graphql/body/file/request_2.json
new file mode 100644
index 0000000..c2f7b2f
--- /dev/null
+++ b/REGRESSION/resources/scenarios/graphql/body/file/request_2.json
@@ -0,0 +1,3 @@
+{
+ "query": "mutation { resetSelfBooks }"
+}
\ No newline at end of file
diff --git a/REGRESSION/resources/scenarios/graphql/body/file/scenario.xml b/REGRESSION/resources/scenarios/graphql/body/file/scenario.xml
new file mode 100644
index 0000000..3ac5c29
--- /dev/null
+++ b/REGRESSION/resources/scenarios/graphql/body/file/scenario.xml
@@ -0,0 +1,48 @@
+
+
+
+ GraphQL Body File
+
+ This scenario verifies GraphQL request execution using file body.
+
+ Test flow includes:
+ 1. Send GraphQL mutation using request body from file.
+ 2. Verify response status = 200.
+ 3. Validate returned GraphQL response.
+ 4. Reset in-memory GraphQL storage after test.
+
+ This scenario validates:
+ - GraphQL request execution using file body
+ - Correct request body file loading
+ - Response body correctness
+
+ Vadym Kostenko
+
+
+
+ graphql
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/REGRESSION/resources/scenarios/graphql/body/raw/expected_1.json b/REGRESSION/resources/scenarios/graphql/body/raw/expected_1.json
new file mode 100644
index 0000000..bf2877d
--- /dev/null
+++ b/REGRESSION/resources/scenarios/graphql/body/raw/expected_1.json
@@ -0,0 +1,9 @@
+{
+ "data" : {
+ "addSelfBook" : {
+ "title" : "Raw Book",
+ "author" : "Raw Author",
+ "number" : 1
+ }
+ }
+}
\ No newline at end of file
diff --git a/REGRESSION/resources/scenarios/graphql/body/raw/expected_2.json b/REGRESSION/resources/scenarios/graphql/body/raw/expected_2.json
new file mode 100644
index 0000000..ba3d419
--- /dev/null
+++ b/REGRESSION/resources/scenarios/graphql/body/raw/expected_2.json
@@ -0,0 +1,5 @@
+{
+ "data" : {
+ "resetSelfBooks" : true
+ }
+}
\ No newline at end of file
diff --git a/REGRESSION/resources/scenarios/graphql/body/raw/scenario.xml b/REGRESSION/resources/scenarios/graphql/body/raw/scenario.xml
new file mode 100644
index 0000000..1a9818d
--- /dev/null
+++ b/REGRESSION/resources/scenarios/graphql/body/raw/scenario.xml
@@ -0,0 +1,56 @@
+
+
+
+ GraphQL Body Raw
+
+ This scenario verifies GraphQL request execution using raw body.
+
+ Test flow includes:
+ 1. Send GraphQL mutation using raw request body.
+ 2. Verify response status = 200.
+ 3. Validate returned GraphQL response.
+ 4. Reset in-memory GraphQL storage after test.
+
+ This scenario validates:
+ - GraphQL request execution using raw body
+ - Correct request body parsing
+ - Response body correctness
+
+ Vadym Kostenko
+
+
+
+ graphql
+
+
+
+
+
+
+
+ {
+ "query": "mutation { addSelfBook(newBook: { title: \"Raw Book\", author: \"Raw Author\", number: 1 }) { title author number } }"
+ }
+
+
+
+
+
+
+
+
+
+
+ {
+ "query": "mutation { resetSelfBooks }"
+ }
+
+
+
+
+
+
\ No newline at end of file
diff --git a/REGRESSION/resources/scenarios/graphql/condition/expected_2.json b/REGRESSION/resources/scenarios/graphql/condition/expected_2.json
new file mode 100644
index 0000000..d71031a
--- /dev/null
+++ b/REGRESSION/resources/scenarios/graphql/condition/expected_2.json
@@ -0,0 +1,9 @@
+{
+ "data" : {
+ "addSelfBook" : {
+ "title" : "Condition Book",
+ "author" : "Vadym",
+ "number" : 1
+ }
+ }
+}
\ No newline at end of file
diff --git a/REGRESSION/resources/scenarios/graphql/condition/expected_3.json b/REGRESSION/resources/scenarios/graphql/condition/expected_3.json
new file mode 100644
index 0000000..7698b48
--- /dev/null
+++ b/REGRESSION/resources/scenarios/graphql/condition/expected_3.json
@@ -0,0 +1,9 @@
+{
+ "data" : {
+ "getAllSelfBooks" : [ {
+ "title" : "Condition Book",
+ "author" : "Vadym",
+ "number" : 1
+ } ]
+ }
+}
\ No newline at end of file
diff --git a/REGRESSION/resources/scenarios/graphql/condition/expected_5.json b/REGRESSION/resources/scenarios/graphql/condition/expected_5.json
new file mode 100644
index 0000000..e69de29
diff --git a/REGRESSION/resources/scenarios/graphql/condition/expected_6.json b/REGRESSION/resources/scenarios/graphql/condition/expected_6.json
new file mode 100644
index 0000000..7698b48
--- /dev/null
+++ b/REGRESSION/resources/scenarios/graphql/condition/expected_6.json
@@ -0,0 +1,9 @@
+{
+ "data" : {
+ "getAllSelfBooks" : [ {
+ "title" : "Condition Book",
+ "author" : "Vadym",
+ "number" : 1
+ } ]
+ }
+}
\ No newline at end of file
diff --git a/REGRESSION/resources/scenarios/graphql/condition/expected_7.json b/REGRESSION/resources/scenarios/graphql/condition/expected_7.json
new file mode 100644
index 0000000..3c82d28
--- /dev/null
+++ b/REGRESSION/resources/scenarios/graphql/condition/expected_7.json
@@ -0,0 +1,5 @@
+{
+ "data": {
+ "resetSelfBooks": true
+ }
+}
\ No newline at end of file
diff --git a/REGRESSION/resources/scenarios/graphql/condition/scenario.xml b/REGRESSION/resources/scenarios/graphql/condition/scenario.xml
new file mode 100644
index 0000000..5db9dbe
--- /dev/null
+++ b/REGRESSION/resources/scenarios/graphql/condition/scenario.xml
@@ -0,0 +1,103 @@
+
+
+
+ GraphQL Condition
+
+ This scenario verifies GraphQL command execution together with condition logic.
+
+ Test flow includes:
+ 1. Create true condition.
+ 2. Execute valid GraphQL mutation when condition is true.
+ 3. Verify created book exists in storage.
+ 4. Create false condition.
+ 5. Attempt to execute invalid GraphQL mutation when condition is false.
+ 6. Verify invalid step was skipped and storage was not changed.
+ 7. Reset in-memory GraphQL storage after test.
+
+ This scenario validates:
+ - Conditional execution when condition is true
+ - Skipped execution when condition is false
+ - Stable storage state after skipped step
+ - GraphQL command interaction with condition logic
+
+ Vadym Kostenko
+
+
+
+ graphql
+
+
+
+
+
+
+
+
+
+ {
+ "query": "mutation { addSelfBook(newBook: { title: \"Condition Book\", author: \"Vadym\", number: 1
+ }) { title author number } }"
+ }
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {
+ "query": "mutation { addSelfBook(newBook: { title: \"\", author: \"\", number: -1 }) { title author
+ number } }"
+ }
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {
+ "query": "mutation { resetSelfBooks }"
+ }
+
+
+
+
+
+
\ No newline at end of file
diff --git a/REGRESSION/resources/scenarios/graphql/methods/add/expected_1.json b/REGRESSION/resources/scenarios/graphql/methods/add/expected_1.json
new file mode 100644
index 0000000..3bfc6be
--- /dev/null
+++ b/REGRESSION/resources/scenarios/graphql/methods/add/expected_1.json
@@ -0,0 +1,9 @@
+{
+ "data": {
+ "addSelfBook": {
+ "title": "GraphQL Book",
+ "author": "Vadym",
+ "number": 1
+ }
+ }
+}
\ No newline at end of file
diff --git a/REGRESSION/resources/scenarios/graphql/methods/add/expected_2.json b/REGRESSION/resources/scenarios/graphql/methods/add/expected_2.json
new file mode 100644
index 0000000..3c82d28
--- /dev/null
+++ b/REGRESSION/resources/scenarios/graphql/methods/add/expected_2.json
@@ -0,0 +1,5 @@
+{
+ "data": {
+ "resetSelfBooks": true
+ }
+}
\ No newline at end of file
diff --git a/REGRESSION/resources/scenarios/graphql/methods/add/scenario.xml b/REGRESSION/resources/scenarios/graphql/methods/add/scenario.xml
new file mode 100644
index 0000000..6c6620c
--- /dev/null
+++ b/REGRESSION/resources/scenarios/graphql/methods/add/scenario.xml
@@ -0,0 +1,58 @@
+
+
+
+ GraphQL ADD
+
+ This scenario verifies GraphQL mutation for adding a book.
+
+ Test flow includes:
+ 1. Send GraphQL mutation to create a new book.
+ 2. Verify response status = 200.
+ 3. Validate created book in response.
+ 4. Reset in-memory GraphQL storage after test.
+
+ This scenario validates:
+ - GraphQL mutation execution
+ - Book creation in memory
+ - Response body correctness
+
+ Vadym Kostenko
+
+
+
+ graphql
+
+
+
+
+
+
+
+ {
+ "query": "mutation { addSelfBook(newBook: { title: \"GraphQL Book\", author: \"Vadym\", number: 1 })
+ { title author number } }"
+ }
+
+
+
+
+
+
+
+
+
+
+ {
+ "query": "mutation { resetSelfBooks }"
+ }
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/REGRESSION/resources/scenarios/graphql/methods/delete/expected_1.json b/REGRESSION/resources/scenarios/graphql/methods/delete/expected_1.json
new file mode 100644
index 0000000..76e907b
--- /dev/null
+++ b/REGRESSION/resources/scenarios/graphql/methods/delete/expected_1.json
@@ -0,0 +1,9 @@
+{
+ "data": {
+ "addSelfBook": {
+ "title": "Delete Me",
+ "author": "Author One",
+ "number": 1
+ }
+ }
+}
\ No newline at end of file
diff --git a/REGRESSION/resources/scenarios/graphql/methods/delete/expected_2.json b/REGRESSION/resources/scenarios/graphql/methods/delete/expected_2.json
new file mode 100644
index 0000000..f91a849
--- /dev/null
+++ b/REGRESSION/resources/scenarios/graphql/methods/delete/expected_2.json
@@ -0,0 +1,9 @@
+{
+ "data": {
+ "addSelfBook": {
+ "title": "Keep Me",
+ "author": "Author Two",
+ "number": 2
+ }
+ }
+}
\ No newline at end of file
diff --git a/REGRESSION/resources/scenarios/graphql/methods/delete/expected_3.json b/REGRESSION/resources/scenarios/graphql/methods/delete/expected_3.json
new file mode 100644
index 0000000..c49f9c0
--- /dev/null
+++ b/REGRESSION/resources/scenarios/graphql/methods/delete/expected_3.json
@@ -0,0 +1,5 @@
+{
+ "data": {
+ "deleteSelfBookByTitle": true
+ }
+}
\ No newline at end of file
diff --git a/REGRESSION/resources/scenarios/graphql/methods/delete/expected_4.json b/REGRESSION/resources/scenarios/graphql/methods/delete/expected_4.json
new file mode 100644
index 0000000..1ac9ffd
--- /dev/null
+++ b/REGRESSION/resources/scenarios/graphql/methods/delete/expected_4.json
@@ -0,0 +1,11 @@
+{
+ "data": {
+ "getAllSelfBooks": [
+ {
+ "title": "Keep Me",
+ "author": "Author Two",
+ "number": 2
+ }
+ ]
+ }
+}
\ No newline at end of file
diff --git a/REGRESSION/resources/scenarios/graphql/methods/delete/expected_5.json b/REGRESSION/resources/scenarios/graphql/methods/delete/expected_5.json
new file mode 100644
index 0000000..3c82d28
--- /dev/null
+++ b/REGRESSION/resources/scenarios/graphql/methods/delete/expected_5.json
@@ -0,0 +1,5 @@
+{
+ "data": {
+ "resetSelfBooks": true
+ }
+}
\ No newline at end of file
diff --git a/REGRESSION/resources/scenarios/graphql/methods/delete/scenario.xml b/REGRESSION/resources/scenarios/graphql/methods/delete/scenario.xml
new file mode 100644
index 0000000..dbbd5aa
--- /dev/null
+++ b/REGRESSION/resources/scenarios/graphql/methods/delete/scenario.xml
@@ -0,0 +1,100 @@
+
+
+
+ GraphQL DELETE
+
+ This scenario verifies GraphQL mutation for deleting a book by title.
+
+ Test flow includes:
+ 1. Create first book using GraphQL mutation.
+ 2. Create second book using GraphQL mutation.
+ 3. Send GraphQL mutation to delete one book by title.
+ 4. Verify response status = 200.
+ 5. Validate delete result.
+ 6. Send GraphQL query to retrieve all books.
+ 7. Verify response status = 200.
+ 8. Validate that only remaining book exists.
+ 9. Reset in-memory GraphQL storage after test.
+
+ This scenario validates:
+ - GraphQL delete mutation execution
+ - Book deletion by title
+ - Storage state after deletion
+ - Response body correctness
+
+ Vadym Kostenko
+
+
+
+ graphql
+
+
+
+
+
+
+
+ {
+ "query": "mutation { addSelfBook(newBook: { title: \"Delete Me\", author: \"Author One\", number: 1
+ }) { title author number } }"
+ }
+
+
+
+
+
+
+
+
+
+
+ {
+ "query": "mutation { addSelfBook(newBook: { title: \"Keep Me\", author: \"Author Two\", number: 2 })
+ { title author number } }"
+ }
+
+
+
+
+
+
+
+
+
+
+ {
+ "query": "mutation { deleteSelfBookByTitle(title: \"Delete Me\") }"
+ }
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {
+ "query": "mutation { resetSelfBooks }"
+ }
+
+
+
+
+
+
\ No newline at end of file
diff --git a/REGRESSION/resources/scenarios/graphql/methods/get/expected_1.json b/REGRESSION/resources/scenarios/graphql/methods/get/expected_1.json
new file mode 100644
index 0000000..f97ec90
--- /dev/null
+++ b/REGRESSION/resources/scenarios/graphql/methods/get/expected_1.json
@@ -0,0 +1,9 @@
+{
+ "data" : {
+ "addSelfBook" : {
+ "title" : "First Book",
+ "author" : "Author One",
+ "number" : 1
+ }
+ }
+}
\ No newline at end of file
diff --git a/REGRESSION/resources/scenarios/graphql/methods/get/expected_2.json b/REGRESSION/resources/scenarios/graphql/methods/get/expected_2.json
new file mode 100644
index 0000000..c8fa9f7
--- /dev/null
+++ b/REGRESSION/resources/scenarios/graphql/methods/get/expected_2.json
@@ -0,0 +1,9 @@
+{
+ "data" : {
+ "addSelfBook" : {
+ "title" : "Second Book",
+ "author" : "Author Two",
+ "number" : 2
+ }
+ }
+}
\ No newline at end of file
diff --git a/REGRESSION/resources/scenarios/graphql/methods/get/expected_3.json b/REGRESSION/resources/scenarios/graphql/methods/get/expected_3.json
new file mode 100644
index 0000000..25ca4f3
--- /dev/null
+++ b/REGRESSION/resources/scenarios/graphql/methods/get/expected_3.json
@@ -0,0 +1,9 @@
+{
+ "data" : {
+ "getSelfBookByTitle" : {
+ "title" : "First Book",
+ "author" : "Author One",
+ "number" : 1
+ }
+ }
+}
\ No newline at end of file
diff --git a/REGRESSION/resources/scenarios/graphql/methods/get/expected_4.json b/REGRESSION/resources/scenarios/graphql/methods/get/expected_4.json
new file mode 100644
index 0000000..e8a42bc
--- /dev/null
+++ b/REGRESSION/resources/scenarios/graphql/methods/get/expected_4.json
@@ -0,0 +1,16 @@
+{
+ "data": {
+ "getAllSelfBooks": [
+ {
+ "title": "First Book",
+ "author": "Author One",
+ "number": 1
+ },
+ {
+ "title": "Second Book",
+ "author": "Author Two",
+ "number": 2
+ }
+ ]
+ }
+}
\ No newline at end of file
diff --git a/REGRESSION/resources/scenarios/graphql/methods/get/expected_5.json b/REGRESSION/resources/scenarios/graphql/methods/get/expected_5.json
new file mode 100644
index 0000000..3c82d28
--- /dev/null
+++ b/REGRESSION/resources/scenarios/graphql/methods/get/expected_5.json
@@ -0,0 +1,5 @@
+{
+ "data": {
+ "resetSelfBooks": true
+ }
+}
\ No newline at end of file
diff --git a/REGRESSION/resources/scenarios/graphql/methods/get/scenario.xml b/REGRESSION/resources/scenarios/graphql/methods/get/scenario.xml
new file mode 100644
index 0000000..493df5c
--- /dev/null
+++ b/REGRESSION/resources/scenarios/graphql/methods/get/scenario.xml
@@ -0,0 +1,98 @@
+
+
+
+ GraphQL GET
+
+ This scenario verifies GraphQL queries for retrieving books.
+
+ Test flow includes:
+ 1. Create first book using GraphQL mutation.
+ 2. Create second book using GraphQL mutation.
+ 3. Send GraphQL query to retrieve one book by title.
+ 4. Verify response status = 200.
+ 5. Validate returned book by title.
+ 6. Send GraphQL query to retrieve all books.
+ 7. Verify response status = 200.
+ 8. Validate returned books list.
+ 9. Reset in-memory GraphQL storage after test.
+
+ This scenario validates:
+ - GraphQL query execution by title
+ - GraphQL query execution for all books
+ - Retrieval of stored books
+ - Response body correctness
+
+ Vadym Kostenko
+
+
+
+ graphql
+
+
+
+
+
+
+
+ {
+ "query": "mutation { addSelfBook(newBook: { title: \"First Book\", author: \"Author One\", number: 1 }) { title author number } }"
+ }
+
+
+
+
+
+
+
+
+
+
+ {
+ "query": "mutation { addSelfBook(newBook: { title: \"Second Book\", author: \"Author Two\", number: 2 }) { title author number } }"
+ }
+
+
+
+
+
+
+
+
+
+
+ {
+ "query": "{ getSelfBookByTitle(title: \"First Book\") { title author number } }"
+ }
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {
+ "query": "mutation { resetSelfBooks }"
+ }
+
+
+
+
+
+
\ No newline at end of file
diff --git a/REGRESSION/resources/scenarios/graphql/methods/update/expected_1.json b/REGRESSION/resources/scenarios/graphql/methods/update/expected_1.json
new file mode 100644
index 0000000..f0aeffe
--- /dev/null
+++ b/REGRESSION/resources/scenarios/graphql/methods/update/expected_1.json
@@ -0,0 +1,9 @@
+{
+ "data": {
+ "addSelfBook": {
+ "title": "Original Book",
+ "author": "Original Author",
+ "number": 1
+ }
+ }
+}
\ No newline at end of file
diff --git a/REGRESSION/resources/scenarios/graphql/methods/update/expected_2.json b/REGRESSION/resources/scenarios/graphql/methods/update/expected_2.json
new file mode 100644
index 0000000..25dd3fb
--- /dev/null
+++ b/REGRESSION/resources/scenarios/graphql/methods/update/expected_2.json
@@ -0,0 +1,9 @@
+{
+ "data": {
+ "updateSelfBookByTitle": {
+ "title": "Updated Book",
+ "author": "Updated Author",
+ "number": 2
+ }
+ }
+}
\ No newline at end of file
diff --git a/REGRESSION/resources/scenarios/graphql/methods/update/expected_3.json b/REGRESSION/resources/scenarios/graphql/methods/update/expected_3.json
new file mode 100644
index 0000000..4895a87
--- /dev/null
+++ b/REGRESSION/resources/scenarios/graphql/methods/update/expected_3.json
@@ -0,0 +1,9 @@
+{
+ "data": {
+ "getSelfBookByTitle": {
+ "title": "Updated Book",
+ "author": "Updated Author",
+ "number": 2
+ }
+ }
+}
\ No newline at end of file
diff --git a/REGRESSION/resources/scenarios/graphql/methods/update/expected_4.json b/REGRESSION/resources/scenarios/graphql/methods/update/expected_4.json
new file mode 100644
index 0000000..3c82d28
--- /dev/null
+++ b/REGRESSION/resources/scenarios/graphql/methods/update/expected_4.json
@@ -0,0 +1,5 @@
+{
+ "data": {
+ "resetSelfBooks": true
+ }
+}
\ No newline at end of file
diff --git a/REGRESSION/resources/scenarios/graphql/methods/update/scenario.xml b/REGRESSION/resources/scenarios/graphql/methods/update/scenario.xml
new file mode 100644
index 0000000..d2a28d3
--- /dev/null
+++ b/REGRESSION/resources/scenarios/graphql/methods/update/scenario.xml
@@ -0,0 +1,91 @@
+
+
+
+ GraphQL UPDATE
+
+ This scenario verifies GraphQL mutation for updating a book by title.
+
+ Test flow includes:
+ 1. Create initial book using GraphQL mutation.
+ 2. Send GraphQL mutation to update existing book by title.
+ 3. Verify response status = 200.
+ 4. Validate updated book in response.
+ 5. Send GraphQL query to retrieve updated book by title.
+ 6. Verify response status = 200.
+ 7. Validate retrieved updated book.
+ 8. Reset in-memory GraphQL storage after test.
+
+ This scenario validates:
+ - GraphQL update mutation execution
+ - Book update by title
+ - Updated state persistence
+ - Response body correctness
+
+ Vadym Kostenko
+
+
+
+ graphql
+
+
+
+
+
+
+
+ {
+ "query": "mutation { addSelfBook(newBook: { title: \"Original Book\", author: \"Original Author\",
+ number: 1 }) { title author number } }"
+ }
+
+
+
+
+
+
+
+
+
+
+ {
+ "query": "mutation { updateSelfBookByTitle(title: \"Original Book\", updatedBook: { title: \"Updated
+ Book\", author: \"Updated Author\", number: 2 }) { title author number } }"
+ }
+
+
+
+
+
+
+
+
+
+
+ {
+ "query": "{ getSelfBookByTitle(title: \"Updated Book\") { title author number } }"
+ }
+
+
+
+
+
+
+
+
+
+
+ {
+ "query": "mutation { resetSelfBooks }"
+ }
+
+
+
+
+
+
\ No newline at end of file
diff --git a/REGRESSION/resources/scenarios/graphql/mode/expected_1.json b/REGRESSION/resources/scenarios/graphql/mode/expected_1.json
new file mode 100644
index 0000000..bfd2b94
--- /dev/null
+++ b/REGRESSION/resources/scenarios/graphql/mode/expected_1.json
@@ -0,0 +1,7 @@
+{
+ "data" : {
+ "addSelfBook" : {
+ "title" : "Mode Book"
+ }
+ }
+}
\ No newline at end of file
diff --git a/REGRESSION/resources/scenarios/graphql/mode/expected_2.json b/REGRESSION/resources/scenarios/graphql/mode/expected_2.json
new file mode 100644
index 0000000..56ba1a5
--- /dev/null
+++ b/REGRESSION/resources/scenarios/graphql/mode/expected_2.json
@@ -0,0 +1,9 @@
+{
+ "data": {
+ "addSelfBook": {
+ "title": "Mode Book 2",
+ "author": "Mode Author 2",
+ "number": 20
+ }
+ }
+}
\ No newline at end of file
diff --git a/REGRESSION/resources/scenarios/graphql/mode/expected_3.json b/REGRESSION/resources/scenarios/graphql/mode/expected_3.json
new file mode 100644
index 0000000..3c82d28
--- /dev/null
+++ b/REGRESSION/resources/scenarios/graphql/mode/expected_3.json
@@ -0,0 +1,5 @@
+{
+ "data": {
+ "resetSelfBooks": true
+ }
+}
\ No newline at end of file
diff --git a/REGRESSION/resources/scenarios/graphql/mode/scenario.xml b/REGRESSION/resources/scenarios/graphql/mode/scenario.xml
new file mode 100644
index 0000000..278a67c
--- /dev/null
+++ b/REGRESSION/resources/scenarios/graphql/mode/scenario.xml
@@ -0,0 +1,69 @@
+
+
+
+ GraphQL Response Mode
+
+ This scenario verifies difference between strict and lenient response comparison modes for GraphQL.
+
+ Test flow includes:
+ 1. Send GraphQL mutation and validate response using lenient mode with partial expected JSON.
+ 2. Send the same GraphQL mutation and validate response using strict mode with full expected JSON.
+ 3. Reset in-memory GraphQL storage after test.
+
+ This scenario validates:
+ - Lenient mode allows partial GraphQL response validation
+ - Strict mode requires full GraphQL response match
+ - Same GraphQL response can be validated differently depending on comparison mode
+
+ Vadym Kostenko
+
+
+
+ graphql
+
+
+
+
+
+
+
+ {
+ "query": "mutation { addSelfBook(newBook: { title: \"Mode Book\", author: \"Mode Author\", number: 10 }) { title author number } }"
+ }
+
+
+
+
+
+
+
+
+
+
+ {
+ "query": "mutation { addSelfBook(newBook: { title: \"Mode Book 2\", author: \"Mode Author 2\", number: 20 }) { title author number } }"
+ }
+
+
+
+
+
+
+
+
+
+
+ {
+ "query": "mutation { resetSelfBooks }"
+ }
+
+
+
+
+
+
\ No newline at end of file
diff --git a/REGRESSION/resources/scenarios/graphql/repeat/times/expected_2.json b/REGRESSION/resources/scenarios/graphql/repeat/times/expected_2.json
new file mode 100644
index 0000000..b6be18e
--- /dev/null
+++ b/REGRESSION/resources/scenarios/graphql/repeat/times/expected_2.json
@@ -0,0 +1,9 @@
+{
+ "data" : {
+ "addSelfBook" : {
+ "title" : "Repeat Times Book",
+ "author" : "Vadym",
+ "number" : 1
+ }
+ }
+}
\ No newline at end of file
diff --git a/REGRESSION/resources/scenarios/graphql/repeat/times/expected_3.json b/REGRESSION/resources/scenarios/graphql/repeat/times/expected_3.json
new file mode 100644
index 0000000..b6be18e
--- /dev/null
+++ b/REGRESSION/resources/scenarios/graphql/repeat/times/expected_3.json
@@ -0,0 +1,9 @@
+{
+ "data" : {
+ "addSelfBook" : {
+ "title" : "Repeat Times Book",
+ "author" : "Vadym",
+ "number" : 1
+ }
+ }
+}
\ No newline at end of file
diff --git a/REGRESSION/resources/scenarios/graphql/repeat/times/expected_4.json b/REGRESSION/resources/scenarios/graphql/repeat/times/expected_4.json
new file mode 100644
index 0000000..b6be18e
--- /dev/null
+++ b/REGRESSION/resources/scenarios/graphql/repeat/times/expected_4.json
@@ -0,0 +1,9 @@
+{
+ "data" : {
+ "addSelfBook" : {
+ "title" : "Repeat Times Book",
+ "author" : "Vadym",
+ "number" : 1
+ }
+ }
+}
\ No newline at end of file
diff --git a/REGRESSION/resources/scenarios/graphql/repeat/times/expected_5.json b/REGRESSION/resources/scenarios/graphql/repeat/times/expected_5.json
new file mode 100644
index 0000000..ebd7b39
--- /dev/null
+++ b/REGRESSION/resources/scenarios/graphql/repeat/times/expected_5.json
@@ -0,0 +1,17 @@
+{
+ "data" : {
+ "getAllSelfBooks" : [ {
+ "title" : "Repeat Times Book",
+ "author" : "Vadym",
+ "number" : 1
+ }, {
+ "title" : "Repeat Times Book",
+ "author" : "Vadym",
+ "number" : 1
+ }, {
+ "title" : "Repeat Times Book",
+ "author" : "Vadym",
+ "number" : 1
+ } ]
+ }
+}
\ No newline at end of file
diff --git a/REGRESSION/resources/scenarios/graphql/repeat/times/expected_6.json b/REGRESSION/resources/scenarios/graphql/repeat/times/expected_6.json
new file mode 100644
index 0000000..ba3d419
--- /dev/null
+++ b/REGRESSION/resources/scenarios/graphql/repeat/times/expected_6.json
@@ -0,0 +1,5 @@
+{
+ "data" : {
+ "resetSelfBooks" : true
+ }
+}
\ No newline at end of file
diff --git a/REGRESSION/resources/scenarios/graphql/repeat/times/request_1.json b/REGRESSION/resources/scenarios/graphql/repeat/times/request_1.json
new file mode 100644
index 0000000..cc8ef1e
--- /dev/null
+++ b/REGRESSION/resources/scenarios/graphql/repeat/times/request_1.json
@@ -0,0 +1,3 @@
+{
+ "query": "mutation { addSelfBook(newBook: { title: \"Repeat Times Book\", author: \"Vadym\", number: 1 }) { title author number } }"
+}
\ No newline at end of file
diff --git a/REGRESSION/resources/scenarios/graphql/repeat/times/scenario.xml b/REGRESSION/resources/scenarios/graphql/repeat/times/scenario.xml
new file mode 100644
index 0000000..79816aa
--- /dev/null
+++ b/REGRESSION/resources/scenarios/graphql/repeat/times/scenario.xml
@@ -0,0 +1,68 @@
+
+
+
+ GraphQL Repeat Times
+
+ This scenario verifies GraphQL execution inside repeat block using times.
+
+ Test flow includes:
+ 1. Execute GraphQL mutation inside repeat block 3 times.
+ 2. Create the same book on each iteration.
+ 3. Verify response status = 200 for each iteration.
+ 4. Retrieve all books after repeat execution.
+ 5. Verify that 3 books were created in memory.
+ 6. Reset GraphQL storage after test.
+
+ This scenario validates:
+ - GraphQL mutation execution inside repeat block
+ - Stable repeated execution using times
+ - Data accumulation across iterations
+ - Correct final storage state
+
+ Vadym Kostenko
+
+
+
+ graphql
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {
+ "query": "mutation { resetSelfBooks }"
+ }
+
+
+
+
+
+
\ No newline at end of file
diff --git a/REGRESSION/resources/scenarios/graphql/repeat/variations/expected_2.json b/REGRESSION/resources/scenarios/graphql/repeat/variations/expected_2.json
new file mode 100644
index 0000000..7817800
--- /dev/null
+++ b/REGRESSION/resources/scenarios/graphql/repeat/variations/expected_2.json
@@ -0,0 +1,9 @@
+{
+ "data" : {
+ "addSelfBook" : {
+ "title" : "Repeat Book One",
+ "author" : "Vadym",
+ "number" : 1
+ }
+ }
+}
\ No newline at end of file
diff --git a/REGRESSION/resources/scenarios/graphql/repeat/variations/expected_3.json b/REGRESSION/resources/scenarios/graphql/repeat/variations/expected_3.json
new file mode 100644
index 0000000..6a04a23
--- /dev/null
+++ b/REGRESSION/resources/scenarios/graphql/repeat/variations/expected_3.json
@@ -0,0 +1,9 @@
+{
+ "data" : {
+ "addSelfBook" : {
+ "title" : "Repeat Book Two",
+ "author" : "Taras",
+ "number" : 2
+ }
+ }
+}
\ No newline at end of file
diff --git a/REGRESSION/resources/scenarios/graphql/repeat/variations/expected_4.json b/REGRESSION/resources/scenarios/graphql/repeat/variations/expected_4.json
new file mode 100644
index 0000000..c5b0143
--- /dev/null
+++ b/REGRESSION/resources/scenarios/graphql/repeat/variations/expected_4.json
@@ -0,0 +1,9 @@
+{
+ "data" : {
+ "addSelfBook" : {
+ "title" : "Repeat Book Three",
+ "author" : "Knubisoft",
+ "number" : 3
+ }
+ }
+}
\ No newline at end of file
diff --git a/REGRESSION/resources/scenarios/graphql/repeat/variations/expected_5.json b/REGRESSION/resources/scenarios/graphql/repeat/variations/expected_5.json
new file mode 100644
index 0000000..c2f63e6
--- /dev/null
+++ b/REGRESSION/resources/scenarios/graphql/repeat/variations/expected_5.json
@@ -0,0 +1,21 @@
+{
+ "data": {
+ "getAllSelfBooks": [
+ {
+ "title": "Repeat Book One",
+ "author": "Vadym",
+ "number": 1
+ },
+ {
+ "title": "Repeat Book Two",
+ "author": "Taras",
+ "number": 2
+ },
+ {
+ "title": "Repeat Book Three",
+ "author": "Knubisoft",
+ "number": 3
+ }
+ ]
+ }
+}
\ No newline at end of file
diff --git a/REGRESSION/resources/scenarios/graphql/repeat/variations/expected_6.json b/REGRESSION/resources/scenarios/graphql/repeat/variations/expected_6.json
new file mode 100644
index 0000000..ba3d419
--- /dev/null
+++ b/REGRESSION/resources/scenarios/graphql/repeat/variations/expected_6.json
@@ -0,0 +1,5 @@
+{
+ "data" : {
+ "resetSelfBooks" : true
+ }
+}
\ No newline at end of file
diff --git a/REGRESSION/resources/scenarios/graphql/repeat/variations/scenario.xml b/REGRESSION/resources/scenarios/graphql/repeat/variations/scenario.xml
new file mode 100644
index 0000000..c3eb9c3
--- /dev/null
+++ b/REGRESSION/resources/scenarios/graphql/repeat/variations/scenario.xml
@@ -0,0 +1,72 @@
+
+
+
+ GraphQL Repeat Variations
+
+ This scenario verifies GraphQL execution inside repeat block using variations.
+
+ Test flow includes:
+ 1. Execute GraphQL mutation inside repeat block using variation rows.
+ 2. Create one book for each variation.
+ 3. Verify response status = 200 for each iteration.
+ 4. Retrieve all books after repeat execution.
+ 5. Verify that all variation books were created in memory.
+ 6. Reset GraphQL storage after test.
+
+ This scenario validates:
+ - GraphQL mutation execution inside repeat block
+ - Variation interpolation inside request files
+ - Stable repeated execution using variations
+ - Correct final storage state
+
+ Vadym Kostenko
+
+
+
+ graphql
+
+
+
+
+
+
+
+
+
+ {
+ "query": "mutation { addSelfBook(newBook: { title: \"{{title}}\", author: \"{{author}}\", number: {{number}} }) { title author number } }"
+ }
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {
+ "query": "mutation { resetSelfBooks }"
+ }
+
+
+
+
+
+
\ No newline at end of file
diff --git a/REGRESSION/resources/scenarios/graphql/variables/expected_13.json b/REGRESSION/resources/scenarios/graphql/variables/expected_13.json
new file mode 100644
index 0000000..bac0690
--- /dev/null
+++ b/REGRESSION/resources/scenarios/graphql/variables/expected_13.json
@@ -0,0 +1,9 @@
+{
+ "data" : {
+ "addSelfBook" : {
+ "title" : "{{fileBookTitle}}",
+ "author" : "{{fileBookAuthor}}",
+ "number" : "{{fileBookNumber}}"
+ }
+ }
+}
\ No newline at end of file
diff --git a/REGRESSION/resources/scenarios/graphql/variables/expected_14.json b/REGRESSION/resources/scenarios/graphql/variables/expected_14.json
new file mode 100644
index 0000000..ba3d419
--- /dev/null
+++ b/REGRESSION/resources/scenarios/graphql/variables/expected_14.json
@@ -0,0 +1,5 @@
+{
+ "data" : {
+ "resetSelfBooks" : true
+ }
+}
\ No newline at end of file
diff --git a/REGRESSION/resources/scenarios/graphql/variables/expected_7.json b/REGRESSION/resources/scenarios/graphql/variables/expected_7.json
new file mode 100644
index 0000000..b222ea5
--- /dev/null
+++ b/REGRESSION/resources/scenarios/graphql/variables/expected_7.json
@@ -0,0 +1,9 @@
+{
+ "data" : {
+ "addSelfBook" : {
+ "title" : "{{bookTitle}}",
+ "author" : "{{bookAuthor}}",
+ "number" : "{{bookNumber}}"
+ }
+ }
+}
\ No newline at end of file
diff --git a/REGRESSION/resources/scenarios/graphql/variables/request_1.json b/REGRESSION/resources/scenarios/graphql/variables/request_1.json
new file mode 100644
index 0000000..766dbcd
--- /dev/null
+++ b/REGRESSION/resources/scenarios/graphql/variables/request_1.json
@@ -0,0 +1,3 @@
+{
+ "query": "mutation { addSelfBook(newBook: { title: \"{{fileBookTitle}}\", author: \"{{fileBookAuthor}}\", number: {{fileBookNumber}} }) { title author number } }"
+}
\ No newline at end of file
diff --git a/REGRESSION/resources/scenarios/graphql/variables/scenario.xml b/REGRESSION/resources/scenarios/graphql/variables/scenario.xml
new file mode 100644
index 0000000..bc3e84c
--- /dev/null
+++ b/REGRESSION/resources/scenarios/graphql/variables/scenario.xml
@@ -0,0 +1,125 @@
+
+
+
+ GraphQL Variables
+
+ This scenario verifies GraphQL request execution using variables.
+
+ Test flow includes:
+ 1. Create variables for comments, endpoint, book fields and expected files.
+ 2. Execute GraphQL mutation using variable values.
+ 3. Verify create response = 200 using variable-based expected file.
+ 4. Reset GraphQL storage using variable-based endpoint.
+
+ This scenario validates:
+ - Variable injection into comment
+ - Variable injection into GraphQL endpoint
+ - Variable injection into GraphQL request body
+ - Variable injection into expected file names
+ - Variable reuse across GraphQL mutation flow
+
+ Vadym Kostenko
+
+
+
+ graphql
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {
+ "query": "mutation { addSelfBook(newBook: { title: \"{{bookTitle}}\", author: \"{{bookAuthor}}\", number: {{bookNumber}} }) { title author number } }"
+ }
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {
+ "query": "mutation { resetSelfBooks }"
+ }
+
+
+
+
+
+
\ No newline at end of file
diff --git a/REGRESSION/resources/scenarios/graphql/variations/expected_1_1.json b/REGRESSION/resources/scenarios/graphql/variations/expected_1_1.json
new file mode 100644
index 0000000..8739ce4
--- /dev/null
+++ b/REGRESSION/resources/scenarios/graphql/variations/expected_1_1.json
@@ -0,0 +1,9 @@
+{
+ "data": {
+ "addSelfBook": {
+ "title": "{{title}}",
+ "author": "{{author}}",
+ "number": "{{number}}"
+ }
+ }
+}
\ No newline at end of file
diff --git a/REGRESSION/resources/scenarios/graphql/variations/expected_1_2.json b/REGRESSION/resources/scenarios/graphql/variations/expected_1_2.json
new file mode 100644
index 0000000..8739ce4
--- /dev/null
+++ b/REGRESSION/resources/scenarios/graphql/variations/expected_1_2.json
@@ -0,0 +1,9 @@
+{
+ "data": {
+ "addSelfBook": {
+ "title": "{{title}}",
+ "author": "{{author}}",
+ "number": "{{number}}"
+ }
+ }
+}
\ No newline at end of file
diff --git a/REGRESSION/resources/scenarios/graphql/variations/expected_3.json b/REGRESSION/resources/scenarios/graphql/variations/expected_3.json
new file mode 100644
index 0000000..3c82d28
--- /dev/null
+++ b/REGRESSION/resources/scenarios/graphql/variations/expected_3.json
@@ -0,0 +1,5 @@
+{
+ "data": {
+ "resetSelfBooks": true
+ }
+}
\ No newline at end of file
diff --git a/REGRESSION/resources/scenarios/graphql/variations/request_1.json b/REGRESSION/resources/scenarios/graphql/variations/request_1.json
new file mode 100644
index 0000000..c0678ea
--- /dev/null
+++ b/REGRESSION/resources/scenarios/graphql/variations/request_1.json
@@ -0,0 +1,3 @@
+{
+ "query": "mutation { addSelfBook(newBook: { title: \"{{title}}\", author: \"{{author}}\", number: {{number}} }) { title author number } }"
+}
\ No newline at end of file
diff --git a/REGRESSION/resources/scenarios/graphql/variations/scenario.xml b/REGRESSION/resources/scenarios/graphql/variations/scenario.xml
new file mode 100644
index 0000000..922a3e6
--- /dev/null
+++ b/REGRESSION/resources/scenarios/graphql/variations/scenario.xml
@@ -0,0 +1,55 @@
+
+
+
+ GraphQL Variations
+
+ This scenario verifies GraphQL request execution using variation data.
+
+ Test flow includes:
+ 1. Load test data from variations CSV file.
+ 2. Send GraphQL mutation for each variation row using request file.
+ 3. Verify response status = 200 for each iteration.
+ 4. Validate created book using variation-based expected file.
+ 5. Reset in-memory GraphQL storage after all variation iterations.
+
+ This scenario validates:
+ - Variation value injection into GraphQL request file content
+ - Variation value injection into expected file names
+ - Variation value injection into GraphQL comment
+ - Stable repeated GraphQL execution using multiple variation rows
+
+ Vadym Kostenko
+
+
+
+ graphqlVariations.csv
+ graphql
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {
+ "query": "mutation { resetSelfBooks }"
+ }
+
+
+
+
+
+
\ No newline at end of file
diff --git a/REGRESSION/resources/scenarios/http/body/file/expected_1.json b/REGRESSION/resources/scenarios/http/body/file/expected_1.json
new file mode 100644
index 0000000..2ea7802
--- /dev/null
+++ b/REGRESSION/resources/scenarios/http/body/file/expected_1.json
@@ -0,0 +1,7 @@
+{
+ "name": "Entity From File",
+ "description": "Created using external request file",
+ "status": "NEW",
+ "category": "FILE_INPUT",
+ "uploadedFile": null
+}
\ No newline at end of file
diff --git a/REGRESSION/resources/scenarios/http/body/file/request_1.json b/REGRESSION/resources/scenarios/http/body/file/request_1.json
new file mode 100644
index 0000000..e98e148
--- /dev/null
+++ b/REGRESSION/resources/scenarios/http/body/file/request_1.json
@@ -0,0 +1,6 @@
+{
+ "name": "Entity From File",
+ "description": "Created using external request file",
+ "status": "NEW",
+ "category": "FILE_INPUT"
+}
\ No newline at end of file
diff --git a/REGRESSION/resources/scenarios/http/body/file/scenario.xml b/REGRESSION/resources/scenarios/http/body/file/scenario.xml
new file mode 100644
index 0000000..0cc2cff
--- /dev/null
+++ b/REGRESSION/resources/scenarios/http/body/file/scenario.xml
@@ -0,0 +1,46 @@
+
+
+
+ HTTP File Payload
+
+ This scenario verifies API support for file-based request payload.
+
+ Test flow includes:
+ 1. Send POST request with request body loaded from external file.
+ 2. Verify response status = 201.
+ 5. Reset in-memory storage after test.
+
+ This scenario validates:
+ - Request body loading from external file
+ - JSON payload processing from file
+ - Entity creation from file-based payload
+ - Stored entity retrieval
+
+ Vadym Kostenko
+
+
+
+ http
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/REGRESSION/resources/scenarios/http/body/multipart/expected_1.json b/REGRESSION/resources/scenarios/http/body/multipart/expected_1.json
new file mode 100644
index 0000000..7786144
--- /dev/null
+++ b/REGRESSION/resources/scenarios/http/body/multipart/expected_1.json
@@ -0,0 +1,11 @@
+{
+ "name" : "Updated from multipart request",
+ "description" : "Created with multipart body",
+ "status" : "MULTIPART",
+ "category" : "FORM",
+ "uploadedFile" : {
+ "uploadedFileName" : "testData.txt",
+ "uploadedFileSize" : 9,
+ "uploadedFileContentType" : "application/octet-stream"
+ }
+}
\ No newline at end of file
diff --git a/REGRESSION/resources/scenarios/http/body/multipart/scenario.xml b/REGRESSION/resources/scenarios/http/body/multipart/scenario.xml
new file mode 100644
index 0000000..cd90cf8
--- /dev/null
+++ b/REGRESSION/resources/scenarios/http/body/multipart/scenario.xml
@@ -0,0 +1,49 @@
+
+
+
+ HTTP Multipart Payload
+
+ This scenario verifies API support for multipart payload processing.
+
+ Test flow includes:
+ 1. Send multipart request with text and file.
+ 2. Verify response status = 200.
+ 3. Validate created entity contains multipart values and uploaded file metadata.
+ 4. Reset in-memory storage after test.
+
+ This scenario validates:
+ - Multipart request body handling
+ - Text field processing from multipart form
+ - File upload metadata extraction
+ - Entity creation from multipart payload
+
+ Vadym Kostenko
+
+
+
+ http
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/REGRESSION/resources/scenarios/http/body/multipart/testData.txt b/REGRESSION/resources/scenarios/http/body/multipart/testData.txt
new file mode 100644
index 0000000..c70be8d
--- /dev/null
+++ b/REGRESSION/resources/scenarios/http/body/multipart/testData.txt
@@ -0,0 +1 @@
+Test Data
\ No newline at end of file
diff --git a/REGRESSION/resources/scenarios/http/body/raw/expected_1.json b/REGRESSION/resources/scenarios/http/body/raw/expected_1.json
new file mode 100644
index 0000000..b70091f
--- /dev/null
+++ b/REGRESSION/resources/scenarios/http/body/raw/expected_1.json
@@ -0,0 +1,7 @@
+{
+ "name": "Entity From Raw",
+ "description": "Created using inline raw body",
+ "status": "ACTIVE",
+ "category": "RAW_INPUT",
+ "uploadedFile": null
+}
\ No newline at end of file
diff --git a/REGRESSION/resources/scenarios/http/body/raw/scenario.xml b/REGRESSION/resources/scenarios/http/body/raw/scenario.xml
new file mode 100644
index 0000000..21f829f
--- /dev/null
+++ b/REGRESSION/resources/scenarios/http/body/raw/scenario.xml
@@ -0,0 +1,52 @@
+
+
+
+ HTTP Raw Payload
+
+ This scenario verifies API support for inline raw request payload.
+
+ Test flow includes:
+ 1. Send POST request with inline raw JSON body.
+ 2. Verify response status = 201.
+ 3. Reset in-memory storage after test.
+
+ This scenario validates:
+ - Inline raw JSON request body processing
+ - Entity creation from raw payload
+ - Stored entity retrieval
+
+ Vadym Kostenko
+
+
+
+ http
+
+
+
+
+
+
+
+
+ {
+ "name": "Entity From Raw",
+ "description": "Created using inline raw body",
+ "status": "ACTIVE",
+ "category": "RAW_INPUT"
+ }
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/REGRESSION/resources/scenarios/http/condition/expected_3.json b/REGRESSION/resources/scenarios/http/condition/expected_3.json
new file mode 100644
index 0000000..aa52c5d
--- /dev/null
+++ b/REGRESSION/resources/scenarios/http/condition/expected_3.json
@@ -0,0 +1,9 @@
+[
+ {
+ "name": "Condition Entity",
+ "description": "Created when condition is true",
+ "status": "ACTIVE",
+ "category": "CONDITION_TRUE",
+ "uploadedFile": null
+ }
+]
\ No newline at end of file
diff --git a/REGRESSION/resources/scenarios/http/condition/expected_6.json b/REGRESSION/resources/scenarios/http/condition/expected_6.json
new file mode 100644
index 0000000..aa52c5d
--- /dev/null
+++ b/REGRESSION/resources/scenarios/http/condition/expected_6.json
@@ -0,0 +1,9 @@
+[
+ {
+ "name": "Condition Entity",
+ "description": "Created when condition is true",
+ "status": "ACTIVE",
+ "category": "CONDITION_TRUE",
+ "uploadedFile": null
+ }
+]
\ No newline at end of file
diff --git a/REGRESSION/resources/scenarios/http/condition/scenario.xml b/REGRESSION/resources/scenarios/http/condition/scenario.xml
new file mode 100644
index 0000000..9772df0
--- /dev/null
+++ b/REGRESSION/resources/scenarios/http/condition/scenario.xml
@@ -0,0 +1,98 @@
+
+
+
+ HTTP Condition
+
+ This scenario verifies HTTP request execution together with condition command.
+
+ Test flow includes:
+ 1. Create true condition.
+ 2. Execute POST request when condition is true.
+ 3. Verify entity was created successfully.
+ 4. Create false condition.
+ 5. Execute invalid POST request when condition is false.
+ 6. Verify invalid step was skipped and storage was not changed.
+ 7. Reset in-memory storage after test.
+
+ This scenario validates:
+ - Conditional execution when condition is true
+ - Skipped execution when condition is false
+ - Stable storage state after skipped step
+ - HTTP command interaction with condition logic
+
+ Vadym Kostenko
+
+
+
+ http
+
+
+
+
+
+
+
+
+
+ {
+ "name": "Condition Entity",
+ "description": "Created when condition is true",
+ "status": "ACTIVE",
+ "category": "CONDITION_TRUE"
+ }
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {
+ "name": "",
+ "description": "bad",
+ "status": "WRONG",
+ "category": "bad"
+ }
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/REGRESSION/resources/scenarios/http/headers/expected_1.json b/REGRESSION/resources/scenarios/http/headers/expected_1.json
new file mode 100644
index 0000000..f70710b
--- /dev/null
+++ b/REGRESSION/resources/scenarios/http/headers/expected_1.json
@@ -0,0 +1,3 @@
+{
+ "message" : "Header validated successfully"
+}
\ No newline at end of file
diff --git a/REGRESSION/resources/scenarios/http/headers/scenario.xml b/REGRESSION/resources/scenarios/http/headers/scenario.xml
new file mode 100644
index 0000000..aa7d190
--- /dev/null
+++ b/REGRESSION/resources/scenarios/http/headers/scenario.xml
@@ -0,0 +1,38 @@
+
+
+
+ HTTP Headers
+
+ This scenario verifies HTTP request and response header handling.
+
+ Test flow includes:
+ 1. Send POST request with custom request header.
+ 2. Verify response status = 200.
+ 3. Validate response body.
+ 4. Validate that response contains mapped custom header.
+
+ This scenario validates:
+ - Request header propagation
+ - Response header validation
+ - Header-based endpoint behavior
+
+ Vadym Kostenko
+
+
+
+ http
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/REGRESSION/resources/scenarios/http/methods/delete/expected_1.json b/REGRESSION/resources/scenarios/http/methods/delete/expected_1.json
new file mode 100644
index 0000000..f2de0ff
--- /dev/null
+++ b/REGRESSION/resources/scenarios/http/methods/delete/expected_1.json
@@ -0,0 +1,7 @@
+{
+ "name" : "Delete Entity",
+ "description" : "Will be deleted",
+ "status" : "NEW",
+ "category" : "DEFAULT",
+ "uploadedFile" : null
+}
\ No newline at end of file
diff --git a/REGRESSION/resources/scenarios/http/methods/delete/expected_3.json b/REGRESSION/resources/scenarios/http/methods/delete/expected_3.json
new file mode 100644
index 0000000..8878e54
--- /dev/null
+++ b/REGRESSION/resources/scenarios/http/methods/delete/expected_3.json
@@ -0,0 +1 @@
+[ ]
\ No newline at end of file
diff --git a/REGRESSION/resources/scenarios/http/methods/delete/scenario.xml b/REGRESSION/resources/scenarios/http/methods/delete/scenario.xml
new file mode 100644
index 0000000..744f6ca
--- /dev/null
+++ b/REGRESSION/resources/scenarios/http/methods/delete/scenario.xml
@@ -0,0 +1,59 @@
+
+
+
+ HTTP DELETE
+
+ This scenario verifies HTTP DELETE method behavior.
+
+ Test flow includes:
+ 1. Create entity in memory.
+ 2. Send DELETE request to remove all entities.
+ 3. Verify response status = 200.
+ 4. Send GET request to verify storage is empty.
+
+ This scenario validates:
+ - Full entity storage cleanup via DELETE method
+ - Correct removal of in-memory data
+ - Empty response state after deletion
+
+ Vadym Kostenko
+
+
+
+ http
+
+
+
+
+
+
+
+ {
+ "name": "Delete Entity",
+ "description": "Will be deleted",
+ "status": "NEW",
+ "category": "DEFAULT"
+ }
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/REGRESSION/resources/scenarios/http/methods/get/expected_2.json b/REGRESSION/resources/scenarios/http/methods/get/expected_2.json
new file mode 100644
index 0000000..cd634b6
--- /dev/null
+++ b/REGRESSION/resources/scenarios/http/methods/get/expected_2.json
@@ -0,0 +1,7 @@
+[ {
+ "name" : "Get Entity",
+ "description" : "Created before GET",
+ "status" : "NEW",
+ "category" : "DEFAULT",
+ "uploadedFile" : null
+} ]
\ No newline at end of file
diff --git a/REGRESSION/resources/scenarios/http/methods/get/scenario.xml b/REGRESSION/resources/scenarios/http/methods/get/scenario.xml
new file mode 100644
index 0000000..024d93b
--- /dev/null
+++ b/REGRESSION/resources/scenarios/http/methods/get/scenario.xml
@@ -0,0 +1,60 @@
+
+
+
+ HTTP GET
+
+ This scenario verifies HTTP GET method behavior.
+
+ Test flow includes:
+ 1. Create entity in memory using POST request.
+ 2. Send GET request to retrieve all entities.
+ 3. Verify response status = 200.
+ 4. Validate returned entities list.
+ 5. Reset in-memory storage after test.
+
+ This scenario validates:
+ - Retrieval of stored entities via GET method
+ - List response correctness
+ - Persistence of created test data in memory
+
+ Vadym Kostenko
+
+
+
+ http
+
+
+
+
+
+
+
+ {
+ "name": "Get Entity",
+ "description": "Created before GET",
+ "status": "NEW",
+ "category": "DEFAULT"
+ }
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/REGRESSION/resources/scenarios/http/methods/head/expected_1.json b/REGRESSION/resources/scenarios/http/methods/head/expected_1.json
new file mode 100644
index 0000000..51710d3
--- /dev/null
+++ b/REGRESSION/resources/scenarios/http/methods/head/expected_1.json
@@ -0,0 +1,7 @@
+{
+ "name" : "Head Entity",
+ "description" : "Entity for HEAD test",
+ "status" : "ACTIVE",
+ "category" : "TEST",
+ "uploadedFile" : null
+}
\ No newline at end of file
diff --git a/REGRESSION/resources/scenarios/http/methods/head/expected_2.json b/REGRESSION/resources/scenarios/http/methods/head/expected_2.json
new file mode 100644
index 0000000..e69de29
diff --git a/REGRESSION/resources/scenarios/http/methods/head/scenario.xml b/REGRESSION/resources/scenarios/http/methods/head/scenario.xml
new file mode 100644
index 0000000..c90ac1c
--- /dev/null
+++ b/REGRESSION/resources/scenarios/http/methods/head/scenario.xml
@@ -0,0 +1,63 @@
+
+
+
+ HTTP HEAD
+
+ This scenario verifies HTTP HEAD method behavior.
+
+ Test flow includes:
+ 1. Create entity in memory.
+ 2. Send HEAD request to retrieve metadata headers.
+ 3. Verify response status = 200.
+ 4. Validate returned custom headers.
+ 5. Reset in-memory storage after test.
+
+ This scenario validates:
+ - Header-only metadata retrieval via HEAD method
+ - Custom response header correctness
+
+ Vadym Kostenko
+
+
+
+ http
+
+
+
+
+
+
+
+ {
+ "name": "Head Entity",
+ "description": "Entity for HEAD test",
+ "status": "ACTIVE",
+ "category": "TEST"
+ }
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/REGRESSION/resources/scenarios/http/methods/options/scenario.xml b/REGRESSION/resources/scenarios/http/methods/options/scenario.xml
new file mode 100644
index 0000000..eb70059
--- /dev/null
+++ b/REGRESSION/resources/scenarios/http/methods/options/scenario.xml
@@ -0,0 +1,35 @@
+
+
+
+ HTTP OPTIONS
+
+ This scenario verifies HTTP OPTIONS method behavior.
+
+ Test flow includes:
+ 1. Send OPTIONS request to entities endpoint.
+ 2. Verify response status = 200.
+ 3. Validate Allow response header contains supported HTTP methods.
+
+ This scenario validates:
+ - Supported HTTP methods discovery via OPTIONS request
+ - Correct Allow response header
+
+ Vadym Kostenko
+
+
+
+ http
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/REGRESSION/resources/scenarios/http/methods/patch/expected_1.json b/REGRESSION/resources/scenarios/http/methods/patch/expected_1.json
new file mode 100644
index 0000000..9a2ad2b
--- /dev/null
+++ b/REGRESSION/resources/scenarios/http/methods/patch/expected_1.json
@@ -0,0 +1,7 @@
+{
+ "name": "Patch Entity",
+ "description": "Before patch",
+ "status": "NEW",
+ "category": "DEFAULT",
+ "uploadedFile": null
+}
\ No newline at end of file
diff --git a/REGRESSION/resources/scenarios/http/methods/patch/expected_2.json b/REGRESSION/resources/scenarios/http/methods/patch/expected_2.json
new file mode 100644
index 0000000..ebcddca
--- /dev/null
+++ b/REGRESSION/resources/scenarios/http/methods/patch/expected_2.json
@@ -0,0 +1,7 @@
+{
+ "name": "Patch Entity",
+ "description": "Before patch",
+ "status": "ARCHIVED",
+ "category": "DEFAULT",
+ "uploadedFile": null
+}
\ No newline at end of file
diff --git a/REGRESSION/resources/scenarios/http/methods/patch/scenario.xml b/REGRESSION/resources/scenarios/http/methods/patch/scenario.xml
new file mode 100644
index 0000000..3778d2a
--- /dev/null
+++ b/REGRESSION/resources/scenarios/http/methods/patch/scenario.xml
@@ -0,0 +1,67 @@
+
+
+
+ HTTP PATCH
+
+ This scenario verifies HTTP PATCH method behavior.
+
+ Test flow includes:
+ 1. Create initial entity in memory.
+ 2. Send PATCH request with partial update body.
+ 3. Verify response status = 200.
+ 4. Validate partially updated entity response body.
+ 5. Reset in-memory storage after test.
+
+ This scenario validates:
+ - Partial entity update via PATCH method
+ - Selective field modification
+ - Updated entity state correctness
+
+ Vadym Kostenko
+
+
+
+ http
+
+
+
+
+
+
+
+ {
+ "name": "Patch Entity",
+ "description": "Before patch",
+ "status": "NEW",
+ "category": "DEFAULT"
+ }
+
+
+
+
+
+
+
+
+
+
+ {
+ "status": "ARCHIVED"
+ }
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/REGRESSION/resources/scenarios/http/methods/post/expected_1.json b/REGRESSION/resources/scenarios/http/methods/post/expected_1.json
new file mode 100644
index 0000000..d5fe0d8
--- /dev/null
+++ b/REGRESSION/resources/scenarios/http/methods/post/expected_1.json
@@ -0,0 +1,7 @@
+{
+ "name" : "Post Entity",
+ "description" : "Created via POST",
+ "status" : "NEW",
+ "category" : "DEFAULT",
+ "uploadedFile" : null
+}
\ No newline at end of file
diff --git a/REGRESSION/resources/scenarios/http/methods/post/scenario.xml b/REGRESSION/resources/scenarios/http/methods/post/scenario.xml
new file mode 100644
index 0000000..805e7d1
--- /dev/null
+++ b/REGRESSION/resources/scenarios/http/methods/post/scenario.xml
@@ -0,0 +1,53 @@
+
+
+
+ HTTP POST
+
+ This scenario verifies HTTP POST method behavior.
+
+ Test flow includes:
+ 1. Send POST request with valid JSON body.
+ 2. Verify response status = 201.
+ 3. Validate created entity response body.
+ 4. Reset in-memory storage after test.
+
+ This scenario validates:
+ - Entity creation via POST method
+ - JSON request body handling
+ - Response body correctness
+ - In-memory reset behavior
+
+ Vadym Kostenko
+
+
+
+ http
+
+
+
+
+
+
+
+ {
+ "name": "Post Entity",
+ "description": "Created via POST",
+ "status": "NEW",
+ "category": "DEFAULT"
+ }
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/REGRESSION/resources/scenarios/http/methods/put/expected_1.json b/REGRESSION/resources/scenarios/http/methods/put/expected_1.json
new file mode 100644
index 0000000..73add39
--- /dev/null
+++ b/REGRESSION/resources/scenarios/http/methods/put/expected_1.json
@@ -0,0 +1,7 @@
+{
+ "name": "Old Name",
+ "description": "Old Description",
+ "status": "NEW",
+ "category": "DEFAULT",
+ "uploadedFile": null
+}
\ No newline at end of file
diff --git a/REGRESSION/resources/scenarios/http/methods/put/expected_2.json b/REGRESSION/resources/scenarios/http/methods/put/expected_2.json
new file mode 100644
index 0000000..1763587
--- /dev/null
+++ b/REGRESSION/resources/scenarios/http/methods/put/expected_2.json
@@ -0,0 +1,7 @@
+{
+ "name": "Updated Name",
+ "description": "Updated Description",
+ "status": "ACTIVE",
+ "category": "UPDATED",
+ "uploadedFile": null
+}
\ No newline at end of file
diff --git a/REGRESSION/resources/scenarios/http/methods/put/scenario.xml b/REGRESSION/resources/scenarios/http/methods/put/scenario.xml
new file mode 100644
index 0000000..59084d4
--- /dev/null
+++ b/REGRESSION/resources/scenarios/http/methods/put/scenario.xml
@@ -0,0 +1,70 @@
+
+
+
+ HTTP PUT
+
+ This scenario verifies HTTP PUT method behavior.
+
+ Test flow includes:
+ 1. Create initial entity in memory.
+ 2. Send PUT request to fully replace the last entity.
+ 3. Verify response status = 200.
+ 4. Validate updated entity response body.
+ 5. Reset in-memory storage after test.
+
+ This scenario validates:
+ - Full entity replacement via PUT method
+ - Request body handling
+ - Updated entity state correctness
+
+ Vadym Kostenko
+
+
+
+ http
+
+
+
+
+
+
+
+ {
+ "name": "Old Name",
+ "description": "Old Description",
+ "status": "NEW",
+ "category": "DEFAULT"
+ }
+
+
+
+
+
+
+
+
+
+
+ {
+ "name": "Updated Name",
+ "description": "Updated Description",
+ "status": "ACTIVE",
+ "category": "UPDATED"
+ }
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/REGRESSION/resources/scenarios/http/mode/expected_1.json b/REGRESSION/resources/scenarios/http/mode/expected_1.json
new file mode 100644
index 0000000..967eced
--- /dev/null
+++ b/REGRESSION/resources/scenarios/http/mode/expected_1.json
@@ -0,0 +1,7 @@
+{
+ "name": "Mode Entity",
+ "description": "Testing comparison mode",
+ "status": "ACTIVE",
+ "category": "MODE",
+ "uploadedFile": null
+}
\ No newline at end of file
diff --git a/REGRESSION/resources/scenarios/http/mode/expected_2.json b/REGRESSION/resources/scenarios/http/mode/expected_2.json
new file mode 100644
index 0000000..16af97a
--- /dev/null
+++ b/REGRESSION/resources/scenarios/http/mode/expected_2.json
@@ -0,0 +1,5 @@
+[
+ {
+ "name": "Mode Entity"
+ }
+]
\ No newline at end of file
diff --git a/REGRESSION/resources/scenarios/http/mode/expected_3.json b/REGRESSION/resources/scenarios/http/mode/expected_3.json
new file mode 100644
index 0000000..c7f5e1c
--- /dev/null
+++ b/REGRESSION/resources/scenarios/http/mode/expected_3.json
@@ -0,0 +1,9 @@
+[
+ {
+ "name": "Mode Entity",
+ "description": "Testing comparison mode",
+ "status": "ACTIVE",
+ "category": "MODE",
+ "uploadedFile": null
+ }
+]
\ No newline at end of file
diff --git a/REGRESSION/resources/scenarios/http/mode/scenario.xml b/REGRESSION/resources/scenarios/http/mode/scenario.xml
new file mode 100644
index 0000000..d45b2eb
--- /dev/null
+++ b/REGRESSION/resources/scenarios/http/mode/scenario.xml
@@ -0,0 +1,68 @@
+
+
+
+ HTTP Response Mode
+
+ This scenario verifies difference between strict and lenient response comparison modes.
+
+ Test flow includes:
+ 1. Create entity in memory.
+ 2. Retrieve all entities using lenient mode and validate response with partial expected JSON.
+ 3. Verify response status = 200 and ensure comparison passes even though expected file contains only part of the response.
+ 4. Retrieve all entities using strict mode and validate response with full expected JSON.
+ 5. Verify response status = 200 and ensure comparison passes only because expected file contains the full response structure.
+ 6. Reset in-memory storage after test.
+
+ This scenario validates:
+ - Lenient mode allows partial response validation
+ - Strict mode requires full response match
+ - Same response can be validated differently depending on comparison mode
+
+ Vadym Kostenko
+
+
+
+ http
+
+
+
+
+
+
+
+ {
+ "name": "Mode Entity",
+ "description": "Testing comparison mode",
+ "status": "ACTIVE",
+ "category": "MODE"
+ }
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/REGRESSION/resources/scenarios/http/repeat/times/expected_5.json b/REGRESSION/resources/scenarios/http/repeat/times/expected_5.json
new file mode 100644
index 0000000..bfae6a6
--- /dev/null
+++ b/REGRESSION/resources/scenarios/http/repeat/times/expected_5.json
@@ -0,0 +1,23 @@
+[
+ {
+ "name": "Repeat Time Entity",
+ "description": "Created inside repeat times block",
+ "status": "ACTIVE",
+ "category": "REPEAT_TIME",
+ "uploadedFile": null
+ },
+ {
+ "name": "Repeat Time Entity",
+ "description": "Created inside repeat times block",
+ "status": "ACTIVE",
+ "category": "REPEAT_TIME",
+ "uploadedFile": null
+ },
+ {
+ "name": "Repeat Time Entity",
+ "description": "Created inside repeat times block",
+ "status": "ACTIVE",
+ "category": "REPEAT_TIME",
+ "uploadedFile": null
+ }
+]
\ No newline at end of file
diff --git a/REGRESSION/resources/scenarios/http/repeat/times/scenario.xml b/REGRESSION/resources/scenarios/http/repeat/times/scenario.xml
new file mode 100644
index 0000000..3e0226e
--- /dev/null
+++ b/REGRESSION/resources/scenarios/http/repeat/times/scenario.xml
@@ -0,0 +1,66 @@
+
+
+
+ HTTP Repeat Times
+
+ This scenario verifies HTTP request execution inside repeat block using times.
+
+ Test flow includes:
+ 1. Execute POST request inside repeat block three times.
+ 2. Create one entity during each iteration.
+ 3. Send GET request after repeat block.
+ 4. Verify that three entities were created in memory.
+ 5. Reset in-memory storage after test.
+
+ This scenario validates:
+ - Repeat execution using times attribute
+ - Stable repeated HTTP POST execution
+ - Data accumulation across repeat iterations
+ - Final storage consistency after repeated execution
+
+ Vadym Kostenko
+
+
+
+ http
+
+
+
+
+
+
+
+
+
+ {
+ "name": "Repeat Time Entity",
+ "description": "Created inside repeat times block",
+ "status": "ACTIVE",
+ "category": "REPEAT_TIME"
+ }
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/REGRESSION/resources/scenarios/http/repeat/variations/expected_5.json b/REGRESSION/resources/scenarios/http/repeat/variations/expected_5.json
new file mode 100644
index 0000000..1e531e2
--- /dev/null
+++ b/REGRESSION/resources/scenarios/http/repeat/variations/expected_5.json
@@ -0,0 +1,23 @@
+[
+ {
+ "name": "Repeat Variation One",
+ "description": "Created from first repeat variation",
+ "status": "NEW",
+ "category": "REPEAT_ONE",
+ "uploadedFile": null
+ },
+ {
+ "name": "Repeat Variation Two",
+ "description": "Created from second repeat variation",
+ "status": "ACTIVE",
+ "category": "REPEAT_TWO",
+ "uploadedFile": null
+ },
+ {
+ "name": "Repeat Variation Three",
+ "description": "Created from third repeat variation",
+ "status": "ARCHIVED",
+ "category": "REPEAT_THREE",
+ "uploadedFile": null
+ }
+]
\ No newline at end of file
diff --git a/REGRESSION/resources/scenarios/http/repeat/variations/scenario.xml b/REGRESSION/resources/scenarios/http/repeat/variations/scenario.xml
new file mode 100644
index 0000000..688c092
--- /dev/null
+++ b/REGRESSION/resources/scenarios/http/repeat/variations/scenario.xml
@@ -0,0 +1,66 @@
+
+
+
+ HTTP Repeat Variations
+
+ This scenario verifies HTTP request execution inside repeat block using variations.
+
+ Test flow includes:
+ 1. Execute POST request inside repeat block using variation rows.
+ 2. Create one entity for each variation.
+ 3. Send GET request after repeat block.
+ 4. Verify that all variation-based entities were created.
+ 5. Reset in-memory storage after test.
+
+ This scenario validates:
+ - Repeat execution using variations attribute
+ - Stable repeated HTTP execution with CSV-based input
+ - Correct interpolation of variation values
+ - Final storage consistency after repeated execution
+
+ Vadym Kostenko
+
+
+
+ http
+
+
+
+
+
+
+
+
+
+ {
+ "name": "{{name}}",
+ "description": "{{description}}",
+ "status": "{{status}}",
+ "category": "{{category}}"
+ }
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/REGRESSION/resources/scenarios/http/variables/body_9.json b/REGRESSION/resources/scenarios/http/variables/body_9.json
new file mode 100644
index 0000000..0fd71df
--- /dev/null
+++ b/REGRESSION/resources/scenarios/http/variables/body_9.json
@@ -0,0 +1,6 @@
+{
+ "name": "{{fileEntityName}}",
+ "description": "{{fileEntityDescription}}",
+ "status": "{{fileEntityStatus}}",
+ "category": "{{fileEntityCategory}}"
+}
\ No newline at end of file
diff --git a/REGRESSION/resources/scenarios/http/variables/expected_23.json b/REGRESSION/resources/scenarios/http/variables/expected_23.json
new file mode 100644
index 0000000..985f989
--- /dev/null
+++ b/REGRESSION/resources/scenarios/http/variables/expected_23.json
@@ -0,0 +1,7 @@
+{
+ "name": "{{entityName}}",
+ "description": "{{entityDescription}}",
+ "status": "{{entityStatus}}",
+ "category": "{{entityCategory}}",
+ "uploadedFile": null
+}
\ No newline at end of file
diff --git a/REGRESSION/resources/scenarios/http/variables/expected_24.json b/REGRESSION/resources/scenarios/http/variables/expected_24.json
new file mode 100644
index 0000000..a625ae0
--- /dev/null
+++ b/REGRESSION/resources/scenarios/http/variables/expected_24.json
@@ -0,0 +1,7 @@
+{
+ "name": "{{fileEntityName}}",
+ "description": "{{fileEntityDescription}}",
+ "status": "{{fileEntityStatus}}",
+ "category": "{{fileEntityCategory}}",
+ "uploadedFile": null
+}
\ No newline at end of file
diff --git a/REGRESSION/resources/scenarios/http/variables/expected_25.json b/REGRESSION/resources/scenarios/http/variables/expected_25.json
new file mode 100644
index 0000000..407b987
--- /dev/null
+++ b/REGRESSION/resources/scenarios/http/variables/expected_25.json
@@ -0,0 +1,3 @@
+{
+ "message": "{{headerResponse}}"
+}
\ No newline at end of file
diff --git a/REGRESSION/resources/scenarios/http/variables/expected_8.json b/REGRESSION/resources/scenarios/http/variables/expected_8.json
new file mode 100644
index 0000000..985f989
--- /dev/null
+++ b/REGRESSION/resources/scenarios/http/variables/expected_8.json
@@ -0,0 +1,7 @@
+{
+ "name": "{{entityName}}",
+ "description": "{{entityDescription}}",
+ "status": "{{entityStatus}}",
+ "category": "{{entityCategory}}",
+ "uploadedFile": null
+}
\ No newline at end of file
diff --git a/REGRESSION/resources/scenarios/http/variables/scenario.xml b/REGRESSION/resources/scenarios/http/variables/scenario.xml
new file mode 100644
index 0000000..a8190af
--- /dev/null
+++ b/REGRESSION/resources/scenarios/http/variables/scenario.xml
@@ -0,0 +1,203 @@
+
+
+
+ HTTP Variables
+
+ This scenario verifies HTTP request execution using variables.
+
+ Test flow includes:
+ 1. Create variables for comments, endpoints, headers, condition, request body values and expected values.
+ 2. Send POST request using variables in comment, endpoint, condition and raw request body.
+ 3. Verify response status = 201 using expected file with injected variables.
+ 4. Send second POST request using body file with injected variables.
+ 5. Verify second entity creation using expected file with injected variables.
+ 6. Send request with variable-based request and response headers.
+ 7. Verify response status, body and headers.
+ 8. Reset in-memory storage using variable-based endpoint.
+
+ This scenario validates:
+ - Variable injection into comment
+ - Variable injection into condition
+ - Variable injection into HTTP endpoints
+ - Variable injection into raw request body
+ - Variable injection into request body file content
+ - Variable injection into expected file content
+ - Variable injection into request headers
+ - Variable injection into response headers
+ - Variable reuse across HTTP steps
+
+ Vadym Kostenko
+
+
+
+ http
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {
+ "name": "{{entityName}}",
+ "description": "{{entityDescription}}",
+ "status": "{{entityStatus}}",
+ "category": "{{entityCategory}}"
+ }
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/REGRESSION/resources/scenarios/http/variations/expected_1_1.json b/REGRESSION/resources/scenarios/http/variations/expected_1_1.json
new file mode 100644
index 0000000..1d6b71b
--- /dev/null
+++ b/REGRESSION/resources/scenarios/http/variations/expected_1_1.json
@@ -0,0 +1,7 @@
+{
+ "name": "{{name}}",
+ "description": "{{description}}",
+ "status": "{{status}}",
+ "category": "{{category}}",
+ "uploadedFile": null
+}
\ No newline at end of file
diff --git a/REGRESSION/resources/scenarios/http/variations/expected_1_2.json b/REGRESSION/resources/scenarios/http/variations/expected_1_2.json
new file mode 100644
index 0000000..1d6b71b
--- /dev/null
+++ b/REGRESSION/resources/scenarios/http/variations/expected_1_2.json
@@ -0,0 +1,7 @@
+{
+ "name": "{{name}}",
+ "description": "{{description}}",
+ "status": "{{status}}",
+ "category": "{{category}}",
+ "uploadedFile": null
+}
\ No newline at end of file
diff --git a/REGRESSION/resources/scenarios/http/variations/scenario.xml b/REGRESSION/resources/scenarios/http/variations/scenario.xml
new file mode 100644
index 0000000..416f73c
--- /dev/null
+++ b/REGRESSION/resources/scenarios/http/variations/scenario.xml
@@ -0,0 +1,57 @@
+
+
+
+ HTTP Variations
+
+ This scenario verifies HTTP request execution using variations file.
+
+ Test flow includes:
+ 1. Load test data from variations CSV file.
+ 2. Send POST request for each variation row.
+ 3. Verify response status = 201 for each iteration.
+ 4. Validate response body using expected file from variation.
+ 5. Reset in-memory storage after all iterations.
+
+ This scenario validates:
+ - Variation value injection into comment
+ - Variation value injection into endpoint
+ - Variation value injection into request body
+ - Variation value injection into expected file names
+ - Repeated HTTP execution using multiple variation rows
+ - Stable entity creation flow for different input values
+
+ Vadym Kostenko
+
+
+
+ httpVariations.csv
+ http
+
+
+
+
+
+
+
+ {
+ "name": "{{name}}",
+ "description": "{{description}}",
+ "status": "{{status}}",
+ "category": "{{category}}"
+ }
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/REGRESSION/resources/scenarios/websocket/standart/condition/expected_3.json b/REGRESSION/resources/scenarios/websocket/standart/condition/expected_3.json
new file mode 100644
index 0000000..d76351e
--- /dev/null
+++ b/REGRESSION/resources/scenarios/websocket/standart/condition/expected_3.json
@@ -0,0 +1,3 @@
+[
+ "ping"
+]
\ No newline at end of file
diff --git a/REGRESSION/resources/scenarios/websocket/standart/condition/expected_7.json b/REGRESSION/resources/scenarios/websocket/standart/condition/expected_7.json
new file mode 100644
index 0000000..d76351e
--- /dev/null
+++ b/REGRESSION/resources/scenarios/websocket/standart/condition/expected_7.json
@@ -0,0 +1,3 @@
+[
+ "ping"
+]
\ No newline at end of file
diff --git a/REGRESSION/resources/scenarios/websocket/standart/condition/scenario.xml b/REGRESSION/resources/scenarios/websocket/standart/condition/scenario.xml
new file mode 100644
index 0000000..d3a9646
--- /dev/null
+++ b/REGRESSION/resources/scenarios/websocket/standart/condition/scenario.xml
@@ -0,0 +1,68 @@
+
+
+
+ WebSocket Standard Text Condition
+
+ This scenario verifies condition support for standard WebSocket commands.
+
+ Test flow includes:
+ 1. Create true and false conditions.
+ 2. Execute standard websocket flow with true condition.
+ 3. Verify websocket command is executed successfully.
+ 4. Execute second websocket flow with false condition.
+ 5. Verify false-conditioned websocket block is skipped.
+
+ This scenario validates:
+ - Websocket command execution when condition = true
+ - Websocket command skipping when condition = false
+ - Stable condition handling for standard websocket flow
+
+ Vadym Kostenko
+
+
+
+ websocket
+
+
+
+
+
+
+
+
+
+
+ ping
+
+
+
+ expected_3.json
+
+
+
+
+
+
+
+ THIS_MUST_NEVER_BE_SENT
+
+
+
+ expected_7.json
+
+
+
+
+
\ No newline at end of file
diff --git a/REGRESSION/resources/scenarios/websocket/standart/general/expected_3.json b/REGRESSION/resources/scenarios/websocket/standart/general/expected_3.json
new file mode 100644
index 0000000..d76351e
--- /dev/null
+++ b/REGRESSION/resources/scenarios/websocket/standart/general/expected_3.json
@@ -0,0 +1,3 @@
+[
+ "ping"
+]
\ No newline at end of file
diff --git a/REGRESSION/resources/scenarios/websocket/standart/general/scenario.xml b/REGRESSION/resources/scenarios/websocket/standart/general/scenario.xml
new file mode 100644
index 0000000..87453fa
--- /dev/null
+++ b/REGRESSION/resources/scenarios/websocket/standart/general/scenario.xml
@@ -0,0 +1,44 @@
+
+
+
+ WebSocket Standard Text General
+
+ This scenario verifies basic standard WebSocket text flow.
+
+ Test flow includes:
+ 1. Connect to standard WebSocket.
+ 2. Receive initial CONNECTED message.
+ 3. Send ping text message.
+ 4. Receive PONG response.
+ 5. Send custom text message.
+ 6. Receive ECHO response.
+
+ This scenario validates:
+ - Standard websocket connection lifecycle
+ - Text message send/receive flow
+ - Correct response handling for different message types
+
+ Vadym Kostenko
+
+
+
+ websocket
+
+
+
+
+
+ ping
+
+
+
+ expected_3.json
+
+
+
+
+
\ No newline at end of file
diff --git a/REGRESSION/resources/scenarios/websocket/standart/variables/expected_4.json b/REGRESSION/resources/scenarios/websocket/standart/variables/expected_4.json
new file mode 100644
index 0000000..9870142
--- /dev/null
+++ b/REGRESSION/resources/scenarios/websocket/standart/variables/expected_4.json
@@ -0,0 +1,3 @@
+[
+ "{{firstMessage}}"
+]
\ No newline at end of file
diff --git a/REGRESSION/resources/scenarios/websocket/standart/variables/scenario.xml b/REGRESSION/resources/scenarios/websocket/standart/variables/scenario.xml
new file mode 100644
index 0000000..7820279
--- /dev/null
+++ b/REGRESSION/resources/scenarios/websocket/standart/variables/scenario.xml
@@ -0,0 +1,72 @@
+
+
+
+ WebSocket Standard Text Variables
+
+ This scenario verifies standard WebSocket text execution using variables.
+
+ Test flow includes:
+ 1. Create variables for websocket comments, messages and expected files.
+ 2. Connect to standard WebSocket.
+ 3. Send first text message using variable.
+ 4. Receive first echoed response.
+
+ This scenario validates:
+ - Variable injection into websocket comments
+ - Variable injection into websocket text messages
+ - Variable injection into expected file names
+ - Variable reuse across send/receive steps
+ - Stable standard websocket text flow
+
+ Vadym Kostenko
+
+
+
+ websocket
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{firstMessage}}
+
+
+
+ expected_4.json
+
+
+
+
\ No newline at end of file
diff --git a/REGRESSION/resources/scenarios/websocket/standart/variations/expected_2_1.json b/REGRESSION/resources/scenarios/websocket/standart/variations/expected_2_1.json
new file mode 100644
index 0000000..e5b22ec
--- /dev/null
+++ b/REGRESSION/resources/scenarios/websocket/standart/variations/expected_2_1.json
@@ -0,0 +1,3 @@
+[
+ "{{message}}"
+]
\ No newline at end of file
diff --git a/REGRESSION/resources/scenarios/websocket/standart/variations/expected_2_2.json b/REGRESSION/resources/scenarios/websocket/standart/variations/expected_2_2.json
new file mode 100644
index 0000000..e5b22ec
--- /dev/null
+++ b/REGRESSION/resources/scenarios/websocket/standart/variations/expected_2_2.json
@@ -0,0 +1,3 @@
+[
+ "{{message}}"
+]
\ No newline at end of file
diff --git a/REGRESSION/resources/scenarios/websocket/standart/variations/scenario.xml b/REGRESSION/resources/scenarios/websocket/standart/variations/scenario.xml
new file mode 100644
index 0000000..d16460a
--- /dev/null
+++ b/REGRESSION/resources/scenarios/websocket/standart/variations/scenario.xml
@@ -0,0 +1,50 @@
+
+
+
+ WebSocket Standard Text Variations
+
+ This scenario verifies standard WebSocket text execution using variations file.
+
+ Test flow includes:
+ 1. Load websocket messages and attributes from variations CSV file.
+ 2. Connect to standard WebSocket.
+ 3. Send text message for each variation row.
+ 4. Receive echoed response for each iteration.
+ 5. Validate echoed response using expected file from variation.
+
+ This scenario validates:
+ - Variation injection into websocket comment
+ - Variation injection into send comment
+ - Variation injection into receive comment
+ - Variation injection into message
+ - Variation injection into timeout and limit
+ - Variation injection into expected file names
+ - Stable execution across variation rows
+
+ Vadym Kostenko
+
+
+
+ websocketStandardVariations.csv
+ websocket
+
+
+
+
+
+ {{message}}
+
+
+
+ {{expected_2}}.json
+
+
+
+
+
\ No newline at end of file
diff --git a/REGRESSION/resources/scenarios/websocket/stomp/condition/expected_13.json b/REGRESSION/resources/scenarios/websocket/stomp/condition/expected_13.json
new file mode 100644
index 0000000..e69de29
diff --git a/REGRESSION/resources/scenarios/websocket/stomp/condition/expected_6.json b/REGRESSION/resources/scenarios/websocket/stomp/condition/expected_6.json
new file mode 100644
index 0000000..ee1e3ee
--- /dev/null
+++ b/REGRESSION/resources/scenarios/websocket/stomp/condition/expected_6.json
@@ -0,0 +1,5 @@
+[
+ {
+ "value": "ping"
+ }
+]
\ No newline at end of file
diff --git a/REGRESSION/resources/scenarios/websocket/stomp/condition/scenario.xml b/REGRESSION/resources/scenarios/websocket/stomp/condition/scenario.xml
new file mode 100644
index 0000000..3e04574
--- /dev/null
+++ b/REGRESSION/resources/scenarios/websocket/stomp/condition/scenario.xml
@@ -0,0 +1,89 @@
+
+
+
+ WebSocket STOMP Condition
+
+ This scenario verifies condition support for STOMP WebSocket commands.
+
+ Test flow includes:
+ 1. Create true and false conditions.
+ 2. Execute STOMP websocket flow with true condition.
+ 3. Subscribe to ping topic.
+ 4. Send ping message.
+ 5. Receive expected ping response.
+ 6. Execute second STOMP websocket flow with false condition.
+ 7. Verify false-conditioned websocket block is skipped.
+
+ This scenario validates:
+ - STOMP websocket execution when condition = true
+ - STOMP websocket skipping when condition = false
+ - Stable condition handling for STOMP flow
+
+ Vadym Kostenko
+
+
+
+ websocket
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ping
+
+
+
+ expected_6.json
+
+
+
+
+
+
+
+
+
+
+
+
+
+ SHOULD_NOT_RUN
+
+
+
+ expected_13.json
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/REGRESSION/resources/scenarios/websocket/stomp/subscribe/ping/expected_4.json b/REGRESSION/resources/scenarios/websocket/stomp/subscribe/ping/expected_4.json
new file mode 100644
index 0000000..af44d4c
--- /dev/null
+++ b/REGRESSION/resources/scenarios/websocket/stomp/subscribe/ping/expected_4.json
@@ -0,0 +1,5 @@
+[
+ {
+ "value": "hello websocket"
+ }
+]
\ No newline at end of file
diff --git a/REGRESSION/resources/scenarios/websocket/stomp/subscribe/ping/scenario.xml b/REGRESSION/resources/scenarios/websocket/stomp/subscribe/ping/scenario.xml
new file mode 100644
index 0000000..8eee39d
--- /dev/null
+++ b/REGRESSION/resources/scenarios/websocket/stomp/subscribe/ping/scenario.xml
@@ -0,0 +1,53 @@
+
+
+
+ WebSocket STOMP General - Simple Send Receive
+
+ This scenario verifies basic STOMP WebSocket functionality.
+
+ Test flow includes:
+ 1. Connect to STOMP WebSocket.
+ 2. Subscribe to /topic/ping.
+ 3. Send message to /app/ping.
+ 4. Receive message from /topic/ping.
+
+ This scenario validates:
+ - STOMP connection
+ - Subscribe mechanism
+ - Send/Receive flow
+
+ Vadym Kostenko
+
+
+
+ websocket
+
+
+
+
+
+
+
+
+
+ hello websocket
+
+
+
+ expected_4.json
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/REGRESSION/resources/scenarios/websocket/stomp/subscribe/test/expected_5.json b/REGRESSION/resources/scenarios/websocket/stomp/subscribe/test/expected_5.json
new file mode 100644
index 0000000..8878e54
--- /dev/null
+++ b/REGRESSION/resources/scenarios/websocket/stomp/subscribe/test/expected_5.json
@@ -0,0 +1 @@
+[ ]
\ No newline at end of file
diff --git a/REGRESSION/resources/scenarios/websocket/stomp/subscribe/test/expected_6.json b/REGRESSION/resources/scenarios/websocket/stomp/subscribe/test/expected_6.json
new file mode 100644
index 0000000..8878e54
--- /dev/null
+++ b/REGRESSION/resources/scenarios/websocket/stomp/subscribe/test/expected_6.json
@@ -0,0 +1 @@
+[ ]
\ No newline at end of file
diff --git a/REGRESSION/resources/scenarios/websocket/stomp/subscribe/test/scenario.xml b/REGRESSION/resources/scenarios/websocket/stomp/subscribe/test/scenario.xml
new file mode 100644
index 0000000..248f381
--- /dev/null
+++ b/REGRESSION/resources/scenarios/websocket/stomp/subscribe/test/scenario.xml
@@ -0,0 +1,58 @@
+
+
+
+ WebSocket STOMP General - Topic Isolation
+
+ This scenario verifies that messages are delivered only to the correct subscribed topic.
+
+ Test flow includes:
+ 1. Connect to STOMP WebSocket.
+ 2. Subscribe to /topic/ping.
+ 3. Subscribe to /topic/test.
+ 4. Send message to /app/ping.
+ 5. Receive message from /topic/ping.
+ 6. Verify that /topic/test remains empty.
+
+ This scenario validates:
+ - STOMP multiple subscriptions
+ - Correct topic routing
+ - No unexpected message delivery to unrelated topic
+
+ Vadym Kostenko
+
+
+
+ websocket
+
+
+
+
+
+
+
+
+
+
+
+ ping isolation check
+
+
+
+ expected_5.json
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/REGRESSION/resources/scenarios/websocket/stomp/variable/expected_7.json b/REGRESSION/resources/scenarios/websocket/stomp/variable/expected_7.json
new file mode 100644
index 0000000..7b69e05
--- /dev/null
+++ b/REGRESSION/resources/scenarios/websocket/stomp/variable/expected_7.json
@@ -0,0 +1,5 @@
+[
+ {
+ "value": "{{pingMessage}}"
+ }
+]
\ No newline at end of file
diff --git a/REGRESSION/resources/scenarios/websocket/stomp/variable/scenario.xml b/REGRESSION/resources/scenarios/websocket/stomp/variable/scenario.xml
new file mode 100644
index 0000000..c07d669
--- /dev/null
+++ b/REGRESSION/resources/scenarios/websocket/stomp/variable/scenario.xml
@@ -0,0 +1,75 @@
+
+
+
+ WebSocket STOMP Variables
+
+ This scenario verifies STOMP WebSocket execution using variables.
+
+ Test flow includes:
+ 1. Create variables for endpoints, message content and expected file.
+ 2. Connect to STOMP WebSocket.
+ 3. Subscribe to topic using variable.
+ 4. Send message using variables in endpoint and body.
+ 5. Receive and verify response using expected file variable.
+
+ This scenario validates:
+ - Variable injection into websocket endpoint
+ - Variable injection into message body
+ - Variable injection into topic
+ - Variable injection into expected file
+
+ Vadym Kostenko
+
+
+
+ websocket
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{pingMessage}}
+
+
+
+ expected_7.json
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/REGRESSION/resources/scenarios/websocket/stomp/variations/expected_2_1.json b/REGRESSION/resources/scenarios/websocket/stomp/variations/expected_2_1.json
new file mode 100644
index 0000000..a81cc88
--- /dev/null
+++ b/REGRESSION/resources/scenarios/websocket/stomp/variations/expected_2_1.json
@@ -0,0 +1,5 @@
+[
+ {
+ "value": "{{message}}"
+ }
+]
\ No newline at end of file
diff --git a/REGRESSION/resources/scenarios/websocket/stomp/variations/expected_2_2.json b/REGRESSION/resources/scenarios/websocket/stomp/variations/expected_2_2.json
new file mode 100644
index 0000000..a81cc88
--- /dev/null
+++ b/REGRESSION/resources/scenarios/websocket/stomp/variations/expected_2_2.json
@@ -0,0 +1,5 @@
+[
+ {
+ "value": "{{message}}"
+ }
+]
\ No newline at end of file
diff --git a/REGRESSION/resources/scenarios/websocket/stomp/variations/scenario.xml b/REGRESSION/resources/scenarios/websocket/stomp/variations/scenario.xml
new file mode 100644
index 0000000..5581a21
--- /dev/null
+++ b/REGRESSION/resources/scenarios/websocket/stomp/variations/scenario.xml
@@ -0,0 +1,56 @@
+
+
+
+ WebSocket STOMP Variations
+
+ This scenario verifies STOMP WebSocket execution using variation data.
+
+ Test flow includes:
+ 1. Load websocket configuration from variations CSV file.
+ 2. Connect to STOMP WebSocket.
+ 3. Subscribe to topic using variation value.
+ 4. Send message using variation endpoint and payload.
+ 5. Receive and verify response using variation expected file.
+
+ This scenario validates:
+ - Variation injection into websocket endpoint
+ - Variation injection into message body
+ - Variation injection into topic
+ - Variation injection into expected file
+ - Stable STOMP execution across multiple variation rows
+
+ Vadym Kostenko
+
+
+
+ websocketStompVariations.csv
+ websocket
+
+
+
+
+
+
+
+
+
+ {{message}}
+
+
+
+ {{expected_2}}.json
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/TEST-API/src/main/java/com/knubisoft/testapi/api/ApiTestBasicAuthApi.java b/TEST-API/src/main/java/com/knubisoft/testapi/api/ApiTestBasicAuthApi.java
new file mode 100644
index 0000000..9d751b4
--- /dev/null
+++ b/TEST-API/src/main/java/com/knubisoft/testapi/api/ApiTestBasicAuthApi.java
@@ -0,0 +1,69 @@
+package com.knubisoft.testapi.api;
+
+import com.knubisoft.testapi.dto.auth.basic.BasicCreateUserRequest;
+import com.knubisoft.testapi.dto.auth.basic.BasicUserResponse;
+import com.knubisoft.testapi.exception.ErrorResponse;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.media.ArraySchema;
+import io.swagger.v3.oas.annotations.media.Content;
+import io.swagger.v3.oas.annotations.media.Schema;
+import io.swagger.v3.oas.annotations.responses.ApiResponse;
+import io.swagger.v3.oas.annotations.responses.ApiResponses;
+import org.springframework.http.MediaType;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestHeader;
+import org.springframework.web.bind.annotation.RequestMapping;
+
+import javax.validation.Valid;
+import java.util.List;
+
+@ApiResponses(value = {
+ @ApiResponse(responseCode = "400", description = "Bad Request", content = {
+ @Content(schema = @Schema(implementation = ErrorResponse.class))
+ }),
+ @ApiResponse(responseCode = "401", description = "Unauthorized", content = {
+ @Content(schema = @Schema(implementation = ErrorResponse.class))
+ }),
+ @ApiResponse(responseCode = "500", description = "Internal Server Error", content = {
+ @Content(schema = @Schema(implementation = ErrorResponse.class))
+ })
+})
+@RequestMapping("/api/test/auth/basic")
+public interface ApiTestBasicAuthApi {
+
+ @GetMapping("/users")
+ @Operation(summary = "Get all users with basic auth", description = "Protected endpoint that requires Authorization Basic header")
+ @ApiResponse(responseCode = "200", description = "Success", content = {
+ @Content(
+ mediaType = MediaType.APPLICATION_JSON_VALUE,
+ array = @ArraySchema(schema = @Schema(implementation = BasicUserResponse.class))
+ )
+ })
+ ResponseEntity> getUsers(
+ @Parameter(description = "Authorization header with Basic credentials", required = true)
+ @RequestHeader(value = "Authorization", required = false) String authorizationHeader
+ );
+
+ @PostMapping("/users")
+ @Operation(summary = "Create user with basic auth", description = "Protected endpoint that creates new user")
+ @ApiResponse(responseCode = "200", description = "Success", content = {
+ @Content(
+ mediaType = MediaType.APPLICATION_JSON_VALUE,
+ schema = @Schema(implementation = BasicUserResponse.class)
+ )
+ })
+ ResponseEntity createUser(
+ @Parameter(description = "Authorization header with Basic credentials", required = true)
+ @RequestHeader(value = "Authorization", required = false) String authorizationHeader,
+ @RequestBody @Valid BasicCreateUserRequest request
+ );
+ @DeleteMapping("/reset")
+ @Operation(summary = "Reset basic auth state", description = "Reset users to default state")
+ @ApiResponse(responseCode = "200", description = "Success")
+ ResponseEntity reset();
+}
\ No newline at end of file
diff --git a/TEST-API/src/main/java/com/knubisoft/testapi/api/ApiTestCustomAuthApi.java b/TEST-API/src/main/java/com/knubisoft/testapi/api/ApiTestCustomAuthApi.java
new file mode 100644
index 0000000..7916d93
--- /dev/null
+++ b/TEST-API/src/main/java/com/knubisoft/testapi/api/ApiTestCustomAuthApi.java
@@ -0,0 +1,57 @@
+package com.knubisoft.testapi.api;
+
+import com.knubisoft.testapi.dto.auth.custom.CustomAuthLoginRequest;
+import com.knubisoft.testapi.dto.auth.custom.CustomAuthLoginResponse;
+import com.knubisoft.testapi.dto.auth.custom.CustomProtectedResponse;
+import com.knubisoft.testapi.exception.ErrorResponse;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.media.Content;
+import io.swagger.v3.oas.annotations.media.Schema;
+import io.swagger.v3.oas.annotations.responses.ApiResponse;
+import io.swagger.v3.oas.annotations.responses.ApiResponses;
+import org.springframework.http.MediaType;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestHeader;
+import org.springframework.web.bind.annotation.RequestMapping;
+
+@ApiResponses(value = {
+ @ApiResponse(responseCode = "400", description = "Bad Request", content = {
+ @Content(schema = @Schema(implementation = ErrorResponse.class))
+ }),
+ @ApiResponse(responseCode = "401", description = "Unauthorized", content = {
+ @Content(schema = @Schema(implementation = ErrorResponse.class))
+ }),
+ @ApiResponse(responseCode = "500", description = "Internal Server Error", content = {
+ @Content(schema = @Schema(implementation = ErrorResponse.class))
+ })
+})
+@RequestMapping("/api/test/auth/custom")
+public interface ApiTestCustomAuthApi {
+
+ @PostMapping("/login")
+ @Operation(summary = "Custom auth login", description = "Authenticate and return custom token")
+ @ApiResponse(responseCode = "200", description = "Success", content = {
+ @Content(mediaType = MediaType.APPLICATION_JSON_VALUE,
+ schema = @Schema(implementation = CustomAuthLoginResponse.class))
+ })
+ ResponseEntity login(@RequestBody CustomAuthLoginRequest request);
+
+ @GetMapping("/resource")
+ @Operation(summary = "Protected custom auth resource", description = "Access protected endpoint with custom token")
+ @ApiResponse(responseCode = "200", description = "Success", content = {
+ @Content(mediaType = MediaType.APPLICATION_JSON_VALUE,
+ schema = @Schema(implementation = CustomProtectedResponse.class))
+ })
+ ResponseEntity getProtectedResource(
+ @RequestHeader(value = "Authorization", required = false) String authorizationHeader
+ );
+
+ @DeleteMapping("/reset")
+ @Operation(summary = "Reset custom auth state", description = "Reset custom auth state after test")
+ @ApiResponse(responseCode = "200", description = "Success")
+ ResponseEntity reset();
+}
\ No newline at end of file
diff --git a/TEST-API/src/main/java/com/knubisoft/testapi/api/ApiTestEntityApi.java b/TEST-API/src/main/java/com/knubisoft/testapi/api/ApiTestEntityApi.java
new file mode 100644
index 0000000..22589e3
--- /dev/null
+++ b/TEST-API/src/main/java/com/knubisoft/testapi/api/ApiTestEntityApi.java
@@ -0,0 +1,147 @@
+package com.knubisoft.testapi.api;
+
+import com.knubisoft.testapi.dto.ApiTestEntityDto;
+import com.knubisoft.testapi.dto.ApiTestEntityPatchDto;
+import com.knubisoft.testapi.dto.HeaderValidationResponse;
+import com.knubisoft.testapi.exception.ErrorResponse;
+import com.knubisoft.testapi.model.http.ApiTestEntity;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.media.ArraySchema;
+import io.swagger.v3.oas.annotations.media.Content;
+import io.swagger.v3.oas.annotations.media.Schema;
+import io.swagger.v3.oas.annotations.responses.ApiResponse;
+import io.swagger.v3.oas.annotations.responses.ApiResponses;
+import org.springframework.http.MediaType;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.web.multipart.MultipartFile;
+
+import javax.validation.Valid;
+import java.io.IOException;
+import java.util.List;
+
+@ApiResponses(value = {
+ @ApiResponse(responseCode = "400", description = "Bad Request", content = {
+ @Content(schema = @Schema(implementation = ErrorResponse.class))
+ }),
+ @ApiResponse(responseCode = "404", description = "Not Found", content = {
+ @Content(schema = @Schema(implementation = ErrorResponse.class))
+ }),
+ @ApiResponse(responseCode = "500", description = "Internal Server Error", content = {
+ @Content(schema = @Schema(implementation = ErrorResponse.class))
+ })
+})
+@RequestMapping("/api/test/entities")
+public interface ApiTestEntityApi {
+
+ @PostMapping
+ @Operation(summary = "Create entity", description = "Create API test entity in memory")
+ @ApiResponse(responseCode = "201", description = "Created", content = {
+ @Content(
+ mediaType = MediaType.APPLICATION_JSON_VALUE,
+ schema = @Schema(implementation = ApiTestEntity.class)
+ )
+ })
+ ResponseEntity create(
+ @Parameter(description = "Entity request body", required = true)
+ @RequestBody @Valid ApiTestEntityDto dto
+ );
+
+ @GetMapping
+ @Operation(summary = "Get all entities", description = "Return all API test entities")
+ @ApiResponse(responseCode = "200", description = "Success", content = {
+ @Content(
+ mediaType = MediaType.APPLICATION_JSON_VALUE,
+ array = @ArraySchema(schema = @Schema(implementation = ApiTestEntity.class))
+ )
+ })
+ ResponseEntity> getAll();
+
+ @PutMapping
+ @Operation(summary = "Replace last entity", description = "Replace last created entity")
+ @ApiResponse(responseCode = "200", description = "Success", content = {
+ @Content(
+ mediaType = MediaType.APPLICATION_JSON_VALUE,
+ schema = @Schema(implementation = ApiTestEntity.class)
+ )
+ })
+ ResponseEntity updateLast(
+ @RequestBody @Valid ApiTestEntityDto dto
+ );
+
+ @PatchMapping
+ @Operation(summary = "Patch last entity", description = "Partially update last created entity")
+ @ApiResponse(responseCode = "200", description = "Success", content = {
+ @Content(
+ mediaType = MediaType.APPLICATION_JSON_VALUE,
+ schema = @Schema(implementation = ApiTestEntity.class)
+ )
+ })
+ ResponseEntity patchLast(
+ @RequestBody @Valid ApiTestEntityPatchDto dto
+ );
+
+ @DeleteMapping
+ @Operation(summary = "Delete all entities", description = "Delete all API test entities")
+ @ApiResponse(responseCode = "200", description = "Success")
+ ResponseEntity deleteAll();
+
+ @RequestMapping(method = RequestMethod.HEAD)
+ @Operation(summary = "HEAD last entity", description = "Return only headers for last entity")
+ @ApiResponse(responseCode = "200", description = "Success")
+ ResponseEntity head();
+
+ @RequestMapping(method = RequestMethod.OPTIONS)
+ @Operation(summary = "OPTIONS entities", description = "Return allowed methods")
+ @ApiResponse(responseCode = "200", description = "Success")
+ ResponseEntity options();
+
+ @PostMapping(value = "/trace", consumes = MediaType.TEXT_PLAIN_VALUE, produces = MediaType.TEXT_PLAIN_VALUE)
+ @Operation(summary = "TRACE-like request", description = "Echo raw request body")
+ @ApiResponse(responseCode = "200", description = "Success")
+ ResponseEntity traceLike(@RequestBody String body);
+
+ @PostMapping("/params")
+ @Operation(summary = "Create entity from params", description = "Create entity from request params")
+ @ApiResponse(responseCode = "201", description = "Created", content = {
+ @Content(
+ mediaType = MediaType.APPLICATION_JSON_VALUE,
+ schema = @Schema(implementation = ApiTestEntity.class)
+ )
+ })
+ ResponseEntity createFromParams(@RequestParam("value") String value);
+
+ @PostMapping(value = "/multipart", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
+ @Operation(summary = "Create entity with multipart", description = "Create entity using multipart form data")
+ @ApiResponse(responseCode = "200", description = "Updated", content = {
+ @Content(
+ mediaType = MediaType.APPLICATION_JSON_VALUE,
+ schema = @Schema(implementation = ApiTestEntity.class)
+ )
+ })
+ ResponseEntity createWithMultipart(
+ @RequestPart(value = "text", required = false) String text,
+ @RequestPart(value = "file", required = false) MultipartFile file
+ ) throws IOException;
+
+ @GetMapping("/health")
+ @Operation(summary = "Health check", description = "Simple health endpoint")
+ @ApiResponse(responseCode = "200", description = "Success")
+ ResponseEntity health();
+
+ @PostMapping(value = "/headers", produces = MediaType.APPLICATION_JSON_VALUE)
+ @Operation(summary = "Validate single request header", description = "Validate one request header and return one response header")
+ @ApiResponse(responseCode = "200", description = "Headers validated successfully", content = {
+ @Content(mediaType = MediaType.APPLICATION_JSON_VALUE,
+ schema = @Schema(implementation = HeaderValidationResponse.class))
+ })
+ ResponseEntity validateHeaders(
+ @RequestHeader(value = "X-Test-Header") String testHeader
+ );
+
+ @PostMapping("/reset")
+ @Operation(summary = "Reset entities", description = "Reset all in-memory entities")
+ @ApiResponse(responseCode = "200", description = "Success")
+ ResponseEntity reset();
+}
\ No newline at end of file
diff --git a/TEST-API/src/main/java/com/knubisoft/testapi/api/ApiTestJwtAuthApi.java b/TEST-API/src/main/java/com/knubisoft/testapi/api/ApiTestJwtAuthApi.java
new file mode 100644
index 0000000..50ee1c1
--- /dev/null
+++ b/TEST-API/src/main/java/com/knubisoft/testapi/api/ApiTestJwtAuthApi.java
@@ -0,0 +1,39 @@
+package com.knubisoft.testapi.api;
+
+import com.knubisoft.testapi.dto.auth.jwt.JwtLoginRequest;
+import com.knubisoft.testapi.dto.auth.jwt.JwtLoginResponse;
+import com.knubisoft.testapi.dto.auth.jwt.JwtProtectedCreateRequest;
+import com.knubisoft.testapi.dto.auth.jwt.JwtProtectedResourceResponse;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.responses.ApiResponse;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.*;
+
+@RequestMapping("/api/test/auth/jwt")
+public interface ApiTestJwtAuthApi {
+
+ @PostMapping("/login")
+ @Operation(summary = "Login and get JWT token")
+ @ApiResponse(responseCode = "200", description = "Success")
+ ResponseEntity login(@RequestBody JwtLoginRequest request);
+
+ @PostMapping("/resource")
+ @Operation(summary = "Create protected resource")
+ @ApiResponse(responseCode = "200", description = "Success")
+ ResponseEntity createProtected(
+ @RequestHeader(value = "Authorization", required = false) String authorizationHeader,
+ @RequestBody JwtProtectedCreateRequest request
+ );
+
+ @GetMapping("/resources")
+ @Operation(summary = "Get all protected resources")
+ @ApiResponse(responseCode = "200", description = "Success")
+ ResponseEntity getAllProtected(
+ @RequestHeader(value = "Authorization", required = false) String authorizationHeader
+ );
+
+ @DeleteMapping("/reset")
+ @Operation(summary = "Reset JWT auth state", description = "Reset JWT users, tokens and resources to default state")
+ @ApiResponse(responseCode = "200", description = "Success")
+ ResponseEntity reset();
+}
\ No newline at end of file
diff --git a/TEST-API/src/main/java/com/knubisoft/testapi/api/SelfGraphqlBookApi.java b/TEST-API/src/main/java/com/knubisoft/testapi/api/SelfGraphqlBookApi.java
new file mode 100644
index 0000000..63868b4
--- /dev/null
+++ b/TEST-API/src/main/java/com/knubisoft/testapi/api/SelfGraphqlBookApi.java
@@ -0,0 +1,20 @@
+package com.knubisoft.testapi.api;
+
+import com.knubisoft.testapi.model.graphql.SelfGraphqlBook;
+
+import java.util.List;
+
+public interface SelfGraphqlBookApi {
+
+ SelfGraphqlBook getSelfBookByTitle(String title);
+
+ List getAllSelfBooks();
+
+ SelfGraphqlBook addSelfBook(SelfGraphqlBook book);
+
+ SelfGraphqlBook updateSelfBookByTitle(String title, SelfGraphqlBook updatedBook);
+
+ boolean deleteSelfBookByTitle(String title);
+
+ boolean resetSelfBooks();
+}
\ No newline at end of file
diff --git a/TEST-API/src/main/java/com/knubisoft/testapi/api/WebSocketApi.java b/TEST-API/src/main/java/com/knubisoft/testapi/api/WebSocketApi.java
index f49605b..96a2bfb 100644
--- a/TEST-API/src/main/java/com/knubisoft/testapi/api/WebSocketApi.java
+++ b/TEST-API/src/main/java/com/knubisoft/testapi/api/WebSocketApi.java
@@ -9,17 +9,18 @@
import org.springframework.web.bind.annotation.RequestBody;
@ApiResponses(value = {
- @ApiResponse(responseCode = "404", description = "Not Found", content = {@Content(
- schema = @Schema(implementation = ErrorResponse.class))}),
- @ApiResponse(responseCode = "400", description = "Bad Request", content = {@Content(
- schema = @Schema(implementation = ErrorResponse.class))}),
- @ApiResponse(responseCode = "500", description = "Internal Server Error", content = {@Content(
- schema = @Schema(implementation = ErrorResponse.class))})
+ @ApiResponse(responseCode = "404", description = "Not Found", content = {
+ @Content(schema = @Schema(implementation = ErrorResponse.class))
+ }),
+ @ApiResponse(responseCode = "400", description = "Bad Request", content = {
+ @Content(schema = @Schema(implementation = ErrorResponse.class))
+ }),
+ @ApiResponse(responseCode = "500", description = "Internal Server Error", content = {
+ @Content(schema = @Schema(implementation = ErrorResponse.class))
+ })
})
public interface WebSocketApi {
- //todo swagger docs
-
@MessageMapping("/ping")
void somePing(@RequestBody final String arg);
@@ -28,4 +29,4 @@ public interface WebSocketApi {
@MessageMapping("/server")
void somePeriodicMessages();
-}
+}
\ No newline at end of file
diff --git a/TEST-API/src/main/java/com/knubisoft/testapi/api/impl/ApiTestBasicAuthController.java b/TEST-API/src/main/java/com/knubisoft/testapi/api/impl/ApiTestBasicAuthController.java
new file mode 100644
index 0000000..0d26d5a
--- /dev/null
+++ b/TEST-API/src/main/java/com/knubisoft/testapi/api/impl/ApiTestBasicAuthController.java
@@ -0,0 +1,112 @@
+package com.knubisoft.testapi.api.impl;
+
+import com.knubisoft.testapi.api.ApiTestBasicAuthApi;
+import com.knubisoft.testapi.dto.auth.basic.BasicAuthUser;
+import com.knubisoft.testapi.dto.auth.basic.BasicCreateUserRequest;
+import com.knubisoft.testapi.dto.auth.basic.BasicUserResponse;
+import com.knubisoft.testapi.exception.ApiTestAuthException;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.annotation.PostConstruct;
+import java.nio.charset.StandardCharsets;
+import java.util.ArrayList;
+import java.util.Base64;
+import java.util.List;
+import java.util.concurrent.CopyOnWriteArrayList;
+
+@RestController
+public class ApiTestBasicAuthController implements ApiTestBasicAuthApi {
+
+ private static final String BASIC_PREFIX = "Basic ";
+
+ private final List users = new CopyOnWriteArrayList<>();
+
+ @PostConstruct
+ public void init() {
+ users.clear();
+ users.add(new BasicAuthUser("testlum", "123456", "ADMIN"));
+ }
+
+ @Override
+ public ResponseEntity> getUsers(final String authorizationHeader) {
+ validateBasicAuth(authorizationHeader);
+
+ final List response = new ArrayList<>();
+ for (BasicAuthUser user : users) {
+ response.add(new BasicUserResponse(user.getUsername(), user.getRole()));
+ }
+
+ return ResponseEntity.ok()
+ .header("X-Auth-Type", "BASIC")
+ .header("X-Users-Count", String.valueOf(response.size()))
+ .body(response);
+ }
+
+ @Override
+ public ResponseEntity createUser(final String authorizationHeader,
+ final BasicCreateUserRequest request) {
+ validateBasicAuth(authorizationHeader);
+
+ final BasicAuthUser user = new BasicAuthUser(
+ request.getUsername(),
+ request.getPassword(),
+ request.getRole()
+ );
+
+ users.add(user);
+
+ return ResponseEntity.ok()
+ .header("X-Auth-Type", "BASIC")
+ .header("X-Created-User", request.getUsername())
+ .body(new BasicUserResponse(user.getUsername(), user.getRole()));
+ }
+
+ @Override
+ public ResponseEntity reset() {
+ users.clear();
+ users.add(new BasicAuthUser("testlum", "123456", "ADMIN"));
+
+ return ResponseEntity.ok()
+ .header("X-Auth-Type", "BASIC")
+ .build();
+ }
+
+ private void validateBasicAuth(final String authorizationHeader) {
+ if (StringUtils.isBlank(authorizationHeader)) {
+ throw new ApiTestAuthException("Missing Authorization header");
+ }
+
+ if (!authorizationHeader.startsWith(BASIC_PREFIX)) {
+ throw new ApiTestAuthException("Authorization header must start with Basic");
+ }
+
+ final String encodedCredentials = authorizationHeader.substring(BASIC_PREFIX.length());
+
+ final String decodedCredentials;
+ try {
+ decodedCredentials = new String(
+ Base64.getDecoder().decode(encodedCredentials),
+ StandardCharsets.UTF_8
+ );
+ } catch (IllegalArgumentException ex) {
+ throw new ApiTestAuthException("Invalid Base64 credentials");
+ }
+
+ final String[] parts = decodedCredentials.split(":", 2);
+ if (parts.length != 2) {
+ throw new ApiTestAuthException("Invalid Basic auth credentials format");
+ }
+
+ final String username = parts[0];
+ final String password = parts[1];
+
+ final boolean valid = users.stream()
+ .anyMatch(user -> user.getUsername().equals(username) && user.getPassword().equals(password));
+
+ if (!valid) {
+ throw new ApiTestAuthException("Invalid username or password");
+ }
+ }
+}
\ No newline at end of file
diff --git a/TEST-API/src/main/java/com/knubisoft/testapi/api/impl/ApiTestCustomAuthController.java b/TEST-API/src/main/java/com/knubisoft/testapi/api/impl/ApiTestCustomAuthController.java
new file mode 100644
index 0000000..d418bf6
--- /dev/null
+++ b/TEST-API/src/main/java/com/knubisoft/testapi/api/impl/ApiTestCustomAuthController.java
@@ -0,0 +1,66 @@
+package com.knubisoft.testapi.api.impl;
+
+import com.knubisoft.testapi.api.ApiTestCustomAuthApi;
+import com.knubisoft.testapi.dto.auth.custom.CustomAuthLoginRequest;
+import com.knubisoft.testapi.dto.auth.custom.CustomAuthLoginResponse;
+import com.knubisoft.testapi.dto.auth.custom.CustomProtectedResponse;
+import com.knubisoft.testapi.exception.ApiTestAuthException;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.RestController;
+
+@RestController
+public class ApiTestCustomAuthController implements ApiTestCustomAuthApi {
+
+ private static final String EXPECTED_CLIENT_ID = "testlum-client";
+ private static final String EXPECTED_CLIENT_SECRET = "super-secret";
+ private static final String TOKEN = "custom-auth-token-123";
+ private static final String CUSTOM_PREFIX = "Custom ";
+
+ @Override
+ public ResponseEntity login(final CustomAuthLoginRequest request) {
+ if (!EXPECTED_CLIENT_ID.equals(request.getClientId())
+ || !EXPECTED_CLIENT_SECRET.equals(request.getClientSecret())) {
+ throw new ApiTestAuthException("Invalid custom auth credentials");
+ }
+
+ return ResponseEntity.ok()
+ .header("X-Auth-Type", "CUSTOM")
+ .body(new CustomAuthLoginResponse(TOKEN));
+ }
+
+ @Override
+ public ResponseEntity getProtectedResource(final String authorizationHeader) {
+ validateCustomAuth(authorizationHeader);
+
+ return ResponseEntity.ok()
+ .header("X-Auth-Type", "CUSTOM")
+ .body(new CustomProtectedResponse(
+ "Custom auth access granted",
+ "CUSTOM"
+ ));
+ }
+
+ @Override
+ public ResponseEntity reset() {
+ return ResponseEntity.ok()
+ .header("X-Auth-Type", "CUSTOM")
+ .build();
+ }
+
+ private void validateCustomAuth(final String authorizationHeader) {
+ if (StringUtils.isBlank(authorizationHeader)) {
+ throw new ApiTestAuthException("Missing Authorization header");
+ }
+
+ if (!authorizationHeader.startsWith(CUSTOM_PREFIX)) {
+ throw new ApiTestAuthException("Authorization header must start with Custom");
+ }
+
+ final String token = authorizationHeader.substring(CUSTOM_PREFIX.length());
+
+ if (!TOKEN.equals(token)) {
+ throw new ApiTestAuthException("Invalid custom auth token");
+ }
+ }
+}
\ No newline at end of file
diff --git a/TEST-API/src/main/java/com/knubisoft/testapi/api/impl/ApiTestEntityController.java b/TEST-API/src/main/java/com/knubisoft/testapi/api/impl/ApiTestEntityController.java
new file mode 100644
index 0000000..69078f7
--- /dev/null
+++ b/TEST-API/src/main/java/com/knubisoft/testapi/api/impl/ApiTestEntityController.java
@@ -0,0 +1,181 @@
+package com.knubisoft.testapi.api.impl;
+
+import com.knubisoft.testapi.api.ApiTestEntityApi;
+import com.knubisoft.testapi.dto.ApiTestEntityDto;
+import com.knubisoft.testapi.dto.ApiTestEntityPatchDto;
+import com.knubisoft.testapi.dto.HeaderValidationResponse;
+import com.knubisoft.testapi.exception.ApiTestEntityException;
+import com.knubisoft.testapi.model.http.ApiTestEntity;
+import com.knubisoft.testapi.model.http.UploadedFileInfo;
+import org.springframework.http.HttpMethod;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.multipart.MultipartFile;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.CopyOnWriteArrayList;
+
+@RestController
+public class ApiTestEntityController implements ApiTestEntityApi {
+
+ private final List storage = new CopyOnWriteArrayList<>();
+
+ @Override
+ public ResponseEntity create(final ApiTestEntityDto dto) {
+ final ApiTestEntity entity = new ApiTestEntity();
+ entity.setName(dto.getName());
+ entity.setDescription(dto.getDescription());
+ entity.setStatus(dto.getStatus());
+ entity.setCategory(dto.getCategory());
+
+ storage.add(entity);
+ return ResponseEntity.status(HttpStatus.CREATED).body(entity);
+ }
+
+ @Override
+ public ResponseEntity> getAll() {
+ return ResponseEntity.ok(new ArrayList<>(storage));
+ }
+
+ @Override
+ public ResponseEntity updateLast(final ApiTestEntityDto dto) {
+ final ApiTestEntity entity = getLastEntity();
+
+ entity.setName(dto.getName());
+ entity.setDescription(dto.getDescription());
+ entity.setStatus(dto.getStatus());
+ entity.setCategory(dto.getCategory());
+
+ return ResponseEntity.ok(entity);
+ }
+
+ @Override
+ public ResponseEntity patchLast(final ApiTestEntityPatchDto dto) {
+ final ApiTestEntity entity = getLastEntity();
+
+ if (dto.getName() != null) {
+ entity.setName(dto.getName());
+ }
+ if (dto.getDescription() != null) {
+ entity.setDescription(dto.getDescription());
+ }
+ if (dto.getStatus() != null) {
+ entity.setStatus(dto.getStatus());
+ }
+ if (dto.getCategory() != null) {
+ entity.setCategory(dto.getCategory());
+ }
+
+ return ResponseEntity.ok(entity);
+ }
+
+ @Override
+ public ResponseEntity deleteAll() {
+ storage.clear();
+ return ResponseEntity.ok().build();
+ }
+
+ @Override
+ public ResponseEntity head() {
+ final ApiTestEntity entity = getLastEntity();
+
+ return ResponseEntity.ok()
+ .header("X-Entity-Name", safe(entity.getName()))
+ .header("X-Entity-Status", safe(entity.getStatus()))
+ .header("X-Entity-Category", safe(entity.getCategory()))
+ .build();
+ }
+
+ @Override
+ public ResponseEntity options() {
+ return ResponseEntity.ok()
+ .allow(
+ HttpMethod.GET,
+ HttpMethod.POST,
+ HttpMethod.PUT,
+ HttpMethod.PATCH,
+ HttpMethod.DELETE,
+ HttpMethod.HEAD,
+ HttpMethod.OPTIONS
+ )
+ .build();
+ }
+
+ @Override
+ public ResponseEntity traceLike(final String body) {
+ final String response = "TRACE /api/test/entities/trace\n"
+ + "Content-Type: text/plain\n"
+ + "Body: " + body;
+
+ return ResponseEntity.ok(response);
+ }
+
+ @Override
+ public ResponseEntity createFromParams(final String value) {
+ final ApiTestEntity entity = new ApiTestEntity();
+ entity.setName(value);
+ entity.setDescription("Created from params");
+ entity.setStatus("PARAM");
+ entity.setCategory("REQUEST_PARAM");
+
+ storage.add(entity);
+ return ResponseEntity.status(HttpStatus.CREATED).body(entity);
+ }
+
+ @Override
+ public ResponseEntity createWithMultipart(final String text,
+ final MultipartFile file) throws IOException {
+ final ApiTestEntity entity = new ApiTestEntity();
+ entity.setName(text != null ? text : "Multipart Entity");
+ entity.setDescription("Created with multipart body");
+ entity.setStatus("MULTIPART");
+ entity.setCategory("FORM");
+
+ if (file != null) {
+ entity.setUploadedFile(new UploadedFileInfo(
+ file.getOriginalFilename(),
+ file.getSize(),
+ file.getContentType()
+ ));
+ }
+
+ storage.add(entity);
+ return ResponseEntity.ok(entity);
+ }
+
+ @Override
+ public ResponseEntity health() {
+ return ResponseEntity.ok("OK");
+ }
+
+ @Override
+ public ResponseEntity validateHeaders(final String testHeader) {
+ if (testHeader == null || testHeader.trim().isEmpty()) {
+ throw new ApiTestEntityException("Missing required header: X-Test-Header");
+ }
+
+ return ResponseEntity.ok()
+ .header("X-Validated-Header", testHeader)
+ .body(new HeaderValidationResponse("Header validated successfully"));
+ }
+
+ @Override
+ public ResponseEntity reset() {
+ storage.clear();
+ return ResponseEntity.ok().build();
+ }
+
+ private ApiTestEntity getLastEntity() {
+ if (storage.isEmpty()) {
+ throw new ApiTestEntityException("No entities found");
+ }
+ return storage.get(storage.size() - 1);
+ }
+
+ private String safe(final String value) {
+ return value == null ? "" : value;
+ }
+}
\ No newline at end of file
diff --git a/TEST-API/src/main/java/com/knubisoft/testapi/api/impl/ApiTestJwtAuthController.java b/TEST-API/src/main/java/com/knubisoft/testapi/api/impl/ApiTestJwtAuthController.java
new file mode 100644
index 0000000..7c8fe0b
--- /dev/null
+++ b/TEST-API/src/main/java/com/knubisoft/testapi/api/impl/ApiTestJwtAuthController.java
@@ -0,0 +1,102 @@
+package com.knubisoft.testapi.api.impl;
+
+import com.knubisoft.testapi.api.ApiTestJwtAuthApi;
+import com.knubisoft.testapi.dto.auth.jwt.JwtLoginRequest;
+import com.knubisoft.testapi.dto.auth.jwt.JwtLoginResponse;
+import com.knubisoft.testapi.dto.auth.jwt.JwtProtectedCreateRequest;
+import com.knubisoft.testapi.dto.auth.jwt.JwtProtectedResourceResponse;
+import com.knubisoft.testapi.exception.ApiTestAuthException;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.annotation.PostConstruct;
+import java.util.ArrayList;
+import java.util.Map;
+import java.util.UUID;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.CopyOnWriteArrayList;
+
+@RestController
+public class ApiTestJwtAuthController implements ApiTestJwtAuthApi {
+
+ private static final String BEARER_PREFIX = "Bearer ";
+
+ private final Map users = new ConcurrentHashMap<>();
+ private final Map tokens = new ConcurrentHashMap<>();
+ private final Map> storageByToken = new ConcurrentHashMap<>();
+
+ @PostConstruct
+ public void init() {
+ users.put("testlum", "123456");
+ }
+
+ @Override
+ public ResponseEntity login(final JwtLoginRequest request) {
+ final String expectedPassword = users.get(request.getUsername());
+
+ if (expectedPassword == null || !expectedPassword.equals(request.getPassword())) {
+ throw new ApiTestAuthException("Invalid username or password");
+ }
+
+ final String token = "jwt-token-" + UUID.randomUUID();
+ tokens.put(token, request.getUsername());
+ storageByToken.put(token, new CopyOnWriteArrayList<>());
+
+ return ResponseEntity.ok()
+ .header("X-Auth-Type", "JWT")
+ .body(new JwtLoginResponse(token));
+ }
+
+ @Override
+ public ResponseEntity createProtected(
+ final String authorizationHeader,
+ final JwtProtectedCreateRequest request) {
+
+ final String token = validateJwt(authorizationHeader);
+
+ storageByToken
+ .computeIfAbsent(token, key -> new CopyOnWriteArrayList<>())
+ .add(request.getValue());
+
+ return ResponseEntity.ok()
+ .header("X-Auth-Type", "JWT")
+ .body(new JwtProtectedResourceResponse(new ArrayList<>(storageByToken.get(token))));
+ }
+
+ @Override
+ public ResponseEntity getAllProtected(final String authorizationHeader) {
+ final String token = validateJwt(authorizationHeader);
+
+ return ResponseEntity.ok()
+ .header("X-Auth-Type", "JWT")
+ .body(new JwtProtectedResourceResponse(
+ new ArrayList<>(storageByToken.getOrDefault(token, new CopyOnWriteArrayList<>()))
+ ));
+ }
+
+ @Override
+ public ResponseEntity reset() {
+ return ResponseEntity.ok()
+ .header("X-Auth-Type", "JWT")
+ .build();
+ }
+
+ private String validateJwt(final String authorizationHeader) {
+ if (StringUtils.isBlank(authorizationHeader)) {
+ throw new ApiTestAuthException("Missing Authorization header");
+ }
+
+ if (!authorizationHeader.startsWith(BEARER_PREFIX)) {
+ throw new ApiTestAuthException("Authorization header must start with Bearer");
+ }
+
+ final String token = authorizationHeader.substring(BEARER_PREFIX.length());
+
+ if (!tokens.containsKey(token)) {
+ throw new ApiTestAuthException("Invalid or expired token");
+ }
+
+ return token;
+ }
+}
\ No newline at end of file
diff --git a/TEST-API/src/main/java/com/knubisoft/testapi/api/impl/SelfGraphqlBookController.java b/TEST-API/src/main/java/com/knubisoft/testapi/api/impl/SelfGraphqlBookController.java
new file mode 100644
index 0000000..1fac74a
--- /dev/null
+++ b/TEST-API/src/main/java/com/knubisoft/testapi/api/impl/SelfGraphqlBookController.java
@@ -0,0 +1,78 @@
+package com.knubisoft.testapi.api.impl;
+
+import com.knubisoft.testapi.api.SelfGraphqlBookApi;
+import com.knubisoft.testapi.model.graphql.SelfGraphqlBook;
+import io.leangen.graphql.annotations.GraphQLArgument;
+import io.leangen.graphql.annotations.GraphQLMutation;
+import io.leangen.graphql.annotations.GraphQLQuery;
+import io.leangen.graphql.spqr.spring.annotations.GraphQLApi;
+import org.springframework.stereotype.Service;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.CopyOnWriteArrayList;
+
+@Service
+@GraphQLApi
+public class SelfGraphqlBookController implements SelfGraphqlBookApi {
+
+ private final List storage = new CopyOnWriteArrayList<>();
+
+ @Override
+ @GraphQLQuery(name = "getSelfBookByTitle")
+ public SelfGraphqlBook getSelfBookByTitle(@GraphQLArgument(name = "title") final String title) {
+ for (final SelfGraphqlBook book : storage) {
+ if (book.getTitle().equals(title)) {
+ return book;
+ }
+ }
+ return null;
+ }
+
+ @Override
+ @GraphQLQuery(name = "getAllSelfBooks")
+ public List getAllSelfBooks() {
+ return new ArrayList<>(storage);
+ }
+
+ @Override
+ @GraphQLMutation(name = "addSelfBook")
+ public SelfGraphqlBook addSelfBook(@GraphQLArgument(name = "newBook") final SelfGraphqlBook book) {
+ storage.add(book);
+ return book;
+ }
+
+ @Override
+ @GraphQLMutation(name = "updateSelfBookByTitle")
+ public SelfGraphqlBook updateSelfBookByTitle(@GraphQLArgument(name = "title") final String title,
+ @GraphQLArgument(name = "updatedBook") final SelfGraphqlBook updatedBook) {
+ for (final SelfGraphqlBook book : storage) {
+ if (book.getTitle().equals(title)) {
+ book.setTitle(updatedBook.getTitle());
+ book.setAuthor(updatedBook.getAuthor());
+ book.setNumber(updatedBook.getNumber());
+ return book;
+ }
+ }
+ return null;
+ }
+
+ @Override
+ @GraphQLMutation(name = "deleteSelfBookByTitle")
+ public boolean deleteSelfBookByTitle(@GraphQLArgument(name = "title") final String title) {
+ for (final SelfGraphqlBook book : storage) {
+ if (book.getTitle().equals(title)) {
+ storage.remove(book);
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ @GraphQLMutation(name = "resetSelfBooks")
+ public boolean resetSelfBooks() {
+ storage.clear();
+ return true;
+ }
+}
\ No newline at end of file
diff --git a/TEST-API/src/main/java/com/knubisoft/testapi/api/impl/WebSocketController.java b/TEST-API/src/main/java/com/knubisoft/testapi/api/impl/WebSocketController.java
index 46cf8d6..b1a8dac 100644
--- a/TEST-API/src/main/java/com/knubisoft/testapi/api/impl/WebSocketController.java
+++ b/TEST-API/src/main/java/com/knubisoft/testapi/api/impl/WebSocketController.java
@@ -7,23 +7,25 @@
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
import org.springframework.messaging.simp.SimpMessagingTemplate;
import org.springframework.scheduling.annotation.Scheduled;
-import org.springframework.web.bind.annotation.RestController;
+import org.springframework.stereotype.Controller;
import java.util.concurrent.TimeUnit;
-@RestController
+@Controller
@ConditionalOnExpression("${spring.websocket.enabled:true}")
public class WebSocketController implements WebSocketApi {
@Autowired
private SimpMessagingTemplate messagingTemplate;
+ @Override
@SneakyThrows
public void somePing(final String arg) {
messagingTemplate.convertAndSend("/topic/ping", new Ping(arg));
TimeUnit.MILLISECONDS.sleep(500);
}
+ @Override
@SneakyThrows
public void someTest(final String arg) {
messagingTemplate.convertAndSend("/topic/test", "some test message");
@@ -31,6 +33,7 @@ public void someTest(final String arg) {
messagingTemplate.convertAndSend("/topic/test", arg);
}
+ @Override
@Scheduled(fixedDelay = 1000)
public void somePeriodicMessages() {
messagingTemplate.convertAndSend("/topic/server", "server periodic message");
@@ -40,4 +43,4 @@ public void somePeriodicMessages() {
private static class Ping {
private final String value;
}
-}
+}
\ No newline at end of file
diff --git a/TEST-API/src/main/java/com/knubisoft/testapi/config/StandardWebSocketConfig.java b/TEST-API/src/main/java/com/knubisoft/testapi/config/StandardWebSocketConfig.java
new file mode 100644
index 0000000..c849f84
--- /dev/null
+++ b/TEST-API/src/main/java/com/knubisoft/testapi/config/StandardWebSocketConfig.java
@@ -0,0 +1,19 @@
+package com.knubisoft.testapi.config;
+
+import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.socket.config.annotation.EnableWebSocket;
+import org.springframework.web.socket.config.annotation.WebSocketConfigurer;
+import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry;
+
+@Configuration
+@EnableWebSocket
+@ConditionalOnExpression("${spring.websocket.enabled:true}")
+public class StandardWebSocketConfig implements WebSocketConfigurer {
+
+ @Override
+ public void registerWebSocketHandlers(final WebSocketHandlerRegistry registry) {
+ registry.addHandler(new StandardWebSocketHandler(), "/ws-standard")
+ .setAllowedOrigins("*");
+ }
+}
\ No newline at end of file
diff --git a/TEST-API/src/main/java/com/knubisoft/testapi/config/StandardWebSocketHandler.java b/TEST-API/src/main/java/com/knubisoft/testapi/config/StandardWebSocketHandler.java
new file mode 100644
index 0000000..d099fa5
--- /dev/null
+++ b/TEST-API/src/main/java/com/knubisoft/testapi/config/StandardWebSocketHandler.java
@@ -0,0 +1,30 @@
+package com.knubisoft.testapi.config;
+
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.web.socket.CloseStatus;
+import org.springframework.web.socket.TextMessage;
+import org.springframework.web.socket.WebSocketSession;
+import org.springframework.web.socket.handler.TextWebSocketHandler;
+
+@Slf4j
+public class StandardWebSocketHandler extends TextWebSocketHandler {
+
+ @Override
+ public void afterConnectionEstablished(final WebSocketSession session) {
+ log.info("Standard websocket connected: {}", session.getId());
+ }
+
+ @Override
+ protected void handleTextMessage(final WebSocketSession session,
+ final TextMessage message) throws Exception {
+ final String payload = message.getPayload();
+ log.info("Standard websocket received: {}", payload);
+ session.sendMessage(new TextMessage(payload));
+ }
+
+ @Override
+ public void afterConnectionClosed(final WebSocketSession session,
+ final CloseStatus status) {
+ log.info("Standard websocket closed: {}", session.getId());
+ }
+}
\ No newline at end of file
diff --git a/TEST-API/src/main/java/com/knubisoft/testapi/dto/ApiTestEntityDto.java b/TEST-API/src/main/java/com/knubisoft/testapi/dto/ApiTestEntityDto.java
new file mode 100644
index 0000000..d687344
--- /dev/null
+++ b/TEST-API/src/main/java/com/knubisoft/testapi/dto/ApiTestEntityDto.java
@@ -0,0 +1,40 @@
+package com.knubisoft.testapi.dto;
+
+import lombok.Getter;
+import lombok.Setter;
+
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.Pattern;
+import javax.validation.constraints.Size;
+
+@Getter
+@Setter
+public class ApiTestEntityDto {
+
+ @NotBlank(message = "Name must not be blank")
+ @Size(min = 3, max = 50, message = "Name must be between 3 and 50 characters")
+ @Pattern(
+ regexp = "^[a-zA-Z0-9 _-]+$",
+ message = "Name can contain only letters, numbers, spaces, underscores and hyphens"
+ )
+ private String name;
+
+ @NotBlank(message = "Description must not be blank")
+ @Size(min = 5, max = 255, message = "Description must be between 5 and 255 characters")
+ private String description;
+
+ @NotBlank(message = "Status must not be blank")
+ @Pattern(
+ regexp = "^(NEW|ACTIVE|INACTIVE|ARCHIVED)$",
+ message = "Status must be one of: NEW, ACTIVE, INACTIVE, ARCHIVED"
+ )
+ private String status;
+
+ @NotBlank(message = "Category must not be blank")
+ @Pattern(
+ regexp = "^[A-Z_]+$",
+ message = "Category must contain only uppercase letters and underscores"
+ )
+ @Size(min = 3, max = 30, message = "Category must be between 3 and 30 characters")
+ private String category;
+}
\ No newline at end of file
diff --git a/TEST-API/src/main/java/com/knubisoft/testapi/dto/ApiTestEntityPatchDto.java b/TEST-API/src/main/java/com/knubisoft/testapi/dto/ApiTestEntityPatchDto.java
new file mode 100644
index 0000000..fa9aefe
--- /dev/null
+++ b/TEST-API/src/main/java/com/knubisoft/testapi/dto/ApiTestEntityPatchDto.java
@@ -0,0 +1,35 @@
+package com.knubisoft.testapi.dto;
+
+import lombok.Getter;
+import lombok.Setter;
+
+import javax.validation.constraints.Pattern;
+import javax.validation.constraints.Size;
+
+@Getter
+@Setter
+public class ApiTestEntityPatchDto {
+
+ @Size(min = 3, max = 50, message = "Name must be between 3 and 50 characters")
+ @Pattern(
+ regexp = "^[a-zA-Z0-9 _-]+$",
+ message = "Name can contain only letters, numbers, spaces, underscores and hyphens"
+ )
+ private String name;
+
+ @Size(min = 5, max = 255, message = "Description must be between 5 and 255 characters")
+ private String description;
+
+ @Pattern(
+ regexp = "^(NEW|ACTIVE|INACTIVE|ARCHIVED)$",
+ message = "Status must be one of: NEW, ACTIVE, INACTIVE, ARCHIVED"
+ )
+ private String status;
+
+ @Pattern(
+ regexp = "^[A-Z_]+$",
+ message = "Category must contain only uppercase letters and underscores"
+ )
+ @Size(min = 3, max = 30, message = "Category must be between 3 and 30 characters")
+ private String category;
+}
\ No newline at end of file
diff --git a/TEST-API/src/main/java/com/knubisoft/testapi/dto/HeaderValidationResponse.java b/TEST-API/src/main/java/com/knubisoft/testapi/dto/HeaderValidationResponse.java
new file mode 100644
index 0000000..53d8ce2
--- /dev/null
+++ b/TEST-API/src/main/java/com/knubisoft/testapi/dto/HeaderValidationResponse.java
@@ -0,0 +1,14 @@
+package com.knubisoft.testapi.dto;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+
+@Getter
+@Setter
+@NoArgsConstructor
+@AllArgsConstructor
+public class HeaderValidationResponse {
+ private String message;
+}
\ No newline at end of file
diff --git a/TEST-API/src/main/java/com/knubisoft/testapi/dto/auth/basic/AuthSuccessResponse.java b/TEST-API/src/main/java/com/knubisoft/testapi/dto/auth/basic/AuthSuccessResponse.java
new file mode 100644
index 0000000..611bfc8
--- /dev/null
+++ b/TEST-API/src/main/java/com/knubisoft/testapi/dto/auth/basic/AuthSuccessResponse.java
@@ -0,0 +1,16 @@
+package com.knubisoft.testapi.dto.auth.basic;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+
+@Getter
+@Setter
+@NoArgsConstructor
+@AllArgsConstructor
+public class AuthSuccessResponse {
+ private String message;
+ private String authType;
+ private String username;
+}
\ No newline at end of file
diff --git a/TEST-API/src/main/java/com/knubisoft/testapi/dto/auth/basic/BasicAuthUser.java b/TEST-API/src/main/java/com/knubisoft/testapi/dto/auth/basic/BasicAuthUser.java
new file mode 100644
index 0000000..7b1b637
--- /dev/null
+++ b/TEST-API/src/main/java/com/knubisoft/testapi/dto/auth/basic/BasicAuthUser.java
@@ -0,0 +1,16 @@
+package com.knubisoft.testapi.dto.auth.basic;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+
+@Getter
+@Setter
+@NoArgsConstructor
+@AllArgsConstructor
+public class BasicAuthUser {
+ private String username;
+ private String password;
+ private String role;
+}
\ No newline at end of file
diff --git a/TEST-API/src/main/java/com/knubisoft/testapi/dto/auth/basic/BasicCreateUserRequest.java b/TEST-API/src/main/java/com/knubisoft/testapi/dto/auth/basic/BasicCreateUserRequest.java
new file mode 100644
index 0000000..208663e
--- /dev/null
+++ b/TEST-API/src/main/java/com/knubisoft/testapi/dto/auth/basic/BasicCreateUserRequest.java
@@ -0,0 +1,24 @@
+package com.knubisoft.testapi.dto.auth.basic;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+
+import javax.validation.constraints.NotBlank;
+
+@Getter
+@Setter
+@NoArgsConstructor
+@AllArgsConstructor
+public class BasicCreateUserRequest {
+
+ @NotBlank
+ private String username;
+
+ @NotBlank
+ private String password;
+
+ @NotBlank
+ private String role;
+}
\ No newline at end of file
diff --git a/TEST-API/src/main/java/com/knubisoft/testapi/dto/auth/basic/BasicLoginRequest.java b/TEST-API/src/main/java/com/knubisoft/testapi/dto/auth/basic/BasicLoginRequest.java
new file mode 100644
index 0000000..ba0067d
--- /dev/null
+++ b/TEST-API/src/main/java/com/knubisoft/testapi/dto/auth/basic/BasicLoginRequest.java
@@ -0,0 +1,21 @@
+package com.knubisoft.testapi.dto.auth.basic;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+
+import javax.validation.constraints.NotBlank;
+
+@Getter
+@Setter
+@NoArgsConstructor
+@AllArgsConstructor
+public class BasicLoginRequest {
+
+ @NotBlank
+ private String username;
+
+ @NotBlank
+ private String password;
+}
\ No newline at end of file
diff --git a/TEST-API/src/main/java/com/knubisoft/testapi/dto/auth/basic/BasicLoginResponse.java b/TEST-API/src/main/java/com/knubisoft/testapi/dto/auth/basic/BasicLoginResponse.java
new file mode 100644
index 0000000..3041755
--- /dev/null
+++ b/TEST-API/src/main/java/com/knubisoft/testapi/dto/auth/basic/BasicLoginResponse.java
@@ -0,0 +1,18 @@
+package com.knubisoft.testapi.dto.auth.basic;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+
+@Getter
+@Setter
+@NoArgsConstructor
+@AllArgsConstructor
+public class BasicLoginResponse {
+ private String message;
+ private String authType;
+ private String username;
+ private String role;
+ private String authorization;
+}
\ No newline at end of file
diff --git a/TEST-API/src/main/java/com/knubisoft/testapi/dto/auth/basic/BasicUserResponse.java b/TEST-API/src/main/java/com/knubisoft/testapi/dto/auth/basic/BasicUserResponse.java
new file mode 100644
index 0000000..2f421ca
--- /dev/null
+++ b/TEST-API/src/main/java/com/knubisoft/testapi/dto/auth/basic/BasicUserResponse.java
@@ -0,0 +1,15 @@
+package com.knubisoft.testapi.dto.auth.basic;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+
+@Getter
+@Setter
+@NoArgsConstructor
+@AllArgsConstructor
+public class BasicUserResponse {
+ private String username;
+ private String role;
+}
\ No newline at end of file
diff --git a/TEST-API/src/main/java/com/knubisoft/testapi/dto/auth/custom/CustomAuthLoginRequest.java b/TEST-API/src/main/java/com/knubisoft/testapi/dto/auth/custom/CustomAuthLoginRequest.java
new file mode 100644
index 0000000..cc941d8
--- /dev/null
+++ b/TEST-API/src/main/java/com/knubisoft/testapi/dto/auth/custom/CustomAuthLoginRequest.java
@@ -0,0 +1,11 @@
+package com.knubisoft.testapi.dto.auth.custom;
+
+import lombok.Getter;
+import lombok.Setter;
+
+@Getter
+@Setter
+public class CustomAuthLoginRequest {
+ private String clientId;
+ private String clientSecret;
+}
\ No newline at end of file
diff --git a/TEST-API/src/main/java/com/knubisoft/testapi/dto/auth/custom/CustomAuthLoginResponse.java b/TEST-API/src/main/java/com/knubisoft/testapi/dto/auth/custom/CustomAuthLoginResponse.java
new file mode 100644
index 0000000..270000d
--- /dev/null
+++ b/TEST-API/src/main/java/com/knubisoft/testapi/dto/auth/custom/CustomAuthLoginResponse.java
@@ -0,0 +1,10 @@
+package com.knubisoft.testapi.dto.auth.custom;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+@Getter
+@AllArgsConstructor
+public class CustomAuthLoginResponse {
+ private String token;
+}
\ No newline at end of file
diff --git a/TEST-API/src/main/java/com/knubisoft/testapi/dto/auth/custom/CustomProtectedResponse.java b/TEST-API/src/main/java/com/knubisoft/testapi/dto/auth/custom/CustomProtectedResponse.java
new file mode 100644
index 0000000..6a4ecf9
--- /dev/null
+++ b/TEST-API/src/main/java/com/knubisoft/testapi/dto/auth/custom/CustomProtectedResponse.java
@@ -0,0 +1,11 @@
+package com.knubisoft.testapi.dto.auth.custom;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+@Getter
+@AllArgsConstructor
+public class CustomProtectedResponse {
+ private String message;
+ private String authType;
+}
\ No newline at end of file
diff --git a/TEST-API/src/main/java/com/knubisoft/testapi/dto/auth/jwt/JwtLoginRequest.java b/TEST-API/src/main/java/com/knubisoft/testapi/dto/auth/jwt/JwtLoginRequest.java
new file mode 100644
index 0000000..54ac1f0
--- /dev/null
+++ b/TEST-API/src/main/java/com/knubisoft/testapi/dto/auth/jwt/JwtLoginRequest.java
@@ -0,0 +1,11 @@
+package com.knubisoft.testapi.dto.auth.jwt;
+
+import lombok.Getter;
+import lombok.Setter;
+
+@Getter
+@Setter
+public class JwtLoginRequest {
+ private String username;
+ private String password;
+}
\ No newline at end of file
diff --git a/TEST-API/src/main/java/com/knubisoft/testapi/dto/auth/jwt/JwtLoginResponse.java b/TEST-API/src/main/java/com/knubisoft/testapi/dto/auth/jwt/JwtLoginResponse.java
new file mode 100644
index 0000000..b672631
--- /dev/null
+++ b/TEST-API/src/main/java/com/knubisoft/testapi/dto/auth/jwt/JwtLoginResponse.java
@@ -0,0 +1,10 @@
+package com.knubisoft.testapi.dto.auth.jwt;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+@Getter
+@AllArgsConstructor
+public class JwtLoginResponse {
+ private String token;
+}
\ No newline at end of file
diff --git a/TEST-API/src/main/java/com/knubisoft/testapi/dto/auth/jwt/JwtProtectedCreateRequest.java b/TEST-API/src/main/java/com/knubisoft/testapi/dto/auth/jwt/JwtProtectedCreateRequest.java
new file mode 100644
index 0000000..dac82e8
--- /dev/null
+++ b/TEST-API/src/main/java/com/knubisoft/testapi/dto/auth/jwt/JwtProtectedCreateRequest.java
@@ -0,0 +1,8 @@
+package com.knubisoft.testapi.dto.auth.jwt;
+
+import lombok.Data;
+
+@Data
+public class JwtProtectedCreateRequest {
+ private String value;
+}
\ No newline at end of file
diff --git a/TEST-API/src/main/java/com/knubisoft/testapi/dto/auth/jwt/JwtProtectedResourceResponse.java b/TEST-API/src/main/java/com/knubisoft/testapi/dto/auth/jwt/JwtProtectedResourceResponse.java
new file mode 100644
index 0000000..7cb2b0b
--- /dev/null
+++ b/TEST-API/src/main/java/com/knubisoft/testapi/dto/auth/jwt/JwtProtectedResourceResponse.java
@@ -0,0 +1,12 @@
+package com.knubisoft.testapi.dto.auth.jwt;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+
+import java.util.List;
+
+@Data
+@AllArgsConstructor
+public class JwtProtectedResourceResponse {
+ private List values;
+}
\ No newline at end of file
diff --git a/TEST-API/src/main/java/com/knubisoft/testapi/dto/websocket/standard/StandardSelfMessage.java b/TEST-API/src/main/java/com/knubisoft/testapi/dto/websocket/standard/StandardSelfMessage.java
new file mode 100644
index 0000000..a12d46e
--- /dev/null
+++ b/TEST-API/src/main/java/com/knubisoft/testapi/dto/websocket/standard/StandardSelfMessage.java
@@ -0,0 +1,10 @@
+package com.knubisoft.testapi.dto.websocket.standard;
+
+import lombok.Data;
+
+@Data
+public class StandardSelfMessage {
+ private String action;
+ private String id;
+ private String value;
+}
\ No newline at end of file
diff --git a/TEST-API/src/main/java/com/knubisoft/testapi/dto/websocket/standard/StandardSelfResponse.java b/TEST-API/src/main/java/com/knubisoft/testapi/dto/websocket/standard/StandardSelfResponse.java
new file mode 100644
index 0000000..78ef4dd
--- /dev/null
+++ b/TEST-API/src/main/java/com/knubisoft/testapi/dto/websocket/standard/StandardSelfResponse.java
@@ -0,0 +1,14 @@
+package com.knubisoft.testapi.dto.websocket.standard;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+public class StandardSelfResponse {
+ private String status;
+ private String id;
+ private String value;
+}
\ No newline at end of file
diff --git a/TEST-API/src/main/java/com/knubisoft/testapi/dto/websocket/stomp/StompSelfMessage.java b/TEST-API/src/main/java/com/knubisoft/testapi/dto/websocket/stomp/StompSelfMessage.java
new file mode 100644
index 0000000..f0f1cdb
--- /dev/null
+++ b/TEST-API/src/main/java/com/knubisoft/testapi/dto/websocket/stomp/StompSelfMessage.java
@@ -0,0 +1,10 @@
+package com.knubisoft.testapi.dto.websocket.stomp;
+
+import lombok.Data;
+
+@Data
+public class StompSelfMessage {
+
+ private String id;
+ private String value;
+}
\ No newline at end of file
diff --git a/TEST-API/src/main/java/com/knubisoft/testapi/dto/websocket/stomp/StompSelfResponse.java b/TEST-API/src/main/java/com/knubisoft/testapi/dto/websocket/stomp/StompSelfResponse.java
new file mode 100644
index 0000000..8bde8d2
--- /dev/null
+++ b/TEST-API/src/main/java/com/knubisoft/testapi/dto/websocket/stomp/StompSelfResponse.java
@@ -0,0 +1,13 @@
+package com.knubisoft.testapi.dto.websocket.stomp;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+
+@Data
+@AllArgsConstructor
+public class StompSelfResponse {
+
+ private String status;
+ private String id;
+ private String value;
+}
\ No newline at end of file
diff --git a/TEST-API/src/main/java/com/knubisoft/testapi/exception/ApiTestAuthException.java b/TEST-API/src/main/java/com/knubisoft/testapi/exception/ApiTestAuthException.java
new file mode 100644
index 0000000..24c6b46
--- /dev/null
+++ b/TEST-API/src/main/java/com/knubisoft/testapi/exception/ApiTestAuthException.java
@@ -0,0 +1,7 @@
+package com.knubisoft.testapi.exception;
+
+public class ApiTestAuthException extends RuntimeException {
+ public ApiTestAuthException(final String message) {
+ super(message);
+ }
+}
\ No newline at end of file
diff --git a/TEST-API/src/main/java/com/knubisoft/testapi/exception/ApiTestEntityException.java b/TEST-API/src/main/java/com/knubisoft/testapi/exception/ApiTestEntityException.java
new file mode 100644
index 0000000..f70a6fe
--- /dev/null
+++ b/TEST-API/src/main/java/com/knubisoft/testapi/exception/ApiTestEntityException.java
@@ -0,0 +1,7 @@
+package com.knubisoft.testapi.exception;
+
+public class ApiTestEntityException extends RuntimeException {
+ public ApiTestEntityException(final String message) {
+ super(message);
+ }
+}
diff --git a/TEST-API/src/main/java/com/knubisoft/testapi/exception/GlobalExceptionHandler.java b/TEST-API/src/main/java/com/knubisoft/testapi/exception/GlobalExceptionHandler.java
index 92527c4..fcc4b2b 100644
--- a/TEST-API/src/main/java/com/knubisoft/testapi/exception/GlobalExceptionHandler.java
+++ b/TEST-API/src/main/java/com/knubisoft/testapi/exception/GlobalExceptionHandler.java
@@ -70,6 +70,16 @@ public ResponseEntity