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
14 changes: 13 additions & 1 deletion .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,18 @@
"<node_internals>/**"
],
"program": "${workspaceFolder}\\server.js"
}
},
{
"name": "Debug Jest Tests",
"type": "node",
"request": "launch",
"runtimeArgs": [
"--inspect-brk",
"${workspaceRoot}/node_modules/jest/bin/jest.js",
"--runInBand"
],
"console": "integratedTerminal",
"internalConsoleOptions": "neverOpen",
}
]
}
122 changes: 42 additions & 80 deletions __tests__/api.test.js
Original file line number Diff line number Diff line change
@@ -1,94 +1,56 @@
const { MongoClient } = require('mongodb');
const { MongoMemoryServer } = require('mongodb-memory-server');
const classController = require('../controllers/classController');
const httpMocks = require('node-mocks-http');
const mongoose = require('mongoose');
const app = require('../server');
const request = require('supertest');
const {initDb} = require('../data/database')

describe('classController Integration Tests', () => {
describe('Test routes, GET -- student, class, teacher, grade, and unknow route', () => {
let mongoServer;
let connection;
let db;

beforeAll(async () => {
// Create an in-memory MongoDB instance
beforeEach(async () => {
mongoServer = await MongoMemoryServer.create();
const mongoUri = mongoServer.getUri();

// Create a MongoDB connection
connection = await MongoClient.connect(mongoUri);
db = connection.db();

// Mock the database.js getDb function
jest.spyOn(require('../data/database'), 'getDb').mockReturnValue(db);
});

afterAll(async () => {
// Clean up resources
await connection.close();
await mongoServer.stop();
});

describe('getAll', () => {
let req;
let res;

beforeEach(async () => {
// Create fresh request and response mocks
req = httpMocks.createRequest();
res = httpMocks.createResponse({
eventEmitter: require('events').EventEmitter
const mongodbUrl = mongoServer.getUri();
await mongoose.connect(mongodbUrl);
await new Promise((resolve, reject) => {
initDb((err) => {
if (err) return reject(err);
resolve();
});

// Clear the collection before each test
await db.collection('class').deleteMany({});
});
}, 5000); // Optional: increase timeout if Jest times out here

it('should return all classes with 200 status when classes exist', async () => {
// Arrange: Insert test data
const testClasses = [
{
course_code: 'MATH101',
subject: 'Mathematics',
class_description: 'Calculus I',
max_class_size: 30
},
{
course_code: 'PHY201',
subject: 'Physics',
class_description: 'Mechanics',
max_class_size: 25
}
];
await db.collection('class').insertMany(testClasses);

// Act: Call getAll
const getAllHandler = classController.getAll();
await getAllHandler(req, res);
afterEach(async () => {
await mongoose.disconnect();
await mongoServer.stop();
});

// Wait for the response to be complete
await new Promise(resolve => res.once('end', resolve));
test('should retrieve all classes', async () => {
const response = await request(app).get('/class');
expect(response.status).toBe(200);
expect(response.body).toBeInstanceOf(Array);
});

// Assert
expect(res.statusCode).toBe(200);
const responseData = JSON.parse(res._getData());
expect(responseData).toHaveLength(2);
expect(responseData[0].course_code).toBe('MATH101');
expect(responseData[1].course_code).toBe('PHY201');
});
test('should retrieve all grades', async () => {
const response = await request(app).get('/grade');
expect(response.status).toBe(200);
expect(response.body).toBeInstanceOf(Array);
});

it('should return 404 status when no classes exist', async () => {
// Act: Call getAll with empty database
const getAllHandler = classController.getAll();
await getAllHandler(req, res);
test('should retrieve all students', async () => {
const response = await request(app).get('/student');
expect(response.status).toBe(200);
expect(response.body).toBeInstanceOf(Array);
});

// Wait for the response to be complete
await new Promise(resolve => res.once('end', resolve));
test('should retrieve all teachers', async () => {
const response = await request(app).get('/teacher');
expect(response.status).toBe(200);
expect(response.body).toBeInstanceOf(Array);
});

// Assert
expect(res.statusCode).toBe(404);
const responseData = JSON.parse(res._getData());
expect(responseData).toEqual({
message: 'No classes found in the database'
});
});
test('should retrieve a grade by ID', async () => {
const response = await request(app).get(`/grade/67099593204dafb2be0993d8`);
expect(response.status).toBe(401);
expect(response.body).toBe('You do not have access.Please Authenticate.');
});
});
});
54 changes: 28 additions & 26 deletions __tests__/database.test.js
Original file line number Diff line number Diff line change
@@ -1,31 +1,33 @@
// __tests__/database.test.js
const { MongoClient } = require('mongodb');
const { initDb, getDb } = require('../data/database');
const {MongoClient} = require('mongodb');
const {initDb} = require('../data/database.js');

jest.mock('mongodb');
describe('Database test', function () {
let connection;
let db;

describe('Database Connection', () => {
beforeAll((done) => {
const mockDb = {
collection: jest.fn().mockReturnValue({
insertOne: jest.fn().mockResolvedValue({ acknowledged: true }),
}),
};

const mockClient = { db: jest.fn().mockReturnValue(mockDb) };

MongoClient.connect.mockResolvedValue(mockClient);

// Initialize database with callback
initDb(done);
beforeEach(async () => {
connection = await MongoClient.connect(process.env.DB_URI, {
useNewUrlParser: true,
useUnifiedTopology: true,
});
db = await new Promise((resolve, reject) => {
initDb((err) => {
if (err) return reject(err);
resolve();
});

}, 5000); // Optional: increase timeout if Jest times out here

test('should initialize the database and perform an insert operation', async () => {
const db = getDb();
expect(db).toBeDefined();
});

const collection = db.collection('test');
await collection.insertOne({ test: 'data' });
expect(collection.insertOne).toHaveBeenCalledWith({ test: 'data' });
});
});
afterEach(async () => {
await connection.close();
});

it('should get students', async () => {
const users = connection.db().collection('student');
const student = await users.find().toArray()
expect(student).toBeInstanceOf(Array);
});

});
49 changes: 35 additions & 14 deletions __tests__/server.test.js
Original file line number Diff line number Diff line change
@@ -1,20 +1,41 @@
const request = require('supertest');
const { MongoMemoryServer } = require('mongodb-memory-server');
const mongoose = require('mongoose');
const app = require('../server.js');
const dbb = require('../data/database.js');
const request = require('supertest');
const {initDb, closeDb} = require('../data/database')
const dotenv = require('dotenv').config()

describe('Server and API Endpoints', () => {
// beforeAll(async () => {
// dbb.initDb(); // Ensure database is initialized
// });
describe('Test server, GET student and unknow route', () => {
let mongoServer;

beforeEach(async () => {
mongoServer = await MongoMemoryServer.create();
const mongodbUrl = mongoServer.getUri();
await mongoose.connect(mongodbUrl);
await new Promise((resolve, reject) => {
initDb((err) => {
if (err) return reject(err);
resolve();
});
});
}, 10000); // Optional: increase timeout if Jest times out here

// afterAll(async () => {
// dbb.closeDb(); // Close database connection
// // app.close(); // Close server to free up the port
// });
afterEach(async () => {
await mongoose.disconnect();
await mongoServer.stop();
await closeDb();
});

test('GET students array', async () => {
const response = await request(app).get('/student')
expect(response.status).toBe(200);
expect(response.body).toBeInstanceOf(Array);
expect(response.body[0]).toHaveProperty('first_name');
});

test('should respond with 404 for unknown routes', async () => {
const res = await request(app).get('/unknown-route');
expect(res.statusCode).toBe(404);
expect(res.body).toEqual({ message: "Route not found" });
test('GET bad request', async () => {
const response = await request(app).get('/unknown')
expect(response.status).toBe(404);
expect(response.body.message).toBe('Route not found');
});
});
2 changes: 1 addition & 1 deletion class.rest
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#GET classes
# GET http://localhost:3000/class/
GET http://localhost:3000/class/

# GET class
# GET http://localhost:3000/class/67099506204dafb2be099394
Expand Down
2 changes: 1 addition & 1 deletion routes/grade.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ routes.post('/', isAuthenticated, validation.gradeCreateValidationRules(), valid

//R
// routes.get('/', gradeController.getOne(''))
routes.get('/',isAuthenticated, gradeController.getAll());
routes.get('/', gradeController.getAll());
routes.get('/student/:studentId',isAuthenticated, validation.gradeFindByStudentIdValidationRules(), validation.validate, gradeController.getStudentId());
routes.get('/:grade',isAuthenticated, validation.gradeFindByIdValidationRules(), validation.validate, gradeController.getGradeId());

Expand Down
2 changes: 1 addition & 1 deletion routes/teacher.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ const { isAuthenticated } = require('../middleware/authenticate');
routes.post('/',isAuthenticated, validation.teacherCreateValidationRules(), validation.validate, teacherController.createTeacher)

//R
routes.get('/',isAuthenticated, teacherController.getAll())
routes.get('/', teacherController.getAll())
routes.get('/:id',isAuthenticated, validation.teacherFindByIdValidationRules(), validation.validate, teacherController.getOne())
routes.get('/name/:name',isAuthenticated, validation.teacherFindNameValidationRules(), validation.validate, teacherController.getByName())

Expand Down
3 changes: 2 additions & 1 deletion server.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ const passport = require("./middleware/passport"); // Passport configuration
const app = express();
const mongodb = require('./data/database.js');

const port = process.env.PORT || 3000;
// const port = process.env.PORT || 3000;
const port = Math.floor((Math.random() * 10000) + 3000);

// Middleware
app.use(cors());
Expand Down