html; } public function renderFromResolved( array $mergedLayout, array $routeParams, string $url, string $locale, string $templateIdentifier, string $layoutName, ?string $moduleId, ?string $pluginId, array $context, ?string $defaultLocale = null, bool $seoOnly = false, ): ?string { $this->calls++; $this->lastSeoOnly = $seoOnly; return $this->html; } }; } private function render(SeoBotPreviewService $svc): ?string { return $svc->render([], [], '/x', 'ko', 'sirsoft-admin_basic', null, null, []); } public function test_seo_only_true_로_렌더_파이프라인을_호출한다(): void { // 봇 미리보기는 SEO 설정 산출물만 받아야 하므로 seoOnly=true 로 호출한다. $renderer = $this->recordingRenderer('T'); $svc = new SeoBotPreviewService($renderer); $this->render($svc); $this->assertSame(1, $renderer->calls); $this->assertTrue($renderer->lastSeoOnly, '봇 미리보기는 seoOnly=true 로 호출'); } public function test_렌더_결과를_가공_없이_그대로_통과시킨다(): void { // 종전 extractSeoMarkup 후처리 폐기 — 파이프라인이 돌려준 SEO 전용 HTML 을 그대로 반환. $html = '봇 제목'; $renderer = $this->recordingRenderer($html); $svc = new SeoBotPreviewService($renderer); $this->assertSame($html, $this->render($svc)); } public function test_seo_비활성_render_null_은_null_로_전달된다(): void { // seoOnly 경로에서도 meta.seo.enabled=false → renderFromResolved 가 null → null 통과. $renderer = $this->recordingRenderer(null); $svc = new SeoBotPreviewService($renderer); $this->assertNull($this->render($svc)); } }