Enable Discovery debug logging for production troubleshooting

- Add DISCOVERY_LOG_LEVEL=debug
- Add DISCOVERY_SHOW_PROGRESS=true
- Temporary changes for debugging InitializerProcessor fixes on production
This commit is contained in:
2025-08-11 20:13:26 +02:00
parent 59fd3dd3b1
commit 55a330b223
3683 changed files with 2956207 additions and 16948 deletions

View File

@@ -0,0 +1,279 @@
<?php
declare(strict_types=1);
use App\Framework\Design\Service\ComponentDetector;
use App\Framework\Design\ValueObjects\CssClass;
describe('ComponentDetector', function () {
beforeEach(function () {
$this->detector = new ComponentDetector();
});
it('detects BEM components correctly', function () {
$cssClasses = [
new CssClass('card'),
new CssClass('card__header'),
new CssClass('card__body'),
new CssClass('card__footer'),
new CssClass('card--featured'),
new CssClass('card__header--large'),
new CssClass('button'),
new CssClass('button--primary'),
];
$components = $this->detector->detectBemComponents($cssClasses);
expect($components)->toHaveCount(2); // card and button
$cardComponent = $components[0];
expect($cardComponent['block'])->toBe('card');
expect($cardComponent['elements'])->toContain('header');
expect($cardComponent['elements'])->toContain('body');
expect($cardComponent['elements'])->toContain('footer');
expect($cardComponent['modifiers'])->toContain('featured');
expect($cardComponent['element_modifiers'])->toHaveKey('header');
expect($cardComponent['element_modifiers']['header'])->toContain('large');
});
it('identifies utility class patterns', function () {
$cssClasses = [
new CssClass('text-center'),
new CssClass('text-left'),
new CssClass('text-right'),
new CssClass('p-4'),
new CssClass('p-8'),
new CssClass('m-2'),
new CssClass('bg-blue-500'),
new CssClass('bg-red-300'),
new CssClass('hover:bg-blue-600'),
new CssClass('card'), // Not a utility
];
$utilityPatterns = $this->detector->detectUtilityPatterns($cssClasses);
expect($utilityPatterns)->toHaveKey('text-alignment');
expect($utilityPatterns)->toHaveKey('padding');
expect($utilityPatterns)->toHaveKey('margin');
expect($utilityPatterns)->toHaveKey('background-color');
expect($utilityPatterns)->toHaveKey('hover-states');
expect($utilityPatterns['text-alignment'])->toHaveCount(3);
expect($utilityPatterns['padding'])->toHaveCount(2);
expect($utilityPatterns['background-color'])->toHaveCount(2);
expect($utilityPatterns['hover-states'])->toHaveCount(1);
});
it('detects component structure patterns', function () {
$cssClasses = [
// Layout components
new CssClass('container'),
new CssClass('row'),
new CssClass('col'),
new CssClass('col-md-6'),
// Form components
new CssClass('form'),
new CssClass('form-group'),
new CssClass('form-control'),
new CssClass('form-label'),
// Navigation components
new CssClass('nav'),
new CssClass('nav-item'),
new CssClass('nav-link'),
];
$patterns = $this->detector->detectStructurePatterns($cssClasses);
expect($patterns)->toHaveKey('layout');
expect($patterns)->toHaveKey('form');
expect($patterns)->toHaveKey('navigation');
expect($patterns['layout']['components'])->toContain('container');
expect($patterns['layout']['components'])->toContain('row');
expect($patterns['form']['components'])->toContain('form');
expect($patterns['form']['components'])->toContain('form-group');
expect($patterns['navigation']['components'])->toContain('nav');
});
it('analyzes responsive design patterns', function () {
$cssClasses = [
new CssClass('hidden-xs'),
new CssClass('visible-md'),
new CssClass('col-sm-12'),
new CssClass('col-md-6'),
new CssClass('col-lg-4'),
new CssClass('text-sm-center'),
new CssClass('text-md-left'),
];
$responsive = $this->detector->analyzeResponsivePatterns($cssClasses);
expect($responsive['breakpoints'])->toContain('xs');
expect($responsive['breakpoints'])->toContain('sm');
expect($responsive['breakpoints'])->toContain('md');
expect($responsive['breakpoints'])->toContain('lg');
expect($responsive['patterns']['visibility'])->toHaveCount(2);
expect($responsive['patterns']['grid'])->toHaveCount(3);
expect($responsive['patterns']['typography'])->toHaveCount(2);
});
it('identifies component complexity levels', function () {
$simpleComponent = [
new CssClass('button'),
new CssClass('button--primary'),
];
$complexComponent = [
new CssClass('card'),
new CssClass('card__header'),
new CssClass('card__title'),
new CssClass('card__subtitle'),
new CssClass('card__body'),
new CssClass('card__content'),
new CssClass('card__actions'),
new CssClass('card__footer'),
new CssClass('card--featured'),
new CssClass('card--compact'),
new CssClass('card__header--large'),
new CssClass('card__actions--centered'),
];
$simpleComplexity = $this->detector->analyzeComponentComplexity($simpleComponent);
$complexComplexity = $this->detector->analyzeComponentComplexity($complexComponent);
expect($simpleComplexity['level'])->toBe('simple');
expect($simpleComplexity['score'])->toBeLessThan(3);
expect($complexComplexity['level'])->toBe('complex');
expect($complexComplexity['score'])->toBeGreaterThan(8);
expect($complexComplexity['recommendations'])->toContain('Consider splitting into smaller components');
});
it('detects atomic design patterns', function () {
$cssClasses = [
// Atoms
new CssClass('btn'),
new CssClass('input'),
new CssClass('label'),
new CssClass('icon'),
// Molecules
new CssClass('search-form'),
new CssClass('form-group'),
new CssClass('nav-item'),
// Organisms
new CssClass('header'),
new CssClass('sidebar'),
new CssClass('footer'),
new CssClass('product-grid'),
];
$atomicAnalysis = $this->detector->analyzeAtomicDesignPatterns($cssClasses);
expect($atomicAnalysis['atoms'])->toHaveCount(4);
expect($atomicAnalysis['molecules'])->toHaveCount(3);
expect($atomicAnalysis['organisms'])->toHaveCount(4);
expect($atomicAnalysis['atoms'])->toContain('btn');
expect($atomicAnalysis['molecules'])->toContain('search-form');
expect($atomicAnalysis['organisms'])->toContain('header');
});
it('validates component naming conventions', function () {
$cssClasses = [
new CssClass('button'), // Good: semantic
new CssClass('btn'), // Good: abbreviation
new CssClass('redButton'), // Bad: camelCase
new CssClass('button_primary'), // Bad: underscore instead of dash
new CssClass('Button'), // Bad: PascalCase
new CssClass('my-custom-btn-2'), // Good: kebab-case
];
$validation = $this->detector->validateNamingConventions($cssClasses);
expect($validation['valid'])->toHaveCount(3);
expect($validation['invalid'])->toHaveCount(3);
$invalidClasses = array_map(fn ($v) => $v['class'], $validation['invalid']);
expect($invalidClasses)->toContain('redButton');
expect($invalidClasses)->toContain('button_primary');
expect($invalidClasses)->toContain('Button');
});
it('detects component relationships', function () {
$cssClasses = [
new CssClass('modal'),
new CssClass('modal__backdrop'),
new CssClass('modal__dialog'),
new CssClass('modal__header'),
new CssClass('modal__title'),
new CssClass('modal__close'),
new CssClass('modal__body'),
new CssClass('modal__footer'),
new CssClass('modal__actions'),
];
$relationships = $this->detector->detectComponentRelationships($cssClasses);
expect($relationships)->toHaveKey('modal');
$modalRelationships = $relationships['modal'];
expect($modalRelationships['children'])->toContain('backdrop');
expect($modalRelationships['children'])->toContain('dialog');
expect($modalRelationships['children'])->toContain('header');
expect($modalRelationships['depth'])->toBe(2); // modal -> header -> title
expect($modalRelationships['complexity_score'])->toBeGreaterThan(5);
});
it('suggests component improvements', function () {
$cssClasses = [
// Inconsistent button pattern
new CssClass('button'),
new CssClass('btn'), // Inconsistent naming
new CssClass('submit-btn'), // Another variation
// Missing BEM structure
new CssClass('card-header'), // Should be card__header
new CssClass('card-body'), // Should be card__body
// Overly specific
new CssClass('red-submit-button-large'),
];
$improvements = $this->detector->suggestImprovements($cssClasses);
expect($improvements['naming_inconsistencies'])->not->toBeEmpty();
expect($improvements['bem_violations'])->not->toBeEmpty();
expect($improvements['overly_specific'])->not->toBeEmpty();
expect($improvements['suggestions'])->toContain('Standardize button naming (choose: button, btn)');
expect($improvements['suggestions'])->toContain('Convert card-header to card__header for BEM compliance');
});
it('analyzes component reusability', function () {
$cssClasses = [
new CssClass('btn'),
new CssClass('btn--primary'),
new CssClass('btn--secondary'),
new CssClass('btn--large'),
new CssClass('btn--small'),
new CssClass('very-specific-page-button'), // Low reusability
];
$reusability = $this->detector->analyzeComponentReusability($cssClasses);
$btnReusability = $reusability['btn'];
expect($btnReusability['score'])->toBeGreaterThan(0.8);
expect($btnReusability['variants'])->toBe(4);
expect($btnReusability['reusability_level'])->toBe('high');
$specificReusability = $reusability['very-specific-page-button'];
expect($specificReusability['score'])->toBeLessThan(0.3);
expect($specificReusability['reusability_level'])->toBe('low');
});
});