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

🏗️ refactor tests folder architectural #127

Merged
merged 1 commit into from
Jan 7, 2024
Merged
Show file tree
Hide file tree
Changes from all 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
File renamed without changes.
3 changes: 0 additions & 3 deletions src/components/CodeBox/index.tsx

This file was deleted.

File renamed without changes.
3 changes: 0 additions & 3 deletions src/components/Collapse/index.tsx

This file was deleted.

File renamed without changes.
3 changes: 0 additions & 3 deletions src/components/Comment/index.tsx

This file was deleted.

File renamed without changes.
3 changes: 0 additions & 3 deletions src/components/Container/index.tsx

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import type { HTMLAttributes } from 'react';
import cn from '@/utils/cn';
import Link from '../Link';
import Link from './Link';

type HTMLHeadingProps = HTMLAttributes<HTMLHeadingElement>;

Expand Down
5 changes: 0 additions & 5 deletions src/components/Heading/index.tsx

This file was deleted.

File renamed without changes.
3 changes: 0 additions & 3 deletions src/components/Image/index.tsx

This file was deleted.

File renamed without changes.
3 changes: 0 additions & 3 deletions src/components/Link/index.tsx

This file was deleted.

File renamed without changes.
3 changes: 0 additions & 3 deletions src/components/List/index.tsx

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ import { useEffect, useLayoutEffect, useState } from 'react';

import useIntersectionObserver from '@/hooks/useIntersectionObserver';
import cn from '@/utils/cn';
import Collapse from '../Collapse';
import Link from '../Link';
import Collapse from './Collapse';
import Link from './Link';

type TableOfContentsProps = {
targetId: `#${string}`;
Expand Down
3 changes: 0 additions & 3 deletions src/components/TableOfContents/index.tsx

This file was deleted.

3 changes: 0 additions & 3 deletions src/components/ThemeSwitcher/index.tsx

This file was deleted.

14 changes: 0 additions & 14 deletions src/utils/__tests__/cn.test.ts

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
import { render, screen } from '@testing-library/react';

import { formatDate } from '@/utils/date';
import Article from '../Article';
import Article from '@/app/[lang]/Article';

describe('Article component', () => {
it('should render correct element', () => {
// Arrange
const data: DataFrontmatter = {
id: 'test_id',
title: 'title test',
Expand All @@ -22,7 +21,7 @@ describe('Article component', () => {
const article = screen.getByRole('article');
const image = screen.getByRole('img');
const heading = screen.getByRole('heading');
// Assert

expect(article).toBeInTheDocument();
expect(image).toHaveAttribute('src', data.image);
expect(image).toHaveAttribute('alt', `${data.title} cover`);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
import { render, screen } from '@testing-library/react';
import Footer from '../Footer';
import Footer from '@/app/[lang]/Footer';

describe('Footer component', () => {
it('should render correct element', () => {
// Arrange
const footerCopyright = 'footer copyright';
render(<Footer copyright={footerCopyright} />);
const footer = screen.getByRole('contentinfo');
// Assert
expect(footer).toBeInTheDocument();
expect(footer).toHaveTextContent(footerCopyright);
});
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { act, render, screen, waitFor } from '@testing-library/react';
import Header, { Avatar } from '../Header';
import Header, { Avatar } from '@/app/[lang]/Header';

const scrollDownTo = (to: number) => {
act(() => {
Expand All @@ -24,53 +24,43 @@ describe('Header component', () => {
);

it('should render correct element', () => {
// Arrange
render(<Header avatar={avatar} />);
const brandLink = screen.getByRole('img');
// Assert
expect(brandLink).toBeInTheDocument();
expect(brandLink.parentElement).toHaveAttribute('href', '/');
});

it('should hide header on scroll down and show on scroll up', async () => {
// Arrange
render(<Header avatar={avatar} scrollThreshold={100} />);
const header = screen.getByRole('banner');
expect(header.tagName).toBe('HEADER');

// Act
scrollDownTo(20);
// Assert
await waitFor(() => {
expect(header).toHaveStyle({ '--header-translate-y': '0px' });
});
// Act

scrollDownTo(99);
// Assert
await waitFor(() => {
expect(header).toHaveStyle({ '--header-translate-y': '0px' });
});
// Act

scrollDownTo(150);
// Assert
await waitFor(() => {
expect(header).toHaveStyle({ '--header-translate-y': '50px' });
});
// Act

scrollDownTo(800);
// Assert
await waitFor(() => {
expect(header).toHaveStyle({ '--header-translate-y': '50px' });
});
// Act

scrollUpTo(500);
// Assert
await waitFor(() => {
expect(header).toHaveStyle({ '--header-translate-y': '300px' });
});
// Act

scrollUpTo(0);
// Assert
await waitFor(() => {
expect(header).toHaveStyle({ '--header-translate-y': '300px' });
});
Expand Down
Original file line number Diff line number Diff line change
@@ -1,43 +1,39 @@
import { render, screen } from '@testing-library/react';
import { locales } from '~/i18n';
import mockPathname from '~/tests/navigation';
import Layout, { generateMetadata, generateStaticParams } from '../layout';
import mockNavigation from '~/tests/navigation';
import Layout, { generateMetadata, generateStaticParams } from '@/app/[lang]/layout';

describe('I18n layout', () => {
it('should render correct element', async () => {
// Arrange
const testText = 'Test layout component';
mockPathname.mockReturnValueOnce('/');
mockNavigation.pathname.mockReturnValueOnce('/');
const layout = await Layout({
children: <h2>{testText}</h2>,
params: { lang: 'en' }
});
render(layout);

const testChildren = await screen.findByRole('heading');
const header = await screen.findByRole('banner');
const nav = await screen.findByRole('navigation');
const footer = await screen.findByRole('contentinfo');
// Assert

expect(testChildren).toHaveTextContent(testText);
expect(header).toBeInTheDocument();
expect(nav).toBeInTheDocument();
expect(footer).toBeInTheDocument();
});

it('should generate correct metadata', async () => {
// Arrange
const metadata = await generateMetadata({
params: { lang: 'en' },
});
// Assert
expect(metadata).toBeTruthy();
});

it('should generate correct static params', async () => {
// Arrange
const staticParams = await generateStaticParams();
const expected = locales.map(lang => ({ lang }));
// Assert
expect(staticParams).toStrictEqual(expected);
});
});
Original file line number Diff line number Diff line change
@@ -1,20 +1,18 @@
import { render, screen } from '@testing-library/react';
import mockPathname from '~/tests/navigation';
import Menu, { MenuProps } from '../Menu';
import mockNavigation from '~/tests/navigation';
import Menu, { MenuProps } from '@/app/[lang]/Menu';

describe('Menu component', () => {
it('should render correct element', () => {
// Arrange
const menu: MenuProps['menu'] = [
{ text: 'Home', href: '/' },
{ text: 'Post', href: '/posts' },
];
mockPathname.mockReturnValue('/');
mockNavigation.pathname.mockReturnValue('/');
render(<Menu menu={menu} />);
const nav = screen.getByRole('navigation');
const linkA = screen.getByRole('link', { name: menu[0].text });
const linkB = screen.getByRole('link', { name: menu[1].text });
// Assert
expect(nav).toBeInTheDocument();
expect(nav.tagName).toBe('NAV');
expect(linkA).toHaveTextContent(menu[0].text);
Expand All @@ -32,17 +30,15 @@ describe('Menu component', () => {
])(
'should render correct active link based on the pathname "%s"',
(activeLinkText, otherLinkText, pathname) => {
// Arrange
const menu: MenuProps['menu'] = [
{ text: 'Home', href: '/' },
{ text: 'Post', href: '/posts' },
];
mockPathname.mockReturnValue(pathname);
mockNavigation.pathname.mockReturnValue(pathname);
render(<Menu menu={menu} />);
const activeLink = screen.getByRole('link', { name: activeLinkText });
const otherLink = screen.getByRole('link', { name: otherLinkText });
const activeClassName = 'neon-text';
// Assert
expect(activeLink).toHaveClass(activeClassName);
expect(otherLink).not.toHaveClass(activeClassName);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,27 +1,23 @@
import { render, screen } from '@testing-library/react';
import en from '~/i18n/locales/en';
import Page, { generateMetadata } from '../page';
import Page, { generateMetadata } from '@/app/[lang]/page';

jest.mock('@/utils/mdx', () => ({
getAllDataFrontmatter: () => [],
}));

describe('Root page component', () => {
it('should render correct element', async () => {
// Arrange
const page = await Page({ params: { lang: 'en' } });
render(page);
const heading = await screen.findByRole('heading', { level: 1 });
// Assert
expect(heading).toBeInTheDocument();
});

it('should generate correct metadata', async () => {
// Arrange
const metadata = await generateMetadata({
params: { lang: 'en' },
});
// Assert
expect(metadata).toStrictEqual({ title: en.common.home });
});
});
Original file line number Diff line number Diff line change
@@ -1,15 +1,13 @@
import { render, screen } from '@testing-library/react';
import Page, { generateMetadata, generateStaticParams } from '../page';
import mockNavigation from '~/tests/navigation';
import Page, {
generateMetadata,
generateStaticParams,
} from '@/app/[lang]/posts/[postId]/page';

const mockNotFound = jest.fn();
const mockDataList = jest.fn();
const mockData = jest.fn();

jest.mock('next/navigation', () => ({
notFound: () => mockNotFound(),
usePathname: () => '',
}));

jest.mock('@/components/TableOfContents', () => () => null);

jest.mock('@/utils/mdx', () => ({
Expand All @@ -18,14 +16,12 @@ jest.mock('@/utils/mdx', () => ({
}));

beforeEach(() => {
mockNotFound.mockClear();
mockDataList.mockClear();
mockData.mockClear();
});

describe('[postId] page', () => {
it('should render correct page', async () => {
// Arrange
const testText = 'test content';
mockData.mockReturnValueOnce({
id: 'test-id',
Expand All @@ -40,36 +36,28 @@ describe('[postId] page', () => {
});
render(page);
const heading = await screen.findByRole('heading', { level: 1 });
// Assert
expect(heading).toBeInTheDocument();
});

it('should call notFound when post data is null', async () => {
// Arrange
mockData.mockReturnValue(null);
await Page({ params: { postId: 'test-id' } });
// Assert
expect(mockNotFound).toBeCalled();
expect(mockNavigation.notFound).toHaveBeenCalled();
});
});

describe('generate static params', () => {

it('should generate correct static params', async () => {
// Arrange
const source = [{ id: 'test-id-1' }, { id: 'test-id-2' }];
mockDataList.mockReturnValueOnce(source);
const staticParams = await generateStaticParams();
const expected = source.map(({ id }) => ({ postId: id }));
// Assert
expect(staticParams).toStrictEqual(expected);
});
});

describe('generate metadata', () => {

it('should generate correct metadata', async () => {
// Arrange
const expected = {
date: '2023/10/28',
title: 'test title',
Expand All @@ -78,14 +66,11 @@ describe('generate metadata', () => {
const metadata = await generateMetadata({
params: { postId: 'test-id' },
});
// Assert
expect(metadata).toStrictEqual(expected);
});

it('should call notFound when post data is null', async () => {
// Arrange
await generateMetadata({ params: { postId: 'test-id' } });
// Assert
expect(mockNotFound).toBeCalled();
expect(mockNavigation.notFound).toHaveBeenCalled();
});
});
Loading
Loading