releases/tests/Paca.Tests/Platform/AvaloniaShellGateTests.cs

89 lines
3.6 KiB
C#

using System.IO;
using System.Text.RegularExpressions;
using Xunit;
namespace Paca.Tests.Platform;
/// <summary>
/// Avalonia 크로스플랫폼 셸 회귀 방지 게이트 테스트 (Phase 5).
/// AVLN5001 경고 회귀 방어, MVVM 데이터 바인딩 무결성, URL 분류 로직 검증.
/// </summary>
public class AvaloniaShellGateTests
{
private static string GetSolutionRoot()
{
var dir = AppContext.BaseDirectory;
while (!string.IsNullOrEmpty(dir) && !File.Exists(Path.Combine(dir, "Paca.slnx")) && !File.Exists(Path.Combine(dir, "Paca.sln")))
{
var parent = Directory.GetParent(dir);
if (parent == null) break;
dir = parent.FullName;
}
return dir ?? AppContext.BaseDirectory;
}
private static string AvaloniaProjectDir => Path.Combine(GetSolutionRoot(), "src", "Paca.Avalonia");
[Fact]
public void Gate_MainWindow_Axaml_Complies_With_Modern_Avalonia_Standards()
{
var axamlPath = Path.Combine(AvaloniaProjectDir, "MainWindow.axaml");
Assert.True(File.Exists(axamlPath), $"MainWindow.axaml must exist at {axamlPath}");
var axamlContent = File.ReadAllText(axamlPath);
// AVLN5001 방어: Obsolete Watermark 속성 사용 금지
Assert.DoesNotContain("Watermark=", axamlContent);
// PlaceholderText 속성 사용 확인
Assert.Contains("PlaceholderText=", axamlContent);
// 핵심 MVVM 바인딩 요소 존재 검증
Assert.Contains("{Binding Url", axamlContent);
Assert.Contains("{Binding Status", axamlContent);
Assert.Contains("{Binding Progress", axamlContent);
Assert.Contains("{Binding DownloadCommand}", axamlContent);
Assert.Contains("{Binding CancelCommand}", axamlContent);
}
[Fact]
public void Gate_MainViewModel_Contains_All_Required_Contracts()
{
var vmPath = Path.Combine(AvaloniaProjectDir, "MainViewModel.cs");
Assert.True(File.Exists(vmPath), $"MainViewModel.cs must exist at {vmPath}");
var vmContent = File.ReadAllText(vmPath);
// INotifyPropertyChanged 구현 및 RelayCommand 검증
Assert.Contains("INotifyPropertyChanged", vmContent);
Assert.Contains("RelayCommand", vmContent);
Assert.Contains("DownloadCommand", vmContent);
Assert.Contains("CancelCommand", vmContent);
Assert.Contains("DownloadByKindAsync", vmContent);
Assert.Contains("Classify", vmContent);
// 4대 스트림 타입 분기 검증
Assert.Contains("Kind.Social", vmContent);
Assert.Contains("Kind.Hls", vmContent);
Assert.Contains("Kind.Dash", vmContent);
Assert.Contains("Kind.Direct", vmContent);
}
[Theory]
[InlineData("https://www.youtube.com/watch?v=dQw4w9WgXcQ", "Social")]
[InlineData("https://youtu.be/dQw4w9WgXcQ", "Social")]
[InlineData("https://instagram.com/reel/123456", "Social")]
[InlineData("https://tiktok.com/@user/video/12345", "Social")]
[InlineData("https://x.com/user/status/12345", "Social")]
[InlineData("https://twitter.com/user/status/12345", "Social")]
[InlineData("https://example.com/video/master.m3u8", "Hls")]
[InlineData("https://example.com/stream/manifest.mpd", "Dash")]
[InlineData("https://example.com/files/video.mp4", "Direct")]
public void Gate_Url_Classification_Matches_Expected_Kind(string rawUrl, string expectedKind)
{
var uri = new Uri(rawUrl);
var actualKind = Paca.Avalonia.MainViewModel.Classify(uri).ToString();
Assert.Equal(expectedKind, actualKind);
}
}