3
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

ZOZOAdvent Calendar 2024

Day 24

【Jest】anchor タグを押してwindow.locationが更新されるかテストするときに発生した console.error の対応方法

Last updated at Posted at 2024-12-23

anchor タグを押して任意のURLに window.location が更新されるかテストを行った時、ナビゲーション周りのconsole.error がでてハマったので備忘録を残しておきます。

使用技術

  • Next.js: v.14.2.14
  • React: v.18.2.0
  • Jest: v.29.7.0
  • @testing-library/user-event: v.13.2.1
  • testing-library/react: v.14.0.0

コード

今回のテスト対象コードとテストコードは以下です。

テスト対象コード

テスト対象コードは以下です。href を受け取って Button Componentに渡し、Buttonが押された時hard navigationで画面遷移します。


const Component = (href: string) => {

  const handleClick = () => {
    if (href) {
          window.location.href = href
    }
    console.log("Next!")
  }
  
  return(
  <div>
    <Button type="anchor" href={href} onClick={handleClick}>Topへ</Button>
  </div>)
}

テストコード

このComponentに対するテストコードは以下です。ボタンを押した時、PCとSPのときそれぞれのURLに遷移するかをテストします。

test.each([
    {
      device: 'Pc',
      url: '/top',
    },
    {
      device: 'Sp',
      url: '/sp/top',
    },
  ])(
    '$device表示時、Topへボタンをクリックすると$urlに遷移する',
    async ({  url }) => {
      const { findByRole } = render(<Compenent href={url} />)

      const anchor = await findByRole('link', { name: 'Topへ' })

      userEvent.click(anchor)

      await waitFor(() => {
        expect(location.href).toBe(url)
      })
    }
  )

発生したエラー

このテストを実行した結果以下エラーが発生しました。(テスト自体は通る)

エラー内容を見てみると、どうやらナビゲーションが実装されてない?旨が書いてありそうです。

console.error
   Error: Not implemented: navigation (except hash changes)
    at module.exports (/***/node_modules/jsdom/lib/jsdom/browser/not-implemented.js:9:17)
       at navigateFetch (/****/node_modules/jsdom/lib/jsdom/living/window/navigation.js:77:3)
       at exports.navigate (/***/node_modules/jsdom/lib/jsdom/living/window/navigation.js:55:3)
       at Timeout._onTimeout (/***/node_modules/jsdom/lib/jsdom/living/nodes/HTMLHyperlinkElementUtils-impl.js:81:7)
       at listOnTimeout (node:internal/timers:569:17)
       at processTimers (node:internal/timers:512:7) {
     type: 'not implemented'
   }
 
     at VirtualConsole.<anonymous> (node_modules/jest-environment-jsdom/build/index.js:63:23)
     at module.exports (node_modules/jsdom/lib/jsdom/browser/not-implemented.js:12:26)
     at navigateFetch (node_modules/jsdom/lib/jsdom/living/window/navigation.js:77:3)
     at exports.navigate (node_modules/jsdom/lib/jsdom/living/window/navigation.js:55:3)
     at Timeout._onTimeout (node_modules/jsdom/lib/jsdom/living/nodes/HTMLHyperlinkElementUtils-impl.js:81:7)

原因

こちらの記事によると原因は以下にありそうでした。

  • JSDOMはナビゲーションをサポートしてない。
  • ナビゲーションをサポートしていないので、anchor タグでページ遷移処理を行おうとすると、遷移が行えないエラーが表示されてしまう。
    • ただしanchor タグを押した時、hrefを元にwindow.locationオブジェクトの更新はできるので、アサーションの比較は成功しテスト自体は通る。

対応

以下のようにテスト内で、anchor タグのページ遷移処理を無効にすることでナビゲーションをサポートしていない旨のエラーをなくすことができました。


beforeAll(() => {
  const defaultLocation = window.location
  Object.defineProperty(window, 'location', {
    writable: true,
    value: {
      ...defaultLocation,
    },
  })
})

afterAll(() => {
  Object.defineProperty(window, 'location', {
    writable: false,
  })
})

test.each([
    {
      device: 'Pc',
      url: '/top',
    },
    {
      device: 'Sp',
      url: '/sp/top',
    },
  ])(
    '$device表示時、Topへボタンをクリックすると$urlに遷移する',
    async ({  url }) => {
      const { findByRole } = render(<Compenent href={url} />)

      const anchor = await findByRole('link', { name: 'Topへ' })

	  //New: .preventDefault()でページ遷移無効
	  anchor.addEventListener('click', (event) => event.preventDefault(), false)
      userEvent.click(anchor)

      await waitFor(() => {
        expect(location.href).toBe(url)
      })
    }
  )

おまけ

ほかにもこのエラーの対応方法はありそうなのでいくつか例をあげてみました。

1.今回のエラーだけ console.error をspyする

今回のナビゲーションのエラー限定で console.error を spy する方法

const defaultErrorLog = console.error

const notImplementedErrorType =
  'Not implemented: navigation (except hash changes)'

jest.spyOn(console, 'error').mockImplementation((error) => {
  if (error.message === notImplementedErrorType) {
    return
  }
  defaultErrorLog(error)
})

2.anchorタグの href に指定されているURLの比較を行う

今回のテストは実際に画面遷移したかはスコープではありません。

なので anchorタグの href に指定されているURLを比較すれば、テストの要件を満たすことができてそうでした。

参考文献

3
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?