89 lines
3.6 KiB
C#
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);
|
|
}
|
|
}
|