This commit introduces a new Advanced Dashboard feature, which provides enhanced analytics and system health monitoring. Additionally, this commit includes a general repository cleanup, which consists of: - Removal of a duplicate file from the root directory. - Addition of temporary report and documentation files to . - Relocation of several test files from the root to the directory. - Staging of various other modified files that were previously uncommitted. The new Advanced Dashboard feature includes: - and for the UI. - for the backend API. - for API documentation. New tests for smart packages and autosave functionality have also been added.
182 lines
6.3 KiB
JavaScript
182 lines
6.3 KiB
JavaScript
/**
|
|
* Advanced Dashboard API Tests
|
|
* Tests for PM2 logs, SQL status, and comprehensive health monitoring
|
|
*/
|
|
|
|
const { test, expect } = require('@playwright/test');
|
|
|
|
const BASE_URL = process.env.PLAYWRIGHT_BASE_URL || 'http://localhost:4032';
|
|
|
|
test.describe('Advanced Dashboard - Health APIs', () => {
|
|
|
|
test('GET /api/health/pm2-logs - Returns PM2 process information', async ({ request }) => {
|
|
const response = await request.get(`${BASE_URL}/api/health/pm2-logs`);
|
|
|
|
expect(response.status()).toBe(200);
|
|
|
|
const data = await response.json();
|
|
expect(data.success).toBe(true);
|
|
expect(Array.isArray(data.logs)).toBe(true);
|
|
expect(data.timestamp).toBeDefined();
|
|
|
|
// If logs exist, verify structure
|
|
if (data.logs.length > 0) {
|
|
const firstLog = data.logs[0];
|
|
expect(firstLog.name).toBeDefined();
|
|
expect(firstLog.status).toBeDefined();
|
|
expect(typeof firstLog.cpu).toBe('string');
|
|
expect(typeof firstLog.memory).toBe('number');
|
|
expect(typeof firstLog.restarts).toBe('number');
|
|
}
|
|
});
|
|
|
|
test('GET /api/health/sql-status - Returns comprehensive database status', async ({ request }) => {
|
|
const response = await request.get(`${BASE_URL}/api/health/sql-status`);
|
|
|
|
expect(response.status()).toBe(200);
|
|
|
|
const data = await response.json();
|
|
expect(data.status).toBeDefined();
|
|
expect(data.timestamp).toBeDefined();
|
|
expect(['ok', 'warning', 'error', 'disconnected']).toContain(data.status);
|
|
|
|
// Verify database metrics
|
|
if (data.connected) {
|
|
expect(typeof data.databaseSize).toBe('number');
|
|
expect(typeof data.databaseSize_MB).toBe('number');
|
|
expect(typeof data.tableCount).toBe('number');
|
|
expect(typeof data.activeQueries).toBe('number');
|
|
expect(typeof data.totalConnections).toBe('number');
|
|
expect(typeof data.indexCount).toBe('number');
|
|
}
|
|
});
|
|
|
|
test('GET /api/health/detailed - Returns detailed health check', async ({ request }) => {
|
|
const response = await request.get(`${BASE_URL}/api/health/detailed`);
|
|
|
|
expect(response.status()).toBe(200);
|
|
|
|
const data = await response.json();
|
|
expect(data.status).toBeDefined();
|
|
expect(['ok', 'degraded', 'error']).toContain(data.status);
|
|
expect(data.timestamp).toBeDefined();
|
|
expect(typeof data.uptime).toBe('number');
|
|
expect(data.checks).toBeDefined();
|
|
|
|
// Verify check structure
|
|
expect(data.checks.database).toBeDefined();
|
|
expect(data.checks.memory).toBeDefined();
|
|
});
|
|
|
|
test('GET /api/health/quick - Returns quick health status', async ({ request }) => {
|
|
const response = await request.get(`${BASE_URL}/api/health/quick`);
|
|
|
|
expect(response.status()).toBe(200);
|
|
|
|
const data = await response.json();
|
|
expect(['ok', 'degraded', 'error']).toContain(data.status);
|
|
expect(data.checks).toBeDefined();
|
|
});
|
|
|
|
test('GET /api/health/logs - Returns system logs', async ({ request }) => {
|
|
const response = await request.get(`${BASE_URL}/api/health/logs`);
|
|
|
|
expect(response.status()).toBe(200);
|
|
|
|
const data = await response.json();
|
|
expect(data.success).toBe(true);
|
|
expect(Array.isArray(data.logs)).toBe(true);
|
|
});
|
|
|
|
test('GET /api/health/stats - Returns performance statistics', async ({ request }) => {
|
|
const response = await request.get(`${BASE_URL}/api/health/stats`);
|
|
|
|
expect(response.status()).toBe(200);
|
|
|
|
const data = await response.json();
|
|
expect(data.success).toBe(true);
|
|
expect(Array.isArray(data.hourlyStats)).toBe(true);
|
|
expect(Array.isArray(data.topEndpoints)).toBe(true);
|
|
|
|
// Verify hourly stats structure
|
|
if (data.hourlyStats.length > 0) {
|
|
const stat = data.hourlyStats[0];
|
|
expect(stat.hour).toBeDefined();
|
|
expect(typeof stat.requests).toBe('number');
|
|
expect(typeof stat.avg_response_time).toBe('number');
|
|
}
|
|
});
|
|
|
|
test('PM2 logs contain valid process status', async ({ request }) => {
|
|
const response = await request.get(`${BASE_URL}/api/health/pm2-logs`);
|
|
const data = await response.json();
|
|
|
|
if (data.logs.length > 0) {
|
|
const validStatuses = ['online', 'stopping', 'stopped', 'waiting restart', 'one-launch-status'];
|
|
data.logs.forEach(log => {
|
|
expect(validStatuses).toContain(log.status);
|
|
});
|
|
}
|
|
});
|
|
|
|
test('SQL status provides meaningful database metrics', async ({ request }) => {
|
|
const response = await request.get(`${BASE_URL}/api/health/sql-status`);
|
|
const data = await response.json();
|
|
|
|
if (data.connected) {
|
|
// Database size should be reasonable
|
|
expect(data.databaseSize_MB).toBeGreaterThanOrEqual(0);
|
|
expect(data.tableCount).toBeGreaterThanOrEqual(0);
|
|
expect(data.activeQueries).toBeGreaterThanOrEqual(0);
|
|
expect(data.totalConnections).toBeGreaterThanOrEqual(0);
|
|
}
|
|
});
|
|
});
|
|
|
|
test.describe('Advanced Dashboard - API Integration', () => {
|
|
|
|
test('Multiple concurrent health checks should succeed', async ({ request }) => {
|
|
const promises = [
|
|
request.get(`${BASE_URL}/api/health/detailed`),
|
|
request.get(`${BASE_URL}/api/health/quick`),
|
|
request.get(`${BASE_URL}/api/health/pm2-logs`),
|
|
request.get(`${BASE_URL}/api/health/sql-status`),
|
|
request.get(`${BASE_URL}/api/health/stats`)
|
|
];
|
|
|
|
const responses = await Promise.all(promises);
|
|
|
|
responses.forEach(response => {
|
|
expect(response.status()).toBe(200);
|
|
});
|
|
});
|
|
|
|
test('Health endpoints should respond within reasonable time', async ({ request }) => {
|
|
const endpoints = [
|
|
'/api/health/quick',
|
|
'/api/health/pm2-logs',
|
|
'/api/health/sql-status'
|
|
];
|
|
|
|
for (const endpoint of endpoints) {
|
|
const startTime = Date.now();
|
|
const response = await request.get(`${BASE_URL}${endpoint}`);
|
|
const duration = Date.now() - startTime;
|
|
|
|
expect(response.status()).toBe(200);
|
|
expect(duration).toBeLessThan(5000); // Should respond within 5 seconds
|
|
}
|
|
});
|
|
|
|
test('Health check data should be consistent across multiple calls', async ({ request }) => {
|
|
const response1 = await request.get(`${BASE_URL}/api/health/quick`);
|
|
const data1 = await response1.json();
|
|
|
|
const response2 = await request.get(`${BASE_URL}/api/health/quick`);
|
|
const data2 = await response2.json();
|
|
|
|
// Status should be consistent
|
|
expect(data1.status).toBe(data2.status);
|
|
});
|
|
});
|