Files
bookmarksite/tests/test_analytics_functionality.html
Rainer Koschnick 0abee5b794 Add comprehensive database setup and user management system
- Implement PostgreSQL database schema with users and bookmarks tables
- Add database connection pooling with retry logic and error handling
- Create migration system with automatic schema initialization
- Add database CLI tools for management (init, status, validate, etc.)
- Include comprehensive error handling and diagnostics
- Add development seed data and testing utilities
- Implement health monitoring and connection pool statistics
- Create detailed documentation and troubleshooting guide

Database features:
- Users table with authentication fields and email verification
- Bookmarks table with user association and metadata
- Proper indexes for performance optimization
- Automatic timestamp triggers
- Transaction support with rollback handling
- Connection pooling (20 max connections, 30s idle timeout)
- Graceful shutdown handling

CLI commands available:
- npm run db:init - Initialize database
- npm run db:status - Check database status
- npm run db:validate - Validate schema
- npm run db:test - Run database tests
- npm run db:diagnostics - Full diagnostics
2025-07-19 23:21:50 +02:00

786 lines
34 KiB
HTML

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Analytics Functionality Test</title>
<style>
body {
font-family: Arial, sans-serif;
max-width: 1200px;
margin: 0 auto;
padding: 20px;
background-color: #f5f5f5;
}
.test-section {
background: white;
margin: 20px 0;
padding: 20px;
border-radius: 8px;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
}
.test-result {
padding: 10px;
margin: 10px 0;
border-radius: 4px;
}
.test-pass {
background-color: #d4edda;
color: #155724;
border: 1px solid #c3e6cb;
}
.test-fail {
background-color: #f8d7da;
color: #721c24;
border: 1px solid #f5c6cb;
}
.test-info {
background-color: #d1ecf1;
color: #0c5460;
border: 1px solid #bee5eb;
}
button {
background: #007bff;
color: white;
border: none;
padding: 10px 20px;
border-radius: 4px;
cursor: pointer;
margin: 5px;
}
button:hover {
background: #0056b3;
}
.analytics-preview {
border: 1px solid #ddd;
padding: 15px;
margin: 10px 0;
border-radius: 4px;
background: #f8f9fa;
}
</style>
</head>
<body>
<h1>Analytics Functionality Test</h1>
<div class="test-section">
<h2>Test Setup</h2>
<p>This test verifies the enhanced statistics and reporting features implementation.</p>
<button onclick="setupTestData()">Setup Test Data</button>
<button onclick="clearTestData()">Clear Test Data</button>
<div id="setupResults"></div>
</div>
<div class="test-section">
<h2>Analytics Dashboard Tests</h2>
<button onclick="testAnalyticsButton()">Test Analytics Button</button>
<button onclick="testAnalyticsModal()">Test Analytics Modal</button>
<button onclick="testAnalyticsTabs()">Test Analytics Tabs</button>
<div id="analyticsResults"></div>
</div>
<div class="test-section">
<h2>Overview Tab Tests</h2>
<button onclick="testOverviewTab()">Test Overview Analytics</button>
<button onclick="testStatusChart()">Test Status Chart</button>
<button onclick="testFoldersChart()">Test Folders Chart</button>
<div id="overviewResults"></div>
</div>
<div class="test-section">
<h2>Trends Tab Tests</h2>
<button onclick="testTrendsTab()">Test Trends Analytics</button>
<button onclick="testTrendsChart()">Test Trends Chart</button>
<button onclick="testTestingTrendsChart()">Test Testing Trends Chart</button>
<div id="trendsResults"></div>
</div>
<div class="test-section">
<h2>Health Report Tests</h2>
<button onclick="testHealthTab()">Test Health Analytics</button>
<button onclick="testHealthMetrics()">Test Health Metrics</button>
<button onclick="testHealthRecommendations()">Test Health Recommendations</button>
<div id="healthResults"></div>
</div>
<div class="test-section">
<h2>Usage Patterns Tests</h2>
<button onclick="testUsageTab()">Test Usage Analytics</button>
<button onclick="testUsageMetrics()">Test Usage Metrics</button>
<button onclick="testUsageCharts()">Test Usage Charts</button>
<div id="usageResults"></div>
</div>
<div class="test-section">
<h2>Export Functionality Tests</h2>
<button onclick="testAnalyticsExport()">Test Analytics Data Export</button>
<button onclick="testReportGeneration()">Test Report Generation</button>
<div id="exportResults"></div>
</div>
<div class="test-section">
<h2>Chart Drawing Tests</h2>
<button onclick="testChartDrawing()">Test Chart Drawing Functions</button>
<div id="chartResults"></div>
</div>
<!-- Include the main application files -->
<link rel="stylesheet" href="styles.css">
<script src="script.js"></script>
<script>
// Initialize bookmark manager for testing
let testBookmarkManager;
function initializeTestManager() {
if (!testBookmarkManager) {
testBookmarkManager = new BookmarkManager();
}
return testBookmarkManager;
}
function setupTestData() {
const manager = initializeTestManager();
const results = document.getElementById('setupResults');
// Clear existing bookmarks
manager.bookmarks = [];
// Create test bookmarks with various statuses, folders, and metadata
const testBookmarks = [
{
id: '1',
title: 'Google',
url: 'https://google.com',
folder: 'Search Engines',
status: 'valid',
addDate: Date.now() - (7 * 24 * 60 * 60 * 1000), // 7 days ago
lastTested: Date.now() - (1 * 24 * 60 * 60 * 1000), // 1 day ago
rating: 5,
favorite: true,
visitCount: 25
},
{
id: '2',
title: 'Broken Link',
url: 'https://broken-link-example.com',
folder: 'Test',
status: 'invalid',
addDate: Date.now() - (30 * 24 * 60 * 60 * 1000), // 30 days ago
lastTested: Date.now() - (2 * 24 * 60 * 60 * 1000), // 2 days ago
rating: 2,
favorite: false,
visitCount: 3
},
{
id: '3',
title: 'GitHub',
url: 'https://github.com',
folder: 'Development',
status: 'valid',
addDate: Date.now() - (15 * 24 * 60 * 60 * 1000), // 15 days ago
lastTested: Date.now() - (3 * 24 * 60 * 60 * 1000), // 3 days ago
rating: 4,
favorite: true,
visitCount: 50
},
{
id: '4',
title: 'Duplicate Google',
url: 'https://www.google.com/',
folder: 'Search Engines',
status: 'duplicate',
addDate: Date.now() - (5 * 24 * 60 * 60 * 1000), // 5 days ago
rating: 3,
favorite: false,
visitCount: 1
},
{
id: '5',
title: 'Untested Link',
url: 'https://example.com',
folder: 'Uncategorized',
status: 'unknown',
addDate: Date.now() - (2 * 24 * 60 * 60 * 1000), // 2 days ago
rating: 0,
favorite: false,
visitCount: 0
},
{
id: '6',
title: 'Old Bookmark',
url: 'https://old-site.com',
folder: 'Archive',
status: 'valid',
addDate: Date.now() - (800 * 24 * 60 * 60 * 1000), // 800 days ago (over 2 years)
lastTested: Date.now() - (100 * 24 * 60 * 60 * 1000), // 100 days ago
rating: 1,
favorite: false,
visitCount: 2
}
];
manager.bookmarks = testBookmarks;
manager.saveBookmarksToStorage();
manager.updateStats();
results.innerHTML = `
<div class="test-pass">✓ Test data setup complete</div>
<div class="test-info">Created ${testBookmarks.length} test bookmarks with various statuses, folders, and metadata</div>
`;
}
function clearTestData() {
const manager = initializeTestManager();
const results = document.getElementById('setupResults');
manager.bookmarks = [];
manager.saveBookmarksToStorage();
manager.updateStats();
results.innerHTML = `
<div class="test-pass">✓ Test data cleared</div>
`;
}
function testAnalyticsButton() {
const results = document.getElementById('analyticsResults');
let testResults = [];
// Check if analytics button exists
const analyticsBtn = document.getElementById('analyticsBtn');
if (analyticsBtn) {
testResults.push('<div class="test-pass">✓ Analytics button found in UI</div>');
// Check if button has correct attributes
if (analyticsBtn.classList.contains('btn') && analyticsBtn.classList.contains('btn-info')) {
testResults.push('<div class="test-pass">✓ Analytics button has correct styling classes</div>');
} else {
testResults.push('<div class="test-fail">✗ Analytics button missing correct styling classes</div>');
}
// Check aria-label
if (analyticsBtn.getAttribute('aria-label')) {
testResults.push('<div class="test-pass">✓ Analytics button has accessibility label</div>');
} else {
testResults.push('<div class="test-fail">✗ Analytics button missing accessibility label</div>');
}
} else {
testResults.push('<div class="test-fail">✗ Analytics button not found in UI</div>');
}
results.innerHTML = testResults.join('');
}
function testAnalyticsModal() {
const results = document.getElementById('analyticsResults');
let testResults = [];
// Check if analytics modal exists
const analyticsModal = document.getElementById('analyticsModal');
if (analyticsModal) {
testResults.push('<div class="test-pass">✓ Analytics modal found in DOM</div>');
// Check modal structure
const modalContent = analyticsModal.querySelector('.modal-content');
if (modalContent && modalContent.classList.contains('analytics-modal-content')) {
testResults.push('<div class="test-pass">✓ Analytics modal has correct content structure</div>');
} else {
testResults.push('<div class="test-fail">✗ Analytics modal missing correct content structure</div>');
}
// Check for tabs
const tabs = analyticsModal.querySelectorAll('.analytics-tab');
if (tabs.length === 4) {
testResults.push('<div class="test-pass">✓ Analytics modal has all 4 tabs (Overview, Trends, Health, Usage)</div>');
} else {
testResults.push('<div class="test-fail">✗ Analytics modal missing tabs (found ' + tabs.length + ', expected 4)</div>');
}
// Check for tab contents
const tabContents = analyticsModal.querySelectorAll('.analytics-tab-content');
if (tabContents.length === 4) {
testResults.push('<div class="test-pass">✓ Analytics modal has all 4 tab contents</div>');
} else {
testResults.push('<div class="test-fail">✗ Analytics modal missing tab contents (found ' + tabContents.length + ', expected 4)</div>');
}
} else {
testResults.push('<div class="test-fail">✗ Analytics modal not found in DOM</div>');
}
results.innerHTML = testResults.join('');
}
function testAnalyticsTabs() {
const results = document.getElementById('analyticsResults');
let testResults = [];
const manager = initializeTestManager();
// Test if analytics methods exist
const methods = ['showAnalyticsModal', 'initializeAnalytics', 'bindAnalyticsTabEvents', 'loadTabAnalytics'];
methods.forEach(method => {
if (typeof manager[method] === 'function') {
testResults.push(`<div class="test-pass">✓ Method ${method} exists</div>`);
} else {
testResults.push(`<div class="test-fail">✗ Method ${method} missing</div>`);
}
});
results.innerHTML = testResults.join('');
}
function testOverviewTab() {
const results = document.getElementById('overviewResults');
let testResults = [];
const manager = initializeTestManager();
// Test overview analytics methods
const methods = ['loadOverviewAnalytics', 'createStatusChart', 'createFoldersChart'];
methods.forEach(method => {
if (typeof manager[method] === 'function') {
testResults.push(`<div class="test-pass">✓ Method ${method} exists</div>`);
} else {
testResults.push(`<div class="test-fail">✗ Method ${method} missing</div>`);
}
});
// Check for overview elements
const overviewElements = [
'totalBookmarksCount',
'validLinksCount',
'invalidLinksCount',
'duplicatesCount',
'statusChart',
'foldersChart'
];
overviewElements.forEach(elementId => {
const element = document.getElementById(elementId);
if (element) {
testResults.push(`<div class="test-pass">✓ Element ${elementId} found</div>`);
} else {
testResults.push(`<div class="test-fail">✗ Element ${elementId} missing</div>`);
}
});
results.innerHTML = testResults.join('');
}
function testStatusChart() {
const results = document.getElementById('overviewResults');
let testResults = [];
const manager = initializeTestManager();
// Test chart drawing methods
const chartMethods = ['drawPieChart', 'drawBarChart', 'drawLineChart', 'drawMultiLineChart'];
chartMethods.forEach(method => {
if (typeof manager[method] === 'function') {
testResults.push(`<div class="test-pass">✓ Chart method ${method} exists</div>`);
} else {
testResults.push(`<div class="test-fail">✗ Chart method ${method} missing</div>`);
}
});
results.innerHTML = testResults.join('');
}
function testFoldersChart() {
const results = document.getElementById('overviewResults');
let testResults = [];
const manager = initializeTestManager();
// Test folder stats method
if (typeof manager.getFolderStats === 'function') {
testResults.push('<div class="test-pass">✓ getFolderStats method exists</div>');
// Test with sample data
if (manager.bookmarks.length > 0) {
const folderStats = manager.getFolderStats();
if (Object.keys(folderStats).length > 0) {
testResults.push('<div class="test-pass">✓ getFolderStats returns data</div>');
testResults.push(`<div class="test-info">Found ${Object.keys(folderStats).length} folders</div>`);
} else {
testResults.push('<div class="test-fail">✗ getFolderStats returns empty data</div>');
}
} else {
testResults.push('<div class="test-info">No test data available for folder stats test</div>');
}
} else {
testResults.push('<div class="test-fail">✗ getFolderStats method missing</div>');
}
results.innerHTML = testResults.join('');
}
function testTrendsTab() {
const results = document.getElementById('trendsResults');
let testResults = [];
const manager = initializeTestManager();
// Test trends analytics methods
const methods = ['loadTrendsAnalytics', 'createTrendsChart', 'createTestingTrendsChart'];
methods.forEach(method => {
if (typeof manager[method] === 'function') {
testResults.push(`<div class="test-pass">✓ Method ${method} exists</div>`);
} else {
testResults.push(`<div class="test-fail">✗ Method ${method} missing</div>`);
}
});
// Check for trends elements
const trendsElements = ['trendsTimeframe', 'trendsChart', 'testingTrendsChart'];
trendsElements.forEach(elementId => {
const element = document.getElementById(elementId);
if (element) {
testResults.push(`<div class="test-pass">✓ Element ${elementId} found</div>`);
} else {
testResults.push(`<div class="test-fail">✗ Element ${elementId} missing</div>`);
}
});
results.innerHTML = testResults.join('');
}
function testTrendsChart() {
const results = document.getElementById('trendsResults');
let testResults = [];
const manager = initializeTestManager();
// Test utility methods for trends
const utilityMethods = ['generateDateRange'];
utilityMethods.forEach(method => {
if (typeof manager[method] === 'function') {
testResults.push(`<div class="test-pass">✓ Utility method ${method} exists</div>`);
} else {
testResults.push(`<div class="test-fail">✗ Utility method ${method} missing</div>`);
}
});
results.innerHTML = testResults.join('');
}
function testTestingTrendsChart() {
const results = document.getElementById('trendsResults');
let testResults = [];
const manager = initializeTestManager();
// Test if bookmarks have lastTested property
if (manager.bookmarks.length > 0) {
const testedBookmarks = manager.bookmarks.filter(b => b.lastTested);
if (testedBookmarks.length > 0) {
testResults.push(`<div class="test-pass">✓ Found ${testedBookmarks.length} bookmarks with test data</div>`);
} else {
testResults.push('<div class="test-info">No bookmarks with test data found</div>');
}
} else {
testResults.push('<div class="test-info">No test data available</div>');
}
results.innerHTML = testResults.join('');
}
function testHealthTab() {
const results = document.getElementById('healthResults');
let testResults = [];
const manager = initializeTestManager();
// Test health analytics methods
const methods = ['loadHealthAnalytics', 'calculateHealthMetrics', 'displayHealthIssues', 'displayHealthRecommendations'];
methods.forEach(method => {
if (typeof manager[method] === 'function') {
testResults.push(`<div class="test-pass">✓ Method ${method} exists</div>`);
} else {
testResults.push(`<div class="test-fail">✗ Method ${method} missing</div>`);
}
});
// Check for health elements
const healthElements = ['healthScore', 'lastFullTest', 'healthIssuesList', 'healthRecommendations'];
healthElements.forEach(elementId => {
const element = document.getElementById(elementId);
if (element) {
testResults.push(`<div class="test-pass">✓ Element ${elementId} found</div>`);
} else {
testResults.push(`<div class="test-fail">✗ Element ${elementId} missing</div>`);
}
});
results.innerHTML = testResults.join('');
}
function testHealthMetrics() {
const results = document.getElementById('healthResults');
let testResults = [];
const manager = initializeTestManager();
if (typeof manager.calculateHealthMetrics === 'function') {
const healthData = manager.calculateHealthMetrics();
if (healthData && typeof healthData === 'object') {
testResults.push('<div class="test-pass">✓ calculateHealthMetrics returns data</div>');
// Check required properties
const requiredProps = ['score', 'lastFullTest', 'issues', 'recommendations'];
requiredProps.forEach(prop => {
if (healthData.hasOwnProperty(prop)) {
testResults.push(`<div class="test-pass">✓ Health data has ${prop} property</div>`);
} else {
testResults.push(`<div class="test-fail">✗ Health data missing ${prop} property</div>`);
}
});
// Display sample health data
testResults.push(`<div class="analytics-preview">
<strong>Sample Health Data:</strong><br>
Score: ${healthData.score}%<br>
Last Full Test: ${healthData.lastFullTest}<br>
Issues: ${healthData.issues ? healthData.issues.length : 0}<br>
Recommendations: ${healthData.recommendations ? healthData.recommendations.length : 0}
</div>`);
} else {
testResults.push('<div class="test-fail">✗ calculateHealthMetrics returns invalid data</div>');
}
} else {
testResults.push('<div class="test-fail">✗ calculateHealthMetrics method missing</div>');
}
results.innerHTML = testResults.join('');
}
function testHealthRecommendations() {
const results = document.getElementById('healthResults');
let testResults = [];
const manager = initializeTestManager();
if (manager.bookmarks.length > 0) {
const healthData = manager.calculateHealthMetrics();
if (healthData.issues && Array.isArray(healthData.issues)) {
testResults.push(`<div class="test-pass">✓ Health issues detected: ${healthData.issues.length}</div>`);
healthData.issues.forEach((issue, index) => {
testResults.push(`<div class="test-info">Issue ${index + 1}: ${issue.title} (${issue.count})</div>`);
});
}
if (healthData.recommendations && Array.isArray(healthData.recommendations)) {
testResults.push(`<div class="test-pass">✓ Health recommendations generated: ${healthData.recommendations.length}</div>`);
healthData.recommendations.forEach((rec, index) => {
testResults.push(`<div class="test-info">Recommendation ${index + 1}: ${rec.title}</div>`);
});
}
} else {
testResults.push('<div class="test-info">No test data available for health recommendations</div>');
}
results.innerHTML = testResults.join('');
}
function testUsageTab() {
const results = document.getElementById('usageResults');
let testResults = [];
const manager = initializeTestManager();
// Test usage analytics methods
const methods = ['loadUsageAnalytics', 'calculateUsageMetrics', 'createTopFoldersChart', 'createRatingsChart'];
methods.forEach(method => {
if (typeof manager[method] === 'function') {
testResults.push(`<div class="test-pass">✓ Method ${method} exists</div>`);
} else {
testResults.push(`<div class="test-fail">✗ Method ${method} missing</div>`);
}
});
// Check for usage elements
const usageElements = ['mostActiveFolder', 'averageRating', 'mostVisited', 'topFoldersChart', 'ratingsChart'];
usageElements.forEach(elementId => {
const element = document.getElementById(elementId);
if (element) {
testResults.push(`<div class="test-pass">✓ Element ${elementId} found</div>`);
} else {
testResults.push(`<div class="test-fail">✗ Element ${elementId} missing</div>`);
}
});
results.innerHTML = testResults.join('');
}
function testUsageMetrics() {
const results = document.getElementById('usageResults');
let testResults = [];
const manager = initializeTestManager();
if (typeof manager.calculateUsageMetrics === 'function') {
const usageData = manager.calculateUsageMetrics();
if (usageData && typeof usageData === 'object') {
testResults.push('<div class="test-pass">✓ calculateUsageMetrics returns data</div>');
// Check required properties
const requiredProps = ['mostActiveFolder', 'averageRating', 'mostVisited'];
requiredProps.forEach(prop => {
if (usageData.hasOwnProperty(prop)) {
testResults.push(`<div class="test-pass">✓ Usage data has ${prop} property</div>`);
} else {
testResults.push(`<div class="test-fail">✗ Usage data missing ${prop} property</div>`);
}
});
// Display sample usage data
testResults.push(`<div class="analytics-preview">
<strong>Sample Usage Data:</strong><br>
Most Active Folder: ${usageData.mostActiveFolder}<br>
Average Rating: ${usageData.averageRating}<br>
Most Visited: ${usageData.mostVisited}
</div>`);
} else {
testResults.push('<div class="test-fail">✗ calculateUsageMetrics returns invalid data</div>');
}
} else {
testResults.push('<div class="test-fail">✗ calculateUsageMetrics method missing</div>');
}
results.innerHTML = testResults.join('');
}
function testUsageCharts() {
const results = document.getElementById('usageResults');
let testResults = [];
const manager = initializeTestManager();
// Test color generation methods
const colorMethods = ['generateFolderColor', 'generateRatingColor', 'hashString'];
colorMethods.forEach(method => {
if (typeof manager[method] === 'function') {
testResults.push(`<div class="test-pass">✓ Color method ${method} exists</div>`);
} else {
testResults.push(`<div class="test-fail">✗ Color method ${method} missing</div>`);
}
});
results.innerHTML = testResults.join('');
}
function testAnalyticsExport() {
const results = document.getElementById('exportResults');
let testResults = [];
const manager = initializeTestManager();
// Test export methods
const exportMethods = ['exportAnalyticsData', 'generateAnalyticsReport'];
exportMethods.forEach(method => {
if (typeof manager[method] === 'function') {
testResults.push(`<div class="test-pass">✓ Export method ${method} exists</div>`);
} else {
testResults.push(`<div class="test-fail">✗ Export method ${method} missing</div>`);
}
});
// Check for export buttons
const exportButtons = ['exportAnalyticsBtn', 'generateReportBtn'];
exportButtons.forEach(buttonId => {
const button = document.getElementById(buttonId);
if (button) {
testResults.push(`<div class="test-pass">✓ Export button ${buttonId} found</div>`);
} else {
testResults.push(`<div class="test-fail">✗ Export button ${buttonId} missing</div>`);
}
});
results.innerHTML = testResults.join('');
}
function testReportGeneration() {
const results = document.getElementById('exportResults');
let testResults = [];
const manager = initializeTestManager();
// Test if we can generate analytics data structure
if (manager.bookmarks.length > 0) {
try {
const analyticsData = {
generatedAt: new Date().toISOString(),
summary: {
totalBookmarks: manager.bookmarks.length,
validLinks: manager.bookmarks.filter(b => b.status === 'valid').length,
invalidLinks: manager.bookmarks.filter(b => b.status === 'invalid').length,
duplicates: manager.bookmarks.filter(b => b.status === 'duplicate').length,
unknownStatus: manager.bookmarks.filter(b => b.status === 'unknown').length
},
folderStats: manager.getFolderStats(),
healthMetrics: manager.calculateHealthMetrics(),
usageMetrics: manager.calculateUsageMetrics()
};
testResults.push('<div class="test-pass">✓ Analytics data structure can be generated</div>');
testResults.push(`<div class="analytics-preview">
<strong>Sample Analytics Data:</strong><br>
Total Bookmarks: ${analyticsData.summary.totalBookmarks}<br>
Valid Links: ${analyticsData.summary.validLinks}<br>
Invalid Links: ${analyticsData.summary.invalidLinks}<br>
Folders: ${Object.keys(analyticsData.folderStats).length}<br>
Health Score: ${analyticsData.healthMetrics.score}%
</div>`);
} catch (error) {
testResults.push(`<div class="test-fail">✗ Error generating analytics data: ${error.message}</div>`);
}
} else {
testResults.push('<div class="test-info">No test data available for report generation test</div>');
}
results.innerHTML = testResults.join('');
}
function testChartDrawing() {
const results = document.getElementById('chartResults');
let testResults = [];
const manager = initializeTestManager();
// Test chart drawing utility methods
const chartUtilities = ['drawPieChart', 'drawBarChart', 'drawLineChart', 'drawMultiLineChart', 'drawLegend', 'drawEmptyChart'];
chartUtilities.forEach(method => {
if (typeof manager[method] === 'function') {
testResults.push(`<div class="test-pass">✓ Chart utility ${method} exists</div>`);
} else {
testResults.push(`<div class="test-fail">✗ Chart utility ${method} missing</div>`);
}
});
// Test if canvas elements exist for charts
const canvasElements = ['statusChart', 'foldersChart', 'trendsChart', 'testingTrendsChart', 'topFoldersChart', 'ratingsChart'];
canvasElements.forEach(canvasId => {
const canvas = document.getElementById(canvasId);
if (canvas && canvas.tagName === 'CANVAS') {
testResults.push(`<div class="test-pass">✓ Canvas element ${canvasId} found</div>`);
} else {
testResults.push(`<div class="test-fail">✗ Canvas element ${canvasId} missing</div>`);
}
});
results.innerHTML = testResults.join('');
}
// Initialize test on page load
window.addEventListener('load', () => {
console.log('Analytics functionality test page loaded');
});
</script>
</body>
</html>