Skip to content

Commit

Permalink
build: add performance-tests (#2539)
Browse files Browse the repository at this point in the history
  • Loading branch information
gpbl authored Oct 13, 2024
1 parent e80f218 commit 7c21f19
Show file tree
Hide file tree
Showing 20 changed files with 1,721 additions and 246 deletions.
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 <io@gpbl.dev>",
"homepage": "https://daypicker.dev",
"packageManager": "pnpm@9.11.0",
"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

0 comments on commit 7c21f19

Please sign in to comment.