mmag

ハマったことメモなど

Svelteコンポーネントをテストするときはテスト用コンポーネントを書くといい気がした

気がしているという程度なので話半分で。

前提

Svelteのコンポーネントをテストしたい。テストにはjest@testing-library/svelteを使用。

本題

発端としては「Buttonコンポーネントをrenderするとslotの中身が表示される」というはじめの一歩的なものを書こうとしたらslotを指定できなくてハマったのでした。Svelte 2の頃はComponent APIslotsオプションを受け付けていてくれたので、testing-library経由で

import { render } from '@testing-library/svelte'
import Button from '../my/Button.svelte'

render(
  Button,
  { props: { ... } },
  { slots: { default: OtherComponent } }
)

みたいなことができたのですが、3になって出来なくなった模様。参考はこちら

で、slotがこちらの自由にできないとなると、他のいろんなテストも不自由な感じになってくるわけで、この不自由の中でテストなんか書きたくないわけです。つーわけでもうテスト用にコンポーネント書いちゃえばいいんじゃないのっていう話。

<!-- ButtonTest.svelte -->

<script>
  import Button from '../../my/Button.svelte'

  let count = 0

  function handleClick() {
    count++
  }
</script>

<Button on:click="{handleClick}">Push</Button>
<span>count == {count}</span>
// Button.test.js

import '@testing-library/jest-dom/extend-expect'
import { render, fireEvent } from '@testing-library/svelte'
import ButtonTest from './ButtonTest.svelte'

test('shows slot text', () => {
  const { getByText } = render(ButtonTest, {})

  expect(getByText('Push')).toBeInTheDocument()
})

test('handles click', async () => {
  const { getByText } = render(ButtonTest, {})
  const button = getByText('Push')

  await fireEvent.click(button)

  expect(getByText('count == 1')).toBeInTheDocument()
})

テストライブラリのAPI何回調べても必ず忘れるので、テストコード側は簡単なことだけやってればいいようにしてます。

もうちょっと整理して、テスト用のコンポーネントにするんじゃなくて、Storybookから読んでもいいようにするのもアリなのかなと思ったり思ってなかったり。

あと関係ないんですが、開発者のフルスタックフレームワーク離れが進んで小さなパッケージを選んで組み合わせる流れがあるのに、テストはこれまでのお茶会が終わってjest入れとけばええんやみたいな空気が出てきてるの、不思議な感じがしています。