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
20 changes: 9 additions & 11 deletions backend/models/user.model.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
const mongoose = require("mongoose");
const mongoose = require('mongoose');
// const bcrypt = require('bcrypt-nodejs');

mongoose.Promise = global.Promise;
Expand All @@ -9,10 +9,10 @@ const userSchema = mongoose.Schema({
lastName: { type: String },
},
email: { type: String, unique: true, lowercase: true },
accessLevel: {
type: String,
enum: ["user", "admin", "superadmin"], // restricts values to "user", "admin" and "superadmin"
default: "user"
accessLevel: {
type: String,
enum: ['user', 'admin', 'superadmin'], // restricts values to "user", "admin" and "superadmin"
default: 'user',
},
createdDate: { type: Date, default: Date.now },
currentRole: { type: String }, // will remove but need to update check-in form
Expand All @@ -23,11 +23,10 @@ const userSchema = mongoose.Schema({
skillsToMatch: [{ type: String }], // skills the user either has or wants to learn - will use to match to projects
firstAttended: { type: String },
attendanceReason: { type: String },
githubHandle: { type: String },
projects: [
{
type: mongoose.Schema.Types.ObjectId,
ref: "Project",
ref: 'Project',
},
],
githubHandle: { type: String }, // handle not including @, not the URL
Expand All @@ -40,7 +39,7 @@ const userSchema = mongoose.Schema({
managedProjects: [{ type: String }], // Which projects managed by user.
//currentProject: { type: String } // no longer need this as we can get it from Project Team Member table
// password: { type: String, required: true }
isActive: { type: Boolean, default: true }
isActive: { type: Boolean, default: true },
});

userSchema.methods.serialize = function () {
Expand All @@ -61,7 +60,6 @@ userSchema.methods.serialize = function () {
skillsToMatch: this.skillsToMatch,
firstAttended: this.firstAttended,
attendanceReason: this.attendanceReason,
githubHandle: this.githubHandle,
projects: this.projects,
//currentProject: this.currentProject
phone: this.phone,
Expand All @@ -71,10 +69,10 @@ userSchema.methods.serialize = function () {
githubPublic2FA: this.githubPublic2FA,
availability: this.availability,
managedProjects: this.managedProjects,
isActive: this.isActive
isActive: this.isActive,
};
};

const User = mongoose.model("User", userSchema);
const User = mongoose.model('User', userSchema);

module.exports = { User };
3 changes: 0 additions & 3 deletions backend/models/user.model.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ describe('Unit tests for User Model', () => {
skillsToMatch: ['Jest', 'Node.js'],
firstAttended: '2025-01-01',
attendanceReason: 'To learn and contribute',
githubHandle: 'mockuser',
projects: ['ProjectId1', 'ProjectId2'],
phone: '123-456-7890',
textingOk: true,
Expand Down Expand Up @@ -62,7 +61,6 @@ describe('Unit tests for User Model', () => {
skillsToMatch: mockUser.skillsToMatch,
firstAttended: mockUser.firstAttended,
attendanceReason: mockUser.attendanceReason,
githubHandle: mockUser.githubHandle,
projects: mockUser.projects,
phone: mockUser.phone,
textingOk: mockUser.textingOk,
Expand Down Expand Up @@ -108,7 +106,6 @@ describe('Unit tests for User Model', () => {
expect(mockUser.email).toBe(uppercaseEmail.toLowerCase());
});


it('should pass validation with valid user data', async () => {
// Create a mock user with valid data
const mockUser = new User({
Expand Down
128 changes: 128 additions & 0 deletions backend/models/user.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
const mongoose = require('mongoose');
const { User } = require('./user.model');
const { setupIntegrationDB } = require('../setup-test');

setupIntegrationDB('user-model');

describe('User Model - Create and Read', () => {
test('Save a model instance and then read from the db', async () => {
const submittedData = {
name: {
firstName: 'Test',
lastName: 'User',
},
email: 'test@test.com',
accessLevel: 'user',
createdDate: 1594023390039,
currentRole: 'mage',
desiredRole: 'warlock',
newMember: true,
currentJobTitle: 'freehand artist',
desiredJobTitle: 'textile factory worker',
skillsToMatch: ['marketing assistant'],
firstAttended: 'year 0',
attendanceReason: 'training',
phone: '867-5309',
textingOk: true,
slackName: 'slacktestuser',
};

await User.create(submittedData);
const savedData = await User.findOne({ email: submittedData.email });
expect(savedData.name.firstName).toBe(submittedData.name.firstName);
expect(savedData.currentRole).toBe(submittedData.currentRole);
expect(savedData.desiredJobTitle).toBe(submittedData.desiredJobTitle);
});

test('Create a simple user', async () => {
const submittedData = {
name: {
firstName: 'Simple',
lastName: 'User',
},
email: 'simple@test.com',
};

await User.create(submittedData);
const savedData = await User.findOne({ email: submittedData.email });
expect(savedData.name.firstName).toBe(submittedData.name.firstName);
expect(savedData.email).toBe(submittedData.email);
});
});

describe('User Model - Serialization', () => {
test('should serialize user data correctly', async () => {
const userData = {
name: { firstName: 'Serialize', lastName: 'Test' },
email: 'serialize.test@example.com',
accessLevel: 'admin',
currentRole: 'Backend Developer',
desiredRole: 'Lead Developer',
newMember: false,
currentJobTitle: 'Actual Current Job Title',
desiredJobTitle: 'Actual Desired Job Title',
skillsToMatch: ['JavaScript', 'MongoDB'],
phone: '555-0101',
textingOk: true,
slackName: 'serializeslack',
isHflaGithubMember: true,
githubPublic2FA: false,
availability: 'Evenings',
managedProjects: ['ProjectGamma'],
isActive: true,
createdDate: new Date(2023, 0, 15),
};

const user = await User.create(userData);
const serializedUser = user.serialize();

expect(serializedUser.id.toString()).toBe(user._id.toString());
expect(serializedUser.name.firstName).toBe(userData.name.firstName);
expect(serializedUser.name.lastName).toBe(userData.name.lastName);
expect(serializedUser.email).toBe(userData.email);
expect(serializedUser.accessLevel).toBe(userData.accessLevel);
expect(serializedUser.createdDate).toEqual(userData.createdDate);
expect(serializedUser.currentRole).toBe(userData.currentRole);
expect(serializedUser.desiredRole).toBe(userData.desiredRole);
expect(serializedUser.newMember).toBe(userData.newMember);
expect([...serializedUser.skillsToMatch]).toEqual(userData.skillsToMatch);
expect(serializedUser.phone).toBe(userData.phone);
expect(serializedUser.textingOk).toBe(userData.textingOk);
expect(serializedUser.slackName).toBe(userData.slackName);
expect(serializedUser.isHflaGithubMember).toBe(userData.isHflaGithubMember);
expect(serializedUser.githubPublic2FA).toBe(userData.githubPublic2FA);
expect(serializedUser.availability).toBe(userData.availability);
expect([...serializedUser.managedProjects]).toEqual(userData.managedProjects);
expect(serializedUser.isActive).toBe(userData.isActive);
});
});

describe('User Model - Validation', () => {
test('should fail if email is not unique', async () => {
const email = 'unique.validation@example.com';
await User.create({
name: { firstName: 'First', lastName: 'User' },
email: email,
accessLevel: 'user',
});

await expect(
User.create({
name: { firstName: 'Second', lastName: 'User' },
email: email,
accessLevel: 'user',
}),
).rejects.toMatchObject({ code: 11000 });
});

test('should fail if accessLevel is not in enum', async () => {
const userData = {
name: { firstName: 'Enum', lastName: 'Test' },
email: 'enum.test@example.com',
accessLevel: 'invalid_access_level',
};

const user = new User(userData);
await expect(user.save()).rejects.toBeInstanceOf(mongoose.Error.ValidationError);
});
});
Loading