Repository: spring-petclinic/spring-petclinic-rest
Pull request #219: Adding Non-Regression Tests with Postman for "First Visit" scenario
Author: login: Isaac-Andradee
Labels: name: enhancement
Created: 2025-04-13T02:14:57Z | Merged: 2025-04-13T17:11:04Z

## 💡 What does this PR do?

This PR introduces a Postman-based non-regression testing suite for this project (Spring Petclinic REST API.)
 It focuses on simulating the real-world scenario where a new customer brings a pet for a first visit, testing the nominal flow end-to-end.

## ✨ Changes

- Added new diractory (postman) at root for:
  - Postman collection: `petclinic-nonregressiontests.postman_collection.json`
  - Enviroment file: `petclinic-env.postman_enviroment.json`
    - Includes variables: baseUrl, ownerId, petId
- Organized the collection with a scenario folder: `01 - First Visit`
  - Creates an owner
  - Creates a pet linked to the owner
  - Registers a visit linked to the pet
- Implemented test assertions for:
  - HTTP status code checks (e.g., 201 Created)
  - Key ID and linkage validations between owner, pet, and visit
- Added shell script `postman-tests.sh` in the project root to run Newman tests:
  - Displays step-by-step scenario messages
  - Generates an HTML report at postman/report/{scenarioName}.html

## ⚠️ Requirements

- Node.js Installed (v14+ recommended)

## 🧪 Running the Tests

 - Currently, there's 2 ways to run the test:

#### 1. Giving Execution Permission to the script file:

- Run `chmod +x postman-tests.sh`
- Run `./postman-tests.sh`

#### 2. Without Permission to the script file:

- Run `zsh postman-tests.sh`

> Note: You can use your currently bash installed. Like: "bash postman-tests.sh"

- This script will:
  I. Print a readable scenario name before each execution (e.g., "🔎 Scenario: 01 - First Visit")
  II. Run the corresponding test folder in the collection using `npx newman`
  III. Generate an HTML report for each scenario in `postman/reports/`
  IV. Output test result summaries directly to your terminal 

## ⁉️ Next Steps?

- Probably we'll need to add instructions with how to use the Newman test into the Readme file of the project?
  - (Let me know if i can change the readme file for this)
- We can extend the tests with more scenarios later or in this PR
  - (Let me know about it) 

## 🔗 Related Issue

Closes: #140  — Adding non-regression tests with Postman for “First Visit” scenario.

---

Let me know if i need to add any more changes. 🚀


Diff:
diff --git a/postman-tests.sh b/postman-tests.sh
new file mode 100755
index 000000000..af4cf1100
--- /dev/null
+++ b/postman-tests.sh
@@ -0,0 +1,49 @@
+#!/bin/zsh
+
+COLLECTION="./src/test/postman/petclinic-nonregressiontests.postman_collection.json"
+ENVIRONMENT="./src/test/postman/petclinic-env.postman_environment.json"
+REPORT_DIR="./src/test/postman/reports"
+
+mkdir -p "$REPORT_DIR"
+
+GREEN='\033[0;32m'
+RED='\033[0;31m'
+YELLOW='\033[0;33m'
+NC='\033[0m'
+
+# If you create a new scenario, each one should be put on this
+# variable on a double quotes to work the script...
+SCENARIOS=("01 - First Visit")
+
+echo ""
+echo -e "${GREEN}🐾 Starting Petclinic API tests with Newman...${NC}"
+sleep 1
+echo ""
+
+for SCENARIO in "${SCENARIOS[@]}"; do
+  echo "🔎 Scenario: $SCENARIO"
+  sleep 1.3
+
+  SAFE_SCENARIO=$(echo "$SCENARIO" | tr ' ' '_' | tr -d '/')
+  REPORT_FILE="$REPORT_DIR/${SAFE_SCENARIO}.html"
+
+  if [ ! -w "$REPORT_DIR" ]; then
+    echo -e "${RED}❌ Error: No write permission to directory '$REPORT_DIR'.${NC}"
+    exit 1
+  fi
+
+  npx -p newman -p newman-reporter-htmlextra newman run "$COLLECTION" \
+    -e "$ENVIRONMENT" \
+    --folder "$SCENARIO" \
+    --reporters cli,htmlextra \
+    --reporter-htmlextra-export "$REPORT_FILE" \
+    --timeout-request 5000 \
+    --suppress-exit-code 1
+
+  echo ""
+  echo -e "${YELLOW}📄 HTML report generated at: $REPORT_FILE${NC}"
+  echo ""
+
+done
+
+
diff --git a/readme.md b/readme.md
index e3c64e046..15fcd7c85 100644
--- a/readme.md
+++ b/readme.md
@@ -303,7 +303,24 @@ To benchmark the scalability of the PetClinic REST API, a JMeter test plan is av
   jmeter -n -t src/test/jmeter/petclinic-jmeter-crud-benchmark.jmx \
   -Jthreads=100 -Jduration=600 -Jops=2000 -Jramp_time=120 \
   -l results/petclinic-test-results.jtl
-  
+
+## API Testing with Postman + Newman
+
+This project contains **non-regression tests** for the Petclinic API, built with **Postman** and executed via **Newman**, with automated **HTML reports** for easy analysis.
+
+- See the [Postman + Newman Test](src/test/postman/README.md) for details.
+- You can run the tests with 2 ways:
+  I. Giving Execution Permission to the script file:
+    ```sh
+    chmod +x postman-tests.sh
+    ./postman-tests.sh
+    ```
+  II. Without Permission to the script file:
+    ```sh
+    zsh postman-tests.sh
+    ```
+> Note: You can use your currently bash installed. Like: "bash postman-tests.sh"
+
 ## Interesting Spring Petclinic forks
 
 The Spring Petclinic master branch in the main [spring-projects](https://github.com/spring-projects/spring-petclinic)
diff --git a/src/test/postman/README.md b/src/test/postman/README.md
new file mode 100644
index 000000000..527769f54
--- /dev/null
+++ b/src/test/postman/README.md
@@ -0,0 +1,94 @@
+# PetClinic API - Postman Non-Regression Tests
+
+## Overview
+
+This project contains a Postman collection designed to validate the **Spring PetClinic REST API** through a series of functional and regression tests. The tests simulate user actions on the API, and are executed via Newman, with results exported to HTML reports.
+
+### What This Test Covers
+
+- It focuses on simulating the real-world scenario where a new customer brings a pet for a first visit, testing the nominal flow end-to-end.
+> Note: We can extend the tests with more scenarios
+
+## Running the Test
+
+### Prerequisites
+
+Ensure the following are available:
+
+- **Node.js installed** ([Download here](https://nodejs.org))
+- **Spring PetClinic REST API running locally**
+
+```sh
+# Run the application from its root directory
+cd /path/to/spring-petclinic-rest
+mvn spring-boot:run
+```
+
+_(Runs by default at http://localhost:9966)_
+
+### Running the Test with Newman
+
+There's 2 ways to run the test:
+
+1. Giving Execution Permission to the script file:
+```sh
+chmod +x postman-tests.sh
+./postman-tests.sh
+```
+2. Without Permission to the script file:
+```sh
+zsh postman-tests.sh
+```
+> Note: You can use your currently bash installed. Like: "bash postman-tests.sh"
+
+This script will:
+
+I. Print a readable scenario name before each execution (e.g., "🔎 Scenario: 01 - First Visit")
+II. Run the corresponding test folder in the collection using `npx newman`
+III. Generate an HTML report for each scenario in `src/test/postman/reports/`
+IV. Output test result summaries directly to your terminal
+
+## Analyzing Test Results
+
+### 1. View HTML Report
+
+After running the tests, open the generated report in your browser:
+
+- Open the the report file in `src/test/postman/reports/`
+
+The report includes:
+
+- Status of each request
+- Response time charts
+- Assertions summary
+- Environment variables at runtime
+
+### 2. Command Line Summary
+
+The shell script provides immediate feedback:
+
+```sh
+📄 HTML report generated at: src/test/postman/reports
+```
+
+## Project Structure
+
+```
+src/
+├── test/
+|    ├── postman/
+|        ├── petclinic-env.postman_environment.json  # Environment configuration (e.g. baseUrl)
+|        ├── petclinic-nonregressiontests.postman_collection.json  # Main collection with test scenarios
+|        └── reports/ # Generated HTML reports
+├── postman-tests.sh # Execution script for running the tests
+```
+
+## Notes
+
+- `ownerId` and `petId` are kept in the environment file to aid debugging in Postman GUI.
+- `--suppress-exit-code` ensures the HTML report is generated even if assertions fail.
+- Newman is invoked via `npx` to avoid global installation.
+
+---
+
+Contributions welcome! Feel free to submit pull requests to add new scenarios or enhance the script/reporting.
diff --git a/src/test/postman/petclinic-env.postman_environment.json b/src/test/postman/petclinic-env.postman_environment.json
new file mode 100644
index 000000000..0a1e4fae3
--- /dev/null
+++ b/src/test/postman/petclinic-env.postman_environment.json
@@ -0,0 +1,27 @@
+{
+	"id": "0c330e5d-586c-4245-b787-1225a2fa50be",
+	"name": "Petclinic Env",
+	"values": [
+		{
+			"key": "baseUrl",
+			"value": "http://localhost:9966/petclinic",
+			"type": "default",
+			"enabled": true
+		},
+		{
+			"key": "ownerId",
+			"value": "",
+			"type": "default",
+			"enabled": true
+		},
+		{
+			"key": "petId",
+			"value": "",
+			"type": "default",
+			"enabled": true
+		}
+	],
+	"_postman_variable_scope": "environment",
+	"_postman_exported_at": "2025-04-12T21:09:56.059Z",
+	"_postman_exported_using": "Postman/11.40.6"
+}
\ No newline at end of file
diff --git a/src/test/postman/petclinic-nonregressiontests.postman_collection.json b/src/test/postman/petclinic-nonregressiontests.postman_collection.json
new file mode 100644
index 000000000..ec0434b03
--- /dev/null
+++ b/src/test/postman/petclinic-nonregressiontests.postman_collection.json
@@ -0,0 +1,792 @@
+{
+	"info": {
+		"_postman_id": "5fd27f12-8cfd-4cf0-81b4-26f8421f0aa4",
+		"name": "Petclinic - Non Regression Tests",
+		"description": "## 🐾 Petclinic - Non Regression Tests\n\nThis Postman collection covers functional API flows to ensure the Petclinic app remains stable during changes.\n\n### 📑 Test Scenarios\n\n1. **01 - First Visit**\n    \n    - _Create Owner_: Registers a new pet owner.\n        \n    - _Create Pet_: Adds a pet to that owner.\n        \n    - _Create Visit_: Schedules the pet’s first visit.\n        \n\nMore flows can be added later, like:\n\n- \"02 - Returning Visit\"\n    \n- \"03 - Owner Edits, etc.\"\n    \n\n### 🛠 Environment Variables\n\n- `baseUrl`: URL of the running API (e.g., `http://localhost:9966/petclinic`)\n    \n- `ownerId`, `petId`: Dynamically set during test execution\n    \n\n### ▶️ Run Tests via Newman\n\n- Make sure that you have Node Js installed in your system\n    \n- Give permission to the script file with `chmod +x postman-tests.sh`\n    \n- With your application running... Run `./postman-tests.sh` in the root directory of the project or `sh postman-tests.sh` if you dont want to give permission to the script file.",
+		"schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json",
+		"_exporter_id": "29491402"
+	},
+	"item": [
+		{
+			"name": "01 - First Visit",
+			"item": [
+				{
+					"name": "Create Owner",
+					"event": [
+						{
+							"listen": "test",
+							"script": {
+								"exec": [
+									"pm.test(\"Owner created successfully\", function () {\r",
+									"    pm.response.to.have.status(201);\r",
+									"    \r",
+									"    const jsonData = pm.response.json();\r",
+									"    pm.expect(jsonData.id).to.be.a(\"number\");\r",
+									"    pm.expect(jsonData.firstName).to.eql(\"Anna Luísa\");\r",
+									"});\r",
+									"\r",
+									"pm.environment.set(\"ownerId\", pm.response.json().id);\r",
+									""
+								],
+								"type": "text/javascript",
+								"packages": {}
+							}
+						}
+					],
+					"request": {
+						"method": "POST",
+						"header": [
+							{
+								"key": "Content-Type",
+								"value": "application/json"
+							},
+							{
+								"key": "Accept",
+								"value": "application/json"
+							}
+						],
+						"body": {
+							"mode": "raw",
+							"raw": "{\n  \"address\": \"123 Brasilia Street\",\n  \"city\": \"Brasília\",\n  \"firstName\": \"Anna Luísa\",\n  \"lastName\": \"Medeiros\",\n  \"telephone\": \"1234567890\"\n}",
+							"options": {
+								"raw": {
+									"language": "json"
+								}
+							}
+						},
+						"url": {
+							"raw": "{{baseUrl}}/api/owners",
+							"host": [
+								"{{baseUrl}}"
+							],
+							"path": [
+								"api",
+								"owners"
+							]
+						},
+						"description": "Records the details of a new pet owner."
+					},
+					"response": [
+						{
+							"name": "The pet owner was successfully added.",
+							"originalRequest": {
+								"method": "POST",
+								"header": [
+									{
+										"key": "Accept",
+										"value": "application/json"
+									}
+								],
+								"body": {
+									"mode": "raw",
+									"raw": "{\n  \"address\": \"<string>\",\n  \"city\": \"<string>\",\n  \"firstName\": \"<string>\",\n  \"lastName\": \"<string>\",\n  \"telephone\": \"<string>\"\n}",
+									"options": {
+										"raw": {
+											"language": "json"
+										}
+									}
+								},
+								"url": {
+									"raw": "http://localhost:9966/petclinic/api/owners",
+									"protocol": "http",
+									"host": [
+										"localhost"
+									],
+									"port": "9966",
+									"path": [
+										"petclinic",
+										"api",
+										"owners"
+									]
+								}
+							},
+							"status": "Created",
+							"code": 201,
+							"_postman_previewlanguage": "json",
+							"header": [
+								{
+									"key": "Content-Type",
+									"value": "application/json"
+								}
+							],
+							"cookie": [],
+							"body": "{\n  \"address\": \"<string>\",\n  \"city\": \"<string>\",\n  \"firstName\": \"<string>\",\n  \"lastName\": \"<string>\",\n  \"pets\": [\n    {\n      \"birthDate\": \"<date>\",\n      \"id\": \"<integer>\",\n      \"name\": \"<string>\",\n      \"type\": {\n        \"id\": \"<integer>\",\n        \"name\": \"<string>\"\n      },\n      \"visits\": [\n        {\n          \"description\": \"<string>\",\n          \"id\": \"<integer>\",\n          \"date\": \"<date>\",\n          \"petId\": \"<integer>\"\n        },\n        {\n          \"description\": \"<string>\",\n          \"id\": \"<integer>\",\n          \"date\": \"<date>\",\n          \"petId\": \"<integer>\"\n        }\n      ],\n      \"ownerId\": \"<integer>\"\n    },\n    {\n      \"birthDate\": \"<date>\",\n      \"id\": \"<integer>\",\n      \"name\": \"<string>\",\n      \"type\": {\n        \"id\": \"<integer>\",\n        \"name\": \"<string>\"\n      },\n      \"visits\": [\n        {\n          \"description\": \"<string>\",\n          \"id\": \"<integer>\",\n          \"date\": \"<date>\",\n          \"petId\": \"<integer>\"\n        },\n        {\n          \"description\": \"<string>\",\n          \"id\": \"<integer>\",\n          \"date\": \"<date>\",\n          \"petId\": \"<integer>\"\n        }\n      ],\n      \"ownerId\": \"<integer>\"\n    }\n  ],\n  \"telephone\": \"<string>\",\n  \"id\": \"<integer>\"\n}"
+						},
+						{
+							"name": "Bad request.",
+							"originalRequest": {
+								"method": "POST",
+								"header": [
+									{
+										"key": "Accept",
+										"value": "application/json"
+									}
+								],
+								"body": {
+									"mode": "raw",
+									"raw": "{\n  \"address\": \"<string>\",\n  \"city\": \"<string>\",\n  \"firstName\": \"<string>\",\n  \"lastName\": \"<string>\",\n  \"telephone\": \"<string>\"\n}",
+									"options": {
+										"raw": {
+											"language": "json"
+										}
+									}
+								},
+								"url": {
+									"raw": "{{baseUrl}}/api/owners",
+									"host": [
+										"{{baseUrl}}"
+									],
+									"path": [
+										"api",
+										"owners"
+									]
+								}
+							},
+							"status": "Bad Request",
+							"code": 400,
+							"_postman_previewlanguage": "json",
+							"header": [
+								{
+									"key": "Content-Type",
+									"value": "application/json"
+								}
+							],
+							"cookie": [],
+							"body": "{\n  \"detail\": \"<string>\",\n  \"schemaValidationErrors\": [\n    {\n      \"message\": \"<string>\"\n    },\n    {\n      \"message\": \"<string>\"\n    }\n  ],\n  \"status\": \"<integer>\",\n  \"timestamp\": \"<dateTime>\",\n  \"title\": \"<string>\",\n  \"type\": \"<uri>\"\n}"
+						},
+						{
+							"name": "Server error.",
+							"originalRequest": {
+								"method": "POST",
+								"header": [
+									{
+										"key": "Accept",
+										"value": "application/json"
+									}
+								],
+								"body": {
+									"mode": "raw",
+									"raw": "{\n  \"address\": \"<string>\",\n  \"city\": \"<string>\",\n  \"firstName\": \"<string>\",\n  \"lastName\": \"<string>\",\n  \"telephone\": \"<string>\"\n}",
+									"options": {
+										"raw": {
+											"language": "json"
+										}
+									}
+								},
+								"url": {
+									"raw": "{{baseUrl}}/api/owners",
+									"host": [
+										"{{baseUrl}}"
+									],
+									"path": [
+										"api",
+										"owners"
+									]
+								}
+							},
+							"status": "Internal Server Error",
+							"code": 500,
+							"_postman_previewlanguage": "json",
+							"header": [
+								{
+									"key": "Content-Type",
+									"value": "application/json"
+								}
+							],
+							"cookie": [],
+							"body": "{\n  \"detail\": \"<string>\",\n  \"schemaValidationErrors\": [\n    {\n      \"message\": \"<string>\"\n    },\n    {\n      \"message\": \"<string>\"\n    }\n  ],\n  \"status\": \"<integer>\",\n  \"timestamp\": \"<dateTime>\",\n  \"title\": \"<string>\",\n  \"type\": \"<uri>\"\n}"
+						}
+					]
+				},
+				{
+					"name": "Create Pet",
+					"event": [
+						{
+							"listen": "test",
+							"script": {
+								"exec": [
+									"pm.test(\"Pet created successfully\", function () {\r",
+									"    pm.response.to.have.status(201);\r",
+									"    \r",
+									"    const jsonData = pm.response.json();\r",
+									"    \r",
+									"    pm.expect(jsonData.id).to.be.a(\"number\");\r",
+									"    pm.expect(jsonData.ownerId).to.eql(parseInt(pm.environment.get(\"ownerId\")));\r",
+									"\r",
+									"    pm.environment.set(\"petId\", jsonData.id);\r",
+									"});\r",
+									""
+								],
+								"type": "text/javascript",
+								"packages": {}
+							}
+						}
+					],
+					"request": {
+						"method": "POST",
+						"header": [
+							{
+								"key": "Content-Type",
+								"value": "application/json"
+							},
+							{
+								"key": "Accept",
+								"value": "application/json"
+							}
+						],
+						"body": {
+							"mode": "raw",
+							"raw": "{\n  \"birthDate\": \"2025-12-04\",\n  \"name\": \"Drax\",\n  \"type\": {\n    \"id\": \"1\",\n    \"name\": \"cat\"\n  }\n}",
+							"options": {
+								"raw": {
+									"language": "json"
+								}
+							}
+						},
+						"url": {
+							"raw": "{{baseUrl}}/api/owners/{{ownerId}}/pets",
+							"host": [
+								"{{baseUrl}}"
+							],
+							"path": [
+								"api",
+								"owners",
+								"{{ownerId}}",
+								"pets"
+							]
+						},
+						"description": "Records the details of a new pet."
+					},
+					"response": [
+						{
+							"name": "The pet was successfully added.",
+							"originalRequest": {
+								"method": "POST",
+								"header": [
+									{
+										"key": "Accept",
+										"value": "application/json"
+									}
+								],
+								"body": {
+									"mode": "raw",
+									"raw": "{\n  \"birthDate\": \"<date>\",\n  \"name\": \"<string>\",\n  \"type\": {\n    \"id\": \"<integer>\",\n    \"name\": \"<string>\"\n  }\n}",
+									"options": {
+										"raw": {
+											"language": "json"
+										}
+									}
+								},
+								"url": {
+									"raw": "http://localhost:9966/petclinic/api/owners/:ownerId/pets",
+									"protocol": "http",
+									"host": [
+										"localhost"
+									],
+									"port": "9966",
+									"path": [
+										"petclinic",
+										"api",
+										"owners",
+										":ownerId",
+										"pets"
+									],
+									"variable": [
+										{
+											"key": "ownerId",
+											"value": "<integer>",
+											"description": "(Required) The ID of the pet owner."
+										}
+									]
+								}
+							},
+							"status": "Created",
+							"code": 201,
+							"_postman_previewlanguage": "json",
+							"header": [
+								{
+									"key": "Content-Type",
+									"value": "application/json"
+								}
+							],
+							"cookie": [],
+							"body": "{\n  \"birthDate\": \"<date>\",\n  \"id\": \"<integer>\",\n  \"name\": \"<string>\",\n  \"type\": {\n    \"id\": \"<integer>\",\n    \"name\": \"<string>\"\n  },\n  \"visits\": [\n    {\n      \"description\": \"<string>\",\n      \"id\": \"<integer>\",\n      \"date\": \"<date>\",\n      \"petId\": \"<integer>\"\n    },\n    {\n      \"description\": \"<string>\",\n      \"id\": \"<integer>\",\n      \"date\": \"<date>\",\n      \"petId\": \"<integer>\"\n    }\n  ],\n  \"ownerId\": \"<integer>\"\n}"
+						},
+						{
+							"name": "Bad request.",
+							"originalRequest": {
+								"method": "POST",
+								"header": [
+									{
+										"key": "Accept",
+										"value": "application/json"
+									}
+								],
+								"body": {
+									"mode": "raw",
+									"raw": "{\n  \"birthDate\": \"<date>\",\n  \"name\": \"<string>\",\n  \"type\": {\n    \"id\": \"<integer>\",\n    \"name\": \"<string>\"\n  }\n}",
+									"options": {
+										"raw": {
+											"language": "json"
+										}
+									}
+								},
+								"url": {
+									"raw": "{{baseUrl}}/api/owners/:ownerId/pets",
+									"host": [
+										"{{baseUrl}}"
+									],
+									"path": [
+										"api",
+										"owners",
+										":ownerId",
+										"pets"
+									],
+									"variable": [
+										{
+											"key": "ownerId",
+											"value": "<integer>",
+											"description": "(Required) The ID of the pet owner."
+										}
+									]
+								}
+							},
+							"status": "Bad Request",
+							"code": 400,
+							"_postman_previewlanguage": "json",
+							"header": [
+								{
+									"key": "Content-Type",
+									"value": "application/json"
+								}
+							],
+							"cookie": [],
+							"body": "{\n  \"detail\": \"<string>\",\n  \"schemaValidationErrors\": [\n    {\n      \"message\": \"<string>\"\n    },\n    {\n      \"message\": \"<string>\"\n    }\n  ],\n  \"status\": \"<integer>\",\n  \"timestamp\": \"<dateTime>\",\n  \"title\": \"<string>\",\n  \"type\": \"<uri>\"\n}"
+						},
+						{
+							"name": "Pet or Owner not found.",
+							"originalRequest": {
+								"method": "POST",
+								"header": [
+									{
+										"key": "Accept",
+										"value": "application/json"
+									}
+								],
+								"body": {
+									"mode": "raw",
+									"raw": "{\n  \"birthDate\": \"<date>\",\n  \"name\": \"<string>\",\n  \"type\": {\n    \"id\": \"<integer>\",\n    \"name\": \"<string>\"\n  }\n}",
+									"options": {
+										"raw": {
+											"language": "json"
+										}
+									}
+								},
+								"url": {
+									"raw": "{{baseUrl}}/api/owners/:ownerId/pets",
+									"host": [
+										"{{baseUrl}}"
+									],
+									"path": [
+										"api",
+										"owners",
+										":ownerId",
+										"pets"
+									],
+									"variable": [
+										{
+											"key": "ownerId",
+											"value": "<integer>",
+											"description": "(Required) The ID of the pet owner."
+										}
+									]
+								}
+							},
+							"status": "Not Found",
+							"code": 404,
+							"_postman_previewlanguage": "json",
+							"header": [
+								{
+									"key": "Content-Type",
+									"value": "application/json"
+								}
+							],
+							"cookie": [],
+							"body": "{\n  \"detail\": \"<string>\",\n  \"schemaValidationErrors\": [\n    {\n      \"message\": \"<string>\"\n    },\n    {\n      \"message\": \"<string>\"\n    }\n  ],\n  \"status\": \"<integer>\",\n  \"timestamp\": \"<dateTime>\",\n  \"title\": \"<string>\",\n  \"type\": \"<uri>\"\n}"
+						},
+						{
+							"name": "Server error.",
+							"originalRequest": {
+								"method": "POST",
+								"header": [
+									{
+										"key": "Accept",
+										"value": "application/json"
+									}
+								],
+								"body": {
+									"mode": "raw",
+									"raw": "{\n  \"birthDate\": \"<date>\",\n  \"name\": \"<string>\",\n  \"type\": {\n    \"id\": \"<integer>\",\n    \"name\": \"<string>\"\n  }\n}",
+									"options": {
+										"raw": {
+											"language": "json"
+										}
+									}
+								},
+								"url": {
+									"raw": "{{baseUrl}}/api/owners/:ownerId/pets",
+									"host": [
+										"{{baseUrl}}"
+									],
+									"path": [
+										"api",
+										"owners",
+										":ownerId",
+										"pets"
+									],
+									"variable": [
+										{
+											"key": "ownerId",
+											"value": "<integer>",
+											"description": "(Required) The ID of the pet owner."
+										}
+									]
+								}
+							},
+							"status": "Internal Server Error",
+							"code": 500,
+							"_postman_previewlanguage": "json",
+							"header": [
+								{
+									"key": "Content-Type",
+									"value": "application/json"
+								}
+							],
+							"cookie": [],
+							"body": "{\n  \"detail\": \"<string>\",\n  \"schemaValidationErrors\": [\n    {\n      \"message\": \"<string>\"\n    },\n    {\n      \"message\": \"<string>\"\n    }\n  ],\n  \"status\": \"<integer>\",\n  \"timestamp\": \"<dateTime>\",\n  \"title\": \"<string>\",\n  \"type\": \"<uri>\"\n}"
+						}
+					]
+				},
+				{
+					"name": "Create a visit",
+					"event": [
+						{
+							"listen": "test",
+							"script": {
+								"exec": [
+									"pm.test(\"Visit registered successfully\", function () {\r",
+									"    pm.response.to.have.status(201);\r",
+									"\r",
+									"    const jsonData = pm.response.json();\r",
+									"\r",
+									"    pm.expect(jsonData.id).to.be.a(\"number\");\r",
+									"    pm.expect(jsonData.petId).to.eql(parseInt(pm.environment.get(\"petId\")));\r",
+									"    pm.expect(jsonData.date).to.match(/^\\d{4}-\\d{2}-\\d{2}$/);\r",
+									"});"
+								],
+								"type": "text/javascript",
+								"packages": {}
+							}
+						}
+					],
+					"request": {
+						"method": "POST",
+						"header": [
+							{
+								"key": "Content-Type",
+								"value": "application/json"
+							},
+							{
+								"key": "Accept",
+								"value": "application/json"
+							}
+						],
+						"body": {
+							"mode": "raw",
+							"raw": "{\n  \"description\": \"Regular checkup\",\n  \"date\": \"2025-04-12\"\n}",
+							"options": {
+								"raw": {
+									"language": "json"
+								}
+							}
+						},
+						"url": {
+							"raw": "{{baseUrl}}/api/owners/{{ownerId}}/pets/{{petId}}/visits",
+							"host": [
+								"{{baseUrl}}"
+							],
+							"path": [
+								"api",
+								"owners",
+								"{{ownerId}}",
+								"pets",
+								"{{petId}}",
+								"visits"
+							],
+							"query": [
+								{
+									"key": "",
+									"value": null,
+									"disabled": true
+								}
+							]
+						},
+						"description": "Creates a visit."
+					},
+					"response": [
+						{
+							"name": "visit created successfully.",
+							"originalRequest": {
+								"method": "POST",
+								"header": [
+									{
+										"key": "Accept",
+										"value": "application/json"
+									}
+								],
+								"body": {
+									"mode": "raw",
+									"raw": "{\n  \"description\": \"<string>\",\n  \"date\": \"<date>\"\n}",
+									"options": {
+										"raw": {
+											"language": "json"
+										}
+									}
+								},
+								"url": {
+									"raw": "http://localhost:9966/petclinic/api/visits",
+									"protocol": "http",
+									"host": [
+										"localhost"
+									],
+									"port": "9966",
+									"path": [
+										"petclinic",
+										"api",
+										"visits"
+									]
+								}
+							},
+							"status": "OK",
+							"code": 200,
+							"_postman_previewlanguage": "json",
+							"header": [
+								{
+									"key": "Content-Type",
+									"value": "application/json"
+								}
+							],
+							"cookie": [],
+							"body": "{\n  \"description\": \"<string>\",\n  \"id\": \"<integer>\",\n  \"date\": \"<date>\",\n  \"petId\": \"<integer>\"\n}"
+						},
+						{
+							"name": "Not modified.",
+							"originalRequest": {
+								"method": "POST",
+								"header": [
+									{
+										"key": "Accept",
+										"value": "application/json"
+									}
+								],
+								"body": {
+									"mode": "raw",
+									"raw": "{\n  \"description\": \"<string>\",\n  \"date\": \"<date>\"\n}",
+									"options": {
+										"raw": {
+											"language": "json"
+										}
+									}
+								},
+								"url": {
+									"raw": "{{baseUrl}}/api/visits",
+									"host": [
+										"{{baseUrl}}"
+									],
+									"path": [
+										"api",
+										"visits"
+									]
+								}
+							},
+							"status": "Not Modified",
+							"code": 304,
+							"_postman_previewlanguage": "json",
+							"header": [
+								{
+									"key": "Content-Type",
+									"value": "application/json"
+								}
+							],
+							"cookie": [],
+							"body": "{\n  \"description\": \"<string>\",\n  \"id\": \"<integer>\",\n  \"date\": \"<date>\",\n  \"petId\": \"<integer>\"\n}"
+						},
+						{
+							"name": "Bad request.",
+							"originalRequest": {
+								"method": "POST",
+								"header": [
+									{
+										"key": "Accept",
+										"value": "application/json"
+									}
+								],
+								"body": {
+									"mode": "raw",
+									"raw": "{\n  \"description\": \"<string>\",\n  \"date\": \"<date>\"\n}",
+									"options": {
+										"raw": {
+											"language": "json"
+										}
+									}
+								},
+								"url": {
+									"raw": "{{baseUrl}}/api/visits",
+									"host": [
+										"{{baseUrl}}"
+									],
+									"path": [
+										"api",
+										"visits"
+									]
+								}
+							},
+							"status": "Bad Request",
+							"code": 400,
+							"_postman_previewlanguage": "json",
+							"header": [
+								{
+									"key": "Content-Type",
+									"value": "application/json"
+								}
+							],
+							"cookie": [],
+							"body": "{\n  \"detail\": \"<string>\",\n  \"schemaValidationErrors\": [\n    {\n      \"message\": \"<string>\"\n    },\n    {\n      \"message\": \"<string>\"\n    }\n  ],\n  \"status\": \"<integer>\",\n  \"timestamp\": \"<dateTime>\",\n  \"title\": \"<string>\",\n  \"type\": \"<uri>\"\n}"
+						},
+						{
+							"name": "Visit not found.",
+							"originalRequest": {
+								"method": "POST",
+								"header": [
+									{
+										"key": "Accept",
+										"value": "application/json"
+									}
+								],
+								"body": {
+									"mode": "raw",
+									"raw": "{\n  \"description\": \"<string>\",\n  \"date\": \"<date>\"\n}",
+									"options": {
+										"raw": {
+											"language": "json"
+										}
+									}
+								},
+								"url": {
+									"raw": "{{baseUrl}}/api/visits",
+									"host": [
+										"{{baseUrl}}"
+									],
+									"path": [
+										"api",
+										"visits"
+									]
+								}
+							},
+							"status": "Not Found",
+							"code": 404,
+							"_postman_previewlanguage": "json",
+							"header": [
+								{
+									"key": "Content-Type",
+									"value": "application/json"
+								}
+							],
+							"cookie": [],
+							"body": "{\n  \"detail\": \"<string>\",\n  \"schemaValidationErrors\": [\n    {\n      \"message\": \"<string>\"\n    },\n    {\n      \"message\": \"<string>\"\n    }\n  ],\n  \"status\": \"<integer>\",\n  \"timestamp\": \"<dateTime>\",\n  \"title\": \"<string>\",\n  \"type\": \"<uri>\"\n}"
+						},
+						{
+							"name": "Server error.",
+							"originalRequest": {
+								"method": "POST",
+								"header": [
+									{
+										"key": "Accept",
+										"value": "application/json"
+									}
+								],
+								"body": {
+									"mode": "raw",
+									"raw": "{\n  \"description\": \"<string>\",\n  \"date\": \"<date>\"\n}",
+									"options": {
+										"raw": {
+											"language": "json"
+										}
+									}
+								},
+								"url": {
+									"raw": "{{baseUrl}}/api/visits",
+									"host": [
+										"{{baseUrl}}"
+									],
+									"path": [
+										"api",
+										"visits"
+									]
+								}
+							},
+							"status": "Internal Server Error",
+							"code": 500,
+							"_postman_previewlanguage": "json",
+							"header": [
+								{
+									"key": "Content-Type",
+									"value": "application/json"
+								}
+							],
+							"cookie": [],
+							"body": "{\n  \"detail\": \"<string>\",\n  \"schemaValidationErrors\": [\n    {\n      \"message\": \"<string>\"\n    },\n    {\n      \"message\": \"<string>\"\n    }\n  ],\n  \"status\": \"<integer>\",\n  \"timestamp\": \"<dateTime>\",\n  \"title\": \"<string>\",\n  \"type\": \"<uri>\"\n}"
+						}
+					]
+				}
+			],
+			"description": "_\"A new customer comes with her pet for a first visit\"_"
+		}
+	],
+	"event": [
+		{
+			"listen": "prerequest",
+			"script": {
+				"type": "text/javascript",
+				"exec": [
+					""
+				]
+			}
+		},
+		{
+			"listen": "test",
+			"script": {
+				"type": "text/javascript",
+				"exec": [
+					""
+				]
+			}
+		}
+	],
+	"variable": [
+		{
+			"key": "baseUrl",
+			"value": "http://localhost:9966/petclinic"
+		},
+		{
+			"key": "ownerId",
+			"value": "",
+			"type": "string"
+		},
+		{
+			"key": "petId",
+			"value": "",
+			"type": "string"
+		}
+	]
+}
\ No newline at end of file


Reviews:
user: login: arey
body: Great job @Isaac-Andradee 
I've done some feedbacks.
Before merging, we need to add a section to the readme. We could take inspiration from the "Running the Tests" section of this PR.
state: APPROVED
author_association: MEMBER
submitted_at: 2025-04-13T08:29:17Z
user: login: copilot-pull-request-reviewer[bot]
body: 

Copilot reviewed 1 out of 3 changed files in this pull request and generated no comments.

<details>
<summary>Files not reviewed (2)</summary>

* **postman-tests.sh**: Language not supported
* **postman/petclinic-env.postman_environment.json**: Language not supported
</details>



state: COMMENTED
author_association: NONE
submitted_at: 2025-04-13T08:29:25Z
user: login: Isaac-Andradee
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-13T12:32:28Z
user: login: Isaac-Andradee
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-13T13:08:47Z
user: login: Isaac-Andradee
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-13T13:32:03Z
user: login: Isaac-Andradee
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-13T13:54:12Z
user: login: Isaac-Andradee
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-13T13:57:09Z
user: login: arey
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-13T15:44:54Z

Review comments:
diff_hunk: @@ -0,0 +1,27 @@
+{
path: postman/petclinic-env.postman_environment.json
user: login: arey
body: **suggestion**: I propose to move the `postman` directory to the `src\test\postman` sub-directory. In other Petclinic forks, we could find at this level a `src\test\jmeter` sub-directory.
created_at: 2025-04-13T08:01:50Z
author_association: MEMBER
diff_hunk: @@ -0,0 +1,54 @@
+#!/bin/zsh
+
+COLLECTION="./postman/petclinic-nonregressiontests.postman_collection.json"
+ENVIRONMENT="./postman/petclinic-env.postman_environment.json"
+REPORT_DIR="./postman/reports"
+
+mkdir -p "$REPORT_DIR"
+
+GREEN='\033[0;32m'
+RED='\033[0;31m'
+NC='\033[0m'
+
+# If you create a new scenario, each one should be put on this
+# variable on a double quotes to work the script...
+SCENARIOS=("01 - First Visit")
+
+echo ""
+echo -e "${GREEN}🐾 Starting Petclinic API tests with Newman...${NC}"
+sleep 1
+echo ""
+
+for SCENARIO in "${SCENARIOS[@]}"; do
+  echo "🔎 Scenario: $SCENARIO"
+  sleep 1.3
+
+  SAFE_SCENARIO=$(echo "$SCENARIO" | tr ' ' '_' | tr -d '/')
+  REPORT_FILE="$REPORT_DIR/${SAFE_SCENARIO}.html"
+
+  if [ ! -w "$REPORT_DIR" ]; then
+    echo -e "${RED}❌ Error: No write permission to directory '$REPORT_DIR'.${NC}"
+    exit 1
+  fi
+
+  npx newman run "$COLLECTION" \
+    -e "$ENVIRONMENT" \
+    --folder "$SCENARIO" \
+    --reporters cli,html \
+    --reporter-html-export "$REPORT_FILE" \
+    --timeout-request 5000
+
+  if [ $? -eq 0 ]; then
+    echo ""
+    echo -e "${GREEN}✅ Scenario passed successfully!${NC}"
+    echo -e "${GREEN}📄 HTML report generated at: $REPORT_FILE${NC}"
path: postman-tests.sh
user: login: arey
body: **issue**: on my desktop, the `/postman/reports/` is empty, both when the tests pass or fail. Any idea?
 

created_at: 2025-04-13T08:18:57Z
author_association: MEMBER
diff_hunk: @@ -0,0 +1,27 @@
+{
+	"id": "0c330e5d-586c-4245-b787-1225a2fa50be",
+	"name": "Petclinic Env",
+	"values": [
+		{
+			"key": "baseUrl",
+			"value": "http://localhost:9966/petclinic",
+			"type": "default",
+			"enabled": true
+		},
+		{
+			"key": "ownerId",
path: postman/petclinic-env.postman_environment.json
user: login: arey
body: **question**: are `ownerId` and  `petId` required in this file? I don't think so, even if we extract the variable from the HTTP response into an environment variable.
Maybe to debug in postman each individual request?
created_at: 2025-04-13T08:19:59Z
author_association: MEMBER
diff_hunk: @@ -0,0 +1,792 @@
+{
+	"info": {
+		"_postman_id": "5fd27f12-8cfd-4cf0-81b4-26f8421f0aa4",
+		"name": "Petclinic - Non Regression Tests",
+		"description": "## 🐾 Petclinic - Non Regression Tests\n\nThis Postman collection covers functional API flows to ensure the Petclinic app remains stable during changes.\n\n### 📑 Test Scenarios\n\n1. **01 - First Visit**\n    \n    - _Create Owner_: Registers a new pet owner.\n        \n    - _Create Pet_: Adds a pet to that owner.\n        \n    - _Create Visit_: Schedules the pet’s first visit.\n        \n\nMore flows can be added later, like:\n\n- \"02 - Returning Visit\"\n    \n- \"03 - Owner Edits, etc.\"\n    \n\n### 🛠 Environment Variables\n\n- `baseUrl`: URL of the running API (e.g., `http://localhost:9966/petclinic`)\n    \n- `ownerId`, `petId`: Dynamically set during test execution\n    \n\n### ▶️ Run Tests via Newman\n\n- Make sure that you have Node Js installed in your system\n    \n- Give permission to the script file with `chmod +x postman-tests.sh`\n    \n- With your application running... Run `./postman-tests.sh` in the root directory of the project or `sh postman-tests.sh` if you dont want to give permission to the script file.",
+		"schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json",
+		"_exporter_id": "29491402"
+	},
+	"item": [
+		{
+			"name": "01 - First Visit",
+			"item": [
+				{
+					"name": "Create Owner",
+					"event": [
+						{
+							"listen": "test",
+							"script": {
+								"exec": [
+									"pm.test(\"Owner created successfully\", function () {\r",
+									"    pm.response.to.have.status(201);\r",
+									"    \r",
+									"    const jsonData = pm.response.json();\r",
+									"    pm.expect(jsonData.id).to.be.a(\"number\");\r",
+									"    pm.expect(jsonData.firstName).to.eql(\"Anna Luísa\");\r",
+									"});\r",
+									"\r",
+									"pm.environment.set(\"ownerId\", pm.response.json().id);\r",
+									""
+								],
+								"type": "text/javascript",
+								"packages": {}
+							}
+						}
+					],
+					"request": {
+						"method": "POST",
+						"header": [
+							{
+								"key": "Content-Type",
+								"value": "application/json"
+							},
+							{
+								"key": "Accept",
+								"value": "application/json"
+							}
+						],
+						"body": {
+							"mode": "raw",
+							"raw": "{\n  \"address\": \"123 Brasilia Street\",\n  \"city\": \"Brasília\",\n  \"firstName\": \"Anna Luísa\",\n  \"lastName\": \"Medeiros\",\n  \"telephone\": \"1234567890\"\n}",
path: postman/petclinic-nonregressiontests.postman_collection.json
user: login: arey
body: **praise**: `Anna Luísa` is a valid name thanks to https://github.com/spring-petclinic/spring-petclinic-rest/pull/217 
created_at: 2025-04-13T08:21:25Z
author_association: MEMBER
diff_hunk: @@ -0,0 +1,27 @@
+{
path: postman/petclinic-env.postman_environment.json
user: login: Isaac-Andradee
body: Thanks for the suggestion, @arey . I'll make this change.
created_at: 2025-04-13T12:32:28Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,54 @@
+#!/bin/zsh
+
+COLLECTION="./postman/petclinic-nonregressiontests.postman_collection.json"
+ENVIRONMENT="./postman/petclinic-env.postman_environment.json"
+REPORT_DIR="./postman/reports"
+
+mkdir -p "$REPORT_DIR"
+
+GREEN='\033[0;32m'
+RED='\033[0;31m'
+NC='\033[0m'
+
+# If you create a new scenario, each one should be put on this
+# variable on a double quotes to work the script...
+SCENARIOS=("01 - First Visit")
+
+echo ""
+echo -e "${GREEN}🐾 Starting Petclinic API tests with Newman...${NC}"
+sleep 1
+echo ""
+
+for SCENARIO in "${SCENARIOS[@]}"; do
+  echo "🔎 Scenario: $SCENARIO"
+  sleep 1.3
+
+  SAFE_SCENARIO=$(echo "$SCENARIO" | tr ' ' '_' | tr -d '/')
+  REPORT_FILE="$REPORT_DIR/${SAFE_SCENARIO}.html"
+
+  if [ ! -w "$REPORT_DIR" ]; then
+    echo -e "${RED}❌ Error: No write permission to directory '$REPORT_DIR'.${NC}"
+    exit 1
+  fi
+
+  npx newman run "$COLLECTION" \
+    -e "$ENVIRONMENT" \
+    --folder "$SCENARIO" \
+    --reporters cli,html \
+    --reporter-html-export "$REPORT_FILE" \
+    --timeout-request 5000
+
+  if [ $? -eq 0 ]; then
+    echo ""
+    echo -e "${GREEN}✅ Scenario passed successfully!${NC}"
+    echo -e "${GREEN}📄 HTML report generated at: $REPORT_FILE${NC}"
path: postman-tests.sh
user: login: Isaac-Andradee
body: Oh. I see, @arey ! 
This issue happened because I forgot to add one more dependency to the newman execution script. I have a legacy version installed globally on my machine, so there was no problem. 😄 

I will modify the script to install the dependency needed to run the html report generation with npx.

Previously I used `newman-reporter-html`, which is a legacy dependency and incompatible with recent versions of newman. Now I will change the script to use `newman-reporter-htmlextra`. You can take a look at if you will: [newman-reporter-htmlextra](https://www.npmjs.com/package/newman-reporter-htmlextra)
created_at: 2025-04-13T13:08:46Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,54 @@
+#!/bin/zsh
+
+COLLECTION="./postman/petclinic-nonregressiontests.postman_collection.json"
+ENVIRONMENT="./postman/petclinic-env.postman_environment.json"
+REPORT_DIR="./postman/reports"
+
+mkdir -p "$REPORT_DIR"
+
+GREEN='\033[0;32m'
+RED='\033[0;31m'
+NC='\033[0m'
+
+# If you create a new scenario, each one should be put on this
+# variable on a double quotes to work the script...
+SCENARIOS=("01 - First Visit")
+
+echo ""
+echo -e "${GREEN}🐾 Starting Petclinic API tests with Newman...${NC}"
+sleep 1
+echo ""
+
+for SCENARIO in "${SCENARIOS[@]}"; do
+  echo "🔎 Scenario: $SCENARIO"
+  sleep 1.3
+
+  SAFE_SCENARIO=$(echo "$SCENARIO" | tr ' ' '_' | tr -d '/')
+  REPORT_FILE="$REPORT_DIR/${SAFE_SCENARIO}.html"
+
+  if [ ! -w "$REPORT_DIR" ]; then
+    echo -e "${RED}❌ Error: No write permission to directory '$REPORT_DIR'.${NC}"
+    exit 1
+  fi
+
+  npx newman run "$COLLECTION" \
+    -e "$ENVIRONMENT" \
+    --folder "$SCENARIO" \
+    --reporters cli,html \
+    --reporter-html-export "$REPORT_FILE" \
+    --timeout-request 5000
+
+  if [ $? -eq 0 ]; then
+    echo ""
+    echo -e "${GREEN}✅ Scenario passed successfully!${NC}"
+    echo -e "${GREEN}📄 HTML report generated at: $REPORT_FILE${NC}"
path: postman-tests.sh
user: login: Isaac-Andradee
body: By the way. 
I'm going to remove this logic for checking whether the test passed or failed. Because with this check, the HTML report is not generated if the tests fail. Cause newman generates an error code when the test fails, preventing the report from being generated.

Therefore, I'm just going to inform at the end of every test run that an HTML report was generated in the corresponding directory, regardless of whether there were failures or not.
created_at: 2025-04-13T13:32:03Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,27 @@
+{
+	"id": "0c330e5d-586c-4245-b787-1225a2fa50be",
+	"name": "Petclinic Env",
+	"values": [
+		{
+			"key": "baseUrl",
+			"value": "http://localhost:9966/petclinic",
+			"type": "default",
+			"enabled": true
+		},
+		{
+			"key": "ownerId",
path: postman/petclinic-env.postman_environment.json
user: login: Isaac-Andradee
body: Yes, @arey . I was thinking like that: 

The ownerId and petId variables are not strictly required for automated runs, since they’re dynamically set from responses. However, they’re included in the environment to improve visibility and support manual debugging in Postman.

This allows developers to:
- Quickly test individual requests using preset values
- Understand which variables are used throughout the flow
- Keep the environment consistent and easier to maintain

But we don't need it for automated runs... What you think about it? I keep with this?
created_at: 2025-04-13T13:54:12Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,792 @@
+{
+	"info": {
+		"_postman_id": "5fd27f12-8cfd-4cf0-81b4-26f8421f0aa4",
+		"name": "Petclinic - Non Regression Tests",
+		"description": "## 🐾 Petclinic - Non Regression Tests\n\nThis Postman collection covers functional API flows to ensure the Petclinic app remains stable during changes.\n\n### 📑 Test Scenarios\n\n1. **01 - First Visit**\n    \n    - _Create Owner_: Registers a new pet owner.\n        \n    - _Create Pet_: Adds a pet to that owner.\n        \n    - _Create Visit_: Schedules the pet’s first visit.\n        \n\nMore flows can be added later, like:\n\n- \"02 - Returning Visit\"\n    \n- \"03 - Owner Edits, etc.\"\n    \n\n### 🛠 Environment Variables\n\n- `baseUrl`: URL of the running API (e.g., `http://localhost:9966/petclinic`)\n    \n- `ownerId`, `petId`: Dynamically set during test execution\n    \n\n### ▶️ Run Tests via Newman\n\n- Make sure that you have Node Js installed in your system\n    \n- Give permission to the script file with `chmod +x postman-tests.sh`\n    \n- With your application running... Run `./postman-tests.sh` in the root directory of the project or `sh postman-tests.sh` if you dont want to give permission to the script file.",
+		"schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json",
+		"_exporter_id": "29491402"
+	},
+	"item": [
+		{
+			"name": "01 - First Visit",
+			"item": [
+				{
+					"name": "Create Owner",
+					"event": [
+						{
+							"listen": "test",
+							"script": {
+								"exec": [
+									"pm.test(\"Owner created successfully\", function () {\r",
+									"    pm.response.to.have.status(201);\r",
+									"    \r",
+									"    const jsonData = pm.response.json();\r",
+									"    pm.expect(jsonData.id).to.be.a(\"number\");\r",
+									"    pm.expect(jsonData.firstName).to.eql(\"Anna Luísa\");\r",
+									"});\r",
+									"\r",
+									"pm.environment.set(\"ownerId\", pm.response.json().id);\r",
+									""
+								],
+								"type": "text/javascript",
+								"packages": {}
+							}
+						}
+					],
+					"request": {
+						"method": "POST",
+						"header": [
+							{
+								"key": "Content-Type",
+								"value": "application/json"
+							},
+							{
+								"key": "Accept",
+								"value": "application/json"
+							}
+						],
+						"body": {
+							"mode": "raw",
+							"raw": "{\n  \"address\": \"123 Brasilia Street\",\n  \"city\": \"Brasília\",\n  \"firstName\": \"Anna Luísa\",\n  \"lastName\": \"Medeiros\",\n  \"telephone\": \"1234567890\"\n}",
path: postman/petclinic-nonregressiontests.postman_collection.json
user: login: Isaac-Andradee
body: Haha, glad to see Anna Luísa made the cut! 😎
created_at: 2025-04-13T13:57:09Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,27 @@
+{
+	"id": "0c330e5d-586c-4245-b787-1225a2fa50be",
+	"name": "Petclinic Env",
+	"values": [
+		{
+			"key": "baseUrl",
+			"value": "http://localhost:9966/petclinic",
+			"type": "default",
+			"enabled": true
+		},
+		{
+			"key": "ownerId",
path: postman/petclinic-env.postman_environment.json
user: login: arey
body: According to your explanation, we can keep them.
created_at: 2025-04-13T15:44:54Z
author_association: MEMBER

PR comments:
user: login: arey
created_at: 2025-04-13T15:57:05Z
body: Everything looks good to me. I've tested the HTML report on my laptop and it's fine. I think we can merge.

Do you want to take on a 2nd scenario and integrate GitHub actions in anothers pull requests?
author_association: MEMBER
user: login: Isaac-Andradee
created_at: 2025-04-13T16:03:43Z
body: > Everything looks good to me. I've tested the HTML report on my laptop and it's fine. I think we can merge.
> 
> Do you want to take on a 2nd scenario and integrate GitHub actions in anothers pull requests?

Yes, in other PRs. Maybe you would open other issues about this? Or is it not necessary?
author_association: CONTRIBUTOR
user: login: arey
created_at: 2025-04-13T17:10:59Z
body: > Yes, in other PRs. Maybe you would open other issues about this? Or is it not necessary?

Not necessary ;)
author_association: MEMBER