;;; test-ob-elixir.el --- Tests for ob-elixir -*- lexical-binding: t; -*- ;;; Commentary: ;; Test suite for ob-elixir package. ;;; Code: (require 'ert) ;; Add parent directory to load path (let ((dir (file-name-directory (or load-file-name buffer-file-name)))) (add-to-list 'load-path (expand-file-name ".." dir))) (require 'ob-elixir) (ert-deftest ob-elixir-test-package-loads () "Test that the package loads successfully." (should (featurep 'ob-elixir))) (ert-deftest ob-elixir-test-elixir-available () "Test that Elixir is available." (should (executable-find ob-elixir-command))) (ert-deftest ob-elixir-test-simple-value () "Test simple value evaluation." (skip-unless (executable-find ob-elixir-command)) (let ((result (ob-elixir--execute "1 + 1" 'value))) (should (equal "2" result)))) (ert-deftest ob-elixir-test-simple-output () "Test simple output evaluation." (skip-unless (executable-find ob-elixir-command)) (let ((result (ob-elixir--execute "IO.puts(\"hello\")" 'output))) (should (equal "hello" result)))) (ert-deftest ob-elixir-test-multiline-value () "Test multiline code value evaluation." (skip-unless (executable-find ob-elixir-command)) (let ((result (ob-elixir--execute "x = 10\ny = 20\nx + y" 'value))) (should (equal "30" result)))) (ert-deftest ob-elixir-test-list-result () "Test list result." (skip-unless (executable-find ob-elixir-command)) (let ((result (ob-elixir--execute "[1, 2, 3]" 'value))) (should (equal "[1, 2, 3]" result)))) (ert-deftest ob-elixir-test-map-result () "Test map result." (skip-unless (executable-find ob-elixir-command)) (let ((result (ob-elixir--execute "%{a: 1, b: 2}" 'value))) ;; Maps are unordered in Elixir, so accept either order (should (or (string-match-p "%{a: 1, b: 2}" result) (string-match-p "%{b: 2, a: 1}" result))))) ;;; Type Conversion Tests (ert-deftest ob-elixir-test-convert-nil () "Test nil conversion." (should (equal "nil" (ob-elixir--elisp-to-elixir nil)))) (ert-deftest ob-elixir-test-convert-true () "Test t conversion." (should (equal "true" (ob-elixir--elisp-to-elixir t)))) (ert-deftest ob-elixir-test-convert-integer () "Test integer conversion." (should (equal "42" (ob-elixir--elisp-to-elixir 42))) (should (equal "-10" (ob-elixir--elisp-to-elixir -10)))) (ert-deftest ob-elixir-test-convert-float () "Test float conversion." (should (equal "3.14" (ob-elixir--elisp-to-elixir 3.14)))) (ert-deftest ob-elixir-test-convert-string () "Test string conversion." (should (equal "\"hello\"" (ob-elixir--elisp-to-elixir "hello")))) (ert-deftest ob-elixir-test-convert-string-escaping () "Test string escaping." (should (equal "\"say \\\"hi\\\"\"" (ob-elixir--elisp-to-elixir "say \"hi\""))) (should (equal "\"line1\\nline2\"" (ob-elixir--elisp-to-elixir "line1\nline2")))) (ert-deftest ob-elixir-test-convert-symbol () "Test symbol conversion to atom." (should (equal ":foo" (ob-elixir--elisp-to-elixir 'foo))) (should (equal ":ok" (ob-elixir--elisp-to-elixir 'ok)))) (ert-deftest ob-elixir-test-convert-list () "Test list conversion." (should (equal "[1, 2, 3]" (ob-elixir--elisp-to-elixir '(1 2 3)))) (should (equal "[\"a\", \"b\"]" (ob-elixir--elisp-to-elixir '("a" "b"))))) (ert-deftest ob-elixir-test-convert-nested-list () "Test nested list conversion." (should (equal "[[1, 2], [3, 4]]" (ob-elixir--elisp-to-elixir '((1 2) (3 4)))))) (ert-deftest ob-elixir-test-convert-vector () "Test vector to tuple conversion." (should (equal "{1, 2, 3}" (ob-elixir--elisp-to-elixir [1 2 3])))) ;;; Variable Injection Tests (ert-deftest ob-elixir-test-variable-assignments () "Test variable assignment generation." (let ((params '((:var . ("x" . 5)) (:var . ("name" . "Alice"))))) (let ((assignments (org-babel-variable-assignments:elixir params))) (should (member "x = 5" assignments)) (should (member "name = \"Alice\"" assignments))))) (ert-deftest ob-elixir-test-var-execution () "Test code execution with variables." (skip-unless (executable-find ob-elixir-command)) (let* ((params '((:var . ("x" . 10)))) (var-lines (org-babel-variable-assignments:elixir params)) (full-body (concat (mapconcat #'identity var-lines "\n") "\nx * 2"))) (should (equal "20" (ob-elixir--execute full-body 'value))))) (ert-deftest ob-elixir-test-var-list () "Test passing list as variable." (skip-unless (executable-find ob-elixir-command)) (let* ((params '((:var . ("data" . (1 2 3))))) (var-lines (org-babel-variable-assignments:elixir params)) (full-body (concat (mapconcat #'identity var-lines "\n") "\nEnum.sum(data)"))) (should (equal "6" (ob-elixir--execute full-body 'value))))) ;;; Error Handling Tests (ert-deftest ob-elixir-test-detect-runtime-error () "Test runtime error detection." (let ((output "** (RuntimeError) something went wrong")) (let ((error-info (ob-elixir--detect-error output))) (should error-info) (should (eq 'runtime (plist-get error-info :type))) (should (equal "RuntimeError" (plist-get error-info :error-type)))))) (ert-deftest ob-elixir-test-detect-compile-error () "Test compile error detection." (let ((output "** (CompileError) test.exs:1: undefined function foo/0")) (let ((error-info (ob-elixir--detect-error output))) (should error-info) (should (eq 'compile (plist-get error-info :type))) (should (equal "CompileError" (plist-get error-info :error-type)))))) (ert-deftest ob-elixir-test-no-error () "Test that valid output is not detected as error." (should-not (ob-elixir--detect-error "42")) (should-not (ob-elixir--detect-error "[1, 2, 3]")) (should-not (ob-elixir--detect-error "\"hello\""))) (ert-deftest ob-elixir-test-error-execution () "Test that errors are properly handled during execution." (skip-unless (executable-find ob-elixir-command)) (let ((ob-elixir-signal-errors nil)) (let ((result (ob-elixir--execute "raise \"test error\"" 'value))) (should (string-match-p "RuntimeError" result))))) (ert-deftest ob-elixir-test-error-signaling () "Test that errors are signaled when configured." (skip-unless (executable-find ob-elixir-command)) (let ((ob-elixir-signal-errors t)) (should-error (ob-elixir--execute "raise \"test error\"" 'value) :type 'ob-elixir-runtime-error))) (ert-deftest ob-elixir-test-undefined-function () "Test handling of undefined function error." (skip-unless (executable-find ob-elixir-command)) (let ((ob-elixir-signal-errors nil)) (let ((result (ob-elixir--execute "undefined_function()" 'value))) (should (string-match-p "\\(UndefinedFunctionError\\|CompileError\\)" result))))) (provide 'test-ob-elixir) ;;; test-ob-elixir.el ends here