The testResults event (also called tests event) is fired when project tests are executed.
Event Payload
The event callback receives an object with the following structure:
An array of test results, where each test result has the following structure:Show TestResult Structure
The time taken to run the test in milliseconds
An array of error messages (empty if test passed)
The test result status:
"pass": Test passed successfully
"fail": Test failed with errors
"skip": Test was skipped
An array representing the hierarchical path to the test (e.g. ["describe block", "test name"])
An error message if the test execution itself failed (optional)
When It Fires
- When
runTests() method is called
- When tests auto-run (if
autotest configuration is enabled)
- After code changes trigger test execution
Usage Example
import { createPlayground } from "livecodes";
createPlayground("#container").then((playground) => {
// Listen for test results
const testsWatcher = playground.watch("tests", ({ results, error }) => {
if (error) {
console.error("Test execution failed:", error);
return;
}
results.forEach((testResult) => {
const testName = testResult.testPath.join(" > ");
console.log(`Test: ${testName}`);
console.log(`Status: ${testResult.status}`);
console.log(`Duration: ${testResult.duration}ms`);
if (testResult.status === "fail") {
console.log("Errors:", testResult.errors);
}
});
});
// Run tests
playground.runTests();
// Later, remove the watcher
// testsWatcher.remove();
});
Common Use Cases
Display Test Results Summary
playground.watch("tests", ({ results, error }) => {
if (error) {
console.error("Test error:", error);
return;
}
const passed = results.filter(r => r.status === "pass").length;
const failed = results.filter(r => r.status === "fail").length;
const skipped = results.filter(r => r.status === "skip").length;
const total = results.length;
console.log(`Test Results: ${passed}/${total} passed`);
if (failed > 0) console.log(`Failed: ${failed}`);
if (skipped > 0) console.log(`Skipped: ${skipped}`);
});
Show Test Details
playground.watch("tests", ({ results }) => {
results.forEach((result) => {
const name = result.testPath.join(" > ");
const icon = result.status === "pass" ? "✓" :
result.status === "fail" ? "✗" : "○";
console.log(`${icon} ${name} (${result.duration}ms)`);
// Show errors for failed tests
if (result.status === "fail" && result.errors.length > 0) {
result.errors.forEach(error => {
console.error(` Error: ${error}`);
});
}
});
});
Update UI with Test Status
const statusElement = document.querySelector("#test-status");
const detailsElement = document.querySelector("#test-details");
playground.watch("tests", ({ results, error }) => {
if (error) {
statusElement.textContent = "Test Error";
statusElement.className = "error";
detailsElement.textContent = error;
return;
}
const allPassed = results.every(r => r.status === "pass" || r.status === "skip");
statusElement.textContent = allPassed ? "All Tests Passed" : "Some Tests Failed";
statusElement.className = allPassed ? "success" : "failure";
// Show details
detailsElement.innerHTML = results.map(r => {
const name = r.testPath.join(" > ");
return `<div class="${r.status}">${name}</div>`;
}).join("");
});
Calculate Test Coverage
let testHistory = [];
playground.watch("tests", ({ results }) => {
const passRate = (results.filter(r => r.status === "pass").length / results.length) * 100;
testHistory.push({
timestamp: new Date(),
passRate: passRate,
total: results.length,
});
console.log(`Current pass rate: ${passRate.toFixed(1)}%`);
});
Trigger Actions on Test Completion
playground.watch("tests", async ({ results, error }) => {
if (error) return;
const allPassed = results.every(r => r.status === "pass" || r.status === "skip");
if (allPassed) {
console.log("All tests passed! Running deployment...");
// Trigger deployment or other actions
await deployProject();
} else {
console.log("Tests failed. Deployment blocked.");
// Send notification
notifyTestFailure(results.filter(r => r.status === "fail"));
}
});
Continuous Testing
// Enable auto-test when creating playground
createPlayground("#container", {
config: {
autotest: true,
},
}).then((playground) => {
playground.watch("tests", ({ results }) => {
// This will run automatically on code changes
console.log("Tests auto-ran:", results.length, "tests");
});
});
playground.watch("tests", ({ results }) => {
const totalDuration = results.reduce((sum, r) => sum + r.duration, 0);
const avgDuration = totalDuration / results.length;
console.log(`Total test time: ${totalDuration}ms`);
console.log(`Average per test: ${avgDuration.toFixed(2)}ms`);
// Find slowest test
const slowest = results.reduce((max, r) =>
r.duration > max.duration ? r : max
);
console.log(`Slowest test: ${slowest.testPath.join(" > ")} (${slowest.duration}ms)`);
});
Removing the Watcher
const watcher = playground.watch("tests", ({ results }) => {
console.log("Tests completed");
});
// Stop watching for test results
watcher.remove();