Skip to content

Commit

Permalink
Merge pull request #20 from hanstanawi/test/components-testing
Browse files Browse the repository at this point in the history
test: components testing
  • Loading branch information
hanstanawi committed Nov 12, 2023
2 parents 5092502 + 13191b1 commit 76aaf0b
Show file tree
Hide file tree
Showing 8 changed files with 219 additions and 2 deletions.
1 change: 1 addition & 0 deletions .eslintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
"simple-import-sort/exports": 1,
"@typescript-eslint/no-shadow": 0,
"@typescript-eslint/no-unused-vars": 1,
"no-restricted-syntax": 0,
"prettier/prettier": [
0,
{
Expand Down
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ dist
dist-ssr
*.local

coverage

# Editor directories and files
.vscode/*
!.vscode/extensions.json
Expand Down
56 changes: 56 additions & 0 deletions src/components/navbar.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import { render, screen } from '@testing-library/react';
import { MemoryRouter } from 'react-router-dom';

import Navbar from './navbar';

function renderComponent() {
render(
<MemoryRouter>
<Navbar />
</MemoryRouter>,
);
}

describe('navbar.tsx', () => {
it('should render a header with fixed position', () => {
renderComponent();

const header = screen.getByRole('banner');
expect(header).toBeInTheDocument();
expect(header).toHaveClass('fixed');
});

it('should show page title on navbar', () => {
renderComponent();

const pageTitle = screen.getByRole('heading', {
level: 1,
});
expect(pageTitle).toBeInTheDocument();
expect(pageTitle).toHaveTextContent('React + TypeScript Starter');
});

it('should show nav with one list and two links', () => {
renderComponent();

const nav = screen.getByRole('navigation');
const list = screen.getByRole('list');
const links = screen.getAllByRole('link');

expect(nav).toBeInTheDocument();
expect(list).toBeInTheDocument();
expect(links).toHaveLength(2);
});

it('should render a home link', () => {
renderComponent();
const homeLink = screen.getByRole('link', { name: /home/i });
expect(homeLink).toHaveAttribute('href', '/');
});

it('should render a learn more link', () => {
renderComponent();
const learnMoreLink = screen.getByRole('link', { name: /learn more/i });
expect(learnMoreLink).toHaveAttribute('href', '/learn-more');
});
});
6 changes: 6 additions & 0 deletions src/components/ui/button.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,4 +24,10 @@ describe('button.tsx', () => {
expect(mockFn).toHaveBeenCalled();
expect(mockFn).toHaveBeenCalledTimes(1);
});

it('should render button element without children props', () => {
render(<Button />);
const button = screen.getByRole('button');
expect(button).toBeInTheDocument();
});
});
57 changes: 57 additions & 0 deletions src/pages/home.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import { render, screen, within } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { MemoryRouter } from 'react-router-dom';

import Homepage from './home';

function renderComponent() {
render(
<MemoryRouter>
<Homepage />
</MemoryRouter>,
);
}

describe('home.tsx', () => {
it('should display React + TypeScript Starter Template title', () => {
renderComponent();
const title = screen.getByRole('heading', { level: 1 });
const subTitle = screen.getByRole('heading', { level: 2 });
expect(title).toHaveTextContent('React + TypeScript');
expect(subTitle).toHaveTextContent('Starter Template');
});

it('should display React and TypeScript logo and link', () => {
renderComponent();

const reactLink = screen.getByTestId('react-link');
const reactLogo = within(reactLink).getByRole('img');
const tsLink = screen.getByTestId('ts-link');
const tsLogo = within(tsLink).getByRole('img');

expect(reactLogo).toHaveAttribute('alt', 'React logo');
expect(reactLink).toHaveAttribute('href', 'https://react.dev');
expect(tsLogo).toHaveAttribute('alt', 'TS logo');
expect(tsLink).toHaveAttribute('href', 'https://typescriptlang.org');
});

it('should render a count button', () => {
renderComponent();

const button = screen.getByRole('button', { name: /count is 0/ });

expect(button).toBeInTheDocument();
});

it('should increment count button', async () => {
const user = userEvent.setup();
renderComponent();

const countButton = screen.getByRole('button', { name: /count is 0/i });
await user.click(countButton);
expect(countButton).toHaveTextContent(/count is 1/i);

await user.click(countButton);
expect(countButton).toHaveTextContent(/count is 2/i);
});
});
14 changes: 12 additions & 2 deletions src/pages/home.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,24 @@ export default function Homepage() {
return (
<div className="flex h-full w-full flex-col items-center justify-center">
<div className="flex justify-center">
<Link to="https://react.dev" target="_blank" rel="noreferrer">
<Link
to="https://react.dev"
target="_blank"
rel="noreferrer"
data-testid="react-link"
>
<img
src={reactLogo}
className="h-24 animate-spin-slow p-6"
alt="React logo"
/>
</Link>
<Link to="https://typescriptlang.org" target="_blank" rel="noreferrer">
<Link
to="https://typescriptlang.org"
target="_blank"
rel="noreferrer"
data-testid="ts-link"
>
<img src={tsLogo} className="h-24 p-6" alt="TS logo" />
</Link>
</div>
Expand Down
47 changes: 47 additions & 0 deletions src/pages/learn-more.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import { render, screen, within } from '@testing-library/react';
import { MemoryRouter } from 'react-router-dom';

import LearnMorePage from './learn-more';

function renderComponent() {
render(
<MemoryRouter>
<LearnMorePage />
</MemoryRouter>,
);
}

describe('learn-more.tsx', () => {
it('should render page title', () => {
renderComponent();

const pageTitle = screen.getByRole('heading', {
level: 1,
});

expect(pageTitle).toHaveTextContent("What's inside?");
});

it('should render list of technologies list item', () => {
renderComponent();

const list = screen.getByRole('list');
const listItems = screen.getAllByRole('listitem');

expect(list).toBeInTheDocument();
expect(listItems).toHaveLength(13);
});

it('should render a learn more button with a link', () => {
renderComponent();

const button = screen.getByRole('button');
const link = within(button).getByRole('link');

expect(button).toBeInTheDocument();
expect(link).toHaveAttribute(
'href',
'https://github.com/hanstanawi/react-ts-starter-template',
);
});
});
38 changes: 38 additions & 0 deletions src/pages/not-found.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { render, screen, within } from '@testing-library/react';
import { createMemoryRouter, RouterProvider } from 'react-router-dom';

import Homepage from './home';
import NotFoundPage from './not-found';

describe('not-found.tsx', () => {
it('should render not found page page', () => {
const router = createMemoryRouter(
[
{
path: '/',
element: <Homepage />,
errorElement: <NotFoundPage />,
},
],
{ initialEntries: ['/', '/sadasdf34'], initialIndex: 1 },
);

render(<RouterProvider router={router} />);

// Get not found page title
const title = screen.getByRole('heading', { level: 1, name: /oops!/i });
const errorText = screen.getByText(
/sorry, an unexpected error has occurred./i,
);
const errorMessage = screen.getByText(/not found/i);
const goBackButton = screen.getByRole('button');
const goHomeLink = within(goBackButton).getByRole('link');

expect(title).toBeInTheDocument();
expect(errorText).toBeInTheDocument();
expect(errorMessage).toBeInTheDocument();
expect(goBackButton).toBeInTheDocument();
expect(goHomeLink).toBeInTheDocument();
expect(goHomeLink).toHaveAttribute('href', '/');
});
});

0 comments on commit 76aaf0b

Please sign in to comment.