Some checks are pending
		
		
	
	HVAC Plugin CI/CD Pipeline / Security Analysis (push) Waiting to run
				
			HVAC Plugin CI/CD Pipeline / Code Quality & Standards (push) Waiting to run
				
			HVAC Plugin CI/CD Pipeline / Unit Tests (push) Waiting to run
				
			HVAC Plugin CI/CD Pipeline / Integration Tests (push) Waiting to run
				
			HVAC Plugin CI/CD Pipeline / Deploy to Staging (push) Blocked by required conditions
				
			HVAC Plugin CI/CD Pipeline / Deploy to Production (push) Blocked by required conditions
				
			HVAC Plugin CI/CD Pipeline / Notification (push) Blocked by required conditions
				
			Security Monitoring & Compliance / Dependency Vulnerability Scan (push) Waiting to run
				
			Security Monitoring & Compliance / Secrets & Credential Scan (push) Waiting to run
				
			Security Monitoring & Compliance / WordPress Security Analysis (push) Waiting to run
				
			Security Monitoring & Compliance / Static Code Security Analysis (push) Waiting to run
				
			Security Monitoring & Compliance / Security Compliance Validation (push) Waiting to run
				
			Security Monitoring & Compliance / Security Summary Report (push) Blocked by required conditions
				
			Security Monitoring & Compliance / Security Team Notification (push) Blocked by required conditions
				
			- Add 90+ test files including E2E, unit, and integration tests - Implement Page Object Model (POM) architecture - Add Docker testing environment with comprehensive services - Include modernized test framework with error recovery - Add specialized test suites for master trainer and trainer workflows - Update .gitignore to properly track test infrastructure 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
		
			
				
	
	
		
			694 lines
		
	
	
		
			No EOL
		
	
	
		
			23 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			694 lines
		
	
	
		
			No EOL
		
	
	
		
			23 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| /**
 | |
|  * Event Creation Page Object Model
 | |
|  * 
 | |
|  * Handles event creation functionality including:
 | |
|  * - Standard HVAC event creation
 | |
|  * - TEC (The Events Calendar) integration
 | |
|  * - Form validation and error handling
 | |
|  * - Event data population and submission
 | |
|  * 
 | |
|  * @package HVAC_Community_Events
 | |
|  * @version 2.0.0
 | |
|  * @created 2025-08-27
 | |
|  * @author Agent-B-Event-Management
 | |
|  */
 | |
| 
 | |
| const BasePage = require('../base/BasePage');
 | |
| const { expect } = require('@playwright/test');
 | |
| 
 | |
| class EventCreation extends BasePage {
 | |
|     constructor(page) {
 | |
|         super(page);
 | |
|         
 | |
|         // Event creation form selectors
 | |
|         this.selectors = {
 | |
|             // Main form containers
 | |
|             createEventForm: [
 | |
|                 '[data-testid="create-event-form"]',
 | |
|                 '.hvac-create-event-form',
 | |
|                 '.tribe-events-community-form',
 | |
|                 '.event-creation-form',
 | |
|                 'form#create-event'
 | |
|             ],
 | |
|             
 | |
|             // Form fields - Standard HVAC
 | |
|             fields: {
 | |
|                 title: [
 | |
|                     '[data-testid="event-title"]',
 | |
|                     'input[name="event_title"]',
 | |
|                     'input[name="post_title"]',
 | |
|                     '#event-title',
 | |
|                     '.event-title-input'
 | |
|                 ],
 | |
|                 description: [
 | |
|                     '[data-testid="event-description"]',
 | |
|                     'textarea[name="event_description"]',
 | |
|                     'textarea[name="post_content"]',
 | |
|                     '#event-description',
 | |
|                     '.event-description-textarea'
 | |
|                 ],
 | |
|                 startDate: [
 | |
|                     '[data-testid="event-start-date"]',
 | |
|                     'input[name="event_start_date"]',
 | |
|                     'input[name="EventStartDate"]',
 | |
|                     '#event-start-date',
 | |
|                     '.event-start-date'
 | |
|                 ],
 | |
|                 endDate: [
 | |
|                     '[data-testid="event-end-date"]',
 | |
|                     'input[name="event_end_date"]',
 | |
|                     'input[name="EventEndDate"]',
 | |
|                     '#event-end-date',
 | |
|                     '.event-end-date'
 | |
|                 ],
 | |
|                 startTime: [
 | |
|                     '[data-testid="event-start-time"]',
 | |
|                     'input[name="event_start_time"]',
 | |
|                     'input[name="EventStartTime"]',
 | |
|                     '#event-start-time',
 | |
|                     '.event-start-time'
 | |
|                 ],
 | |
|                 endTime: [
 | |
|                     '[data-testid="event-end-time"]',
 | |
|                     'input[name="event_end_time"]',
 | |
|                     'input[name="EventEndTime"]',
 | |
|                     '#event-end-time',
 | |
|                     '.event-end-time'
 | |
|                 ],
 | |
|                 venue: [
 | |
|                     '[data-testid="event-venue"]',
 | |
|                     'select[name="venue"]',
 | |
|                     'select[name="event_venue"]',
 | |
|                     '#event-venue',
 | |
|                     '.venue-select'
 | |
|                 ],
 | |
|                 organizer: [
 | |
|                     '[data-testid="event-organizer"]',
 | |
|                     'select[name="organizer"]',
 | |
|                     'select[name="event_organizer"]',
 | |
|                     '#event-organizer',
 | |
|                     '.organizer-select'
 | |
|                 ],
 | |
|                 category: [
 | |
|                     '[data-testid="event-category"]',
 | |
|                     'select[name="event_category"]',
 | |
|                     'select[name="tax_input[tribe_events_cat][]"]',
 | |
|                     '#event-category',
 | |
|                     '.event-category-select'
 | |
|                 ],
 | |
|                 capacity: [
 | |
|                     '[data-testid="event-capacity"]',
 | |
|                     'input[name="event_capacity"]',
 | |
|                     'input[name="_EventCapacity"]',
 | |
|                     '#event-capacity',
 | |
|                     '.event-capacity'
 | |
|                 ],
 | |
|                 cost: [
 | |
|                     '[data-testid="event-cost"]',
 | |
|                     'input[name="event_cost"]',
 | |
|                     'input[name="_EventCost"]',
 | |
|                     '#event-cost',
 | |
|                     '.event-cost'
 | |
|                 ],
 | |
|                 website: [
 | |
|                     '[data-testid="event-website"]',
 | |
|                     'input[name="event_website"]',
 | |
|                     'input[name="_EventURL"]',
 | |
|                     '#event-website',
 | |
|                     '.event-website'
 | |
|                 ]
 | |
|             },
 | |
|             
 | |
|             // TEC specific fields
 | |
|             tecFields: {
 | |
|                 allDayEvent: [
 | |
|                     '[data-testid="all-day-event"]',
 | |
|                     'input[name="_EventAllDay"]',
 | |
|                     '#allDayCheckbox',
 | |
|                     '.all-day-checkbox'
 | |
|                 ],
 | |
|                 timezone: [
 | |
|                     '[data-testid="event-timezone"]',
 | |
|                     'select[name="_EventTimezone"]',
 | |
|                     '#event-timezone',
 | |
|                     '.timezone-select'
 | |
|                 ],
 | |
|                 showMapLink: [
 | |
|                     '[data-testid="show-map-link"]',
 | |
|                     'input[name="_EventShowMapLink"]',
 | |
|                     '#show-map-link',
 | |
|                     '.show-map-link'
 | |
|                 ],
 | |
|                 showMap: [
 | |
|                     '[data-testid="show-map"]',
 | |
|                     'input[name="_EventShowMap"]',
 | |
|                     '#show-map',
 | |
|                     '.show-map'
 | |
|                 ]
 | |
|             },
 | |
|             
 | |
|             // Action buttons
 | |
|             buttons: {
 | |
|                 submit: [
 | |
|                     '[data-testid="submit-event"]',
 | |
|                     'input[type="submit"]',
 | |
|                     'button[type="submit"]',
 | |
|                     '#submit-event',
 | |
|                     '.submit-event-btn',
 | |
|                     '.tribe-community-event-submit'
 | |
|                 ],
 | |
|                 preview: [
 | |
|                     '[data-testid="preview-event"]',
 | |
|                     'button[name="preview"]',
 | |
|                     '#preview-event',
 | |
|                     '.preview-event-btn'
 | |
|                 ],
 | |
|                 saveDraft: [
 | |
|                     '[data-testid="save-draft"]',
 | |
|                     'button[name="save_draft"]',
 | |
|                     '#save-draft',
 | |
|                     '.save-draft-btn'
 | |
|                 ],
 | |
|                 cancel: [
 | |
|                     '[data-testid="cancel-event"]',
 | |
|                     'button[name="cancel"]',
 | |
|                     '#cancel-event',
 | |
|                     '.cancel-btn'
 | |
|                 ]
 | |
|             },
 | |
|             
 | |
|             // Validation and error elements
 | |
|             validation: {
 | |
|                 errors: [
 | |
|                     '[data-testid="form-errors"]',
 | |
|                     '.form-errors',
 | |
|                     '.tribe-community-notice-error',
 | |
|                     '.event-validation-errors',
 | |
|                     '.error-message'
 | |
|                 ],
 | |
|                 success: [
 | |
|                     '[data-testid="form-success"]',
 | |
|                     '.form-success',
 | |
|                     '.tribe-community-notice-success',
 | |
|                     '.event-success-message',
 | |
|                     '.success-message'
 | |
|                 ],
 | |
|                 fieldError: [
 | |
|                     '.field-error',
 | |
|                     '.input-error',
 | |
|                     '.validation-error'
 | |
|                 ]
 | |
|             },
 | |
|             
 | |
|             // Loading states
 | |
|             loading: [
 | |
|                 '[data-testid="form-loading"]',
 | |
|                 '.form-loading',
 | |
|                 '.tribe-community-loading',
 | |
|                 '.loading-spinner'
 | |
|             ]
 | |
|         };
 | |
|         
 | |
|         this.urls = {
 | |
|             createEvent: '/trainer/create-event/',
 | |
|             tecCreateEvent: '/trainer/tec-create-event/',
 | |
|             customCreateEvent: '/create-event/',
 | |
|             communityCreate: '/events/community/add/'
 | |
|         };
 | |
|         
 | |
|         // Test data templates
 | |
|         this.testEventData = {
 | |
|             basic: {
 | |
|                 title: 'Test HVAC Training Event',
 | |
|                 description: 'Comprehensive HVAC training covering heat pump installation and maintenance.',
 | |
|                 startDate: this.getFormattedDate(7), // 7 days from now
 | |
|                 endDate: this.getFormattedDate(7),
 | |
|                 startTime: '09:00',
 | |
|                 endTime: '17:00',
 | |
|                 capacity: '25',
 | |
|                 cost: '299.00'
 | |
|             },
 | |
|             advanced: {
 | |
|                 title: 'Advanced Heat Pump Diagnostics Workshop',
 | |
|                 description: 'Deep dive into advanced heat pump diagnostic techniques using measureQuick tools and protocols.',
 | |
|                 startDate: this.getFormattedDate(14),
 | |
|                 endDate: this.getFormattedDate(15),
 | |
|                 startTime: '08:30',
 | |
|                 endTime: '16:30',
 | |
|                 capacity: '15',
 | |
|                 cost: '499.00',
 | |
|                 website: 'https://upskill-staging.measurequick.com/advanced-diagnostics'
 | |
|             },
 | |
|             multiDay: {
 | |
|                 title: 'HVAC Certification Bootcamp',
 | |
|                 description: 'Intensive 3-day certification program covering all aspects of HVAC systems.',
 | |
|                 startDate: this.getFormattedDate(21),
 | |
|                 endDate: this.getFormattedDate(23),
 | |
|                 startTime: '09:00',
 | |
|                 endTime: '17:00',
 | |
|                 capacity: '20',
 | |
|                 cost: '799.00'
 | |
|             }
 | |
|         };
 | |
|     }
 | |
|     
 | |
|     /**
 | |
|      * Navigate to event creation page
 | |
|      */
 | |
|     async navigate(pageType = 'standard') {
 | |
|         let url;
 | |
|         switch (pageType) {
 | |
|             case 'tec':
 | |
|                 url = this.urls.tecCreateEvent;
 | |
|                 break;
 | |
|             case 'community':
 | |
|                 url = this.urls.communityCreate;
 | |
|                 break;
 | |
|             case 'custom':
 | |
|                 url = this.urls.customCreateEvent;
 | |
|                 break;
 | |
|             default:
 | |
|                 url = this.urls.createEvent;
 | |
|         }
 | |
|         
 | |
|         await this.goto(url);
 | |
|         await this.waitForFormLoad();
 | |
|         console.log(`✅ Navigated to event creation page: ${pageType}`);
 | |
|     }
 | |
|     
 | |
|     /**
 | |
|      * Wait for event creation form to load completely
 | |
|      */
 | |
|     async waitForFormLoad() {
 | |
|         // Wait for form container
 | |
|         await this.waitForVisible(this.selectors.createEventForm, { timeout: 10000 });
 | |
|         
 | |
|         // Wait for essential fields
 | |
|         await this.waitForVisible(this.selectors.fields.title, { timeout: 5000 });
 | |
|         await this.waitForVisible(this.selectors.fields.description, { timeout: 5000 });
 | |
|         
 | |
|         // Wait for WordPress and any AJAX to complete
 | |
|         await this.waitForWordPressReady();
 | |
|         await this.waitForAjax();
 | |
|         
 | |
|         // Wait for loading indicators to disappear
 | |
|         await this.waitForHidden(this.selectors.loading, { timeout: 3000 });
 | |
|         
 | |
|         console.log('✅ Event creation form loaded');
 | |
|     }
 | |
|     
 | |
|     /**
 | |
|      * Fill event creation form with provided data
 | |
|      */
 | |
|     async fillEventForm(eventData) {
 | |
|         console.log('📝 Filling event form with data:', eventData.title);
 | |
|         
 | |
|         // Fill basic event information
 | |
|         if (eventData.title) {
 | |
|             await this.fill(this.selectors.fields.title, eventData.title);
 | |
|         }
 | |
|         
 | |
|         if (eventData.description) {
 | |
|             await this.fill(this.selectors.fields.description, eventData.description);
 | |
|         }
 | |
|         
 | |
|         // Fill date and time information
 | |
|         if (eventData.startDate) {
 | |
|             await this.fill(this.selectors.fields.startDate, eventData.startDate);
 | |
|         }
 | |
|         
 | |
|         if (eventData.endDate) {
 | |
|             await this.fill(this.selectors.fields.endDate, eventData.endDate);
 | |
|         }
 | |
|         
 | |
|         if (eventData.startTime) {
 | |
|             await this.fill(this.selectors.fields.startTime, eventData.startTime);
 | |
|         }
 | |
|         
 | |
|         if (eventData.endTime) {
 | |
|             await this.fill(this.selectors.fields.endTime, eventData.endTime);
 | |
|         }
 | |
|         
 | |
|         // Fill additional event details
 | |
|         if (eventData.capacity) {
 | |
|             await this.fill(this.selectors.fields.capacity, eventData.capacity);
 | |
|         }
 | |
|         
 | |
|         if (eventData.cost) {
 | |
|             await this.fill(this.selectors.fields.cost, eventData.cost);
 | |
|         }
 | |
|         
 | |
|         if (eventData.website) {
 | |
|             await this.fill(this.selectors.fields.website, eventData.website);
 | |
|         }
 | |
|         
 | |
|         // Handle venue selection if provided
 | |
|         if (eventData.venue) {
 | |
|             await this.selectVenue(eventData.venue);
 | |
|         }
 | |
|         
 | |
|         // Handle organizer selection if provided
 | |
|         if (eventData.organizer) {
 | |
|             await this.selectOrganizer(eventData.organizer);
 | |
|         }
 | |
|         
 | |
|         // Handle category selection if provided
 | |
|         if (eventData.category) {
 | |
|             await this.selectCategory(eventData.category);
 | |
|         }
 | |
|         
 | |
|         // Wait for form validation
 | |
|         await this.waitForAjax();
 | |
|         
 | |
|         console.log('✅ Event form filled successfully');
 | |
|     }
 | |
|     
 | |
|     /**
 | |
|      * Submit event creation form
 | |
|      */
 | |
|     async submitEvent(options = {}) {
 | |
|         const { 
 | |
|             waitForRedirect = true, 
 | |
|             expectedOutcome = 'success',
 | |
|             timeout = 15000 
 | |
|         } = options;
 | |
|         
 | |
|         console.log('🚀 Submitting event creation form');
 | |
|         
 | |
|         // Take screenshot before submission
 | |
|         await this.takeScreenshot('before-event-submission');
 | |
|         
 | |
|         // Click submit button
 | |
|         await this.click(this.selectors.buttons.submit, { timeout });
 | |
|         
 | |
|         if (waitForRedirect) {
 | |
|             // Wait for form processing
 | |
|             await this.waitForAjax();
 | |
|             
 | |
|             // Wait for either success or error message
 | |
|             if (expectedOutcome === 'success') {
 | |
|                 await Promise.race([
 | |
|                     this.waitForVisible(this.selectors.validation.success, { timeout }),
 | |
|                     this.waitForUrlChange(timeout)
 | |
|                 ]);
 | |
|                 
 | |
|                 console.log('✅ Event submitted successfully');
 | |
|             } else if (expectedOutcome === 'error') {
 | |
|                 await this.waitForVisible(this.selectors.validation.errors, { timeout });
 | |
|                 console.log('⚠️ Event submission resulted in expected error');
 | |
|             }
 | |
|         }
 | |
|         
 | |
|         // Take screenshot after submission
 | |
|         await this.takeScreenshot('after-event-submission');
 | |
|         
 | |
|         return await this.getSubmissionResult();
 | |
|     }
 | |
|     
 | |
|     /**
 | |
|      * Get form submission result
 | |
|      */
 | |
|     async getSubmissionResult() {
 | |
|         // Check for success messages
 | |
|         if (await this.isVisible(this.selectors.validation.success)) {
 | |
|             const successMessage = await this.getText(this.selectors.validation.success);
 | |
|             return {
 | |
|                 success: true,
 | |
|                 message: successMessage,
 | |
|                 redirectUrl: await this.page.url()
 | |
|             };
 | |
|         }
 | |
|         
 | |
|         // Check for error messages
 | |
|         if (await this.isVisible(this.selectors.validation.errors)) {
 | |
|             const errorMessage = await this.getText(this.selectors.validation.errors);
 | |
|             const fieldErrors = await this.getFieldErrors();
 | |
|             return {
 | |
|                 success: false,
 | |
|                 message: errorMessage,
 | |
|                 fieldErrors,
 | |
|                 currentUrl: await this.page.url()
 | |
|             };
 | |
|         }
 | |
|         
 | |
|         // Check if URL changed (successful redirect)
 | |
|         const currentUrl = await this.page.url();
 | |
|         const isRedirected = !currentUrl.includes('create-event');
 | |
|         
 | |
|         return {
 | |
|             success: isRedirected,
 | |
|             redirected: isRedirected,
 | |
|             currentUrl
 | |
|         };
 | |
|     }
 | |
|     
 | |
|     /**
 | |
|      * Get field-specific validation errors
 | |
|      */
 | |
|     async getFieldErrors() {
 | |
|         const fieldErrors = {};
 | |
|         const errorElements = await this.page.locator(this.selectors.validation.fieldError.join(', ')).all();
 | |
|         
 | |
|         for (const errorElement of errorElements) {
 | |
|             const fieldName = await errorElement.getAttribute('data-field') || 
 | |
|                              await errorElement.getAttribute('for') ||
 | |
|                              'unknown';
 | |
|             const errorText = await errorElement.textContent();
 | |
|             fieldErrors[fieldName] = errorText.trim();
 | |
|         }
 | |
|         
 | |
|         return fieldErrors;
 | |
|     }
 | |
|     
 | |
|     /**
 | |
|      * Select venue from dropdown
 | |
|      */
 | |
|     async selectVenue(venueName) {
 | |
|         if (await this.isVisible(this.selectors.fields.venue)) {
 | |
|             // If venue is a dropdown
 | |
|             await this.selectByText(this.selectors.fields.venue, venueName);
 | |
|         } else {
 | |
|             // If venue needs to be created or searched
 | |
|             const venueInput = await this.getVisibleSelector([
 | |
|                 'input[name="venue_name"]',
 | |
|                 '#venue-search',
 | |
|                 '.venue-input'
 | |
|             ]);
 | |
|             
 | |
|             if (venueInput) {
 | |
|                 await this.fill(venueInput, venueName);
 | |
|                 await this.waitForAjax();
 | |
|             }
 | |
|         }
 | |
|         
 | |
|         console.log(`📍 Selected venue: ${venueName}`);
 | |
|     }
 | |
|     
 | |
|     /**
 | |
|      * Select organizer from dropdown
 | |
|      */
 | |
|     async selectOrganizer(organizerName) {
 | |
|         if (await this.isVisible(this.selectors.fields.organizer)) {
 | |
|             await this.selectByText(this.selectors.fields.organizer, organizerName);
 | |
|         } else {
 | |
|             // Handle organizer creation if needed
 | |
|             const organizerInput = await this.getVisibleSelector([
 | |
|                 'input[name="organizer_name"]',
 | |
|                 '#organizer-search',
 | |
|                 '.organizer-input'
 | |
|             ]);
 | |
|             
 | |
|             if (organizerInput) {
 | |
|                 await this.fill(organizerInput, organizerName);
 | |
|                 await this.waitForAjax();
 | |
|             }
 | |
|         }
 | |
|         
 | |
|         console.log(`👤 Selected organizer: ${organizerName}`);
 | |
|     }
 | |
|     
 | |
|     /**
 | |
|      * Select event category
 | |
|      */
 | |
|     async selectCategory(categoryName) {
 | |
|         if (await this.isVisible(this.selectors.fields.category)) {
 | |
|             await this.selectByText(this.selectors.fields.category, categoryName);
 | |
|             console.log(`🏷️ Selected category: ${categoryName}`);
 | |
|         }
 | |
|     }
 | |
|     
 | |
|     /**
 | |
|      * Create event with test data
 | |
|      */
 | |
|     async createTestEvent(dataType = 'basic', options = {}) {
 | |
|         const eventData = { ...this.testEventData[dataType], ...options.data };
 | |
|         
 | |
|         console.log(`🧪 Creating test event: ${dataType}`);
 | |
|         
 | |
|         await this.fillEventForm(eventData);
 | |
|         const result = await this.submitEvent(options);
 | |
|         
 | |
|         return {
 | |
|             ...result,
 | |
|             eventData,
 | |
|             testType: dataType
 | |
|         };
 | |
|     }
 | |
|     
 | |
|     /**
 | |
|      * Validate form fields
 | |
|      */
 | |
|     async validateForm() {
 | |
|         const validationResults = {
 | |
|             requiredFields: [],
 | |
|             validationErrors: [],
 | |
|             fieldsPresent: {}
 | |
|         };
 | |
|         
 | |
|         // Check required fields
 | |
|         const requiredFields = ['title', 'description', 'startDate', 'startTime'];
 | |
|         
 | |
|         for (const fieldName of requiredFields) {
 | |
|             const fieldSelectors = this.selectors.fields[fieldName];
 | |
|             const isPresent = await this.isVisible(fieldSelectors);
 | |
|             
 | |
|             validationResults.fieldsPresent[fieldName] = isPresent;
 | |
|             
 | |
|             if (!isPresent) {
 | |
|                 validationResults.requiredFields.push(fieldName);
 | |
|             }
 | |
|         }
 | |
|         
 | |
|         // Check for existing validation errors
 | |
|         if (await this.isVisible(this.selectors.validation.errors)) {
 | |
|             const errors = await this.getText(this.selectors.validation.errors);
 | |
|             validationResults.validationErrors.push(errors);
 | |
|         }
 | |
|         
 | |
|         console.log('🔍 Form validation results:', validationResults);
 | |
|         return validationResults;
 | |
|     }
 | |
|     
 | |
|     /**
 | |
|      * Test form validation by submitting empty form
 | |
|      */
 | |
|     async testValidation() {
 | |
|         console.log('🧪 Testing form validation');
 | |
|         
 | |
|         // Clear any existing data
 | |
|         await this.clearForm();
 | |
|         
 | |
|         // Attempt to submit empty form
 | |
|         await this.click(this.selectors.buttons.submit);
 | |
|         
 | |
|         // Wait for validation errors
 | |
|         await this.waitForVisible(this.selectors.validation.errors, { timeout: 5000 });
 | |
|         
 | |
|         return await this.getFieldErrors();
 | |
|     }
 | |
|     
 | |
|     /**
 | |
|      * Clear all form fields
 | |
|      */
 | |
|     async clearForm() {
 | |
|         const fieldsToCheck = ['title', 'description', 'startDate', 'endDate', 'startTime', 'endTime', 'capacity', 'cost'];
 | |
|         
 | |
|         for (const fieldName of fieldsToCheck) {
 | |
|             const fieldSelectors = this.selectors.fields[fieldName];
 | |
|             if (await this.isVisible(fieldSelectors)) {
 | |
|                 await this.clear(fieldSelectors);
 | |
|             }
 | |
|         }
 | |
|         
 | |
|         console.log('🧹 Form cleared');
 | |
|     }
 | |
|     
 | |
|     /**
 | |
|      * Handle TEC-specific functionality
 | |
|      */
 | |
|     async configureTECOptions(options = {}) {
 | |
|         if (options.allDay) {
 | |
|             await this.check(this.selectors.tecFields.allDayEvent);
 | |
|             console.log('☑️ Set as all-day event');
 | |
|         }
 | |
|         
 | |
|         if (options.timezone) {
 | |
|             await this.selectByText(this.selectors.tecFields.timezone, options.timezone);
 | |
|             console.log(`🌍 Set timezone: ${options.timezone}`);
 | |
|         }
 | |
|         
 | |
|         if (options.showMap !== undefined) {
 | |
|             if (options.showMap) {
 | |
|                 await this.check(this.selectors.tecFields.showMap);
 | |
|             } else {
 | |
|                 await this.uncheck(this.selectors.tecFields.showMap);
 | |
|             }
 | |
|             console.log(`🗺️ Show map: ${options.showMap}`);
 | |
|         }
 | |
|     }
 | |
|     
 | |
|     /**
 | |
|      * Preview event before submission
 | |
|      */
 | |
|     async previewEvent() {
 | |
|         if (await this.isVisible(this.selectors.buttons.preview)) {
 | |
|             await this.click(this.selectors.buttons.preview);
 | |
|             await this.waitForAjax();
 | |
|             console.log('👁️ Event preview opened');
 | |
|             return true;
 | |
|         }
 | |
|         return false;
 | |
|     }
 | |
|     
 | |
|     /**
 | |
|      * Save event as draft
 | |
|      */
 | |
|     async saveDraft() {
 | |
|         if (await this.isVisible(this.selectors.buttons.saveDraft)) {
 | |
|             await this.click(this.selectors.buttons.saveDraft);
 | |
|             await this.waitForAjax();
 | |
|             
 | |
|             const result = await this.getSubmissionResult();
 | |
|             console.log('📝 Event saved as draft');
 | |
|             return result;
 | |
|         }
 | |
|         
 | |
|         throw new Error('Save draft button not available');
 | |
|     }
 | |
|     
 | |
|     /**
 | |
|      * Get formatted date for form input
 | |
|      */
 | |
|     getFormattedDate(daysFromNow = 0) {
 | |
|         const date = new Date();
 | |
|         date.setDate(date.getDate() + daysFromNow);
 | |
|         return date.toISOString().split('T')[0]; // YYYY-MM-DD format
 | |
|     }
 | |
|     
 | |
|     /**
 | |
|      * Take screenshot of form state
 | |
|      */
 | |
|     async screenshotForm(name = 'event-creation-form') {
 | |
|         return await this.takeScreenshot(name, { fullPage: true });
 | |
|     }
 | |
|     
 | |
|     /**
 | |
|      * Verify form is accessible and ready for input
 | |
|      */
 | |
|     async verifyFormAccessibility() {
 | |
|         const checks = {
 | |
|             formVisible: await this.isVisible(this.selectors.createEventForm),
 | |
|             titleFieldAccessible: await this.isVisible(this.selectors.fields.title),
 | |
|             descriptionFieldAccessible: await this.isVisible(this.selectors.fields.description),
 | |
|             submitButtonAccessible: await this.isVisible(this.selectors.buttons.submit),
 | |
|             hasNoLoadingIndicators: !await this.isVisible(this.selectors.loading)
 | |
|         };
 | |
|         
 | |
|         const isAccessible = Object.values(checks).every(check => check === true);
 | |
|         
 | |
|         console.log('♿ Form accessibility check:', { isAccessible, ...checks });
 | |
|         return { isAccessible, checks };
 | |
|     }
 | |
| }
 | |
| 
 | |
| module.exports = EventCreation; |