From ae45d01b533b00686e382535b06c00e104eb639e Mon Sep 17 00:00:00 2001 From: Pontus Lundin Date: Mon, 8 Jun 2020 14:49:43 +0200 Subject: [PATCH] feat: add support for custom elements Closes #319 --- src/__tests__/helpers/customElement.js | 35 ++++++++++++++++++++++++++ src/__tests__/helpers/utils.js | 13 +++++++--- src/__tests__/type.js | 24 ++++++++++++++++++ src/type.js | 13 ++++++++-- 4 files changed, 80 insertions(+), 5 deletions(-) create mode 100644 src/__tests__/helpers/customElement.js diff --git a/src/__tests__/helpers/customElement.js b/src/__tests__/helpers/customElement.js new file mode 100644 index 00000000..e3d1c801 --- /dev/null +++ b/src/__tests__/helpers/customElement.js @@ -0,0 +1,35 @@ +const observed = ['value'] + +class CustomEl extends HTMLElement { + static getObservedAttributes() { + return observed + } + + constructor() { + super() + this.attachShadow({mode: 'open'}) + this.shadowRoot.innerHTML = `` + this.$input = this.shadowRoot.querySelector('input') + } + + connectedCallback() { + observed.forEach(name => { + this.render(name, this.getAttribute(name)) + }) + } + + attributeChangedCallback(name, oldVal, newVal) { + if (oldVal === newVal) return + this.render(name, newVal) + } + + render(name, value) { + if (value == null) { + this.$input.removeAttribute(name) + } else { + this.$input.setAttribute(name, value) + } + } +} + +customElements.define('custom-el', CustomEl) diff --git a/src/__tests__/helpers/utils.js b/src/__tests__/helpers/utils.js index 50f5d68d..a8bf0538 100644 --- a/src/__tests__/helpers/utils.js +++ b/src/__tests__/helpers/utils.js @@ -37,14 +37,21 @@ function addEventListener(el, type, listener, options) { el.addEventListener(type, hijackedListener, options) } -function setup(ui) { - const { +function setup(ui, {shadowRootSelector} = {}) { + let hostElement + let { container: {firstChild: element}, } = render(ui) + + if (shadowRootSelector) { + hostElement = element + element = element.shadowRoot.querySelector(shadowRootSelector) + } + element.previousTestData = getTestData(element) const {getEventCalls, clearEventCalls} = addListeners(element) - return {element, getEventCalls, clearEventCalls} + return {element, hostElement, getEventCalls, clearEventCalls} } function addListeners(element) { diff --git a/src/__tests__/type.js b/src/__tests__/type.js index 71ab097b..ea773541 100644 --- a/src/__tests__/type.js +++ b/src/__tests__/type.js @@ -2,6 +2,7 @@ import React, {Fragment} from 'react' import {render, screen} from '@testing-library/react' import userEvent from '..' import {setup} from './helpers/utils' +import './helpers/customElement' it('types text in input', async () => { const {element, getEventCalls} = setup() @@ -23,6 +24,29 @@ it('types text in input', async () => { `) }) +it('types text inside custom element', async () => { + const {element, hostElement, getEventCalls} = setup(, { + shadowRootSelector: 'input', + }) + + await userEvent.type(element, 'Sup', {hostElement}) + expect(getEventCalls()).toMatchInlineSnapshot(` + focus + keydown: S (83) + keypress: S (83) + input: "{CURSOR}" -> "S" + keyup: S (83) + keydown: u (117) + keypress: u (117) + input: "S{CURSOR}" -> "Su" + keyup: u (117) + keydown: p (112) + keypress: p (112) + input: "Su{CURSOR}" -> "Sup" + keyup: p (112) + `) +}) + it('types text in textarea', async () => { const {element, getEventCalls} = setup(