Skip to content

Commit 0fc60bd

Browse files
committed
model/user: add unit test for user model
1 parent 2d37b08 commit 0fc60bd

File tree

2 files changed

+124
-1
lines changed

2 files changed

+124
-1
lines changed
Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
import mongoose from 'mongoose';
2+
import bcrypt from 'bcryptjs';
3+
import User from '../user';
4+
5+
beforeAll(async () => {
6+
const mongoUri = 'mongodb://127.0.0.1:27017/test_db_user';
7+
await mongoose.connect(mongoUri, {
8+
dbName: 'test_db_user', // optional
9+
autoIndex: true
10+
});
11+
});
12+
13+
afterAll(async () => {
14+
await mongoose.connection.dropDatabase();
15+
await mongoose.connection.close();
16+
});
17+
18+
beforeEach(async () => {
19+
await User.deleteMany({});
20+
});
21+
22+
describe('User model', () => {
23+
it('should hash password before saving', async () => {
24+
const user = new User({
25+
username: 'alice',
26+
email: 'alice@example.com',
27+
password: 'mypassword'
28+
});
29+
await user.save();
30+
31+
expect(user.password).not.toBe('mypassword');
32+
const match = await bcrypt.compare('mypassword', user.password);
33+
expect(match).toBe(true);
34+
});
35+
36+
it('should compare passwords correctly', async () => {
37+
const user = new User({
38+
username: 'bob',
39+
email: 'bob@example.com',
40+
password: 'secret'
41+
});
42+
await user.save();
43+
44+
const isMatch = await user.comparePassword('secret');
45+
expect(isMatch).toBe(true);
46+
47+
const isNotMatch = await user.comparePassword('wrong');
48+
expect(isNotMatch).toBe(false);
49+
});
50+
51+
it('should expose virtual id as string', async () => {
52+
const user = new User({
53+
username: 'carol',
54+
email: 'carol@example.com',
55+
password: 'pass123'
56+
});
57+
await user.save();
58+
59+
expect(user.id).toBe(user._id.toHexString());
60+
});
61+
62+
it('should include virtuals in toJSON output', () => {
63+
const user = new User({
64+
username: 'testuser',
65+
email: 'test@example.com',
66+
password: 'secret'
67+
});
68+
expect(user.id).toBe(user._id.toHexString());
69+
70+
const json = user.toJSON();
71+
72+
// check that virtual id is included in the serialized output
73+
expect(json).toHaveProperty('id', user._id.toHexString());
74+
75+
// check that regular fields are also present
76+
expect(json).toHaveProperty('username', 'testuser');
77+
expect(json).toHaveProperty('email', 'test@example.com');
78+
});
79+
80+
it('should find user by email (case insensitive)', async () => {
81+
await new User({
82+
username: 'dave',
83+
email: 'Dave@Example.com',
84+
password: 'pass'
85+
}).save();
86+
87+
const found = await User.findByEmail('dave@example.com');
88+
expect(found).not.toBeNull();
89+
expect(found.username).toBe('dave');
90+
});
91+
92+
it('should find user by username (case insensitive)', async () => {
93+
await new User({
94+
username: 'Eve',
95+
email: 'eve@example.com',
96+
password: 'pass'
97+
}).save();
98+
99+
const found = await User.findByUsername('eve', { caseInsensitive: true });
100+
expect(found).not.toBeNull();
101+
expect(found.email).toBe('eve@example.com');
102+
});
103+
104+
it('should return null for wrong username/email', async () => {
105+
const found = await User.findByEmail('nope@example.com');
106+
expect(found).toBeNull();
107+
});
108+
109+
it('should hash apiKeys on save and find matching key', async () => {
110+
const user = new User({
111+
username: 'frank',
112+
email: 'frank@example.com',
113+
apiKeys: [{ hashedKey: 'hashedApiKey' }] // gets hashed by bcrypt in pre-save
114+
});
115+
await user.save();
116+
117+
const savedUser = await User.findOne({ email: 'frank@example.com' });
118+
const keyObj = await savedUser.findMatchingKey('hashedApiKey');
119+
120+
expect(keyObj.isMatch).toBe(true);
121+
expect(keyObj.keyDocument).not.toBeNull();
122+
});
123+
});

server/models/apiKey.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import mongoose, { Schema } from 'mongoose';
1+
import { Schema } from 'mongoose';
22

33
export const apiKeySchema = new Schema(
44
{

0 commit comments

Comments
 (0)