Files
cv-site/tests/mjs/9-hyperscript-def-limit.test.mjs
T
juanatsap 5d5b050029 feat: confirm no hyperscript def limit + update documentation
MAJOR FINDING: Latest hyperscript version has NO 3 def statement limit!

Test Results (tests/mjs/9-hyperscript-def-limit.test.mjs):
 1 def statement - PASS
 2 def statements - PASS
 3 def statements - PASS
 4 def statements - PASS (beyond historical limit)
 5 def statements - PASS (well beyond limit)

Changes:
1. Created comprehensive def limit test
   - tests/mjs/9-hyperscript-def-limit.test.mjs
   - Tests 1, 2, 3, 4, 5 def statements
   - Verifies both parsing and function execution
   - Provides detailed analysis and recommendations

2. Updated PROJECT-MEMORY.md
   - Section 2: Changed from "NEEDS RETESTING" to "REMOVED IN LATEST VERSION"
   - Documented test findings and historical context
   - Added migration plan for hyperscript file organization
   - Updated test count to 10 systematic tests

3. Updated doc/HYPERSCRIPT-RULES.md
   - Rule 2: Removed 3 def limit warning
   - Documented historical context (Hyperscript 0.9.12 had limit)
   - New best practice: Organize by category in separate files
   - Added recommended file structure

Impact:
- Can now use unlimited def statements in hyperscript
- Enables cleaner architecture with category-based organization
- Allows migration from cv-functions.js back to hyperscript
- Better alignment with hypermedia/server-driven pattern

Next Steps:
- Create organized hyperscript file structure
- Migrate toggle functions from JavaScript to hyperscript
- Migrate hover sync functions to hyperscript
- Test each migration thoroughly
2025-11-17 15:02:30 +00:00

590 lines
18 KiB
JavaScript
Executable File

#!/usr/bin/env bun
/**
* HYPERSCRIPT DEF STATEMENT LIMIT TEST
* =====================================
* Tests if hyperscript parser still has the 3 def statement limit
*
* CRITICAL: This test determines if we need to keep using JavaScript
* functions or if we can safely use more def statements in hyperscript.
*
* Historical context:
* - Hyperscript 0.9.12 had a hard limit of 3 def statements
* - We moved functions to JavaScript to work around this
* - Now using LATEST hyperscript version - need to verify if limit still exists
*
* Test methodology:
* 1. Create test page with 1, 2, 3, 4, 5 def statements
* 2. Check for parser errors after each addition
* 3. Verify functions actually work (not just parse)
* 4. Document findings for PROJECT-MEMORY.md
*/
import { chromium } from 'playwright';
const PORT = 1999;
const TEST_SERVER_URL = `http://localhost:${PORT}`;
// We'll need to check if the main server is running first
async function checkServerRunning() {
try {
const response = await fetch(TEST_SERVER_URL);
return response.ok;
} catch (e) {
return false;
}
}
async function testHyperscriptDefLimit() {
console.log('🧪 HYPERSCRIPT DEF STATEMENT LIMIT TEST\n');
console.log('='.repeat(70));
// Check if server is running
const serverRunning = await checkServerRunning();
if (!serverRunning) {
console.log(`\n⚠️ WARNING: Server not running on port ${PORT}`);
console.log('This test will create standalone HTML pages to test hyperscript limits.\n');
}
const browser = await chromium.launch({ headless: false });
const testResults = [];
const errors = [];
// ========================================================================
// TEST 1: Baseline - 1 def statement (should always work)
// ========================================================================
console.log("\n1️⃣ Testing 1 def statement...");
const page1 = await browser.newPage();
const html1 = `<!DOCTYPE html>
<html>
<head>
<title>1 Def Statement Test</title>
<script src="https://unpkg.com/hyperscript.org@latest"></script>
</head>
<body>
<h1>Test: 1 Def Statement</h1>
<button id="test-btn-1">Click me</button>
<div id="result-1"></div>
<script type="text/hyperscript">
def testFunction1()
put "Function 1 works!" into #result-1
end
</script>
<script type="text/hyperscript">
on click from #test-btn-1
call testFunction1()
end
</script>
</body>
</html>`;
await page1.setContent(html1);
await page1.waitForTimeout(1000);
const test1 = await page1.evaluate(() => {
const errors = [];
const warnings = [];
// Capture console errors
const originalError = console.error;
console.error = (...args) => {
errors.push(args.join(' '));
originalError.apply(console, args);
};
// Check for hyperscript parse errors
const hasParseError = document.body.innerText.includes('Parse Error') ||
document.body.innerText.includes('SyntaxError');
// Try to trigger the function
const btn = document.getElementById('test-btn-1');
const result = document.getElementById('result-1');
btn.click();
const functionWorks = result.innerText === "Function 1 works!";
return {
hasParseError,
functionWorks,
resultText: result.innerText,
errors: errors.length
};
});
console.log(` Parse errors: ${test1.hasParseError ? '❌ YES' : '✅ NO'}`);
console.log(` Function works: ${test1.functionWorks ? '✅ YES' : '❌ NO'}`);
console.log(` Result: "${test1.resultText}"`);
const test1Pass = !test1.hasParseError && test1.functionWorks;
console.log(` ${test1Pass ? '✅ PASS' : '❌ FAIL'} - 1 def statement`);
testResults.push({ test: '1 Def Statement', passed: test1Pass });
await page1.close();
// ========================================================================
// TEST 2: 2 def statements
// ========================================================================
console.log("\n2️⃣ Testing 2 def statements...");
const page2 = await browser.newPage();
const html2 = `<!DOCTYPE html>
<html>
<head>
<title>2 Def Statements Test</title>
<script src="https://unpkg.com/hyperscript.org@latest"></script>
</head>
<body>
<h1>Test: 2 Def Statements</h1>
<button id="test-btn-1">Test 1</button>
<button id="test-btn-2">Test 2</button>
<div id="result"></div>
<script type="text/hyperscript">
def testFunction1()
put "Function 1 works!" into #result
end
def testFunction2()
put "Function 2 works!" into #result
end
</script>
<script type="text/hyperscript">
on click from #test-btn-1
call testFunction1()
end
on click from #test-btn-2
call testFunction2()
end
</script>
</body>
</html>`;
await page2.setContent(html2);
await page2.waitForTimeout(1000);
const test2 = await page2.evaluate(() => {
const hasParseError = document.body.innerText.includes('Parse Error') ||
document.body.innerText.includes('SyntaxError');
const btn1 = document.getElementById('test-btn-1');
const btn2 = document.getElementById('test-btn-2');
const result = document.getElementById('result');
btn1.click();
const func1Works = result.innerText === "Function 1 works!";
btn2.click();
const func2Works = result.innerText === "Function 2 works!";
return {
hasParseError,
func1Works,
func2Works,
bothWork: func1Works && func2Works
};
});
console.log(` Parse errors: ${test2.hasParseError ? '❌ YES' : '✅ NO'}`);
console.log(` Function 1 works: ${test2.func1Works ? '✅ YES' : '❌ NO'}`);
console.log(` Function 2 works: ${test2.func2Works ? '✅ YES' : '❌ NO'}`);
const test2Pass = !test2.hasParseError && test2.bothWork;
console.log(` ${test2Pass ? '✅ PASS' : '❌ FAIL'} - 2 def statements`);
testResults.push({ test: '2 Def Statements', passed: test2Pass });
await page2.close();
// ========================================================================
// TEST 3: 3 def statements (CRITICAL - historical limit)
// ========================================================================
console.log("\n3️⃣ Testing 3 def statements (CRITICAL - historical limit)...");
const page3 = await browser.newPage();
const html3 = `<!DOCTYPE html>
<html>
<head>
<title>3 Def Statements Test</title>
<script src="https://unpkg.com/hyperscript.org@latest"></script>
</head>
<body>
<h1>Test: 3 Def Statements</h1>
<button id="test-btn-1">Test 1</button>
<button id="test-btn-2">Test 2</button>
<button id="test-btn-3">Test 3</button>
<div id="result"></div>
<script type="text/hyperscript">
def testFunction1()
put "Function 1 works!" into #result
end
def testFunction2()
put "Function 2 works!" into #result
end
def testFunction3()
put "Function 3 works!" into #result
end
</script>
<script type="text/hyperscript">
on click from #test-btn-1
call testFunction1()
end
on click from #test-btn-2
call testFunction2()
end
on click from #test-btn-3
call testFunction3()
end
</script>
</body>
</html>`;
await page3.setContent(html3);
await page3.waitForTimeout(1000);
const test3 = await page3.evaluate(() => {
const hasParseError = document.body.innerText.includes('Parse Error') ||
document.body.innerText.includes('SyntaxError');
const btn1 = document.getElementById('test-btn-1');
const btn2 = document.getElementById('test-btn-2');
const btn3 = document.getElementById('test-btn-3');
const result = document.getElementById('result');
btn1.click();
const func1Works = result.innerText === "Function 1 works!";
btn2.click();
const func2Works = result.innerText === "Function 2 works!";
btn3.click();
const func3Works = result.innerText === "Function 3 works!";
return {
hasParseError,
func1Works,
func2Works,
func3Works,
allWork: func1Works && func2Works && func3Works
};
});
console.log(` Parse errors: ${test3.hasParseError ? '❌ YES' : '✅ NO'}`);
console.log(` Function 1 works: ${test3.func1Works ? '✅ YES' : '❌ NO'}`);
console.log(` Function 2 works: ${test3.func2Works ? '✅ YES' : '❌ NO'}`);
console.log(` Function 3 works: ${test3.func3Works ? '✅ YES' : '❌ NO'}`);
const test3Pass = !test3.hasParseError && test3.allWork;
console.log(` ${test3Pass ? '✅ PASS' : '❌ FAIL'} - 3 def statements`);
testResults.push({ test: '3 Def Statements', passed: test3Pass });
await page3.close();
// ========================================================================
// TEST 4: 4 def statements (BEYOND historical limit)
// ========================================================================
console.log("\n4️⃣ Testing 4 def statements (BEYOND historical limit)...");
const page4 = await browser.newPage();
const html4 = `<!DOCTYPE html>
<html>
<head>
<title>4 Def Statements Test</title>
<script src="https://unpkg.com/hyperscript.org@latest"></script>
</head>
<body>
<h1>Test: 4 Def Statements</h1>
<button id="test-btn-1">Test 1</button>
<button id="test-btn-2">Test 2</button>
<button id="test-btn-3">Test 3</button>
<button id="test-btn-4">Test 4</button>
<div id="result"></div>
<script type="text/hyperscript">
def testFunction1()
put "Function 1 works!" into #result
end
def testFunction2()
put "Function 2 works!" into #result
end
def testFunction3()
put "Function 3 works!" into #result
end
def testFunction4()
put "Function 4 works!" into #result
end
</script>
<script type="text/hyperscript">
on click from #test-btn-1
call testFunction1()
end
on click from #test-btn-2
call testFunction2()
end
on click from #test-btn-3
call testFunction3()
end
on click from #test-btn-4
call testFunction4()
end
</script>
</body>
</html>`;
await page4.setContent(html4);
await page4.waitForTimeout(1000);
const test4 = await page4.evaluate(() => {
const hasParseError = document.body.innerText.includes('Parse Error') ||
document.body.innerText.includes('SyntaxError');
const btn1 = document.getElementById('test-btn-1');
const btn2 = document.getElementById('test-btn-2');
const btn3 = document.getElementById('test-btn-3');
const btn4 = document.getElementById('test-btn-4');
const result = document.getElementById('result');
btn1.click();
const func1Works = result.innerText === "Function 1 works!";
btn2.click();
const func2Works = result.innerText === "Function 2 works!";
btn3.click();
const func3Works = result.innerText === "Function 3 works!";
btn4.click();
const func4Works = result.innerText === "Function 4 works!";
return {
hasParseError,
func1Works,
func2Works,
func3Works,
func4Works,
allWork: func1Works && func2Works && func3Works && func4Works
};
});
console.log(` Parse errors: ${test4.hasParseError ? '❌ YES' : '✅ NO'}`);
console.log(` Function 1 works: ${test4.func1Works ? '✅ YES' : '❌ NO'}`);
console.log(` Function 2 works: ${test4.func2Works ? '✅ YES' : '❌ NO'}`);
console.log(` Function 3 works: ${test4.func3Works ? '✅ YES' : '❌ NO'}`);
console.log(` Function 4 works: ${test4.func4Works ? '✅ YES' : '❌ NO'}`);
const test4Pass = !test4.hasParseError && test4.allWork;
console.log(` ${test4Pass ? '✅ PASS' : '❌ FAIL'} - 4 def statements`);
testResults.push({ test: '4 Def Statements', passed: test4Pass });
await page4.close();
// ========================================================================
// TEST 5: 5 def statements (well beyond limit)
// ========================================================================
console.log("\n5️⃣ Testing 5 def statements (well beyond limit)...");
const page5 = await browser.newPage();
const html5 = `<!DOCTYPE html>
<html>
<head>
<title>5 Def Statements Test</title>
<script src="https://unpkg.com/hyperscript.org@latest"></script>
</head>
<body>
<h1>Test: 5 Def Statements</h1>
<button id="test-btn-1">Test 1</button>
<button id="test-btn-2">Test 2</button>
<button id="test-btn-3">Test 3</button>
<button id="test-btn-4">Test 4</button>
<button id="test-btn-5">Test 5</button>
<div id="result"></div>
<script type="text/hyperscript">
def testFunction1()
put "Function 1 works!" into #result
end
def testFunction2()
put "Function 2 works!" into #result
end
def testFunction3()
put "Function 3 works!" into #result
end
def testFunction4()
put "Function 4 works!" into #result
end
def testFunction5()
put "Function 5 works!" into #result
end
</script>
<script type="text/hyperscript">
on click from #test-btn-1
call testFunction1()
end
on click from #test-btn-2
call testFunction2()
end
on click from #test-btn-3
call testFunction3()
end
on click from #test-btn-4
call testFunction4()
end
on click from #test-btn-5
call testFunction5()
end
</script>
</body>
</html>`;
await page5.setContent(html5);
await page5.waitForTimeout(1000);
const test5 = await page5.evaluate(() => {
const hasParseError = document.body.innerText.includes('Parse Error') ||
document.body.innerText.includes('SyntaxError');
const btn1 = document.getElementById('test-btn-1');
const btn2 = document.getElementById('test-btn-2');
const btn3 = document.getElementById('test-btn-3');
const btn4 = document.getElementById('test-btn-4');
const btn5 = document.getElementById('test-btn-5');
const result = document.getElementById('result');
btn1.click();
const func1Works = result.innerText === "Function 1 works!";
btn2.click();
const func2Works = result.innerText === "Function 2 works!";
btn3.click();
const func3Works = result.innerText === "Function 3 works!";
btn4.click();
const func4Works = result.innerText === "Function 4 works!";
btn5.click();
const func5Works = result.innerText === "Function 5 works!";
return {
hasParseError,
func1Works,
func2Works,
func3Works,
func4Works,
func5Works,
allWork: func1Works && func2Works && func3Works && func4Works && func5Works
};
});
console.log(` Parse errors: ${test5.hasParseError ? '❌ YES' : '✅ NO'}`);
console.log(` Function 1 works: ${test5.func1Works ? '✅ YES' : '❌ NO'}`);
console.log(` Function 2 works: ${test5.func2Works ? '✅ YES' : '❌ NO'}`);
console.log(` Function 3 works: ${test5.func3Works ? '✅ YES' : '❌ NO'}`);
console.log(` Function 4 works: ${test5.func4Works ? '✅ YES' : '❌ NO'}`);
console.log(` Function 5 works: ${test5.func5Works ? '✅ YES' : '❌ NO'}`);
const test5Pass = !test5.hasParseError && test5.allWork;
console.log(` ${test5Pass ? '✅ PASS' : '❌ FAIL'} - 5 def statements`);
testResults.push({ test: '5 Def Statements', passed: test5Pass });
await page5.close();
// ========================================================================
// FINAL SUMMARY & ANALYSIS
// ========================================================================
console.log("\n" + "=".repeat(70));
console.log("📊 TEST SUMMARY & ANALYSIS\n");
const totalTests = testResults.length;
const passedTests = testResults.filter(r => r.passed).length;
const failedTests = totalTests - passedTests;
testResults.forEach(result => {
console.log(` ${result.passed ? '✅' : '❌'} ${result.test}`);
});
console.log(`\n Total: ${passedTests}/${totalTests} tests passed`);
console.log("\n" + "=".repeat(70));
console.log("🔍 ANALYSIS & CONCLUSION\n");
// Determine if limit exists
const limitExists = !test4.allWork || test4.hasParseError;
const limitAt = passedTests;
if (passedTests === 5) {
console.log("✅ GOOD NEWS: NO 3 DEF LIMIT!");
console.log("\n The latest hyperscript version does NOT have the 3 def limit.");
console.log(" All 5 def statements worked perfectly.");
console.log("\n RECOMMENDATION:");
console.log(" - We can safely use def statements in hyperscript");
console.log(" - No need to keep using JavaScript workarounds");
console.log(" - Can simplify code by moving functions back to hyperscript");
console.log("\n ACTION ITEMS:");
console.log(" 1. Update PROJECT-MEMORY.md: Remove def limit warning");
console.log(" 2. Consider refactoring: Move simple functions from cv-functions.js to hyperscript");
console.log(" 3. Update HYPERSCRIPT-RULES.md: Document new findings");
} else if (passedTests >= 3 && !test4.allWork) {
console.log("⚠️ LIMIT CONFIRMED: 3 DEF STATEMENT LIMIT STILL EXISTS");
console.log("\n The historical 3 def limit is STILL present.");
console.log(` Working: ${passedTests} def statements`);
console.log(" Failed: 4+ def statements");
console.log("\n RECOMMENDATION:");
console.log(" - Keep current JavaScript workaround approach");
console.log(" - Continue using cv-functions.js for toggle functions");
console.log(" - Limit hyperscript def statements to 3 maximum");
console.log("\n ACTION ITEMS:");
console.log(" 1. Update PROJECT-MEMORY.md: Confirm limit still exists");
console.log(" 2. Keep HYPERSCRIPT-RULES.md warnings in place");
console.log(" 3. Document this test result for future reference");
} else {
console.log("⚠️ UNEXPECTED RESULT");
console.log("\n Some basic def statements failed unexpectedly.");
console.log(" This requires further investigation.");
console.log("\n ACTION ITEMS:");
console.log(" 1. Check hyperscript version being loaded");
console.log(" 2. Review console errors in browser");
console.log(" 3. Verify hyperscript.org CDN is working");
}
console.log("\n" + "=".repeat(70));
console.log("\nBrowser will stay open for manual verification.");
console.log("Please test the buttons in the last page to confirm results.");
console.log("Press Ctrl+C when done.\n");
await new Promise(() => {}); // Keep browser open
}
await testHyperscriptDefLimit();