127 lines
4.2 KiB
Python
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"]
|