(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 "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)]) 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") :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)))