mirror of
https://github.com/rcourtman/Pulse.git
synced 2026-09-23 03:33:53 +00:00
cleanup: remove temporary test files from main repository
🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -1,153 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Test Backup Health Fix</title>
|
||||
<style>
|
||||
body { font-family: Arial, sans-serif; padding: 20px; }
|
||||
.status { margin: 20px 0; padding: 15px; border: 1px solid #ccc; background: #f0f0f0; }
|
||||
.success { background: #d4edda; border-color: #c3e6cb; }
|
||||
.error { background: #f8d7da; border-color: #f5c6cb; }
|
||||
pre { background: #f4f4f4; padding: 10px; overflow-x: auto; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Backup Health Fix Test</h1>
|
||||
|
||||
<div id="status" class="status">
|
||||
<h3>Instructions:</h3>
|
||||
<ol>
|
||||
<li>Start the Pulse server: <code>npm run dev</code></li>
|
||||
<li>Open this file in a browser</li>
|
||||
<li>Open the browser console to see debug logs</li>
|
||||
<li>Click "Connect to Pulse" below</li>
|
||||
<li>Look for "[Backup Health Debug]" messages in the console</li>
|
||||
</ol>
|
||||
</div>
|
||||
|
||||
<button onclick="connectToPulse()">Connect to Pulse</button>
|
||||
|
||||
<div id="results"></div>
|
||||
|
||||
<script>
|
||||
async function connectToPulse() {
|
||||
const statusDiv = document.getElementById('status');
|
||||
const resultsDiv = document.getElementById('results');
|
||||
|
||||
statusDiv.innerHTML = '<p>Connecting to Pulse WebSocket...</p>';
|
||||
|
||||
try {
|
||||
const ws = new WebSocket('ws://localhost:7655');
|
||||
|
||||
ws.onopen = () => {
|
||||
console.log('[Test] Connected to Pulse');
|
||||
statusDiv.innerHTML = '<p>Connected! Check the browser console for debug logs.</p>';
|
||||
statusDiv.className = 'status success';
|
||||
|
||||
// Request initial data
|
||||
ws.send(JSON.stringify({ type: 'requestData' }));
|
||||
};
|
||||
|
||||
ws.onmessage = (event) => {
|
||||
const data = JSON.parse(event.data);
|
||||
if (data.type === 'stateUpdate') {
|
||||
console.log('[Test] Received state update');
|
||||
analyzeBackupData(data);
|
||||
}
|
||||
};
|
||||
|
||||
ws.onerror = (error) => {
|
||||
console.error('[Test] WebSocket error:', error);
|
||||
statusDiv.innerHTML = '<p>Error connecting to Pulse. Make sure the server is running.</p>';
|
||||
statusDiv.className = 'status error';
|
||||
};
|
||||
|
||||
ws.onclose = () => {
|
||||
console.log('[Test] WebSocket closed');
|
||||
};
|
||||
|
||||
} catch (error) {
|
||||
console.error('[Test] Error:', error);
|
||||
statusDiv.innerHTML = '<p>Error: ' + error.message + '</p>';
|
||||
statusDiv.className = 'status error';
|
||||
}
|
||||
}
|
||||
|
||||
function analyzeBackupData(data) {
|
||||
const resultsDiv = document.getElementById('results');
|
||||
|
||||
// Count guests
|
||||
const totalGuests = (data.vmsData || []).length + (data.containersData || []).length;
|
||||
|
||||
// Analyze backup ages
|
||||
const now = Date.now() / 1000;
|
||||
const categories = {
|
||||
'<24h': 0,
|
||||
'1-7d': 0,
|
||||
'7-14d': 0,
|
||||
'>14d': 0,
|
||||
'none': 0
|
||||
};
|
||||
|
||||
const allGuests = [...(data.vmsData || []), ...(data.containersData || [])];
|
||||
allGuests.forEach(guest => {
|
||||
let mostRecentBackup = null;
|
||||
|
||||
// Check PBS backups
|
||||
if (data.pbs && Array.isArray(data.pbs)) {
|
||||
data.pbs.forEach(pbsInstance => {
|
||||
if (pbsInstance.datastores) {
|
||||
pbsInstance.datastores.forEach(ds => {
|
||||
if (ds.snapshots) {
|
||||
ds.snapshots.forEach(snap => {
|
||||
if (snap['backup-id'] == guest.vmid) {
|
||||
const backupTime = snap['backup-time'];
|
||||
if (!mostRecentBackup || backupTime > mostRecentBackup) {
|
||||
mostRecentBackup = backupTime;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (!mostRecentBackup) {
|
||||
categories.none++;
|
||||
} else {
|
||||
const ageSeconds = now - mostRecentBackup;
|
||||
const ageDays = ageSeconds / (24 * 60 * 60);
|
||||
if (ageDays < 1) categories['<24h']++;
|
||||
else if (ageDays <= 7) categories['1-7d']++;
|
||||
else if (ageDays <= 14) categories['7-14d']++;
|
||||
else categories['>14d']++;
|
||||
}
|
||||
});
|
||||
|
||||
// Calculate expected health score
|
||||
const totalIssues = categories['>14d'] + categories.none;
|
||||
const expectedHealthScore = Math.round(((totalGuests - totalIssues) / totalGuests) * 100);
|
||||
|
||||
const html = `
|
||||
<div class="status">
|
||||
<h3>Expected Results:</h3>
|
||||
<pre>
|
||||
Total Guests: ${totalGuests}
|
||||
Health Distribution:
|
||||
<24h: ${categories['<24h']} guests
|
||||
1-7d: ${categories['1-7d']} guests
|
||||
7-14d: ${categories['7-14d']} guests
|
||||
>14d: ${categories['>14d']} guests
|
||||
none: ${categories.none} guests
|
||||
|
||||
Expected Health Score: ${expectedHealthScore}%
|
||||
</pre>
|
||||
<p><strong>Check the browser console for "[Backup Health Debug]" messages to see what the UI is actually calculating.</strong></p>
|
||||
</div>
|
||||
`;
|
||||
|
||||
resultsDiv.innerHTML = html;
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,105 +0,0 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
/**
|
||||
* Timestamp Validation Test
|
||||
* Simple test to verify our timestamp validation logic works correctly
|
||||
*/
|
||||
|
||||
const AlertManager = require('./server/alertManager');
|
||||
|
||||
function testTimestampValidation() {
|
||||
console.log('🔍 Testing Timestamp Validation Logic...\n');
|
||||
|
||||
const alertManager = new AlertManager();
|
||||
|
||||
try {
|
||||
console.log('1. Testing with valid triggeredAt...');
|
||||
const alertWithTriggeredAt = {
|
||||
triggeredAt: 1640995200000,
|
||||
lastUpdate: 1640995260000
|
||||
};
|
||||
const timestamp1 = alertManager.getValidTimestamp(alertWithTriggeredAt);
|
||||
console.log(` Result: ${timestamp1} (should be ${alertWithTriggeredAt.triggeredAt})`);
|
||||
if (timestamp1 !== alertWithTriggeredAt.triggeredAt) {
|
||||
throw new Error('Should use triggeredAt when available');
|
||||
}
|
||||
console.log('✅ PASS');
|
||||
|
||||
console.log('\n2. Testing with missing triggeredAt (should use lastUpdate)...');
|
||||
const alertWithLastUpdate = {
|
||||
lastUpdate: 1640995260000
|
||||
};
|
||||
const timestamp2 = alertManager.getValidTimestamp(alertWithLastUpdate);
|
||||
console.log(` Result: ${timestamp2} (should be ${alertWithLastUpdate.lastUpdate})`);
|
||||
if (timestamp2 !== alertWithLastUpdate.lastUpdate) {
|
||||
throw new Error('Should use lastUpdate when triggeredAt is missing');
|
||||
}
|
||||
console.log('✅ PASS');
|
||||
|
||||
console.log('\n3. Testing with both timestamps missing (should use current time)...');
|
||||
const alertWithoutTimestamps = {};
|
||||
const before = Date.now();
|
||||
const timestamp3 = alertManager.getValidTimestamp(alertWithoutTimestamps);
|
||||
const after = Date.now();
|
||||
console.log(` Result: ${timestamp3} (should be between ${before} and ${after})`);
|
||||
if (timestamp3 < before || timestamp3 > after) {
|
||||
throw new Error('Should use current time when both timestamps are missing');
|
||||
}
|
||||
console.log('✅ PASS');
|
||||
|
||||
console.log('\n4. Testing with invalid timestamps (should use current time)...');
|
||||
const alertWithInvalidTimestamps = {
|
||||
triggeredAt: 'invalid-date',
|
||||
lastUpdate: null
|
||||
};
|
||||
const before2 = Date.now();
|
||||
const timestamp4 = alertManager.getValidTimestamp(alertWithInvalidTimestamps);
|
||||
const after2 = Date.now();
|
||||
console.log(` Result: ${timestamp4} (should be between ${before2} and ${after2})`);
|
||||
if (timestamp4 < before2 || timestamp4 > after2) {
|
||||
throw new Error('Should use current time when timestamps are invalid');
|
||||
}
|
||||
console.log('✅ PASS');
|
||||
|
||||
console.log('\n5. Testing ISO string generation (the original error)...');
|
||||
const testTimestamps = [
|
||||
1640995200000, // Valid timestamp
|
||||
'invalid-date', // Invalid string
|
||||
null, // Null
|
||||
undefined, // Undefined
|
||||
NaN // NaN
|
||||
];
|
||||
|
||||
testTimestamps.forEach((testTs, index) => {
|
||||
const testAlert = { triggeredAt: testTs };
|
||||
const validTs = alertManager.getValidTimestamp(testAlert);
|
||||
try {
|
||||
const isoString = new Date(validTs).toISOString();
|
||||
console.log(` Test ${index + 1}: ${testTs} → ${validTs} → ${isoString} ✅`);
|
||||
} catch (error) {
|
||||
throw new Error(`Failed to generate ISO string for ${testTs}: ${error.message}`);
|
||||
}
|
||||
});
|
||||
console.log('✅ PASS - No RangeError exceptions thrown');
|
||||
|
||||
console.log('\n🎉 All Timestamp Validation Tests Passed!');
|
||||
console.log(' ✅ Valid timestamps are preserved');
|
||||
console.log(' ✅ Invalid timestamps fall back to current time');
|
||||
console.log(' ✅ ISO string generation never throws RangeError');
|
||||
console.log(' ✅ Teams webhook "Time Value Error" is completely fixed');
|
||||
|
||||
console.log('\n📝 Summary:');
|
||||
console.log(' - The original bug was caused by undefined alert.timestamp');
|
||||
console.log(' - Our fix adds robust validation with proper fallbacks');
|
||||
console.log(' - The getValidTimestamp() method ensures valid dates always');
|
||||
console.log(' - Teams webhook notifications will now work reliably');
|
||||
|
||||
} catch (error) {
|
||||
console.error('❌ Test failed:', error.message);
|
||||
process.exit(1);
|
||||
} finally {
|
||||
alertManager.destroy();
|
||||
}
|
||||
}
|
||||
|
||||
testTimestampValidation();
|
||||
@@ -1,132 +0,0 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
/**
|
||||
* Webhook Integration Test
|
||||
* This script tests the webhook functionality by simulating alert triggers
|
||||
*/
|
||||
|
||||
const axios = require('axios');
|
||||
|
||||
const PULSE_API_BASE = 'http://localhost:7655/api';
|
||||
const WEBHOOK_SERVER = 'http://localhost:3001/webhook';
|
||||
|
||||
async function testWebhookIntegration() {
|
||||
console.log('🔍 Testing Webhook Integration...\n');
|
||||
|
||||
try {
|
||||
// 1. Check if Pulse server is running
|
||||
console.log('1. Checking Pulse server status...');
|
||||
const healthResponse = await axios.get(`${PULSE_API_BASE}/health`);
|
||||
console.log('✅ Pulse server is running');
|
||||
|
||||
// 2. Check if webhook server is running
|
||||
console.log('\n2. Checking webhook server status...');
|
||||
const webhookTestResponse = await axios.post(WEBHOOK_SERVER, {
|
||||
test: true,
|
||||
message: 'Integration test ping'
|
||||
});
|
||||
console.log('✅ Webhook server is responding');
|
||||
|
||||
// 3. Get current alert configuration
|
||||
console.log('\n3. Fetching current alert configuration...');
|
||||
const alertsResponse = await axios.get(`${PULSE_API_BASE}/alerts`);
|
||||
const alertData = alertsResponse.data;
|
||||
|
||||
console.log(`📊 Alert System Status:`);
|
||||
console.log(` - Active alerts: ${alertData.stats.active}`);
|
||||
console.log(` - Total rules: ${alertData.stats.totalRules}`);
|
||||
console.log(` - Webhook channel enabled: ${alertData.stats.channels.find(c => c.id === 'default')?.enabled}`);
|
||||
|
||||
// 4. Test webhook using Pulse's built-in test endpoint
|
||||
console.log('\n4. Testing webhook using Pulse API...');
|
||||
const testWebhookApiResponse = await axios.post(`${PULSE_API_BASE}/test-webhook`, {
|
||||
url: WEBHOOK_SERVER,
|
||||
enabled: true
|
||||
});
|
||||
|
||||
if (testWebhookApiResponse.data.success) {
|
||||
console.log('✅ Webhook test via Pulse API succeeded');
|
||||
} else {
|
||||
console.log('❌ Webhook test via Pulse API failed:', testWebhookApiResponse.data.error);
|
||||
}
|
||||
|
||||
// 5. Test webhook payload format
|
||||
console.log('\n5. Testing webhook payload format...');
|
||||
const testPayload = {
|
||||
timestamp: new Date().toISOString(),
|
||||
alert: {
|
||||
id: "test_alert_" + Date.now(),
|
||||
rule: {
|
||||
name: "Webhook Integration Test",
|
||||
description: "Test alert to verify webhook functionality",
|
||||
severity: "warning",
|
||||
metric: "cpu"
|
||||
},
|
||||
guest: {
|
||||
name: "test-webhook-guest",
|
||||
id: "999",
|
||||
type: "test",
|
||||
node: "test-node",
|
||||
status: "running"
|
||||
},
|
||||
value: 92,
|
||||
threshold: 85,
|
||||
emoji: "⚠️"
|
||||
},
|
||||
embeds: [{
|
||||
title: "⚠️ Webhook Integration Test",
|
||||
description: "Test alert to verify webhook functionality",
|
||||
color: 15844367,
|
||||
fields: [
|
||||
{
|
||||
name: "Test Type",
|
||||
value: "Integration Test",
|
||||
inline: true
|
||||
},
|
||||
{
|
||||
name: "Status",
|
||||
value: "SUCCESS",
|
||||
inline: true
|
||||
}
|
||||
],
|
||||
footer: {
|
||||
text: "Pulse Monitoring System - Test Mode"
|
||||
}
|
||||
}]
|
||||
};
|
||||
|
||||
const testWebhookResponse = await axios.post(WEBHOOK_SERVER, testPayload, {
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'User-Agent': 'Pulse-Monitoring/1.0'
|
||||
}
|
||||
});
|
||||
|
||||
console.log('✅ Webhook payload test successful');
|
||||
|
||||
console.log('\n🎉 Webhook Integration Test Results:');
|
||||
console.log(' ✅ Pulse server: Running');
|
||||
console.log(' ✅ Webhook server: Running');
|
||||
console.log(' ✅ Alert system: Configured');
|
||||
console.log(' ✅ Webhook channel: Enabled');
|
||||
console.log(' ✅ Payload format: Valid');
|
||||
|
||||
console.log('\n📝 Next Steps:');
|
||||
console.log(' 1. Monitor the test-webhook.js console for incoming webhooks');
|
||||
console.log(' 2. Check if alerts are triggered naturally by your system metrics');
|
||||
console.log(' 3. If needed, temporarily lower alert thresholds to test real alerts');
|
||||
console.log(' 4. Webhook URL configured in .env: http://localhost:3001/webhook');
|
||||
|
||||
} catch (error) {
|
||||
console.error('❌ Webhook integration test failed:', error.message);
|
||||
|
||||
if (error.code === 'ECONNREFUSED') {
|
||||
console.log('\n💡 Troubleshooting:');
|
||||
console.log(' - Make sure both Pulse (port 7655) and test-webhook.js (port 3001) are running');
|
||||
console.log(' - Check that WEBHOOK_URL is set in .env file');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Run the test
|
||||
testWebhookIntegration();
|
||||
Reference in New Issue
Block a user