-
Notifications
You must be signed in to change notification settings - Fork 7
feat(purchase-order): cover purchase_order_number payloads #95
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,2 +1 @@ | ||
| export { assertEquals } from "https://deno.land/std@0.196.0/assert/mod.ts"; | ||
| export * as mf from "https://deno.land/x/mock_fetch@0.3.0/mod.ts"; | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -13,8 +13,11 @@ const subscriptionInput = { | |
| "external_id": "54321", | ||
| "billing_time": "calendar", | ||
| "subscription_at": "2022-08-08T00:00:00Z", | ||
| "purchase_order_number": "PO-123", | ||
| }, | ||
| } satisfies SubscriptionCreateInput; | ||
| } satisfies SubscriptionCreateInput & { | ||
| subscription: { purchase_order_number: string }; | ||
| }; | ||
|
Comment on lines
+18
to
+20
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why is the I regenerated the client from the current spec — const wt = {
wallet_transaction: { wallet_id: "1", paid_credits: "100", purchase_order_number: "PO-123" },
} satisfies WalletTransactionCreateInput; // ✅By widening the target type, the fixture keeps type-checking even if the generated client ever loses the field — which is exactly the regression these fixtures should catch. It also pins the field as required Suggest dropping every |
||
|
|
||
| const subscriptionResponse = { | ||
| "subscription": { | ||
|
|
@@ -34,8 +37,11 @@ const subscriptionResponse = { | |
| "previous_plan_code": "previous_code", | ||
| "next_plan_code": "next_code", | ||
| "downgrade_plan_date": "2022-09-14T16:35:31Z", | ||
| "purchase_order_number": "PO-123", | ||
| }, | ||
| } satisfies Subscription; | ||
| } satisfies Subscription & { | ||
| subscription: { purchase_order_number: string }; | ||
| }; | ||
|
|
||
| const subscriptionsResponse = { | ||
| subscriptions: [subscriptionResponse.subscription], | ||
|
|
@@ -50,6 +56,7 @@ Deno.test("Successfully sent subscription responds with 2xx", async (t) => { | |
| inputParams: [subscriptionInput], | ||
| responseObject: subscriptionResponse, | ||
| status: 200, | ||
| expectedBody: subscriptionInput, | ||
| }); | ||
| }); | ||
|
|
||
|
|
@@ -76,6 +83,7 @@ Deno.test( | |
| inputParams: ["id", subscriptionInput], | ||
| responseObject: subscriptionResponse, | ||
| status: 200, | ||
| expectedBody: subscriptionInput, | ||
| }); | ||
| }, | ||
| ); | ||
|
|
||
| Original file line number | Diff line number | Diff line change | ||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -1,6 +1,5 @@ | ||||||||||||||
| // deno-lint-ignore-file no-explicit-any ban-types | ||||||||||||||
| import { assertEquals } from "../dev_deps.ts"; | ||||||||||||||
| import { mf } from "../dev_deps.ts"; | ||||||||||||||
| import { Client, getLagoError } from "../mod.ts"; | ||||||||||||||
| import type { | ||||||||||||||
| Api, | ||||||||||||||
|
|
@@ -27,10 +26,20 @@ type ExtractLagoResponse<E> = E extends ( | |||||||||||||
|
|
||||||||||||||
| const errorMessage = "Lago Error" as const; | ||||||||||||||
|
|
||||||||||||||
| export function setupMockClient(route: string, handler: mf.MatchHandler) { | ||||||||||||||
| const { fetch, mock } = mf.sandbox(); | ||||||||||||||
| type MatchHandler = (request: Request) => Response | Promise<Response>; | ||||||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||||||||||||||
|
|
||||||||||||||
| mock(route, handler); | ||||||||||||||
| export function setupMockClient(route: string, handler: MatchHandler) { | ||||||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||||||||||||||
| const [method, path] = route.split("@"); | ||||||||||||||
|
|
||||||||||||||
| const fetch = (async (input: RequestInfo | URL, init?: RequestInit) => { | ||||||||||||||
| const request = input instanceof Request ? input : new Request(input, init); | ||||||||||||||
| const url = new URL(request.url); | ||||||||||||||
|
|
||||||||||||||
| assertEquals(request.method, method); | ||||||||||||||
| assertEquals(url.pathname, path); | ||||||||||||||
|
Comment on lines
+38
to
+39
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Asserting from inside Alternative: capture the request in the handler and assert after the client call returns, so mismatches show up as normal assertion failures rather than as request errors. |
||||||||||||||
|
|
||||||||||||||
| return await handler(request); | ||||||||||||||
| }) as typeof globalThis.fetch; | ||||||||||||||
|
|
||||||||||||||
| return Client("api_key", { customFetch: fetch }); | ||||||||||||||
| } | ||||||||||||||
|
|
@@ -48,6 +57,7 @@ export async function lagoTest< | |||||||||||||
| status, | ||||||||||||||
| testType, | ||||||||||||||
| urlParams, | ||||||||||||||
| expectedBody, | ||||||||||||||
| }: { | ||||||||||||||
| testType: "error" | "200"; | ||||||||||||||
| t: Deno.TestContext; | ||||||||||||||
|
|
@@ -59,17 +69,21 @@ export async function lagoTest< | |||||||||||||
| >; | ||||||||||||||
| status: number; | ||||||||||||||
| urlParams?: Record<string, string>; | ||||||||||||||
| expectedBody?: unknown; | ||||||||||||||
| }, | ||||||||||||||
| ) { | ||||||||||||||
| const client = setupMockClient( | ||||||||||||||
| route, | ||||||||||||||
| (_req) => { | ||||||||||||||
| async (_req) => { | ||||||||||||||
| if (urlParams) { | ||||||||||||||
| const urlSearchParams = new URLSearchParams(new URL(_req.url).search); | ||||||||||||||
| Object.entries(urlParams).forEach(([key, value]) => { | ||||||||||||||
| assertEquals(urlSearchParams.get(key), value); | ||||||||||||||
| }); | ||||||||||||||
| } | ||||||||||||||
| if (expectedBody) { | ||||||||||||||
| assertEquals(await _req.json(), expectedBody); | ||||||||||||||
| } | ||||||||||||||
|
Comment on lines
+84
to
+86
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
Truthiness skips a |
||||||||||||||
| return new Response( | ||||||||||||||
| responseObject ? JSON.stringify(responseObject) : null, | ||||||||||||||
| { status }, | ||||||||||||||
|
|
||||||||||||||
| Original file line number | Diff line number | Diff line change | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -15,8 +15,24 @@ const walletInput = { | |||||||||
| "granted_credits": 10, | ||||||||||
| "external_customer_id": "12345", | ||||||||||
| "expiration_at": "2022-09-14T23:59:59Z", | ||||||||||
| "purchase_order_number": "PO-123", | ||||||||||
| "recurring_transaction_rules": [ | ||||||||||
| { | ||||||||||
| "trigger": "interval", | ||||||||||
| "interval": "monthly", | ||||||||||
| "method": "fixed", | ||||||||||
| "paid_credits": 100, | ||||||||||
| "granted_credits": 10, | ||||||||||
|
Comment on lines
+24
to
+25
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same here — the create payload types these as It doesn't error today only because the |
||||||||||
| "purchase_order_number": "PO-RULE-123", | ||||||||||
| }, | ||||||||||
| ], | ||||||||||
| }, | ||||||||||
| } as const satisfies WalletInput; | ||||||||||
| } satisfies WalletInput & { | ||||||||||
| wallet: { | ||||||||||
| purchase_order_number: string; | ||||||||||
| recurring_transaction_rules: Array<{ purchase_order_number: string }>; | ||||||||||
| }; | ||||||||||
| }; | ||||||||||
|
Comment on lines
+30
to
+35
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same as the subscription fixture — the intersection isn't needed ( Worth noting this |
||||||||||
|
|
||||||||||
| const walletResponse = { | ||||||||||
| "wallet": { | ||||||||||
|
|
@@ -35,15 +51,35 @@ const walletResponse = { | |||||||||
| "last_balance_sync_at": "2022-09-14T16:35:31Z", | ||||||||||
| "last_consumed_credit_at": "2022-09-14T16:35:31Z", | ||||||||||
| "terminated_at": "2022-09-14T16:35:31Z", | ||||||||||
| "purchase_order_number": "PO-123", | ||||||||||
| "recurring_transaction_rules": [ | ||||||||||
| { | ||||||||||
| "lago_id": "483da83c-c007-4fbb-afcd-b00c07c41ffe", | ||||||||||
| "trigger": "interval", | ||||||||||
| "interval": "monthly", | ||||||||||
| "method": "fixed", | ||||||||||
| "paid_credits": 100, | ||||||||||
| "granted_credits": 10, | ||||||||||
|
Comment on lines
+61
to
+62
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
These two lines are also the only new type errors this PR introduces — I ran The rule object is also missing fields the response type marks required: |
||||||||||
| "purchase_order_number": "PO-RULE-123", | ||||||||||
| }, | ||||||||||
| ], | ||||||||||
| }, | ||||||||||
| } as const satisfies Wallet; | ||||||||||
| } satisfies Wallet & { | ||||||||||
| wallet: { | ||||||||||
| purchase_order_number: string; | ||||||||||
| recurring_transaction_rules: Array<{ purchase_order_number: string }>; | ||||||||||
| }; | ||||||||||
| }; | ||||||||||
|
|
||||||||||
| const walletUpdateInput = { | ||||||||||
| "wallet": { | ||||||||||
| "name": "Wallet name", | ||||||||||
| "expiration_at": "2022-09-14T23:59:59Z", | ||||||||||
| "purchase_order_number": "PO-123", | ||||||||||
| }, | ||||||||||
| } as const satisfies WalletUpdateInput; | ||||||||||
| } satisfies WalletUpdateInput & { | ||||||||||
| wallet: { purchase_order_number: string }; | ||||||||||
| }; | ||||||||||
|
|
||||||||||
| const walletsResponse = { | ||||||||||
| wallets: [walletInput.wallet], | ||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||
|
|
@@ -58,6 +94,7 @@ Deno.test("Successfully sent wallet responds with 2xx", async (t) => { | |||||||||
| inputParams: [walletInput], | ||||||||||
| responseObject: walletResponse, | ||||||||||
| status: 200, | ||||||||||
| expectedBody: walletInput, | ||||||||||
| }); | ||||||||||
| }); | ||||||||||
|
|
||||||||||
|
|
@@ -82,6 +119,7 @@ Deno.test("Successfully sent wallet update request responds with 2xx", async (t) | |||||||||
| inputParams: ["id", walletUpdateInput], | ||||||||||
| responseObject: walletResponse, | ||||||||||
| status: 200, | ||||||||||
| expectedBody: walletUpdateInput, | ||||||||||
| }); | ||||||||||
| }); | ||||||||||
|
|
||||||||||
|
|
||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -6,8 +6,11 @@ const walletTransactionInput = { | |
| "wallet_id": "985da83c-c007-4fbb-afcd-b00c07c41ffe", | ||
| "paid_credits": 100, | ||
| "granted_credits": 10, | ||
| "purchase_order_number": "PO-123", | ||
| }, | ||
| } as const satisfies WalletTransactionInput; | ||
| } satisfies WalletTransactionInput & { | ||
| wallet_transaction: { purchase_order_number: string }; | ||
| }; | ||
|
Comment on lines
+11
to
+13
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same intersection point as the other two fixtures — (Heads-up while you're here: |
||
|
|
||
| Deno.test( | ||
| "Successfully sent wallet transaction responds with 2xx", | ||
|
|
@@ -27,12 +30,14 @@ Deno.test( | |
| transaction_type: "inbound", | ||
| amount: 500, | ||
| credit_amount: 500, | ||
| purchase_order_number: "PO-123", | ||
| settled_at: "2022-09-14T16:35:31Z", | ||
| created_at: "2022-09-14T16:35:31Z", | ||
| }, | ||
| ], | ||
| }, | ||
| status: 200, | ||
| expectedBody: walletTransactionInput, | ||
| }); | ||
| }, | ||
| ); | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Removed because the mock package is not available anymore