|
| 1 | +--- |
| 2 | +title: 'Angular: Vitest Browser Modeへの移行とTesting Library Custom Matcher' |
| 3 | +slug: 'angular-vitest-browser-mode-testing-library' |
| 4 | +icon: '' |
| 5 | +created_time: '2026-01-30T14:03:00.000Z' |
| 6 | +last_edited_time: '2026-01-30T14:15:00.000Z' |
| 7 | +tags: |
| 8 | + - 'Angular' |
| 9 | + - 'Testing' |
| 10 | + - 'Vitest' |
| 11 | + - 'Testing Library' |
| 12 | +published: true |
| 13 | +locale: 'ja' |
| 14 | +category: 'Tech' |
| 15 | +canonical_url: 'https://zenn.dev/lacolaco/articles/angular-vitest-browser-mode-testing-library' |
| 16 | +notion_url: 'https://www.notion.so/Angular-Vitest-Browser-Mode-Testing-Library-Custom-Matcher-2e93521b014a80579534cd937331ad0b' |
| 17 | +features: |
| 18 | + katex: false |
| 19 | + mermaid: false |
| 20 | + tweet: false |
| 21 | +--- |
| 22 | + |
| 23 | +## 結論 |
| 24 | + |
| 25 | +VitestのBrowser Modeで使う`expect` APIにははじめからDOM要素向けカスタムマッチャが組み込まれているので `@testing-library/jest-dom` は必要ない。 |
| 26 | + |
| 27 | +https://vitest.dev/api/browser/assertions.html |
| 28 | + |
| 29 | +## Vitest移行とTesting Library |
| 30 | + |
| 31 | +Angularプロジェクトのユニットテスト環境をAngular CLI公式のVItestサポートに移行しても、Angular Testing Libraryは変わらず使える。いまとなってはTesting LibraryなしでAngularコンポーネントのテストを書くことは考えたくない。 |
| 32 | + |
| 33 | +https://testing-library.com/docs/angular-testing-library/intro/ |
| 34 | + |
| 35 | +Testing Libraryを使ってテストを書く場合、アサーション用のカスタムマッチャを導入しているケースのほうが多いだろう。`toBeVisible`や`toBeDisabled`のようにDOM特有のアサーションを簡単にしてくれる。 |
| 36 | + |
| 37 | +```typescript |
| 38 | +expect(screen.queryByTestId('not-empty')).not.toBeEmptyDOMElement() |
| 39 | +expect(screen.getByText('Visible Example')).toBeVisible() |
| 40 | +``` |
| 41 | + |
| 42 | +Karma/Jasmineであれば`@testing-library/jasmine-dom` 、Jestであれば `@testing-library/jest-dom` をインストールして、テストセットアップファイルでカスタムマッチャの登録をする必要がある。VitestのNode.js実行モードで同じことをするには、`@testing-library/jest-dom/vitest`をインポートすればよい。Jest版と同じカスタムマッチャをVitest互換で提供してくれる。 |
| 43 | + |
| 44 | +[https://github.com/testing-library/jest-dom/blob/main/README.md#with-vitest](https://github.com/testing-library/jest-dom/blob/main/README.md#with-vitest) |
| 45 | + |
| 46 | +## Vitest Browser ModeのAssertion |
| 47 | + |
| 48 | +しかし、AngularのユニットテストをVitestに移行したうえで、実行環境をNode.jsではなくBrowser Modeにした場合は事情が変わる。 |
| 49 | + |
| 50 | +https://vitest.dev/guide/browser/ |
| 51 | + |
| 52 | +Browser Modeで使えるexpectには、はじめから`@testing-library/jest-dom` と同等の組み込みマッチャが存在する。なので何も導入する必要がない。 |
| 53 | + |
| 54 | +> Vitest provides a wide range of DOM assertions out of the box forked from @testing-library/jest-dom library with the added support for locators and built-in retry-ability. |
| 55 | +
|
| 56 | +[https://vitest.dev/api/browser/assertions.html](https://vitest.dev/api/browser/assertions.html) |
| 57 | + |
| 58 | +さらにカスタムマッチャだけでなく、`expect.element`というAPIによって、タイミングによってflakyになりがちなDOM要素の取得を自動リトライしてくれる機能もある。これまではTesting Libraryの`waitFor`などで工夫する必要があったが、これからは`expect.element`を使ってもいいだろう。 |
| 59 | + |
| 60 | +```typescript |
| 61 | +import { expect, test } from 'vitest' |
| 62 | +import { page } from 'vitest/browser' |
| 63 | + |
| 64 | +test('error banner is rendered', async () => { |
| 65 | + triggerError() |
| 66 | + |
| 67 | + // This creates a locator that will try to find the element |
| 68 | + // when any of its methods are called. |
| 69 | + // This call by itself doesn't check the existence of the element. |
| 70 | + const banner = page.getByRole('alert', { |
| 71 | + name: /error/i, |
| 72 | + }) |
| 73 | + |
| 74 | + // Vitest provides `expect.element` with built-in retry-ability |
| 75 | + // It will repeatedly check that the element exists in the DOM and that |
| 76 | + // the content of `element.textContent` is equal to "Error!" |
| 77 | + // until all the conditions are met |
| 78 | + await expect.element(banner).toHaveTextContent('Error!') |
| 79 | +}) |
| 80 | +``` |
| 81 | + |
| 82 | +## Angular CLIのVitest Browser Modeサポート |
| 83 | + |
| 84 | +Angular v21.0アップデート時点ではBrowser Modeへのマイグレーションは用意されていなかったが、v21.2に向けてサポートが入ってきている。 |
| 85 | + |
| 86 | +https://github.com/angular/angular-cli/commit/f80db6fb714aa326f6ed03a8a51090ca59ad0955 |
| 87 | + |
| 88 | +このコミットは`ng add @vitest/browser-playwright` のように、`ng add`コマンドでVitestのBrowser Mode用モジュールを導入できるようにするものだ。ただパッケージをインストールするだけでなく、設定ファイルの自動セットアップをしてくれる。あらかじめVitest実行環境に移行できている必要はあるが、`ng new`で作成した直後のプロジェクトからあっという間にBrowser Modeに移行できるだろう。 |
| 89 | + |
| 90 | +https://angular.dev/guide/testing/migrating-to-vitest |
| 91 | + |
| 92 | +Karma/Jasmine環境からVitestへの移行は既存テストのJasmine依存が強いほど大変ではあるが、しかしひと手間だけ我慢して一気にBrowser Modeまで導入してしまうことを個人的にはおすすめしたい。実行環境を実ブラウザのまま維持したほうが、JSDOMとの間の互換性の心配をしなくていいからだ。逆にもともとJest環境だった場合はBrowser Modeには移行せずデフォルトのNode.jsモードのままでいいだろう。 |
| 93 | + |
| 94 | +## まとめ |
| 95 | + |
| 96 | +Vitest Browser Modeへの移行により、`@testing-library/jest-dom`のような追加パッケージが不要になり、DOM要素向けカスタムマッチャが標準で使える。また`expect.element`による自動リトライ機能も組み込まれている。Angular v21.2以降では`ng add`コマンドによる導入が可能になる予定だ。 |
| 97 | + |
| 98 | +Karmaが非推奨だからという消極的な理由だけでなく、モダンな開発者体験の恩恵を受けるためにも、なるべく多くのAngularプロジェクトでVitestに移行してもらいたい。 |
| 99 | + |
0 commit comments