Skip to content

Commit

Permalink
Add tests for mutations returning void response
Browse files Browse the repository at this point in the history
  • Loading branch information
adamraya committed Mar 21, 2023
1 parent 5c60483 commit 887efe7
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 26 deletions.
7 changes: 2 additions & 5 deletions packages/commerce-sdk-react/src/hooks/ShopperBaskets/cache.ts
Original file line number Diff line number Diff line change
Expand Up @@ -196,12 +196,9 @@ export const cacheUpdateMatrix: CacheUpdateMatrix<Client> = {
// TODO: Convert invalidate to an update that removes the matching basket
...invalidateCustomerBasketsQuery(customerId, parameters),
remove: [
// We want to fuzzy match all query keys that contain starting with the path
// We want to fuzzy match all queryKeys with the `basketId` in their path
// `["/organizations/",${organization},"/baskets/",${basketId}]`
{queryKey: getBasket.path(parameters)},
...(customerId
? [{queryKey: getCustomerBaskets.queryKey({...parameters, customerId})}]
: [])
{queryKey: getBasket.path(parameters)}
]
}
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,13 +74,13 @@ const deletedCustomerBaskets: BasketsResult = {
}

// --- TEST CASES --- //
/** All Shopper Baskets mutations except these ones have the same cache update logic. */
type NonResponseMutations = Exclude<
/** All Shopper Baskets mutations except these have the same cache update logic. */
type EmptyResponseMutations = Exclude<
ShopperBasketsMutation,
'deleteBasket' | 'addPriceBooksToBasket' | 'addTaxesForBasket' | 'addTaxesForBasketItem'
>
// This is an object rather than an array to more easily ensure we cover all mutations
type TestMap = {[Mut in NonResponseMutations]: Argument<Client[Mut]>}
type TestMap = {[Mut in EmptyResponseMutations]: Argument<Client[Mut]>}
const testMap: TestMap = {
addGiftCertificateItemToBasket: createOptions<'addGiftCertificateItemToBasket'>(
{recipientEmail: 'customer@email', amount: 100},
Expand Down Expand Up @@ -142,8 +142,6 @@ const testMap: TestMap = {
)
}
const deleteTestCase = ['deleteBasket', createOptions<'deleteBasket'>(undefined, {})] as const

// TODO: Implement test cases for mutations returning void
const addPriceBooksToBasketTestCase = [
'addPriceBooksToBasket',
createOptions<'addPriceBooksToBasket'>([], {})
Expand All @@ -160,14 +158,20 @@ const addTaxesForBasketTestCase = [
const addTaxesForBasketItemTestCase = [
'addTaxesForBasketItem',
createOptions<'addTaxesForBasketItem'>({}, {itemId: 'itemId'})
]
] as const

// Type assertion because the built-in type definition for `Object.entries` is limited :\
const nonDeleteTestCases = Object.entries(testMap) as Array<
[NonResponseMutations, Argument<Client[NonResponseMutations]>]
const emptyResponseTestCases = Object.entries(testMap) as Array<
[EmptyResponseMutations, Argument<Client[EmptyResponseMutations]>]
>
// Most test cases only apply to non-delete test cases, some (error handling) can include deleteBasket
const allTestCases = [...nonDeleteTestCases, deleteTestCase]
const allTestCases = [
...emptyResponseTestCases,
deleteTestCase,
addPriceBooksToBasketTestCase,
addTaxesForBasketTestCase,
addTaxesForBasketItemTestCase
]

describe('ShopperBaskets mutations', () => {
const storedCustomerIdKey = `${DEFAULT_TEST_CONFIG.siteId}_customer_id`
Expand All @@ -181,16 +185,19 @@ describe('ShopperBaskets mutations', () => {
})

beforeEach(() => nock.cleanAll())
test.each(nonDeleteTestCases)('`%s` returns data on success', async (mutationName, options) => {
mockMutationEndpoints(basketsEndpoint, oldBasket)
const {result, waitForValueToChange: wait} = renderHookWithProviders(() => {
return useShopperBasketsMutation(mutationName)
})
expect(result.current.data).toBeUndefined()
act(() => result.current.mutate(options))
await waitAndExpectSuccess(wait, () => result.current)
expect(result.current.data).toEqual(oldBasket)
})
test.each(emptyResponseTestCases)(
'`%s` returns data on success',
async (mutationName, options) => {
mockMutationEndpoints(basketsEndpoint, oldBasket)
const {result, waitForValueToChange: wait} = renderHookWithProviders(() => {
return useShopperBasketsMutation(mutationName)
})
expect(result.current.data).toBeUndefined()
act(() => result.current.mutate(options))
await waitAndExpectSuccess(wait, () => result.current)
expect(result.current.data).toEqual(oldBasket)
}
)
test.each(allTestCases)('`%s` returns error on error', async (mutationName, options) => {
mockMutationEndpoints(basketsEndpoint, {error: true}, 400)
const {result, waitForValueToChange: wait} = renderHookWithProviders(() => {
Expand All @@ -203,7 +210,7 @@ describe('ShopperBaskets mutations', () => {
// `.toBeInstanceOf(ResponseError)`, but the class isn't exported. :\
expect(result.current.error).toHaveProperty('response')
})
test.each(nonDeleteTestCases)(
test.each(emptyResponseTestCases)(
'`%s` updates the cache on success',
async (mutationName, options) => {
mockQueryEndpoint(basketsEndpoint, oldBasket) // getBasket
Expand Down Expand Up @@ -247,7 +254,12 @@ describe('ShopperBaskets mutations', () => {
assertUpdateQuery(result.current.customerBaskets, oldCustomerBaskets)
}
)
test('`deleteBasket` returns void on success', async () => {
test.each([
deleteTestCase,
addPriceBooksToBasketTestCase,
addTaxesForBasketTestCase,
addTaxesForBasketItemTestCase
])('`%s` returns void on success', async () => {
// Almost the standard 'returns data' test, just a different return type
const [mutationName, options] = deleteTestCase
mockMutationEndpoints(basketsEndpoint, oldBasket)
Expand Down

0 comments on commit 887efe7

Please sign in to comment.