diff --git a/pisnap/pisnap.go b/pisnap/pisnap.go index 2a87926..66c9446 100644 --- a/pisnap/pisnap.go +++ b/pisnap/pisnap.go @@ -7,12 +7,13 @@ package pisnap import ( "errors" "fmt" - "github.com/elgopher/pi" "image" "image/color" "image/png" "os" "runtime" + + "github.com/elgopher/pi" ) // CaptureOrErr captures a screenshot and saves it to the temporary directory. diff --git a/pisnap/pisnap_js_test.go b/pisnap/pisnap_js_test.go new file mode 100644 index 0000000..dcb0223 --- /dev/null +++ b/pisnap/pisnap_js_test.go @@ -0,0 +1,20 @@ +// Copyright 2025 Jacek Olszak +// This code is licensed under MIT license (see LICENSE for details) + +//go:build js + +package pisnap_test + +import ( + "testing" + + "github.com/elgopher/pi/pisnap" + + "github.com/stretchr/testify/assert" +) + +func TestCaptureOrErr(t *testing.T) { + file, err := pisnap.CaptureOrErr() + assert.Error(t, err) + assert.Empty(t, file) +} diff --git a/pisnap/pisnap_nonjs_test.go b/pisnap/pisnap_nonjs_test.go new file mode 100644 index 0000000..1c81a7a --- /dev/null +++ b/pisnap/pisnap_nonjs_test.go @@ -0,0 +1,37 @@ +// Copyright 2025 Jacek Olszak +// This code is licensed under MIT license (see LICENSE for details) + +//go:build !js + +package pisnap_test + +import ( + "bytes" + "image" + "image/png" + "os" + "testing" + + "github.com/elgopher/pi" + "github.com/elgopher/pi/pisnap" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestCaptureOrErr(t *testing.T) { + // when + file, err := pisnap.CaptureOrErr() + // then + require.NoError(t, err) + assert.NotEmpty(t, file) + // and file exists + f, err := os.ReadFile(file) + require.NoError(t, err, "cannot read PNG file") + // and + img, err := png.Decode(bytes.NewReader(f)) + require.NoError(t, err, "file is not a valid PNG") + // and + palettedImage, ok := img.(*image.Paletted) + require.True(t, ok, "image is not a Paletted") + assertPalettedImage(t, palettedImage, pi.Screen()) +} diff --git a/pisnap/pisnap_test.go b/pisnap/pisnap_test.go new file mode 100644 index 0000000..af4ab8f --- /dev/null +++ b/pisnap/pisnap_test.go @@ -0,0 +1,60 @@ +// Copyright 2025 Jacek Olszak +// This code is licensed under MIT license (see LICENSE for details) + +package pisnap_test + +import ( + "image" + "testing" + + "github.com/elgopher/pi" + "github.com/elgopher/pi/pisnap" + "github.com/stretchr/testify/assert" +) + +func TestPalettedImage(t *testing.T) { + pi.SetScreenSize(2, 3) + pi.Palette[1] = 0xffaa44 + pi.Palette[2] = 0xff0000 + pi.Palette[3] = 0x00ff00 + pi.Palette[4] = 0x0000ff + pi.Palette[5] = 0x00ffff + pi.Palette[6] = 0xff00ff + screen := pi.Screen() + screen.SetAll(1, 2, 3, 4, 5, 6) + // when + img := pisnap.PalettedImage() + // then + assertPalettedImage(t, img, screen) +} + +func assertPalettedImage(t *testing.T, img image.PalettedImage, screen pi.Canvas) { + t.Helper() + + // then color indexes are the same + for y := 0; y < screen.H(); y++ { + for x := 0; x < screen.W(); x++ { + actual := img.ColorIndexAt(x, y) + expected := screen.Get(x, y) + assert.Equal(t, expected, actual) + } + } + // and RGBA colors match + for y := 0; y < screen.H(); y++ { + for x := 0; x < screen.W(); x++ { + r, g, b, a := img.At(x, y).RGBA() + assert.Equal(t, uint8(0xff), uint8(a)) + actual := pi.FromRGB(uint8(r), uint8(g), uint8(b)) + expected := pi.Palette[screen.Get(x, y)] + assert.Equal(t, expected, actual) + } + } + // and size is the same + assert.Equal(t, + image.Rectangle{ + Max: image.Point{X: screen.W(), Y: screen.H()}, + }, + img.Bounds(), + "image size is not same as screen size", + ) +} diff --git a/pitest/pitest.go b/pitest/pitest.go index d67219e..14dce35 100644 --- a/pitest/pitest.go +++ b/pitest/pitest.go @@ -57,17 +57,7 @@ func AssertSpriteEqual(t *testing.T, expected, actual pi.Sprite) { expectedArrayPointer := unsafe.SliceData(expectedSource.Data()) actualArrayPointer := unsafe.SliceData(actualSource.Data()) sameArrayPointer := actualArrayPointer == expectedArrayPointer - sameWidth := expectedSource.W() == actualSource.W() - sameHeight := expectedSource.H() == actualSource.H() - if !sameWidth { - t.Errorf("sprites are using different sources, "+ - "expected Canvas width: %d, actual width: %d", expectedSource.W(), actualSource.W()) - } - if !sameHeight { - t.Errorf("sprites are using different sources, "+ - "expected Canvas height: %d, actual height: %d", expectedSource.H(), actualSource.H()) - } if !sameArrayPointer { t.Errorf("sprites are using different sources, "+ "pointers to Canvas data are not the same, expected: %+v, actual: %+v", diff --git a/pitest/pitest_test.go b/pitest/pitest_test.go new file mode 100644 index 0000000..3e1e251 --- /dev/null +++ b/pitest/pitest_test.go @@ -0,0 +1,127 @@ +// Copyright 2025 Jacek Olszak +// This code is licensed under MIT license (see LICENSE for details) + +package pitest_test + +import ( + "testing" + + "github.com/elgopher/pi" + "github.com/elgopher/pi/pitest" + "github.com/stretchr/testify/assert" +) + +func TestAssertSurfaceEqual(t *testing.T) { + t.Run("should not fail when surfaces are equal", func(t *testing.T) { + surface1 := pi.NewSurface[int](2, 3) + surface1.SetAll(0, 1, 2, 3, 4, 5) + surface2 := surface1.Clone() + mockT := new(testing.T) + // when + actual := pitest.AssertSurfaceEqual(mockT, surface1, surface2) + // then + assert.False(t, mockT.Failed()) + assert.True(t, actual) + }) + + t.Run("should fail when surfaces are not equal", func(t *testing.T) { + tests := map[string]struct { + surface1, surface2 pi.Surface[int] + }{ + "different data": { + surface1: func() pi.Surface[int] { + surface := pi.NewSurface[int](1, 1) + surface.SetAll(1, 2) + return surface + }(), + surface2: pi.NewSurface[int](1, 1), + }, + "different width": { + surface1: pi.NewSurface[int](1, 1), + surface2: pi.NewSurface[int](2, 1), + }, + "different height": { + surface1: pi.NewSurface[int](1, 1), + surface2: pi.NewSurface[int](1, 2), + }, + } + for testName, testCase := range tests { + t.Run(testName, func(t *testing.T) { + mockT := new(testing.T) + // when + actual := pitest.AssertSurfaceEqual(mockT, testCase.surface1, testCase.surface2) + // then + assert.True(t, mockT.Failed()) + assert.False(t, actual) + }) + } + }) +} + +func TestAssertSpriteEqual(t *testing.T) { + t.Run("should not fail when sprites are equal", func(t *testing.T) { + canvas := pi.NewCanvas(1, 1) + canvas.SetAll(1, 2) + sprite1 := pi.CanvasSprite(canvas) + sprite2 := pi.CanvasSprite(canvas) + mockT := new(testing.T) + // when + pitest.AssertSpriteEqual(mockT, sprite1, sprite2) + // then + assert.False(t, mockT.Failed()) + }) + + t.Run("should fail when sprites are not equal", func(t *testing.T) { + var data = []pi.Color{1, 2} + canvas := pi.NewCanvas(1, 1) + canvas.SetData(data) + + tests := map[string]struct { + sprite1, sprite2 pi.Sprite + }{ + "different canvas": { + sprite1: func() pi.Sprite { + return pi.CanvasSprite(canvas) + }(), + sprite2: func() pi.Sprite { + canvas := pi.NewCanvas(1, 1) + canvas.SetData(data) + return pi.CanvasSprite(canvas) + }(), + }, + "different area": { + sprite1: func() pi.Sprite { + return pi.CanvasSprite(canvas) + }(), + sprite2: func() pi.Sprite { + return pi.SpriteFrom(canvas, 1, 1, 0, 0) + }(), + }, + "different flipX": { + sprite1: func() pi.Sprite { + return pi.CanvasSprite(canvas).WithFlipX(true) + }(), + sprite2: func() pi.Sprite { + return pi.CanvasSprite(canvas) + }(), + }, + "different flipY": { + sprite1: func() pi.Sprite { + return pi.CanvasSprite(canvas).WithFlipY(true) + }(), + sprite2: func() pi.Sprite { + return pi.CanvasSprite(canvas) + }(), + }, + } + for testName, testCase := range tests { + t.Run(testName, func(t *testing.T) { + mockT := new(testing.T) + // when + pitest.AssertSpriteEqual(mockT, testCase.sprite1, testCase.sprite2) + // then + assert.True(t, mockT.Failed()) + }) + } + }) +}