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
151
tests/Paca.Tests/Mobile/MobileIntuitiveUxGateTests.cs
Normal file
151
tests/Paca.Tests/Mobile/MobileIntuitiveUxGateTests.cs
Normal file
|
|
@ -0,0 +1,151 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using Paca.Mobile.Core;
|
||||
using Xunit;
|
||||
|
||||
namespace Paca.Tests.Mobile;
|
||||
|
||||
/// <summary>
|
||||
/// 직관적 다운로드 큐, 다운로드 파일 브라우징, 필터링, 정렬 및 일괄 정리 게이트 (Gate 146 ~ Gate 152)
|
||||
/// </summary>
|
||||
public class MobileIntuitiveUxGateTests
|
||||
{
|
||||
[Fact]
|
||||
public void Gate146_MobileLibraryFileManager_Scan_Audit()
|
||||
{
|
||||
var manager = new MobileLibraryFileManager();
|
||||
var fakeFiles = new List<LocalDownloadedFile>
|
||||
{
|
||||
new("v1.mp4", "/storage/emulated/0/Download/v1.mp4", 1024 * 1024 * 50, DateTime.UtcNow.AddMinutes(-10), LocalMediaType.Video),
|
||||
new("a1.mp3", "/storage/emulated/0/Download/a1.mp3", 1024 * 1024 * 5, DateTime.UtcNow.AddMinutes(-5), LocalMediaType.Audio),
|
||||
new("doc.pdf", "/storage/emulated/0/Download/doc.pdf", 1024 * 100, DateTime.UtcNow, LocalMediaType.Other)
|
||||
};
|
||||
|
||||
manager.SetFiles(fakeFiles);
|
||||
Assert.Equal(3, manager.Files.Count);
|
||||
Assert.Equal("50.0 MB", fakeFiles[0].FormattedSize);
|
||||
Assert.Equal("5.0 MB", fakeFiles[1].FormattedSize);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Gate147_MobileLibraryFilterEngine_Category_Audit()
|
||||
{
|
||||
var filter = new MobileLibraryFilterEngine();
|
||||
var files = new List<LocalDownloadedFile>
|
||||
{
|
||||
new("vid1.mp4", "/path/vid1.mp4", 500, DateTime.UtcNow, LocalMediaType.Video),
|
||||
new("vid2.webm", "/path/vid2.webm", 300, DateTime.UtcNow, LocalMediaType.Video),
|
||||
new("song.mp3", "/path/song.mp3", 100, DateTime.UtcNow, LocalMediaType.Audio),
|
||||
new("podcast.m4a", "/path/podcast.m4a", 150, DateTime.UtcNow, LocalMediaType.Audio)
|
||||
};
|
||||
|
||||
var videos = filter.FilterByCategory(files, LibraryCategoryFilter.Video);
|
||||
Assert.Equal(2, videos.Count);
|
||||
Assert.All(videos, f => Assert.Equal(LocalMediaType.Video, f.Type));
|
||||
|
||||
var audios = filter.FilterByCategory(files, LibraryCategoryFilter.Audio);
|
||||
Assert.Equal(2, audios.Count);
|
||||
Assert.All(audios, f => Assert.Equal(LocalMediaType.Audio, f.Type));
|
||||
|
||||
var all = filter.FilterByCategory(files, LibraryCategoryFilter.All);
|
||||
Assert.Equal(4, all.Count);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Gate148_MobileLibrarySortEngine_MultiCriteria_Audit()
|
||||
{
|
||||
var sorter = new MobileLibrarySortEngine();
|
||||
var files = new List<LocalDownloadedFile>
|
||||
{
|
||||
new("Banana.mp4", "/path/b", 100, DateTime.UtcNow.AddHours(-2), LocalMediaType.Video),
|
||||
new("Apple.mp4", "/path/a", 500, DateTime.UtcNow.AddHours(-1), LocalMediaType.Video),
|
||||
new("Cherry.mp4", "/path/c", 200, DateTime.UtcNow, LocalMediaType.Video)
|
||||
};
|
||||
|
||||
// 최신순 (DateDesc)
|
||||
var byDate = sorter.Sort(files, LibrarySortCriteria.DateDesc);
|
||||
Assert.Equal("Cherry.mp4", byDate[0].FileName);
|
||||
Assert.Equal("Banana.mp4", byDate[2].FileName);
|
||||
|
||||
// 이름순 (NameAsc)
|
||||
var byName = sorter.Sort(files, LibrarySortCriteria.NameAsc);
|
||||
Assert.Equal("Apple.mp4", byName[0].FileName);
|
||||
Assert.Equal("Cherry.mp4", byName[2].FileName);
|
||||
|
||||
// 크기순 (SizeDesc)
|
||||
var bySize = sorter.Sort(files, LibrarySortCriteria.SizeDesc);
|
||||
Assert.Equal("Apple.mp4", bySize[0].FileName); // 500
|
||||
Assert.Equal("Banana.mp4", bySize[2].FileName); // 100
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Gate149_MobileLibraryBatchManager_Cleanup_Audit()
|
||||
{
|
||||
var batch = new MobileLibraryBatchManager();
|
||||
var files = new List<LocalDownloadedFile>
|
||||
{
|
||||
new("corrupt.part", "/path/corrupt.part", 0, DateTime.UtcNow, LocalMediaType.Other),
|
||||
new("normal.mp4", "/path/normal.mp4", 1024, DateTime.UtcNow, LocalMediaType.Video),
|
||||
new("empty.tmp", "/path/empty.tmp", 0, DateTime.UtcNow, LocalMediaType.Other)
|
||||
};
|
||||
|
||||
var cleaned = batch.PurgeEmptyFiles(files);
|
||||
Assert.Single(cleaned);
|
||||
Assert.Equal("normal.mp4", cleaned[0].FileName);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Gate150_MobileQuickDownloadBar_ClipboardDetection_Audit()
|
||||
{
|
||||
var quickBar = new MobileQuickDownloadBar();
|
||||
Assert.False(quickBar.TryDetectDownloadableMedia("안녕하세요 일반 텍스트입니다.", out _));
|
||||
|
||||
Assert.True(quickBar.TryDetectDownloadableMedia("이 영상 봐봐 https://youtu.be/dQw4w9WgXcQ 짱이야", out var extractedUrl));
|
||||
Assert.Equal("https://youtu.be/dQw4w9WgXcQ", extractedUrl);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Gate151_DownloadsPage_HubModel_Audit()
|
||||
{
|
||||
// 큐 관리와 파일 보관함을 한 곳에서 탭으로 쉽게 전환하는 통합 허브 모델
|
||||
var hub = new DownloadsHubModel();
|
||||
Assert.Equal(DownloadsHubTab.Queue, hub.CurrentTab);
|
||||
|
||||
hub.SwitchTab(DownloadsHubTab.CompletedLibrary);
|
||||
Assert.Equal(DownloadsHubTab.CompletedLibrary, hub.CurrentTab);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Gate152_EndToEndDownloadsAndLibraryJourneyAudit_Audit()
|
||||
{
|
||||
var qm = new MobileQueueManager();
|
||||
var library = new MobileLibraryFileManager();
|
||||
var filter = new MobileLibraryFilterEngine();
|
||||
var sorter = new MobileLibrarySortEngine();
|
||||
|
||||
// 1. 큐에 비디오 및 오디오 다운로드 등록
|
||||
var item1 = qm.Enqueue("https://example.com/v1.mp4", "Epic Nature 4K");
|
||||
var item2 = qm.Enqueue("https://example.com/a1.m4a", "Chill Beats");
|
||||
|
||||
// 2. 다운로드 완료 시 보관함에 자동 등록
|
||||
item1.Status = MobileQueueStatus.Completed;
|
||||
item2.Status = MobileQueueStatus.Completed;
|
||||
|
||||
library.SetFiles(new List<LocalDownloadedFile>
|
||||
{
|
||||
new(item1.Title + ".mp4", "/storage/v1.mp4", 1024 * 1024 * 80, DateTime.UtcNow.AddMinutes(-2), LocalMediaType.Video),
|
||||
new(item2.Title + ".m4a", "/storage/a1.m4a", 1024 * 1024 * 10, DateTime.UtcNow, LocalMediaType.Audio)
|
||||
});
|
||||
|
||||
// 3. 비디오만 필터링
|
||||
var videosOnly = filter.FilterByCategory(library.Files, LibraryCategoryFilter.Video);
|
||||
Assert.Single(videosOnly);
|
||||
Assert.Equal("Epic Nature 4K.mp4", videosOnly[0].FileName);
|
||||
|
||||
// 4. 최신순 정렬
|
||||
var sorted = sorter.Sort(library.Files, LibrarySortCriteria.DateDesc);
|
||||
Assert.Equal("Chill Beats.m4a", sorted[0].FileName);
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue