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
147
tests/Paca.Tests/Browser/ChromeParityNavigationAndToolsTests.cs
Normal file
147
tests/Paca.Tests/Browser/ChromeParityNavigationAndToolsTests.cs
Normal file
|
|
@ -0,0 +1,147 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using Paca.Browser;
|
||||
using Paca.Browser.Tabs;
|
||||
using Paca.Tests.Infrastructure;
|
||||
using Xunit;
|
||||
|
||||
namespace Paca.Tests.Browser;
|
||||
|
||||
public class ChromeParityNavigationAndToolsTests
|
||||
{
|
||||
// =========================================================================
|
||||
// 1. 소스 보기 (View Page Source in New Tab)
|
||||
// =========================================================================
|
||||
[Fact]
|
||||
public void ViewSourceInNewTab_기존_탭을_보존하고_우측에_새_소스_탭을_생성한다()
|
||||
{
|
||||
var mgr = new TabManager(() => new TabItem());
|
||||
var original = mgr.NewTab("https://github.com/Paca");
|
||||
original.Title = "GitHub - Paca";
|
||||
|
||||
// 소스 보기 전용 탭 생성 헬퍼
|
||||
var sourceTab = mgr.NewTabAfter(original, "view-source:" + original.Url, activate: true);
|
||||
sourceTab.Title = $"소스: {original.Title}";
|
||||
|
||||
Assert.Equal(2, mgr.Tabs.Count);
|
||||
Assert.Equal(original, mgr.Tabs[0]);
|
||||
Assert.Equal(sourceTab, mgr.Tabs[1]);
|
||||
Assert.Equal("view-source:https://github.com/Paca", sourceTab.Url);
|
||||
Assert.Equal("소스: GitHub - Paca", sourceTab.Title);
|
||||
Assert.Same(sourceTab, mgr.ActiveTab);
|
||||
}
|
||||
|
||||
// =========================================================================
|
||||
// 2. 인터넷 사용 기록 삭제 (Clear Browsing Data Filter & Range)
|
||||
// =========================================================================
|
||||
[Fact]
|
||||
public void BrowsingDataCleaner_시간_범위별_기준시각을_정확히_산출한다()
|
||||
{
|
||||
var now = new DateTime(2026, 9, 9, 15, 0, 0, DateTimeKind.Utc);
|
||||
|
||||
Assert.Equal(now.AddHours(-1), BrowsingDataCleaner.CalculateCutoff(ClearBrowsingTimeRange.LastHour, now));
|
||||
Assert.Equal(now.AddHours(-24), BrowsingDataCleaner.CalculateCutoff(ClearBrowsingTimeRange.Last24Hours, now));
|
||||
Assert.Equal(now.AddDays(-7), BrowsingDataCleaner.CalculateCutoff(ClearBrowsingTimeRange.Last7Days, now));
|
||||
Assert.Equal(now.AddDays(-28), BrowsingDataCleaner.CalculateCutoff(ClearBrowsingTimeRange.Last4Weeks, now));
|
||||
Assert.Null(BrowsingDataCleaner.CalculateCutoff(ClearBrowsingTimeRange.AllTime, now));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void BrowsingDataCleaner_시간_범위_기준으로_방문_기록을_정밀_필터링하여_삭제한다()
|
||||
{
|
||||
var now = new DateTime(2026, 9, 9, 15, 0, 0, DateTimeKind.Utc);
|
||||
var history = new List<HistoryEntry>
|
||||
{
|
||||
new("10분 전", "https://recent.com", now.AddMinutes(-10)),
|
||||
new("3시간 전", "https://earlier.com", now.AddHours(-3)),
|
||||
new("2일 전", "https://old.com", now.AddDays(-2)),
|
||||
new("한달 전", "https://ancient.com", now.AddDays(-30))
|
||||
};
|
||||
|
||||
// 지난 1시간 삭제 -> 10분 전 기록만 삭제되고 나머지는 보존
|
||||
var remainingAfter1Hour = BrowsingDataCleaner.FilterHistory(history, ClearBrowsingTimeRange.LastHour, now);
|
||||
Assert.Equal(3, remainingAfter1Hour.Count);
|
||||
Assert.DoesNotContain(remainingAfter1Hour, h => h.Url == "https://recent.com");
|
||||
Assert.Contains(remainingAfter1Hour, h => h.Url == "https://earlier.com");
|
||||
|
||||
// 지난 24시간 삭제 -> 10분 전, 3시간 전 삭제, 2일 전/한달 전 보존
|
||||
var remainingAfter24Hours = BrowsingDataCleaner.FilterHistory(history, ClearBrowsingTimeRange.Last24Hours, now);
|
||||
Assert.Equal(2, remainingAfter24Hours.Count);
|
||||
Assert.DoesNotContain(remainingAfter24Hours, h => h.Url == "https://earlier.com");
|
||||
Assert.Contains(remainingAfter24Hours, h => h.Url == "https://old.com");
|
||||
|
||||
// 전체 기간 삭제 -> 모든 기록 제거
|
||||
var remainingAfterAll = BrowsingDataCleaner.FilterHistory(history, ClearBrowsingTimeRange.AllTime, now);
|
||||
Assert.Empty(remainingAfterAll);
|
||||
}
|
||||
|
||||
// =========================================================================
|
||||
// 3. 주소창 QR 코드 생성기 (Chrome Parity URL QR Code Generator)
|
||||
// =========================================================================
|
||||
[Fact]
|
||||
public void QrCodeSvgGenerator_유효한_URL_입력시_규격_SVG_마크업을_반환한다()
|
||||
{
|
||||
string testUrl = "https://github.com/Paca/browser";
|
||||
string svg = QrCodeSvgGenerator.GenerateSvg(testUrl, size: 240);
|
||||
|
||||
Assert.NotNull(svg);
|
||||
Assert.StartsWith("<svg", svg.Trim());
|
||||
Assert.EndsWith("</svg>", svg.Trim());
|
||||
Assert.Contains("width=\"240\"", svg);
|
||||
Assert.Contains("height=\"240\"", svg);
|
||||
Assert.Contains("<rect", svg); // QR 코드 모듈(사각형) 렌더링 검증
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void QrCodeSvgGenerator_빈_문자열_또는_공백_입력시_빈_SVG_또는_안전_마크업_반환()
|
||||
{
|
||||
string svg = QrCodeSvgGenerator.GenerateSvg("", size: 200);
|
||||
Assert.NotNull(svg);
|
||||
Assert.Contains("<svg", svg);
|
||||
}
|
||||
|
||||
// =========================================================================
|
||||
// 4. 크롬 작업 관리자 (Chrome Browser Task Manager: Shift+Esc)
|
||||
// =========================================================================
|
||||
[Fact]
|
||||
public void BrowserTaskManager_열린_탭과_백그라운드_프로세스_목록을_정상_수집한다()
|
||||
{
|
||||
var tabMgr = new TabManager(() => new TabItem());
|
||||
var tab1 = tabMgr.NewTab("https://github.com");
|
||||
tab1.Title = "GitHub";
|
||||
var tab2 = tabMgr.NewTab("https://youtube.com");
|
||||
tab2.Title = "YouTube";
|
||||
|
||||
var tasks = BrowserTaskManager.CollectTasks(tabMgr);
|
||||
|
||||
// 최소 브라우저 메인 프로세스 1개 + 탭 2개 = 3개 태스크
|
||||
Assert.True(tasks.Count >= 3);
|
||||
|
||||
var mainProcess = tasks.FirstOrDefault(t => t.Type == BrowserTaskType.Browser);
|
||||
Assert.NotNull(mainProcess);
|
||||
Assert.Equal("브라우저 (Paca)", mainProcess!.Title);
|
||||
|
||||
var tabTasks = tasks.Where(t => t.Type == BrowserTaskType.Tab).ToList();
|
||||
Assert.Equal(2, tabTasks.Count);
|
||||
Assert.Contains(tabTasks, t => t.Title == "GitHub");
|
||||
Assert.Contains(tabTasks, t => t.Title == "YouTube");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void BrowserTaskManager_EndTask_호출시_해당_탭을_안전하게_종료한다()
|
||||
{
|
||||
var tabMgr = new TabManager(() => new TabItem());
|
||||
var tab1 = tabMgr.NewTab("https://tab1.com");
|
||||
var tab2 = tabMgr.NewTab("https://tab2.com");
|
||||
|
||||
var tasks = BrowserTaskManager.CollectTasks(tabMgr);
|
||||
var taskToKill = tasks.First(t => t.Title == "tab2.com" || t.Url == "https://tab2.com");
|
||||
|
||||
bool success = BrowserTaskManager.EndTask(taskToKill, tabMgr);
|
||||
Assert.True(success);
|
||||
Assert.Single(tabMgr.Tabs);
|
||||
Assert.Equal(tab1, tabMgr.Tabs[0]);
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue