From 3749ce50a884a82cf536cc4ccf53c6e835dd8bfe Mon Sep 17 00:00:00 2001 From: aelassas Date: Mon, 19 Feb 2024 23:18:11 +0100 Subject: [PATCH] Add coverage --- .github/workflows/api.yml | 4 + api/coverage/cobertura-coverage.xml | 2404 +++++++++++++++++++++ api/jest.config.js | 2 + api/package.json | 2 +- api/src/controllers/locationController.ts | 4 +- api/tests/agency.test.ts | 65 +- api/tests/location.test.ts | 154 +- 7 files changed, 2620 insertions(+), 15 deletions(-) create mode 100644 api/coverage/cobertura-coverage.xml diff --git a/.github/workflows/api.yml b/.github/workflows/api.yml index 096caeb5..37d240df 100644 --- a/.github/workflows/api.yml +++ b/.github/workflows/api.yml @@ -34,3 +34,7 @@ jobs: - run: npm install - run: npm run lint - run: npm run build + - name: Upload coverage reports to Codecov + uses: codecov/codecov-action@v3 + env: + CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} diff --git a/api/coverage/cobertura-coverage.xml b/api/coverage/cobertura-coverage.xml new file mode 100644 index 00000000..b4cff3a6 --- /dev/null +++ b/api/coverage/cobertura-coverage.xml @@ -0,0 +1,2404 @@ + + + + + C:\dev\movinin\src\api + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/api/jest.config.js b/api/jest.config.js index 85cc2814..b3081946 100644 --- a/api/jest.config.js +++ b/api/jest.config.js @@ -7,6 +7,8 @@ const config = { roots: [ './tests/', ], + collectCoverage: true, + coverageReporters: ['cobertura'], } export default config diff --git a/api/package.json b/api/package.json index 24bca182..d9b08e1f 100644 --- a/api/package.json +++ b/api/package.json @@ -8,7 +8,7 @@ "dev": "nodemon", "build": "rimraf dist && tsc && babel dist -d dist", "start": "npm run build && node dist/src", - "test": "cross-env NODE_ENV=test NODE_OPTIONS=--experimental-vm-modules jest", + "test": "rimraf coverage && cross-env NODE_ENV=test NODE_OPTIONS=--experimental-vm-modules jest --coverage", "lint": "eslint --ext .ts .", "ncu": "ncu -u" }, diff --git a/api/src/controllers/locationController.ts b/api/src/controllers/locationController.ts index a086b4fe..76226380 100644 --- a/api/src/controllers/locationController.ts +++ b/api/src/controllers/locationController.ts @@ -62,7 +62,7 @@ export async function create(req: Request, res: Response) { const location = new Location({ values }) await location.save() - return res.sendStatus(200) + return res.json(location) } catch (err) { console.error(`[location.create] ${strings.DB_ERROR} ${req.body}`, err) return res.status(400).send(strings.DB_ERROR + err) @@ -102,7 +102,7 @@ export async function update(req: Request, res: Response) { await location.save() } } - return res.sendStatus(200) + return res.json(location) } console.error('[location.update] Location not found:', id) diff --git a/api/tests/agency.test.ts b/api/tests/agency.test.ts index c5b29db9..26b15d2e 100644 --- a/api/tests/agency.test.ts +++ b/api/tests/agency.test.ts @@ -1,11 +1,19 @@ import 'dotenv/config' import request from 'supertest' +import url from 'url' +import path from 'path' +import fs from 'node:fs/promises' import * as movininTypes from 'movinin-types' import * as DatabaseHelper from '../src/common/DatabaseHelper' import * as TestHelper from './TestHelper' import app from '../src/app' import * as env from '../src/config/env.config' +import * as Helper from '../src/common/Helper' import User from '../src/models/User' +import Property from '../src/models/Property' + +const __filename = url.fileURLToPath(import.meta.url) +const __dirname = path.dirname(__filename) let AGENCY1_ID: string let AGENCY2_ID: string @@ -149,20 +157,69 @@ describe('DELETE /api/delete-agency/:id', () => { const token = await TestHelper.signinAsAdmin() const agencyName = TestHelper.getAgencyName() - const _id = await TestHelper.createAgency(`${agencyName}@test.movinin.io`, agencyName) + const agencyId = await TestHelper.createAgency(`${agencyName}@test.movinin.io`, agencyName) - let agency = await User.findById(_id) + let agency = await User.findById(agencyId) expect(agency).not.toBeNull() + const avatarName = 'avatar1.jpg' + const avatarPath = path.resolve(__dirname, `./img/${avatarName}`) + + const avatar = path.join(env.CDN_USERS, avatarName) + if (!await Helper.exists(avatar)) { + fs.copyFile(avatarPath, avatar) + } + agency!.avatar = avatarName + await agency?.save() + + const locationId = await TestHelper.createLocation('Location 1 EN', 'Location 1 FR') + + const propertyImageName = 'main1.jpg' + const propertyImagePath = path.resolve(__dirname, `./img/${propertyImageName}`) + + const property = new Property({ + name: 'Beautiful House in Detroit', + agency: agencyId, + type: movininTypes.PropertyType.House, + description: '

Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium rem aperiam, veritatis et quasi.

', + image: propertyImageName, + images: [], + bedrooms: 3, + bathrooms: 2, + kitchens: 1, + parkingSpaces: 1, + size: 200, + petsAllowed: false, + furnished: true, + aircon: true, + minimumAge: 21, + location: locationId, + address: '', + price: 4000, + hidden: true, + cancellation: 0, + available: false, + rentalTerm: movininTypes.RentalTerm.Monthly, + }) + + const propertyImage = path.join(env.CDN_PROPERTIES, propertyImageName) + if (!await Helper.exists(propertyImage)) { + fs.copyFile(propertyImagePath, propertyImage) + } + + await property.save() + const res = await request(app) - .delete(`/api/delete-agency/${_id}`) + .delete(`/api/delete-agency/${agencyId}`) .set(env.X_ACCESS_TOKEN, token) expect(res.statusCode).toBe(200) - agency = await User.findById(_id) + agency = await User.findById(agencyId) expect(agency).toBeNull() + await TestHelper.deleteLocation(locationId) + await TestHelper.signout(token) }) }) diff --git a/api/tests/location.test.ts b/api/tests/location.test.ts index a53b3e9d..a3376296 100644 --- a/api/tests/location.test.ts +++ b/api/tests/location.test.ts @@ -1,6 +1,27 @@ import 'dotenv/config' +import request from 'supertest' +import { v1 as uuid } from 'uuid' +import * as movininTypes from 'movinin-types' +import app from '../src/app' import * as DatabaseHelper from '../src/common/DatabaseHelper' import * as TestHelper from './TestHelper' +import * as env from '../src/config/env.config' +import LocationValue from '../src/models/LocationValue' +import Location from '../src/models/Location' +import Property from '../src/models/Property' + +let LOCATION_ID: string + +let LOCATION_NAMES: movininTypes.LocationName[] = [ + { + language: 'en', + name: uuid(), + }, + { + language: 'fr', + name: uuid(), + }, +] // // Connecting and initializing the database before running the test suite @@ -27,7 +48,34 @@ describe('POST /api/validate-location', () => { it('should validate a location', async () => { const token = await TestHelper.signinAsAdmin() - // TODO + const language = TestHelper.LANGUAGE + const name = uuid() + + const locationValue = new LocationValue({ language, value: name }) + await locationValue.save() + + const payload: movininTypes.ValidateLocationPayload = { + language, + name, + } + + let res = await request(app) + .post('/api/validate-location') + .set(env.X_ACCESS_TOKEN, token) + .send(payload) + + expect(res.statusCode).toBe(204) + + payload.name = uuid() + + res = await request(app) + .post('/api/validate-location') + .set(env.X_ACCESS_TOKEN, token) + .send(payload) + + expect(res.statusCode).toBe(200) + + await LocationValue.deleteOne({ _id: locationValue._id }) await TestHelper.signout(token) }) @@ -37,17 +85,47 @@ describe('POST /api/create-location', () => { it('should create a location', async () => { const token = await TestHelper.signinAsAdmin() - // TODO + const payload: movininTypes.LocationName[] = LOCATION_NAMES + + const res = await request(app) + .post('/api/create-location') + .set(env.X_ACCESS_TOKEN, token) + .send(payload) + + expect(res.statusCode).toBe(200) + expect(res.body?.values?.length).toBe(2) + LOCATION_ID = res.body?._id await TestHelper.signout(token) }) }) -describe('POST /api/update-location/:id', () => { +describe('PUT /api/update-location/:id', () => { it('should update a location', async () => { const token = await TestHelper.signinAsAdmin() - // TODO + LOCATION_NAMES = [ + { + language: 'en', + name: uuid(), + }, + { + language: 'fr', + name: uuid(), + }, + { + language: 'es', + name: uuid(), + }, + ] + + const res = await request(app) + .put(`/api/update-location/${LOCATION_ID}`) + .set(env.X_ACCESS_TOKEN, token) + .send(LOCATION_NAMES) + + expect(res.statusCode).toBe(200) + expect(res.body.values?.length).toBe(3) await TestHelper.signout(token) }) @@ -55,17 +133,25 @@ describe('POST /api/update-location/:id', () => { describe('GET /api/location/:id/:language', () => { it('should get a location', async () => { + const language = 'en' - // TODO + const res = await request(app) + .get(`/api/location/${LOCATION_ID}/${language}`) + expect(res.statusCode).toBe(200) + expect(res.body?.name).toBe(LOCATION_NAMES.filter((v) => v.language === language)[0].name) }) }) describe('GET /api/locations/:page/:size/:language', () => { it('should get locations', async () => { + const language = 'en' - // TODO + const res = await request(app) + .get(`/api/locations/${TestHelper.PAGE}/${TestHelper.SIZE}/${language}?s=${LOCATION_NAMES[0].name}`) + expect(res.statusCode).toBe(200) + expect(res.body.length).toBe(1) }) }) @@ -73,7 +159,49 @@ describe('GET /api/check-location/:id', () => { it('should check a location', async () => { const token = await TestHelper.signinAsAdmin() - // TODO + const agencyName = TestHelper.getAgencyName() + const agencyId = await TestHelper.createAgency(`${agencyName}@test.movinin.io`, agencyName) + + const property = new Property({ + name: 'Beautiful House in Detroit', + agency: agencyId, + type: movininTypes.PropertyType.House, + description: '

Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium rem aperiam, veritatis et quasi.

', + image: 'main1.jpg', + images: [], + bedrooms: 3, + bathrooms: 2, + kitchens: 1, + parkingSpaces: 1, + size: 200, + petsAllowed: false, + furnished: true, + aircon: true, + minimumAge: 21, + location: LOCATION_ID, + address: '', + price: 4000, + hidden: true, + cancellation: 0, + available: false, + rentalTerm: movininTypes.RentalTerm.Monthly, + }) + await property.save() + + let res = await request(app) + .get(`/api/check-location/${LOCATION_ID}`) + .set(env.X_ACCESS_TOKEN, token) + + expect(res.statusCode).toBe(200) + + await Property.deleteOne({ _id: property._id }) + await TestHelper.deleteAgency(agencyId) + + res = await request(app) + .get(`/api/check-location/${LOCATION_ID}`) + .set(env.X_ACCESS_TOKEN, token) + + expect(res.statusCode).toBe(204) await TestHelper.signout(token) }) @@ -83,7 +211,17 @@ describe('DELETE /api/delete-location/:id', () => { it('should delete a location', async () => { const token = await TestHelper.signinAsAdmin() - // TODO + let location = await Location.findById(LOCATION_ID) + expect(location).not.toBeNull() + + const res = await request(app) + .delete(`/api/delete-location/${LOCATION_ID}`) + .set(env.X_ACCESS_TOKEN, token) + + expect(res.statusCode).toBe(200) + + location = await Location.findById(LOCATION_ID) + expect(location).toBeNull() await TestHelper.signout(token) })