diff --git a/.env b/.env index 85e5c7b..e45e305 100644 --- a/.env +++ b/.env @@ -1,7 +1,7 @@ # .env.example, commit to repo SECRET=segredo CLIENTS_URL=backend_clients - +USERS_URL=backend_users DB_USER=api_user DB_PASS=api_password DB_NAME=api_database diff --git a/.eslintrc.json b/.eslintrc.json index 88f996f..aa60fde 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -11,6 +11,7 @@ "ecmaVersion": 12 }, "rules": { - "no-underscore-dangle": "off" + "no-underscore-dangle": "off", + "consistent-return": "off" } } diff --git a/scripts/consts.js b/scripts/consts.js index 0e4238e..dce46d1 100644 --- a/scripts/consts.js +++ b/scripts/consts.js @@ -1,6 +1,7 @@ const REPO = '2020-2-SiGeD-Demands'; const OWNER = 'fga-eps-mds'; -const SONAR_URL = `https://sonarcloud.io/api/measures/search_history?component=${OWNER}_${REPO}&metrics=new_technical_debt,blocker_violations,bugs,classes,code_smells,cognitive_complexity,comment_lines,comment_lines_density,complexity_in_classes,complexity_in_functions,branch_coverage,new_branch_coverage,new_conditions_to_cover,confirmed_issues,coverage,new_coverage,complexity,development_cost,new_development_cost,duplicated_blocks,new_duplicated_blocks,duplicated_files,duplicated_lines,duplicated_lines_density,new_duplicated_lines_density,new_duplicated_lines,duplications_data,effort_to_reach_maintainability_rating_a,false_positive_issues,file_complexity_distribution,files,function_complexity_distribution,functions,generated_lines,generated_ncloc,info_violations,violations,line_coverage,new_line_coverage,ncloc,ncloc_language_distribution,lines_to_cover,new_lines_to_cover,sqale_rating,new_maintainability_rating,major_violations,minor_violations,new_blocker_violations,new_bugs,new_code_smells,new_critical_violations,new_info_violations,new_violations,new_lines,new_major_violations,new_minor_violations,new_security_hotspots,new_vulnerabilities,open_issues,quality_profiles,projects,public_api,public_documented_api_density,quality_gate_details,alert_status,reliability_rating,new_reliability_rating,reliability_remediation_effort,new_reliability_remediation_effort,reopened_issues,security_hotspots,security_hotspots_reviewed,new_security_hotspots_reviewed,security_rating,new_security_rating,security_remediation_effort,new_security_remediation_effort,security_review_rating,new_security_review_rating,security_hotspots_reviewed_status,new_security_hotspots_reviewed_status,security_hotspots_to_review_status,new_security_hotspots_to_review_status,skipped_tests,statements,sqale_index,sqale_debt_ratio,new_sqale_debt_ratio`; +const SONAR_ID= 'fga-eps-mds_2020-2-G4-Demands' +const SONAR_URL = `https://sonarcloud.io/api/measures/search_history?component=${SONAR_ID}&metrics=new_technical_debt,blocker_violations,bugs,classes,code_smells,cognitive_complexity,comment_lines,comment_lines_density,complexity_in_classes,complexity_in_functions,branch_coverage,new_branch_coverage,new_conditions_to_cover,confirmed_issues,coverage,new_coverage,complexity,development_cost,new_development_cost,duplicated_blocks,new_duplicated_blocks,duplicated_files,duplicated_lines,duplicated_lines_density,new_duplicated_lines_density,new_duplicated_lines,duplications_data,effort_to_reach_maintainability_rating_a,false_positive_issues,file_complexity_distribution,files,function_complexity_distribution,functions,generated_lines,generated_ncloc,info_violations,violations,line_coverage,new_line_coverage,ncloc,ncloc_language_distribution,lines_to_cover,new_lines_to_cover,sqale_rating,new_maintainability_rating,major_violations,minor_violations,new_blocker_violations,new_bugs,new_code_smells,new_critical_violations,new_info_violations,new_violations,new_lines,new_major_violations,new_minor_violations,new_security_hotspots,new_vulnerabilities,open_issues,quality_profiles,projects,public_api,public_documented_api_density,quality_gate_details,alert_status,reliability_rating,new_reliability_rating,reliability_remediation_effort,new_reliability_remediation_effort,reopened_issues,security_hotspots,security_hotspots_reviewed,new_security_hotspots_reviewed,security_rating,new_security_rating,security_remediation_effort,new_security_remediation_effort,security_review_rating,new_security_review_rating,security_hotspots_reviewed_status,new_security_hotspots_reviewed_status,security_hotspots_to_review_status,new_security_hotspots_to_review_status,skipped_tests,statements,sqale_index,sqale_debt_ratio,new_sqale_debt_ratio`; module.exports = { SONAR_URL, diff --git a/src/Controllers/DemandController.js b/src/Controllers/DemandController.js index 3cd5698..4d75be9 100644 --- a/src/Controllers/DemandController.js +++ b/src/Controllers/DemandController.js @@ -4,6 +4,8 @@ const Demand = require('../Models/DemandSchema'); const Category = require('../Models/CategorySchema'); const validation = require('../Utils/validate'); const { getClients } = require('../Services/Axios/clientService'); +const { getUser } = require('../Services/Axios/userService'); +const verifyChanges = require('../Utils/verifyChanges'); const demandGetWithClientsNames = async (req, res) => { try { @@ -150,34 +152,50 @@ const demandsSectorsStatistic = async (req, res) => { }; const demandCreate = async (req, res) => { - const { - name, description, process, categoryID, sectorID, clientID, userID, - } = req.body; + try { + const { + name, description, process, categoryID, sectorID, clientID, userID, + } = req.body; + + const validFields = validation.validateDemand( + name, description, categoryID, sectorID, clientID, userID, + ); + if (validFields.length) { + return res.status(400).json({ status: validFields }); + } + const token = req.headers['x-access-token']; - const validFields = validation.validateDemand( - name, description, categoryID, sectorID, clientID, userID, - ); - if (validFields.length) { - return res.status(400).json({ status: validFields }); - } + const user = await getUser(userID, token); - const newDemand = await Demand.create({ - name, - description, - process: process || '', - categoryID, - sectorHistory: { - sectorID, - createdAt: moment.utc(moment.tz('America/Sao_Paulo').format('YYYY-MM-DDTHH:mm:ss')).toDate(), - updatedAt: moment.utc(moment.tz('America/Sao_Paulo').format('YYYY-MM-DDTHH:mm:ss')).toDate(), - }, - clientID, - userID, - createdAt: moment.utc(moment.tz('America/Sao_Paulo').format('YYYY-MM-DDTHH:mm:ss')).toDate(), - updatedAt: moment.utc(moment.tz('America/Sao_Paulo').format('YYYY-MM-DDTHH:mm:ss')).toDate(), - }); + if (user.error) { + return res.status(400).json({ message: user.error }); + } + const date = moment.utc(moment.tz('America/Sao_Paulo').format('YYYY-MM-DDTHH:mm:ss')).toDate(); + const newDemand = await Demand.create({ + name, + description, + process: process || '', + categoryID, + sectorHistory: { + sectorID, + createdAt: date, + updatedAt: date, + }, + clientID, + userID, + demandHistory: { + userID, + date, + label: 'created', + }, + createdAt: date, + updatedAt: date, + }); - return res.json(newDemand); + return res.json(newDemand); + } catch (err) { + return res.status(400).json({ message: 'Failed to create demand' }); + } }; const demandUpdate = async (req, res) => { @@ -195,6 +213,15 @@ const demandUpdate = async (req, res) => { } try { + const token = req.headers['x-access-token']; + + const user = await getUser(userID, token); + + if (user.error) { + return res.status(400).json({ message: user.error }); + } + + const demandHistory = await verifyChanges(req.body, id); const updateStatus = await Demand.findOneAndUpdate({ _id: id }, { name, description, @@ -203,8 +230,9 @@ const demandUpdate = async (req, res) => { sectorID, clientID, userID, + demandHistory, updatedAt: moment.utc(moment.tz('America/Sao_Paulo').format('YYYY-MM-DDTHH:mm:ss')).toDate(), - }, { new: true }, (user) => user); + }, { new: true }, (err) => err); return res.json(updateStatus); } catch { return res.status(400).json({ err: 'invalid id' }); @@ -400,6 +428,42 @@ const deleteDemandUpdate = async (req, res) => { } }; +const history = async (req, res) => { + const { id } = req.params; + + try { + let error = ''; + const token = req.headers['x-access-token']; + const demandFound = await Demand.findOne({ _id: id }); + const userHistory = await Promise.all(demandFound.demandHistory.map(async (elem) => { + const user = await getUser(elem.userID, token); + + if (user.error) { + error = user.error; + return; + } + return { + label: elem.label, + before: elem.before, + after: elem.after, + date: elem.date, + user: { + _id: user._id, + name: user.name, + sector: user.sector, + role: user.role, + }, + }; + })); + if (error) { + return res.status(400).json({ message: error }); + } + return res.json(userHistory); + } catch { + return res.status(400).json({ message: 'Demand not found' }); + } +}; + module.exports = { demandGet, demandCreate, @@ -414,4 +478,5 @@ module.exports = { deleteDemandUpdate, demandsCategoriesStatistic, demandsSectorsStatistic, + history, }; diff --git a/src/Models/DemandSchema.js b/src/Models/DemandSchema.js index 1baa330..eaed4d7 100644 --- a/src/Models/DemandSchema.js +++ b/src/Models/DemandSchema.js @@ -36,6 +36,30 @@ const DemandSchema = new mongoose.Schema({ require: true, }, }], + demandHistory: [{ + userID: { + type: String, + require: true, + }, + date: { + type: Date, + require: true, + }, + label: { + type: String, + require: true, + }, + before: { + type: String, + require: true, + default: '', + }, + after: { + type: String, + require: true, + default: '', + }, + }], clientID: { type: String, require: true, diff --git a/src/Services/Axios/baseService.js b/src/Services/Axios/baseService.js index 6e081f6..e7ca41a 100644 --- a/src/Services/Axios/baseService.js +++ b/src/Services/Axios/baseService.js @@ -1,11 +1,16 @@ const axios = require('axios'); -const { CLIENTS_URL } = process.env; +const { CLIENTS_URL, USERS_URL } = process.env; const APIClients = axios.create({ baseURL: `http://${CLIENTS_URL}:3002/`, }); +const APIUsers = axios.create({ + baseURL: `http://${USERS_URL}:3001/`, +}); + module.exports = { APIClients, + APIUsers, }; diff --git a/src/Services/Axios/userService.js b/src/Services/Axios/userService.js new file mode 100644 index 0000000..2f7223c --- /dev/null +++ b/src/Services/Axios/userService.js @@ -0,0 +1,16 @@ +const { APIUsers } = require('./baseService'); + +const getUser = async (userID, token) => { + try { + const user = await APIUsers.get(`/users/${userID}`, { headers: { 'x-access-token': token } }) + .then((response) => response.data); + if (!user) { + return { error: 'User not found' }; + } + return user; + } catch { + return { error: 'Could not connect to user api' }; + } +}; + +module.exports = { getUser }; diff --git a/src/Utils/verifyChanges.js b/src/Utils/verifyChanges.js new file mode 100644 index 0000000..08c771e --- /dev/null +++ b/src/Utils/verifyChanges.js @@ -0,0 +1,56 @@ +const moment = require('moment-timezone'); +const Demand = require('../Models/DemandSchema'); + +const buildHistory = (body, demand, label) => { + const date = moment.utc(moment.tz('America/Sao_Paulo').format('YYYY-MM-DDTHH:mm:ss')).toDate(); + return { + label, + before: demand[label], + after: body[label], + userID: body.userID, + date, + }; +}; + +const biggerArray = (arr1, arr2) => { + if (arr1.length > arr2.length) { + return { bigger: arr1, smaller: arr2, body: true }; + } + return { bigger: arr2, smaller: arr1, body: false }; +}; + +const verifyChanges = async (body, id) => { + const date = moment.utc(moment.tz('America/Sao_Paulo').format('YYYY-MM-DDTHH:mm:ss')).toDate(); + const demand = await Demand.findOne({ _id: id }); + const newHistory = []; + + if (body.name !== demand.name) { + newHistory.push(buildHistory(body, demand, 'name')); + } + if (body.description !== demand.description) { + newHistory.push(buildHistory(body, demand, 'description')); + } + if (body.process !== demand.process) { + newHistory.push(buildHistory(body, demand, 'process')); + } + + const categoryArrays = biggerArray(body.categoryID, demand.categoryID); + categoryArrays.bigger.map((item, index) => { + const value0 = String(item ?? ''); + const value1 = String(categoryArrays.smaller[index] ?? ''); + if (value0 !== value1) { + newHistory.push({ + label: 'category', + before: categoryArrays.body ? value1 : value0, + after: categoryArrays.body ? value0 : value1, + userID: body.userID, + date, + }); + } + return item; + }); + + return [...demand.demandHistory, ...newHistory]; +}; + +module.exports = verifyChanges; diff --git a/src/routes.js b/src/routes.js index 9c58bc4..9425d3d 100644 --- a/src/routes.js +++ b/src/routes.js @@ -21,7 +21,7 @@ routes.get('/clientsNames', verifyJWT, DemandController.demandGetWithClientsName routes.put('/demand/create-demand-update/:id', verifyJWT, DemandController.createDemandUpdate); routes.put('/demand/update-demand-update/:id', verifyJWT, DemandController.updateDemandUpdate); routes.put('/demand/delete-demand-update/:id', verifyJWT, DemandController.deleteDemandUpdate); +routes.get('/demand/history/:id', verifyJWT, DemandController.history); routes.get('/statistic/category', verifyJWT, DemandController.demandsCategoriesStatistic); routes.get('/statistic/sector', verifyJWT, DemandController.demandsSectorsStatistic); - module.exports = routes; diff --git a/tests/__mocks__/apiResponses/clients.json b/tests/__mocks__/apiResponses/clients.json index 085d6e6..9979f5e 100644 --- a/tests/__mocks__/apiResponses/clients.json +++ b/tests/__mocks__/apiResponses/clients.json @@ -14,7 +14,7 @@ { "before": "", "after": "", - "_id": "6085e65a664ee00049cc7639", + "_id": "6089c3538dfebe00555bc17e", "userID": "608335084771520040cea104", "date": "2021-04-25T18:59:54.000Z", "label": "created" @@ -22,7 +22,7 @@ { "before": "Julia Batist", "after": "Julia Batista", - "_id": "6085e6ae664ee00049cc763b", + "_id": "6089c3538dfebe00555bc17e", "label": "name", "userID": "608335084771520040cea104", "date": "2021-04-25T19:01:18.000Z" diff --git a/tests/__mocks__/apiResponses/user.json b/tests/__mocks__/apiResponses/user.json new file mode 100644 index 0000000..7ed6023 --- /dev/null +++ b/tests/__mocks__/apiResponses/user.json @@ -0,0 +1,11 @@ +{ + "temporaryPassword": false, + "_id": "6089c3538dfebe00555bc17e", + "name": "Maria Joaquina", + "email": "mariajoaquina@email.com", + "role": "admin", + "sector": "606fa89e15281a0040cff1fd", + "createdAt": "2021-04-28T17:19:31.000Z", + "updatedAt": "2021-04-28T17:27:29.000Z", + "__v": 0 +} \ No newline at end of file diff --git a/tests/__mocks__/axios.js b/tests/__mocks__/axios.js index 5a97b13..d10cad7 100644 --- a/tests/__mocks__/axios.js +++ b/tests/__mocks__/axios.js @@ -1,11 +1,16 @@ const clients = require('./apiResponses/clients.json') +const user = require('./apiResponses/user.json') + const GET_CLIENTS = '/clients' +const GET_USER_BY_ID = '/users/6089c3538dfebe00555bc17e' const axios = { get: jest.fn((url) => { switch (url) { case GET_CLIENTS: - return Promise.resolve({ data: clients }); + return Promise.resolve({ data: clients }); + case GET_USER_BY_ID: + return Promise.resolve({ data: user }); default: return Promise.resolve({ data: { error: `Mock URL ${url} not found` }}); } diff --git a/tests/api.test.js b/tests/api.test.js index 2d054da..577dee3 100644 --- a/tests/api.test.js +++ b/tests/api.test.js @@ -7,6 +7,7 @@ const mongoose = require('mongoose'); describe('Sample Test', () => { // Saving categories ids to use when create demands constants let category_id; + let demand_id; // Categories test comes first. @@ -36,6 +37,21 @@ describe('Sample Test', () => { expiresIn: 240, }); + beforeAll(async () => { + // Create demand with client and user from mock + const demand = { + name: 'Nome da Demanda', + description: 'Descrição da Demanda', + process: '000000', + categoryID: ['6070b70835599b005b48b32d', '6070b71635599b005b48b32e'], + sectorID: '606281ba4772b00034eb13fe', + clientID: '6085e65a664ee00049cc7638', + userID: '6089c3538dfebe00555bc17e' + } + const res = await request(app).post('/demand/create').set('x-access-token', token).send(demand); + demand_id = res.body._id; + }) + // Test API: it('App is defined', (done) => { @@ -183,7 +199,7 @@ describe('Sample Test', () => { categoryID: ['6070b70835599b005b48b32d', '6070b71635599b005b48b32e'], sectorID: '6064ffa9942d5e008c0734dc', clientID: '6054dacb934bd000d7ca623b', - userID: '60578028cb9349004580fb8d' + userID: '6089c3538dfebe00555bc17e' }; const falseDemand = { name: 'Nome da Demanda', @@ -192,7 +208,7 @@ describe('Sample Test', () => { categoryID: ['6070b70835599b005b48b32d', '6070b71635599b005b48b32e'], sectorID: '6064ffa9942d5e008c0734dc', clientID: '6054dacb934bd000d7ca623b', - userID: '60578028cb9349004580fb8d', + userID: '6089c3538dfebe00555bc17e', }; const updatedSectorID = { sectorID: 'TESTE' @@ -336,7 +352,7 @@ describe('Sample Test', () => { categoryID: ['6064ffa9942d5e008c07e61a'], sectorID: 'sectorID', clientID: 'clientID', - userID: 'userID' + userID: '6089c3538dfebe00555bc17e' }; const res = await request(app).put(`/demand/update/${id}`).set('x-access-token', token).send(demandUpdate); expect(res.statusCode).toBe(200); @@ -382,7 +398,7 @@ describe('Sample Test', () => { categoryID: [categoryId3], sectorID: '6064ffa9942d5e008c0734dc', clientID: '6054dacb934bd000d7ca623b', - userID: '60578028cb9349004580fb8d' + userID: '6089c3538dfebe00555bc17e' } await request(app).post('/demand/create').set('x-access-token', token).send(statisticDemand); const res = await request(app).get(`/statistic/sector?id=${categoryId3}`).set('x-access-token', token); @@ -398,7 +414,7 @@ describe('Sample Test', () => { name: '', process: '4005', description: 'Retirar documento na DPSS', - userID: 'userID', + userID: '6089c3538dfebe00555bc17e', categoryID: 'categoryID', clientID: 'clientID', sectorID: 'sectorID' @@ -418,7 +434,7 @@ describe('Sample Test', () => { categoryID: 'categoryID', description: '', sectorID: 'sectorID', - userID: 'userID', + userID: '6089c3538dfebe00555bc17e', clientID: 'clientID', process: '4005' } @@ -436,7 +452,7 @@ describe('Sample Test', () => { categoryID: '', description: 'Retirar documento na DPSS', sectorID: 'sectorID', - userID: 'userID', + userID: '6089c3538dfebe00555bc17e', process: '4005', clientID: 'clientID', name: 'Retirada de documento' @@ -458,7 +474,7 @@ describe('Sample Test', () => { categoryID: 'categoryID', description: 'Retirar documento na DPSS', process: '4005', - userID: 'userID' + userID: '6089c3538dfebe00555bc17e' } const res = await request(app) @@ -477,7 +493,7 @@ describe('Sample Test', () => { process: '4005', description: 'Retirar documento na DPSS', clientID: '', - userID: 'userID', + userID: '6089c3538dfebe00555bc17e', } const res = await request(app) @@ -512,7 +528,7 @@ describe('Sample Test', () => { name: 'Retirada de arma', categoryID: 'IDcategory', sectorID: 'IDsector', - userID: 'IDuser', + userID: '6089c3538dfebe00555bc17e', description: 'Retirar token', clientID: 'IDclient', process: '504' @@ -528,7 +544,7 @@ describe('Sample Test', () => { it('Update demand without token', async () => { const demand = { - userID: 'IDuser', + userID: '6089c3538dfebe00555bc17e', sectorID: 'IDsector', categoryID: 'IDcategory', description: 'Retirar token', @@ -547,7 +563,7 @@ describe('Sample Test', () => { it('Update demand with invalid token', async () => { const tokenFalho = 'abc123'; const demand = { - userID: '839589v4c8984', + userID: '6089c3538dfebe00555bc17e', sectorID: 'jkncjh8e7c8nc4819c', categoryID: 'cewdu8eu8eceh882em21', description: 'Teste', @@ -571,7 +587,7 @@ describe('Sample Test', () => { expect(res.body.clientID).toBe('clientID'); expect(res.body.process).toBe('4005'); expect(res.body.sectorHistory[0].sectorID).toBe(updatedSectorID.sectorID); - expect(res.body.userID).toBe('userID'); + expect(res.body.userID).toBe('6089c3538dfebe00555bc17e'); expect(res.body.description).toBe('Retirar documento na DPSS'); done(); }); @@ -598,7 +614,7 @@ describe('Sample Test', () => { expect(res.body.process).toBe('4005'); expect(res.body.sectorHistory[0].sectorID).toBe(updatedSectorID.sectorID); expect(res.body.sectorHistory[1].sectorID).toBe(forwardSectorID.sectorID); - expect(res.body.userID).toBe('userID'); + expect(res.body.userID).toBe('6089c3538dfebe00555bc17e'); expect(res.body.description).toBe('Retirar documento na DPSS'); done(); }); @@ -636,7 +652,7 @@ describe('Sample Test', () => { expect(res.body.process).toBe('4005'); expect(res.body.sectorHistory[0].sectorID).toBe(updatedSectorID.sectorID); expect(res.body.sectorHistory[1].sectorID).toBe(forwardSectorID.sectorID); - expect(res.body.userID).toBe('userID'); + expect(res.body.userID).toBe('6089c3538dfebe00555bc17e'); expect(res.body.description).toBe('Retirar documento na DPSS'); expect(res.body.updateList[0].userName).toBe(demandUpdate.userName); expect(res.body.updateList[0].userSector).toBe(demandUpdate.userSector); @@ -760,23 +776,26 @@ describe('Sample Test', () => { done(); }); - it('Return demands with clients names', async () => { - // Create demand with client from mock - const demand = { - name: 'Nome da Demanda', - description: 'Descrição da Demanda', - process: '000000', - categoryID: ['6070b70835599b005b48b32d', '6070b71635599b005b48b32e'], - sectorID: '6064ffa9942d5e008c0734dc', - clientID: '6085e65a664ee00049cc7638', - userID: '60578028cb9349004580fb8d' - } - const demand_created = await request(app).post('/demand/create').set('x-access-token', token).send(demand); + it('Return demands with clients names', async (done) => { const res = await request(app).get('/clientsNames').set('x-access-token', token) - const lastIdx = res.body.length - 1; // Get last demand on list expect(res.body[lastIdx].clientName).toEqual("Julia Batista"); - }) + done(); + }); + + it('Get demand history', async (done) => { + const res = await request(app).get(`/demand/history/${demand_id}`).set('x-access-token', token) + expect(res.body[0].label).toEqual("created"); + expect(res.body[0].user.name).toEqual("Maria Joaquina"); + done(); + }); + + it('Get demand history error', async (done) => { + const res = await request(app).get(`/demand/history/123`).set('x-access-token', token); + expect(res.statusCode).toBe(400); + expect(res.body).toEqual({ "message": "Demand not found" }); + done(); + }); }); afterAll(async (done) => { diff --git a/tests/services.test.js b/tests/services.test.js index 3109a83..e166aac 100644 --- a/tests/services.test.js +++ b/tests/services.test.js @@ -1,13 +1,21 @@ const {getClients} = require('../src/Services/Axios/clientService'); -const {APIClients} = require('../src/Services/Axios/baseService'); +const {getUser} = require('../src/Services/Axios/userService'); const jwt = require('jsonwebtoken'); const clients = require('./__mocks__/apiResponses/clients.json') +const user = require('./__mocks__/apiResponses/user.json') -const { CLIENTS_URL } = process.env; +const { CLIENTS_URL, USERS_URL } = process.env; it('Should get clients', async () => { const token = ''; const res = await getClients(token); expect(res).toEqual(clients); }); + +it('Should get user', async () => { + const token = ''; + const id = '6089c3538dfebe00555bc17e' + const res = await getUser(id, token); + expect(res).toEqual(user); +});