🐈

Next.jsでテストするときのメモ

5 min read

テキストがあるかのテスト

it('Should render hello text', () => {
  render(<Home />)
  expect(screen.getByText('Hello Next.js')).toBeInTheDocument()
})

<Home />の中に'Hello Next.js'のテキストがあればパスする。

page navigationのテスト

<a
  data-testid="blog-nav"
  className="text-gray-300 hover:bg-gray-700 px-3 py-2 rounded"
>

data-testidでテストしたい場所にidを付与

import { render, screen } from '@testing-library/react'
import '@testing-library/jest-dom/extend-expect'
import userEvent from '@testing-library/user-event'
import { getPage } from 'next-page-tester'
import { initTestHelpers } from 'next-page-tester'

initTestHelpers()

describe('Navigation by Link', () => {
    it('Should route to selected page in navbar', async () => {
        const { page } = await getPage({
          route: '/index',
        })
        render(page)

        userEvent.click(screen.getByTestId('blog-nav'))
        expect(await screen.findByText('blog page')).toBeInTheDocument()
    })
})

next-page-testerのinitTestHelpersをimportし、
clickイベントなのでuserEvent.click(先程指定したid)で、
非同期処理なのでawaitとfindByTextを使う。

getStaticPropsとgetStaticPathsのテスト

export const getStaticProps: GetStaticProps = async () => {
  const posts = await getAllPostsData()
  return {
    props: { posts },
  }
}

getStaticPropsでgetAllPostsDataを実行しているとして、
テストは、以下になります。

const handlers = [
  rest.get('https://jsonplaceholder.typicode.com/posts/', (req, res, ctx) => {
    const query = req.url.searchParams
    const _limit = query.get('_limit')
    if (_limit === '10') {
      return res(
      // 以下はダミーデータです
        ctx.status(200),
        ctx.json([
          {
            userId: 1,
            id: 1,
            title: 'dummy title 1',
            body: 'dummy body 1',
          },
          {
            userId: 2,
            id: 2,
            title: 'dummy title 2',
            body: 'dummy body 2',
          },
        ])
      )
    }
  }),
]

Mock Service Workerでhandlersの中にAPIのレスポンスを定義します。

const server = setupServer(...handlers)

セットアップサーバーを立てます。

beforeAll(() => {
  server.listen()
})

beforeAllでモックサーバーを起動します。

afterEach(() => {
  server.resetHandlers()
  cleanup()
})

afterEachでサーバーのリセットとクリーンアップ。

afterAll(() => {
  server.close()
})

afterAllでサーバーを閉じます。

describe(`Blog page`, () => {
  it('Should render the list of blogs pre-fetched by getStaticProps', async () => {
  // blog-pageを取得する
    const { page } = await getPage({
      route: '/blog-page',
    })
    // renderでpageの内容を取得する
    render(page)
    // ブログページのテキストが取得できるまで待機する
    expect(await screen.findByText('blog page')).toBeInTheDocument()
    // ダミーデータのレスポンスがDOMに表示されているかを確認する
    expect(screen.getByText('dummy title 1')).toBeInTheDocument()
    expect(screen.getByText('dummy title 2')).toBeInTheDocument()
  })
})

テストはこのようになります。

useSWRのテスト

const server = setupServer(
  rest.get(
    'https://jsonplaceholder.typicode.com/comments/',
    (req, res, ctx) => {
      const query = req.url.searchParams
      const _limit = query.get('_limit')
      if (_limit === '10') {
        return res(
          ctx.status(200),
          ctx.json([
            {
              postId: 1,
              id: 1,
              name: 'A',
              email: 'dummya@gmail.com',
              body: 'test body a',
            },
            {
              postId: 2,
              id: 2,
              name: 'B',
              email: 'dummyb@gmail.com',
              body: 'test body b',
            },
          ])
        )
      }
    }
  )
)

まず、先程と同じようにAPIのサーバー(getレスポンス)を作る。

it('Should render the value fetched by useSWR ', async () => {
    render(
      <SWRConfig value={{ dedupingInterval: 0 }}>
        <CommentPage />
      </SWRConfig>
    )
    expect(await screen.findByText('1:test body a')).toBeInTheDocument()
    expect(screen.getByText('2:test body b')).toBeInTheDocument()
  })

200番の場合。
useSWRの機能をテストする場合はSWRConfigで括ってdedupingIntervalを0にセットします。

it('Should render Error text when fetch failed', async () => {
    server.use(
      rest.get(
        'https://jsonplaceholder.typicode.com/comments/',
        (req, res, ctx) => {
          const query = req.url.searchParams
          const _limit = query.get('_limit')
          if (_limit === '10') {
            return res(ctx.status(400))
          }
        }
      )
    )
    render(
      <SWRConfig value={{ dedupingInterval: 0 }}>
        <CommentPage />
      </SWRConfig>
    )
    expect(await screen.findByText('Error!')).toBeInTheDocument()

400番の場合。
モックを変更して、Error!が表示されるかのテスト。

Discussion

ログインするとコメントできます