using System;
using System.IO;
using System.Text.Json;
using System.Xml.Linq;
using Xunit;
namespace Paca.Tests.Infrastructure;
///
/// PACA 웹사이트 및 제품의 SEO(검색엔진), AEO(답변엔진), GEO(생성형 AI) 최적화 인프라 무결성 검증 게이트
///
public class SiteSeoAeoGeoGateTests
{
private static string SiteDir => Path.Combine(SourceTree.Root, "site");
[Fact]
public void Gate211_SchemaOrgStructuredDataIntegrity()
{
// 1. index.html의 SoftwareApplication 및 FAQPage Schema.org 검증
var indexPath = Path.Combine(SiteDir, "index.html");
Assert.True(File.Exists(indexPath), "site/index.html 파일이 존재해야 합니다.");
var indexHtml = File.ReadAllText(indexPath);
Assert.Contains("application/ld+json", indexHtml);
Assert.Contains("\"@type\": \"SoftwareApplication\"", indexHtml);
Assert.Contains("\"offers\"", indexHtml);
Assert.Contains("\"operatingSystem\"", indexHtml);
// 2. how-to-download-m3u8.html (HLS m3u8 다운로드 완벽 가이드) 및 HowTo Schema.org 검증
var m3u8GuidePath = Path.Combine(SiteDir, "how-to-download-m3u8.html");
Assert.True(File.Exists(m3u8GuidePath), "site/how-to-download-m3u8.html 랜딩 페이지가 존재해야 합니다.");
var m3u8Html = File.ReadAllText(m3u8GuidePath);
Assert.Contains("\"@type\": \"HowTo\"", m3u8Html);
Assert.Contains("\"step\"", m3u8Html);
Assert.Contains("m3u8", m3u8Html);
Assert.Contains("HLS", m3u8Html);
Assert.Contains("MP4", m3u8Html);
// 3. vs-idm-alternative.html (IDM / 4K Video Downloader 대체 비교 가이드) 검증
var vsIdmPath = Path.Combine(SiteDir, "vs-idm-alternative.html");
Assert.True(File.Exists(vsIdmPath), "site/vs-idm-alternative.html 랜딩 페이지가 존재해야 합니다.");
var vsIdmHtml = File.ReadAllText(vsIdmPath);
Assert.Contains("IDM", vsIdmHtml);
Assert.Contains("4K Video Downloader", vsIdmHtml);
Assert.Contains("Internet Download Manager", vsIdmHtml);
Assert.Contains("\"@type\": \"FAQPage\"", vsIdmHtml);
}
[Fact]
public void Gate212_AiCrawlerAndLlmStandardIntegrity()
{
// 1. robots.txt 검증: 모든 AI 크롤러 봇 (GPTBot, PerplexityBot, ClaudeBot, Google-Extended 등) 접근 허용
var robotsPath = Path.Combine(SiteDir, "robots.txt");
Assert.True(File.Exists(robotsPath), "site/robots.txt 파일이 존재해야 합니다.");
var robotsTxt = File.ReadAllText(robotsPath);
Assert.Contains("User-agent: *", robotsTxt);
Assert.Contains("GPTBot", robotsTxt);
Assert.Contains("PerplexityBot", robotsTxt);
Assert.Contains("ClaudeBot", robotsTxt);
Assert.Contains("Allow: /", robotsTxt);
Assert.Contains("llms.txt", robotsTxt);
Assert.Contains("sitemap.xml", robotsTxt);
// 2. llms.txt (Answer.AI 표준 AI 모델용 제품 요약) 검증
var llmsPath = Path.Combine(SiteDir, "llms.txt");
Assert.True(File.Exists(llmsPath), "site/llms.txt 파일이 존재해야 합니다.");
var llmsTxt = File.ReadAllText(llmsPath);
Assert.Contains("# Paca", llmsTxt);
Assert.Contains("HLS", llmsTxt);
Assert.Contains("DASH", llmsTxt);
Assert.Contains("AES-128", llmsTxt);
Assert.Contains("ffmpeg", llmsTxt);
Assert.Contains("llms-full.txt", llmsTxt);
// 3. llms-full.txt (전체 상세 기술 명세 및 인용 문서) 검증
var llmsFullPath = Path.Combine(SiteDir, "llms-full.txt");
Assert.True(File.Exists(llmsFullPath), "site/llms-full.txt 파일이 존재해야 합니다.");
var llmsFullTxt = File.ReadAllText(llmsFullPath);
Assert.True(llmsFullTxt.Length >= 2500, "llms-full.txt는 AI 모델이 충분히 인용할 수 있도록 2,500자 이상의 상세 기술 명세를 담아야 합니다.");
Assert.Contains("IDM", llmsFullTxt);
Assert.Contains("Benchmark", llmsFullTxt);
Assert.Contains("AES-128", llmsFullTxt);
Assert.Contains("FAQ", llmsFullTxt);
}
[Fact]
public void Gate213_AeoComparisonMatrixAndSitemapIntegrity()
{
// 1. AEO 경쟁 툴 비교 테이블 (Comparison Matrix) 존재성 검증
var vsIdmPath = Path.Combine(SiteDir, "vs-idm-alternative.html");
var indexPath = Path.Combine(SiteDir, "index.html");
Assert.True(File.Exists(vsIdmPath));
var vsHtml = File.ReadAllText(vsIdmPath);
Assert.Contains("