85 lines
3.8 KiB
C#
85 lines
3.8 KiB
C#
using System.Windows;
|
|
using Microsoft.Web.WebView2.Core;
|
|
using VideoDownloader.App.Browser.Features;
|
|
using VideoDownloader.Browser.Tabs;
|
|
using VideoDownloader.Tests.Infrastructure;
|
|
|
|
namespace VideoDownloader.Tests.E2E;
|
|
|
|
/// <summary>
|
|
/// E2E (T2-4): 실제 WebView2 + 번들된 Mozilla Readability.js 로
|
|
/// 기사 페이지에서 본문을 추출해 리더 뷰로 교체하고 원본 URL 복귀까지 검증.
|
|
/// </summary>
|
|
[Collection("E2E")]
|
|
public class ReaderModeE2ETests
|
|
{
|
|
private const string ArticleHtml = """
|
|
<html><head><title>테스트 기사</title></head><body>
|
|
<nav>광고 광고 광고 내비게이션</nav>
|
|
<article>
|
|
<h1>리더 모드 E2E 기사</h1>
|
|
<p>첫 번째 문단입니다. 이 문단은 Readability 가 본문으로 추출해야 합니다. 충분한 길이의 텍스트가 필요하므로 몇 번 더 반복합니다. 본문 본문 본문.</p>
|
|
<p>두 번째 문단입니다. 리더 모드는 광고와 내비게이션을 제거하고 본문만 남깁니다. 추출 결과에 이 텍스트가 포함되어야 합니다.</p>
|
|
<p>세 번째 문단입니다. 문단이 세 개 이상이면 Readability 의 휴리스틱이 본문으로 판정합니다. 마커텍스트-고유문구-레인보우4747.</p>
|
|
</article>
|
|
<footer>푸터 링크 모음</footer>
|
|
</body></html>
|
|
""";
|
|
|
|
[Fact]
|
|
public async Task 기사를_리더로_추출하고_원본으로_복귀한다()
|
|
{
|
|
using var sta = StaDispatcher.Start();
|
|
var udf = Path.Combine(Path.GetTempPath(), $"vd_reader_{Guid.NewGuid():N}");
|
|
var ok = await sta.InvokeAsync(async () =>
|
|
{
|
|
var window = new Window();
|
|
var browser = new Microsoft.Web.WebView2.Wpf.WebView2();
|
|
window.Content = browser;
|
|
window.Show();
|
|
var env = await CoreWebView2Environment.CreateAsync(userDataFolder: udf);
|
|
await browser.EnsureCoreWebView2Async(env);
|
|
var cv = browser.CoreWebView2;
|
|
|
|
cv.NavigateToString(ArticleHtml);
|
|
await WaitNav(cv);
|
|
|
|
var tab = new TabItem { View = browser };
|
|
|
|
// 1) 리더 진입
|
|
var entered = await ReaderMode.ToggleAsync(tab, lightTheme: false);
|
|
await Wait.Until(() => Task.FromResult(cv.DocumentTitle ?? ""), t => t.Contains("테스트 기사"), 15000);
|
|
var titleAfter = cv.DocumentTitle ?? "";
|
|
var bodyText = await cv.ExecuteScriptAsync("document.body.innerText");
|
|
var hasMarker = bodyText.Contains("마커텍스트-고유문구-레인보우4747");
|
|
var hasNav = bodyText.Contains("광고 광고 광고");
|
|
var isReader = tab.IsReader;
|
|
var originalSaved = tab.ReaderOriginalUrl;
|
|
|
|
// 2) 복귀
|
|
var exited = await ReaderMode.ToggleAsync(tab, lightTheme: false);
|
|
var restoredReader = tab.IsReader == false;
|
|
|
|
window.Close();
|
|
return (entered: entered == true, titleAfter, hasMarker, navRemoved: !hasNav, isReader, originalSaved, exited: exited == false, restoredReader);
|
|
});
|
|
|
|
try { Directory.Delete(udf, true); } catch { }
|
|
Assert.True(ok.entered, "리더 진입 실패");
|
|
Assert.Contains("테스트 기사", ok.titleAfter);
|
|
Assert.True(ok.hasMarker, "본문 마커 누락");
|
|
Assert.True(ok.navRemoved, "내비/광고 제거 안됨");
|
|
Assert.True(ok.isReader);
|
|
Assert.True(ok.exited);
|
|
Assert.True(ok.restoredReader);
|
|
}
|
|
|
|
private static Task WaitNav(CoreWebView2 cv)
|
|
{
|
|
var tcs = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously);
|
|
EventHandler<CoreWebView2NavigationCompletedEventArgs>? h = null;
|
|
h = (_, _) => { cv.NavigationCompleted -= h; tcs.TrySetResult(); };
|
|
cv.NavigationCompleted += h;
|
|
return tcs.Task.WaitAsync(TimeSpan.FromSeconds(15));
|
|
}
|
|
}
|