Skip to content

Commit

Permalink
feat: create domain driver, infra, and tests
Browse files Browse the repository at this point in the history
  • Loading branch information
GabrielCoruja committed Jan 11, 2024
1 parent 2f22e80 commit 78d5dc8
Show file tree
Hide file tree
Showing 14 changed files with 451 additions and 3 deletions.
12 changes: 12 additions & 0 deletions src/application/routes/driverRoutes.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { Router, Request, Response } from 'express';
import driverController from '../../infraestructure/factories/DriverFactory';

const router = Router();

router.post('/', (req: Request, res: Response) => driverController.create(req, res));
router.put('/:id', (req: Request, res: Response) => driverController.update(req, res));
router.delete('/:id', (req: Request, res: Response) => driverController.delete(req, res));
router.get('/', (req: Request, res: Response) => driverController.getAllByName(req, res));
router.get('/:id', (req: Request, res: Response) => driverController.getById(req, res));

export default router;
9 changes: 9 additions & 0 deletions src/domain/entities/Driver.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
class Driver {
constructor(
public id: number,
public fullname: string,
public email: string,
) { }
}

export default Driver;
28 changes: 28 additions & 0 deletions src/domain/repositories/Driver/DriverRepository.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import Driver from '../../entities/Driver';
import IDriverPersistence from './IDriverPersistence';

class DriverRepository {
constructor(private iDriverPersistence: IDriverPersistence) { }

async create(driver: Omit<Driver, 'id'>): Promise<Driver> {
return this.iDriverPersistence.save(driver);
}

async update(id: string, driver: Partial<Driver>): Promise<Driver | null> {
return this.iDriverPersistence.update(id, driver);
}

async delete(id: string): Promise<void | null> {
this.iDriverPersistence.delete(id);
}

async getById(id: string): Promise<Driver | null> {
return this.iDriverPersistence.getById(id);
}

async getAllByName(fullname: string): Promise<Driver[]> {
return this.iDriverPersistence.getAllByName(fullname);
}
}

export default DriverRepository;
11 changes: 11 additions & 0 deletions src/domain/repositories/Driver/IDriverPersistence.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import Driver from '../../entities/Driver';

interface IDriverPersistence {
save(driver: Omit<Driver, 'id'>): Promise<Driver>;
update(id: string, driver: Partial<Driver>): Promise<Driver | null>;
delete(id: string): Promise<void | null>;
getById(id: string): Promise<Driver | null>;
getAllByName(fullname: string): Promise<Driver[]>;
}

export default IDriverPersistence;
37 changes: 37 additions & 0 deletions src/domain/usecase/DriverUseCase.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import Driver from '../entities/Driver';
import DriverRepository from '../repositories/Driver/DriverRepository';

class DriverUseCase {
constructor(private driverRepository: DriverRepository) {}

public async create(driver: Omit<Driver, 'id'>): Promise<Driver> {
return this.driverRepository.create(driver);
}

public async getAllByName(fullname: string): Promise<Driver[]> {
return this.driverRepository.getAllByName(fullname);
}

public async getById(id: string): Promise<Driver | null> {
const findDriver = await this.driverRepository.getById(id);
return findDriver;
}

public async update(id: string, driver: Partial<Driver>): Promise<Driver | null> {
const findDriver = await this.driverRepository.getById(id);

if (!findDriver) return null;

return this.driverRepository.update(id, driver);
}

public async delete(id: string): Promise<void | null> {
const findDriver = await this.driverRepository.getById(id);

if (!findDriver) return null;

await this.driverRepository.delete(id);
}
}

export default DriverUseCase;
61 changes: 61 additions & 0 deletions src/infraestructure/controllers/DriverController.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import { Request, Response } from 'express';
import DriverUseCase from '../../domain/usecase/DriverUseCase';
import StatusCode from '../enum/statusCode';

class DriverController {
private messageDriverNotFound = 'Driver not found';

constructor(private driverUseCase: DriverUseCase) { }

async create(req: Request, res: Response): Promise<Response> {
const { fullname, email } = req.body;

const driver = await this.driverUseCase.create({ fullname, email });

return res.status(StatusCode.CREATED).json(driver);
}

async update(req: Request, res: Response): Promise<Response> {
const { id } = req.params;
const { fullname, email } = req.body;

const driver = await this.driverUseCase.update(id, { fullname, email });
if (!driver) {
return res.status(StatusCode.NOT_FOUND).json({ message: this.messageDriverNotFound });
}

return res.status(StatusCode.OK).json(driver);
}

async delete(req: Request, res: Response): Promise<Response> {
const { id } = req.params;

const deleteDriver = await this.driverUseCase.delete(id);
if (deleteDriver === null) {
return res.status(StatusCode.NOT_FOUND).json({ message: this.messageDriverNotFound });
}

return res.status(StatusCode.NO_CONTENT).end();
}

async getAllByName(req: Request, res: Response): Promise<Response> {
const { fullname } = req.query;

const drivers = await this.driverUseCase.getAllByName(fullname as string);

return res.status(StatusCode.OK).json(drivers);
}

async getById(req: Request, res: Response): Promise<Response> {
const { id } = req.params;

const driver = await this.driverUseCase.getById(id);
if (!driver) {
return res.status(StatusCode.NOT_FOUND).json({ message: this.messageDriverNotFound });
}

return res.status(StatusCode.OK).json(driver);
}
}

export default DriverController;
12 changes: 12 additions & 0 deletions src/infraestructure/factories/DriverFactory.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import DriverController from '../controllers/DriverController';
import DriverRepository from '../../domain/repositories/Driver/DriverRepository';
import DriverUseCase from '../../domain/usecase/DriverUseCase';
import DriverPersistence from '../persistence/DriverPersistence';
import DriverModel from '../persistence/database/models/DriverModel';

const driverPersistence = new DriverPersistence(DriverModel);
const driverRepository = new DriverRepository(driverPersistence);
const driverUseCases = new DriverUseCase(driverRepository);
const controller = new DriverController(driverUseCases);

export default controller;
46 changes: 46 additions & 0 deletions src/infraestructure/persistence/DriverPersistence.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import { ModelStatic, Op } from 'sequelize';
import Driver from '../../domain/entities/Driver';
import IDriverPersistence from '../../domain/repositories/Driver/IDriverPersistence';
import DriverModel from './database/models/DriverModel';

class DriverPersistence implements IDriverPersistence {
constructor(private driverModel: ModelStatic<DriverModel>) { }

async save(driver: Omit<Driver, 'id'>): Promise<Driver> {
const newDriver = await this.driverModel.create(driver);
return newDriver.dataValues;
}

async update(id: string, driver: Partial<Driver>): Promise<Driver | null> {
const findDriver = await this.driverModel.findByPk(id);
if (!findDriver) return null;

const test = await findDriver.update(driver);
console.log('test', test);

return findDriver.dataValues;
}

async delete(id: string): Promise<void | null> {
const findDriver = await this.driverModel.findByPk(id);
if (!findDriver) return null;
await findDriver.destroy();
}

async getById(id: string): Promise<Driver | null> {
const findDriver = await this.driverModel.findByPk(id);
if (!findDriver) return null;
return findDriver.dataValues;
}

async getAllByName(fullname: string): Promise<Driver[]> {
const getDrivers = await this.driverModel.findAll({
where: {
fullname: { [Op.like]: `%${fullname}%` },
},
});
return getDrivers.map((driver) => driver.dataValues);
}
}

export default DriverPersistence;
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { DataTypes, Model, QueryInterface } from 'sequelize';
import Driver from '../../../../domain/entities/Driver';

export default {
up(queryInterface: QueryInterface) {
return queryInterface.createTable<Model<Driver>>('drivers', {
id: {
type: DataTypes.INTEGER,
primaryKey: true,
allowNull: false,
},
fullname: {
type: DataTypes.STRING,
allowNull: false,
},
email: {
type: DataTypes.STRING,
allowNull: false,
},
});
},

down(queryInterface: QueryInterface) {
return queryInterface.dropTable('drivers');
},
};
38 changes: 38 additions & 0 deletions src/infraestructure/persistence/database/models/DriverModel.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import {
DataTypes,
Model,
InferAttributes,
InferCreationAttributes,
CreationOptional,
} from 'sequelize';
import db from '.';

class DriverModel extends Model<InferAttributes<DriverModel>,
InferCreationAttributes<DriverModel>> {
declare id: CreationOptional<number>;
declare fullname: string;
declare email: string;
}

DriverModel.init({
id: {
type: DataTypes.INTEGER,
primaryKey: true,
allowNull: false,
},
fullname: {
type: DataTypes.STRING,
allowNull: false,
},
email: {
type: DataTypes.STRING,
allowNull: false,
},
}, {
tableName: 'drivers',
timestamps: false,
underscored: true,
sequelize: db,
});

export default DriverModel;
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { QueryInterface } from 'sequelize';

export default {
up(queryInterface: QueryInterface) {
return queryInterface.bulkInsert('drivers', [
{
fullname: 'Lucas Silva',
email: 'lucas.silva@email.com',
},
{
fullname: 'João Nascimento',
email: 'joao.nascimento@email.com',
},
{
fullname: 'Maria Silva',
email: 'maria.silva@email.com',
},
{
fullname: 'Pedro Silva',
email: 'pedro.silva@email.com',
},
{
fullname: 'Pedro Nascimento',
email: 'pedro.nascimento@email.com',
},
], {});
},

down(queryInterface: QueryInterface) {
return queryInterface.bulkDelete('drivers', {});
}
};
6 changes: 3 additions & 3 deletions src/tests/integration/car.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ describe('Car routes', () => {
expect(response.body).toEqual(carsMock[0]);
});

it('Return any car when not found', async () => {
it('Return no car when not found', async () => {
jest.spyOn(CarModel, 'findByPk').mockResolvedValueOnce(null);

const response = await request(app).get('/cars/AAA-8888');
Expand All @@ -55,7 +55,7 @@ describe('Car routes', () => {
});

describe('PUT/', () => {
it('Return any car when not found', async () => {
it('Return no car when not found', async () => {
jest.spyOn(CarModel, 'findByPk').mockResolvedValueOnce(null);

const response = await request(app).put('/cars/AAA-8888').send(carsMock[0]);
Expand All @@ -66,7 +66,7 @@ describe('Car routes', () => {
});

describe('DELETE/', () => {
it('Return any car when not found', async () => {
it('Return no car when not found', async () => {
jest.spyOn(CarModel, 'findByPk').mockResolvedValueOnce(null);

const response = await request(app).delete('/cars/AAA-8888');
Expand Down
Loading

0 comments on commit 78d5dc8

Please sign in to comment.