Skip to content
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

build: add performance-tests #2539

Merged
merged 51 commits into from
Oct 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
51 commits
Select commit Hold shift + click to select a range
94f4833
Add performance-tests workspace
gpbl Oct 13, 2024
b0a6728
Clean up .gitignore
gpbl Oct 13, 2024
a73df40
Add RangeLong example
gpbl Oct 13, 2024
7984593
Update capture and deps
gpbl Oct 13, 2024
94393ab
Add workflow
gpbl Oct 13, 2024
47ba816
Update workflow
gpbl Oct 13, 2024
2ce55ea
Fix workflow
gpbl Oct 13, 2024
807d06e
Fix workflow
gpbl Oct 13, 2024
ffb9115
Fix
gpbl Oct 13, 2024
8e485ff
Fix workflow
gpbl Oct 13, 2024
6dd549a
Update workflow
gpbl Oct 13, 2024
b242126
Update workflow
gpbl Oct 13, 2024
1cb41ac
Headless
gpbl Oct 13, 2024
1b4e9bf
Install chrome
gpbl Oct 13, 2024
42130c7
Update script
gpbl Oct 13, 2024
06fb0d5
browser-actions/setup-chrome@v1
gpbl Oct 13, 2024
3c7821c
Add /opt/hostedtoolcache/setup-chrome/chromium/1368061/x64
gpbl Oct 13, 2024
a61946d
Echo
gpbl Oct 13, 2024
6e7fafe
Fix chrome path
gpbl Oct 13, 2024
5384e1c
Add timeout, create dir
gpbl Oct 13, 2024
58ee51d
Update pnpm-lock.yaml
gpbl Oct 13, 2024
7cc7250
Fix
gpbl Oct 13, 2024
74f5fba
Update performance.yml
gpbl Oct 13, 2024
9fa198b
Tuning
gpbl Oct 13, 2024
6fa9ffc
.pnpm-store
gpbl Oct 13, 2024
b9a0110
Remove version
gpbl Oct 13, 2024
ada5105
Headless browser
gpbl Oct 13, 2024
38f28dc
Use latest
gpbl Oct 13, 2024
a3c22fa
Fix package manager
gpbl Oct 13, 2024
e6f1589
Fix CI env
gpbl Oct 13, 2024
c4afbdd
Fix packageManager
gpbl Oct 13, 2024
63eeaef
Fix package manager
gpbl Oct 13, 2024
5d65e74
Fix engines
gpbl Oct 13, 2024
e9ea1ae
Run only if labeled performance
gpbl Oct 13, 2024
251d77c
Fix label
gpbl Oct 13, 2024
7465d49
Add reports dir
gpbl Oct 13, 2024
660bfa8
add linkt to download
gpbl Oct 13, 2024
ae6f8e9
Add comment
gpbl Oct 13, 2024
1cfab75
Run only
gpbl Oct 13, 2024
1bb5283
Fix event name
gpbl Oct 13, 2024
f84bdb8
Capture report
gpbl Oct 13, 2024
e01709a
Fix workflow
gpbl Oct 13, 2024
46c5818
Throw error
gpbl Oct 13, 2024
1c7ec2c
Add CLI support
gpbl Oct 13, 2024
c340f96
Remove extra file
gpbl Oct 13, 2024
d669e60
Fix download url
gpbl Oct 13, 2024
f01ba0a
Updates
gpbl Oct 13, 2024
fc61c7c
Fix markdown report
gpbl Oct 13, 2024
a139aeb
Add gitignore
gpbl Oct 13, 2024
c70a696
Fix
gpbl Oct 13, 2024
8e7b6a3
Fix content
gpbl Oct 13, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 0 additions & 10 deletions .github/workflows/package.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,6 @@ jobs:
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
with:
version: 9.4.0
- uses: actions/setup-node@v4
with:
node-version: 20.16
Expand All @@ -37,8 +35,6 @@ jobs:
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
with:
version: 9.4.0
- uses: actions/setup-node@v4
with:
node-version: 20.16
Expand All @@ -52,8 +48,6 @@ jobs:
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
with:
version: 9.4.0
- uses: actions/setup-node@v4
with:
node-version: 20.16
Expand All @@ -66,8 +60,6 @@ jobs:
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
with:
version: 9.4.0
- uses: actions/setup-node@v4
with:
node-version: 20.16
Expand All @@ -88,8 +80,6 @@ jobs:
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
with:
version: 9.4.0
- uses: actions/setup-node@v4
with:
node-version: 20.16
Expand Down
168 changes: 168 additions & 0 deletions .github/workflows/performance.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
name: Performance Test

on:
pull_request:
branches:
- main
push:
branches:
- main

jobs:
build-react-day-picker:
if: contains(github.event.pull_request.labels.*.name, 'performance')
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4

- name: Set up pnpm
uses: pnpm/action-setup@v4

- name: Set up Node.js
uses: actions/setup-node@v4
with:
cache: pnpm

- name: Create pnpm store directory
run: mkdir -p ~/.pnpm-store

- name: Cache node_modules
uses: actions/cache@v4
with:
path: ~/.pnpm-store
key: ${{ runner.os }}-pnpm-${{ hashFiles('**/pnpm-lock.yaml') }}
restore-keys: |
${{ runner.os }}-pnpm-

- name: Install dependencies
run: pnpm install --frozen-lockfile

- name: Build project
run: pnpm build

- name: Upload build artifacts
uses: actions/upload-artifact@v4
with:
name: rdp-dist
path: dist

run-performance-test:
needs: [build-react-day-picker]
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4

- name: Set up Chrome
uses: browser-actions/setup-chrome@v1
id: setup-chrome

- name: Set up pnpm
uses: pnpm/action-setup@v4

- name: Set up Node.js
uses: actions/setup-node@v4
with:
cache: pnpm

- name: Download build artifacts
uses: actions/download-artifact@v4
with:
name: rdp-dist
path: dist

- name: Create pnpm store directory
run: mkdir -p ~/.pnpm-store

- name: Cache node_modules
uses: actions/cache@v4
with:
path: ~/.pnpm-store
key: ${{ runner.os }}-pnpm-${{ hashFiles('**/pnpm-lock.yaml') }}
restore-keys: |
${{ runner.os }}-pnpm-

- name: Install dependencies
run: pnpm install --frozen-lockfile

- name: Start server
run: pnpm --filter performance-tests start-server &
env:
CHROME_PATH: ${{ steps.setup-chrome.outputs.chrome-path }}

- name: Wait for server to start
run: pnpx wait-on http://localhost:4173 --timeout 10000

- name: Capture performance test
run: pnpm --filter performance-tests run capture
env:
CHROME_PATH: ${{ steps.setup-chrome.outputs.chrome-path }}
CI: true

- name: Upload report
uses: actions/upload-artifact@v4
with:
name: report
path: ./performance-tests/reports/report.html

- name: Upload markdown report
uses: actions/upload-artifact@v4
with:
name: markdown-report
path: ./performance-tests/reports/markdown-report.md

- name: Download markdown report
uses: actions/download-artifact@v4
with:
name: markdown-report
path: ./markdown-report

- name: Read markdown report
id: read-markdown
run: |
markdown_content=$(cat ./markdown-report/markdown-report.md)
echo "markdown_content<<EOF" >> $GITHUB_ENV
echo "$markdown_content" >> $GITHUB_ENV
echo "EOF" >> $GITHUB_ENV

- name: Post comment with download link and markdown content
if: success()
uses: actions/github-script@v7
with:
script: |
const artifactUrl = `https://github.com/${context.repo.owner}/${context.repo.repo}/actions/runs/${context.runId}`;
const markdownContent = process.env.markdown_content;
const comment = `Performance test reports are available [here](${artifactUrl}).\n\n### Markdown Report:\n\n${markdownContent}`;
github.rest.issues.createComment({
...context.repo,
issue_number: context.issue.number,
body: comment
});

# - name: Post comment with download link and markdown content
# if: success()
# uses: actions/github-script@v7
# with:
# script: |
# const artifactUrl = `https://github.com/${context.repo.owner}/${context.repo.repo}/actions/runs/${context.runId}`;
# const markdownContent = process.env.markdown;
# const comment = `Performance test reports are available [here](${artifactUrl}).\n\n### Markdown Report:\n\n${markdownContent}`;
# github.rest.issues.createComment({
# ...context.repo,
# issue_number: context.issue.number,
# body: comment
# });

# - name: Post comment with download link
# if: success()
# uses: actions/github-script@v7
# with:
# script: |
# const artifactUrl = `https://github.com/${context.repo.owner}/${context.repo.repo}/actions/runs/${context.runId}`;
# const comment = `Performance test reports are available [here](${artifactUrl}).`;
# github.rest.issues.createComment({
# ...context.repo,
# issue_number: context.issue.number,
# body: comment
# });
6 changes: 0 additions & 6 deletions .github/workflows/website.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,6 @@ jobs:
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
with:
version: 9.4.0
- uses: actions/setup-node@v4
with:
node-version: 20.16
Expand All @@ -35,8 +33,6 @@ jobs:
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
with:
version: 9.4.0
- uses: actions/setup-node@v4
with:
node-version: 20.16
Expand All @@ -54,8 +50,6 @@ jobs:
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
with:
version: 9.4.0
- uses: actions/setup-node@v4
with:
node-version: 20.16
Expand Down
4 changes: 2 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@

node_modules
dist
/website/docs/api
/test-website
/performance-tests/reports/report.html
/performance-tests/reports/markdown-report.md
4 changes: 2 additions & 2 deletions examples-app/tsconfig.app.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@

/* Linting */
"strict": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"noUnusedLocals": false,
"noUnusedParameters": false,
"noFallthroughCasesInSwitch": true
},
"include": ["src"]
Expand Down
22 changes: 22 additions & 0 deletions examples/RangeLong.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import React, { useState } from "react";

import { type DateRange, DayPicker } from "react-day-picker";

export function RangeLong() {
const [range, setRange] = useState<DateRange | undefined>({
from: new Date("0001-01-01"),
to: new Date(2024, 9, 10)
});

return (
<DayPicker
id="test"
mode="range"
defaultMonth={new Date(2024, 9)}
selected={range}
onSelect={setRange}
excludeDisabled
disabled={new Date("2000-01-01")}
/>
);
}
1 change: 1 addition & 0 deletions examples/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ export * from "./RangeExcludeDisabled";
export * from "./RangeMinMax";
export * from "./RangeRequired";
export * from "./RangeShiftKey";
export * from "./RangeLong";
export * from "./Rtl";
export * from "./Single";
export * from "./SingleControlled";
Expand Down
4 changes: 4 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@
"description": "Customizable Date Picker for React",
"author": "Giampaolo Bellavite <[email protected]>",
"homepage": "https://daypicker.dev",
"packageManager": "[email protected]",
"engines": {
"node": ">=18"
},
"license": "MIT",
"repository": {
"type": "git",
Expand Down
5 changes: 5 additions & 0 deletions performance-tests/.eslintrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"env": {
"node": true
}
}
1 change: 1 addition & 0 deletions performance-tests/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
!reports/.gitkeep
87 changes: 87 additions & 0 deletions performance-tests/capture.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
import fs from "fs";
import { startFlow } from "lighthouse";
import open from "open";
import puppeteer from "puppeteer";

import { rangeLong } from "./flows/range-long.mjs";
import lighthouseConfig from "./lighthouse-config.mjs";

const reportFileName = `./reports/report.html`;

async function captureReport() {
const browser = await puppeteer.launch({
headless: Boolean(process.env.CI) === true,
executablePath: process.env.CHROME_PATH || undefined,
defaultViewport: { width: 1200, height: 800, deviceScaleFactor: 2 }
});
const page = await browser.newPage();
await page.emulateMediaFeatures([
{ name: "prefers-color-scheme", value: "light" }
]);
const flow = await startFlow(page, {
name: "DayPicker Examples Flow",
config: lighthouseConfig
});

await rangeLong(flow, page);

const report = await flow.generateReport();
await browser.close();

fs.writeFileSync(reportFileName, report);

const jsonReport = await flow.createFlowResult();
let hasFailure = false;
for (const step of jsonReport.steps) {
const categories = step.lhr.categories;

for (const key in categories) {
const score = categories[key]?.score;

if (score !== undefined && score < 1) {
console.error(
`❌ Test failed on step "${step.name}" in category "${key}": Score: ${score}`
);
hasFailure = true; // Mark as failure but continue
}
}
}

let markdownReport = "# Lighthouse Report\n\n";

// Add table header
markdownReport +=
"| Step Name | Accessibility | Performance | Best Practices |\n";
markdownReport +=
"|-----------------|---------------|-------------|----------------|\n";

// Iterate through each step and build table rows
for (const step of jsonReport.steps) {
const categories = step.lhr.categories;

const accessibilityScore = categories["accessibility"]?.score ?? "/";
const performanceScore = categories["performance"]?.score ?? "/";
const bestPracticesScore = categories["best-practices"]?.score ?? "/";

// Append row for the current step
markdownReport += `| ${step.name} | ${accessibilityScore} | ${performanceScore} | ${bestPracticesScore} |\n`;
}

// Write the markdown report to a file
fs.writeFileSync("./reports/markdown-report.md", markdownReport);
console.log(`Markdown report generated: ${reportFileName}`);

if (hasFailure) {
console.error(
"❌ Test failed: Some steps do not meet the score threshold."
);
} else {
console.log("✅ Test passed: All steps meet the score threshold.");
}

if (!process.env.CI) {
open(reportFileName, { wait: false });
}
}

captureReport();
Loading