diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml new file mode 100644 index 0000000..a8e88dd --- /dev/null +++ b/.github/workflows/main.yml @@ -0,0 +1,17 @@ +name: Automated API tests using Postman CLI + +on: push + +jobs: + automated-api-tests: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Install Postman CLI + run: | + curl -o- "https://dl-cli.pstmn.io/install/linux64.sh" | sh + - name: Login to Postman CLI + run: postman login --with-api-key ${{ secrets.POSTMAN_API_KEY }} + - name: Run API tests + run: | + postman collection run "53985486-f1b73652-140b-4afd-b365-23ae14516f39" -e "53985486-ae2364ed-fa80-59b7-8e3d-32deca3c4930" --report-events diff --git a/.postman/resources.yaml b/.postman/resources.yaml new file mode 100644 index 0000000..cf5aefc --- /dev/null +++ b/.postman/resources.yaml @@ -0,0 +1,17 @@ +# Use this workspace to collaborate +workspace: + id: "" + +localResources: + specs: + - ../contract/index.yaml + +# Each entry here maps a local resource to one or more corresponding objects in Postman Cloud + +cloudResources: + specs: + ../contract/index.yaml: c45f6ab4-3160-48c3-bafe-117b7a29cb27 + environments: + ../postman/environments/Staging Environment.environment.yaml: 53985486-ae2364ed-fa80-59b7-8e3d-32deca3c4930 + collections: + ../postman/collections/User API Integration Tests: 53985486-f1b73652-140b-4afd-b365-23ae14516f39 diff --git a/.postman/workflows.yaml b/.postman/workflows.yaml new file mode 100644 index 0000000..d1218f9 --- /dev/null +++ b/.postman/workflows.yaml @@ -0,0 +1,11 @@ +# This is a Workflow metadata file for defining entity relationships in this workspace. +# Each workflow defines relations between entities and may include optional behavior/settings. +# The Paths are relative to the .postman directory (avoid absolute paths). +# Keep relation entries explicit and avoid duplicate pairs within the same workflow. +# This file is declarative metadata and does not execute workflows by itself. +workflows: + syncSpecToCollection: + - spec: ../contract/index.yaml + collection: ../postman/collections/User API Integration Tests + options: + syncExamples: false diff --git a/contract/index.yaml b/contract/index.yaml index cb9181a..12cf7b6 100644 --- a/contract/index.yaml +++ b/contract/index.yaml @@ -1,5 +1,6 @@ openapi: 3.0.0 info: + description: for practice title: User API version: 1.0.0 paths: diff --git a/postman/collections/User API Integration Tests/.resources/definition.yaml b/postman/collections/User API Integration Tests/.resources/definition.yaml new file mode 100644 index 0000000..2f34774 --- /dev/null +++ b/postman/collections/User API Integration Tests/.resources/definition.yaml @@ -0,0 +1,11 @@ +$kind: collection +name: User API Integration Tests +description: for practice +auth: + - id: b3545068-2904-4059-8969-97cfdaad729c + type: apikey + name: apikey auth + credentials: + key: X-API-Key + value: "{{apiKey}}" + in: header diff --git a/postman/collections/User API Integration Tests/v1/.resources/definition.yaml b/postman/collections/User API Integration Tests/v1/.resources/definition.yaml new file mode 100644 index 0000000..53d990d --- /dev/null +++ b/postman/collections/User API Integration Tests/v1/.resources/definition.yaml @@ -0,0 +1,2 @@ +$kind: collection +order: 1000 diff --git a/postman/collections/User API Integration Tests/v1/users/.resources/definition.yaml b/postman/collections/User API Integration Tests/v1/users/.resources/definition.yaml new file mode 100644 index 0000000..53d990d --- /dev/null +++ b/postman/collections/User API Integration Tests/v1/users/.resources/definition.yaml @@ -0,0 +1,2 @@ +$kind: collection +order: 1000 diff --git a/postman/collections/User API Integration Tests/v1/users/login/.resources/Log in a user.resources/examples/Error occurred.example.yaml b/postman/collections/User API Integration Tests/v1/users/login/.resources/Log in a user.resources/examples/Error occurred.example.yaml new file mode 100644 index 0000000..c77403e --- /dev/null +++ b/postman/collections/User API Integration Tests/v1/users/login/.resources/Log in a user.resources/examples/Error occurred.example.yaml @@ -0,0 +1,31 @@ +$kind: http-example +request: + url: "{{baseUrl}}/v1/users/login" + method: POST + headers: + - key: Content-Type + value: application/json + - key: Accept + value: application/json + - key: X-API-Key + value: + description: "Added as a part of security scheme: apikey" + body: + type: json + content: |- + { + "username": "string", + "password": "string" + } +response: + statusCode: 500 + statusText: Internal Server Error + headers: + Content-Type: application/json + body: + type: json + content: |- + { + "message": "string" + } +order: 3000 diff --git a/postman/collections/User API Integration Tests/v1/users/login/.resources/Log in a user.resources/examples/Unauthorized.example.yaml b/postman/collections/User API Integration Tests/v1/users/login/.resources/Log in a user.resources/examples/Unauthorized.example.yaml new file mode 100644 index 0000000..546f8fd --- /dev/null +++ b/postman/collections/User API Integration Tests/v1/users/login/.resources/Log in a user.resources/examples/Unauthorized.example.yaml @@ -0,0 +1,31 @@ +$kind: http-example +request: + url: "{{baseUrl}}/v1/users/login" + method: POST + headers: + - key: Content-Type + value: application/json + - key: Accept + value: application/json + - key: X-API-Key + value: + description: "Added as a part of security scheme: apikey" + body: + type: json + content: |- + { + "username": "string", + "password": "string" + } +response: + statusCode: 401 + statusText: Unauthorized + headers: + Content-Type: application/json + body: + type: json + content: |- + { + "message": "string" + } +order: 2000 diff --git a/postman/collections/User API Integration Tests/v1/users/login/.resources/Log in a user.resources/examples/User logged in successfully.example.yaml b/postman/collections/User API Integration Tests/v1/users/login/.resources/Log in a user.resources/examples/User logged in successfully.example.yaml new file mode 100644 index 0000000..3d6964d --- /dev/null +++ b/postman/collections/User API Integration Tests/v1/users/login/.resources/Log in a user.resources/examples/User logged in successfully.example.yaml @@ -0,0 +1,33 @@ +$kind: http-example +request: + url: "{{baseUrl}}/v1/users/login" + method: POST + headers: + - key: Content-Type + value: application/json + - key: Accept + value: application/json + - key: X-API-Key + value: + description: "Added as a part of security scheme: apikey" + body: + type: json + content: |- + { + "username": "string", + "password": "string" + } +response: + statusCode: 200 + statusText: OK + headers: + Content-Type: application/json + body: + type: json + content: |- + { + "id": 9115, + "username": "string", + "token": "string" + } +order: 1000 diff --git a/postman/collections/User API Integration Tests/v1/users/login/.resources/definition.yaml b/postman/collections/User API Integration Tests/v1/users/login/.resources/definition.yaml new file mode 100644 index 0000000..6522e17 --- /dev/null +++ b/postman/collections/User API Integration Tests/v1/users/login/.resources/definition.yaml @@ -0,0 +1,2 @@ +$kind: collection +order: 2000 diff --git a/postman/collections/User API Integration Tests/v1/users/login/Log in a user.request.yaml b/postman/collections/User API Integration Tests/v1/users/login/Log in a user.request.yaml new file mode 100644 index 0000000..b41611f --- /dev/null +++ b/postman/collections/User API Integration Tests/v1/users/login/Log in a user.request.yaml @@ -0,0 +1,23 @@ +$kind: http-request +name: Log in a user +url: "{{baseUrl}}/v1/users/login" +method: POST +headers: + Content-Type: application/json + Accept: application/json +body: + type: json + content: |- + { + "username": "{{username}}", + "password": "{{password}}" + } +scripts: + - type: afterResponse + code: |- + pm.test("Status code is 200", function () { + pm.response.to.have.status(200); + }); + language: text/javascript +examples: ./.resources/Log in a user.resources/examples +order: 1000 diff --git a/postman/collections/User API Integration Tests/v1/users/register/.resources/Register a new user.resources/examples/Error occurred.example.yaml b/postman/collections/User API Integration Tests/v1/users/register/.resources/Register a new user.resources/examples/Error occurred.example.yaml new file mode 100644 index 0000000..ebe0f21 --- /dev/null +++ b/postman/collections/User API Integration Tests/v1/users/register/.resources/Register a new user.resources/examples/Error occurred.example.yaml @@ -0,0 +1,31 @@ +$kind: http-example +request: + url: "{{baseUrl}}/v1/users/register" + method: POST + headers: + - key: Content-Type + value: application/json + - key: Accept + value: application/json + - key: X-API-Key + value: + description: "Added as a part of security scheme: apikey" + body: + type: json + content: |- + { + "username": "string", + "password": "string" + } +response: + statusCode: 500 + statusText: Internal Server Error + headers: + Content-Type: application/json + body: + type: json + content: |- + { + "message": "string" + } +order: 2000 diff --git a/postman/collections/User API Integration Tests/v1/users/register/.resources/Register a new user.resources/examples/User registered successfully.example.yaml b/postman/collections/User API Integration Tests/v1/users/register/.resources/Register a new user.resources/examples/User registered successfully.example.yaml new file mode 100644 index 0000000..18b25ee --- /dev/null +++ b/postman/collections/User API Integration Tests/v1/users/register/.resources/Register a new user.resources/examples/User registered successfully.example.yaml @@ -0,0 +1,33 @@ +$kind: http-example +request: + url: "{{baseUrl}}/v1/users/register" + method: POST + headers: + - key: Content-Type + value: application/json + - key: Accept + value: application/json + - key: X-API-Key + value: + description: "Added as a part of security scheme: apikey" + body: + type: json + content: |- + { + "username": "string", + "password": "string" + } +response: + statusCode: 201 + statusText: Created + headers: + Content-Type: application/json + body: + type: json + content: |- + { + "id": 9115, + "username": "string", + "token": "string" + } +order: 1000 diff --git a/postman/collections/User API Integration Tests/v1/users/register/.resources/definition.yaml b/postman/collections/User API Integration Tests/v1/users/register/.resources/definition.yaml new file mode 100644 index 0000000..53d990d --- /dev/null +++ b/postman/collections/User API Integration Tests/v1/users/register/.resources/definition.yaml @@ -0,0 +1,2 @@ +$kind: collection +order: 1000 diff --git a/postman/collections/User API Integration Tests/v1/users/register/Register a new user.request.yaml b/postman/collections/User API Integration Tests/v1/users/register/Register a new user.request.yaml new file mode 100644 index 0000000..12c26ab --- /dev/null +++ b/postman/collections/User API Integration Tests/v1/users/register/Register a new user.request.yaml @@ -0,0 +1,29 @@ +$kind: http-request +name: Register a new user +url: "{{baseUrl}}/v1/users/register" +method: POST +headers: + Content-Type: application/json + Accept: application/json +body: + type: json + content: |- + { + "username": "{{$randomUserName}}", + "password": "{{$randomPassword}}" + } +scripts: + - type: afterResponse + code: | + pm.test("Status code is 201", function () { + pm.response.to.have.status(201); + }); + + const jsonData = pm.response.json(); + pm.variables.set("username", jsonData.username); + pm.variables.set("id", jsonData.id); + const requestBody = JSON.parse(pm.request.body) + pm.variables.set("password", requestBody.password); + language: text/javascript +examples: ./.resources/Register a new user.resources/examples +order: 1000 diff --git a/postman/collections/User API Integration Tests/v1/users/{id}/.resources/Delete a user.resources/examples/Error occurred.example.yaml b/postman/collections/User API Integration Tests/v1/users/{id}/.resources/Delete a user.resources/examples/Error occurred.example.yaml new file mode 100644 index 0000000..b07081b --- /dev/null +++ b/postman/collections/User API Integration Tests/v1/users/{id}/.resources/Delete a user.resources/examples/Error occurred.example.yaml @@ -0,0 +1,27 @@ +$kind: http-example +request: + url: "{{baseUrl}}/v1/users/:id" + method: DELETE + headers: + - key: Accept + value: application/json + - key: X-API-Key + value: + description: "Added as a part of security scheme: apikey" + pathVariables: + id: "9696" + body: + type: text + content: "" +response: + statusCode: 500 + statusText: Internal Server Error + headers: + Content-Type: application/json + body: + type: json + content: |- + { + "message": "string" + } +order: 2000 diff --git a/postman/collections/User API Integration Tests/v1/users/{id}/.resources/Delete a user.resources/examples/User deleted successfully.example.yaml b/postman/collections/User API Integration Tests/v1/users/{id}/.resources/Delete a user.resources/examples/User deleted successfully.example.yaml new file mode 100644 index 0000000..c294399 --- /dev/null +++ b/postman/collections/User API Integration Tests/v1/users/{id}/.resources/Delete a user.resources/examples/User deleted successfully.example.yaml @@ -0,0 +1,27 @@ +$kind: http-example +request: + url: "{{baseUrl}}/v1/users/:id" + method: DELETE + headers: + - key: Accept + value: application/json + - key: X-API-Key + value: + description: "Added as a part of security scheme: apikey" + pathVariables: + id: "9696" + body: + type: text + content: "" +response: + statusCode: 200 + statusText: OK + headers: + Content-Type: application/json + body: + type: json + content: |- + { + "message": "string" + } +order: 1000 diff --git a/postman/collections/User API Integration Tests/v1/users/{id}/.resources/Retrieve a user.resources/examples/Error occurred.example.yaml b/postman/collections/User API Integration Tests/v1/users/{id}/.resources/Retrieve a user.resources/examples/Error occurred.example.yaml new file mode 100644 index 0000000..7d94db0 --- /dev/null +++ b/postman/collections/User API Integration Tests/v1/users/{id}/.resources/Retrieve a user.resources/examples/Error occurred.example.yaml @@ -0,0 +1,27 @@ +$kind: http-example +request: + url: "{{baseUrl}}/v1/users/:id" + method: GET + headers: + - key: Accept + value: application/json + - key: X-API-Key + value: + description: "Added as a part of security scheme: apikey" + pathVariables: + id: "9696" + body: + type: text + content: "" +response: + statusCode: 500 + statusText: Internal Server Error + headers: + Content-Type: application/json + body: + type: json + content: |- + { + "message": "string" + } +order: 3000 diff --git a/postman/collections/User API Integration Tests/v1/users/{id}/.resources/Retrieve a user.resources/examples/Successful operation.example.yaml b/postman/collections/User API Integration Tests/v1/users/{id}/.resources/Retrieve a user.resources/examples/Successful operation.example.yaml new file mode 100644 index 0000000..ab42e65 --- /dev/null +++ b/postman/collections/User API Integration Tests/v1/users/{id}/.resources/Retrieve a user.resources/examples/Successful operation.example.yaml @@ -0,0 +1,28 @@ +$kind: http-example +request: + url: "{{baseUrl}}/v1/users/:id" + method: GET + headers: + - key: Accept + value: application/json + - key: X-API-Key + value: + description: "Added as a part of security scheme: apikey" + pathVariables: + id: "9696" + body: + type: text + content: "" +response: + statusCode: 200 + statusText: OK + headers: + Content-Type: application/json + body: + type: json + content: |- + { + "id": 4696, + "username": "string" + } +order: 1000 diff --git a/postman/collections/User API Integration Tests/v1/users/{id}/.resources/Retrieve a user.resources/examples/User not found.example.yaml b/postman/collections/User API Integration Tests/v1/users/{id}/.resources/Retrieve a user.resources/examples/User not found.example.yaml new file mode 100644 index 0000000..debc6a4 --- /dev/null +++ b/postman/collections/User API Integration Tests/v1/users/{id}/.resources/Retrieve a user.resources/examples/User not found.example.yaml @@ -0,0 +1,27 @@ +$kind: http-example +request: + url: "{{baseUrl}}/v1/users/:id" + method: GET + headers: + - key: Accept + value: application/json + - key: X-API-Key + value: + description: "Added as a part of security scheme: apikey" + pathVariables: + id: "9696" + body: + type: text + content: "" +response: + statusCode: 404 + statusText: Not Found + headers: + Content-Type: application/json + body: + type: json + content: |- + { + "message": "string" + } +order: 2000 diff --git a/postman/collections/User API Integration Tests/v1/users/{id}/.resources/definition.yaml b/postman/collections/User API Integration Tests/v1/users/{id}/.resources/definition.yaml new file mode 100644 index 0000000..40bbb1c --- /dev/null +++ b/postman/collections/User API Integration Tests/v1/users/{id}/.resources/definition.yaml @@ -0,0 +1,2 @@ +$kind: collection +order: 3000 diff --git a/postman/collections/User API Integration Tests/v1/users/{id}/Delete a user.request.yaml b/postman/collections/User API Integration Tests/v1/users/{id}/Delete a user.request.yaml new file mode 100644 index 0000000..1a6488b --- /dev/null +++ b/postman/collections/User API Integration Tests/v1/users/{id}/Delete a user.request.yaml @@ -0,0 +1,19 @@ +$kind: http-request +url: "{{baseUrl}}/v1/users/:id" +method: DELETE +headers: + Accept: application/json +pathVariables: + id: "{{id}}" +body: + type: text + content: "" +scripts: + - type: afterResponse + code: |- + pm.test("Status code is 200", function () { + pm.response.to.have.status(200); + }); + language: text/javascript +examples: ./.resources/Delete a user.resources/examples +order: 2000 diff --git a/postman/collections/User API Integration Tests/v1/users/{id}/Retrieve a user.request.yaml b/postman/collections/User API Integration Tests/v1/users/{id}/Retrieve a user.request.yaml new file mode 100644 index 0000000..2af6794 --- /dev/null +++ b/postman/collections/User API Integration Tests/v1/users/{id}/Retrieve a user.request.yaml @@ -0,0 +1,19 @@ +$kind: http-request +url: "{{baseUrl}}/v1/users/:id" +method: GET +headers: + Accept: application/json +pathVariables: + id: "{{id}}" +body: + type: text + content: "" +scripts: + - type: afterResponse + code: |- + pm.test("Status code is 200", function () { + pm.response.to.have.status(200); + }); + language: text/javascript +examples: ./.resources/Retrieve a user.resources/examples +order: 1000 diff --git a/postman/environments/Staging Environment.environment.yaml b/postman/environments/Staging Environment.environment.yaml new file mode 100644 index 0000000..523c9ba --- /dev/null +++ b/postman/environments/Staging Environment.environment.yaml @@ -0,0 +1,9 @@ +name: Staging Environment +values: + - key: baseUrl + value: https://customer-education.postmanlabs.com + enabled: true + - key: apiKey + value: "1234" + enabled: true +color: 240 diff --git a/postman/globals/workspace.globals.yaml b/postman/globals/workspace.globals.yaml new file mode 100644 index 0000000..e96c6d6 --- /dev/null +++ b/postman/globals/workspace.globals.yaml @@ -0,0 +1,2 @@ +name: Globals +values: []