UI 복잡 버전 234 RED→GREEN 완료(docs/UI_USECASES.md §A~§J): 라이브 테마 전환(DynamicResource 전환+ThemeResolver+HighContrast 테마, 재시작 없음), 디자인 토큰 체계·WCAG 대비 결함 5건 수정, 설정창 카테고리 내비/검색 재구성+AppConfig 40여 속성, 다운로드 관리자(속도/ETA/세그먼트맵/전체 일시정지-이어받기/CSV 내보내기/예약 게이트/중복 확인), 라이브러리·아카이브·작업공간·재생목록·즐겨찾기 편집 뷰, 접근성(자동화 속성 30여 개·커스텀 피어·docs/ACCESSIBILITY.md), 인터랙션(휠 클릭 새 탭·XButton 탐색·F12·영역 캡처·프로필 전환), 상태/알림(토스트·알림센터·온보딩·CrashReportDialog). 보강 테스트 35건+실창 E2E 4건(StaDispatcher 기반 — 프록시 설정이 기시작 핸들러를 건드리는 크래시 실결함 수정 포함) — 453/453 GREEN. 이전 미커밋 작업(CI 워크플로·Mdns·QueueHub·UpdateChecker·AGENTS/CLAUDE·빌드 스크립트) 일괄 포함

This commit is contained in:
Yun Chan 2026-08-17 15:54:53 +09:00
parent 5a0ce730b2
commit 17f2f91152
88 changed files with 9463 additions and 1127 deletions

View file

@ -0,0 +1,194 @@
using VideoDownloader.App;
using VideoDownloader.App.Browser.Features;
using VideoDownloader.App.ViewModels;
using VideoDownloader.Core.Config;
using VideoDownloader.Tests.Infrastructure;
namespace VideoDownloader.Tests.E2E;
/// <summary>
/// UI 복잡 버전 RED 스펙 — §E 다운로드 관리자 유즈케이스(docs/UI_USECASES.md §E, UC-D01~D30).
/// RED 단계: 전부 실패하는 것이 정상이다.
/// </summary>
public class UiUsecaseDownloadsRedTests
{
[Fact]
public void UC_D01_다운로드_정렬_순서를_설정할_수_있다()
=> SourceTree.Usecase(
SourceTree.PropertyExists(typeof(AppConfig), "DownloadSortOrder"),
"UC-D01", "AppConfig.DownloadSortOrder 속성이 필요하다");
[Fact]
public void UC_D02_진행중_완료_실패_필터_탭이_있다()
=> SourceTree.Usecase(
SourceTree.MainWindowXaml.Contains("DownloadFilterTabs"),
"UC-D02", "다운로드 필터 탭(DownloadFilterTabs) 요소가 필요하다");
[Fact]
public void UC_D03_다운로드_목록을_검색할_수_있다()
=> SourceTree.Usecase(
SourceTree.MainWindowXaml.Contains("DownloadSearchBox"),
"UC-D03", "다운로드 검색 상자(DownloadSearchBox)가 필요하다");
[Fact]
public void UC_D04_남은_시간_ETA가_카드에_표시된다()
=> SourceTree.Usecase(
SourceTree.PropertyExists(typeof(DownloadItemViewModel), "RemainingText"),
"UC-D04", "다운로드 카드 VM 에 RemainingText(남은 시간) 속성이 필요하다");
[Fact]
public void UC_D05_현재_속도가_카드에_표시된다()
=> SourceTree.Usecase(
SourceTree.PropertyExists(typeof(DownloadItemViewModel), "SpeedText"),
"UC-D05", "다운로드 카드 VM 에 SpeedText 속성이 필요하다");
[Fact]
public void UC_D06_전체_일시정지를_할_수_있다()
=> SourceTree.Usecase(
SourceTree.MethodExists(typeof(MainWindow), "PauseAllDownloads"),
"UC-D06", "MainWindow.PauseAllDownloads() 가 필요하다");
[Fact]
public void UC_D07_전체_재개를_할_수_있다()
=> SourceTree.Usecase(
SourceTree.MethodExists(typeof(MainWindow), "ResumeAllDownloads"),
"UC-D07", "MainWindow.ResumeAllDownloads() 가 필요하다");
[Fact]
public void UC_D08_완료_항목_자동_치움을_설정할_수_있다()
=> SourceTree.Usecase(
SourceTree.PropertyExists(typeof(AppConfig), "AutoClearCompleted"),
"UC-D08", "AppConfig.AutoClearCompleted 속성이 필요하다");
[Fact]
public void UC_D09_재시도_횟수가_카드에_표시된다()
=> SourceTree.Usecase(
SourceTree.PropertyExists(typeof(DownloadItemViewModel), "RetryCount"),
"UC-D09", "다운로드 카드 VM 에 RetryCount 속성이 필요하다");
[Fact]
public void UC_D10_세그먼트_진행이_시각화된다()
=> SourceTree.Usecase(
SourceTree.PropertyExists(typeof(DownloadItemViewModel), "SegmentMap"),
"UC-D10", "세그먼트별 진행 맵(SegmentMap) 속성이 필요하다");
[Fact]
public void UC_D11_토스트_알림_컴포넌트가_있다()
=> SourceTree.Usecase(
SourceTree.FindType("ToastNotifier") is not null,
"UC-D11", "다운로드 완료 알림을 담당하는 ToastNotifier 컴포넌트가 필요하다");
[Fact]
public void UC_D12_알림_소리를_설정할_수_있다()
=> SourceTree.Usecase(
SourceTree.PropertyExists(typeof(AppConfig), "NotifySound"),
"UC-D12", "AppConfig.NotifySound 속성이 필요하다");
[Fact]
public void UC_D13_완료_시_폴더_자동_열기를_설정할_수_있다()
=> SourceTree.Usecase(
SourceTree.PropertyExists(typeof(AppConfig), "OpenFolderOnComplete"),
"UC-D13", "AppConfig.OpenFolderOnComplete 속성이 필요하다");
[Fact]
public void UC_D14_카드_우클릭_컨텍스트_메뉴가_있다()
=> SourceTree.Usecase(
SourceTree.MainWindowXaml.Contains("CardContextMenu"),
"UC-D14", "다운로드 카드 컨텍스트 메뉴(CardContextMenu)가 필요하다");
[Fact]
public void UC_D15_카드를_펼쳐_상세_정보를_본다()
=> SourceTree.Usecase(
SourceTree.MainWindowXaml.Contains("CardDetailExpander"),
"UC-D15", "카드 상세 펼침(CardDetailExpander) 요소가 필요하다");
[Fact]
public void UC_D16_대기_현황_요약이_표시된다()
=> SourceTree.Usecase(
SourceTree.MainWindowXaml.Contains("QueueSummaryText"),
"UC-D16", "패널의 대기 현황 요약(QueueSummaryText)이 필요하다");
[Fact]
public void UC_D17_속도_스파크라인이_표시된다()
=> SourceTree.Usecase(
SourceTree.MainWindowXaml.Contains("SpeedSparkline"),
"UC-D17", "속도 추이 스파크라인(SpeedSparkline) 요소가 필요하다");
[Fact]
public void UC_D18_전체_속도_합계가_표시된다()
=> SourceTree.Usecase(
SourceTree.MainWindowXaml.Contains("GlobalSpeedText"),
"UC-D18", "전체 다운로드 속도(GlobalSpeedText) 표시가 필요하다");
[Fact]
public void UC_D19_파일_총_크기가_카드에_표시된다()
=> SourceTree.Usecase(
SourceTree.PropertyExists(typeof(DownloadItemViewModel), "TotalSizeText"),
"UC-D19", "카드 VM 에 TotalSizeText 속성이 필요하다");
[Fact]
public void UC_D20_자막_언어를_설정할_수_있다()
=> SourceTree.Usecase(
SourceTree.SettingsWindowXaml.Contains("SubtitleLangBox"),
"UC-D20", "설정창에 자막 언어 선택(SubtitleLangBox)이 필요하다");
[Fact]
public void UC_D21_다운로드_스케줄러가_있다()
=> SourceTree.Usecase(
SourceTree.FindType("DownloadScheduler") is not null,
"UC-D21", "시간대 예약을 담당하는 DownloadScheduler 컴포넌트가 필요하다");
[Fact]
public void UC_D22_속도_상한을_설정할_수_있다()
=> SourceTree.Usecase(
SourceTree.PropertyExists(typeof(AppConfig), "MaxDownloadSpeedKbps"),
"UC-D22", "AppConfig.MaxDownloadSpeedKbps 속성이 필요하다");
[Fact]
public void UC_D23_목록을_CSV로_내보낼_수_있다()
=> SourceTree.Usecase(
SourceTree.MethodExists(typeof(MainWindow), "ExportDownloads"),
"UC-D23", "MainWindow.ExportDownloads() 내보내기 기능이 필요하다");
[Fact]
public void UC_D24_항목_우선순위를_정할_수_있다()
=> SourceTree.Usecase(
SourceTree.PropertyExists(typeof(DownloadItemViewModel), "Priority"),
"UC-D24", "카드 VM 에 대기열 우선순위(Priority) 속성이 필요하다");
[Fact]
public void UC_D25_중복_다운로드_경고를_받는다()
=> SourceTree.Usecase(
SourceTree.MethodExists(typeof(MainWindow), "ConfirmDuplicateDownload"),
"UC-D25", "MainWindow.ConfirmDuplicateDownload() 확인 절차가 필요하다");
[Fact]
public void UC_D26_최종_저장_파일명이_카드에_표시된다()
=> SourceTree.Usecase(
SourceTree.PropertyExists(typeof(DownloadItemViewModel), "FinalFileName"),
"UC-D26", "카드 VM 에 충돌 회피 후 파일명(FinalFileName)이 필요하다");
[Fact]
public void UC_D27_오류_메시지_복사_버튼이_있다()
=> SourceTree.Usecase(
SourceTree.MainWindowXaml.Contains("CopyErrorButton"),
"UC-D27", "오류 복사 버튼(CopyErrorButton) 요소가 필요하다");
[Fact]
public void UC_D28_페이지_다운로드도_전체_일시정지가_된다()
=> SourceTree.Usecase(
SourceTree.MethodExists(typeof(PageDownloadTracker), "PauseAll"),
"UC-D28", "PageDownloadTracker.PauseAll() 메서드가 필요하다");
[Fact]
public void UC_D29_미디어_종류_배지가_표시된다()
=> SourceTree.Usecase(
SourceTree.MainWindowXaml.Contains("MediaKindBadge"),
"UC-D29", "감지 미디어 종류 배지(MediaKindBadge) 요소가 필요하다");
[Fact]
public void UC_D30_사이트별_그룹_헤더가_표시된다()
=> SourceTree.Usecase(
SourceTree.MainWindowXaml.Contains("SiteGroupHeader"),
"UC-D30", "사이트별 묶음 헤더(SiteGroupHeader) 요소가 필요하다");
}