Skip to content

Commit

Permalink
Implementing method adoption and test e2e
Browse files Browse the repository at this point in the history
  • Loading branch information
WesleyR10 committed Dec 28, 2023
1 parent ada2938 commit 64c47a2
Show file tree
Hide file tree
Showing 14 changed files with 152 additions and 36 deletions.
2 changes: 2 additions & 0 deletions src/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { env } from '@/env'
import { usersRoutes } from "@/http/controllers/users/routes";
import { orgsRoutes } from "./http/controllers/orgs/routes";
import { petsRoutes } from "./http/controllers/pets/routes";
import { adoptionsRoutes } from "./http/controllers/adoption/routes";

export const app = fastify()

Expand All @@ -24,6 +25,7 @@ app.register(fastifyCookie)
app.register(usersRoutes)
app.register(orgsRoutes)
app.register(petsRoutes)
app.register(adoptionsRoutes)

app.setErrorHandler((error, _, reply) => {
if (error instanceof ZodError) {
Expand Down
55 changes: 55 additions & 0 deletions src/http/controllers/adoption/adoption.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import request from 'supertest'
import { app } from '@/app'
import { afterAll, beforeAll, describe, expect, it } from 'vitest'
import { createAndAuthenticateOrgs } from '@/utils/test/create-and-authenticate-orgs'
import { createAndAuthenticateUser } from '@/utils/test/create-and-authenticate-user'

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

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

it('should be able to adoption pets and after adopting pets appear as unavailable', async () => {
const { token: tokenUser, userId } = await createAndAuthenticateUser(app, true) // true = isAdmin
const { token: tokenOrg, orgId } = await createAndAuthenticateOrgs(app, true) // true = isAdmin

const pet = await request(app.server)
.post(`/orgs/${orgId}/pets`)
.set('Authorization', `Bearer ${tokenOrg}`)
.send({
animalType: 'dog',
name: 'max',
breed: 'pit-bull',
size: 'large',
age: 1,
})

const petId = pet.body.registeredPet.pet.id

const response = await request(app.server)
.post(`/${userId}/${petId}/adoption`)
.set('Authorization', `Bearer ${tokenUser}`)
.send()

expect(response.statusCode).toEqual(201)
expect(response.body).toEqual(
expect.objectContaining({phone: expect.any(String)}),
)

const responseFilter = await request(app.server)
.get('/pets/filter')
.query({
animalType: 'dog',
breed: 'pit-bull',
age: 1,
})
.set('Authorization', `Bearer ${tokenUser}`)
.send()

expect(responseFilter.statusCode).toEqual(400)
})
})
30 changes: 30 additions & 0 deletions src/http/controllers/adoption/adoption.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { FastifyReply, FastifyRequest } from 'fastify'
import { z } from "zod"
import { makeAdoptionsUseCase } from '@/use-cases/factories/make-adoptions-use-case'
import { PetNotFoundError } from '@/use-cases/errors/pet-not-found'

export async function Adoption(request: FastifyRequest, reply: FastifyReply) {
const adoptionParamsSchema = z.object({
userId: z.string().uuid(),
petId: z.string().uuid(),
})

try {
const { userId, petId } = adoptionParamsSchema.parse(request.params)

const adoptionPetUseCase = makeAdoptionsUseCase()

const adoptionDetails = await adoptionPetUseCase.execute({
userId,
petId,
})

return reply.status(201).send(adoptionDetails)
} catch (err) {
if(err instanceof PetNotFoundError){
return reply.status(409).send({ message: err.message})
}

throw err
}
}
11 changes: 11 additions & 0 deletions src/http/controllers/adoption/routes.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { FastifyInstance } from 'fastify'

import { verifyJWT } from '@/http/middlewares/verify-jwt'

import { Adoption } from './adoption'

export async function adoptionsRoutes(app: FastifyInstance) {
app.addHook('onRequest', verifyJWT)

app.post('/:userId/:petId/adoption', Adoption)
}
3 changes: 0 additions & 3 deletions src/http/controllers/pets/filterPet.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,19 +40,16 @@ describe('Filter Pets (e2e)', () => {
const response = await request(app.server)
.get('/pets/filter')
.query({
data: {
animalType: 'dog',
breed: 'pit-bull',
age: 1,
}
})
.set('Authorization', `Bearer ${token}`)
.send()

expect(response.statusCode).toEqual(200)
expect(response.body.pets).toHaveLength(2)

console.log(response.body.pets)
expect(response.body.pets).toEqual([
expect.objectContaining( {breed: 'pit-bull',}),
expect.objectContaining( {breed: 'pit-bull',}),
Expand Down
10 changes: 7 additions & 3 deletions src/http/controllers/pets/filterPet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,27 +7,31 @@ export async function filter(request: FastifyRequest, reply: FastifyReply) {
animalType: z.string().optional(),
breed: z.string().optional(),
size: z.string().optional(),
age: z.number().optional(),
age: z.coerce.number().optional(),
name: z.string().optional(),
available: z.boolean().optional(),
})

try {
const { animalType, breed, age, name, size, available } = filterPetsQuerySchema.parse(request.query)

const filterPetsUseCase = makeFilterPetByCharacteristicsUseCase()

const { pets } = await filterPetsUseCase.execute({
data: {
animalType,
breed,
size,
age,
name,
available,
}
})

return reply.status(200).send({
pets,
})
} catch (error) {
return reply.status(400).send({
message: 'Erro na validação dos parâmetros',
})
}
}
6 changes: 3 additions & 3 deletions src/http/controllers/pets/register.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,21 +21,21 @@ export async function registerPets(request: FastifyRequest, reply: FastifyReply)

const registerPetUseCase = makeRegisterPetUseCase()

await registerPetUseCase.execute({
const registeredPet = await registerPetUseCase.execute({
animalType,
name,
breed,
size,
age,
orgId,
})
return reply.status(201).send({registeredPet})

} catch (err) {
if(err instanceof OrgNotFoundError){
return reply.status(409).send({ message: err.message})
}

throw err
}

return reply.status(201).send()
}
14 changes: 7 additions & 7 deletions src/repositories/in-memory/in-memory-pets-repository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,16 +53,16 @@ export class InMemoryPetsRepository implements PetsRepository {
return pet
}

async filterPetByCharacteristics(data: Prisma.PetWhereInput): Promise<Pet[]> {
async filterPetByCharacteristics(animalType: string | undefined, breed: string | undefined, size: string | undefined, age: number | undefined, name: string | undefined, available:boolean | undefined): Promise<Pet[]> {
const filteredPets = this.items.filter((pet) => {
const matchAvailable = data.available === null || data.available === undefined || pet.available === data.available;
const matchAvailable = available === null || available === undefined || pet.available === available;

if (pet.available && matchAvailable) {
const matchAnimalType = !data.animalType || pet.animalType === data.animalType;
const matchName = !data.name || pet.name === data.name;
const matchBreed = !data.breed || pet.breed === data.breed;
const matchSize = !data.size || pet.size === data.size;
const matchAge = data.age === undefined || data.age === null || pet.age === data.age;
const matchAnimalType = !animalType || pet.animalType === animalType;
const matchName = !name || pet.name === name;
const matchBreed = !breed || pet.breed === breed;
const matchSize = !size || pet.size === size;
const matchAge = age === undefined || age === null || pet.age === age;

return matchAnimalType && matchName && matchBreed && matchSize && matchAge;
}
Expand Down
2 changes: 1 addition & 1 deletion src/repositories/pets-repository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,6 @@ import { Prisma, Pet } from '@prisma/client'
export interface PetsRepository {
findById(id: string): Promise<Pet | null>
create(data: Prisma.PetUncheckedCreateInput): Promise<Pet>
filterPetByCharacteristics(data: Prisma.PetWhereInput): Promise<Pet[]>
filterPetByCharacteristics( animalType: string | undefined, breed: string | undefined, size: string | undefined, age: number | undefined, name: string | undefined, available:boolean | undefined ): Promise<Pet[]>
updateAvailability(petId: string, available: boolean): Promise<void>;
}
12 changes: 9 additions & 3 deletions src/repositories/prisma/prisma-pets-repository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,16 @@ export class PrismaPetsRepository implements PetsRepository {
return pet
}

async filterPetByCharacteristics(data: Prisma.PetWhereInput){
async filterPetByCharacteristics(animalType: string, breed: string, size: string, age: number, name: string, available:boolean){
const pets = await prisma.pet.findMany({
where: data,
where: {
animalType,
breed,
size,
age,
name,
available,
},
})
return pets
}
Expand All @@ -32,5 +39,4 @@ export class PrismaPetsRepository implements PetsRepository {
data: { available },
});
}

}
2 changes: 1 addition & 1 deletion src/use-cases/adoptions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ export class AdoptionUseCase {
})

await this.petsRepository.updateAvailability(petId, false);

const getOrgPhone = await this.orgsRepository.findById(pet.org_id)

if (!getOrgPhone) {
Expand Down
8 changes: 0 additions & 8 deletions src/use-cases/filter-pets-by-characteristics.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,14 +67,12 @@ describe('Filter Pet By Characteristics Use Case', () => {
});

const { pets } = await sut.execute({
data: {
animalType: 'Dog',
name: 'Max',
breed: 'Labrador',
size: 'Large',
available: true,
age: 3,
}
})


Expand Down Expand Up @@ -125,10 +123,8 @@ describe('Filter Pet By Characteristics Use Case', () => {

await expect(() =>
sut.execute({
data: {
animalType: 'Dog',
// Possui o tipo dog mas o available é false
}
}),
).rejects.toBeInstanceOf(FilterByPetError)
})
Expand Down Expand Up @@ -185,10 +181,8 @@ describe('Filter Pet By Characteristics Use Case', () => {
});

const { pets } = await sut.execute({
data: {
animalType: 'Dog',
// Adicione outras características para filtrar
}
})

expect(pets).toHaveLength(2)
Expand Down Expand Up @@ -241,9 +235,7 @@ describe('Filter Pet By Characteristics Use Case', () => {

await expect(() =>
sut.execute({
data: {
animalType: 'monkey', // Característica que não existe
}
}),
).rejects.toBeInstanceOf(FilterByPetError)
})
Expand Down
28 changes: 23 additions & 5 deletions src/use-cases/filter-pets-by-characteristics.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
import { PetsRepository } from '@/repositories/pets-repository';
import { Pet, Prisma } from '@prisma/client'
import { Pet } from '@prisma/client'
import { FilterByPetError } from './errors/filter-by-pet-error';

interface FilterPetsUseCaseRequest {
data: Prisma.PetWhereInput
animalType?: string;
breed?: string;
size?: string;
age?: number;
name?: string;
available?: boolean;
}

interface FilterPetsUseCaseResponse {
Expand All @@ -14,11 +19,24 @@ export class FilterPetByCharacteristicsUseCase {
constructor(private petsRepository: PetsRepository) {}

async execute({
data
animalType,
breed,
size,
age,
name,
available,
}: FilterPetsUseCaseRequest): Promise<FilterPetsUseCaseResponse> {
const pets = await this.petsRepository.filterPetByCharacteristics(data)
const pets = await this.petsRepository.filterPetByCharacteristics(
animalType ,
breed,
size,
age,
name,
available,)

if (pets.length <= 0 ) {
const petAvailable = pets.some(pet => pet.available === true);

if (pets.length <= 0 || !petAvailable ) {
throw new FilterByPetError()
}

Expand Down
5 changes: 3 additions & 2 deletions src/utils/test/create-and-authenticate-user.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import request from 'supertest'
app: FastifyInstance,
isAdmin = false,
) {
await prisma.user.create({
const user = await prisma.user.create({
data: {
name: 'John Doe',
email: '[email protected]',
Expand All @@ -22,6 +22,7 @@ import request from 'supertest'
})

const { token } = authResponse.body
const userId = user.id

return {token}
return {token, userId}
}

0 comments on commit 64c47a2

Please sign in to comment.