- 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
199 lines
11 KiB
Clojure
199 lines
11 KiB
Clojure
(ns auto-ap.company.expense-reports-test
|
|
(:require
|
|
[auto-ap.datomic :refer [conn]]
|
|
[auto-ap.integration.util :refer [admin-token setup-test-data test-account test-client test-invoice test-vendor user-token wrap-setup]]
|
|
[auto-ap.ssr.company.reports.expense :as expense-reports]
|
|
[clj-time.core :as time]
|
|
[clojure.string :as str]
|
|
[clojure.test :refer [deftest is testing use-fixtures]]
|
|
[datomic.api :as dc]))
|
|
|
|
(use-fixtures :each wrap-setup)
|
|
|
|
;; ============================================================================
|
|
;; Expense Reports - Chart Behaviors
|
|
;; ============================================================================
|
|
|
|
(deftest test-vendor-typeahead-filter
|
|
(testing "Behavior 6.3: It should provide a vendor typeahead to filter expenses to a specific vendor"
|
|
(let [{:strs [test-client-id]} (setup-test-data
|
|
[(test-client :db/id "test-client-id"
|
|
:client/code "TEST01")])]
|
|
(let [response (expense-reports/expense-breakdown-card
|
|
{:identity (user-token test-client-id)
|
|
:clients [{:db/id test-client-id}]
|
|
:client {:db/id test-client-id}
|
|
:query-params {}})]
|
|
(is (= 200 (:status response)))
|
|
;; Response should contain vendor typeahead with vendor search URL
|
|
(is (re-find #"/vendor/search" (:body response)))))))
|
|
|
|
(deftest test-expense-account-typeahead-filter
|
|
(testing "Behavior 6.4: It should provide an expense account typeahead to filter to a specific account"
|
|
(let [{:strs [test-client-id]} (setup-test-data
|
|
[(test-client :db/id "test-client-id"
|
|
:client/code "TEST01")])]
|
|
(let [response (expense-reports/expense-breakdown-card
|
|
{:identity (user-token test-client-id)
|
|
:clients [{:db/id test-client-id}]
|
|
:client {:db/id test-client-id}
|
|
:query-params {}})]
|
|
(is (= 200 (:status response)))
|
|
;; Response should contain account typeahead with account search URL
|
|
(is (re-find #"/account/search" (:body response)))))))
|
|
|
|
(deftest test-refresh-chart-on-filter-change
|
|
(testing "Behavior 6.5: It should refresh the chart when filters change"
|
|
(let [{:strs [test-client-id]} (setup-test-data
|
|
[(test-client :db/id "test-client-id"
|
|
:client/code "TEST01")])]
|
|
(let [response (expense-reports/expense-breakdown-card
|
|
{:identity (user-token test-client-id)
|
|
:clients [{:db/id test-client-id}]
|
|
:client {:db/id test-client-id}
|
|
:query-params {}})]
|
|
(is (= 200 (:status response)))
|
|
;; The form should have hx-get pointing to the breakdown card endpoint
|
|
(is (re-find #"/company/reports/expense/card" (:body response)))
|
|
;; The form should trigger on change
|
|
(is (re-find #"change" (:body response)))
|
|
;; The form should target the chart container
|
|
(is (re-find #"expense-breakdown-report" (:body response)))))))
|
|
|
|
(deftest test-default-65-days-last-8-weeks
|
|
(testing "Behavior 6.6: It should default to last 65 days of data but display last 8 weeks"
|
|
(let [{:strs [test-client-id test-vendor-id test-account-id]} (setup-test-data
|
|
[(test-client :db/id "test-client-id"
|
|
:client/code "TEST01")])
|
|
;; Create invoices across the last 65 days
|
|
now (time/now)
|
|
days-ago-10 (time/minus now (time/days 10))
|
|
days-ago-50 (time/minus now (time/days 50))
|
|
days-ago-70 (time/minus now (time/days 70))]
|
|
@(dc/transact conn
|
|
[{:db/id "invoice-1"
|
|
:invoice/client test-client-id
|
|
:invoice/vendor test-vendor-id
|
|
:invoice/date (clj-time.coerce/to-date days-ago-10)
|
|
:invoice/status :invoice-status/unpaid
|
|
:invoice/import-status :import-status/imported
|
|
:invoice/total 100.0
|
|
:invoice/outstanding-balance 100.0
|
|
:invoice/invoice-number "INV-001"
|
|
:invoice/expense-accounts [{:invoice-expense-account/account test-account-id
|
|
:invoice-expense-account/amount 100.0
|
|
:invoice-expense-account/location "DT"}]}
|
|
{:db/id "invoice-2"
|
|
:invoice/client test-client-id
|
|
:invoice/vendor test-vendor-id
|
|
:invoice/date (clj-time.coerce/to-date days-ago-50)
|
|
:invoice/status :invoice-status/unpaid
|
|
:invoice/import-status :import-status/imported
|
|
:invoice/total 200.0
|
|
:invoice/outstanding-balance 200.0
|
|
:invoice/invoice-number "INV-002"
|
|
:invoice/expense-accounts [{:invoice-expense-account/account test-account-id
|
|
:invoice-expense-account/amount 200.0
|
|
:invoice-expense-account/location "DT"}]}
|
|
{:db/id "invoice-3"
|
|
:invoice/client test-client-id
|
|
:invoice/vendor test-vendor-id
|
|
:invoice/date (clj-time.coerce/to-date days-ago-70)
|
|
:invoice/status :invoice-status/unpaid
|
|
:invoice/import-status :import-status/imported
|
|
:invoice/total 300.0
|
|
:invoice/outstanding-balance 300.0
|
|
:invoice/invoice-number "INV-003"
|
|
:invoice/expense-accounts [{:invoice-expense-account/account test-account-id
|
|
:invoice-expense-account/amount 300.0
|
|
:invoice-expense-account/location "DT"}]}])
|
|
|
|
;; The lookup function should include invoices from last 65 days (invoice-1 and invoice-2)
|
|
;; but not invoice-3 (70 days ago)
|
|
(let [data (expense-reports/lookup-breakdown-data
|
|
{:clients [{:db/id test-client-id}]
|
|
:client {:db/id test-client-id}
|
|
:query-params {}})]
|
|
;; Should include 2 invoices (10 days and 50 days ago)
|
|
;; Note: invoice-3 at 70 days should be excluded by default 65-day window
|
|
(is (>= 2 (count data))))
|
|
|
|
;; The card should mention "last 8 weeks"
|
|
(let [response (expense-reports/expense-breakdown-card
|
|
{:identity (user-token test-client-id)
|
|
:clients [{:db/id test-client-id}]
|
|
:client {:db/id test-client-id}
|
|
:query-params {}})]
|
|
(is (re-find #"last 8 weeks" (:body response)))))))
|
|
|
|
;; ============================================================================
|
|
;; Invoice Totals Behaviors
|
|
;; ============================================================================
|
|
|
|
(deftest test-default-date-range-last-30-days
|
|
(testing "Behavior 7.3: It should default the date range to the last 30 days"
|
|
(let [{:strs [test-client-id test-vendor-id test-account-id]} (setup-test-data
|
|
[(test-client :db/id "test-client-id"
|
|
:client/code "TEST01")])
|
|
now (time/now)
|
|
days-ago-10 (time/minus now (time/days 10))
|
|
days-ago-40 (time/minus now (time/days 40))]
|
|
@(dc/transact conn
|
|
[{:db/id "invoice-1"
|
|
:invoice/client test-client-id
|
|
:invoice/vendor test-vendor-id
|
|
:invoice/date (clj-time.coerce/to-date days-ago-10)
|
|
:invoice/status :invoice-status/unpaid
|
|
:invoice/import-status :import-status/imported
|
|
:invoice/total 100.0
|
|
:invoice/outstanding-balance 100.0
|
|
:invoice/invoice-number "INV-001"
|
|
:invoice/expense-accounts [{:invoice-expense-account/account test-account-id
|
|
:invoice-expense-account/amount 100.0
|
|
:invoice-expense-account/location "DT"}]}
|
|
{:db/id "invoice-2"
|
|
:invoice/client test-client-id
|
|
:invoice/vendor test-vendor-id
|
|
:invoice/date (clj-time.coerce/to-date days-ago-40)
|
|
:invoice/status :invoice-status/unpaid
|
|
:invoice/import-status :import-status/imported
|
|
:invoice/total 200.0
|
|
:invoice/outstanding-balance 200.0
|
|
:invoice/invoice-number "INV-002"
|
|
:invoice/expense-accounts [{:invoice-expense-account/account test-account-id
|
|
:invoice-expense-account/amount 200.0
|
|
:invoice-expense-account/location "DT"}]}])
|
|
|
|
;; Default lookup should only include invoice from 10 days ago
|
|
(let [data (expense-reports/lookup-invoice-total-data
|
|
{:clients [{:db/id test-client-id}]
|
|
:client {:db/id test-client-id}
|
|
:query-params {}})]
|
|
;; Should include only invoice-1 (10 days ago, within 30 days)
|
|
(is (>= 1 (count data)))))))
|
|
|
|
(deftest test-push-filter-changes-to-history
|
|
(testing "Behavior 7.6: It should push filter changes to browser history"
|
|
(let [{:strs [test-client-id]} (setup-test-data
|
|
[(test-client :db/id "test-client-id"
|
|
:client/code "TEST01")])]
|
|
;; Test expense breakdown card pushes URL
|
|
(let [response (expense-reports/expense-breakdown-card
|
|
{:identity (user-token test-client-id)
|
|
:clients [{:db/id test-client-id}]
|
|
:client {:db/id test-client-id}
|
|
:query-params {}})]
|
|
(is (= 200 (:status response)))
|
|
;; Should have hx-push-url header
|
|
(is (some? (get-in response [:headers "hx-push-url"]))))
|
|
|
|
;; Test invoice total card pushes URL
|
|
(let [response (expense-reports/invoice-total-card
|
|
{:identity (user-token test-client-id)
|
|
:clients [{:db/id test-client-id}]
|
|
:client {:db/id test-client-id}
|
|
:query-params {}})]
|
|
(is (= 200 (:status response)))
|
|
;; Should have hx-push-url header
|
|
(is (some? (get-in response [:headers "hx-push-url"])))))))
|