Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
62a0aac
feat: install and config jest enviroment
Jaedsonn Jan 24, 2026
3cace74
feat: add tests for bodyParser middleware and comparePasswords utility
Jaedsonn Jan 24, 2026
bbab926
refactor: improve tests for bodyParser middleware with consistent str…
Jaedsonn Jan 24, 2026
ea1c7ad
refactor: rename folder unity to unit
Jaedsonn Jan 24, 2026
077c0d1
feat: add healthcheck for postgres services and update test scripts i…
Jaedsonn Jan 24, 2026
2fca782
feat: implement authentication tests and setup test database configur…
Jaedsonn Jan 24, 2026
4ff3482
feat: update CI pipeline to support dynamic branch handling and add i…
Jaedsonn Jan 24, 2026
856cce2
refactor: streamline CI pipeline steps by removing unnecessary error …
Jaedsonn Jan 24, 2026
2102ead
lint: fix lint errors
Jaedsonn Jan 24, 2026
855cd9d
fix: ignoring audit critical dependencies because the dependencie cla…
Jaedsonn Jan 24, 2026
a7ee822
feat: add MCP configuration file for Atlassian server integration
Jaedsonn Jan 24, 2026
11c8a12
fix: correct command for installing dependencies in CI pipeline
Jaedsonn Jan 24, 2026
9db489b
fix: remove security audit step from CI pipeline
Jaedsonn Jan 24, 2026
466566f
fix: update docker-compose commands to use 'docker compose' syntax
Jaedsonn Jan 24, 2026
dcc2136
fix: simplify docker compose commands in CI pipeline
Jaedsonn Jan 24, 2026
57b6095
fix: update database readiness check in CI pipeline
Jaedsonn Jan 24, 2026
861c9e9
fix: add environment variables for database and email configuration i…
Jaedsonn Jan 24, 2026
aabfe19
fix: move environment variables to the test job in CI pipeline
Jaedsonn Jan 24, 2026
b4ddca1
refactor: put CI run push only in main branch
Jaedsonn Jan 24, 2026
dcf9cf9
fix: update docker-compose and database initialization for testing en…
Jaedsonn Jan 25, 2026
f2a042d
fix: correct database service name in readiness check
Jaedsonn Jan 25, 2026
e1f329f
fix: change password hash to use a new variable do password_digest in…
Jaedsonn Jan 28, 2026
3fcf1a8
fix: standardize error message for invalid credentials and improve au…
Jaedsonn Jan 29, 2026
19dca17
feat: implement integration tests for UserService and export MockEmai…
Jaedsonn Jan 29, 2026
aff109a
lint: remove ununsed import from auth service test file
Jaedsonn Jan 29, 2026
6275d13
feat: bank details
Jaedsonn Jan 30, 2026
73d1393
lint: fix bank service let variable and disable logging
Jaedsonn Jan 30, 2026
56448d6
feat: create new utility functions to help in tests
Jaedsonn Jan 30, 2026
61b720f
feat: enhance Jest configuration, improve error handling in AccountSe…
Jaedsonn Jan 31, 2026
74654a2
Merge branch 'main' into KAN-15-arch-005-implementar-testes
Jaedsonn Jan 31, 2026
8c7aaee
fix: improve error logging during Data Source initialization and stre…
Jaedsonn Jan 31, 2026
1e3a786
Merge branch 'KAN-15-arch-005-implementar-testes' of github.com-pesso…
Jaedsonn Jan 31, 2026
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
77 changes: 61 additions & 16 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,46 +3,35 @@ name: "CI pipeline"
on:
push:
branches:
- main
- 'main'

pull_request:
branches:
- main
- '**'

jobs:
build:
runs-on: ubuntu-latest

steps:
- name: Checkout repository

uses: actions/checkout@v5

- name: Set up Node.js

uses: actions/setup-node@v5

with:
node-version: "18"

cache: "npm"

- name: Install dependencies

run: npm ci --audit false

- name: Lint code

run: npm run lint || echo "Lint check failed, but continuing..."
run: npm run lint

- name: Build application

run: npm run build

- name: Run security audit

run: npm audit || echo "Security vulnerabilities found, but continuing..."

- name: Cache node_modules
uses: actions/cache@v4

Expand All @@ -58,10 +47,66 @@ jobs:
${{ runner.os }}-modules-

- name: Upload build artifacts

uses: actions/upload-artifact@v4
with:
name: build
path: dist/

test:
runs-on: ubuntu-latest
needs: build
env:
DB_HOST: localhost
DB_PORT: 5432
DB_USERNAME: postgres
DB_PASSWORD: postgres
DB_DATABASE: payment_records
PORT: 3000
FRONTEND_URL: http://localhost:5173
SMTP_HOST: smtp.example.com
EMAIL_USER: email@gmail.com
EMAIL_PASS: your-email-password
ACCESS_SECRET: secret1
ACCESS_EXPIRE: 15m
REFRESH_SECRET: secret2
REFRESH_EXPIRE: 7d
RESET_SECRET: secret3
RESET_EXPIRE: 15m

steps:
- name: Checkout repository
uses: actions/checkout@v5

- name: Set up Node.js
uses: actions/setup-node@v5
with:
node-version: "18"
cache: "npm"

- name: Install dependencies
run: npm ci --audit false

- name: Download build artifacts
uses: actions/download-artifact@v4
with:
name: build
Copy link

Copilot AI Jan 24, 2026

Choose a reason for hiding this comment

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

The build artifacts are downloaded but there's no specified path parameter, which means they will be downloaded to the current directory. However, the build artifacts should be placed in the 'dist/' directory to match the project structure. Add 'path: dist/' to this step's 'with' configuration.

Suggested change
name: build
name: build
path: dist/

Copilot uses AI. Check for mistakes.

path: dist/
- name: Up docker services
run: docker compose up -d --build

- name: Wait for Database
run: |
until docker exec payment_records_db pg_isready; do
echo "Waiting for database..."
sleep 2
done

- name: 'Run unit tests'
run: npm run test:unit

- name: 'Run integration tests'
run: npm run test:integration

- name: Stop containers
if: always()
run: docker compose down
11 changes: 11 additions & 0 deletions .vscode/mcp.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"servers": {
"atlassian/atlassian-mcp-server": {
"type": "http",
"url": "https://mcp.atlassian.com/v1/sse",
"gallery": "https://api.mcp.github.com",
"version": "1.0.0"
}
},
"inputs": []
}
Comment on lines +1 to +11
Copy link

Copilot AI Jan 24, 2026

Choose a reason for hiding this comment

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

This VSCode configuration file for the Atlassian MCP server appears to be unrelated to the test implementation work described in the PR. Unless this is intentionally part of the development setup for this project, it should likely be excluded from this PR or added to .gitignore to prevent individual developer configurations from being committed.

Suggested change
{
"servers": {
"atlassian/atlassian-mcp-server": {
"type": "http",
"url": "https://mcp.atlassian.com/v1/sse",
"gallery": "https://api.mcp.github.com",
"version": "1.0.0"
}
},
"inputs": []
}
{}

Copilot uses AI. Check for mistakes.
12 changes: 8 additions & 4 deletions docker-compose.yaml
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
services:
postgres:
image: postgres:latest
container_name: payment_records
container_name: payment_records_db
ports:
- "5432:5432"
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres"]
interval: 10s
timeout: 5s
retries: 5
environment:
POSTGRES_HOST: localhost
POSTGRES_PORT: 5432
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
POSTGRES_DB: payment_records
volumes:
- ./init-db.sql:/docker-entrypoint-initdb.d/init-db.sql
2 changes: 2 additions & 0 deletions init-db.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
CREATE DATABASE payment_records;
CREATE DATABASE payment_records_test;
17 changes: 17 additions & 0 deletions jest.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
const { pathsToModuleNameMapper } = require("ts-jest");
const { compilerOptions } = require("./tsconfig.json");

/** @type {import("jest").Config} **/
module.exports = {
testEnvironment: "node",
preset: "ts-jest",
moduleNameMapper: pathsToModuleNameMapper(compilerOptions.paths, { prefix: "<rootDir>/src" }),

transformIgnorePatterns: [
"node_modules/(?!@faker-js/faker)"
],

transform: {
"^.+\\.(t|j)sx?$": ["ts-jest", { useESM: true }],
},
};
24 changes: 20 additions & 4 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
"@asteasolutions/zod-to-openapi": "^8.4.0",
"@types/cors": "^2.8.19",
"@types/express": "^5.0.3",
"@types/faker": "^6.6.8",
"@types/jsonwebtoken": "^9.0.10",
"@types/node": "^24.3.0",
"@types/nodemailer": "^7.0.1",
Expand All @@ -41,7 +42,7 @@
},
"devDependencies": {
"@eslint/js": "^9.34.0",
"@faker-js/faker": "^10.0.0",
"@faker-js/faker": "^10.2.0",
"@types/jest": "^30.0.0",
"eslint": "^9.34.0",
"globals": "^16.3.0",
Expand Down
4 changes: 1 addition & 3 deletions src/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,12 +46,10 @@ app.get("/health", (_req, res) => {

AppDataSource.initialize()
.then(() => {
console.log("Data Source has been initialized!");
app.listen(port, async () => {
console.log(`Server is running on port ${port}`);
await runSeeds();
});
})
.catch((err) => {
console.error("Error during Data Source initialization:", err);
console.error("Error during Data Source initialization", err);
});
4 changes: 2 additions & 2 deletions src/lib/enums.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,8 @@ export const ErrorEnum = {
NOT_FOUND: { message: "Not Found", status: 404 },
CONFLICT: { message: "Conflict", status: 409 },
INTERNAL_SERVER_ERROR: { message: "Internal Server Error", status: 500 },
USER_ALREADY_EXISTS: { message: "User Already Exists", status: 409 },
INVALID_CREDENTIALS: { message: "Invalid Credentials", status: 401 },
USER_ALREADY_EXISTS: { message: "User already exists", status: 409 },
INVALID_CREDENTIALS: { message: "Invalid credentials", status: 401 },
VALIDATION_ERROR: { message: "Validation Error", status: 400 },
INSUFFICIENT_FUNDS: { message: "Insufficient Funds", status: 400 },
ACCOUNT_BLOCKED: { message: "Account Blocked", status: 403 },
Expand Down
32 changes: 32 additions & 0 deletions src/lib/utils.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
import bcrypt from "bcryptjs";
import { IncomingHttpHeaders } from "http";
import { faker } from "@faker-js/faker"; // search for an alternative with ESM support
import { CreateUserSchema, CreateAccountSchema, CreateBankSchema } from "./schema";
import { Account as accountEnum } from "./enums";
import z from 'zod';

export const hashPassword = async (password: string): Promise<string> => {
const salt = await bcrypt.genSalt(10);
Expand Down Expand Up @@ -33,3 +37,31 @@ export const extractTokenFromHeader = (

return config;
};

export function generateRandomUser(): z.infer<typeof CreateUserSchema> {
return {
name: faker.person.fullName(),
age: faker.number.int({ min: 18, max: 80 }),
email: faker.internet.email(),
password: faker.internet.password()
};
}

export function generateRandomBank(): z.infer<typeof CreateBankSchema> {
return {
name: faker.company.name() + " Bank",
code: faker.number.int({ min: 1000, max: 9999 }).toString()
};
}

export function generateRandomAccount(bankId: string): z.infer<typeof CreateAccountSchema> {
return {
accountNumber: faker.finance.accountNumber({ length: 10 }),
agency: faker.number.int({ min: 1000, max: 9999 }).toString(),
accountType: faker.helpers.arrayElement([accountEnum.CHECKING, accountEnum.SAVINGS]),
name: faker.finance.accountName(),
bankId
};
}

export const getRandomFromArray = (length: number): number => Math.floor(Math.random() * length);
10 changes: 7 additions & 3 deletions src/modules/Account/account.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,9 @@ export default class AccountService {
accountNumber: string,
userId: string
): Promise<Account | null> {
if (!accountNumber || !userId) {
throw new Error(ErrorEnum.BAD_REQUEST.message);
}
return this.accountRepository.findOne({
where: { accountNumber, user: { id: userId } },
relations: ["bank"],
Expand Down Expand Up @@ -150,19 +153,20 @@ export default class AccountService {
accountId: string,
userId: string
): Promise<DefaultMessage> {
const account = await this.accountRepository.findOne({
const account = await this.accountRepository.find({
where: { id: accountId, user: { id: userId } },
select: ["balance"],
});

if (!account) {

if (!account || account.length === 0) {
throw new Error(ErrorEnum.NOT_FOUND.message);
}

return {
success: true,
message: `Account balance retrieved successfully`,
data: { balance: account.balance },
data: { balance: account[0].balance },
};
}
}
Loading