From 82a9d2bec1650d574dda930f9103926c27855529 Mon Sep 17 00:00:00 2001 From: hdamker-bot Date: Thu, 7 Aug 2025 11:43:32 +0000 Subject: [PATCH 01/10] admin: migrate to centralized linting workflows Applied via project-admin workflow Repository: DeviceSwap Operation: centralize-linting-workflows --- .github/workflows/pr_validation_caller.yml | 49 ++++++++++++++++++++++ .github/workflows/spectral-oas-caller.yml | 42 +++++++++++++++++++ 2 files changed, 91 insertions(+) create mode 100644 .github/workflows/pr_validation_caller.yml create mode 100644 .github/workflows/spectral-oas-caller.yml diff --git a/.github/workflows/pr_validation_caller.yml b/.github/workflows/pr_validation_caller.yml new file mode 100644 index 0000000..d847f6e --- /dev/null +++ b/.github/workflows/pr_validation_caller.yml @@ -0,0 +1,49 @@ +# ========================================================================================= +# CAMARA Project - Pull Request Validation Workflow Caller +# +# This GitHub Actions workflow is responsible for invoking a reusable PR validation workflow +# from the camaraproject/tooling repository. It is intended to ensure consistent validation +# steps for all PRs targeting the main branch in this repository. +# +# CHANGELOG: +# - 2025-08-01: Initial version for v0 +# +# USAGE: +# - Automatically triggers on pull requests targeting main. +# - Can be triggered manually via workflow_dispatch. +# - Calls by default the reusable workflow at +# camaraproject/tooling/.github/workflows/pr_validation.yml@v0 +# +# DOCUMENTATION: +# see https://github.com/camaraproject/tooling/tree/main/linting/docs +# ========================================================================================= + +name: Caller for PR validation workflow + +on: + # Trigger on pull requests to the main branch only + pull_request: + branches: main + # Enable manual trigger via the GitHub UI + workflow_dispatch: + +concurrency: + group: ${{ github.ref }}-${{ github.workflow }} + cancel-in-progress: true + +permissions: + # Grant necessary write permissions for PRs, contents, and issues + pull-requests: write + contents: write + issues: write + statuses: write + +jobs: + pr_validation: + # Invoke the reusable PR validation workflow from "v0" tag of camaraproject/tooling + uses: camaraproject/tooling/.github/workflows/pr_validation.yml@v0 + secrets: inherit +# Tools configuration from the tooling repository subfolder of /linting/config/ indicated by `configurations` variable +# If needed, you can specify a configuration from another subfolder of camaraproject/tooling/linting/config/ (uncomment below) +# with: +# configurations: api-name diff --git a/.github/workflows/spectral-oas-caller.yml b/.github/workflows/spectral-oas-caller.yml new file mode 100644 index 0000000..05cde3f --- /dev/null +++ b/.github/workflows/spectral-oas-caller.yml @@ -0,0 +1,42 @@ +# ========================================================================================= +# CAMARA Project - Linting OpenAPI Specification with CAMARA Ruleset Caller +# +# This GitHub Actions workflow is responsible for invoking a reusable "Spectral linting with +# CAMARA ruleset" workflow from the camaraproject/tooling repository. It is intended to +# provide more detailed output from Spectral tool (warnings, hints) +# +# CHANGELOG: +# - 2025-08-01: Initial version for v0 +# +# USAGE: +# - Can be triggered manually via workflow_dispatch. +# - Calls by default the reusable workflow at +# camaraproject/tooling/.github/workflows/spectral-oas.yml@v0 +# +# DOCUMENTATION: +# see https://github.com/camaraproject/tooling/tree/main/linting/docs +# ========================================================================================= + +name: Caller for Spectral linting with CAMARA ruleset + +on: + workflow_dispatch: + +concurrency: + group: ${{ github.ref }}-${{ github.workflow }} + cancel-in-progress: true + +permissions: + # Grant necessary write permissions for PRs and issues + pull-requests: write + contents: read + issues: write + +jobs: + spectral: + # Invoke the reusable PR validation workflow from the main branch of camaraproject/tooling + uses: camaraproject/tooling/.github/workflows/spectral-oas.yml@v0 +# Spectral configuration from the tooling repository subfolder of /linting/config/ indicated by `configurations` variable +# If needed, you can specify a configuration from another subfolder of camaraproject/tooling/linting/config/ (uncomment below) +# with: +# configurations: api-name From 30de1f59830ca2aa2b294f1b8504443d531d9aa5 Mon Sep 17 00:00:00 2001 From: Ludovic Robert <30499179+bigludo7@users.noreply.github.com> Date: Wed, 20 Aug 2025 16:27:13 +0200 Subject: [PATCH 02/10] Update device-swap.yaml --- code/API_definitions/device-swap.yaml | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/code/API_definitions/device-swap.yaml b/code/API_definitions/device-swap.yaml index 45f1497..8cad305 100644 --- a/code/API_definitions/device-swap.yaml +++ b/code/API_definitions/device-swap.yaml @@ -6,7 +6,7 @@ info: # Introduction - The Device Swap API performs real-time checks on the last Device Swap event, providing real-time information about whether the SIM card associated with a user's phone number has been transferred to a different physical device. + The Device Swap API performs real-time checks on the last Device Swap event, providing real-time information about whether the SIM card associated with a user's phone number has been transferred to a different physical device. Device Swap information can be invaluable for enhancing security, fraud detection, and ensuring compliance with regulatory requirements in various applications, apart from providing useful information of device upgrade trends in user segments. @@ -22,7 +22,7 @@ info: # API Functionality The Device Swap API provides a programmable interface for developers and other users (capabilities consumers) to request the last date of a device swap performed on the mobile line, or, to check whether a device swap has been performed during a past period. - + The API provides 2 operations: - POST retrieve-date: Provides timestamp of latest device swap, if any, for a given phone number. @@ -63,7 +63,7 @@ info: license: name: Apache 2.0 url: https://www.apache.org/licenses/LICENSE-2.0.html - version: 1.0.0-rc.1 + version: wip x-camara-commonalities: 0.6 externalDocs: @@ -71,7 +71,7 @@ externalDocs: url: https://github.com/camaraproject/DeviceSwap servers: - - url: '{apiRoot}/device-swap/v1rc1' + - url: '{apiRoot}/device-swap/vwip' variables: apiRoot: default: http://localhost:9091 @@ -81,7 +81,7 @@ tags: description: Receive the last date in which the device of the end-user was swapped - name: Check Device Swap description: Validate if the SIM of the end-user has been installed in a different device during a past period -paths: +paths: /retrieve-date: post: tags: @@ -91,9 +91,9 @@ paths: operationId: retrieveDeviceSwapDate security: - openId: - - device-swap + - device-swap - openId: - - device-swap:retrieve-date + - device-swap:retrieve-date parameters: - $ref: '#/components/parameters/x-correlator' requestBody: @@ -145,9 +145,9 @@ paths: operationId: checkDeviceSwap security: - openId: - - device-swap + - device-swap - openId: - - device-swap:check + - device-swap:check parameters: - $ref: '#/components/parameters/x-correlator' requestBody: @@ -268,7 +268,7 @@ components: description: Code given to this error message: type: string - description: Detailed error description + description: Detailed error description responses: Generic400: description: Bad Request @@ -288,8 +288,7 @@ components: message: Client specified an invalid argument, request body or query param. Generic400Check: description: |- - Bad Request - + Bad Request In addition to regular scenario of INVALID_ARGUMENT, other scenarios may exist: - Out of Range. Specific Syntax Exception used when a given field has a pre-defined range or a invalid filter criteria combination is requested ("code": "OUT_OF_RANGE","message": "Client specified an invalid range.") headers: From 7718fdd8afb339e3a3ee7ef43cabde55e82ad5e9 Mon Sep 17 00:00:00 2001 From: Ludovic Robert <30499179+bigludo7@users.noreply.github.com> Date: Wed, 20 Aug 2025 16:27:57 +0200 Subject: [PATCH 03/10] Update checkDeviceSwap.feature --- code/Test_definitions/checkDeviceSwap.feature | 407 +++++++++--------- 1 file changed, 202 insertions(+), 205 deletions(-) diff --git a/code/Test_definitions/checkDeviceSwap.feature b/code/Test_definitions/checkDeviceSwap.feature index 144223b..d315f2f 100644 --- a/code/Test_definitions/checkDeviceSwap.feature +++ b/code/Test_definitions/checkDeviceSwap.feature @@ -1,213 +1,210 @@ -Feature: CAMARA Device Swap API, 1.0.0-rc.1 - Operation checkDeviceSwap - +Feature: CAMARA Device Swap API, wip - Operation checkDeviceSwap # Input to be provided by the implementation to the tester # # Testing assets: - # - # References to OAS spec schemas refer to schemas specifies in device-swap.yaml, version 1.0.0-rc.1 - # - # Check if device swap has been performed during a past period - - - Background: Common checkDeviceSwap setup - Given the resource "device-swap/v1rc1/check" - 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" complies with the schema at "#/components/schemas/XCorrelator" - And the request body is set by default to a request body compliant with the schema - - # This first scenario serves as a minimum, not testing any specific verificationResult - @check_device_swap_1_generic_success_scenario - Scenario: Common validations for any sucess scenario - Given a valid phone number identified by the token or provided in the request body - When the request "checkDeviceSwap" 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/CheckDeviceSwapInfo" + # * A device object which a device swap occured in the last 240 hours. + # * for additional testing another device without device swapping last 240 hours. + # References to OAS spec schemas refer to schemas specifies in device-swap.yaml + + Background: Common checkDeviceSwap setup + Given the resource "device-swap/vwip/check" + 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" complies with the schema at "#/components/schemas/XCorrelator" + And the request body is set by default to a request body compliant with the schema + + # This first scenario serves as a minimum, not testing any specific verificationResult + @check_device_swap_1_generic_success_scenario + Scenario: Common validations for any sucess scenario + Given a valid phone number identified by the token or provided in the request body + When the request "checkDeviceSwap" 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/CheckDeviceSwapInfo" # Scenarios testing specific situations - @check_device_swap_2_valid_device_swap_no_max_age - Scenario: Check that the response shows that the device has been swapped using default value for maxAge - Given a valid phone number identified by the token or provided in the request body - And the device has been swapped in the last 240 hours - When the request "checkDeviceSwap" is sent - Then the response status code is 200 - And the value of response property "$.swapped" == true - - @check_device_swap_3_valid_device_swap_max_age - Scenario Outline: Check that the response shows that the device has been swapped - maxAge is provided in the request - Given a valid phone number identified by the token or provided in the request body - And the device has been swapped in the last "" - And the request body property "maxAge" is set to a value equal or greater than "" within the allowed range - When the request "checkDeviceSwap" is sent - Then the response status code is 200 - And the value of response property "$.swapped" == true - - Examples: - | hours | - | 260 | - | 120 | - | 24 | - | 12 | - - @check_device_swap_4_more_than_240_hours - Scenario: Check that the response shows that the device has not been swapped when "maxAge" is not set and the last swap was more than 240 (default) hours ago - Given a valid phone number identified by the token or provided in the request body - And the request body property "maxAge" is not setted - And the device has been swapped more than 240 hours ago - When the request "checkDeviceSwap" is sent - Then the response status code is 200 - And the value of response property "$.swapped" == false - - @check_device_swap_5_out_of_max_age - Scenario: Check that the response shows that the device has not been swapped when the last swap was before the maxAge field - Given a valid phone number identified by the token or provided in the request body - And the last swap for this phone number's in the device is known - And the request body property "maxAge" is set to a value lower that the last known device swap - When the request "checkDeviceSwap" is sent - Then the response status code is 200 - And the value of response property "$.swapped" == false - - @check_device_swap_6_no_device_swap_no_max_age - Scenario: Check that the response shows that the device has not been swapped - maxAge is not provided in the request parameter - Given a valid phone number identified by the token or provided in the request body - And the device has never been swapped - And the sim card has been associated with this device for more than 240 hours - When the request "checkDeviceSwap" is sent - Then the response status code is 200 - And the value of response property "$.swapped" == false - - @check_device_swap_7_no_device_swap_with_max_age - Scenario Outline: Check that the response shows that the device has never been swapped - maxAge is provided in the request - Given a valid phone number identified by the token or provided in the request body - And the device has never been swapped - And the sim card has been associated with this device for more than "" hours - And the request body property "maxAge" is set to a value less than "" within the allowed range - When the request "checkDeviceSwap" is sent - Then the response status code is 200 - And the value of response property "$.swapped" == false - - Examples: - | hours | - | 260 | - | 120 | - | 24 | - | 12 | + @check_device_swap_2_valid_device_swap_no_max_age + Scenario: Check that the response shows that the device has been swapped using default value for maxAge + Given a valid phone number identified by the token or provided in the request body + And the device has been swapped in the last 240 hours + When the request "checkDeviceSwap" is sent + Then the response status code is 200 + And the value of response property "$.swapped" == true + + @check_device_swap_3_valid_device_swap_max_age + Scenario Outline: Check that the response shows that the device has been swapped - maxAge is provided in the request + Given a valid phone number identified by the token or provided in the request body + And the device has been swapped in the last "" + And the request body property "maxAge" is set to a value equal or greater than "" within the allowed range + When the request "checkDeviceSwap" is sent + Then the response status code is 200 + And the value of response property "$.swapped" == true + + Examples: + | hours | + | 260 | + | 120 | + | 24 | + | 12 | + + @check_device_swap_4_more_than_240_hours + Scenario: Check that the response shows that the device has not been swapped when "maxAge" is not set and the last swap was more than 240 (default) hours ago + Given a valid phone number identified by the token or provided in the request body + And the request body property "maxAge" is not setted + And the device has been swapped more than 240 hours ago + When the request "checkDeviceSwap" is sent + Then the response status code is 200 + And the value of response property "$.swapped" == false + + @check_device_swap_5_out_of_max_age + Scenario: Check that the response shows that the device has not been swapped when the last swap was before the maxAge field + Given a valid phone number identified by the token or provided in the request body + And the last swap for this phone number's in the device is known + And the request body property "maxAge" is set to a value lower that the last known device swap + When the request "checkDeviceSwap" is sent + Then the response status code is 200 + And the value of response property "$.swapped" == false + + @check_device_swap_6_no_device_swap_no_max_age + Scenario: Check that the response shows that the device has not been swapped - maxAge is not provided in the request parameter + Given a valid phone number identified by the token or provided in the request body + And the device has never been swapped + And the sim card has been associated with this device for more than 240 hours + When the request "checkDeviceSwap" is sent + Then the response status code is 200 + And the value of response property "$.swapped" == false + + @check_device_swap_7_no_device_swap_with_max_age + Scenario Outline: Check that the response shows that the device has never been swapped - maxAge is provided in the request + Given a valid phone number identified by the token or provided in the request body + And the device has never been swapped + And the sim card has been associated with this device for more than "" hours + And the request body property "maxAge" is set to a value less than "" within the allowed range + When the request "checkDeviceSwap" is sent + Then the response status code is 200 + And the value of response property "$.swapped" == false + + Examples: + | hours | + | 260 | + | 120 | + | 24 | + | 12 | # Specific errors - # This scenario may not apply if the Operators's implementation does not allow a valid access token to be issued for a phone number that has never been connected to the network and, therefore, cannot reach the API. - @check_device_swap_8_NoDeviceSwapPhoneNumberNeverConnected - Scenario: Error when the phone number has never connected to the Operators's network so the device has never been activated - Given a valid phone number provided in the request body - And the sim for that device has never been connected to the Operator's network - When the HTTP "POST" request is sent - Then the response status code is 422 - And the response property "$.status" is 422 - And the response property "$.code" is "NOT_SUPPORTED" - And the response property "$.message" contains a user friendly text - - # Test cases related to the device identifier - - @check_device_swap_9_C02_01_phone_number_not_schema_compliant - Scenario: Phone number value does not comply with the schema - Given the header "Authorization" is set to a valid access token which does not identify a single phone number - And the request body property "$.phoneNumber" does not comply with the OAS schema at "/components/schemas/PhoneNumber" - When the HTTP "POST" request is sent - Then the response status code is 400 - 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 - - @check_device_swap_10_C02_02_phone_number_not_found - Scenario: Phone number not found - Given the header "Authorization" is set to a valid access token which does not identify a single phone number - And the request body property "$.phoneNumber" is compliant with the schema but does not identify a valid phone number - When the HTTP "POST" request is sent - Then the response status code is 404 - And the response property "$.status" is 404 - And the response property "$.code" is "IDENTIFIER_NOT_FOUND" - And the response property "$.message" contains a user friendly text - - @check_device_swap_11_C02_03_unnecessary_phone_number - Scenario: Phone number not to be included when it can be deduced from the access token - Given the header "Authorization" is set to a valid access token identifying a phone number - And the request body property "$.phoneNumber" is set to a valid phone number - When the HTTP "POST" request is sent - Then the response status code is 422 - And the response property "$.status" is 422 - And the response property "$.code" is "UNNECESSARY_IDENTIFIER" - And the response property "$.message" contains a user friendly text - - @check_device_swap_12_C02_04_missing_phone_number - Scenario: Phone number not included and cannot be deducted from the access token - Given the header "Authorization" is set to a valid access token which does not identify a single phone number - And the request body property "$.phoneNumber" is not included - When the HTTP "POST" request is sent - Then the response status code is 422 - And the response property "$.status" is 422 - And the response property "$.code" is "MISSING_IDENTIFIER" - And the response property "$.message" contains a user friendly text - - @check_device_swap_13_C02_05_phone_number_not_supported - Scenario: Service not available for the phone number - Given that the service is not available for all phone numbers commercialized by the operator - And a valid phone number, identified by the token or provided in the request body, for which the service is not applicable - When the HTTP "POST" request is sent - Then the response status code is 422 - And the response property "$.status" is 422 - And the response property "$.code" is "SERVICE_NOT_APPLICABLE" - And the response property "$.message" contains a user friendly text - - # Generic 401 errors - - @check_device_swap_401.1_no_authorization_header - Scenario: No Authorization header - Given the header "Authorization" is removed - And the request body is set to a valid request body - When the HTTP "POST" request is sent - Then the response status code is "401" - And the response property "$.status" is 401 - And the response property "$.code" is "UNAUTHENTICATED" - And the response property "$.message" contains a user friendly text - - @check_device_swap_401.2_expired_access_token - Scenario: 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 HTTP "POST" request is sent - Then the response status code is "401" - And the response property "$.status" is 401 - And the response property "$.code" is "UNAUTHENTICATED" - And the response property "$.message" contains a user friendly text - - @check_device_swap_401.3_invalid_access_token - Scenario: 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 HTTP "POST" request is sent - Then the response status code is "401" - And the response property "$.status" is 401 - And the response property "$.code" is "UNAUTHENTICATED" - And the response property "$.message" contains a user friendly text - - # Generic 400 errors - - @check_device_swap_400.2_invalid_max_age - Scenario: Check that the response shows an error when the max age is invalid - Given the request body property "$.maxAge" does not comply with the OAS schema at "/components/schemas/CreateCheckDeviceSwap" - When the HTTP "POST" request is sent - Then the response status code is 400 - 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 - - @check_device_swap_400.3_out_of_range - Scenario: Error when maxAge is out of range - Given the request body property "$.maxAge" is set to a value greater than the allowed range - When the HTTP "POST" request is sent - Then the response status code is 400 - And the response property "$.status" is 400 - And the response property "$.code" is "OUT_OF_RANGE" - And the response property "$.message" contains a user friendly text + # This scenario may not apply if the Operators's implementation does not allow a valid access token to be issued for a phone number that has never been connected to the network and, therefore, cannot reach the API. + @check_device_swap_8_NoDeviceSwapPhoneNumberNeverConnected + Scenario: Error when the phone number has never connected to the Operators's network so the device has never been activated + Given a valid phone number provided in the request body + And the sim for that device has never been connected to the Operator's network + When the HTTP "POST" request is sent + Then the response status code is 422 + And the response property "$.status" is 422 + And the response property "$.code" is "SERVICE_NOT_APPLICABLE" + And the response property "$.message" contains a user friendly text + + # Test cases related to the device identifier + + @check_device_swap_9_C02_01_phone_number_not_schema_compliant + Scenario: Phone number value does not comply with the schema + Given the header "Authorization" is set to a valid access token which does not identify a single phone number + And the request body property "$.phoneNumber" does not comply with the OAS schema at "/components/schemas/PhoneNumber" + When the HTTP "POST" request is sent + Then the response status code is 400 + 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 + + @check_device_swap_10_C02_02_phone_number_not_found + Scenario: Phone number not found + Given the header "Authorization" is set to a valid access token which does not identify a single phone number + And the request body property "$.phoneNumber" is compliant with the schema but does not identify a valid phone number + When the HTTP "POST" request is sent + Then the response status code is 404 + And the response property "$.status" is 404 + And the response property "$.code" is "IDENTIFIER_NOT_FOUND" + And the response property "$.message" contains a user friendly text + + @check_device_swap_11_C02_03_unnecessary_phone_number + Scenario: Phone number not to be included when it can be deduced from the access token + Given the header "Authorization" is set to a valid access token identifying a phone number + And the request body property "$.phoneNumber" is set to a valid phone number + When the HTTP "POST" request is sent + Then the response status code is 422 + And the response property "$.status" is 422 + And the response property "$.code" is "UNNECESSARY_IDENTIFIER" + And the response property "$.message" contains a user friendly text + + @check_device_swap_12_C02_04_missing_phone_number + Scenario: Phone number not included and cannot be deducted from the access token + Given the header "Authorization" is set to a valid access token which does not identify a single phone number + And the request body property "$.phoneNumber" is not included + When the HTTP "POST" request is sent + Then the response status code is 422 + And the response property "$.status" is 422 + And the response property "$.code" is "MISSING_IDENTIFIER" + And the response property "$.message" contains a user friendly text + + @check_device_swap_13_C02_05_phone_number_not_supported + Scenario: Service not available for the phone number + Given that the service is not available for all phone numbers commercialized by the operator + And a valid phone number, identified by the token or provided in the request body, for which the service is not applicable + When the HTTP "POST" request is sent + Then the response status code is 422 + And the response property "$.status" is 422 + And the response property "$.code" is "SERVICE_NOT_APPLICABLE" + And the response property "$.message" contains a user friendly text + + # Generic 401 errors + + @check_device_swap_401.1_no_authorization_header + Scenario: No Authorization header + Given the header "Authorization" is removed + And the request body is set to a valid request body + When the HTTP "POST" request is sent + Then the response status code is "401" + And the response property "$.status" is 401 + And the response property "$.code" is "UNAUTHENTICATED" + And the response property "$.message" contains a user friendly text + + @check_device_swap_401.2_expired_access_token + Scenario: 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 HTTP "POST" request is sent + Then the response status code is "401" + And the response property "$.status" is 401 + And the response property "$.code" is "UNAUTHENTICATED" + And the response property "$.message" contains a user friendly text + + @check_device_swap_401.3_invalid_access_token + Scenario: 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 HTTP "POST" request is sent + Then the response status code is "401" + And the response property "$.status" is 401 + And the response property "$.code" is "UNAUTHENTICATED" + And the response property "$.message" contains a user friendly text + + # Generic 400 errors + + @check_device_swap_400.2_invalid_max_age + Scenario: Check that the response shows an error when the max age is invalid + Given the request body property "$.maxAge" does not comply with the OAS schema at "/components/schemas/CreateCheckDeviceSwap" + When the HTTP "POST" request is sent + Then the response status code is 400 + 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 + + @check_device_swap_400.3_out_of_range + Scenario: Error when maxAge is out of range + Given the request body property "$.maxAge" is set to a value greater than the allowed range + When the HTTP "POST" request is sent + Then the response status code is 400 + And the response property "$.status" is 400 + And the response property "$.code" is "OUT_OF_RANGE" + And the response property "$.message" contains a user friendly text From 821cc5f2149ee87121af4f6fb965eef65726d76d Mon Sep 17 00:00:00 2001 From: Ludovic Robert <30499179+bigludo7@users.noreply.github.com> Date: Wed, 20 Aug 2025 16:28:47 +0200 Subject: [PATCH 04/10] Update and rename retrieveDeviceSwapDate to device-swap-retrieveDeviceSwapDate.feature --- ...device-swap-retrieveDeviceSwapDate.feature | 150 +++++++++++++++++ code/Test_definitions/retrieveDeviceSwapDate | 152 ------------------ 2 files changed, 150 insertions(+), 152 deletions(-) create mode 100644 code/Test_definitions/device-swap-retrieveDeviceSwapDate.feature delete mode 100644 code/Test_definitions/retrieveDeviceSwapDate diff --git a/code/Test_definitions/device-swap-retrieveDeviceSwapDate.feature b/code/Test_definitions/device-swap-retrieveDeviceSwapDate.feature new file mode 100644 index 0000000..2177c93 --- /dev/null +++ b/code/Test_definitions/device-swap-retrieveDeviceSwapDate.feature @@ -0,0 +1,150 @@ +Feature: CAMARA Device Swap API, wip - Operation retrieveDeviceSwapDate + + # Input to be provided by the implementation to the tester + # + # Testing assets: + # * A device object which a device swap occured in the last 240 hours. + # + # References to OAS spec schemas refer to schemas specifies in device-swap.yaml. + + Background: Common retrieveDeviceSwapDate setup + Given the resource "device-swap/vwip/retrieve-date" + 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" complies with the schema at "#/components/schemas/XCorrelator" + And the request body is set by default to a request body compliant with the schema + + # This first scenario serves as a minimum, not testing any specific verificationResult + @retrieve_device_swap_date_1_generic_success_scenario + Scenario: Common validations for any sucess scenario + Given a valid phone number identified by the token or provided in the request body + When the request "retrieveDeviceSwapDate" 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/DeviceSwapInfo" + + # Scenarios testing specific situations + + @retrieve_device_swap_date_2_valid_device_swap + Scenario: Retrieve decive swap date for a valid device swap + Given a valid phone number identified by the token or provided in the request body + And the device has been swapped + When the request "retrieveDeviceSwapDate" is sent + Then the response status code is 200 + And the response property "$.latestDeviceChange" contains a valid timestamp + + # This scenario applies for operators which do not limit the "monitoring history" + @retrieve_device_swap_date_3_no_device_swap_returns_activation_date + Scenario: Response contains the first time that the SIM is installed in the device when it hasn't been swapped + Given a valid phone number identified by the token or provided in the request body + And the device has never been swapped + When the request "retrieveDeviceSwapDate" is sent + Then the response status code is 200 + And the response property "$.latestDeviceChange" contains the timestamp of the first time that the SIM is installed in the device + + # This scenario applies when there is a local regulation with a time limitation on the information that can be returned + @retrieve_device_swap_date_4_no_device_swap_or_activation_date_due_to_legal_constrain + Scenario: Retrieves device swap empty for a valid device swap when exists local regulations + Given a valid phone number identified by the token or provided in the request body + And the last device swap occurred outside the monitoring period allowed by local regulation + When the request "retrieveDeviceSwapDate" is sent + Then the response status code is 200 + And the response property "$.latestDeviceChange" is null + + # Specific errors + + # This test applies if the operator allows to do the request for a sim that has never been connected to the network + @retrieve_device_swap_date_5_not_activated + Scenario: Error device swap date for a non-activated sim + Given a valid phone number provided in the request body + And the sim for that device has never been connected to the Operator's network + When the HTTP "POST" request is sent + Then the response status code is 422 + And the response property "$.status" is 422 + And the response property "$.code" is "SERVICE_NOT_APPLICABLE" + And the response property "$.message" contains a user friendly text + + # Test cases related to the device identifier + + @retrieve_device_swap_date_6_C02_01_phone_number_not_schema_compliant + Scenario: Phone number value does not comply with the schema + Given the header "Authorization" is set to a valid access token which does not identify a single phone number + And the request body property "$.phoneNumber" does not comply with the OAS schema at "/components/schemas/PhoneNumber" + When the HTTP "POST" request is sent + Then the response status code is 400 + 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 + + @retrieve_device_swap_date_7_C02_02_phone_number_not_found + Scenario: Phone number not found + Given the header "Authorization" is set to a valid access token which does not identify a single phone number + And the request body property "$.phoneNumber" is compliant with the schema but does not identify a valid phone number + When the HTTP "POST" request is sent + Then the response status code is 404 + And the response property "$.status" is 404 + And the response property "$.code" is "IDENTIFIER_NOT_FOUND" + And the response property "$.message" contains a user friendly text + + @retrieve_device_swap_date_8_C02_03_unnecessary_phone_number + Scenario: Phone number not to be included when it can be deduced from the access token + Given the header "Authorization" is set to a valid access token identifying a phone number + And the request body property "$.phoneNumber" is set to a valid phone number + When the HTTP "POST" request is sent + Then the response status code is 422 + And the response property "$.status" is 422 + And the response property "$.code" is "UNNECESSARY_IDENTIFIER" + And the response property "$.message" contains a user friendly text + + @check_device_swap_9_C02_04_missing_phone_number + Scenario: Phone number not included and cannot be deducted from the access token + Given the header "Authorization" is set to a valid access token which does not identify a single phone number + And the request body property "$.phoneNumber" is not included + When the HTTP "POST" request is sent + Then the response status code is 422 + And the response property "$.status" is 422 + And the response property "$.code" is "MISSING_IDENTIFIER" + And the response property "$.message" contains a user friendly text + + @retrieve_device_swap_date_10_C02_05_phone_number_not_supported + Scenario: Service not available for the phone number + Given that the service is not available for all phone numbers commercialized by the operator + And a valid phone number, identified by the token or provided in the request body, for which the service is not applicable + When the HTTP "POST" request is sent + Then the response status code is 422 + And the response property "$.status" is 422 + And the response property "$.code" is "SERVICE_NOT_APPLICABLE" + And the response property "$.message" contains a user friendly text + + # Generic 401 errors + + @retrieve_device_swap_date_401.1_no_authorization_header + Scenario: No Authorization header + Given the header "Authorization" is removed + And the request body is set to a valid request body + When the HTTP "POST" request is sent + Then the response status code is 401 + And the response property "$.status" is 401 + And the response property "$.code" is "UNAUTHENTICATED" + And the response property "$.message" contains a user friendly text + + @retrieve_device_swap_date_401.2_expired_access_token + Scenario: 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 HTTP "POST" request is sent + Then the response status code is 401 + And the response property "$.status" is 401 + And the response property "$.code" is "UNAUTHENTICATED" + And the response property "$.message" contains a user friendly text + + @retrieve_device_swap_date_401.3_invalid_access_token + Scenario: 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 HTTP "POST" request is sent + Then the response status code is 401 + And the response property "$.status" is 401 + And the response property "$.code" is "UNAUTHENTICATED" + And the response property "$.message" contains a user friendly text diff --git a/code/Test_definitions/retrieveDeviceSwapDate b/code/Test_definitions/retrieveDeviceSwapDate deleted file mode 100644 index 5073a0a..0000000 --- a/code/Test_definitions/retrieveDeviceSwapDate +++ /dev/null @@ -1,152 +0,0 @@ -Feature: CAMARA Device Swap API, 1.0.0-rc.1 - Operation retrieveDeviceSwapDate - - # Input to be provided by the implementation to the tester - # - # Testing assets: - # - # References to OAS spec schemas refer to schemas specifies in device-swap.yaml, version 1.0.0-rc.1 - # - # Get timestamp of last device swap for a mobile user account provided with phone number. - - Background: Common retrieveDeviceSwapDate setup - Given the resource "device-swap/v1rc1/retrieve-date" - 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" complies with the schema at "#/components/schemas/XCorrelator" - And the request body is set by default to a request body compliant with the schema - - # This first scenario serves as a minimum, not testing any specific verificationResult - @retrieve_device_swap_date_1_generic_success_scenario - Scenario: Common validations for any sucess scenario - Given a valid phone number identified by the token or provided in the request body - When the request "retrieveDeviceSwapDate" 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/DeviceSwapInfo" - - # Scenarios testing specific situations - - @retrieve_device_swap_date_2_valid_device_swap - Scenario: Retrieve decive swap date for a valid device swap - Given a valid phone number identified by the token or provided in the request body - And the device has been swapped - When the request "retrieveDeviceSwapDate" is sent - Then the response status code is 200 - And the response property "$.latestDeviceChange" contains a valid timestamp - - # This scenario applies for operators which do not limit the "monitoring history" - @retrieve_device_swap_date_3_no_device_swap_returns_activation_date - Scenario: Response contains the first time that the SIM is installed in the device when it hasn't been swapped - Given a valid phone number identified by the token or provided in the request body - And the device has never been swapped - When the request "retrieveDeviceSwapDate" is sent - Then the response status code is 200 - And the response property "$.latestDeviceChange" contains the timestamp of the first time that the SIM is installed in the device - - - # This scenario applies when there is a local regulation with a time limitation on the information that can be returned - @retrieve_device_swap_date_4_no_device_swap_or_activation_date_due_to_legal_constrain - Scenario: Retrieves device swap empty for a valid device swap when exists local regulations - Given a valid phone number identified by the token or provided in the request body - And the last device swap occurred outside the monitoring period allowed by local regulation - When the request "retrieveDeviceSwapDate" is sent - Then the response status code is 200 - And the response property "$.latestDeviceChange" is null - - # Specific errors - - # This test applies if the operator allows to do the request for a sim that has never been connected to the network - @retrieve_device_swap_date_5_not_activated - Scenario: Error device swap date for a non-activated sim - Given a valid phone number provided in the request body - And the sim for that device has never been connected to the Operator's network - When the HTTP "POST" request is sent - Then the response status code is 422 - And the response property "$.status" is 422 - And the response property "$.code" is "NOT_SUPPORTED" - And the response property "$.message" contains a user friendly text - - # Test cases related to the device identifier - - @retrieve_device_swap_date_6_C02_01_phone_number_not_schema_compliant - Scenario: Phone number value does not comply with the schema - Given the header "Authorization" is set to a valid access token which does not identify a single phone number - And the request body property "$.phoneNumber" does not comply with the OAS schema at "/components/schemas/PhoneNumber" - When the HTTP "POST" request is sent - Then the response status code is 400 - 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 - - @retrieve_device_swap_date_7_C02_02_phone_number_not_found - Scenario: Phone number not found - Given the header "Authorization" is set to a valid access token which does not identify a single phone number - And the request body property "$.phoneNumber" is compliant with the schema but does not identify a valid phone number - When the HTTP "POST" request is sent - Then the response status code is 404 - And the response property "$.status" is 404 - And the response property "$.code" is "IDENTIFIER_NOT_FOUND" - And the response property "$.message" contains a user friendly text - - @retrieve_device_swap_date_8_C02_03_unnecessary_phone_number - Scenario: Phone number not to be included when it can be deduced from the access token - Given the header "Authorization" is set to a valid access token identifying a phone number - And the request body property "$.phoneNumber" is set to a valid phone number - When the HTTP "POST" request is sent - Then the response status code is 422 - And the response property "$.status" is 422 - And the response property "$.code" is "UNNECESSARY_IDENTIFIER" - And the response property "$.message" contains a user friendly text - - @check_device_swap_9_C02_04_missing_phone_number - Scenario: Phone number not included and cannot be deducted from the access token - Given the header "Authorization" is set to a valid access token which does not identify a single phone number - And the request body property "$.phoneNumber" is not included - When the HTTP "POST" request is sent - Then the response status code is 422 - And the response property "$.status" is 422 - And the response property "$.code" is "MISSING_IDENTIFIER" - And the response property "$.message" contains a user friendly text - - @retrieve_device_swap_date_10_C02_05_phone_number_not_supported - Scenario: Service not available for the phone number - Given that the service is not available for all phone numbers commercialized by the operator - And a valid phone number, identified by the token or provided in the request body, for which the service is not applicable - When the HTTP "POST" request is sent - Then the response status code is 422 - And the response property "$.status" is 422 - And the response property "$.code" is "SERVICE_NOT_APPLICABLE" - And the response property "$.message" contains a user friendly text - - # Generic 401 errors - - @retrieve_device_swap_date_401.1_no_authorization_header - Scenario: No Authorization header - Given the header "Authorization" is removed - And the request body is set to a valid request body - When the HTTP "POST" request is sent - Then the response status code is 401 - And the response property "$.status" is 401 - And the response property "$.code" is "UNAUTHENTICATED" - And the response property "$.message" contains a user friendly text - - @retrieve_device_swap_date_401.2_expired_access_token - Scenario: 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 HTTP "POST" request is sent - Then the response status code is 401 - And the response property "$.status" is 401 - And the response property "$.code" is "UNAUTHENTICATED" - And the response property "$.message" contains a user friendly text - - @retrieve_device_swap_date_401.3_invalid_access_token - Scenario: 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 HTTP "POST" request is sent - Then the response status code is 401 - And the response property "$.status" is 401 - And the response property "$.code" is "UNAUTHENTICATED" - And the response property "$.message" contains a user friendly text From 33d299196f720608922d1ecd383b39454e1cb1b4 Mon Sep 17 00:00:00 2001 From: Ludovic Robert <30499179+bigludo7@users.noreply.github.com> Date: Wed, 20 Aug 2025 16:29:02 +0200 Subject: [PATCH 05/10] Rename checkDeviceSwap.feature to device-swap-checkDeviceSwap.feature --- ...heckDeviceSwap.feature => device-swap-checkDeviceSwap.feature} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename code/Test_definitions/{checkDeviceSwap.feature => device-swap-checkDeviceSwap.feature} (100%) diff --git a/code/Test_definitions/checkDeviceSwap.feature b/code/Test_definitions/device-swap-checkDeviceSwap.feature similarity index 100% rename from code/Test_definitions/checkDeviceSwap.feature rename to code/Test_definitions/device-swap-checkDeviceSwap.feature From cdd8ded0b0ef57ca59586f8f28e82139274025fd Mon Sep 17 00:00:00 2001 From: Ludovic Robert <30499179+bigludo7@users.noreply.github.com> Date: Thu, 21 Aug 2025 09:48:46 +0200 Subject: [PATCH 06/10] Rename device-swap-checkDeviceSwap.feature to checkDeviceSwap.feature --- ...evice-swap-checkDeviceSwap.feature => checkDeviceSwap.feature} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename code/Test_definitions/{device-swap-checkDeviceSwap.feature => checkDeviceSwap.feature} (100%) diff --git a/code/Test_definitions/device-swap-checkDeviceSwap.feature b/code/Test_definitions/checkDeviceSwap.feature similarity index 100% rename from code/Test_definitions/device-swap-checkDeviceSwap.feature rename to code/Test_definitions/checkDeviceSwap.feature From c38759ba8aedc01912cf5b40a4473f6acebe85c9 Mon Sep 17 00:00:00 2001 From: Ludovic Robert <30499179+bigludo7@users.noreply.github.com> Date: Thu, 21 Aug 2025 09:49:07 +0200 Subject: [PATCH 07/10] Rename device-swap-retrieveDeviceSwapDate.feature to retrieveDeviceSwapDate.feature --- ...rieveDeviceSwapDate.feature => retrieveDeviceSwapDate.feature} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename code/Test_definitions/{device-swap-retrieveDeviceSwapDate.feature => retrieveDeviceSwapDate.feature} (100%) diff --git a/code/Test_definitions/device-swap-retrieveDeviceSwapDate.feature b/code/Test_definitions/retrieveDeviceSwapDate.feature similarity index 100% rename from code/Test_definitions/device-swap-retrieveDeviceSwapDate.feature rename to code/Test_definitions/retrieveDeviceSwapDate.feature From a345ce6e9c338c5de1164a3ce9725f53d3dbb360 Mon Sep 17 00:00:00 2001 From: Ludovic Robert <30499179+bigludo7@users.noreply.github.com> Date: Thu, 21 Aug 2025 09:54:56 +0200 Subject: [PATCH 08/10] Update device-swap.yaml --- code/API_definitions/device-swap.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/API_definitions/device-swap.yaml b/code/API_definitions/device-swap.yaml index 8cad305..fcd8155 100644 --- a/code/API_definitions/device-swap.yaml +++ b/code/API_definitions/device-swap.yaml @@ -268,7 +268,7 @@ components: description: Code given to this error message: type: string - description: Detailed error description + description: Detailed error description responses: Generic400: description: Bad Request From d6824e0682919c2f24baff2da97dfed3cacfb05a Mon Sep 17 00:00:00 2001 From: Ludovic Robert <30499179+bigludo7@users.noreply.github.com> Date: Thu, 21 Aug 2025 09:56:06 +0200 Subject: [PATCH 09/10] Update checkDeviceSwap.feature --- code/Test_definitions/checkDeviceSwap.feature | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/code/Test_definitions/checkDeviceSwap.feature b/code/Test_definitions/checkDeviceSwap.feature index 0fc5f06..00f4f00 100644 --- a/code/Test_definitions/checkDeviceSwap.feature +++ b/code/Test_definitions/checkDeviceSwap.feature @@ -3,7 +3,7 @@ Feature: CAMARA Device Swap API, wip - Operation checkDeviceSwap # Input to be provided by the implementation to the tester # # Testing assets: - # * A device object which a device swap occured in the last 240 hours. + # * A device object which a device swap occured in the last 240 hours. # * for additional testing another device without device swapping last 240 hours. # References to OAS spec schemas refer to schemas specifies in device-swap.yaml @@ -43,11 +43,11 @@ Feature: CAMARA Device Swap API, wip - Operation checkDeviceSwap And the value of response property "$.swapped" == true Examples: - | hours | - | 260 | - | 120 | - | 24 | - | 12 | + | hours | + | 260 | + | 120 | + | 24 | + | 12 | @check_device_swap_4_more_than_240_hours Scenario: Check that the response shows that the device has not been swapped when "maxAge" is not set and the last swap was more than 240 (default) hours ago @@ -87,11 +87,11 @@ Feature: CAMARA Device Swap API, wip - Operation checkDeviceSwap And the value of response property "$.swapped" == false Examples: - | hours | - | 260 | - | 120 | - | 24 | - | 12 | + | hours | + | 260 | + | 120 | + | 24 | + | 12 | # Specific errors @@ -208,4 +208,4 @@ Feature: CAMARA Device Swap API, wip - Operation checkDeviceSwap Then the response status code is 400 And the response property "$.status" is 400 And the response property "$.code" is "OUT_OF_RANGE" - And the response property "$.message" contains a user friendly text \ No newline at end of file + And the response property "$.message" contains a user friendly text From 2dfefb12cb7b681b964fc683355d54f18f63f46b Mon Sep 17 00:00:00 2001 From: Ludovic Robert <30499179+bigludo7@users.noreply.github.com> Date: Thu, 21 Aug 2025 09:56:21 +0200 Subject: [PATCH 10/10] Update retrieveDeviceSwapDate.feature --- code/Test_definitions/retrieveDeviceSwapDate.feature | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/code/Test_definitions/retrieveDeviceSwapDate.feature b/code/Test_definitions/retrieveDeviceSwapDate.feature index c06ae58..f3adcc4 100644 --- a/code/Test_definitions/retrieveDeviceSwapDate.feature +++ b/code/Test_definitions/retrieveDeviceSwapDate.feature @@ -3,8 +3,8 @@ Feature: CAMARA Device Swap API, wip - Operation retrieveDeviceSwapDate # Input to be provided by the implementation to the tester # # Testing assets: - # * A device object which a device swap occured in the last 240 hours. - # + # * A device object which a device swap occured in the last 240 hours. + # # References to OAS spec schemas refer to schemas specifies in device-swap.yaml. Background: Common retrieveDeviceSwapDate setup @@ -147,4 +147,4 @@ Feature: CAMARA Device Swap API, wip - Operation retrieveDeviceSwapDate Then the response status code is 401 And the response property "$.status" is 401 And the response property "$.code" is "UNAUTHENTICATED" - And the response property "$.message" contains a user friendly text \ No newline at end of file + And the response property "$.message" contains a user friendly text