diff --git a/.devops/azure-templates/api-tests.yml b/.devops/azure-templates/api-tests.yml new file mode 100644 index 0000000..8809699 --- /dev/null +++ b/.devops/azure-templates/api-tests.yml @@ -0,0 +1,23 @@ +parameters: + # Required + - name: "ENV_FILE" + type: string + - name: "API_TEST_FILE" + type: string + - name: "TEST_FILE_PREFIX" + type: string + - name: 'TEST_DISPLAY_NAME' + type: string +steps: + - script: | + yarn global add newman + displayName: 'Newman installation' + - script: | + newman run ${{ parameters.API_TEST_FILE }} -e ${{ parameters.ENV_FILE }} --ignore-redirects --reporters cli,junit --reporter-junit-export Results/${{ parameters.TEST_FILE_PREFIX }}-api-TEST.xml + displayName: ${{ parameters.TEST_DISPLAY_NAME }} + - task: PublishTestResults@2 + condition: succeededOrFailed() + inputs: + testResultsFormat: 'JUnit' + testResultsFiles: '**/${{ parameters.TEST_FILE_PREFIX }}-api-TEST.xml' + searchFolder: '$(System.DefaultWorkingDirectory)' diff --git a/.devops/code-review-pipelines.yml b/.devops/code-review-pipelines.yml index defe280..69794f1 100644 --- a/.devops/code-review-pipelines.yml +++ b/.devops/code-review-pipelines.yml @@ -62,3 +62,23 @@ stages: displayName: 'Publish Code Coverage on Azure Devops' + - stage: IntegrationTest + dependsOn: [ ] + jobs: + - job: make_integration_test + steps: + - script: cp .env.example .env + displayName: 'Setup env for localhost' + - script: docker compose up -d + displayName: 'Run app with docker compose' + - script: | + timeout 180 bash -c 'while [[ "$(curl -s -o /dev/null -w ''%{http_code}'' localhost:8080/actuator/health/liveness)" != "200" ]]; do sleep 5; done' || exit 1 + displayName: 'Health check' + - template: azure-templates/api-tests.yml + parameters: + TEST_DISPLAY_NAME: "User stats api tests" + ENV_FILE: "api-tests/localhost.postman_environment.json" + API_TEST_FILE: "api-tests/user_stats_tests.postman_collection.json" + TEST_FILE_PREFIX: "wallet-api-test-cards" + + diff --git a/api-tests/localhost.postman_environment.json b/api-tests/localhost.postman_environment.json new file mode 100644 index 0000000..2c357ce --- /dev/null +++ b/api-tests/localhost.postman_environment.json @@ -0,0 +1,51 @@ +{ + "id": "5885a323-53a9-4090-b64d-758417ddc21c", + "name": "user stats [LOCAL]", + "values": [ + { + "key": "HOSTNAME", + "value": "http://localhost:8080", + "type": "default", + "enabled": true + }, + { + "key": "BASE_PATH", + "value": "", + "type": "default", + "enabled": true + }, + { + "key": "USER_ID", + "value": "00000000-0000-0000-0000-000000000000", + "type": "default", + "enabled": true + }, + { + "key": "GUEST_METHOD_LAST_USAGE_DATE", + "value": "2000-01-01T12:00:00.123Z", + "type": "any", + "enabled": true + }, + { + "key": "WALLET_LAST_USAGE_DATE", + "value": "2000-01-02T12:00:00.123Z", + "type": "default", + "enabled": true + }, + { + "key": "WALLET_ID", + "value": "00000000-0000-0000-0000-000000000001", + "type": "default", + "enabled": true + }, + { + "key": "PAYMENT_METHOD_ID", + "value": "00000000-0000-0000-0000-000000000002", + "type": "default", + "enabled": true + } + ], + "_postman_variable_scope": "environment", + "_postman_exported_at": "2024-10-07T10:53:52.414Z", + "_postman_exported_using": "Postman/11.15.0" +} \ No newline at end of file diff --git a/api-tests/user_stats_tests.postman_collection.json b/api-tests/user_stats_tests.postman_collection.json new file mode 100644 index 0000000..a23ae1d --- /dev/null +++ b/api-tests/user_stats_tests.postman_collection.json @@ -0,0 +1,355 @@ +{ + "info": { + "_postman_id": "48e586b0-cbe4-4827-ba52-4f78cedff848", + "name": "eCommerce user stats service", + "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json", + "_exporter_id": "23963988" + }, + "item": [ + { + "name": "Update user last usage [GUEST]", + "event": [ + { + "listen": "prerequest", + "script": { + "exec": [ + "" + ], + "type": "text/javascript", + "packages": {} + } + }, + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"[eCommerce user stats] Update user last usage for GUEST method\", function() {", + " pm.response.to.have.status(201);", + "});" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "x-user-id", + "value": "{{USER_ID}}", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"type\": \"guest\",\n \"paymentMethodId\": \"{{PAYMENT_METHOD_ID}}\",\n \"date\": \"{{GUEST_METHOD_LAST_USAGE_DATE}}\"\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{HOSTNAME}}{{BASE_PATH}}/user/lastPaymentMethodUsed", + "host": [ + "{{HOSTNAME}}{{BASE_PATH}}" + ], + "path": [ + "user", + "lastPaymentMethodUsed" + ] + } + }, + "response": [] + }, + { + "name": "Retrieve user last used method [GUEST]", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"[eCommerce user stats] Retrieve last usage method for guest method\", function() {", + " pm.response.to.have.status(200);", + " const response = pm.response.json();", + " pm.expect(response.type).to.eq(\"guest\")", + " pm.expect(response.paymentMethodId).to.eq(pm.environment.get(\"PAYMENT_METHOD_ID\"))", + " pm.expect(response.walletId).to.be.undefined", + " pm.expect(response.date).to.eq(pm.environment.get(\"GUEST_METHOD_LAST_USAGE_DATE\"))", + "});" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "GET", + "header": [ + { + "key": "x-user-id", + "value": "{{USER_ID}}", + "type": "text" + } + ], + "url": { + "raw": "{{HOSTNAME}}{{BASE_PATH}}/user/lastPaymentMethodUsed", + "host": [ + "{{HOSTNAME}}{{BASE_PATH}}" + ], + "path": [ + "user", + "lastPaymentMethodUsed" + ] + } + }, + "response": [] + }, + { + "name": "Update user last usage [WALLET]", + "event": [ + { + "listen": "prerequest", + "script": { + "exec": [ + "" + ], + "type": "text/javascript", + "packages": {} + } + }, + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"[eCommerce user stats] Update user last usage for WALLET method\", function() {", + " pm.response.to.have.status(201);", + "});" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "x-user-id", + "value": "{{USER_ID}}", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"type\": \"wallet\",\n \"walletId\": \"{{WALLET_ID}}\",\n \"date\": \"{{WALLET_LAST_USAGE_DATE}}\"\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{HOSTNAME}}{{BASE_PATH}}/user/lastPaymentMethodUsed", + "host": [ + "{{HOSTNAME}}{{BASE_PATH}}" + ], + "path": [ + "user", + "lastPaymentMethodUsed" + ] + } + }, + "response": [] + }, + { + "name": "Retrieve user last used method [WALLET]", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"[eCommerce user stats] Retrieve last usage method for WALLET\", function() {", + " pm.response.to.have.status(200);", + " const response = pm.response.json();", + " pm.expect(response.type).to.eq(\"wallet\")", + " pm.expect(response.walletId).to.eq(pm.environment.get(\"WALLET_ID\"))", + " pm.expect(response.paymentMethodId).to.be.undefined", + " pm.expect(response.date).to.eq(pm.environment.get(\"WALLET_LAST_USAGE_DATE\"))", + "});" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "GET", + "header": [ + { + "key": "x-user-id", + "value": "{{USER_ID}}", + "type": "text" + } + ], + "url": { + "raw": "{{HOSTNAME}}{{BASE_PATH}}/user/lastPaymentMethodUsed", + "host": [ + "{{HOSTNAME}}{{BASE_PATH}}" + ], + "path": [ + "user", + "lastPaymentMethodUsed" + ] + } + }, + "response": [] + }, + { + "name": "Get last user method for unknown user", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"[eCommerce user stats] Retrieve last usage information for unknown user should return 404\", function() {", + " pm.response.to.have.status(404);", + " const response = pm.response.json();", + " pm.expect(response.title).to.eq(\"User not found\")", + " pm.expect(response.status).to.eq(404)", + " pm.expect(response.detail).to.eq(\"The input user cannot be found\")", + "});" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "GET", + "header": [ + { + "key": "x-user-id", + "value": "{{$guid}}", + "type": "text" + } + ], + "url": { + "raw": "{{HOSTNAME}}{{BASE_PATH}}/user/lastPaymentMethodUsed", + "host": [ + "{{HOSTNAME}}{{BASE_PATH}}" + ], + "path": [ + "user", + "lastPaymentMethodUsed" + ] + } + }, + "response": [] + }, + { + "name": "Get last user method for invalid user id", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"[eCommerce user stats] Retrieve last usage information for invalid user id should return 400\", function() {", + " pm.response.to.have.status(400);", + " const response = pm.response.json();", + " pm.expect(response.title).to.eq(\"Bad request\")", + " pm.expect(response.status).to.eq(400)", + " pm.expect(response.detail).to.eq(\"Input request is invalid.\")", + "});" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "GET", + "header": [ + { + "key": "x-user-id", + "value": "invalid", + "type": "text" + } + ], + "url": { + "raw": "{{HOSTNAME}}{{BASE_PATH}}/user/lastPaymentMethodUsed", + "host": [ + "{{HOSTNAME}}{{BASE_PATH}}" + ], + "path": [ + "user", + "lastPaymentMethodUsed" + ] + } + }, + "response": [] + }, + { + "name": "Update user with invalid request", + "event": [ + { + "listen": "prerequest", + "script": { + "exec": [ + "" + ], + "type": "text/javascript", + "packages": {} + } + }, + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"[eCommerce user stats] Update user with invalid request should return 400 bad request\", function() {", + " pm.response.to.have.status(400);", + " const response = pm.response.json();", + " pm.expect(response.title).to.eq(\"Bad request\")", + " pm.expect(response.status).to.eq(400)", + " pm.expect(response.detail).to.eq(\"Input request is invalid.\")", + "});" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "x-user-id", + "value": "{{USER_ID}}", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"paymentMethodId\": \"{{PAYMENT_METHOD_ID}}\",\n \"date\": \"{{GUEST_METHOD_LAST_USAGE_DATE}}\"\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{HOSTNAME}}{{BASE_PATH}}/user/lastPaymentMethodUsed", + "host": [ + "{{HOSTNAME}}{{BASE_PATH}}" + ], + "path": [ + "user", + "lastPaymentMethodUsed" + ] + } + }, + "response": [] + } + ] +} \ No newline at end of file