Skip to content

Commit

Permalink
feat(infra): controllers of driver and administrator registration and…
Browse files Browse the repository at this point in the history
… search for pending requests

In the http layer created driver and administrator registration controllers and e2e tests,
and a fetch pending solicitations controller and e2e test.
In the persistence layer, factories were created for use cases of these controllers.
  • Loading branch information
ClaudionorOjr committed Nov 24, 2023
1 parent d693de6 commit c8b25cf
Show file tree
Hide file tree
Showing 17 changed files with 252 additions and 4 deletions.
15 changes: 15 additions & 0 deletions src/infra/cryptography/bcrypt-hasher.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,25 @@ import { compare, hash } from 'bcryptjs'
export class BcryptHasher implements HashGenerator, HashComparer {
readonly HASH_SALT_LENGTH = 8

/**
* Generates a hash of the given plain text string.
*
* @param {string} plain - The plain text string to be hashed.
* @return {Promise<string>} A promise that resolves to the hashed string.
*/
hash(plain: string): Promise<string> {
return hash(plain, this.HASH_SALT_LENGTH)
}

/**
* Compares a plain text string with a hashed string and returns a promise
* that resolves to a boolean indicating whether they match.
*
* @param {string} plain - The plain text string to compare.
* @param {string} hash - The hashed string to compare against.
* @return {Promise<boolean>} A promise that resolves to a boolean indicating
* whether the plain text and hashed string match.
*/
compare(plain: string, hash: string): Promise<boolean> {
return compare(plain, hash)
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { FetchPendingSolicitationsUseCase } from '@account/application/use-cases/fetch-pending-solicitations'
import { PrismaSolicitatitonsRepository } from '../repositories/prisma-solicitations-repository'

export function makeFetchPendingSolicitationsUseCase() {
const solicitationsRepository = new PrismaSolicitatitonsRepository()
const fetchPendingSolicitationsUseCase = new FetchPendingSolicitationsUseCase(
solicitationsRepository,
)

return fetchPendingSolicitationsUseCase
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { RegisterAdminUseCase } from '@account/application/use-cases/register-admin'
import { PrismaUsersRepository } from '../repositories/prisma-users-repository'
import { BcryptHasher } from '@infra/cryptography/bcrypt-hasher'

export function makeRegisterAdminUseCase() {
const usersRepository = new PrismaUsersRepository()
const hasher = new BcryptHasher()
const registerAdminUseCase = new RegisterAdminUseCase(usersRepository, hasher)

return registerAdminUseCase
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { RegisterDriverUseCase } from '@account/application/use-cases/register-driver'
import { PrismaUsersRepository } from '../repositories/prisma-users-repository'
import { BcryptHasher } from '@infra/cryptography/bcrypt-hasher'

export function makeRegisterDriverUseCase() {
const usersRepository = new PrismaUsersRepository()
const hasher = new BcryptHasher()
const registerDriverUseCase = new RegisterDriverUseCase(
usersRepository,
hasher,
)

return registerDriverUseCase
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { SignUpStudentUseCase } from '@account/application/use-cases/signup-student'
import { PrismaSolicitatitonsRepository } from '../repositories/prisma-solicitations-repository'
import { BcryptHasher } from 'src/infra/cryptography/bcrypt-hasher'
import { BcryptHasher } from '@infra/cryptography/bcrypt-hasher'
import { PrismaUsersRepository } from '../repositories/prisma-users-repository'

export function makeSignupStudentUseCase() {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { databaseE2ETests } from 'prisma/vitest-environment-prisma/setup-e2e'
import { app } from 'src/app'
import request from 'supertest'
import { makePrismaSolicitation } from 'test/factories/make-solicitation'

describe('Fetch pending solicitations (e2e)', () => {
beforeAll(async () => {
await app.ready()
})

afterAll(async () => {
await app.close()
})

test('[GET] /solicitations', async () => {
await makePrismaSolicitation()
await makePrismaSolicitation()

const response = await request(app.server).get('/solicitations').send()

expect(response.statusCode).toEqual(200)

const solicitationsOnDatabase =
await databaseE2ETests.solicitation.findMany()

expect(solicitationsOnDatabase).toHaveLength(2)
})
})
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { makeFetchPendingSolicitationsUseCase } from '@infra/database/prisma/factories/make-fetch-pending-solicitations-use-case'
import { FastifyReply, FastifyRequest } from 'fastify'

export async function fetchPendingSolicitations(
request: FastifyRequest,
reply: FastifyReply,
) {
const fetchPendingSolicitationsUseCase =
makeFetchPendingSolicitationsUseCase()

const result = await fetchPendingSolicitationsUseCase.execute()

if (result.isFailure()) {
return reply.status(400).send()
}
const { solicitations } = result.value

return reply.status(200).send(solicitations)
}
32 changes: 32 additions & 0 deletions src/infra/http/controllers/register-admin-controller.e2e.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { databaseE2ETests } from 'prisma/vitest-environment-prisma/setup-e2e'
import { app } from 'src/app'
import request from 'supertest'

describe('Register Admin (e2e)', () => {
beforeAll(async () => {
await app.ready()
})

afterAll(async () => {
await app.close()
})

test('[POST] /admins/register', async () => {
const response = await request(app.server).post('/admins/register').send({
completeName: 'John Doe',
email: '[email protected]',
password: '123456',
phone: '(00) 98765-4321',
})

expect(response.statusCode).toEqual(201)

const adminOnDatabase = await databaseE2ETests.user.findUnique({
where: {
email: '[email protected]',
},
})

expect(adminOnDatabase).toBeTruthy()
})
})
36 changes: 36 additions & 0 deletions src/infra/http/controllers/register-admin-controller.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { UserAlreadyExistsError } from '@account/application/use-cases/errors/user-already-exists-error'
import { makeRegisterAdminUseCase } from '@infra/database/prisma/factories/make-register-admin-use-case'
import { FastifyReply, FastifyRequest } from 'fastify'
import { z } from 'zod'

export async function registerAdmin(
request: FastifyRequest,
reply: FastifyReply,
) {
const registerAdminBodySchema = z.object({
completeName: z.string(),
email: z.string().email(),
password: z.coerce.string().min(6),
phone: z.string(),
})

const { completeName, email, password, phone } =
registerAdminBodySchema.parse(request.body)

try {
const registerAdminUseCase = makeRegisterAdminUseCase()

await registerAdminUseCase.execute({
completeName,
email,
password,
phone,
})

return reply.status(201).send()
} catch (error) {
if (error instanceof UserAlreadyExistsError) {
return reply.status(409).send({ message: error.message })
}
}
}
32 changes: 32 additions & 0 deletions src/infra/http/controllers/register-driver-controller.e2e.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { databaseE2ETests } from 'prisma/vitest-environment-prisma/setup-e2e'
import { app } from 'src/app'
import request from 'supertest'

describe('Register driver (e2e)', () => {
beforeAll(async () => {
await app.ready()
})

afterAll(async () => {
await app.close()
})

test('[POST] /drivers/register', async () => {
const response = await request(app.server).post('/drivers/register').send({
completeName: 'John Doe',
email: '[email protected]',
password: '123456',
phone: '(00) 98765-4321',
})

expect(response.statusCode).toEqual(201)

const driverOnDatabase = await databaseE2ETests.user.findUnique({
where: {
email: '[email protected]',
},
})

expect(driverOnDatabase).toBeTruthy()
})
})
38 changes: 38 additions & 0 deletions src/infra/http/controllers/register-driver-controller.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { FastifyReply, FastifyRequest } from 'fastify'
import { UserAlreadyExistsError } from '@account/application/use-cases/errors/user-already-exists-error'
import { makeRegisterDriverUseCase } from '@infra/database/prisma/factories/make-register-driver-use-case'
import { z } from 'zod'

export async function registerDriver(
request: FastifyRequest,
reply: FastifyReply,
) {
const registerDriverBodySchema = z.object({
completeName: z.string(),
email: z.string().email(),
password: z.coerce.string().min(6),
phone: z.string(),
})

const { completeName, email, password, phone } =
registerDriverBodySchema.parse(request.body)

try {
const registerDriverUseCase = makeRegisterDriverUseCase()

await registerDriverUseCase.execute({
completeName,
email,
password,
phone,
})

return reply.status(201).send()
} catch (error) {
if (error instanceof UserAlreadyExistsError) {
return reply.status(409).send({ message: error.message })
}

throw error
}
}
2 changes: 1 addition & 1 deletion src/infra/http/controllers/register-student-controller.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { ResourceNotFoundError } from '@core/errors/resource-not-found-error'
import { FastifyReply, FastifyRequest } from 'fastify'
import { makeRegisterStudentUseCase } from 'src/infra/database/prisma/factories/make-register-student-use-case'
import { makeRegisterStudentUseCase } from '@infra/database/prisma/factories/make-register-student-use-case'
import { z } from 'zod'

export async function registerStudent(
Expand Down
7 changes: 7 additions & 0 deletions src/infra/http/controllers/routes.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,16 @@
import { FastifyInstance } from 'fastify'
import { signUpStudent } from './signup-student-controller'
import { registerStudent } from './register-student-controller'
import { registerDriver } from './register-driver-controller'
import { registerAdmin } from './register-admin-controller'
import { fetchPendingSolicitations } from './fetch-pending-solicitations-controller'

export async function routes(app: FastifyInstance) {
app.post('/signup', signUpStudent)

app.post('/solicitations/:solicitationId/register', registerStudent)
app.post('/drivers/register', registerDriver)
app.post('/admins/register', registerAdmin)

app.get('/solicitations', fetchPendingSolicitations)
}
2 changes: 1 addition & 1 deletion src/infra/http/controllers/signup-student-controller.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { FastifyReply, FastifyRequest } from 'fastify'
import { makeSignupStudentUseCase } from 'src/infra/database/prisma/factories/make-signup-student-use-case'
import { makeSignupStudentUseCase } from '@infra/database/prisma/factories/make-signup-student-use-case'
import { UserAlreadyExistsError } from '@account/application/use-cases/errors/user-already-exists-error'
import { z } from 'zod'
import dayjs from 'dayjs'
Expand Down
2 changes: 1 addition & 1 deletion test/factories/make-solicitation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import {
} from '@account/enterprise/entities/solicitation'
import { faker } from '@faker-js/faker'
import { databaseE2ETests } from 'prisma/vitest-environment-prisma/setup-e2e'
import { PrismaSolicitationMapper } from 'src/infra/database/prisma/mappers/prisma-solicitatiton-mapper'
import { PrismaSolicitationMapper } from '@infra/database/prisma/mappers/prisma-solicitatiton-mapper'

/**
* Creates a solicitation with optional overrides and an optional ID.
Expand Down
1 change: 1 addition & 0 deletions tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
"@account/*": ["./src/domain/account/*"],
"@institutional/*": ["./src/domain/institutional/*"],
"@transportation/*": ["./src/domain/transportation/*"],
"@infra/*":["./src/infra/*"]
}, /* Specify a set of entries that re-map imports to additional lookup locations. */
// "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */
// "typeRoots": [], /* Specify multiple folders that act like './node_modules/@types'. */
Expand Down
4 changes: 4 additions & 0 deletions vitest.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,9 @@ import { defineConfig } from 'vitest/config'
import tsconfigPaths from 'vite-tsconfig-paths'

export default defineConfig({
test: {
globals: true,
root: './',
},
plugins: [tsconfigPaths()],
})

0 comments on commit c8b25cf

Please sign in to comment.