This commit implements Phase 1 of the Communication Schedule system, providing: Core Infrastructure: - HVAC_Communication_Scheduler: Main controller with cron integration and AJAX handlers - HVAC_Communication_Schedule_Manager: CRUD operations and database interactions - HVAC_Communication_Trigger_Engine: Automation logic and recipient management - HVAC_Communication_Logger: Execution logging and performance tracking - HVAC_Communication_Installer: Database table creation and management Features: - Event-based triggers (before/after event, on registration) - Custom date scheduling with recurring options - Flexible recipient targeting (all attendees, confirmed, custom lists) - Template integration with placeholder replacement - WordPress cron integration for automated execution - Comprehensive AJAX API for schedule management - Template quickstart options for common scenarios UI Components: - Communication Schedules page with full management interface - Form-based schedule creation with validation - Schedule listing with filtering and status management - Modal recipient preview functionality - Pre-configured schedule templates for quick setup Database Design: - hvac_communication_schedules: Schedule configurations - hvac_communication_logs: Execution history and statistics - hvac_event_communication_tracking: Individual email tracking The system integrates with existing email templates and provides a foundation for automated communication workflows for HVAC trainers. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
332 lines
No EOL
12 KiB
TypeScript
332 lines
No EOL
12 KiB
TypeScript
import { test, expect } from './fixtures/auth';
|
|
import { CommonActions } from './utils/common-actions';
|
|
|
|
/**
|
|
* Debug Tests for Communication Templates
|
|
*
|
|
* Comprehensive debugging to identify why features aren't working
|
|
*/
|
|
|
|
test.describe('Debug Communication Templates', () => {
|
|
|
|
test('Debug page source and JavaScript loading', async ({ authenticatedPage: page }) => {
|
|
test.setTimeout(30000);
|
|
const actions = new CommonActions(page);
|
|
|
|
// Capture all console messages
|
|
const consoleMessages: { type: string, text: string }[] = [];
|
|
page.on('console', (msg) => {
|
|
consoleMessages.push({ type: msg.type(), text: msg.text() });
|
|
});
|
|
|
|
// Navigate to templates page
|
|
await actions.navigateAndWait('/communication-templates/');
|
|
await actions.screenshot('debug-templates-page');
|
|
|
|
// Get page source
|
|
const pageSource = await page.content();
|
|
|
|
// Check if shortcode was processed
|
|
const hasShortcode = pageSource.includes('[hvac_communication_templates]');
|
|
const hasTemplateWrapper = pageSource.includes('hvac-templates-wrapper');
|
|
|
|
console.log('=== Page Debug Info ===');
|
|
console.log('Raw shortcode visible:', hasShortcode);
|
|
console.log('Template wrapper present:', hasTemplateWrapper);
|
|
|
|
// Check for PHP errors in source
|
|
const phpErrors = pageSource.match(/Fatal error:|Warning:|Notice:|Parse error:/gi);
|
|
if (phpErrors) {
|
|
console.log('PHP Errors found:', phpErrors);
|
|
}
|
|
|
|
// Check if CSS is loaded
|
|
const cssLoaded = await page.evaluate(() => {
|
|
const links = Array.from(document.querySelectorAll('link[rel="stylesheet"]'));
|
|
return links.some(link => link.href.includes('communication-templates.css'));
|
|
});
|
|
console.log('CSS loaded:', cssLoaded);
|
|
|
|
// Check if JavaScript is loaded
|
|
const jsLoaded = await page.evaluate(() => {
|
|
const scripts = Array.from(document.querySelectorAll('script'));
|
|
return scripts.some(script => script.src && script.src.includes('communication-templates.js'));
|
|
});
|
|
console.log('JavaScript loaded:', jsLoaded);
|
|
|
|
// Check JavaScript objects
|
|
const jsObjects = await page.evaluate(() => {
|
|
return {
|
|
jQuery: typeof jQuery !== 'undefined',
|
|
hvacTemplates: typeof hvacTemplates !== 'undefined',
|
|
HVACTemplates: typeof HVACTemplates !== 'undefined',
|
|
ajaxUrl: typeof hvacTemplates !== 'undefined' ? hvacTemplates.ajaxUrl : 'not found'
|
|
};
|
|
});
|
|
console.log('JavaScript objects:', jsObjects);
|
|
|
|
// Log all console messages
|
|
console.log('\n=== Console Messages ===');
|
|
consoleMessages.forEach(msg => {
|
|
console.log(`[${msg.type}] ${msg.text}`);
|
|
});
|
|
|
|
// Check page title to verify we're on the right page
|
|
const pageTitle = await page.title();
|
|
console.log('\nPage title:', pageTitle);
|
|
|
|
// Save page source for analysis
|
|
const fs = require('fs');
|
|
fs.writeFileSync('test-results/debug-page-source.html', pageSource);
|
|
console.log('\nPage source saved to test-results/debug-page-source.html');
|
|
});
|
|
|
|
test('Test AJAX endpoints directly', async ({ authenticatedPage: page }) => {
|
|
test.setTimeout(20000);
|
|
|
|
// Test get templates endpoint
|
|
const getTemplatesResponse = await page.evaluate(async () => {
|
|
if (typeof jQuery === 'undefined') return { error: 'jQuery not loaded' };
|
|
if (typeof hvacTemplates === 'undefined') return { error: 'hvacTemplates not defined' };
|
|
|
|
return new Promise((resolve) => {
|
|
jQuery.ajax({
|
|
url: hvacTemplates.ajaxUrl,
|
|
type: 'POST',
|
|
data: {
|
|
action: 'hvac_get_templates',
|
|
nonce: hvacTemplates.nonce
|
|
},
|
|
success: function(response) {
|
|
resolve({ success: true, data: response });
|
|
},
|
|
error: function(xhr, status, error) {
|
|
resolve({ success: false, error: error, status: xhr.status });
|
|
}
|
|
});
|
|
});
|
|
});
|
|
|
|
console.log('Get Templates Response:', JSON.stringify(getTemplatesResponse, null, 2));
|
|
|
|
// Test save template endpoint
|
|
const saveTemplateResponse = await page.evaluate(async () => {
|
|
if (typeof jQuery === 'undefined') return { error: 'jQuery not loaded' };
|
|
if (typeof hvacTemplates === 'undefined') return { error: 'hvacTemplates not defined' };
|
|
|
|
return new Promise((resolve) => {
|
|
jQuery.ajax({
|
|
url: hvacTemplates.ajaxUrl,
|
|
type: 'POST',
|
|
data: {
|
|
action: 'hvac_save_template',
|
|
nonce: hvacTemplates.nonce,
|
|
title: 'Test Template',
|
|
content: 'This is a test template content with {attendee_name} placeholder.',
|
|
category: 'general',
|
|
description: 'Test template created by E2E test'
|
|
},
|
|
success: function(response) {
|
|
resolve({ success: true, data: response });
|
|
},
|
|
error: function(xhr, status, error) {
|
|
resolve({ success: false, error: error, status: xhr.status, responseText: xhr.responseText });
|
|
}
|
|
});
|
|
});
|
|
});
|
|
|
|
console.log('Save Template Response:', JSON.stringify(saveTemplateResponse, null, 2));
|
|
});
|
|
|
|
test('Check template post type registration', async ({ authenticatedPage: page }) => {
|
|
test.setTimeout(20000);
|
|
|
|
// Check if post type exists via REST API
|
|
const postTypeExists = await page.evaluate(async () => {
|
|
try {
|
|
const response = await fetch('/wp-json/wp/v2/types/hvac_email_template');
|
|
return {
|
|
exists: response.ok,
|
|
status: response.status,
|
|
data: response.ok ? await response.json() : null
|
|
};
|
|
} catch (error) {
|
|
return { exists: false, error: error.message };
|
|
}
|
|
});
|
|
|
|
console.log('Post Type Check:', JSON.stringify(postTypeExists, null, 2));
|
|
|
|
// Try to access templates via REST API
|
|
const templatesViaRest = await page.evaluate(async () => {
|
|
try {
|
|
const response = await fetch('/wp-json/wp/v2/hvac_email_template');
|
|
return {
|
|
success: response.ok,
|
|
status: response.status,
|
|
data: response.ok ? await response.json() : await response.text()
|
|
};
|
|
} catch (error) {
|
|
return { success: false, error: error.message };
|
|
}
|
|
});
|
|
|
|
console.log('Templates via REST:', JSON.stringify(templatesViaRest, null, 2));
|
|
});
|
|
|
|
test('Test template widget in email attendees page', async ({ authenticatedPage: page }) => {
|
|
test.setTimeout(30000);
|
|
const actions = new CommonActions(page);
|
|
|
|
// First, create a test event with attendees
|
|
await actions.navigateAndWait('/manage-event/');
|
|
|
|
// Fill in basic event details
|
|
const eventTitle = `Test Event ${Date.now()}`;
|
|
await page.fill('#event_title', eventTitle);
|
|
|
|
// Fill description
|
|
const descFrame = page.frameLocator('iframe[id*="_ifr"]').first();
|
|
await descFrame.locator('body').fill('Test event for template validation');
|
|
|
|
// Set date/time (tomorrow)
|
|
const tomorrow = new Date();
|
|
tomorrow.setDate(tomorrow.getDate() + 1);
|
|
const dateStr = tomorrow.toISOString().split('T')[0];
|
|
|
|
await page.fill('input[name="EventStartDate"]', dateStr);
|
|
await page.fill('input[name="EventStartTime"]', '10:00');
|
|
await page.fill('input[name="EventEndDate"]', dateStr);
|
|
await page.fill('input[name="EventEndTime"]', '12:00');
|
|
|
|
// Submit
|
|
await page.click('button[type="submit"]');
|
|
await page.waitForLoadState('networkidle');
|
|
|
|
// Now navigate to dashboard to find the event
|
|
await actions.navigateAndWait('/hvac-dashboard/');
|
|
|
|
// Look for email attendees link for our event
|
|
const emailLink = page.locator(`a[href*="email-attendees"]:has-text("${eventTitle}")`).first();
|
|
|
|
if (await emailLink.isVisible()) {
|
|
await emailLink.click();
|
|
await page.waitForLoadState('networkidle');
|
|
await actions.screenshot('email-attendees-with-widget');
|
|
|
|
// Check for template manager elements
|
|
const widgetExists = await page.locator('.hvac-template-manager').count() > 0;
|
|
const toggleExists = await page.locator('.hvac-template-toggle').count() > 0;
|
|
|
|
console.log('Template widget exists:', widgetExists);
|
|
console.log('Template toggle exists:', toggleExists);
|
|
|
|
// Check if scripts are loaded on this page
|
|
const scriptsOnEmailPage = await page.evaluate(() => {
|
|
return {
|
|
jQuery: typeof jQuery !== 'undefined',
|
|
hvacTemplates: typeof hvacTemplates !== 'undefined',
|
|
HVACTemplates: typeof HVACTemplates !== 'undefined'
|
|
};
|
|
});
|
|
|
|
console.log('Scripts on email page:', scriptsOnEmailPage);
|
|
} else {
|
|
console.log('Could not find email attendees link for test event');
|
|
}
|
|
});
|
|
|
|
test('Test user capabilities and permissions', async ({ authenticatedPage: page }) => {
|
|
test.setTimeout(20000);
|
|
|
|
// Check current user capabilities
|
|
const userInfo = await page.evaluate(async () => {
|
|
try {
|
|
const response = await fetch('/wp-json/wp/v2/users/me', {
|
|
credentials: 'include'
|
|
});
|
|
|
|
if (response.ok) {
|
|
const data = await response.json();
|
|
return {
|
|
id: data.id,
|
|
name: data.name,
|
|
roles: data.roles,
|
|
capabilities: data.capabilities
|
|
};
|
|
}
|
|
return { error: 'Failed to get user info', status: response.status };
|
|
} catch (error) {
|
|
return { error: error.message };
|
|
}
|
|
});
|
|
|
|
console.log('Current User Info:', JSON.stringify(userInfo, null, 2));
|
|
|
|
// Check if user can create posts
|
|
const canCreatePosts = await page.evaluate(() => {
|
|
// This would need to be exposed by WordPress
|
|
return typeof wp !== 'undefined' && wp.data ?
|
|
wp.data.select('core').canUser('create', 'posts') :
|
|
'WordPress data not available';
|
|
});
|
|
|
|
console.log('Can create posts:', canCreatePosts);
|
|
});
|
|
|
|
test('Manually test template creation flow', async ({ authenticatedPage: page }) => {
|
|
test.setTimeout(30000);
|
|
const actions = new CommonActions(page);
|
|
|
|
// Navigate to templates page
|
|
await actions.navigateAndWait('/communication-templates/');
|
|
|
|
// Try clicking the create button if it exists
|
|
const createButton = page.locator('button:has-text("Create New Template")');
|
|
|
|
if (await createButton.isVisible()) {
|
|
await createButton.click();
|
|
await page.waitForTimeout(2000);
|
|
await actions.screenshot('after-create-click');
|
|
|
|
// Check what happened
|
|
const modalVisible = await page.locator('.hvac-template-form-overlay').isVisible();
|
|
const formVisible = await page.locator('.hvac-template-form').isVisible();
|
|
|
|
console.log('Modal visible after click:', modalVisible);
|
|
console.log('Form visible after click:', formVisible);
|
|
|
|
// Try to fill the form if visible
|
|
if (modalVisible || formVisible) {
|
|
const titleInput = page.locator('#hvac_template_title');
|
|
if (await titleInput.isVisible()) {
|
|
await titleInput.fill('E2E Test Template');
|
|
await page.locator('#hvac_template_content').fill('Test content with {attendee_name}');
|
|
await page.selectOption('#hvac_template_category', 'general');
|
|
|
|
await actions.screenshot('form-filled');
|
|
|
|
// Try to save
|
|
const saveButton = page.locator('.hvac-template-form-save');
|
|
if (await saveButton.isVisible()) {
|
|
await saveButton.click();
|
|
await page.waitForTimeout(3000);
|
|
await actions.screenshot('after-save-attempt');
|
|
|
|
// Check for success/error messages
|
|
const messages = await page.locator('.hvac-template-message').allTextContents();
|
|
console.log('Messages after save:', messages);
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
console.log('Create button not found - checking page structure');
|
|
|
|
// Get all visible text on page
|
|
const visibleText = await page.locator('body').innerText();
|
|
console.log('Page text preview:', visibleText.substring(0, 500));
|
|
}
|
|
});
|
|
|
|
}); |