Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Component Testing with WebdriverIO

Component Testing with WebdriverIO

With more frontend frameworks on the rise web component testing becomes a crucial part of everyones testing stack. It allows to test various features of a single component of your UI and can help to reduce the amount of e2e around it that usually would run slower.

There are already many component testing tools available but almost all of them miss an important feature: running the test in an actual browser. While one might argue that running test in a virtual DOM is fine for testing why not just run them in the browser if you can. With WebdriverIO v8 and its new browser runner capabilities, you can now execute unit or component tests directly in the browser with no complicated set-up required and use the power of the WebDriver protocol to seamlessly interact with them, as a user would do.

In this session, Christian Bromann, Founding Engineer at Stateful, will tell you all about the new browser runner capabilities and will show case hands on live demos testing components in Vue, Svelte, React or Preact. Be amazed as component testing has never been so easy before!

Christian Bromann

March 29, 2023
Tweet

More Decks by Christian Bromann

Other Decks in Technology

Transcript

  1. Holà 👋 I am Christian! Lead maintainer of the WebdriverIO

    Project. Cross Council Project Member at OpenJS Foundation Open Source and Open Standard Advocate Working with the awesome folks over at @bromann | mastodon.social/@bromann
  2. Contents 01 What are Web Components? 🧱 What are Web

    Components and why do they matter? How do they look like when using React, Svelte, Vue etc.? 02 Testing Principles 📜 How can we improve the stability of our tests and increase test coverage by shifting to smaller test units? 03 Status Quo 📏 What are people already using today and why the heck should I care? 04 WebdriverIO Setup 🛠 How to get started with WebdriverIO and component / unit testing in my project? 05 Live Coding 󰳕 Let’s see WebdriverIO component tests in action and check out features like mocking to test coverage reporting. 06 What’s Next? 🚀 An outlook into the WebdriverIO roadmap in regards to web-component testing @bromann | mastodon.social/@bromann
  3. What are Web Components? 🧱 What are Web Components and

    why do they matter? How do they look like when using React, Svelte, Vue etc.?
  4. <template id="hello-world"> <style> p { color: #00B56C } </style> <p>

    Hello <slot></slot>! </p> </template> <script type="module"> class HelloWorld extends HTMLElement { connectedCallback() { const shadow = this.attachShadow({ mode: 'closed' }) const template = document.getElementById('hello-world') shadow.append(template.content.cloneNode(true)); } } customElements.define('hello-world', HelloWorld); </script> <p>Hello World!</p> <hello-world>Selenium Conf</hello-world> @bromann | mastodon.social/@bromann
  5. <script type="module"> import { LitElement, html, css } from "https://esm.sh/[email protected]";

    class HelloWorld extends LitElement { static get styles() { return css`p { color: #00B56C }`; } render () { return html` <p> Hello <slot></slot>! </p> ` } } customElements.define('hello-world', HelloWorld); </script> <p>Hello World!</p> <hello-world>Selenium Conf</hello-world> @bromann | mastodon.social/@bromann
  6. import React from 'react'; import ReactDOM from 'react-dom/client'; export function

    HelloWorld(props) { return ( <p> Hello {props.children} </p> ); } export function App(props) { return (<HelloWorld>Selenium Conf</HelloWorld>) } ReactDOM.createRoot( document.querySelector('#root') ).render(<App />) @bromann | mastodon.social/@bromann
  7. Testing Principles 📜 How can we improve the stability of

    our tests and increase test coverage by shifting to smaller test units?
  8. The Testing Trophy Source: https://kentcdodds.com/blog/the-testing-trophy-and-testing-classifications End to End A helper

    robot that behaves like a user to click around the app and verify that it functions correctly. Integration Verify that several units work together in harmony. Unit Verify that individual, isolated parts work as expected. Static Catch typos and type errors as you write the code. High Confidence Low Confidence Slow Execution Fast Execution
  9. “Jest is a JavaScript test runner that lets you access

    the DOM via jsdom. While jsdom is only an approximation of how the browser works, it is often good enough for testing React components.” reactjs.org @bromann | mastodon.social/@bromann
  10. JSDOM Caveats • Interactions with components can only be imitated

    via JavaScript • Missing Web APIs ◦ Module scripts (ESM) ◦ Fetch API ◦ CORS ◦ … • Canvas support requires additional dependencies and has limitations • May behave different than Web APIs implemented in actual browsers • No element pseudo states, e.g. :hover or :active @bromann | mastodon.social/@bromann
  11. 🙈🙉 🙊 .btn { visibility: hidden } ❌ Button Click

    Fails Button Clicked @bromann | mastodon.social/@bromann
  12. 🙈🙉 🙊 .btn { height: 0px } ❌ Button Click

    Fails Button Clicked @bromann | mastodon.social/@bromann
  13. 🙈🙉 🙊 .forgotEmailOrPassword { transform: translateY(-50px) } ❌ Button Click

    Fails Button Clicked @bromann | mastodon.social/@bromann
  14. 🙈🙉 🙊 .forgotEmailOrPassword { transform: translateX(10000px) } ❌ Button Click

    Fails Button Clicked ⁉ @bromann | mastodon.social/@bromann
  15. import { render } from '@testing-library/react' import { mock, fn

    } from '@wdio/browser-runner' // or import { vi } from 'vitest' const mock = vi.mock const fn = vi.fn import { InstantSearchComponent } from './InstantSearch' mock('algoliasearch/lite', () => ({ default: fn().mockReturnValue({ search: fn().mockImplementation(async () => { const fixture = await import('./__fixtures__/algolia.json') return Promise.resolve(fixture) }), searchForFacetValues: fn(), addAlgoliaAgent: fn(), clearCache: fn() }) })) mock('../constants', () => ({ HEADING: 'mocked out' })) describe('InstantSearch Component', () => { before(() => { // render component render(<InstantSearchComponent />) }) it('...', async () => { // ... }) }) Mocking ❌ Dependencies Modules @bromann | mastodon.social/@bromann
  16. ❌ @bromann | mastodon.social/@bromann Hidden Element Zero Height Overlaying Element

    Out of Viewport Support Scroll Action Support Pinch Zoom Support Mocking ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌ ❌ Overview
  17. WebdriverIO Setup 🛠 How to get started with WebdriverIO and

    component / unit testing in my project?
  18. Live Coding 󰳕 Let’s see WebdriverIO component tests in action

    and check out features like mocking to test coverage reporting. https://github.com/christian-bromann/seconf-2023-demo
  19. • Improved mocking capabilities / fixing known issues • Support

    for more testrunner, e.g. Jasmine or Cucumber • Snapshot testing support for images and DOM nodes const component = render(<LoginComponent />) await expect($(component)).toMatchSnapshot() • Improve support for more frameworks, e.g. AngularJS • What else? @bromann | mastodon.social/@bromann Component Testing with WebdriverIO