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:
Yun Chan 2026-09-14 00:39:44 +09:00
parent a88aafa1e5
commit 0e568f1f0a
975 changed files with 130593 additions and 16783 deletions

View file

@ -0,0 +1,88 @@
using System;
using System.Collections.Generic;
using System.IO;
using Paca.Mobile.Core;
using Xunit;
namespace Paca.Tests.Core;
public class SubtitleSyncEngineGateTests
{
[Fact]
public void Gate261_SubtitleSyncEngine_DetectsSubtitleFiles_InMediaDirectory()
{
var tempDir = Path.Combine(Path.GetTempPath(), "paca_sub_test_" + Guid.NewGuid());
Directory.CreateDirectory(tempDir);
try
{
var videoPath = Path.Combine(tempDir, "video1.mp4");
File.WriteAllText(videoPath, "dummy video");
File.WriteAllText(Path.Combine(tempDir, "video1.ko.srt"), "1\n00:00:01,000 --> 00:00:04,000\n안녕하세요");
File.WriteAllText(Path.Combine(tempDir, "video1.en.vtt"), "WEBVTT\n\n00:00:01.000 --> 00:00:04.000\nHello");
File.WriteAllText(Path.Combine(tempDir, "other.srt"), "1\n00:00:01,000 --> 00:00:04,000\nOther");
var tracks = SubtitleSyncEngine.FindAssociatedSubtitles(videoPath);
Assert.Equal(2, tracks.Count);
Assert.Contains(tracks, t => t.LanguageCode == "ko" && t.Format == "srt");
Assert.Contains(tracks, t => t.LanguageCode == "en" && t.Format == "vtt");
Assert.DoesNotContain(tracks, t => t.FileName.Contains("other"));
}
finally
{
try { Directory.Delete(tempDir, true); } catch { }
}
}
[Fact]
public void Gate262_SubtitleSyncEngine_ParsesVttAndSrtCues()
{
var srtContent = @"1
00:01:10,500 --> 00:01:14,200
안녕하세요 반갑습니다
2
00:01:15,000 --> 00:01:18,500
다음 대사입니다";
var cues = SubtitleSyncEngine.ParseCues(srtContent, "srt");
Assert.Equal(2, cues.Count);
Assert.Equal(70.5, cues[0].StartSec);
Assert.Equal(74.2, cues[0].EndSec);
Assert.Equal("안녕하세요 반갑습니다", cues[0].Text);
}
[Fact]
public void Gate263_SubtitleSyncEngine_FindsActiveCue_AtCurrentPosition()
{
var cues = new List<SubtitleCue>
{
new(10.0, 15.0, "Active Subtitle Text")
};
var active12 = SubtitleSyncEngine.GetActiveCue(cues, currentPosSec: 12.5);
Assert.NotNull(active12);
Assert.Equal("Active Subtitle Text", active12!.Text);
var active20 = SubtitleSyncEngine.GetActiveCue(cues, currentPosSec: 20.0);
Assert.Null(active20);
}
[Fact]
public void Gate264_SubtitleSyncEngine_AppliesTimeOffsetAdjustment()
{
var cues = new List<SubtitleCue>
{
new(10.0, 15.0, "Adjusted Subtitle")
};
// Offset +2.0s means original 10.0s now displays at 12.0s to 17.0s
var active11 = SubtitleSyncEngine.GetActiveCue(cues, currentPosSec: 11.0, offsetSec: 2.0);
Assert.Null(active11); // Not active yet at 11s
var active13 = SubtitleSyncEngine.GetActiveCue(cues, currentPosSec: 13.0, offsetSec: 2.0);
Assert.NotNull(active13);
Assert.Equal("Adjusted Subtitle", active13!.Text);
}
}