Skip to content
Merged
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
7 changes: 7 additions & 0 deletions tests/unit/authMiddleware.auth.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,18 +12,25 @@ import jwt from 'jsonwebtoken';
import { authenticate, optionalAuth } from '../../middleware/auth.js';
import { createMockReq, createMockRes } from '../helpers/mockUtils.js';

/**
* Test suite for JWT token authentication middleware.
* Tests token presence, format, validity, and expiration handling.
*/
describe('Auth Middleware - Token Handling', () => {
const originalEnv = process.env.JWT_SECRET;

// Set up test JWT secret for token generation
beforeAll(() => {
process.env.JWT_SECRET = 'test-secret-key-for-testing';
});

// Restore original JWT secret after tests
afterAll(() => {
process.env.JWT_SECRET = originalEnv;
});


// Tests for required authentication middleware (blocks unauthenticated)
describe('authenticate', () => {
it('should return 401 when no authorization header', () => {
const req = createMockReq();
Expand Down
11 changes: 11 additions & 0 deletions tests/unit/authMiddleware.roles.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,19 +11,28 @@ import { userAuth, adminAuth } from '../../middleware/auth.js';
import { USER_ROLES } from '../../config/constants.js';
import { createMockReq, createMockRes } from '../helpers/mockUtils.js';

/**
* Test suite for role-based access control middleware.
* Tests userAuth (resource ownership) and adminAuth (admin-only access).
*/
describe('Auth Middleware - Role-Based Access', () => {
const originalEnv = process.env.JWT_SECRET;

// Set up test JWT secret for token generation
beforeAll(() => {
process.env.JWT_SECRET = 'test-secret-key-for-testing';
});

// Restore original JWT secret after tests
afterAll(() => {
process.env.JWT_SECRET = originalEnv;
});


// Tests for user authorization middleware (resource ownership checks)
// Tests for user authorization: verifies owner access, denies others
describe('userAuth', () => {
// User accessing their own resource should be allowed
it('should allow access when user ID matches authenticated user', () => {
const validToken = jwt.sign(
{ userId: 123, username: 'testuser' },
Expand Down Expand Up @@ -134,7 +143,9 @@ describe('Auth Middleware - Role-Based Access', () => {
});
});

// Tests for admin authorization: only ADMIN role gets access
describe('adminAuth', () => {
// Admin token with ADMIN role should pass
it('should allow access for admin users', () => {
const adminToken = jwt.sign(
{ userId: 1, username: 'admin', role: USER_ROLES.ADMIN },
Expand Down
5 changes: 5 additions & 0 deletions tests/unit/favouriteService.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,15 @@ import * as favouriteService from '../../services/favouriteService.js';
import db from '../../config/db.js';
import { ValidationError, NotFoundError } from '../../utils/errors.js';

/**
* Test suite for favourite and disliked places service.
* Tests add, get, and remove operations for both favourites and dislikes.
*/
describe('Favourite Service', () => {
let testUserId;
let testPlaceId;

// Create test user and place before each test
beforeEach(async () => {
// Create test user and place
const user = await db.createUser({
Expand Down
10 changes: 8 additions & 2 deletions tests/unit/helpers.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,10 @@ import {
*/
describe('Helpers - Core Functions', () => {

// Tests for Haversine distance calculation between coordinates
describe('calculateDistance()', () => {

// Validates accurate distance calculations between known points
describe('Happy Path - Valid Distance Calculations', () => {

it('should calculate correctly the distance between two points', () => {
Expand Down Expand Up @@ -59,8 +61,10 @@ describe('Helpers - Core Functions', () => {

});

// Tests for user object sanitization (password removal)
describe('sanitizeUser()', () => {

// Verifies password field is removed from user objects
describe('Happy Path - Remove Password', () => {

it('should remove the password field from user object', () => {
Expand Down Expand Up @@ -123,8 +127,9 @@ describe('Helpers - Core Functions', () => {

});

// Tests for batch user sanitization
describe('sanitizeUsers()', () => {

// Should remove password from all users in array
it('should sanitize array of users', () => {
const users = [
{ userId: 1, username: 'user1', password: 'pass1' },
Expand All @@ -145,8 +150,9 @@ describe('Helpers - Core Functions', () => {

});

// Tests for pagination query parameter parsing
describe('parsePagination()', () => {

// Validates page and pageSize extraction from query
it('should parse pagination parameters', () => {
const result = parsePagination({ page: '2', pageSize: '10' });
expect(result).toEqual({ page: 2, pageSize: 10, skip: 10 });
Expand Down
11 changes: 11 additions & 0 deletions tests/unit/mongoDb.data.test.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
/**
* @fileoverview MongoDB Unit Tests - Data Operations
* @module tests/unit/mongoDb.data.test
*
* Tests MongoDB data layer operations including reviews and favourites.
* Uses in-memory MongoDB for isolated testing without external dependencies.
*/

import mongoDb from '../../config/mongoDb.js';
Expand All @@ -11,20 +14,28 @@ import {
clearMongoDbData
} from '../helpers/mongoDbSetup.js';

/**
* Test suite for MongoDB data operations.
* Covers review CRUD and favourite place management.
*/
describe('MongoDB Data Operations', () => {
// Initialize in-memory MongoDB before tests
beforeAll(async () => {
await setupMongoDb();
});

// Clean up MongoDB connection after tests
afterAll(async () => {
await teardownMongoDb();
});

// Reset data state before each test for isolation
beforeEach(async () => {
await clearMongoDbData();
});


// Tests for adding and retrieving place reviews
describe('Review Operations', () => {
let testUser;
let testPlace;
Expand Down
7 changes: 7 additions & 0 deletions tests/unit/mongoDb.user.test.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
/**
* @fileoverview MongoDB Unit Tests - User Operations
* @module tests/unit/mongoDb.user.test
*
* Tests MongoDB user data layer: user creation, email lookup, and settings.
* Uses in-memory MongoDB for fast, isolated test execution.
*/

import mongoDb from '../../config/mongoDb.js';
Expand All @@ -10,6 +13,10 @@ import {
clearMongoDbData
} from '../helpers/mongoDbSetup.js';

/**
* Test suite for MongoDB user operations.
* Covers createUser, findUserByEmail, and user settings management.
*/
describe('MongoDB User Operations', () => {
beforeAll(async () => {
await setupMongoDb();
Expand Down
5 changes: 5 additions & 0 deletions tests/unit/placeService.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,12 @@ import * as placeService from '../../services/placeService.js';
import db from '../../config/db.js';
import { ValidationError, NotFoundError } from '../../utils/errors.js';

/**
* Test suite for place service business logic.
* Tests CRUD operations and search functionality for places.
*/
describe('Place Service', () => {
// Tests for place creation with full and minimal data
describe('createPlace', () => {
it('should create a new place successfully', async () => {
const placeData = {
Expand Down
7 changes: 6 additions & 1 deletion tests/unit/preferenceController.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,14 +28,19 @@ jest.unstable_mockModule('../../config/db.js', () => ({
}
}));

// Import controller after mocking
// Import controller after mocking to ensure mocks are in place
const preferenceController = (await import('../../controllers/preferenceController.js')).default;

/**
* Test suite for preference controller error handling paths.
* Verifies that database errors are properly passed to next() middleware.
*/
describe('Preference Controller - Error Handling', () => {
let mockReq;
let mockRes;
let mockNext;

// Reset mocks and create fresh request/response objects
beforeEach(() => {
jest.clearAllMocks();

Expand Down
8 changes: 8 additions & 0 deletions tests/unit/preferenceService.crud.test.js
Original file line number Diff line number Diff line change
@@ -1,15 +1,23 @@
/**
* @fileoverview Unit Tests for Preference Service - CRUD Operations
* @module tests/unit/preferenceService.crud.test
*
* Tests preference profile CRUD: create, read, update operations.
* Validates ID formats in input and proper NotFoundError handling.
*/

import * as preferenceService from '../../services/preferenceService.js';
import db from '../../config/db.js';
import { ValidationError, NotFoundError } from '../../utils/errors.js';

/**
* Test suite for preference profile CRUD operations.
* Tests createPreferenceProfile, getPreferenceProfiles, getPreferenceProfile.
*/
describe('Preference Service - CRUD Operations', () => {
let testUserId;

// Create test user to own the preference profiles
beforeEach(async () => {
const user = await db.createUser({
username: 'prefuser',
Expand Down
8 changes: 8 additions & 0 deletions tests/unit/preferenceService.mutations.test.js
Original file line number Diff line number Diff line change
@@ -1,15 +1,23 @@
/**
* @fileoverview Unit Tests for Preference Service - Mutations
* @module tests/unit/preferenceService.mutations.test
*
* Tests preference profile mutation operations: update and delete.
* Validates ID formats in input and proper NotFoundError handling.
*/

import * as preferenceService from '../../services/preferenceService.js';
import db from '../../config/db.js';
import { ValidationError, NotFoundError } from '../../utils/errors.js';

/**
* Test suite for preference profile mutation operations.
* Tests updatePreferenceProfile and deletePreferenceProfile functions.
*/
describe('Preference Service - Mutations', () => {
let testUserId;

// Create test user to own the preference profiles
beforeEach(async () => {
const user = await db.createUser({
username: 'prefuser',
Expand Down
10 changes: 10 additions & 0 deletions tests/unit/responses.error.test.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
/**
* @fileoverview Response Utilities Tests - Error Responses
* @module tests/unit/responses.error.test
*
* Tests standardized error response functions for HTTP responses.
* Verifies correct status codes, error types, and message formatting.
*/

import {
Expand All @@ -14,10 +17,17 @@ import {
import { createMockRes } from '../helpers/mockUtils.js';


/**
* Test suite for error response utility functions.
* Tests sendError, sendValidationError, sendAuthError, sendForbiddenError,
* sendNotFoundError, and sendConflictError functions.
*/
describe('Response Utilities - Error Responses', () => {

// Tests for the generic sendError function with status codes and details
describe('sendError()', () => {

// Validates correct error response structure and status codes
describe('Happy Path - Error Responses', () => {

it('should return error with status code', () => {
Expand Down
10 changes: 9 additions & 1 deletion tests/unit/responses.success.test.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
/**
* @fileoverview Response Utilities Tests - Success Responses
* @module tests/unit/responses.success.test
*
* Tests standardized success response functions for HTTP responses.
* Verifies status codes, data structure, and pagination metadata.
*/

import {
Expand All @@ -11,11 +14,16 @@ import {
} from '../../utils/responses.js';
import { createMockRes } from '../helpers/mockUtils.js';


/**
* Test suite for success response utility functions.
* Tests sendSuccess, sendCreated, sendNoContent, sendPaginatedResponse.
*/
describe('Response Utilities - Success Responses', () => {

// Tests for generic success response with data and optional meta
describe('sendSuccess()', () => {

// Validates correct response structure and status codes
describe('Happy Path - Success Responses', () => {

it('should return 200 with data', () => {
Expand Down
7 changes: 6 additions & 1 deletion tests/unit/userController.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,19 @@ jest.unstable_mockModule('../../services/userService.js', () => ({
}
}));

// Import controller after mocking
// Import controller after mocking to ensure mocks are in place
const userController = (await import('../../controllers/userController.js')).default;

/**
* Test suite for user controller error handling paths.
* Verifies that service errors are properly passed to next() middleware.
*/
describe('User Controller - Error Handling', () => {
let mockReq;
let mockRes;
let mockNext;

// Reset mocks and create fresh request/response objects
beforeEach(() => {
jest.clearAllMocks();

Expand Down
7 changes: 7 additions & 0 deletions tests/unit/userService.profile.test.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,19 @@
/**
* @fileoverview Unit Tests for User Service - Profile Operations
* @module tests/unit/userService.profile.test
*
* Tests user profile service functions: get, update, delete operations.
* Validates data sanitization (password removal) and email uniqueness.
*/

import * as userService from '../../services/userService.js';
import db from '../../config/db.js';
import { ValidationError, NotFoundError, ConflictError } from '../../utils/errors.js';

/**
* Test suite for user profile service operations.
* Covers getUserProfile, updateUserProfile, deleteUser, getAllUsers.
*/
describe('User Service - Profile Operations', () => {
let testUser;

Expand Down
8 changes: 8 additions & 0 deletions tests/unit/userService.settings.test.js
Original file line number Diff line number Diff line change
@@ -1,15 +1,23 @@
/**
* @fileoverview Unit Tests for User Service - Settings Operations
* @module tests/unit/userService.settings.test
*
* Tests user settings management including language preferences,
* notifications, accessibility settings, and privacy options.
*/

import * as userService from '../../services/userService.js';
import db from '../../config/db.js';
import { ValidationError, NotFoundError } from '../../utils/errors.js';

/**
* Test suite for user settings service functions.
* Covers getUserSettings and updateUserSettings operations.
*/
describe('User Service - Settings Operations', () => {
let testUser;

// Create fresh test user before each test
beforeEach(async () => {
// Create a test user in DB
testUser = await db.createUser({
Expand Down
Loading