Skip to content

Commit c6a48e2

Browse files
authored
chore: create a github workflow that runs percy on the latest website deploy for VRT baseline (twilio-labs#2677)
1 parent 9825576 commit c6a48e2

File tree

22 files changed

+190
-91
lines changed

22 files changed

+190
-91
lines changed

.github/workflows/on_merge_to_main.yml

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,3 +183,91 @@ jobs:
183183
exitOnceUploaded: true
184184
env:
185185
STORYBOOK_GITHUB_SHA: ${{ github.sha }}
186+
187+
# run this job first to create a single timestamped id for all percy batches on parallel machines
188+
percy-batch-id:
189+
runs-on: ubuntu-latest
190+
# persist job results to other jobs in the workflow
191+
outputs:
192+
result: ${{ steps.percy-batch-id.outputs.result }}
193+
steps:
194+
# persist step results to other steps in the job
195+
- name: Create Percy Batch ID
196+
id: percy-batch-id
197+
# adding a timestamp makes the batch id more unique for re-runs
198+
run: echo "::set-output name=result::${{ github.run_id }}-$(date +%s)"
199+
200+
# run cypress against main so we can create Percy baselines with the latest code
201+
cypress:
202+
name: Website tests
203+
runs-on: ubuntu-latest
204+
needs: percy-batch-id
205+
strategy:
206+
fail-fast: false
207+
matrix:
208+
containers: [1, 2, 3]
209+
env:
210+
CYPRESS_CACHE_FOLDER: ./node_modules/cypress
211+
CYPRESS_RECORD_KEY: ${{ secrets.CYPRESS_RECORD_KEY }}
212+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
213+
PERCY_TOKEN: ${{ secrets.PERCY_TOKEN }}
214+
USE_CYPRESS_VRT: true
215+
216+
steps:
217+
- name: Checkout Repo
218+
uses: actions/checkout@v2
219+
220+
- name: Setup Node.js 16.13
221+
uses: actions/setup-node@v2
222+
with:
223+
node-version: 16.13.x
224+
225+
- name: Get yarn cache directory path
226+
id: yarn-cache-dir-path
227+
run: echo "::set-output name=dir::$(yarn config get cacheFolder)"
228+
229+
- name: Percy Batch ID
230+
run: echo "${{ needs.percy-batch-id.outputs.result }}"
231+
232+
- name: Load Yarn cache
233+
uses: actions/cache@v2
234+
id: yarn_cache_id
235+
with:
236+
path: ${{ steps.yarn-cache-dir-path.outputs.dir }}
237+
key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }}
238+
restore-keys: |
239+
${{ runner.os }}-yarn
240+
241+
- name: Node modules cache
242+
uses: actions/cache@v2
243+
id: node_modules_cache_id
244+
with:
245+
path: |
246+
node_modules
247+
*/*/node_modules
248+
key: ${{ runner.os }}-${{ hashFiles('**/yarn.lock') }}
249+
250+
- name: Install Dependencies
251+
if: steps.yarn_cache_id.outputs.cache-hit != 'true' || steps.node_modules_cache_id.outputs.cache-hit != 'true'
252+
run: yarn install --immutable
253+
254+
- name: Wait for Netlify
255+
uses: hharnisc/[email protected]
256+
id: waitForDeployment
257+
with:
258+
site_id: ${{ secrets.NETLIFY_SITE_ID }}
259+
env:
260+
NETLIFY_TOKEN: ${{ secrets.NETLIFY_TOKEN }}
261+
262+
- name: Cypress run with site VRT
263+
uses: cypress-io/[email protected]
264+
with:
265+
record: true
266+
parallel: true
267+
group: "Paste Actions with VRT Parallel"
268+
config: baseUrl=${{ steps.waitForDeployment.outputs.url }}
269+
# enabled percy to run cypress for VRT
270+
command-prefix: "percy exec --parallel -- npx"
271+
env:
272+
PERCY_PARALLEL_NONCE: ${{ needs.percy-batch-id.outputs.result }}
273+
PERCY_PARALLEL_TOTAL: 3

.github/workflows/on_pull_request_cypress.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ jobs:
8080
NETLIFY_TOKEN: ${{ secrets.NETLIFY_TOKEN }}
8181

8282
- name: Cypress run
83-
uses: cypress-io/github-action@v2
83+
uses: cypress-io/github-action@v4.2.0
8484
if: ${{ !contains(github.event.pull_request.labels.*.name, '🕵🏻‍♀️ Run website visual regression') }}
8585
with:
8686
record: true
@@ -89,7 +89,7 @@ jobs:
8989
config: baseUrl=${{ steps.waitForDeployment.outputs.url }}
9090

9191
- name: Cypress run with site VRT
92-
uses: cypress-io/github-action@v2
92+
uses: cypress-io/github-action@v4.2.0
9393
if: ${{ contains(github.event.pull_request.labels.*.name, '🕵🏻‍♀️ Run website visual regression') }}
9494
with:
9595
record: true

cypress.config.ts

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import {defineConfig} from 'cypress';
2+
3+
// eslint-disable-next-line import/no-default-export
4+
export default defineConfig({
5+
e2e: {
6+
baseUrl: 'http://localhost:8000',
7+
env: {
8+
USE_CYPRESS_VRT: process.env.USE_CYPRESS_VRT,
9+
},
10+
viewportWidth: 1440,
11+
viewportHeight: 1020,
12+
projectId: 'pe4h41',
13+
retries: {
14+
runMode: 2,
15+
openMode: 2,
16+
},
17+
video: false,
18+
blockHosts: [
19+
'*.google-analytics.com',
20+
'*.codesandbox.io',
21+
'codesandbox.io',
22+
'*.loom.com',
23+
'*.youtube.com',
24+
'*.github.com',
25+
'*.googletagmanager.com',
26+
],
27+
specPattern: ['cypress/**/*.spec.ts'],
28+
},
29+
});

cypress.json

Lines changed: 0 additions & 21 deletions
This file was deleted.

cypress/plugins/index.js

Lines changed: 0 additions & 26 deletions
This file was deleted.

cypress/support/commands/child-commands.ts

Lines changed: 0 additions & 7 deletions
This file was deleted.

cypress/support/commands/dual-commands.ts

Lines changed: 0 additions & 7 deletions
This file was deleted.

cypress/support/commands/index.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1 @@
1-
import './child-commands';
21
import './parent-commands';

cypress/support/commands/override-commands.ts

Lines changed: 0 additions & 7 deletions
This file was deleted.

cypress/support/commands/parent-commands.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import {DEFAULT_VRT_OPTIONS, vrtIsEnabled} from 'support/utils/vrt';
1+
import {DEFAULT_VRT_OPTIONS, vrtIsEnabled} from '../utils/vrt';
22

33
/**
44
* @file Custom parent commands
@@ -108,6 +108,13 @@ Cypress.Commands.add('visualRegressionTestUrl', ({url, testName}) => {
108108
...DEFAULT_VRT_OPTIONS,
109109
};
110110

111+
// Date and time pickers, and anywhere that displays the current date and time
112+
// Will cause a VRT diff every time it is run as the time is always changing
113+
// By freezing the date we can guarantee that displayed current date and time never
114+
// changes across snapshots
115+
const now = new Date(2018, 1, 1);
116+
cy.clock(now);
117+
111118
// Take a snapshot for visual diffing
112119
cy.log(`[VRT]: Taking snapshot with these params: ${vrtOptions}`);
113120
cy.percySnapshot(testName, vrtOptions);
File renamed without changes.

cypress/tsconfig.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
{
22
"compilerOptions": {
3+
"forceConsistentCasingInFileNames": true,
34
"strict": true,
45
"target": "es5",
56
"lib": ["es2017", "DOM"],
67
"types": ["cypress", "@percy/cypress"],
78
"baseUrl": ".",
8-
"moduleResolution": "node"
9+
"moduleResolution": "node",
10+
"isolatedModules": false
911
},
1012
"include": ["./**/*.ts"],
1113
"exclude": ["node_modules/**/*"]

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,7 @@
174174
"concurrently": "^4.1.1",
175175
"cross-env": "^5.2.0",
176176
"csstype": "3.0.11",
177-
"cypress": "9.3.1",
177+
"cypress": "10.8.0",
178178
"danger": "^10.6.6",
179179
"del": "^5.1.0",
180180
"directory-named-webpack-plugin": "^4.0.1",

packages/paste-website/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,7 @@
137137
"react-scrollspy": "^3.4.0",
138138
"react-visibility-sensor": "5.1.1",
139139
"rollbar": "^2.25.0",
140+
"typescript": "^4.6.4",
140141
"use-resize-observer": "^7.0.0",
141142
"winston": "^3.8.1"
142143
},

packages/paste-website/src/component-examples/DataVisualizationExamples.tsx

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import type {ThemeShape} from '@twilio-paste/theme';
55
import {ColorSwatchText} from '../components/color-swatch/ColorSwatch';
66
import {ImageCaption} from '../components/ImageCaption';
77
import {StyledSwatchGrid} from './ColorsFoundationExamples';
8+
import {inCypress} from '../utils/inCypress';
89

910
interface TokenData {
1011
name: string;
@@ -36,7 +37,7 @@ export const DataVizColorSwatches: React.FC = () => {
3637
<Box as="ul" margin="space0" padding="space0" marginBottom="space70">
3738
<StyledSwatchGrid numberColumns={5}>
3839
{dataVizTokenValues.map(({name, value}) => (
39-
<Box as="li" listStyleType="none">
40+
<Box as="li" listStyleType="none" key={`${name}-${value}`}>
4041
<StyledSwatch backgroundColor={value} />
4142
<ColorSwatchText>{name}</ColorSwatchText>
4243
</Box>
@@ -63,24 +64,33 @@ export const LineChartCaption: React.FC = () => (
6364
export const LineChartOptions = {
6465
title: {text: 'Solar Employment Growth by Sector, 2010-2016'},
6566
subtitle: {text: 'Source: thesolarfoundation.com'},
67+
chart: {
68+
//this controls animation of updates, to disable animation on initial render you have to disable animation on the series
69+
animation: !inCypress(),
70+
},
6671
series: [
6772
{
73+
animation: !inCypress(),
6874
name: 'Installation',
6975
data: [43934, 52503, 57177, 69658, 97031, 119931, 137133, 154175],
7076
},
7177
{
78+
animation: !inCypress(),
7279
name: 'Manufacturing',
7380
data: [24916, 24064, 29742, 29851, 32490, 30282, 38121, 40434],
7481
},
7582
{
83+
animation: !inCypress(),
7684
name: 'Sales & Distribution',
7785
data: [11744, 17722, 16005, 19771, 20185, 24377, 32147, 39387],
7886
},
7987
{
88+
animation: !inCypress(),
8089
name: 'Project Development',
8190
data: [null, null, 7988, 12169, 15112, 22452, 34400, 34227],
8291
},
8392
{
93+
animation: !inCypress(),
8494
name: 'Other',
8595
data: [12908, 5948, 8105, 11248, 8989, 11816, 18274, 18111],
8696
},

packages/paste-website/src/components/homepage/HomeHeroIllustration.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import {useReducedMotion} from '@twilio-paste/animation-library';
55
import lottie from 'lottie-web';
66
import VisibilitySensor from 'react-visibility-sensor';
77
import HomeHeroIllu from '../../assets/illustrations/home_hero.svg';
8+
import {inCypress} from '../../utils/inCypress';
89

910
const IllustrationStates = {
1011
UNINITIALIZED: 0, // This is SSR too
@@ -32,7 +33,9 @@ const IllustrationChildren: React.FC<{state: IllustrationStatesType}> = ({state}
3233
* - If prefers reduced motion, render static.
3334
*/
3435
const HomeHeroIllustration: React.FC = () => {
35-
const prefersReducedMotion = useReducedMotion();
36+
// lottie doesn't honour our disableAnimations global, so we have to
37+
// manually detect running in cypress to stop the animation on the homepage
38+
const prefersReducedMotion = useReducedMotion() || inCypress();
3639
const containerRef = React.useRef(null);
3740
const [illustrationState, setIllustrationState] = React.useState(IllustrationStates.UNINITIALIZED);
3841

packages/paste-website/src/components/site-wrapper/index.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import {SkipLinkContainer} from '../SkipLinkContainer';
1010
import {PASTE_DOCS_CONTENT_AREA, PASTE_DOCS_SEARCH_INPUT, SITE_BREAKPOINTS} from '../../constants';
1111
import type {NavigationQuery} from '../../context/NavigationContext';
1212
import {DarkModeContext} from '../../context/DarkModeContext';
13+
import {inCypress} from '../../utils/inCypress';
1314

1415
const pageQuery = graphql`
1516
{
@@ -78,7 +79,7 @@ const SiteWrapper: React.FC<SiteWrapperProps> = ({pathname, children}) => {
7879
const [theme, toggleMode, componentMounted] = useDarkMode();
7980

8081
return (
81-
<Theme.Provider theme={theme} customBreakpoints={SITE_BREAKPOINTS}>
82+
<Theme.Provider theme={theme} customBreakpoints={SITE_BREAKPOINTS} disableAnimations={inCypress()}>
8283
<NavigationContext.Provider value={{...navigationQueryData, pathname}}>
8384
<DarkModeContext.Provider value={{theme, toggleMode, componentMounted}}>
8485
<SkipLinkContainer>

packages/paste-website/src/utils/RouteUtils.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import toLower from 'lodash/toLower';
55
import {useLocation} from '@reach/router';
66
import {PASTE_PACKAGE_PREFIX, SidebarCategoryRoutes} from '../constants';
77

8-
const hasWindowObject = (): boolean => typeof window !== `undefined` && window.location != null;
8+
export const hasWindowObject = (): boolean => typeof window !== `undefined` && window.location != null;
99

1010
// Gets the current browser pathname
1111
export function useLocationPathname(): string {
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import {hasWindowObject} from './RouteUtils';
2+
3+
export const inCypress = (): boolean => {
4+
if (hasWindowObject() && window.Cypress) {
5+
return true;
6+
}
7+
return false;
8+
};

packages/paste-website/types/index.d.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
interface Window {
2+
Cypress: Record<string, string>;
3+
}
4+
15
declare module "*.svg" {
26
const content: any;
37
export default content;

tsconfig.json

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,14 @@
2626
"resolveJsonModule": true,
2727
"esModuleInterop": true
2828
},
29-
"include": ["packages/**/*", "dangerfile.ts", ".danger/**/*", "./.jest/@types/index.d.ts", "tools/**/*"],
29+
"include": [
30+
"packages/**/*",
31+
"dangerfile.ts",
32+
".danger/**/*",
33+
"./.jest/@types/index.d.ts",
34+
"tools/**/*",
35+
"cypress.config.ts"
36+
],
3037
"exclude": [
3138
"node_modules",
3239
"docs",

0 commit comments

Comments
 (0)