Skip to content

Commit e76cb84

Browse files
committed
wip
1 parent 578a6cb commit e76cb84

File tree

11 files changed

+73398
-22
lines changed

11 files changed

+73398
-22
lines changed

.github/workflows/ci.yml

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,8 @@ jobs:
125125
# needs: npm-install
126126
name: Run tests
127127
runs-on: ubuntu-latest
128+
permissions:
129+
contents: write # Needed to push performance baseline updates
128130
env:
129131
NEXT_PUBLIC_BASE_URL: https://infinite-table.com/.netlify/functions/json-server
130132
NEXT_PUBLIC_INFINITE_LICENSE_KEY: ${{ secrets.NEXT_PUBLIC_INFINITE_LICENSE_KEY }}
@@ -134,6 +136,8 @@ jobs:
134136

135137
steps:
136138
- uses: actions/checkout@v4
139+
with:
140+
token: ${{ secrets.GITHUB_TOKEN }}
137141
- name: Use Node.js ${{ matrix.node-version }}
138142
uses: actions/setup-node@v3
139143
with:
@@ -189,3 +193,17 @@ jobs:
189193
with:
190194
path: '~/.cache/ms-playwright'
191195
key: '${{ runner.os }}-playwright-${{ steps.playwright-version.outputs.version }}'
196+
197+
- name: Commit updated performance baselines
198+
# if: github.ref == 'refs/heads/main' || github.ref == 'refs/heads/master'
199+
run: |
200+
cd examples
201+
if [ -n "$(git status --porcelain perf-baselines.ci.json)" ]; then
202+
git config --local user.email "github-actions[bot]@users.noreply.github.com"
203+
git config --local user.name "github-actions[bot]"
204+
git add perf-baselines.ci.json
205+
git commit -m "chore: update CI performance baselines [skip ci]"
206+
git push
207+
else
208+
echo "No changes to performance baselines"
209+
fi

examples/package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818
"test:debug": "chokidar '**/*.spec.ts' -c 'echo \"\n{path} was modified\n\" && npm run play:test -- --retries=0 {path} --debug'",
1919
"test:watch": "chokidar '**/*.spec.ts' '**/*.page.tsx' -c 'test_file_path=$(echo {path} | sed s/page.tsx/spec.ts/) && npm run play:test -- --retries=0 ${test_file_path}'",
2020
"ci:test": "concurrently -s first --kill-others \"npm run start-server -- -s\" \"npm run play:test\"",
21+
"perf:list": "node scripts/perf-baseline.js list",
22+
"perf:copy-to-ci": "node scripts/perf-baseline.js copy-to-ci",
2123
"tsc": "tsc --project tsconfig.json",
2224
"tscw": "tsc --watch --project tsconfig.json"
2325
},

examples/perf-baselines.ci.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
{
2+
"tests/table/props/data/update:clicks update button 30 times with performance tracing": {
3+
"scriptingTime": 1419.78,
4+
"renderingTime": 10.85,
5+
"paintingTime": 5.62,
6+
"totalTime": 1436.25,
7+
"threshold": 10
8+
}
9+
}

examples/scripts/perf-baseline.js

Lines changed: 169 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,169 @@
1+
#!/usr/bin/env node
2+
3+
/**
4+
* CLI tool for managing performance baselines
5+
*
6+
* Usage:
7+
* node scripts/perf-baseline.js list - List all baseline files
8+
* node scripts/perf-baseline.js copy-to-ci - Copy your dev baselines to CI file
9+
*/
10+
11+
const fs = require('fs');
12+
const path = require('path');
13+
const { execSync } = require('child_process');
14+
15+
const BASELINES_DIR = path.resolve(__dirname, '..');
16+
const CI_PATH = path.resolve(BASELINES_DIR, 'perf-baselines.ci.json');
17+
18+
function getDevName() {
19+
if (process.env.PERF_DEV_NAME) {
20+
return process.env.PERF_DEV_NAME;
21+
}
22+
try {
23+
const gitUser = execSync('git config user.name', {
24+
encoding: 'utf-8',
25+
}).trim();
26+
return gitUser
27+
.toLowerCase()
28+
.replace(/[^a-z0-9]/g, '-')
29+
.replace(/-+/g, '-');
30+
} catch {
31+
return 'local';
32+
}
33+
}
34+
35+
function getDevPath() {
36+
return path.resolve(BASELINES_DIR, `perf-baselines.${getDevName()}.json`);
37+
}
38+
39+
function loadBaselines(filePath) {
40+
if (!fs.existsSync(filePath)) {
41+
return {};
42+
}
43+
const content = fs.readFileSync(filePath, 'utf-8');
44+
return JSON.parse(content);
45+
}
46+
47+
function saveBaselines(filePath, baselines) {
48+
fs.writeFileSync(filePath, JSON.stringify(baselines, null, 2) + '\n');
49+
}
50+
51+
function printBaselines(baselines, title) {
52+
const entries = Object.entries(baselines);
53+
54+
if (entries.length === 0) {
55+
console.log(`${title}: No baselines found.\n`);
56+
return;
57+
}
58+
59+
console.log(`\n${title}:\n`);
60+
61+
for (const [name, baseline] of entries) {
62+
// Extract just the test name part after the colon
63+
const testNameParts = name.split(':');
64+
const shortPath = testNameParts[0].replace('tests/', '');
65+
const testTitle = testNameParts.slice(1).join(':');
66+
67+
console.log(`📊 ${shortPath}`);
68+
console.log(` "${testTitle}"`);
69+
console.log(` ┌──────────────────────────────────┐`);
70+
console.log(
71+
` │ Scripting: ${String(baseline.scriptingTime + 'ms').padEnd(
72+
10,
73+
)} (threshold: ${baseline.threshold}%)`,
74+
);
75+
if (baseline.renderingTime !== undefined) {
76+
console.log(
77+
` │ Rendering: ${String(baseline.renderingTime + 'ms').padEnd(10)} │`,
78+
);
79+
console.log(
80+
` │ Painting: ${String(baseline.paintingTime + 'ms').padEnd(10)} │`,
81+
);
82+
console.log(
83+
` │ Total: ${String(baseline.totalTime + 'ms').padEnd(10)} │`,
84+
);
85+
}
86+
console.log(` └──────────────────────────────────┘`);
87+
console.log('');
88+
}
89+
90+
console.log(`Total: ${entries.length} baseline(s)\n`);
91+
}
92+
93+
function listBaselines() {
94+
// Find all baseline files
95+
const files = fs
96+
.readdirSync(BASELINES_DIR)
97+
.filter((f) => f.startsWith('perf-baselines.') && f.endsWith('.json'));
98+
99+
const devName = getDevName();
100+
101+
console.log(`\nYour dev name: ${devName}`);
102+
console.log(`Your baseline file: perf-baselines.${devName}.json\n`);
103+
104+
// Show CI baselines first
105+
if (files.includes('perf-baselines.ci.json')) {
106+
printBaselines(loadBaselines(CI_PATH), '🔄 CI Baselines');
107+
}
108+
109+
// Show all dev baselines
110+
for (const file of files.sort()) {
111+
if (file === 'perf-baselines.ci.json') continue;
112+
113+
const devMatch = file.match(/^perf-baselines\.(.+)\.json$/);
114+
if (devMatch) {
115+
const name = devMatch[1];
116+
const isYou = name === devName ? ' (you)' : '';
117+
const filePath = path.resolve(BASELINES_DIR, file);
118+
printBaselines(loadBaselines(filePath), `👤 ${name}${isYou}`);
119+
}
120+
}
121+
}
122+
123+
function copyToCi() {
124+
const devPath = getDevPath();
125+
const devBaselines = loadBaselines(devPath);
126+
const ciBaselines = loadBaselines(CI_PATH);
127+
128+
if (Object.keys(devBaselines).length === 0) {
129+
console.log('❌ No dev baselines to copy.');
130+
return;
131+
}
132+
133+
// Merge dev into CI (dev overwrites CI for matching keys)
134+
const merged = { ...ciBaselines, ...devBaselines };
135+
saveBaselines(CI_PATH, merged);
136+
137+
console.log(
138+
`✅ Copied ${Object.keys(devBaselines).length} baseline(s) to CI file.`,
139+
);
140+
console.log(' Remember to commit perf-baselines.ci.json');
141+
}
142+
143+
// CLI handling
144+
const [, , command] = process.argv;
145+
146+
switch (command) {
147+
case 'list':
148+
listBaselines();
149+
break;
150+
case 'copy-to-ci':
151+
copyToCi();
152+
break;
153+
default:
154+
console.log(`
155+
Performance Baseline Manager
156+
157+
Usage:
158+
node scripts/perf-baseline.js <command>
159+
160+
Commands:
161+
list List all baseline files (CI and all devs)
162+
copy-to-ci Copy your dev baselines to CI file (then commit)
163+
164+
Files:
165+
perf-baselines.<your-name>.json - Your personal baselines (auto-updated, committed)
166+
perf-baselines.ci.json - CI baselines (committed, used in CI)
167+
`);
168+
process.exit(command ? 1 : 0);
169+
}

examples/src/pages/tests/table/props/data/lazy-load-simple-example.spec.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ async function getCallCount({ page }: { page: Page }) {
1010
return (await getFnCalls('dataSource', { page })).length;
1111
}
1212

13-
const TIMEOUT = 150;
13+
const TIMEOUT = 180;
1414

1515
export default test.describe.parallel('Lazy Load Data', () => {
1616
test('should work', async ({ page, tableModel }) => {

0 commit comments

Comments
 (0)