From 3b83f53e31534d067df543d0c25889e87ee40f5e Mon Sep 17 00:00:00 2001 From: nickofthyme Date: Wed, 8 Nov 2023 09:55:28 -0700 Subject: [PATCH 1/3] test: add resize config for easy story and e2e resizing --- e2e/page_objects/common.ts | 13 +++ e2e/tests/tooltip.test.ts | 2 - .../server/generate/vrt_page_template.js | 29 ++++--- .../server/mocks/use_global_parameters.ts | 8 +- storybook/stories/metric/1_basic.story.tsx | 65 +++++++-------- .../test_cases/11_resize_debounce.story.tsx | 81 ++++++++----------- storybook/story_wrapper.tsx | 35 +++++--- storybook/style.scss | 9 +++ storybook/types.ts | 8 +- 9 files changed, 142 insertions(+), 108 deletions(-) diff --git a/e2e/page_objects/common.ts b/e2e/page_objects/common.ts index 4dae3748cd..da744f9e78 100644 --- a/e2e/page_objects/common.ts +++ b/e2e/page_objects/common.ts @@ -548,6 +548,19 @@ export class CommonPage { strict: false, // should be true but some stories have multiple charts }); }; + + setResizeDimensions = (page: Page) => async (dimensions: { height?: string; width?: string }) => { + const el = page.locator('#story-resize-wrapper'); + if (!(await el.isVisible())) { + throw new Error('setResizeDimensions was called when no #story-resize-wrapper exists'); + } + + await el.evaluate((element, { height, width }) => { + console.log({ height, width }); + if (height !== undefined) element.style.height = height; + if (width !== undefined) element.style.width = width; + }, dimensions); + }; } function getSnapshotOptions(options?: ScreenshotDOMElementOptions) { diff --git a/e2e/tests/tooltip.test.ts b/e2e/tests/tooltip.test.ts index 9ad138d568..ebcb044192 100644 --- a/e2e/tests/tooltip.test.ts +++ b/e2e/tests/tooltip.test.ts @@ -10,8 +10,6 @@ import { test } from '@playwright/test'; import { common } from '../page_objects/common'; -process.env.ENV_URL = 'http://localhost:9002/'; - test.describe('Tooltip', () => { test.describe('Chart Types', () => { test.describe('Cartesian', () => { diff --git a/e2e_server/server/generate/vrt_page_template.js b/e2e_server/server/generate/vrt_page_template.js index 6087cd0851..7db2a4d3ac 100644 --- a/e2e_server/server/generate/vrt_page_template.js +++ b/e2e_server/server/generate/vrt_page_template.js @@ -43,17 +43,24 @@ ReactDOM.render(, document.getElementById('story-root') as HTMLElemen function pageTemplate(imports, routes, urls) { return ` -import React, { Suspense } from 'react'; +import React, { PropsWithChildren, FC, Suspense, CSSProperties } from 'react'; import { EuiProvider } from '@elastic/eui'; import { ThemeIdProvider, BackgroundIdProvider } from '../../storybook/use_base_theme'; import { useGlobalsParameters } from '../server/mocks/use_global_parameters'; import { StoryContext } from '../../storybook/types'; +const ResizeWrapper: FC> = ({ resize, children }) => resize ? ( +
+ { children } +
+) : (<>{children}) + export function VRTPage() { const { themeId, backgroundId, toggles, + resize, setParams, } = useGlobalsParameters(); const urlParams = new URL(window.location.toString()).searchParams; @@ -84,15 +91,17 @@ export function VRTPage() { } return ( - - - - Loading...}> - ${routes.join('\n ')} - - - - + + + + + Loading...}> + ${routes.join('\n ')} + + + + + ); } diff --git a/e2e_server/server/mocks/use_global_parameters.ts b/e2e_server/server/mocks/use_global_parameters.ts index ff856ba9b0..27417aff1f 100644 --- a/e2e_server/server/mocks/use_global_parameters.ts +++ b/e2e_server/server/mocks/use_global_parameters.ts @@ -8,13 +8,13 @@ import { useMemo, useState } from 'react'; -import type { StoryGlobals } from './../../../storybook/types'; +import type { StoryGlobals, StoryParameters } from './../../../storybook/types'; import { BackgroundParameter } from '../../../storybook/node_modules/storybook-addon-background-toggle'; import { ThemeParameter } from '../../../storybook/node_modules/storybook-addon-theme-toggle'; import { storybookParameters as globalParams } from '../../../storybook/parameters'; import { ThemeId } from '../../../storybook/use_base_theme'; -type Parameters = BackgroundParameter & ThemeParameter; +type Parameters = BackgroundParameter & ThemeParameter & Pick; const themeParams = globalParams.theme!; const backgroundParams = globalParams.background!; @@ -48,6 +48,7 @@ interface GlobalParameters { themeId: StoryGlobals['theme']; backgroundId: StoryGlobals['background']; toggles: StoryGlobals['toggles']; + resize: StoryParameters['resize']; setParams(params: URLSearchParams, parameters?: Parameters): void; } @@ -55,6 +56,7 @@ export function useGlobalsParameters(): GlobalParameters { const [themeId, setThemeId] = useState(ThemeId.Light); const [backgroundId, setBackgroundId] = useState(); const [togglesJSON, setTogglesJSON] = useState('{}'); + const [resize, setResize] = useState(false); /** * Handles setting global context values. Stub for theme and background addons @@ -67,6 +69,7 @@ export function useGlobalsParameters(): GlobalParameters { setThemeId(themeIdFromParams); setTogglesJSON(JSON.stringify(globals.toggles ?? '{}')); applyThemeCSS(themeIdFromParams); + setResize(parameters?.resize); } // using toggles object creates an infinite update loop, thus using JSON state. @@ -76,6 +79,7 @@ export function useGlobalsParameters(): GlobalParameters { themeId, backgroundId, toggles, + resize, setParams, }; } diff --git a/storybook/stories/metric/1_basic.story.tsx b/storybook/stories/metric/1_basic.story.tsx index 7f02afc330..fca6f2f987 100644 --- a/storybook/stories/metric/1_basic.story.tsx +++ b/storybook/stories/metric/1_basic.story.tsx @@ -117,40 +117,35 @@ export const Example: ChartsStory = (_, { title: storyTitle, description }) => { const configuredData = [[numberTextSwitch ? numericData : textualData]]; return ( -
- - { - if (isMetricElementEvent(d)) { - const { rowIndex, columnIndex } = d; - onEventClickAction( - `row:${rowIndex} col:${columnIndex} value:${configuredData[rowIndex][columnIndex].value}`, - ); - } - }} - onElementOver={([d]) => { - if (isMetricElementEvent(d)) { - const { rowIndex, columnIndex } = d; - onEventOverAction( - `row:${rowIndex} col:${columnIndex} value:${configuredData[rowIndex][columnIndex].value}`, - ); - } - }} - onElementOut={() => onEventOutAction('out')} - /> - - -
+ + { + if (isMetricElementEvent(d)) { + const { rowIndex, columnIndex } = d; + onEventClickAction( + `row:${rowIndex} col:${columnIndex} value:${configuredData[rowIndex][columnIndex].value}`, + ); + } + }} + onElementOver={([d]) => { + if (isMetricElementEvent(d)) { + const { rowIndex, columnIndex } = d; + onEventOverAction( + `row:${rowIndex} col:${columnIndex} value:${configuredData[rowIndex][columnIndex].value}`, + ); + } + }} + onElementOut={() => onEventOutAction('out')} + /> + + ); }; + +Example.parameters = { + resize: { + height: '200px', + width: '200px', + }, +}; diff --git a/storybook/stories/test_cases/11_resize_debounce.story.tsx b/storybook/stories/test_cases/11_resize_debounce.story.tsx index 12e9dcbee0..f368f81344 100644 --- a/storybook/stories/test_cases/11_resize_debounce.story.tsx +++ b/storybook/stories/test_cases/11_resize_debounce.story.tsx @@ -37,57 +37,46 @@ export const Example: ChartsStory = (_, { title, description }) => { const resizeDebounce = number('resizeDebounce (ms)', 10, { min: 0, step: 20 }); const cardinality = number('cardinality', 100, { min: 1, max: maxCardinality }); return ( -
- - - - + + + + - values.slice(0, cardinality).map(({ v, cat }) => ({ t, v, cat })))} - /> - -
+ values.slice(0, cardinality).map(({ v, cat }) => ({ t, v, cat })))} + /> + ); }; Example.parameters = { markdown: `The \`resizeDebounce\` option on the \`Settings\` spec provides control over the eagerness of the chart to re-render upon resize. A value of \`0\` will remove the debounce altogether. You can play with the cardinality and debounce time to see how the debouncing affects the chart render timing`, + resize: true, }; diff --git a/storybook/story_wrapper.tsx b/storybook/story_wrapper.tsx index a413305430..8a6d9ff2fe 100644 --- a/storybook/story_wrapper.tsx +++ b/storybook/story_wrapper.tsx @@ -9,24 +9,35 @@ import { EuiProvider, EuiMarkdownFormat, EuiFlexGroup, EuiFlexItem, EuiHorizontalRule, EuiText } from '@elastic/eui'; import { DecoratorFunction } from '@storybook/addons'; import classNames from 'classnames'; -import React from 'react'; +import React, { FC, PropsWithChildren } from 'react'; +import { StoryGlobals, StoryParameters } from './types'; import { ThemeId, ThemeIdProvider, BackgroundIdProvider } from './use_base_theme'; +const ResizeWrapper: FC> = ({ resize, children }) => + resize ? ( +
+ {children} +
+ ) : ( + <>{children} + ); + export const StoryWrapper: DecoratorFunction = (Story, context) => { if (!Story) return
No Story
; - const { globals, parameters } = context; + const globals = (context.globals as StoryGlobals) ?? {}; + const parameters = (context.parameters as StoryParameters) ?? {}; - const themeId = globals?.theme ?? ThemeId.Light; - const backgroundId = globals?.background; + const themeId = (globals.theme as ThemeId) ?? ThemeId.Light; + const backgroundId = globals.background; const { showHeader = false, showChartTitle = false, showChartDescription = false, showChartBoundary = false, - } = globals?.toggles ?? {}; - const markdown = parameters?.markdown; + } = globals.toggles ?? {}; + const { markdown, resize } = parameters; const colorMode = themeId.includes('light') ? 'light' : 'dark'; return ( @@ -56,11 +67,13 @@ export const StoryWrapper: DecoratorFunction = (Story, context) =>
- + + +
{markdown && ( diff --git a/storybook/style.scss b/storybook/style.scss index 226e3abab3..f46b3eded2 100644 --- a/storybook/style.scss +++ b/storybook/style.scss @@ -141,6 +141,15 @@ body { } } +#story-resize-wrapper { + resize: both; + height: 100%; + width: 100%; + overflow: auto; + max-width: 100%; + max-height: 80vh; +} + #story-header { padding: 20px 40px 16px; } diff --git a/storybook/types.ts b/storybook/types.ts index d96a5c3530..5d4e502013 100644 --- a/storybook/types.ts +++ b/storybook/types.ts @@ -8,7 +8,7 @@ import type { Parameters as SBParameters } from '@storybook/addons'; import { ArgTypes, Args, StoryContext as SBStoryContext } from '@storybook/react'; -import { ReactElement } from 'react'; +import { CSSProperties, ReactElement } from 'react'; import { StoryBackgroundParameter, BackgroundGlobals } from 'storybook-addon-background-toggle'; import { StoryThemeParameter, ThemeGlobals } from 'storybook-addon-theme-toggle'; import { StoryTogglesParameter, TogglesGlobals } from 'storybook-addon-toggles'; @@ -16,7 +16,7 @@ import { StoryTogglesParameter, TogglesGlobals } from 'storybook-addon-toggles'; /** * Parameter accessible at the story level */ -type StoryParameters = SBParameters & +export type StoryParameters = SBParameters & StoryThemeParameter & StoryBackgroundParameter & StoryTogglesParameter & { @@ -24,6 +24,10 @@ type StoryParameters = SBParameters & * Renders markdown content below story */ markdown?: string; + /** + * Defines resize wrapper under `#story-root` to define + */ + resize?: boolean | CSSProperties; }; export type StoryGlobals = ThemeGlobals & BackgroundGlobals & TogglesGlobals; From 64f53a1fc763e0ca37ce52b498d01752b317e695 Mon Sep 17 00:00:00 2001 From: nickofthyme Date: Wed, 8 Nov 2023 10:07:19 -0700 Subject: [PATCH 2/3] test: remove console log --- e2e/page_objects/common.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/e2e/page_objects/common.ts b/e2e/page_objects/common.ts index da744f9e78..b2b109d6ed 100644 --- a/e2e/page_objects/common.ts +++ b/e2e/page_objects/common.ts @@ -556,7 +556,6 @@ export class CommonPage { } await el.evaluate((element, { height, width }) => { - console.log({ height, width }); if (height !== undefined) element.style.height = height; if (width !== undefined) element.style.width = width; }, dimensions); From d47a40780c2f48c54d89f18918fccb92e848bf7c Mon Sep 17 00:00:00 2001 From: nickofthyme Date: Wed, 8 Nov 2023 10:10:18 -0700 Subject: [PATCH 3/3] chore: update comment --- storybook/types.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/storybook/types.ts b/storybook/types.ts index 5d4e502013..8f5f6a803d 100644 --- a/storybook/types.ts +++ b/storybook/types.ts @@ -25,7 +25,7 @@ export type StoryParameters = SBParameters & */ markdown?: string; /** - * Defines resize wrapper under `#story-root` to define + * Used to enable and style resize wrapper under `#story-root` */ resize?: boolean | CSSProperties; };