diff --git a/code/Test_definitions/QoD_API_Test.feature b/code/Test_definitions/QoD_API_Test.feature deleted file mode 100644 index fdc6e40750..0000000000 --- a/code/Test_definitions/QoD_API_Test.feature +++ /dev/null @@ -1,70 +0,0 @@ -#/*- ---license-start -#* CAMARA Project -#* --- -#* Copyright (C) 2022 - 2023 Contributors | Deutsche Telekom AG to CAMARA a Series of LF Projects, LLC -#* The contributor of this file confirms his sign-off for the -#* Developer Certificate of Origin (http://developercertificate.org). -#* --- -#* Licensed under the Apache License, Version 2.0 (the "License"); -#* you may not use this file except in compliance with the License. -#* You may obtain a copy of the License at -#* -#* http://www.apache.org/licenses/LICENSE-2.0 -#* -#* Unless required by applicable law or agreed to in writing, software -#* distributed under the License is distributed on an "AS IS" BASIS, -#* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -#* See the License for the specific language governing permissions and -#* limitations under the License. -#* ---license-end -#*/ - -@QoD @QoDSanity -Feature: Automated QoD System Integration Test - - @QQoDSessionCreateGetDelete - Scenario: Create QoD session with mandatory parameters - Given Use the QoD MOCK URL - When Create a new QoD session with mandatory parameters - Then Response code is 201 - When Get QoD session - Then Response code is 200 - When Delete existing QoD session - Then Response code is 204 - - @QoDSessionCreateGetDeleteAllparams - Scenario: Create QoD session with all parameters & Deletion of Session id - Given Use the QoD MOCK URL - When Create a new QoD session with all parameters - Then Response code is 201 - When Get QoD session - Then Response code is 200 - When Delete existing QoD session - Then Response code is 204 - - @QoDCreateSessionDeleteInvalidSession - Scenario: Delete a Invalid QoD session for session id - Given Use the QoD MOCK URL - When Create a new QoD session with mandatory parameters - Then Response code is 201 - When Delete Invalid QoD session - Then Response code is 404 - - - @QoDInvalidCreateSession - Scenario: QoD session with 5XX response - # Test with end point not reachable - Given Use the QoD MOCK URL with invalid scenario - When Create a new QoD session along with all parameters - Then Response code is 500 - - - @QoDInvalidCreateSessionpayload - Scenario: QoD session with invalid payload 4XX - # Test with invalid Payload - Given Use the QoD MOCK URL with invalid scenario - When Create a new QoD session with parameters - Then Response code is 400 - - - diff --git a/code/Test_definitions/README.md b/code/Test_definitions/README.md index 27a1f06586..01a2888348 100644 --- a/code/Test_definitions/README.md +++ b/code/Test_definitions/README.md @@ -1 +1,17 @@ -This directory contains at least one `.feature` file containing test definitions for the repository API(s). +This directory contains the `.feature` files with test definitions for the 3 repository API(s). +There is a separate Feature file per API operation. + +The test plan has to be enhanced and some scenarios still contains comments and questions to be resolved: + +* Should `sinkCredential` be returned as part of `SessionInfo` and `ProvisioningInfo` responses? +* For port ranges, the maximum is considered in the schema so a generic schema validator may generate a 400 INVALID_ARGUMENT without further distinction, instead of the specific 400 OUT_OF_RANGE, so both could be accepted +* For `sinkCredential.accessTokenType`, only `bearer` is considered in the schema so a generic schema validator may generate a 400 INVALID_ARGUMENT without further distinction, instead of the specific 400 INVALID_TOKEN, so both could be accepted +* When providing a non existent QoS Profile to create a session or provisioning, what code to return? 400 INVALID_ARGUMENT is proposed +* For expired tokens, both codes "UNAUTHENTICATED" or "AUTHENTICATION_REQUIRED" for 401 may be returned, depending on whether the access token can be refreshed or not +* Decision about 422 DEVICE_IDENTIFIERS_MISMATCH is under discussion +* Now that QoS Profiles may be restricted to certain devices, what code to return when the provided device in createSession is not suitable for the provided qosProfile. We may reuse 422 DEVICE_NOT_APPLICABLE +* When providing a path parameter, such sessionId or provisioningId, which is not compliant with the spec format (UUID), what code to return? Options are 400 INVALID_ARGUMENT or 404 NOT_FOUND if path parameter format is not checked previously +* 422 UNSUPPORTED_DEVICE_IDENTIFIERS is in the Commonalities guidelines (document) but it is not yet in the artifact and it not yet considered in the quality-on-demand or qos-profiles API specs, but it is in qod-provisioning API spec +* For QoS Profile response validations, it is pending to check additional constraints, such as minDuration being less or equal than maxDuration, etc +* When accessing a session or provisioning created by a different client, both 403 INVALID_TOKEN_CONTEXT and the generic 403 PERMISSION_DENIED codes could make sense. + diff --git a/code/Test_definitions/qod-provisioning-createProvisioning.feature b/code/Test_definitions/qod-provisioning-createProvisioning.feature new file mode 100644 index 0000000000..087066f486 --- /dev/null +++ b/code/Test_definitions/qod-provisioning-createProvisioning.feature @@ -0,0 +1,342 @@ +Feature: CAMARA QoD Provisioning API, v0.1.0 - Operation createProvisioning + # Input to be provided by the implementation to the tester + # + # Implementation indications: + # * apiRoot: API root of the server URL + # * List of device identifier types which are not supported, among: phoneNumber, ipv4Address, ipv6Address. + # For this version, CAMARA does not allow the use of networkAccessIdentifier, so it is considered by default as not supported. + # + # Testing assets: + # * A device object applicable for QoD provisioning service + # * A device object identifying a device commercialized by the implementation for which the service is not applicable, if any + # + # References to OAS spec schemas refer to schemas specified in qod-provisioning.yaml, version 0.1.0 + + Background: Common createProvisioning setup + Given an environment at "apiRoot" + And the resource "/qod-provisioning/v0.1/device-qos" | + And the header "Content-Type" is set to "application/json" + And the header "Authorization" is set to a valid access token + And the header "x-correlator" is set to a UUID value + # Properties not explicitly overwitten in the Scenarios can take any values compliant with the schema + And the request body is set by default to a request body compliant with the schema at "/components/schemas/CreateProvisioning" + + # Success scenarios + + @qod_provisioning_createProvisioning_01_generic_success_scenario + Scenario: Common validations for any sucess scenario + # Valid testing device and default request body compliant with the schema + Given a valid testing device supported by the service, identified by the token or provided in the request body + And the request property "$.qosProfile" is set to a valid QoS Profile as returned by QoS Profiles API + When the request "createProvisioning" is sent + Then the response status code is 201 + And the response header "x-correlator" has same value as the request header "x-correlator" + And the response header "Content-Type" is "application/json" + # The response has to comply with the generic response schema which is part of the spec + And the response body complies with the OAS schema at "/components/schemas/ProvisioningInfo" + # Additionally any success response has to comply with some constraints beyond the schema compliance + And the response property "$.device" exists only if provided in the request body and with the same value + And the response property "$.qosProfile" has the same value as in the request body + And the response property "$.sink" exists only if provided in the request body and with the same value + # sinkCredentials not explicitly mentioned to be returned if present, as this is debatible for security concerns + And the response property "$.startedAt" exists only if "$.status" is "AVAILABLE" and the value is in the past + And the response property "$.statusInfo" exists only if "$.status" is "UNAVAILABLE" + + @qod_provisioning_createProvisioning_02_event_notification + Scenario: Events for the outcome of provisioning creation if sink is provided + Given a valid testing device supported by the service, identified by the token or provided in the request body + And the request property "$.qosProfile" is set to a valid QoS Profile as returned by QoS Profiles API + And the request property "$.sink" is set to a URL when events can be monitored + And the request property "$.sinkCredentials.credentialType" is set to "ACCESSTOKEN" + And the request property "$.sinkCredentials.accessTokenType" is set to "bearer" + And the request property "$.sinkCredentials.accessToken" is set to a valid access token accepted by the events receiver + And the request property "$.sinkCredentials.accessTokenExpiresUtc" is set to a value long enough in the future + And the request "createProvisioning" is sent + And the response status code is 201 + # There is no specific limit defined for the process to end + When the provisioning outcome is known + Then an event is received at the address of the request property "$.sink" + And the event header "Authorization" is set to "Bearer: " + the value of the request property "$.sinkCredentials.accessToken" + And the event header "Content-Type" is set to "application/cloudevents+json" + And the event body complies with the OAS schema at "/components/schemas/EventStatusChanged" + # Additionally any event body has to comply with some constraints beyond the schema compliance + And the event body property "$.id" is unique + And the event body property "$.type" is set to "org.camaraproject.qod-provisioning.v0.status-changed" + And the event body property "$.data.provisioningId" has the same value as createProvisioning response property "$.provisioningId" + And the event body property "$.data.status" is "AVAILABLE" or "UNAVAILABLE" + And the event body property "$.data.statusInfo" exists only if "$.data.status" is "UNAVAILABLE" + + @qod_provisioning_createProvisioning_03_3_legged_missing_device + Scenario: Device is not returned if not included in the creation request + Given the header "Authorization" is set to a valid 3-legged access token associated to a valid testing device supported by the service + And the request property "$.device" is not included + When the request "createProvisioning" is sent + Then the response status code is 201 + And the response header "x-correlator" has same value as the request header "x-correlator" + And the response header "Content-Type" is "application/json" + And the response body complies with the OAS schema at "/components/schemas/ProvisioningInfo" + And the response property "$.device" does not exist + + # Errors 400 + + @qod_provisioning_createProvisioning_400.1_schema_not_compliant + Scenario: Invalid Argument. Generic Syntax Exception + Given the request body is set to any value which is not compliant with the schema at "/components/schemas/CreateProvisioning" + When the request "createProvisioning" is sent + Then the response status code is 400 + And the response header "x-correlator" has same value as the request header "x-correlator" + And the response header "Content-Type" is "application/json" + And the response property "$.status" is 400 + And the response property "$.code" is "INVALID_ARGUMENT" + And the response property "$.message" contains a user friendly text + + @qod_provisioning_createProvisioning_400.2_no_request_body + Scenario: Missing request body + Given the request body is not included + When the request "createProvisioning" is sent + Then the response status code is 400 + And the response header "x-correlator" has same value as the request header "x-correlator" + And the response header "Content-Type" is "application/json" + And the response property "$.status" is 400 + And the response property "$.code" is "INVALID_ARGUMENT" + And the response property "$.message" contains a user friendly text + + @qod_provisioning_createProvisioning_400.3_empty_request_body + Scenario: Empty object as request body + Given the request body is set to {} + When the request "createProvisioning" is sent + Then the response status code is 400 + And the response header "x-correlator" has same value as the request header "x-correlator" + And the response header "Content-Type" is "application/json" + And the response property "$.status" is 400 + And the response property "$.code" is "INVALID_ARGUMENT" + And the response property "$.message" contains a user friendly text + + @qod_provisioning_createProvisioning_400.4_device_empty + Scenario: The device value is an empty object + Given the request body property "$.device" is set to: {} + When the request "createProvisioning" is sent + Then the response status code is 400 + And the response header "x-correlator" has same value as the request header "x-correlator" + And the response header "Content-Type" is "application/json" + And the response property "$.status" is 400 + And the response property "$.code" is "INVALID_ARGUMENT" + And the response property "$.message" contains a user friendly text + + @qod_provisioning_createProvisioning_400.5_device_identifiers_not_schema_compliant + # Test every type of identifier even if not supported by the implementation + Scenario Outline: Some device identifier value does not comply with the schema + Given the request body property "" does not comply with the OAS schema at "" + When the request "createProvisioning" is sent + Then the response status code is 400 + And the response header "x-correlator" has same value as the request header "x-correlator" + And the response header "Content-Type" is "application/json" + And the response property "$.status" is 400 + And the response property "$.code" is "INVALID_ARGUMENT" + And the response property "$.message" contains a user friendly text + + Examples: + | device_identifier | oas_spec_schema | + | $.device.phoneNumber | /components/schemas/PhoneNumber | + | $.device.ipv4Address | /components/schemas/NetworkAccessIdentifier | + | $.device.ipv6Address | /components/schemas/DeviceIpv4Addr | + | $.device.networkIdentifier | /components/schemas/DeviceIpv6Address | + + # The maximum is considered in the schema so a generic schema validator may fail and generate a 400 INVALID_ARGUMENT without further distinction, and both could be accepted + @qod_provisioning_createProvisioning_400.6_out_of_range_port + Scenario: Out of range port + Given the request body property "$.device.ipv4Address.publicPort" is set to a value not between 0 and 65536 + When the request "createProvisioning" is sent + Then the response status code is 400 + And the response header "x-correlator" has same value as the request header "x-correlator" + And the response header "Content-Type" is "application/json" + And the response property "$.status" is 400 + And the response property "$.code" is "OUT_OF_RANGE" or "INVALID_ARGUMENT" + And the response property "$.message" contains a user friendly text + + # PLAIN and REFRESHTOKEN are considered in the schema so INVALID_ARGUMENT is not expected + @qod_provisioning_createProvisioning_400.7_invalid_sink_credential + Scenario Outline: Invalid credential + Given the request body property "$.sinkCredential.credentialType" is set to "" + When the request "createProvisioning" is sent + Then the response status code is 400 + And the response header "x-correlator" has same value as the request header "x-correlator" + And the response header "Content-Type" is "application/json" + And the response property "$.status" is 400 + And the response property "$.code" is "INVALID_CREDENTIAL" + And the response property "$.message" contains a user friendly text + + Examples: + | unsupported_credential_type | + | PLAIN | + | REFRESHTOKEN | + + # Only "bearer" is considered in the schema so a generic schema validator may fail and generate a 400 INVALID_ARGUMENT without further distinction, + # and both could be accepted + @qod_provisioning_createProvisioning_400.8_sink_credential_invalid_token + Scenario: Invalid token + Given the request body property "$.sinkCredential.accessTokenType" is set to a value other than "bearer" + When the request "createProvisioning" is sent + Then the response status code is 400 + And the response header "x-correlator" has same value as the request header "x-correlator" + And the response header "Content-Type" is "application/json" + And the response property "$.status" is 400 + And the response property "$.code" is "INVALID_TOKEN" or "INVALID_ARGUMENT" + And the response property "$.message" contains a user friendly text + + # TBD if we neeed a dedicated code + @qod_provisioning_createProvisioning_400.9_non_existent_qos_profile + Scenario: Non existent QoS profile + Given the request body property "qosProfile" is set to a non-existent QoS Profile + When the request "createProvisioning" is sent + Then the response status code is 400 + And the response header "x-correlator" has same value as the request header "x-correlator" + And the response header "Content-Type" is "application/json" + And the response property "$.status" is 400 + And the response property "$.code" is "INVALID_ARGUMENT" + And the response property "$.message" contains a user friendly text + + # Generic 401 errors + + @qod_provisioning_createProvisioning_401.1_no_authorization_header + Scenario: No Authorization header + Given the header "Authorization" is removed + When the request "createProvisioning" is sent + Then the response status code is 401 + And the response header "x-correlator" has same value as the request header "x-correlator" + And the response header "Content-Type" is "application/json" + And the response property "$.status" is 401 + And the response property "$.code" is "UNAUTHENTICATED" + And the response property "$.message" contains a user friendly text + + # In this case both codes could make sense depending on whether the access token can be refreshed or not + @qod_provisioning_createProvisioning_401.2_expired_access_token + Scenario: Expired access token + Given the header "Authorization" is set to an expired access token + When the request "createProvisioning" is sent + Then the response status code is 401 + And the response header "x-correlator" has same value as the request header "x-correlator" + And the response header "Content-Type" is "application/json" + And the response property "$.status" is 401 + And the response property "$.code" is "UNAUTHENTICATED" or "AUTHENTICATION_REQUIRED" + And the response property "$.message" contains a user friendly text + + @qod_provisioning_createProvisioning_401.3_invalid_access_token + Scenario: Invalid access token + Given the header "Authorization" is set to an invalid access token + When the request "createProvisioning" is sent + Then the response status code is 401 + And the response header "x-correlator" has same value as the request header "x-correlator" + And the response header "Content-Type" is "application/json" + And the response property "$.status" is 401 + And the response property "$.code" is "UNAUTHENTICATED" + And the response property "$.message" contains a user friendly text + + # Errors 403 + + @qod_provisioning_createProvisioning_403.1_device_token_mismatch + Scenario: Inconsistent access token context for the device + # To test this, a token have to be obtained for a different device + Given the request body property "$.device" is set to a valid testing device + And the header "Authorization" is set to a valid access token emitted for a different device + When the request "createProvisioning" is sent + Then the response status code is 403 + And the response header "x-correlator" has same value as the request header "x-correlator" + And the response header "Content-Type" is "application/json" + And the response property "$.status" is 403 + And the response property "$.code" is "INVALID_TOKEN_CONTEXT" + And the response property "$.message" contains a user friendly text + + # Errors 404 + + # Typically with a 2-legged access token + @qod_provisioning_createProvisioning_404.1_device_not_found + Scenario: Some identifier cannot be matched to a device + Given that the device cannot be identified from the access token + And the request body property "$.device" is compliant with the request body schema but does not identify a valid device + When the request "createProvisioning" is sent + Then the response status code is 404 + And the response header "x-correlator" has same value as the request header "x-correlator" + And the response header "Content-Type" is "application/json" + And the response property "$.status" is 404 + And the response property "$.code" is "DEVICE_NOT_FOUND" + And the response property "$.message" contains a user friendly text + + # Errors 409 + + @qod_provisioning_createProvisioning_409.1_provisioning_conflict + Scenario: Provisioning conflict + Given a valid testing device supported by the service, identified by the token or provided in the request body + And a QoD provisioning already exists for that device + When the request "createProvisioning" is sent + And the response header "x-correlator" has same value as the request header "x-correlator" + And the response header "Content-Type" is "application/json" + And the response property "$.status" is 409 + And the response property "$.code" is "CONFLICT" + And the response property "$.message" contains a user friendly text + + # Errors 422 + + @qod_provisioning_createProvisioning_422.1_device_identifiers_unsupported + Scenario: None of the provided device identifiers is supported by the implementation + Given that some type of device identifiers are not supported by the implementation + And the request body property "$.device" only includes device identifiers not supported by the implementation + When the request "createProvisioning" is sent + Then the response status code is 422 + And the response header "x-correlator" has same value as the request header "x-correlator" + And the response header "Content-Type" is "application/json" + And the response property "$.status" is 422 + And the response property "$.code" is "UNSUPPORTED_DEVICE_IDENTIFIERS" + And the response property "$.message" contains a user friendly text + + # This scenario is under discussion + @qod_provisioning_createProvisioning_422.2_device_identifiers_mismatch + Scenario: Device identifiers mismatch + Given that al least 2 types of device identifiers are supported by the implementation + And the request body property "$.device" includes several identifiers, each of them identifying a valid but different device + When the request "createProvisioning" is sent + Then the response status code is 422 + And the response header "x-correlator" has same value as the request header "x-correlator" + And the response header "Content-Type" is "application/json" + And the response property "$.status" is 422 + And the response property "$.code" is "DEVICE_IDENTIFIERS_MISMATCH" + And the response property "$.message" contains a user friendly text + + @qod_provisioning_createProvisioning_422.3_device_not_supported + Scenario: Service not available for the device + Given that service is not supported for all devices commercialized by the operator + And the service is not applicable for the device identified by the token or provided in the request body + When the request "createProvisioning" is sent + Then the response status code is 422 + And the response header "x-correlator" has same value as the request header "x-correlator" + And the response header "Content-Type" is "application/json" + And the response property "$.status" is 422 + And the response property "$.code" is "DEVICE_NOT_APPLICABLE" + And the response property "$.message" contains a user friendly text + + # TBD if we neeed a dedicated code + @qod_provisioning_createProvisioning_422.4_qos_profile_incompatible_device + Scenario: QoS profile is not suitable for the device + Given that implementation has QoS Profiles restricted to certain devices + And the request body property "qosProfile" is set to a restricted QoS Profile + And a device not suitable for the restricted QoS Profiles is provided in the request body or identified by the access token + When the request "createProvisioning" is sent + Then the response status code is 400 + And the response header "x-correlator" has same value as the request header "x-correlator" + And the response header "Content-Type" is "application/json" + And the response property "$.status" is 422 + And the response property "$.code" is "DEVICE_NOT_APPLICABLE" + And the response property "$.message" contains a user friendly text + + # Typically with a 2-legged access token + @qod_provisioning_createProvisioning_422.5_unidentifiable_device + Scenario: Device not included and cannot be deducted from the access token + Given the header "Authorization" is set to a valid access which does not identifiy a single device + And the request body property "$.device" is not included + When the request "createProvisioning" is sent + Then the response status code is 422 + And the response header "x-correlator" has same value as the request header "x-correlator" + And the response header "Content-Type" is "application/json" + And the response property "$.status" is 422 + And the response property "$.code" is "UNIDENTIFIABLE_DEVICE" + And the response property "$.message" contains a user friendly text diff --git a/code/Test_definitions/qod-provisioning-deleteProvisioning.feature b/code/Test_definitions/qod-provisioning-deleteProvisioning.feature new file mode 100644 index 0000000000..b50cadb64f --- /dev/null +++ b/code/Test_definitions/qod-provisioning-deleteProvisioning.feature @@ -0,0 +1,166 @@ +Feature: CAMARA QoD Provisioning API, v0.1.0 - Operation deleteProvisioning + # Input to be provided by the implementation to the tester + # + # Implementation indications: + # * apiRoot: API root of the server URL + # + # Testing assets: + # * The ProvisioningInfo of an existing QoD Provisiong + # * The ProvisioningInfo of an existing QoD Provisiong with status "AVAILABLE", and with provided values for "sink" and "sinkCredential" + # + # References to OAS spec schemas refer to schemas specified in qod-provisioning.yaml, version 0.1.0 + + Background: Common deleteProvisioning setup + Given an environment at "apiRoot" + And the resource "/qod-provisioning/v0.1/device-qos/{provisioningId}" + # Unless indicated otherwise the QoD provisioning must be created by the same API client given in the access token + And the header "Authorization" is set to a valid access token granted to the same client that created the QoD provisoning + And the header "x-correlator" is set to a UUID value + And the path parameter "provisoningId" is set by default to an existing QoD provisioning ID + + # Success scenarios + + @qod_provisioning_deleteProvisioning_01_delete_existing_qod_provisioning_sync + Scenario: Delete an existing QoD Provisioning synchronously + Given that implementation deletes QoD provisioning synchronously + And an existing QoD provisioning created by operation createProvisioning + And the path parameter "provisoningId" is set to the value for that QoD provisioning + When the request "deleteProvisioning" is sent + Then the response status code is 204 + And the response header "x-correlator" has same value as the request header "x-correlator" + + @qod_provisioning_deleteProvisioning_02_delete_existing_qod_provisioning_async + Scenario: Delete an existing QoD Provisioning asynchronously + Given that implementation deletes QoD provisioning asynchronously + And an existing QoD provisioning created by operation createProvisioning + And the path parameter "provisoningId" is set to the value for that QoD provisioning + When the request "deleteProvisioning" is sent + Then the response status code is 202 + And the response header "x-correlator" has same value as the request header "x-correlator" + And the response header "Content-Type" is "application/json" + # The response has to comply with the generic response schema which is part of the spec + And the response body complies with the OAS schema at "/components/schemas/ProvisioningInfo" + # Additionally any success response has to comply with some constraints beyond the schema compliance + And the response property "$.device" exists only if provided for createProvisioning and with the same value + And the response property "$.qosProfile" has the value provided for createProvisioning + And the response property "$.status" is "AVAILABLE" + And the response property "$.statusInfo" is "DELETE_REQUESTED" + And the response property "$.sink" exists only if provided for createProvisioning and with the same value + # sinkCredentials not explicitly mentioned to be returned if present, as this is debatible for security concerns + And the response property "$.startedAt" exists and the value is in the past + + @qod_provisioning_deleteProvisioning_03_event_notification_sync + Scenario: Event is received if the provisioning was AVAILABLE and sink was provided (synchronous deletion) + Given that implementation deletes QoD provisioning synchronously + And an existing QoD provisioning created by operation createProvisioning with provided values for "sink" and "sinkCredential", and with status "AVAILABLE" + And the path parameter "provisoningId" is set to the value for that QoD provisioning + When the request "deleteProvisioning" is sent + Then the response status code is 204 + And an event is received at the address of the "$.sink" provided for createProvisioning + And the event header "Authorization" is set to "Bearer: " + the value of "$.sinkCredentials.accessToken" provided for createProvisioning + And the event header "Content-Type" is set to "application/cloudevents+json" + And the event body complies with the OAS schema at "/components/schemas/EventStatusChanged" + # Additionally any event body has to comply with some constraints beyond the schema compliance + And the event body property "$.id" is unique + And the event body property "$.type" is set to "org.camaraproject.qod-provisioning.v0.status-changed" + And the event body property "$.data.provisioningId" as returned for createProvisioning + And the event body property "$.data.status" is "UNAVAILABLE" + And the event body property "$.data.statusInfo" is "DELETE_REQUESTED" + + @qod_provisioning_deleteProvisioning_04_event_notification_async + Scenario: Event is received if the provisioning was AVAILABLE and sink was provided (asynchronous deletion) + Given that implementation deletes QoD provisioning asynchronously + And an existing QoD provisioning created by operation createProvisioning with provided values for "sink" and "sinkCredential", and with status "AVAILABLE" + And the path parameter "provisoningId" is set to the value for that QoD provisioning + When the request "deleteProvisioning" is sent + Then the response status code is 202 + And when the asynchronous deletion process is completed + Then an event is received at the address of the "$.sink" provided for createProvisioning + And the event header "Authorization" is set to "Bearer: " + the value of "$.sinkCredentials.accessToken" provided for createProvisioning + And the event header "Content-Type" is set to "application/cloudevents+json" + And the event body complies with the OAS schema at "/components/schemas/EventStatusChanged" + # Additionally any event body has to comply with some constraints beyond the schema compliance + And the event body property "$.id" is unique + And the event body property "$.type" is set to "org.camaraproject.qod-provisioning.v0.status-changed" + And the event body property "$.data.provisioningId" as returned for createProvisioning + And the event body property "$.data.status" is "UNAVAILABLE" + And the event body property "$.data.statusInfo" is "DELETE_REQUESTED" + + # Errors 400 + + # 400 errors are not expected for this operation unless the implementation validates the format of provisioningId + # 404 NOT_FOUND is an alternative if path parameter format is not validated + @qod_provisioning_deleteProvisioning_400.1_invalid_id + Scenario: Invalid Argument. Generic Syntax Exception + Given the path parameter "provisioningId" has not a UUID format + When the request "deleteProvisioning" is sent + Then the response status code is 404 + And the response header "x-correlator" has same value as the request header "x-correlator" + And the response header "Content-Type" is "application/json" + And the response property "$.status" is 400 + And the response property "$.code" is "INVALID_ARGUMENT" + And the response property "$.message" contains a user friendly text + + # Generic 401 errors + + @qod_provisioning_deleteProvisioning_401.1_no_authorization_header + Scenario: No Authorization header + Given the header "Authorization" is not sent + When the request "deleteProvisioning" is sent + Then the response status code is 401 + And the response header "x-correlator" has same value as the request header "x-correlator" + And the response header "Content-Type" is "application/json" + And the response property "$.status" is 401 + And the response property "$.code" is "UNAUTHENTICATED" + And the response property "$.message" contains a user friendly text + + # In this case both codes could make sense depending on whether the access token can be refreshed or not + @qod_provisioning_deleteProvisioning_401.2_expired_access_token + Scenario: Expired access token + Given the header "Authorization" is set to an expired access token + When the request "deleteProvisioning" is sent + Then the response status code is 401 + And the response header "x-correlator" has same value as the request header "x-correlator" + And the response header "Content-Type" is "application/json" + And the response property "$.status" is 401 + And the response property "$.code" is "UNAUTHENTICATED" or "AUTHENTICATION_REQUIRED" + And the response property "$.message" contains a user friendly text + + @qod_provisioning_deleteProvisioning_401.3_invalid_access_token + Scenario: Invalid access token + Given the header "Authorization" is set to an invalid access token + When the request "deleteProvisioning" is sent + Then the response status code is 401 + And the response header "x-correlator" has same value as the request header "x-correlator" + And the response header "Content-Type" is "application/json" + And the response property "$.status" is 401 + And the response property "$.code" is "UNAUTHENTICATED" + And the response property "$.message" contains a user friendly text + + # Errors 403 + + # TBD which code is more appropriate for this scenario + @qod_provisioning_deleteProvisioning_403.1_different_client_id + Scenario: QoD provisioning not created by the API client given in the access token + # To test this, a token have to be obtained by a different client + Given the header "Authorization" is set to a valid access token emitted to a client which did not created the QoD provisioning + When the request "deleteProvisioning" is sent + Then the response status code is 403 + And the response header "x-correlator" has same value as the request header "x-correlator" + And the response header "Content-Type" is "application/json" + And the response property "$.status" is 403 + And the response property "$.code" is "PERMISSION_DENIED" or "INVALID_TOKEN_CONTEXT" + And the response property "$.message" contains a user friendly text + + # Errors 404 + + @qod_provisioning_deleteProvisioning_404.1_not_found + Scenario: provisioningId of a no existing QoD provisioning + Given the path parameter "provisoningId" is set to a random UUID + When the request "deleteProvisioning" is sent + Then the response status code is 404 + And the response header "x-correlator" has same value as the request header "x-correlator" + And the response header "Content-Type" is "application/json" + And the response property "$.status" is 404 + And the response property "$.code" is "NOT_FOUND" + And the response property "$.message" contains a user friendly text diff --git a/code/Test_definitions/qod-provisioning-getProvisioningById.feature b/code/Test_definitions/qod-provisioning-getProvisioningById.feature new file mode 100644 index 0000000000..09142ecbd8 --- /dev/null +++ b/code/Test_definitions/qod-provisioning-getProvisioningById.feature @@ -0,0 +1,128 @@ +Feature: CAMARA QoD Provisioning API, v0.1.0 - Operation getProvisioningById + # Input to be provided by the implementation to the tester + # + # Implementation indications: + # * apiRoot: API root of the server URL + # + # Testing assets: + # * The provisioningId of an existing QoD Provisiong, and the request properties used for createProvisioning + # + # References to OAS spec schemas refer to schemas specified in qod-provisioning.yaml, version 0.1.0 + + Background: Common getProvisioningById setup + Given an environment at "apiRoot" + And the resource "/qod-provisioning/v0.1/device-qos/{provisioningId}" | + # Unless indicated otherwise the QoD provisioning must be created by the same API client given in the access token + And the header "Authorization" is set to a valid access token granted to the same client that created the QoD provisoning + And the header "x-correlator" is set to a UUID value + And the path parameter "provisoningId" is set by default to an existing QoD provisioning ID + + # Success scenarios + + @qod_provisioning_getProvisioningById_01_get_existing_qod_provisioning + Scenario: Get an existing QoD Provisioning by provisioningId + Given an existing QoD provisioning created by operation createProvisioning + And the path parameter "provisoningId" is set to the value for that QoD provisioning + When the request "getProvisioningById" is sent + Then the response status code is 200 + And the response header "x-correlator" has same value as the request header "x-correlator" + And the response header "Content-Type" is "application/json" + # The response has to comply with the generic response schema which is part of the spec + And the response body complies with the OAS schema at "/components/schemas/ProvisioningInfo" + # Additionally any success response has to comply with some constraints beyond the schema compliance + And the response property "$.device" exists only if provided for createProvisioning and with the same value + And the response property "$.qosProfile" has the value provided for createProvisioning + And the response property "$.sink" exists only if provided for createProvisioning and with the same value + # sinkCredentials not explicitly mentioned to be returned if present, as this is debatible for security concerns + And the response property "$.startedAt" exists only if "$.status" is not "REQUESTED" and the value is in the past + And the response property "$.statusInfo" exists only if "$.status" is "UNAVAILABLE" + + @qod_provisioning_getProvisioningById_02_get_recent_unvailable + Scenario: Provisioning becoming "UNAVAILABLE" is not released for at least 360 seconds + Given an existing QoD provisioning deleted in the last 360 seconds + And the path parameter "provisoningId" is set to the value for that QoD provisioning + When the request "getProvisioningById" is sent + Then the response status code is 200 + And the response header "x-correlator" has same value as the request header "x-correlator" + And the response header "Content-Type" is "application/json" + And the response body complies with the OAS schema at "/components/schemas/ProvisioningInfo" + And the response property "$.status" is "UNAVAILABLE" + + # Errors 400 + + # 400 errors are not expected for this operation unless the implementation validates the format of provisioningId + # 404 NOT_FOUND is an alternative if path parameter format is not validated + @qod_provisioning_getProvisioningById_400.1_invalid_id + Scenario: Invalid Argument. Generic Syntax Exception + Given the path parameter "provisioningId" has not a UUID format + When the request "getProvisioningById" is sent + Then the response status code is 400 + And the response header "x-correlator" has same value as the request header "x-correlator" + And the response header "Content-Type" is "application/json" + And the response property "$.status" is 400 + And the response property "$.code" is "INVALID_ARGUMENT" + And the response property "$.message" contains a user friendly text + + # Generic 401 errors + + @qod_provisioning_getProvisioningById_401.1_no_authorization_header + Scenario: No Authorization header + Given the header "Authorization" is not sent + When the request "getProvisioningById" is sent + Then the response status code is 401 + And the response header "x-correlator" has same value as the request header "x-correlator" + And the response header "Content-Type" is "application/json" + And the response property "$.status" is 401 + And the response property "$.code" is "UNAUTHENTICATED" + And the response property "$.message" contains a user friendly text + + # In this case both codes could make sense depending on whether the access token can be refreshed or not + @qod_provisioning_getProvisioningById_401.2_expired_access_token + Scenario: Expired access token + Given the header "Authorization" is set to an expired access token + When the request "getProvisioningById" is sent + Then the response status code is 401 + And the response header "x-correlator" has same value as the request header "x-correlator" + And the response header "Content-Type" is "application/json" + And the response property "$.status" is 401 + And the response property "$.code" is "UNAUTHENTICATED" or "AUTHENTICATION_REQUIRED" + And the response property "$.message" contains a user friendly text + + @qod_provisioning_getProvisioningById_401.3_invalid_access_token + Scenario: Invalid access token + Given the header "Authorization" is set to an invalid access token + When the request "getProvisioningById" is sent + Then the response status code is 401 + And the response header "x-correlator" has same value as the request header "x-correlator" + And the response header "Content-Type" is "application/json" + And the response property "$.status" is 401 + And the response property "$.code" is "UNAUTHENTICATED" + And the response property "$.message" contains a user friendly text + + # Errors 403 + + # TBD which code is more appropriate for this scenario + @qod_provisioning_getProvisioningById_403.1_different_client_id + Scenario: QoD provisioning not created by the API client given in the access token + # To test this, a token have to be obtained by a different client + Given the header "Authorization" is set to a valid access token emitted to a client which did not created the QoD provisioning + When the request "getProvisioningById" is sent + Then the response status code is 403 + And the response header "x-correlator" has same value as the request header "x-correlator" + And the response header "Content-Type" is "application/json" + And the response property "$.status" is 403 + And the response property "$.code" is "PERMISSION_DENIED" or "INVALID_TOKEN_CONTEXT" + And the response property "$.message" contains a user friendly text + + # Errors 404 + + @qod_provisioning_getProvisioningById_404.1_not_found + Scenario: provisioningId of a no existing QoD provisioning + Given the path parameter "provisoningId" is set to a random UUID + When the request "getProvisioningById" is sent + Then the response status code is 404 + And the response header "x-correlator" has same value as the request header "x-correlator" + And the response header "Content-Type" is "application/json" + And the response property "$.status" is 404 + And the response property "$.code" is "NOT_FOUND" + And the response property "$.message" contains a user friendly text diff --git a/code/Test_definitions/qod-provisioning-retrieveProvisioningByDevice.feature b/code/Test_definitions/qod-provisioning-retrieveProvisioningByDevice.feature new file mode 100644 index 0000000000..66faf18899 --- /dev/null +++ b/code/Test_definitions/qod-provisioning-retrieveProvisioningByDevice.feature @@ -0,0 +1,260 @@ +Feature: CAMARA QoD Provisioning API, v0.1.0 - Operation retrieveProvisioningByDevice + # Input to be provided by the implementation to the tester + # + # Implementation indications: + # * apiRoot: API root of the server URL + # * List of device identifier types which are not supported, among: phoneNumber, ipv4Address, ipv6Address. + # For this version, CAMARA does not allow the use of networkAccessIdentifier, so it is considered by default as not supported. + # + # Testing assets: + # * A device object with an existing QoD provisioning associated, and the request properties used for createProvisioning + # * A device object with NO existing QoD provisioning associated + # * A device object identifying a device commercialized by the implementation for which the service is not applicable, if any + # + # References to OAS spec schemas refer to schemas specified in qod-provisioning.yaml, version 0.1.0 + + Background: Common retrieveProvisioningByDevice setup + Given an environment at "apiRoot" + And the resource "/qod-provisioning/v0.1/retrieve-device-qos" | + And the header "Content-Type" is set to "application/json" + # Unless indicated otherwise the QoD provisioning must be created by the same API client given in the access token + And the header "Authorization" is set to a valid access token granted to the same client that created the QoD provisoning + And the header "x-correlator" is set to a UUID value + + # Success scenarios + + @qod_provisioning_retrieveProvisioningByDevice_01_get_existing_qod_provisioning_by_device + Scenario: Get an existing QoD Provisioning by device + Given a valid testing device with an existing QoD Provisioning, identified by the token or provided in the request body + When the request "retrieveProvisioningByDevice" is sent + Then the response status code is 200 + And the response header "x-correlator" has same value as the request header "x-correlator" + And the response header "Content-Type" is "application/json" + # The response has to comply with the generic response schema which is part of the spec + And the response body complies with the OAS schema at "/components/schemas/ProvisioningInfo" + # Additionally any success response has to comply with some constraints beyond the schema compliance + And the response property "$.device" exists only if provided for createProvisioning and with the same value + And the response property "$.qosProfile" has the value provided for createProvisioning + And the response property "$.sink" exists only if provided for createProvisioning and with the same value + # sinkCredentials not explicitly mentioned to be returned if present, as this is debatible for security concerns + And the response property "$.startedAt" exists only if "$.status" is "AVAILABLE" and the value is in the past + And the response property "$.statusInfo" exists only if "$.status" is "UNAVAILABLE" + + # Errors 400 + + @qod_provisioning_retrieveProvisioningByDevice_400.1_schema_not_compliant + Scenario: Invalid Argument. Generic Syntax Exception + Given the request body is set to any value which is not compliant with the schema at "/components/schemas/RetrieveProvisioningByDevice" + When the request "retrieveProvisioningByDevice" is sent + And the response header "x-correlator" has same value as the request header "x-correlator" + And the response header "Content-Type" is "application/json" + And the response property "$.status" is 400 + And the response property "$.code" is "INVALID_ARGUMENT" + And the response property "$.message" contains a user friendly text + + @qod_provisioning_retrieveProvisioningByDevice_400.2_no_request_body + Scenario: Missing request body + Given the request body is not included + When the request "retrieveProvisioningByDevice" is sent + Then the response status code is 400 + And the response header "x-correlator" has same value as the request header "x-correlator" + And the response header "Content-Type" is "application/json" + And the response property "$.status" is 400 + And the response property "$.code" is "INVALID_ARGUMENT" + And the response property "$.message" contains a user friendly text + + @qod_provisioning_retrieveProvisioningByDevice_400.3_empty_request_body + Scenario: Empty object as request body + Given the request body is set to {} + When the request "retrieveProvisioningByDevice" is sent + Then the response status code is 400 + And the response header "x-correlator" has same value as the request header "x-correlator" + And the response header "Content-Type" is "application/json" + And the response property "$.status" is 400 + And the response property "$.code" is "INVALID_ARGUMENT" + And the response property "$.message" contains a user friendly text + + @qod_provisioning_retrieveProvisioningByDevice_400.4_device_empty + Scenario: The device value is an empty object + Given the request body property "$.device" is set to: {} + When the request "retrieveProvisioningByDevice" is sent + Then the response status code is 400 + And the response header "x-correlator" has same value as the request header "x-correlator" + And the response header "Content-Type" is "application/json" + And the response property "$.status" is 400 + And the response property "$.code" is "INVALID_ARGUMENT" + And the response property "$.message" contains a user friendly text + + @qod_provisioning_retrieveProvisioningByDevice_400.5_device_identifiers_not_schema_compliant + # Test every type of identifier even if not supported by the implementation + Scenario Outline: Some device identifier value does not comply with the schema + Given the request body property "" does not comply with the OAS schema at "" + When the request "retrieveProvisioningByDevice" is sent + Then the response status code is 400 + And the response header "x-correlator" has same value as the request header "x-correlator" + And the response header "Content-Type" is "application/json" + And the response property "$.status" is 400 + And the response property "$.code" is "INVALID_ARGUMENT" + And the response property "$.message" contains a user friendly text + + Examples: + | device_identifier | oas_spec_schema | + | $.device.phoneNumber | /components/schemas/PhoneNumber | + | $.device.ipv4Address | /components/schemas/NetworkAccessIdentifier | + | $.device.ipv6Address | /components/schemas/DeviceIpv4Addr | + | $.device.networkIdentifier | /components/schemas/DeviceIpv6Address | + + # The maximum is considered in the schema so a generic schema validator may fail and generate a 400 INVALID_ARGUMENT without further distinction, + # and both could be accepted + @qod_provisioning_retrieveProvisioningByDevice_400.6_out_of_range_port + Scenario: Out of range port + Given the request body property "$.device.ipv4Address.publicPort" is set to a value not between 0 and 65536 + When the request "retrieveProvisioningByDevice" is sent + Then the response status code is 400 + And the response header "x-correlator" has same value as the request header "x-correlator" + And the response header "Content-Type" is "application/json" + And the response property "$.status" is 400 + And the response property "$.code" is "OUT_OF_RANGE" or "INVALID_ARGUMENT" + And the response property "$.message" contains a user friendly text + + # Generic 401 errors + + @qod_provisioning_retrieveProvisioningByDevice_401.1_no_authorization_header + Scenario: No Authorization header + Given the header "Authorization" is not sent + When the request "retrieveProvisioningByDevice" is sent + Then the response status code is 401 + And the response header "x-correlator" has same value as the request header "x-correlator" + And the response header "Content-Type" is "application/json" + And the response property "$.status" is 401 + And the response property "$.code" is "UNAUTHENTICATED" + And the response property "$.message" contains a user friendly text + + # In this case both codes could make sense depending on whether the access token can be refreshed or not + @qod_provisioning_retrieveProvisioningByDevice_401.2_expired_access_token + Scenario: Expired access token + Given the header "Authorization" is set to an expired access token + When the request "retrieveProvisioningByDevice" is sent + Then the response status code is 401 + And the response header "x-correlator" has same value as the request header "x-correlator" + And the response header "Content-Type" is "application/json" + And the response property "$.status" is 401 + And the response property "$.code" is "UNAUTHENTICATED" or "AUTHENTICATION_REQUIRED" + And the response property "$.message" contains a user friendly text + + @qod_provisioning_retrieveProvisioningByDevice_401.3_invalid_access_token + Scenario: Invalid access token + Given the header "Authorization" is set to an invalid access token + When the request "retrieveProvisioningByDevice" is sent + Then the response status code is 401 + And the response header "x-correlator" has same value as the request header "x-correlator" + And the response header "Content-Type" is "application/json" + And the response property "$.status" is 401 + And the response property "$.code" is "UNAUTHENTICATED" + And the response property "$.message" contains a user friendly text + + # Errors 403 + + # TBD which code is more appropriate for this scenario + @qod_provisioning_retrieveProvisioningByDevice_403.1_different_client_id + Scenario: QoD provisioning not created by the API client given in the access token + # To test this, a token have to be obtained for a different client + Given the header "Authorization" is set to a valid access token emitted to a client which did not created the QoD provisioning + When the request "retrieveProvisioningByDevice" is sent + Then the response status code is 403 + And the response header "x-correlator" has same value as the request header "x-correlator" + And the response header "Content-Type" is "application/json" + And the response property "$.status" is 403 + And the response property "$.code" is "PERMISSION_DENIED" or "INVALID_TOKEN_CONTEXT" + And the response property "$.message" contains a user friendly text + + @qod_provisioning_retrieveProvisioningByDevice_403.2_device_token_mismatch + Scenario: Inconsistent access token context for the device + # To test this, a token have to be obtained for a different device + Given the request body property "$.device" is set to a valid testing device + And the header "Authorization" is set to a valid access token emitted for a different device + When the request "retrieveProvisioningByDevice" is sent + Then the response status code is 403 + And the response header "x-correlator" has same value as the request header "x-correlator" + And the response header "Content-Type" is "application/json" + And the response property "$.status" is 403 + And the response property "$.code" is "INVALID_TOKEN_CONTEXT" + And the response property "$.message" contains a user friendly text + + # Errors 404 + + @qod_provisioning_retrieveProvisioningByDevice_404.1_not_found + Scenario: Device with no existing QoD provisioning + Given a valid testing device without an existing QoD Provisioning, identified by the token or provided in the request body + When the request "retrieveProvisioningByDevice" is sent + Then the response status code is 404 + And the response header "x-correlator" has same value as the request header "x-correlator" + And the response header "Content-Type" is "application/json" + And the response property "$.status" is 404 + And the response property "$.code" is "NOT_FOUND" + And the response property "$.message" contains a user friendly text + + # Typically with a 2-legged access token + @qod_provisioning_retrieveProvisioningByDevice_404.2_device_not_found + Scenario: Some identifier cannot be matched to a device + Given that the device cannot be identified from the access token + And the request body property "$.device" is compliant with the request body schema but does not identify a valid device + When the request "retrieveProvisioningByDevice" is sent + Then the response status code is 404 + And the response header "x-correlator" has same value as the request header "x-correlator" + And the response header "Content-Type" is "application/json" + And the response property "$.status" is 404 + And the response property "$.code" is "DEVICE_NOT_FOUND" + And the response property "$.message" contains a user friendly text + + # Errors 422 + + @qod_provisioning_retrieveProvisioningByDevice_422.1_device_identifiers_unsupported + Scenario: None of the provided device identifiers is supported by the implementation + Given that some type of device identifiers are not supported by the implementation + And the request body property "$.device" only includes device identifiers not supported by the implementation + When the request "retrieveProvisioningByDevice" is sent + Then the response status code is 422 + And the response header "x-correlator" has same value as the request header "x-correlator" + And the response header "Content-Type" is "application/json" + And the response property "$.status" is 422 + And the response property "$.code" is "UNSUPPORTED_DEVICE_IDENTIFIERS" + And the response property "$.message" contains a user friendly text + + # This scenario is under discussion + @qod_provisioning_retrieveProvisioningByDevice_422.2_device_identifiers_mismatch + Scenario: Device identifiers mismatch + Given that al least 2 types of device identifiers are supported by the implementation + And the request body property "$.device" includes several identifiers, each of them identifying a valid but different device + When the request "retrieveProvisioningByDevice" is sent + Then the response status code is 422 + And the response header "x-correlator" has same value as the request header "x-correlator" + And the response header "Content-Type" is "application/json" + And the response property "$.status" is 422 + And the response property "$.code" is "DEVICE_IDENTIFIERS_MISMATCH" + And the response property "$.message" contains a user friendly text + + @qod_provisioning_retrieveProvisioningByDevice_422.3_device_not_supported + Scenario: Service not available for the device + Given that service is not supported for all devices commercialized by the operator + And the service is not applicable for the device identified by the token or provided in the request body + When the request "retrieveProvisioningByDevice" is sent + Then the response status code is 422 + And the response header "x-correlator" has same value as the request header "x-correlator" + And the response header "Content-Type" is "application/json" + And the response property "$.status" is 422 + And the response property "$.code" is "DEVICE_NOT_APPLICABLE" + And the response property "$.message" contains a user friendly text + + # Typically with a 2-legged access token + @qod_provisioning_retrieveProvisioningByDevice_422.4_unidentifiable_device + Scenario: Device not included and cannot be deducted from the access token + Given the header "Authorization" is set to a valid access which does not identifiy a single device + And the request body property "$.device" is not included + When the request "retrieveProvisioningByDevice" is sent + Then the response status code is 422 + And the response header "x-correlator" has same value as the request header "x-correlator" + And the response header "Content-Type" is "application/json" + And the response property "$.status" is 422 + And the response property "$.code" is "UNIDENTIFIABLE_DEVICE" + And the response property "$.message" contains a user friendly text diff --git a/code/Test_definitions/qos-profiles-getQosProfile.feature b/code/Test_definitions/qos-profiles-getQosProfile.feature new file mode 100644 index 0000000000..ef0268a7af --- /dev/null +++ b/code/Test_definitions/qos-profiles-getQosProfile.feature @@ -0,0 +1,108 @@ +Feature: CAMARA QoS Profiles API, v0.11.0 - Operation getQosProfile + # Input to be provided by the implementation to the tester + # + # Implementation indications: + # * apiRoot: API root of the server URL + # + # Testing assets: + # * The name of an existing QoS profile + # + # References to OAS spec schemas refer to schemas specifies in qos-profiles.yaml, version 0.11.0 + + Background: Common getQosProfile setup + Given an environment at "apiRoot" + And the resource "qos-profiles/v0.11/qos-profiles/{name}" + And the header "Authorization" is set to a valid access token + And the header "x-correlator" is set to a UUID value + And the path param "name" is set by default to a existing QoS profile name + + # Success scenarios + + @qos_profiles_getQosProfile_01_generic_success_scenario + Scenario: Common validations for any sucess scenario + # Valid testing device and default request body compliant with the schema + Given an existing QoS profile + And the path parameter "name" is set to the value for an that QoS profile + When the request "getQosProfile" is sent + Then the response status code is 200 + And the response header "Content-Type" is "application/json" + And the response header "x-correlator" has same value as the request header "x-correlator" + And each item of the the response array complies with the OAS schema at "/components/schemas/QosProfile" + And the response property "$.name" value is equal to path param "name" + # TBC: Add additional constraints, such as max* properties must be higher than min* equivalent properties, etc + + # Errors 400 + + @qos_profiles_getQosProfile_400.1_name_does_not_match_regex + Scenario: Path parameter name doesn't match the defined regular expression + Given path parameter "name" does not match the regular expression "^[a-zA-Z0-9_.-]+$" + When the request "getQosProfile" is sent + Then the response status code is 400 + And the response header "x-correlator" has same value as the request header "x-correlator" + And the response header "Content-Type" is "application/json" + And the response property "$.status" is 400 + And the response property "$.code" is "INVALID_ARGUMENT" + And the response property "$.message" contains a user friendly text + + @qos_profiles_getQosProfile_400.2_invalid_name_length + Scenario: Path parameter name has an invalid length + Given path parameter "name" has a length not between 3 and 256 + When the request "getQosProfile" is sent + Then the response status code is 400 + And the response header "x-correlator" has same value as the request header "x-correlator" + And the response header "Content-Type" is "application/json" + And the response property "$.status" is 400 + And the response property "$.code" is "INVALID_ARGUMENT" + And the response property "$.message" contains a user friendly text + + # Generic 401 errors + + @qos_profiles_getQosProfile_401.1_no_authorization_header + Scenario: Error response for no header "Authorization" + Given the header "Authorization" is not sent + And the request body is set to a valid request body + When the request "getQosProfile" is sent + Then the response status code is 401 + And the response header "x-correlator" has same value as the request header "x-correlator" + And the response header "Content-Type" is "application/json" + And the response property "$.status" is 401 + And the response property "$.code" is "UNAUTHENTICATED" + And the response property "$.message" contains a user friendly text + + # In this case both codes could make sense depending on whether the access token can be refreshed or not + @qos_profiles_getQosProfile_401.2_expired_access_token + Scenario: Error response for expired access token + Given the header "Authorization" is set to an expired access token + And the request body is set to a valid request body + When the request "getQosProfile" is sent + Then the response status code is 401 + And the response header "x-correlator" has same value as the request header "x-correlator" + And the response header "Content-Type" is "application/json" + And the response property "$.status" is 401 + And the response property "$.code" is "UNAUTHENTICATED" or "AUTHENTICATION_REQUIRED" + And the response property "$.message" contains a user friendly text + + @qos_profiles_getQosProfile_401.3_invalid_access_token + Scenario: Error response for invalid access token + Given the header "Authorization" is set to an invalid access token + And the request body is set to a valid request body + When the request "getQosProfile" is sent + Then the response status code is 401 + And the response header "x-correlator" has same value as the request header "x-correlator" + And the response header "Content-Type" is "application/json" + And the response property "$.status" is 401 + And the response property "$.code" is "UNAUTHENTICATED" + And the response property "$.message" contains a user friendly text + + # Errors 404 + + @qos_profiles_getQosProfile_404.1_not_found + Scenario: name of a no existing QoS profile + Given the path parameter "name" is set to a random string compliant with the pattern + When the request "getQosProfile" is sent + Then the response status code is 404 + And the response header "x-correlator" has same value as the request header "x-correlator" + And the response header "Content-Type" is "application/json" + And the response property "$.status" is 404 + And the response property "$.code" is "NOT_FOUND" + And the response property "$.message" contains a user friendly text \ No newline at end of file diff --git a/code/Test_definitions/qos-profiles-retrieveQoSProfiles.feature b/code/Test_definitions/qos-profiles-retrieveQoSProfiles.feature new file mode 100644 index 0000000000..b9ffd9ab12 --- /dev/null +++ b/code/Test_definitions/qos-profiles-retrieveQoSProfiles.feature @@ -0,0 +1,221 @@ +Feature: CAMARA QoS Profiles API, v0.11.0 - Operation retrieveQoSProfiles + # Input to be provided by the implementation to the tester + # + # Implementation indications: + # * apiRoot: API root of the server URL + # * List of device identifier types which are not supported, among: phoneNumber, ipv4Address, ipv6Address. + # For this version, CAMARA does not allow the use of networkAccessIdentifier, so it is considered by default as not supported. + # + # Testing assets: + # * The name of an existing QoS profile + # * If some QoS Profile is restricted for some devices, provide the QoS profile name and device + # * A device object identifying a device commercialized by the implementation for which the service is not applicable, if any + + # References to OAS spec schemas refer to schemas specifies in qos-profiles.yaml, version 0.11.0 + + Background: Common retrieveQoSProfiles setup + Given an environment at "apiRoot" + And the resource "qos-profiles/v0.11/retrieve-qos-profiles" + And the header "Content-Type" is set to "application/json" + And the header "Authorization" is set to a valid access token + And the header "x-correlator" is set to a UUID value + # Properties not explicitly overwitten in the Scenarios can take any values compliant with the schema + And the request body is set by default to a request body compliant with the schema at "/components/schemas/QosProfileDeviceRequest" + + # Success scenarios + + @qos_profiles_retrieveQoSProfiles_01_generic_success_scenario + Scenario: Common validations for any sucess scenario + # Valid testing device and default request body compliant with the schema + Given a request body compliant with the schema at "/components/schemas/QosProfileDeviceRequest" + When the request "retrieveQoSProfiles" is sent + Then the response status code is 200 + And the response header "Content-Type" is "application/json" + And the response header "x-correlator" has same value as the request header "x-correlator" + And each item of the the response array, if any, complies with the OAS schema at "/components/schemas/QosProfile" + # TBC: Add additional constraints, such as max* properties must be higher than min* equivalent properties, etc + + @qos_profiles_retrieveQoSProfiles_02_filter_by_name_only + Scenario: Retrieve QoS profiles only by name + Given the request body property "$.name" is set to an existing QoS profile name + And the request body properties "$.device" and "$.status" are not included + When the request "retrieveQoSProfiles" is sent + Then the response status code is 200 + And the response header "Content-Type" is "application/json" + And the response header "x-correlator" has same value as the request header "x-correlator" + And the response array has only one item which complies with the OAS schema at "/components/schemas/QosProfile" + And the response property "$[0].name" value is equal to the request body property "$.name" + + @qos_profiles_retrieveQoSProfiles_03_filter_by_status_only + Scenario Outline: Retrieve QoS profiles only by status + Given the request body property "$.status" is set to the value + And the request body properties "$.device" and "$.name" are not included + When the request "retrieveQoSProfiles" is sent + Then the response status code is 200 + And the response header "Content-Type" is "application/json" + And the response header "x-correlator" has same value as the request header "x-correlator" + And each item of the the response array, if any, complies with the OAS schema at "/components/schemas/QosProfile" + And each item of the the response array, if any, has property "$[*].status" equal to + + Examples: + | status | + | ACTIVE | + | INACTIVE | + | DEPRECATED | + + @qos_profiles_retrieveQoSProfiles_04_return_restricted_profiles + Scenario: Return QoS Profiles restricted to certain devices + Given that implementation has QoS Profiles restricted to certain devices + And a device suitable for the restricted QoS Profiles is provided in the request body or identified by the access token + And the request body properties "$.name" and "$.status" are not included + When the request "retrieveQoSProfiles" is sent + Then the response status code is 200 + And the response header "Content-Type" is "application/json" + And the response header "x-correlator" has same value as the request header "x-correlator" + And each item of the the response array complies with the OAS schema at "/components/schemas/QosProfile" + And the restricted QoS Profiles is returned in the response + + @qos_profiles_retrieveQoSProfiles_05_not_return_restricted_profiles + Scenario: Do not return restricted QoS Profiles restricted to certain devices + Given that implementation has QoS Profiles restricted to certain devices + And no device is provided in the request body or identified by the access token + And the request body properties "$.name" and "$.status" are not included + When the request "retrieveQoSProfiles" is sent + Then the response status code is 200 + And the response header "Content-Type" is "application/json" + And the response header "x-correlator" has same value as the request header "x-correlator" + And each item of the the response array complies with the OAS schema at "/components/schemas/QosProfile" + And no restricted QoS Profile is included in the response + + @qos_profiles_retrieveQoSProfiles_06_device_qos_profiles_not_found + Scenario: Device has not QoS profiles associated + Given a device for which the service is not applicable, provided in the request body or identified by the access token + When the request "retrieveQoSProfiles" is sent + Then the response status code is 200 + And the response header "Content-Type" is "application/json" + And the response header "x-correlator" has same value as the request header "x-correlator" + And the response body is [] + + # Errors 400 + + @qos_profiles_retrieveQoSProfiles_400.1_schema_not_compliant + Scenario: Invalid Argument. Generic Syntax Exception + Given the request body is set to any value which is not compliant with the schema at "/components/schemas/QosProfileDeviceRequest" + When the request "retrieveQoSProfiles" is sent + Then the response status code is 400 + And the response header "x-correlator" has same value as the request header "x-correlator" + And the response header "Content-Type" is "application/json" + And the response property "$.code" is "INVALID_ARGUMENT" + And the response property "$.message" contains a user friendly text + + @qos_profiles_retrieveQoSProfiles_400.2_no_request_body + Scenario: Missing request body + Given the request body is not included + When the request "retrieveQoSProfiles" is sent + Then the response status code is 400 + And the response header "x-correlator" has same value as the request header "x-correlator" + And the response header "Content-Type" is "application/json" + And the response property "$.status" is 400 + And the response property "$.code" is "INVALID_ARGUMENT" + And the response property "$.message" contains a user friendly text + + @qos_profiles_retrieveQoSProfiles_400.3_device_identifiers_not_schema_compliant + # Test every type of identifier even if not supported by the implementation + Scenario Outline: Some device identifier value does not comply with the schema + Given the request body property "" does not comply with the OAS schema at "" + When the request "retrieveQoSProfiles" is sent + Then the response status code is 400 + And the response header "x-correlator" has same value as the request header "x-correlator" + And the response header "Content-Type" is "application/json" + And the response property "$.status" is 400 + And the response property "$.code" is "INVALID_ARGUMENT" + And the response property "$.message" contains a user friendly text + + Examples: + | device_identifier | oas_spec_schema | + | $.device.phoneNumber | /components/schemas/PhoneNumber | + | $.device.ipv4Address | /components/schemas/NetworkAccessIdentifier | + | $.device.ipv6Address | /components/schemas/DeviceIpv4Addr | + | $.device.networkIdentifier | /components/schemas/DeviceIpv6Address | + + # Generic 401 errors + + @qos_profiles_retrieveQoSProfiles_401.1_no_authorization_header + Scenario: Error response for no header "Authorization" + Given the header "Authorization" is not sent + And the request body is set to a valid request body + When the request "retrieveQoSProfiles" is sent + Then the response status code is 401 + And the response header "x-correlator" has same value as the request header "x-correlator" + And the response header "Content-Type" is "application/json" + And the response property "$.status" is 401 + And the response property "$.code" is "UNAUTHENTICATED" + And the response property "$.message" contains a user friendly text + + # In this case both codes could make sense depending on whether the access token can be refreshed or not + @qos_profiles_retrieveQoSProfiles_401.2_expired_access_token + Scenario: Error response for expired access token + Given the header "Authorization" is set to an expired access token + And the request body is set to a valid request body + When the request "retrieveQoSProfiles" is sent + Then the response status code is 401 + And the response header "x-correlator" has same value as the request header "x-correlator" + And the response header "Content-Type" is "application/json" + And the response property "$.status" is 401 + And the response property "$.code" is "UNAUTHENTICATED" or "AUTHENTICATION_REQUIRED" + And the response property "$.message" contains a user friendly text + + @qos_profiles_retrieveQoSProfiles_401.3_invalid_access_token + Scenario: Error response for invalid access token + Given the header "Authorization" is set to an invalid access token + And the request body is set to a valid request body + When the request "retrieveQoSProfiles" is sent + Then the response status code is 401 + And the response header "x-correlator" has same value as the request header "x-correlator" + And the response header "Content-Type" is "application/json" + And the response property "$.status" is 401 + And the response property "$.code" is "UNAUTHENTICATED" + And the response property "$.message" contains a user friendly text + + # Errors 403 + + @qos_profiles_retrieveQoSProfiles_403.1_device_token_mismatch + Scenario: Inconsistent access token context for the device + # To test this, a token have to be obtained for a different device + Given the request body property "$.device" is set to a valid testing device + And the header "Authorization" is set to a valid access token emitted for a different device + When the request "retrieveQoSProfiles" is sent + Then the response status code is 403 + And the response header "x-correlator" has same value as the request header "x-correlator" + And the response header "Content-Type" is "application/json" + And the response property "$.status" is 403 + And the response property "$.code" is "INVALID_TOKEN_CONTEXT" + And the response property "$.message" contains a user friendly text + + # Errors 422 + + # UNSUPPORTED_DEVICE_IDENTIFIERS is in the Commonalities guidelines (document) but it is not yet considered in the API spec + @qos_profiles_retrieveQoSProfiles_422.1_device_identifiers_unsupported + Scenario: None of the provided device identifiers is supported by the implementation + Given that some type of device identifiers are not supported by the implementation + And the request body property "$.device" only includes device identifiers not supported by the implementation + When the request "retrieveQoSProfiles" is sent + Then the response status code is 422 + And the response header "x-correlator" has same value as the request header "x-correlator" + And the response header "Content-Type" is "application/json" + And the response property "$.status" is 422 + And the response property "$.code" is "UNPROCESSABLE_ENTITY" + And the response property "$.message" contains a user friendly text + + # This scenario is under discussion + @qos_profiles_retrieveQoSProfiles_422.2_device_identifiers_mismatch + Scenario: Device identifiers mismatch + Given that al least 2 types of device identifiers are supported by the implementation + And the request body property "$.device" includes several identifiers, each of them identifying a valid but different device + When the request "retrieveQoSProfiles" is sent + Then the response status code is 422 + And the response header "x-correlator" has same value as the request header "x-correlator" + And the response header "Content-Type" is "application/json" + And the response property "$.status" is 422 + And the response property "$.code" is "DEVICE_IDENTIFIERS_MISMATCH" + And the response property "$.message" contains a user friendly text diff --git a/code/Test_definitions/quality-on-demand-createSession.feature b/code/Test_definitions/quality-on-demand-createSession.feature new file mode 100644 index 0000000000..7f2ae3e148 --- /dev/null +++ b/code/Test_definitions/quality-on-demand-createSession.feature @@ -0,0 +1,371 @@ +Feature: CAMARA Quality On Demand API, v0.11.0 - Operation createSession + # Input to be provided by the implementation to the tester + # + # Implementation indications: + # * apiRoot: API root of the server URL + # * List of device identifier types which are not supported, among: phoneNumber, ipv4Address, ipv6Address. + # For this version, CAMARA does not allow the use of networkAccessIdentifier, so it is considered by default as not supported. + # * List of application server ip formats which are not supported, among ipv4 and ipv6. + # + # Testing assets: + # * A device object applicable for Quality On Demand service. + # * A device object identifying a device commercialized by the implementation for which the service is not applicable, if any. + # + # References to OAS spec schemas refer to schemas specifies in quality-on-demand.yaml, version 0.11.0 + + Background: Common createSession setup + Given an environment at "apiRoot" + And the resource "/quality-on-demand/v0.11/sessions" + And the header "Content-Type" is set to "application/json" + And the header "Authorization" is set to a valid access token + And the header "x-correlator" is set to a UUID value + # Properties not explicitly overwitten in the Scenarios can take any values compliant with the schema + And the request body is set by default to a request body compliant with the schema at "/components/schemas/CreateSession" + + # Success scenarios + + @quality_on_demand_createSession_01_generic_success_scenario + Scenario: Common validations for any sucess scenario + # Valid testing device and default request body compliant with the schema + Given a valid testing device supported by the service, identified by the token or provided in the request body + And the request body property "$.applicationServer" is set to a valid application server + And the request property "$.qosProfile" is set to a valid QoS Profile as returned by QoS Profiles API + And the request body property "$.duration" is set to a valid duration for the selected QoS profile + When the request "createSession" is sent + Then the response status code is 201 + And the response header "Content-Type" is "application/json" + And the response header "x-correlator" has same value as the request header "x-correlator" + # The response has to comply with the generic response schema which is part of the spec + And the response body complies with the OAS schema at "/components/schemas/SessionInfo" + # Additionally any success response has to comply with some constraints beyond the schema compliance + And the response property "$.device" exists only if provided in the request body and with the same value + And the response property "$.applicationServer" has the same value as in the request body + And the response property "$.qosProfile" has the same value as in the request body + And the response property "$.devicePorts" exists only if provided in the request body and with the same value + And the response property "$.applicationServerPorts" exists only if provided in the request body and with the same value + And the response property "$.sink" exists only if provided in the request body and with the same value + # sinkCredentials not explicitly mentioned to be returned if present, as this is debatible for security concerns + And the response property "$.startedAt" exists only if "$.qosStatus" is "AVAILABLE" and the value is in the past + And the response property "$.expiresAt" exists only if "$.qosStatus" is not "REQUESTED" and the value is later than "$.startedAt" + And the response property "$.statusInfo" exists only if "$.qosStatus" is "UNAVAILABLE" + + @quality_on_demand_createSession_02_event_notification + Scenario: Events are received after a QoS session change if sink is provided + # Valid testing device and default request body compliant with the schema + Given a valid testing device supported by the service, identified by the token or provided in the request body + And the request body property "$.applicationServer" is set to a valid application server + And the request property "$.qosProfile" is set to a valid QoS Profile as returned by QoS Profiles API + And the request body property "$.duration" is set to a valid duration for the selected QoS profile + And the request property "$.sink" is set to a URL when events can be monitored + And the request property "$.sinkCredentials.credentialType" is set to "ACCESSTOKEN" + And the request property "$.sinkCredentials.accessTokenType" is set to "bearer" + And the request property "$.sinkCredentials.accessToken" is set to a valid access token accepted by the events receiver + When the request "createSession" is sent + Then the response status code is 201 + # There is no specific limit defined for the process to end + And an event is received at the address of the request property "$.sink" + And the event header "Authorization" is set to "Bearer: " + the value of the request property "$.sinkCredentials.accessToken" + And the event header "Content-Type" is set to "application/cloudevents+json" + And the event body complies with the OAS schema at "/components/schemas/EventQosStatusChanged" + # Additionally any event body has to comply with some constraints beyond the schema compliance + And the event body property "$.id" is unique + And the event body property "$.type" is set to "org.camaraproject.qod.v0.qos-status-changed" + And the event body property "$.data.sessionId" has the same value as createSession response property "$.sessionId" + And the event body property "$.data.qosStatus" is "AVAILABLE" or "UNAVAILABLE" + And the event body property "$.data.statusInfo" exists only if "$.data.qosStatus" is "UNAVAILABLE" + + @quality_on_demand_createSession_03_3_legged_missing_device + Scenario: Device is not returned if not included in the creation + # Valid testing device and default request body compliant with the schema + Given the header "Authorization" is set to a valid 3-legged access token associated to a valid testing device supported by the service + And the request property "$.device" is not included + When the request "createSession" is sent + Then the response status code is 201 + And the response header "Content-Type" is "application/json" + And the response header "x-correlator" has same value as the request header "x-correlator" + And the response body complies with the OAS schema at "/components/schemas/SessionInfo" + And the response property "$.device" does not exist + + # Errors 400 + + @quality_on_demand_createSession_400.1_schema_not_compliant + Scenario: Invalid Argument. Generic Syntax Exception + Given the request body is set to any value which is not compliant with the schema at "/components/schemas/CreateSession" + When the request "createSession" is sent + Then the response status code is 400 + And the response header "x-correlator" has same value as the request header "x-correlator" + And the response header "Content-Type" is "application/json" + And the response property "$.status" is 400 + And the response property "$.code" is "INVALID_ARGUMENT" + And the response property "$.message" contains a user friendly text + + @quality_on_demand_createSession_400.2_no_request_body + Scenario: Missing request body + Given the request body is not included + When the request "createSession" is sent + Then the response status code is 400 + And the response header "x-correlator" has same value as the request header "x-correlator" + And the response header "Content-Type" is "application/json" + And the response property "$.status" is 400 + And the response property "$.code" is "INVALID_ARGUMENT" + And the response property "$.message" contains a user friendly text + + @quality_on_demand_createSession_400.3_empty_request_body + Scenario: Empty object as request body + Given the request body is set to {} + When the request "createSession" is sent + Then the response status code is 400 + And the response header "x-correlator" has same value as the request header "x-correlator" + And the response header "Content-Type" is "application/json" + And the response property "$.status" is 400 + And the response property "$.code" is "INVALID_ARGUMENT" + And the response property "$.message" contains a user friendly text + + @quality_on_demand_createSession_400.4_empty_property + Scenario Outline: Error response for empty property in request body + Given the request body property "" is set to {} + When the request "createSession" is sent + Then the response status code is 400 + And the response header "x-correlator" has same value as the request header "x-correlator" + And the response header "Content-Type" is "application/json" + And the response property "$.status" is 400 + And the response property "$.code" is "INVALID_ARGUMENT" + And the response property "$.message" contains a user friendly text + + Examples: + | required_property | + | $.device | + | $.applicationServer | + | $.devicePorts | + | $.applicationServerPorts | + | $.sinkCredential | + + @quality_on_demand_createSession_400.5_device_identifiers_not_schema_compliant + # Test every type of identifier even if not supported by the implementation + Scenario Outline: Some device identifier value does not comply with the schema + Given the request body property "" does not comply with the OAS schema at "" + When the request "createSession" is sent + Then the response status code is 400 + And the response header "x-correlator" has same value as the request header "x-correlator" + And the response header "Content-Type" is "application/json" + And the response property "$.status" is 400 + And the response property "$.code" is "INVALID_ARGUMENT" + And the response property "$.message" contains a user friendly text + + Examples: + | device_identifier | oas_spec_schema | + | $.device.phoneNumber | /components/schemas/PhoneNumber | + | $.device.ipv4Address | /components/schemas/NetworkAccessIdentifier | + | $.device.ipv6Address | /components/schemas/DeviceIpv4Addr | + | $.device.networkIdentifier | /components/schemas/DeviceIpv6Address | + + # The maximum is considered in the schema so a generic schema validator may fail and generate a 400 INVALID_ARGUMENT without further distinction, + # and both could be accepted + @quality_on_demand_createSession_400.6_out_of_range_port + Scenario Outline: Out of range port + Given the request body property "" is set to a value not between between 0 and 65536 + When the request "createSession" is sent + Then the response status code is 400 + And the response header "x-correlator" has same value as the request header "x-correlator" + And the response header "Content-Type" is "application/json" + And the response property "$.status" is 400 + And the response property "$.code" is "OUT_OF_RANGE" or "INVALID_ARGUMENT" + And the response property "$.message" contains a user friendly text + + Examples: + | port_property | + | $.device.ipv4Address.publicPort | + | $.devicePorts.ranges.from | + | $.devicePorts.ranges.to | + | $.devicePorts.ports[*] | + | $.applicationServerPorts.ranges.from | + | $.applicationServerPorts.ranges.to | + | $.applicationServerPorts.ports[*] | + + # PLAIN and REFRESHTOKEN are considered in the schema so INVALID_ARGUMENT is not expected + @quality_on_demand_createSession_400.7_invalid_sink_credential + Scenario Outline: Invalid credential + Given the request body property "$.sinkCredential.credentialType" is set to "" + When the request "createSession" is sent + Then the response status code is 400 + And the response header "x-correlator" has same value as the request header "x-correlator" + And the response header "Content-Type" is "application/json" + And the response property "$.status" is 400 + And the response property "$.code" is "INVALID_CREDENTIAL" + And the response property "$.message" contains a user friendly text + + Examples: + | unsupported_credential_type | + | PLAIN | + | REFRESHTOKEN | + + # Only "bearer" is considered in the schema so a generic schema validator may fail and generate a 400 INVALID_ARGUMENT without further distinction, + # and both could be accepted + @quality_on_demand_createSession_400.8_sink_credential_invalid_token + Scenario: Invalid token + Given the request body property "$.sinkCredential.accessTokenType" is set to a value other than "bearer" + When the request "createSession" is sent + Then the response status code is 400 + And the response header "x-correlator" has same value as the request header "x-correlator" + And the response header "Content-Type" is "application/json" + And the response property "$.status" is 400 + And the response property "$.code" is "INVALID_TOKEN" or "INVALID_ARGUMENT" + And the response property "$.message" contains a user friendly text + + @quality_on_demand_createSession_400.9_non_existent_qos_profile + Scenario: Error response for invalid qos profile in request body + Given the request body property "qosProfile" is set to a non existent qos Profile + When the request "createSession" is sent + Then the response status code is 400 + And the response header "x-correlator" has same value as the request header "x-correlator" + And the response header "Content-Type" is "application/json" + And the response property "$.status" is 400 + And the response property "$.code" is "INVALID_ARGUMENT" + And the response property "$.message" contains a user friendly text + + @quality_on_demand_createSession_400.10_invalid_duration + Scenario: Error response when duration is not valid for selected qos profile + Given the request body property "duration" is set to an invalid duration for the selected qosProfile + When the request "createSession" is sent + Then the response status code is 400 + And the response header "x-correlator" has same value as the request header "x-correlator" + And the response header "Content-Type" is "application/json" + And the response property "$.status" is 400 + And the response property "$.code" is "INVALID_ARGUMENT" + And the response property "$.message" contains a user friendly text + + # Generic 401 errors + + @quality_on_demand_createSession_401.1_no_authorization_header + Scenario: Error response for no header "Authorization" + Given the header "Authorization" is not sent + And the request body is set to a valid request body + When the request "createSession" is sent + Then the response status code is 401 + And the response header "x-correlator" has same value as the request header "x-correlator" + And the response header "Content-Type" is "application/json" + And the response property "$.status" is 401 + And the response property "$.code" is "UNAUTHENTICATED" + And the response property "$.message" contains a user friendly text + + # In this case both codes could make sense depending on whether the access token can be refreshed or not + @quality_on_demand_createSession_401.2_expired_access_token + Scenario: Error response for expired access token + Given the header "Authorization" is set to an expired access token + And the request body is set to a valid request body + When the request "createSession" is sent + Then the response status code is 401 + And the response header "x-correlator" has same value as the request header "x-correlator" + And the response header "Content-Type" is "application/json" + And the response property "$.status" is 401 + And the response property "$.code" is "UNAUTHENTICATED" or "AUTHENTICATION_REQUIRED" + And the response property "$.message" contains a user friendly text + + @quality_on_demand_createSession_401.3_invalid_access_token + Scenario: Error response for invalid access token + Given the header "Authorization" is set to an invalid access token + And the request body is set to a valid request body + When the request "createSession" is sent + Then the response status code is 401 + And the response header "x-correlator" has same value as the request header "x-correlator" + And the response header "Content-Type" is "application/json" + And the response property "$.status" is 401 + And the response property "$.code" is "UNAUTHENTICATED" + And the response property "$.message" contains a user friendly text + + # Errors 403 + + @quality_on_demand_createSession_403.1_device_token_mismatch + Scenario: Inconsistent access token context for the device + # To test this, a token have to be obtained for a different device + Given the request body property "$.device" is set to a valid testing device + And the header "Authorization" is set to a valid access token emitted for a different device + When the request "createSession" is sent + Then the response status code is 403 + And the response header "x-correlator" has same value as the request header "x-correlator" + And the response header "Content-Type" is "application/json" + And the response property "$.status" is 403 + And the response property "$.code" is "INVALID_TOKEN_CONTEXT" + And the response property "$.message" contains a user friendly text + + # Errors 404 + + # Typically with a 2-legged access token + @quality_on_demand_createSession_404.1_device_not_found + Scenario: Some identifier cannot be matched to a device + Given that the device cannot be identified from the access token + And the request body property "$.device" is compliant with the request body schema but does not identify a valid device + When the request "createSession" is sent + Then the response status code is 404 + And the response header "x-correlator" has same value as the request header "x-correlator" + And the response header "Content-Type" is "application/json" + And the response property "$.status" is 404 + And the response property "$.code" is "DEVICE_NOT_FOUND" + And the response property "$.message" contains a user friendly text + + # Errors 409 + + @quality_on_demand_createSession_409.1_session_conflict + Scenario: Session in conflict + Given a valid testing device supported by the service, identified by the token or provided in the request body + And a QoD session already exists for that device + When the request "createSession" is sent + Then the response status code is 409 + And the response header "x-correlator" has same value as the request header "x-correlator" + And the response header "Content-Type" is "application/json" + And the response property "$.status" is 409 + And the response property "$.code" is "CONFLICT" + And the response property "$.message" contains a user friendly text + + # Errors 422 + + # UNSUPPORTED_DEVICE_IDENTIFIERS is in the Commonalities guidelines (document) but it is not yet considered in the API spec + @quality_on_demand_createSession_422.1_device_identifiers_unsupported + Scenario: None of the provided device identifiers is supported by the implementation + Given that some type of device identifiers are not supported by the implementation + And the request body property "$.device" only includes device identifiers not supported by the implementation + When the request "createSession" is sent + Then the response status code is 422 + And the response header "x-correlator" has same value as the request header "x-correlator" + And the response header "Content-Type" is "application/json" + And the response property "$.status" is 422 + And the response property "$.code" is "UNSUPPORTED_DEVICE_IDENTIFIERS" + And the response property "$.message" contains a user friendly text + + # This scenario is under discussion + @quality_on_demand_createSession_422.2_device_identifiers_mismatch + Scenario: Device identifiers mismatch + Given that al least 2 types of device identifiers are supported by the implementation + And the request body property "$.device" includes several identifiers, each of them identifying a valid but different device + When the request "createSession" is sent + Then the response status code is 422 + And the response header "x-correlator" has same value as the request header "x-correlator" + And the response header "Content-Type" is "application/json" + And the response property "$.status" is 422 + And the response property "$.code" is "DEVICE_IDENTIFIERS_MISMATCH" + And the response property "$.message" contains a user friendly text + + @quality_on_demand_createSession_422.3_device_not_supported + Scenario: Service not available for the device + Given that service is not supported for all devices commercialized by the operator + And the service is not applicable for the device identified by the token or provided in the request body + When the request "createSession" is sent + Then the response status code is 422 + And the response header "x-correlator" has same value as the request header "x-correlator" + And the response header "Content-Type" is "application/json" + And the response property "$.status" is 422 + And the response property "$.code" is "DEVICE_NOT_APPLICABLE" + And the response property "$.message" contains a user friendly text + + # Typically with a 2-legged access token + @quality_on_demand_createSession_422.4_unidentifiable_device + Scenario: Device not included and cannot be deducted from the access token + Given the header "Authorization" is set to a valid access which does not identifiy a single device + And the request body property "$.device" is not included + When the request "createSession" is sent + Then the response status code is 422 + And the response header "x-correlator" has same value as the request header "x-correlator" + And the response header "Content-Type" is "application/json" + And the response property "$.status" is 422 + And the response property "$.code" is "UNIDENTIFIABLE_DEVICE" + And the response property "$.message" contains a user friendly text diff --git a/code/Test_definitions/quality-on-demand-deleteSession.feature b/code/Test_definitions/quality-on-demand-deleteSession.feature new file mode 100644 index 0000000000..b3fc26a1f1 --- /dev/null +++ b/code/Test_definitions/quality-on-demand-deleteSession.feature @@ -0,0 +1,126 @@ +Feature: CAMARA Quality On Demand API, v0.11.0 - Operation deleteSession + # Input to be provided by the implementation to the tester + # + # Implementation indications: + # * apiRoot: API root of the server URL + # + # Testing assets: + # * The sessionId of an existing session. + # * The sessionId of an existing session with status "AVAILABLE", and with provided values for "sink" and "sinkCredential". + # * The sessionId of an existing session with status "UNAVAILABLE", and with provided values for "sink" and "sinkCredential". + # + # References to OAS spec schemas refer to schemas specifies in quality-on-demand.yaml, version 0.11.0 + + Background: Common deleteSession setup + Given an environment at "apiRoot" + And the resource "/quality_on_demand/v0.11/sessions/{sessionId}" + # Unless indicated otherwise the QoD provisioning must be created by the same API client given in the access token + And the header "Authorization" is set to a valid access token + And the header "x-correlator" is set to a UUID value + And the path parameter "sessionId" is set by default to a existing QoS session sessionId + + # Success scenarios + + @quality_on_demand_deleteSession_01_delete_existing_qod_session + Scenario: Delete an existing QoD session + Given an existing QoS session created by operation createSession + And the path parameter "sessionId" is set to the value for that QoS session + When the request "deleteSession" is sent + Then the response status code is 204 + And the response header "Content-Type" is "application/json" + And the response header "x-correlator" has same value as the request header "x-correlator" + + @quality_on_demand_deleteSession_02_event_notification + Scenario: Event is received if the session was AVAILABLE and sink was provided + Given an existing QoS session created by operation createProvisioning with provided values for "sink" and "sinkCredential", and with status "AVAILABLE" + And the path parameter "sessionId" is set to the value for that QoS session + When the request "deleteSession" is sent + Then the response status code is 204 + And an event is received at the address of the "$.sink" provided for createSession + And the event header "Authorization" is set to "Bearer: " + the value of the property "$.sinkCredentials.accessToken" provided for createSession + And the event header "Content-Type" is set to "application/cloudevents+json" + And the event body complies with the OAS schema at "/components/schemas/EventQosStatusChanged" + # Additionally any event body has to comply with some constraints beyond the schema compliance + And the event body property "$.id" is unique + And the event body property "$.type" is set to "org.camaraproject.qod.v0.qos-status-changed" + And the event body property "$.data.sessionId" as returned for createProvisioning + And the event body property "$.data.qosStatus" is "UNAVAILABLE" + And the event body property "$.data.statusInfo" is "DELETE_REQUESTED" + + # Errors 400 + + # 400 errors are not expected for this operation unless the implementation validates the format of sessionId + # 404 NOT_FOUND is an alternative if path parameter format is not validated + @quality_on_demand_deleteSession_400.1_invalid_session_id + Scenario: Invalid Argument. Generic Syntax Exception + Given the path parameter "sessionId" has not a UUID format + When the request "deleteSession" is sent + Then the response status code is 400 + And the response header "x-correlator" has same value as the request header "x-correlator" + And the response header "Content-Type" is "application/json" + And the response property "$.code" is "INVALID_ARGUMENT" + And the response property "$.message" contains a user friendly text + + # Generic 401 errors + + @quality_on_demand_deleteSession_401.1_no_authorization_header + Scenario: Error response for no header "Authorization" + Given the header "Authorization" is not sent + When the request "deleteSession" is sent + Then the response status code is 401 + And the response header "x-correlator" has same value as the request header "x-correlator" + And the response header "Content-Type" is "application/json" + And the response property "$.status" is 401 + And the response property "$.code" is "UNAUTHENTICATED" + And the response property "$.message" contains a user friendly text + + # In this case both codes could make sense depending on whether the access token can be refreshed or not + @quality_on_demand_deleteSession_401.2_expired_access_token + Scenario: Error response for expired access token + Given the header "Authorization" is set to an expired access token + When the request "deleteSession" is sent + Then the response status code is 401 + And the response header "x-correlator" has same value as the request header "x-correlator" + And the response header "Content-Type" is "application/json" + And the response property "$.status" is 401 + And the response property "$.code" is "UNAUTHENTICATED" or "AUTHENTICATION_REQUIRED" + And the response property "$.message" contains a user friendly text + + @quality_on_demand_deleteSession_401.3_invalid_access_token + Scenario: Error response for invalid access token + Given the header "Authorization" is set to an invalid access token + When the request "deleteSession" is sent + Then the response status code is 401 + And the response header "x-correlator" has same value as the request header "x-correlator" + And the response header "Content-Type" is "application/json" + And the response property "$.status" is 401 + And the response property "$.code" is "UNAUTHENTICATED" + And the response property "$.message" contains a user friendly text + + # Errors 403 + + # TBD which code is more appropriate for this scenario + @quality_on_demand_deleteSession_403.1_session_token_mismatch + Scenario: QoS session not created by the API client given in the access token + # To test this, a token have to be obtained for a different client + Given the header "Authorization" is set to a valid access token emitted to a client which did not created the QoS session + When the request "deleteSession" is sent + Then the response status code is 403 + And the response header "x-correlator" has same value as the request header "x-correlator" + And the response header "Content-Type" is "application/json" + And the response property "$.status" is 403 + And the response property "$.code" is "PERMISSION_DENIED" or "INVALID_TOKEN_CONTEXT" + And the response property "$.message" contains a user friendly text + + # Errors 404 + + @quality_on_demand_deleteSession_404.1_not_found + Scenario: sessionId of a no existing QoS session + Given the path parameter "sessionId" is set to a random UUID + When the request "deleteSession" is sent + Then the response status code is 404 + And the response header "x-correlator" has same value as the request header "x-correlator" + And the response header "Content-Type" is "application/json" + And the response property "$.status" is 404 + And the response property "$.code" is "NOT_FOUND" + And the response property "$.message" contains a user friendly text diff --git a/code/Test_definitions/quality-on-demand-extendQosSessionDuration.feature b/code/Test_definitions/quality-on-demand-extendQosSessionDuration.feature new file mode 100644 index 0000000000..80ab9a1bba --- /dev/null +++ b/code/Test_definitions/quality-on-demand-extendQosSessionDuration.feature @@ -0,0 +1,187 @@ +Feature: CAMARA Quality On Demand API, v0.11.0 - Operation extendQosSessionDuration + # Input to be provided by the implementation to the tester + # + # Implementation indications: + # * apiRoot: API root of the server URL + # + # Testing assets: + # * The sessionId of an existing session with qosStatus "AVAILABLE" + # * The sessionId of an existing session with qosStatus "UNAVAILABLE" + # + # References to OAS spec schemas refer to schemas specifies in quality-on-demand.yaml, version 0.11.0 + + Background: Common extendQosSessionDuration setup + Given an environment at "apiRoot" + And the resource "/quality-on-demand/v0.11/sessions/{sessionId}/extend" + And the header "Content-Type" is set to "application/json" + And the header "Authorization" is set to a valid access token + And the header "x-correlator" is set to a UUID value + # Properties not explicitly overwitten in the Scenarios can take any values compliant with the schema + And the request body is set by default to a request body compliant with the schema at "/components/schemas/ExtendSessionDuration" + And the path parameter "sessionId" is set by default to a existing QoS session sessionId + + # Success scenarios + + @quality_on_demand_extendQosSessionDuration_01_generic_success_scenario + Scenario: Common validations for any sucess scenario + # Valid testing device and default request body compliant with the schema + Given an existing QoS session created by operation createSession with qosStatus "AVAILABLE" + And the path parameter "sessionId" is set to the value for that QoS session + And the request body property "$.requestedAdditionalDuration" is set to a valid additional session duration + When the request "extendQosSessionDuration" is sent + Then the response status code is 200 + And the response header "Content-Type" is "application/json" + And the response header "x-correlator" has same value as the request header "x-correlator" + # The response has to comply with the generic response schema which is part of the spec + And the response body complies with the OAS schema at "/components/schemas/SessionInfo" + And the response property "$.device" exists only if provided for createSession and with the same value + And the response property "$.applicationServer" has the same value as in the request body + And the response property "$.qosProfile" has the value provided for createSession + And the response property "$.devicePorts" exists only if provided for createSession and with the same value + And the response property "$.applicationServerPorts" exists only if provided for createSession and with the same value + And the response property "$.sink" exists only if provided for createSession and with the same value + # Implementations may not grant the requested extensions but they duration can not be reduced in any case + And the response property "$.duration" is not lower than request property "$.requestedAdditionalDuration" + + @quality_on_demand_extendQosSessionDuration_02_exceed_max_duration + Scenario: Extended duration cannot exceed the maxDuration for the QoS profile + # Valid testing device and default request body compliant with the schema + Given an existing QoS session created by operation createSession with qosStatus "AVAILABLE" + And the path parameter "sessionId" is set to the value for that QoS session + And the "maxDuration" for the QoS profile of the session as returned by "qos-profiles" API + And the request body property "$.requestedAdditionalDuration" is set to a value that added to the existing QoS session "duration" exceeds the "maxDuration" for the QoS Profile + When the request "extendQosSessionDuration" is sent + Then the response status code is 200 + And the response header "Content-Type" is "application/json" + And the response header "x-correlator" has same value as the request header "x-correlator" + # The response has to comply with the generic response schema which is part of the spec + And the response body complies with the OAS schema at "/components/schemas/SessionInfo" + And the response property "$.duration" does not exceed the "maxDuration" for the QoS Profile + + # Errors 400 + + @quality_on_demand_extendQosSessionDuration_400.1_schema_not_compliant + Scenario: Invalid Argument. Generic Syntax Exception + Given the request body is set to any value which is not compliant with the schema at "/components/schemas/extendQosSessionDuration" + When the request "extendQosSessionDuration" is sent + Then the response status code is 400 + And the response header "x-correlator" has same value as the request header "x-correlator" + And the response header "Content-Type" is "application/json" + And the response property "$.code" is "INVALID_ARGUMENT" + And the response property "$.message" contains a user friendly text + + # 404 NOT_FOUND is an alternative if path parameter format is not validated + @quality_on_demand_extendQosSessionDuration_400.2_invalid_session_id + Scenario: Invalid sessionId + Given the path parameter "sessionId" has not a UUID format + When the request "extendQosSessionDuration" is sent + Then the response status code is 400 + And the response header "x-correlator" has same value as the request header "x-correlator" + And the response header "Content-Type" is "application/json" + And the response property "$.code" is "INVALID_ARGUMENT" + And the response property "$.message" contains a user friendly text + + @quality_on_demand_extendQosSessionDuration_400.3_no_request_body + Scenario: Missing request body + Given the request body is not included + When the request "extendQosSessionDuration" is sent + Then the response status code is 400 + And the response header "x-correlator" has same value as the request header "x-correlator" + And the response header "Content-Type" is "application/json" + And the response property "$.status" is 400 + And the response property "$.code" is "INVALID_ARGUMENT" + And the response property "$.message" contains a user friendly text + + @quality_on_demand_extendQosSessionDuration_400.4_empty_request_body + Scenario: Empty object as request body + Given the request body is set to {} + When the request "extendQosSessionDuration" is sent + Then the response status code is 400 + And the response header "x-correlator" has same value as the request header "x-correlator" + And the response header "Content-Type" is "application/json" + And the response property "$.status" is 400 + And the response property "$.code" is "INVALID_ARGUMENT" + And the response property "$.message" contains a user friendly text + + # Generic 401 errors + + @quality_on_demand_extendQosSessionDuration_401.1_no_authorization_header + Scenario: Error response for no header "Authorization" + Given the header "Authorization" is not sent + And the request body is set to a valid request body + When the request "extendQosSessionDuration" is sent + Then the response status code is 401 + And the response header "x-correlator" has same value as the request header "x-correlator" + And the response header "Content-Type" is "application/json" + And the response property "$.status" is 401 + And the response property "$.code" is "UNAUTHENTICATED" + And the response property "$.message" contains a user friendly text + + # In this case both codes could make sense depending on whether the access token can be refreshed or not + @quality_on_demand_extendQosSessionDuration_401.2_expired_access_token + Scenario: Error response for expired access token + Given the header "Authorization" is set to an expired access token + And the request body is set to a valid request body + When the request "extendQosSessionDuration" is sent + Then the response status code is 401 + And the response header "x-correlator" has same value as the request header "x-correlator" + And the response header "Content-Type" is "application/json" + And the response property "$.status" is 401 + And the response property "$.code" is "UNAUTHENTICATED" or "AUTHENTICATION_REQUIRED" + And the response property "$.message" contains a user friendly text + + @quality_on_demand_extendQosSessionDuration_401.3_invalid_access_token + Scenario: Error response for invalid access token + Given the header "Authorization" is set to an invalid access token + And the request body is set to a valid request body + When the request "extendQosSessionDuration" is sent + Then the response status code is 401 + And the response header "x-correlator" has same value as the request header "x-correlator" + And the response header "Content-Type" is "application/json" + And the response property "$.status" is 401 + And the response property "$.code" is "UNAUTHENTICATED" + And the response property "$.message" contains a user friendly text + + # Errors 403 + + # TBD which code is more appropriate for this scenario + @quality_on_demand_extendQosSessionDuration_403.1_session_token_mismatch + Scenario: QoS session not created by the API client given in the access token + # To test this, a token have to be obtained for a different client + Given the header "Authorization" is set to a valid access token emitted to a client which did not created the QoS session + When the request "extendQosSessionDuration" is sent + Then the response status code is 403 + And the response header "x-correlator" has same value as the request header "x-correlator" + And the response header "Content-Type" is "application/json" + And the response property "$.status" is 403 + And the response property "$.code" is "PERMISSION_DENIED" or "INVALID_TOKEN_CONTEXT" + And the response property "$.message" contains a user friendly text + + # Errors 404 + + @quality_on_demand_extendQosSessionDuration_404.1_not_found + Scenario: sessionId of a no existing QoS session + Given the path parameter "sessionId" is set to a random UUID + And the request body is set to a valid request body + When the request "extendQosSessionDuration" is sent + Then the response status code is 404 + And the response header "x-correlator" has same value as the request header "x-correlator" + And the response header "Content-Type" is "application/json" + And the response property "$.status" is 404 + And the response property "$.code" is "NOT_FOUND" + And the response property "$.message" contains a user friendly text + + # Errors 409 + + @quality_on_demand_extendQosSessionDuration_409.1_session_not_available + Scenario: Extending duration for session with qosStatus not available + Given an existing QoS session with qosStatus not "AVAILABLE" + And the path parameter "sessionId" is set to the value for that QoS session + And the request body is set to a valid request body + When the request "extendQosSessionDuration" is sent + Then the response status code is 409 + And the response header "x-correlator" has same value as the request header "x-correlator" + And the response header "Content-Type" is "application/json" + And the response property "$.status" is 409 + And the response property "$.code" is "QUALITY_ON_DEMAND.SESSION_EXTENSION_NOT_ALLOWED" + And the response property "$.message" contains a user friendly text diff --git a/code/Test_definitions/quality-on-demand-getSession.feature b/code/Test_definitions/quality-on-demand-getSession.feature new file mode 100644 index 0000000000..1a305242c7 --- /dev/null +++ b/code/Test_definitions/quality-on-demand-getSession.feature @@ -0,0 +1,132 @@ +Feature: CAMARA Quality On Demand API, v0.11.0 - Operation getSession + # Input to be provided by the implementation to the tester + # + # Implementation indications: + # * apiRoot: API root of the server URL + # + # Testing assets: + # * The sessionId of an existing QoS session, and the request properties used for createSession + # + # References to OAS spec schemas refer to schemas specifies in quality-on-demand.yaml, version 0.11.0 + + Background: Common getSession setup + Given an environment at "apiRoot" + And the resource "/quality-on-demand/v0.11/sessions/{sessionId}" + # Unless indicated otherwise the session must be created by the same API client given in the access token + And the header "Authorization" is set to a valid access token + And the header "x-correlator" is set to a UUID value + And the path parameter "sessionId" is set by default to a existing QoS session sessionId + + # Success scenarios + + @quality_on_demand_getSession_01_get_existing_session + Scenario: Get an existing QoD session by sessionId + Given an existing QoS session created by operation createSession + And the path parameter "sessionId" is set to the value for that QoS session + When the request "getSession" is sent + Then the response status code is 200 + And the response header "Content-Type" is "application/json" + And the response header "x-correlator" has same value as the request header "x-correlator" + # The response has to comply with the generic response schema which is part of the spec + And the response body complies with the OAS schema at "/components/schemas/SessionInfo" + # Additionally any success response has to comply with some constraints beyond the schema compliance + And the response property "$.device" exists only if provided for createSession and with the same value + And the response property "$.applicationServer" has the same value as in the request body + And the response property "$.qosProfile" has the value provided for createSession + And the response property "$.devicePorts" exists only if provided for createSession and with the same value + And the response property "$.applicationServerPorts" exists only if provided for createSession and with the same value + And the response property "$.sink" exists only if provided for createSession and with the same value + # sinkCredentials not explicitly mentioned to be returned if present, as this is debatible for security concerns + And the response property "$.startedAt" exists only if "$.qosStatus" is "AVAILABLE" and the value is in the past + And the response property "$.expiresAt" exists only if "$.qosStatus" is not "REQUESTED" and the value is later than "$.startedAt" + And the response property "$.statusInfo" exists only if "$.qosStatus" is "UNAVAILABLE" + + @quality_on_demand_getSession_02_get_recent_unvailable + Scenario: QOS Session becoming "UNAVAILABLE" is not released for at least 360 seconds + Given an existing QoS session deleted in the last 360 seconds + And the path parameter "sessionId" is set to the value for that QoS session + When the request "getSession" is sent + Then the response status code is 200 + And the response header "Content-Type" is "application/json" + And the response header "x-correlator" has same value as the request header "x-correlator" + And the response body complies with the OAS schema at "/components/schemas/SessionInfo" + And the response property "$.status" is "UNAVAILABLE" + + # Errors 400 + + # 400 errors are not expected for this operation unless the implementation validates the format of sessionId + # 404 NOT_FOUND is an alternative if path parameter format is not validated + @quality_on_demand_getSession_400.1_invalid_session_id + Scenario: Invalid Argument. Generic Syntax Exception + Given the path parameter "sessionId" has not a UUID format + When the request "getSession" is sent + Then the response status code is 400 + And the response header "x-correlator" has same value as the request header "x-correlator" + And the response header "Content-Type" is "application/json" + And the response property "$.status" is 400 + And the response property "$.code" is "INVALID_ARGUMENT" + And the response property "$.message" contains a user friendly text + + # Generic 401 errors + + @quality_on_demand_getSession_401.1_no_authorization_header + Scenario: Error response for no header "Authorization" + Given the header "Authorization" is not sent + When the request "getSession" is sent + Then the response status code is 401 + And the response header "x-correlator" has same value as the request header "x-correlator" + And the response header "Content-Type" is "application/json" + And the response property "$.status" is 401 + And the response property "$.code" is "UNAUTHENTICATED" + And the response property "$.message" contains a user friendly text + + # In this case both codes could make sense depending on whether the access token can be refreshed or not + @quality_on_demand_getSession_401.2_expired_access_token + Scenario: Error response for expired access token + Given the header "Authorization" is set to an expired access token + When the request "getSession" is sent + Then the response status code is 401 + And the response header "x-correlator" has same value as the request header "x-correlator" + And the response header "Content-Type" is "application/json" + And the response property "$.status" is 401 + And the response property "$.code" is "UNAUTHENTICATED" or "AUTHENTICATION_REQUIRED" + And the response property "$.message" contains a user friendly text + + @quality_on_demand_getSession_401.3_invalid_access_token + Scenario: Error response for invalid access token + Given the header "Authorization" is set to an invalid access token + When the request "getSession" is sent + Then the response status code is 401 + And the response header "x-correlator" has same value as the request header "x-correlator" + And the response header "Content-Type" is "application/json" + And the response property "$.status" is 401 + And the response property "$.code" is "UNAUTHENTICATED" + And the response property "$.message" contains a user friendly text + + # Errors 403 + + # TBD which code is more appropriate for this scenario + @quality_on_demand_getSession_403.1_session_token_mismatch + Scenario: QoS session not created by the API client given in the access token + # To test this, a token have to be obtained for a different client + Given the header "Authorization" is set to a valid access token emitted to a client which did not created the QoS session + When the request "getSession" is sent + Then the response status code is 403 + And the response header "x-correlator" has same value as the request header "x-correlator" + And the response header "Content-Type" is "application/json" + And the response property "$.status" is 403 + And the response property "$.code" is "PERMISSION_DENIED" or "INVALID_TOKEN_CONTEXT" + And the response property "$.message" contains a user friendly text + + # Errors 404 + + @quality_on_demand_getSession_404.1_not_found + Scenario: sessionId of a no existing QoS session + Given the path parameter "sessionId" is set to a random UUID + When the request "getSession" is sent + Then the response status code is 404 + And the response header "x-correlator" has same value as the request header "x-correlator" + And the response header "Content-Type" is "application/json" + And the response property "$.status" is 404 + And the response property "$.code" is "NOT_FOUND" + And the response property "$.message" contains a user friendly text diff --git a/code/Test_definitions/quality-on-demand-retrieveSessionsByDevice.feature b/code/Test_definitions/quality-on-demand-retrieveSessionsByDevice.feature new file mode 100644 index 0000000000..71b71927b0 --- /dev/null +++ b/code/Test_definitions/quality-on-demand-retrieveSessionsByDevice.feature @@ -0,0 +1,256 @@ +Feature: CAMARA Quality On Demand API, v0.11.0 - Operation retrieveSessionsByDevice + # Input to be provided by the implementation to the tester + # + # Implementation indications: + # * apiRoot: API root of the server URL + # * List of device identifier types which are not supported, among: phoneNumber, ipv4Address, ipv6Address. + # For this version, CAMARA does not allow the use of networkAccessIdentifier, so it is considered by default as not supported. + # + # Testing assets: + # * A device object applicable for Quality On Demand service with an QoS Sessions associated, and the request properties used for createSession + # * A device object applicable for Quality On Demand service with NO QoS Sessions associated + # * A device object identifying a device commercialized by the implementation for which the service is not applicable, if any. + # + # References to OAS spec schemas refer to schemas specifies in quality-on-demand.yaml, version 0.11.0 + + Background: Common retrieveSessionsByDevice setup + Given an environment at "apiRoot" + And the resource "/quality-on-demand/v0.11/retrieve-sessions" + And the header "Content-Type" is set to "application/json" + And the header "Authorization" is set to a valid access token + And the header "x-correlator" is set to a UUID value + # Properties not explicitly overwitten in the Scenarios can take any values compliant with the schema + And the request body is set by default to a request body compliant with the schema at "/components/schemas/RetrieveSessionsInput" + + # Success scenarios + + @quality_on_demand_retrieveSessionsByDevice_01_get_existing_session_by_device + Scenario: Get an existing QoD session by device + Given a valid testing device supported by the service, identified by the token or provided in the request body, with QoS active sessions associated + When the request "retrieveSessionsByDevice" is sent + Then the response status code is 200 + And the response header "Content-Type" is "application/json" + And the response header "x-correlator" has same value as the request header "x-correlator" + # The response has to comply with the generic response schema which is part of the spec + And the response body complies with the OAS schema at "/components/schemas/RetrieveSessionsOutput" + # Additionally any success response has to comply with some constraints beyond the schema compliance + And the response property "$.device" exists only if provided for createSession and with the same value + And the response property "$.applicationServer" has the same value as in the request body + And the response property "$.qosProfile" has the value provided for createSession + And the response property "$.devicePorts" exists only if provided for createSession and with the same value + And the response property "$.applicationServerPorts" exists only if provided for createSession and with the same value + And the response property "$.sink" exists only if provided for createSession and with the same value + # sinkCredentials not explicitly mentioned to be returned if present, as this is debatible for security concerns + And the response property "$.startedAt" exists only if "$.qosStatus" is "AVAILABLE" and the value is in the past + And the response property "$.expiresAt" exists only if "$.qosStatus" is not "REQUESTED" and the value is later than "$.startedAt" + And the response property "$.statusInfo" exists only if "$.qosStatus" is "UNAVAILABLE" + + @quality_on_demand_retrieveSessionsByDevice_02_sessions_not_found + Scenario: Device has not QoS sessions + # Valid testing device and default request body compliant with the schema + Given a valid testing device supported by the service, identified by the token or provided in the request body with no QoS active sessions associated + When the request "retrieveSessionsByDevice" is sent + Then the response status code is 200 + And the response header "Content-Type" is "application/json" + And the response header "x-correlator" has same value as the request header "x-correlator" + And the response body is [] + + # Errors 400 + + @quality_on_demand_retrieveSessionsByDevice_400.1_schema_not_compliant + Scenario: Invalid Argument. Generic Syntax Exception + Given the request body is set to any value which is not compliant with the schema at "/components/schemas/retrieveSessionsByDevice" + When the request "retrieveSessionsByDevice" is sent + Then the response status code is 400 + And the response header "x-correlator" has same value as the request header "x-correlator" + And the response header "Content-Type" is "application/json" + And the response property "$.status" is 400 + And the response property "$.code" is "INVALID_ARGUMENT" + And the response property "$.message" contains a user friendly text + + @quality_on_demand_retrieveSessionsByDevice_400.2_no_request_body + Scenario: Missing request body + Given the request body is not included + When the request "retrieveSessionsByDevice" is sent + Then the response status code is 400 + And the response header "x-correlator" has same value as the request header "x-correlator" + And the response header "Content-Type" is "application/json" + And the response property "$.status" is 400 + And the response property "$.code" is "INVALID_ARGUMENT" + And the response property "$.message" contains a user friendly text + + @quality_on_demand_retrieveSessionsByDevice_400.3_empty_request_body + Scenario: Empty object as request body + Given the request body is set to {} + When the request "retrieveSessionsByDevice" is sent + Then the response status code is 400 + And the response header "x-correlator" has same value as the request header "x-correlator" + And the response header "Content-Type" is "application/json" + And the response property "$.status" is 400 + And the response property "$.code" is "INVALID_ARGUMENT" + And the response property "$.message" contains a user friendly text + + @quality_on_demand_retrieveSessionsByDevice_400.4_empty_device + Scenario: Error response for empty device in request body + Given the request body property "$.device" is set to {} + When the request "retrieveSessionsByDevice" is sent + Then the response status code is 400 + And the response header "x-correlator" has same value as the request header "x-correlator" + And the response header "Content-Type" is "application/json" + And the response property "$.status" is 400 + And the response property "$.code" is "INVALID_ARGUMENT" + And the response property "$.message" contains a user friendly text + + @quality_on_demand_retrieveSessionsByDevice_400.5_device_identifiers_not_schema_compliant + # Test every type of identifier even if not supported by the implementation + Scenario Outline: Some device identifier value does not comply with the schema + Given the request body property "" does not comply with the OAS schema at "" + When the request "retrieveSessionsByDevice" is sent + Then the response status code is 400 + And the response header "x-correlator" has same value as the request header "x-correlator" + And the response header "Content-Type" is "application/json" + And the response property "$.status" is 400 + And the response property "$.code" is "INVALID_ARGUMENT" + And the response property "$.message" contains a user friendly text + + Examples: + | device_identifier | oas_spec_schema | + | $.device.phoneNumber | /components/schemas/PhoneNumber | + | $.device.ipv4Address | /components/schemas/NetworkAccessIdentifier | + | $.device.ipv6Address | /components/schemas/DeviceIpv4Addr | + | $.device.networkIdentifier | /components/schemas/DeviceIpv6Address | + + # The maximum is considered in the schema so a generic schema validator may fail and generate a 400 INVALID_ARGUMENT without further distinction, + # and both could be accepted + @quality_on_demand_retrieveSessionsByDevice_400.6_out_of_range_port + Scenario: Out of range port + Given the request body property "$.device.ipv4Address.publicPort" is set to a value not between between 0 and 65536 + When the request "retrieveSessionsByDevice" is sent + Then the response status code is 400 + And the response header "x-correlator" has same value as the request header "x-correlator" + And the response header "Content-Type" is "application/json" + And the response property "$.status" is 400 + And the response property "$.code" is "OUT_OF_RANGE" or "INVALID_ARGUMENT" + And the response property "$.message" contains a user friendly text + + # Generic 401 errors + + @quality_on_demand_retrieveSessionsByDevice_401.1_no_authorization_header + Scenario: Error response for no header "Authorization" + Given the header "Authorization" is not sent + And the request body is set to a valid request body + When the request "retrieveSessionsByDevice" is sent + Then the response status code is 401 + And the response header "x-correlator" has same value as the request header "x-correlator" + And the response header "Content-Type" is "application/json" + And the response property "$.status" is 401 + And the response property "$.code" is "UNAUTHENTICATED" + And the response property "$.message" contains a user friendly text + + # In this case both codes could make sense depending on whether the access token can be refreshed or not + @quality_on_demand_retrieveSessionsByDevice_401.2_expired_access_token + Scenario: Error response for expired access token + Given the header "Authorization" is set to an expired access token + And the request body is set to a valid request body + When the request "retrieveSessionsByDevice" is sent + Then the response status code is 401 + And the response header "x-correlator" has same value as the request header "x-correlator" + And the response header "Content-Type" is "application/json" + And the response property "$.status" is 401 + And the response property "$.code" is "UNAUTHENTICATED" or "AUTHENTICATION_REQUIRED" + And the response property "$.message" contains a user friendly text + + @quality_on_demand_retrieveSessionsByDevice_401.3_invalid_access_token + Scenario: Error response for invalid access token + Given the header "Authorization" is set to an invalid access token + And the request body is set to a valid request body + When the request "retrieveSessionsByDevice" is sent + Then the response status code is 401 + And the response header "x-correlator" has same value as the request header "x-correlator" + And the response header "Content-Type" is "application/json" + And the response property "$.status" is 401 + And the response property "$.code" is "UNAUTHENTICATED" + And the response property "$.message" contains a user friendly text + + # Errors 403 + + @quality_on_demand_retrieveSessionsByDevice_403.1_device_token_mismatch + Scenario: Inconsistent access token context for the device + # To test this, a token have to be obtained for a different device + Given the request body property "$.device" is set to a valid testing device + And the header "Authorization" is set to a valid access token emitted for a different device + When the request "retrieveSessionsByDevice" is sent + Then the response status code is 403 + And the response header "x-correlator" has same value as the request header "x-correlator" + And the response header "Content-Type" is "application/json" + And the response property "$.status" is 403 + And the response property "$.code" is "INVALID_TOKEN_CONTEXT" + And the response property "$.message" contains a user friendly text + + # Errors 404 + + # Typically with a 2-legged access token + @quality_on_demand_retrieveSessionsByDevice_404.1_device_not_found + Scenario: Some identifier cannot be matched to a device + Given that the device cannot be identified from the access token + And the request body property "$.device" is compliant with the request body schema but does not identify a valid device + When the request "retrieveSessionsByDevice" is sent + Then the response status code is 404 + And the response header "x-correlator" has same value as the request header "x-correlator" + And the response header "Content-Type" is "application/json" + And the response property "$.status" is 404 + And the response property "$.code" is "DEVICE_NOT_FOUND" + And the response property "$.message" contains a user friendly text + + # Errors 422 + + # UNSUPPORTED_DEVICE_IDENTIFIERS is in the Commonalities guidelines (document) but it is not yet considered in the API spec + @quality_on_demand_retrieveSessionsByDevice_422.1_device_identifiers_unsupported + Scenario: None of the provided device identifiers is supported by the implementation + Given that some type of device identifiers are not supported by the implementation + And the request body property "$.device" only includes device identifiers not supported by the implementation + When the request "retrieveSessionsByDevice" is sent + Then the response status code is 422 + And the response header "x-correlator" has same value as the request header "x-correlator" + And the response header "Content-Type" is "application/json" + And the response property "$.status" is 422 + And the response property "$.code" is "UNPROCESSABLE_ENTITY" + And the response property "$.message" contains a user friendly text + + # This scenario is under discussion + @quality_on_demand_retrieveSessionsByDevice_422.2_device_identifiers_mismatch + Scenario: Device identifiers mismatch + Given that al least 2 types of device identifiers are supported by the implementation + And the request body property "$.device" includes several identifiers, each of them identifying a valid but different device + When the request "retrieveSessionsByDevice" is sent + Then the response status code is 422 + And the response header "x-correlator" has same value as the request header "x-correlator" + And the response header "Content-Type" is "application/json" + And the response property "$.status" is 422 + And the response property "$.code" is "DEVICE_IDENTIFIERS_MISMATCH" + And the response property "$.message" contains a user friendly text + + @quality_on_demand_retrieveSessionsByDevice_422.3_device_not_supported + Scenario: Service not available for the device + Given that service is not supported for all devices commercialized by the operator + And the service is not applicable for the device identified by the token or provided in the request body + When the request "retrieveSessionsByDevice" is sent + Then the response status code is 422 + And the response header "x-correlator" has same value as the request header "x-correlator" + And the response header "Content-Type" is "application/json" + And the response property "$.status" is 422 + And the response property "$.code" is "DEVICE_NOT_APPLICABLE" + And the response property "$.message" contains a user friendly text + + # Typically with a 2-legged access token + @quality_on_demand_retrieveSessionsByDevice_422.4_unidentifiable_device + Scenario: Device not included and cannot be deducted from the access token + Given the header "Authorization" is set to a valid access which does not identifiy a single device + And the request body property "$.device" is not included + When the request "retrieveSessionsByDevice" is sent + Then the response status code is 422 + And the response header "x-correlator" has same value as the request header "x-correlator" + And the response header "Content-Type" is "application/json" + And the response property "$.status" is 422 + And the response property "$.code" is "UNIDENTIFIABLE_DEVICE" + And the response property "$.message" contains a user friendly text