Skip to content

Commit 094f03b

Browse files
authored
chore: Adds iframe helper and iframe vr test (#61)
* chore: Adds iframe helper and iframe vr test * simplify iframe helper
1 parent bdef0f5 commit 094f03b

File tree

5 files changed

+134
-3
lines changed

5 files changed

+134
-3
lines changed

pages/06-visual-tests/cartesian-tooltip.page.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,8 @@ export default function () {
4141
<Page title="Cartesian chart tooltip visual regression page">
4242
<CoreChart
4343
{...omit(chartProps.cartesian, "ref")}
44+
ariaLabel="Line chart"
4445
options={{
45-
lang: { accessibility: { chartContainerLabel: "Line chart" } },
4646
series: series,
4747
xAxis: [{ type: "datetime", title: { text: "Time (UTC)" }, valueFormatter: dateFormatter }],
4848
yAxis: [{ title: { text: "Events" } }],
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
import { omit } from "lodash";
5+
6+
import CoreChart from "../../lib/components/internal-do-not-use/core-chart";
7+
import { useChartSettings } from "../common/page-settings";
8+
import { Page } from "../common/templates";
9+
import { IframeWrapper } from "../utils/iframe-wrapper";
10+
11+
export default function () {
12+
return (
13+
<IframeWrapper
14+
AppComponent={() => {
15+
const { chartProps } = useChartSettings();
16+
return (
17+
<Page title="Chart inside iframe visual regression page">
18+
<CoreChart
19+
{...omit(chartProps.pie, "ref")}
20+
ariaLabel="Pie chart"
21+
options={{
22+
series: [
23+
{
24+
name: "Resource count",
25+
type: "pie",
26+
data: [
27+
{ name: "Running", y: 60 },
28+
{ name: "Failed", y: 30 },
29+
{ name: "In-progress", y: 10 },
30+
],
31+
},
32+
],
33+
}}
34+
callback={(api) => {
35+
setTimeout(() => {
36+
if (api.chart.series) {
37+
const point = api.chart.series[0].data.find((p) => p.y === 10)!;
38+
api.highlightChartPoint(point);
39+
}
40+
}, 0);
41+
}}
42+
/>
43+
</Page>
44+
);
45+
}}
46+
/>
47+
);
48+
}

pages/06-visual-tests/pie-tooltip.page.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,9 @@ export default function () {
2626
return (
2727
<Page title="Pie chart tooltip visual regression page">
2828
<CoreChart
29-
{...omit(chartProps.cartesian, "ref")}
29+
{...omit(chartProps.pie, "ref")}
30+
ariaLabel="Pie chart"
3031
options={{
31-
lang: { accessibility: { chartContainerLabel: "Pie chart" } },
3232
series: series,
3333
}}
3434
chartHeight={400}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
/*
2+
Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
.full-screen {
7+
inline-size: 100%;
8+
block-size: calc(
9+
100vh - var(--awsui-sticky-vertical-top-offset, 0px) - var(--awsui-sticky-vertical-bottom-offset, 0px)
10+
);
11+
border-inline: 0;
12+
border-block: 0;
13+
display: block;
14+
}

pages/utils/iframe-wrapper.tsx

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
import { useEffect, useRef } from "react";
5+
import { createRoot } from "react-dom/client";
6+
7+
import styles from "./iframe-wrapper.module.scss";
8+
9+
export function IframeWrapper({ id = "iframe", AppComponent }: { id?: string; AppComponent: React.ComponentType }) {
10+
const iframeRef = useRef<HTMLIFrameElement>(null);
11+
12+
useEffect(() => {
13+
const iframe = iframeRef.current;
14+
if (!iframe) {
15+
return;
16+
}
17+
18+
const iframeDocument = iframe.contentDocument!;
19+
// Prevent iframe document instance from reload
20+
// https://bugzilla.mozilla.org/show_bug.cgi?id=543435
21+
iframeDocument.open();
22+
// set html5 doctype
23+
iframeDocument.writeln("<!DOCTYPE html>");
24+
iframeDocument.close();
25+
26+
const innerAppRoot = iframeDocument.createElement("div");
27+
iframeDocument.body.appendChild(innerAppRoot);
28+
copyStyles(document, iframeDocument);
29+
iframeDocument.dir = document.dir;
30+
const syncClassesCleanup = syncClasses(document.body, iframeDocument.body);
31+
const root = createRoot(innerAppRoot);
32+
root.render(<AppComponent />);
33+
return () => {
34+
syncClassesCleanup();
35+
root.unmount();
36+
};
37+
}, [id, AppComponent]);
38+
39+
return <iframe ref={iframeRef} id={id} title={id} className={styles["full-screen"]}></iframe>;
40+
}
41+
42+
function copyStyles(srcDoc: Document, targetDoc: Document) {
43+
for (const stylesheet of Array.from(srcDoc.querySelectorAll("link[rel=stylesheet]"))) {
44+
const newStylesheet = targetDoc.createElement("link");
45+
for (const attr of stylesheet.getAttributeNames()) {
46+
newStylesheet.setAttribute(attr, stylesheet.getAttribute(attr)!);
47+
}
48+
targetDoc.head.appendChild(newStylesheet);
49+
}
50+
51+
for (const styleEl of Array.from(srcDoc.querySelectorAll("style"))) {
52+
const newStyle = targetDoc.createElement("style");
53+
newStyle.textContent = styleEl.textContent;
54+
targetDoc.head.appendChild(newStyle);
55+
}
56+
}
57+
58+
function syncClasses(from: HTMLElement, to: HTMLElement) {
59+
to.className = from.className;
60+
const observer = new MutationObserver(() => {
61+
to.className = from.className;
62+
});
63+
64+
observer.observe(from, { attributes: true, attributeFilter: ["class"] });
65+
66+
return () => {
67+
observer.disconnect();
68+
};
69+
}

0 commit comments

Comments
 (0)