GFramework/GFramework.Godot.Tests/Text/RichTextEffectsControllerTests.cs
GeWuYou 11515ff791 feat(godot): 添加富文本标签效果系统支持
- 新增 GfRichTextLabel 组件作为富文本标签宿主
- 实现 IRichTextEffectHost 接口用于效果控制器驱动
- 创建 RichTextEffectsController 处理效果装配逻辑
- 添加 RichTextProfile 配置资源类型
- 引入 RichTextEffectPlan 和 RichTextEffectPlanEntry 类型
- 在 CI 工作流中添加 GFramework.Godot.Tests 项目
- 优化 Godot 测试诊断条件判断逻辑
- 添加富文本效果控制器相关单元测试
2026-04-18 15:47:08 +08:00

130 lines
4.1 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

namespace GFramework.Godot.Tests.Text;
/// <summary>
/// <see cref="RichTextEffectsController" /> 的纯托管行为测试。
/// </summary>
[TestFixture]
public sealed class RichTextEffectsControllerTests
{
/// <summary>
/// 验证启用框架效果时会开启宿主 BBCode并在 Profile 为空时回退到内置默认配置。
/// </summary>
[Test]
public void RefreshEffects_Should_Enable_Bbcode_And_Use_BuiltIn_Default_Profile()
{
var host = new FakeRichTextEffectHost();
var controller = new RichTextEffectsController(
host,
() => null,
() => true,
() => false);
controller.RefreshEffects();
Assert.That(host.BbcodeEnabled, Is.True);
Assert.That(host.CapturedAnimatedEffectsEnabled, Has.Count.EqualTo(1));
Assert.That(host.CapturedAnimatedEffectsEnabled[0], Is.False);
Assert.That(host.CapturedProfiles, Has.Count.EqualTo(1));
Assert.That(host.CapturedProfiles[0].Effects.Select(static entry => entry.Key), Is.EqualTo(new[]
{
"green",
"red",
"gold",
"blue",
"fade_in",
"sine",
"jitter",
"fly_in"
}));
}
/// <summary>
/// 验证关闭框架效果时不会触发新的效果安装,并会清空宿主的自定义效果集合。
/// </summary>
[Test]
public void RefreshEffects_Should_Clear_CustomEffects_When_Framework_Effects_Are_Disabled()
{
var host = new FakeRichTextEffectHost
{
BbcodeEnabled = true
};
host.SimulateInstalledEffects();
var controller = new RichTextEffectsController(
host,
() => RichTextEffectPlan.CreateBuiltInDefault(),
() => false,
() => true);
controller.RefreshEffects();
Assert.That(host.BbcodeEnabled, Is.True);
Assert.That(host.CustomEffectsInstalled, Is.False);
Assert.That(host.ClearCustomEffectsCallCount, Is.EqualTo(1));
Assert.That(host.CapturedProfiles, Is.Empty);
}
/// <summary>
/// 验证控制器会在每次刷新时读取最新的配置访问器结果,避免缓存旧配置。
/// </summary>
[Test]
public void RefreshEffects_Should_Use_The_Current_Profile_From_Accessor()
{
var host = new FakeRichTextEffectHost();
var firstProfile = new RichTextEffectPlan(
[
new RichTextEffectPlanEntry("green")
]);
var secondProfile = new RichTextEffectPlan(
[
new RichTextEffectPlanEntry("gold")
]);
RichTextEffectPlan? currentProfile = firstProfile;
var controller = new RichTextEffectsController(
host,
() => currentProfile,
() => true,
() => true);
controller.RefreshEffects();
currentProfile = secondProfile;
controller.RefreshEffects();
Assert.That(host.CapturedProfiles, Has.Count.EqualTo(2));
Assert.That(host.CapturedProfiles[0], Is.SameAs(firstProfile));
Assert.That(host.CapturedProfiles[1], Is.SameAs(secondProfile));
}
private sealed class FakeRichTextEffectHost : IRichTextEffectHost
{
public List<RichTextEffectPlan> CapturedProfiles { get; } = [];
public List<bool> CapturedAnimatedEffectsEnabled { get; } = [];
public bool CustomEffectsInstalled { get; private set; }
public int ClearCustomEffectsCallCount { get; private set; }
public bool BbcodeEnabled { get; set; }
public void ApplyEffects(RichTextEffectPlan profile, bool animatedEffectsEnabled)
{
ArgumentNullException.ThrowIfNull(profile);
CapturedProfiles.Add(profile);
CapturedAnimatedEffectsEnabled.Add(animatedEffectsEnabled);
CustomEffectsInstalled = true;
}
public void ClearCustomEffects()
{
ClearCustomEffectsCallCount++;
CustomEffectsInstalled = false;
}
public void SimulateInstalledEffects()
{
CustomEffectsInstalled = true;
}
}
}