upskill-event-manager/docs/DOCKER-DEVELOPMENT-GUIDE.md
Ben c3e7fe9140 feat: comprehensive HVAC plugin development framework and modernization
## Major Enhancements

### 🏗️ Architecture & Infrastructure
- Implement comprehensive Docker testing infrastructure with hermetic environment
- Add Forgejo Actions CI/CD pipeline for automated deployments
- Create Page Object Model (POM) testing architecture reducing test duplication by 90%
- Establish security-first development patterns with input validation and output escaping

### 🧪 Testing Framework Modernization
- Migrate 146+ tests from 80 duplicate files to centralized architecture
- Add comprehensive E2E test suites for all user roles and workflows
- Implement WordPress error detection with automatic site health monitoring
- Create robust browser lifecycle management with proper cleanup

### 📚 Documentation & Guides
- Add comprehensive development best practices guide
- Create detailed administrator setup documentation
- Establish user guides for trainers and master trainers
- Document security incident reports and migration guides

### 🔧 Core Plugin Features
- Enhance trainer profile management with certification system
- Improve find trainer functionality with advanced filtering
- Strengthen master trainer area with content management
- Add comprehensive venue and organizer management

### 🛡️ Security & Reliability
- Implement security-first patterns throughout codebase
- Add comprehensive input validation and output escaping
- Create secure credential management system
- Establish proper WordPress role-based access control

### 🎯 WordPress Integration
- Strengthen singleton pattern implementation across all classes
- Enhance template hierarchy with proper WordPress integration
- Improve page manager with hierarchical URL structure
- Add comprehensive shortcode and menu system

### 🔍 Developer Experience
- Add extensive debugging and troubleshooting tools
- Create comprehensive test data seeding scripts
- Implement proper error handling and logging
- Establish consistent code patterns and standards

### 📊 Performance & Optimization
- Optimize database queries and caching strategies
- Improve asset loading and script management
- Enhance template rendering performance
- Streamline user experience across all interfaces

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-08-29 11:26:10 -03:00

1078 lines
No EOL
24 KiB
Markdown

# Docker Development Guide
**Version**: 2.0.0
**Last Updated**: August 28, 2025
**Audience**: Developers, QA Engineers
**Platform**: HVAC Community Events
## Executive Summary
This guide provides comprehensive documentation for the Docker-based development and testing environment for the HVAC Community Events WordPress plugin. The environment includes a complete WordPress stack with testing tools, database management, and email testing capabilities.
## Table of Contents
1. [Environment Overview](#environment-overview)
2. [Prerequisites](#prerequisites)
3. [Initial Setup](#initial-setup)
4. [Container Management](#container-management)
5. [Database Operations](#database-operations)
6. [Test Framework Architecture](#test-framework-architecture)
7. [Running Tests](#running-tests)
8. [Debugging](#debugging)
9. [Performance Testing](#performance-testing)
10. [Troubleshooting](#troubleshooting)
11. [Best Practices](#best-practices)
12. [Advanced Configuration](#advanced-configuration)
## Environment Overview
### Architecture Diagram
```
┌─────────────────────────────────────────────────────────────┐
│ Host Machine │
│ │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ Docker Compose Network │ │
│ │ │ │
│ │ ┌──────────────┐ ┌──────────────┐ ┌───────────┐ │ │
│ │ │ WordPress │ │ MySQL │ │ Redis │ │ │
│ │ │ PHP 8.2 │◄─┤ 8.0 │◄─┤ Cache │ │ │
│ │ │ Port: 8080 │ │ Port: 3307 │ │Port: 6380 │ │ │
│ │ └──────────────┘ └──────────────┘ └───────────┘ │ │
│ │ │ │
│ │ ┌──────────────┐ ┌──────────────┐ ┌───────────┐ │ │
│ │ │ PhpMyAdmin │ │ Mailhog │ │ Selenium │ │ │
│ │ │ Port: 8081 │ │ Port: 8025 │ │ Port: 4444│ │ │
│ │ └──────────────┘ └──────────────┘ └───────────┘ │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
│ Test Files ◄──────► Plugin Source ◄──────► Test Results │
└─────────────────────────────────────────────────────────────┘
```
### Service Details
| Service | Image | Port | Purpose |
|---------|-------|------|---------|
| WordPress | wordpress:6.4-php8.2-apache | 8080 | Main application |
| MySQL | mysql:8.0 | 3307 | Database server |
| Redis | redis:7-alpine | 6380 | Object caching |
| PhpMyAdmin | phpmyadmin:5 | 8081 | Database management |
| Mailhog | mailhog/mailhog | 8025 | Email testing |
| Selenium | selenium/standalone-chrome | 4444 | Browser automation |
## Prerequisites
### System Requirements
```yaml
Operating System:
- Linux (Ubuntu 20.04+, Debian 11+)
- macOS (11.0+)
- Windows 10/11 with WSL2
Docker:
version: "20.10+"
compose: "2.0+"
Resources:
RAM: "8GB minimum, 16GB recommended"
CPU: "4 cores minimum"
Disk: "20GB free space"
Development Tools:
- Node.js 16+
- npm or yarn
- Git
- Visual Studio Code (recommended)
```
### Installation
#### Linux/macOS
```bash
# Install Docker
curl -fsSL https://get.docker.com -o get-docker.sh
sh get-docker.sh
# Install Docker Compose
sudo curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose
# Verify installation
docker --version
docker compose version
```
#### Windows (WSL2)
```powershell
# Install WSL2
wsl --install
# Install Docker Desktop
# Download from https://docker.com/products/docker-desktop
# Enable WSL2 integration in Docker Desktop settings
```
## Initial Setup
### 1. Clone Repository
```bash
# Clone the repository
git clone https://github.com/your-org/upskill-event-manager.git
cd upskill-event-manager
# Checkout development branch
git checkout development
```
### 2. Environment Configuration
```bash
# Copy environment template
cp tests/.env.template tests/.env
# Edit environment variables
nano tests/.env
```
#### Environment Variables
```env
# WordPress Configuration
WORDPRESS_DB_HOST=mysql-test
WORDPRESS_DB_USER=hvac_test_user
WORDPRESS_DB_PASSWORD=hvac_test_password
WORDPRESS_DB_NAME=hvac_test_db
WORDPRESS_DEBUG=1
WORDPRESS_DEBUG_LOG=1
WORDPRESS_DEBUG_DISPLAY=0
# Test Configuration
HVAC_TEST_MODE=true
HVAC_TEST_DATA_ISOLATION=true
HVAC_TEST_EMAIL=test@example.com
# Service Ports
WORDPRESS_PORT=8080
MYSQL_PORT=3307
REDIS_PORT=6380
PHPMYADMIN_PORT=8081
MAILHOG_PORT=8025
SELENIUM_PORT=4444
# Volumes
WORDPRESS_VOLUME=wordpress_test_data
MYSQL_VOLUME=mysql_test_data
REDIS_VOLUME=redis_test_data
```
### 3. Build and Start Containers
```bash
# Navigate to tests directory
cd tests
# Build and start all services
docker compose -f docker-compose.test.yml up -d --build
# Wait for services to be healthy
docker compose -f docker-compose.test.yml ps
# Check logs
docker compose -f docker-compose.test.yml logs -f
```
### 4. Initialize WordPress
```bash
# Install WordPress
docker compose exec wordpress-test wp core install \
--url="http://localhost:8080" \
--title="HVAC Test Site" \
--admin_user="admin" \
--admin_password="admin123" \
--admin_email="admin@test.local"
# Activate plugin
docker compose exec wordpress-test wp plugin activate hvac-community-events
# Install The Events Calendar
docker compose exec wordpress-test wp plugin install the-events-calendar --activate
# Create test pages
docker compose exec wordpress-test wp eval 'HVAC_Page_Manager::create_required_pages();'
# Flush permalinks
docker compose exec wordpress-test wp rewrite flush
```
### 5. Seed Test Data
```bash
# Create test users
./scripts/seed-test-users.sh
# Create test events
./scripts/seed-test-events.sh
# Import sample venues
docker compose exec wordpress-test wp import fixtures/venues.xml --authors=create
# Generate test certificates
docker compose exec wordpress-test wp eval 'HVAC_Test_Data::generate_certificates(50);'
```
## Container Management
### Starting and Stopping
```bash
# Start all containers
docker compose -f docker-compose.test.yml up -d
# Stop all containers (preserves data)
docker compose -f docker-compose.test.yml stop
# Stop and remove containers (preserves volumes)
docker compose -f docker-compose.test.yml down
# Stop and remove everything (including volumes)
docker compose -f docker-compose.test.yml down -v
# Restart specific service
docker compose -f docker-compose.test.yml restart wordpress-test
```
### Accessing Services
```bash
# WordPress site
open http://localhost:8080
# WordPress admin
open http://localhost:8080/wp-admin
# Username: admin
# Password: admin123
# PhpMyAdmin
open http://localhost:8081
# Username: hvac_test_user
# Password: hvac_test_password
# Mailhog (email testing)
open http://localhost:8025
# Redis Commander (if installed)
docker run -d --name redis-commander \
--network hvac-test-network \
-p 8082:8081 \
rediscommander/redis-commander \
--redis-host redis-test
```
### Executing Commands
```bash
# WordPress CLI
docker compose exec wordpress-test wp [command]
# MySQL CLI
docker compose exec mysql-test mysql -u root -p
# Redis CLI
docker compose exec redis-test redis-cli
# PHP commands
docker compose exec wordpress-test php [script.php]
# Bash shell
docker compose exec wordpress-test bash
```
## Database Operations
### Backup and Restore
```bash
# Backup database
docker compose exec mysql-test mysqldump \
-u hvac_test_user -phvac_test_password \
hvac_test_db > backup-$(date +%Y%m%d).sql
# Restore database
docker compose exec -T mysql-test mysql \
-u hvac_test_user -phvac_test_password \
hvac_test_db < backup-20250828.sql
# Export specific tables
docker compose exec mysql-test mysqldump \
-u hvac_test_user -phvac_test_password \
hvac_test_db wp_posts wp_postmeta > posts-backup.sql
```
### Database Management
```bash
# Connect to MySQL
docker compose exec mysql-test mysql -u root -p
# Common queries
SHOW DATABASES;
USE hvac_test_db;
SHOW TABLES;
DESCRIBE wp_users;
# Check plugin tables
SHOW TABLES LIKE 'wp_hvac%';
# Query examples
SELECT * FROM wp_users WHERE user_login LIKE 'hvac_%';
SELECT COUNT(*) FROM wp_posts WHERE post_type = 'tribe_events';
```
### Reset Database
```bash
#!/bin/bash
# reset-database.sh
# Drop and recreate database
docker compose exec mysql-test mysql -u root -p -e "
DROP DATABASE IF EXISTS hvac_test_db;
CREATE DATABASE hvac_test_db CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
GRANT ALL ON hvac_test_db.* TO 'hvac_test_user'@'%';
FLUSH PRIVILEGES;
"
# Reinstall WordPress
docker compose exec wordpress-test wp core install \
--url="http://localhost:8080" \
--title="HVAC Test Site" \
--admin_user="admin" \
--admin_password="admin123" \
--admin_email="admin@test.local"
# Reactivate plugins and recreate pages
docker compose exec wordpress-test wp plugin activate hvac-community-events
docker compose exec wordpress-test wp eval 'HVAC_Page_Manager::create_required_pages();'
```
## Test Framework Architecture
### Page Object Model (POM)
The test framework uses the Page Object Model pattern for maintainability and reusability:
```javascript
// Structure
tests/
├── e2e/
├── page-objects/
├── BasePage.js
├── LoginPage.js
├── DashboardPage.js
├── EventPage.js
└── VenuePage.js
├── fixtures/
├── users.json
├── events.json
└── venues.json
├── helpers/
├── BrowserManager.js
├── TestData.js
└── Utilities.js
└── tests/
├── authentication.test.js
├── event-management.test.js
└── venue-management.test.js
```
### Browser Manager (Singleton)
```javascript
// BrowserManager.js
const { chromium, firefox, webkit } = require('playwright');
class BrowserManager {
constructor() {
if (BrowserManager.instance) {
return BrowserManager.instance;
}
this.browser = null;
this.context = null;
this.page = null;
BrowserManager.instance = this;
}
async initialize(options = {}) {
const browserType = options.browser || 'chromium';
const headless = options.headless !== false;
this.browser = await chromium.launch({
headless,
args: ['--no-sandbox', '--disable-setuid-sandbox'],
});
this.context = await this.browser.newContext({
viewport: { width: 1920, height: 1080 },
ignoreHTTPSErrors: true,
...options.context,
});
this.page = await this.context.newPage();
// Set up error handling
this.page.on('pageerror', error => {
console.error('Page error:', error.message);
});
return this.page;
}
async cleanup() {
if (this.page) await this.page.close();
if (this.context) await this.context.close();
if (this.browser) await this.browser.close();
}
}
module.exports = new BrowserManager();
```
### Test Configuration
```javascript
// test.config.js
module.exports = {
baseURL: process.env.BASE_URL || 'http://localhost:8080',
timeout: 30000,
retries: 2,
workers: 4,
use: {
headless: process.env.HEADLESS === 'true',
screenshot: 'only-on-failure',
video: 'retain-on-failure',
trace: 'on-first-retry',
},
projects: [
{
name: 'Chrome',
use: { browserName: 'chromium' },
},
{
name: 'Firefox',
use: { browserName: 'firefox' },
},
{
name: 'Safari',
use: { browserName: 'webkit' },
},
],
reporter: [
['html', { outputFolder: 'test-results/html' }],
['json', { outputFile: 'test-results/results.json' }],
['junit', { outputFile: 'test-results/junit.xml' }],
],
};
```
## Running Tests
### E2E Test Execution
```bash
# Run all tests (headless)
HEADLESS=true BASE_URL=http://localhost:8080 npm test
# Run specific test file
HEADLESS=true npm test -- test-master-trainer-e2e.js
# Run with visible browser
HEADLESS=false npm test
# Run specific test suite
npm test -- --grep "Event Management"
# Run in parallel
npm test -- --workers=4
# Generate HTML report
npm test -- --reporter=html
open test-results/index.html
```
### Test Categories
```bash
# Authentication tests
node tests/e2e/auth.test.js
# Event management tests
node tests/e2e/events.test.js
# Venue management tests
node tests/e2e/venues.test.js
# Certificate generation tests
node tests/e2e/certificates.test.js
# Master trainer features
node tests/e2e/master-trainer.test.js
# Performance tests
node tests/performance/load-test.js
```
### Cross-Browser Testing
```bash
# Chrome
BROWSER=chromium npm test
# Firefox
BROWSER=firefox npm test
# Safari (WebKit)
BROWSER=webkit npm test
# All browsers sequentially
npm run test:cross-browser
# All browsers in parallel
npm run test:cross-browser:parallel
```
### Visual Regression Testing
```bash
# Capture baseline screenshots
npm run test:visual:baseline
# Run visual comparison tests
npm run test:visual:compare
# Update baseline images
npm run test:visual:update
# View diff report
open test-results/visual-diff/index.html
```
## Debugging
### Debug Mode
```javascript
// Enable debug mode in tests
const DEBUG = process.env.DEBUG === 'true';
if (DEBUG) {
// Slow down actions
page.setDefaultTimeout(60000);
// Pause on failures
page.on('pageerror', async () => {
await page.pause();
});
// Take screenshots at each step
afterEach(async () => {
await page.screenshot({
path: `debug/step-${Date.now()}.png`
});
});
}
```
### Interactive Debugging
```bash
# Launch browser with DevTools
PWDEBUG=1 node test-file.js
# Use Playwright Inspector
npx playwright test --debug
# Pause at specific point
await page.pause(); // Add in test code
```
### Container Debugging
```bash
# View container logs
docker compose logs -f wordpress-test
# Access container shell
docker compose exec wordpress-test bash
# Check PHP errors
docker compose exec wordpress-test tail -f /var/log/apache2/error.log
# Monitor MySQL queries
docker compose exec mysql-test tail -f /var/log/mysql/query.log
# Debug WordPress
docker compose exec wordpress-test wp shell
```
### Network Debugging
```bash
# Monitor network traffic
docker compose exec wordpress-test tcpdump -i any -w traffic.pcap
# Check container connectivity
docker compose exec wordpress-test ping mysql-test
# Inspect Docker network
docker network inspect hvac-test-network
# Port forwarding issues
netstat -tuln | grep 8080
```
## Performance Testing
### Load Testing Setup
```javascript
// load-test.js
const { chromium } = require('playwright');
const { performance } = require('perf_hooks');
async function loadTest(config) {
const { concurrent = 10, iterations = 100 } = config;
const results = [];
const runTest = async () => {
const start = performance.now();
const browser = await chromium.launch({ headless: true });
const page = await browser.newPage();
await page.goto('http://localhost:8080/trainer/dashboard/');
await page.waitForSelector('.hvac-dashboard');
const end = performance.now();
await browser.close();
return end - start;
};
// Run concurrent tests
for (let i = 0; i < iterations; i += concurrent) {
const batch = Array(concurrent).fill().map(() => runTest());
const times = await Promise.all(batch);
results.push(...times);
}
// Calculate statistics
const avg = results.reduce((a, b) => a + b, 0) / results.length;
const max = Math.max(...results);
const min = Math.min(...results);
console.log(`Average: ${avg}ms, Max: ${max}ms, Min: ${min}ms`);
}
// Run load test
loadTest({ concurrent: 20, iterations: 200 });
```
### Performance Metrics
```bash
# Monitor container resources
docker stats
# MySQL performance
docker compose exec mysql-test mysqladmin -u root -p status
# Redis performance
docker compose exec redis-test redis-cli INFO stats
# Apache performance
docker compose exec wordpress-test apache2ctl -S
```
## Troubleshooting
### Common Issues
#### Container won't start
```bash
# Check for port conflicts
lsof -i :8080
lsof -i :3307
# Kill conflicting processes
kill -9 $(lsof -t -i:8080)
# Reset Docker
docker system prune -a
docker volume prune
```
#### Database connection errors
```bash
# Verify MySQL is running
docker compose ps mysql-test
# Check MySQL logs
docker compose logs mysql-test
# Test connection
docker compose exec wordpress-test wp db check
# Reset MySQL password
docker compose exec mysql-test mysql -u root -e "
ALTER USER 'hvac_test_user'@'%' IDENTIFIED BY 'hvac_test_password';
FLUSH PRIVILEGES;
"
```
#### Plugin activation fails
```bash
# Check PHP errors
docker compose exec wordpress-test tail -f /var/log/apache2/error.log
# Verify plugin files
docker compose exec wordpress-test ls -la /var/www/html/wp-content/plugins/hvac-community-events/
# Debug plugin activation
docker compose exec wordpress-test wp plugin activate hvac-community-events --debug
```
#### Tests timing out
```javascript
// Increase timeout in test
test.setTimeout(60000);
// Or globally
module.exports = {
timeout: 60000,
// ...
};
// Debug slow operations
console.time('operation');
await slowOperation();
console.timeEnd('operation');
```
### Reset Everything
```bash
#!/bin/bash
# full-reset.sh
# Stop and remove all containers
docker compose -f docker-compose.test.yml down -v
# Remove all test data
rm -rf wordpress_test_data/
rm -rf mysql_test_data/
rm -rf redis_test_data/
# Clean Docker system
docker system prune -a --volumes
# Rebuild and start fresh
docker compose -f docker-compose.test.yml up -d --build
# Wait for healthy state
sleep 30
# Initialize WordPress
./scripts/init-wordpress.sh
# Seed test data
./scripts/seed-all-data.sh
```
## Best Practices
### Development Workflow
1. **Branch Strategy**
```bash
# Create feature branch
git checkout -b feature/new-venue-system
# Make changes and test locally
docker compose up -d
npm test
# Commit with conventional commits
git commit -m "feat: implement new venue management system"
```
2. **Test-Driven Development**
```javascript
// Write test first
test('should create new venue', async () => {
await venuePage.createVenue({
name: 'Test Venue',
address: '123 Test St',
});
expect(await venuePage.venueExists('Test Venue')).toBe(true);
});
// Then implement feature
```
3. **Data Isolation**
```javascript
// Use unique test data
const testId = Date.now();
const venueName = `Venue_${testId}`;
// Clean up after tests
afterEach(async () => {
await cleanup(testId);
});
```
### Code Quality
1. **Linting**
```bash
# JavaScript
npm run lint
# PHP
docker compose exec wordpress-test ./vendor/bin/phpcs
# Fix automatically
npm run lint:fix
```
2. **Code Coverage**
```bash
# Generate coverage report
npm run test:coverage
# View report
open coverage/index.html
```
3. **Security Scanning**
```bash
# Scan for vulnerabilities
npm audit
# PHP dependencies
docker compose exec wordpress-test ./vendor/bin/security-checker security:check
```
### Performance Optimization
1. **Container Resources**
```yaml
# docker-compose.yml
services:
wordpress-test:
deploy:
resources:
limits:
cpus: '2'
memory: 2G
reservations:
cpus: '1'
memory: 1G
```
2. **Caching Strategy**
```bash
# Enable Redis object cache
docker compose exec wordpress-test wp plugin install redis-cache --activate
docker compose exec wordpress-test wp redis enable
```
3. **Database Optimization**
```sql
-- Add indexes
ALTER TABLE wp_posts ADD INDEX idx_type_status (post_type, post_status);
ALTER TABLE wp_postmeta ADD INDEX idx_meta_key (meta_key);
-- Optimize tables
OPTIMIZE TABLE wp_posts;
OPTIMIZE TABLE wp_postmeta;
```
## Advanced Configuration
### Custom Docker Network
```yaml
# docker-compose.override.yml
networks:
hvac-test-network:
driver: bridge
ipam:
config:
- subnet: 172.28.0.0/16
gateway: 172.28.0.1
```
### SSL Configuration
```bash
# Generate self-signed certificate
openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
-keyout nginx/ssl/private.key \
-out nginx/ssl/certificate.crt
# Add nginx proxy container
services:
nginx:
image: nginx:alpine
ports:
- "443:443"
volumes:
- ./nginx/conf.d:/etc/nginx/conf.d
- ./nginx/ssl:/etc/nginx/ssl
```
### Multi-Site Testing
```yaml
# Enable WordPress Multisite
environment:
WORDPRESS_CONFIG_EXTRA: |
define('WP_ALLOW_MULTISITE', true);
define('MULTISITE', true);
define('SUBDOMAIN_INSTALL', false);
define('DOMAIN_CURRENT_SITE', 'localhost');
define('PATH_CURRENT_SITE', '/');
define('SITE_ID_CURRENT_SITE', 1);
define('BLOG_ID_CURRENT_SITE', 1);
```
### CI/CD Integration
```yaml
# .github/workflows/test.yml
name: E2E Tests
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Start Docker Compose
run: |
docker compose -f tests/docker-compose.test.yml up -d
sleep 30
- name: Initialize WordPress
run: |
docker compose exec -T wordpress-test wp core install \
--url="http://localhost:8080" \
--title="Test" \
--admin_user="admin" \
--admin_password="admin123" \
--admin_email="test@test.com"
- name: Run Tests
run: |
npm ci
npm test
- name: Upload Results
if: always()
uses: actions/upload-artifact@v3
with:
name: test-results
path: test-results/
```
---
## Quick Reference
### Essential Commands
```bash
# Start environment
docker compose -f tests/docker-compose.test.yml up -d
# Stop environment
docker compose -f tests/docker-compose.test.yml down
# View logs
docker compose -f tests/docker-compose.test.yml logs -f
# Run tests
HEADLESS=true npm test
# Access WordPress
open http://localhost:8080
# Access database
open http://localhost:8081
# View emails
open http://localhost:8025
# Shell access
docker compose exec wordpress-test bash
# WP-CLI
docker compose exec wordpress-test wp [command]
```
### Service URLs
| Service | URL | Credentials |
|---------|-----|-------------|
| WordPress | http://localhost:8080 | admin / admin123 |
| WordPress Admin | http://localhost:8080/wp-admin | admin / admin123 |
| PhpMyAdmin | http://localhost:8081 | hvac_test_user / hvac_test_password |
| Mailhog | http://localhost:8025 | No auth required |
| Redis Commander | http://localhost:8082 | No auth required |
### File Locations
```bash
# Plugin source
./
# Test files
./tests/
# Docker config
./tests/docker-compose.test.yml
# Test results
./test-results/
# Screenshots
./screenshots/
# Fixtures
./tests/fixtures/
```
---
*This guide is maintained by the HVAC Community Events development team. For updates or issues, please submit a pull request or open an issue in the repository.*
**Document Version**: 2.0.0
**Last Updated**: August 28, 2025
**Next Review**: September 28, 2025