fischer-agentkit/tests/unit/bitable/test_functions_text.py

127 lines
4.2 KiB
Python

"""Tests for text formula functions (R1)."""
from __future__ import annotations
from agentkit.bitable.formula.functions.text import TEXT_FUNCTIONS
# ── Registry ────────────────────────────────────────────
def test_registry_has_17_functions() -> None:
assert len(TEXT_FUNCTIONS) == 17
expected = {
"CONCAT", "LEN", "FIND", "MID", "LEFT", "RIGHT", "REPLACE", "SUBSTITUTE",
"UPPER", "LOWER", "TRIM", "REPT", "TEXT", "VALUE", "STARTSWITH", "ENDSWITH",
"SPLIT",
}
assert set(TEXT_FUNCTIONS.keys()) == expected
# ── migrated functions ──────────────────────────────────
def test_concat() -> None:
assert TEXT_FUNCTIONS["CONCAT"]("a", "b", "c") == "abc"
assert TEXT_FUNCTIONS["CONCAT"]("a", None, "c") == "ac"
def test_len() -> None:
assert TEXT_FUNCTIONS["LEN"]("hello") == 5
assert TEXT_FUNCTIONS["LEN"](None) == 0
assert TEXT_FUNCTIONS["LEN"](123) == 3
# ── find / extract ──────────────────────────────────────
def test_find() -> None:
assert TEXT_FUNCTIONS["FIND"]("hello world", "world") == 6
assert TEXT_FUNCTIONS["FIND"]("hello", "xyz") == -1
assert TEXT_FUNCTIONS["FIND"]("hello", "") == 0
def test_mid() -> None:
assert TEXT_FUNCTIONS["MID"]("hello", 1, 3) == "ell"
assert TEXT_FUNCTIONS["MID"]("hello", 0, 2) == "he"
assert TEXT_FUNCTIONS["MID"]("hello", -1, 2) == "he" # negative clamped
def test_left() -> None:
assert TEXT_FUNCTIONS["LEFT"]("hello", 3) == "hel"
assert TEXT_FUNCTIONS["LEFT"]("hello") == "h" # default n=1
assert TEXT_FUNCTIONS["LEFT"]("hello", 0) == ""
def test_right() -> None:
assert TEXT_FUNCTIONS["RIGHT"]("hello", 3) == "llo"
assert TEXT_FUNCTIONS["RIGHT"]("hello") == "o" # default n=1
# ── replace / substitute ────────────────────────────────
def test_replace() -> None:
# REPLACE("hello", 1, 3, "XYZ") → "h" + "XYZ" + "o" = "hXYZo"
# Replaces 3 chars starting at index 1: "ell" → "XYZ"
assert TEXT_FUNCTIONS["REPLACE"]("hello", 1, 3, "XYZ") == "hXYZo"
def test_substitute_all() -> None:
assert TEXT_FUNCTIONS["SUBSTITUTE"]("a-b-c", "-", "+") == "a+b+c"
def test_substitute_nth() -> None:
# Replace only the 2nd occurrence
assert TEXT_FUNCTIONS["SUBSTITUTE"]("a-b-c", "-", "+", 2) == "a-b+c"
# ── case / trim ─────────────────────────────────────────
def test_upper_lower() -> None:
assert TEXT_FUNCTIONS["UPPER"]("hello") == "HELLO"
assert TEXT_FUNCTIONS["LOWER"]("HELLO") == "hello"
def test_trim() -> None:
assert TEXT_FUNCTIONS["TRIM"](" hello world ") == "hello world"
# ── repeat / format / convert ───────────────────────────
def test_rept() -> None:
assert TEXT_FUNCTIONS["REPT"]("ab", 3) == "ababab"
assert TEXT_FUNCTIONS["REPT"]("ab", 0) == ""
def test_text_format() -> None:
assert TEXT_FUNCTIONS["TEXT"](3.14159, ".2f") == "3.14"
assert TEXT_FUNCTIONS["TEXT"](42) == "42"
def test_value() -> None:
assert TEXT_FUNCTIONS["VALUE"]("42") == 42
assert TEXT_FUNCTIONS["VALUE"]("3.14") == 3.14
assert TEXT_FUNCTIONS["VALUE"]("not a number") is None
assert TEXT_FUNCTIONS["VALUE"](None) is None
# ── predicates / split ──────────────────────────────────
def test_startswith() -> None:
assert TEXT_FUNCTIONS["STARTSWITH"]("hello world", "hello") is True
assert TEXT_FUNCTIONS["STARTSWITH"]("hello world", "world") is False
def test_endswith() -> None:
assert TEXT_FUNCTIONS["ENDSWITH"]("hello world", "world") is True
assert TEXT_FUNCTIONS["ENDSWITH"]("hello world", "hello") is False
def test_split() -> None:
assert TEXT_FUNCTIONS["SPLIT"]("a,b,c", ",") == ["a", "b", "c"]
assert TEXT_FUNCTIONS["SPLIT"]("hello", ",") == ["hello"]