Interactive (DeprecatedLinks.interactions.stories.ts)
Interaction test stories (automated tests, not usage patterns).
Deprecated Links
Story: tests-interactive--deprecated-links · tags: play-fn
<h2 class="oc-headline-200">oc-button-v1 (Deprecated)</h2>
<oc-button-v1 href="/foo" rel="noreferrer" target="_blank">oc-button-v1</oc-button-v1>
<h2 class="oc-headline-200 oc-mt-100">oc-card-v2 (Deprecated)</h2>
<oc-card-v2 href="/foo" rel="noreferrer" target="_blank">oc-card-v2</oc-card-v2>
<h2 class="oc-headline-200 oc-mt-100">oc-energy-label-v1 (Deprecated)</h2>
<oc-energy-label-v1 href="/foo" rel="noreferrer" target="_blank"></oc-energy-label-v1>
<h2 class="oc-headline-200 oc-mt-100">oc-icon-button-v2 (Deprecated)</h2>
<oc-icon-button-v2
href="/foo"
rel="noreferrer"
target="_blank"
icon="almond"
oc-aria-label="oc-icon-button-v2 (screen reader only)"
></oc-icon-button-v2>
<h2 class="oc-headline-200 oc-mt-100">oc-link-v2 (Deprecated)</h2>
<oc-link-v2 href="/foo" rel="noreferrer" target="_blank">oc-link-v2</oc-link-v2>
<h2 class="oc-headline-200 oc-mt-100">oc-logo-v1 (Deprecated)</h2>
<oc-logo-v1
href="/foo"
rel="noreferrer"
target="_blank"
logo="otto"
oc-aria-label="oc-logo-v1 (screen reader only)"
></oc-logo-v1>
<h2 class="oc-headline-200 oc-mt-100">oc-promo-card-v1 (Deprecated)</h2>
<oc-promo-card-v1 href="/foo" rel="noreferrer" target="_blank"
>oc-promo-card-v1
</oc-promo-card-v1>
<h2 class="oc-headline-200 oc-mt-100">oc-row-v2 (Deprecated)</h2>
<oc-row-v2 href="/foo" rel="noreferrer" target="_blank">oc-row-v2 </oc-row-v2>
Story source (TypeScript, verbatim from Storybook)
{
render() {
return html`
<h2 class="oc-headline-200">oc-button-v1 (Deprecated)</h2>
<oc-button-v1 href="/foo" rel="noreferrer" target="_blank">oc-button-v1</oc-button-v1>
<h2 class="oc-headline-200 oc-mt-100">oc-card-v2 (Deprecated)</h2>
<oc-card-v2 href="/foo" rel="noreferrer" target="_blank">oc-card-v2</oc-card-v2>
<h2 class="oc-headline-200 oc-mt-100">oc-energy-label-v1 (Deprecated)</h2>
<oc-energy-label-v1 href="/foo" rel="noreferrer" target="_blank"></oc-energy-label-v1>
<h2 class="oc-headline-200 oc-mt-100">oc-icon-button-v2 (Deprecated)</h2>
<oc-icon-button-v2
href="/foo"
rel="noreferrer"
target="_blank"
icon="almond"
oc-aria-label="oc-icon-button-v2 (screen reader only)"
></oc-icon-button-v2>
<h2 class="oc-headline-200 oc-mt-100">oc-link-v2 (Deprecated)</h2>
<oc-link-v2 href="/foo" rel="noreferrer" target="_blank">oc-link-v2</oc-link-v2>
<h2 class="oc-headline-200 oc-mt-100">oc-logo-v1 (Deprecated)</h2>
<oc-logo-v1
href="/foo"
rel="noreferrer"
target="_blank"
logo="otto"
oc-aria-label="oc-logo-v1 (screen reader only)"
></oc-logo-v1>
<h2 class="oc-headline-200 oc-mt-100">oc-promo-card-v1 (Deprecated)</h2>
<oc-promo-card-v1 href="/foo" rel="noreferrer" target="_blank"
>oc-promo-card-v1
</oc-promo-card-v1>
<h2 class="oc-headline-200 oc-mt-100">oc-row-v2 (Deprecated)</h2>
<oc-row-v2 href="/foo" rel="noreferrer" target="_blank">oc-row-v2 </oc-row-v2>
`;
},
async play({
canvasElement
}) {
const components = Array.from(canvasElement.querySelectorAll("*")).filter(el => el.tagName.startsWith("OC-")) as HTMLAnchorElement[];
await expect(components.length).toBe(8);
await waitFor(function hrefAttribute() {
return components.map(c => expect(c.getAttribute("href"), `${c.tagName}.getAttribute("href")`).toBe("/foo"));
});
await waitFor(function hrefProperty() {
return components.map(c => expect(c.href, `${c.tagName}.href`).toBe(`${window.location.origin}/foo`));
});
await waitFor(function aTagInShadowDom() {
return components.flatMap(c => [expect(c.shadowRoot!.querySelector("a"), `${c.tagName} > a`).toBeTruthy(), expect(c.shadowRoot!.querySelector("a")?.href, `${c.tagName} > a.href`).toBe(`${window.location.origin}/foo`), expect(c.shadowRoot!.querySelector("a")?.rel, `${c.tagName} > a.rel`).toBe(`noreferrer`), expect(c.shadowRoot!.querySelector("a")?.target, `${c.tagName} > a.target`).toBe(`_blank`)]);
});
components.forEach(c => {
c.href = "/bar";
});
await tick();
await waitFor(function hrefPropertyBar() {
return components.map(c => expect(c.href, `${c.tagName}.href`).toBe(`${window.location.origin}/bar`));
});
}
}
Interactive (MultipleInteractions.interactions.stories.ts)
Interaction test stories (automated tests, not usage patterns).
Multiple Interactions
Story: tests-interactive--multiple-interactions · tags: play-fn
<h2 class="oc-headline-200">oc-card-v2</h2>
<oc-card-v2>
<a
slot="primary-action"
href="/foo"
rel="noreferrer"
target="_blank"
aria-label="oc-card-v2 (screen reader only)"
></a>
<div class="oc-m-100">oc-card-v2</div>
<button class="oc-secondary-action oc-m-100 oc-p-100">secondary action</button>
</oc-card-v2>
<h2 class="oc-headline-200 oc-mt-100">oc-promo-card-v1</h2>
<oc-promo-card-v1>
<a
slot="primary-action"
href="/foo"
rel="noreferrer"
target="_blank"
aria-label="oc-promo-card-v1 (screen reader only)"
></a>
<div class="oc-m-100">oc-promo-card-v1</div>
<button class="oc-secondary-action oc-m-100 oc-p-100">secondary action</button>
</oc-promo-card-v1>
Story source (TypeScript, verbatim from Storybook)
{
render() {
return html`
<h2 class="oc-headline-200">oc-card-v2</h2>
<oc-card-v2>
<a
slot="primary-action"
href="/foo"
rel="noreferrer"
target="_blank"
aria-label="oc-card-v2 (screen reader only)"
></a>
<div class="oc-m-100">oc-card-v2</div>
<button class="oc-secondary-action oc-m-100 oc-p-100">secondary action</button>
</oc-card-v2>
<h2 class="oc-headline-200 oc-mt-100">oc-promo-card-v1</h2>
<oc-promo-card-v1>
<a
slot="primary-action"
href="/foo"
rel="noreferrer"
target="_blank"
aria-label="oc-promo-card-v1 (screen reader only)"
></a>
<div class="oc-m-100">oc-promo-card-v1</div>
<button class="oc-secondary-action oc-m-100 oc-p-100">secondary action</button>
</oc-promo-card-v1>
`;
},
async play({
canvasElement
}) {
const components = Array.from(canvasElement.querySelectorAll("*")).filter(el => el.tagName.startsWith("OC-")) as HTMLAnchorElement[];
await expect(components.length).toBe(2);
await expectNoInteractiveElementsInShadowDom(components);
}
}
Interactive (MultipleInteractionsWithButtons.interactions.stories.ts)
Interaction test stories (automated tests, not usage patterns).
Multiple Interactions With Buttons
Story: tests-interactive--multiple-interactions-with-buttons · tags: play-fn
<h2 class="oc-headline-200">oc-card-v2</h2>
<oc-card-v2>
<button slot="primary-action" aria-label="oc-card-v2 (screen reader only)"></button>
<div class="oc-m-100">oc-card-v2</div>
<button class="oc-secondary-action oc-m-100 oc-p-100">secondary action</button>
</oc-card-v2>
<h2 class="oc-headline-200 oc-mt-100">oc-promo-card-v1</h2>
<oc-promo-card-v1>
<button slot="primary-action" aria-label="oc-promo-card-v1 (screen reader only)"></button>
<div class="oc-m-100">oc-promo-card-v1</div>
<button class="oc-secondary-action oc-m-100 oc-p-100">secondary action</button>
</oc-promo-card-v1>
Story source (TypeScript, verbatim from Storybook)
{
render() {
return html`
<h2 class="oc-headline-200">oc-card-v2</h2>
<oc-card-v2>
<button slot="primary-action" aria-label="oc-card-v2 (screen reader only)"></button>
<div class="oc-m-100">oc-card-v2</div>
<button class="oc-secondary-action oc-m-100 oc-p-100">secondary action</button>
</oc-card-v2>
<h2 class="oc-headline-200 oc-mt-100">oc-promo-card-v1</h2>
<oc-promo-card-v1>
<button slot="primary-action" aria-label="oc-promo-card-v1 (screen reader only)"></button>
<div class="oc-m-100">oc-promo-card-v1</div>
<button class="oc-secondary-action oc-m-100 oc-p-100">secondary action</button>
</oc-promo-card-v1>
`;
},
async play({
canvasElement
}) {
const components = Array.from(canvasElement.querySelectorAll("*")).filter(el => el.tagName.startsWith("OC-")) as HTMLAnchorElement[];
await expect(components.length).toBe(2);
await expectNoInteractiveElementsInShadowDom(components);
}
}
Interactive (MultipleInteractionsWithMaskedLinks.interactions.stories.ts)
Interaction test stories (automated tests, not usage patterns).
Multiple interactions with masked links
Story: tests-interactive--multiple-interactions-with-masked-links · tags: play-fn
<h2 class="oc-headline-200">oc-card-v2</h2>
<oc-card-v2 base64-href="L2Zvbw==" rel="noreferrer" target="_blank">
<span slot="primary-action" aria-label="oc-card-v2 (screen reader only)"></span>
<div class="oc-m-100">oc-card-v2</div>
<button class="oc-secondary-action oc-m-100 oc-p-100">secondary action</button>
</oc-card-v2>
<h2 class="oc-headline-200 oc-mt-100">oc-promo-card-v1</h2>
<oc-promo-card-v1 base64-href="L2Zvbw==" rel="noreferrer" target="_blank">
<span slot="primary-action" aria-label="oc-promo-card-v1 (screen reader only)"></span>
<div class="oc-m-100">oc-promo-card-v1</div>
<button class="oc-secondary-action oc-m-100 oc-p-100">secondary action</button>
</oc-promo-card-v1>
Story source (TypeScript, verbatim from Storybook)
{
name: "Multiple interactions with masked links",
render() {
return html`
<h2 class="oc-headline-200">oc-card-v2</h2>
<oc-card-v2 base64-href="L2Zvbw==" rel="noreferrer" target="_blank">
<span slot="primary-action" aria-label="oc-card-v2 (screen reader only)"></span>
<div class="oc-m-100">oc-card-v2</div>
<button class="oc-secondary-action oc-m-100 oc-p-100">secondary action</button>
</oc-card-v2>
<h2 class="oc-headline-200 oc-mt-100">oc-promo-card-v1</h2>
<oc-promo-card-v1 base64-href="L2Zvbw==" rel="noreferrer" target="_blank">
<span slot="primary-action" aria-label="oc-promo-card-v1 (screen reader only)"></span>
<div class="oc-m-100">oc-promo-card-v1</div>
<button class="oc-secondary-action oc-m-100 oc-p-100">secondary action</button>
</oc-promo-card-v1>
`;
},
async play({
canvasElement
}) {
const components = Array.from(canvasElement.querySelectorAll("*")).filter(el => el.tagName.startsWith("OC-")) as HTMLAnchorElement[];
await expect(components.length).toBe(2);
await expectNoInteractiveElementsInShadowDom(components);
await waitFor(function unmaskAndCheckFocus() {
return components.map(c => {
(c.querySelector('[slot="primary-action"]') as HTMLElement).focus();
return expect(document.activeElement, `${c.tagName} > a`).toBe(c.querySelector("a"));
});
});
await waitFor(function aTagHrefShouldBeFoo() {
return components.flatMap(c => [expect(c.querySelector("a")!.href, `${c.tagName} > a`).toBe(`${window.location.origin}/foo`)]);
});
await expectNoInteractiveElementsInShadowDom(components);
}
}
Interactive (SEOMaskedLinks.interactions.stories.ts)
Interaction test stories (automated tests, not usage patterns).
SEO Masked Links
Story: tests-interactive--seo-masked-links · tags: play-fn
<h2 class="oc-headline-200">oc-button-v1</h2>
<oc-button-v1 base64-href="L2Zvbw==" rel="noreferrer" target="_blank"
>oc-button-v1</oc-button-v1
>
<h2 class="oc-headline-200 oc-mt-100">oc-card-v2</h2>
<oc-card-v2 base64-href="L2Zvbw==" rel="noreferrer" target="_blank">oc-card-v2</oc-card-v2>
<h2 class="oc-headline-200 oc-mt-100">oc-energy-label-v1 (Deprecated)</h2>
<oc-energy-label-v1
base64-href="L2Zvbw=="
rel="noreferrer"
target="_blank"
></oc-energy-label-v1>
<h2 class="oc-headline-200 oc-mt-100">oc-icon-button-v3</h2>
<oc-icon-button-v3
base64-href="L2Zvbw=="
rel="noreferrer"
target="_blank"
icon="almond"
oc-aria-label="oc-icon-button-v3 (screen reader only)"
></oc-icon-button-v3>
<h2 class="oc-headline-200 oc-mt-100">oc-interactive-overlay-v1</h2>
<oc-interactive-overlay-v1 base64-href="L2Zvbw==" rel="noreferrer" target="_blank"
>oc-interactive-overlay-v1
</oc-interactive-overlay-v1>
<h2 class="oc-headline-200 oc-mt-100">oc-link-v2</h2>
<oc-link-v2 base64-href="L2Zvbw==" rel="noreferrer" target="_blank">oc-link-v2</oc-link-v2>
<h2 class="oc-headline-200 oc-mt-100">oc-logo-v1 (Deprecated)</h2>
<oc-logo-v1
base64-href="L2Zvbw=="
rel="noreferrer"
target="_blank"
logo="otto"
oc-aria-label="oc-logo-v1 (screen reader only)"
></oc-logo-v1>
<h2 class="oc-headline-200">oc-media-object-card-v1</h2>
<oc-media-object-card-v1
variant="ambient-image"
base64-href="L2Zvbw=="
rel="noreferrer"
target="_blank"
>
<img slot="img" src="${placeholderImage}" alt="blue checkered background" />
<div>Headline</div>
<div slot="subline">Subline</div>
</oc-media-object-card-v1>
<h2 class="oc-headline-200 oc-mt-100">oc-promo-card-v1</h2>
<oc-promo-card-v1 base64-href="L2Zvbw==" rel="noreferrer" target="_blank"
>oc-promo-card-v1
</oc-promo-card-v1>
<h2 class="oc-headline-200 oc-mt-100">oc-row-v2</h2>
<oc-row-v2 base64-href="L2Zvbw==" rel="noreferrer" target="_blank">oc-row-v2 </oc-row-v2>
Story source (TypeScript, verbatim from Storybook)
{
render() {
return html`
<h2 class="oc-headline-200">oc-button-v1</h2>
<oc-button-v1 base64-href="L2Zvbw==" rel="noreferrer" target="_blank"
>oc-button-v1</oc-button-v1
>
<h2 class="oc-headline-200 oc-mt-100">oc-card-v2</h2>
<oc-card-v2 base64-href="L2Zvbw==" rel="noreferrer" target="_blank">oc-card-v2</oc-card-v2>
<h2 class="oc-headline-200 oc-mt-100">oc-energy-label-v1 (Deprecated)</h2>
<oc-energy-label-v1
base64-href="L2Zvbw=="
rel="noreferrer"
target="_blank"
></oc-energy-label-v1>
<h2 class="oc-headline-200 oc-mt-100">oc-icon-button-v3</h2>
<oc-icon-button-v3
base64-href="L2Zvbw=="
rel="noreferrer"
target="_blank"
icon="almond"
oc-aria-label="oc-icon-button-v3 (screen reader only)"
></oc-icon-button-v3>
<h2 class="oc-headline-200 oc-mt-100">oc-interactive-overlay-v1</h2>
<oc-interactive-overlay-v1 base64-href="L2Zvbw==" rel="noreferrer" target="_blank"
>oc-interactive-overlay-v1
</oc-interactive-overlay-v1>
<h2 class="oc-headline-200 oc-mt-100">oc-link-v2</h2>
<oc-link-v2 base64-href="L2Zvbw==" rel="noreferrer" target="_blank">oc-link-v2</oc-link-v2>
<h2 class="oc-headline-200 oc-mt-100">oc-logo-v1 (Deprecated)</h2>
<oc-logo-v1
base64-href="L2Zvbw=="
rel="noreferrer"
target="_blank"
logo="otto"
oc-aria-label="oc-logo-v1 (screen reader only)"
></oc-logo-v1>
<h2 class="oc-headline-200">oc-media-object-card-v1</h2>
<oc-media-object-card-v1
variant="ambient-image"
base64-href="L2Zvbw=="
rel="noreferrer"
target="_blank"
>
<img slot="img" src="${placeholderImage}" alt="blue checkered background" />
<div>Headline</div>
<div slot="subline">Subline</div>
</oc-media-object-card-v1>
<h2 class="oc-headline-200 oc-mt-100">oc-promo-card-v1</h2>
<oc-promo-card-v1 base64-href="L2Zvbw==" rel="noreferrer" target="_blank"
>oc-promo-card-v1
</oc-promo-card-v1>
<h2 class="oc-headline-200 oc-mt-100">oc-row-v2</h2>
<oc-row-v2 base64-href="L2Zvbw==" rel="noreferrer" target="_blank">oc-row-v2 </oc-row-v2>
`;
},
async play({
canvasElement
}) {
const components = Array.from(canvasElement.querySelectorAll("*")).filter(el => el.tagName.startsWith("OC-")) as HTMLAnchorElement[];
await expect(components.length).toBe(10);
await waitFor(function hrefProperty() {
return components.map(c => expect(c.href, `${c.tagName}.href`).toBe(`${window.location.origin}/foo`));
});
await expectNoInteractiveElementsInShadowDom(components);
await waitFor(function unmaskAndCheckFocus() {
return components.map(c => {
(c.shadowRoot!.querySelector(".-interactive") as HTMLElement).focus();
return expect(document.activeElement!.shadowRoot!.activeElement, `${c.tagName} > a`).toBe(c.shadowRoot!.querySelector("a"));
});
});
await waitFor(function hrefProperty() {
return components.map(c => expect(c.href, `${c.tagName}.href`).toBe(`${window.location.origin}/foo`));
});
await waitFor(function aTagInShadowDom() {
return components.flatMap(c => [expect(c.shadowRoot!.querySelector("a"), `${c.tagName} > a`).toBeTruthy(), expect(c.shadowRoot!.querySelector("a")?.href, `${c.tagName} > a.href`).toBe(`${window.location.origin}/foo`), expect(c.shadowRoot!.querySelector("a")?.rel, `${c.tagName} > a.rel`).toBe(`noreferrer`), expect(c.shadowRoot!.querySelector("a")?.target, `${c.tagName} > a.target`).toBe(`_blank`)]);
});
components.forEach(c => {
c.href = "/bar";
});
await tick();
await waitFor(function hrefPropertyBar() {
return components.map(c => expect(c.href, `${c.tagName}.href`).toBe(`${window.location.origin}/bar`));
});
}
}
Interactive (SEORelevantLinks.interactions.stories.ts)
Interaction test stories (automated tests, not usage patterns).
SEO Relevant Links
Story: tests-interactive--seo-relevant-links · tags: play-fn
<h2 class="oc-headline-200">oc-button-v1</h2>
<oc-button-v1><a href="/foo" rel="noreferrer" target="_blank">oc-button-v1</a></oc-button-v1>
<h2 class="oc-headline-200 oc-mt-100">oc-card-v2</h2>
<oc-card-v2>
<a
slot="primary-action"
href="/foo"
rel="noreferrer"
target="_blank"
aria-label="oc-card-v2 (screen reader only)"
></a>
<div>oc-card-v2</div>
</oc-card-v2>
<h2 class="oc-headline-200 oc-mt-100">oc-icon-button-v3</h2>
<oc-icon-button-v3 icon="almond">
<a
href="/foo"
rel="noreferrer"
target="_blank"
aria-label="oc-icon-button-v3 (screen reader only)"
></a>
</oc-icon-button-v3>
<h2 class="oc-headline-200 oc-mt-100">oc-interactive-overlay-v1</h2>
<oc-interactive-overlay-v1
><a href="/foo" rel="noreferrer" target="_blank"
>oc-interactive-overlay-v1</a
></oc-interactive-overlay-v1
>
<h2 class="oc-headline-200 oc-mt-100">oc-link-v2</h2>
<oc-link-v2><a href="/foo" rel="noreferrer" target="_blank">oc-link-v2</a></oc-link-v2>
<h2 class="oc-headline-200">oc-media-object-card-v1</h2>
<oc-media-object-card-v1 variant="ambient-image">
<a
slot="primary-action"
href="/foo"
rel="noreferrer"
target="_blank"
aria-label="oc-media-object-card-v1 (screen reader only)"
></a>
<img slot="img" src="${placeholderImage}" alt="blue checkered background" />
<div>Headline</div>
<div slot="subline">Subline</div>
</oc-media-object-card-v1>
<h2 class="oc-headline-200 oc-mt-100">oc-promo-card-v1</h2>
<oc-promo-card-v1>
<a
slot="primary-action"
href="/foo"
rel="noreferrer"
target="_blank"
aria-label="oc-promo-card-v1 (screen reader only)"
></a>
<div>oc-promo-card-v1</div>
</oc-promo-card-v1>
<h2 class="oc-headline-200 oc-mt-100">oc-row-v2</h2>
<oc-row-v2>
<a
slot="primary-action"
href="/foo"
rel="noreferrer"
target="_blank"
aria-label="oc-row-v2 (screen reader only)"
></a>
<div>oc-row-v2</div>
</oc-row-v2>
Story source (TypeScript, verbatim from Storybook)
{
render() {
return html`
<h2 class="oc-headline-200">oc-button-v1</h2>
<oc-button-v1><a href="/foo" rel="noreferrer" target="_blank">oc-button-v1</a></oc-button-v1>
<h2 class="oc-headline-200 oc-mt-100">oc-card-v2</h2>
<oc-card-v2>
<a
slot="primary-action"
href="/foo"
rel="noreferrer"
target="_blank"
aria-label="oc-card-v2 (screen reader only)"
></a>
<div>oc-card-v2</div>
</oc-card-v2>
<h2 class="oc-headline-200 oc-mt-100">oc-icon-button-v3</h2>
<oc-icon-button-v3 icon="almond">
<a
href="/foo"
rel="noreferrer"
target="_blank"
aria-label="oc-icon-button-v3 (screen reader only)"
></a>
</oc-icon-button-v3>
<h2 class="oc-headline-200 oc-mt-100">oc-interactive-overlay-v1</h2>
<oc-interactive-overlay-v1
><a href="/foo" rel="noreferrer" target="_blank"
>oc-interactive-overlay-v1</a
></oc-interactive-overlay-v1
>
<h2 class="oc-headline-200 oc-mt-100">oc-link-v2</h2>
<oc-link-v2><a href="/foo" rel="noreferrer" target="_blank">oc-link-v2</a></oc-link-v2>
<h2 class="oc-headline-200">oc-media-object-card-v1</h2>
<oc-media-object-card-v1 variant="ambient-image">
<a
slot="primary-action"
href="/foo"
rel="noreferrer"
target="_blank"
aria-label="oc-media-object-card-v1 (screen reader only)"
></a>
<img slot="img" src="${placeholderImage}" alt="blue checkered background" />
<div>Headline</div>
<div slot="subline">Subline</div>
</oc-media-object-card-v1>
<h2 class="oc-headline-200 oc-mt-100">oc-promo-card-v1</h2>
<oc-promo-card-v1>
<a
slot="primary-action"
href="/foo"
rel="noreferrer"
target="_blank"
aria-label="oc-promo-card-v1 (screen reader only)"
></a>
<div>oc-promo-card-v1</div>
</oc-promo-card-v1>
<h2 class="oc-headline-200 oc-mt-100">oc-row-v2</h2>
<oc-row-v2>
<a
slot="primary-action"
href="/foo"
rel="noreferrer"
target="_blank"
aria-label="oc-row-v2 (screen reader only)"
></a>
<div>oc-row-v2</div>
</oc-row-v2>
`;
},
async play({
canvasElement
}) {
const components = Array.from(canvasElement.querySelectorAll("*")).filter(el => el.tagName.startsWith("OC-")) as HTMLAnchorElement[];
await expect(components.length).toBe(8);
await expectNoInteractiveElementsInShadowDom(components);
}
}
Interactive (SEOSwitchingLinks.interactions.stories.ts)
Interaction test stories (automated tests, not usage patterns).
SEO Switching Links
Story: tests-interactive--seo-switching-links · tags: play-fn
<h2 class="oc-headline-200">oc-button-v1</h2>
<oc-button-v1 base64-href="L2Zvbw=="
><a href="/bar" rel="noreferrer" target="_blank">oc-button-v1</a></oc-button-v1
>
<h2 class="oc-headline-200 oc-mt-100">oc-card-v2</h2>
<oc-card-v2 base64-href="L2Zvbw==">
<a
slot="primary-action"
href="/bar"
rel="noreferrer"
target="_blank"
aria-label="oc-card-v2 (screen reader only)"
></a>
<div>oc-card-v2</div>
</oc-card-v2>
<h2 class="oc-headline-200 oc-mt-100">oc-icon-button-v3</h2>
<oc-icon-button-v3 base64-href="L2Zvbw==" icon="almond">
<a
href="/bar"
rel="noreferrer"
target="_blank"
aria-label="oc-icon-button-v3 (screen reader only)"
></a>
</oc-icon-button-v3>
<h2 class="oc-headline-200 oc-mt-100">oc-interactive-overlay-v1</h2>
<oc-interactive-overlay-v1 base64-href="L2Zvbw=="
><a href="/bar" rel="noreferrer" target="_blank"
>oc-interactive-overlay-v1</a
></oc-interactive-overlay-v1
>
<h2 class="oc-headline-200 oc-mt-100">oc-link-v2</h2>
<oc-link-v2 base64-href="L2Zvbw=="
><a href="/bar" rel="noreferrer" target="_blank">oc-link-v2</a></oc-link-v2
>
<h2 class="oc-headline-200">oc-media-object-card-v1</h2>
<oc-media-object-card-v1 variant="ambient-image" base64-href="L2Zvbw==">
<a
slot="primary-action"
href="/bar"
rel="noreferrer"
target="_blank"
aria-label="oc-media-object-card-v1 (screen reader only)"
></a>
<img slot="img" src="${placeholderImage}" alt="blue checkered background" />
<div>Headline</div>
<div slot="subline">Subline</div>
</oc-media-object-card-v1>
<h2 class="oc-headline-200 oc-mt-100">oc-promo-card-v1</h2>
<oc-promo-card-v1 base64-href="L2Zvbw==">
<a
slot="primary-action"
href="/bar"
rel="noreferrer"
target="_blank"
aria-label="oc-promo-card-v1 (screen reader only)"
></a>
<div>oc-promo-card-v1</div>
</oc-promo-card-v1>
<h2 class="oc-headline-200 oc-mt-100">oc-row-v2</h2>
<oc-row-v2 base64-href="L2Zvbw==">
<a
slot="primary-action"
href="/bar"
rel="noreferrer"
target="_blank"
aria-label="oc-row-v2 (screen reader only)"
></a>
<div>oc-row-v2</div>
</oc-row-v2>
Story source (TypeScript, verbatim from Storybook)
{
render() {
return html`
<h2 class="oc-headline-200">oc-button-v1</h2>
<oc-button-v1 base64-href="L2Zvbw=="
><a href="/bar" rel="noreferrer" target="_blank">oc-button-v1</a></oc-button-v1
>
<h2 class="oc-headline-200 oc-mt-100">oc-card-v2</h2>
<oc-card-v2 base64-href="L2Zvbw==">
<a
slot="primary-action"
href="/bar"
rel="noreferrer"
target="_blank"
aria-label="oc-card-v2 (screen reader only)"
></a>
<div>oc-card-v2</div>
</oc-card-v2>
<h2 class="oc-headline-200 oc-mt-100">oc-icon-button-v3</h2>
<oc-icon-button-v3 base64-href="L2Zvbw==" icon="almond">
<a
href="/bar"
rel="noreferrer"
target="_blank"
aria-label="oc-icon-button-v3 (screen reader only)"
></a>
</oc-icon-button-v3>
<h2 class="oc-headline-200 oc-mt-100">oc-interactive-overlay-v1</h2>
<oc-interactive-overlay-v1 base64-href="L2Zvbw=="
><a href="/bar" rel="noreferrer" target="_blank"
>oc-interactive-overlay-v1</a
></oc-interactive-overlay-v1
>
<h2 class="oc-headline-200 oc-mt-100">oc-link-v2</h2>
<oc-link-v2 base64-href="L2Zvbw=="
><a href="/bar" rel="noreferrer" target="_blank">oc-link-v2</a></oc-link-v2
>
<h2 class="oc-headline-200">oc-media-object-card-v1</h2>
<oc-media-object-card-v1 variant="ambient-image" base64-href="L2Zvbw==">
<a
slot="primary-action"
href="/bar"
rel="noreferrer"
target="_blank"
aria-label="oc-media-object-card-v1 (screen reader only)"
></a>
<img slot="img" src="${placeholderImage}" alt="blue checkered background" />
<div>Headline</div>
<div slot="subline">Subline</div>
</oc-media-object-card-v1>
<h2 class="oc-headline-200 oc-mt-100">oc-promo-card-v1</h2>
<oc-promo-card-v1 base64-href="L2Zvbw==">
<a
slot="primary-action"
href="/bar"
rel="noreferrer"
target="_blank"
aria-label="oc-promo-card-v1 (screen reader only)"
></a>
<div>oc-promo-card-v1</div>
</oc-promo-card-v1>
<h2 class="oc-headline-200 oc-mt-100">oc-row-v2</h2>
<oc-row-v2 base64-href="L2Zvbw==">
<a
slot="primary-action"
href="/bar"
rel="noreferrer"
target="_blank"
aria-label="oc-row-v2 (screen reader only)"
></a>
<div>oc-row-v2</div>
</oc-row-v2>
`;
},
async play({
canvasElement
}) {
const components = Array.from(canvasElement.querySelectorAll("*")).filter(el => el.tagName.startsWith("OC-")) as HTMLAnchorElement[];
await expect(components.length).toBe(8);
await expectNoInteractiveElementsInShadowDom(components);
await waitFor(function aTagHrefShouldBeBar() {
return components.flatMap(c => [expect(c.querySelector("a")!.href, `${c.tagName} > a`).toBe(`${window.location.origin}/bar`)]);
});
await waitFor(function unmaskAndCheckFocus() {
return components.map(async c => {
(c.querySelector("a") as HTMLElement).focus();
return expect(document.activeElement, `${c.tagName} > a`).toBe(c.querySelector("a"));
});
});
await waitFor(function aTagHrefShouldBeFoo() {
return components.flatMap(c => [expect(c.querySelector("a")!.href, `${c.tagName} > a`).toBe(`${window.location.origin}/foo`)]);
});
await expectNoInteractiveElementsInShadowDom(components);
}
}