diff --git a/docs/main.css b/docs/main.css index 06bda39b54..8e566b44d6 100644 --- a/docs/main.css +++ b/docs/main.css @@ -291,28 +291,14 @@ header.band h1 { color: var(--pf-theme--color--white, #fff); } -.example-preview.pf-background-image pf-v5-background-image { +.example-preview.pf-v6-background-image pf-v6-background-image { position: absolute; z-index: -1; - top: 0; - left: 0; -} - -.example-preview.pf-background-image pf-v5-background-image::part(container) { - position: relative; -} - -.example-preview.pf-background-image pf-v5-background-image, -.example-preview.pf-background-image pf-v5-background-image::part(container) { + inset: 0; height: 100%; width: 100%; } -.example-preview.pf-background-image pf-v5-background-image::part(container)::after { - position: absolute; - background-size: cover; -} - section.api.band.api-properties dl { padding: var(--pf-global--spacer--md, 1rem); background-color: var(--pf-global--BackgroundColor--100, #fff); diff --git a/docs/main.mjs b/docs/main.mjs index 2664df6bb8..623d1898f0 100644 --- a/docs/main.mjs +++ b/docs/main.mjs @@ -4,7 +4,7 @@ import '@patternfly/elements/pf-v5-accordion/pf-v5-accordion.js'; import '@patternfly/elements/pf-v5-alert/pf-v5-alert.js'; import '@patternfly/elements/pf-v5-avatar/pf-v5-avatar.js'; import '@patternfly/elements/pf-v5-back-to-top/pf-v5-back-to-top.js'; -import '@patternfly/elements/pf-v5-background-image/pf-v5-background-image.js'; +import '@patternfly/elements/pf-v6-background-image/pf-v6-background-image.js'; import '@patternfly/elements/pf-v5-badge/pf-v5-badge.js'; import '@patternfly/elements/pf-v5-banner/pf-v5-banner.js'; import '@patternfly/elements/pf-v5-button/pf-v5-button.js'; diff --git a/elements/pf-v5-background-image/README.md b/elements/pf-v5-background-image/README.md deleted file mode 100644 index 084b8d4c93..0000000000 --- a/elements/pf-v5-background-image/README.md +++ /dev/null @@ -1,37 +0,0 @@ -# Background Image - -A **background image** allows you to place an image in the background of your page or area of a page. - - -## Installation -Load `` via CDN: - -```html - - - -Or, if you are using [NPM](https://npm.im), install it - -```bash -npm install @patternfly/elements -``` - -Then once installed, import it to your application: - -```js -import '@patternfly/elements/pf-v5-background-image/pf-v5-background-image.js'; -``` - -## Usage - -```html - -``` - -[docs]: https://patternflyelements.org/components/background-image diff --git a/elements/pf-v5-background-image/demo/filter-override.html b/elements/pf-v5-background-image/demo/filter-override.html deleted file mode 100644 index 2656d2dcef..0000000000 --- a/elements/pf-v5-background-image/demo/filter-override.html +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - - - - - - diff --git a/elements/pf-v5-background-image/demo/index.html b/elements/pf-v5-background-image/demo/index.html deleted file mode 100644 index a469b4d92a..0000000000 --- a/elements/pf-v5-background-image/demo/index.html +++ /dev/null @@ -1,18 +0,0 @@ - - - - - diff --git a/elements/pf-v5-background-image/demo/pfbg.jpg b/elements/pf-v5-background-image/demo/pfbg.jpg deleted file mode 100644 index 88ee1f4250..0000000000 Binary files a/elements/pf-v5-background-image/demo/pfbg.jpg and /dev/null differ diff --git a/elements/pf-v5-background-image/demo/pfbg_1200.jpg b/elements/pf-v5-background-image/demo/pfbg_1200.jpg deleted file mode 100644 index 0c0e826257..0000000000 Binary files a/elements/pf-v5-background-image/demo/pfbg_1200.jpg and /dev/null differ diff --git a/elements/pf-v5-background-image/demo/pfbg_576.jpg b/elements/pf-v5-background-image/demo/pfbg_576.jpg deleted file mode 100644 index a0a7fc3cdb..0000000000 Binary files a/elements/pf-v5-background-image/demo/pfbg_576.jpg and /dev/null differ diff --git a/elements/pf-v5-background-image/demo/pfbg_768.jpg b/elements/pf-v5-background-image/demo/pfbg_768.jpg deleted file mode 100644 index af83172425..0000000000 Binary files a/elements/pf-v5-background-image/demo/pfbg_768.jpg and /dev/null differ diff --git a/elements/pf-v5-background-image/demo/pfbg_768@2x.jpg b/elements/pf-v5-background-image/demo/pfbg_768@2x.jpg deleted file mode 100644 index a4ca09cb82..0000000000 Binary files a/elements/pf-v5-background-image/demo/pfbg_768@2x.jpg and /dev/null differ diff --git a/elements/pf-v5-background-image/demo/sibling-content.html b/elements/pf-v5-background-image/demo/sibling-content.html deleted file mode 100644 index 5a5a2221ae..0000000000 --- a/elements/pf-v5-background-image/demo/sibling-content.html +++ /dev/null @@ -1,30 +0,0 @@ - - - -
-

Sibling Content

- Button -
- - - - - - diff --git a/elements/pf-v5-background-image/docs/pf-v5-background-image.md b/elements/pf-v5-background-image/docs/pf-v5-background-image.md deleted file mode 100644 index 0e45547415..0000000000 --- a/elements/pf-v5-background-image/docs/pf-v5-background-image.md +++ /dev/null @@ -1,65 +0,0 @@ -{% renderOverview %} - {% htmlexample class="pf-v5-background-image" %} - - {% endhtmlexample %} - - View the [full screen demo](/components/background-image/demo/). - -{% endrenderOverview %} - -{% band header="Usage" %} - ### Sibling content w/ no filter - {% htmlexample class="pf-v5-background-image" %} - -

Sibling Content

- Button - {% endhtmlexample %} - - View the [full screen demo](/components/background-image/demo/sibling-content/). - - ### Override SVG Filter - - [MDN documentation for ``](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/filter) - - {% htmlexample class="pf-v5-background-image" %} - - - - - - - - {% endhtmlexample %} - - View the [full screen demo](/components/background-image/demo/filter-override/). - -{% endband %} - -{% renderSlots %}{% endrenderSlots %} - -{% renderAttributes %}{% endrenderAttributes %} - -{% renderMethods %}{% endrenderMethods %} - -{% renderEvents %}{% endrenderEvents %} - -{% renderCssCustomProperties %}{% endrenderCssCustomProperties %} - -{% renderCssParts %}{% endrenderCssParts %} diff --git a/elements/pf-v5-background-image/docs/screenshot.png b/elements/pf-v5-background-image/docs/screenshot.png deleted file mode 100644 index f7b9df8e54..0000000000 Binary files a/elements/pf-v5-background-image/docs/screenshot.png and /dev/null differ diff --git a/elements/pf-v5-background-image/pf-v5-background-image.css b/elements/pf-v5-background-image/pf-v5-background-image.css deleted file mode 100644 index c787efe3cf..0000000000 --- a/elements/pf-v5-background-image/pf-v5-background-image.css +++ /dev/null @@ -1,73 +0,0 @@ -:host { - display: flex; - - /** Background image for the element */ - --_background-image: var(--pf-v5-c-background-image--BackgroundImage); -} - -#outer-container { - display: contents; -} - -#container { - padding: 0; - margin: 0; - background-color: transparent; -} - -#container::after { - display: block; - position: fixed; - top: 0; - left: 0; - z-index: -1; - width: 100%; - height: 100%; - content: ""; - /** Background color for the background image */ - background-color: var(--pf-v5-c-background-image--BackgroundColor, var(--pf-global--BackgroundColor--dark-100, #151515)); - background-image: var(--_background-image); - /** SVG filter applied to the background image */ - filter: var(--pf-v5-c-background-image--Filter, url("#image_overlay")); - background-repeat: no-repeat; - background-size: cover; -} - -slot[name="filter"] { - display: none; -} - -slot[part="content"] { - display: block; - position: relative; - z-index: 1; - color: white; -} - -@media screen and (-webkit-min-device-pixel-ratio: 2), (min-resolution: 192dpi) { - #container::after { - /** Background image for 2x DPI screens */ - background-image: var(--pf-v5-c-background-image--BackgroundImage-2x, var(--_background-image-2x, var(--_background-image))); - } -} - -@media screen and (min-width: 576px) { - #container::after { - /** Background image for small screens */ - background-image: var(--pf-v5-c-background-image--BackgroundImage--sm, var(--_background-image-sm, var(--_background-image))); - } -} - -@media screen and (min-width: 576px) and (-webkit-min-device-pixel-ratio: 2), (min-width: 576px) and (min-resolution: 192dpi) { - #container::after { - /** Background image for small screens with 2x DPI */ - background-image: var(--pf-v5-c-background-image--BackgroundImage--sm-2x, var(--_background-image-sm-2x, var(--_background-image))); - } -} - -@media screen and (min-width: 992px) { - #container::after { - /** Background image for large screens */ - background-image: var(--pf-v5-c-background-image--BackgroundImage--lg, var(--_background-image-lg, var(--_background-image))); - } -} diff --git a/elements/pf-v5-background-image/pf-v5-background-image.ts b/elements/pf-v5-background-image/pf-v5-background-image.ts deleted file mode 100644 index f961c31998..0000000000 --- a/elements/pf-v5-background-image/pf-v5-background-image.ts +++ /dev/null @@ -1,115 +0,0 @@ -import { LitElement, html, type TemplateResult } from 'lit'; -import { customElement } from 'lit/decorators/custom-element.js'; -import { queryAssignedElements } from 'lit/decorators/query-assigned-elements.js'; -import { property } from 'lit/decorators/property.js'; - - -import { styleMap, type StyleInfo } from 'lit/directives/style-map.js'; - -import styles from './pf-v5-background-image.css'; - -/** - * A **background image** allows you to place an image in the background of your page or area of a page. - * @summary Allows users to place an image in the background of your page or area of a page. - * @alias Background Image - */ -@customElement('pf-v5-background-image') -export class PfV5BackgroundImage extends LitElement { - static readonly styles: CSSStyleSheet[] = [styles]; - - /** - * The URL for the image shown on mobile - */ - @property({ reflect: true }) src?: string; - - /** - * The image shown on mobile with 2x DPI - */ - @property({ reflect: true, attribute: 'src-2x' }) src2x?: string; - - /** - * The URL for the image shown on small screens (min-width: 576px) - */ - @property({ reflect: true, attribute: 'src-sm' }) srcSm?: string; - - /** - * The URL for the image shown on small screens (min-width: 576px) with 2x DPI - */ - @property({ reflect: true, attribute: 'src-sm-2x' }) srcSm2x?: string; - - /** - * The URL for the image shown on large screens (min-width: 992px) - */ - @property({ reflect: true, attribute: 'src-lg' }) srcLg?: string; - - /** - * Apply SVG Filter to the image - */ - @property({ type: Boolean, reflect: true }) filter = false; - - @queryAssignedElements({ slot: 'filter', selector: 'svg' }) private _svg?: SVGElement[]; - - #svg?: SVGElement; - - #updated = false; - - render(): TemplateResult<1> { - const cssProps = { - '--_background-image': this.src, - '--_background-image-2x': this.src2x, - '--_background-image-sm': this.srcSm, - '--_background-image-sm-2x': this.srcSm2x, - '--_background-image-lg': this.srcLg, - } as StyleInfo; - - Object.entries(cssProps).forEach(([key, value]) => { - // if the value is undefined, remove the css property - if (!value) { - delete cssProps[key]; - } else { - // otherwise, add the value with the url() css function - cssProps[key] = `url(${value})`; - } - }); - - return html` -
- ${!this.filter ? html`` : html` - - - ${(this.#svg && this.#updated) ? this.#svg : html` - - - - - - - - - - - - `} - - `} -
- `; - } - - #onSlotChange() { - const [svg] = this._svg as SVGElement[]; - if (svg) { - this.#svg = svg; - this.#updated = true; - this.requestUpdate(); - } else { - this.#updated = false; - } - } -} - -declare global { - interface HTMLElementTagNameMap { - 'pf-v5-background-image': PfV5BackgroundImage; - } -} diff --git a/elements/pf-v5-background-image/test/pf-background-image.spec.ts b/elements/pf-v5-background-image/test/pf-background-image.spec.ts deleted file mode 100644 index 23acf3b66c..0000000000 --- a/elements/pf-v5-background-image/test/pf-background-image.spec.ts +++ /dev/null @@ -1,102 +0,0 @@ -import { expect, html } from '@open-wc/testing'; -import { createFixture } from '@patternfly/pfe-tools/test/create-fixture.js'; -import { PfV5BackgroundImage } from '@patternfly/elements/pf-v5-background-image/pf-v5-background-image.js'; -import { setViewport } from '@web/test-runner-commands'; - -const example = html` - - -`; - -function isMobile() { - const matches = !!window.matchMedia('(max-width: 575px)').matches; - return matches; -} - -function isTablet() { - const matches = !!window.matchMedia('(min-width: 576px)').matches; - return matches; -} - -function isDesktop() { - const matches = !!window.matchMedia('(min-width: 992px)').matches; - return matches; -} - -describe('', function() { - describe('simply instantiating', function() { - let element: PfV5BackgroundImage; - - it('imperatively instantiates', function() { - expect(document.createElement('pf-v5-background-image')).to.be.an.instanceof(PfV5BackgroundImage); - }); - - it('should upgrade', async function() { - element = await createFixture(html``); - const klass = customElements.get('pf-v5-background-image'); - expect(element) - .to.be.an.instanceOf(klass) - .and - .to.be.an.instanceOf(PfV5BackgroundImage); - }); - - describe('adjusting window size', function() { - describe('when the window is less than 576px wide', function() { - beforeEach(async function() { - await setViewport({ width: 320, height: 500 }); - await element.updateComplete; - expect(isMobile()).to.be.true; - }); - - it('should background image', async function() { - const element = await createFixture(example); - await element.updateComplete; - const container = element.shadowRoot!.querySelector('#container')!; - const afterStyles = getComputedStyle(container, '::after'); - expect(afterStyles.getPropertyValue('background-image')).to.contain('/components/background-image/demo/pfbg.jpg'); - }); - }); - }); - - describe('when the window is less greater then 576px wide', function() { - beforeEach(async function() { - await setViewport({ width: 576, height: 500 }); - await element.updateComplete; - expect(isTablet()).to.be.true; - }); - - it('should background image', async function() { - const element = await createFixture(example); - await element.updateComplete; - const container = element.shadowRoot!.querySelector('#container')!; - const afterStyles = getComputedStyle(container, '::after'); - /* the image sizes are not named based off viewport but their own intrinsic size */ - expect(afterStyles.getPropertyValue('background-image')).to.contain('/components/background-image/demo/pfbg_768.jpg'); - }); - }); - - describe('when the window is less greater then 992px wide', function() { - beforeEach(async function() { - await setViewport({ width: 992, height: 500 }); - await element.updateComplete; - expect(isDesktop()).to.be.true; - }); - - it('should background image', async function() { - const element = await createFixture(example); - await element.updateComplete; - const container = element.shadowRoot!.querySelector('#container')!; - const afterStyles = getComputedStyle(container, '::after'); - /* the image sizes are not named based off viewport but their own intrinsic size */ - expect(afterStyles.getPropertyValue('background-image')).to.contain('/components/background-image/demo/pfbg_1200.jpg'); - }); - }); - }); -}); - diff --git a/elements/pf-v6-background-image/README.md b/elements/pf-v6-background-image/README.md new file mode 100644 index 0000000000..40c1865813 --- /dev/null +++ b/elements/pf-v6-background-image/README.md @@ -0,0 +1,23 @@ +# Background image + +`` places an image in the background of a page or area of a page. + +## Usage + +```html + +``` + +The element uses fixed positioning and sits behind all other content at `z-index: -1`. + +## Divergences from React `BackgroundImage` + +### Not implemented + +| React prop | Notes | +|-------------|-------------------------------------------------| +| `className` | Not needed; shadow DOM provides encapsulation. | + +### Changed API + +No changed APIs. The `src` attribute maps directly to the React `src` prop. diff --git a/elements/pf-v6-background-image/demo/index.html b/elements/pf-v6-background-image/demo/index.html new file mode 100644 index 0000000000..b8cf997b98 --- /dev/null +++ b/elements/pf-v6-background-image/demo/index.html @@ -0,0 +1,11 @@ + + + + + diff --git a/elements/pf-v6-background-image/demo/pf-background.svg b/elements/pf-v6-background-image/demo/pf-background.svg new file mode 100644 index 0000000000..b7fd73f70a --- /dev/null +++ b/elements/pf-v6-background-image/demo/pf-background.svg @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/elements/pf-v6-background-image/docs/pf-v6-background-image.md b/elements/pf-v6-background-image/docs/pf-v6-background-image.md new file mode 100644 index 0000000000..69ce8e71f2 --- /dev/null +++ b/elements/pf-v6-background-image/docs/pf-v6-background-image.md @@ -0,0 +1,21 @@ +{% renderInstallation %} {% endrenderInstallation %} + +{% renderOverview %} + {% htmlexample class="pf-v6-background-image" %} + + {% endhtmlexample %} + + View the [full screen demo](/components/pf-v6-background-image/demo/). + +{% endrenderOverview %} + +{% band header="Usage" %} + ### Basic + {% htmlexample class="pf-v6-background-image" %} + + {% endhtmlexample %} +{% endband %} + +{% renderAttributes %}{% endrenderAttributes %} + +{% renderCssCustomProperties %}{% endrenderCssCustomProperties %} diff --git a/elements/pf-v6-background-image/docs/screenshot.png b/elements/pf-v6-background-image/docs/screenshot.png new file mode 100644 index 0000000000..62852a3cd8 Binary files /dev/null and b/elements/pf-v6-background-image/docs/screenshot.png differ diff --git a/elements/pf-v6-background-image/pf-v6-background-image.css b/elements/pf-v6-background-image/pf-v6-background-image.css new file mode 100644 index 0000000000..18ac1de781 --- /dev/null +++ b/elements/pf-v6-background-image/pf-v6-background-image.css @@ -0,0 +1,37 @@ +:host { + display: block; + position: fixed; + inset-block-start: 0; + inset-inline-start: 0; + z-index: -1; + width: 100%; + height: 100%; + pointer-events: none; +} + +#background { + width: 100%; + height: 100%; + /** Background color shown behind or instead of the image */ + background-color: var(--pf-v6-c-background-image--BackgroundColor, var(--pf-t--global--background--color--primary--default, #292929)); + /** Background image URL, automatically set via the `src` attribute */ + background-image: var(--pf-v6-c-background-image--BackgroundImage, none); + background-repeat: no-repeat; + /** Position of the background image within the viewport */ + background-position: var(--pf-v6-c-background-image--BackgroundPosition, bottom right); + /** Computed background size using clamp() for responsive scaling */ + background-size: var(--pf-v6-c-background-image--BackgroundSize, + clamp( + /** Minimum width for responsive background sizing */ + var(--pf-v6-c-background-image--BackgroundSize--min-width, 200px), + /** Responsive width percentage for background sizing */ + var(--pf-v6-c-background-image--BackgroundSize--width, 60%), + /** Maximum width for responsive background sizing */ + var(--pf-v6-c-background-image--BackgroundSize--max-width, 600px) + ) + ); +} + +:host(:dir(rtl)) #background { + background-position: var(--pf-v6-c-background-image--BackgroundPosition, bottom left); +} diff --git a/elements/pf-v6-background-image/pf-v6-background-image.ts b/elements/pf-v6-background-image/pf-v6-background-image.ts new file mode 100644 index 0000000000..2ebe742f01 --- /dev/null +++ b/elements/pf-v6-background-image/pf-v6-background-image.ts @@ -0,0 +1,36 @@ +import { LitElement, html, type TemplateResult } from 'lit'; +import { customElement } from 'lit/decorators/custom-element.js'; +import { property } from 'lit/decorators/property.js'; +import { styleMap } from 'lit/directives/style-map.js'; + +import styles from './pf-v6-background-image.css'; + +/** + * A **background image** allows you to place a decorative image in the + * background of your page or area of a page. Use this when you want to + * provide a branded backdrop. The element SHOULD be placed as a direct + * child of ``. Users MUST set `src` to display an image. This + * element SHOULD NOT contain interactive content. It is hidden from + * screen readers via `aria-hidden` for WCAG compliance. + * + * @summary Places a decorative image in the background of a page. + */ +@customElement('pf-v6-background-image') +export class PfV6BackgroundImage extends LitElement { + static readonly styles: CSSStyleSheet[] = [styles]; + + /** URL or file path of the background image */ + @property({ reflect: true }) src?: string; + + override render(): TemplateResult<1> { + return html``; + } +} + +declare global { + interface HTMLElementTagNameMap { + 'pf-v6-background-image': PfV6BackgroundImage; + } +} diff --git a/elements/pf-v5-background-image/test/pf-background-image.e2e.ts b/elements/pf-v6-background-image/test/pf-background-image.e2e.ts similarity index 94% rename from elements/pf-v5-background-image/test/pf-background-image.e2e.ts rename to elements/pf-v6-background-image/test/pf-background-image.e2e.ts index 9f7bc5a7a0..812dae8c9b 100644 --- a/elements/pf-v5-background-image/test/pf-background-image.e2e.ts +++ b/elements/pf-v6-background-image/test/pf-background-image.e2e.ts @@ -2,7 +2,7 @@ import { test } from '@playwright/test'; import { PfeDemoPage } from '@patternfly/pfe-tools/test/playwright/PfeDemoPage.js'; import { SSRPage } from '@patternfly/pfe-tools/test/playwright/SSRPage.js'; -const tagName = 'pf-v5-background-image'; +const tagName = 'pf-v6-background-image'; test.describe(tagName, () => { test('snapshot', async ({ page }) => { diff --git a/elements/pf-v6-background-image/test/pf-background-image.spec.ts b/elements/pf-v6-background-image/test/pf-background-image.spec.ts new file mode 100644 index 0000000000..c83695a871 --- /dev/null +++ b/elements/pf-v6-background-image/test/pf-background-image.spec.ts @@ -0,0 +1,94 @@ +import { expect, html } from '@open-wc/testing'; +import { createFixture } from '@patternfly/pfe-tools/test/create-fixture.js'; +import { a11ySnapshot } from '@patternfly/pfe-tools/test/a11y-snapshot.js'; + +import { PfV6BackgroundImage } from '../pf-v6-background-image.js'; + +describe('', function() { + it('imperatively instantiates', function() { + expect(document.createElement('pf-v6-background-image')).to.be.an.instanceof(PfV6BackgroundImage); + }); + + describe('simply instantiating', function() { + let element: PfV6BackgroundImage; + + beforeEach(async function() { + element = await createFixture(html` + + `); + }); + + it('should upgrade', function() { + const klass = customElements.get('pf-v6-background-image'); + expect(element) + .to.be.an.instanceOf(klass) + .and + .to.be.an.instanceOf(PfV6BackgroundImage); + }); + + it('should not have a background image set', function() { + const bg = element.shadowRoot!.querySelector('#background')!; + const styles = getComputedStyle(bg); + expect(styles.getPropertyValue('background-image')).to.equal('none'); + }); + }); + + describe('with src attribute', function() { + let element: PfV6BackgroundImage; + + beforeEach(async function() { + element = await createFixture(html` + + `); + }); + + it('should apply the background image', function() { + const bg = element.shadowRoot!.querySelector('#background')!; + const styles = getComputedStyle(bg); + expect(styles.getPropertyValue('background-image')).to.contain('/test/image.jpg'); + }); + + it('should reflect src attribute', function() { + expect(element.getAttribute('src')).to.equal('/test/image.jpg'); + }); + + it('should use fixed positioning', function() { + const styles = getComputedStyle(element); + expect(styles.position).to.equal('fixed'); + }); + + it('should have a negative z-index', function() { + const styles = getComputedStyle(element); + expect(Number(styles.zIndex)).to.be.lessThan(0); + }); + + it('should update background image when src changes dynamically', async function() { + element.src = '/test/other-image.jpg'; + await element.updateComplete; + const bg = element.shadowRoot!.querySelector('#background')!; + const styles = getComputedStyle(bg); + expect(styles.getPropertyValue('background-image')).to.contain('/test/other-image.jpg'); + }); + + it('should not intercept pointer events', function() { + const styles = getComputedStyle(element); + expect(styles.pointerEvents).to.equal('none'); + }); + + it('should be presentational in the accessibility tree', async function() { + const snapshot = await a11ySnapshot(); + interface A11yNode { + role?: string; + children?: A11yNode[]; + } + function findNode(node: A11yNode): boolean { + if (node.role === 'img') { + return true; + } else { + return node.children?.some(findNode) ?? false; + } + } + expect(findNode(snapshot), 'no img role should exist in the tree').to.be.false; + }); + }); +});