Files
integreat/test/clj/auto_ap/test_server.clj
Bryce 8bd0cee1b1 Add e2e tests for bulk coding transactions and fix SSR location validation
- Create requirements document based on master cljs implementation
- Add Playwright e2e tests covering happy path, validation, and distribution
- Fix hiccup id syntax in SSR bulk code form (div#id.class order)
- Add missing account location validation to SSR bulk code submit
- Enhance test server with multiple transactions and fixed-location account
2026-05-21 13:21:22 -07:00

175 lines
8.5 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]]
[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]]))
(defn admin-identity []
{:user "TEST ADMIN"
:user/role "admin"
:user/name "TEST ADMIN"
:exp (time/plus (time/now) (time/days 1))
:user/clients [{:db/id "client-id" :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)))
(def test-transaction-id (atom nil))
(def test-account-ids (atom {}))
(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")])
{: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/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/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)])
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")})
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})})
(defn wrap-test-info [handler]
(fn [request]
(if (= "/test-info" (:uri request))
(test-info-handler request)
(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)))