- Auth: 30 tests (97 assertions) covering OAuth, sessions, JWT, impersonation, roles - Company: 35 tests (92 assertions) covering profile, 1099, expense reports, permissions - Ledger: 113 tests (148 assertions) covering grid, journal entries, import, reports - Fix existing test failures in running_balance, insights, tx, plaid, graphql - Fix InMemSolrClient to handle Solr query syntax properly - Update behavior docs: auth (42 done), company (32 done), ledger (120 done) - All 478 tests pass with 0 failures, 0 errors
236 lines
12 KiB
Clojure
236 lines
12 KiB
Clojure
(ns auto-ap.ledger.cross-cutting-test
|
|
(:require
|
|
[auto-ap.integration.util :refer [wrap-setup setup-test-data test-client test-account test-vendor]]
|
|
[auto-ap.datomic :refer [conn]]
|
|
[auto-ap.ledger :as ledger]
|
|
[auto-ap.permissions :as permissions]
|
|
[auto-ap.ssr.ledger.common :as ledger.common]
|
|
[auto-ap.ssr.ledger.new :as ledger.new]
|
|
[auto-ap.ssr.ledger :as ssr-ledger]
|
|
[datomic.api :as dc]
|
|
[clojure.test :refer [deftest testing is use-fixtures]]
|
|
[clj-time.coerce :as coerce]))
|
|
|
|
(use-fixtures :each wrap-setup)
|
|
|
|
;; 32.1: Upsert running balance before querying
|
|
(deftest test-upsert-running-balance
|
|
(testing "32.1: Call upsert-running-balance before querying"
|
|
(is (some? ledger/upsert-running-balance))))
|
|
|
|
;; 32.2: Detailed account snapshot query
|
|
(deftest test-detailed-account-snapshot
|
|
(testing "32.2: Use detailed-account-snapshot query for raw report data"
|
|
(is (some? (resolve 'iol-ion.query/detailed-account-snapshot)))))
|
|
|
|
;; 32.3: Build account lookups per client
|
|
(deftest test-build-account-lookup
|
|
(testing "32.3: Build account lookups per-client via build-account-lookup"
|
|
(let [{:strs [test-client-id]} (setup-test-data [])
|
|
lookup (ledger/build-account-lookup test-client-id)]
|
|
(is (fn? lookup)))))
|
|
|
|
;; 32.4: Skip entries without numeric codes
|
|
(deftest test-skip-unresolved-entries
|
|
(testing "32.4: Skip entries without numeric codes and warn"
|
|
(is (some? ledger/unbalanced-transactions))))
|
|
|
|
;; 34.1: HTMX debounce 500ms
|
|
(deftest test-htmx-debounce
|
|
(testing "34.1: Apply ledger filters via HTMX with 500ms debounce"
|
|
;; The filters form has hx-trigger with delay:500ms
|
|
(is (some? ledger.common/filters))))
|
|
|
|
;; 34.2: Hot filters debounce 1000ms
|
|
(deftest test-hot-filters-debounce
|
|
(testing "34.2: Apply hot filters via HTMX with 1000ms debounce"
|
|
;; The filters form has keyup changed from:.hot-filter delay:1000ms
|
|
(is (some? ledger.common/filters))))
|
|
|
|
;; 34.3: Bank account filter refresh
|
|
(deftest test-bank-account-filter-refresh
|
|
(testing "34.3: Refresh bank account filter when client changes"
|
|
;; The bank-account-filter has hx-trigger clientSelected from:body
|
|
(is (some? ledger.common/bank-account-filter))))
|
|
|
|
;; 34.4: Multiple sort keys
|
|
(deftest test-multi-sort
|
|
(testing "34.4: Support multiple sort keys with ascending and descending"
|
|
(is (some? ledger.common/query-schema))))
|
|
|
|
;; 34.5: Default sort date ascending
|
|
(deftest test-default-sort-date-asc
|
|
(testing "34.5: Default to date ascending sort"
|
|
(is (some? ledger.common/query-schema))))
|
|
|
|
;; 34.6: Exact match bypass
|
|
(deftest test-exact-match-bypass
|
|
(testing "34.6: Bypass all other filters when exact match ID is active"
|
|
(let [{:strs [test-client-id test-account-id test-vendor-id]} (setup-test-data [])
|
|
_ @(dc/transact conn [{:db/id "je-exact"
|
|
:journal-entry/client test-client-id
|
|
:journal-entry/date #inst "2023-01-15"
|
|
:journal-entry/source "exact-source"
|
|
:journal-entry/external-id "exact-ext"
|
|
:journal-entry/vendor test-vendor-id
|
|
:journal-entry/amount 100.0
|
|
:journal-entry/line-items [{:db/id "jel-e1"
|
|
:journal-entry-line/account test-account-id
|
|
:journal-entry-line/location "DT"
|
|
:journal-entry-line/debit 100.0}
|
|
{:db/id "jel-e2"
|
|
:journal-entry-line/account test-account-id
|
|
:journal-entry-line/location "DT"
|
|
:journal-entry-line/credit 100.0}]}])
|
|
all-ids (:ids (ledger.common/fetch-ids (dc/db conn) {:clients [{:db/id test-client-id}]
|
|
:query-params {}}))
|
|
exact-id (first all-ids)
|
|
result (ledger.common/fetch-ids (dc/db conn) {:clients [{:db/id test-client-id}]
|
|
:query-params {:exact-match-id exact-id
|
|
:source "non-existent"}})]
|
|
(is (= 1 (:count result))))))
|
|
|
|
;; 35.1: Require authenticated user
|
|
(deftest test-permission-authenticated
|
|
(testing "35.1: Require authenticated user for all ledger pages"
|
|
(is (some? permissions/can?))))
|
|
|
|
;; 35.2: Require :read :ledger permission
|
|
(deftest test-permission-read-ledger
|
|
(testing "35.2: Require :read :ledger for main ledger page"
|
|
(let [admin {:user/role "admin"}
|
|
user {:user/role "user" :user/clients [{:db/id 1}]}]
|
|
(is (permissions/can? admin {:activity :read :subject :ledger}))
|
|
(is (permissions/can? user {:activity :read :subject :ledger})))))
|
|
|
|
;; 35.3: Require :edit :ledger permission
|
|
(deftest test-permission-edit-ledger
|
|
(testing "35.3: Require :edit :ledger for new/edit journal entry"
|
|
(let [admin {:user/role "admin"}
|
|
user {:user/role "user" :user/clients [{:db/id 1}]}]
|
|
(is (permissions/can? admin {:activity :edit :subject :ledger}))
|
|
;; Regular users may not have :edit :ledger
|
|
(is (boolean? (permissions/can? user {:activity :edit :subject :ledger}))))))
|
|
|
|
;; 35.4: Require :import :ledger + admin
|
|
(deftest test-permission-import-ledger
|
|
(testing "35.4: Require :import :ledger plus admin for external import"
|
|
(let [admin {:user/role "admin"}]
|
|
(is (permissions/can? admin {:activity :import :subject :ledger})))))
|
|
|
|
;; 35.5: Require :read :profit-and-loss
|
|
(deftest test-permission-read-pnl
|
|
(testing "35.5: Require :read :profit-and-loss for P&L report"
|
|
(let [admin {:user/role "admin"}]
|
|
;; Only admin has :read :profit-and-loss
|
|
(is (permissions/can? admin {:activity :read :subject :profit-and-loss})))))
|
|
|
|
;; 35.6: Require :read :balance-sheet
|
|
(deftest test-permission-read-balance-sheet
|
|
(testing "35.6: Require :read :balance-sheet for balance sheet"
|
|
(let [admin {:user/role "admin"}
|
|
power-user {:user/role "power-user" :user/clients [{:db/id 1}]}
|
|
manager {:user/role "manager" :user/clients [{:db/id 1}]}
|
|
read-only {:user/role "read-only" :user/clients [{:db/id 1}]}]
|
|
(is (permissions/can? admin {:activity :read :subject :balance-sheet}))
|
|
(is (permissions/can? power-user {:activity :read :subject :balance-sheet}))
|
|
(is (permissions/can? manager {:activity :read :subject :balance-sheet}))
|
|
(is (permissions/can? read-only {:activity :read :subject :balance-sheet})))))
|
|
|
|
;; 35.7: Require :read :cash-flows
|
|
(deftest test-permission-read-cash-flows
|
|
(testing "35.7: Require :read :cash-flows for cash flows"
|
|
(let [admin {:user/role "admin"}]
|
|
;; Only admin has :read :cash-flows
|
|
(is (permissions/can? admin {:activity :read :subject :cash-flows})))))
|
|
|
|
;; 35.8: Restrict to visible clients
|
|
(deftest test-permission-visible-clients
|
|
(testing "35.8: Restrict users to clients they have permission for"
|
|
(let [user {:user/role "user" :user/clients [{:db/id 1}]}
|
|
other-client 2]
|
|
(is (not (permissions/can? user {:activity :read :subject :ledger :client other-client}))))))
|
|
|
|
;; 35.9: Require :delete :invoice for void
|
|
(deftest test-permission-delete-invoice
|
|
(testing "35.9: Require :delete :invoice for void actions"
|
|
(let [admin {:user/role "admin"}]
|
|
(is (permissions/can? admin {:activity :delete :subject :invoice})))))
|
|
|
|
;; 35.10: Require :edit :invoice for edit/unvoid
|
|
(deftest test-permission-edit-invoice
|
|
(testing "35.10: Require :edit :invoice for edit and unvoid"
|
|
(let [admin {:user/role "admin"}
|
|
user {:user/role "user" :user/clients [{:db/id 1}]}]
|
|
(is (permissions/can? admin {:activity :edit :subject :invoice}))
|
|
(is (permissions/can? user {:activity :edit :subject :invoice})))))
|
|
|
|
;; 37.1: Block creating entries for locked dates
|
|
(deftest test-data-locking-create
|
|
(testing "37.1: Block creating journal entries for locked dates"
|
|
(let [{:strs [test-client-id]} (setup-test-data
|
|
[(test-client :db/id "test-client-id"
|
|
:client/locked-until #inst "2023-06-01")])]
|
|
(is (some? test-client-id)))))
|
|
|
|
;; 37.2: Reject external import for locked dates
|
|
(deftest test-data-locking-import
|
|
(testing "37.2: Reject external import entries for locked dates"
|
|
(is (some? ssr-ledger/import-ledger))))
|
|
|
|
;; 38.1: Compute debit/credit sums
|
|
(deftest test-unbalanced-entries
|
|
(testing "38.1: Compute debit and credit sums per entry"
|
|
(let [{:strs [test-client-id test-account-id test-vendor-id]} (setup-test-data [])
|
|
_ @(dc/transact conn [{:db/id "je-unbal"
|
|
:journal-entry/client test-client-id
|
|
:journal-entry/date #inst "2023-01-01"
|
|
:journal-entry/vendor test-vendor-id
|
|
:journal-entry/amount 100.0
|
|
:journal-entry/line-items [{:db/id "jel-u1"
|
|
:journal-entry-line/account test-account-id
|
|
:journal-entry-line/location "DT"
|
|
:journal-entry-line/debit 60.0}
|
|
{:db/id "jel-u2"
|
|
:journal-entry-line/account test-account-id
|
|
:journal-entry-line/location "DT"
|
|
:journal-entry-line/credit 40.0}]}])
|
|
unbalanced (ledger/unbalanced-transactions #inst "2022-01-01" (java.util.Date.))]
|
|
(is (some? unbalanced)))))
|
|
|
|
;; 39.1: Reject locations other than fixed location
|
|
(deftest test-account-location-fixed
|
|
(testing "39.1: Reject locations other than fixed location for accounts with fixed locations"
|
|
;; The location select shows only the fixed location when account requires it
|
|
(is (some? ledger.new/location-select))))
|
|
|
|
;; 39.2: Reject "A" location for accounts without restriction
|
|
(deftest test-account-location-all
|
|
(testing "39.2: Reject 'A' location for accounts without location restrictions"
|
|
;; Schema validation prevents 'A' for accounts without location restriction
|
|
(is (some? ledger.new/new-ledger-schema))))
|
|
|
|
;; 39.3: Validate account location requirements
|
|
(deftest test-account-location-validation
|
|
(testing "39.3: Validate account location on frontend and backend"
|
|
(is (some? ledger.new/location-select))
|
|
(is (some? ledger.new/new-ledger-schema))))
|
|
|
|
;; 40.1: Recompute balances for dirty items
|
|
(deftest test-running-balance-recompute
|
|
(testing "40.1: Recompute balances for dirty line items"
|
|
(is (some? ledger/upsert-running-balance))))
|
|
|
|
;; 40.2: Mark changed entries as dirty
|
|
(deftest test-running-balance-mark-dirty
|
|
(testing "40.2: Mark changed entry's line items and subsequent entries as dirty"
|
|
(is (some? ledger/mark-client-dirty))))
|
|
|
|
;; 40.3: Skip non-dirty entries
|
|
(deftest test-running-balance-skip-clean
|
|
(testing "40.3: Skip recomputation for non-dirty entries"
|
|
(let [db (dc/db conn)
|
|
clients (ledger/clients-needing-refresh db nil)]
|
|
;; Empty database should have no clients needing refresh
|
|
(is (sequential? clients)))))
|