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
3 changes: 2 additions & 1 deletion pisnap/pisnap.go
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
20 changes: 20 additions & 0 deletions pisnap/pisnap_js_test.go
Original file line number Diff line number Diff line change
@@ -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)
}
37 changes: 37 additions & 0 deletions pisnap/pisnap_nonjs_test.go
Original file line number Diff line number Diff line change
@@ -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())
}
60 changes: 60 additions & 0 deletions pisnap/pisnap_test.go
Original file line number Diff line number Diff line change
@@ -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",
)
}
10 changes: 0 additions & 10 deletions pitest/pitest.go
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
127 changes: 127 additions & 0 deletions pitest/pitest_test.go
Original file line number Diff line number Diff line change
@@ -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())
})
}
})
}