142 lines
4.5 KiB
Python
142 lines
4.5 KiB
Python
"""Tests for logical formula functions (R1)."""
|
|
|
|
from __future__ import annotations
|
|
|
|
from agentkit.bitable.formula.functions.logical import LOGICAL_FUNCTIONS
|
|
|
|
|
|
def test_registry_has_15_functions() -> None:
|
|
assert len(LOGICAL_FUNCTIONS) == 15
|
|
expected = {
|
|
"IF", "IFS", "SWITCH", "IFERROR", "COALESCE", "AND", "OR", "NOT",
|
|
"ISBLANK", "ISNUMBER", "ISTEXT", "ISDATE", "TRUE", "FALSE", "NULL",
|
|
}
|
|
assert set(LOGICAL_FUNCTIONS.keys()) == expected
|
|
|
|
|
|
# ── IF (migrated) ───────────────────────────────────────
|
|
|
|
|
|
def test_if_true() -> None:
|
|
assert LOGICAL_FUNCTIONS["IF"](1, "yes", "no") == "yes"
|
|
|
|
|
|
def test_if_false() -> None:
|
|
assert LOGICAL_FUNCTIONS["IF"](0, "yes", "no") == "no"
|
|
|
|
|
|
def test_if_default_false() -> None:
|
|
assert LOGICAL_FUNCTIONS["IF"](0, "yes") is None
|
|
|
|
|
|
# ── IFS ─────────────────────────────────────────────────
|
|
|
|
|
|
def test_ifs_first_match() -> None:
|
|
assert LOGICAL_FUNCTIONS["IFS"](1, "a", 0, "b", 1, "c") == "a"
|
|
|
|
|
|
def test_ifs_second_match() -> None:
|
|
assert LOGICAL_FUNCTIONS["IFS"](0, "a", 1, "b", 0, "c") == "b"
|
|
|
|
|
|
def test_ifs_no_match() -> None:
|
|
assert LOGICAL_FUNCTIONS["IFS"](0, "a", 0, "b") is None
|
|
|
|
|
|
# ── SWITCH ──────────────────────────────────────────────
|
|
|
|
|
|
def test_switch_match() -> None:
|
|
assert LOGICAL_FUNCTIONS["SWITCH"]("b", "a", 1, "b", 2, "c", 3) == 2
|
|
|
|
|
|
def test_switch_default() -> None:
|
|
assert LOGICAL_FUNCTIONS["SWITCH"]("x", "a", 1, "b", 2, "default") == "default"
|
|
|
|
|
|
def test_switch_no_match_no_default() -> None:
|
|
assert LOGICAL_FUNCTIONS["SWITCH"]("x", "a", 1, "b", 2) is None
|
|
|
|
|
|
# ── IFERROR ─────────────────────────────────────────────
|
|
|
|
|
|
def test_iferror_passes_non_error() -> None:
|
|
assert LOGICAL_FUNCTIONS["IFERROR"](42, "default") == 42
|
|
|
|
|
|
def test_iferror_returns_default_for_error() -> None:
|
|
error_dict = {"__error": "division by zero"}
|
|
assert LOGICAL_FUNCTIONS["IFERROR"](error_dict, "default") == "default"
|
|
|
|
|
|
# ── COALESCE ────────────────────────────────────────────
|
|
|
|
|
|
def test_coalesce_first_non_empty() -> None:
|
|
assert LOGICAL_FUNCTIONS["COALESCE"]("a", "b", "c") == "a"
|
|
|
|
|
|
def test_coalesce_skips_none_and_empty() -> None:
|
|
assert LOGICAL_FUNCTIONS["COALESCE"](None, "", "c") == "c"
|
|
|
|
|
|
def test_coalesce_all_empty() -> None:
|
|
assert LOGICAL_FUNCTIONS["COALESCE"](None, "", None) is None
|
|
|
|
|
|
# ── Boolean operators ───────────────────────────────────
|
|
|
|
|
|
def test_and() -> None:
|
|
assert LOGICAL_FUNCTIONS["AND"](1, 1, 1) is True
|
|
assert LOGICAL_FUNCTIONS["AND"](1, 0, 1) is False
|
|
|
|
|
|
def test_or() -> None:
|
|
assert LOGICAL_FUNCTIONS["OR"](0, 0, 1) is True
|
|
assert LOGICAL_FUNCTIONS["OR"](0, 0, 0) is False
|
|
|
|
|
|
def test_not() -> None:
|
|
assert LOGICAL_FUNCTIONS["NOT"](1) is False
|
|
assert LOGICAL_FUNCTIONS["NOT"](0) is True
|
|
|
|
|
|
# ── Predicates ──────────────────────────────────────────
|
|
|
|
|
|
def test_isblank() -> None:
|
|
assert LOGICAL_FUNCTIONS["ISBLANK"](None) is True
|
|
assert LOGICAL_FUNCTIONS["ISBLANK"]("") is True
|
|
assert LOGICAL_FUNCTIONS["ISBLANK"]("x") is False
|
|
|
|
|
|
def test_isnumber() -> None:
|
|
assert LOGICAL_FUNCTIONS["ISNUMBER"](42) is True
|
|
assert LOGICAL_FUNCTIONS["ISNUMBER"](3.14) is True
|
|
assert LOGICAL_FUNCTIONS["ISNUMBER"]("42") is False
|
|
assert LOGICAL_FUNCTIONS["ISNUMBER"](True) is False # bool excluded
|
|
|
|
|
|
def test_istext() -> None:
|
|
assert LOGICAL_FUNCTIONS["ISTEXT"]("hello") is True
|
|
assert LOGICAL_FUNCTIONS["ISTEXT"](42) is False
|
|
|
|
|
|
def test_isdate() -> None:
|
|
assert LOGICAL_FUNCTIONS["ISDATE"]("2026-07-06") is True
|
|
assert LOGICAL_FUNCTIONS["ISDATE"]("2026-07-06T10:30:00") is True
|
|
assert LOGICAL_FUNCTIONS["ISDATE"]("not a date") is False
|
|
assert LOGICAL_FUNCTIONS["ISDATE"](42) is False
|
|
|
|
|
|
# ── Constants ───────────────────────────────────────────
|
|
|
|
|
|
def test_true_false_null() -> None:
|
|
assert LOGICAL_FUNCTIONS["TRUE"]() is True
|
|
assert LOGICAL_FUNCTIONS["FALSE"]() is False
|
|
assert LOGICAL_FUNCTIONS["NULL"]() is None
|