WitNote / internal /bridge /normalize_selector_test.go
AUXteam's picture
Upload folder using huggingface_hub
6a7089a verified
package bridge
import (
"testing"
)
// ---------------------------------------------------------------------------
// NormalizeSelector – legacy Ref promotion
// ---------------------------------------------------------------------------
func TestNormalizeSelector_RefPromotion(t *testing.T) {
// When Ref is set and Selector is empty, Ref should promote to Selector.
req := ActionRequest{Ref: "e5"}
req.NormalizeSelector()
if req.Selector != "e5" {
t.Errorf("after NormalizeSelector: Selector = %q, want %q", req.Selector, "e5")
}
}
func TestNormalizeSelector_RefPromotionVariousRefs(t *testing.T) {
refs := []string{"e0", "e1", "e42", "e99999"}
for _, ref := range refs {
req := ActionRequest{Ref: ref}
req.NormalizeSelector()
if req.Selector != ref {
t.Errorf("NormalizeSelector(Ref=%q): Selector = %q, want %q", ref, req.Selector, ref)
}
}
}
// ---------------------------------------------------------------------------
// NormalizeSelector – Selector preserved
// ---------------------------------------------------------------------------
func TestNormalizeSelector_SelectorPreserved(t *testing.T) {
// When Selector is already set, it should not be overwritten.
req := ActionRequest{Selector: "#login"}
req.NormalizeSelector()
if req.Selector != "#login" {
t.Errorf("after NormalizeSelector: Selector = %q, want %q", req.Selector, "#login")
}
}
func TestNormalizeSelector_SelectorPreservedVariousTypes(t *testing.T) {
selectors := []string{
"#login",
".btn.primary",
"div > span",
"//div[@id='main']",
"button",
"e5", // even if it looks like a ref, if it's in Selector field, keep it
}
for _, sel := range selectors {
req := ActionRequest{Selector: sel}
req.NormalizeSelector()
if req.Selector != sel {
t.Errorf("NormalizeSelector(Selector=%q): Selector = %q, want %q", sel, req.Selector, sel)
}
}
}
// ---------------------------------------------------------------------------
// NormalizeSelector – Ref wins when both set
// ---------------------------------------------------------------------------
func TestNormalizeSelector_RefWinsWhenBothSet(t *testing.T) {
// When both Ref and Selector are set, Selector is already populated
// so NormalizeSelector leaves it as-is (Ref doesn't overwrite).
// This tests the documented "Ref > Selector" priority β€” but the
// implementation only promotes Ref when Selector is empty.
req := ActionRequest{Ref: "e5", Selector: "#login"}
req.NormalizeSelector()
// Selector stays as "#login" because it was already set
if req.Selector != "#login" {
t.Errorf("after NormalizeSelector: Selector = %q, want %q", req.Selector, "#login")
}
}
// ---------------------------------------------------------------------------
// NormalizeSelector – empty fields
// ---------------------------------------------------------------------------
func TestNormalizeSelector_BothEmpty(t *testing.T) {
req := ActionRequest{}
req.NormalizeSelector()
if req.Selector != "" {
t.Errorf("after NormalizeSelector: Selector = %q, want empty", req.Selector)
}
if req.Ref != "" {
t.Errorf("after NormalizeSelector: Ref = %q, want empty", req.Ref)
}
}
func TestNormalizeSelector_EmptyRef(t *testing.T) {
req := ActionRequest{Ref: "", Selector: ".btn"}
req.NormalizeSelector()
if req.Selector != ".btn" {
t.Errorf("after NormalizeSelector: Selector = %q, want %q", req.Selector, ".btn")
}
}
// ---------------------------------------------------------------------------
// NormalizeSelector – idempotency
// ---------------------------------------------------------------------------
func TestNormalizeSelector_Idempotent(t *testing.T) {
// Calling NormalizeSelector multiple times should produce the same result.
tests := []ActionRequest{
{Ref: "e5"},
{Selector: "#login"},
{Ref: "e42", Selector: ""},
{},
{Ref: "e10", Selector: ".btn"},
}
for _, req := range tests {
r1 := req
r1.NormalizeSelector()
sel1 := r1.Selector
ref1 := r1.Ref
r1.NormalizeSelector()
if r1.Selector != sel1 {
t.Errorf("idempotency failed: Selector changed from %q to %q", sel1, r1.Selector)
}
if r1.Ref != ref1 {
t.Errorf("idempotency failed: Ref changed from %q to %q", ref1, r1.Ref)
}
// Third call for good measure
r1.NormalizeSelector()
if r1.Selector != sel1 {
t.Errorf("idempotency failed on 3rd call: Selector = %q, want %q", r1.Selector, sel1)
}
}
}
// ---------------------------------------------------------------------------
// NormalizeSelector – does not modify other fields
// ---------------------------------------------------------------------------
func TestNormalizeSelector_OtherFieldsUntouched(t *testing.T) {
req := ActionRequest{
Ref: "e5",
Kind: "click",
Text: "hello",
Key: "Enter",
TabID: "tab1",
NodeID: 42,
X: 1.5,
Y: 2.5,
HasXY: true,
}
req.NormalizeSelector()
if req.Kind != "click" {
t.Errorf("Kind changed: %q", req.Kind)
}
if req.Text != "hello" {
t.Errorf("Text changed: %q", req.Text)
}
if req.Key != "Enter" {
t.Errorf("Key changed: %q", req.Key)
}
if req.TabID != "tab1" {
t.Errorf("TabID changed: %q", req.TabID)
}
if req.NodeID != 42 {
t.Errorf("NodeID changed: %d", req.NodeID)
}
if req.X != 1.5 || req.Y != 2.5 {
t.Errorf("X/Y changed: %f, %f", req.X, req.Y)
}
if !req.HasXY {
t.Error("HasXY changed")
}
// Ref should still be "e5" (not cleared)
if req.Ref != "e5" {
t.Errorf("Ref changed: %q", req.Ref)
}
}
// ---------------------------------------------------------------------------
// NormalizeSelector – non-ref values in Ref field (legacy edge case)
// ---------------------------------------------------------------------------
func TestNormalizeSelector_NonRefValueInRefField(t *testing.T) {
// Some legacy callers might put a CSS selector in the Ref field.
// NormalizeSelector should still promote it to Selector.
req := ActionRequest{Ref: "#login"}
req.NormalizeSelector()
if req.Selector != "#login" {
t.Errorf("after NormalizeSelector: Selector = %q, want %q", req.Selector, "#login")
}
}