Security News
tea.xyz Spam Plagues npm and RubyGems Package Registries
Tea.xyz, a crypto project aimed at rewarding open source contributions, is once again facing backlash due to an influx of spam packages flooding public package registries.
shadow-dom-testing-library
Advanced tools
Readme
Currently, DOM-testing-library does not support checking
shadow roots for elements. This can be troublesome when
you're looking for something with a "button"
that's
nested inside a shadowRoot.
https://github.com/testing-library/dom-testing-library/issues/413
https://github.com/Westbrook/dom-testing-library
testing-library__dom
is a hard fork of DOM testing
library which presents its own set of challenges.
shadow-dom-testing-library looks to augment the existing
functionality.
Make sure you are using a library which supports rendering shadow roots. For Jest users, this means ensuring you have JSDOM >= 16.2 and Jest >= 26.2
npm install -D shadow-dom-testing-library
// my-button.jsx
export default () => (
<sl-button>I get wrapped by a button in the shadowRoot!</sl-button>
);
// my-button.test.jsx
import { render } from "@testing-library/react";
import { screen } from "shadow-dom-testing-library";
import Button from "./my-button";
test("Find the button in the shadow root", async () => {
render(<Button />);
const btn = await screen.findByShadowRole("button");
expect(btn).toBeInTheDocument();
});
All queries found here: https://testing-library.com/docs/queries/about/#priority are implemented with a "Shadow" prefix prior to the query type.
import { render } from "@testing-library/react"
import { getByShadowRole, findByShadowLabelText, queryAllByShadowTitle } from "shadow-dom-testing-library"
test("Find the button", () => {
const { container } = render(<Button />)
getByShadowRole(container, "button")
await findByShadowLabelText(container, /Car Manufacturer/i)
queryAllByShadowTitle(container, "delete")
})
Shadow dom testing library ships its own "screen" that
you're familiar with. It has all the <ByShadow>
functions prebound
to the document.
import { render } from "@testing-library/react"
import { screen } from "shadow-dom-testing-library"
test("Lets test some rendering", () => {
render(<Button />)
screen.getByShadowRole("button")
await screen.findByShadowLabelText(/Car Manufacturer/i)
screen.queryAllByShadowTitle("delete")
})
In addition, every <ByShadow>
function also accepts a
"shallow" option. The shallow option means to only go 1
shadowRoot deep. Perhaps in the future a "recurseDepth"
will be implemented to specify shadowRoot depth recursion.
import { render } from "@testing-library/react"
import { screen, getByShadowRole } from "shadow-dom-testing-library"
test("Lets test some rendering", () => {
render(<Button />)
getByShadowRole(document, "button", { shallow: true })
await screen.findByShadowLabelText(/Car Manufacturer/i, { shallow: true })
screen.queryAllByShadowTitle("delete", { shallow: true })
})
Shadow DOM testing library also ships its own
"deepQuerySelector"
and "deepQuerySelectorAll"
functions
for if you need more fine-grained access to the DOM.
import {
deepQuerySelector,
deepQuerySelectorAll,
} from "shadow-dom-testing-library";
const elements = deepQuerySelectorAll(document, "my-button");
const element = deepQuerySelector(document, "my-button", { shallow: true });
A within
function is exported to provide the <ByShadow>
queries
bound to a particular container element.
import { render } from "@testing-library/react";
import { screen, within } from "shadow-dom-testing-library";
test("Lets test some rendering", () => {
render(<ComplicatedControl />);
const fieldGroup = screen.getByShadowRole("group");
const nameInput = within(fieldGroup).getByShadowRole("textbox", {
name: "foobar",
});
});
Be careful with the shadowQueries and deepQueries. These functions recurse through every shadow root which can easily lead to unintended elements being found in your tests.
Also, this library is very new, use with caution. Feel free to report any issues.
Recursing through the Shadow DOM can be expensive if you
render a large number of elements in an element. Benchmarks
have not been measured, but it will easily be much worse
than a regular querySelector
call.
Shadow
queries will work for both Light DOM and for
Shadow DOM elements. For example you can search for a
"button" in the Light DOM.
function SimpleButton() {
const [count, setCount] = React.useState(0);
return <button onClick={() => setCount(count + 1)}>{count}</button>;
}
import { screen } from "shadow-dom-testing-library";
test("Regular buttons should also work with shadow query", async () => {
render(<SimpleButton />);
fireEvent.click(await screen.findByRole("button"));
const el = await screen.findByText(/1/);
expect(el).toBeInTheDocument();
});
Shadow-dom-testing-library supports serializing shadow doms. To do so, it ships its own "debug" function attached to the screen.
import { screen, render } from "shadow-dom-testing-library";
test("Debug", () => {
render(<my-element />);
screen.debug();
});
// Calling debug directly
import { debug, render } from "shadow-dom-testing-library";
test("Debug", () => {
render(<my-element />);
debug();
});
// Changing indentation
import { screen, render } from "shadow-dom-testing-library";
test("Debug", () => {
render(<my-element />);
debug(document.documentElement, undefined, { indent: 4 });
});
// Changing max depth
import { screen, render } from "shadow-dom-testing-library";
test("Debug", () => {
render(<my-element />);
debug(document.documentElement, undefined, {
// default is 7000.
maxDepth: 100,
});
});
This is the equivalent of logDOM
from "@testing-library/dom"
logShadowDOM
will log to the console the state of the DOM
and internally calls prettyShadowDOM
. This is called via screen.debug()
import { logShadowDOM } from "shadow-dom-testing-library";
logShadowDOM(element, maxLength, options); // void; calls console.log()
This is the equivalent of prettyDOM
from "@testing-library/dom". This is called by logShadowDOM
.
prettyShadowDOM
returns string | false
and does not automatically log to the console.
This is useful for custom error messages for elements.
import { prettyShadowDOM } from "shadow-dom-testing-library";
prettyShadowDOM(element, maxLength, options); // => string | false
Perhaps you don't want the extended screen. That's fine. To import just the shadowQueries you can do so like this:
import { shadowQueries } from "shadow-dom-testing-library";
test("findByShadowRole", async () => {
render(<Button />);
const btn = await shadowQueries.findByShadowRole("button");
expect(btn).toBeInTheDocument();
});
You could also use this method to extend your own screen.
import { shadowQueries } from "shadow-dom-testing-library";
import { screen as DOMScreen } from "@testing-library/dom";
const screen = {
...DOMScreen,
...shadowQueries,
};
screen.getByShadowRole("button");
import { screen, shadowQueries } from "shadow-dom-testing-library";
const btn = await screen.findByShadowRole<HTMLButtonElement>("button");
const btn = shadowQueries.getByShadowRole<HTMLButtonElement>("button");
FAQs
An extension of DOM-testing-library to provide hooks into the shadow dom
The npm package shadow-dom-testing-library receives a total of 36,857 weekly downloads. As such, shadow-dom-testing-library popularity was classified as popular.
We found that shadow-dom-testing-library demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 2 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
Tea.xyz, a crypto project aimed at rewarding open source contributions, is once again facing backlash due to an influx of spam packages flooding public package registries.
Security News
As cyber threats become more autonomous, AI-powered defenses are crucial for businesses to stay ahead of attackers who can exploit software vulnerabilities at scale.
Security News
UnitedHealth Group disclosed that the ransomware attack on Change Healthcare compromised protected health information for millions in the U.S., with estimated costs to the company expected to reach $1 billion.