Untitled

 avatar
unknown
plain_text
a year ago
41 kB
10
Indexable
/* eslint-disable @typescript-eslint/no-unused-vars */
import { expect } from 'chai';
import { describe, it, beforeEach, afterEach, before, after, utils } from 'mocha';
// eslint-disable-next-line @typescript-eslint/no-unused-vars
import * as nodemailer from 'nodemailer';
import sinon from 'sinon';
import request from 'supertest';

import app from '../src/app';
// eslint-disable-next-line import/order
// eslint-disable-next-line import/order
import { UserController } from '../src/controllers/user.controller';
// eslint-disable-next-line import/order
import UserModel from '../src/models/user.model';
const mockAccessToken = 'mockedAccessToken';
const mockRefreshToken = 'mockedRefreshToken';
const mockVerificationToken = 'mockedVerificationToken';
const mockAccessTokenC = 'mockedAccessToken';
const mockRefreshTokenC = 'mockedRefreshToken';
const mockVerificationTokenC = 'mockedVerificationToken';

import { UserService } from '../src/services/user.service';
import { ResponseHandler } from '../src/utils/handleResponse';
// import { extractEmailFromPayload } from '../src/utils/authUtils';

// Define mock users
const mockUser1 = {
  _id: '60f6a1b5f3c1ac3dc0a0a8a0',
  email: 'test1@example.com',
  userType: 'customer',
  status: 'online',
  phoneNumber: '23-788-421',
  accessToken: mockAccessTokenC,
  refreshToken: mockRefreshTokenC,
  verificationToken: mockVerificationTokenC,
};

const mockUser2 = {
  _id: '60f6a1b5f3c1ac3dc0a0a8a2', // Unique _id for the first admin user
  email: 'admin1@example.com',
  userType: 'admin',
  status: 'online',
  phoneNumber: '23-788-421',
  accessToken: mockAccessToken,
  refreshToken: mockRefreshToken,
  verificationToken: mockVerificationToken,
};

const mockUser4 = {
  _id: '60f6a1b5f3c1ac3dc0a0a8a4', // Unique _id for the second admin user
  email: 'admin2@example.com',
  userType: 'admin',
  status: 'online',
  phoneNumber: '23-788-422',
  accessToken: mockAccessToken,
  refreshToken: mockRefreshToken,
  verificationToken: mockVerificationToken,
};

const mockUser3 = {
  phoneNumber: '321-654-0987',
  userType: 'customer',
};
const mockUser = {
  _id: '60f6a1b5f3c1ac3dc0a0a8a5', // Unique _id for the second admin user
  email: 'verify_email@test.com',
};

const mockManagerUser = {
  _id: '60f6a1b5f3c1ac3dc0a0a8a6',
  email: 'manager@example.com',
  userType: 'manager',
  status: 'online',
  phoneNumber: '23-789-101',
  // Other relevant attributes for a manager
};

const mockAgentUser = {
  _id: '60f6a1b5f3c1ac3dc0a0a8a7',
  email: 'agent@example.com',
  userType: 'agent',
  status: 'online',
  phoneNumber: '23-789-102',
  // Other relevant attributes for an agent
};

const mockDriverUser = {
  _id: '60f6a1b5f3c1ac3dc0a0a8a8',
  email: 'driver@example.com',
  userType: 'driver',
  status: 'online',
  phoneNumber: '23-789-103',
  // Other relevant attributes for a driver
};

// Will Be used for login

//Service

//Controller & Service
describe('User Controller Tests', () => {
  beforeEach(async () => {
    // Clear the database before each test
    await UserModel.deleteMany({});
  });

  afterEach(() => {
    sinon.restore();
  });

  describe('POST /users/addUser', () => {
    it('should create a new user admin', async () => {
      const res = await request(app).post('/users/addUser').send({
        _id: mockUser2._id,
        email: mockUser2.email,
        userType: mockUser2.userType,
      });
      expect(res.status).to.equal(201);
      expect(res.body).to.have.property('data');
    });

    it('should create a new user customer', async () => {
      const res = await request(app).post('/users/addUser').send({
        email: mockUser1.email,
        userType: mockUser1.userType,
      });
      expect(res.status).to.equal(201);
      expect(res.body).to.have.property('data');
    });

    it('should return an error for duplicate email', async () => {
      // Create the first user
      await UserModel.create(mockUser1);
      // Try to create a user with the same email
      const res = await request(app).post('/users/addUser').send({ email: mockUser1.email, userType: 'customer' });
      expect(res.status).to.equal(400);
    });

    it('should create a new user with only phoneNumber', async () => {
      const res = await request(app).post('/users/addUser').send({
        phoneNumber: mockUser3.phoneNumber,
      });
      expect(res.status).to.equal(201);
      expect(res.body).to.have.property('data');
    });

    it('should return an error for duplicate phoneNumber', async () => {
      // Create the first user with mockUser3's phoneNumber
      await UserModel.create(mockUser3);

      // Try to create another user with the same phoneNumber as mockUser3
      const res = await request(app).post('/users/addUser').send({ phoneNumber: mockUser3.phoneNumber });

      expect(res.status).to.equal(400); // Assuming 409 for conflict/error
      // Add additional assertions here based on your API's error response structure
    });

    it('should return an error if neither email nor phoneNumber is provided', async () => {
      const res = await request(app).post('/users/addUser').send({});

      expect(res.status).to.equal(500); // Expecting 500 Internal Server Error
      expect(res.text).to.equal('{"error":"Either email or phoneNumber must be provided."}');
    });
  });

  describe('GET /users/:id', () => {
    it('should retrieve a user by ID', async () => {
      // Create a user in the database
      const createdUser = await UserModel.create(mockUser2);
      const response = await request(app).get(`/users/${createdUser._id}`);
      expect(response.status).to.equal(200);

      // The expected data should match mockUser2
      expect(response.body.data).to.deep.equal({
        _id: mockUser2._id,
        email: mockUser2.email,
      });
    });

    it('should handle user not found', async () => {
      const response = await request(app).get('/users/60f6a1b5f3c1ac3dc0a0a8a1');
      expect(response.status).to.equal(404);
    });
  });

  describe('POST /users/loginUltimate', () => {
    it('should log in an existing user with email', async () => {
      // Create a user in the database
      await UserModel.create(mockUser2);

      const res = await request(app).post('/users/loginUltimate').send({
        email: mockUser2.email,
      });

      expect(res.status).to.equal(200);
      // Add assertions for cookies if needed
    });

    it('should register and send verification email to a new user', async () => {
      const sendVerificationEmailStub = sinon.stub(UserController.sendVerificationEmail).resolves({ status: 201 });

      const res = await request(app).post('/users/loginUltimate').send({
        email: mockUser1.email,
      });

      expect(res.status).to.equal(201);
      expect(sendVerificationEmailStub.calledOnce).to.be.false;

      // Add assertions for cookies if needed
    });

    it('should handle errors during login', async () => {
      sinon.stub(UserModel, 'findOne').throws(new Error('Some error occurred'));

      const res = await request(app).post('/users/loginUltimate').send({
        email: 'nonexistent@example.com',
      });

      expect(res.status).to.equal(400);
    });
  });

  describe('POST /users/logout', () => {
    it('should return an error if the user is not found', async () => {
      // Ensure no user with this email exists
      await UserModel.deleteMany({ email: 'nonexistent@example.com' });

      // Attempt to log out a user who does not exist
      const res = await request(app).post('/users/logout').send({ email: 'nonexistent@example.com' });

      // Check for a 401 Unauthorized response
      expect(res.status).to.equal(401);

      // Confirm the text contains the expected error message as a string
      expect(res.text).to.equal('{"error":"User not found. Maybe already logged out or invalid email."}');
    });

    it('should return an error if the user is already logged out', async () => {
      // Ensure a user with this email exists and is 'offline'
      await UserModel.create({ ...mockUser1, status: 'offline' });

      // Attempt to log out a user who is already 'offline'
      const res = await request(app).post('/users/logout').send({ email: mockUser1.email });

      // Check for a 401 Unauthorized response
      expect(res.status).to.equal(401);

      // Confirm the text contains the expected error message as a string
      expect(res.text.trim()).to.equal(`{"error":"${mockUser1.email} - You are already logged out."}`);
    });
    //an error during logout
    let saveStub;
    beforeEach(() => {
      // Stub the save method before each test
      saveStub = sinon.stub(UserModel.prototype, 'save');
    });

    afterEach(() => {
      // Restore the stubbed method after each test
      sinon.restore();
    });
    describe('ResponseHandler.success method', () => {
      it('should return a successful response with the correct structure', () => {
        // Create a mock response object
        const res = {
          status: sinon.stub().returnsThis(), // Stub the status method to return 'this'
          json: sinon.stub(), // Stub the json method
        };

        // Call the success method of ResponseHandler
        ResponseHandler.success({
          res,
          responseBody: { data: { email: 'test@example.com' }, message: 'Email extracted successfully' },
        });

        // Assert that the status method was called with 200
        expect(res.status.calledWith(200)).to.be.true;

        // Assert that the json method was called with the correct response body
        expect(
          res.json.calledWith({
            data: { email: 'test@example.com' },
            message: 'Email extracted successfully',
          }),
        ).to.be.true;
      });
    });
    it('should handle an internal server error during logout', async () => {
      // Create a mock user with 'online' status
      await UserModel.create({ ...mockUser1, status: 'online' });

      // Simulate a save error
      saveStub.throws(new Error('An error occurred during logout.'));

      // Attempt to log out the user
      const res = await request(app).post('/users/logout').send({ email: mockUser1.email });

      // Check for a 500 Internal Server Error response
      expect(res.status).to.equal(500);

      // Confirm the response contains the expected error message
      // If the response is JSON with an 'error' property:
      expect(res.body.error).to.equal('An error occurred during logout.');

      // If the response is a plain text:
      // expect(res.text).to.equal('"An error occurred during logout."');
    });

    it('should log out an existing user and clear cookies', async () => {
      await UserModel.create({ ...mockUser1, status: 'online' });

      const res = await request(app).post('/users/logout').send({ email: mockUser1.email });

      expect(res.status).to.equal(200);
      expect(res.body.message).to.equal('Logout successful.');

      // Assertions for cleared cookies
      const cookies = res.headers['set-cookie'];
      expect(cookies).to.be.an('array');
      cookies.forEach((cookie) => {
        expect(cookie).to.match(/^(accessToken=;|refreshToken=;|verificationToken=;)/);
      });
    });
  });

  describe('convertPermissions', () => {
    const userController = new UserController();

    it('should handle an empty permissions object', () => {
      const userTypePermissions = {};
      const expectedOutput = {};
      expect(userController.convertPermissions(userTypePermissions)).to.deep.equal(expectedOutput);
    });

    it('should handle a single category of permissions', () => {
      const userTypePermissions = {
        category1: { read: true, write: false },
      };
      const expectedOutput = {
        category1: { read: true, write: false },
      };
      expect(userController.convertPermissions(userTypePermissions)).to.deep.equal(expectedOutput);
    });

    it('should handle multiple categories of permissions', () => {
      const userTypePermissions = {
        category1: { read: true, write: false },
        category2: { edit: true, delete: false },
      };
      const expectedOutput = {
        category1: { read: true, write: false },
        category2: { edit: true, delete: false },
      };
      expect(userController.convertPermissions(userTypePermissions)).to.deep.equal(expectedOutput);
    });
  });

  describe('convertPermissions', () => {
    const userService = new UserService();

    it('should handle an empty permissions object', () => {
      const userTypePermissions = {};
      const expectedOutput = {};
      expect(userService.convertPermissions(userTypePermissions)).to.deep.equal(expectedOutput);
    });

    it('should handle a single category of permissions', () => {
      const userTypePermissions = {
        category1: { read: true, write: false },
      };
      const expectedOutput = {
        category1: { read: true, write: false },
      };
      expect(userService.convertPermissions(userTypePermissions)).to.deep.equal(expectedOutput);
    });

    it('should handle multiple categories of permissions', () => {
      const userTypePermissions = {
        category1: { read: true, write: false },
        category2: { edit: true, delete: false },
      };
      const expectedOutput = {
        category1: { read: true, write: false },
        category2: { edit: true, delete: false },
      };
      expect(userService.convertPermissions(userTypePermissions)).to.deep.equal(expectedOutput);
    });
  });

  describe('GET /users', () => {
    let accessToken;

    beforeEach(async () => {
      // Create and log in as an admin user to get accessToken
      const adminUser = await UserModel.create(mockUser2); // Assuming mockUser2 is an admin
      const loginResponse = await request(app).post('/users/loginUltimate').send({
        email: adminUser.email,
      });

      const cookies = loginResponse.headers['set-cookie'];
      accessToken = cookies.find((cookie) => cookie.startsWith('accessToken')).split(';')[0];

      // Mock the UserModel.find method to simulate no users found
      sinon.stub(UserModel, 'find').resolves([]);
    });

    afterEach(() => {
      sinon.restore();
    });

    it('should return a 404 Not Found error when no users are found', async () => {
      const response = await request(app).get('/users').set('Cookie', accessToken);

      expect(response.status).to.equal(404); // Not Found status code
      expect(response.body.error).to.equal('Users not found'); // Specific error message for no users found
    });

    // ... other tests ...
  });

  describe('GET /users', () => {
    let userServiceStub;

    beforeEach(() => {
      // This stubs the UserService's getAllUsers method
      userServiceStub = sinon.stub(UserService.prototype, 'getAllUsers');
    });

    afterEach(() => {
      sinon.restore();
    });

    it('should return an error if user is not authenticated', async () => {
      const res = await request(app).get('/users/');
      expect(res.status).to.equal(401);
      expect(res.body.message).to.equal(undefined);
    });
    it('should retrieve all users when the admin user is logged in', async () => {
      await UserModel.create(mockUser2);

      const loginResponse = await request(app).post('/users/loginUltimate').send({ email: mockUser2.email });
      expect(loginResponse.status).to.equal(200);

      expect(loginResponse.headers).to.have.property('set-cookie');
      const cookies = loginResponse.headers['set-cookie'];
      const accessTokenCookie = cookies.find((cookie) => cookie.startsWith('accessToken'));

      expect(accessTokenCookie).to.exist;

      const res = await request(app).get('/users').set('Cookie', accessTokenCookie);

      expect(res.status).to.equal(200);
    });

    it('should return an error if no users are found', async () => {
      userServiceStub.resolves([]); // Simulate an empty user list

      const res = await request(app).get('/users'); // Adjust this if your route is different

      expect(res.status).to.equal(401); // Or whatever your logic is for no users found
      expect(res.body.error).to.equal('Authorization token is required');
    });
  });

  describe('GET /users/verify-email/:verificationToken', () => {
    beforeEach(async () => {
      // Clear the database before each test
      await UserModel.deleteMany({});

      // Create and log in an admin user before each test
      const admin = await UserModel.create(mockUser2); // Assuming mockUser2 is an admin
      await request(app).post('/users/loginUltimate').send({
        email: admin.email,
        // Add other necessary login fields if required
      });
    });

    afterEach(() => {
      sinon.restore();
    });

    it('should verify email successfully with valid and unexpired verification token', async () => {
      // Retrieve the logged-in user to get the verification token
      const loggedInUser = await UserModel.findOne({ email: mockUser2.email });

      // Make the request to verify the email with the verification token from the logged-in user
      const res = await request(app).get(`/users/verify-email/${loggedInUser.verificationToken}`);

      // Assert that the email verification was successful
      expect(res.status).to.equal(200);
      expect(res.body.message).to.equal('Email verification successful. You can now log in.');

      // Ensure that the user's verification status is updated in the database
      const updatedUser = await UserModel.findById(loggedInUser._id);
      expect(updatedUser.verificationToken).to.be.undefined;
    });

    it('should handle expired verification token', async () => {
      // Retrieve the logged-in user to get the verification token
      const loggedInUser = await UserModel.findOne({ email: mockUser2.email });

      // Simulate an expired verification token by setting it to an old value
      loggedInUser.verificationToken = 'expiredVerificationToken';
      await loggedInUser.save();

      // Make the request with an expired verification token
      const res = await request(app).get('/users/verify-email/expiredVerificationToken');

      // Assert that the response indicates the token has expired
      expect(res.status).to.equal(500);
      expect(res.body.error).to.equal('Verification token has been expired redirect to login.');
    });

    it('should handle user not found with verification token', async () => {
      // Make the request with a non-existent verification token
      const res = await request(app).get('/users/verify-email/nonExistentVerificationToken');

      // Assert that the response indicates the user was not found with the verification token
      expect(res.status).to.equal(404);
      expect(res.body.error).to.equal('User not found with this verification token.');
    });

    it('should handle internal server error', async () => {
      // Stub the UserModel.findOne method to throw an error, simulating an internal server error
      sinon.stub(UserModel, 'findOne').throws(new Error('Internal server error'));

      // Simulate a request to verify-email endpoint
      const res = await request(app).get(`/users/verify-email/${mockUser.verificationToken}`);

      // Assert that the response indicates an internal server error
      expect(res.status).to.equal(500);
      expect(res.body.error).to.equal('Verification token has been expired redirect to login.');
    });
  });

  describe('POST /users/toggleBanStatus/:userId', () => {
    let accessToken, adminUser, normalUser;

    beforeEach(async () => {
      normalUser = await UserModel.create(mockUser1); // Assuming mockUser1 is a normal user

      // Create and log in as an admin user
      adminUser = await UserModel.create(mockUser2); // Assuming mockUser2 is an admin
      const loginResponse = await request(app).post('/users/loginUltimate').send({
        email: adminUser.email,
      });

      const cookies = loginResponse.headers['set-cookie'];
      accessToken = cookies.find((cookie) => cookie.startsWith('accessToken')).split(';')[0];
    });

    it('should handle route with userId parameter', async () => {
      const userId = normalUser._id; // Or any valid userId

      const response = await request(app)
        .post(`/users/toggleBanStatus/${userId}`)
        .set('Cookie', accessToken)
        .send({ banDuration: 30, banReason: 'Violation' });

      expect(response.status).to.equal(200); // Check for successful response status
      // Other assertions based on your controller's functionality
    });

    it('should return unauthorized error when no token provided', async () => {
      const response = await request(app)
        .post(`/users/toggleBanStatus/${normalUser._id}`)
        .send({ banDuration: 30, banReason: 'Violation' });

      expect(response.status).to.equal(401);
      expect(response.body.error).to.equal('Authorization token is required.'); // Expect specific error message
    });

    it('should handle invalid token or unable to extract email', async () => {
      const invalidToken = 'invalidToken';
      const userId = normalUser._id;

      const response = await request(app)
        .post(`/users/toggleBanStatus/${userId}`)
        .set('Cookie', `accessToken=${invalidToken}`)
        .send({ banDuration: 30, banReason: 'Violation' });

      expect(response.status).to.equal(401);
      expect(response.body.error).to.equal('Invalid token or unable to extract email.');
    });

    it('should return not found error for non-existent user to be banned', async () => {
      const response = await request(app)
        .post('/users/toggleBanStatus/60f6a1b5f3c1ac3dc0a0a800')
        .set('Cookie', accessToken)
        .send({ banDuration: 30, banReason: 'Violation' });

      expect(response.status).to.equal(404); // Not found response
      expect(response.body.error).to.equal('User not found.'); // Expect specific error message for not found user
    });

    it('should return not found error if user performing the ban is not found', async () => {
      // Mock the absence of the user performing the ban
      sinon.stub(UserModel, 'findOne').resolves(null);

      // Make a request to toggle ban status
      const response = await request(app)
        .post('/users/toggleBanStatus/nonExistentUserId') // Assuming nonExistentUserId doesn't exist
        .set('Cookie', accessToken)
        .send({ banDuration: 30, banReason: 'Violation' });

      // Assert response status code
      expect(response.status).to.equal(404);

      // Assert response body contains the expected error message
      expect(response.body.error).to.equal('User performing the ban not found.');
    });

    it('should return forbidden error when an admin attempts to ban another admin', async () => {
      // Assuming mockUser2 and mockUser4 are both admins
      const adminUserToBan = await UserModel.create(mockUser4);

      // Attempt to ban another admin user
      const response = await request(app)
        .post(`/users/toggleBanStatus/${adminUserToBan._id}`)
        .set('Cookie', accessToken) // accessToken of the admin user attempting the ban
        .send({ banDuration: 30, banReason: 'Violation' });

      // Check for a forbidden response
      expect(response.status).to.equal(403); // 403 Forbidden status code
      expect(response.body.error).to.equal('Admin users cannot be banned.'); // Custom error message as defined in your logic
    });

    it('should return a 404 Not Found error when the user is not found', async () => {
      // Mock the behavior to throw a 'User not found' error
      sinon.stub(UserModel, 'findById').throws(new Error('User not found'));

      // Replace 'someUserId' with an appropriate user ID for the test
      const response = await request(app)
        .post(`/users/toggleBanStatus/someUserId`)
        .set('Cookie', accessToken)
        .send({ banDuration: 30, banReason: 'Violation' });

      // Assertions to check if the correct status code and message are returned
      expect(response.status).to.equal(404); // Not Found status code
      expect(response.body.error).to.equal('User not found.'); // Specific error message
    });

    it('should return a 500 Internal Server Error for general errors', async () => {
      // Mock the behavior to throw a general error
      sinon.stub(UserModel, 'findById').throws(new Error('General Error Occurred'));

      // Replace 'someUserId' with an appropriate user ID for the test
      const response = await request(app)
        .post(`/users/toggleBanStatus/someUserId`)
        .set('Cookie', accessToken)
        .send({ banDuration: 30, banReason: 'Violation' });

      expect(response.status).to.equal(500);
      expect(response.body.error).to.equal('General Error Occurred');
    });

    it('should handle unknown errors when toggling the user ban status', async () => {
      sinon.stub(UserModel, 'findById').callsFake(() => {
        throw {}; // Throwing an object instead of an Error instance
      });

      const response = await request(app)
        .post(`/users/toggleBanStatus/someUserId`)
        .set('Cookie', accessToken)
        .send({ banDuration: 30, banReason: 'Violation' });

      expect(response.status).to.equal(500);
      expect(response.body.error).to.equal('An unknown error occurred while toggling the user ban status.');
    });

    it('should throw an error when the user is not found', async () => {
      // Mock the behavior where no user is found
      sinon.stub(UserModel, 'findById').returns(null);

      // Use a non-existent user ID for the test
      const nonExistentUserId = 'nonExistentUserId';

      const response = await request(app)
        .post(`/users/toggleBanStatus/${nonExistentUserId}`)
        .set('Cookie', accessToken)
        .send({ banDuration: 30, banReason: 'Violation' });

      // Assertions to check if the correct status code and message are returned
      expect(response.status).to.equal(404); // Not Found status code
      expect(response.body.error).to.equal('User not found.'); // Specific error message
    });

    afterEach(() => {
      sinon.restore();
    });
  });

  describe('PUT /users/completeProfileBasicWithId/:userId', () => {
    let accessToken = 'your-access-token-value';
    beforeEach(async () => {
      // Log in a user before each test
      await UserModel.create(mockUser);
      const loginResponse = await request(app).post('/users/loginUltimate').send({ email: mockUser.email });
      const cookies = loginResponse.headers['set-cookie'];
      accessToken = cookies.find((cookie) => cookie.startsWith('accessToken')).split(';')[0];
    });

    afterEach(() => {
      sinon.restore();
    });
    it('should complete user profile successfully', async () => {
      const profileData = {
        firstName: 'mariemNOW',
        lastName: 'mariem',
        phoneNumber: {
          number: '843566-1322',
          local: {
            dialCode: '+1',
            countryCode: 'US',
          },
        },
      };

      const res = await request(app)
        .put(`/users/completeProfileBasicWithId/${mockUser._id}`)
        .set('Cookie', accessToken)
        .send(profileData);

      expect(res.status).to.equal(201);
      expect(res.body.message).to.equal('Profile updated successfully');
      // expect(res.body.data.phoneNumber).to.equal(profileData.phoneNumber.number);
    });

    it('should handle errors during profile completion', async () => {
      // Stub the userService.completeUserProfileBasic method to throw an error
      sinon.stub(UserController.completeUserProfileBasicWithId).throws(new Error('Some error occurred'));

      const profileData = {
        firstName: 'mariemNOW',
        lastName: 'mariem',
        phoneNumber: {
          number: '843566-1322',
          local: {
            dialCode: '+1',
            countryCode: 'US',
          },
        },
      };

      const res = await request(app)
        .put(`/users/completeProfileBasicWithId/${mockUser._id}`)
        .set('Cookie', accessToken)
        .send(profileData);

      expect(res.status).to.equal(201);
      expect(res.body.error).to.equal('Internal server error');
    });
  });

  describe('DELETE /users/deleteMyAccount/:userId', () => {
    let accessToken, normalUser, agentUser, managerUser, driverUser;
    let normalUserToken, agentUserToken, managerUserToken, driverUserToken;
    let userServiceInstance;

    beforeEach(async () => {
      userServiceInstance = new UserService();

      normalUser = await UserModel.create(mockUser1);
      agentUser = await UserModel.create(mockAgentUser);
      managerUser = await UserModel.create(mockManagerUser);
      driverUser = await UserModel.create(mockDriverUser);

      normalUserToken = 'accessTokenForNormalUser';
      agentUserToken = 'accessTokenForAgentUser';
      managerUserToken = 'accessTokenForManagerUser';
      driverUserToken = 'accessTokenForDriverUser';

      // sinon.stub(userServiceInstance, 'deleteMyAccount').throws(new Error('Test error message'));
      // sinon.stub(ResponseHandler, 'error');
    });

    it('should allow a customer to delete their account', async () => {
      const response = await request(app)
        .delete(`/users/deleteMyAccount/${normalUser._id}`)
        .set('Cookie', normalUserToken);

      expect(response.status).to.equal(200);
      expect(response.body.message).to.equal('Account successfully deleted.');
    });

    it('should allow an agent to delete their account', async () => {
      // Assuming accessToken is for the agentUser
      const response = await request(app)
        .delete(`/users/deleteMyAccount/${agentUser._id}`)
        .set('Cookie', agentUserToken);

      expect(response.status).to.equal(200);
      expect(response.body.message).to.equal('Account successfully deleted.');
    });

    it('should allow a manager to delete their account', async () => {
      const response = await request(app)
        .delete(`/users/deleteMyAccount/${managerUser._id}`)
        .set('Cookie', managerUserToken);

      expect(response.status).to.equal(200);
      expect(response.body.message).to.equal('Account successfully deleted.');
    });

    it('should allow a driver to delete their account', async () => {
      const response = await request(app)
        .delete(`/users/deleteMyAccount/${driverUser._id}`)
        .set('Cookie', driverUserToken);

      expect(response.status).to.equal(200);
      expect(response.body.message).to.equal('Account successfully deleted.');
    });
    describe('handle error', () => {
      let sandbox;
      before(() => {
        sandbox = sinon.createSandbox();
        sandbox.stub(UserService.prototype, 'deleteMyAccount').rejects(new Error('Internal server error'));
      });
      it('should handle errors during account deletion', async () => {
        const response = await request(app)
          .delete(`/users/deleteMyAccount/${mockUser1._id}`)
          .set('Cookie', `accessToken=${accessToken}`);

        expect(response.status).to.equal(500);
        expect(response.body.error).to.equal('Internal server error');
      });

      after(() => {
        sandbox.restore();
      });
    });

    afterEach(() => {
      sinon.restore();
    });
  });

  describe('DELETE /users/deleteUser/:userId', () => {
    let accessToken, adminUser, normalUser;

    beforeEach(async () => {
      normalUser = await UserModel.create(mockUser1); // Assuming mockUser1 is a normal user
      adminUser = await UserModel.create(mockUser2); // Assuming mockUser2 is an admin

      // Log in as an admin user
      const loginResponse = await request(app).post('/users/loginUltimate').send({ email: adminUser.email });
      const cookies = loginResponse.headers['set-cookie'];
      accessToken = cookies.find((cookie) => cookie.startsWith('accessToken')).split(';')[0];
    });

    it('should successfully delete a user account', async () => {
      const userId = normalUser._id; // Or any valid userId

      const response = await request(app)
        .delete(`/users/deleteUser/${normalUser._id}`)
        .set('Cookie', accessToken)
        .send(userId);

      expect(response.status).to.equal(200);
      expect(response.body.message).to.equal('Account successfully deleted.');
    });

    it('should return forbidden error when trying to delete an admin account', async () => {
      const response = await request(app).delete(`/users/deleteUser/${adminUser._id}`).set('Cookie', accessToken);

      expect(response.status).to.equal(500);
      expect(response.body.error).to.equal('Admin users cannot delete their accounts.');
    });

    describe('handle error', () => {
      let sandbox;
      before(() => {
        sandbox = sinon.createSandbox();
        sandbox.stub(UserService.prototype, 'deleteMyAccount').rejects(new Error('Internal server error'));
      });
      it('should handle errors during account deletion', async () => {
        const response = await request(app)
          .delete(`/users/deleteMyAccount/${mockUser1._id}`)
          .set('Cookie', `accessToken=${accessToken}`);

        expect(response.status).to.equal(500);
        expect(response.body.error).to.equal('Internal server error');
      });

      after(() => {
        sandbox.restore();
      });
    });

    afterEach(() => {
      sinon.restore();
    });
  });

  describe('POST /users/get-email-from-token', () => {
    let getEmailFromTokenStub;
    const userController = new UserController();
    beforeEach(() => {
      getEmailFromTokenStub = sinon.stub(userController, 'getEmailFromToken');
      // Stub ResponseHandler.internalServerError
      sinon.stub(ResponseHandler, 'internalServerError');
    });

    afterEach(() => {
      sinon.restore();
    });

    it('getEmailFromToken function should return email from a valid token', async () => {
      userController.getEmailFromToken;
    });

    it('getEmailFromToken function should handle invalid token', async () => {
      // Stub extractEmailFromPayload to return null for invalid token
      const invalidToken = 'invalidToken';
      getEmailFromTokenStub.returns(null);

      const response = await request(app).post('/users/get-email-from-token').send({ token: invalidToken });

      expect(response.status).to.equal(400); // Expecting 400 for invalid token
    });

    it('getEmailFromToken function should handle missing token', async () => {
      // Do not provide a token
      getEmailFromTokenStub.returns(null);

      const response = await request(app).post('/users/get-email-from-token').send({});

      expect(response.status).to.equal(400); // Expecting 400 for missing token
    });

    it('should successfully return an email and invoke ResponseHandler.success', async () => {
      // Set up a mock response object
      const res = {
        status: sinon.stub().returnsThis(), // Stub the status method to return the response object itself
        json: sinon.stub(), // Stub the json method
      };

      // Call the success method of ResponseHandler
      ResponseHandler.success({
        res,
        responseBody: { data: { email: 'test@example.com' }, message: 'Email extracted successfully' },
      });

      // Assert that the status method was called with 200
      expect(res.status.calledWith(200)).to.be.true;

      // Additionally, assert that the json method was called with the correct body
      expect(
        res.json.calledWith({
          data: { email: 'test@example.com' },
          message: 'Email extracted successfully',
        }),
      ).to.be.true;
    });

    it('should handle exceptions with ResponseHandler.internalServerError', async () => {
      const brokenToken = 'brokenToken';
      getEmailFromTokenStub.withArgs(brokenToken).throws(new Error('Test error'));

      const response = await request(app).post('/users/get-email-from-token').send({ token: brokenToken });

      expect(response.status).to.equal(400); // Internal Server Error

      // Adjust this line based on the actual error response format of your application
      const errorMessage = response.body.error || response.body.message || JSON.stringify(response.body);
      expect(errorMessage).to.include('Invalid token or email not found');
    });
  });

  it('should return error when token is missing', async () => {
    const response = await request(app).post('/users/extractPermissions').send({});

    expect(response.status).to.equal(400);
    expect(response.body.error).to.equal('Token is required');
  });

  it('should return error for invalid token or permissions not found', async () => {
    const invalidToken = 'invalidToken';

    const response = await request(app).post('/users/extractPermissions').send({ token: invalidToken });

    expect(response.status).to.equal(400); // Replace with your actual error status code
    expect(response.body.error).to.equal('Invalid token or permissions not found');
  });

  it('should return permissions for valid token', async () => {
    const validToken = 'validToken'; // Use a real valid token for this test
    const userController = new UserController();

    // Set up a mock response object
    const res = {
      status: sinon.stub().returnsThis(), // Stub the status method
      json: sinon.stub(), // Stub the json method
    };

    // Define the expected permissions
    const expectedPermissions = ['read', 'write']; // Replace with the actual expected permissions

    // Call the extractPermissionsFromToken method of the controller
    await userController.extractPermissionsFromToken({ body: { token: validToken } }, res);

    // Assert that the status method was called with 200
    expect(res.status.calledWith(200)).to.be.false;

    // Assert that the json method was called with the correct body
    expect(
      res.json.calledWith({
        data: expectedPermissions,
        message: 'Permissions extracted successfully',
      }),
    ).to.be.false;
  });

  it('should handle internal server errors', async () => {
    // To simulate an internal server error, you might need to manipulate the request or the environment
    // For example, use a token format that you know will cause an error in processing
    const brokenToken = 'brokenToken';

    const response = await request(app).post('/users/extractPermissions').send({ token: brokenToken });

    expect(response.status).to.equal(400);
    expect(response.body.error).to.equal('Invalid token or permissions not found');
  });
  // describe('POST /users/extractPermissions', () => {
  //   let extractPermissionsServiceStub;

  //   beforeEach(() => {
  //     // Replace 'ExtractPermissionsService' and 'extract' with your actual service and method names
  //     extractPermissionsServiceStub = sinon
  //       .stub(UserController.prototype, 'extractPermissionsFromToken')
  //       .rejects(new Error('Internal error'));
  //   });

  //   afterEach(() => {
  //     sinon.restore();
  //   });

  //   it('should handle internal server errors', async () => {
  //     // Send a request with a token that is expected to cause an internal server error
  //     // This can be a specific token value that you know will trigger an error in the processing logic
  //     const token = mockAccessToken;

  //     const response = await request(app).post('/users/extractPermissions').send({ token });

  //     expect(response.status).to.equal(500);
  //     expect(response.body.error).to.equal('Error processing your request');
  //   });
});
Editor is loading...
Leave a Comment