refactor: reorganize project structure for better maintainability
- Move 45 debug/test files from root to organized scripts/ directories - Secure public/ directory by removing debug files (security improvement) - Create structured scripts organization: • scripts/debug/ (20 files) - Framework debugging tools • scripts/test/ (18 files) - Test and validation scripts • scripts/maintenance/ (5 files) - Maintenance utilities • scripts/dev/ (2 files) - Development tools Security improvements: - Removed all debug/test files from public/ directory - Only production files remain: index.php, health.php Root directory cleanup: - Reduced from 47 to 2 PHP files in root - Only essential production files: console.php, worker.php This improves: ✅ Security (no debug code in public/) ✅ Organization (clear separation of concerns) ✅ Maintainability (easy to find and manage scripts) ✅ Professional structure (clean root directory)
This commit is contained in:
119
scripts/test/test_agents_simple.php
Normal file
119
scripts/test/test_agents_simple.php
Normal file
@@ -0,0 +1,119 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
echo "=== Framework Agents Status Check ===\n\n";
|
||||
|
||||
// Check if our FrameworkAgents class exists and has the correct MCP Tool attributes
|
||||
$frameworkAgentsFile = __DIR__ . '/src/Framework/Mcp/Tools/FrameworkAgents.php';
|
||||
|
||||
if (file_exists($frameworkAgentsFile)) {
|
||||
echo "✅ FrameworkAgents class file exists\n";
|
||||
|
||||
$content = file_get_contents($frameworkAgentsFile);
|
||||
|
||||
// Check for each agent method
|
||||
$agents = [
|
||||
'framework_core_agent' => 'Framework-Core Architecture Specialist Agent',
|
||||
'mcp_specialist_agent' => 'MCP-Integration Specialist Agent',
|
||||
'value_object_agent' => 'Value Object Specialist Agent',
|
||||
'discovery_expert_agent' => 'Attribute-Discovery Specialist Agent'
|
||||
];
|
||||
|
||||
foreach ($agents as $agentMethod => $description) {
|
||||
if (strpos($content, "name: '$agentMethod'") !== false) {
|
||||
echo "✅ $agentMethod MCP tool found\n";
|
||||
} else {
|
||||
echo "❌ $agentMethod MCP tool missing\n";
|
||||
}
|
||||
}
|
||||
|
||||
// Check if class has correct namespace and MCP attributes
|
||||
if (strpos($content, '#[McpTool(') !== false) {
|
||||
echo "✅ MCP Tool attributes detected\n";
|
||||
} else {
|
||||
echo "❌ No MCP Tool attributes found\n";
|
||||
}
|
||||
|
||||
if (strpos($content, 'namespace App\Framework\Mcp\Tools;') !== false) {
|
||||
echo "✅ Correct namespace found\n";
|
||||
} else {
|
||||
echo "❌ Incorrect namespace\n";
|
||||
}
|
||||
|
||||
} else {
|
||||
echo "❌ FrameworkAgents class file not found\n";
|
||||
exit(1);
|
||||
}
|
||||
|
||||
echo "\n=== Integration Status ===\n";
|
||||
|
||||
// Check if CLAUDE.md includes framework-personas.md
|
||||
$claudeFile = __DIR__ . '/CLAUDE.md';
|
||||
if (file_exists($claudeFile)) {
|
||||
$claudeContent = file_get_contents($claudeFile);
|
||||
if (strpos($claudeContent, '@docs/claude/framework-personas.md') !== false) {
|
||||
echo "✅ Framework personas integrated in CLAUDE.md\n";
|
||||
} else {
|
||||
echo "❌ Framework personas not integrated in CLAUDE.md\n";
|
||||
}
|
||||
} else {
|
||||
echo "❌ CLAUDE.md not found\n";
|
||||
}
|
||||
|
||||
// Check if framework-personas.md exists
|
||||
$personasFile = __DIR__ . '/docs/claude/framework-personas.md';
|
||||
if (file_exists($personasFile)) {
|
||||
echo "✅ Framework personas documentation exists\n";
|
||||
|
||||
$personasContent = file_get_contents($personasFile);
|
||||
$expectedPersonas = [
|
||||
'--persona-framework-core',
|
||||
'--persona-mcp-specialist',
|
||||
'--persona-value-object-architect',
|
||||
'--persona-discovery-expert'
|
||||
];
|
||||
|
||||
foreach ($expectedPersonas as $persona) {
|
||||
if (strpos($personasContent, $persona) !== false) {
|
||||
echo " ✅ $persona documented\n";
|
||||
} else {
|
||||
echo " ❌ $persona missing from documentation\n";
|
||||
}
|
||||
}
|
||||
} else {
|
||||
echo "❌ Framework personas documentation missing\n";
|
||||
}
|
||||
|
||||
// Check global .claude reference
|
||||
$globalReferenceFile = '/home/michael/.claude/FRAMEWORK-PERSONAS.md';
|
||||
if (file_exists($globalReferenceFile)) {
|
||||
echo "✅ Global Claude reference file exists\n";
|
||||
|
||||
$referenceContent = file_get_contents($globalReferenceFile);
|
||||
if (strpos($referenceContent, '@/home/michael/dev/michaelschiemer/docs/claude/framework-personas.md') !== false) {
|
||||
echo "✅ Correct reference path in global file\n";
|
||||
} else {
|
||||
echo "❌ Incorrect reference path in global file\n";
|
||||
}
|
||||
} else {
|
||||
echo "❌ Global Claude reference file missing\n";
|
||||
}
|
||||
|
||||
echo "\n=== Summary ===\n";
|
||||
echo "🎉 Framework-specific agents have been successfully implemented!\n\n";
|
||||
|
||||
echo "📋 Available Framework Agents (as MCP Tools):\n";
|
||||
foreach ($agents as $agentMethod => $description) {
|
||||
echo " - $agentMethod: $description\n";
|
||||
}
|
||||
|
||||
echo "\n💡 How to use:\n";
|
||||
echo "1. The agents are automatically available when using the framework's MCP server\n";
|
||||
echo "2. They will appear in Claude Code's /agents list when MCP server is properly configured\n";
|
||||
echo "3. Each agent provides specialized expertise for framework-specific tasks\n";
|
||||
|
||||
echo "\n🔧 Next Steps:\n";
|
||||
echo "1. Configure Claude Desktop to use the framework's MCP server\n";
|
||||
echo "2. Test the agents via: echo '{\"jsonrpc\":\"2.0\",\"method\":\"tools/list\",\"id\":1}' | docker exec -i php php console.php mcp:server\n";
|
||||
echo "3. Use the agents for framework-specific development tasks\n";
|
||||
95
scripts/test/test_arrow_keys.php
Normal file
95
scripts/test/test_arrow_keys.php
Normal file
@@ -0,0 +1,95 @@
|
||||
<?php
|
||||
|
||||
require_once __DIR__ . '/vendor/autoload.php';
|
||||
|
||||
echo "Arrow Key Test\n";
|
||||
echo "==============\n\n";
|
||||
echo "Press arrow keys to test input reading.\n";
|
||||
echo "Press 'q' to quit.\n\n";
|
||||
|
||||
// Enable raw mode
|
||||
shell_exec('stty -icanon -echo');
|
||||
|
||||
function readKey(): string
|
||||
{
|
||||
$key = fgetc(STDIN);
|
||||
if ($key === false) {
|
||||
return '';
|
||||
}
|
||||
|
||||
// Handle escape sequences (arrow keys, etc.)
|
||||
if ($key === "\033") {
|
||||
$sequence = $key;
|
||||
|
||||
// Read the next character
|
||||
$next = fgetc(STDIN);
|
||||
if ($next === false) {
|
||||
return $key; // Just escape
|
||||
}
|
||||
$sequence .= $next;
|
||||
|
||||
// If it's a bracket, read more
|
||||
if ($next === '[') {
|
||||
$third = fgetc(STDIN);
|
||||
if ($third !== false) {
|
||||
$sequence .= $third;
|
||||
|
||||
// Some sequences have more characters (like Page Up/Down)
|
||||
if ($third === '5' || $third === '6' || $third === '3') {
|
||||
$fourth = fgetc(STDIN);
|
||||
if ($fourth !== false) {
|
||||
$sequence .= $fourth;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $sequence;
|
||||
}
|
||||
|
||||
return $key;
|
||||
}
|
||||
|
||||
try {
|
||||
while (true) {
|
||||
$key = readKey();
|
||||
|
||||
if ($key === 'q') {
|
||||
break;
|
||||
}
|
||||
|
||||
$hexKey = bin2hex($key);
|
||||
echo "Key pressed: '$key' (hex: $hexKey)\n";
|
||||
|
||||
switch ($key) {
|
||||
case "\033[A":
|
||||
echo " -> Arrow UP detected!\n";
|
||||
break;
|
||||
case "\033[B":
|
||||
echo " -> Arrow DOWN detected!\n";
|
||||
break;
|
||||
case "\033[C":
|
||||
echo " -> Arrow RIGHT detected!\n";
|
||||
break;
|
||||
case "\033[D":
|
||||
echo " -> Arrow LEFT detected!\n";
|
||||
break;
|
||||
case "\n":
|
||||
echo " -> ENTER detected!\n";
|
||||
break;
|
||||
case " ":
|
||||
echo " -> SPACE detected!\n";
|
||||
break;
|
||||
case "\033":
|
||||
echo " -> ESC detected!\n";
|
||||
break;
|
||||
default:
|
||||
echo " -> Regular key: '$key'\n";
|
||||
break;
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
// Restore terminal
|
||||
shell_exec('stty icanon echo');
|
||||
echo "\nTerminal restored. Goodbye!\n";
|
||||
}
|
||||
191
scripts/test/test_final_tui.php
Normal file
191
scripts/test/test_final_tui.php
Normal file
@@ -0,0 +1,191 @@
|
||||
<?php
|
||||
|
||||
require_once __DIR__ . '/vendor/autoload.php';
|
||||
|
||||
// Final comprehensive TUI test
|
||||
use App\Framework\Console\Components\TuiState;
|
||||
use App\Framework\Console\Components\TuiInputHandler;
|
||||
use App\Framework\Console\Components\TuiCommandExecutor;
|
||||
use App\Framework\Console\Components\TuiRenderer;
|
||||
use App\Framework\Console\CommandHistory;
|
||||
use App\Framework\Console\CommandGroupRegistry;
|
||||
use App\Framework\Console\TuiView;
|
||||
use App\Framework\Console\TuiKeyCode;
|
||||
use App\Framework\Console\ConsoleOutput;
|
||||
use App\Framework\Console\Screen\ScreenManager;
|
||||
use App\Framework\Discovery\Results\DiscoveryRegistry;
|
||||
|
||||
echo "Final TUI Test - Complete Workflow Simulation\n";
|
||||
echo "=============================================\n\n";
|
||||
|
||||
try {
|
||||
// Create a minimal discovery registry for testing
|
||||
$discoveryRegistry = new class implements \App\Framework\Discovery\Results\DiscoveryRegistry {
|
||||
public function interfaces() {
|
||||
return new class {
|
||||
public function get(string $interface) {
|
||||
return [];
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public function attributes() {
|
||||
return new class {
|
||||
public function get(string $attributeClass) {
|
||||
// Return empty array for ConsoleCommand attributes
|
||||
return [];
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
// Create mock executor
|
||||
$mockExecutor = new class implements \App\Framework\Console\Components\TuiCommandExecutor {
|
||||
public function executeSelectedCommand(object $command): void {
|
||||
echo "Mock: Execute command\n";
|
||||
}
|
||||
public function executeCommand(string $commandName): void {
|
||||
echo "Mock: Execute command: $commandName\n";
|
||||
}
|
||||
public function validateSelectedCommand(object $command): void {
|
||||
echo "Mock: Validate command\n";
|
||||
}
|
||||
public function validateCommand(string $commandName): void {
|
||||
echo "Mock: Validate command: $commandName\n";
|
||||
}
|
||||
public function showSelectedCommandHelp(object $command): void {
|
||||
echo "Mock: Show help\n";
|
||||
}
|
||||
public function showCommandHelp(string $commandName): void {
|
||||
echo "Mock: Show help: $commandName\n";
|
||||
}
|
||||
public function showAllCommandsHelp(): void {
|
||||
echo "Mock: Show all commands help\n";
|
||||
}
|
||||
public function startInteractiveForm(object $command, \App\Framework\Console\Components\TuiState $state): void {
|
||||
echo "Mock: Start form\n";
|
||||
}
|
||||
public function findCommandObject(string $commandName): ?object {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
// Create components
|
||||
$screenManager = new ScreenManager(new ConsoleOutput());
|
||||
$output = new ConsoleOutput();
|
||||
$output->screen = $screenManager;
|
||||
|
||||
$state = new TuiState();
|
||||
$history = new CommandHistory();
|
||||
$inputHandler = new TuiInputHandler($mockExecutor);
|
||||
$renderer = new TuiRenderer($output);
|
||||
$groupRegistry = new CommandGroupRegistry($discoveryRegistry);
|
||||
|
||||
echo "✓ Components created successfully\n\n";
|
||||
|
||||
// Test CommandGroupRegistry::getOrganizedCommands() returns numeric array
|
||||
echo "Testing CommandGroupRegistry::getOrganizedCommands():\n";
|
||||
$categories = $groupRegistry->getOrganizedCommands();
|
||||
|
||||
echo " Categories type: " . (is_array($categories) ? "array" : gettype($categories)) . "\n";
|
||||
echo " Categories count: " . count($categories) . "\n";
|
||||
echo " Keys are numeric: " . (array_is_list($categories) ? "YES" : "NO") . "\n";
|
||||
|
||||
if (!empty($categories)) {
|
||||
echo " First category structure:\n";
|
||||
$firstCategory = $categories[0];
|
||||
echo " - name: '{$firstCategory['name']}'\n";
|
||||
echo " - description: '{$firstCategory['description']}'\n";
|
||||
echo " - icon: '{$firstCategory['icon']}'\n";
|
||||
echo " - commands count: " . count($firstCategory['commands']) . "\n";
|
||||
}
|
||||
echo "\n";
|
||||
|
||||
// Setup TUI state with the organized categories
|
||||
$state->setCategories($categories);
|
||||
$state->setCurrentView(TuiView::CATEGORIES);
|
||||
$state->setRunning(true);
|
||||
|
||||
echo "✓ TUI State initialized:\n";
|
||||
echo " Categories loaded: " . count($categories) . "\n";
|
||||
echo " Current view: " . $state->getCurrentView()->name . "\n";
|
||||
echo " Selected category: " . $state->getSelectedCategory() . "\n";
|
||||
|
||||
$currentCategory = $state->getCurrentCategory();
|
||||
if ($currentCategory) {
|
||||
echo " Current category name: '{$currentCategory['name']}'\n";
|
||||
} else {
|
||||
echo " ❌ Current category: NULL\n";
|
||||
}
|
||||
echo "\n";
|
||||
|
||||
// Test the complete navigation workflow
|
||||
echo "🔍 Testing Complete Navigation Workflow:\n\n";
|
||||
|
||||
$maxCategoryIndex = count($categories) - 1;
|
||||
|
||||
if ($maxCategoryIndex >= 0) {
|
||||
// Test navigation through all categories
|
||||
echo "Navigation Test - Moving through all categories:\n";
|
||||
|
||||
// Start at first category
|
||||
$state->setSelectedCategory(0);
|
||||
$startCategory = $state->getCurrentCategory();
|
||||
echo " Start: Category 0 => '{$startCategory['name']}'\n";
|
||||
|
||||
// Navigate down to last category
|
||||
for ($i = 0; $i < $maxCategoryIndex; $i++) {
|
||||
$inputHandler->handleInput(TuiKeyCode::ARROW_DOWN->value, $state, $history);
|
||||
$category = $state->getCurrentCategory();
|
||||
echo " Arrow DOWN: Category {$state->getSelectedCategory()} => '{$category['name']}'\n";
|
||||
}
|
||||
|
||||
// Try to go past last category (should stay at last)
|
||||
$beforeIndex = $state->getSelectedCategory();
|
||||
$inputHandler->handleInput(TuiKeyCode::ARROW_DOWN->value, $state, $history);
|
||||
$afterIndex = $state->getSelectedCategory();
|
||||
echo " Boundary test (down): {$beforeIndex} => {$afterIndex} " . ($beforeIndex === $afterIndex ? "✓ PROTECTED" : "❌ FAILED") . "\n";
|
||||
|
||||
// Navigate back up
|
||||
echo " Navigating back up...\n";
|
||||
for ($i = $maxCategoryIndex; $i > 0; $i--) {
|
||||
$inputHandler->handleInput(TuiKeyCode::ARROW_UP->value, $state, $history);
|
||||
$category = $state->getCurrentCategory();
|
||||
echo " Arrow UP: Category {$state->getSelectedCategory()} => '{$category['name']}'\n";
|
||||
}
|
||||
|
||||
// Try to go past first category (should stay at first)
|
||||
$beforeIndex = $state->getSelectedCategory();
|
||||
$inputHandler->handleInput(TuiKeyCode::ARROW_UP->value, $state, $history);
|
||||
$afterIndex = $state->getSelectedCategory();
|
||||
echo " Boundary test (up): {$beforeIndex} => {$afterIndex} " . ($beforeIndex === $afterIndex ? "✓ PROTECTED" : "❌ FAILED") . "\n";
|
||||
|
||||
} else {
|
||||
echo " No categories available for navigation test\n";
|
||||
}
|
||||
|
||||
echo "\n";
|
||||
|
||||
// Test rendering
|
||||
echo "Testing TUI Rendering:\n";
|
||||
echo "======================\n";
|
||||
$renderer->render($state, $history);
|
||||
echo "\n";
|
||||
|
||||
echo "✅ FINAL TUI TEST PASSED\n";
|
||||
echo "🎯 Summary:\n";
|
||||
echo " ✓ CommandGroupRegistry returns numeric array\n";
|
||||
echo " ✓ TuiState navigation works correctly\n";
|
||||
echo " ✓ Arrow key input handling functional\n";
|
||||
echo " ✓ Boundary protection working\n";
|
||||
echo " ✓ TUI rendering operational\n";
|
||||
echo " ✓ Welcome screen integration ready\n";
|
||||
echo "\n";
|
||||
echo "🚀 The TUI is now fully functional and ready for use in a real terminal!\n";
|
||||
|
||||
} catch (\Throwable $e) {
|
||||
echo "\n❌ FINAL TUI TEST FAILED:\n";
|
||||
echo "Error: " . $e->getMessage() . "\n";
|
||||
echo "File: " . $e->getFile() . ":" . $e->getLine() . "\n";
|
||||
echo "\nStack trace:\n" . $e->getTraceAsString() . "\n";
|
||||
}
|
||||
102
scripts/test/test_framework_agents.php
Normal file
102
scripts/test/test_framework_agents.php
Normal file
@@ -0,0 +1,102 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
require_once __DIR__ . '/vendor/autoload.php';
|
||||
|
||||
use App\Framework\Core\AppBootstrapper;
|
||||
use App\Framework\Mcp\Tools\FrameworkAgents;
|
||||
use App\Framework\Performance\EnhancedPerformanceCollector;
|
||||
use App\Framework\DateTime\SystemClock;
|
||||
use App\Framework\DateTime\SystemHighResolutionClock;
|
||||
use App\Framework\Performance\MemoryMonitor;
|
||||
|
||||
try {
|
||||
// Bootstrap the application (similar to console.php)
|
||||
$clock = new SystemClock();
|
||||
$highResClock = new SystemHighResolutionClock();
|
||||
$memoryMonitor = new MemoryMonitor();
|
||||
$collector = new EnhancedPerformanceCollector($clock, $highResClock, $memoryMonitor, enabled: false);
|
||||
$bootstrapper = new AppBootstrapper(__DIR__, $collector, $memoryMonitor);
|
||||
|
||||
$consoleApp = $bootstrapper->bootstrapConsole();
|
||||
// Extract container from the ConsoleApplication via reflection
|
||||
$reflection = new \ReflectionClass($consoleApp);
|
||||
$containerProperty = $reflection->getProperty('container');
|
||||
$containerProperty->setAccessible(true);
|
||||
$container = $containerProperty->getValue($consoleApp);
|
||||
|
||||
// Get the FrameworkAgents instance
|
||||
$frameworkAgents = $container->get(FrameworkAgents::class);
|
||||
|
||||
echo "=== Testing Framework Agents ===\n\n";
|
||||
|
||||
// Test Framework Core Agent
|
||||
echo "🔧 Testing Framework Core Agent:\n";
|
||||
$coreResult = $frameworkAgents->frameworkCoreAgent(
|
||||
'Analyze current framework architecture and patterns',
|
||||
'architecture'
|
||||
);
|
||||
|
||||
echo "✅ Framework Core Agent Response:\n";
|
||||
echo "- Agent: " . $coreResult['agent_identity'] . "\n";
|
||||
echo "- Principles: " . count($coreResult['core_principles']) . " core principles\n";
|
||||
echo "- Framework Health: " . $coreResult['framework_health']['status'] . "\n";
|
||||
echo "- Recommendations: " . count($coreResult['recommendations']) . " recommendations\n";
|
||||
echo "\n";
|
||||
|
||||
// Test MCP Specialist Agent
|
||||
echo "🤖 Testing MCP Specialist Agent:\n";
|
||||
$mcpResult = $frameworkAgents->mcpSpecialistAgent(
|
||||
'Analyze MCP integration capabilities',
|
||||
'tools'
|
||||
);
|
||||
|
||||
echo "✅ MCP Specialist Agent Response:\n";
|
||||
echo "- Agent: " . $mcpResult['agent_identity'] . "\n";
|
||||
echo "- Principles: " . count($mcpResult['core_principles']) . " core principles\n";
|
||||
echo "- Available Tools: " . count($mcpResult['mcp_framework_integration']['available_tools']) . " MCP tools\n";
|
||||
echo "- Routes: " . $mcpResult['mcp_framework_integration']['routes_analysis']['total_routes'] . " total routes\n";
|
||||
echo "\n";
|
||||
|
||||
// Test Value Object Agent
|
||||
echo "💎 Testing Value Object Agent:\n";
|
||||
$voResult = $frameworkAgents->valueObjectAgent(
|
||||
'Analyze current value object usage and suggest improvements',
|
||||
'core'
|
||||
);
|
||||
|
||||
echo "✅ Value Object Agent Response:\n";
|
||||
echo "- Agent: " . $voResult['agent_identity'] . "\n";
|
||||
echo "- Principles: " . count($voResult['core_principles']) . " core principles\n";
|
||||
echo "- VO Categories: " . count($voResult['value_object_categories']) . " categories\n";
|
||||
echo "- Recommendations: " . count($voResult['recommendations']) . " recommendations\n";
|
||||
echo "\n";
|
||||
|
||||
// Test Discovery Expert Agent
|
||||
echo "🔍 Testing Discovery Expert Agent:\n";
|
||||
$discoveryResult = $frameworkAgents->discoveryExpertAgent(
|
||||
'Analyze attribute discovery system performance',
|
||||
'routing'
|
||||
);
|
||||
|
||||
echo "✅ Discovery Expert Agent Response:\n";
|
||||
echo "- Agent: " . $discoveryResult['agent_identity'] . "\n";
|
||||
echo "- Principles: " . count($discoveryResult['core_principles']) . " core principles\n";
|
||||
echo "- Attribute Systems: " . count($discoveryResult['attribute_expertise']) . " expertise areas\n";
|
||||
echo "- Components: " . count($discoveryResult['attribute_components']) . " components analyzed\n";
|
||||
echo "\n";
|
||||
|
||||
echo "🎉 All Framework Agents are working successfully!\n";
|
||||
echo "\nThese agents are now available as MCP tools:\n";
|
||||
echo "- framework_core_agent\n";
|
||||
echo "- mcp_specialist_agent\n";
|
||||
echo "- value_object_agent\n";
|
||||
echo "- discovery_expert_agent\n";
|
||||
|
||||
} catch (\Throwable $e) {
|
||||
echo "❌ Error testing framework agents:\n";
|
||||
echo "Error: " . $e->getMessage() . "\n";
|
||||
echo "File: " . $e->getFile() . ":" . $e->getLine() . "\n";
|
||||
exit(1);
|
||||
}
|
||||
159
scripts/test/test_interactive_input.php
Normal file
159
scripts/test/test_interactive_input.php
Normal file
@@ -0,0 +1,159 @@
|
||||
<?php
|
||||
|
||||
require_once __DIR__ . '/vendor/autoload.php';
|
||||
|
||||
echo "Interactive Input Test\n";
|
||||
echo "=====================\n\n";
|
||||
|
||||
echo "This test requires a real TTY terminal.\n";
|
||||
echo "Run with: docker exec -it php php test_interactive_input.php\n\n";
|
||||
|
||||
// Check if we have a TTY
|
||||
if (!posix_isatty(STDIN)) {
|
||||
echo "❌ ERROR: This script requires a TTY terminal.\n";
|
||||
echo "Current environment is not a TTY.\n";
|
||||
echo "Please run with: docker exec -it php php test_interactive_input.php\n";
|
||||
exit(1);
|
||||
}
|
||||
|
||||
echo "✓ TTY detected. Terminal is interactive.\n\n";
|
||||
|
||||
// Check stty availability
|
||||
if (!function_exists('shell_exec') || shell_exec('which stty') === null) {
|
||||
echo "❌ ERROR: stty command not available.\n";
|
||||
echo "Raw mode setup will not work.\n";
|
||||
exit(1);
|
||||
}
|
||||
|
||||
echo "✓ stty command available.\n\n";
|
||||
|
||||
echo "Setting up raw mode...\n";
|
||||
|
||||
// Save current terminal settings
|
||||
$originalSettings = trim(shell_exec('stty -g'));
|
||||
echo "✓ Original terminal settings saved: $originalSettings\n";
|
||||
|
||||
// Set raw mode
|
||||
shell_exec('stty -icanon -echo');
|
||||
echo "✓ Raw mode enabled.\n\n";
|
||||
|
||||
echo "=== ARROW KEY TEST ===\n";
|
||||
echo "Press arrow keys to test. Press 'q' to quit.\n";
|
||||
echo "You should see the exact key codes being detected.\n\n";
|
||||
|
||||
function readKeySequence(): string {
|
||||
$key = fgetc(STDIN);
|
||||
if ($key === false) {
|
||||
return '';
|
||||
}
|
||||
|
||||
// Handle escape sequences
|
||||
if ($key === "\033") {
|
||||
$sequence = $key;
|
||||
|
||||
// Read next character with timeout
|
||||
stream_set_blocking(STDIN, false);
|
||||
$next = fgetc(STDIN);
|
||||
stream_set_blocking(STDIN, true);
|
||||
|
||||
if ($next === false) {
|
||||
return $key; // Just escape
|
||||
}
|
||||
$sequence .= $next;
|
||||
|
||||
// If it's a bracket, read more
|
||||
if ($next === '[') {
|
||||
stream_set_blocking(STDIN, false);
|
||||
$third = fgetc(STDIN);
|
||||
stream_set_blocking(STDIN, true);
|
||||
|
||||
if ($third !== false) {
|
||||
$sequence .= $third;
|
||||
|
||||
// Some sequences have more characters
|
||||
if (in_array($third, ['5', '6', '3', '1', '2', '4'])) {
|
||||
stream_set_blocking(STDIN, false);
|
||||
$fourth = fgetc(STDIN);
|
||||
stream_set_blocking(STDIN, true);
|
||||
|
||||
if ($fourth !== false) {
|
||||
$sequence .= $fourth;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $sequence;
|
||||
}
|
||||
|
||||
return $key;
|
||||
}
|
||||
|
||||
try {
|
||||
$testCount = 0;
|
||||
while (true) {
|
||||
$key = readKeySequence();
|
||||
|
||||
if ($key === 'q' || $key === 'Q') {
|
||||
echo "\nQuitting...\n";
|
||||
break;
|
||||
}
|
||||
|
||||
if ($key !== '') {
|
||||
$testCount++;
|
||||
$hexKey = bin2hex($key);
|
||||
$asciiKey = addcslashes($key, "\0..\37\177..\377");
|
||||
|
||||
echo "Test $testCount:\n";
|
||||
echo " Raw: '$asciiKey'\n";
|
||||
echo " Hex: $hexKey\n";
|
||||
echo " Bytes: " . strlen($key) . "\n";
|
||||
|
||||
switch ($key) {
|
||||
case "\033[A":
|
||||
echo " ✓ ARROW UP detected correctly!\n";
|
||||
break;
|
||||
case "\033[B":
|
||||
echo " ✓ ARROW DOWN detected correctly!\n";
|
||||
break;
|
||||
case "\033[C":
|
||||
echo " ✓ ARROW RIGHT detected correctly!\n";
|
||||
break;
|
||||
case "\033[D":
|
||||
echo " ✓ ARROW LEFT detected correctly!\n";
|
||||
break;
|
||||
case "\n":
|
||||
case "\r":
|
||||
echo " ✓ ENTER detected!\n";
|
||||
break;
|
||||
case " ":
|
||||
echo " ✓ SPACE detected!\n";
|
||||
break;
|
||||
case "\033":
|
||||
echo " ✓ ESC detected!\n";
|
||||
break;
|
||||
case "\177":
|
||||
case "\x08":
|
||||
echo " ✓ BACKSPACE detected!\n";
|
||||
break;
|
||||
default:
|
||||
if (ctype_print($key)) {
|
||||
echo " → Regular key: '$key'\n";
|
||||
} else {
|
||||
echo " → Special key (unknown)\n";
|
||||
}
|
||||
break;
|
||||
}
|
||||
echo "\n";
|
||||
}
|
||||
|
||||
// Add small delay to prevent CPU spinning
|
||||
usleep(50000); // 50ms
|
||||
}
|
||||
} finally {
|
||||
// Always restore terminal settings
|
||||
echo "Restoring terminal settings...\n";
|
||||
shell_exec("stty $originalSettings");
|
||||
echo "✓ Terminal restored.\n";
|
||||
echo "\nTest completed. Total inputs processed: $testCount\n";
|
||||
}
|
||||
72
scripts/test/test_modern_syntax_highlighter.php
Normal file
72
scripts/test/test_modern_syntax_highlighter.php
Normal file
@@ -0,0 +1,72 @@
|
||||
<?php
|
||||
|
||||
require_once __DIR__ . '/vendor/autoload.php';
|
||||
|
||||
use App\Framework\SyntaxHighlighter\SyntaxHighlighter;
|
||||
|
||||
// Test code to highlight
|
||||
$phpCode = <<<'PHP'
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Example;
|
||||
|
||||
use App\Framework\Http\JsonResult;
|
||||
|
||||
#[Route(path: '/api/users', method: 'GET')]
|
||||
final readonly class UserController
|
||||
{
|
||||
/**
|
||||
* Get all users
|
||||
*
|
||||
* @param UserRepository $repository
|
||||
* @return JsonResult<array<User>>
|
||||
*/
|
||||
public function getUsers(UserRepository $repository): JsonResult
|
||||
{
|
||||
$users = $repository->findAll();
|
||||
$count = count($users);
|
||||
|
||||
return new JsonResult([
|
||||
'users' => $users,
|
||||
'count' => $count,
|
||||
'message' => "Found {$count} users"
|
||||
]);
|
||||
}
|
||||
}
|
||||
PHP;
|
||||
|
||||
$highlighter = new SyntaxHighlighter();
|
||||
|
||||
// Test HTML output
|
||||
echo "=== HTML Output ===\n";
|
||||
$html = $highlighter->highlightWithCss($phpCode, [
|
||||
'theme' => 'dark',
|
||||
'lineNumbers' => true
|
||||
]);
|
||||
echo $html . "\n\n";
|
||||
|
||||
// Test console output
|
||||
echo "=== Console Output ===\n";
|
||||
$console = $highlighter->highlight($phpCode, 'console', [
|
||||
'colorize' => true,
|
||||
'lineNumbers' => true
|
||||
]);
|
||||
echo $console . "\n";
|
||||
|
||||
// Test tokenization
|
||||
echo "=== Tokenization Test ===\n";
|
||||
$tokens = $highlighter->tokenize($phpCode);
|
||||
echo "Total tokens: " . $tokens->count() . "\n";
|
||||
|
||||
// Show first few tokens
|
||||
$first5 = $tokens->slice(0, 5);
|
||||
foreach ($first5 as $token) {
|
||||
echo sprintf(
|
||||
"Line %d: %s = '%s'\n",
|
||||
$token->line,
|
||||
$token->type->value,
|
||||
trim($token->value)
|
||||
);
|
||||
}
|
||||
207
scripts/test/test_phpstorm_terminal.php
Normal file
207
scripts/test/test_phpstorm_terminal.php
Normal file
@@ -0,0 +1,207 @@
|
||||
<?php
|
||||
|
||||
require_once __DIR__ . '/vendor/autoload.php';
|
||||
|
||||
echo "PHPStorm Terminal Compatibility Test\n";
|
||||
echo "====================================\n\n";
|
||||
|
||||
echo "Environment Analysis:\n";
|
||||
echo "- TERM: " . (getenv('TERM') ?: 'not set') . "\n";
|
||||
echo "- COLORTERM: " . (getenv('COLORTERM') ?: 'not set') . "\n";
|
||||
echo "- TERMINAL_EMULATOR: " . (getenv('TERMINAL_EMULATOR') ?: 'not set') . "\n";
|
||||
echo "- INSIDE_EMACS: " . (getenv('INSIDE_EMACS') ?: 'not set') . "\n";
|
||||
echo "- IDE_PROJECT_ROOTS: " . (getenv('IDE_PROJECT_ROOTS') ?: 'not set') . "\n";
|
||||
|
||||
// Check if this looks like PHPStorm/IntelliJ
|
||||
$isPhpStorm = getenv('TERMINAL_EMULATOR') === 'JetBrains-JediTerm' ||
|
||||
!empty(getenv('IDE_PROJECT_ROOTS')) ||
|
||||
strpos(getenv('TERM') ?: '', 'jetbrains') !== false;
|
||||
|
||||
echo "- Detected PHPStorm: " . ($isPhpStorm ? 'YES' : 'NO') . "\n";
|
||||
|
||||
// TTY check
|
||||
$hasTTY = posix_isatty(STDIN);
|
||||
echo "- Has TTY: " . ($hasTTY ? 'YES' : 'NO') . "\n";
|
||||
|
||||
// STDIN properties
|
||||
echo "- STDIN is resource: " . (is_resource(STDIN) ? 'YES' : 'NO') . "\n";
|
||||
echo "- STDIN type: " . get_resource_type(STDIN) . "\n";
|
||||
|
||||
// stty availability
|
||||
$hasStty = function_exists('shell_exec') && !empty(shell_exec('which stty 2>/dev/null'));
|
||||
echo "- stty available: " . ($hasStty ? 'YES' : 'NO') . "\n";
|
||||
|
||||
if ($hasStty) {
|
||||
$sttySettings = trim(shell_exec('stty -a 2>/dev/null') ?: '');
|
||||
echo "- Current stty settings: " . (!empty($sttySettings) ? 'available' : 'unavailable') . "\n";
|
||||
}
|
||||
|
||||
echo "\n";
|
||||
|
||||
if (!$hasTTY) {
|
||||
echo "❌ No TTY available. TUI will not work in this environment.\n";
|
||||
echo "Try running in a real terminal instead of PHPStorm's integrated terminal.\n";
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (!$hasStty) {
|
||||
echo "❌ stty command not available. Raw mode cannot be set.\n";
|
||||
exit(1);
|
||||
}
|
||||
|
||||
echo "Setting up PHPStorm-compatible input reading...\n\n";
|
||||
|
||||
// Save original settings
|
||||
$originalSettings = trim(shell_exec('stty -g') ?: '');
|
||||
if (empty($originalSettings)) {
|
||||
echo "❌ Could not save terminal settings\n";
|
||||
exit(1);
|
||||
}
|
||||
|
||||
echo "✓ Original settings saved\n";
|
||||
|
||||
// PHPStorm-specific terminal setup
|
||||
echo "Setting up terminal for PHPStorm...\n";
|
||||
|
||||
// Try different approaches for PHPStorm
|
||||
if ($isPhpStorm) {
|
||||
echo "Using PHPStorm-optimized settings...\n";
|
||||
// PHPStorm sometimes needs different settings
|
||||
shell_exec('stty raw -echo min 1 time 0 2>/dev/null');
|
||||
} else {
|
||||
echo "Using standard settings...\n";
|
||||
shell_exec('stty -icanon -echo 2>/dev/null');
|
||||
}
|
||||
|
||||
echo "✓ Raw mode set\n\n";
|
||||
|
||||
echo "=== INPUT TEST ===\n";
|
||||
echo "Press keys to test input. Type 'quit' to exit.\n";
|
||||
echo "Pay attention to arrow key behavior.\n\n";
|
||||
|
||||
function readInput(): string {
|
||||
$input = '';
|
||||
|
||||
while (true) {
|
||||
$char = fgetc(STDIN);
|
||||
if ($char === false) {
|
||||
break;
|
||||
}
|
||||
|
||||
$input .= $char;
|
||||
|
||||
// Check for complete escape sequence
|
||||
if ($char === "\033") {
|
||||
// Read potential escape sequence
|
||||
$next = fgetc(STDIN);
|
||||
if ($next !== false) {
|
||||
$input .= $next;
|
||||
if ($next === '[') {
|
||||
$third = fgetc(STDIN);
|
||||
if ($third !== false) {
|
||||
$input .= $third;
|
||||
// Some sequences have a 4th character
|
||||
if (in_array($third, ['5', '6', '3', '1', '2', '4'])) {
|
||||
$fourth = fgetc(STDIN);
|
||||
if ($fourth !== false) {
|
||||
$input .= $fourth;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// For regular characters, break immediately
|
||||
if ($char !== "\033") {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return $input;
|
||||
}
|
||||
|
||||
try {
|
||||
$buffer = '';
|
||||
$testCount = 0;
|
||||
|
||||
while (true) {
|
||||
$key = readInput();
|
||||
|
||||
if ($key === '') {
|
||||
continue;
|
||||
}
|
||||
|
||||
$testCount++;
|
||||
$buffer .= $key;
|
||||
|
||||
echo "Input $testCount:\n";
|
||||
echo " Raw: '" . addcslashes($key, "\0..\37\177..\377") . "'\n";
|
||||
echo " Hex: " . bin2hex($key) . "\n";
|
||||
echo " Length: " . strlen($key) . "\n";
|
||||
|
||||
// Check for complete words
|
||||
if (str_contains($buffer, 'quit')) {
|
||||
echo "Quit command detected!\n";
|
||||
break;
|
||||
}
|
||||
|
||||
// Analyze the key
|
||||
switch ($key) {
|
||||
case "\033[A":
|
||||
echo " ✓ ARROW UP - Perfect!\n";
|
||||
break;
|
||||
case "\033[B":
|
||||
echo " ✓ ARROW DOWN - Perfect!\n";
|
||||
break;
|
||||
case "\033[C":
|
||||
echo " ✓ ARROW RIGHT - Perfect!\n";
|
||||
break;
|
||||
case "\033[D":
|
||||
echo " ✓ ARROW LEFT - Perfect!\n";
|
||||
break;
|
||||
case "\n":
|
||||
case "\r":
|
||||
echo " ✓ ENTER\n";
|
||||
$buffer = ''; // Reset buffer on enter
|
||||
break;
|
||||
case "\033":
|
||||
echo " → ESC (incomplete sequence?)\n";
|
||||
break;
|
||||
default:
|
||||
if (ctype_print($key)) {
|
||||
echo " → Character: '$key'\n";
|
||||
} else {
|
||||
echo " → Special/Unknown\n";
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
echo "\n";
|
||||
|
||||
// Limit output to prevent spam
|
||||
if ($testCount > 20) {
|
||||
echo "Test limit reached. Type 'quit' to exit.\n";
|
||||
}
|
||||
}
|
||||
|
||||
} finally {
|
||||
echo "\nRestoring terminal...\n";
|
||||
shell_exec("stty $originalSettings 2>/dev/null");
|
||||
echo "✓ Terminal restored\n";
|
||||
echo "Total inputs processed: $testCount\n";
|
||||
}
|
||||
|
||||
echo "\n=== RECOMMENDATIONS ===\n";
|
||||
|
||||
if ($isPhpStorm) {
|
||||
echo "PHPStorm Terminal detected. Consider:\n";
|
||||
echo "1. Use external terminal (Windows Terminal, iTerm2, etc.)\n";
|
||||
echo "2. Or use PHPStorm's 'Terminal' tool window with different shell\n";
|
||||
echo "3. Some TUI features may be limited in integrated terminals\n";
|
||||
} else {
|
||||
echo "Standard terminal detected. TUI should work normally.\n";
|
||||
}
|
||||
|
||||
echo "\nIf arrow keys didn't work properly, the TUI navigation will also fail.\n";
|
||||
38
scripts/test/test_presave_container.php
Normal file
38
scripts/test/test_presave_container.php
Normal file
@@ -0,0 +1,38 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
require_once __DIR__ . '/vendor/autoload.php';
|
||||
|
||||
use App\Framework\Core\AppBootstrapper;
|
||||
use App\Framework\Performance\EnhancedPerformanceCollector;
|
||||
use App\Framework\DateTime\SystemClock;
|
||||
use App\Framework\DateTime\SystemHighResolutionClock;
|
||||
use App\Framework\Performance\MemoryMonitor;
|
||||
use App\Application\Campaign\PreSaveCampaign;
|
||||
|
||||
try {
|
||||
$basePath = __DIR__;
|
||||
$clock = new SystemClock();
|
||||
$highResClock = new SystemHighResolutionClock();
|
||||
$memoryMonitor = new MemoryMonitor();
|
||||
$collector = new EnhancedPerformanceCollector($clock, $highResClock, $memoryMonitor, enabled: true);
|
||||
|
||||
$bootstrapper = new AppBootstrapper($basePath, $collector, $memoryMonitor);
|
||||
$app = $bootstrapper->bootstrapWeb();
|
||||
|
||||
$container = $app->getContainer();
|
||||
|
||||
echo "✅ Container bootstrapped successfully\n";
|
||||
|
||||
$preSave = $container->get(PreSaveCampaign::class);
|
||||
|
||||
echo "✅ PreSaveCampaign successfully resolved from container\n";
|
||||
echo "PreSaveCampaign class: " . get_class($preSave) . "\n";
|
||||
|
||||
} catch (\Exception $e) {
|
||||
echo "❌ Error: " . $e->getMessage() . "\n";
|
||||
echo "File: " . $e->getFile() . ":" . $e->getLine() . "\n";
|
||||
echo "\nStack trace:\n";
|
||||
echo $e->getTraceAsString() . "\n";
|
||||
}
|
||||
170
scripts/test/test_real_navigation.php
Normal file
170
scripts/test/test_real_navigation.php
Normal file
@@ -0,0 +1,170 @@
|
||||
<?php
|
||||
|
||||
require_once __DIR__ . '/vendor/autoload.php';
|
||||
|
||||
// Test with real category structure like CommandGroupRegistry
|
||||
use App\Framework\Console\Components\TuiState;
|
||||
use App\Framework\Console\Components\TuiInputHandler;
|
||||
use App\Framework\Console\Components\TuiCommandExecutor;
|
||||
use App\Framework\Console\CommandHistory;
|
||||
use App\Framework\Console\TuiView;
|
||||
use App\Framework\Console\TuiKeyCode;
|
||||
|
||||
echo "Testing Real Navigation with CommandGroupRegistry Structure...\n";
|
||||
echo "============================================================\n\n";
|
||||
|
||||
try {
|
||||
// Create mock executor
|
||||
$mockExecutor = new class implements \App\Framework\Console\Components\TuiCommandExecutor {
|
||||
public function executeSelectedCommand(object $command): void {
|
||||
echo "Mock: Execute command\n";
|
||||
}
|
||||
public function executeCommand(string $commandName): void {
|
||||
echo "Mock: Execute command: $commandName\n";
|
||||
}
|
||||
public function validateSelectedCommand(object $command): void {
|
||||
echo "Mock: Validate command\n";
|
||||
}
|
||||
public function validateCommand(string $commandName): void {
|
||||
echo "Mock: Validate command: $commandName\n";
|
||||
}
|
||||
public function showSelectedCommandHelp(object $command): void {
|
||||
echo "Mock: Show help\n";
|
||||
}
|
||||
public function showCommandHelp(string $commandName): void {
|
||||
echo "Mock: Show help: $commandName\n";
|
||||
}
|
||||
public function showAllCommandsHelp(): void {
|
||||
echo "Mock: Show all commands help\n";
|
||||
}
|
||||
public function startInteractiveForm(object $command, \App\Framework\Console\Components\TuiState $state): void {
|
||||
echo "Mock: Start form\n";
|
||||
}
|
||||
public function findCommandObject(string $commandName): ?object {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
$state = new TuiState();
|
||||
$history = new CommandHistory();
|
||||
$inputHandler = new TuiInputHandler($mockExecutor);
|
||||
|
||||
// Simulate the EXACT structure from CommandGroupRegistry::getOrganizedCommands()
|
||||
// After uasort by priority and array_values conversion
|
||||
$organizedCategories = [
|
||||
'Testing' => [
|
||||
'name' => 'Testing',
|
||||
'description' => '',
|
||||
'icon' => '🧪',
|
||||
'priority' => 0,
|
||||
'commands' => []
|
||||
],
|
||||
'Demo' => [
|
||||
'name' => 'Demo',
|
||||
'description' => '',
|
||||
'icon' => '🎮',
|
||||
'priority' => 0,
|
||||
'commands' => []
|
||||
],
|
||||
'Generator' => [
|
||||
'name' => 'Generator',
|
||||
'description' => '',
|
||||
'icon' => '⚙️',
|
||||
'priority' => 0,
|
||||
'commands' => []
|
||||
],
|
||||
'General' => [
|
||||
'name' => 'General',
|
||||
'description' => '',
|
||||
'icon' => '📂',
|
||||
'priority' => 0,
|
||||
'commands' => []
|
||||
]
|
||||
];
|
||||
|
||||
// Sort by priority (all have priority 0 in this case, so order by keys)
|
||||
uasort($organizedCategories, fn($a, $b) => $b['priority'] <=> $a['priority']);
|
||||
|
||||
echo "📊 Before array_values() conversion (associative array):\n";
|
||||
foreach ($organizedCategories as $key => $category) {
|
||||
echo " Key: '$key' => Category: '{$category['name']}'\n";
|
||||
}
|
||||
echo "\n";
|
||||
|
||||
// Convert to numeric array like our fix
|
||||
$numericCategories = array_values($organizedCategories);
|
||||
|
||||
echo "📊 After array_values() conversion (numeric array):\n";
|
||||
foreach ($numericCategories as $index => $category) {
|
||||
echo " Index: $index => Category: '{$category['name']}'\n";
|
||||
}
|
||||
echo "\n";
|
||||
|
||||
// Test with the numeric array structure
|
||||
$state->setCategories($numericCategories);
|
||||
$state->setCurrentView(TuiView::CATEGORIES);
|
||||
$state->setRunning(true);
|
||||
|
||||
echo "✓ Setup Complete:\n";
|
||||
echo " Categories Count: " . count($numericCategories) . "\n";
|
||||
echo " Current View: " . $state->getCurrentView()->name . "\n";
|
||||
echo " Selected Category Index: " . $state->getSelectedCategory() . "\n";
|
||||
|
||||
$currentCategory = $state->getCurrentCategory();
|
||||
if ($currentCategory) {
|
||||
echo " Current Category Name: '{$currentCategory['name']}'\n";
|
||||
} else {
|
||||
echo " ❌ Current Category: NULL (This would cause navigation issues!)\n";
|
||||
}
|
||||
echo "\n";
|
||||
|
||||
// Test navigation with the real structure
|
||||
echo "🔍 Testing Navigation with Real Structure:\n\n";
|
||||
|
||||
// Test 1: Arrow Down
|
||||
echo "Test 1: Arrow DOWN\n";
|
||||
$beforeCategory = $state->getCurrentCategory();
|
||||
$beforeIndex = $state->getSelectedCategory();
|
||||
echo " Before: Index $beforeIndex => '{$beforeCategory['name']}'\n";
|
||||
|
||||
$inputHandler->handleInput(TuiKeyCode::ARROW_DOWN->value, $state, $history);
|
||||
|
||||
$afterCategory = $state->getCurrentCategory();
|
||||
$afterIndex = $state->getSelectedCategory();
|
||||
echo " After: Index $afterIndex => '{$afterCategory['name']}'\n";
|
||||
echo " ✓ Navigation worked: " . ($beforeIndex !== $afterIndex ? "YES" : "NO") . "\n\n";
|
||||
|
||||
// Test 2: Arrow Down again
|
||||
echo "Test 2: Arrow DOWN again\n";
|
||||
$beforeCategory = $state->getCurrentCategory();
|
||||
$beforeIndex = $state->getSelectedCategory();
|
||||
echo " Before: Index $beforeIndex => '{$beforeCategory['name']}'\n";
|
||||
|
||||
$inputHandler->handleInput(TuiKeyCode::ARROW_DOWN->value, $state, $history);
|
||||
|
||||
$afterCategory = $state->getCurrentCategory();
|
||||
$afterIndex = $state->getSelectedCategory();
|
||||
echo " After: Index $afterIndex => '{$afterCategory['name']}'\n";
|
||||
echo " ✓ Navigation worked: " . ($beforeIndex !== $afterIndex ? "YES" : "NO") . "\n\n";
|
||||
|
||||
// Test 3: Arrow Up
|
||||
echo "Test 3: Arrow UP\n";
|
||||
$beforeCategory = $state->getCurrentCategory();
|
||||
$beforeIndex = $state->getSelectedCategory();
|
||||
echo " Before: Index $beforeIndex => '{$beforeCategory['name']}'\n";
|
||||
|
||||
$inputHandler->handleInput(TuiKeyCode::ARROW_UP->value, $state, $history);
|
||||
|
||||
$afterCategory = $state->getCurrentCategory();
|
||||
$afterIndex = $state->getSelectedCategory();
|
||||
echo " After: Index $afterIndex => '{$afterCategory['name']}'\n";
|
||||
echo " ✓ Navigation worked: " . ($beforeIndex !== $afterIndex ? "YES" : "NO") . "\n\n";
|
||||
|
||||
echo "✅ Real Navigation Test COMPLETED\n";
|
||||
|
||||
} catch (\Throwable $e) {
|
||||
echo "\n❌ Real Navigation Test FAILED:\n";
|
||||
echo "Error: " . $e->getMessage() . "\n";
|
||||
echo "File: " . $e->getFile() . ":" . $e->getLine() . "\n";
|
||||
echo "\nStack trace:\n" . $e->getTraceAsString() . "\n";
|
||||
}
|
||||
69
scripts/test/test_request_container.php
Normal file
69
scripts/test/test_request_container.php
Normal file
@@ -0,0 +1,69 @@
|
||||
<?php
|
||||
|
||||
require __DIR__ . '/vendor/autoload.php';
|
||||
|
||||
use App\Framework\Performance\EnhancedPerformanceCollector;
|
||||
use App\Framework\DateTime\SystemClock;
|
||||
use App\Framework\DateTime\SystemHighResolutionClock;
|
||||
use App\Framework\Core\AppBootstrapper;
|
||||
use App\Framework\Performance\MemoryMonitor;
|
||||
|
||||
echo "=== Request Container Test ===\n";
|
||||
|
||||
try {
|
||||
$basePath = __DIR__;
|
||||
$clock = new SystemClock();
|
||||
$highResClock = new SystemHighResolutionClock();
|
||||
$memoryMonitor = new MemoryMonitor();
|
||||
$collector = new EnhancedPerformanceCollector($clock, $highResClock, $memoryMonitor, enabled: true);
|
||||
$bootstrapper = new AppBootstrapper($basePath, $collector, $memoryMonitor);
|
||||
|
||||
echo "1. Creating worker container...\n";
|
||||
$container = $bootstrapper->bootstrapWorker();
|
||||
|
||||
echo "2. Container created successfully\n";
|
||||
echo "3. Testing Request resolution...\n";
|
||||
|
||||
// Try to resolve Request interface
|
||||
$request = $container->get('App\\Framework\\Http\\Request');
|
||||
echo "4. ✅ SUCCESS: Request resolved as " . get_class($request) . "\n";
|
||||
echo "5. Is HttpRequest instance: " . ($request instanceof \App\Framework\Http\HttpRequest ? 'YES' : 'NO') . "\n";
|
||||
|
||||
// Check discovery registry
|
||||
echo "\n=== Discovery Registry Check ===\n";
|
||||
$registry = $container->get('App\\Framework\\Discovery\\Results\\DiscoveryRegistry');
|
||||
$initializers = $registry->getInitializersByClass();
|
||||
echo "Total initializers: " . count($initializers) . "\n";
|
||||
|
||||
$requestFactoryFound = false;
|
||||
foreach ($initializers as $class => $methods) {
|
||||
if (str_contains($class, 'RequestFactory')) {
|
||||
echo "Found RequestFactory: $class\n";
|
||||
foreach ($methods as $method) {
|
||||
echo " Method: $method\n";
|
||||
}
|
||||
$requestFactoryFound = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!$requestFactoryFound) {
|
||||
echo "❌ RequestFactory not found in discovery registry!\n";
|
||||
}
|
||||
|
||||
// Try creating request directly
|
||||
echo "\n=== Direct Request Creation Test ===\n";
|
||||
$requestFactory = $container->get('App\\Framework\\Http\\RequestFactory');
|
||||
echo "RequestFactory resolved: " . get_class($requestFactory) . "\n";
|
||||
|
||||
$directRequest = $requestFactory->createFromGlobals();
|
||||
echo "Direct request created: " . get_class($directRequest) . "\n";
|
||||
echo "Is Request interface: " . ($directRequest instanceof \App\Framework\Http\Request ? 'YES' : 'NO') . "\n";
|
||||
|
||||
} catch (Throwable $e) {
|
||||
echo "ERROR: " . $e->getMessage() . "\n";
|
||||
echo "FILE: " . $e->getFile() . ":" . $e->getLine() . "\n";
|
||||
if (str_contains($e->getMessage(), 'Cannot instantiate')) {
|
||||
echo "\n=== ANALYSIS ===\n";
|
||||
echo "This suggests the Discovery system did not register the RequestFactory initializer\n";
|
||||
}
|
||||
}
|
||||
26
scripts/test/test_request_factory.php
Normal file
26
scripts/test/test_request_factory.php
Normal file
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
require_once 'vendor/autoload.php';
|
||||
|
||||
use App\Framework\Http\HttpRequest;
|
||||
use App\Framework\Http\Request;
|
||||
use App\Framework\DI\DefaultContainer;
|
||||
|
||||
echo "Testing DI Container Request binding..." . PHP_EOL;
|
||||
|
||||
try {
|
||||
// Test simple DI binding
|
||||
$container = new DefaultContainer();
|
||||
|
||||
// Manual binding (this should work)
|
||||
$container->bind(Request::class, HttpRequest::class);
|
||||
echo "Binding created successfully" . PHP_EOL;
|
||||
|
||||
// Test resolution
|
||||
$request = $container->get(Request::class);
|
||||
echo "Request resolved: " . get_class($request) . PHP_EOL;
|
||||
echo "Implements Request interface: " . (($request instanceof Request) ? "YES" : "NO") . PHP_EOL;
|
||||
|
||||
} catch (Exception $e) {
|
||||
echo "Error: " . $e->getMessage() . PHP_EOL;
|
||||
echo "Trace: " . $e->getTraceAsString() . PHP_EOL;
|
||||
}
|
||||
42
scripts/test/test_request_web.php
Normal file
42
scripts/test/test_request_web.php
Normal file
@@ -0,0 +1,42 @@
|
||||
<?php
|
||||
require __DIR__ . '/vendor/autoload.php';
|
||||
|
||||
// Test if the issue is specifically in web context
|
||||
// by accessing localhost directly
|
||||
echo "Testing localhost web request...\n";
|
||||
|
||||
$context = [
|
||||
'http' => [
|
||||
'method' => 'GET',
|
||||
'header' => [
|
||||
'User-Agent: Mozilla/5.0 (compatible test)',
|
||||
'Host: localhost'
|
||||
],
|
||||
'ignore_errors' => true
|
||||
],
|
||||
'ssl' => [
|
||||
'verify_peer' => false,
|
||||
'verify_peer_name' => false
|
||||
]
|
||||
];
|
||||
|
||||
$response = @file_get_contents('https://localhost/', false, stream_context_create($context));
|
||||
|
||||
if ($response === false) {
|
||||
$error = error_get_last();
|
||||
echo "Failed to fetch localhost: " . $error['message'] . "\n";
|
||||
|
||||
// Try HTTP instead
|
||||
echo "Trying HTTP instead of HTTPS...\n";
|
||||
$response = @file_get_contents('http://localhost/', false, stream_context_create($context));
|
||||
|
||||
if ($response === false) {
|
||||
echo "HTTP also failed\n";
|
||||
} else {
|
||||
echo "HTTP response length: " . strlen($response) . "\n";
|
||||
echo "Response snippet: " . substr($response, 0, 200) . "\n";
|
||||
}
|
||||
} else {
|
||||
echo "Response length: " . strlen($response) . "\n";
|
||||
echo "Response snippet: " . substr($response, 0, 200) . "\n";
|
||||
}
|
||||
79
scripts/test/test_route_discovery.php
Normal file
79
scripts/test/test_route_discovery.php
Normal file
@@ -0,0 +1,79 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
require_once __DIR__ . '/vendor/autoload.php';
|
||||
|
||||
use App\Framework\Discovery\UnifiedDiscoveryService;
|
||||
use App\Framework\Discovery\ValueObjects\DiscoveryOptions;
|
||||
use App\Framework\Cache\Cache;
|
||||
use App\Framework\Cache\CacheKey;
|
||||
use App\Framework\Cache\CacheItem;
|
||||
use App\Framework\Attributes\Route;
|
||||
|
||||
// Simple null cache for testing
|
||||
$cache = new class implements Cache {
|
||||
public function get(CacheKey $key): ?CacheItem { return null; }
|
||||
public function set(CacheItem ...$items): bool { return true; }
|
||||
public function delete(CacheKey ...$keys): bool { return true; }
|
||||
public function clear(): bool { return true; }
|
||||
public function has(CacheKey $key): bool { return false; }
|
||||
};
|
||||
|
||||
try {
|
||||
|
||||
// Create discovery service
|
||||
$discoveryService = new UnifiedDiscoveryService($cache);
|
||||
|
||||
// Perform discovery
|
||||
$options = new DiscoveryOptions(
|
||||
paths: [__DIR__ . '/src'],
|
||||
cachingEnabled: false, // Disable caching for test
|
||||
attributeTypes: [Route::class]
|
||||
);
|
||||
|
||||
$registry = $discoveryService->discover($options);
|
||||
|
||||
$routes = $registry->getByAttribute(Route::class);
|
||||
|
||||
echo "=== DISCOVERED ROUTES ===\n\n";
|
||||
echo "Total routes found: " . count($routes) . "\n\n";
|
||||
|
||||
foreach ($routes as $discovered) {
|
||||
$routeAttr = $discovered->attribute->newInstance();
|
||||
$className = $discovered->className;
|
||||
$methodName = $discovered->methodName ?? '__invoke';
|
||||
|
||||
echo "Route: {$routeAttr->method->value} {$routeAttr->path}\n";
|
||||
echo " Class: {$className}\n";
|
||||
echo " Method: {$methodName}\n";
|
||||
|
||||
// Check for Campaign routes specifically
|
||||
if (str_contains($className, 'Campaign')) {
|
||||
echo " ⭐ CAMPAIGN ROUTE\n";
|
||||
}
|
||||
|
||||
echo "\n";
|
||||
}
|
||||
|
||||
// Specifically search for PreSaveCampaign
|
||||
echo "\n=== SEARCHING FOR PreSaveCampaign ===\n";
|
||||
$found = false;
|
||||
foreach ($routes as $discovered) {
|
||||
if (str_contains($discovered->className, 'PreSaveCampaign')) {
|
||||
echo "✅ PreSaveCampaign FOUND!\n";
|
||||
echo " Path: {$discovered->attribute->newInstance()->path}\n";
|
||||
$found = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!$found) {
|
||||
echo "❌ PreSaveCampaign NOT FOUND in discovery!\n";
|
||||
}
|
||||
|
||||
} catch (\Exception $e) {
|
||||
echo "❌ Error during discovery: " . $e->getMessage() . "\n";
|
||||
echo "File: " . $e->getFile() . ":" . $e->getLine() . "\n";
|
||||
echo "\nStack trace:\n";
|
||||
echo $e->getTraceAsString() . "\n";
|
||||
}
|
||||
43
scripts/test/test_spotify_init.php
Normal file
43
scripts/test/test_spotify_init.php
Normal file
@@ -0,0 +1,43 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
require_once __DIR__ . '/vendor/autoload.php';
|
||||
|
||||
use App\Framework\Core\ContainerBootstrapper;
|
||||
use App\Framework\OAuth\Providers\SpotifyProvider;
|
||||
use App\Framework\Config\Environment;
|
||||
|
||||
try {
|
||||
$envPath = __DIR__ . '/.env';
|
||||
if (!file_exists($envPath)) {
|
||||
throw new \RuntimeException(".env file not found at: {$envPath}");
|
||||
}
|
||||
|
||||
$envVars = parse_ini_file($envPath);
|
||||
if ($envVars === false) {
|
||||
throw new \RuntimeException("Failed to parse .env file");
|
||||
}
|
||||
|
||||
$env = new Environment($envVars);
|
||||
|
||||
echo "Environment loaded\n";
|
||||
echo "SPOTIFY_CLIENT_ID: " . $env->get(\App\Framework\Config\EnvKey::fromString('SPOTIFY_CLIENT_ID'), 'NOT SET') . "\n";
|
||||
echo "SPOTIFY_CLIENT_SECRET: " . $env->get(\App\Framework\Config\EnvKey::fromString('SPOTIFY_CLIENT_SECRET'), 'NOT SET') . "\n";
|
||||
|
||||
$containerBootstrapper = new ContainerBootstrapper($env);
|
||||
$container = $containerBootstrapper->bootstrap();
|
||||
|
||||
echo "Container bootstrapped\n";
|
||||
|
||||
$spotifyProvider = $container->get(SpotifyProvider::class);
|
||||
|
||||
echo "✅ SpotifyProvider successfully resolved from container\n";
|
||||
echo "Provider name: " . $spotifyProvider->getName() . "\n";
|
||||
|
||||
} catch (\Exception $e) {
|
||||
echo "❌ Error: " . $e->getMessage() . "\n";
|
||||
echo "File: " . $e->getFile() . ":" . $e->getLine() . "\n";
|
||||
echo "\nStack trace:\n";
|
||||
echo $e->getTraceAsString() . "\n";
|
||||
}
|
||||
7
scripts/test/test_spotify_simple.php
Normal file
7
scripts/test/test_spotify_simple.php
Normal file
@@ -0,0 +1,7 @@
|
||||
<?php
|
||||
|
||||
echo "Testing Spotify environment variables:\n\n";
|
||||
|
||||
echo "SPOTIFY_CLIENT_ID: " . (getenv('SPOTIFY_CLIENT_ID') ?: 'NOT SET') . "\n";
|
||||
echo "SPOTIFY_CLIENT_SECRET: " . (getenv('SPOTIFY_CLIENT_SECRET') ?: 'NOT SET') . "\n";
|
||||
echo "SPOTIFY_REDIRECT_URI: " . (getenv('SPOTIFY_REDIRECT_URI') ?: 'NOT SET') . "\n";
|
||||
140
scripts/test/test_tui_complete.php
Normal file
140
scripts/test/test_tui_complete.php
Normal file
@@ -0,0 +1,140 @@
|
||||
<?php
|
||||
|
||||
require_once __DIR__ . '/vendor/autoload.php';
|
||||
|
||||
// Test TUI complete functionality
|
||||
use App\Framework\Console\Components\TuiState;
|
||||
use App\Framework\Console\Components\TuiInputHandler;
|
||||
use App\Framework\Console\Components\TuiCommandExecutor;
|
||||
use App\Framework\Console\Components\TuiRenderer;
|
||||
use App\Framework\Console\CommandHistory;
|
||||
use App\Framework\Console\TuiView;
|
||||
use App\Framework\Console\TuiKeyCode;
|
||||
use App\Framework\Console\ConsoleOutput;
|
||||
use App\Framework\Console\Screen\ScreenManager;
|
||||
|
||||
echo "Testing Complete TUI Functionality...\n";
|
||||
echo "=====================================\n\n";
|
||||
|
||||
try {
|
||||
// Create mock executor
|
||||
$mockExecutor = new class implements \App\Framework\Console\Components\TuiCommandExecutor {
|
||||
public function executeSelectedCommand(object $command): void {
|
||||
echo "Mock: Execute command\n";
|
||||
}
|
||||
public function executeCommand(string $commandName): void {
|
||||
echo "Mock: Execute command: $commandName\n";
|
||||
}
|
||||
public function validateSelectedCommand(object $command): void {
|
||||
echo "Mock: Validate command\n";
|
||||
}
|
||||
public function validateCommand(string $commandName): void {
|
||||
echo "Mock: Validate command: $commandName\n";
|
||||
}
|
||||
public function showSelectedCommandHelp(object $command): void {
|
||||
echo "Mock: Show help\n";
|
||||
}
|
||||
public function showCommandHelp(string $commandName): void {
|
||||
echo "Mock: Show help: $commandName\n";
|
||||
}
|
||||
public function showAllCommandsHelp(): void {
|
||||
echo "Mock: Show all commands help\n";
|
||||
}
|
||||
public function startInteractiveForm(object $command, \App\Framework\Console\Components\TuiState $state): void {
|
||||
echo "Mock: Start form\n";
|
||||
}
|
||||
public function findCommandObject(string $commandName): ?object {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
// Create mock output and screen manager
|
||||
$screenManager = new ScreenManager(new ConsoleOutput());
|
||||
$output = new ConsoleOutput();
|
||||
$output->screen = $screenManager;
|
||||
|
||||
$state = new TuiState();
|
||||
$history = new CommandHistory();
|
||||
$inputHandler = new TuiInputHandler($mockExecutor);
|
||||
$renderer = new TuiRenderer($output);
|
||||
|
||||
// Setup test categories
|
||||
$categories = [
|
||||
'Database' => [
|
||||
'name' => 'Database',
|
||||
'description' => 'Database commands',
|
||||
'icon' => '🗄️',
|
||||
'commands' => []
|
||||
],
|
||||
'Cache' => [
|
||||
'name' => 'Cache',
|
||||
'description' => 'Cache commands',
|
||||
'icon' => '⚡',
|
||||
'commands' => []
|
||||
],
|
||||
'Testing' => [
|
||||
'name' => 'Testing',
|
||||
'description' => 'Testing commands',
|
||||
'icon' => '🧪',
|
||||
'commands' => []
|
||||
]
|
||||
];
|
||||
|
||||
$state->setCategories($categories);
|
||||
$state->setCurrentView(TuiView::CATEGORIES);
|
||||
$state->setRunning(true);
|
||||
|
||||
echo "✅ Initial Setup Complete\n";
|
||||
echo "Categories loaded: " . count($categories) . "\n";
|
||||
echo "Current view: " . $state->getCurrentView()->name . "\n";
|
||||
echo "Selected category: " . $state->getSelectedCategory() . "\n\n";
|
||||
|
||||
// Test Arrow Down Navigation
|
||||
echo "Testing Arrow DOWN navigation:\n";
|
||||
echo "Before: Category " . $state->getSelectedCategory() . " ('{$categories[array_keys($categories)[$state->getSelectedCategory()]]['name']}')\n";
|
||||
|
||||
$inputHandler->handleInput(TuiKeyCode::ARROW_DOWN->value, $state, $history);
|
||||
|
||||
echo "After Arrow DOWN: Category " . $state->getSelectedCategory() . " ('{$categories[array_keys($categories)[$state->getSelectedCategory()]]['name']}')\n\n";
|
||||
|
||||
// Test Arrow Up Navigation
|
||||
echo "Testing Arrow UP navigation:\n";
|
||||
echo "Before: Category " . $state->getSelectedCategory() . " ('{$categories[array_keys($categories)[$state->getSelectedCategory()]]['name']}')\n";
|
||||
|
||||
$inputHandler->handleInput(TuiKeyCode::ARROW_UP->value, $state, $history);
|
||||
|
||||
echo "After Arrow UP: Category " . $state->getSelectedCategory() . " ('{$categories[array_keys($categories)[$state->getSelectedCategory()]]['name']}')\n\n";
|
||||
|
||||
// Test bounds checking - try to go below 0
|
||||
echo "Testing boundary protection (going below 0):\n";
|
||||
|
||||
$inputHandler->handleInput(TuiKeyCode::ARROW_UP->value, $state, $history);
|
||||
|
||||
echo "After Arrow UP (should stay at 0): Category " . $state->getSelectedCategory() . " ('{$categories[array_keys($categories)[$state->getSelectedCategory()]]['name']}')\n\n";
|
||||
|
||||
// Test bounds checking - try to go above max
|
||||
echo "Testing boundary protection (going above max):\n";
|
||||
|
||||
// Go to last item
|
||||
$state->setSelectedCategory(2); // Testing category
|
||||
echo "Set to last category (2): '{$categories[array_keys($categories)[$state->getSelectedCategory()]]['name']}'\n";
|
||||
|
||||
$inputHandler->handleInput(TuiKeyCode::ARROW_DOWN->value, $state, $history);
|
||||
|
||||
echo "After Arrow DOWN (should stay at 2): Category " . $state->getSelectedCategory() . " ('{$categories[array_keys($categories)[$state->getSelectedCategory()]]['name']}')\n\n";
|
||||
|
||||
// Test rendering with actual state
|
||||
echo "Testing TUI Rendering:\n";
|
||||
echo "=====================\n";
|
||||
|
||||
$state->setSelectedCategory(0);
|
||||
$renderer->render($state, $history);
|
||||
|
||||
echo "\n✅ TUI Complete Test PASSED - All functionality works!\n";
|
||||
|
||||
} catch (\Throwable $e) {
|
||||
echo "\n❌ TUI Complete Test FAILED:\n";
|
||||
echo "Error: " . $e->getMessage() . "\n";
|
||||
echo "File: " . $e->getFile() . ":" . $e->getLine() . "\n";
|
||||
echo "\nStack trace:\n" . $e->getTraceAsString() . "\n";
|
||||
}
|
||||
95
scripts/test/test_tui_navigation.php
Normal file
95
scripts/test/test_tui_navigation.php
Normal file
@@ -0,0 +1,95 @@
|
||||
<?php
|
||||
|
||||
require_once __DIR__ . '/vendor/autoload.php';
|
||||
|
||||
// Test TUI navigation functionality
|
||||
use App\Framework\Console\Components\TuiState;
|
||||
use App\Framework\Console\Components\TuiInputHandler;
|
||||
use App\Framework\Console\Components\TuiCommandExecutor;
|
||||
use App\Framework\Console\CommandHistory;
|
||||
use App\Framework\Console\TuiView;
|
||||
use App\Framework\Console\TuiKeyCode;
|
||||
|
||||
echo "Testing TUI Navigation...\n";
|
||||
echo "=========================\n\n";
|
||||
|
||||
try {
|
||||
// Create mock executor
|
||||
$mockExecutor = new class implements \App\Framework\Console\Components\TuiCommandExecutor {
|
||||
public function executeSelectedCommand(object $command): void {
|
||||
echo "Mock: Execute command\n";
|
||||
}
|
||||
public function executeCommand(string $commandName): void {
|
||||
echo "Mock: Execute command: $commandName\n";
|
||||
}
|
||||
public function validateSelectedCommand(object $command): void {
|
||||
echo "Mock: Validate command\n";
|
||||
}
|
||||
public function validateCommand(string $commandName): void {
|
||||
echo "Mock: Validate command: $commandName\n";
|
||||
}
|
||||
public function showSelectedCommandHelp(object $command): void {
|
||||
echo "Mock: Show help\n";
|
||||
}
|
||||
public function showCommandHelp(string $commandName): void {
|
||||
echo "Mock: Show help: $commandName\n";
|
||||
}
|
||||
public function showAllCommandsHelp(): void {
|
||||
echo "Mock: Show all commands help\n";
|
||||
}
|
||||
public function startInteractiveForm(object $command, \App\Framework\Console\Components\TuiState $state): void {
|
||||
echo "Mock: Start form\n";
|
||||
}
|
||||
public function findCommandObject(string $commandName): ?object {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
$state = new TuiState();
|
||||
$history = new CommandHistory();
|
||||
$inputHandler = new TuiInputHandler($mockExecutor);
|
||||
|
||||
// Setup test categories
|
||||
$categories = [
|
||||
'Database' => [
|
||||
'name' => 'Database',
|
||||
'description' => 'Database commands',
|
||||
'icon' => '🗄️',
|
||||
'commands' => []
|
||||
],
|
||||
'Cache' => [
|
||||
'name' => 'Cache',
|
||||
'description' => 'Cache commands',
|
||||
'icon' => '⚡',
|
||||
'commands' => []
|
||||
]
|
||||
];
|
||||
|
||||
$state->setCategories($categories);
|
||||
$state->setCurrentView(TuiView::CATEGORIES);
|
||||
$state->setRunning(true);
|
||||
|
||||
// Test arrow navigation
|
||||
echo "Testing arrow key navigation:\n";
|
||||
echo "Initial category: " . $state->getSelectedCategory() . "\n";
|
||||
|
||||
// Test arrow down
|
||||
$inputHandler->handleInput(TuiKeyCode::ARROW_DOWN->value, $state, $history);
|
||||
echo "After arrow down: " . $state->getSelectedCategory() . "\n";
|
||||
|
||||
// Test arrow up
|
||||
$inputHandler->handleInput(TuiKeyCode::ARROW_UP->value, $state, $history);
|
||||
echo "After arrow up: " . $state->getSelectedCategory() . "\n";
|
||||
|
||||
// Test bounds checking - try to go below 0
|
||||
$inputHandler->handleInput(TuiKeyCode::ARROW_UP->value, $state, $history);
|
||||
echo "After arrow up (should stay at 0): " . $state->getSelectedCategory() . "\n";
|
||||
|
||||
echo "\n✅ TUI Navigation Test PASSED - Arrow key handling works!\n";
|
||||
|
||||
} catch (\Throwable $e) {
|
||||
echo "\n❌ TUI Navigation Test FAILED:\n";
|
||||
echo "Error: " . $e->getMessage() . "\n";
|
||||
echo "File: " . $e->getFile() . ":" . $e->getLine() . "\n";
|
||||
echo "\nStack trace:\n" . $e->getTraceAsString() . "\n";
|
||||
}
|
||||
46
scripts/test/websocket.php
Executable file
46
scripts/test/websocket.php
Executable file
@@ -0,0 +1,46 @@
|
||||
#!/usr/bin/env php
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
require __DIR__ . '/vendor/autoload.php';
|
||||
require __DIR__ . '/src/Framework/Debug/helpers.php';
|
||||
|
||||
use App\Framework\Core\AppBootstrapper;
|
||||
use App\Framework\DateTime\SystemClock;
|
||||
use App\Framework\DateTime\SystemHighResolutionClock;
|
||||
use App\Framework\Http\WebSocketServer;
|
||||
use App\Framework\Performance\EnhancedPerformanceCollector;
|
||||
use App\Framework\Performance\MemoryMonitor;
|
||||
|
||||
// Bootstrapping mit minimaler Konfiguration
|
||||
$bootstrapper = new AppBootstrapper(
|
||||
getcwd(),
|
||||
new EnhancedPerformanceCollector(
|
||||
new SystemClock(),
|
||||
new SystemHighResolutionClock(),
|
||||
new MemoryMonitor(),
|
||||
false),
|
||||
new MemoryMonitor,
|
||||
);
|
||||
$container = $bootstrapper->bootstrapWebSocket();
|
||||
|
||||
// WebSocket-Server erstellen und konfigurieren
|
||||
$server = $container->get(WebSocketServer::class);
|
||||
|
||||
// Signal-Handler für sauberes Beenden
|
||||
pcntl_signal(SIGTERM, function () use ($server) {
|
||||
echo "Beende WebSocket-Server..." . PHP_EOL;
|
||||
$server->stop();
|
||||
exit(0);
|
||||
});
|
||||
|
||||
pcntl_signal(SIGINT, function () use ($server) {
|
||||
echo "Beende WebSocket-Server..." . PHP_EOL;
|
||||
$server->stop();
|
||||
exit(0);
|
||||
});
|
||||
|
||||
// Server starten (blockierend)
|
||||
echo "WebSocket-Server wird gestartet..." . PHP_EOL;
|
||||
$server->start('0.0.0.0', 8080);
|
||||
Reference in New Issue
Block a user