Skip to content

Commit 9a3275a

Browse files
committed
[Feat] Add Jest configuration and initial test setup for backend testing
1 parent 3971381 commit 9a3275a

19 files changed

Lines changed: 1698 additions & 198 deletions

File tree

Backend/api/index.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ try {
1111
const fallbackApp = express();
1212

1313
// Log the error details
14-
console.error('Error loading main application:', error);
14+
// console.error('Error loading main application:', error);
1515

1616
// Basic routes
1717
fallbackApp.get('/', (req, res) => {

Backend/jest.config.js

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
module.exports = {
2+
testEnvironment: 'node',
3+
collectCoverageFrom: [
4+
'src/**/*.js',
5+
'!src/migrations/**',
6+
'!src/config/**',
7+
'!src/tests/**'
8+
],
9+
coverageDirectory: 'coverage',
10+
coverageReporters: ['text', 'lcov'],
11+
testMatch: [
12+
'**/src/tests/**/*.test.js'
13+
],
14+
setupFilesAfterEnv: ['<rootDir>/src/tests/setup.js'],
15+
testTimeout: 10000,
16+
verbose: true,
17+
forceExit: true,
18+
clearMocks: true,
19+
resetMocks: true,
20+
restoreMocks: true
21+
};

Backend/package.json

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,7 @@
77
"start": "NODE_ENV=production node src/app.js",
88
"cpanel": "NODE_ENV=production DISABLE_DB_SYNC=true CPANEL=true node index.js",
99
"dev": "nodemon src/app.js",
10-
"test": "cross-env NODE_ENV=test jest --detectOpenHandles",
11-
"test:watch": "cross-env NODE_ENV=test jest --watch",
12-
"test:coverage": "cross-env NODE_ENV=test jest --coverage",
10+
"test": "cross-env NODE_ENV=test jest --detectOpenHandles --forceExit",
1311
"lint": "eslint .",
1412
"migrate": "node src/migrations/run_migrations.js",
1513
"migrate:indexes": "node -e \"require('./src/migrations/run_migrations').runSingleFile('./src/migrations/create_indexes.sql')\""

Backend/src/controllers/auth.controller.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ const signup = async (req, res) => {
105105
user: newUser
106106
});
107107
} catch (error) {
108-
console.error('[LOG signup ERROR] =========', error);
108+
109109
res.status(500).json({ message: 'Error creating user', error: error.message });
110110
}
111111
};
@@ -154,7 +154,7 @@ const login = async (req, res) => {
154154
user
155155
});
156156
} catch (error) {
157-
console.error('[LOG login ERROR] =========', error);
157+
// console.error('[LOG login ERROR] =========', error);
158158
res.status(500).json({ message: 'Error during login', error: error.message });
159159
}
160160
};

Backend/src/middleware/auth.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ module.exports = async (req, res, next) => {
4444
// Continue to next middleware or route handler
4545
next();
4646
} catch (error) {
47-
console.error('[LOG auth middleware] ========= Error:', error);
47+
// console.error('[LOG auth middleware] ========= Error:', error);
4848

4949
if (error.name === 'JsonWebTokenError') {
5050
return res.status(401).json({ message: 'Invalid authentication token' });
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
const { DataTypes } = require('sequelize');
2+
3+
module.exports = (sequelize) => {
4+
const SharedContent = sequelize.define('SharedContent', {
5+
id: {
6+
type: DataTypes.CHAR(36),
7+
defaultValue: DataTypes.UUIDV4,
8+
primaryKey: true
9+
},
10+
user_id: {
11+
type: DataTypes.CHAR(36),
12+
allowNull: false,
13+
references: {
14+
model: 'users',
15+
key: 'id'
16+
}
17+
},
18+
content_type: {
19+
type: DataTypes.ENUM('topic', 'quiz'),
20+
allowNull: false
21+
},
22+
content_url: {
23+
type: DataTypes.STRING(500),
24+
allowNull: false
25+
},
26+
title: {
27+
type: DataTypes.STRING(255),
28+
allowNull: false
29+
},
30+
description: {
31+
type: DataTypes.TEXT,
32+
allowNull: true
33+
},
34+
tags: {
35+
type: DataTypes.JSON,
36+
allowNull: true,
37+
defaultValue: []
38+
},
39+
likes_count: {
40+
type: DataTypes.INTEGER,
41+
defaultValue: 0
42+
},
43+
comments_count: {
44+
type: DataTypes.INTEGER,
45+
defaultValue: 0
46+
},
47+
created_at: {
48+
type: DataTypes.DATE,
49+
allowNull: false,
50+
defaultValue: DataTypes.NOW
51+
},
52+
updated_at: {
53+
type: DataTypes.DATE,
54+
allowNull: false,
55+
defaultValue: DataTypes.NOW
56+
}
57+
}, {
58+
tableName: 'shared_content',
59+
timestamps: true,
60+
underscored: true,
61+
createdAt: 'created_at',
62+
updatedAt: 'updated_at',
63+
indexes: [
64+
{
65+
fields: ['user_id']
66+
},
67+
{
68+
fields: ['content_type']
69+
},
70+
{
71+
fields: ['created_at']
72+
}
73+
]
74+
});
75+
76+
SharedContent.associate = (models) => {
77+
SharedContent.belongsTo(models.User, {
78+
foreignKey: 'user_id',
79+
as: 'author'
80+
});
81+
82+
SharedContent.hasMany(models.SharedContentLike, {
83+
foreignKey: 'shared_content_id',
84+
as: 'likes'
85+
});
86+
87+
SharedContent.hasMany(models.SharedContentComment, {
88+
foreignKey: 'shared_content_id',
89+
as: 'comments'
90+
});
91+
};
92+
93+
return SharedContent;
94+
};

Backend/src/tests/auth.test.js

Lines changed: 0 additions & 93 deletions
This file was deleted.
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
const request = require('supertest');
2+
const app = require('../../app');
3+
4+
describe('Simple Integration Tests', () => {
5+
describe('GET /api/status', () => {
6+
it('should return API status', async () => {
7+
const res = await request(app)
8+
.get('/api/status')
9+
.send();
10+
11+
console.log('[LOG integration_test] ========= Status endpoint test completed');
12+
13+
// Should return either 200 (if DB connected) or 500 (if DB not connected)
14+
expect([200, 500]).toContain(res.status);
15+
expect(res.body).toHaveProperty('status');
16+
17+
// Only check for timestamp if status is 'ok' (database connected)
18+
if (res.body.status === 'ok') {
19+
expect(res.body).toHaveProperty('timestamp');
20+
}
21+
});
22+
});
23+
24+
describe('GET /', () => {
25+
it('should redirect to API documentation', async () => {
26+
const res = await request(app)
27+
.get('/')
28+
.send();
29+
30+
console.log('[LOG integration_test] ========= Root redirect test completed');
31+
32+
expect(res.status).toBe(302);
33+
expect(res.headers.location).toBe('/api-docs');
34+
});
35+
});
36+
37+
describe('GET /api-docs', () => {
38+
it('should serve Swagger documentation', async () => {
39+
const res = await request(app)
40+
.get('/api-docs/')
41+
.send();
42+
43+
console.log('[LOG integration_test] ========= Swagger docs test completed');
44+
45+
expect(res.status).toBe(200);
46+
expect(res.headers['content-type']).toContain('text/html');
47+
});
48+
});
49+
});

0 commit comments

Comments
 (0)