refactor(P5b-1): CommunityToolkit.Mvvm 도입 + OptionsViewModel 추출 (옵션 로직 테스트화)
MVVM 첫 슬라이스 — 테스트 불가능했던 코드비하인드 BuildOptions의 순수 옵션 구성 로직을 헤드리스 단위테스트 가능한 OptionsViewModel.ToConvertOptions로 추출. XAML 바인딩 미변경(런타임 위험 0). - CommunityToolkit.Mvvm 8.2.2(CPM) + App.csproj. App/ViewModels/OptionsViewModel.cs: ObservableObject + [ObservableProperty](Quality/CustomOutputDirectory/ConflictRule/AiTaskIndex/ TargetLanguage/VideoPreferGpu) → 향후 옵션 패널 직접 바인딩 토대. ToConvertOptions()는 순수. - MainWindow.BuildOptions: 컨트롤 값을 VM에 반영 후 ToConvertOptions() 위임(동작 동일). - Tests → App ProjectReference 추가(App 뷰모델 헤드리스 테스트 가능화). - OptionsViewModelTests 10케이스(품질매핑·AVIF clamp·커스텀폴더 trim·AI작업·대상언어·충돌/GPU). 71 → 81개 테스트 전부 그린, 빌드 0경고/0오류.
This commit is contained in:
parent
729b9b699d
commit
ba5738e705
6 changed files with 136 additions and 29 deletions
|
|
@ -18,6 +18,7 @@
|
|||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Everything2Everything.Core\Everything2Everything.Core.csproj" />
|
||||
<ProjectReference Include="..\Everything2Everything.App\Everything2Everything.App.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
|
|||
68
src/Everything2Everything.Tests/OptionsViewModelTests.cs
Normal file
68
src/Everything2Everything.Tests/OptionsViewModelTests.cs
Normal file
|
|
@ -0,0 +1,68 @@
|
|||
using Everything2Everything.App.ViewModels;
|
||||
using Everything2Everything.Core;
|
||||
using Xunit;
|
||||
|
||||
namespace Everything2Everything.Tests;
|
||||
|
||||
/// <summary>
|
||||
/// OptionsViewModel.ToConvertOptions 단위 테스트 — 기존 MainWindow.BuildOptions(코드비하인드, 테스트 불가)에서
|
||||
/// 추출한 순수 옵션 구성 로직을 헤드리스로 검증(P5b MVVM). UI 컨트롤 읽기와 분리되어 회귀를 기계적으로 방어.
|
||||
/// </summary>
|
||||
public class OptionsViewModelTests
|
||||
{
|
||||
[Fact]
|
||||
public void ToConvertOptions_MapsQualityToImageFormats()
|
||||
{
|
||||
var o = new OptionsViewModel { Quality = 70 }.ToConvertOptions();
|
||||
Assert.Equal(70, o.Jpeg.Quality);
|
||||
Assert.Equal(70, o.Webp.Quality);
|
||||
Assert.Equal(40, o.Avif.Quality); // AVIF = Quality - 30
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ToConvertOptions_AvifQualityClampedToFloor()
|
||||
{
|
||||
Assert.Equal(1, new OptionsViewModel { Quality = 10 }.ToConvertOptions().Avif.Quality);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ToConvertOptions_EmptyCustomDir_UsesSubfolder()
|
||||
{
|
||||
var o = new OptionsViewModel { CustomOutputDirectory = " " }.ToConvertOptions();
|
||||
Assert.Equal(OutputLocation.SubfolderBesideSource, o.OutputLocation);
|
||||
Assert.Null(o.CustomOutputDirectory);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ToConvertOptions_CustomDir_TrimmedAndCustomLocation()
|
||||
{
|
||||
var o = new OptionsViewModel { CustomOutputDirectory = " C:\\out " }.ToConvertOptions();
|
||||
Assert.Equal(OutputLocation.Custom, o.OutputLocation);
|
||||
Assert.Equal("C:\\out", o.CustomOutputDirectory);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(0, "summarize")]
|
||||
[InlineData(1, "translate")]
|
||||
[InlineData(2, "proofread")]
|
||||
[InlineData(99, "summarize")]
|
||||
public void ToConvertOptions_MapsAiTask(int index, string expected)
|
||||
{
|
||||
Assert.Equal(expected, new OptionsViewModel { AiTaskIndex = index }.ToConvertOptions().Ai.Task);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ToConvertOptions_TargetLanguage_EmptyBecomesNullElseTrimmed()
|
||||
{
|
||||
Assert.Null(new OptionsViewModel { TargetLanguage = " " }.ToConvertOptions().Ai.TargetLanguage);
|
||||
Assert.Equal("일본어", new OptionsViewModel { TargetLanguage = " 일본어 " }.ToConvertOptions().Ai.TargetLanguage);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ToConvertOptions_PassesConflictAndGpu()
|
||||
{
|
||||
var o = new OptionsViewModel { ConflictRule = NameCollision.Skip, VideoPreferGpu = false }.ToConvertOptions();
|
||||
Assert.Equal(NameCollision.Skip, o.OnCollision);
|
||||
Assert.False(o.VideoPreferGpu);
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue