Construção de API
Back-end Web
Rotas do Host API
Método | Caminho | Resposta |
---|---|---|
POST | /hosts | Cria um novo host |
GET | /hosts | Retorna todos os hosts |
GET | /hosts?id=1 | Retorna o host com id igual a 1 |
GET | /hosts/1 | Retorna o host com id igual a 1 |
PUT | /hosts/1 | Atualiza o host com id igual a 1 |
DELETE | /hosts/1 | Exclui o host com id igual a 1 |
HTTP Status Codes
- Respostas de informação (100-199)
- Respostas de sucesso (200-299)
- Redirecionamentos (300-399)
- Erros do cliente (400-499)
- Erros do servidor (500-599)
Exemplos de Códigos
Código | Nome | Significado |
---|---|---|
200 | Ok | Solicitação gerada com sucesso |
201 | Created | Solicitação gerada com sucesso e um novo recurso foi criado como resultado |
204 | No Content | Solicitação gerada com sucesso e não há conteúdo para ser enviado |
400 | Bad Request | Solicitação não compreendida por motivos de erro |
401 | Unauthorized | Solicitação foi bloqueada porque não possui credenciais de autenticação válidas |
404 | Not Found | O servidor não pode encontrar o recurso solicitado |
500 | Internal Server Error | O servidor encontrou uma situação com a qual não sabe lidar. |
API de Investimentos
Arquivos
back
├── package-lock.json
├── package.json
├── requests.http
└── src
├── data
│ └── hosts.js
├── index.js
├── routes.js
└── routes.test.js
Arquivos
back
├── package-lock.json
├── package.json
├── requests.http
└── src
├── data
│ └── hosts.js
├── index.js
├── routes.js
└── routes.test.js
/codes/expressjs/monitor-app-api/back/src/data/hosts.js
export const hosts = [
{
id: 'e4cfb6bb-4431-42a9-b660-d5701b2f49cd',
name: 'Google DNS',
address: '8.8.8.8',
},
{
id: 'a2bb615a-6153-41bf-8cbe-0bfb538ce511',
name: 'Google Search',
address: 'www.google.com',
},
];
/codes/expressjs/monitor-app-api/back/src/data/hosts.js
export const hosts = [
{
id: 'e4cfb6bb-4431-42a9-b660-d5701b2f49cd',
name: 'Google DNS',
address: '8.8.8.8',
},
{
id: 'a2bb615a-6153-41bf-8cbe-0bfb538ce511',
name: 'Google Search',
address: 'www.google.com',
},
];
/codes/expressjs/monitor-app-api/back/src/index.js
import 'express-async-errors';
import express from 'express';
import cors from 'cors';
import morgan from 'morgan';
import router from './routes.js';
const server = express();
server.use(morgan('tiny'));
server.use(
cors({
origin: '*',
methods: 'GET,HEAD,OPTIONS,PUT,PATCH,POST,DELETE',
allowedHeaders: ['Content-Type', 'Authorization'],
credentials: true,
preflightContinue: false,
})
);
server.use(express.json());
server.use(router);
server.listen(3000, () => {
console.log('Server is running on port 3000');
});
export default server;
/codes/expressjs/monitor-app-api/back/src/index.js
import 'express-async-errors';
import express from 'express';
import cors from 'cors';
import morgan from 'morgan';
import router from './routes.js';
const server = express();
server.use(morgan('tiny'));
server.use(
cors({
origin: '*',
methods: 'GET,HEAD,OPTIONS,PUT,PATCH,POST,DELETE',
allowedHeaders: ['Content-Type', 'Authorization'],
credentials: true,
preflightContinue: false,
})
);
server.use(express.json());
server.use(router);
server.listen(3000, () => {
console.log('Server is running on port 3000');
});
export default server;
/codes/expressjs/monitor-app-api/back/src/routes.js
import express from 'express';
import { v4 as uuidv4 } from 'uuid';
import { hosts } from './data/hosts.js';
class HttpError extends Error {
constructor(message, code = 400) {
super(message);
this.code = code;
}
}
const router = express.Router();
router.post('/hosts', (req, res) => {
const { name, address } = req.body;
if (!name || !address) {
throw new HttpError('Error when passing parameters');
}
const id = uuidv4();
const newHost = { id, name, address };
hosts.push(newHost);
res.status(201).json(newHost);
});
router.get('/hosts', (req, res) => {
const where = req.query;
if (where) {
const field = Object.keys(where)[0];
const value = where[field];
const filteredHosts = hosts.filter((host) =>
host[field] instanceof String
? host[field].toLowerCase().includes(value.toLowerCase())
: host[field] === value
);
return res.json(filteredHosts);
}
return res.json(hosts);
});
router.get('/hosts/:id', (req, res) => {
const { id } = req.params;
const index = hosts.findIndex((host) => host.id === id);
if (!hosts[index]) {
throw new HttpError('Unable to read a host');
}
return res.json(hosts[index]);
});
router.put('/hosts/:id', (req, res) => {
const { name, address } = req.body;
const { id } = req.params;
if (!name || !address) {
throw new HttpError('Error when passing parameters');
}
const newHost = { id, name, address };
const index = hosts.findIndex((host) => host.id === id);
if (!hosts[index]) {
throw new HttpError('Unable to update a host');
}
hosts[index] = newHost;
return res.json(newHost);
});
router.delete('/hosts/:id', (req, res) => {
const { id } = req.params;
const index = hosts.findIndex((host) => host.id === id);
if (!hosts[index]) {
throw new HttpError('Unable to delete a host');
}
hosts.splice(index, 1);
return res.send(204);
});
// 404 handler
router.use((req, res, next) => {
return res.status(404).json({ message: 'Content not found!' });
});
// Error handler
router.use((err, req, res, next) => {
// console.error(err.message);
console.error(err.stack);
if (err instanceof HttpError) {
return res.status(err.code).json({ message: err.message });
}
// next(err);
return res.status(500).json({ message: 'Something broke!' });
});
export default router;
/codes/expressjs/monitor-app-api/back/src/routes.js
import express from 'express';
import { v4 as uuidv4 } from 'uuid';
import { hosts } from './data/hosts.js';
class HttpError extends Error {
constructor(message, code = 400) {
super(message);
this.code = code;
}
}
const router = express.Router();
router.post('/hosts', (req, res) => {
const { name, address } = req.body;
if (!name || !address) {
throw new HttpError('Error when passing parameters');
}
const id = uuidv4();
const newHost = { id, name, address };
hosts.push(newHost);
res.status(201).json(newHost);
});
router.get('/hosts', (req, res) => {
const where = req.query;
if (where) {
const field = Object.keys(where)[0];
const value = where[field];
const filteredHosts = hosts.filter((host) =>
host[field] instanceof String
? host[field].toLowerCase().includes(value.toLowerCase())
: host[field] === value
);
return res.json(filteredHosts);
}
return res.json(hosts);
});
router.get('/hosts/:id', (req, res) => {
const { id } = req.params;
const index = hosts.findIndex((host) => host.id === id);
if (!hosts[index]) {
throw new HttpError('Unable to read a host');
}
return res.json(hosts[index]);
});
router.put('/hosts/:id', (req, res) => {
const { name, address } = req.body;
const { id } = req.params;
if (!name || !address) {
throw new HttpError('Error when passing parameters');
}
const newHost = { id, name, address };
const index = hosts.findIndex((host) => host.id === id);
if (!hosts[index]) {
throw new HttpError('Unable to update a host');
}
hosts[index] = newHost;
return res.json(newHost);
});
router.delete('/hosts/:id', (req, res) => {
const { id } = req.params;
const index = hosts.findIndex((host) => host.id === id);
if (!hosts[index]) {
throw new HttpError('Unable to delete a host');
}
hosts.splice(index, 1);
return res.send(204);
});
// 404 handler
router.use((req, res, next) => {
return res.status(404).json({ message: 'Content not found!' });
});
// Error handler
router.use((err, req, res, next) => {
// console.error(err.message);
console.error(err.stack);
if (err instanceof HttpError) {
return res.status(err.code).json({ message: err.message });
}
// next(err);
return res.status(500).json({ message: 'Something broke!' });
});
export default router;
/codes/expressjs/monitor-app-api/back/requests.http
@server=http://localhost:3000
@createdHostId = {{createHost.response.body.$.id}}
### Create a host
# @name createHost
POST {{server}}/hosts
Content-Type: application/json
{
"name": "DNS Server",
"address": "1.1.1.1"
}
### Create a host without name or address
POST {{server}}/hosts
Content-Type: application/json
{
"name": "DNS Server"
}
### Read hosts
GET {{server}}/hosts
### Read a host by name
GET {{server}}/hosts?name=Google%20DNS
# GET {{server}}/hosts?name=DNS
# GET {{server}}/hosts?name=dns
### Read a host by id
GET {{server}}/hosts/{{createdHostId}}
### Read a host by id with invalid id
GET {{server}}/hosts/x
### Update a host
PUT {{server}}/hosts/{{createdHostId}}
Content-Type: application/json
{
"name": "Cloudflare DNS",
"address": "1.1.1.1"
}
### Update a host without name or address
PUT {{server}}/hosts/{{createdHostId}}
Content-Type: application/json
{
"name": "Cloudflare DNS"
}
### Update a host with invalid id
PUT {{server}}/hosts/x
Content-Type: application/json
{
"name": "Cloudflare DNS",
"address": "1.1.1.1"
}
### Delete a host
DELETE {{server}}/hosts/{{createdHostId}}
### Delete a host with invalid id
DELETE {{server}}/hosts/x
/codes/expressjs/monitor-app-api/back/requests.http
@server=http://localhost:3000
@createdHostId = {{createHost.response.body.$.id}}
### Create a host
# @name createHost
POST {{server}}/hosts
Content-Type: application/json
{
"name": "DNS Server",
"address": "1.1.1.1"
}
### Create a host without name or address
POST {{server}}/hosts
Content-Type: application/json
{
"name": "DNS Server"
}
### Read hosts
GET {{server}}/hosts
### Read a host by name
GET {{server}}/hosts?name=Google%20DNS
# GET {{server}}/hosts?name=DNS
# GET {{server}}/hosts?name=dns
### Read a host by id
GET {{server}}/hosts/{{createdHostId}}
### Read a host by id with invalid id
GET {{server}}/hosts/x
### Update a host
PUT {{server}}/hosts/{{createdHostId}}
Content-Type: application/json
{
"name": "Cloudflare DNS",
"address": "1.1.1.1"
}
### Update a host without name or address
PUT {{server}}/hosts/{{createdHostId}}
Content-Type: application/json
{
"name": "Cloudflare DNS"
}
### Update a host with invalid id
PUT {{server}}/hosts/x
Content-Type: application/json
{
"name": "Cloudflare DNS",
"address": "1.1.1.1"
}
### Delete a host
DELETE {{server}}/hosts/{{createdHostId}}
### Delete a host with invalid id
DELETE {{server}}/hosts/x
/codes/expressjs/monitor-app-api/back/package.json
{
"name": "invest-app",
"type": "module",
"scripts": {
"start": "node src/index.js",
"dev": "node --watch src/index.js",
"test": "node --experimental-vm-modules ./node_modules/.bin/jest src",
"test:coverage": "node --experimental-vm-modules ./node_modules/.bin/jest src --coverage"
},
"jest": {
"collectCoverage": true,
"testTimeout": 20000,
"coverageReporters": [
"json",
"html"
]
},
"dependencies": {
"cors": "^2.8.5",
"express": "^4.18.2",
"express-async-errors": "^3.1.1",
"morgan": "^1.10.0",
"uuid": "^9.0.0"
},
"devDependencies": {
"jest": "^29.7.0",
"supertest": "^6.3.4"
}
}
/codes/expressjs/monitor-app-api/back/package.json
{
"name": "invest-app",
"type": "module",
"scripts": {
"start": "node src/index.js",
"dev": "node --watch src/index.js",
"test": "node --experimental-vm-modules ./node_modules/.bin/jest src",
"test:coverage": "node --experimental-vm-modules ./node_modules/.bin/jest src --coverage"
},
"jest": {
"collectCoverage": true,
"testTimeout": 20000,
"coverageReporters": [
"json",
"html"
]
},
"dependencies": {
"cors": "^2.8.5",
"express": "^4.18.2",
"express-async-errors": "^3.1.1",
"morgan": "^1.10.0",
"uuid": "^9.0.0"
},
"devDependencies": {
"jest": "^29.7.0",
"supertest": "^6.3.4"
}
}
Create
/codes/expressjs/invest-app-api/src/routes.js
router.post('/hosts', (req, res) => {
const { name, address } = req.body;
if (!name || !address) {
throw new HttpError('Error when passing parameters');
}
const id = uuidv4();
const newHost = { id, name, address };
hosts.push(newHost);
res.status(201).json(newHost);
});
/codes/expressjs/invest-app-api/src/routes.js
router.post('/hosts', (req, res) => {
const { name, address } = req.body;
if (!name || !address) {
throw new HttpError('Error when passing parameters');
}
const id = uuidv4();
const newHost = { id, name, address };
hosts.push(newHost);
res.status(201).json(newHost);
});
/codes/expressjs/invest-app-api/back/requests.http
@server=http://localhost:3000
@createdHostId = {{createHost.response.body.$.id}}
### Create a host
# @name createHost
POST {{server}}/hosts
Content-Type: application/json
{
"name": "DNS Server",
"address": "1.1.1.1"
}
### Create a host (bad params)
# @name createHost
POST {{server}}/hosts
Content-Type: application/json
{
"name": "DNS Server"
}
/codes/expressjs/invest-app-api/back/requests.http
@server=http://localhost:3000
@createdHostId = {{createHost.response.body.$.id}}
### Create a host
# @name createHost
POST {{server}}/hosts
Content-Type: application/json
{
"name": "DNS Server",
"address": "1.1.1.1"
}
### Create a host (bad params)
# @name createHost
POST {{server}}/hosts
Content-Type: application/json
{
"name": "DNS Server"
}
Read
/codes/expressjs/invest-app-api/src/routes.js
router.get('/hosts', (req, res) => {
const where = req.query;
if (where) {
const field = Object.keys(where)[0];
const value = where[field];
const filteredHosts = hosts.filter((host) =>
host[field] instanceof String
? host[field].toLowerCase().includes(value.toLowerCase())
: host[field] === value
);
return res.json(filteredHosts);
}
return res.json(hosts);
});
router.get('/hosts/:id', (req, res) => {
const { id } = req.params;
const index = hosts.findIndex((host) => host.id === id);
if (!hosts[index]) {
throw new HttpError('Unable to read a host');
}
return res.json(hosts[index]);
});
/codes/expressjs/invest-app-api/src/routes.js
router.get('/hosts', (req, res) => {
const where = req.query;
if (where) {
const field = Object.keys(where)[0];
const value = where[field];
const filteredHosts = hosts.filter((host) =>
host[field] instanceof String
? host[field].toLowerCase().includes(value.toLowerCase())
: host[field] === value
);
return res.json(filteredHosts);
}
return res.json(hosts);
});
router.get('/hosts/:id', (req, res) => {
const { id } = req.params;
const index = hosts.findIndex((host) => host.id === id);
if (!hosts[index]) {
throw new HttpError('Unable to read a host');
}
return res.json(hosts[index]);
});
/codes/expressjs/invest-app-api/back/requests.http
@server=http://localhost:3000
### Read hosts
GET {{server}}/hosts
### Read a host by name
GET {{server}}/hosts?name=Google%20DNS
### Read a host by id
GET {{server}}/hosts/{{createdHostId}}
### Read a host by id (bad params)
GET {{server}}/hosts/x
/codes/expressjs/invest-app-api/back/requests.http
@server=http://localhost:3000
### Read hosts
GET {{server}}/hosts
### Read a host by name
GET {{server}}/hosts?name=Google%20DNS
### Read a host by id
GET {{server}}/hosts/{{createdHostId}}
### Read a host by id (bad params)
GET {{server}}/hosts/x
Update
/codes/expressjs/invest-app-api/src/routes.js
router.put('/hosts/:id', (req, res) => {
const { name, address } = req.body;
const { id } = req.params;
if (!name || !address) {
throw new HttpError('Error when passing parameters');
}
const newHost = { id, name, address };
const index = hosts.findIndex((host) => host.id === id);
if (!hosts[index]) {
throw new HttpError('Unable to update a host');
}
hosts[index] = newHost;
return res.json(newHost);
});
/codes/expressjs/invest-app-api/src/routes.js
router.put('/hosts/:id', (req, res) => {
const { name, address } = req.body;
const { id } = req.params;
if (!name || !address) {
throw new HttpError('Error when passing parameters');
}
const newHost = { id, name, address };
const index = hosts.findIndex((host) => host.id === id);
if (!hosts[index]) {
throw new HttpError('Unable to update a host');
}
hosts[index] = newHost;
return res.json(newHost);
});
@createdHostId = {{createHost.response.body.$.id}}
### Update a host
PUT {{server}}/hosts/{{createdHostId}}
Content-Type: application/json
{
"name": "Cloudflare DNS",
"address": "1.1.1.1"
}
### Update a host (bad params)
PUT {{server}}/hosts/{{createdHostId}}
Content-Type: application/json
{
"name": "Cloudflare DNS"
}
### Update a host (bad params)
PUT {{server}}/hosts/x
Content-Type: application/json
{
"name": "Cloudflare DNS",
"address": "1.1.1.1"
}
@createdHostId = {{createHost.response.body.$.id}}
### Update a host
PUT {{server}}/hosts/{{createdHostId}}
Content-Type: application/json
{
"name": "Cloudflare DNS",
"address": "1.1.1.1"
}
### Update a host (bad params)
PUT {{server}}/hosts/{{createdHostId}}
Content-Type: application/json
{
"name": "Cloudflare DNS"
}
### Update a host (bad params)
PUT {{server}}/hosts/x
Content-Type: application/json
{
"name": "Cloudflare DNS",
"address": "1.1.1.1"
}
Delete
/codes/expressjs/invest-app-api/src/routes.js
router.delete('/hosts/:id', (req, res) => {
const { id } = req.params;
const index = hosts.findIndex((host) => host.id === id);
if (!hosts[index]) {
throw new HttpError('Unable to delete a host');
}
hosts.splice(index, 1);
return res.send(204);
});
/codes/expressjs/invest-app-api/src/routes.js
router.delete('/hosts/:id', (req, res) => {
const { id } = req.params;
const index = hosts.findIndex((host) => host.id === id);
if (!hosts[index]) {
throw new HttpError('Unable to delete a host');
}
hosts.splice(index, 1);
return res.send(204);
});
/codes/expressjs/invest-app-api/back/requests.http
@server=http://localhost:3000
@createdHostId = {{createHost.response.body.$.id}}
### Delete a host
DELETE {{server}}/hosts/{{createdHostId}}
### Delete a host (bad params)
DELETE {{server}}/hosts/x
/codes/expressjs/invest-app-api/back/requests.http
@server=http://localhost:3000
@createdHostId = {{createHost.response.body.$.id}}
### Delete a host
DELETE {{server}}/hosts/{{createdHostId}}
### Delete a host (bad params)
DELETE {{server}}/hosts/x
Teste
$ npm i jest supertest -D
$ npm run test
$ npm i jest supertest -D
$ npm run test
/codes/expressjs/monitor-app-api/back/src/routes.test.js
import request from 'supertest';
import app from './index.js';
let createdHost;
const newHost = {
name: 'DNS Server',
address: '1.1.1.1',
};
const updatedHost = {
name: 'Cloudflare DNS',
address: '1.1.1.1',
};
describe('Moniotr App', () => {
describe('Hosts Endpoints', () => {
describe('POST /hosts', () => {
it('should create a new host', async () => {
const response = await request(app).post('/hosts').send(newHost);
createdHost = response.body;
expect(response.statusCode).toBe(201);
});
it('should not create a new host without name or address', async () => {
const response = await request(app).post('/hosts').send({
name: 'DNS Server',
});
expect(response.statusCode).toBe(400);
});
});
describe('GET /hosts', () => {
it('should show all hosts', async () => {
const response = await request(app).get('/hosts');
expect(response.statusCode).toBe(200);
});
it('should list the valid host', async () => {
const response = await request(app).get('/hosts');
const hasValidHost = response.body.some(
(host) => host.address === createdHost.address
);
expect(hasValidHost).toBeTruthy();
});
it('should show all hosts by name', async () => {
const response = await request(app).get('/hosts?name=DNS');
expect(response.statusCode).toBe(200);
});
});
describe('GET /hosts/:hostId', () => {
it('should show a host by id', async () => {
const response = await request(app).get(`/hosts/${createdHost.id}`);
expect(response.statusCode).toBe(200);
expect(response.body.name).toBe(createdHost.name);
});
it('should not show a host with invalid id', async () => {
const response = await request(app).get(`/hosts/x`);
expect(response.statusCode).toBe(400);
expect(response.body.message).toBe('Unable to read a host');
});
});
describe('PUT /hosts/:hostId', () => {
it('should update a host', async () => {
const response = await request(app)
.put(`/hosts/${createdHost.id}`)
.send(updatedHost);
expect(response.statusCode).toBe(200);
});
it('should list an updated host', async () => {
const response = await request(app).get('/hosts');
const hasValidHost = response.body.some(
(host) => host.address === updatedHost.address
);
expect(hasValidHost).toBeTruthy();
});
it('should not update a host without name or address', async () => {
const response = await request(app)
.put(`/hosts/${createdHost.id}`)
.send({
name: 'Cloudflare DNS',
});
expect(response.statusCode).toBe(400);
});
it('should not update a host with invalid id', async () => {
const response = await request(app).put(`/hosts/x`).send(updatedHost);
expect(response.statusCode).toBe(400);
expect(response.body.message).toBe('Unable to update a host');
});
});
describe('DELETE /hosts/:hostId', () => {
it('should remove a host', async () => {
const response = await request(app).delete(`/hosts/${createdHost.id}`);
expect(response.statusCode).toBe(204);
});
it('should not delete a host with invalid id', async () => {
const response = await request(app).delete(`/hosts/x`);
expect(response.statusCode).toBe(400);
expect(response.body.message).toBe('Unable to delete a host');
});
});
});
});
/codes/expressjs/monitor-app-api/back/src/routes.test.js
import request from 'supertest';
import app from './index.js';
let createdHost;
const newHost = {
name: 'DNS Server',
address: '1.1.1.1',
};
const updatedHost = {
name: 'Cloudflare DNS',
address: '1.1.1.1',
};
describe('Moniotr App', () => {
describe('Hosts Endpoints', () => {
describe('POST /hosts', () => {
it('should create a new host', async () => {
const response = await request(app).post('/hosts').send(newHost);
createdHost = response.body;
expect(response.statusCode).toBe(201);
});
it('should not create a new host without name or address', async () => {
const response = await request(app).post('/hosts').send({
name: 'DNS Server',
});
expect(response.statusCode).toBe(400);
});
});
describe('GET /hosts', () => {
it('should show all hosts', async () => {
const response = await request(app).get('/hosts');
expect(response.statusCode).toBe(200);
});
it('should list the valid host', async () => {
const response = await request(app).get('/hosts');
const hasValidHost = response.body.some(
(host) => host.address === createdHost.address
);
expect(hasValidHost).toBeTruthy();
});
it('should show all hosts by name', async () => {
const response = await request(app).get('/hosts?name=DNS');
expect(response.statusCode).toBe(200);
});
});
describe('GET /hosts/:hostId', () => {
it('should show a host by id', async () => {
const response = await request(app).get(`/hosts/${createdHost.id}`);
expect(response.statusCode).toBe(200);
expect(response.body.name).toBe(createdHost.name);
});
it('should not show a host with invalid id', async () => {
const response = await request(app).get(`/hosts/x`);
expect(response.statusCode).toBe(400);
expect(response.body.message).toBe('Unable to read a host');
});
});
describe('PUT /hosts/:hostId', () => {
it('should update a host', async () => {
const response = await request(app)
.put(`/hosts/${createdHost.id}`)
.send(updatedHost);
expect(response.statusCode).toBe(200);
});
it('should list an updated host', async () => {
const response = await request(app).get('/hosts');
const hasValidHost = response.body.some(
(host) => host.address === updatedHost.address
);
expect(hasValidHost).toBeTruthy();
});
it('should not update a host without name or address', async () => {
const response = await request(app)
.put(`/hosts/${createdHost.id}`)
.send({
name: 'Cloudflare DNS',
});
expect(response.statusCode).toBe(400);
});
it('should not update a host with invalid id', async () => {
const response = await request(app).put(`/hosts/x`).send(updatedHost);
expect(response.statusCode).toBe(400);
expect(response.body.message).toBe('Unable to update a host');
});
});
describe('DELETE /hosts/:hostId', () => {
it('should remove a host', async () => {
const response = await request(app).delete(`/hosts/${createdHost.id}`);
expect(response.statusCode).toBe(204);
});
it('should not delete a host with invalid id', async () => {
const response = await request(app).delete(`/hosts/x`);
expect(response.statusCode).toBe(400);
expect(response.body.message).toBe('Unable to delete a host');
});
});
});
});
.skip()
describe.skip()
it.skip()
describe.skip()
it.skip()
Cobertura de Testes
/codes/expressjs/monitor-app-api/back/package.json
{
"name": "invest-app",
"type": "module",
"scripts": {
"start": "node src/index.js",
"dev": "node --watch src/index.js",
"test": "node --experimental-vm-modules ./node_modules/.bin/jest src",
"test:coverage": "node --experimental-vm-modules ./node_modules/.bin/jest src --coverage"
},
"jest": {
"collectCoverage": true,
"testTimeout": 20000,
"coverageReporters": [
"json",
"html"
]
},
"dependencies": {
"cors": "^2.8.5",
"express": "^4.18.2",
"express-async-errors": "^3.1.1",
"morgan": "^1.10.0",
"uuid": "^9.0.0"
},
"devDependencies": {
"jest": "^29.7.0",
"supertest": "^6.3.4"
}
}
/codes/expressjs/monitor-app-api/back/package.json
{
"name": "invest-app",
"type": "module",
"scripts": {
"start": "node src/index.js",
"dev": "node --watch src/index.js",
"test": "node --experimental-vm-modules ./node_modules/.bin/jest src",
"test:coverage": "node --experimental-vm-modules ./node_modules/.bin/jest src --coverage"
},
"jest": {
"collectCoverage": true,
"testTimeout": 20000,
"coverageReporters": [
"json",
"html"
]
},
"dependencies": {
"cors": "^2.8.5",
"express": "^4.18.2",
"express-async-errors": "^3.1.1",
"morgan": "^1.10.0",
"uuid": "^9.0.0"
},
"devDependencies": {
"jest": "^29.7.0",
"supertest": "^6.3.4"
}
}
$ npm run test:coverage
$ npm run test:coverage
Front-end Web
Arquivos
front
├── css
│ └── style.css
├── index.html
├── js
│ ├── components
│ │ ├── HostForm.js
│ │ ├── HostTableRow.js
│ │ └── Modal.js
│ ├── lib
│ │ ├── dom.js
│ │ └── hosts.js
│ ├── main.js
│ └── services
│ └── storage.js
├── package-lock.json
├── package.json
├── public
│ └── vite.svg
└── vite.config.js
Arquivos
front
├── css
│ └── style.css
├── index.html
├── js
│ ├── components
│ │ ├── HostForm.js
│ │ ├── HostTableRow.js
│ │ └── Modal.js
│ ├── lib
│ │ ├── dom.js
│ │ └── hosts.js
│ ├── main.js
│ └── services
│ └── storage.js
├── package-lock.json
├── package.json
├── public
│ └── vite.svg
└── vite.config.js
/codes/expressjs/monitor-app-api/front/vite.config.js
import { defineConfig } from 'vite';
// https://vitejs.dev/config/
export default defineConfig({
server: {
open: 'index.html',
proxy: {
'/api': {
target: 'http://localhost:3000',
changeOrigin: true,
rewrite: (path) => path.replace(/^\/api/, ''),
},
},
},
});
/codes/expressjs/monitor-app-api/front/vite.config.js
import { defineConfig } from 'vite';
// https://vitejs.dev/config/
export default defineConfig({
server: {
open: 'index.html',
proxy: {
'/api': {
target: 'http://localhost:3000',
changeOrigin: true,
rewrite: (path) => path.replace(/^\/api/, ''),
},
},
},
});
/codes/expressjs/monitor-app-api/front/index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Monitor App</title>
<script src="https://code.iconify.design/3/3.1.0/iconify.min.js"></script>
</head>
<body>
<nav class="navbar navbar-expand-lg bg-body-tertiary">
<div class="container">
<a class="navbar-brand" href="#">Monitor App</a>
<button
class="navbar-toggler"
type="button"
data-bs-toggle="collapse"
data-bs-target="#navbarSupportedContent"
aria-controls="navbarSupportedContent"
aria-expanded="false"
aria-label="Toggle navigation"
>
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarSupportedContent">
<ul class="navbar-nav me-auto mb-2 mb-lg-0">
<li class="nav-item">
<a class="nav-link active" aria-current="page" href="#">Home</a>
</li>
</ul>
</div>
</div>
</nav>
<div class="container">
<h1 class="text-center m-0 p-5">Monitor App</h1>
<div class="card table-hosts">
<div class="card-header">
<h5 class="text-center">
Hosts
<div
class="float-end create-host-event lh-base"
data-bs-toggle="offcanvas"
data-bs-target="#offcanvasRight"
aria-controls="offcanvasRight"
>
<iconify-icon icon="bx:plus"></iconify-icon>
</div>
</h5>
</div>
<div class="card-body">
<table class="table table-hosts">
<thead>
<tr>
<th>Nome</th>
<th>Endereço</th>
<th></th>
</tr>
</thead>
<tbody></tbody>
</table>
</div>
</div>
</div>
<script type="module" src="/js/main.js"></script>
</body>
</html>
/codes/expressjs/monitor-app-api/front/index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Monitor App</title>
<script src="https://code.iconify.design/3/3.1.0/iconify.min.js"></script>
</head>
<body>
<nav class="navbar navbar-expand-lg bg-body-tertiary">
<div class="container">
<a class="navbar-brand" href="#">Monitor App</a>
<button
class="navbar-toggler"
type="button"
data-bs-toggle="collapse"
data-bs-target="#navbarSupportedContent"
aria-controls="navbarSupportedContent"
aria-expanded="false"
aria-label="Toggle navigation"
>
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarSupportedContent">
<ul class="navbar-nav me-auto mb-2 mb-lg-0">
<li class="nav-item">
<a class="nav-link active" aria-current="page" href="#">Home</a>
</li>
</ul>
</div>
</div>
</nav>
<div class="container">
<h1 class="text-center m-0 p-5">Monitor App</h1>
<div class="card table-hosts">
<div class="card-header">
<h5 class="text-center">
Hosts
<div
class="float-end create-host-event lh-base"
data-bs-toggle="offcanvas"
data-bs-target="#offcanvasRight"
aria-controls="offcanvasRight"
>
<iconify-icon icon="bx:plus"></iconify-icon>
</div>
</h5>
</div>
<div class="card-body">
<table class="table table-hosts">
<thead>
<tr>
<th>Nome</th>
<th>Endereço</th>
<th></th>
</tr>
</thead>
<tbody></tbody>
</table>
</div>
</div>
</div>
<script type="module" src="/js/main.js"></script>
</body>
</html>
/codes/expressjs/monitor-app-api/front/css/style.css
iconify-icon:hover {
cursor: pointer;
}
/codes/expressjs/monitor-app-api/front/css/style.css
iconify-icon:hover {
cursor: pointer;
}
/codes/expressjs/monitor-app-api/front/js/main.js
import 'bootstrap';
import 'iconify-icon';
import HostForm from './components/HostForm';
import Modal from './components/Modal';
import Hosts from './lib/hosts';
import 'bootstrap/dist/css/bootstrap.css';
import '../css/style.css';
Hosts.load();
HostForm.create();
Modal.create();
/codes/expressjs/monitor-app-api/front/js/main.js
import 'bootstrap';
import 'iconify-icon';
import HostForm from './components/HostForm';
import Modal from './components/Modal';
import Hosts from './lib/hosts';
import 'bootstrap/dist/css/bootstrap.css';
import '../css/style.css';
Hosts.load();
HostForm.create();
Modal.create();
/codes/expressjs/monitor-app-api/front/js/services/storage.js
const API_URL = '/api';
async function create(resource, data) {
resource = `${API_URL}/${resource}`;
const options = {
headers: {
'Content-Type': 'application/json',
},
method: 'post',
body: JSON.stringify(data),
};
const res = await fetch(resource, options);
const createdData = await res.json();
return createdData;
}
async function read(resource) {
resource = `${API_URL}/${resource}`;
const res = await fetch(resource);
return await res.json();
}
async function update(resource, data) {
resource = `${API_URL}/${resource}`;
const options = {
headers: {
'Content-Type': 'application/json',
},
method: 'put',
body: JSON.stringify(data),
};
const res = await fetch(resource, options);
const updatedData = await res.json();
return updatedData;
}
async function remove(resource) {
resource = `${API_URL}/${resource}`;
const options = {
method: 'delete',
};
const res = await fetch(resource, options);
return res.ok;
}
export default { create, read, update, remove };
/codes/expressjs/monitor-app-api/front/js/services/storage.js
const API_URL = '/api';
async function create(resource, data) {
resource = `${API_URL}/${resource}`;
const options = {
headers: {
'Content-Type': 'application/json',
},
method: 'post',
body: JSON.stringify(data),
};
const res = await fetch(resource, options);
const createdData = await res.json();
return createdData;
}
async function read(resource) {
resource = `${API_URL}/${resource}`;
const res = await fetch(resource);
return await res.json();
}
async function update(resource, data) {
resource = `${API_URL}/${resource}`;
const options = {
headers: {
'Content-Type': 'application/json',
},
method: 'put',
body: JSON.stringify(data),
};
const res = await fetch(resource, options);
const updatedData = await res.json();
return updatedData;
}
async function remove(resource) {
resource = `${API_URL}/${resource}`;
const options = {
method: 'delete',
};
const res = await fetch(resource, options);
return res.ok;
}
export default { create, read, update, remove };