defmodule Tilly.BDD.NodeTest do use ExUnit.Case, async: true alias Tilly.BDD.Node describe "Smart Constructors" do test "mk_true/0 returns true" do assert Node.mk_true() == true end test "mk_false/0 returns false" do assert Node.mk_false() == false end test "mk_leaf/1 creates a leaf node" do assert Node.mk_leaf(:some_value) == {:leaf, :some_value} assert Node.mk_leaf(123) == {:leaf, 123} end test "mk_split/4 creates a split node" do assert Node.mk_split(:el, :p_id, :i_id, :n_id) == {:split, :el, :p_id, :i_id, :n_id} end end describe "Predicates" do setup do %{ true_node: Node.mk_true(), false_node: Node.mk_false(), leaf_node: Node.mk_leaf("data"), split_node: Node.mk_split(1, 2, 3, 4) } end test "is_true?/1", %{true_node: t, false_node: f, leaf_node: l, split_node: s} do assert Node.is_true?(t) == true assert Node.is_true?(f) == false assert Node.is_true?(l) == false assert Node.is_true?(s) == false end test "is_false?/1", %{true_node: t, false_node: f, leaf_node: l, split_node: s} do assert Node.is_false?(f) == true assert Node.is_false?(t) == false assert Node.is_false?(l) == false assert Node.is_false?(s) == false end test "is_leaf?/1", %{true_node: t, false_node: f, leaf_node: l, split_node: s} do assert Node.is_leaf?(l) == true assert Node.is_leaf?(t) == false assert Node.is_leaf?(f) == false assert Node.is_leaf?(s) == false end test "is_split?/1", %{true_node: t, false_node: f, leaf_node: l, split_node: s} do assert Node.is_split?(s) == true assert Node.is_split?(t) == false assert Node.is_split?(f) == false assert Node.is_split?(l) == false end end describe "Accessors" do setup do %{ leaf_node: Node.mk_leaf("leaf_data"), split_node: Node.mk_split(:elem_id, :pos_child, :ign_child, :neg_child) } end test "value/1 for leaf node", %{leaf_node: l} do assert Node.value(l) == "leaf_data" end test "value/1 raises for non-leaf node" do assert_raise ArgumentError, ~r/Not a leaf node/, fn -> Node.value(Node.mk_true()) end assert_raise ArgumentError, ~r/Not a leaf node/, fn -> Node.value(Node.mk_split(1, 2, 3, 4)) end end test "element/1 for split node", %{split_node: s} do assert Node.element(s) == :elem_id end test "element/1 raises for non-split node" do assert_raise ArgumentError, ~r/Not a split node/, fn -> Node.element(Node.mk_true()) end assert_raise ArgumentError, ~r/Not a split node/, fn -> Node.element(Node.mk_leaf(1)) end end test "positive_child/1 for split node", %{split_node: s} do assert Node.positive_child(s) == :pos_child end test "positive_child/1 raises for non-split node" do assert_raise ArgumentError, ~r/Not a split node/, fn -> Node.positive_child(Node.mk_leaf(1)) end end test "ignore_child/1 for split node", %{split_node: s} do assert Node.ignore_child(s) == :ign_child end test "ignore_child/1 raises for non-split node" do assert_raise ArgumentError, ~r/Not a split node/, fn -> Node.ignore_child(Node.mk_leaf(1)) end end test "negative_child/1 for split node", %{split_node: s} do assert Node.negative_child(s) == :neg_child end test "negative_child/1 raises for non-split node" do assert_raise ArgumentError, ~r/Not a split node/, fn -> Node.negative_child(Node.mk_leaf(1)) end end end end