Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rayane barbosa/testes unitarios #86

Merged
Merged
Show file tree
Hide file tree
Changes from 10 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@
"@rocketseat/eslint-config": "^2.2.2",
"@testing-library/jest-dom": "^6.4.5",
"@testing-library/react": "^15.0.7",
"@testing-library/react-hooks": "^8.0.1",
"@testing-library/user-event": "^14.5.2",
"@types/jest": "^29.5.12",
"@types/mocha": "^10.0.6",
"@types/node": "^20.12.12",
Expand Down
2 changes: 0 additions & 2 deletions src/components/footer/index.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,6 @@ describe('AppFooter', () => {
expect(linkElement).toBeInTheDocument()
if (menu.href.startsWith('http')) {
expect(linkElement.closest('a')).toHaveAttribute('href', menu.href)
} else {
expect(linkElement.closest('a')).toHaveAttribute('href', menu.href)
}
})
})
Expand Down
20 changes: 20 additions & 0 deletions src/components/footer/socials.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { socials } from './socials'

describe('socials', () => {
it('should have at least one social link', () => {
expect(socials.length).toBeGreaterThan(0)
})

it('should have valid href values', () => {
socials.forEach((social) => {
expect(social.href).toMatch(/^https?:\/\/[^\s/$.?#].[^\s]*$/)
})
})

it('should have valid icon components', () => {
socials.forEach((social) => {
expect(social.icon).toBeDefined()
expect(typeof social.icon).toBe('object')
})
})
})
65 changes: 65 additions & 0 deletions src/components/header/index.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import { AppHeader } from '@/components/header'
import '@testing-library/jest-dom'
import { fireEvent, render, screen } from '@testing-library/react'
import { BrowserRouter as Router } from 'react-router-dom'

jest.mock('@/hooks/useIsMobile', () => ({
useIsMobile: () => true,
}))

jest.mock('@uidotdev/usehooks', () => ({
useWindowScroll: () => [{ y: 0 }],
}))

describe('AppHeader', () => {
it('renders without crashing', () => {
render(
<Router>
<AppHeader />
</Router>,
)
})
it('displays the hamburger menu icon on mobile', () => {
render(
<Router>
<AppHeader />
</Router>,
)
const hamburgerMenuIcon = screen.getByRole('button')
expect(hamburgerMenuIcon).toBeInTheDocument()
})

it('displays the navigation menu when the hamburger menu icon is clicked', () => {
render(
<Router>
<AppHeader />
</Router>,
)
const hamburgerMenuIcon = screen.getByRole('button')
fireEvent.click(hamburgerMenuIcon)
const navMenu = screen.getByRole('navigation')
expect(navMenu).toBeInTheDocument()
})

it('displays the "Voltar à home" link when not on the home page', () => {
window.history.pushState({}, '', '/not-home')
render(
<Router>
<AppHeader />
</Router>,
)
const link = screen.getByText('Voltar à home')
expect(link).toBeInTheDocument()
})

it('displays the "Cadastrar um pet" link when not on the subscription page', () => {
window.history.pushState({}, '', '/not-subscription')
render(
<Router>
<AppHeader />
</Router>,
)
const link = screen.getByText('Cadastrar um pet')
expect(link).toBeInTheDocument()
})
})
2 changes: 1 addition & 1 deletion src/components/header/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { Fragment, useState } from 'react'
import { Link, useLocation } from 'react-router-dom'
import { Link as ScrollLink } from 'react-scroll'
import { Logo } from '../logo'
import { Button } from '../ui/button'
import { Button } from '../ui/components/button/button'
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Acredito que seja melhor ser amenas /ui/button (o arquivo do botão estar no index.tsx) e remover a pasta de components, já estamos dentro dela, não faz sentido ter components dentro de components. Já é entendível que itens dentro da ui são componentes.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Eu atualizei dessa forma por se tratar de uma boa prática na escrita de testes unitários de acordo com a arquitetura component-based-architecture

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

O projeto já está em arquitetura baseada em componentes, só não acredito que ter que importar form/form seja um modelo mental bom.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fora que também já estamos na pasta de components, não faz sentido ter outra. Se não daqui a pouco vamos ter ui/components/form/components...

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Blz. Vou realizar os ajustes


const menus = [
{
Expand Down
32 changes: 32 additions & 0 deletions src/components/join-us/index.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import '@testing-library/jest-dom'
import { render, screen } from '@testing-library/react'
import { JoinUs } from './index'

describe('JoinUs component', () => {
beforeEach(() => {
render(<JoinUs />)
})

it('renders without crashing', () => {
const joinUsElement = screen.getByText(/Faça parte da nossa equipe/i)
expect(joinUsElement).toBeInTheDocument()
})

it('contains a Paw component', () => {
const pawElement = screen.getByTestId('join-us-paw')
expect(pawElement).toBeInTheDocument()
})

it('contains a Button component', () => {
const buttonElement = screen.getByTestId('join-us-button')
expect(buttonElement).toBeInTheDocument()
})

it('contains a link to the Discord server', () => {
const linkElement = screen.getByRole('link')
expect(linkElement).toHaveAttribute(
'href',
'https://discord.com/invite/Pr2BZmUG',
)
})
})
8 changes: 6 additions & 2 deletions src/components/join-us/index.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
import { ChevronRight } from 'lucide-react'
import { Paw } from '../paw'
import { Button } from '../ui/button'
import { Button } from '../ui/components/button/button'
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Acredito que seja melhor ser amenas /ui/button (o arquivo do botão estar no index.tsx) e remover a pasta de components, já estamos dentro dela, não faz sentido ter components dentro de components. Já é entendível que itens dentro da ui são componentes.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Eu atualizei dessa forma por se tratar de uma boa prática na escrita de testes unitários de acordo com a arquitetura component-based-architecture


export function JoinUs() {
return (
<section className="bg-primary-500 py-10 text-white lg:py-20">
<div className="container">
<Paw className="mx-auto mb-2.5 size-10 lg:mb-11 lg:h-[68px] lg:w-[72px]" />
<Paw
data-testid="join-us-paw"
className="mx-auto mb-2.5 size-10 lg:mb-11 lg:h-[68px] lg:w-[72px]"
/>

<h2 className="mb-6 text-balance text-center text-2xl font-bold lg:mb-11 lg:text-5xl">
Faça parte da nossa equipe
Expand All @@ -20,6 +23,7 @@ export function JoinUs() {
</p>

<Button
data-testid="join-us-button"
asChild
className="mx-auto mt-7 flex h-auto w-full gap-1 bg-white px-6 py-3 text-base font-semibold text-primary hover:bg-white/80 lg:mt-14 lg:w-fit"
>
Expand Down
22 changes: 22 additions & 0 deletions src/components/others-platforms/index.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import '@testing-library/jest-dom'
import { render, screen } from '@testing-library/react'
import { OthersPlatforms } from '.'

describe('OthersPlatforms', () => {
test('renders without crashing', () => {
render(<OthersPlatforms />)
expect(screen).not.toBeNull()
})

test('contains the heading', () => {
render(<OthersPlatforms />)
const heading = screen.getByText(/Explore Mais Opções/i)
expect(heading).toBeInTheDocument()
})

test('contains the paragraph text', () => {
render(<OthersPlatforms />)
const paragraph = screen.getByText(/Se você ainda não encontrou seu pet/i)
expect(paragraph).toBeInTheDocument()
})
})
24 changes: 24 additions & 0 deletions src/components/pet-card/index.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import '@testing-library/jest-dom'
import { render, screen } from '@testing-library/react'
import { PetCard } from '.'

describe('PetCard', () => {
const mockProps = {
id: 1,
imageSrc: 'testImageSrc',
title: 'testTitle',
description: 'testDescription',
specie: 'testSpecie',
size: 'testSize',
color: 'testColor',
}
it('displays the correct title', () => {
render(<PetCard {...mockProps} />)
expect(screen.getByText(mockProps.title)).toBeInTheDocument()
})

it('displays the correct description', () => {
render(<PetCard {...mockProps} />)
expect(screen.getByText(mockProps.description)).toBeInTheDocument()
})
})
4 changes: 2 additions & 2 deletions src/components/pet-card/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@ import {
DialogPortal,
DialogTitle,
DialogTrigger,
} from '@/components/ui/dialog'
} from '@/components/ui/components/dialog/dialog'
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Acredito que seja melhor ser amenas /ui/dialog (o arquivo do dialog estar no index.tsx) e remover a pasta de components, já estamos dentro dela, não faz sentido ter components dentro de components. Já é entendível que itens dentro da ui são componentes.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Eu atualizei dessa forma por se tratar de uma boa prática na escrita de testes unitários de acordo com a arquitetura component-based-architecture

import { ChevronRight, ZoomIn } from 'lucide-react'
import { Link } from 'react-router-dom'
import { Button } from '../ui/button'
import { Button } from '../ui/components/button/button'

interface PetCardProps {
id: number
Expand Down
28 changes: 28 additions & 0 deletions src/components/ui/components/button/button.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import '@testing-library/jest-dom'
import { render, screen } from '@testing-library/react'
import { Button } from './button'

describe('Button', () => {
it('renders correctly with default props', () => {
render(<Button />)
const button = screen.getByRole('button')
expect(button).toBeInTheDocument()
expect(button).toHaveClass(
'inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50',
)
})

it('renders correctly with variant prop', () => {
render(<Button variant="destructive" />)
const button = screen.getByRole('button')
expect(button).toHaveClass(
'bg-destructive text-destructive-foreground shadow-sm hover:bg-destructive/90',
)
})

it('renders correctly with size prop', () => {
render(<Button size="lg" />)
const button = screen.getByRole('button')
expect(button).toHaveClass('h-10 rounded-md px-8')
})
})
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import * as React from 'react'
import { Slot } from '@radix-ui/react-slot'
import { cva, type VariantProps } from 'class-variance-authority'
import * as React from 'react'

import { cn } from '@/lib/utils'

Expand Down
35 changes: 35 additions & 0 deletions src/components/ui/components/dialog/dialog.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import '@testing-library/jest-dom'
import { render, screen } from '@testing-library/react'
import {
Dialog,
DialogClose,
DialogContent,
DialogDescription,
DialogFooter,
DialogHeader,
DialogTitle,
DialogTrigger,
} from './dialog'

describe('Dialog Component', () => {
it('renders without crashing', () => {
render(
<Dialog>
<DialogTrigger>Open Dialog</DialogTrigger>
<DialogContent>
<DialogHeader>
<DialogTitle>Dialog Title</DialogTitle>
<DialogClose>Close</DialogClose>
</DialogHeader>
<DialogDescription>Dialog Description</DialogDescription>
<DialogFooter>
<button>Cancel</button>
<button>Save</button>
</DialogFooter>
</DialogContent>
</Dialog>,
)

expect(screen.findByRole('dialog')).toBeDefined()
})
})
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

colocaria como index.tsx pra quando for usar não ficar um import duplicado. "/ui/components/form/form" e removeria o components já que já tem uma pasta mãe que se chama components.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Eu atualizei dessa forma por se tratar de uma boa prática na escrita de testes unitários de acordo com a arquitetura component-based-architecture

Nos projetos é até preferivel você manter separação de componentes. No caso dos componentes UI os separei de forma que seja mais organizavel observar e criar os testes unitários e testes de componentes

File renamed without changes.
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { render } from '@testing-library/react'
import { ImageWithLoader } from './image-with-loader'
import '@testing-library/jest-dom'

describe('ImageWithLoader', () => {
it('renders without errors', () => {
render(<ImageWithLoader src="test.jpg" alt="Test Image" />)
})

it('renders with the correct alt text', () => {
const altText = 'Test Image'
const { getByAltText } = render(
<ImageWithLoader src="test.jpg" alt={altText} />,
)
expect(getByAltText(altText)).toBeInTheDocument()
})

it('applies the provided className', () => {
const className = 'custom-class'
const { container } = render(
<ImageWithLoader src="test.jpg" alt="Test Image" className={className} />,
)
expect(container.firstChild).toHaveClass(className)
})
})
20 changes: 20 additions & 0 deletions src/components/ui/components/input/input-masked.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import '@testing-library/jest-dom'
import { render, screen } from '@testing-library/react'
import React from 'react'
import { MaskedInput } from './input-masked'
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Acredito que seja melhor e mais fácil deixar separado em pastas (input, input-masked e textarea) cada um com a sua pasta ao invés de todos ficarem dentro de input.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Adicionei-os em input por se tratarem de entradas de texto (mesmo segmento) assim sendo mais fácil sua leitura e compreensão


describe('MaskedInput', () => {
it('renders without errors', () => {
render(<MaskedInput />)
expect(screen.getByRole('textbox')).toBeInTheDocument()
})
it('renders with custom class name', () => {
render(<MaskedInput className="custom-input" />)
expect(screen.getByRole('textbox')).toHaveClass('custom-input')
})
it('forwards ref to the input element', () => {
const ref = React.createRef<HTMLInputElement>()
render(<MaskedInput ref={ref} />)
expect(ref.current).toBeInstanceOf(HTMLInputElement)
})
})
30 changes: 30 additions & 0 deletions src/components/ui/components/input/input.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import '@testing-library/jest-dom'
import { fireEvent, render, screen } from '@testing-library/react'
import React from 'react'
import { Input } from './input'

describe('Input', () => {
test('renders without errors', () => {
render(<Input />)
expect(screen.getByRole('textbox')).toBeInTheDocument()
})

test('renders with custom class name', () => {
render(<Input className="custom-input" />)
expect(screen.getByRole('textbox')).toHaveClass('custom-input')
})

test('forwards ref to the input element', () => {
const ref = React.createRef<HTMLInputElement>()
render(<Input ref={ref} />)
expect(ref.current).toBeInstanceOf(HTMLInputElement)
})

test('triggers onChange event', () => {
const handleChange = jest.fn()
render(<Input onChange={handleChange} />)
fireEvent.change(screen.getByRole('textbox'), { target: { value: 'test' } })
expect(handleChange).toHaveBeenCalledTimes(1)
expect(handleChange).toHaveBeenCalledWith(expect.any(Object))
})
})
Loading
Loading