概要

バージョン2.4以降、NightwatchはJSXを使用し、Component Story Format (CSF) サブセットで記述されたReactコンポーネントテストの実行をサポートしています。

Component Story Formatとは

Component Story Format(CSF)は、オープンスタンダードであり、Storybookチームによって、コンポーネントストーリーを作成するための宣言的なモデルとして導入されたES6モジュールに基づいています。

ストーリーは、propsargs、またはテスト機能とともに、コンポーネントのインスタンスである名前付きexportです。コンポーネントテストファイルには、1つ以上のストーリーが含まれています。

ファイル名には拡張子として.jsxまたは.tsxを使用する必要があります。最も単純な形式では、コンポーネントテストは次のようになります

test/sampleTest.jsx
import Form from '../components/Form.jsx';

export default { title: 'Form', component: Form, }
export const FormStory = () => <Form />

上記の例を考慮して、コンポーネントテストの2番目のストーリーを追加しましょう。

test/sampleTest.spec.jsx
import Form from '../components/Form.jsx';

export default { title: 'Form Component', component: Form }
export const EmptyForm = () => <Form />
export const AnotherForm = Object.assign(() => <Form addTask={function(value) { console.log('Add Task', value); }} />, { // additional parameters });

インタラクションテストの追加

各コンポーネントストーリー(つまり、名前付きexport)は、実行する必要があるテストを定義するいくつかの(async)関数プロパティを受け取ります。テスト機能は、次の関数を使用して記述できます

  • play({canvasElement, args}) – DOMコンテキストで実行され、コンポーネントストーリー要素を受け取ります
  • test(browser, {component, result}) – Nodeコンテキストで実行され、Nightwatch apiオブジェクト(browser)を受け取ります。Nightwatch互換の要素インスタンスとしてcomponent要素オブジェクトを受け取ります
  • preRender() – コンポーネントがレンダリングされる前に実行されます
  • postRender() – コンポーネントがレンダリングされた後に実行されます

さらに、コンポーネントレベルのテストフックは、最上位レベルのdefault exportセクションで宣言できます。

下の例では、play()関数は、Testing LibraryのDOMユーティリティを使用しています。

test/sampleTest.spec.jsx
import { fireEvent, within } from '@testing-library/dom';
import Form from '../components/Form.jsx';

export default { title: 'Form Component', component: Form,
// executed before all the individual component stories; runs in Node context async setup(browser) { console.log('global setup hook', browser.capabilities) },
// executed after all the individual component stories; runs in Node context async teardown(browser) { console.log('global teardown hook') },
// executed before each individual component story; runs in Node context async preRender(browser, context) { // context is made of {id, name, title} console.log('preRender', context.id); },
// executed after each individual component story; runs in Node context async postRender(browser, context) { // context is made of {id, name, title} console.log('postRender', context.id); } }
export const AnotherForm = Object.assign(() => <Form addTask={function(value) { console.log('Add Task', value); }} />, { async preRender() {},
async postRender() { console.log('after mount', window); },
async play({canvasElement, args}) { console.log('play function', args);
const root = within(canvasElement); const input = root.getByTestId('new-todo-input');

fireEvent.change(input, { target: { value: 'another one bites the dust' } });
return { fromPlay: input } },
test: async (browser, {component, result}) => { console.log('Result from play', result) await expect(component).to.be.visible;
await expect(component.find('input')).to.have.property('value').equal('another one bites the dust'); } });

静的アセットのロード

コンポーネントを個別にロードする場合、コンポーネントで使用されるスタイルを含むCSSファイルなど、追加の静的アセットをロードする必要があることがよくあります。

(JSX)テストファイルにアセットを直接ロードする以外に、Nightwatchにはこれを実現する2つの方法が用意されています

  1. 現在のプロジェクトにnightwatch/index.jsxファイルを作成する
  2. まったく新しいテストレンダラーファイルを作成し、ViteプラグインrenderPageオプションを使用する

プロジェクト例

Reactで記述され、Viteの上に構築された基本的なTo-doアプリを、ボイラープレートとして使用できるようにまとめました。https://github.com/nightwatchjs-community/todo-reactで確認できます

nightwatch-react-plugin on Github