エンドツーエンドのテスト
E2Eテストは、実際のブラウザーでコンポーネントを検証します。たとえば、 my-componentにX属性がある場合、子コンポーネントはテキストYをレンダリングし、イベントZを受信することを期待します。レンダリングテストにPuppeteerを使用することにより(ブラウザの動作をシミュレートするノード環境ではなく)、より良い結果を得るために、エンドツーエンドのテストを実際のブラウザ内で実行できます。
ステンシルは、JestおよびPuppeteerのテストに役立つ多くのユーティリティ関数を提供します。たとえば、コンポーネントのシャドウdomは、Puppeteer上に構築されたStencilユーティリティ関数を使用してクエリおよびテストできます。テストは、模擬HTMLコンテンツを提供できるだけでなく、Puppeteerが開いてStencilの開発サーバーでテストできるアプリのURLにアクセスすることもできます。
エンドツーエンドのテストでは、テストを実際に実行する前に、新しいビルド、dev-server、およびpuppeteerブラウザーインスタンスを作成する必要があります。追加されたビルドの複雑さにより、 stenciltestコマンドはビルド要件を事前に整理することができます。
E2Eテストを実行するには、 stencil test--e2eを実行します。デフォルトでは、 .e2e.tsで終わるファイルが実行されます。
ステンシルのE2Eテストは、次のAPIで提供され、 @stencil/core/testingから入手できます。 ほとんどのメソッドは非同期であり、Promisesを返します。 asyncとawaitを使用して、テストを整理します。
newE2EPage:新しいE2EPageオブジェクトをインスタンス化するには、各テストの開始時に呼び出す必要がありますE2EPageは、テストの作成を簡素化するためのPuppeteerのラッパーユーティリティです。E2EPageのいくつかの便利なメソッドは次のとおりです。setContent(html: string):ページのコンテンツを設定します。 これは、テスト対象のコンポーネントのマークアップを含める場所です。find(selector: string):セレクターに一致する要素を検索します。document.querySelectorに似ています。waitForChanges():StencilとPuppeteerの両方に非同期アーキテクチャがあり、これはパフォーマンスにとって良いことです。 すべての呼び出しは非同期であるため、コンポーネントに変更が加えられたときにawait page.waitForChanges()が呼び出される必要があります。
E2Eテストの例には、次の定型文があります。
import { newE2EPage } from '@stencil/core/testing'; describe('example', () => { it('should render a foo-component', async () => { const page = await newE2EPage(); await page.setContent(`<foo-component></foo-component>`); const el = await page.find('foo-component'); expect(el).not.toBeNull(); }); }); E2Eテストの例
import { newE2EPage } from '@stencil/core/testing'; it('should create toggle, unchecked by default', async () => { const page = await newE2EPage(); await page.setContent(` <ion-toggle class="pretty-toggle"></ion-toggle> `); const ionChange = await page.spyOnEvent('ionChange'); const toggle = await page.find('ion-toggle'); expect(toggle).toHaveClasses(['pretty-toggle', 'hydrated']); expect(toggle).not.toHaveClass('toggle-checked'); toggle.setProperty('checked', true); await page.waitForChanges(); expect(toggle).toHaveClass('toggle-checked'); expect(ionChange).toHaveReceivedEventDetail({ checked: true, value: 'on' }); }); E2Eテストレシピ
ShadowDOMで要素を検索する
「ピアス」セレクター >>>を使用して、コンポーネントのシャドウルート内のオブジェクトをクエリします。
const el = await page.find('foo-component >>> .close-button'); コンポーネントに@Prop()を設定します
page。$ eval(Puppeteer APIの一部)を使用して、Propを設定するか、コンポーネントを操作します。
// create a new puppeteer page // load the page with html content await page.setContent(` <prop-cmp></prop-cmp> `); // select the "prop-cmp" element // and run the callback in the browser's context await page.$eval('prop-cmp', (elm: any) => { // within the browser's context // let's set new property values on the component elm.first = 'Marty'; elm.lastName = 'McFly'; }); // we just made a change and now the async queue need to process it // make sure the queue does its work before we continue await page.waitForChanges(); 外部参照を使用してコンポーネントに@Prop()を設定します
page。$ evalには分離されたスコープがあるため、外部参照を明示的に渡す必要があります。そうしないと、undefinedエラーが発生します。 これは、別のファイルからデータをインポートしたり、同じファイル内の複数のテストでモックデータを再利用したりする場合に役立ちます。
const props = { first: 'Marty', lastName: 'McFly', }; await page.setContent(`<prop-cmp></prop-cmp>`); await page.$eval('prop-cmp', (elm: any, { first, lastName }) => { elm.first = first; elm.lastName = lastName; }, props ); await page.waitForChanges(); コンポーネントで@Method()を呼び出す
const elm = await page.find('method-cmp'); elm.setProperty('someProp', 88); const methodRtnValue = await elm.callMethod('someMethod'); 入力フィールドに入力します
const page = await newE2EPage({ html: ` <dom-interaction></dom-interaction> ` }); const input = await page.find('dom-interaction >>> .input'); let value = await input.getProperty('value'); expect(value).toBe(''); await input.press('8'); await input.press('8'); await input.press(' '); await page.keyboard.down('Shift'); await input.press('KeyM'); await input.press('KeyP'); await input.press('KeyH'); await page.keyboard.up('Shift'); レンダリングされたコンポーネントのテキストを確認する
await page.setContent(` <prop-cmp first="Marty" last-name="McFly"></prop-cmp> `); const elm = await page.find('prop-cmp >>> div'); expect(elm).toEqualText('Hello, my name is Marty McFly'); コンポーネントのHTMLを確認する
shadowRootコンテンツの場合:
expect(el.shadowRoot).toEqualHtml(`<div> <div class=\"nav-desktop\"> <slot></slot> </div> </div>`); }); For non-shadow content:
expect(el).toEqualHtml(`<div> <div class=\"nav-desktop\"> <slot></slot> </div> </div>`); }); CD/CIでのe2eテストの自動化に関する警告
かなり一般的な方法であるため、継続的デプロイ/統合(CD/CI)システムでエンドツーエンドのテストを自動的に実行することをお勧めします。 ただし、環境によっては、構成を微調整する必要がある場合があります。 その場合、 stencil.config.tsファイルのconfigオブジェクトには、パイプラインでヘッドレスChromeが実際にどのように使用されるかを変更するパラメーターを受け入れる testing属性があります。
Gitlab CI環境で必要になる可能性のある構成の例:
export const config: Config = { namespace: 'Foo', testing: { /** * Gitlab CI doesn't allow sandbox, therefor this parameters must be passed to your Headless Chrome * before it can run your tests */ browserArgs: ['--no-sandbox', '--disable-setuid-sandbox'], }, outputTargets: [ { type: 'dist' }, { type: 'www', }, ], }; この問題の可能性について詳しくは、ドキュメントのこの部分を確認してください。
Contributors
Thanks for your interest!
We just need some basic information so we can send the guide your way.