-
Notifications
You must be signed in to change notification settings - Fork 650
Add the framework required to run component stress tests #5929
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from 70 commits
Commits
Show all changes
76 commits
Select commit
Hold shift + click to select a range
d6e2218
Add stress-tests.yml
hectahertz 9544472
Add default stress test
hectahertz 26131f7
Run on push to test
hectahertz 50f396b
Remove shard
hectahertz b295934
Don't update shapshots
hectahertz da50be3
Test code
hectahertz d951fed
Export results
hectahertz 19e85f9
Snapshot
hectahertz bae25dd
Upload snapshot
hectahertz e84fedb
--update-snapshots
hectahertz ffb257a
Warn
hectahertz 9161405
Don't run on load
hectahertz 02b9980
Better button
hectahertz 08ae3d1
Run iterations
hectahertz 3344db6
Framework
hectahertz a280f61
Extract StressTest
hectahertz a89d11c
Extract StressTest to utils
hectahertz 4b56f2c
Styling
hectahertz 3db0c29
Basic UI
hectahertz 82691a5
Simplify stress test
hectahertz 180f299
Add ActionList stress test
hectahertz 471af66
Add title to tests
hectahertz 908fd1d
Don't wait for button
hectahertz 5acba58
Fix console.warn
hectahertz 5dc98e6
Group stresstest stories
hectahertz cb5fcf8
Custom reporter
hectahertz 4d7b2ea
Try attachments
hectahertz 0efe062
Report attachments
hectahertz 69d0f02
Fix reporter
hectahertz 52527ca
Cleanup
hectahertz a8751e9
Parse attachment
hectahertz 484273f
Fix typo
hectahertz 5b0e1b5
Save results to a file
hectahertz c181ee3
Fix typo
hectahertz 6e6a85c
Import instead of require
hectahertz 11da535
Test benchmark-action/github-action-benchmark@v1
hectahertz 96e24d0
Accumulate all results
hectahertz 7d26cf7
Tool is customSmallerIsBetter
hectahertz 3275be0
Make it slow to trigger it
hectahertz 54c1186
Add some TODO:
hectahertz 5f83b4b
Add some more TODOs
hectahertz 7db4b07
Run on 2 cores
hectahertz ab269c0
Clean commits
hectahertz 3611730
Alert commit content
hectahertz 848f82c
Run on 4 cores
hectahertz f4f38b0
Restore stress test
hectahertz ac03717
Clean comments
hectahertz bc01de7
Add comment
hectahertz 031a342
Restyling
hectahertz 96520ec
Clean up StressTest component
hectahertz 0c5fbc8
Display more metrics
hectahertz 04944be
Count elapsed time
hectahertz 14f53f3
Restyle
hectahertz 9fc0e97
Styling
hectahertz 88d2186
Cleanup work
hectahertz 4c00bff
Add a couple of Button stress tests
hectahertz 0f2863d
Change Icon
hectahertz 09a9e6e
Reduce iterations on ActionList test
hectahertz 8c4979e
Update TODOs
hectahertz 5f0fd69
Reduce actionlist Iterations
hectahertz 85f8603
Styling
hectahertz a543f56
Add TreeView stress test
hectahertz 0ebe91c
Cleanup reporter
hectahertz 932e4eb
Lower CurrentUpdate iterations
hectahertz c109f18
Rename reporter
hectahertz 220cd24
Remove TODOs
hectahertz 120f667
Unify all stress tests in one file
hectahertz c763ffc
Clean up
hectahertz dac0e50
Merge branch 'main' into hectahertz/stress-test
hectahertz f330e44
Add changeset
hectahertz 28a2d89
Merge branch 'main' into hectahertz/stress-test
hectahertz 443736a
Fix lint errors
hectahertz ee8f6de
Merge branch 'main' into hectahertz/stress-test
hectahertz 1d9892f
Fix css linting issues
hectahertz 2b9aa23
Make the stress stories dev only
hectahertz 0c5a18a
Merge branch 'main' into hectahertz/stress-test
jonrohan File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or 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,5 @@ | ||
| --- | ||
| '@primer/react': minor | ||
| --- | ||
|
|
||
| Add the framework required to run component stress tests |
This file contains hidden or 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,55 @@ | ||
| name: Stress Tests | ||
|
|
||
| on: [push] | ||
|
|
||
| jobs: | ||
| stress-tests: | ||
| runs-on: ubuntu-latest-4-cores | ||
| steps: | ||
| - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 | ||
| - name: Set up Node.js | ||
| uses: actions/setup-node@cdca7365b2dadb8aad0a33bc7601856ffabcc48e | ||
| with: | ||
| node-version: 22 | ||
| cache: 'npm' | ||
| - name: Install dependencies | ||
| run: npm ci | ||
| - name: Build storybook | ||
| run: npx storybook build | ||
| working-directory: packages/react | ||
| - name: Run storybook | ||
| id: storybook | ||
| run: | | ||
| npx serve -l 6006 packages/react/storybook-static & | ||
| pid=$! | ||
| echo "pid=$pid" >> $GITHUB_OUTPUT | ||
| sleep 5 | ||
| - name: Run Stress Tests | ||
| uses: docker://mcr.microsoft.com/playwright:v1.51.0-jammy | ||
| env: | ||
| STORYBOOK_URL: 'http://172.17.0.1:6006' | ||
| with: | ||
| args: npx playwright test --grep @stress-test" | ||
| - name: Stop storybook | ||
| if: ${{ always() }} | ||
| run: kill ${{ steps.storybook.outputs.pid }} | ||
| - name: Download previous benchmark data (if any) | ||
| uses: actions/cache@v4 | ||
| with: | ||
| path: ./cache | ||
| key: stress-tests-benchmark | ||
| - name: Store benchmark result | ||
| uses: benchmark-action/github-action-benchmark@v1 | ||
| with: | ||
| tool: 'customSmallerIsBetter' | ||
| output-file-path: results.json | ||
| # Where the previous data file is stored | ||
| external-data-json-path: ./cache/stress-tests-benchmark-data.json | ||
| # Workflow will fail when an alert happens | ||
| fail-on-alert: true | ||
| github-token: ${{ secrets.GITHUB_TOKEN }} | ||
| alert-threshold: '150%' | ||
| # Enable alert commit comment | ||
| comment-on-alert: true | ||
| # Mention @rhysd in the commit comment | ||
| alert-comment-cc-users: '@hectahertz' | ||
This file contains hidden or 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,24 @@ | ||
| import {test} from '@playwright/test' | ||
| import {visit} from '../test-helpers/storybook' | ||
|
|
||
| const stressTests = [ | ||
| {component: 'ActionList', testName: 'Single select', id: 'stresstests-components-actionlist--single-select'}, | ||
| {component: 'Pagination', testName: 'Page update', id: 'stresstests-components-pagination--page-update'}, | ||
| {component: 'Button', testName: 'Label update', id: 'stresstests-components-button--label-update'}, | ||
| {component: 'Button', testName: 'Count update', id: 'stresstests-components-button--count-update'}, | ||
| {component: 'TreeView', testName: 'Current update', id: 'stresstests-components-treeview--current-update'}, | ||
| ] | ||
|
|
||
| stressTests.forEach(({component, testName, id}) => { | ||
| test.describe(`${component} Stress Tests`, () => { | ||
| test(`${testName} @stress-test`, async ({page}, testInfo) => { | ||
| await visit(page, {id}) | ||
| await page.getByTestId('start').click() | ||
| const result = await page.getByTestId('result').textContent() | ||
| await testInfo.attach('stress-test-result', { | ||
| body: JSON.stringify({id, duration: result}), | ||
| contentType: 'application/json', | ||
| }) | ||
| }) | ||
| }) | ||
| }) | ||
This file contains hidden or 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,39 @@ | ||
| import type {FullResult, Reporter, TestCase, TestResult} from '@playwright/test/reporter' | ||
| import {writeFileSync} from 'fs' | ||
|
|
||
| class MyReporter implements Reporter { | ||
| // Format we need: | ||
| // https://github.com/benchmark-action/github-action-benchmark?tab=readme-ov-file#examples | ||
| results: {name: string; unit: string; value: number}[] = [] | ||
|
|
||
| onTestEnd(test: TestCase, result: TestResult) { | ||
| console.log(`⚡️ Finished stress-test ${test.title}: ${result.status}`) | ||
| for (const attachment of result.attachments) { | ||
| // get the content of the attachment to an object | ||
| if ( | ||
| attachment.body !== undefined && | ||
| attachment.name === 'stress-test-result' && | ||
| attachment.contentType === 'application/json' | ||
| ) { | ||
| const content = JSON.parse(attachment.body.toString()) | ||
| console.log(`⚡️ Test result: ${content}`) | ||
| this.results.push({ | ||
| name: content.id, | ||
| unit: 'ms', | ||
| value: parseFloat(content.duration), | ||
| }) | ||
| } | ||
| } | ||
| } | ||
|
|
||
| onEnd(result: FullResult) { | ||
| console.log(`⚡️ Finished the stress tests run: ${result.status}`) | ||
| const fileName = 'results.json' | ||
| const fileContentString = JSON.stringify(this.results, null, 2) | ||
| console.log(`⚡️ Results file content: ${fileContentString}`) | ||
| writeFileSync(fileName, fileContentString) | ||
| console.log(`⚡️ File saved: ${fileName}`) | ||
| } | ||
| } | ||
|
|
||
| export default MyReporter | ||
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains hidden or 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
52 changes: 52 additions & 0 deletions
52
packages/react/src/ActionList/ActionList.stress.stories.tsx
This file contains hidden or 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,52 @@ | ||
| import React from 'react' | ||
|
|
||
| import type {Meta} from '@storybook/react' | ||
| import type {ComponentProps} from '../utils/types' | ||
| import {StressTest} from '../utils/StressTest' | ||
| import {TableIcon} from '@primer/octicons-react' | ||
| import {ActionList} from '.' | ||
|
|
||
| export default { | ||
| title: 'StressTests/Components/ActionList', | ||
hectahertz marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| component: ActionList, | ||
| } as Meta<ComponentProps<typeof ActionList>> | ||
|
|
||
| const totalIterations = 100 | ||
|
|
||
| const projects = Array.from({length: totalIterations}, (_, i) => ({ | ||
| name: `Project ${i + 1}`, | ||
| scope: `Scope ${i + 1}`, | ||
| })) | ||
|
|
||
| export const SingleSelect = () => { | ||
| return ( | ||
| <StressTest | ||
| componentName="ActionList" | ||
| title="Single Select" | ||
| description="Selecting a single item from a large list." | ||
| totalIterations={totalIterations} | ||
| renderIteration={count => { | ||
| return ( | ||
| <> | ||
| <ActionList selectionVariant="single" showDividers role="menu" aria-label="Project"> | ||
| {projects.map((project, index) => ( | ||
| <ActionList.Item | ||
| key={index} | ||
| role="menuitemradio" | ||
| selected={index === count} | ||
| aria-checked={index === count} | ||
| > | ||
| <ActionList.LeadingVisual> | ||
| <TableIcon /> | ||
| </ActionList.LeadingVisual> | ||
| {project.name} | ||
| <ActionList.Description variant="block">{project.scope}</ActionList.Description> | ||
| </ActionList.Item> | ||
| ))} | ||
| </ActionList> | ||
| </> | ||
| ) | ||
| }} | ||
| /> | ||
| ) | ||
| } | ||
This file contains hidden or 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,61 @@ | ||
| import React from 'react' | ||
|
|
||
| import type {Meta} from '@storybook/react' | ||
| import type {ComponentProps} from '../utils/types' | ||
| import {StressTest} from '../utils/StressTest' | ||
| import {Button} from '.' | ||
|
|
||
| export default { | ||
| title: 'StressTests/Components/Button', | ||
| component: Button, | ||
| } as Meta<ComponentProps<typeof Button>> | ||
|
|
||
| const totalIterations = 500 | ||
|
|
||
| export const LabelUpdate = () => { | ||
| return ( | ||
| <StressTest | ||
| componentName="Button" | ||
| title="Label update" | ||
| description="Update the label a large number of times." | ||
| totalIterations={totalIterations} | ||
| renderIteration={count => ( | ||
| <div> | ||
| <Button variant="primary" size="large" onClick={() => {}}> | ||
| {`Button ${count + 1}`} | ||
| </Button> | ||
| <Button variant="default" size="medium" onClick={() => {}}> | ||
| {`Button ${count + 1}`} | ||
| </Button> | ||
| <Button variant="danger" size="small" onClick={() => {}}> | ||
| {`Button ${count + 1}`} | ||
| </Button> | ||
| </div> | ||
| )} | ||
| /> | ||
| ) | ||
| } | ||
|
|
||
| export const CountUpdate = () => { | ||
| return ( | ||
| <StressTest | ||
| componentName="Button" | ||
| title="Count update" | ||
| description="Update the count a large number of times." | ||
| totalIterations={totalIterations} | ||
| renderIteration={count => ( | ||
| <div> | ||
| <Button variant="primary" size="large" onClick={() => {}} count={count}> | ||
| Button | ||
| </Button> | ||
| <Button variant="default" size="medium" onClick={() => {}} count={count}> | ||
| Button | ||
| </Button> | ||
| <Button variant="danger" size="small" onClick={() => {}} count={count}> | ||
| Button | ||
| </Button> | ||
| </div> | ||
| )} | ||
| /> | ||
| ) | ||
| } |
27 changes: 27 additions & 0 deletions
27
packages/react/src/Pagination/Pagination.stress.stories.tsx
This file contains hidden or 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,27 @@ | ||
| import React from 'react' | ||
|
|
||
| import type {Meta} from '@storybook/react' | ||
| import type {ComponentProps} from '../utils/types' | ||
| import Pagination from './Pagination' | ||
| import {StressTest} from '../utils/StressTest' | ||
|
|
||
| export default { | ||
| title: 'StressTests/Components/Pagination', | ||
| component: Pagination, | ||
| } as Meta<ComponentProps<typeof Pagination>> | ||
|
|
||
| const totalIterations = 500 | ||
|
|
||
| export const PageUpdate = () => { | ||
| return ( | ||
| <StressTest | ||
| componentName="Pagination" | ||
| title="Page update" | ||
| description="Navigation through a large number of pages." | ||
| totalIterations={totalIterations} | ||
| renderIteration={count => ( | ||
| <Pagination pageCount={totalIterations} currentPage={count + 1} showPages={{narrow: false}} /> | ||
| )} | ||
| /> | ||
| ) | ||
| } |
This file contains hidden or 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,53 @@ | ||
| import React from 'react' | ||
|
|
||
| import type {Meta} from '@storybook/react' | ||
| import type {ComponentProps} from '../utils/types' | ||
| import {StressTest} from '../utils/StressTest' | ||
| import {TreeView} from './TreeView' | ||
| import {FileIcon, DiffAddedIcon, DiffModifiedIcon} from '@primer/octicons-react' | ||
| import Octicon from '../Octicon' | ||
|
|
||
| export default { | ||
| title: 'StressTests/Components/TreeView', | ||
| component: TreeView, | ||
| } as Meta<ComponentProps<typeof TreeView>> | ||
|
|
||
| const totalIterations = 100 | ||
|
|
||
| const Files = Array.from({length: totalIterations}, (_, i) => ({ | ||
| name: `File_${i + 1}.tsx`, | ||
| })) | ||
|
|
||
| export const CurrentUpdate = () => { | ||
| return ( | ||
| <StressTest | ||
| componentName="TreeView" | ||
| title="Simple current update" | ||
| description="Marking a file as current from a large list." | ||
| totalIterations={totalIterations} | ||
| renderIteration={count => ( | ||
| <TreeView aria-label="Files changed"> | ||
| <TreeView.Item id="src" defaultExpanded> | ||
| <TreeView.LeadingVisual> | ||
| <TreeView.DirectoryIcon /> | ||
| </TreeView.LeadingVisual> | ||
| src | ||
| <TreeView.SubTree> | ||
| {Files.map((file, index) => ( | ||
| <TreeView.Item key={index} id={`src/${file.name}`} current={index === count}> | ||
| <TreeView.LeadingVisual> | ||
| <FileIcon /> | ||
| </TreeView.LeadingVisual> | ||
| {file.name} | ||
| <TreeView.TrailingVisual label="Added"> | ||
| <Octicon icon={DiffAddedIcon} color="success.fg" /> | ||
| </TreeView.TrailingVisual> | ||
| </TreeView.Item> | ||
| ))} | ||
| </TreeView.SubTree> | ||
| </TreeView.Item> | ||
| </TreeView> | ||
| )} | ||
| /> | ||
| ) | ||
| } | ||
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.