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,142 @@
using VideoDownloader.Core.Config;
using VideoDownloader.Tests.Infrastructure;
namespace VideoDownloader.Tests.E2E;
/// <summary>
/// UI 복잡 버전 RED 스펙 — §G 접근성 유즈케이스(docs/UI_USECASES.md §G, UC-A01~A20).
/// RED 단계: 전부 실패하는 것이 정상이다.
/// </summary>
public class UiUsecaseAccessibilityRedTests
{
[Fact]
public void UC_A01_자동화_속성이_하나라도_사용된다()
=> SourceTree.Usecase(
SourceTree.MainWindowXaml.Contains("AutomationProperties"),
"UC-A01", "화면 낭독기 지원을 위한 AutomationProperties 사용이 필요하다");
[Fact]
public void UC_A02_주요_컨트롤에_자동화_이름이_부여된다()
{
var count = System.Text.RegularExpressions.Regex.Matches(SourceTree.MainWindowXaml, "AutomationProperties\\.Name").Count;
SourceTree.Usecase(
count >= 15,
$"UC-A02", $"주요 컨트롤 15개 이상에 AutomationProperties.Name 이 필요하다 (현재 {count}개)");
}
[Fact]
public void UC_A03_상태_변화가_낭독기에_자동_전달된다()
=> SourceTree.Usecase(
SourceTree.MainWindowXaml.Contains("LiveSetting"),
"UC-A03", "상태바·진행률의 LiveSetting 선언이 필요하다");
[Fact]
public void UC_A04_시스템_고대비_모드를_감지한다()
=> SourceTree.Usecase(
SourceTree.MainWindowCs.Contains("HighContrast"),
"UC-A04", "SystemParameters.HighContrast 감지 처리가 필요하다");
[Fact]
public void UC_A05_키보드_포커스_비주얼이_정의된다()
=> SourceTree.Usecase(
SourceTree.SharedXaml.Contains("FocusVisualStyle"),
"UC-A05", "공용 FocusVisualStyle 정의가 필요하다");
[Fact]
public void UC_A06_Tab_순서가_지정된다()
=> SourceTree.Usecase(
SourceTree.MainWindowXaml.Contains("TabIndex"),
"UC-A06", "논리적 Tab 이동을 위한 TabIndex 지정이 필요하다");
[Fact]
public void UC_A07_ToolTipService_설정이_사용된다()
=> SourceTree.Usecase(
SourceTree.MainWindowXaml.Contains("ToolTipService"),
"UC-A07", "툴팁 표시 시간 등 ToolTipService 설정이 필요하다");
[Fact]
public void UC_A08_접근_키_AccessText가_사용된다()
=> SourceTree.Usecase(
SourceTree.MainWindowXaml.Contains("AccessText"),
"UC-A08", "Alt 접근 키를 위한 AccessText 사용이 필요하다");
[Fact]
public void UC_A09_사용자_지정_자동화_피어가_있다()
=> SourceTree.Usecase(
SourceTree.MainWindowCs.Contains("AutomationPeer"),
"UC-A09", "목록·탭 컨트롤용 AutomationPeer 구현이 필요하다");
[Fact]
public void UC_A10_HelpText가_제공된다()
=> SourceTree.Usecase(
SourceTree.MainWindowXaml.Contains("AutomationProperties.HelpText"),
"UC-A10", "컨트롤 추가 설명 AutomationProperties.HelpText 가 필요하다");
[Fact]
public void UC_A11_완료_상태가_색과_무관하게_표시된다()
=> SourceTree.Usecase(
SourceTree.MainWindowXaml.Contains("SuccessIcon"),
"UC-A11", "완료 상태 아이콘(SuccessIcon)으로 색 무의존 표시가 필요하다");
[Fact]
public void UC_A12_접근성_설정_섹션이_있다()
=> SourceTree.Usecase(
SourceTree.SettingsWindowXaml.Contains("접근성"),
"UC-A12", "설정창에 '접근성' 섹션이 필요하다");
[Fact]
public void UC_A13_UI_확대_배율을_설정할_수_있다()
=> SourceTree.Usecase(
SourceTree.PropertyExists(typeof(AppConfig), "UiFontScale"),
"UC-A13", "저시력 지원용 AppConfig.UiFontScale 속성이 필요하다");
[Fact]
public void UC_A14_팝업_키보드_탐색이_설정된다()
=> SourceTree.Usecase(
SourceTree.MainWindowXaml.Contains("KeyboardNavigation.TabNavigation"),
"UC-A14", "팝업 내 키보드 탐색(KeyboardNavigation) 설정이 필요하다");
[Fact]
public void UC_A15_자막_표시_옵션이_있다()
=> SourceTree.Usecase(
SourceTree.PropertyExists(typeof(AppConfig), "ShowCaptions"),
"UC-A15", "AppConfig.ShowCaptions 속성이 필요하다");
[Fact]
public void UC_A16_애니메이션_감소_설정이_스타일에_반영된다()
=> SourceTree.Usecase(
SourceTree.SharedXaml.Contains("ReduceMotion"),
"UC-A16", "Shared.xaml 이 ReduceMotion 설정을 스타일에 반영해야 한다");
[Fact]
public void UC_A17_리더_모드_HTML에_언어가_선언된다()
=> SourceTree.Usecase(
SourceTree.ReaderModeCs.Contains("lang="),
"UC-A17", "리더 모드 HTML 에 lang=\"ko\" 선언이 필요하다");
[Fact]
public void UC_A18_접근성_선언_문서가_있다()
=> SourceTree.Usecase(
SourceTree.DocFileExists("ACCESSIBILITY.md"),
"UC-A18", "접근성 지원 범위 문서(docs/ACCESSIBILITY.md)가 필요하다");
[Fact]
public void UC_A19_라이트_진행_트랙이_배경과_구별된다()
{
var fg = SourceTree.BrushHex(SourceTree.ThemeLightXaml, "TrackBrush");
var bg = SourceTree.BrushHex(SourceTree.ThemeLightXaml, "PanelBg");
Assert.False(fg is null || bg is null, "UC-A19 — 테마 브러시 파싱 실패");
var ratio = SourceTree.ContrastRatio(fg!, bg!);
Assert.True(ratio >= 3.0, $"UC-A19 RED — 라이트 TrackBrush/PanelBg 대비 {ratio:F2}:1 < 3:1 (비텍스트 구성요소 기준)");
}
[Fact]
public void UC_A20_버튼_테두리가_카드_배경과_구별된다()
{
var fg = SourceTree.BrushHex(SourceTree.ThemeDarkXaml, "BorderBrush");
var bg = SourceTree.BrushHex(SourceTree.ThemeDarkXaml, "CardBg");
Assert.False(fg is null || bg is null, "UC-A20 — 테마 브러시 파싱 실패");
var ratio = SourceTree.ContrastRatio(fg!, bg!);
Assert.True(ratio >= 3.0, $"UC-A20 RED — 다크 BorderBrush/CardBg 대비 {ratio:F2}:1 < 3:1 (클릭 대상 식별 기준)");
}
}