diff --git a/server/api/helcim/existing-card.get.js b/server/api/helcim/existing-card.get.js index 14405fc..6ec83a6 100644 --- a/server/api/helcim/existing-card.get.js +++ b/server/api/helcim/existing-card.get.js @@ -9,10 +9,7 @@ export default defineEventHandler(async (event) => { return { cardToken: null } } - const cardsResponse = await listHelcimCustomerCards(member.helcimCustomerId) - const cards = Array.isArray(cardsResponse) - ? cardsResponse - : (cardsResponse?.cards || cardsResponse?.data || []) + const cards = await listHelcimCustomerCards(member.helcimCustomerId) if (!cards.length) { return { cardToken: null } diff --git a/server/api/helcim/update-card.post.js b/server/api/helcim/update-card.post.js index b3dd2d9..1ccd17a 100644 --- a/server/api/helcim/update-card.post.js +++ b/server/api/helcim/update-card.post.js @@ -45,10 +45,7 @@ export default defineEventHandler(async (event) => { const { cardToken } = body // Step 3: verify the submitted token is attached to this member's customer - const cardsResponse = await listHelcimCustomerCards(member.helcimCustomerId) - const cards = Array.isArray(cardsResponse) - ? cardsResponse - : (cardsResponse?.cards || cardsResponse?.data || []) + const cards = await listHelcimCustomerCards(member.helcimCustomerId) const matchingCard = cards.find((c) => c?.cardToken === cardToken) if (!matchingCard) { diff --git a/server/api/helcim/verify-payment.post.js b/server/api/helcim/verify-payment.post.js index 5f3238a..e00d28d 100644 --- a/server/api/helcim/verify-payment.post.js +++ b/server/api/helcim/verify-payment.post.js @@ -13,7 +13,7 @@ export default defineEventHandler(async (event) => { const cards = await listHelcimCustomerCards(body.customerId) // Verify the card token exists for this customer - const cardExists = Array.isArray(cards) && cards.some(card => + const cardExists = cards.some(card => card.cardToken === body.cardToken ) diff --git a/server/utils/helcim.js b/server/utils/helcim.js index ca6eb34..a96f630 100644 --- a/server/utils/helcim.js +++ b/server/utils/helcim.js @@ -86,8 +86,10 @@ export const createHelcimCustomer = (payload) => export const updateHelcimCustomer = (id, payload) => helcimFetch(`/customers/${id}`, { method: 'PATCH', body: payload, errorMessage: 'Billing update failed' }) -export const listHelcimCustomerCards = (id) => - helcimFetch(`/customers/${id}/cards`, { errorMessage: 'Card lookup failed' }) +export const listHelcimCustomerCards = async (id) => { + const raw = await helcimFetch(`/customers/${id}/cards`, { errorMessage: 'Card lookup failed' }) + return Array.isArray(raw) ? raw : (raw?.cards || raw?.data || []) +} /** * Set a customer's default payment method by card token. diff --git a/tests/server/api/helcim-existing-card.test.js b/tests/server/api/helcim-existing-card.test.js index 4dcf2ce..8cf77ce 100644 --- a/tests/server/api/helcim-existing-card.test.js +++ b/tests/server/api/helcim-existing-card.test.js @@ -82,28 +82,6 @@ describe('helcim existing-card endpoint', () => { expect(result.cardToken).toBe('tok-b') }) - it('unwraps a { cards: [...] } response envelope', async () => { - requireAuth.mockResolvedValue({ _id: 'm1', helcimCustomerId: 9876 }) - listHelcimCustomerCards.mockResolvedValue({ - cards: [{ cardToken: 'tok-only' }] - }) - - const result = await existingCardHandler(newEvent()) - - expect(result.cardToken).toBe('tok-only') - }) - - it('unwraps a { data: [...] } response envelope', async () => { - requireAuth.mockResolvedValue({ _id: 'm1', helcimCustomerId: 9876 }) - listHelcimCustomerCards.mockResolvedValue({ - data: [{ cardToken: 'tok-only' }] - }) - - const result = await existingCardHandler(newEvent()) - - expect(result.cardToken).toBe('tok-only') - }) - it('returns { cardToken: null } if the resolved card has no cardToken', async () => { requireAuth.mockResolvedValue({ _id: 'm1', helcimCustomerId: 9876 }) listHelcimCustomerCards.mockResolvedValue([{ default: true }]) diff --git a/tests/server/utils/helcim.test.js b/tests/server/utils/helcim.test.js index d863b99..5fe63b0 100644 --- a/tests/server/utils/helcim.test.js +++ b/tests/server/utils/helcim.test.js @@ -1,6 +1,7 @@ import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest' import { + listHelcimCustomerCards, listHelcimCustomerTransactions, updateHelcimCustomerDefaultPaymentMethod, updateHelcimSubscriptionPaymentMethod @@ -25,6 +26,56 @@ function errResponse(status = 500, body = 'boom') { } } +describe('listHelcimCustomerCards', () => { + beforeEach(() => { + vi.clearAllMocks() + }) + afterEach(() => { + mockFetch.mockReset() + }) + + it('passes through a bare array response', async () => { + const cards = [ + { id: 1, cardToken: 'tok-a' }, + { id: 2, cardToken: 'tok-b' } + ] + mockFetch.mockResolvedValue(okResponse(cards)) + + const result = await listHelcimCustomerCards('2488717') + + expect(result).toEqual(cards) + }) + + it('unwraps a { cards: [...] } response envelope', async () => { + const cards = [{ id: 1, cardToken: 'tok-a' }] + mockFetch.mockResolvedValue(okResponse({ cards })) + + const result = await listHelcimCustomerCards('2488717') + + expect(result).toEqual(cards) + }) + + it('unwraps a { data: [...] } response envelope', async () => { + const cards = [{ id: 1, cardToken: 'tok-a' }] + mockFetch.mockResolvedValue(okResponse({ data: cards })) + + const result = await listHelcimCustomerCards('2488717') + + expect(result).toEqual(cards) + }) + + it('returns an empty array for null, undefined, or unrecognized object responses', async () => { + mockFetch.mockResolvedValueOnce(okResponse(null)) + expect(await listHelcimCustomerCards('2488717')).toEqual([]) + + mockFetch.mockResolvedValueOnce(okResponse(undefined)) + expect(await listHelcimCustomerCards('2488717')).toEqual([]) + + mockFetch.mockResolvedValueOnce(okResponse({ unexpected: 'shape' })) + expect(await listHelcimCustomerCards('2488717')).toEqual([]) + }) +}) + describe('listHelcimCustomerTransactions', () => { beforeEach(() => { vi.clearAllMocks()