fix: Implement comprehensive edit event button functionality and resolve authentication issues

Major fixes and improvements:
- Fixed edit event button functionality with proper event handlers and DOM ready state checking
- Added status column to tickets table via Supabase migration to resolve 500 API errors
- Updated stats API to correctly calculate revenue from decimal price values
- Resolved authentication redirect loops by fixing cookie configuration for Docker environment
- Fixed Permissions-Policy header syntax errors
- Added comprehensive debugging and error handling for event management
- Implemented modal-based event editing with form validation and API integration
- Enhanced event data loading with proper error handling and user feedback

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2025-07-14 18:49:49 -06:00
parent b07ee8cdff
commit dbf4b11e81
216 changed files with 15891 additions and 468 deletions

View File

@@ -0,0 +1,324 @@
const { chromium } = require('playwright');
const fs = require('fs');
const path = require('path');
async function runQATests() {
const browser = await chromium.launch({ headless: false });
const context = await browser.newContext({
viewport: { width: 1280, height: 720 }
});
const page = await context.newPage();
// Monitor console errors
const consoleErrors = [];
page.on('console', msg => {
if (msg.type() === 'error') {
consoleErrors.push({
timestamp: new Date().toISOString(),
message: msg.text(),
url: page.url()
});
}
});
const results = {
themeTests: {},
interactiveTests: {},
mobileTests: {},
consoleErrors: []
};
try {
console.log('🚀 Starting QA Tests - Theme Functionality and Interactive Components');
// Navigate to login page
console.log('\n📋 Step 1: Logging in...');
await page.goto('http://localhost:3001/login');
await page.waitForLoadState('networkidle');
// Take screenshot of login page
await page.screenshot({ path: 'login-page-qa.png', fullPage: true });
// Login
await page.fill('input[type="email"]', 'tmartinez@gmail.com');
await page.fill('input[type="password"]', 'Skittles@420');
await page.click('button[type="submit"]');
// Wait for dashboard
await page.waitForURL('**/dashboard', { timeout: 10000 });
await page.waitForLoadState('networkidle');
console.log('✅ Successfully logged in');
// THEME TESTING
console.log('\n🎨 Step 2: Testing Theme Functionality...');
results.themeTests.startingTheme = 'Testing for theme toggle elements';
// Look for theme toggle elements
const themeToggleSelectors = [
'[data-theme-toggle]',
'.theme-toggle',
'.dark-mode-toggle',
'button[aria-label*="theme"]',
'button[aria-label*="dark"]',
'button[aria-label*="light"]',
'[role="switch"]'
];
let themeToggleFound = false;
let themeToggleElement = null;
for (const selector of themeToggleSelectors) {
try {
const element = await page.$(selector);
if (element) {
themeToggleFound = true;
themeToggleElement = element;
results.themeTests.toggleSelector = selector;
console.log(`✅ Found theme toggle: ${selector}`);
break;
}
} catch (e) {
// Continue checking other selectors
}
}
if (!themeToggleFound) {
// Check navigation area for any button that might be a theme toggle
const navButtons = await page.$$('nav button, header button');
console.log(`🔍 Checking ${navButtons.length} navigation buttons for theme toggle...`);
for (let i = 0; i < navButtons.length; i++) {
const button = navButtons[i];
const text = await button.textContent();
const ariaLabel = await button.getAttribute('aria-label');
console.log(`Button ${i}: text="${text}", aria-label="${ariaLabel}"`);
if (text && (text.toLowerCase().includes('theme') || text.toLowerCase().includes('dark') || text.toLowerCase().includes('light'))) {
themeToggleFound = true;
themeToggleElement = button;
results.themeTests.toggleSelector = `nav button:nth-child(${i+1})`;
break;
}
if (ariaLabel && (ariaLabel.toLowerCase().includes('theme') || ariaLabel.toLowerCase().includes('dark') || ariaLabel.toLowerCase().includes('light'))) {
themeToggleFound = true;
themeToggleElement = button;
results.themeTests.toggleSelector = `button[aria-label="${ariaLabel}"]`;
break;
}
}
}
if (themeToggleFound && themeToggleElement) {
console.log('🎨 Testing theme toggle functionality...');
// Take screenshot before toggle
await page.screenshot({ path: 'theme-before-toggle.png', fullPage: true });
results.themeTests.beforeToggleScreenshot = 'theme-before-toggle.png';
// Get initial theme state
const initialTheme = await page.evaluate(() => {
return {
documentClass: document.documentElement.className,
bodyClass: document.body.className,
localStorage: localStorage.getItem('theme') || localStorage.getItem('dark-mode') || localStorage.getItem('color-theme'),
dataTheme: document.documentElement.getAttribute('data-theme')
};
});
results.themeTests.initialState = initialTheme;
// Click theme toggle
await themeToggleElement.click();
await page.waitForTimeout(500); // Wait for theme transition
// Get state after toggle
const afterToggleTheme = await page.evaluate(() => {
return {
documentClass: document.documentElement.className,
bodyClass: document.body.className,
localStorage: localStorage.getItem('theme') || localStorage.getItem('dark-mode') || localStorage.getItem('color-theme'),
dataTheme: document.documentElement.getAttribute('data-theme')
};
});
results.themeTests.afterToggleState = afterToggleTheme;
// Take screenshot after toggle
await page.screenshot({ path: 'theme-after-toggle.png', fullPage: true });
results.themeTests.afterToggleScreenshot = 'theme-after-toggle.png';
// Test persistence - reload page
await page.reload();
await page.waitForLoadState('networkidle');
const afterReloadTheme = await page.evaluate(() => {
return {
documentClass: document.documentElement.className,
bodyClass: document.body.className,
localStorage: localStorage.getItem('theme') || localStorage.getItem('dark-mode') || localStorage.getItem('color-theme'),
dataTheme: document.documentElement.getAttribute('data-theme')
};
});
results.themeTests.afterReloadState = afterReloadTheme;
results.themeTests.persistenceWorks = JSON.stringify(afterToggleTheme) === JSON.stringify(afterReloadTheme);
console.log(`✅ Theme toggle found and tested. Persistence: ${results.themeTests.persistenceWorks ? '✅' : '❌'}`);
} else {
console.log('❌ No theme toggle found');
results.themeTests.status = 'No theme toggle functionality found';
}
// INTERACTIVE COMPONENTS TESTING
console.log('\n🖱 Step 3: Testing Interactive Components...');
// Test navigation menu
console.log('Testing navigation menu...');
const navLinks = await page.$$('nav a, header a');
results.interactiveTests.navigationLinks = navLinks.length;
console.log(`Found ${navLinks.length} navigation links`);
// Test event creation form
console.log('Testing event creation form...');
try {
await page.goto('http://localhost:3001/events/new');
await page.waitForLoadState('networkidle');
// Take screenshot of form
await page.screenshot({ path: 'event-creation-form.png', fullPage: true });
// Test form fields
const formFields = await page.$$('input, textarea, select');
results.interactiveTests.eventFormFields = formFields.length;
console.log(`Found ${formFields.length} form fields`);
// Test form validation - submit empty form
console.log('Testing form validation...');
const submitButton = await page.$('button[type="submit"], input[type="submit"]');
if (submitButton) {
await submitButton.click();
await page.waitForTimeout(1000);
// Check for validation messages
const validationMessages = await page.$$('.error, .invalid, [role="alert"], .text-red-500, .text-red-600');
results.interactiveTests.validationMessages = validationMessages.length;
console.log(`Found ${validationMessages.length} validation messages`);
// Take screenshot with validation
await page.screenshot({ path: 'form-validation-test.png', fullPage: true });
}
} catch (e) {
console.log('❌ Error testing event creation form:', e.message);
results.interactiveTests.eventFormError = e.message;
}
// Test dashboard interactive elements
console.log('Testing dashboard interactions...');
await page.goto('http://localhost:3001/dashboard');
await page.waitForLoadState('networkidle');
// Look for buttons, links, and interactive elements
const buttons = await page.$$('button');
const links = await page.$$('a');
const inputs = await page.$$('input, select, textarea');
results.interactiveTests.dashboardButtons = buttons.length;
results.interactiveTests.dashboardLinks = links.length;
results.interactiveTests.dashboardInputs = inputs.length;
console.log(`Dashboard: ${buttons.length} buttons, ${links.length} links, ${inputs.length} inputs`);
// Look for modals or dropdowns
console.log('Looking for modals and dropdowns...');
const modalTriggers = await page.$$('[data-modal], [data-toggle="modal"], .modal-trigger');
const dropdownTriggers = await page.$$('[data-dropdown], .dropdown-toggle, [aria-haspopup]');
results.interactiveTests.modalTriggers = modalTriggers.length;
results.interactiveTests.dropdownTriggers = dropdownTriggers.length;
// Test any dropdown that exists
if (dropdownTriggers.length > 0) {
console.log('Testing dropdown functionality...');
try {
await dropdownTriggers[0].click();
await page.waitForTimeout(500);
const dropdownMenu = await page.$('.dropdown-menu, [role="menu"], .dropdown-content');
results.interactiveTests.dropdownWorks = !!dropdownMenu;
if (dropdownMenu) {
await page.screenshot({ path: 'dropdown-open.png', fullPage: true });
}
} catch (e) {
results.interactiveTests.dropdownError = e.message;
}
}
// MOBILE RESPONSIVENESS TESTING
console.log('\n📱 Step 4: Testing Mobile Responsiveness...');
// Switch to mobile viewport
await page.setViewportSize({ width: 375, height: 667 });
await page.reload();
await page.waitForLoadState('networkidle');
// Test mobile navigation
await page.screenshot({ path: 'mobile-dashboard.png', fullPage: true });
// Look for mobile menu toggle
const mobileMenuToggle = await page.$('.mobile-menu-toggle, .hamburger, [aria-label*="menu"]');
if (mobileMenuToggle) {
console.log('Testing mobile menu...');
await mobileMenuToggle.click();
await page.waitForTimeout(500);
await page.screenshot({ path: 'mobile-menu-open.png', fullPage: true });
results.mobileTests.mobileMenuWorks = true;
} else {
results.mobileTests.mobileMenuWorks = false;
}
// Test mobile form
await page.goto('http://localhost:3001/events/new');
await page.waitForLoadState('networkidle');
await page.screenshot({ path: 'mobile-form.png', fullPage: true });
// Check for horizontal scroll
const hasHorizontalScroll = await page.evaluate(() => {
return document.body.scrollWidth > window.innerWidth;
});
results.mobileTests.hasHorizontalScroll = hasHorizontalScroll;
console.log(`Mobile menu: ${results.mobileTests.mobileMenuWorks ? '✅' : '❌'}`);
console.log(`Horizontal scroll: ${hasHorizontalScroll ? '❌' : '✅'}`);
} catch (error) {
console.error('❌ Test execution error:', error);
results.error = error.message;
} finally {
// Collect final console errors
results.consoleErrors = consoleErrors;
// Write results to file
fs.writeFileSync('qa-test-results.json', JSON.stringify(results, null, 2));
console.log('\n📊 QA Test Summary:');
console.log('Theme Tests:', Object.keys(results.themeTests).length, 'checks');
console.log('Interactive Tests:', Object.keys(results.interactiveTests).length, 'checks');
console.log('Mobile Tests:', Object.keys(results.mobileTests).length, 'checks');
console.log('Console Errors:', consoleErrors.length);
if (consoleErrors.length > 0) {
console.log('\n❌ Console Errors Found:');
consoleErrors.forEach((error, i) => {
console.log(`${i+1}. ${error.message} (${error.url})`);
});
}
console.log('\n📄 Results saved to qa-test-results.json');
console.log('🖼️ Screenshots saved with descriptive names');
await browser.close();
}
}
// Run the tests
runQATests().catch(console.error);