데스크톱 T3 잔여 완성 + 스타일 폴리시: 도메인 라우팅(WorkspaceRoutingRules 자동 워크스페이스 전환), 탭 아카이브(TabArchive 영속·팔레트 복구), 페이지 액션(흑백/세피아 필터), 노트 패널(NotesStore+플라이아웃), 컴팩트 모드(크롬 숨김+엣지 호버). 스타일: 한국어 폰트 폴백, 암시 폰트 통일, 다크 툴팁, 텍스트 대비 상향. UpdateNavState dispose 가드. 164/164 GREEN + 실창 스크린샷 검증
This commit is contained in:
parent
04ff0ff93d
commit
f380518919
12 changed files with 594 additions and 24 deletions
130
VideoDownloader.Tests/Browser/DesktopRemainderTests.cs
Normal file
130
VideoDownloader.Tests/Browser/DesktopRemainderTests.cs
Normal file
|
|
@ -0,0 +1,130 @@
|
|||
using VideoDownloader.App.Browser.Features;
|
||||
using VideoDownloader.Browser;
|
||||
|
||||
namespace VideoDownloader.Tests.Browser;
|
||||
|
||||
/// <summary>데스크톱 T3 잔여 — 워크스페이스 라우팅(T3-1), 탭 아카이브(T3-2), 노트(T3-12).</summary>
|
||||
public class DesktopRemainderTests : IDisposable
|
||||
{
|
||||
private readonly string _dir = Path.Combine(Path.GetTempPath(), $"vd_t3_{Guid.NewGuid():N}");
|
||||
|
||||
// ── T3-1: 도메인 → 워크스페이스 자동 라우팅 규칙 ──
|
||||
|
||||
[Fact]
|
||||
public void 라우팅_규칙_도메인_매칭()
|
||||
{
|
||||
var rules = new WorkspaceRoutingRules(Path.Combine(_dir, "routing.json"));
|
||||
rules.Add("youtube.com", "영상");
|
||||
Assert.Equal("영상", rules.Match("https://www.youtube.com/watch?v=1")); // www 정규화
|
||||
Assert.Equal("영상", rules.Match("https://m.youtube.com/watch?v=1")); // 서브도메인
|
||||
Assert.Null(rules.Match("https://example.com")); // 무관 도메인
|
||||
Assert.Null(rules.Match("about:blank")); // 비 HTTP
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void 라우팅_규칙_영속_및_제거()
|
||||
{
|
||||
var p = Path.Combine(_dir, "routing.json");
|
||||
new WorkspaceRoutingRules(p).Add("x.com", "SNS");
|
||||
var reloaded = new WorkspaceRoutingRules(p); // 재시작
|
||||
Assert.Equal("SNS", reloaded.Match("https://x.com/home"));
|
||||
reloaded.Remove("x.com");
|
||||
Assert.Null(reloaded.Match("https://x.com/home"));
|
||||
}
|
||||
|
||||
// ── T3-2: 탭 아카이브(닫힘 이력 영속·검색·중복 제거) ──
|
||||
|
||||
[Fact]
|
||||
public void 아카이브_기록_검색_중복제거()
|
||||
{
|
||||
var arc = new TabArchive(Path.Combine(_dir, "archive.json"));
|
||||
arc.Add("영상1", "https://a.com/1");
|
||||
arc.Add("영상1 다시", "https://a.com/1"); // 같은 URL 연속 → 제목만 갱신
|
||||
arc.Add("문서", "https://b.com/doc");
|
||||
Assert.Single(arc.Search("a.com/1"));
|
||||
Assert.Equal("영상1 다시", arc.Search("a.com/1")[0].Title);
|
||||
Assert.Single(arc.Search("문서"));
|
||||
Assert.Equal(2, arc.Search("").Count);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void 아카이브_영속_삭제()
|
||||
{
|
||||
var p = Path.Combine(_dir, "archive.json");
|
||||
var arc = new TabArchive(p);
|
||||
arc.Add("t", "https://x.com");
|
||||
var re = new TabArchive(p);
|
||||
Assert.Single(re.Search("x.com"));
|
||||
re.Remove("https://x.com");
|
||||
Assert.Empty(new TabArchive(p).Search("x.com"));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void 아카이브_최대_500_제한()
|
||||
{
|
||||
var arc = new TabArchive(Path.Combine(_dir, "archive.json"));
|
||||
for (var i = 0; i < 520; i++) arc.Add($"t{i}", $"https://x.com/{i}");
|
||||
Assert.Equal(500, arc.Search("").Count);
|
||||
Assert.Equal("t519", arc.Search("")[0].Title); // 최신이 앞
|
||||
}
|
||||
|
||||
// ── T3-12: 노트 저장소 ──
|
||||
|
||||
[Fact]
|
||||
public void 노트_추가_목록_삭제_영속()
|
||||
{
|
||||
var p = Path.Combine(_dir, "notes.json");
|
||||
var notes = new NotesStore(p);
|
||||
var id = notes.Add("제목", "본문 내용");
|
||||
Assert.Single(notes.List());
|
||||
Assert.Equal(("제목", "본문 내용"), (notes.List()[0].Title, notes.List()[0].Body));
|
||||
|
||||
var re = new NotesStore(p); // 재시작
|
||||
Assert.Single(re.List());
|
||||
re.Delete(id);
|
||||
Assert.Empty(new NotesStore(p).List());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void 노트_검색()
|
||||
{
|
||||
var notes = new NotesStore(Path.Combine(_dir, "notes.json"));
|
||||
notes.Add("유튜브 모음", "링크들");
|
||||
notes.Add("회의록", "유튜브 언급됨");
|
||||
Assert.Equal(2, notes.Search("유튜브").Count);
|
||||
Assert.Single(notes.Search("회의"));
|
||||
}
|
||||
|
||||
|
||||
// ── T3-6: 페이지 액션 — 흑백/세피아 CSS 필터(Vivaldi Page Actions, Boost 통합) ──
|
||||
|
||||
[Fact]
|
||||
public void 페이지액션_흑백_CSS_생성()
|
||||
{
|
||||
var js = VideoDownloader.App.Browser.Features.BoostCssBuilder.BuildScript(
|
||||
"https://x.com", new VideoDownloader.App.Browser.Features.BoostSettings(false, "", PageFilter.Grayscale));
|
||||
Assert.Contains("grayscale(1)", js);
|
||||
Assert.DoesNotContain("invert(1)", js);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void 페이지액션_세피아_CSS_생성()
|
||||
{
|
||||
var js = VideoDownloader.App.Browser.Features.BoostCssBuilder.BuildScript(
|
||||
"https://x.com", new VideoDownloader.App.Browser.Features.BoostSettings(false, "", PageFilter.Sepia));
|
||||
Assert.Contains("sepia(", js);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void 페이지액션_미적용_시_빈_스크립트()
|
||||
{
|
||||
var js = VideoDownloader.App.Browser.Features.BoostCssBuilder.BuildScript(
|
||||
"https://x.com", new VideoDownloader.App.Browser.Features.BoostSettings(false, "", PageFilter.None));
|
||||
Assert.Equal("", js);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
try { Directory.Delete(_dir, true); } catch { }
|
||||
}
|
||||
}
|
||||
|
|
@ -68,9 +68,53 @@ public class MainWindowSmokeE2ETests
|
|||
window.ToggleFullscreen();
|
||||
var toolbarBack = window.ToolbarRow.Visibility == Visibility.Visible;
|
||||
|
||||
// ── T3-13 컴팩트 모드: 크롬 행 높이 0 → 해제 시 복원 ──
|
||||
window.ToggleCompactMode();
|
||||
var compactRowZero = window.MainGrid.RowDefinitions[0].Height.Value == 0;
|
||||
window.ToggleCompactMode();
|
||||
var compactRowBack = window.MainGrid.RowDefinitions[0].Height.IsAuto;
|
||||
|
||||
// ── T3-12 노트: 패널 열림 + 현재 페이지 추가 → 목록 1건 ──
|
||||
window.ToggleNotes();
|
||||
var notesOpen = window.NotesPopup.IsOpen;
|
||||
window.NotesAddPage_Click(window, new RoutedEventArgs());
|
||||
var notesCount = window.Notes.List().Count;
|
||||
window.NotesPopup.IsOpen = false;
|
||||
|
||||
// ── T3-2 아카이브: 위에서 닫았던 탭이 영속 아카이브에 기록 ──
|
||||
// ── T3-2 아카이브: URL 있는 탭을 닫으면 영속 아카이브에 기록 ──
|
||||
var tab3 = window.Tabs.NewTab();
|
||||
await Wait.Until(() => Task.FromResult(tab3.Core), c => c != null, 30000);
|
||||
tab3.Url = "https://e2e.test/archived-page"; // URL 확정 상태 시뮬레이션(실제는 SourceChanged 가 설정)
|
||||
window.Tabs.CloseTab(tab3);
|
||||
await Task.Delay(800); // 진행 중이던 초기 네비게이션 이벤트가 dispose 이후 터지지 않게 여유
|
||||
var archivedCount = window.Archive.Search("").Count;
|
||||
var archivedHasUrl = window.Archive.Search("").Any(a => a.Url.Contains("e2e.test"));
|
||||
|
||||
// ── T3-6 페이지 액션: 실제 HTTP 문서에서 흑백 적용 → 부스트 저장 ──
|
||||
var port = Random.Shared.Next(21000, 59000);
|
||||
using var server = new System.Net.HttpListener();
|
||||
server.Prefixes.Add($"http://127.0.0.1:{port}/");
|
||||
server.Start();
|
||||
var serveTask = Task.Run(async () =>
|
||||
{
|
||||
var ctx = await server.GetContextAsync();
|
||||
var bytes = System.Text.Encoding.UTF8.GetBytes("<html><body><p>page-action-e2e</p></body></html>");
|
||||
await ctx.Response.OutputStream.WriteAsync(bytes);
|
||||
ctx.Response.Close();
|
||||
});
|
||||
window.Tabs.Activate(first);
|
||||
cv1.Navigate($"http://127.0.0.1:{port}/");
|
||||
await Wait.Until(() => Task.FromResult(cv1.Source ?? ""), s => s.Contains("127.0.0.1"), 15000);
|
||||
await serveTask.WaitAsync(TimeSpan.FromSeconds(10));
|
||||
window.ApplyPageFilter(VideoDownloader.App.Browser.Features.PageFilter.Grayscale);
|
||||
var filterSaved = window.BoostStore.Get($"http://127.0.0.1:{port}/").Filter;
|
||||
server.Stop();
|
||||
|
||||
window.Close();
|
||||
return (init: true, switched, countAfterClose, reopened: reopened != null, countAfterReopen,
|
||||
findVisible, findCollapsed, toolbarHidden, toolbarBack);
|
||||
findVisible, findCollapsed, toolbarHidden, toolbarBack,
|
||||
compactRowZero, compactRowBack, notesOpen, notesCount, archivedCount, archivedHasUrl, filterSaved);
|
||||
});
|
||||
|
||||
Assert.True(ok.init, "WebView2 초기화 실패");
|
||||
|
|
@ -82,6 +126,12 @@ public class MainWindowSmokeE2ETests
|
|||
Assert.True(ok.findCollapsed, "검색 바 미닫힘");
|
||||
Assert.True(ok.toolbarHidden, "전체화면에서 크롬 미숨김");
|
||||
Assert.True(ok.toolbarBack, "전체화면 복원 실패");
|
||||
Assert.True(ok.compactRowZero, "컴팩트 모드에서 크롬 행이 숨겨지지 않음");
|
||||
Assert.True(ok.compactRowBack, "컴팩트 모드 해제 후 크롬 행 미복원");
|
||||
Assert.True(ok.notesOpen, "노트 패널 미열림");
|
||||
Assert.True(ok.notesCount == 1, $"노트 추가 실패: {ok.notesCount}");
|
||||
Assert.True(ok.archivedCount >= 1 && ok.archivedHasUrl, $"탭 아카이브 미기록: {ok.archivedCount}");
|
||||
Assert.Equal(VideoDownloader.App.Browser.Features.PageFilter.Grayscale, ok.filterSaved);
|
||||
}
|
||||
finally
|
||||
{
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue