Untitled

 avatar
unknown
plain_text
a year ago
49 kB
5
Indexable
import { expect } from 'chai';
import { after, afterEach, before, describe, it } from 'mocha';
import sinon from 'sinon';

import app from '../src/app.js';
import { AmenityController } from '../src/controllers/amenity.controller.js';
import { AccommodationRepository } from '../src/repositories/accommodation.repository.js';
import { AccommodationServicesRepository } from '../src/repositories/accommodationServices.repository.js';
import { AmenityRepository } from '../src/repositories/amenity.repository.js';
import { DestinationRepository } from '../src/repositories/destination.repository.js';
import { FacilityRepository } from '../src/repositories/facility.repository.js';
// import { AccommodationService } from '../src/services/accommodation.service.js';
import { AccommodationService } from '../src/services/accommodation.service.js';
import { AccommodationServicesService } from '../src/services/accommodationService.service.js';
import { AmenityService } from '../src/services/amenity.service.js';
import { DestinationService } from '../src/services/destination.service.js';
import { FacilityService } from '../src/services/facility.service.js';

const providedAccessToken =
  'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJkYXRhIjoiU0FrM3F1eEVnMU9xYyt2ejUwVnVBbWF1VXpQa3pDbXd4emg0VStNd0t6WnpkakFGemVvTW15NllwQ2JYd2llN1RDdHRJdzBPRlltdmdxREhxTjR2OUJrVUpkSVgwK0hYZ2ZROWFXUllhNkFkT1BGNTF0WXZUZjAzMW1US2djaGNJcno3TDJoZHgzVG9oWFlLYlZzdFpTNm03NnFZRm9oMUo3ZmJUMjdhS3RaSnJXL2oyZWFIOFZ6bVppam8wUW9lWXNuQUpUZm1RR09MTkFDNFp3UGRIMmY2YVp1R0VuUy9veWR2R1FrNStWNFBlVXYrYVdETmd2ZUpJdUN3OVJMdnBWYXkwVWJTWDh0RHlDb28vZ29ZNWs3dTZacHg2NEY1MU0rQkxaYVI4UWpuOWRTS0dMZXBOa0NZcFppaEMvRzJzVUZEdVY4MUtyMHdNOGt6RUpwOXhBPT0iLCJpYXQiOjE3MjA2ODQ0MTMsImV4cCI6MTcyMDY4NTAxM30.zg2zVuMACza0WY8AJ5JEXqFC1iQYJmAP41lll8c2hM8';

const mockUser = {
  _id: '6659f65f9cde6a32b9d3c8fe',
  email: 'mariem.nacib@esprit.tn',
  //   verificationToken: providedAccessToken,
  type: 'USER',
  status: 'ONLINE',
  accessToken: providedAccessToken,
};
// Custom middleware to mock authentication
const authMiddleware = (req, res, next) => {
  req.userId = mockUser._id;
  req.user = mockUser;
  return next();
};

const mockAmenity = {
  title: 'TEST_AMENITY',
  category: 'WELLNESS',
  alternatives: [],
};

const mockFacility = {
  title: 'TEST_FACILITY',
  category: 'BEDROOM',
  alternatives: [],
};
const mockAccommodationService = {
  name: 'TEST ACCOMMODATION SERVICE',
  description: ['dscription1', 'description2'],
  image: { url: 'test', blur: 'test', alt: 'test' },
};
const mockAccommodationServiceUpdate = {
  description: ['dscription1', 'description2', 'descriprion3 updated'],
};
const mockDestination = {
  country: 'country',
  city: 'city',
  description: ['description1', 'description2'],
  hasChalets: true,
  hasVillas: false,
  hasApartments: false,
  image: { url: 'test', blur: 'test', alt: 'test' },
  activities: [
    {
      title: 'activity1',
      season: 'SUMMER',
      description: 'description',
      image: { url: 'test', blur: 'test', alt: 'test' },
    },
  ],
  hotels: [
    {
      name: 'hotel1',
      description: 'description',
      gallery: [
        { url: 'test', blur: 'test', alt: 'test' },
        { url: 'test1', blur: 'test1', alt: 'test1' },
      ],
    },
  ],
  restaurants: [
    {
      name: 'restaurant1',
      webSite: 'web site',
      description: 'description',
      address: 'address test',
      typeOfCuisine: 'VEGAN',
      gallery: [
        { url: 'test', blur: 'test', alt: 'test' },
        { url: 'test1', blur: 'test1', alt: 'test1' },
      ],
    },
  ],
};

// const mockWishList = {
//   accommodations: ['', ''],
// };
const mockAccommodation = {
  description: 'description',
  isActive: false,
  isPrivate: true,
  name: 'test',
  type: 'VILLA',
  location: '666ad06319cd2589bfd20134',
  detailedLocation: 'Near Eiffel Tower',
  geoLocation: {
    longitude: 2.2943506,
    latitude: 48.8588443,
    country: 'aaa',
    city: 'eeee',
    address: 'aaaa',
    label: 'aaaa',
  },
  guestsCount: 8,
  childrenCount: 6,
  bedroomsCount: 4,
  bathroomsCount: 4,
  surfaceArea: {
    value: 700,
    unit: '',
  },
  policies: ['No pets allowed', 'No smoking'],
  amenities: ['662f70969d66016ca19a811e'],
  agency: '66472b56998506e08993abe2',

  prices: [
    {
      price: 500,
      currency: {
        label: 'aaaaa',
        code: 'EUR',
      },
      priceUnit: 'WEEK',
      priceType: 'NET_PRICE',
      from: '2024-02-04T00:00:00.000Z',
      to: '2024-02-06T00:00:00.000Z',
      isAvailable: true,
    },
  ],
  layouts: [
    {
      title: 'Ground Floor',
      order: 1,
      image: { url: 'test', blur: 'test', alt: 'test' },
      facilities: ['661d1d862b4207d7a43af662'],
    },
    {
      title: 'First Floor',
      order: 2,
      image: { url: 'test', blur: 'test', alt: 'test' },
      facilities: ['662b6bbec6f1500452e30520'],
    },
  ],
  nearbyLocations: ['Eiffel Tower', 'Louvre Museum'],
  categories: ['MOUNTAIN_VIEW', 'PET_FRIENDLY'],
  seasons: ['SUMMER'],
  services: ['SELF_CATERED', 'BED_AND_BREAKFAST'],
  gallery: [
    { url: 'test', blur: 'test', alt: 'test' },
    { url: 'test1', blur: 'test1', alt: 'test1' },
  ],

  image: { url: 'test', blur: 'test', alt: 'test' },
};
// Custom middleware to mock authentication
app.use(authMiddleware);

describe('Amenity Service', () => {
  let amenityRepository;
  let amenityService;
  let amenityController;
  before(async () => {
    amenityRepository = new AmenityRepository();
    amenityService = new AmenityService();
    amenityController = new AmenityController();
    await amenityRepository.deleteMany({ filter: {} });
  });

  describe('addAmenity', () => {
    it('should add amenity successfully', async () => {
      const req = {
        body: mockAmenity,
        userId: mockUser._id,
        user: mockUser,
        get: () => providedAccessToken,
      };
      const res = {
        status: sinon.stub().returnsThis(),
        json: sinon.stub().returnsThis(),
        send: sinon.stub().returnsThis(),
      };

      // await amenityService.addAmenity(req.body, req, res);
      await amenityController.addAmenity(mockAmenity, req, res);

      expect(res.status.calledWith(201)).to.be.true;
    });

    it('should return error if amenity already exists', async () => {
      sinon.stub(amenityRepository, 'findOne').resolves(mockAmenity.title);
      const req = { body: mockAmenity, userId: mockUser._id, user: mockUser };

      const res = {
        status: sinon.stub().returnsThis(),
        json: sinon.stub().returnsThis(),
      };

      await amenityService.addAmenity(mockAmenity, req, res);
      console.log(res.status);
      console.log(res.error);
      await amenityController.addAmenity(req.body, req, res);
      expect(res.status, 400);
      expect(res.error, 'Amenity title already exists');
      // sinon.restore();
      // sinon.stub(amenityRepository, 'findOne').resolves(null);
    });
  });

  describe('displayAllAmenities', () => {
    it('should display all amenities', async () => {
      const req = {};
      const res = {
        status: sinon.stub().returnsThis(),
        json: sinon.stub().returnsThis(),
      };

      await amenityController.displayAmenities(req, res);
      expect(res.status.calledWith(200)).to.be.true;
    });
    it('should return internal server error', async () => {
      const errorMessage = 'Internal Server Error';
      sinon.stub(amenityRepository, 'findAll').throws(new Error(errorMessage));

      const req = {};
      const res = {
        status: sinon.stub().returnsThis(),
        json: sinon.stub().returnsThis(),
      };

      await amenityService.displayAllAmenities(req, res);
      await amenityController.displayAmenities(req, res);
      expect(res.status, 500);
      expect(res.json, { error: errorMessage });
    });
  });
});

describe('Facility Service', () => {
  let facilityRepository;

  let facilityService;
  before(async () => {
    facilityRepository = new FacilityRepository();
    facilityService = new FacilityService();

    await facilityRepository.deleteMany({ filter: {} });
    // sinon.stub(facilityRepository, 'findOne').resolves(null);
    // sinon.stub(facilityRepository, 'create').resolves(mockFacility);
    // sinon.stub(facilityRepository, 'findAll').resolves([mockFacility]);
    // sinon.stub(facilityRepository, 'insertMany').resolves([{ acknowledged: true }]);
    // sinon.stub(fs, 'readFile').callsFake((path, encoding, callback) => {
    //   if (path === './seed/facilities.json') {
    //     callback(null, JSON.stringify([mockFacility]));
    //   } else {
    //     callback(new Error('File not found'));
    //   }
    // });
  });
  after(() => {
    sinon.restore();
  });
  describe('addFacility', () => {
    it('should add facility successfully', async () => {
      const req = { body: mockFacility, userId: mockUser._id };
      const res = {
        status: sinon.stub().returnsThis(),
        json: sinon.stub().returnsThis(),
      };

      await facilityService.addFacility(req.body, req, res);
      expect(res.status.calledWith(201)).to.be.true;
    });

    it('should return error if facility already exists', async () => {
      sinon.restore();
      // sinon.stub(facilityRepository, 'findOne').resolves(mockFacility);
      const req = {
        headers: {
          authorization: `Bearer ${providedAccessToken}`,
        },
        body: mockFacility,
        userId: mockUser._id,
        get: () => providedAccessToken,
      };
      //   const req = { body: mockFacility, userId: mockUser._id };
      const res = {
        status: sinon.stub().returnsThis(),
        json: sinon.stub().returnsThis(),
      };

      await facilityService.addFacility(req.body, req, res);
      expect(res.status.calledWith(400)).to.be.true;

      sinon.restore();
      // sinon.stub(facilityRepository, 'findOne').resolves(null);
    });
  });

  describe('displayAllFacilities', () => {
    it('should display all facilities', async () => {
      const req = {};
      const res = {
        status: sinon.stub().returnsThis(),
        json: sinon.stub().returnsThis(),
      };

      await facilityService.displayAllFacilities(req, res);
      expect(res.status.calledWith(200)).to.be.true;
    });
  });

  //   describe('addFacilitiesFromSeed', () => {
  //     it('should add facilities from seed file successfully', async () => {
  //       const req = {};
  //       const res = {
  //         status: sinon.stub().returnsThis(),
  //         json: sinon.stub().returnsThis(),
  //       };

  //       await facilityService.addFacilitiesFromSeed(req, res);
  //       expect(res.status.calledWith(200)).to.be.true;
  //     });

  //     it('should return error if file read fails', async () => {
  //       sinon.restore();
  //       sinon.stub(fs, 'readFile').callsFake((path, encoding, callback) => {
  //         callback(new Error('File not found'));
  //       });

  //       const req = {};
  //       const res = {
  //         status: sinon.stub().returnsThis(),
  //         json: sinon.stub().returnsThis(),
  //       };

  //       await facilityService.addFacilitiesFromSeed(req, res);
  //       expect(res.status.calledWith(500)).to.be.true;

  //       sinon.restore();
  //       sinon.stub(fs, 'readFile').callsFake((path, encoding, callback) => {
  //         callback(null, JSON.stringify([mockFacility]));
  //       });
  //     });

  //     it('should return error if JSON parsing fails', async () => {
  //       sinon.restore();
  //       sinon.stub(fs, 'readFile').callsFake((path, encoding, callback) => {
  //         callback(null, 'invalid JSON');
  //       });

  //       const req = {};
  //       const res = {
  //         status: sinon.stub().returnsThis(),
  //         json: sinon.stub().returnsThis(),
  //       };

  //       await facilityService.addFacilitiesFromSeed(req, res);
  //       expect(res.status.calledWith(500)).to.be.true;

  //       sinon.restore();
  //       sinon.stub(fs, 'readFile').callsFake((path, encoding, callback) => {
  //         callback(null, JSON.stringify([mockFacility]));
  //       });
  //     });
  //   });
});

describe('AccommodationService Service', () => {
  let accommodationServicesRepository;

  let accommodationServicesService;
  //   let fileServiceStub;

  before(async () => {
    accommodationServicesRepository = new AccommodationServicesRepository();
    accommodationServicesService = new AccommodationServicesService();

    // fileServiceStub = sinon.stub(FileService.prototype, 'addImage');
    await accommodationServicesRepository.deleteMany({ filter: {} });
  });

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

  describe('POST /v1/services', () => {
    it('should add a new service with a slugified name', async () => {
      // sinon.stub(accommodationServicesRepository, 'findOne').resolves();
      // sinon.stub(accommodationServicesRepository, 'create').resolves(mockAccommodationService);
      const req = {
        headers: {
          authorization: `Bearer ${providedAccessToken}`,
        },
        // body: { mockAccommodationService },
        userId: mockUser._id,
      };
      const res = {
        status: sinon.stub().returnsThis(),
        json: sinon.stub().returnsThis(),
      };

      await accommodationServicesService.addServices(mockAccommodationService, req, res);

      expect(res.status, 201);
      expect(res.data, mockAccommodationService.slug);
    });

    it('should return error if service slug already exists', async () => {
      // await accommodationServicesRepository.create({ ...mockAccommodationService, slug: 'test-accommodation-service' });

      const req = {
        headers: {
          authorization: `Bearer ${providedAccessToken}`,
        },
        body: mockAccommodationService,
        get: () => providedAccessToken,
      };
      const res = {
        status: sinon.stub().returnsThis(),
        json: sinon.stub().returnsThis(),
      };

      await accommodationServicesService.addServices(mockAccommodationService, req, res);

      expect(res.status, 400);
      expect(res.error, 'Services slug already exists');
    });
  });

  describe('GET /v1/services', () => {
    it('should get all services', async () => {
      const req = {
        headers: {
          authorization: `Bearer ${providedAccessToken}`,
        },
        query: { search: 'test' },
      };
      const res = {
        status: sinon.stub().returnsThis(),
        json: sinon.stub().returnsThis(),
      };

      await accommodationServicesService.displayAllServices(req, res);

      expect(res.status, 200);
      expect(Array.isArray(res.data), true);
    });
  });

  describe('GET /v1/services/:slug', () => {
    it('should get a service by slug', async () => {
      const req = {
        headers: {
          authorization: `Bearer ${providedAccessToken}`,
        },
        params: {
          slug: 'test-accommodation-service',
        },
      };
      const res = {
        status: sinon.stub().returnsThis(),
        json: sinon.stub().returnsThis(),
      };

      await accommodationServicesService.getServiceBySlug(req.params.slug, req, res);

      expect(res.status, 200);
      expect(res.data, 'test-accommodation-service');
    });

    it('should return error if service not found', async () => {
      const req = {
        headers: {
          authorization: `Bearer ${providedAccessToken}`,
        },
        params: {
          slug: 'non-existent-slug',
        },
      };
      const res = {
        status: sinon.stub().returnsThis(),
        json: sinon.stub().returnsThis(),
      };

      await accommodationServicesService.getServiceBySlug(req.params.slug, req, res);

      expect(res.status, 404);
      expect(res.error, 'Service not found');
    });
  });

  describe('PUT /v1/services/:slug', () => {
    it('should update a service by slug', async () => {
      const req = {
        headers: {
          authorization: `Bearer ${providedAccessToken}`,
        },
        params: {
          slug: 'test-accommodation-service',
        },
        body: { mockAccommodationServiceUpdate },
      };
      const res = {
        status: sinon.stub().returnsThis(),
        json: sinon.stub().returnsThis(),
      };

      await accommodationServicesService.updateServiceBySlug(req.params.slug, req.body, req, res);

      expect(res.status.calledWith(200)).to.be.true;
      expect(res.message, 'Service updated successfully');
    });

    it('should return error if service not found', async () => {
      const req = {
        headers: {
          authorization: `Bearer ${providedAccessToken}`,
        },
        params: {
          slug: 'non-existent-slug',
        },
        body: { name: 'NEW NAME' },
      };
      const res = {
        status: sinon.stub().returnsThis(),
        json: sinon.stub().returnsThis(),
      };

      await accommodationServicesService.updateServiceBySlug(req.params.slug, req.body, req, res);

      expect(res.status, 404);
      expect(res.error, 'Service not found');
    });
  });

  describe('DELETE /v1/services/:slug', () => {
    it('should delete a service by slug', async () => {
      const req = {
        headers: {
          authorization: `Bearer ${providedAccessToken}`,
        },
        params: {
          slug: 'test-accommodation-service',
        },
      };
      const res = {
        status: sinon.stub().returnsThis(),
        json: sinon.stub().returnsThis(),
      };

      await accommodationServicesService.deleteServiceBySlug(req.params.slug, req, res);

      expect(res.status.calledWith(200)).to.be.true;
      expect(res.message, 'Service deleted successfully');
    });

    it('should return error if service not found', async () => {
      const req = {
        headers: {
          authorization: `Bearer ${providedAccessToken}`,
        },
        params: {
          slug: 'non-existent-slug',
        },
      };
      const res = {
        status: sinon.stub().returnsThis(),
        json: sinon.stub().returnsThis(),
      };

      await accommodationServicesService.deleteServiceBySlug(req.params.slug, req, res);

      expect(res.status, 404);
      expect(res.error, 'Services not found');
    });
  });
});

describe('Destination Service', () => {
  let destinationRepository;

  let destinationService;
  before(async () => {
    destinationRepository = new DestinationRepository();
    destinationService = new DestinationService();

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

  afterEach(() => {
    sinon.restore();
  });
  describe('POST /v1/destinations', () => {
    it('should add a new destination', async () => {
      // sinon.stub(destinationRepository, 'exists').resolves(false);
      // sinon.stub(destinationRepository, 'create').resolves(mockDestination);
      const req = {
        headers: {
          authorization: `Bearer ${providedAccessToken}`,
        },
        userId: mockUser._id,
      };
      const res = {
        status: sinon.stub().returnsThis(),
        json: sinon.stub().returnsThis(),
      };
      await destinationService.addDestination(mockDestination, req, res);

      expect(res.status, 201);
      expect(res.data, mockDestination.slug);
      expect(res.message, 'Destination created successfully');
    });

    it('should return error if destination slug already exists', async () => {
      // sinon.stub(destinationRepository, 'exists').resolves(true);
      const req = {
        headers: {
          authorization: `Bearer ${providedAccessToken}`,
        },
        userId: mockUser._id,
        get: () => providedAccessToken,
      };
      const res = {
        status: sinon.stub().returnsThis(),
        json: sinon.stub().returnsThis(),
      };
      await destinationService.addDestination(mockDestination, req, res);

      //   expect(result).to.have.property('status').that.equals(400);
      //   expect(result).to.have.property('error').that.equals('Destination slug already exists');

      expect(res.status, 400);
      expect(res.error, 'Destination slug already exists');
    });

    it('should handle internal server error during add destination', async () => {
      // sinon.stub(destinationRepository, 'exists').rejects(new Error('Database connection error'));
      const req = {
        headers: {
          authorization: `Bearer ${providedAccessToken}`,
        },
        userId: mockUser._id,
        get: () => providedAccessToken,
      };
      const res = {
        status: sinon.stub().returnsThis(),
        json: sinon.stub().returnsThis(),
      };
      await destinationService.addDestination(mockDestination, req, res);

      //   expect(result).to.have.property('status').that.equals(500);
      // expect(result).to.have.property('error').that.equals('Database connection error');

      expect(res.status, 500);
      expect(res.error, 'Database connection error');
    });
  });

  describe('GET /v1/destinations', () => {
    it('should get all destinations with filters', async () => {
      // const query = new URLSearchParams(filters).toString();
      // sinon.stub(destinationRepository, 'findAllWithPagination').resolves([mockDestination]);
      // sinon.stub(destinationRepository, '').resolves(query);
      const req = {
        headers: {
          authorization: `Bearer ${providedAccessToken}`,
        },
        userId: mockUser._id,
        query: {
          search: 'france',
          country: 'france',
          hasChalets: 'true',
          hasVillas: 'true',
          hasApartments: 'true',
          season: 'summer',
          hotelName: 'hotel1',
          restaurantName: 'restaurant1',
          activityTitle: 'activity1',
          cuisineType: 'VEGAN',
          page: '1',
          itemsPerPage: '1',
        },
      };
      // const res = await request(app).get(`/v1/destinations?${query}`);
      // expect(res.status).to.equal(200);
      // expect(res.body.message).to.include(
      //   'Filter applied successfully. Requests filtered based on the provided criteria.',
      // );
      const res = {
        status: sinon.stub().returnsThis(),
        json: sinon.stub().returnsThis(),
      };

      await destinationService.displayDestinations(req, res);

      //   expect(result).to.have.property('status').that.equals(200);
      //   expect(result).to.have.property('data').that.has.property('count').that.equals(1);
      // expect(result).to.have.property('data').that.has.property('data').that.deep.equals([mockDestination]);

      expect(res.status, 200);
      //   expect(res.data).that.has.property('count').that.equals(1);
      expect(res.message, mockDestination);
    });
  });

  describe('PUT /v1/destinations/:slug', () => {
    it('should update a destination', async () => {
      const mockUpdatedDestination = { ...mockDestination, city: 'Updated City' };
      // sinon.stub(destinationRepository, 'findOne').resolves(mockDestination);
      // sinon.stub(destinationRepository, 'updateById').resolves(mockUpdatedDestination);
      const req = {
        headers: {
          authorization: `Bearer ${providedAccessToken}`,
        },
        userId: mockUser._id,
      };
      const res = {
        status: sinon.stub().returnsThis(),
        json: sinon.stub().returnsThis(),
      };
      await destinationService.editDestination(mockDestination.slug, mockUpdatedDestination, req, res);

      //   expect(result).to.have.property('status').that.equals(200);
      //   expect(result)
      //     .to.have.property('data')
      //     .that.deep.equals({ data: mockUpdatedDestination, message: 'Destination updated successfully' });

      expect(res.status, 200);
      expect(res.data, mockUpdatedDestination);
      expect(res.message, 'Destination updated successfully');
    });

    it('should return error if destination not found', async () => {
      // sinon.stub(destinationRepository, 'findOne').resolves(null);
      const req = {
        headers: {
          authorization: `Bearer ${providedAccessToken}`,
        },
        userId: mockUser._id,
      };
      const res = {
        status: sinon.stub().returnsThis(),
        json: sinon.stub().returnsThis(),
      };
      await destinationService.editDestination('non-existent-slug', mockDestination, req, res);

      //   expect(result).to.have.property('status').that.equals(404);
      // expect(result).to.have.property('error').that.equals('Destination not found');
      expect(res.status, 404);
      expect(res.error, 'Destination not found');
    });

    // Add more tests for handling errors, validation, etc.
  });

  describe('GET /v1/destinations/filters', () => {
    it('should fetch filters for destinations', async () => {
      // sinon.stub(destinationRepository, 'getDistinctValues').resolves(['Country1', 'Country2']);
      sinon.stub(destinationRepository, 'aggregate').resolves({
        hotels: [{ title: 'Hotel1', value: 'Hotel1' }],
        restaurants: [{ title: 'Restaurant1', value: 'Restaurant1' }],
        activities: [{ title: 'Activity1', value: 'Activity1' }],
        cuisineTypesInRestaurants: [{ title: 'Vegan', value: 'Vegan' }],
      });
      const req = {
        headers: {
          authorization: `Bearer ${providedAccessToken}`,
        },
        userId: mockUser._id,
      };
      const res = {
        status: sinon.stub().returnsThis(),
        json: sinon.stub().returnsThis(),
      };
      await destinationService.getFilters(req, res);

      // expect(result).to.have.property('status').that.equals(200);
      expect(res.status, 200);
    });
  });
  describe('GET /v1/destinations/:slug', () => {
    it('should get a destination by slug', async () => {
      const req = {
        headers: {
          authorization: `Bearer ${providedAccessToken}`,
        },
        params: {
          slug: 'city',
        },
      };
      const res = {
        status: sinon.stub().returnsThis(),
        json: sinon.stub().returnsThis(),
      };

      await destinationService.getDestinationBySlug(req.params.slug, req, res);

      expect(res.status, 200);
      expect(res.data, 'city');
    });

    it('should return error if destination not found', async () => {
      const req = {
        headers: {
          authorization: `Bearer ${providedAccessToken}`,
        },
        params: {
          slug: 'non-existent-slug',
        },
      };
      const res = {
        status: sinon.stub().returnsThis(),
        json: sinon.stub().returnsThis(),
      };

      await destinationService.getDestinationBySlug(req.params.slug, req, res);

      expect(res.status, 404);
      expect(res.error, 'Destination not found');
    });
  });
});

describe('Accommodation Service', () => {
  let accommodationRepository;
  let destinationRepository;
  let amenityRepository;
  let facilityRepository;
  let accommodationService;
  let createdDestination;
  let createdAmenity;
  let createdFacility;
  let createdService;
  let accommodationServicesRepository;
  before(async () => {
    accommodationRepository = new AccommodationRepository();
    accommodationService = new AccommodationService();
    destinationRepository = new DestinationRepository();
    amenityRepository = new AmenityRepository();
    facilityRepository = new FacilityRepository();
    accommodationServicesRepository = new AccommodationServicesRepository();

    // Clean up existing data
    await accommodationRepository.deleteMany({});
    await destinationRepository.deleteMany({});
    await amenityRepository.deleteMany({});
    await facilityRepository.deleteMany({});
    await accommodationServicesRepository.deleteMany({});

    // Create necessary dependencies
    createdDestination = await destinationRepository.create(mockDestination);
    createdAmenity = await amenityRepository.create(mockAmenity);
    createdFacility = await facilityRepository.create(mockFacility);
    createdService = await accommodationServicesRepository.create(mockAccommodationService);

    // // Update mockAccommodation with created dependencies
    // mockAccommodation.location = createdDestination._id;
    // mockAccommodation.amenities = [createdAmenity._id];
    // mockAccommodation.layouts[0].facilities = [createdFacility._id];
  });
  describe('POST /v1/accommodations', () => {
    it('should create a new accommodation', async () => {
      const mockAccommodation = {
        description: 'description',
        isActive: false,
        isPrivate: true,
        name: 'test',
        type: 'VILLA',
        location: createdDestination._id,
        detailedLocation: 'Near Eiffel Tower',
        geoLocation: {
          longitude: 2.2943506,
          latitude: 48.8588443,
          country: 'aaa',
          city: 'eeee',
          address: 'aaaa',
          label: 'aaaa',
        },
        guestsCount: 8,
        childrenCount: 6,
        bedroomsCount: 4,
        bathroomsCount: 4,
        surfaceArea: {
          value: 700,
          unit: '',
        },
        policies: ['No pets allowed', 'No smoking'],
        amenities: [createdAmenity._id],
        agency: '66472b56998506e08993abe2',

        prices: [
          {
            price: 500,
            currency: {
              label: 'aaaaa',
              code: 'EUR',
            },
            priceUnit: 'WEEK',
            priceType: 'NET_PRICE',
            from: '2024-02-04T00:00:00.000Z',
            to: '2024-02-06T00:00:00.000Z',
            isAvailable: true,
          },
        ],
        layouts: [
          {
            title: 'Ground Floor',
            order: 1,
            image: { url: 'test', blur: 'test', alt: 'test' },
            facilities: [createdFacility._id],
          },
          {
            title: 'First Floor',
            order: 2,
            image: { url: 'test', blur: 'test', alt: 'test' },
            facilities: [createdFacility._id],
          },
        ],
        nearbyLocations: ['Eiffel Tower', 'Louvre Museum'],
        categories: ['MOUNTAIN_VIEW', 'PET_FRIENDLY'],
        seasons: ['SUMMER'],
        services: [createdService._id],
        gallery: [
          { url: 'test', blur: 'test', alt: 'test' },
          { url: 'test1', blur: 'test1', alt: 'test1' },
        ],

        image: { url: 'test', blur: 'test', alt: 'test' },
      };
      // sinon.stub(accommodationRepository, 'exists').resolves();
      // sinon.stub(accommodationRepository, 'create').resolves(mockAccommodation);
      // sinon.stub(destinationRepository, 'findById').resolves();
      const req = {
        headers: {
          authorization: `Bearer ${providedAccessToken}`,
        },
        userId: mockUser._id,
      };
      const res = {
        status: sinon.stub().returnsThis(),
        json: sinon.stub().returnsThis(),
      };
      await accommodationService.addAccommodation(mockAccommodation, req, res);

      expect(res.status, 201);
      expect(res.data, mockAccommodation);
    });
    it('should return error if accommodation slug already exists', async () => {
      const mockAccommodation = {
        description: 'description',
        isActive: false,
        isPrivate: true,
        name: 'test',
        type: 'VILLA',
        location: createdDestination._id,
        detailedLocation: 'Near Eiffel Tower',
        geoLocation: {
          longitude: 2.2943506,
          latitude: 48.8588443,
          country: 'aaa',
          city: 'eeee',
          address: 'aaaa',
          label: 'aaaa',
        },
        guestsCount: 8,
        childrenCount: 6,
        bedroomsCount: 4,
        bathroomsCount: 4,
        surfaceArea: {
          value: 700,
          unit: '',
        },
        policies: ['No pets allowed', 'No smoking'],
        amenities: [createdAmenity._id],
        agency: '66472b56998506e08993abe2',

        prices: [
          {
            price: 500,
            currency: {
              label: 'aaaaa',
              code: 'EUR',
            },
            priceUnit: 'WEEK',
            priceType: 'NET_PRICE',
            from: '2024-02-04T00:00:00.000Z',
            to: '2024-02-06T00:00:00.000Z',
            isAvailable: true,
          },
        ],
        layouts: [
          {
            title: 'Ground Floor',
            order: 1,
            image: { url: 'test', blur: 'test', alt: 'test' },
            facilities: [createdFacility._id],
          },
          {
            title: 'First Floor',
            order: 2,
            image: { url: 'test', blur: 'test', alt: 'test' },
            facilities: [createdFacility._id],
          },
        ],
        nearbyLocations: ['Eiffel Tower', 'Louvre Museum'],
        categories: ['MOUNTAIN_VIEW', 'PET_FRIENDLY'],
        seasons: ['SUMMER'],
        services: [createdService._id],
        gallery: [
          { url: 'test', blur: 'test', alt: 'test' },
          { url: 'test1', blur: 'test1', alt: 'test1' },
        ],

        image: { url: 'test', blur: 'test', alt: 'test' },
      };

      const req = {
        headers: {
          authorization: `Bearer ${providedAccessToken}`,
        },
        body: mockAccommodation,
        get: () => providedAccessToken,
      };
      const res = {
        status: sinon.stub().returnsThis(),
        json: sinon.stub().returnsThis(),
      };

      await accommodationService.addAccommodation(mockAccommodation, req, res);

      expect(res.status, 400);
      expect(res.error, 'Accommodation already exists');
    });
  });

  describe('GET /v1/accommodations', () => {
    it('should get all accommodations', async () => {
      // sinon.stub(accommodationRepository, 'findAllWithPagination').resolves([mockAccommodation]);

      const req = {
        headers: {
          authorization: `Bearer ${providedAccessToken}`,
        },
        query: {
          search: 'test',
          locations: 'city',
          countries: 'country',
          minPrice: 1,
          maxPrice: 2,
          minNbGuests: 1,
          maxNbGuests: 2,
          minNbChildren: 1,
          maxNbChildren: 2,
          minNbBedrooms: 1,
          maxNbBedrooms: 2,
          guestsCountMin: 1,
          guestsCountMax: 2,
          childrenCountMin: 1,
          childrenCountMax: 2,
          bedroomsCountMin: 1,
          bedroomsCountMax: 2,
          bathroomsCountMin: 1,
          bathroomsCountMax: 2,
          priceMin: 1,
          priceMax: 2,
          country: 'country',
          location: 'country',
          amenities: 'test',
          facilities: 'string',
          isActive: true,
          isPrivate: true,
          category: 'category',
          season: 'summer',
          type: 'chalet',
          services: 'bed and breakfast',
          from: '2024-01-01',
          to: '2024-02-02',
          page: '1',
          itemsPerPage: '1',
        },
      };
      const res = {
        status: sinon.stub().returnsThis(),
        json: sinon.stub().returnsThis(),
      };
      await accommodationService.displayAllAccommodations(req, res);

      expect(res.status, 200);
      expect(Array.isArray(res.data), true);
    });
    it('should get all available accommodation', async () => {
      // sinon.stub(accommodationRepository, 'findAllWithPagination').resolves([mockAccommodation]);
      const req = {
        headers: {
          authorization: `Bearer ${providedAccessToken}`,
        },
        query: {
          search: 'test',
          locations: 'city',
          countries: 'country',
          minPrice: 1,
          maxPrice: 2,
          minNbGuests: 1,
          maxNbGuests: 2,
          minNbChildren: 1,
          maxNbChildren: 2,
          minNbBedrooms: 1,
          maxNbBedrooms: 2,
          guestsCountMin: 1,
          guestsCountMax: 2,
          childrenCountMin: 1,
          childrenCountMax: 2,
          bedroomsCountMin: 1,
          bedroomsCountMax: 2,
          bathroomsCountMin: 1,
          bathroomsCountMax: 2,
          priceMin: 1,
          priceMax: 2,
          country: 'country',
          location: 'country',
          amenities: 'test',
          facilities: 'string',
          isActive: true,
          isPrivate: true,
          category: 'category',
          season: 'summer',
          type: 'chalet',
          services: 'bed and breakfast',
          from: '2024-01-01',
          to: '2024-02-02',
          page: '1',
          itemsPerPage: '1',
        },
      };
      const res = {
        status: sinon.stub().returnsThis(),
        json: sinon.stub().returnsThis(),
      };
      await accommodationService.getAllAccommodationsByAvailability(req, res);

      expect(res.status, 200);
      expect(Array.isArray(res.data), true);
    });
    it('should get list of accommodation by Ids', async () => {
      const req = {
        headers: {
          authorization: `Bearer ${providedAccessToken}`,
        },
        query: {
          search: 'test',
          locations: 'city',
          countries: 'country',
          id: 'test',
          maxPrice: 2,
          minNbGuests: 1,
          maxNbGuests: 2,
          minNbChildren: 1,
          maxNbChildren: 2,
          minNbBedrooms: 1,
          maxNbBedrooms: 2,
          guestsCountMin: 1,
          guestsCountMax: 2,
          childrenCountMin: 1,
          childrenCountMax: 2,
          bedroomsCountMin: 1,
          bedroomsCountMax: 2,
          bathroomsCountMin: 1,
          bathroomsCountMax: 2,
          priceMin: 1,
          priceMax: 2,
          country: 'country',
          location: 'country',
          amenities: 'test',
          facilities: 'string',
          isActive: true,
          isPrivate: true,
          category: 'category',
          season: 'summer',
          type: 'chalet',
          services: 'bed and breakfast',
          from: '2024-01-01',
          to: '2024-02-02',
          page: '1',
          itemsPerPage: '1',
        },
      };
      const res = {
        status: sinon.stub().returnsThis(),
        json: sinon.stub().returnsThis(),
      };
      await accommodationService.getListOfAccommodationById(req, res);
      expect(res.status, 200);
      expect(Array.isArray(res.data), true);
    });
    it('should get accommodation with specific filters', async () => {
      const req = {
        headers: {
          authorization: `Bearer ${providedAccessToken}`,
        },
        query: {
          search: 'test',
          locations: 'city',
          countries: 'country',
          id: 'test',
          maxPrice: 2,
          minNbGuests: 1,
          maxNbGuests: 2,
          minNbChildren: 1,
          maxNbChildren: 2,
          minNbBedrooms: 1,
          maxNbBedrooms: 2,
          guestsCountMin: 1,
          guestsCountMax: 2,
          childrenCountMin: 1,
          childrenCountMax: 2,
          bedroomsCountMin: 1,
          bedroomsCountMax: 2,
          bathroomsCountMin: 1,
          bathroomsCountMax: 2,
          priceMin: 1,
          priceMax: 2,
          country: 'country',
          location: 'country',
          amenities: 'test',
          facilities: 'string',
          isActive: true,
          isPrivate: true,
          category: 'category',
          season: 'summer',
          type: 'chalet',
          services: 'bed and breakfast',
          from: '2024-01-01',
          to: '2024-02-02',
          page: '1',
          itemsPerPage: '1',
        },
      };
      const res = {
        status: sinon.stub().returnsThis(),
        json: sinon.stub().returnsThis(),
      };
      await accommodationService.displayAllAccommodationsWithSpecification(req, res);
      expect(res.status, 200);
      expect(Array.isArray(res.data), true);
    });
    it('should get accommodation by slug ', async () => {
      // sinon.stub(accommodationRepository, 'findOne').resolves(mockAccommodation.slug);

      const req = {
        headers: {
          authorization: `Bearer ${providedAccessToken}`,
        },
        params: {
          slug: 'villa-new1-city',
        },
      };
      const res = {
        status: sinon.stub().returnsThis(),
        json: sinon.stub().returnsThis(),
      };

      await accommodationService.getAccommodationBySlug(req.params.slug, req, res);

      expect(res.status, 200);
      expect(res.data, 'city');
    });
    it('should get accommodation features by accommodation slug ', async () => {
      // sinon.stub(accommodationRepository, 'findOne').resolves(mockAccommodation.slug);

      const req = {
        headers: {
          authorization: `Bearer ${providedAccessToken}`,
        },
        params: {
          slug: 'villa-new1-city',
        },
      };
      const res = {
        status: sinon.stub().returnsThis(),
        json: sinon.stub().returnsThis(),
      };

      await accommodationService.getAccommodationFeaturesBySlug(req.params.slug, req, res);

      expect(res.status, 200);
      expect(res.data, 'city');
    });
    it('should get accommodation features by accommodation Id ', async () => {
      // sinon.stub(accommodationRepository, 'findOne').resolves(mockAccommodation.slug);

      const req = {
        headers: {
          authorization: `Bearer ${providedAccessToken}`,
        },
        params: {
          id: 'test',
        },
      };
      const res = {
        status: sinon.stub().returnsThis(),
        json: sinon.stub().returnsThis(),
      };

      await accommodationService.getAccommodationById(req.params.id, req, res);

      expect(res.status, 200);
      expect(res.data, mockAccommodation);
    });
  });

  describe('PUT /v1/accommodations/:slug', () => {
    it('should update an existing accommodation', async () => {
      const mockUpdateAccommodation = {
        description: 'updated Accommodation TDD',
      };
      const mockAccommodation = {
        description: 'description',
        isActive: false,
        isPrivate: true,
        name: 'test',
        type: 'VILLA',
        location: createdDestination._id,
        detailedLocation: 'Near Eiffel Tower',
        geoLocation: {
          longitude: 2.2943506,
          latitude: 48.8588443,
          country: 'aaa',
          city: 'eeee',
          address: 'aaaa',
          label: 'aaaa',
        },
        guestsCount: 8,
        childrenCount: 6,
        bedroomsCount: 4,
        bathroomsCount: 4,
        surfaceArea: {
          value: 700,
          unit: '',
        },
        policies: ['No pets allowed', 'No smoking'],
        amenities: [createdAmenity._id],
        agency: '66472b56998506e08993abe2',

        prices: [
          {
            price: 500,
            currency: {
              label: 'aaaaa',
              code: 'EUR',
            },
            priceUnit: 'WEEK',
            priceType: 'NET_PRICE',
            from: '2024-02-04T00:00:00.000Z',
            to: '2024-02-06T00:00:00.000Z',
            isAvailable: true,
          },
        ],
        layouts: [
          {
            title: 'Ground Floor',
            order: 1,
            image: { url: 'test', blur: 'test', alt: 'test' },
            facilities: [createdFacility._id],
          },
          {
            title: 'First Floor',
            order: 2,
            image: { url: 'test', blur: 'test', alt: 'test' },
            facilities: [createdFacility._id],
          },
        ],
        nearbyLocations: ['Eiffel Tower', 'Louvre Museum'],
        categories: ['MOUNTAIN_VIEW', 'PET_FRIENDLY'],
        seasons: ['SUMMER'],
        services: [createdService._id],
        gallery: [
          { url: 'test', blur: 'test', alt: 'test' },
          { url: 'test1', blur: 'test1', alt: 'test1' },
        ],

        image: { url: 'test', blur: 'test', alt: 'test' },
      };

      // sinon.stub(accommodationRepository, 'findOne').resolves(mockAccommodation);
      // sinon.stub(accommodationRepository, 'findOneAndUpdate').resolves(mockUpdateAccommodation);
      const req = {
        headers: {
          authorization: `Bearer ${providedAccessToken}`,
        },
        userId: mockUser._id,
      };
      const res = {
        status: sinon.stub().returnsThis(),
        json: sinon.stub().returnsThis(),
      };
      await accommodationService.editAccommodation(mockAccommodation.slug, mockUpdateAccommodation, req, res);
      expect(res.status, 200);
      expect(res.data, mockUpdateAccommodation);
    });
    it('should approve the accommodation edit', async () => {
      // const existingAccommodation = {
      //   ...mockAccommodation,
      //   approvalRequests: {
      //     12345: {
      //       new: { name: 'Updated Accommodation' },
      //       old: { name: 'Old Accommodation' },
      //     },
      //   },
      // };

      // sinon.stub(accommodationRepository, 'findOne').resolves(existingAccommodation);
      // sinon.stub(accommodationRepository, 'findOneAndUpdate').resolves();

      const req = {
        headers: {
          authorization: `Bearer ${providedAccessToken}`,
        },
        userId: mockUser._id,
      };
      const res = {
        status: sinon.stub().returnsThis(),
        json: sinon.stub().returnsThis(),
      };

      await accommodationService.approveOrRejectEdit('test-accommodation', '12345', true, req, res);

      expect(res.status, 200);
    });

    it('should reject the accommodation edit', async () => {
      // const existingAccommodation = {
      //   ...mockAccommodation,
      //   approvalRequests: {
      //     12345: {
      //       new: { name: 'Updated Accommodation' },
      //       old: { name: 'Old Accommodation' },
      //     },
      //   },
      // };

      // sinon.stub(accommodationRepository, 'findOne').resolves(existingAccommodation);
      // sinon.stub(accommodationRepository, 'findOneAndUpdate').resolves();

      const req = {
        headers: {
          authorization: `Bearer ${providedAccessToken}`,
        },
        userId: mockUser._id,
      };
      const res = {
        status: sinon.stub().returnsThis(),
        json: sinon.stub().returnsThis(),
      };

      await accommodationService.approveOrRejectEdit('test-accommodation', '12345', false, req, res);

      expect(res.status, 200);
    });
    it('should return not found if accommodation does not exist', async () => {
      // sinon.stub(accommodationRepository, 'findOne').resolves(null);

      const req = {
        headers: {
          authorization: `Bearer ${providedAccessToken}`,
        },
        userId: mockUser._id,
      };
      const res = {
        status: sinon.stub().returnsThis(),
        json: sinon.stub().returnsThis(),
      };

      await accommodationService.approveOrRejectEdit('non-existing-accommodation', '12345', true, req, res);

      expect(res.status, 404);
    });

    it('should return error if approval request does not exist', async () => {
      // const existingAccommodation = {
      //   ...mockAccommodation,
      //   approvalRequests: {},
      // };

      // sinon.stub(accommodationRepository, 'findOne').resolves(existingAccommodation);

      const req = {
        headers: {
          authorization: `Bearer ${providedAccessToken}`,
        },
        userId: mockUser._id,
      };
      const res = {
        status: sinon.stub().returnsThis(),
        json: sinon.stub().returnsThis(),
      };

      await accommodationService.approveOrRejectEdit('test-accommodation', 'non-existing-request', true, req, res);

      expect(res.status, 400);
    });
  });
});
Editor is loading...
Leave a Comment