Jestのユニットテストで、Stripe Appsでのボタンクリックやフォーム操作等の操作をテストする

この記事は、[Stripe Apps を25日間紹介し続ける Advent Calendar 2022](https://qiita.com/advent-calendar/2022/stripe-apps) 14日目の記事です。

![スクリーンショット 2022-11-24 17.56.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2366300/e0261865-0418-daa2-423a-5f4d70558b1b.png)

Jestを使うことで、Stripe Appsで開発したアプリのテストも、ReactやTypeScriptでのアプリ開発とほぼ同様に実装できます。

今回は、テストケースのうち、ボタンクリックなどのイベント処理について紹介します。

## `trigger`を利用してイベントを発火する

テストには、`render`でコンポーネントをレンダリングした際、戻り値として取得した`wrapper`を利用します。

```typescript
const { wrapper } = render(<App />);
```

`wrapper`に対して`find`でターゲットのコンポーネントを特定します。

```typescript
const button = wrapper.find(Button)
```

要素が存在する場合、`trigger`を利用してイベントを発火できます。

```typescript
button!.trigger("onPress", "pressed")
```


これを使うと、次のような「ボタンをクリックすると、表示が切り替わる」ケースのテストができます。

**src/views/App.tsx**
```tsx
import { Box,　Button } from "@stripe/ui-extension-sdk/ui"
import { FC, useState　} from 'react'

export const CustomButton: FC = () => {
  const [label, setLabel] = useState("Press it")
  return (
    <>
      <Box>{label}</Box>
      <Button
        onPress={() => {
          console.log(true)
          setLabel("Pressed")
        }}
      >
        {label}
      </Button>
    </>
  )
}
```

**src/views/App.test.tsx**
```typescript
import { render, getMockContextProps } from "@stripe/ui-extension-sdk/testing"
import { Box, Button } from "@stripe/ui-extension-sdk/ui"
import { CustomButton } from "./App"

describe("CustomButton", () => {
  it("Clicked button", async () => {
    const {wrapper} = render(<CustomButton {...getMockContextProps()} />)
    wrapper.find(Button)?.trigger("onPress")
    expect(wrapper.find(Box)).toContainText("Pressed")
  })
})
```

## イベント内容を指定して`trigger`を実行する

`TextField`など、ユーザーが入力した情報を利用する要素の場合、`trigger`の第二引数を利用します。

今度は、Buttonの代わりに`TextField`を利用した要素を試しましょう。

**src/views/App.tsx**

```tsx
import { Box,　TextField } from "@stripe/ui-extension-sdk/ui"
import { FC, useState　} from 'react'

export const CustomTextField: FC = () => {
  const [label, setLabel] = useState("Press it")
  return (
    <>
      <Box>{label}</Box>
      <TextField
        onChange={e => {
          setLabel(e.target.value)
        }}
      />
    </>
  )
}
```

この要素では、`e.target.value`を利用します。

**src/views/App.test.tsx**に、`trigger`の第二引数を利用して、値を設定しましょう。

```typescript
import { render, getMockContextProps } from "@stripe/ui-extension-sdk/testing"
import { Box, Button } from "@stripe/ui-extension-sdk/ui"
import { CustomTextField } from "./App"

describe("CustomTextField", () => {
  it("Change text field input", async () => {
    const {wrapper} = render(<App {...getMockContextProps()} />);
    expect(wrapper.find(Box)).toContainText("Press it")
    const textField = wrapper.find(TextField)
    textField?.trigger("onChange", {
        target: {
            value: "hello"
        }
    })
    expect(wrapper.find(Box)).toContainText("hello")
  })
})
```

このようにして、アプリ内のさまざまなイベント処理をテストできます。

## `find`の第二引数で、要素を絞り込む

`TextField`など、複数配置することのあるコンポーネントをテストする場合、`find`の第二引数でターゲットを絞り込むこともできます。

次の例では、`TextField`を２つ利用しています。

```tsx
export const CustomForm: FC = () => {
  const [label, setLabel] = useState("Press it")
  const [name, setName] = useState("Press it")
  return (
    <>
      <TextField
        label="Name"
        onChange={e => {
          setName(e.target.value)
        }}
      />
      <TextField
        label="Label"
        onChange={e => {
          setLabel(e.target.value)
        }}
      />
      <Box>{label}: {name}</Box>
    </>
  )
}
```

そのため、テストコードでは「どの`TextField`を操作したか」を明らかにする必要があります。

この例では、`find`で`TextField`の`label`パラメータを利用して絞り込みを行います。

```typescript
    const {wrapper} = render(<App {...getMockContextProps()} />)
    const textField = wrapper.find(TextField, {
        label: "Name"
    })
    textField?.trigger("onChange", {
        target: {
            value: "hello"
        }
    })
    expect(wrapper.find(Box)).toContainText("hello")

```


## Stripe Appsひとりアドベントカレンダー 2022

今年ベータリリースされたばかりのStripe Appsは、まだ日本語の情報が多くありません。

そこでQiita Advent Calendar 2022にて、毎日Stripe Appsについての情報を投稿します。

https://qiita.com/advent-calendar/2022/stripe-apps

ノーコードで利用する方法や、開発するためのTipsなども紹介予定ですので、ぜひ購読をお願いします。