assertEquals('', PageSSR::render([])); $this->assertEquals('', PageSSR::render(['sections' => []])); } /** * Test render_section with unknown type falls back to generic */ public function test_render_section_fallback_to_generic() { $section = [ 'id' => 'test-section', 'type' => 'unknown-type', 'props' => [ 'title' => 'Test Title', 'description' => 'Test Description', ], ]; $html = PageSSR::render_section($section); $this->assertStringContainsString('wn-unknown-type', $html); $this->assertStringContainsString('Test Title', $html); $this->assertStringContainsString('Test Description', $html); } /** * Test render_hero section */ public function test_render_hero() { $props = [ 'title' => 'Welcome', 'subtitle' => 'To our site', 'image' => 'https://example.com/hero.jpg', 'cta_text' => 'Get Started', 'cta_url' => '/start', ]; $html = PageSSR::render_hero($props, 'default', 'default', 'hero-section'); $this->assertStringContainsString('wn-hero', $html); $this->assertStringContainsString('Welcome', $html); $this->assertStringContainsString('To our site', $html); $this->assertStringContainsString('Get Started', $html); $this->assertStringContainsString('/start', $html); } /** * Test render_hero with section styles */ public function test_render_hero_with_section_styles() { $props = [ 'title' => 'Styled Hero', ]; $section_styles = [ 'backgroundType' => 'gradient', 'gradientFrom' => '#ff0000', 'gradientTo' => '#0000ff', 'gradientAngle' => 90, 'paddingTop' => '3rem', 'paddingBottom' => '3rem', 'contentWidth' => 'contained', ]; $html = PageSSR::render_hero($props, 'default', 'default', 'hero-styled', [], $section_styles); $this->assertStringContainsString('background:', $html); $this->assertStringContainsString('linear-gradient', $html); $this->assertStringContainsString('padding-top', $html); } /** * Test resolve_props handles static values */ public function test_resolve_props_static_values() { $props = [ 'title' => ['type' => 'static', 'value' => 'Static Title'], 'subtitle' => ['type' => 'static', 'value' => 'Static Subtitle'], ]; $resolved = PageSSR::resolve_props($props); $this->assertEquals('Static Title', $resolved['title']); $this->assertEquals('Static Subtitle', $resolved['subtitle']); } /** * Test resolve_props handles dynamic values */ public function test_resolve_props_dynamic_values() { $props = [ 'title' => ['type' => 'dynamic', 'source' => 'post_title'], 'subtitle' => ['type' => 'dynamic', 'source' => 'post_excerpt'], ]; $post_data = [ 'title' => 'Dynamic Title', 'excerpt' => 'Dynamic Excerpt', ]; $resolved = PageSSR::resolve_props($props, $post_data); $this->assertEquals('Dynamic Title', $resolved['title']); $this->assertEquals('Dynamic Excerpt', $resolved['subtitle']); } /** * Test resolve_props with options */ public function test_resolve_props_with_options() { $props = [ 'title' => ['type' => 'dynamic', 'source' => 'post_title'], ]; $post_data = [ 'title' => '', ]; // With fallbacks $resolved = PageSSR::resolve_props($props, $post_data, ['use_fallbacks' => true]); $this->assertEquals('(Untitled)', $resolved['title']); // Without fallbacks $resolved = PageSSR::resolve_props($props, $post_data, ['use_fallbacks' => false]); $this->assertEquals('', $resolved['title']); } /** * Test resolve_props handles non-array props */ public function test_resolve_props_non_array_props() { $props = [ 'title' => 'Plain String Title', 'count' => 42, ]; $resolved = PageSSR::resolve_props($props); $this->assertEquals('Plain String Title', $resolved['title']); $this->assertEquals(42, $resolved['count']); } /** * Test render_feature_grid section */ public function test_render_feature_grid() { $props = [ 'heading' => 'Our Features', 'items' => [ ['title' => 'Feature 1', 'description' => 'Desc 1', 'icon' => 'Star'], ['title' => 'Feature 2', 'description' => 'Desc 2', 'icon' => 'Heart'], ], ]; $html = PageSSR::render_feature_grid($props, 'grid-3', 'default', 'features-section'); $this->assertStringContainsString('wn-feature-grid', $html); $this->assertStringContainsString('Our Features', $html); $this->assertStringContainsString('Feature 1', $html); $this->assertStringContainsString('Feature 2', $html); } /** * Test render_feature_grid falls back to features prop */ public function test_render_feature_grid_falls_back_to_features() { $props = [ 'heading' => 'Features', 'features' => [ ['title' => 'Legacy Feature', 'description' => 'From features prop'], ], ]; $html = PageSSR::render_feature_grid($props, 'grid-2', 'default', 'features-legacy'); $this->assertStringContainsString('Legacy Feature', $html); } /** * Test render_feature_grid with section styles */ public function test_render_feature_grid_with_styles() { $props = [ 'heading' => 'Styled Features', 'items' => [ ['title' => 'Styled Item'], ], ]; $section_styles = [ 'backgroundType' => 'gradient', 'gradientFrom' => '#9333ea', 'gradientTo' => '#3b82f6', 'gradientAngle' => 135, 'heightPreset' => 'medium', ]; $html = PageSSR::render_feature_grid($props, 'grid-3', 'default', 'features-styled', [], $section_styles); $this->assertStringContainsString('linear-gradient', $html); $this->assertStringContainsString('py-16', $html); } /** * Test render_cta_banner section */ public function test_render_cta_banner() { $props = [ 'title' => 'Ready to Start?', 'text' => 'Join thousands of users today.', 'button_text' => 'Get Started', 'button_url' => '/signup', ]; $html = PageSSR::render_cta_banner($props, 'default', 'primary', 'cta-section'); $this->assertStringContainsString('wn-cta-banner', $html); $this->assertStringContainsString('Ready to Start?', $html); $this->assertStringContainsString('Get Started', $html); $this->assertStringContainsString('/signup', $html); } /** * Test render_cta_banner with section styles */ public function test_render_cta_banner_with_styles() { $props = [ 'title' => 'Styled CTA', ]; $section_styles = [ 'backgroundType' => 'solid', 'backgroundColor' => '#1a1a1a', 'contentWidth' => 'full', ]; $html = PageSSR::render_cta_banner($props, 'default', 'default', 'cta-styled', [], $section_styles); $this->assertStringContainsString('background-color', $html); $this->assertStringContainsString('w-full', $html); } /** * Test render_contact_form section */ public function test_render_contact_form() { $props = [ 'title' => 'Contact Us', 'fields' => ['name', 'email', 'message'], ]; $html = PageSSR::render_contact_form($props, 'default', 'default', 'contact-section'); $this->assertStringContainsString('wn-contact-form', $html); $this->assertStringContainsString('Contact Us', $html); $this->assertStringContainsString('name', $html); $this->assertStringContainsString('email', $html); $this->assertStringContainsString('message', $html); } /** * Test render_bento_category_grid section */ public function test_render_bento_category_grid() { $props = [ 'title' => 'Shop by Category', 'items' => [ ['label' => 'Electronics', 'url' => '/category/electronics', 'image' => 'https://example.com/elec.jpg'], ['label' => 'Clothing', 'url' => '/category/clothing'], ], ]; $html = PageSSR::render_bento_category_grid($props, 'default', 'default', 'bento-section'); $this->assertStringContainsString('wn-bento-grid', $html); $this->assertStringContainsString('Shop by Category', $html); $this->assertStringContainsString('Electronics', $html); $this->assertStringContainsString('Clothing', $html); } /** * Test render_marquee_banner section */ public function test_render_marquee_banner() { $props = [ 'text' => 'Free Shipping * Easy Returns * 24/7 Support', 'separator' => '*', ]; $html = PageSSR::render_marquee_banner($props, 'default', 'default', 'marquee-section'); $this->assertStringContainsString('wn-marquee', $html); $this->assertStringContainsString('Free Shipping', $html); $this->assertStringContainsString('Easy Returns', $html); } /** * Test render with full structure */ public function test_render_full_structure() { $structure = [ 'sections' => [ [ 'id' => 'hero-1', 'type' => 'hero', 'props' => [ 'title' => ['type' => 'static', 'value' => 'Full Render Test'], 'subtitle' => ['type' => 'static', 'value' => 'Testing complete render'], ], ], [ 'id' => 'features-1', 'type' => 'feature-grid', 'props' => [ 'heading' => ['type' => 'static', 'value' => 'Features'], 'items' => [ ['title' => 'Feature A'], ], ], ], ], ]; $html = PageSSR::render($structure); $this->assertStringContainsString('Full Render Test', $html); $this->assertStringContainsString('Testing complete render', $html); $this->assertStringContainsString('Features', $html); $this->assertStringContainsString('Feature A', $html); } /** * Test get_icon_svg returns SVG for known icons */ public function test_get_icon_svg_known() { $reflection = new \ReflectionClass(PageSSR::class); $method = $reflection->getMethod('get_icon_svg'); $method->setAccessible(true); $starSvg = $method->invoke(null, 'Star'); $this->assertStringContainsString('assertStringContainsString('polygon', $starSvg); $heartSvg = $method->invoke(null, 'Heart'); $this->assertStringContainsString('assertStringContainsString('path', $heartSvg); } }