From 666b510ddef72fd6554d37c6a7f482ac9a8a7838 Mon Sep 17 00:00:00 2001 From: nora-weisser Date: Tue, 27 Jan 2026 21:40:26 +0100 Subject: [PATCH 1/4] feat: added bruno collection to craft API test flows --- README.md | 104 ++- admin-wcc-app/.gitignore | 1 + api-flows/.DS_Store | Bin 0 -> 6148 bytes .../API to update mentor data.bru | 51 ++ .../Delete a member.bru | 25 + ...bers and verify that mentor is created.bru | 39 + ...bers and verify that mentor is deleted.bru | 39 + ...tors and verify that mentor is created.bru | 39 + ...tors and verify that mentor is deleted.bru | 39 + .../Submit Mentor Registration.bru | 92 ++ .../MentorRegisterUpdateDeleteFlow/folder.bru | 8 + api-flows/bruno.json | 9 + api-flows/collection.bru | 0 api-flows/environments/local.bru | 4 + api-flows/results.html | 795 ++++++++++++++++++ 15 files changed, 1230 insertions(+), 15 deletions(-) create mode 100644 api-flows/.DS_Store create mode 100644 api-flows/MentorRegisterUpdateDeleteFlow/API to update mentor data.bru create mode 100644 api-flows/MentorRegisterUpdateDeleteFlow/Delete a member.bru create mode 100644 api-flows/MentorRegisterUpdateDeleteFlow/GET list of members and verify that mentor is created.bru create mode 100644 api-flows/MentorRegisterUpdateDeleteFlow/GET list of members and verify that mentor is deleted.bru create mode 100644 api-flows/MentorRegisterUpdateDeleteFlow/GET list of mentors and verify that mentor is created.bru create mode 100644 api-flows/MentorRegisterUpdateDeleteFlow/GET list of mentors and verify that mentor is deleted.bru create mode 100644 api-flows/MentorRegisterUpdateDeleteFlow/Submit Mentor Registration.bru create mode 100644 api-flows/MentorRegisterUpdateDeleteFlow/folder.bru create mode 100644 api-flows/bruno.json create mode 100644 api-flows/collection.bru create mode 100644 api-flows/environments/local.bru create mode 100644 api-flows/results.html diff --git a/README.md b/README.md index 81e00a5c..0a42b03c 100644 --- a/README.md +++ b/README.md @@ -2,21 +2,35 @@ -* [WCC: Platform Backend Service](#wcc-platform-backend-service) - * [How to start?](#how-to-start) - * [Setup locally](#setup-locally) - * [JAVA 21 with SDKMAN](#java-21-with-sdkman) - * [Setup IntelliJ](#setup-intellij) - * [Lombok](#lombok) - * [Enable Save Actions](#enable-save-actions) - * [Enable Checkstyle Warnings](#enable-checkstyle-warnings) - * [Google Format](#google-format) - * [IntelliJ JRE Config](#intellij-jre-config) - * [Setup PostgreSQL database](#setup-postgresql-database) - * [Run Locally](#run-locally) - * [Open API Documentation](#open-api-documentation) - * [Quality Checks](#quality-checks) - * [Deploy](#deploy) +- [WCC: Platform Backend Service](#wcc-platform-backend-service) + - [How to start?](#how-to-start) + - [Setup locally](#setup-locally) + - [JAVA 21 with SDKMAN](#java-21-with-sdkman) + - [Setup IntelliJ](#setup-intellij) + - [Lombok](#lombok) + - [Enable Save Actions](#enable-save-actions) + - [Enable Checkstyle Warnings](#enable-checkstyle-warnings) + - [Google Format](#google-format) + - [IntelliJ JRE Config](#intellij-jre-config) + - [Setup PostgreSQL database](#setup-postgresql-database) + - [Run Locally](#run-locally) + - [Run Locally without Authentication](#run-locally-without-authentication) + - [Generate Postman Collection](#generate-postman-collection) + - [Open API Documentation](#open-api-documentation) + - [API Documentation](#api-documentation) + - [Quality Checks](#quality-checks) + - [Deploy](#deploy) + - [Frontend (Administration Platform)](#frontend-administration-platform) + - [Run frontend locally](#run-frontend-locally) + - [Test credentials (seeded)](#test-credentials-seeded) + - [Frontend tests](#frontend-tests) + - [CORS configuration (backend)](#cors-configuration-backend) + - [CI/CD and deploy (Vercel)](#cicd-and-deploy-vercel) + - [API Testing Collection with Bruno](#api-testing-collection-with-bruno) + - [Prerequisites:](#prerequisites) + - [Open the Collection in Bruno](#open-the-collection-in-bruno) + - [Running Requests](#running-requests) + - [How to Add New Flows / Requests](#how-to-add-new-flows--requests) @@ -351,3 +365,63 @@ A GitHub Actions workflow is provided at `.github/workflows/deploy-admin-fronten - NEXT_PUBLIC_APP_URL (optional) Alternatively, you can connect the repository directly in Vercel dashboard and set env vars there. + +### API Testing Collection with Bruno + +`api-flows` folder contains a Bruno API flow used for testing, and validating our backend APIs in a consistent, shareable way. + +Bruno is a fast, Git-friendly API client (think Postman, but local-first and text-based). This flow is designed so the whole team can run the same requests with minimal setup and predictable results. + +#### Prerequisites: +Before using this flow, make sure you have: +1. Bruno installed: https://www.usebruno.com/ +2. Access to the target API environment (local/dev/staging) by running docker locally. + +#### Open the Collection in Bruno + +1. Open Bruno +2. Click Open Collection +3. Select the `api-flows` folder of this repository +4. Bruno will automatically load all requests and local environment variables. + +#### Running Requests +**Run a Single Request** +1. Select a request +2. Choose the correct environment (top-right) +3. Click Send + +**Run a Folder / Flow** +1. Right-click a folder +2. Select Run Folder +3. Bruno will execute requests in order + +This is useful for end-to-end flows like: + +Mentor creation → Get Mentors and validate if the mentor was created → Update Mentor data → Get Mentors and validate if the mentor was updated → Delete Mentor → Get Mentors and validate if the mentor was deleted + +**Run a Folder and Generate HRML Report** + +1. Install Bruno CLI: `npm install -g @usebruno/cli` +2. Execute Flow using this command: `bru run --env local --output results.html --format html` +3. Open report in browser + +#### How to Add New Flows / Requests + +Follow these guidelines to keep the collection consistent and easy to maintain. + +**Adding a New Request** +1. In Bruno, right-click the target folder +2. Select New Request +3. Give the request a clear, descriptive name +4. Select the HTTP method and configure the endpoint, headers, and body +5. Use environment variables (e.g. {{baseUrl}}, {{mentorId}}) instead of hardcoded values +6. Use faker built-in faker library to generate realistic data for payloads + +**Adding a New Flow (Folder)** + +1. Right-click in the collection root or relevant parent folder +2. Select New Folder +3. Name the folder after the business flow or feature +4. Example: `Mentee Registration & Approval Flow`, `Matching Flow` +5. Add requests in the order they should be executed +6. Ensure each request can be run sequentially as part of a folder execution diff --git a/admin-wcc-app/.gitignore b/admin-wcc-app/.gitignore index e985853e..83baf963 100644 --- a/admin-wcc-app/.gitignore +++ b/admin-wcc-app/.gitignore @@ -1 +1,2 @@ .vercel +.env \ No newline at end of file diff --git a/api-flows/.DS_Store b/api-flows/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..b1d7f33d9316318916164ecd2d233321f46d179b GIT binary patch literal 6148 zcmeHKO>5gg5S?}0MkX!z&_YgSp;tqlq-_Yf2-oQ?m#80yq_`3?si>kgk{lh3LFe`l z<(KsL^v&+Zv`up=m?q4?%p1+l?0VnAu7`-!XrAs6^@%8eGIn|}e-R#My&)YR*#Ig# zM@fbXx}Yhn$X#H7&+d^uuS?44*Ym5Xx{S&qH^n(}aK7}6j%{X*Q!eQQ{yAzYs^OLN zo@SI%Y`?~cFw@bvC*W9&QGk!B+4o`eK@>j_Y|f zipx{}dS^_YT>EkIA)7Xn{*yPRsN<}dmbM^Er${;bm=&pMMrK~5m9353K+p?%lm7N% zvAh3jp!fCufG?X#)*gCXV2aIh2fL(;Gz~^3qYqZDE zW9twj5amjNu2lIJL%DLqwa*JZwhmo6Dc^i3zq0Zjin6O?er?l9g$~6E1H!=X3~=uU z>GS)4bbJ4Alf(!E!odAxKy}B_c!a(AxAn#@`K{H^&rlZ5YaOmi;Mk`ax%?DwL#-gL X*#U+gTZf21 m.id === userId); + + expect( + mentor, + `Mentor with id ${userId} should be present in mentors list` + ).to.exist; +} diff --git a/api-flows/MentorRegisterUpdateDeleteFlow/GET list of members and verify that mentor is deleted.bru b/api-flows/MentorRegisterUpdateDeleteFlow/GET list of members and verify that mentor is deleted.bru new file mode 100644 index 00000000..fa303a51 --- /dev/null +++ b/api-flows/MentorRegisterUpdateDeleteFlow/GET list of members and verify that mentor is deleted.bru @@ -0,0 +1,39 @@ +meta { + name: GET list of members and verify that mentor is deleted + type: http + seq: 6 +} + +get { + url: {{baseUrl}}/api/platform/v1/members + body: none + auth: apikey +} + +headers { + X-API-KEY: {{apiKey}} +} + +auth:apikey { + key: X-API-KEY + value: {{apiKey}} + placement: header +} + +tests { + test("Response Status is OK (200)", function() { + expect(res.getStatus()).to.equal(200); + }); + + const mentors = res.body; + const userId = Number(bru.getEnvVar("userId")); + + expect(mentors, "Mentors response should be an array").to.be.an('array'); + + const mentor = mentors.find(m => m.id === userId); + + expect( + mentor, + `Mentor with id ${userId} should be present in mentors list` + ).to.not.exist; +} diff --git a/api-flows/MentorRegisterUpdateDeleteFlow/GET list of mentors and verify that mentor is created.bru b/api-flows/MentorRegisterUpdateDeleteFlow/GET list of mentors and verify that mentor is created.bru new file mode 100644 index 00000000..7116217c --- /dev/null +++ b/api-flows/MentorRegisterUpdateDeleteFlow/GET list of mentors and verify that mentor is created.bru @@ -0,0 +1,39 @@ +meta { + name: GET list of mentors and verify that mentor is created + type: http + seq: 3 +} + +get { + url: {{baseUrl}}/api/platform/v1/mentors + body: none + auth: apikey +} + +headers { + X-API-KEY: {{apiKey}} +} + +auth:apikey { + key: X-API-KEY + value: {{apiKey}} + placement: header +} + +tests { + test("Response Status is OK (200)", function() { + expect(res.getStatus()).to.equal(200); + }); + + const mentors = res.body; + const userId = Number(bru.getEnvVar("userId")); + + expect(mentors, "Mentors response should be an array").to.be.an('array'); + + const mentor = mentors.find(m => m.id === userId); + + expect( + mentor, + `Mentor with id ${userId} should be present in mentors list` + ).to.exist; +} diff --git a/api-flows/MentorRegisterUpdateDeleteFlow/GET list of mentors and verify that mentor is deleted.bru b/api-flows/MentorRegisterUpdateDeleteFlow/GET list of mentors and verify that mentor is deleted.bru new file mode 100644 index 00000000..8805a708 --- /dev/null +++ b/api-flows/MentorRegisterUpdateDeleteFlow/GET list of mentors and verify that mentor is deleted.bru @@ -0,0 +1,39 @@ +meta { + name: GET list of mentors and verify that mentor is deleted + type: http + seq: 7 +} + +get { + url: {{baseUrl}}/api/platform/v1/mentors + body: none + auth: apikey +} + +headers { + X-API-KEY: {{apiKey}} +} + +auth:apikey { + key: X-API-KEY + value: {{apiKey}} + placement: header +} + +tests { + test("Response Status is OK (200)", function() { + expect(res.getStatus()).to.equal(200); + }); + + const mentors = res.body; + const userId = Number(bru.getEnvVar("userId")); + + expect(mentors, "Mentors response should be an array").to.be.an('array'); + + const mentor = mentors.find(m => m.id === userId); + + expect( + mentor, + `Mentor with id ${userId} should be present in mentors list` + ).to.not.exist; +} diff --git a/api-flows/MentorRegisterUpdateDeleteFlow/Submit Mentor Registration.bru b/api-flows/MentorRegisterUpdateDeleteFlow/Submit Mentor Registration.bru new file mode 100644 index 00000000..0f3974c7 --- /dev/null +++ b/api-flows/MentorRegisterUpdateDeleteFlow/Submit Mentor Registration.bru @@ -0,0 +1,92 @@ +meta { + name: Submit Mentor Registration + type: http + seq: 1 +} + +post { + url: {{baseUrl}}/api/platform/v1/mentors + body: json + auth: apikey +} + +headers { + X-API-KEY: {{apiKey}} +} + +auth:apikey { + key: X-API-KEY + value: {{apiKey}} + placement: header +} + +body:json { + {{payload}} +} + +script:pre-request { + const countryCode = bru.interpolate('{{$randomCountryCode}}'); + const countryName = bru.interpolate('{{$randomCountry}}'); + + const fullName = bru.interpolate('{{$randomFullName}}'); + + const email = bru.interpolate(`{{$randomEmail}}`).toLowerCase(); + const slackDisplayName = fullName + .toLowerCase() + .replace(/\s+/g, '.'); + + const city = bru.interpolate('{{$randomCity}}'); + + const payload = { + fullName, + position: bru.interpolate('{{$randomJobTitle}}'), + email, + slackDisplayName, + country: { + countryCode, + countryName + }, + city, + companyName: bru.interpolate('{{$randomCompanyName}}'), + memberTypes: ["MENTOR"], + images: [], + network: [], + profileStatus: "PENDING", + skills: { + yearsExperience: 10, + areas: ["Quality Assurance"], + languages: ["Python", "Javascript", "Java"], + mentorshipFocus: ["Switch career to IT"] + }, + spokenLanguages: ["English", "Portuguese"], + bio: bru.interpolate('{{$randomLoremSentences}}'), + menteeSection: { + mentorshipType: ["LONG_TERM"], + availability: [ + { month: 6, hours: 2 }, + { month: 7, hours: 2 }, + { month: 8, hours: 2 }, + { month: 9, hours: 2 }, + { month: 10, hours: 2 }, + { month: 11, hours: 2 } + ], + idealMentee: bru.interpolate('{{$randomLoremSentence}}'), + additional: "Best practices" + } + }; + + bru.setVar("payload", payload); + +} + +script:post-response { + const id = res.body.id; + bru.setEnvVar("userId", id); + +} + +tests { + test("Response Status is OK (200)", function() { + expect(res.getStatus()).to.equal(201); + }); +} diff --git a/api-flows/MentorRegisterUpdateDeleteFlow/folder.bru b/api-flows/MentorRegisterUpdateDeleteFlow/folder.bru new file mode 100644 index 00000000..df87159d --- /dev/null +++ b/api-flows/MentorRegisterUpdateDeleteFlow/folder.bru @@ -0,0 +1,8 @@ +meta { + name: MentorRegisterUpdateDeleteFlow + seq: 2 +} + +auth { + mode: inherit +} diff --git a/api-flows/bruno.json b/api-flows/bruno.json new file mode 100644 index 00000000..704523eb --- /dev/null +++ b/api-flows/bruno.json @@ -0,0 +1,9 @@ +{ + "version": "1", + "name": "APIFlows", + "type": "collection", + "ignore": [ + "node_modules", + ".git" + ] +} \ No newline at end of file diff --git a/api-flows/collection.bru b/api-flows/collection.bru new file mode 100644 index 00000000..e69de29b diff --git a/api-flows/environments/local.bru b/api-flows/environments/local.bru new file mode 100644 index 00000000..f450321c --- /dev/null +++ b/api-flows/environments/local.bru @@ -0,0 +1,4 @@ +vars { + baseUrl: http://localhost:8080 + apiKey: local +} diff --git a/api-flows/results.html b/api-flows/results.html new file mode 100644 index 00000000..07e05d3b --- /dev/null +++ b/api-flows/results.html @@ -0,0 +1,795 @@ + + + + + + + + + Bruno + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + From 9abfed02554ee9268690b0e7d1594c9460ee68f7 Mon Sep 17 00:00:00 2001 From: nora-weisser Date: Tue, 27 Jan 2026 21:46:29 +0100 Subject: [PATCH 2/4] feat: updated README --- README.md | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index 0a42b03c..bb142f01 100644 --- a/README.md +++ b/README.md @@ -26,11 +26,11 @@ - [Frontend tests](#frontend-tests) - [CORS configuration (backend)](#cors-configuration-backend) - [CI/CD and deploy (Vercel)](#cicd-and-deploy-vercel) - - [API Testing Collection with Bruno](#api-testing-collection-with-bruno) - - [Prerequisites:](#prerequisites) - - [Open the Collection in Bruno](#open-the-collection-in-bruno) - - [Running Requests](#running-requests) - - [How to Add New Flows / Requests](#how-to-add-new-flows--requests) + - [API Testing Collection with Bruno](#api-testing-collection-with-bruno) + - [Prerequisites](#prerequisites) + - [Open the Collection in Bruno](#open-the-collection-in-bruno) + - [Running Requests](#running-requests) + - [How to Add New Flows / Requests](#how-to-add-new-flows--requests) @@ -366,25 +366,25 @@ A GitHub Actions workflow is provided at `.github/workflows/deploy-admin-fronten Alternatively, you can connect the repository directly in Vercel dashboard and set env vars there. -### API Testing Collection with Bruno +## API Testing Collection with Bruno `api-flows` folder contains a Bruno API flow used for testing, and validating our backend APIs in a consistent, shareable way. Bruno is a fast, Git-friendly API client (think Postman, but local-first and text-based). This flow is designed so the whole team can run the same requests with minimal setup and predictable results. -#### Prerequisites: +### Prerequisites Before using this flow, make sure you have: 1. Bruno installed: https://www.usebruno.com/ 2. Access to the target API environment (local/dev/staging) by running docker locally. -#### Open the Collection in Bruno +### Open the Collection in Bruno 1. Open Bruno 2. Click Open Collection 3. Select the `api-flows` folder of this repository 4. Bruno will automatically load all requests and local environment variables. -#### Running Requests +### Running Requests **Run a Single Request** 1. Select a request 2. Choose the correct environment (top-right) @@ -405,7 +405,7 @@ Mentor creation → Get Mentors and validate if the mentor was created → Updat 2. Execute Flow using this command: `bru run --env local --output results.html --format html` 3. Open report in browser -#### How to Add New Flows / Requests +### How to Add New Flows / Requests Follow these guidelines to keep the collection consistent and easy to maintain. From c6a7dbefef535d03560545bf627403467ca0d703 Mon Sep 17 00:00:00 2001 From: nora-weisser Date: Tue, 27 Jan 2026 21:49:41 +0100 Subject: [PATCH 3/4] feat: deleted results from PR --- api-flows/results.html | 795 ----------------------------------------- 1 file changed, 795 deletions(-) delete mode 100644 api-flows/results.html diff --git a/api-flows/results.html b/api-flows/results.html deleted file mode 100644 index 07e05d3b..00000000 --- a/api-flows/results.html +++ /dev/null @@ -1,795 +0,0 @@ - - - - - - - - - Bruno - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - - From 28f4b8f42839fe0800ae2b19439874d7b7ff0d0c Mon Sep 17 00:00:00 2001 From: nora-weisser Date: Tue, 27 Jan 2026 21:51:06 +0100 Subject: [PATCH 4/4] feat: added results.html from bruno to gitignore --- .gitignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitignore b/.gitignore index 2f45f2ab..143b6ee8 100644 --- a/.gitignore +++ b/.gitignore @@ -38,3 +38,6 @@ src/main/resources/application-local.yml /scripts/init-dev-env.sh .vercel /scripts/init-prod-env.sh + +# bruno +api-flows/results.html