feat(ads/seo/release): v1.2.0 with live Google Ads, isolated ad profile, ads.txt, and SEO/AEO/GEO optimization
This commit is contained in:
parent
a88aafa1e5
commit
0e568f1f0a
975 changed files with 130593 additions and 16783 deletions
121
tests/Paca.Tests/Browser/SearchEngineResolverTests.cs
Normal file
121
tests/Paca.Tests/Browser/SearchEngineResolverTests.cs
Normal file
|
|
@ -0,0 +1,121 @@
|
|||
using Paca.Browser;
|
||||
|
||||
namespace Paca.Tests.Browser;
|
||||
|
||||
// T1-4 검색엔진: 주소창 입력이 URL인지 검색어인지 판별하고, 키워드(g, yt, ...)로 엔진을 전환한다.
|
||||
public class SearchEngineResolverTests
|
||||
{
|
||||
private readonly SearchEngineResolver _resolver = new("Google");
|
||||
|
||||
[Theory]
|
||||
[InlineData("https://example.com", "https://example.com")] // 스킴 있음 → 그대로
|
||||
[InlineData("http://example.com/path?q=1", "http://example.com/path?q=1")]
|
||||
[InlineData("example.com", "https://example.com")] // 도메인 → https 보정
|
||||
[InlineData("www.example.co.kr/a/b", "https://www.example.co.kr/a/b")]
|
||||
[InlineData("sub.domain.org", "https://sub.domain.org")]
|
||||
[InlineData("localhost", "https://localhost")] // localhost → URL
|
||||
[InlineData("localhost:8080/x", "https://localhost:8080/x")]
|
||||
[InlineData("192.168.1.10", "https://192.168.1.10")] // IPv4 → URL
|
||||
[InlineData("192.168.1.10:9000/v.html", "https://192.168.1.10:9000/v.html")]
|
||||
[InlineData("file:///C:/tmp/a.html", "file:///C:/tmp/a.html")]
|
||||
public void Url_입력은_URL_의도로_판별한다(string input, string expected)
|
||||
{
|
||||
var intent = _resolver.Resolve(input);
|
||||
Assert.NotNull(intent);
|
||||
Assert.True(intent.IsUrl);
|
||||
Assert.Equal(expected, intent.Target);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("hello world")] // 공백 포함 일반어 → 검색
|
||||
[InlineData("cats")] // 점 없는 단일 단어 → 검색
|
||||
[InlineData("how to download mp4")]
|
||||
[InlineData("나는 한국어 검색어")]
|
||||
public void 검색어_입력은_기본_엔진으로_검색한다(string input)
|
||||
{
|
||||
var intent = _resolver.Resolve(input);
|
||||
Assert.NotNull(intent);
|
||||
Assert.False(intent.IsUrl);
|
||||
Assert.Equal("https://www.google.com/search?q=" + Uri.EscapeDataString(input).Replace("%20", "+"), intent.Target);
|
||||
Assert.Equal("Google", intent.EngineName);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void 키워드_g는_Google로_라우팅한다()
|
||||
{
|
||||
var intent = _resolver.Resolve("g cute cats");
|
||||
Assert.NotNull(intent);
|
||||
Assert.False(intent.IsUrl);
|
||||
Assert.Contains("google.com/search", intent.Target);
|
||||
Assert.Contains("cute+cats", intent.Target);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void 키워드_yt는_YouTube_검색으로_라우팅한다()
|
||||
{
|
||||
var intent = _resolver.Resolve("yt lofi beats");
|
||||
Assert.NotNull(intent);
|
||||
Assert.False(intent.IsUrl);
|
||||
Assert.Contains("youtube.com/results", intent.Target);
|
||||
Assert.Equal("YouTube", intent.EngineName);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void 기본_엔진을_Bing으로_바꾸면_일반_검색어가_Bing으로_간다()
|
||||
{
|
||||
var r = new SearchEngineResolver("Bing");
|
||||
var intent = r.Resolve("weather today");
|
||||
Assert.NotNull(intent);
|
||||
Assert.False(intent.IsUrl);
|
||||
Assert.Contains("bing.com/search", intent.Target);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void 알_수_없는_키워드는_검색어의_일부로_취급한다()
|
||||
{
|
||||
// "zzz query" — zzz 는 등록된 키워드가 아님 → 전체가 기본 엔진 검색어
|
||||
var intent = _resolver.Resolve("zzz query");
|
||||
Assert.NotNull(intent);
|
||||
Assert.False(intent.IsUrl);
|
||||
Assert.Contains("zzz+query", intent.Target);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void 키워드_단독_입력은_검색어로_취급한다()
|
||||
{
|
||||
var intent = _resolver.Resolve("g");
|
||||
Assert.NotNull(intent);
|
||||
Assert.False(intent.IsUrl);
|
||||
Assert.EndsWith("q=g", intent.Target); // "g" 자체를 기본 엔진으로 검색
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void 커스텀_엔진_키워드를_등록하면_사용_가능하다()
|
||||
{
|
||||
var r = new SearchEngineResolver("Google", customEngines:
|
||||
new[] { new SearchEngine("Wikipedia", "w", "https://en.wikipedia.org/wiki/Special:Search?search={0}") });
|
||||
var intent = r.Resolve("w mars rover");
|
||||
Assert.NotNull(intent);
|
||||
Assert.False(intent.IsUrl);
|
||||
Assert.Contains("wikipedia.org", intent.Target);
|
||||
Assert.Equal("Wikipedia", intent.EngineName);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void 빈_입력은_Null을_반환한다()
|
||||
{
|
||||
Assert.Null(_resolver.Resolve(""));
|
||||
Assert.Null(_resolver.Resolve(" "));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void 프리셋에는_주요_엔진이_포함된다()
|
||||
{
|
||||
var names = SearchEngines.Presets.Select(e => e.Name).ToList();
|
||||
Assert.Contains("Google", names);
|
||||
Assert.Contains("Bing", names);
|
||||
Assert.Contains("DuckDuckGo", names);
|
||||
Assert.Contains("Naver", names); // 한국 사용자
|
||||
Assert.Contains("YouTube", names);
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue