Files
tbd/test/tbd/todo/db_test.clj
ajet b1783e3f85
CI / Test + coverage (push) Failing after 22s
add todo api
2026-09-19 07:46:05 -09:00

70 lines
2.9 KiB
Clojure

(ns tbd.todo.db-test
(:require [clojure.java.io :as io]
[clojure.test :refer [deftest is testing]]
[tbd.todo.db :as db])
(:import (java.nio.file Files)
(java.nio.file.attribute FileAttribute)))
(defn temp-db-path
"A path for a database file inside a fresh temp directory (which `open` has to create a
subdirectory of, as with the default data/todo.db)."
[]
(str (Files/createTempDirectory "tbd-todo" (make-array FileAttribute 0)) "/data/todo.db"))
(defn todo [owner-id title]
{:owner-id owner-id :title title :done false :created-at 1000 :updated-at 1000})
(deftest env-config-test
(is (= {:db-path "data/todo.db"} (db/env-config {})))
(is (= {:db-path "data/todo.db"} (db/env-config {"TODO_DB_PATH" " "})))
(is (= {:db-path "/var/todo.db"} (db/env-config {"TODO_DB_PATH" " /var/todo.db "}))))
(deftest open-test
(testing "creates the file and its directory"
(let [path (temp-db-path)]
(db/open path)
(is (.exists (io/file path)))))
(testing "reopening keeps the data"
(let [path (temp-db-path)
saved (db/insert! (db/open path) (todo 7 "buy milk"))]
(is (= [saved] (db/list-todos (db/open path) 7)))))
(testing "a path is required"
(doseq [path [nil "" " "]]
(is (thrown? clojure.lang.ExceptionInfo (db/open path))))))
(deftest crud-test
(let [ds (db/open (temp-db-path))
saved (db/insert! ds (todo 7 "buy milk"))
id (:id saved)]
(testing "insert returns the stored todo with an id"
(is (= (assoc (todo 7 "buy milk") :id id) saved))
(is (not= id (:id (db/insert! ds (todo 7 "walk dog"))))))
(testing "find and list"
(is (= saved (db/find-todo ds 7 id)))
(is (= ["buy milk" "walk dog"] (map :title (db/list-todos ds 7)))))
(testing "update"
(is (= (assoc saved :title "buy oat milk" :done true :updated-at 2000)
(db/update! ds 7 (assoc saved :title "buy oat milk" :done true :updated-at 2000))))
(is (= true (:done (db/find-todo ds 7 id)))))
(testing "missing ids"
(is (nil? (db/find-todo ds 7 999)))
(is (nil? (db/update! ds 7 (assoc saved :id 999))))
(is (false? (db/delete! ds 7 999))))
(testing "delete"
(is (true? (db/delete! ds 7 id)))
(is (nil? (db/find-todo ds 7 id)))
(is (false? (db/delete! ds 7 id))))))
(deftest owner-scoping-test
(let [ds (db/open (temp-db-path))
mine (db/insert! ds (todo 7 "mine"))
theirs (db/insert! ds (todo 8 "theirs"))]
(is (= [mine] (db/list-todos ds 7)))
(is (= [theirs] (db/list-todos ds 8)))
(is (= [] (db/list-todos ds 9)))
(testing "another owner's todo can't be found, changed, or deleted by its id"
(is (nil? (db/find-todo ds 8 (:id mine))))
(is (nil? (db/update! ds 8 (assoc mine :title "hijacked"))))
(is (false? (db/delete! ds 8 (:id mine))))
(is (= mine (db/find-todo ds 7 (:id mine)))))))