@@ -1,260 +0,0 @@
1−module CallbackTest.Spec where
2−
3−import Prelude
4−
5−import Data.Maybe (Maybe(..))
6−import Data.String as String
7−import Effect (Effect)
8−import Type.Proxy (Proxy(..))
9−import Yoga.HTTP.API.Path (Path, Lit)
10−import Yoga.HTTP.API.Route (GET, POST, Route, Request, buildOpenAPISpec, toOpenAPI)
11−import Yoga.HTTP.API.Route.Encoding (JSON)
12−import Yoga.HTTP.API.Route.OpenAPIMetadata (Callback, type (#))
13−import Yoga.JSON (writeJSON)
14−import ViTest (ViTest, describe, test)
15−import ViTest.Expect (expectToBe)
16−
17−--------------------------------------------------------------------------------
18−-- Type Definitions for Callback Tests
19−--------------------------------------------------------------------------------
20−
21−-- Payment processing with callback for completion notification
22−type PaymentRequest = { amount :: Int, currency :: String, callbackUrl :: String }
23−type PaymentResponse = { transactionId :: String, status :: String }
24−type PaymentCallbackRequest = { status :: String, transactionId :: String }
25−type PaymentCallbackResponse = { received :: Boolean }
26−
27−type PaymentRoute =
28− Route POST (Path (Lit "payment"))
29− (Request { body :: JSON PaymentRequest })
30− ( ok :: { body :: PaymentResponse }
31− ) # Callback "onPaymentComplete" "{$request.body#/callbackUrl}" POST
32− (JSON PaymentCallbackRequest)
33− (ok :: { body :: PaymentCallbackResponse })
34−
35−-- Webhook subscription with multiple callbacks
36−type WebhookSubscription = { url :: String, events :: Array String }
37−type WebhookEvent = { event :: String, data :: String, timestamp :: String }
38−type WebhookAck = { acknowledged :: Boolean }
39−
40−type WebhookRoute =
41− Route POST (Path (Lit "webhooks"))
42− (Request { body :: JSON WebhookSubscription })
43− ( created :: { body :: { id :: String } }
44− )
45− # Callback "onUserCreated" "{$request.body#/url}" POST
46− (JSON WebhookEvent)
47− ( ok :: { body :: WebhookAck }
48− , badRequest :: { body :: { error :: String } }
49− )
50− # Callback "onUserUpdated" "{$request.body#/url}" POST
51− (JSON WebhookEvent)
52− (ok :: { body :: WebhookAck })
53−
54−-- Async job processing with status callback
55−type JobRequest = { task :: String, statusUrl :: String }
56−type JobResponse = { jobId :: String }
57−type JobStatusUpdate = { jobId :: String, status :: String, progress :: Int }
58−type StatusAck = { received :: Boolean }
59−
60−type AsyncJobRoute =
61− Route POST (Path (Lit "jobs"))
62− (Request { body :: JSON JobRequest })
63− ( accepted :: { body :: JobResponse }
64− ) # Callback "onStatusUpdate" "{$request.body#/statusUrl}" POST
65− (JSON JobStatusUpdate)
66− (ok :: { body :: StatusAck })
67−
68−-- Notification service with GET callback
69−type NotificationRequest = { message :: String, confirmUrl :: String }
70−type NotificationResponse = { notificationId :: String }
71−
72−type NotificationRoute =
73− Route POST (Path (Lit "notifications"))
74− (Request { body :: JSON NotificationRequest })
75− ( created :: { body :: NotificationResponse }
76− ) # Callback "onDeliveryConfirm" "{$request.body#/confirmUrl}" GET
77− (JSON { delivered :: Boolean })
78− (ok :: { body :: { confirmed :: Boolean } })
79−
80−--------------------------------------------------------------------------------
81−-- Basic Callback Tests
82−--------------------------------------------------------------------------------
83−
84−testPaymentCallback :: Effect ViTest
85−testPaymentCallback = describe "OpenAPI Callbacks - Payment Processing" do
86− _ <- test "includes callbacks in operation" do
87− let
88− result = toOpenAPI @PaymentRoute
89− expectToBe true (String.contains (String.Pattern "callbacks") result)
90−
91− _ <- test "includes callback name onPaymentComplete" do
92− let
93− result = toOpenAPI @PaymentRoute
94− expectToBe true (String.contains (String.Pattern "onPaymentComplete") result)
95−
96− _ <- test "includes callback expression with runtime reference" do
97− let
98− result = toOpenAPI @PaymentRoute
99− expectToBe true (String.contains (String.Pattern "{$request.body#/callbackUrl}") result)
100−
101− _ <- test "includes callback method POST" do
102− let
103− result = toOpenAPI @PaymentRoute
104− expectToBe true (String.contains (String.Pattern "\"post\"") result)
105−
106− _ <- test "includes callback request body schema" do
107− let
108− result = toOpenAPI @PaymentRoute
109− expectToBe true (String.contains (String.Pattern "status") result)
110− expectToBe true (String.contains (String.Pattern "transactionId") result)
111−
112− test "includes callback response schema" do
113− let
114− result = toOpenAPI @PaymentRoute
115− expectToBe true (String.contains (String.Pattern "received") result)
116−
117−--------------------------------------------------------------------------------
118−-- Multiple Callbacks Tests
119−--------------------------------------------------------------------------------
120−
121−testMultipleCallbacks :: Effect ViTest
122−testMultipleCallbacks = describe "OpenAPI Callbacks - Multiple Webhooks" do
123− _ <- test "includes multiple callback definitions" do
124− let
125− result = toOpenAPI @WebhookRoute
126− expectToBe true (String.contains (String.Pattern "onUserCreated") result)
127− expectToBe true (String.contains (String.Pattern "onUserUpdated") result)
128−
129− _ <- test "each callback has its own expression" do
130− let
131− result = toOpenAPI @WebhookRoute
132− expectToBe true (String.contains (String.Pattern "{$request.body#/url}") result)
133−
134− test "callbacks with multiple response types" do
135− let
136− result = toOpenAPI @WebhookRoute
137− expectToBe true (String.contains (String.Pattern "\"200\"") result)
138− expectToBe true (String.contains (String.Pattern "\"400\"") result)
139−
140−--------------------------------------------------------------------------------
141−-- Different HTTP Methods Tests
142−--------------------------------------------------------------------------------
143−
144−testCallbackMethods :: Effect ViTest
145−testCallbackMethods = describe "OpenAPI Callbacks - HTTP Methods" do
146− _ <- test "supports POST callback method" do
147− let
148− result = toOpenAPI @AsyncJobRoute
149− expectToBe true (String.contains (String.Pattern "onStatusUpdate") result)
150− expectToBe true (String.contains (String.Pattern "\"post\"") result)
151−
152− test "supports GET callback method" do
153− let
154− result = toOpenAPI @NotificationRoute
155− expectToBe true (String.contains (String.Pattern "onDeliveryConfirm") result)
156− expectToBe true (String.contains (String.Pattern "\"get\"") result)
157−
158−--------------------------------------------------------------------------------
159−-- API Spec with Callbacks
160−--------------------------------------------------------------------------------
161−
162−type CallbackAPI =
163− { payment :: PaymentRoute
164− , webhook :: WebhookRoute
165− , job :: AsyncJobRoute
166− , notification :: NotificationRoute
167− }
168−
169−testAPISpecWithCallbacks :: Effect ViTest
170−testAPISpecWithCallbacks = describe "OpenAPI Spec - API with Callbacks" do
171− _ <- test "builds complete spec with callback operations" do
172− let
173− spec = buildOpenAPISpec @CallbackAPI
174− { title: "Callback Test API"
175− , version: "1.0.0"
176− , description: Nothing
177− , contact: Nothing
178− , license: Nothing
179− }
180− json = writeJSON spec
181− expectToBe true (String.contains (String.Pattern "callbacks") json)
182−
183− _ <- test "includes all callback operations in spec" do
184− let
185− spec = buildOpenAPISpec @CallbackAPI
186− { title: "Callback Test API"
187− , version: "1.0.0"
188− , description: Nothing
189− , contact: Nothing
190− , license: Nothing
191− }
192− json = writeJSON spec
193− expectToBe true (String.contains (String.Pattern "onPaymentComplete") json)
194− expectToBe true (String.contains (String.Pattern "onUserCreated") json)
195− expectToBe true (String.contains (String.Pattern "onStatusUpdate") json)
196− expectToBe true (String.contains (String.Pattern "onDeliveryConfirm") json)
197−
198− test "callback expressions use runtime references" do
199− let
200− spec = buildOpenAPISpec @CallbackAPI
201− { title: "Callback Test API"
202− , version: "1.0.0"
203− , description: Nothing
204− , contact: Nothing
205− , license: Nothing
206− }
207− json = writeJSON spec
208− expectToBe true (String.contains (String.Pattern "{$request.body#/callbackUrl}") json)
209− expectToBe true (String.contains (String.Pattern "{$request.body#/url}") json)
210− expectToBe true (String.contains (String.Pattern "{$request.body#/statusUrl}") json)
211− expectToBe true (String.contains (String.Pattern "{$request.body#/confirmUrl}") json)
212−
213−--------------------------------------------------------------------------------
214−-- Real-World Webhook Scenarios
215−--------------------------------------------------------------------------------
216−
217−-- GitHub-style webhook
218−type GitHubWebhookSetup = { url :: String, secret :: String }
219−type GitHubPushEvent = { ref :: String, commits :: Array { message :: String } }
220−
221−type GitHubWebhookRoute =
222− Route POST (Path (Lit "github" /\ Lit "webhooks"))
223− (Request { body :: JSON GitHubWebhookSetup })
224− ( created :: { body :: { id :: Int } }
225− ) # Callback "push" "{$request.body#/url}" POST
226− (JSON GitHubPushEvent)
227− (ok :: { body :: Unit })
228−
229−-- Stripe-style payment webhook
230−type StripeCheckout = { successUrl :: String, cancelUrl :: String }
231−type StripeEvent = { type :: String, data :: { amount :: Int } }
232−
233−type StripeWebhookRoute =
234− Route POST (Path (Lit "stripe" /\ Lit "checkout"))
235− (Request { body :: JSON StripeCheckout })
236− ( ok :: { body :: { sessionId :: String } }
237− )
238− # Callback "checkout.completed" "{$request.body#/successUrl}" POST
239− (JSON StripeEvent)
240− (ok :: { body :: Unit })
241− # Callback "checkout.canceled" "{$request.body#/cancelUrl}" POST
242− (JSON StripeEvent)
243− (ok :: { body :: Unit })
244−
245−testRealWorldWebhooks :: Effect ViTest
246−testRealWorldWebhooks = describe "OpenAPI Callbacks - Real-World Webhooks" do
247− _ <- test "GitHub-style webhook with push callback" do
248− let
249− result = toOpenAPI @GitHubWebhookRoute
250− expectToBe true (String.contains (String.Pattern "push") result)
251− expectToBe true (String.contains (String.Pattern "ref") result)
252− expectToBe true (String.contains (String.Pattern "commits") result)
253−
254− test "Stripe-style webhook with success and cancel callbacks" do
255− let
256− result = toOpenAPI @StripeWebhookRoute
257− expectToBe true (String.contains (String.Pattern "checkout.completed") result)
258− expectToBe true (String.contains (String.Pattern "checkout.canceled") result)
259− expectToBe true (String.contains (String.Pattern "{$request.body#/successUrl}") result)
260− expectToBe true (String.contains (String.Pattern "{$request.body#/cancelUrl}") result)