Skip to content

Commit

Permalink
get project by tag use case
Browse files Browse the repository at this point in the history
  • Loading branch information
MatheusSanchez committed Jan 31, 2024
1 parent 2121582 commit a45db94
Show file tree
Hide file tree
Showing 5 changed files with 200 additions and 0 deletions.
8 changes: 8 additions & 0 deletions src/repositories/in-memory-db/inMemoryProjectRepository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,4 +40,12 @@ export class InMemoryProjectRepository implements ProjectRepository {
}
return project
}

async fetchProjectByTags(tags: string[]): Promise<Project[]> {
const projects = this.dbProject.filter((project) =>
project.tags.some((tag) => tags.includes(tag)),
)

return projects
}
}
4 changes: 4 additions & 0 deletions src/repositories/prisma/prisma-project-repository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,4 +30,8 @@ export class PrismaProjectRepository implements ProjectRepository {

return project
}

async fetchProjectByTags(tags: string[]): Promise<Project[]> {
throw new Error('Method not implemented.')
}
}
1 change: 1 addition & 0 deletions src/repositories/project-repository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,5 @@ export interface ProjectRepository {
create(data: Prisma.ProjectUncheckedCreateInput): Promise<Project>
fetchProjectsByUserId(userId: string): Promise<Project[]>
fetchProjectById(projectId: string): Promise<Project | null>
fetchProjectByTags(tags: string[]): Promise<Project[]>
}
157 changes: 157 additions & 0 deletions src/use-cases/getProjetsByTagsUseCase.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
import { expect, describe, it, beforeEach } from 'vitest'

import { InMemoryProjectRepository } from '../repositories/in-memory-db/inMemoryProjectRepository'

import { ProjectRepository } from '../repositories/project-repository'
import { GetProjectsByTagsUseCase } from './getProjetsByTagsUseCase'

let projectRepository: ProjectRepository
let getProjectsByTagsUseCase: GetProjectsByTagsUseCase

describe('Get Project By Tags', () => {
beforeEach(() => {
projectRepository = new InMemoryProjectRepository()
getProjectsByTagsUseCase = new GetProjectsByTagsUseCase(projectRepository)
})

it('should be able get projects that include a tag', async () => {
await projectRepository.create({
title: 'React Typescript 1',
description: 'Best Project',
tags: ['react', 'node'],
link: 'https://github.com/luiseduardo3/nodets-petcanil',
user_id: 'user_id',
})

await projectRepository.create({
title: 'React Typescript 2',
description: 'Best Project 2',
tags: ['react', 'node', 'typescript'],
link: 'https://github.com/luiseduardo3/nodets-petcanil',
user_id: 'user_id',
})

const { projects } = await getProjectsByTagsUseCase.execute({
projectTags: ['typescript'],
})

expect(projects).toHaveLength(1)
expect(projects[0]).toEqual(
expect.objectContaining({ title: 'React Typescript 2' }),
)

expect(projects[0]).toEqual(
expect.objectContaining({ tags: ['react', 'node', 'typescript'] }),
)
})

it('Should be able to get projects that include some tags without duplicating the results.', async () => {
await projectRepository.create({
title: 'React Typescript 1',
description: 'Best Project',
tags: ['react', 'node'],
link: 'https://github.com/luiseduardo3/nodets-petcanil',
user_id: 'user_id',
})

await projectRepository.create({
title: 'React Typescript 2',
description: 'Best Project 2',
tags: ['react', 'node', 'typescript'],
link: 'https://github.com/luiseduardo3/nodets-petcanil',
user_id: 'user_id',
})

await projectRepository.create({
title: 'React Typescript 3',
description: 'Best Project 2',
tags: ['react', 'node'],
link: 'https://github.com/luiseduardo3/nodets-petcanil',
user_id: 'user_id',
})

const { projects } = await getProjectsByTagsUseCase.execute({
projectTags: ['react', 'node'],
})

expect(projects).toHaveLength(3)
expect(projects[0]).toEqual(
expect.objectContaining({ title: 'React Typescript 1' }),
)

expect(projects[1]).toEqual(
expect.objectContaining({ title: 'React Typescript 2' }),
)

expect(projects[2]).toEqual(
expect.objectContaining({ title: 'React Typescript 3' }),
)
})

it('Should be able to get projects that include tags NOT being case sensitive', async () => {
await projectRepository.create({
title: 'React Typescript 1',
description: 'Best Project',
tags: ['react', 'node'],
link: 'https://github.com/luiseduardo3/nodets-petcanil',
user_id: 'user_id',
})

await projectRepository.create({
title: 'React Typescript 2',
description: 'Best Project 2',
tags: ['react', 'node', 'typescript'],
link: 'https://github.com/luiseduardo3/nodets-petcanil',
user_id: 'user_id',
})

await projectRepository.create({
title: 'React Typescript 3',
description: 'Best Project 2',
tags: ['react', 'node'],
link: 'https://github.com/luiseduardo3/nodets-petcanil',
user_id: 'user_id',
})

const { projects } = await getProjectsByTagsUseCase.execute({
projectTags: ['REACT', 'NODE'],
})

expect(projects).toHaveLength(3)
expect(projects[0]).toEqual(
expect.objectContaining({ title: 'React Typescript 1' }),
)

expect(projects[1]).toEqual(
expect.objectContaining({ title: 'React Typescript 2' }),
)

expect(projects[2]).toEqual(
expect.objectContaining({ title: 'React Typescript 3' }),
)
})

it('should not be able to get a project if the tag was not registered', async () => {
await projectRepository.create({
title: 'React Typescript 1',
description: 'Best Project',
tags: ['tag'],
link: 'https://github.com/luiseduardo3/nodets-petcanil',
user_id: 'user_id',
})

await projectRepository.create({
title: 'React Typescript 2',
description: 'Best Project 2',
tags: ['tag'],
link: 'https://github.com/luiseduardo3/nodets-petcanil',
user_id: 'user_id',
})

const { projects } = await getProjectsByTagsUseCase.execute({
projectTags: ['react', 'node'],
})

expect(projects).toHaveLength(0)
})
})
30 changes: 30 additions & 0 deletions src/use-cases/getProjetsByTagsUseCase.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { Project } from '@prisma/client'

import { ProjectRepository } from '../repositories/project-repository'

import { ResourceNotFoundError } from './errors/ResourceNotFoundError'

interface GetProjectsByTagsRequest {
projectTags: string[]
}

interface GetProjectsByTagsResponse {
projects: Project[]
}

export class GetProjectsByTagsUseCase {
constructor(private projectRepository: ProjectRepository) {}

async execute({
projectTags,
}: GetProjectsByTagsRequest): Promise<GetProjectsByTagsResponse> {
const lowercaseTags = projectTags.map((tag) => tag.toLowerCase())

const projects =
await this.projectRepository.fetchProjectByTags(lowercaseTags)

return {
projects,
}
}
}

0 comments on commit a45db94

Please sign in to comment.