Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -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
104 changes: 89 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,35 @@

<!-- TOC -->

* [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)

<!-- TOC -->

Expand Down Expand Up @@ -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/
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe 3. would be npm install -g @usebruno/cli (that is only seen below) ?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we create package.json or dependencies so we could just execute npm install?

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**
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Despite the suggestion, maybe worth to explain why such a report is useful?

Suggested change
**Run a Folder and Generate HRML Report**
**Run a Folder and Generate HTML Report**


1. Install Bruno CLI: `npm install -g @usebruno/cli`
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe step 0 would be to put up the application in docker?

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
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this step necessary to have spaces?
GET list of mentors and verify that mentor is deleted.bru

or could be like this:
get_active_mentors_and_delete_mentor.bru

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
Copy link
Contributor

@gpaOliveira gpaOliveira Jan 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This item-6 deserves some pointers to articles or how-to... are there some available?


**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
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe worth adding a stage in the CI to run the folder via CLI so we know when it breaks?

Suggested change
6. Ensure each request can be run sequentially as part of a folder execution
6. Ensure each request can be run sequentially as part of a folder execution by running the whole folder and making sure the HTML report is generated

1 change: 1 addition & 0 deletions admin-wcc-app/.gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
.vercel
.env
Binary file added api-flows/.DS_Store
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
meta {
name: API to update mentor data
type: http
seq: 4
}

put {
url: {{baseUrl}}/api/platform/v1/mentors/:mentorId
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is an automated way to populate the bruno collection in an openAPI format via the gradle build plugin ( similar to what we have done for generating the postman collection), not sure if that can help you import the endpoints quicker ?

Copy link
Contributor

@gpaOliveira gpaOliveira Jan 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unfortunately (bc I also got excited with that idea) I don't think openapi-generator supports Bruno, as neither their README nor the languages folder list it :(

We can be creative and parse the OpenAPI ourselves via a custom script and re-populate the Bruno URLs or do it manually, but either approach seems too much for this PR...

body: json
auth: apikey
}

params:path {
mentorId: {{userId}}
}

headers {
X-API-KEY: {{apiKey}}
}

auth:apikey {
key: X-API-KEY
value: {{apiKey}}
placement: header
}

body:json {
{{PUTpayload}}
}

script:pre-request {
const original = bru.getVar("payload");
const userId = bru.getVar("userId");

const putPayload = {
id: userId,
fullName: original.fullName,
position: bru.interpolate('{{$randomJobTitle}}'),
email: original.email,
slackDisplayName: original.slackDisplayName,
country: {
countryCode: original.country.countryCode,
countryName: original.country.countryName
},
city: original.city,
companyName: original.companyName,
//memberTypes: original.memberTypes
};

bru.setVar("PUTpayload", putPayload);
}
25 changes: 25 additions & 0 deletions api-flows/MentorRegisterUpdateDeleteFlow/Delete a member.bru
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
meta {
name: Delete a member
type: http
seq: 5
}

delete {
url: {{baseUrl}}/api/platform/v1/members/:memberId
body: none
auth: apikey
}

params:path {
memberId: {{userId}}
}

headers {
X-API-KEY: {{apiKey}}
}

auth:apikey {
key: X-API-KEY
value: {{apiKey}}
placement: header
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
meta {
name: GET list of members and verify that mentor is created
type: http
seq: 2
}

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.exist;
}
Original file line number Diff line number Diff line change
@@ -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;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
meta {
name: GET list of mentors and verify that mentor is created
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am wondering if tis the convention of use files with spaces in Bruno. For me it is a bit confuse 🙈

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;
}
Original file line number Diff line number Diff line change
@@ -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;
}
Loading
Loading