Skip to content
Snippets Groups Projects
Unverified Commit e441f1d5 authored by Nicolò Pretto's avatar Nicolò Pretto Committed by GitHub
Browse files

poc of using loki to test png/pdf exports (#45650)

* use loki to test png exports on questions

* try to put the img in the body to see if it fixes the scrollbar issues in ci

* fix linting issues

* let's try again in ci

* Attempt to make CI wait before taking a snapshot for downloaded PNGs

* Use the snapshots from CI for PNG downloads

* pdf export test thanks to kelvin suggestion about just testing the png

* refactored the code to extract a util function

* remove pdf tests as they broke in ci :shrug:



* Update frontend/src/metabase/env.ts

Co-authored-by: default avatarPhoomparin Mano <poom@metabase.com>

* Update frontend/src/metabase/lib/loki-utils.ts

---------

Co-authored-by: default avatarMahatthana (Kelvin) Nomsawadi <me@bboykelvin.dev>
Co-authored-by: default avatarPhoomparin Mano <poom@metabase.com>
parent f749c695
No related branches found
No related tags found
No related merge requests found
.loki/reference/chrome_laptop_embed_PublicOrEmbeddedQuestionView_Dark_Theme_Download.png

9.96 KiB

......@@ -11,6 +11,7 @@ import { getMetabaseCssVariables } from "metabase/styled-components/theme/css-va
import { css, Global, useTheme } from "@emotion/react";
import { baseStyle, rootStyle } from "metabase/css/core/base.styled";
import { defaultFontFiles } from "metabase/css/core/fonts.styled";
import { saveDomImageStyles } from "metabase/visualizations/lib/save-chart-image";
export const parameters = {
actions: { argTypesRegex: "^on[A-Z].*" },
......@@ -30,6 +31,7 @@ const globalStyles = css`
${rootStyle}
}
${saveDomImageStyles}
${baseStyle}
`;
......
// @ts-expect-error window.Cypress is not typed
export const isCypressActive = !!window.Cypress;
// eslint-disable-next-line no-undef
export const isStorybookActive = !!process.env.STORYBOOK;
// eslint-disable-next-line no-undef
export const isProduction = process.env.WEBPACK_BUNDLE === "production";
// eslint-disable-next-line no-undef
export const isTest = process.env.NODE_ENV === "test";
// eslint-disable-next-line no-undef
export const shouldLogAnalytics = process.env.MB_LOG_ANALYTICS === "true";
export const isChartsDebugLoggingEnabled =
// eslint-disable-next-line no-undef
process.env.MB_LOG_CHARTS_DEBUG === "true";
// eslint-disable-next-line no-undef
export const isEmbeddingSdk = !!process.env.IS_EMBEDDING_SDK_BUILD;
export const openImageBlobOnStorybook = ({
canvas,
blob,
}: {
canvas: HTMLCanvasElement;
blob: Blob;
}) => {
const imgElement = document.createElement("img");
imgElement.src = URL.createObjectURL(blob);
// scale to /2 to compensate `scale:2` in html2canvas
imgElement.width = canvas.width / 2;
imgElement.height = canvas.height / 2;
const root: HTMLElement = document.querySelector("#root")!;
const imageDownloaded = document.createElement("div");
imageDownloaded.setAttribute("data-testid", "image-downloaded");
root.replaceChildren(imgElement);
// the presence of this element is used to detect when the image is ready
// in the storybook you'll need to `await canvas.findByTestId("image-downloaded");`
// and then call `asyncCallback()` to continue the story
root.appendChild(imageDownloaded);
window.document.body.style.height = "initial";
};
......@@ -136,6 +136,16 @@ LightThemeDefaultNoResults.args = {
result: createMockDataset(),
};
export const LightThemeDownload = Template.bind({});
LightThemeDownload.args = {
...LightThemeDefault.args,
downloadsEnabled: true,
};
LightThemeDownload.play = async ({ canvasElement }) => {
const asyncCallback = createAsyncCallback();
await downloadQuestionAsPng(canvasElement, asyncCallback);
};
// Dark theme
export const DarkThemeDefault = Template.bind({});
DarkThemeDefault.args = {
......@@ -150,6 +160,13 @@ DarkThemeDefaultNoResults.args = {
result: createMockDataset(),
};
export const DarkThemeDownload = Template.bind({});
DarkThemeDownload.args = {
...DarkThemeDefault.args,
downloadsEnabled: true,
};
DarkThemeDownload.play = LightThemeDownload.play;
// Transparent theme
export const TransparentThemeDefault = Template.bind({});
TransparentThemeDefault.args = {
......@@ -308,3 +325,19 @@ function NarrowContainer(Story: Story) {
</Box>
);
}
const downloadQuestionAsPng = async (
canvasElement: HTMLElement,
asyncCallback: () => void,
) => {
const canvas = within(canvasElement);
const downloadButton = await canvas.findByTestId("download-button");
await userEvent.click(downloadButton!);
const documentElement = within(document.documentElement);
const pngButton = await documentElement.findByText(".png");
await userEvent.click(pngButton);
await canvas.findByTestId("image-downloaded");
asyncCallback();
};
import { css } from "@emotion/react";
import { isStorybookActive } from "metabase/env";
import { openImageBlobOnStorybook } from "metabase/lib/loki-utils";
import EmbedFrameS from "metabase/public/components/EmbedFrame/EmbedFrame.module.css";
export const SAVING_DOM_IMAGE_CLASS = "saving-dom-image";
export const SAVING_DOM_IMAGE_HIDDEN_CLASS = "saving-dom-image-hidden";
export const SAVING_DOM_IMAGE_DISPLAY_NONE_CLASS =
"saving-dom-image-display-none";
import EmbedFrameS from "metabase/public/components/EmbedFrame/EmbedFrame.module.css";
export const saveDomImageStyles = css`
.${SAVING_DOM_IMAGE_CLASS} {
.${SAVING_DOM_IMAGE_HIDDEN_CLASS} {
......@@ -41,14 +43,20 @@ export const saveChartImage = async (selector: string, fileName: string) => {
canvas.toBlob(blob => {
if (blob) {
const link = document.createElement("a");
const url = URL.createObjectURL(blob);
link.rel = "noopener";
link.download = fileName;
link.href = url;
link.click();
link.remove();
setTimeout(() => URL.revokeObjectURL(url), 60_000);
if (isStorybookActive) {
// if we're running storybook we open the image in place
// so we can test the export result with loki
openImageBlobOnStorybook({ canvas, blob });
} else {
const link = document.createElement("a");
const url = URL.createObjectURL(blob);
link.rel = "noopener";
link.download = fileName;
link.href = url;
link.click();
link.remove();
setTimeout(() => URL.revokeObjectURL(url), 60_000);
}
}
});
};
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment