diff --git a/pimath/pimath_test.go b/pimath/pimath_test.go new file mode 100644 index 00000000..cb897c16 --- /dev/null +++ b/pimath/pimath_test.go @@ -0,0 +1,96 @@ +// Copyright 2025 Jacek Olszak +// This code is licensed under MIT license (see LICENSE for details) + +package pimath_test + +import ( + "testing" + + "github.com/elgopher/pi/pimath" + "github.com/stretchr/testify/assert" +) + +func TestClamp(t *testing.T) { + tests := map[string]struct { + x, min, max int + expected int + }{ + "lower than min": { + x: -1, min: 0, max: 1, + expected: 0, + }, + "equal to min": { + x: 0, min: 0, max: 1, + expected: 0, + }, + "greater than max": { + x: 2, min: 0, max: 1, + expected: 1, + }, + "equal to max": { + x: 1, min: 0, max: 1, + expected: 1, + }, + "between min and max": { + x: 1, min: 0, max: 2, + expected: 1, + }, + } + for testName, testCase := range tests { + t.Run(testName, func(t *testing.T) { + actual := pimath.Clamp(testCase.x, testCase.min, testCase.max) + assert.Equal(t, testCase.expected, actual) + }) + } +} + +func TestLerp(t *testing.T) { + tests := map[string]struct { + a, b, t float64 + expected float64 + }{ + "in the middle": { + a: 1, b: 2, t: 0.5, + expected: 1.5, + }, + "beginning": { + a: 1, b: 2, t: 0, + expected: 1, + }, + "end": { + a: 1, b: 2, t: 1, + expected: 2, + }, + } + for testName, testCase := range tests { + t.Run(testName, func(t *testing.T) { + actual := pimath.Lerp(testCase.a, testCase.b, testCase.t) + assert.InDelta(t, testCase.expected, actual, 0.01) + }) + } +} + +func TestDistance(t *testing.T) { + tests := map[string]struct { + x1, y1 float64 + x2, y2 float64 + expected float64 + }{ + "(0,0) to (2,2)": { + x1: 0, y1: 0, + x2: 2, y2: 2, + expected: 2.83, + }, + "(2,2) to (0,0)": { + x1: 2, y1: 2, + x2: 0, y2: 0, + expected: 2.83, + }, + } + for testName, testCase := range tests { + t.Run(testName, func(t *testing.T) { + actual := pimath.Distance(testCase.x1, testCase.y1, testCase.x2, testCase.y2) + assert.InDelta(t, testCase.expected, actual, 0.01) + }) + } +} diff --git a/piroutine/piroutine_test.go b/piroutine/piroutine_test.go index 2ecc9d6b..607154c5 100644 --- a/piroutine/piroutine_test.go +++ b/piroutine/piroutine_test.go @@ -6,8 +6,10 @@ package piroutine_test import ( "testing" + "github.com/elgopher/pi/piloop" "github.com/elgopher/pi/piroutine" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func TestPiroutine(t *testing.T) { @@ -45,3 +47,78 @@ func TestRoutine_Resume(t *testing.T) { assert.False(t, routine.Resume()) // nothing changed }) } + +func TestCall(t *testing.T) { + t.Run("should call callback", func(t *testing.T) { + var executed = false + step := piroutine.Call(func() { + executed = true + }) + // when + result := step() + // then + assert.True(t, executed) + assert.True(t, result) + }) +} + +func TestSlowDown(t *testing.T) { + t.Run("should wait n updates before running callback", func(t *testing.T) { + executionCount := 0 + step := piroutine.SlowDown(2, func() bool { + executionCount++ + return true + }) + assert.False(t, step()) + assert.Equal(t, 0, executionCount) + assert.False(t, step()) + assert.Equal(t, 0, executionCount) + assert.True(t, step()) + assert.Equal(t, 1, executionCount) + }) + + t.Run("should immediately run callback", func(t *testing.T) { + executionCount := 0 + step := piroutine.SlowDown(0, func() bool { + executionCount++ + return true + }) + assert.True(t, step()) + assert.Equal(t, 1, executionCount) + }) + + t.Run("should wait another n updates after callback returned false", func(t *testing.T) { + executionCount := 0 + step := piroutine.SlowDown(3, func() bool { + executionCount++ + return executionCount%2 == 0 + }) + for range 3 { + assert.False(t, step()) // wait + } + assert.False(t, step()) // callback returns false + for range 3 { + assert.False(t, step()) // wait + } + assert.True(t, step()) // callback returns true this time + assert.Equal(t, 2, executionCount) + }) +} + +func TestRoutine_ScheduleOn(t *testing.T) { + t.Run("should run callback on event", func(t *testing.T) { + executionCount := 0 + step := func() bool { + executionCount++ + return true + } + routine := piroutine.New(step) + // when + handler := routine.ScheduleOn(piloop.EventDraw) + // then + require.True(t, piloop.Target().IsSubscribed(handler)) + piloop.Target().Publish(piloop.EventDraw) // runs callback and unsubscribes handlers + assert.Equal(t, 1, executionCount) + assert.False(t, piloop.Target().IsSubscribed(handler)) + }) +} diff --git a/pisnap/pisnap_js_test.go b/pisnap/pisnap_js_test.go index dcb02239..782be925 100644 --- a/pisnap/pisnap_js_test.go +++ b/pisnap/pisnap_js_test.go @@ -1,8 +1,6 @@ // Copyright 2025 Jacek Olszak // This code is licensed under MIT license (see LICENSE for details) -//go:build js - package pisnap_test import (