From 25f59d1353ed8354d780eaf35f9cdd9c2e52e58d Mon Sep 17 00:00:00 2001 From: Lachlan Miller Date: Thu, 20 May 2021 11:09:15 +1000 Subject: [PATCH 1/8] fix(runner-ct): viewport scaling during screenshots (#16543) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix: correctly scale viewport * correct height * consider max width * update tests * remove unneeded css Co-authored-by: Barthélémy Ledoux --- .../cypress/component/screenshot.spec.tsx | 75 ++++++++++++++++++- packages/runner-ct/src/app/RunnerCt.scss | 5 ++ .../src/app/useScreenshotHandler.tsx | 8 ++ packages/runner-ct/src/iframe/iframes.jsx | 2 +- packages/runner-ct/src/iframe/iframes.scss | 1 + 5 files changed, 89 insertions(+), 2 deletions(-) diff --git a/packages/runner-ct/cypress/component/screenshot.spec.tsx b/packages/runner-ct/cypress/component/screenshot.spec.tsx index cd4aa86ebbfd..eb5bb67d1f48 100644 --- a/packages/runner-ct/cypress/component/screenshot.spec.tsx +++ b/packages/runner-ct/cypress/component/screenshot.spec.tsx @@ -56,7 +56,7 @@ describe('screenshot', () => { // TODO: This will technically pass, but the screenshot is not correct. // AUT transform appears to be buggy for extreme viewports. - xit('screenshot with a really long viewport', () => { + it('screenshot with a really long viewport', () => { cy.viewport(200, 2000) mount(, { styles, @@ -64,4 +64,77 @@ describe('screenshot', () => { cy.screenshot('percy/component_testing_screenshot_long_viewport') }) + + const style = ` + html, body { + margin: 0; + padding: 0; + } + * { + box-sizing: content-box; + } + .wrapper { + width: 1500px; + height: 1000px; + display: grid; + grid-template-columns: repeat(3, 1fr); + gap: 10px; + grid-auto-rows: minmax(100px, auto); + } + .wrapper > div { + border: 5px solid orange; + border-radius: 10px; + padding: 10px; + margin: 10px; + background: rgba(233,171,88,.5); + } + .one { + grid-column: 1 / 3; + grid-row: 1; + } + .two { + grid-column: 2 / 4; + grid-row: 1 / 3; + } + .three { + grid-column: 1; + grid-row: 2 / 5; + } + .four { + grid-column: 3; + grid-row: 3; + } + .five { + grid-column: 2; + grid-row: 4; + } + .six { + grid-column: 3; + grid-row: 4; + } + ` + + ;[[1500, 850], [1500, 1000]].forEach((viewport) => { + it(`works with a large component with viewport ${viewport[0]} x ${viewport[1]}`, () => { + cy.viewport(viewport[0], viewport[1]) + + const Comp = () => { + return ( +
+
One
+
Two
+
Three
+
Four
+
Five
+
Six
+
+ ) + } + + mount(, { style }).then(() => { + cy.screenshot(`percy/large_component_hardcoded_size_viewport_${viewport[0]}_${viewport[1]}`, { capture: 'viewport' }) + cy.screenshot(`percy/large_component_hardcoded_size_fullPage_${viewport[0]}_${viewport[1]}`, { capture: 'fullPage' }) + }) + }) + }) }) diff --git a/packages/runner-ct/src/app/RunnerCt.scss b/packages/runner-ct/src/app/RunnerCt.scss index c8a1bb569fd6..7660b7667fb7 100644 --- a/packages/runner-ct/src/app/RunnerCt.scss +++ b/packages/runner-ct/src/app/RunnerCt.scss @@ -32,6 +32,11 @@ body, html { background-image: url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI1IiBoZWlnaHQ9IjUiPgo8cmVjdCB3aWR0aD0iNSIgaGVpZ2h0PSI1IiBmaWxsPSIjZGJkYmRiIj48L3JlY3Q+CjxwYXRoIGQ9Ik0wIDVMNSAwWk02IDRMNCA2Wk0tMSAxTDEgLTFaIiBzdHJva2U9IiNjNGM0YzQiIHN0cm9rZS13aWR0aD0iMSI+PC9wYXRoPgo8L3N2Zz4="); } +.aut-iframe-screenshotting { + height: min(100vh, 100%) !important; + overflow: scroll !important; +} + // Prevent left-most Resizer from showing up when the pane is hidden. .isSpecsListClosed { > .Resizer { diff --git a/packages/runner-ct/src/app/useScreenshotHandler.tsx b/packages/runner-ct/src/app/useScreenshotHandler.tsx index 85df57d07a62..96a988ec2ab9 100644 --- a/packages/runner-ct/src/app/useScreenshotHandler.tsx +++ b/packages/runner-ct/src/app/useScreenshotHandler.tsx @@ -25,6 +25,10 @@ export function useScreenshotHandler ({ eventManager, state, splitPaneRef }: { splitPaneRef.current.splitPane.firstElementChild.classList.remove('d-none') splitPaneRef.current.splitPane.querySelector('[role="presentation"]').classList.remove('d-none') + + const iframe = document.querySelector('.aut-iframe') + + iframe.classList.remove('aut-iframe-screenshotting') } const hidePane = () => { @@ -34,6 +38,10 @@ export function useScreenshotHandler ({ eventManager, state, splitPaneRef }: { splitPaneRef.current.splitPane.firstElementChild.classList.add('d-none') splitPaneRef.current.splitPane.querySelector('[role="presentation"]').classList.add('d-none') + + const iframe = document.querySelector('.aut-iframe') + + iframe.classList.add('aut-iframe-screenshotting') } React.useEffect(() => { diff --git a/packages/runner-ct/src/iframe/iframes.jsx b/packages/runner-ct/src/iframe/iframes.jsx index 0335b0059153..6219020095f4 100644 --- a/packages/runner-ct/src/iframe/iframes.jsx +++ b/packages/runner-ct/src/iframe/iframes.jsx @@ -45,7 +45,7 @@ export default class Iframes extends Component { style={{ height: viewportHeight, width: viewportWidth, - transform: `scale(${scale})`, + transform: `scale(${screenshotting ? 1 : scale})`, }} /> diff --git a/packages/runner-ct/src/iframe/iframes.scss b/packages/runner-ct/src/iframe/iframes.scss index 658d80ddb313..76b8b66e92fb 100644 --- a/packages/runner-ct/src/iframe/iframes.scss +++ b/packages/runner-ct/src/iframe/iframes.scss @@ -16,4 +16,5 @@ .size-container { overflow: auto; box-shadow: shadow(m); + max-width: 100%; } From 2ec343b40e428088138b058d0b9b859385bb46e9 Mon Sep 17 00:00:00 2001 From: Adam Gastineau Date: Wed, 19 May 2021 19:38:53 -0700 Subject: [PATCH 2/8] chore: Added Percy snapshots for design system (#16566) * chore: Added Percy snapshots for design system * Add PERCY_TOKEN to design-system CI * Remove accidental "yarn" string Co-authored-by: Lachlan Miller --- circle.yml | 9 ++- npm/design-system/cypress.json | 6 +- npm/design-system/cypress/support/index.js | 1 + .../src/components/Nav/LeftNav.spec.tsx | 3 +- .../src/components/fileTree/FileTree.spec.tsx | 5 +- .../searchInput/SearchInput.spec.tsx | 5 +- .../virtualizedTree/VirtualizedTree.spec.tsx | 10 ++-- .../src/core/button/Button.spec.tsx | 28 +++++++++ .../src/core/button/Button.stories.tsx | 28 ++++----- npm/design-system/src/core/icon/Icon.spec.tsx | 28 +++++++++ .../src/core/icon/Icon.stories.tsx | 58 +++++++++---------- .../src/core/input/Input.spec.tsx | 28 +++++++++ .../src/core/input/Input.stories.tsx | 45 +++++++------- .../core/surface/elevation/Elevation.spec.tsx | 14 +++++ .../surface/elevation/Elevation.stories.tsx | 31 +++++----- .../core/surface/paddedBox/PaddedBox.spec.tsx | 14 +++++ .../surface/paddedBox/PaddedBox.stories.tsx | 29 +++++----- .../text/placeholder/Placeholder.spec.tsx | 14 +++++ .../text/placeholder/Placeholder.stories.tsx | 2 +- .../core/text/styledText/StyledText.spec.tsx | 18 ++++++ .../text/styledText/StyledText.stories.tsx | 44 +++++++------- npm/design-system/src/stories/util.ts | 4 +- npm/design-system/src/util/testing.ts | 9 +++ npm/design-system/tsconfig.json | 4 +- 24 files changed, 301 insertions(+), 136 deletions(-) create mode 100644 npm/design-system/src/core/button/Button.spec.tsx create mode 100644 npm/design-system/src/core/icon/Icon.spec.tsx create mode 100644 npm/design-system/src/core/input/Input.spec.tsx create mode 100644 npm/design-system/src/core/surface/elevation/Elevation.spec.tsx create mode 100644 npm/design-system/src/core/surface/paddedBox/PaddedBox.spec.tsx create mode 100644 npm/design-system/src/core/text/placeholder/Placeholder.spec.tsx create mode 100644 npm/design-system/src/core/text/styledText/StyledText.spec.tsx create mode 100644 npm/design-system/src/util/testing.ts diff --git a/circle.yml b/circle.yml index c10c458189aa..72dbe41359ba 100644 --- a/circle.yml +++ b/circle.yml @@ -1353,7 +1353,14 @@ jobs: command: yarn workspace @cypress/design-system build - run: name: Run tests - command: yarn test --reporter cypress-circleci-reporter --reporter-options resultsDir=./test_results + # will use PERCY_TOKEN environment variable if available + command: | + CYPRESS_KONFIG_ENV=production \ + PERCY_PARALLEL_NONCE=$CIRCLE_WORKFLOW_ID \ + PERCY_ENABLE=${PERCY_TOKEN:-0} \ + PERCY_PARALLEL_TOTAL=-1 \ + yarn percy exec --parallel -- -- \ + yarn test --reporter cypress-circleci-reporter --reporter-options resultsDir=./test_results working_directory: npm/design-system - store_test_results: path: npm/design-system/test_results diff --git a/npm/design-system/cypress.json b/npm/design-system/cypress.json index 65f6885eb73c..00494ad9b75c 100644 --- a/npm/design-system/cypress.json +++ b/npm/design-system/cypress.json @@ -1,6 +1,6 @@ { - "viewportWidth": 400, - "viewportHeight": 400, + "viewportWidth": 1024, + "viewportHeight": 800, "video": false, "projectId": "z9dxah", "testFiles": "**/*spec.{js,jsx,ts,tsx}", @@ -13,4 +13,4 @@ ], "componentFolder": "src", "fixturesFolder": false -} \ No newline at end of file +} diff --git a/npm/design-system/cypress/support/index.js b/npm/design-system/cypress/support/index.js index c5ecc8a83e5f..1ae415651555 100644 --- a/npm/design-system/cypress/support/index.js +++ b/npm/design-system/cypress/support/index.js @@ -1,5 +1,6 @@ import 'regenerator-runtime/runtime' import 'cypress-real-events/support' +import '@percy/cypress' import './storybook' // Need to register these once per app. Depending which components are consumed diff --git a/npm/design-system/src/components/Nav/LeftNav.spec.tsx b/npm/design-system/src/components/Nav/LeftNav.spec.tsx index 820e4e319e2d..96eeaf539351 100644 --- a/npm/design-system/src/components/Nav/LeftNav.spec.tsx +++ b/npm/design-system/src/components/Nav/LeftNav.spec.tsx @@ -4,6 +4,7 @@ import { library } from '@fortawesome/fontawesome-svg-core' import { fab } from '@fortawesome/free-brands-svg-icons' import { fas } from '@fortawesome/free-solid-svg-icons' +import { mountAndSnapshot } from 'util/testing' import { NavItem } from './types' import { LeftNav } from './LeftNav' @@ -43,7 +44,7 @@ describe('LeftNav', () => { }) it('renders a stack of items', () => { - mount() + mountAndSnapshot() cy.get('nav').should('exist') }) diff --git a/npm/design-system/src/components/fileTree/FileTree.spec.tsx b/npm/design-system/src/components/fileTree/FileTree.spec.tsx index ecb30fccb776..cc52c38c21ed 100644 --- a/npm/design-system/src/components/fileTree/FileTree.spec.tsx +++ b/npm/design-system/src/components/fileTree/FileTree.spec.tsx @@ -1,6 +1,7 @@ import React from 'react' import { mount } from '@cypress/react' -import { FileTree } from './index' +import { FileTree } from './FileTree' +import { mountAndSnapshot } from 'util/testing' const files = [ { @@ -36,7 +37,7 @@ describe('FileTree', () => { it('should send onFilePress callback on space and enter', () => { const filePressStub = cy.stub() - mount( + mountAndSnapshot(
, diff --git a/npm/design-system/src/components/searchInput/SearchInput.spec.tsx b/npm/design-system/src/components/searchInput/SearchInput.spec.tsx index c5fd9163040c..a91f97c649ab 100644 --- a/npm/design-system/src/components/searchInput/SearchInput.spec.tsx +++ b/npm/design-system/src/components/searchInput/SearchInput.spec.tsx @@ -3,6 +3,7 @@ import { mount } from '@cypress/react' import { SearchInput } from './SearchInput' import { useCallback, useState } from 'react' +import { mountAndSnapshot } from 'util/testing' describe('SearchInput', () => { const StatefulWrapper: React.FC<{onInput?: (input: string) => void}> = ({ onInput }) => { @@ -18,7 +19,7 @@ describe('SearchInput', () => { } it('should render', () => { - mount( {}} />) + mountAndSnapshot( {}} />) cy.get('input').should('exist') }) @@ -47,6 +48,8 @@ describe('SearchInput', () => { cy.get('input').type('some input') cy.get('[aria-label="Clear search"]').should('exist') + + cy.percySnapshot() }) it('should clear input on click', () => { diff --git a/npm/design-system/src/components/virtualizedTree/VirtualizedTree.spec.tsx b/npm/design-system/src/components/virtualizedTree/VirtualizedTree.spec.tsx index 01bdaa89b490..529e668fd7df 100644 --- a/npm/design-system/src/components/virtualizedTree/VirtualizedTree.spec.tsx +++ b/npm/design-system/src/components/virtualizedTree/VirtualizedTree.spec.tsx @@ -1,12 +1,14 @@ import * as React from 'react' -import { mount } from '@cypress/react' import { composeStories } from '@storybook/testing-react' -import * as stories from './VirtualizedTree.stories' +import { mountAndSnapshot } from 'util/testing' + +import * as stories from './VirtualizedTree.stories' const { VirtualizedTree } = composeStories(stories) +// TODO: Autogenerate from stories describe('', () => { - it('playground', () => { - mount() + it('VirtualizedTree', () => { + mountAndSnapshot() }) }) diff --git a/npm/design-system/src/core/button/Button.spec.tsx b/npm/design-system/src/core/button/Button.spec.tsx new file mode 100644 index 000000000000..68b7f7a0353f --- /dev/null +++ b/npm/design-system/src/core/button/Button.spec.tsx @@ -0,0 +1,28 @@ +import * as React from 'react' +import { composeStories } from '@storybook/testing-react' + +import { mountAndSnapshot } from 'util/testing' + +import * as stories from './Button.stories' +const { Button, IconButton } = composeStories(stories) + +// TODO: Autogenerate from stories +describe(' ))} {ifThen(!appState.isPaused, ( - + {appState.autoScrollingEnabled ? 'Disable' : 'Enable'} Auto-scrolling A

} className='cy-tooltip'>
diff --git a/packages/reporter/src/lib/events.ts b/packages/reporter/src/lib/events.ts index cf5d3ba9fa14..c6bca4489f80 100644 --- a/packages/reporter/src/lib/events.ts +++ b/packages/reporter/src/lib/events.ts @@ -152,6 +152,8 @@ const events: Events = { })) localBus.on('next', action('next', () => { + appState.resume() + statsStore.resume() runner.emit('runner:next') })) diff --git a/packages/reporter/src/lib/shortcuts.ts b/packages/reporter/src/lib/shortcuts.ts index 9bf2de2e99d9..43e3f9b6a27a 100644 --- a/packages/reporter/src/lib/shortcuts.ts +++ b/packages/reporter/src/lib/shortcuts.ts @@ -2,6 +2,7 @@ import dom from '@packages/driver/src/dom' import events from './events' import appState from './app-state' +import { action } from 'mobx' class Shortcuts { start () { @@ -23,6 +24,15 @@ class Shortcuts { case 's': !appState.isPaused && !appState.studioActive && events.emit('stop') break case 'f': events.emit('focus:tests') + break + case 'c': events.emit('resume') + break + case 'n': events.emit('next') + break + case 'a': action('set:scrolling', () => { + appState.setAutoScrolling(!appState.autoScrollingEnabled) + })() + break default: return } From 340a6e4dd87357eefe8f064ef3220d35141d875e Mon Sep 17 00:00:00 2001 From: Adam Gastineau Date: Thu, 20 May 2021 09:16:58 -0700 Subject: [PATCH 8/8] chore: Fix design system flake (#16604) --- npm/design-system/src/components/fileTree/FileTree.spec.tsx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/npm/design-system/src/components/fileTree/FileTree.spec.tsx b/npm/design-system/src/components/fileTree/FileTree.spec.tsx index cc52c38c21ed..c3c193cbf9be 100644 --- a/npm/design-system/src/components/fileTree/FileTree.spec.tsx +++ b/npm/design-system/src/components/fileTree/FileTree.spec.tsx @@ -119,6 +119,8 @@ describe('FileTree', () => { cy.get('[data-cy=virtualized-tree] > div').scrollTo('bottom') + cy.contains('.treeChild', 'File 99').should('be.visible') + cy.get('[data-cy=virtualized-tree]').focus().type('{downarrow}').type('{downarrow}') cy.contains('.treeChild', 'File 3').should('be.visible')