From 103194e50ca71513705868f1401c1339baf881c9 Mon Sep 17 00:00:00 2001 From: Tarun Date: Fri, 12 Jan 2024 20:42:34 +0530 Subject: [PATCH 1/2] Add nil check on expiration time while reserving tickets --- .../src/swift_ticketing/db/ticket.clj | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/swift-ticketing/src/swift_ticketing/db/ticket.clj b/swift-ticketing/src/swift_ticketing/db/ticket.clj index d2cbecb..4cb93fa 100644 --- a/swift-ticketing/src/swift_ticketing/db/ticket.clj +++ b/swift-ticketing/src/swift_ticketing/db/ticket.clj @@ -101,13 +101,17 @@ (select-reserved-tickets db-spec true booking-id)) (defn reserve-tickets [db-spec ticket-ids booking-id reservation-expiration-time] - (run-query! - db-spec - (sql/format {:update :ticket - :set {:booking_id [:cast booking-id :uuid] - :ticket_status [:cast reserved :ticket_status] - :reservation_expiration_time [:cast (.toString reservation-expiration-time) :timestamptz]} - :where [:in :ticket_id ticket-ids]}))) + (let [expiration-time + (if (nil? reservation-expiration-time) + nil + [:cast (.toString reservation-expiration-time) :timestamptz])] + (run-query! + db-spec + (sql/format {:update :ticket + :set {:booking_id [:cast booking-id :uuid] + :ticket_status [:cast reserved :ticket_status] + :reservation_expiration_time expiration-time} + :where [:in :ticket_id ticket-ids]})))) (defn reset-ticket-status [db-spec ticket-ids status] (run-query! From c00cf918ebc90f20918e9513a7b5dd0ccd7b9734 Mon Sep 17 00:00:00 2001 From: Tarun Date: Fri, 12 Jan 2024 20:43:15 +0530 Subject: [PATCH 2/2] Add tests for booking flow --- .../src/swift_ticketing/db/ticket.clj | 10 +- .../swift_ticketing/booking_flow_test.clj | 106 ++++++++++++++++++ .../test/swift_ticketing/client.clj | 8 +- 3 files changed, 116 insertions(+), 8 deletions(-) create mode 100644 swift-ticketing/test/swift_ticketing/booking_flow_test.clj diff --git a/swift-ticketing/src/swift_ticketing/db/ticket.clj b/swift-ticketing/src/swift_ticketing/db/ticket.clj index 4cb93fa..6dfc5f0 100644 --- a/swift-ticketing/src/swift_ticketing/db/ticket.clj +++ b/swift-ticketing/src/swift_ticketing/db/ticket.clj @@ -34,11 +34,11 @@ [:cast seat-type :seat_type]]]})))) (defn get-ticket-type [db-spec ticket-type-id] - (run-query-one! - db-spec - (sql/format {:select [:*] - :from :ticket_type - :where [:= :ticket_type_id [:cast ticket-type-id :uuid]]}))) + (run-query-one! + db-spec + (sql/format {:select [:*] + :from :ticket_type + :where [:= :ticket_type_id [:cast ticket-type-id :uuid]]}))) (defn insert-tickets [db-spec ticket-type-id tickets price] (run-query! diff --git a/swift-ticketing/test/swift_ticketing/booking_flow_test.clj b/swift-ticketing/test/swift_ticketing/booking_flow_test.clj new file mode 100644 index 0000000..be96bb4 --- /dev/null +++ b/swift-ticketing/test/swift_ticketing/booking_flow_test.clj @@ -0,0 +1,106 @@ +(ns swift-ticketing.booking-flow-test + (:require [clojure.test :refer [deftest testing is use-fixtures]] + [swift-ticketing.fixtures :as fixtures] + [swift-ticketing.factory :as factory] + [swift-ticketing.client :as client] + [swift-ticketing.db.booking :as db-booking] + [camel-snake-kebab.extras :as cske] + [camel-snake-kebab.core :as csk])) + +(use-fixtures :each fixtures/clear-tables) + +(deftest general-ticket-booking-flow-test + (testing "Ticket booking (General)" + ;; setup event and tickets + (let [{:keys [db-spec]} fixtures/test-env + event-id (->> (client/create-event) + :response + (cske/transform-keys csk/->kebab-case-keyword) + :event-id) + {:keys [ticket-type-id + tickets]} (->> (client/create-general-tickets event-id) + :response + (cske/transform-keys csk/->kebab-case-keyword)) + total-tickets (count tickets) + reserve-tickets (fn [quantity] + (->> (factory/mk-reserve-general-ticket-request + quantity + ticket-type-id) + (client/reserve-ticket event-id))) + get-booking-id #(get % "booking_id")] + + (testing "Reserving more tickets than available" + ;; Reserving more tickets than available should return REJECTED + (let [{:keys [status response]} (reserve-tickets (inc total-tickets)) + booking-id (get-booking-id response)] + (is (= 201 status)) + (Thread/sleep 2000) + (is (= db-booking/rejected + (db-booking/get-booking-status db-spec booking-id))))) + + (testing "Reserving available tickets" + ;; Reserve available tickets -> PaymentPending + (let [{:keys [status response]} (reserve-tickets total-tickets) + booking-id (get-booking-id response)] + (is (= 201 status)) + (Thread/sleep 2000) + (is (= db-booking/payment-pending + (db-booking/get-booking-status db-spec booking-id))) + + (testing "Cancelling reserved ticket" + (client/cancel-booking booking-id) + (Thread/sleep 2000) + (is (= db-booking/canceled + (db-booking/get-booking-status db-spec booking-id)))))) + + (testing "Making Payment" + (let [booking-id (-> (reserve-tickets total-tickets) + :response + (get "booking_id"))] + (Thread/sleep 2000) + (client/make-payment booking-id) + (Thread/sleep 2000) + (is (= db-booking/confirmed + (db-booking/get-booking-status db-spec booking-id)))))))) + +(deftest seated-ticket-booking-flow-test + (testing "Ticket booking (Seated)" + (let [{:keys [db-spec]} fixtures/test-env + event-id (->> (client/create-event) + :response + (cske/transform-keys csk/->kebab-case-keyword) + :event-id) + tickets (->> (client/create-seated-tickets event-id) + :response + (cske/transform-keys csk/->kebab-case-keyword) + :tickets) + ticket-ids (map :ticket-id tickets) + reserve-tickets (fn [tids] + (->> (factory/mk-reserve-seated-ticket-request + tids) + (client/reserve-ticket event-id))) + get-booking-id #(get % "booking_id")] + + (testing "Reserving available tickets" + (let [{:keys [status response]} (reserve-tickets ticket-ids) + booking-id (get-booking-id response)] + (is (= 201 status)) + (Thread/sleep 2000) + (is (= db-booking/payment-pending + (db-booking/get-booking-status db-spec booking-id))) + + (testing "Cancelling reserved ticket" + (client/cancel-booking booking-id) + (Thread/sleep 2000) + (is (= db-booking/canceled + (db-booking/get-booking-status db-spec booking-id)))))) + + (testing "Making Payment" + (let [booking-id (-> (reserve-tickets ticket-ids) + :response + (get "booking_id"))] + (Thread/sleep 2000) + (client/make-payment booking-id) + (Thread/sleep 2000) + (is (= db-booking/confirmed + (db-booking/get-booking-status db-spec booking-id)))))))) diff --git a/swift-ticketing/test/swift_ticketing/client.clj b/swift-ticketing/test/swift_ticketing/client.clj index 00af9cc..2da7aaa 100644 --- a/swift-ticketing/test/swift_ticketing/client.clj +++ b/swift-ticketing/test/swift_ticketing/client.clj @@ -44,9 +44,11 @@ :status (:status response) :response (response-to-json response)}))) -(defn reserve-general-ticket - [request] - (let [response (post-request "/event" request)] +(defn reserve-ticket + [event-id request] + (let [response (post-request + (str "/event/" event-id "/booking") + request)] {:request request :status (:status response) :response (response-to-json response)}))