Keep the horizontal thumb at its raw pointer position so both endpoints are reachable, honor the stack entry's authored right alignment, and preserve PublicWeenieDesc plural names from CreateObject through the object table. Port retail's singular s/es fallback when no plural was sent. Co-Authored-By: Codex <codex@openai.com>
105 lines
3.6 KiB
C#
105 lines
3.6 KiB
C#
using AcDream.App.UI;
|
|
using Xunit;
|
|
|
|
namespace AcDream.App.Tests.UI;
|
|
|
|
/// <summary>
|
|
/// Pure unit tests for <see cref="UiScrollbar.ThumbRect"/> — no GL dependency.
|
|
/// </summary>
|
|
public class UiScrollbarTests
|
|
{
|
|
// Model: content=400, view=100, trackLen=200.
|
|
// ThumbRatio = 100/400 = 0.25 → thumbH = max(8, 200*0.25) = 50.
|
|
// Travel = 200 - 50 = 150.
|
|
|
|
[Fact]
|
|
public void ThumbRect_AtStart_HasCorrectSizeAndZeroOffset()
|
|
{
|
|
var m = new UiScrollable { ContentHeight = 400, ViewHeight = 100 };
|
|
// PositionRatio = 0 (start).
|
|
var (y, h) = UiScrollbar.ThumbRect(m, trackTop: 0f, trackLen: 200f);
|
|
Assert.Equal(50f, h, 3f);
|
|
Assert.Equal(0f, y, 3f);
|
|
}
|
|
|
|
[Fact]
|
|
public void ThumbRect_AtEnd_PinsToBottomOfTrack()
|
|
{
|
|
var m = new UiScrollable { ContentHeight = 400, ViewHeight = 100 };
|
|
m.ScrollToEnd(); // PositionRatio = 1.
|
|
float trackTop = 16f, trackLen = 200f;
|
|
var (y, h) = UiScrollbar.ThumbRect(m, trackTop, trackLen);
|
|
Assert.Equal(50f, h, 3f);
|
|
// y = trackTop + travel * 1 = 16 + 150 = 166.
|
|
Assert.Equal(166f, y, 3f);
|
|
}
|
|
|
|
[Fact]
|
|
public void ThumbRect_WithButtonH_CorrectlyOffsetsFromTrackTop()
|
|
{
|
|
// Matches task spec: content=400, view=100, trackLen=200, PositionRatio=1.
|
|
// thumbH=50; travel=150; y = trackTop + 150 = trackTop + 150.
|
|
var m = new UiScrollable { ContentHeight = 400, ViewHeight = 100 };
|
|
m.ScrollToEnd();
|
|
var (y, h) = UiScrollbar.ThumbRect(m, trackTop: 16f, trackLen: 200f);
|
|
Assert.Equal(50f, h, 3f);
|
|
Assert.Equal(166f, y, 3f); // 16 + 150
|
|
}
|
|
|
|
[Fact]
|
|
public void ThumbRect_MidScroll_InterpolatesPosition()
|
|
{
|
|
// content=400 view=100 → MaxScroll=300; ScrollY=150 → PositionRatio=0.5.
|
|
var m = new UiScrollable { ContentHeight = 400, ViewHeight = 100 };
|
|
m.SetScrollY(150);
|
|
Assert.Equal(0.5f, m.PositionRatio, 3);
|
|
|
|
var (y, h) = UiScrollbar.ThumbRect(m, trackTop: 0f, trackLen: 200f);
|
|
Assert.Equal(50f, h, 3f);
|
|
// y = 0 + 150 * 0.5 = 75.
|
|
Assert.Equal(75f, y, 3f);
|
|
}
|
|
|
|
[Fact]
|
|
public void ThumbRect_SmallContent_EnforcesMinThumb()
|
|
{
|
|
// content=1000, view=10, trackLen=200 → ThumbRatio=0.01 → raw=2 < 8 → clamp to 8.
|
|
var m = new UiScrollable { ContentHeight = 1000, ViewHeight = 10 };
|
|
var (_, h) = UiScrollbar.ThumbRect(m, trackTop: 0f, trackLen: 200f);
|
|
Assert.Equal(8f, h, 3f);
|
|
}
|
|
|
|
[Fact]
|
|
public void ThumbRect_NoOverflow_ThumbFillsTrack()
|
|
{
|
|
// content <= view → ThumbRatio = 1 → thumbH = trackLen.
|
|
var m = new UiScrollable { ContentHeight = 50, ViewHeight = 100 };
|
|
var (y, h) = UiScrollbar.ThumbRect(m, trackTop: 16f, trackLen: 100f);
|
|
Assert.Equal(100f, h, 3f);
|
|
Assert.Equal(16f, y, 3f); // travel = 0 → y = trackTop
|
|
}
|
|
|
|
[Fact]
|
|
public void HorizontalScalar_clickAndDrag_updatesNormalizedValue()
|
|
{
|
|
float value = 1f;
|
|
var bar = new UiScrollbar
|
|
{
|
|
Width = 90f,
|
|
Height = 14f,
|
|
Horizontal = true,
|
|
ScalarChanged = next => value = next,
|
|
};
|
|
bar.SetScalarPosition(1f);
|
|
|
|
Assert.True(bar.OnEvent(new UiEvent(0u, bar, UiEventType.MouseDown, Data1: 8)));
|
|
Assert.Equal(0f, value, 3);
|
|
Assert.Equal(0f, bar.ScalarPosition, 3);
|
|
|
|
Assert.True(bar.OnEvent(new UiEvent(0u, bar, UiEventType.MouseMove, Data1: 45)));
|
|
Assert.Equal(0.5f, value, 3);
|
|
Assert.Equal(0.5f, bar.ScalarPosition, 3);
|
|
|
|
Assert.True(bar.OnEvent(new UiEvent(0u, bar, UiEventType.MouseUp, Data1: 45)));
|
|
}
|
|
}
|