Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 18 additions & 26 deletions .github/instructions/testing.instructions.md
Original file line number Diff line number Diff line change
Expand Up @@ -84,35 +84,27 @@ public class DataGridSourceSortingTests

---

## `FakeDrawingContext` — test double for renderers
## `RecordingDrawingContext` — test double for rendering

When testing `ICellRenderer` or `DrawnComponent`, create a no-op `IDrawingContext`:
Rendering tests run without SkiaSharp against `tests/KumikoUI.Core.Tests/TestHelpers/RecordingDrawingContext.cs`.
It records every `IDrawingContext` call as a `DrawOp` in call order (so index = z-order), in viewport
coordinates with the active clip, and measures text monospace (8 px per character, 14 px tall).
`DrawOp.Visible` is the part of an op its clip lets reach the screen.

For `DataGridRenderer`, use `RenderHarness` (same folder): it builds a four-column grid of people, gives
every `GridColor` on the style a distinct value (so a recorded colour identifies its style role) and
renders into a fresh recording context:

```csharp
// tests/KumikoUI.Core.Tests/TestHelpers/FakeDrawingContext.cs
using KumikoUI.Core.Rendering;
var h = RenderHarness.Create(width: 300);
h.Column("Name").FreezeMode = ColumnFreezeMode.Left;
h.Scroll.OffsetX = 50;

namespace KumikoUI.Core.Tests.TestHelpers;
var ctx = h.Render();

internal sealed class FakeDrawingContext : IDrawingContext
{
public void DrawRect(GridRect r, GridPaint p) { }
public void FillRect(GridRect r, GridPaint p) { }
public void DrawRoundRect(GridRect r, float cr, GridPaint p) { }
public void FillRoundRect(GridRect r, float cr, GridPaint p) { }
public void DrawLine(float x1, float y1, float x2, float y2, GridPaint p) { }
public void DrawText(string t, float x, float y, GridPaint p) { }
public void DrawTextInRect(string t, GridRect r, GridPaint p,
GridTextAlignment h = GridTextAlignment.Left,
GridVerticalAlignment v = GridVerticalAlignment.Center,
bool clip = true) { }
public GridSize MeasureText(string t, GridPaint p) => new GridSize(t.Length * 8, 14);
public GridFontMetrics GetFontMetrics(GridPaint p) => new GridFontMetrics(14, 0, 2);
public void ClipRect(GridRect r) { }
public void Save() { }
public void Restore() { }
public void Translate(float dx, float dy) { }
public void DrawImage(object image, GridRect dest) { }
public void Dispose() { }
}
var cell = ctx.SingleText("P00");
Assert.Equal(new GridRect(0, 0, 150, 400), cell.Clip);
```

Known renderer defects are pinned as `[Fact(Skip = "<finding>, fixed by #<issue>: …")]` tests in
`tests/KumikoUI.Core.Tests/Rendering/`; the fix removes the `Skip`.
12 changes: 0 additions & 12 deletions src/KumikoUI.Core/DataGridRenderer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
private readonly List<(DataGridColumn Column, float X, int OriginalIndex)> _scrollableCols = new();
private readonly List<(DataGridColumn Column, float X, int OriginalIndex)> _allCols = new();

public DataGridRenderer()

Check warning on line 25 in src/KumikoUI.Core/DataGridRenderer.cs

View workflow job for this annotation

GitHub Actions / Build & Test (Core + SkiaSharp)

Missing XML comment for publicly visible type or member 'DataGridRenderer.DataGridRenderer()'

Check warning on line 25 in src/KumikoUI.Core/DataGridRenderer.cs

View workflow job for this annotation

GitHub Actions / Build (KumikoUI.Maui — all TFMs)

Missing XML comment for publicly visible type or member 'DataGridRenderer.DataGridRenderer()'

Check warning on line 25 in src/KumikoUI.Core/DataGridRenderer.cs

View workflow job for this annotation

GitHub Actions / Build & Test (KumikoUI.Uno — all heads)

Missing XML comment for publicly visible type or member 'DataGridRenderer.DataGridRenderer()'
{
var textRenderer = new TextCellRenderer();
_cellRenderers[DataGridColumnType.Text] = textRenderer;
Expand Down Expand Up @@ -307,11 +307,6 @@
popupManager?.DrawPopups(ctx);
}

private static float ColumnScreenX(float colContentX, ScrollState scroll, bool isFrozen)
{
return isFrozen ? colContentX : colContentX - scroll.OffsetX;
}

/// <summary>
/// Returns screen X for a column, handling left-frozen, right-frozen, and scrollable.
/// For right-frozen columns, the X is already an absolute screen position from GetVisibleRightFrozenColumns.
Expand All @@ -326,13 +321,6 @@
};
}

private void DrawFrozenBackground(
IDrawingContext ctx, float frozenWidth, ScrollState scroll, DataGridStyle style)
{
ctx.FillRect(new GridRect(0, 0, frozenWidth, scroll.ViewportHeight),
_paintCache.FrozenColumnBackground);
}

private void DrawRightFrozenBackground(
IDrawingContext ctx, float rightFrozenLeft, float rightFrozenWidth, ScrollState scroll, DataGridStyle style)
{
Expand Down
3 changes: 3 additions & 0 deletions src/KumikoUI.Core/Rendering/Primitives.cs
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,9 @@ public GridRect Offset(float dx, float dy)

/// <summary>A zero-size rectangle at the origin.</summary>
public static GridRect Empty => new(0, 0, 0, 0);

/// <inheritdoc />
public override string ToString() => FormattableString.Invariant($"GridRect({X}, {Y}, {Width}, {Height})");
}

/// <summary>
Expand Down
6 changes: 3 additions & 3 deletions tests/KumikoUI.Core.Tests/PinnedBottomSummaryTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -312,14 +312,14 @@ public void Render_PinnedFooter_IsDrawnAfterDragHandleGrips()
grid.Style.ShowRowDragHandle = true;
grid.Style.RowDragHandlePosition = DragHandlePosition.Left;

var fills = grid.Render().Fills;
var fills = grid.Render().Fills.ToList();

int footerIndex = fills.FindLastIndex(f =>
f.Color == grid.Style.SummaryRowBackgroundColor &&
Math.Abs(f.Rect.Y - grid.FooterTop) < 0.01f &&
f.Rect.Width >= ViewportWidth);
int lastGripIndex = fills.FindLastIndex(f =>
f.Kind == "FillRoundRect" && f.Color == grid.Style.RowDragHandleColor);
f.Kind == DrawOpKind.FillRoundRect && f.Color == grid.Style.RowDragHandleColor);

Assert.True(footerIndex >= 0, "pinned footer background was not drawn");
Assert.True(lastGripIndex >= 0, "drag handle grips were not drawn");
Expand All @@ -332,7 +332,7 @@ public void Render_Unpinned_SummaryIsDrawnAfterLastRow()
var grid = CreateGrid(rowCount: 3, pinned: false);
float expectedY = grid.Style.HeaderHeight + 3 * grid.Style.RowHeight;

var fills = grid.Render().Fills;
var fills = grid.Render().Fills.ToList();

Assert.Contains(fills, f => f.Color == grid.Style.SummaryRowBackgroundColor && Math.Abs(f.Rect.Y - expectedY) < 0.01f);
Assert.DoesNotContain(fills, f => f.Color == grid.Style.SummaryRowBackgroundColor && Math.Abs(f.Rect.Y - grid.FooterTop) < 0.01f);
Expand Down
Loading
Loading