- Add new memo filter to transaction page (searches :transaction/memo) - Enhance existing description filter to use case-insensitive regex - Both filters support wildcard matching via .* pattern - Add e2e tests for filter functionality - Update test data with memo fields
245 lines
13 KiB
Clojure
245 lines
13 KiB
Clojure
(ns auto-ap.test-server
|
|
"Test server for browser automation tests (Playwright, etc.)"
|
|
(:require
|
|
[auto-ap.datomic :refer [conn transact-schema install-functions]]
|
|
[auto-ap.handler :as handler]
|
|
[auto-ap.integration.util :refer [setup-test-data test-client test-bank-account test-transaction test-payment test-invoice]]
|
|
[auto-ap.routes.transactions :as route]
|
|
[auto-ap.ssr.transaction.edit :as edit]
|
|
[auto-ap.ssr.components.multi-modal :as mm]
|
|
[auto-ap.ssr.utils :refer [wrap-entity wrap-schema-enforce]]
|
|
[auto-ap.permissions :refer [wrap-must]]
|
|
[auto-ap.datomic.transactions :as d-transactions]
|
|
[auto-ap.datomic.accounts :as d-accounts]
|
|
[auto-ap.session-version :as session-version]
|
|
[datomic.api :as dc]
|
|
[ring.adapter.jetty :refer [run-jetty]]
|
|
[ring.middleware.edn :refer [wrap-edn-params]]
|
|
[ring.middleware.multipart-params :as mp]
|
|
[ring.middleware.params :refer [wrap-params]]
|
|
[ring.middleware.session :refer [wrap-session]]
|
|
[ring.middleware.session.cookie :refer [cookie-store]]
|
|
[mount.core :as mount]
|
|
[clj-time.core :as time]
|
|
[buddy.sign.jwt :as jwt]
|
|
[cheshire.core]
|
|
[config.core :refer [env]]))
|
|
|
|
(def test-identity-mode (atom :single-client))
|
|
(def test-transaction-id (atom nil))
|
|
(def test-account-ids (atom {}))
|
|
(def test-client-ids (atom {}))
|
|
|
|
(defn admin-identity []
|
|
(case @test-identity-mode
|
|
:multi-client
|
|
{:user "TEST ADMIN"
|
|
:user/role "admin"
|
|
:user/name "TEST ADMIN"
|
|
:exp (time/plus (time/now) (time/days 1))
|
|
:user/clients [{:db/id (:test @test-client-ids) :client/code "TEST" :client/locations ["DT"]}
|
|
{:db/id (:test2 @test-client-ids) :client/code "TEST2" :client/locations ["NY"]}]}
|
|
;; default single-client
|
|
{:user "TEST ADMIN"
|
|
:user/role "admin"
|
|
:user/name "TEST ADMIN"
|
|
:exp (time/plus (time/now) (time/days 1))
|
|
:user/clients [{:db/id (:test @test-client-ids) :client/code "TEST" :client/locations ["DT"]}]}))
|
|
|
|
(defn wrap-test-auth [handler]
|
|
(fn [request]
|
|
(handler (assoc request :identity (admin-identity)))))
|
|
|
|
(defn create-test-db []
|
|
(let [uri "datomic:mem://playwright-test"]
|
|
(dc/delete-database uri)
|
|
(dc/create-database uri)
|
|
(let [test-conn (dc/connect uri)]
|
|
;; Must replace conn before install-functions since it uses the global var
|
|
(alter-var-root #'auto-ap.datomic/conn (constantly test-conn))
|
|
(alter-var-root #'auto-ap.datomic/uri (constantly uri))
|
|
(transact-schema test-conn)
|
|
(install-functions)
|
|
test-conn)))
|
|
|
|
(defn seed-test-data [conn]
|
|
(let [tx-result @(dc/transact conn
|
|
[(assoc (test-client :db/id "client-id"
|
|
:client/code "TEST"
|
|
:client/locations ["DT"])
|
|
:client/bank-accounts [(test-bank-account :db/id "bank-account-id")])
|
|
(test-client :db/id "client-id-2"
|
|
:client/code "TEST2"
|
|
:client/locations ["NY"])
|
|
{:db/id "account-id"
|
|
:account/name "Test Account"
|
|
:account/type :account-type/expense
|
|
:account/numeric-code 50000
|
|
:account/applicability :account-applicability/global
|
|
:account/default-allowance {:db/ident :allowance/allowed}}
|
|
{:db/id "account-id-2"
|
|
:account/name "Second Account"
|
|
:account/type :account-type/expense
|
|
:account/numeric-code 50001
|
|
:account/applicability :account-applicability/global
|
|
:account/default-allowance {:db/ident :allowance/allowed}}
|
|
{:db/id "account-id-fixed-loc"
|
|
:account/name "Fixed Location Account"
|
|
:account/type :account-type/expense
|
|
:account/numeric-code 50002
|
|
:account/applicability :account-applicability/global
|
|
:account/location "DT"
|
|
:account/default-allowance {:db/ident :allowance/allowed}}
|
|
{:db/id "ap-account-id"
|
|
:account/name "Accounts Payable"
|
|
:db/ident :account/accounts-payable
|
|
:account/numeric-code 21000
|
|
:account/account-set "default"
|
|
:account/applicability :account-applicability/global
|
|
:account/default-allowance {:db/ident :allowance/allowed}}
|
|
{:db/id "vendor-id"
|
|
:vendor/name "Test Vendor"
|
|
:vendor/default-account "account-id"}
|
|
(test-transaction :db/id "transaction-id"
|
|
:transaction/client "client-id"
|
|
:transaction/bank-account "bank-account-id"
|
|
:transaction/amount 100.0
|
|
:transaction/description-original "Test transaction"
|
|
:transaction/memo "Monthly rent payment"
|
|
:transaction/approval-status :transaction-approval-status/unapproved)
|
|
(test-transaction :db/id "transaction-id-2"
|
|
:transaction/client "client-id"
|
|
:transaction/bank-account "bank-account-id"
|
|
:transaction/amount 200.0
|
|
:transaction/description-original "Second transaction"
|
|
:transaction/memo "Grocery shopping"
|
|
:transaction/approval-status :transaction-approval-status/unapproved)
|
|
(test-transaction :db/id "transaction-id-3"
|
|
:transaction/client "client-id"
|
|
:transaction/bank-account "bank-account-id"
|
|
:transaction/amount 300.0
|
|
:transaction/description-original "Third transaction"
|
|
:transaction/approval-status :transaction-approval-status/unapproved)
|
|
;; Transaction and payment for link testing
|
|
(test-transaction :db/id "transaction-id-payment"
|
|
:transaction/client "client-id"
|
|
:transaction/bank-account "bank-account-id"
|
|
:transaction/amount -100.0
|
|
:transaction/description-original "Transaction for payment link"
|
|
:transaction/approval-status :transaction-approval-status/unapproved)
|
|
(test-payment :db/id "payment-id"
|
|
:payment/client "client-id"
|
|
:payment/vendor "vendor-id"
|
|
:payment/bank-account "bank-account-id"
|
|
:payment/amount 100.0
|
|
:payment/status :payment-status/pending
|
|
:payment/date #inst "2023-06-15")
|
|
;; Transaction and unpaid invoice for link testing
|
|
(test-transaction :db/id "transaction-id-unpaid"
|
|
:transaction/client "client-id"
|
|
:transaction/bank-account "bank-account-id"
|
|
:transaction/amount -150.0
|
|
:transaction/description-original "Transaction for unpaid invoice link"
|
|
:transaction/approval-status :transaction-approval-status/unapproved)
|
|
(test-invoice :db/id "invoice-unpaid-id"
|
|
:invoice/client "client-id"
|
|
:invoice/vendor "vendor-id"
|
|
:invoice/total 150.0
|
|
:invoice/outstanding-balance 150.0
|
|
:invoice/status :invoice-status/unpaid
|
|
:invoice/date #inst "2023-07-20"
|
|
:invoice/invoice-number "UNPAID-001"
|
|
:invoice/expense-accounts [{:invoice-expense-account/account "account-id"
|
|
:invoice-expense-account/amount 150.0
|
|
:invoice-expense-account/location "DT"}])])
|
|
tempids (:tempids tx-result)
|
|
tx-entity-id (get tempids "transaction-id")]
|
|
(println "Test transaction entity ID:" tx-entity-id)
|
|
(reset! test-account-ids
|
|
{:test-account (get tempids "account-id")
|
|
:second-account (get tempids "account-id-2")
|
|
:fixed-location-account (get tempids "account-id-fixed-loc")
|
|
:ap-account (get tempids "ap-account-id")
|
|
:vendor (get tempids "vendor-id")})
|
|
(reset! test-client-ids
|
|
{:test (get tempids "client-id")
|
|
:test2 (get tempids "client-id-2")})
|
|
tx-entity-id))
|
|
|
|
(defn test-info-handler [request]
|
|
{:status 200
|
|
:headers {"Content-Type" "application/json"}
|
|
:body (cheshire.core/generate-string
|
|
{:transactionId @test-transaction-id
|
|
:accounts @test-account-ids
|
|
:clientMode @test-identity-mode
|
|
:clients (mapv :client/code (:clients request))})})
|
|
|
|
(defn test-set-client-mode-handler [request]
|
|
(let [query-string (get request :query-string "")
|
|
params (when (seq query-string)
|
|
(into {} (for [param (clojure.string/split query-string #"&")]
|
|
(let [[k v] (clojure.string/split param #"=")]
|
|
[(keyword k) (java.net.URLDecoder/decode v "UTF-8")]))))
|
|
mode (keyword (:mode params))]
|
|
(reset! test-identity-mode mode)
|
|
{:status 200
|
|
:headers {"Content-Type" "application/json"}
|
|
:body (cheshire.core/generate-string
|
|
{:mode mode})}))
|
|
|
|
(defn wrap-test-info [handler]
|
|
(fn [request]
|
|
(cond
|
|
(= "/test-info" (:uri request))
|
|
(test-info-handler request)
|
|
(= "/test-set-client-mode" (:uri request))
|
|
(test-set-client-mode-handler request)
|
|
:else
|
|
(handler request))))
|
|
|
|
(defn test-app []
|
|
;; Build app without auth middleware, inject test identity after all middleware
|
|
(-> handler/route-handler
|
|
(handler/wrap-hx-current-url-params)
|
|
(handler/wrap-guess-route)
|
|
(handler/wrap-logging)
|
|
(handler/wrap-trim-clients)
|
|
(handler/wrap-hydrate-clients)
|
|
(handler/wrap-store-client-in-session)
|
|
(handler/wrap-gunzip-jwt)
|
|
;; Skip wrap-authorization and wrap-authentication
|
|
(session-version/wrap-session-version)
|
|
(handler/wrap-idle-session-timeout)
|
|
(wrap-session {:store (cookie-store
|
|
{:key
|
|
(byte-array
|
|
[42, 52, -31, 101, -126, -33, -118, -69, -82, -59, -15, -69, -38, 103, -102, -1])})})
|
|
(wrap-params)
|
|
(mp/wrap-multipart-params)
|
|
(wrap-edn-params)
|
|
(handler/wrap-error)
|
|
wrap-test-auth
|
|
wrap-test-info))
|
|
|
|
(defn start-test-server []
|
|
(let [test-conn (create-test-db)
|
|
tx-id (seed-test-data test-conn)]
|
|
(reset! test-transaction-id tx-id)
|
|
(let [server (run-jetty (test-app) {:port 3333 :join? false})]
|
|
(println "Test server started on http://localhost:3333")
|
|
(println "Transaction entity ID:" tx-id)
|
|
server)))
|
|
|
|
(defn stop-test-server [server]
|
|
(.stop server)
|
|
(dc/delete-database "datomic:mem://playwright-test")
|
|
(println "Test server stopped"))
|
|
|
|
(defn -main [& _]
|
|
(let [server (start-test-server)]
|
|
(.addShutdownHook (Runtime/getRuntime)
|
|
(Thread. #(stop-test-server server)))
|
|
;; Keep running
|
|
@(promise)))
|