Skip to content

Commit

Permalink
Wrote unit and intergration tests for the user service
Browse files Browse the repository at this point in the history
  • Loading branch information
OomsOoms committed Sep 20, 2024
1 parent ca7699c commit 5ae3f3c
Show file tree
Hide file tree
Showing 14 changed files with 632 additions and 294 deletions.
1 change: 1 addition & 0 deletions server/jest.setup.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
process.env.PORT = '4000'; // Set the port for testing
process.env.DOMAIN = 'http://localhost:4000'; // Set the domain for testing
process.env.NODE_ENV = 'test'; // Ensure NODE_ENV is set to test, jest already does this but just to be sure
process.env.ADMIN_PASSWORD = 'admin'; // Set the admin password for testing
4 changes: 2 additions & 2 deletions server/src/api/middlewares/verifyCaptcha.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ const verifyCaptcha = async (req, res, next) => {
if (data.success === true) {
next();
} else {
if (process.env.NODE_ENV === 'development') {
next(); // Skip captcha verification in development
if (process.env.NODE_ENV !== 'production') {
next(); // Skip captcha verification in development and testing
} else {
next(Error.invalidCredentials('Invalid captcha token'));
}
Expand Down
2 changes: 1 addition & 1 deletion server/src/api/models/user.model.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ const UserSchema = new mongoose.Schema(
},
profilePicture: {
type: String,
default: `${process.env.CDN_DOMAIN}/uploads/avatars/default-avatar.jpg`,
default: '/uploads/avatars/default-avatar.jpg',
},
roles: {
type: [String],
Expand Down
31 changes: 14 additions & 17 deletions server/src/api/services/user.service.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ async function requestVerification(email) {
const user = await User.findOne({ newEmail: email });
if (!user || !user.newEmail) throw Error.userNotFound('User not found or email already verified');

const token = generateJwt({ id: user._id }, { expiresIn: '24h' });
const token = generateJwt({ id: user.id }, { expiresIn: '24h' });
sendEmail(email, 'Verify your email', 'verifyEmail', { username: user.username, token });
}

Expand Down Expand Up @@ -72,7 +72,7 @@ async function registerUser(username, email, password) {
// This is because the newEmail field is the email that needs to be verified, but the email field cannot be empty.
const user = new User({ username, newEmail: email, password });
await user.save();
const token = generateJwt({ id: user._id }, { expiresIn: '24h' });
const token = generateJwt({ id: user.id }, { expiresIn: '24h' });
sendEmail(email, 'Verify your email', 'verifyEmail', { username, token });
} catch (error) {
if (error.code === 11000) {
Expand Down Expand Up @@ -111,13 +111,10 @@ async function updateUser(requestingUser, username, currentPassword, updatedFiel
const changes = { user: user.username };

if (file) {
const oldFile = user.profile.profilePicture.split('/').pop();
if (oldFile !== 'default-avatar.jpg') await deleteFile(`uploads/avatars/${oldFile}`);
const result = await uploadFile(
file,
`uploads/avatars/${user.id}-${Date.now()}.${file.originalname.split('.').pop()}`
);
user.profile.profilePicture = `${process.env.CDN_DOMAIN}/${result.key}`;
const oldFile = user.profile.profilePicture;
if (oldFile !== 'default-avatar.jpg') await deleteFile(oldFile);
const result = await uploadFile(file, oldFile);
user.set('profile.profilePicture', result.key);
changes.profilePicture = { message: 'Profile picture updated' };
}

Expand All @@ -130,12 +127,13 @@ async function updateUser(requestingUser, username, currentPassword, updatedFiel
// Users can update themselves with their password
if (isSameUser && !(await comparePasswords(currentPassword, user.password)))
throw Error.invalidCredentials('Invalid password');
user.password = value;
user.set(path, value);
changes.password = { message: 'Password changed, signed out of all sessions' };
await mongoose.connection.db.collection('sessions').deleteMany({ 'session.userId': user.id });
break;
case 'email':
user.newEmail = value;
// newEmail instead of email, this is the request is email instead of newEmail
user.set('newEmail', value);
changes.email = { message: 'Email change requested, verify email', value };
break;
default:
Expand All @@ -146,7 +144,7 @@ async function updateUser(requestingUser, username, currentPassword, updatedFiel
try {
await user.save();
if (changes.email) {
const token = generateJwt({ id: user._id }, { expiresIn: '24h' });
const token = generateJwt({ id: user.id }, { expiresIn: '24h' });
sendEmail(changes.email.value, 'Verify your email', 'verifyEmail', { username: user.username, token });
}
} catch (error) {
Expand All @@ -157,7 +155,7 @@ async function updateUser(requestingUser, username, currentPassword, updatedFiel
throw error;
}

return { changes, destroySessions: isSameUser && changes.password };
return { changes, destroySessions: isSameUser && changes.password !== undefined };
}

/**
Expand Down Expand Up @@ -188,10 +186,9 @@ async function deleteUser(requestingUser, username, password) {
throw Error.invalidCredentials('Invalid password');

await mongoose.connection.db.collection('sessions').deleteMany({ 'session.userId': user.id });
const oldFile = user.profile.profilePicture.split('/').pop();
if (oldFile !== 'default-avatar.jpg') await deleteFile(`uploads/avatars/${oldFile}`);
await uploadFile(null, `uploads/avatars/${user.id}-${Date.now()}.${oldFile.split('.').pop()}`);
await User.deleteOne({ _id: user.id });
const oldFile = user.profile.profilePicture;
if (oldFile !== '/uploads/avatars/default-avatar.jpg') await deleteFile(oldFile);
await User.deleteOne({ id: user.id });

return { message: `User ${user.username} deleted`, destroySessions: isSameUser };
}
Expand Down
2 changes: 1 addition & 1 deletion server/src/api/validations/user.validation.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ const verifyUser = [
req.user = decoded;
next();
} catch {
res.status(401).json({ message: 'Invalid Token' });
res.status(401).json({ message: 'Invalid token' });
}
},
];
Expand Down
2 changes: 1 addition & 1 deletion server/src/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,9 @@ if (process.env.NODE_ENV === 'production') {
// tests and development
app.use(morgan('dev')); // console logs only
}

// Enable CORS for all routes
app.use(corsMiddleware);
app.set('trust proxy', 1);

// built-in middleware for json
app.use(express.json());
Expand Down
Loading

0 comments on commit 5ae3f3c

Please sign in to comment.