From a3484005add4913cf99292a17b3ed83e1de12b84 Mon Sep 17 00:00:00 2001 From: Pavithra Kodmad Date: Wed, 31 Aug 2022 13:09:19 +1000 Subject: [PATCH] Add interaction tests for pagelayout sticky (#2241) * Add interaction tests for pagelayout sticky Maybe add a wait Remove wait times * The second check makes things flaky * add interaction tests for custom sticky header * remove unnecessary import * remove fireEvent scroll Co-authored-by: Armagan Ersoz --- src/PageLayout/PageLayout.stories.tsx | 97 +++--- src/PageLayout/interaction.stories.tsx | 425 +++++++++++++++++++++++++ 2 files changed, 485 insertions(+), 37 deletions(-) create mode 100644 src/PageLayout/interaction.stories.tsx diff --git a/src/PageLayout/PageLayout.stories.tsx b/src/PageLayout/PageLayout.stories.tsx index 83ddf55db28..ce34d512d3e 100644 --- a/src/PageLayout/PageLayout.stories.tsx +++ b/src/PageLayout/PageLayout.stories.tsx @@ -489,27 +489,38 @@ export const StickyPane: Story = args => ( - {Array.from({length: args.numParagraphsInContent}).map((_, i) => ( - - Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam at enim id lorem tempus egestas a non ipsum. - Maecenas imperdiet ante quam, at varius lorem molestie vel. Sed at eros consequat, varius tellus et, auctor - felis. Donec pulvinar lacinia urna nec commodo. Phasellus at imperdiet risus. Donec sit amet massa purus. - Nunc sem lectus, bibendum a sapien nec, tristique tempus felis. Ut porttitor auctor tellus in imperdiet. Ut - blandit tincidunt augue, quis fringilla nunc tincidunt sed. Vestibulum auctor euismod nisi. Nullam tincidunt - est in mi tincidunt dictum. Sed consectetur aliquet velit ut ornare. - - ))} + {Array.from({length: args.numParagraphsInContent}).map((_, i) => { + const testId = `content${i}` + return ( + + + Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam at enim id lorem tempus egestas a non + ipsum. Maecenas imperdiet ante quam, at varius lorem molestie vel. Sed at eros consequat, varius tellus + et, auctor felis. Donec pulvinar lacinia urna nec commodo. Phasellus at imperdiet risus. Donec sit amet + massa purus. Nunc sem lectus, bibendum a sapien nec, tristique tempus felis. Ut porttitor auctor tellus + in imperdiet. Ut blandit tincidunt augue, quis fringilla nunc tincidunt sed. Vestibulum auctor euismod + nisi. Nullam tincidunt est in mi tincidunt dictum. Sed consectetur aliquet velit ut ornare. + + + ) + })} - {Array.from({length: args.numParagraphsInPane}).map((_, i) => ( - - Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam at enim id lorem tempus egestas a non ipsum. - Maecenas imperdiet ante quam, at varius lorem molestie vel. Sed at eros consequat, varius tellus et, auctor - felis. Donec pulvinar lacinia urna nec commodo. Phasellus at imperdiet risus. Donec sit amet massa purus. - - ))} + {Array.from({length: args.numParagraphsInPane}).map((_, i) => { + const testId = `paragraph${i}` + return ( + + + Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam at enim id lorem tempus egestas a non + ipsum. Maecenas imperdiet ante quam, at varius lorem molestie vel. Sed at eros consequat, varius tellus + et, auctor felis. Donec pulvinar lacinia urna nec commodo. Phasellus at imperdiet risus. Donec sit amet + massa purus. + + + ) + })} @@ -589,8 +600,9 @@ NestedScrollContainer.argTypes = { export const CustomStickyHeader: Story = args => ( // a box to create a sticky top element that will be on the consumer side and outside of the PageLayout component - + ( - - {Array.from({length: args.numParagraphsInContent}).map((_, i) => ( - - Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam at enim id lorem tempus egestas a non ipsum. - Maecenas imperdiet ante quam, at varius lorem molestie vel. Sed at eros consequat, varius tellus et, - auctor felis. Donec pulvinar lacinia urna nec commodo. Phasellus at imperdiet risus. Donec sit amet massa - purus. Nunc sem lectus, bibendum a sapien nec, tristique tempus felis. Ut porttitor auctor tellus in - imperdiet. Ut blandit tincidunt augue, quis fringilla nunc tincidunt sed. Vestibulum auctor euismod nisi. - Nullam tincidunt est in mi tincidunt dictum. Sed consectetur aliquet velit ut ornare. - - ))} + + {Array.from({length: args.numParagraphsInContent}).map((_, i) => { + const testId = `content${i}` + return ( + + + Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam at enim id lorem tempus egestas a non + ipsum. Maecenas imperdiet ante quam, at varius lorem molestie vel. Sed at eros consequat, varius + tellus et, auctor felis. Donec pulvinar lacinia urna nec commodo. Phasellus at imperdiet risus. Donec + sit amet massa purus. Nunc sem lectus, bibendum a sapien nec, tristique tempus felis. Ut porttitor + auctor tellus in imperdiet. Ut blandit tincidunt augue, quis fringilla nunc tincidunt sed. Vestibulum + auctor euismod nisi. Nullam tincidunt est in mi tincidunt dictum. Sed consectetur aliquet velit ut + ornare. + + + ) + })} - {Array.from({length: args.numParagraphsInPane}).map((_, i) => ( - - Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam at enim id lorem tempus egestas a non ipsum. - Maecenas imperdiet ante quam, at varius lorem molestie vel. Sed at eros consequat, varius tellus et, - auctor felis. Donec pulvinar lacinia urna nec commodo. Phasellus at imperdiet risus. Donec sit amet massa - purus. - - ))} + {Array.from({length: args.numParagraphsInPane}).map((_, i) => { + const testId = `paragraph${i}` + return ( + + + Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam at enim id lorem tempus egestas a non + ipsum. Maecenas imperdiet ante quam, at varius lorem molestie vel. Sed at eros consequat, varius + tellus et, auctor felis. Donec pulvinar lacinia urna nec commodo. Phasellus at imperdiet risus. Donec + sit amet massa purus. + + + ) + })} diff --git a/src/PageLayout/interaction.stories.tsx b/src/PageLayout/interaction.stories.tsx new file mode 100644 index 00000000000..6c225176b0d --- /dev/null +++ b/src/PageLayout/interaction.stories.tsx @@ -0,0 +1,425 @@ +import {Meta} from '@storybook/react' +import {StickyPane, CustomStickyHeader} from './PageLayout.stories' +import {within} from '@storybook/testing-library' +import {expect} from '@storybook/jest' + +const meta: Meta = { + title: 'Layout/PageLayout/interactions', + // component: PageLayout, + parameters: { + layout: 'fullscreen', + controls: {expanded: true} + }, + argTypes: { + // Debug controls + 'Render header?': { + type: 'boolean', + defaultValue: true, + table: {category: 'Debug'} + }, + 'Render pane?': { + type: 'boolean', + defaultValue: true, + table: {category: 'Debug'} + }, + 'Render footer?': { + type: 'boolean', + defaultValue: true, + table: {category: 'Debug'} + }, + 'Header placeholder height': { + type: 'number', + defaultValue: 64, + table: {category: 'Debug'} + }, + 'Pane placeholder height': { + type: 'number', + defaultValue: 200, + table: {category: 'Debug'} + }, + 'Content placeholder height': { + type: 'number', + defaultValue: 400, + table: {category: 'Debug'} + }, + 'Footer placeholder height': { + type: 'number', + defaultValue: 64, + table: {category: 'Debug'} + }, + + // PageLayout prop controls + containerWidth: { + type: { + name: 'enum', + value: ['full', 'medium', 'large', 'xlarge'] + }, + defaultValue: 'xlarge', + control: {type: 'radio'}, + table: {category: 'PageLayout props'} + }, + padding: { + type: { + name: 'enum', + value: ['none', 'condensed', 'normal'] + }, + defaultValue: 'normal', + control: {type: 'radio'}, + table: {category: 'PageLayout props'} + }, + rowGap: { + type: { + name: 'enum', + value: ['none', 'condensed', 'normal'] + }, + defaultValue: 'normal', + control: {type: 'radio'}, + table: {category: 'PageLayout props'} + }, + columnGap: { + type: { + name: 'enum', + value: ['none', 'condensed', 'normal'] + }, + defaultValue: 'normal', + control: {type: 'radio'}, + table: {category: 'PageLayout props'} + }, + + // Header prop controls + 'Header.divider.regular': { + type: { + name: 'enum', + value: ['none', 'line'] + }, + defaultValue: 'none', + control: { + type: 'radio' + }, + table: { + category: 'Header props' + } + }, + 'Header.divider.narrow': { + type: { + name: 'enum', + value: ['none', 'line', 'filled'] + }, + defaultValue: 'none', + control: { + type: 'radio' + }, + table: { + category: 'Header props' + } + }, + 'Header.divider.wide': { + type: { + name: 'enum', + value: ['none', 'line'] + }, + defaultValue: 'none', + control: { + type: 'radio' + }, + table: { + category: 'Header props' + } + }, + 'Header.padding': { + type: { + name: 'enum', + value: ['none', 'condensed', 'normal'] + }, + defaultValue: 'none', + control: {type: 'radio'}, + table: {category: 'Header props'} + }, + 'Header.hidden.regular': { + type: 'boolean', + defaultValue: false, + table: {category: 'Header props'} + }, + 'Header.hidden.narrow': { + type: 'boolean', + defaultValue: false, + table: {category: 'Header props'} + }, + 'Header.hidden.wide': { + type: 'boolean', + defaultValue: false, + table: {category: 'Header props'} + }, + + // Content prop controls + 'Content.width': { + type: { + name: 'enum', + value: ['full', 'medium', 'large', 'xlarge'] + }, + defaultValue: 'full', + control: {type: 'radio'}, + table: {category: 'Content props'} + }, + 'Content.padding': { + type: { + name: 'enum', + value: ['none', 'condensed', 'normal'] + }, + defaultValue: 'none', + control: {type: 'radio'}, + table: {category: 'Content props'} + }, + 'Content.hidden.regular': { + type: 'boolean', + defaultValue: false, + table: {category: 'Content props'} + }, + 'Content.hidden.narrow': { + type: 'boolean', + defaultValue: false, + table: {category: 'Content props'} + }, + 'Content.hidden.wide': { + type: 'boolean', + defaultValue: false, + table: {category: 'Content props'} + }, + + // Pane prop controls + 'Pane.position.regular': { + type: { + name: 'enum', + value: ['start', 'end'] + }, + defaultValue: 'end', + control: {type: 'radio'}, + table: {category: 'Pane props'} + }, + 'Pane.position.narrow': { + type: { + name: 'enum', + value: ['start', 'end'] + }, + defaultValue: 'end', + control: {type: 'radio'}, + table: {category: 'Pane props'} + }, + 'Pane.position.wide': { + type: { + name: 'enum', + value: ['start', 'end'] + }, + defaultValue: 'end', + control: {type: 'radio'}, + table: {category: 'Pane props'} + }, + 'Pane.width': { + type: { + name: 'enum', + value: ['small', 'medium', 'large'] + }, + defaultValue: 'medium', + control: {type: 'radio'}, + table: {category: 'Pane props'} + }, + 'Pane.sticky': { + type: 'boolean', + defaultValue: false, + table: {category: 'Pane props'} + }, + 'Pane.padding': { + type: { + name: 'enum', + value: ['none', 'condensed', 'normal'] + }, + defaultValue: 'none', + control: {type: 'radio'}, + table: {category: 'Pane props'} + }, + 'Pane.divider.regular': { + type: { + name: 'enum', + value: ['none', 'line'] + }, + defaultValue: 'none', + control: {type: 'radio'}, + table: {category: 'Pane props'} + }, + 'Pane.divider.narrow': { + type: { + name: 'enum', + value: ['none', 'line', 'filled'] + }, + defaultValue: 'none', + control: {type: 'radio'}, + table: {category: 'Pane props'} + }, + 'Pane.divider.wide': { + type: { + name: 'enum', + value: ['none', 'line'] + }, + defaultValue: 'none', + control: {type: 'radio'}, + table: {category: 'Pane props'} + }, + + // Footer prop controls + 'Footer.divider.regular': { + type: { + name: 'enum', + value: ['none', 'line'] + }, + defaultValue: 'none', + control: { + type: 'radio' + }, + table: { + category: 'Footer props' + } + }, + 'Footer.divider.narrow': { + type: { + name: 'enum', + value: ['none', 'line', 'filled'] + }, + defaultValue: 'none', + control: { + type: 'radio' + }, + table: { + category: 'Footer props' + } + }, + 'Footer.divider.wide': { + type: { + name: 'enum', + value: ['none', 'line'] + }, + defaultValue: 'none', + control: { + type: 'radio' + }, + table: { + category: 'Footer props' + } + }, + 'Footer.padding': { + type: { + name: 'enum', + value: ['none', 'condensed', 'normal'] + }, + defaultValue: 'none', + control: {type: 'radio'}, + table: {category: 'Footer props'} + }, + 'Footer.hidden.regular': { + type: 'boolean', + defaultValue: false, + table: {category: 'Footer props'} + }, + 'Footer.hidden.narrow': { + type: 'boolean', + defaultValue: false, + table: {category: 'Footer props'} + }, + 'Footer.hidden.wide': { + type: 'boolean', + defaultValue: false, + table: {category: 'Footer props'} + } + } +} + +StickyPane.argTypes = { + sticky: { + type: 'boolean', + defaultValue: true + }, + numParagraphsInPane: { + type: 'number', + defaultValue: 3 + }, + numParagraphsInContent: { + type: 'number', + defaultValue: 30 + } +} + +const isInViewPort = (boundingRect: {top: number; left: number; right: number; bottom: number}) => { + return ( + boundingRect.top >= 0 && + boundingRect.left >= 0 && + boundingRect.right <= document.documentElement.clientWidth && + boundingRect.bottom <= document.documentElement.clientHeight + ) +} + +StickyPane.play = async ({canvasElement}: {canvasElement: HTMLElement}) => { + const canvas = within(canvasElement) + const content3 = await canvas.getByTestId('content3') + content3.scrollIntoView() + const paragraph0 = await canvas.getByTestId('paragraph0') + const paragraphRect = paragraph0.getBoundingClientRect() + expect(isInViewPort(paragraphRect)).toBe(true) +} + +const NonStickyPane = StickyPane.bind({}) +NonStickyPane.argTypes = { + sticky: { + type: 'boolean', + defaultValue: false + }, + numParagraphsInPane: { + type: 'number', + defaultValue: 6 + }, + numParagraphsInContent: { + type: 'number', + defaultValue: 30 + } +} + +NonStickyPane.play = async ({canvasElement}: {canvasElement: HTMLElement}) => { + const canvas = within(canvasElement) + const content3 = await canvas.getByTestId('content3') + content3.scrollIntoView() + const paragraph0 = await canvas.getByTestId('paragraph0') + const paragraphRect = paragraph0.getBoundingClientRect() + expect(isInViewPort(paragraphRect)).toBe(false) +} + +CustomStickyHeader.argTypes = { + sticky: { + type: 'boolean', + defaultValue: true + }, + stickyTop: { + type: 'string', + defaultValue: '8rem' + }, + numParagraphsInPane: { + type: 'number', + defaultValue: 10 + }, + numParagraphsInContent: { + type: 'number', + defaultValue: 30 + } +} + +CustomStickyHeader.play = async ({canvasElement}: {canvasElement: HTMLElement}) => { + const canvas = within(canvasElement) + const contentToScroll = await canvas.getByTestId('content3') + contentToScroll.scrollIntoView() + + const stickyPaneFirstParagraph = await canvas.getByTestId('paragraph0') + const paragraphBoundaries = stickyPaneFirstParagraph.getBoundingClientRect() + const stickyHeader = await canvas.getByTestId('sticky-header') + const stickyHeaderBoundaries = stickyHeader.getBoundingClientRect() + expect(isInViewPort(paragraphBoundaries)).toBe(true) + expect(isInViewPort(stickyHeaderBoundaries)).toBe(true) +} +export default meta +export {StickyPane, NonStickyPane, CustomStickyHeader}