Files

91 lines
3.0 KiB
Go

// Copyright (c) 2026 Storm Dragon
// Authors: Storm Dragon, Angus Kola
// SPDX-License-Identifier: GPL-3.0-or-later
package ocr
import (
"image"
"math"
"testing"
)
func TestTransformScreenRectangle(t *testing.T) {
transform := Transform{
ImageContent: image.Rect(10, 20, 310, 221),
ScreenBounds: image.Rect(-120, -50, -20, 50),
HasScreenMapping: true,
}
for _, test := range []struct {
name string
bounds, expected image.Rectangle
valid bool
}{
{"full", transform.ImageContent, transform.ScreenBounds, true},
{"independent axes", image.Rect(13, 22, 19, 26), image.Rect(-119, -50, -117, -47), true},
{"partial padding", image.Rect(0, 0, 13, 22), image.Rect(-120, -50, -119, -49), true},
{"only padding", image.Rect(0, 0, 10, 20), image.Rectangle{}, false},
{"empty", image.Rectangle{}, image.Rectangle{}, false},
{"beyond image", image.Rect(400, 400, 410, 410), image.Rectangle{}, false},
} {
t.Run(test.name, func(t *testing.T) {
got, valid := transform.ScreenRectangle(test.bounds)
if got != test.expected || valid != test.valid {
t.Fatalf("mapped %v, %v; want %v, %v", got, valid, test.expected, test.valid)
}
})
}
transform.HasScreenMapping = false
if _, valid := transform.ScreenRectangle(transform.ImageContent); valid {
t.Fatal("clipboard image acquired screen coordinates")
}
transform.HasScreenMapping = true
transform.ScreenBounds = image.Rect(math.MinInt32, 0, math.MinInt32+100, 100)
if _, valid := transform.ScreenRectangle(transform.ImageContent); valid {
t.Fatal("unknown native origin acquired coordinates")
}
transform.ScreenBounds = image.Rect(-math.MaxInt32, 0, math.MaxInt32, 100)
if _, valid := transform.ScreenRectangle(transform.ImageContent); valid {
t.Fatal("overflow-sized screen rectangle acquired coordinates")
}
}
func TestRuneOffsetsAndWordHitTesting(t *testing.T) {
result := Result{
Text: "é 中文\ne\u0301",
Words: []Word{
{Text: "é", Span: Span{0, 1}},
{Text: "中文", Span: Span{2, 4}},
{Text: "e\u0301", Span: Span{5, 7}},
},
}
for offset, want := range []int{0, 2, 3, 6, 9, 10, 11, 13} {
got, valid := result.ByteOffset(offset)
if !valid || got != want {
t.Fatalf("byte offset %d = %d, %v; want %d", offset, got, valid, want)
}
}
for _, offset := range []int{-1, 1, 4, 7, 8} {
if word, valid := result.WordAt(offset); valid {
t.Fatalf("separator/end offset %d chose %q", offset, word.Text)
}
}
for _, offset := range []int{0, 2, 3, 5, 6} {
if _, valid := result.WordAt(offset); !valid {
t.Fatalf("word offset %d missing", offset)
}
}
for _, offset := range []int{-1, 8} {
if _, valid := result.ByteOffset(offset); valid {
t.Fatalf("invalid rune offset %d accepted", offset)
}
}
if offset, valid := (Result{}).ByteOffset(0); offset != 0 || !valid {
t.Fatal("empty document lost its end position")
}
phrase := Result{Text: "a b", Words: []Word{{Text: "a b", Span: Span{0, 3}}}}
if _, valid := phrase.WordAt(1); valid {
t.Fatal("whitespace inside an engine word acquired an activation target")
}
}