Untitled

mail@pastecode.io avatar
unknown
plain_text
7 days ago
14 kB
1
Indexable
Never
import { expect } from 'chai';
import { before, describe, it } from 'mocha';
import sinon from 'sinon';
import request from 'supertest';

import app from '../src/app.js';
import { AccommodationRequestRepository } from '../src/repositories/accommodationRequest.repository.js';
import { AccommodationRequestService } from '../src/services/accommodationRequest.service.js';
const providedAccessToken =
  'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJkYXRhIjoiTzNiMTNJYzlmTmszVEVOTDZHeUxBV3c0bkF3RzZ1V0I1YUI3WVFoQk9YR2NMV2VMQWlJTEdrZ3M2ZFJzaWpTMjRVa29OMkNJZ2VYeDBXU2RXSUR3cDJvUmdtWWw2YlRlQkxSK2NEOTRuUTJNTitBTnkrbEhZN1BpUlpOUVA5UEhRa2lmSERhaXpieDhsSlFHeVlDcExMUmhsa2l2VlBpR2Z5VWo5RlhnUFdtQS9ZZk9FNmZWbC8yNFZ6aEVHMSswenFpR0NrY3poVFNicC9xT0U1Sm9lNmlNMHhac280UTVyVzRwWlBiNjExb21NZ2M0d0NmN09QcEZjamNybWllZTkxbk9BeU56Qys3NEl4YUpwdzBRdnpGU2tpWXpscWZxRjNHRDZlVERGUVBTbldXUEp0QXRWZ0Vhc0c0MWsvQW9WMk9ZR01kamdRUnRRZ3NrLzY2dDh3PT0iLCJpYXQiOjE3MjA0MjUxNzMsImV4cCI6MTcyMTAyOTk3M30.9WQoS0-9V5UXjdTQB_EN0aH9H6knqQeX_AGquwjRwtE';

const mockUser = {
  _id: '6659f65f9cde6a32b9d3c8fe',
  email: 'mariem.nacib@esprit.tn',
  verificationToken: providedAccessToken,
  type: 'USER',
  status: 'ONLINE',
  //   accessToken: providedAccessToken,
};

const mockAccommodationRequestDataWithoutReference = {
  source: 'EMAIL',
  details: {
    accommodation: '664b5d3f3da9bcd0465522ed',
    checkIn: '2024-01-01',
    checkOut: '2025-01-01',
    guestsCount: 5,
    childrenCount: 5,
    selectedService: 'CATERED',
    type: 'chalet',
    note: 'contact me on my personal phone number',
  },
  onModel: 'User',
  customer: { _id: '6659f65f9cde6a32b9d3c8fe' },
  comments: ['Comment 1', 'Comment 2'],
};
const mockAccommodationRequestData = {
  reference: 'A24_00001',
  source: 'EMAIL',
  details: {
    accommodation: '664b5d3f3da9bcd0465522ed',
    checkIn: '2024-01-01',
    checkOut: '2025-01-01',
    guestsCount: 5,
    childrenCount: 5,
    selectedService: 'CATERED',
    type: 'chalet',
    note: 'contact me on my personal phone number',
  },
  onModel: 'User',
  customer: '6659f65f9cde6a32b9d3c8fe',
  comments: ['Comment 1', 'Comment 2'],
};

const mockRequestDataWithNonExistentUser = {
  source: 'EMAIL',
  details: {
    accommodation: '664b5d3f3da9bcd0465522ed',
    checkIn: '2024-01-01',
    checkOut: '2025-01-01',
    guestsCount: 5,
    childrenCount: 5,
    selectedService: 'CATERED',
    type: 'chalet',
    note: 'contact me on my personal phone number',
  },
  onModel: 'User',
  customer: '0059f65f9cde6a32b9d3c800',
  comments: ['Comment 1', 'Comment 2'],
};

const mockRequestDataUpdated = {
  source: 'EMAIL',
  details: {
    accommodation: '664b5d3f3da9bcd0465522ed',
    checkIn: '2024-01-01',
    checkOut: '2025-01-01',
    guestsCount: 5,
    childrenCount: 5,
    selectedService: 'CATERED',
    type: 'chalet',
    note: 'contact me on my personal phone number',
  },
  onModel: 'User',
  customer: { _id: '6659f65f9cde6a32b9d3c8fe' },
  comments: ['Comment 1 updated via TDD tests', 'Comment 2', 'Added comment via tdd']
};

// Custom middleware to mock authentication
app.use((req, res, next) => {
  const token = req.cookies.accessToken;
  if (token === providedAccessToken) {
    req.userId = mockUser._id;
    req.userIds = [mockUser._id];
    return next();
  }
  return res.status(401).json({ error: 'Unauthorized. Invalid access token.' });
});

describe('Accommodation Request Controller', () => {
  let requestRepository;
  let createdRequestId;
  let requestService;

  before(async () => {
    requestRepository = new AccommodationRequestRepository();
    requestService = new AccommodationRequestService();

    await requestRepository.deleteMany({ filter: {} });

    // Create a request to be updated
    const res = await request(app)
      .post('/v1/accommodation')
      .set('Cookie', `accessToken=${providedAccessToken}`)
      .send(mockAccommodationRequestData);
    createdRequestId = res.body.data?._id;
    mockAccommodationRequestData.reference = res.body.data?.reference;
  });

  describe('POST /v1/accommodation', () => {
    const accessToken = `accessToken=${providedAccessToken}`;

    it('should return 401 if no token is provided', async () => {
      const res = await request(app).post('/v1/accommodation').send(mockAccommodationRequestData);
      expect(res.status).to.equal(401);
      expect(res.body.error).to.equal('Unauthorized. Invalid access token.');
    });

    it('should return 401 if token is invalid', async () => {
      const res = await request(app)
        .post('/v1/accommodation')
        .set('Cookie', 'accessToken=invalidToken')
        .send(mockAccommodationRequestData);
      expect(res.status).to.equal(401);
      expect(res.body.error).to.equal('Unauthorized. Invalid access token.');
    });

    it('should add request successfully', async () => {
      const requestDataWithoutReference = { ...mockAccommodationRequestDataWithoutReference };
      delete requestDataWithoutReference.reference;
      const res = await request(app)
        .post('/v1/accommodation')
        .set('Cookie', `accessToken=${providedAccessToken}`)
        .send(requestDataWithoutReference);
      expect(res.status).to.equal(200);
      expect(res.body.message).to.equal('Accommodation Request added successfully');
      expect(res.body.data).to.have.property('_id');
    });

    it('should return 400 if required fields are missing', async () => {
      const incompleteRequestData = {
        source: 'EMAIL',
        customer: '6641e2656e43ce84995ea43e',
      };
      const res = await request(app)
        .post('/v1/accommodation')
        .set('Cookie', `accessToken=${providedAccessToken}`)
        .send(incompleteRequestData);
      expect(res.status).to.equal(500);
      expect(res.body.error).to.include('Error adding request');
    });

    it('should return 404 if customer does not exist', async () => {
      const invalidCustomerRequestData = {
        ...mockRequestDataWithNonExistentUser,
        customer: 'nonexistentCustomerId',
      };
      const res = await request(app)
        .post('/v1/accommodation')
        .set('Cookie', `accessToken=${providedAccessToken}`)
        .send(invalidCustomerRequestData);
      expect(res.status).to.equal(500);
      expect(res.body.error).to.include('Error processing user ID verification');
    });

    it('should generate correct reference and increment requestsCount', async () => {
      // Mock the RequestRepository count and exists methods
      const countStub = sinon.stub(requestRepository.prototype, 'count').resolves(0);
      const existsStub = sinon.stub(requestRepository.prototype, 'exists').onFirstCall().resolves(false);

      const mockAccommodationRequestDataWithoutReference = { ...mockAccommodationRequestDataWithoutReference };
      delete mockAccommodationRequestDataWithoutReference.reference;

      const res1 = await request(app)
        .post('/v1/accommodation')
        .set('Cookie', `accessToken=${providedAccessToken}`)
        .send(requestDataWithoutReference);
      expect(res1.status).to.equal(200);
      expect(res1.body.data.reference).to.equal('A24_00001');
      // Mock exists to return true once to simulate an existing reference
      existsStub.onSecondCall().resolves(true).onThirdCall().resolves(false);

      const res2 = await request(app)
        .post('/v1/accommodation')
        .set('Cookie', `accessToken=${providedAccessToken}`)
        .send(requestDataWithoutReference);
      expect(res2.status).to.equal(200);
      expect(res2.body.data.reference).to.equal('A24_00002');

      expect(countStub.calledTwice).to.be.true;
      expect(existsStub.calledThrice).to.be.true;

      // Restore stubs
      countStub.restore();
      existsStub.restore();
    });
  });

  describe('PUT /v1/accommodation/:reference', () => {
    // const accessToken = `accessToken=${providedAccessToken}`;

    it('should update request successfully', async () => {
      const res = await request(app)
        .put(`/v1/accommodation/A24_00001`)
        // .set('Cookie', `accessToken=${providedAccessToken}`)
        .send(mockRequestDataUpdated);
      expect(res.status).to.equal(200);
      expect(res.body.message).to.equal('Accommodation Request updated successfully');
      expect(res.body.data).to.have.property('_id');
    });

    it('should return 404 if request does not exist', async () => {
      const nonExistentReference = 'nonexistentReference';
      const res = await request(app)
        .put(`/v1/accommodation/${nonExistentReference}`)
        .set('Cookie', `accessToken=${providedAccessToken}`)
        .send(mockRequestDataUpdated);
      expect(res.status).to.equal(404);
      expect(res.body.error).to.include('Request not found');
    });

    it('should return 500 if update fails', async () => {
      const updateStub = sinon.stub(requestRepository.prototype, 'updateById').resolves(null);
      const res = await request(app)
        .put(`/v1/accommodation/${mockAccommodationRequestData.reference}`)
        .set('Cookie', `accessToken=${providedAccessToken}`)
        .send(mockRequestDataUpdated);
      expect(res.status).to.equal(400);
      expect(res.body.error).to.include('Failed to update request');
      updateStub.restore();
    });
  });

  describe('GET /v1/accommodation/:reference', () => {
    const accessToken = `accessToken=${providedAccessToken}`;

    it('should fetch request successfully by reference', async () => {
      const res = await request(app)
        .get('/v1/accommodation/A24_00001')
        .set('Cookie', `accessToken=${providedAccessToken}`);
      expect(res.status).to.equal(200);
      expect(res.body.message).to.equal('Request fetched successfully by reference');
      expect(res.body.data).to.have.property('_id');
    });

    it('should return 404 if request does not exist', async () => {
      const res = await request(app)
        .get('/v1/accommodation/A24_00010')
        .set('Cookie', `accessToken=${providedAccessToken}`);
      expect(res.status).to.equal(404);
      expect(res.body.error).to.include('Request not found by reference');
    });

    it('should fetch request and update collaborator names', async () => {
      const res = await request(app)
        .get('/v1/accommodation/A24_00001')
        .set('Cookie', `accessToken=${providedAccessToken}`);
      expect(res.status).to.equal(200);
      expect(res.body.message).to.equal('Request fetched successfully by reference');
      expect(res.body.data).to.have.property('_id');

      // Verify collaborator names update logic
      res.body.data.services.forEach((service, serviceIndex) => {
        service.collaborators.forEach((collaborator, collaboratorIndex) => {
          expect(collaborator).to.be.a('string');
        });
      });
    });
  });

  describe('GET /v1/accommodation', () => {
    const accessToken = `accessToken=${providedAccessToken}`;

    it('should return empty array if no requests match the reference filter', async () => {
      const res = await request(app)
        .get('/v1/accommodation?reference=NON_EXISTENT_REFERENCE')
        .set('Cookie', `accessToken=${providedAccessToken}`);
      expect(res.status).to.equal(200);
      expect(res.body).to.have.property('data').that.is.an('array').that.is.empty;
      expect(res.body.message).to.include('No requests match the provided criteria');
    });

    it('should filter requests with all provided filters', async () => {
      const filters = {
        isDelegation: true,
        vatIncluded: false,
        type: 'RENT',
        method: 'DIGITAL',
        paymentStatus: 'PROCESSING',
        paymentType: 'DEPOSIT',
        smallLuggageCount: 2,
        bigLuggageCount: 6,
        kidsCount: 2,
        babiesCount: 0,
        requestedDuration: 180,
        kmIncluded: 20,
        pickupWithMeetAndGreetPickUp: true,
        pickupWithMeetAndGreetDropoff: true,
        statusOffre: 'UNDER_REVIEW',
        page: 2,
        isUrgent: false,
        isB2B: 'B2C',
      };
      const query = new URLSearchParams(filters).toString();

      const res = await request(app)
        .get(`/v1/accommodation?${query}`)
        .set('Cookie', `accessToken=${providedAccessToken}`);
      expect(res.status).to.equal(200);
      expect(res.body.message).to.include('No requests match the provided criteria');
      expect(res.body.data).to.be.an('array');
    });

    it('should filter requests by search query', async () => {
      // Create a request to be matched by search query
      const requestDataWithoutReference = { ...mockAccommodationRequestData };
      delete requestDataWithoutReference.reference;
      await request(app)
        .post('/v1/accommodation')
        .set('Cookie', `accessToken=${providedAccessToken}`)
        .send(requestDataWithoutReference);

      const searchQuery = 'EMAIL';
      const res = await request(app)
        .get(`/v1/accommodation?search=${searchQuery}`)
        .set('Cookie', `accessToken=${providedAccessToken}`);
      expect(res.status).to.equal(200);
      expect(res.body).to.have.property('paginatedResults').that.is.an('array');
      expect(res.body.paginatedResults).to.not.be.empty;
      expect(res.body.paginatedResults[0].source).to.include(searchQuery);
    });

    it('should filter requests by status', async () => {
      // Create a request to be matched by status filter
      const requestDataWithoutReference = { ...mockAccommodationRequestData, status: 'NEW' };
      delete requestDataWithoutReference.reference;
      await request(app)
        .post('/v1/accommodation')
        .set('Cookie', `accessToken=${providedAccessToken}`)
        .send(requestDataWithoutReference);

      const statusFilter = 'new';
      const res = await request(app)
        .get(`/v1/accommodation?status=${statusFilter}`)
        .set('Cookie', `accessToken=${providedAccessToken}`);
      expect(res.status).to.equal(200);
      expect(res.body).to.have.property('paginatedResults').that.is.an('array');
      expect(res.body.paginatedResults).to.not.be.empty;
      expect(res.body.paginatedResults[0].status).to.equal('NEW');
    });
  });
});
Leave a Comment