Skip to content

Commit

Permalink
If the image export request fails, try again (just once)
Browse files Browse the repository at this point in the history
  • Loading branch information
crismali committed Oct 28, 2024
1 parent 8f7187b commit c4ecbc6
Show file tree
Hide file tree
Showing 2 changed files with 98 additions and 10 deletions.
87 changes: 83 additions & 4 deletions src/network/__tests__/useExportImage.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,18 +11,23 @@ jest.mock('../useAuthedFetch')

describe('useExportImage', () => {
let mockAuthedFetch: AuthedFetch
let blob: Blob
let emptyBlob: Blob
let html: string
let client: QueryClient

beforeEach(() => {
userIsSignedIn()
mockAuthedFetch = jest.fn()
asMock(useAuthedFetch).mockReturnValue(mockAuthedFetch)
client = new QueryClient()
html = `<html><body>${faker.lorem.paragraph()}</body></html>`
blob = new Blob([faker.lorem.paragraph()], { type: 'image/png' })
emptyBlob = new Blob([])
})

it('requests a png of the image', async () => {
const client = new QueryClient()
const html = `<html><body>${faker.lorem.paragraph()}</body></html>`
const blob = new Blob([])
asMock(mockAuthedFetch).mockResolvedValue({ statusCode: 200, json: { blob } })
asMock(mockAuthedFetch).mockResolvedValue({ statusCode: 201, blob })

const { result } = renderHook(() => useExportImage(), {
wrapper: ({ children }) => {
Expand All @@ -42,4 +47,78 @@ describe('useExportImage', () => {
body: { html },
})
})

it('returns the image', async () => {
asMock(mockAuthedFetch).mockResolvedValue({ statusCode: 201, blob })

const { result } = renderHook(() => useExportImage(), {
wrapper: ({ children }) => {
return (
<QueryClientProvider client={client}>
<AuthProvider>{children}</AuthProvider>
</QueryClientProvider>
)
},
})

await result.current.mutateAsync(html)
await waitFor(() => expect(result.current.isSuccess).toEqual(true))
expect(blob === emptyBlob).toEqual(false)
expect(result.current.data).toEqual(blob)
})

describe('when the response code is not a 201 (unsuccessful)', () => {
it('reattempts the request and returns the image', async () => {
let numberOfCalls = 0
asMock(mockAuthedFetch).mockImplementation(() => {
numberOfCalls += 1

if (numberOfCalls === 1) {
return Promise.resolve({ statusCode: 500 })
} else if (numberOfCalls === 2) {
return Promise.resolve({ statusCode: 201, blob })
} else {
throw new Error('something went wrong')
}
})

const { result } = renderHook(() => useExportImage(), {
wrapper: ({ children }) => {
return (
<QueryClientProvider client={client}>
<AuthProvider>{children}</AuthProvider>
</QueryClientProvider>
)
},
})

expect(mockAuthedFetch).toHaveBeenCalledTimes(0)
await result.current.mutateAsync(html)
await waitFor(() => expect(result.current.isSuccess).toEqual(true))
expect(mockAuthedFetch).toHaveBeenCalledTimes(2)
expect(blob === emptyBlob).toEqual(false)
expect(result.current.data).toEqual(blob)
})

it('reattempts the request and returns an empty blob if it fails again', async () => {
asMock(mockAuthedFetch).mockResolvedValue({ statusCode: 500 })

const { result } = renderHook(() => useExportImage(), {
wrapper: ({ children }) => {
return (
<QueryClientProvider client={client}>
<AuthProvider>{children}</AuthProvider>
</QueryClientProvider>
)
},
})

expect(mockAuthedFetch).toHaveBeenCalledTimes(0)
await result.current.mutateAsync(html)
await waitFor(() => expect(result.current.isSuccess).toEqual(true))
expect(mockAuthedFetch).toHaveBeenCalledTimes(2)
expect(blob === emptyBlob).toEqual(false)
expect(result.current.data).toEqual(emptyBlob)
})
})
})
21 changes: 15 additions & 6 deletions src/network/useExportImage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,21 @@ export const useExportImage = () => {

return useMutation({
mutationFn: async (html: string) => {
const result = await authedFetch({
body: { html },
method: 'POST',
path: '/image-export',
})
return result.blob
const requestImage = () => {
return authedFetch({
body: { html },
method: 'POST',
path: '/image-export',
})
}

const result = await requestImage()

if (result.statusCode === 201) {
return result.blob
} else {
return (await requestImage()).blob ?? new Blob([])
}
},
})
}

0 comments on commit c4ecbc6

Please sign in to comment.