formies/__tests__/unit/models/User.db.test.js
Mohamad.Elsena a3236ae9d5 Refactor environment configuration for PostgreSQL and enhance application structure
- Updated `.env` and `.env.test` files to include PostgreSQL connection settings and Redis configuration.
- Migrated database from SQLite to PostgreSQL, updating relevant queries and connection logic.
- Enhanced error handling and logging throughout the application.
- Added new test utilities for PostgreSQL integration and updated user model methods.
- Introduced new routes for user authentication and form management, ensuring compatibility with the new database structure.
- Created login and registration views in EJS for user interaction.
2025-05-28 16:16:33 +02:00

155 lines
4.8 KiB
JavaScript

// __tests__/unit/models/User.db.test.js
const User = require("../../../src/models/User"); // Adjust path
const { pool, clearAllTables } = require("../../setup/testDbUtils"); // Adjust path
describe("User Model (PostgreSQL)", () => {
beforeEach(async () => {
await clearAllTables(); // Ensure clean state for each test
});
describe("create", () => {
it("should create a new user with hashed password and verification token", async () => {
const userData = {
email: "test@example.com",
password: "Password123!",
first_name: "Test",
last_name: "User",
};
const user = await User.create(userData);
expect(user.id).toBeDefined();
expect(user.uuid).toBeDefined();
expect(user.email).toBe(userData.email);
expect(user.password_hash).not.toBe(userData.password); // Should be hashed
expect(user.verification_token).toBeDefined();
expect(user.is_verified).toBe(0); // Default for SQLite, ensure it's FALSE for PG
const dbUser = await pool.query("SELECT * FROM users WHERE id = $1", [
user.id,
]);
expect(dbUser.rows[0].email).toBe(userData.email);
expect(dbUser.rows[0].password_hash).not.toBe(userData.password);
});
it("should throw an error if email already exists", async () => {
const userData = {
email: "duplicate@example.com",
password: "Password123!",
};
await User.create(userData);
await expect(User.create(userData)).rejects.toThrow(
"Email already exists"
);
});
});
describe("findByEmail", () => {
it("should find an active user by email", async () => {
const createdUser = await User.create({
email: "findme@example.com",
password: "Password123!",
});
const foundUser = await User.findByEmail("findme@example.com");
expect(foundUser).toBeDefined();
expect(foundUser.id).toBe(createdUser.id);
});
it("should return null if user not found or inactive", async () => {
expect(await User.findByEmail("dontexist@example.com")).toBeNull();
// Add test for inactive user if you implement that logic
});
});
describe("findById", () => {
it("should find an active user by ID", async () => {
const createdUser = await User.create({
email: "findbyid@example.com",
password: "Password123!",
});
const foundUser = await User.findById(createdUser.id);
expect(foundUser).toBeDefined();
expect(foundUser.email).toBe(createdUser.email);
});
});
describe("verifyEmail", () => {
it("should verify a user and nullify the token", async () => {
const user = await User.create({
email: "verify@example.com",
password: "Pass!",
});
const verificationToken = user.verification_token;
const verified = await User.verifyEmail(verificationToken);
expect(verified).toBe(true);
const dbUser = await User.findById(user.id);
expect(dbUser.is_verified).toBe(1); // Or TRUE depending on PG boolean handling
expect(dbUser.verification_token).toBeNull();
});
});
describe("setPasswordResetToken and findByPasswordResetToken", () => {
it("should set and find a valid password reset token", async () => {
const user = await User.create({
email: "reset@example.com",
password: "password",
});
const { token } = await User.setPasswordResetToken(user.email);
expect(token).toBeDefined();
const foundUser = await User.findByPasswordResetToken(token);
expect(foundUser).toBeDefined();
expect(foundUser.id).toBe(user.id);
});
it("should not find an expired password reset token", async () => {
const user = await User.create({
email: "resetexpired@example.com",
password: "password",
});
const { token } = await User.setPasswordResetToken(user.email);
// Manually expire the token in DB for testing
await pool.query(
"UPDATE users SET password_reset_expires = NOW() - INTERVAL '2 hour' WHERE id = $1",
[user.id]
);
const foundUser = await User.findByPasswordResetToken(token);
expect(foundUser).toBeNull();
});
});
// ... more tests for other User model methods (updatePassword, login attempts, etc.) ...
// Example: updatePasswordAndClearChangeFlag
describe("updatePasswordAndClearChangeFlag", () => {
it("should update password and set must_change_password to false", async () => {
const user = await User.create({
email: "changeme@example.com",
password: "oldpassword",
});
// Manually set must_change_password to true for test
await pool.query(
"UPDATE users SET must_change_password = TRUE WHERE id = $1",
[user.id]
);
const newPassword = "NewStrongPassword123!";
const updated = await User.updatePasswordAndClearChangeFlag(
user.id,
newPassword
);
expect(updated).toBe(true);
const dbUser = await User.findById(user.id);
const isMatch = await require("bcryptjs").compare(
newPassword,
dbUser.password_hash
);
expect(isMatch).toBe(true);
expect(dbUser.must_change_password).toBe(0); // Or FALSE
});
});
});