Skip to content

Commit

Permalink
Merge pull request #127 from JohnsonMao/refactor/tests-folder
Browse files Browse the repository at this point in the history
🏗️ refactor tests folder architectural
  • Loading branch information
JohnsonMao authored Jan 7, 2024
2 parents 645508d + 9c751a2 commit 26dfc9c
Show file tree
Hide file tree
Showing 54 changed files with 170 additions and 383 deletions.
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.

File renamed without changes.
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

0 comments on commit 26dfc9c

Please sign in to comment.