// Test suite for CRM Frontend JavaScript // Run with: open this file in a browser or use a test runner like Jest // Simple test framework const TestRunner = { tests: [], results: [], add(name, testFn) { this.tests.push({ name, testFn }); }, async run() { console.log('🧪 Running CRM Frontend Tests...\n'); this.results = []; for (const test of this.tests) { try { await test.testFn(); this.results.push({ name: test.name, passed: true }); console.log(`✅ ${test.name}`); } catch (error) { this.results.push({ name: test.name, passed: false, error: error.message }); console.log(`❌ ${test.name}: ${error.message}`); } } const passed = this.results.filter(r => r.passed).length; const total = this.results.length; console.log(`\n📊 Results: ${passed}/${total} tests passed`); return this.results; } }; function assert(condition, message) { if (!condition) { throw new Error(message || 'Assertion failed'); } } function assertEqual(actual, expected, message) { if (actual !== expected) { throw new Error(message || `Expected ${expected}, got ${actual}`); } } // ========================================== // Test: Sidebar menu text is "每周进度" // ========================================== TestRunner.add('Sidebar menu shows "每周进度" (not "每周客户进度")', () => { const navItems = document.querySelectorAll('.nav-item'); let found = false; let hasOldText = false; navItems.forEach(item => { const text = item.textContent.trim(); if (text.includes('每周进度') && !text.includes('每周客户进度')) { found = true; } if (text.includes('每周客户进度')) { hasOldText = true; } }); assert(!hasOldText, 'Found old text "每周客户进度" which should be removed'); assert(found, 'Could not find "每周进度" in sidebar'); }); // ========================================== // Test: Bell and Settings buttons removed from header // ========================================== TestRunner.add('Header does not have bell and settings icons', () => { const headerRight = document.querySelector('.header-right'); if (headerRight) { const bellBtn = headerRight.querySelector('.fa-bell'); const cogBtn = headerRight.querySelector('.fa-cog'); assert(!bellBtn, 'Bell icon should be removed from header'); assert(!cogBtn, 'Settings (cog) icon should be removed from header'); } // Verify logout button still exists const logoutBtn = document.getElementById('logoutBtn'); assert(logoutBtn, 'Logout button should exist'); }); // ========================================== // Test: Add trial modal has "是否试用" option // ========================================== TestRunner.add('Add trial modal has "是否试用" radio options', () => { const modal = document.getElementById('addTrialPeriodModal'); assert(modal, 'Add trial period modal should exist'); const isTrialRadios = modal.querySelectorAll('input[name="isTrial"]'); assert(isTrialRadios.length === 2, `Should have 2 radio buttons for "是否试用", found ${isTrialRadios.length}`); const trueRadio = modal.querySelector('input[name="isTrial"][value="true"]'); const falseRadio = modal.querySelector('input[name="isTrial"][value="false"]'); assert(trueRadio, 'Should have a radio for isTrial=true'); assert(falseRadio, 'Should have a radio for isTrial=false'); }); // ========================================== // Test: Edit trial modal has "是否试用" option // ========================================== TestRunner.add('Edit trial modal has "是否试用" radio options', () => { const modal = document.getElementById('editTrialPeriodModal'); assert(modal, 'Edit trial period modal should exist'); const editIsTrialRadios = modal.querySelectorAll('input[name="editIsTrial"]'); assert(editIsTrialRadios.length === 2, `Should have 2 radio buttons for edit "是否试用", found ${editIsTrialRadios.length}`); const trueRadio = modal.querySelector('input[name="editIsTrial"][value="true"]'); const falseRadio = modal.querySelector('input[name="editIsTrial"][value="false"]'); assert(trueRadio, 'Should have a radio for editIsTrial=true'); assert(falseRadio, 'Should have a radio for editIsTrial=false'); }); // ========================================== // Test: Trial periods table has "是否试用" column // ========================================== TestRunner.add('Trial periods table has "是否试用" column header', () => { const trialPeriodsSection = document.getElementById('trialPeriodsSection'); if (trialPeriodsSection) { const headers = trialPeriodsSection.querySelectorAll('th'); let found = false; headers.forEach(header => { if (header.textContent.includes('是否试用')) { found = true; } }); assert(found, 'Trial periods table should have "是否试用" column header'); } }); // ========================================== // Test: Logout button clears crmToken // ========================================== TestRunner.add('Logout button has correct event listener setup', () => { const logoutBtn = document.getElementById('logoutBtn'); assert(logoutBtn, 'Logout button should exist'); // Check that the button is wired up (we can't directly test the function without clicking) assert(logoutBtn.id === 'logoutBtn', 'Logout button should have correct ID'); }); // ========================================== // Test: Refresh button for customers exists // ========================================== TestRunner.add('Refresh customers button exists', () => { const refreshBtn = document.getElementById('refreshCustomersBtn'); assert(refreshBtn, 'Refresh customers button should exist'); }); // ========================================== // Test: Refresh button for followups exists // ========================================== TestRunner.add('Refresh followups button exists', () => { const refreshBtn = document.getElementById('refreshFollowupsBtn'); assert(refreshBtn, 'Refresh followups button should exist'); }); // ========================================== // Test: Add trial button exists // ========================================== TestRunner.add('Add trial button exists', () => { const addTrialBtn = document.getElementById('addTrialBtn'); assert(addTrialBtn, 'Add trial button should exist'); }); // ========================================== // Test: Quick add dropdown exists // ========================================== TestRunner.add('Quick add dropdown exists in header', () => { const quickAddBtn = document.getElementById('headerQuickAddBtn'); const quickAddDropdown = document.getElementById('headerQuickAddDropdown'); assert(quickAddBtn, 'Quick add button should exist'); assert(quickAddDropdown, 'Quick add dropdown should exist'); }); // ========================================== // Test: Global search input exists // ========================================== TestRunner.add('Global search input exists', () => { const searchInput = document.getElementById('globalSearchInput'); assert(searchInput, 'Global search input should exist'); }); // ========================================== // Test: All required sections exist // ========================================== TestRunner.add('All required sections exist', () => { const customerSection = document.getElementById('customerSection'); const dashboardSection = document.getElementById('dashboardSection'); const followupSection = document.getElementById('followupSection'); const trialPeriodsSection = document.getElementById('trialPeriodsSection'); assert(customerSection, 'Customer section should exist'); assert(dashboardSection, 'Dashboard section should exist'); assert(followupSection, 'Followup section should exist'); assert(trialPeriodsSection, 'Trial periods section should exist'); }); // ========================================== // Run tests when DOM is loaded // ========================================== if (typeof document !== 'undefined' && document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', () => { setTimeout(() => TestRunner.run(), 1000); }); } else if (typeof document !== 'undefined') { setTimeout(() => TestRunner.run(), 1000); } // Export for use in other modules if (typeof module !== 'undefined' && module.exports) { module.exports = { TestRunner, assert, assertEqual }; }