Documentation
¶
Overview ¶
Package uitest provides reusable testing utilities for the gogpu/ui toolkit.
This package eliminates the need for each test file to define its own mock Canvas and Context implementations. It provides:
- MockCanvas: A recording mock that implements widget.Canvas and captures all draw calls for verification.
- MockContext: A configurable mock that implements widget.Context with sensible defaults for headless testing.
- Event factory functions: Click, DoubleClick, RightClick, MouseMove, MouseDrag, KeyPress, WheelScroll, and FocusGained/FocusLost for creating test events without boilerplate.
- Widget test helpers: LayoutWidget, DrawWidget, SimulateClick, and SimulateKeyPress for common test patterns.
Example usage:
func TestButton_Draw(t *testing.T) {
btn := button.New(button.Text("OK"))
btn.SetBounds(geometry.NewRect(0, 0, 100, 40))
canvas := &uitest.MockCanvas{}
ctx := uitest.NewMockContext()
btn.Draw(ctx, canvas)
if len(canvas.Texts) == 0 {
t.Fatal("expected text to be drawn")
}
if canvas.Texts[0].Text != "OK" {
t.Errorf("text = %q, want %q", canvas.Texts[0].Text, "OK")
}
}
Index ¶
- func AssertColorEqual(t *testing.T, got, want widget.Color)
- func AssertCursor(t *testing.T, ctx *MockContext, expected widget.CursorType)
- func AssertDrawnText(t *testing.T, canvas *MockCanvas, expected string)
- func AssertFocused(t *testing.T, ctx *MockContext, w widget.Widget)
- func AssertInvalidated(t *testing.T, ctx *MockContext)
- func AssertNoDrawnText(t *testing.T, canvas *MockCanvas, text string)
- func AssertNotFocused(t *testing.T, ctx *MockContext, w widget.Widget)
- func AssertNotInvalidated(t *testing.T, ctx *MockContext)
- func AssertRectDrawn(t *testing.T, canvas *MockCanvas, expected geometry.Rect)
- func Click(x, y float32) *event.MouseEvent
- func DoubleClick(x, y float32) *event.MouseEvent
- func FocusGained() *event.FocusEvent
- func FocusLost() *event.FocusEvent
- func KeyPress(code event.Key, mods event.Modifiers) *event.KeyEvent
- func KeyRelease(code event.Key, mods event.Modifiers) *event.KeyEvent
- func KeyType(code event.Key, r rune, mods event.Modifiers) *event.KeyEvent
- func LayoutWidget(w widget.Widget, width, height float32) geometry.Size
- func LayoutWidgetTight(w widget.Widget, width, height float32) geometry.Size
- func MouseDrag(x, y float32) *event.MouseEvent
- func MouseEnter(x, y float32) *event.MouseEvent
- func MouseLeave(x, y float32) *event.MouseEvent
- func MouseMove(x, y float32) *event.MouseEvent
- func Release(x, y float32) *event.MouseEvent
- func RightClick(x, y float32) *event.MouseEvent
- func SimulateClick(w widget.Widget, x, y float32) bool
- func SimulateClickWithContext(w widget.Widget, ctx widget.Context, x, y float32) bool
- func SimulateKeyPress(w widget.Widget, code event.Key) bool
- func SimulateKeyPressWithMods(w widget.Widget, code event.Key, mods event.Modifiers) bool
- func WheelScroll(x, y, deltaY float32) *event.WheelEvent
- func WheelScrollH(x, y, deltaX, deltaY float32) *event.WheelEvent
- type ClipRoundRectCall
- type DrawCircleCall
- type DrawImageCall
- type DrawLineCall
- type DrawRectCall
- type DrawRoundRectCall
- type DrawTextCall
- type MockCanvas
- func (c *MockCanvas) Clear(color widget.Color)
- func (c *MockCanvas) ClipBounds() geometry.Rect
- func (c *MockCanvas) DrawCircle(center geometry.Point, radius float32, color widget.Color)
- func (c *MockCanvas) DrawImage(img image.Image, at geometry.Point)
- func (c *MockCanvas) DrawLine(from, to geometry.Point, color widget.Color, strokeWidth float32)
- func (c *MockCanvas) DrawRect(r geometry.Rect, color widget.Color)
- func (c *MockCanvas) DrawRoundRect(r geometry.Rect, color widget.Color, radius float32)
- func (c *MockCanvas) DrawText(text string, bounds geometry.Rect, fontSize float32, color widget.Color, ...)
- func (c *MockCanvas) FillRectDirect(r geometry.Rect, color widget.Color)
- func (c *MockCanvas) MeasureText(text string, fontSize float32, _ bool) float32
- func (c *MockCanvas) PopClip()
- func (c *MockCanvas) PopTransform()
- func (c *MockCanvas) PushClip(r geometry.Rect)
- func (c *MockCanvas) PushClipRoundRect(r geometry.Rect, radius float32)
- func (c *MockCanvas) PushTransform(offset geometry.Point)
- func (c *MockCanvas) ReplayScene(_ *scene.Scene)
- func (c *MockCanvas) Reset()
- func (c *MockCanvas) StrokeArc(center geometry.Point, radius float32, startAngle, sweepAngle float64, ...)
- func (c *MockCanvas) StrokeArcStyled(center geometry.Point, radius float32, startAngle, sweepAngle float64, ...)
- func (c *MockCanvas) StrokeCircle(center geometry.Point, radius float32, color widget.Color, strokeWidth float32)
- func (c *MockCanvas) StrokeRect(r geometry.Rect, color widget.Color, strokeWidth float32)
- func (c *MockCanvas) StrokeRoundRect(r geometry.Rect, color widget.Color, radius float32, strokeWidth float32)
- func (c *MockCanvas) TotalDrawCalls() int
- func (c *MockCanvas) TransformOffset() geometry.Point
- type MockContext
- func (c *MockContext) Cursor() widget.CursorType
- func (c *MockContext) DeltaTime() time.Duration
- func (c *MockContext) FocusedWidget() widget.Widget
- func (c *MockContext) Invalidate()
- func (c *MockContext) InvalidateRect(r geometry.Rect)
- func (c *MockContext) IsFocused(w widget.Widget) bool
- func (c *MockContext) Now() time.Time
- func (c *MockContext) OverlayManager() widget.OverlayManager
- func (c *MockContext) ReleaseFocus(w widget.Widget)
- func (c *MockContext) RequestFocus(w widget.Widget)
- func (c *MockContext) Reset()
- func (c *MockContext) Scale() float32
- func (c *MockContext) Scheduler() widget.SchedulerRef
- func (c *MockContext) SetCursor(cursor widget.CursorType)
- func (c *MockContext) ThemeProvider() widget.ThemeProvider
- func (c *MockContext) WindowSize() geometry.Size
- type StrokeArcCall
- type StrokeArcStyledCall
- type StrokeCircleCall
- type StrokeRectCall
- type StrokeRoundRectCall
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func AssertColorEqual ¶
AssertColorEqual checks that two colors are approximately equal within floating-point tolerance.
func AssertCursor ¶
func AssertCursor(t *testing.T, ctx *MockContext, expected widget.CursorType)
AssertCursor checks that the context cursor matches the expected type.
func AssertDrawnText ¶
func AssertDrawnText(t *testing.T, canvas *MockCanvas, expected string)
AssertDrawnText checks that the canvas contains at least one DrawText call with the expected text string. It fails the test if no matching text is found.
func AssertFocused ¶
func AssertFocused(t *testing.T, ctx *MockContext, w widget.Widget)
AssertFocused checks that the given widget currently has focus in the context.
func AssertInvalidated ¶
func AssertInvalidated(t *testing.T, ctx *MockContext)
AssertInvalidated checks that the context was invalidated at least once.
func AssertNoDrawnText ¶
func AssertNoDrawnText(t *testing.T, canvas *MockCanvas, text string)
AssertNoDrawnText checks that the canvas does not contain a DrawText call with the given text string. It fails the test if the text is found.
func AssertNotFocused ¶
func AssertNotFocused(t *testing.T, ctx *MockContext, w widget.Widget)
AssertNotFocused checks that the given widget does NOT have focus.
func AssertNotInvalidated ¶
func AssertNotInvalidated(t *testing.T, ctx *MockContext)
AssertNotInvalidated checks that the context was not invalidated.
func AssertRectDrawn ¶
func AssertRectDrawn(t *testing.T, canvas *MockCanvas, expected geometry.Rect)
AssertRectDrawn checks that a rectangle was drawn at the expected bounds. It compares using approximate float32 equality.
func Click ¶
func Click(x, y float32) *event.MouseEvent
Click creates a left mouse button press event at the given position.
Both Position and GlobalPosition are set to (x, y) with no modifiers.
func DoubleClick ¶
func DoubleClick(x, y float32) *event.MouseEvent
DoubleClick creates a double-click event at the given position.
Both Position and GlobalPosition are set to (x, y) with ClickCount=2.
func KeyRelease ¶
KeyRelease creates a key release event for the given key code.
func KeyType ¶
KeyType creates a key press event that also produces a character (rune).
Use this for simulating text input where both the key code and the typed character matter.
func LayoutWidget ¶
LayoutWidget performs layout on a widget with the given available dimensions and returns the resulting size.
The constraints are set to a loose box from (0,0) to (width, height). This simulates the common case where a parent offers available space and the widget sizes itself within those bounds.
func LayoutWidgetTight ¶
LayoutWidgetTight performs layout on a widget with tight constraints (the widget must be exactly the given size) and returns the resulting size.
func MouseDrag ¶
func MouseDrag(x, y float32) *event.MouseEvent
MouseDrag creates a mouse drag event at the given position with the left button held.
func MouseEnter ¶
func MouseEnter(x, y float32) *event.MouseEvent
MouseEnter creates a mouse enter event at the given position.
func MouseLeave ¶
func MouseLeave(x, y float32) *event.MouseEvent
MouseLeave creates a mouse leave event at the given position.
func MouseMove ¶
func MouseMove(x, y float32) *event.MouseEvent
MouseMove creates a mouse move event at the given position.
func Release ¶
func Release(x, y float32) *event.MouseEvent
Release creates a left mouse button release event at the given position.
Both Position and GlobalPosition are set to (x, y) with no modifiers.
func RightClick ¶
func RightClick(x, y float32) *event.MouseEvent
RightClick creates a right mouse button press event at the given position.
func SimulateClick ¶
SimulateClick sends a press+release sequence at (x, y) to the widget and returns true if the press event was consumed.
This simulates a complete click gesture: MousePress followed by MouseRelease at the same position.
func SimulateClickWithContext ¶
SimulateClickWithContext sends a press+release sequence using the provided context.
func SimulateKeyPress ¶
SimulateKeyPress sends a key press event to the widget and returns true if the event was consumed.
func SimulateKeyPressWithMods ¶
SimulateKeyPressWithMods sends a key press event with modifiers to the widget and returns true if the event was consumed.
func WheelScroll ¶
func WheelScroll(x, y, deltaY float32) *event.WheelEvent
WheelScroll creates a wheel scroll event at position (x, y) with the given vertical delta.
Positive deltaY scrolls up (content moves down), negative scrolls down.
func WheelScrollH ¶
func WheelScrollH(x, y, deltaX, deltaY float32) *event.WheelEvent
WheelScrollH creates a wheel scroll event with both horizontal and vertical deltas.
Types ¶
type ClipRoundRectCall ¶
ClipRoundRectCall records a single PushClipRoundRect invocation.
type DrawCircleCall ¶
DrawCircleCall records a single DrawCircle invocation.
type DrawImageCall ¶
DrawImageCall records a single DrawImage invocation.
type DrawLineCall ¶
type DrawLineCall struct {
From geometry.Point
To geometry.Point
Color widget.Color
StrokeWidth float32
}
DrawLineCall records a single DrawLine invocation.
type DrawRectCall ¶
DrawRectCall records a single DrawRect invocation.
type DrawRoundRectCall ¶
DrawRoundRectCall records a single DrawRoundRect invocation.
type DrawTextCall ¶
type DrawTextCall struct {
Text string
Bounds geometry.Rect
FontSize float32
Color widget.Color
Bold bool
Align widget.TextAlign
}
DrawTextCall records a single DrawText invocation.
type MockCanvas ¶
type MockCanvas struct {
// Clears records arguments passed to Clear.
Clears []widget.Color
// Rects records arguments passed to DrawRect.
Rects []DrawRectCall
// StrokeRects records arguments passed to StrokeRect.
StrokeRects []StrokeRectCall
// RoundRects records arguments passed to DrawRoundRect.
RoundRects []DrawRoundRectCall
// StrokeRoundRects records arguments passed to StrokeRoundRect.
StrokeRoundRects []StrokeRoundRectCall
// Circles records arguments passed to DrawCircle.
Circles []DrawCircleCall
// StrokeCircles records arguments passed to StrokeCircle.
StrokeCircles []StrokeCircleCall
// StrokeArcs records arguments passed to StrokeArc.
StrokeArcs []StrokeArcCall
// StrokeArcStyleds records arguments passed to StrokeArcStyled.
StrokeArcStyleds []StrokeArcStyledCall
// Lines records arguments passed to DrawLine.
Lines []DrawLineCall
// Texts records arguments passed to DrawText.
Texts []DrawTextCall
// Images records arguments passed to DrawImage.
Images []DrawImageCall
// Clips records arguments passed to PushClip.
Clips []geometry.Rect
// ClipRoundRects records arguments passed to PushClipRoundRect.
ClipRoundRects []ClipRoundRectCall
// Transforms records arguments passed to PushTransform.
Transforms []geometry.Point
// PopClipCount tracks how many times PopClip was called.
PopClipCount int
// PopTransformCount tracks how many times PopTransform was called.
PopTransformCount int
// contains filtered or unexported fields
}
MockCanvas records all draw calls for verification in tests.
It implements widget.Canvas and stores each invocation in typed slices. Use MockCanvas.Reset to clear all recorded calls between test phases.
Example:
canvas := &uitest.MockCanvas{}
myWidget.Draw(ctx, canvas)
if len(canvas.Rects) != 1 {
t.Errorf("expected 1 rect, got %d", len(canvas.Rects))
}
func DrawWidget ¶
func DrawWidget(w widget.Widget) *MockCanvas
DrawWidget performs a draw on the widget using a fresh MockCanvas and MockContext, then returns the canvas for inspection.
The widget should have its bounds set before calling this function (typically via SetBounds or after a Layout call).
func DrawWidgetWithContext ¶
func DrawWidgetWithContext(w widget.Widget, ctx widget.Context) *MockCanvas
DrawWidgetWithContext performs a draw on the widget using a fresh MockCanvas and the provided context, then returns the canvas for inspection.
func (*MockCanvas) Clear ¶
func (c *MockCanvas) Clear(color widget.Color)
Clear records the color argument.
func (*MockCanvas) ClipBounds ¶ added in v0.1.14
func (c *MockCanvas) ClipBounds() geometry.Rect
ClipBounds returns a large default clip rectangle.
func (*MockCanvas) DrawCircle ¶
DrawCircle records the center, radius, and color arguments.
func (*MockCanvas) DrawImage ¶
func (c *MockCanvas) DrawImage(img image.Image, at geometry.Point)
DrawImage records the image and position arguments.
func (*MockCanvas) DrawRect ¶
func (c *MockCanvas) DrawRect(r geometry.Rect, color widget.Color)
DrawRect records the rect and color arguments.
func (*MockCanvas) DrawRoundRect ¶
DrawRoundRect records the rect, color, and radius arguments.
func (*MockCanvas) DrawText ¶
func (c *MockCanvas) DrawText(text string, bounds geometry.Rect, fontSize float32, color widget.Color, bold bool, align widget.TextAlign)
DrawText records all text drawing arguments.
func (*MockCanvas) FillRectDirect ¶ added in v0.1.14
func (c *MockCanvas) FillRectDirect(r geometry.Rect, color widget.Color)
FillRectDirect records as DrawRect — mock does not distinguish CPU/GPU path.
func (*MockCanvas) MeasureText ¶
func (c *MockCanvas) MeasureText(text string, fontSize float32, _ bool) float32
MeasureText returns an approximate width for the given text. Uses average character width (0.5 * fontSize) for test predictability.
func (*MockCanvas) PopClip ¶
func (c *MockCanvas) PopClip()
PopClip increments the pop clip counter.
func (*MockCanvas) PopTransform ¶
func (c *MockCanvas) PopTransform()
PopTransform restores the previous transform offset.
func (*MockCanvas) PushClip ¶
func (c *MockCanvas) PushClip(r geometry.Rect)
PushClip records the clip rectangle.
func (*MockCanvas) PushClipRoundRect ¶
func (c *MockCanvas) PushClipRoundRect(r geometry.Rect, radius float32)
PushClipRoundRect records the clip rounded rectangle and radius.
func (*MockCanvas) PushTransform ¶
func (c *MockCanvas) PushTransform(offset geometry.Point)
PushTransform records the translation offset and updates the cumulative offset.
func (*MockCanvas) ReplayScene ¶ added in v0.1.14
func (c *MockCanvas) ReplayScene(_ *scene.Scene)
ReplayScene is a no-op for the mock canvas.
func (*MockCanvas) Reset ¶
func (c *MockCanvas) Reset()
Reset clears all recorded calls, returning the canvas to its initial state.
func (*MockCanvas) StrokeArc ¶ added in v0.1.14
func (c *MockCanvas) StrokeArc(center geometry.Point, radius float32, startAngle, sweepAngle float64, color widget.Color, strokeWidth float32)
StrokeArc records the center, radius, angles, color, and stroke width arguments.
func (*MockCanvas) StrokeArcStyled ¶ added in v0.1.14
func (c *MockCanvas) StrokeArcStyled(center geometry.Point, radius float32, startAngle, sweepAngle float64, color widget.Color, strokeWidth float32, lineCap widget.LineCap)
StrokeArcStyled records the center, radius, angles, color, stroke width, and line cap.
func (*MockCanvas) StrokeCircle ¶
func (c *MockCanvas) StrokeCircle(center geometry.Point, radius float32, color widget.Color, strokeWidth float32)
StrokeCircle records the center, radius, color, and stroke width arguments.
func (*MockCanvas) StrokeRect ¶
StrokeRect records the rect, color, and stroke width arguments.
func (*MockCanvas) StrokeRoundRect ¶
func (c *MockCanvas) StrokeRoundRect(r geometry.Rect, color widget.Color, radius float32, strokeWidth float32)
StrokeRoundRect records the rect, color, radius, and stroke width arguments.
func (*MockCanvas) TotalDrawCalls ¶
func (c *MockCanvas) TotalDrawCalls() int
TotalDrawCalls returns the total number of recorded draw operations (excluding clip and transform operations).
func (*MockCanvas) TransformOffset ¶
func (c *MockCanvas) TransformOffset() geometry.Point
TransformOffset returns the current cumulative transform offset.
type MockContext ¶
type MockContext struct {
// FocusedVal is the widget that currently has focus.
FocusedVal widget.Widget
// TimeVal is returned by Now(). Defaults to a fixed time.
TimeVal time.Time
// DeltaVal is returned by DeltaTime(). Defaults to 16ms.
DeltaVal time.Duration
// ScaleVal is returned by Scale(). Defaults to 1.0.
ScaleVal float32
// CursorVal is returned by Cursor() and set by SetCursor().
CursorVal widget.CursorType
// ThemeVal is returned by ThemeProvider(). Defaults to nil.
ThemeVal widget.ThemeProvider
// OverlayVal is returned by OverlayManager(). Defaults to nil.
OverlayVal widget.OverlayManager
// WindowSizeVal is returned by WindowSize(). Defaults to 800x600.
WindowSizeVal geometry.Size
// SchedulerVal is returned by Scheduler(). Defaults to nil.
SchedulerVal widget.SchedulerRef
// Invalidated is set to true when Invalidate() is called.
Invalidated bool
// InvalidatedRects collects all rectangles passed to InvalidateRect().
InvalidatedRects []geometry.Rect
// InvalidateCount tracks how many times Invalidate() was called.
InvalidateCount int
}
MockContext provides a configurable test implementation of widget.Context.
All fields are exported for direct configuration. Use NewMockContext for sensible defaults, then override fields as needed.
Example:
ctx := uitest.NewMockContext()
ctx.ScaleVal = 2.0 // HiDPI
myWidget.Draw(ctx, canvas)
if ctx.Invalidated {
t.Log("widget requested redraw")
}
func NewMockContext ¶
func NewMockContext() *MockContext
NewMockContext creates a MockContext with sensible defaults for testing.
Defaults:
- Scale: 1.0
- DeltaTime: 16ms
- WindowSize: 800x600
- Time: 2025-01-01 00:00:00 UTC (deterministic for tests)
func (*MockContext) Cursor ¶
func (c *MockContext) Cursor() widget.CursorType
Cursor returns CursorVal.
func (*MockContext) DeltaTime ¶
func (c *MockContext) DeltaTime() time.Duration
DeltaTime returns DeltaVal.
func (*MockContext) FocusedWidget ¶
func (c *MockContext) FocusedWidget() widget.Widget
FocusedWidget returns the currently focused widget.
func (*MockContext) Invalidate ¶
func (c *MockContext) Invalidate()
Invalidate sets Invalidated to true and increments InvalidateCount.
func (*MockContext) InvalidateRect ¶
func (c *MockContext) InvalidateRect(r geometry.Rect)
InvalidateRect appends the rectangle to InvalidatedRects.
func (*MockContext) IsFocused ¶
func (c *MockContext) IsFocused(w widget.Widget) bool
IsFocused returns true if w is the currently focused widget.
func (*MockContext) OverlayManager ¶
func (c *MockContext) OverlayManager() widget.OverlayManager
OverlayManager returns OverlayVal.
func (*MockContext) ReleaseFocus ¶
func (c *MockContext) ReleaseFocus(w widget.Widget)
ReleaseFocus clears focus if the given widget currently has it.
func (*MockContext) RequestFocus ¶
func (c *MockContext) RequestFocus(w widget.Widget)
RequestFocus sets FocusedVal to the given widget.
func (*MockContext) Reset ¶
func (c *MockContext) Reset()
Reset clears all recorded state (invalidation, cursor) while preserving configuration.
func (*MockContext) Scheduler ¶
func (c *MockContext) Scheduler() widget.SchedulerRef
Scheduler returns SchedulerVal.
func (*MockContext) SetCursor ¶
func (c *MockContext) SetCursor(cursor widget.CursorType)
SetCursor sets CursorVal.
func (*MockContext) ThemeProvider ¶
func (c *MockContext) ThemeProvider() widget.ThemeProvider
ThemeProvider returns ThemeVal.
func (*MockContext) WindowSize ¶
func (c *MockContext) WindowSize() geometry.Size
WindowSize returns WindowSizeVal.
type StrokeArcCall ¶ added in v0.1.14
type StrokeArcCall struct {
Center geometry.Point
Radius float32
StartAngle float64
SweepAngle float64
Color widget.Color
StrokeWidth float32
}
StrokeArcCall records a single StrokeArc invocation.
type StrokeArcStyledCall ¶ added in v0.1.14
type StrokeArcStyledCall struct {
Center geometry.Point
Radius float32
StartAngle float64
SweepAngle float64
Color widget.Color
StrokeWidth float32
Cap widget.LineCap
}
StrokeArcStyledCall records a single StrokeArcStyled invocation.
type StrokeCircleCall ¶
type StrokeCircleCall struct {
Center geometry.Point
Radius float32
Color widget.Color
StrokeWidth float32
}
StrokeCircleCall records a single StrokeCircle invocation.
type StrokeRectCall ¶
StrokeRectCall records a single StrokeRect invocation.