defmodule CljElixir.REPLTest do use ExUnit.Case, async: true alias CljElixir.REPL describe "REPL.new" do test "creates initial state" do state = REPL.new() assert state.bindings == [] assert state.history == [] assert state.counter == 1 end end describe "REPL.eval" do test "evaluates simple expression" do state = REPL.new() assert {:ok, "3", _} = REPL.eval("(+ 1 2)", state) end test "pr-str formats output" do state = REPL.new() {:ok, result, _} = REPL.eval("\"hello\"", state) assert result == "\"hello\"" end test "nil result" do state = REPL.new() {:ok, result, _} = REPL.eval("nil", state) assert result == "nil" end test "map result" do state = REPL.new() {:ok, result, _} = REPL.eval("{:a 1 :b 2}", state) assert result =~ ":a" assert result =~ "1" end test "increments counter" do state = REPL.new() {:ok, _, state2} = REPL.eval("1", state) assert state2.counter == 2 {:ok, _, state3} = REPL.eval("2", state2) assert state3.counter == 3 end test "stores history" do state = REPL.new() {:ok, _, state2} = REPL.eval("(+ 1 2)", state) assert state2.history == ["(+ 1 2)"] {:ok, _, state3} = REPL.eval("(+ 3 4)", state2) assert state3.history == ["(+ 3 4)", "(+ 1 2)"] end test "error returns error tuple" do state = REPL.new() {:error, msg, _} = REPL.eval("(defmodule REPLErrTest (invalid-syntax", state) assert is_binary(msg) assert msg =~ "Error" or msg =~ "error" end test "defmodule persists across evals" do state = REPL.new() {:ok, _, state2} = REPL.eval(""" (defmodule REPLTestMod (defn hello [] :hi)) """, state) {:ok, result, _} = REPL.eval("(REPLTestMod/hello)", state2) assert result == ":hi" end test "tuple result" do state = REPL.new() {:ok, result, _} = REPL.eval("#el[:ok 42]", state) assert result == "#el[:ok 42]" end test "list result" do state = REPL.new() {:ok, result, _} = REPL.eval("(list 1 2 3)", state) assert result == "(1 2 3)" end end describe "REPL.balanced?" do test "balanced parens" do assert REPL.balanced?("(+ 1 2)") assert REPL.balanced?("(defn foo [x] (+ x 1))") assert REPL.balanced?("42") assert REPL.balanced?("") end test "unbalanced parens" do refute REPL.balanced?("(+ 1 2") refute REPL.balanced?("(defn foo [x]") refute REPL.balanced?("(let [x 1") end test "balanced with nested" do assert REPL.balanced?("(let [x (+ 1 2)] (* x x))") end test "string contents not counted" do assert REPL.balanced?("(str \"(hello)\")") assert REPL.balanced?("(str \"[not real]\")") end test "comment contents not counted" do assert REPL.balanced?("(+ 1 2) ; this has unbalanced (") end test "mixed delimiters" do assert REPL.balanced?("(let [{:keys [a b]} {:a 1 :b 2}] (+ a b))") refute REPL.balanced?("(let [{:keys [a b]} {:a 1 :b 2}] (+ a b)") end end end