-
Notifications
You must be signed in to change notification settings - Fork 4.2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Storybook: Set up local visual regression testing (#43393)
* Storybook: Set up local visual regression testing * Alter for custom-written tests * Add custom FM animation waiter and some FontSizePicker specs * Use explicit wait for the animated elements * Use simpler handle getter waitForSelector implies element is visible * Add config to load CSS * Add support for decorators * Migrate example FontSizePicker test to new setup * Rename test files * Rename to avoid clashes * Improve readme Co-authored-by: Bart Kalisz <bartlomiej.kalisz@gmail.com>
- Loading branch information
1 parent
cb5e716
commit fd058df
Showing
12 changed files
with
241 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
47 changes: 47 additions & 0 deletions
47
packages/components/src/font-size-picker/stories/e2e/index.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
/** | ||
* WordPress dependencies | ||
*/ | ||
import { useState } from '@wordpress/element'; | ||
|
||
/** | ||
* Internal dependencies | ||
*/ | ||
import FontSizePicker from '../..'; | ||
|
||
export default { | ||
title: 'Components/FontSizePicker', | ||
component: FontSizePicker, | ||
}; | ||
|
||
const FontSizePickerWithState = ( { initialValue, ...props } ) => { | ||
const [ fontSize, setFontSize ] = useState( initialValue ); | ||
return ( | ||
<FontSizePicker | ||
{ ...props } | ||
value={ fontSize } | ||
onChange={ setFontSize } | ||
/> | ||
); | ||
}; | ||
|
||
export const Default = FontSizePickerWithState.bind( {} ); | ||
Default.args = { | ||
fontSizes: [ | ||
{ | ||
name: 'Small', | ||
slug: 'small', | ||
size: 12, | ||
}, | ||
{ | ||
name: 'Normal', | ||
slug: 'normal', | ||
size: 16, | ||
}, | ||
{ | ||
name: 'Big', | ||
slug: 'big', | ||
size: 26, | ||
}, | ||
], | ||
initialValue: 16, | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
/** | ||
* WordPress dependencies | ||
*/ | ||
import { useState } from '@wordpress/element'; | ||
|
||
/** | ||
* Internal dependencies | ||
*/ | ||
import Popover from '../..'; | ||
|
||
export default { | ||
title: 'Components/Popover', | ||
component: Popover, | ||
}; | ||
|
||
export const Default = () => { | ||
const [ isVisible, setIsVisible ] = useState( false ); | ||
|
||
return ( | ||
<button onClick={ () => setIsVisible( ( state ) => ! state ) }> | ||
Toggle Popover! | ||
{ isVisible && <Popover>Popover is toggled!</Popover> } | ||
</button> | ||
); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
# Storybook Playwright Tests | ||
|
||
This is currently set up for testing visual regressions in the `components` package. The tests do not run on CI, and is meant as a testing tool for local development. | ||
|
||
## How to run | ||
|
||
First, build and serve the E2E Storybook. | ||
|
||
```sh | ||
npm run storybook:e2e:dev | ||
``` | ||
|
||
You are now ready to run the tests. The first run will generate the reference images, and subsequent runs will compare against them. (On the first run, you may be prompted to first install Playwright. If so, follow the instructions.) | ||
|
||
```sh | ||
npm run test:e2e:storybook | ||
``` | ||
|
||
To update the reference images, pass the `--update-snapshots` flag. | ||
|
||
```sh | ||
npm run test:e2e:storybook -- --update-snapshots | ||
``` | ||
|
||
## How to write tests | ||
|
||
Any stories matching the glob patterns listed in the [E2E Storybook config](./storybook/main.js) will be included in the special build. Note that these are exclusive fixtures for our tests, and are separate from the stories included in the [main Storybook build](../../storybook/main.js) to be [published online](https://wordpress.github.io/gutenberg/). | ||
|
||
The Playwright test files live in the [`specs`](./specs/) folder. See the [E2E Tests README](../e2e/README.md) for general best practices. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
/** | ||
* External dependencies | ||
*/ | ||
import { PlaywrightTestConfig } from '@playwright/test'; | ||
|
||
const config: PlaywrightTestConfig = { | ||
outputDir: 'test-results/output', | ||
reporter: [ | ||
[ 'html', { open: 'on-failure', outputFolder: 'test-results/report' } ], | ||
], | ||
}; | ||
|
||
export default config; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
/** | ||
* WordPress dependencies | ||
*/ | ||
import { test, expect } from '@wordpress/e2e-test-utils-playwright'; | ||
|
||
/** | ||
* Internal dependencies | ||
*/ | ||
import { gotoStoryId } from '../utils'; | ||
|
||
const waitUntilButtonHighlightStable = async ( page ) => { | ||
const handle = await page.waitForSelector( | ||
'[aria-label="Font size"] > div[role=presentation]' | ||
); | ||
|
||
await handle?.waitForElementState( 'stable' ); | ||
|
||
return handle; | ||
}; | ||
|
||
test.describe.parallel( 'FontSizePicker', () => { | ||
test.beforeEach( async ( { page } ) => { | ||
await gotoStoryId( page, 'components-fontsizepicker--default' ); | ||
} ); | ||
|
||
// This isn't a meaningful test, just some example code to demonstrate a way to | ||
// wait until a certain element has finished animating. | ||
// We can remove it once we have real tests. | ||
test( 'with value', async ( { page } ) => { | ||
const button = await page.locator( 'button[aria-label="Normal"]' ); | ||
|
||
await waitUntilButtonHighlightStable( page ); | ||
|
||
expect( button ).toHaveAttribute( 'aria-checked', 'true' ); | ||
expect( await page.screenshot() ).toMatchSnapshot(); | ||
} ); | ||
} ); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
/** | ||
* WordPress dependencies | ||
*/ | ||
import { test, expect } from '@wordpress/e2e-test-utils-playwright'; | ||
|
||
/** | ||
* Internal dependencies | ||
*/ | ||
import { gotoStoryId } from '../utils'; | ||
|
||
test.describe( 'Popover', () => { | ||
// This isn't a meaningful test, just some example code. | ||
// We can remove it once we have real tests. | ||
test( 'should render', async ( { page } ) => { | ||
await gotoStoryId( page, 'components-popover--default', { | ||
decorators: { marginChecker: 'show' }, | ||
} ); | ||
|
||
await page.click( 'role=button' ); | ||
const popover = await page.waitForSelector( '.components-popover' ); | ||
await popover.waitForElementState( 'stable' ); | ||
|
||
expect( await page.screenshot() ).toMatchSnapshot(); | ||
} ); | ||
} ); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
/** | ||
* Internal dependencies | ||
*/ | ||
const baseConfig = require( '../../../storybook/main' ); | ||
|
||
const config = { | ||
...baseConfig, | ||
addons: [ '@storybook/addon-toolbars' ], | ||
stories: [ | ||
'../../../packages/components/src/**/stories/e2e/*.@(js|tsx|mdx)', | ||
], | ||
}; | ||
|
||
module.exports = config; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export * from '../../../storybook/preview'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
/** | ||
* Internal dependencies | ||
*/ | ||
const baseConfig = require( '../../../storybook/webpack.config' ); | ||
|
||
module.exports = baseConfig; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
/** | ||
* External dependencies | ||
*/ | ||
import type { Page } from '@playwright/test'; | ||
|
||
const STORYBOOK_PORT = '50241'; | ||
|
||
type Decorators = { | ||
css?: 'none' | 'basic' | 'wordpress'; | ||
direction?: 'ltr' | 'rtl'; | ||
marginChecker?: 'show' | 'hide'; | ||
}; | ||
type Options = { decorators?: Decorators }; | ||
|
||
const buildDecoratorString = ( decorators: Decorators = {} ) => { | ||
const decoratorParamStrings = Object.entries( decorators ).map( | ||
( keyValue ) => keyValue.join( ':' ) | ||
); | ||
return decoratorParamStrings.join( ';' ); | ||
}; | ||
|
||
export const gotoStoryId = ( | ||
page: Page, | ||
storyId: string, | ||
{ decorators }: Options = {} | ||
) => { | ||
const params = new URLSearchParams(); | ||
const decoratorString = buildDecoratorString( decorators ); | ||
|
||
if ( decoratorString ) { | ||
params.set( 'globals', decoratorString ); | ||
} | ||
|
||
params.set( 'id', storyId ); | ||
|
||
page.goto( | ||
`http://localhost:${ STORYBOOK_PORT }/iframe.html?${ params.toString() }`, | ||
{ waitUntil: 'load' } | ||
); | ||
}; |