Skip to content

Commit

Permalink
feat: setup interaction testing (#1895)
Browse files Browse the repository at this point in the history
Co-authored-by: Chaitanya Deorukhkar <deorukhkarchaitanya@gmail.com>
Co-authored-by: Nitin Kumar <nitin.kumar@razorpay.com>
Co-authored-by: Nitin Kumar <snitin315@gmail.com>
Co-authored-by: anuraghazra <anurag.hazra@razorpay.com>
  • Loading branch information
5 people authored Jan 10, 2024
1 parent 817a616 commit cad80ef
Show file tree
Hide file tree
Showing 14 changed files with 1,906 additions and 450 deletions.
37 changes: 37 additions & 0 deletions .github/workflows/blade-interaction-tests.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
name: Blade Interaction Tests

# Runs the action when
# 1. 'Run Interaction Tests' label is added to PR
# 2. Workflow is trigerred manually
# 3. PR is merged to master

on:
workflow_dispatch:
pull_request:
types: [labeled]
push:
branches:
- 'master'

env:
GITHUB_ACCESS_TOKEN: ${{ secrets.CI_BOT_TOKEN }}

jobs:
interaction-tests:
name: Run Interaction Tests
runs-on: ubuntu-latest # nosemgrep: non-self-hosted-runner
if: ${{ github.event_name == 'workflow_dispatch' || github.event.label.name == 'Run Interaction Tests' || github.event_name == 'push' }}
steps:
- name: Checkout Codebase
uses: actions/checkout@v3
- name: Use Node v18
uses: actions/setup-node@v3
with:
node-version: 18.12.1
- name: Setup Cache & Install Dependencies
uses: ./.github/actions/install-dependencies
- name: Run Interaction Tests
run: |
npx playwright install chromium firefox webkit --with-deps
yarn test:react:interaction:ci
working-directory: packages/blade
2 changes: 1 addition & 1 deletion .github/workflows/blade-validate.yml
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ jobs:
node-version: 18.12.1
- name: Setup Cache & Install Dependencies
uses: ./.github/actions/install-dependencies
- name: Run React & React Native Tests
- name: Run Unit Tests
run: yarn test
working-directory: packages/blade
env:
Expand Down
189 changes: 97 additions & 92 deletions packages/blade/.storybook/react-native/storybook.requires.js

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions packages/blade/.storybook/react/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ const config: StorybookConfig = {
'@storybook/addon-docs',
'@storybook/addon-a11y',
'@storybook/preset-create-react-app',
'@storybook/addon-interactions'
],
framework: {
name: '@storybook/react-webpack5',
Expand Down
16 changes: 15 additions & 1 deletion packages/blade/.storybook/react/preview.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { INTERNAL_STORY_ADDON_PARAM } from './constants';
const { GlobalStyle } = global;
import { DocsContainer } from '@storybook/addon-docs';
import React from 'react';
import { MINIMAL_VIEWPORTS } from '@storybook/addon-viewport';
import './global.css';

export const parameters = {
Expand All @@ -27,6 +28,19 @@ export const parameters = {
disable: true,
},
},
viewport: {
viewports: {
...MINIMAL_VIEWPORTS,
iPhone6: {
name: 'iPhone 6',
styles: {
height: '667px',
width: '375px',
},
type: 'mobile',
},
},
},
// on development setting it to undefined so that on 'live reload' it won't switch
// to docs panel while developing the component
viewMode: process.env.NODE_ENV === 'development' ? undefined : 'docs',
Expand Down Expand Up @@ -58,7 +72,7 @@ export const parameters = {
'useTheme',
],
'Components',
['*', 'KitchenSink'],
['*', 'Interaction Tests', 'KitchenSink'],
'Recipes',
],
},
Expand Down
15 changes: 13 additions & 2 deletions packages/blade/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -105,8 +105,12 @@
"react-native:storybook:ios": "yarn react-native:get-stories && cross-env FRAMEWORK=REACT_NATIVE react-native run-ios",
"react-native:storybook:start": "yarn react-native:get-stories && cross-env NODE_OPTIONS=--openssl-legacy-provider FRAMEWORK=REACT_NATIVE react-native start --reset-cache",
"react": "yarn run react:storybook",
"react:storybook": "cross-env NODE_OPTIONS=--openssl-legacy-provider FRAMEWORK=REACT storybook dev -c ./.storybook/react -p 9009",
"react:storybook:build": "cross-env NODE_OPTIONS=--openssl-legacy-provider FRAMEWORK=REACT storybook build -c ./.storybook/react -o storybook-site",
"react:storybook": "cross-env FRAMEWORK=REACT storybook dev -c ./.storybook/react -p 9009",
"react:storybook:build": "cross-env FRAMEWORK=REACT storybook build -c ./.storybook/react -o storybook-site --quiet",
"react:storybook:serve": "http-server storybook-site --port 9009 --silent",
"react:storybook:serve:test": "wait-on http://127.0.0.1:9009/ && yarn test:react:interaction",
"test:react:interaction": "cross-env FRAMEWORK=REACT test-storybook -c ./.storybook/react --url http://127.0.0.1:9009/",
"test:react:interaction:ci": "yarn react:storybook:build && run-p react:storybook:serve react:storybook:serve:test --race",
"test:react": "cross-env FRAMEWORK=REACT jest -c ./jest.web.config.js --shard=$SHARD --forceExit",
"test:react-native": "cross-env FRAMEWORK=REACT_NATIVE jest -c ./jest.native.config.js --shard=$SHARD --forceExit",
"start:ios": "cross-env NODE_OPTIONS=--openssl-legacy-provider run-p react-native:storybook:start react-native:storybook:ios",
Expand Down Expand Up @@ -135,6 +139,13 @@
"tinycolor2": "1.6.0"
},
"devDependencies": {
"http-server": "14.1.1",
"wait-on": "7.2.0",
"@storybook/addon-interactions": "7.6.6",
"@storybook/testing-library": "0.2.2",
"@storybook/test-runner": "0.16.0",
"@storybook/jest": "0.2.3",
"playwright": "1.40.1",
"chromatic": "6.22.0",
"@babel/cli": "7.23.0",
"@babel/core": "7.20.2",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -255,7 +255,7 @@ const TestimonialCard = ({
);
};

const CarouselExample = (props: Omit<CarouselProps, 'children'>): React.ReactElement => {
export const CarouselExample = (props: Omit<CarouselProps, 'children'>): React.ReactElement => {
const key = `${props.visibleItems}-${props.shouldAddStartEndSpacing}`;
return (
<Box width="100%" height={isReactNative() ? '350px' : 'auto'}>
Expand Down
41 changes: 34 additions & 7 deletions packages/blade/src/components/Carousel/Carousel.web.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,18 +13,18 @@ import type { CarouselContextProps } from './CarouselContext';
import { CarouselContext } from './CarouselContext';
import { getCarouselItemId } from './utils';
import { CAROUSEL_AUTOPLAY_INTERVAL, componentIds } from './constants';
import debounce from '~utils/lodashButBetter/debounce';
import throttle from '~utils/lodashButBetter/throttle';
import getIn from '~utils/lodashButBetter/get';
import throttle from '~utils/lodashButBetter/throttle';
import debounce from '~utils/lodashButBetter/debounce';
import { Box } from '~components/Box';
import BaseBox from '~components/Box/BaseBox';
import { castWebType, makeMotionTime, useInterval } from '~utils';
import { castWebType, makeMotionTime, useInterval, usePrevious } from '~utils';
import { useId } from '~utils/useId';
import { makeAccessible } from '~utils/makeAccessible';
import { metaAttribute, MetaConstants } from '~utils/metaAttribute';
import { useDidUpdate } from '~utils/useDidUpdate';
import { useVerifyAllowedChildren } from '~utils/useVerifyAllowedChildren/useVerifyAllowedChildren';
import { useTheme } from '~components/BladeProvider';
import { useFirstRender } from '~utils/useFirstRender';

type ControlsProp = Required<
Pick<
Expand Down Expand Up @@ -223,6 +223,29 @@ const CarouselBody = React.forwardRef<HTMLDivElement, CarouselBodyProps>(
},
);

/**
* A custom hook which syncs an effect with a state
* While ignoring the first render & only running the effect when the state changes
*/
function useSyncUpdateEffect<T>(
effect: React.EffectCallback,
stateToSyncWith: T,
deps: React.DependencyList,
) {
const isFirst = useFirstRender();
const prevState = usePrevious<T>(stateToSyncWith);

React.useEffect(() => {
if (!isFirst) {
// if the state is the same as the previous state
// we don't want to run the effect
if (prevState === stateToSyncWith) return;
return effect();
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [stateToSyncWith, ...deps]);
}

const Carousel = ({
autoPlay,
visibleItems = 1,
Expand Down Expand Up @@ -450,9 +473,13 @@ const Carousel = ({
shouldAddStartEndSpacing,
]);

useDidUpdate(() => {
onChange?.(activeSlide);
}, [activeSlide, onChange]);
useSyncUpdateEffect(
() => {
onChange?.(activeSlide);
},
activeSlide,
[onChange],
);

return (
<CarouselContext.Provider value={carouselContext}>
Expand Down
Loading

0 comments on commit cad80ef

Please sign in to comment.