feat(ads/seo/release): v1.2.0 with live Google Ads, isolated ad profile, ads.txt, and SEO/AEO/GEO optimization
This commit is contained in:
parent
a88aafa1e5
commit
0e568f1f0a
975 changed files with 130593 additions and 16783 deletions
89
tests/Paca.Tests/Platform/AvaloniaShellGateTests.cs
Normal file
89
tests/Paca.Tests/Platform/AvaloniaShellGateTests.cs
Normal file
|
|
@ -0,0 +1,89 @@
|
|||
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);
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue