Skip to content

Commit

Permalink
test: refactor use-swr-error.test.tsx (#1031)
Browse files Browse the repository at this point in the history
  • Loading branch information
koba04 authored Mar 13, 2021
1 parent 79c8570 commit 6f03890
Showing 1 changed file with 68 additions and 98 deletions.
166 changes: 68 additions & 98 deletions test/use-swr-error.test.tsx
Original file line number Diff line number Diff line change
@@ -1,24 +1,21 @@
import { act, fireEvent, render, screen } from '@testing-library/react'
import React, { useEffect, useState } from 'react'
import useSWR, { mutate } from '../src'
import { sleep } from './utils'
import { sleep, createResponse } from './utils'

describe('useSWR - error', () => {
it('should handle errors', async () => {
function Page() {
const { data, error } = useSWR(
'error-1',
() =>
new Promise((_, rej) =>
setTimeout(() => rej(new Error('error!')), 200)
)
const { data, error } = useSWR('error-1', () =>
createResponse(new Error('error!'))
)
if (error) return <div>{error.message}</div>
return <div>hello, {data}</div>
}
const { container } = render(<Page />)

expect(container.firstChild.textContent).toMatchInlineSnapshot(`"hello, "`)
render(<Page />)
screen.getByText('hello,')

// mount
await screen.findByText('error!')
})
Expand All @@ -28,18 +25,16 @@ describe('useSWR - error', () => {
function Page() {
const { data, error } = useSWR(
'error-2',
() =>
new Promise((_, rej) =>
setTimeout(() => rej(new Error('error!')), 200)
),
() => createResponse(new Error('error!')),
{ onError: (_, key) => (erroredSWR = key) }
)
if (error) return <div>{error.message}</div>
return <div>hello, {data}</div>
}
const { container } = render(<Page />)

expect(container.firstChild.textContent).toMatchInlineSnapshot(`"hello, "`)
render(<Page />)
screen.getByText('hello,')

// mount
await screen.findByText('error!')
expect(erroredSWR).toEqual('error-2')
Expand All @@ -50,30 +45,29 @@ describe('useSWR - error', () => {
function Page() {
const { data, error } = useSWR(
'error-3',
() => {
return new Promise((_, rej) =>
setTimeout(() => rej(new Error('error: ' + count++)), 100)
)
},
() => createResponse(new Error('error: ' + count++), { delay: 100 }),
{
onErrorRetry: (_, __, ___, revalidate, revalidateOpts) => {
setTimeout(() => revalidate(revalidateOpts), 100)
setTimeout(() => revalidate(revalidateOpts), 50)
},
dedupingInterval: 0
}
)
if (error) return <div>{error.message}</div>
return <div>hello, {data}</div>
}
const { container } = render(<Page />)

expect(container.firstChild.textContent).toMatchInlineSnapshot(`"hello, "`)
render(<Page />)
screen.getByText('hello,')

// mount
await screen.findByText('error: 0')
await act(() => sleep(210)) // retry
expect(container.firstChild.textContent).toMatchInlineSnapshot(`"error: 1"`)
await act(() => sleep(210)) // retry
expect(container.firstChild.textContent).toMatchInlineSnapshot(`"error: 2"`)

await act(() => sleep(200)) // retry
screen.getByText('error: 1')

await act(() => sleep(200)) // retry
screen.getByText('error: 2')
})

it('should trigger the onLoadingSlow and onSuccess event', async () => {
Expand All @@ -82,7 +76,7 @@ describe('useSWR - error', () => {
function Page() {
const { data } = useSWR(
'error-4',
() => new Promise(res => setTimeout(() => res('SWR'), 200)),
() => createResponse('SWR', { delay: 200 }),
{
onLoadingSlow: key => (loadingSlow = key),
onSuccess: (_, key) => (success = key),
Expand All @@ -91,29 +85,25 @@ describe('useSWR - error', () => {
)
return <div>hello, {data}</div>
}
const { container } = render(<Page />)

expect(container.firstChild.textContent).toMatchInlineSnapshot(`"hello, "`)
render(<Page />)
screen.getByText('hello,')
expect(loadingSlow).toEqual(null)
await act(() => sleep(110)) // slow

await act(() => sleep(150)) // trigger onLoadingSlow event
expect(loadingSlow).toEqual('error-4')
expect(success).toEqual(null)
await act(() => sleep(100)) // finish

await act(() => sleep(150)) // finish the request
expect(success).toEqual('error-4')
expect(container.firstChild.textContent).toMatchInlineSnapshot(
`"hello, SWR"`
)
screen.getByText('hello, SWR')
})
it('should trigger limited error retries if errorRetryCount exists', async () => {
let count = 0
function Page() {
const { data, error } = useSWR(
'error-5',
() => {
return new Promise((_, rej) =>
setTimeout(() => rej(new Error('error: ' + count++)), 100)
)
},
() => createResponse(new Error('error: ' + count++)),
{
errorRetryCount: 1,
errorRetryInterval: 50,
Expand All @@ -123,36 +113,33 @@ describe('useSWR - error', () => {
if (error) return <div>{error.message}</div>
return <div>hello, {data}</div>
}
const { container } = render(<Page />)

expect(container.firstChild.textContent).toMatchInlineSnapshot(`"hello, "`)
render(<Page />)
screen.getByText('hello,')

// mount
await screen.findByText('error: 0')

await act(() => sleep(210)) // retry
expect(container.firstChild.textContent).toMatchInlineSnapshot(`"error: 1"`)
await act(() => sleep(210)) // retry
expect(container.firstChild.textContent).toMatchInlineSnapshot(`"error: 1"`)
await screen.findByText('error: 1') // retry

await act(() => sleep(200)) // a retry request won't happen because retryCount is over
screen.getByText('error: 1')
})

it('should not trigger the onLoadingSlow and onSuccess event after component unmount', async () => {
let loadingSlow = null,
success = null
function Page() {
const { data } = useSWR(
'error-6',
() => new Promise(res => setTimeout(() => res('SWR'), 200)),
{
onLoadingSlow: key => {
loadingSlow = key
},
onSuccess: (_, key) => {
success = key
},
loadingTimeout: 100
}
)
return <div>{data}</div>
const { data } = useSWR('error-6', () => createResponse('SWR'), {
onLoadingSlow: key => {
loadingSlow = key
},
onSuccess: (_, key) => {
success = key
},
loadingTimeout: 100
})
return <div>hello, {data}</div>
}

function App() {
Expand All @@ -164,15 +151,13 @@ describe('useSWR - error', () => {
)
}

const { container } = render(<App />)

render(<App />)
screen.getByText('hello,')
expect(loadingSlow).toEqual(null)
expect(success).toEqual(null)

await act(async () => sleep(10))
fireEvent.click(container.firstElementChild)
fireEvent.click(screen.getByText('hello,'))
await act(async () => sleep(200))

expect(success).toEqual(null)
expect(loadingSlow).toEqual(null)
})
Expand All @@ -183,10 +168,7 @@ describe('useSWR - error', () => {
function Page() {
const { data } = useSWR(
'error-7',
() =>
new Promise((_, rej) =>
setTimeout(() => rej(new Error('error!')), 200)
),
() => createResponse(new Error('error!')),
{
onError: (_, key) => {
failed = key
Expand All @@ -197,7 +179,7 @@ describe('useSWR - error', () => {
dedupingInterval: 0
}
)
return <div>{data}</div>
return <div>hello, {data}</div>
}

function App() {
Expand All @@ -209,15 +191,13 @@ describe('useSWR - error', () => {
)
}

const { container } = render(<App />)

render(<App />)
screen.getByText('hello,')
expect(retry).toEqual(null)
expect(failed).toEqual(null)

await act(async () => sleep(10))
fireEvent.click(container.firstElementChild)
fireEvent.click(screen.getByText('hello,'))
await act(async () => sleep(200))

expect(retry).toEqual(null)
expect(failed).toEqual(null)
})
Expand All @@ -227,11 +207,7 @@ describe('useSWR - error', () => {
function Page() {
const { data, error } = useSWR(
'error-8',
() => {
return new Promise((_, rej) =>
setTimeout(() => rej(new Error('error: ' + count++)), 100)
)
},
() => createResponse(new Error('error: ' + count++)),
{
errorRetryCount: 0,
errorRetryInterval: 50,
Expand All @@ -241,30 +217,26 @@ describe('useSWR - error', () => {
if (error) return <div>{error.message}</div>
return <div>hello, {data}</div>
}
const { container } = render(<Page />)

expect(container.firstChild.textContent).toMatchInlineSnapshot(`"hello, "`)
render(<Page />)
screen.getByText('hello,')

// mount
await screen.findByText('error: 0')
await act(() => sleep(210)) // retry
expect(container.firstChild.textContent).toMatchInlineSnapshot(`"error: 0"`)

await act(() => sleep(210)) // retry is never happen
screen.getByText('error: 0')
})

it('should not clear error during revalidating until fetcher is finished successfully', async () => {
const errors = []
const key = 'error-9'
function Page() {
const { error } = useSWR(
key,
() => {
return new Promise((_, rej) => rej(new Error('error')))
},
{
errorRetryCount: 0,
errorRetryInterval: 0,
dedupingInterval: 0
}
)
const { error } = useSWR(key, () => createResponse(new Error('error')), {
errorRetryCount: 0,
errorRetryInterval: 0,
dedupingInterval: 0
})
useEffect(() => {
errors.push(error ? error.message : null)
}, [error])
Expand All @@ -277,9 +249,7 @@ describe('useSWR - error', () => {
// mount
await screen.findByText('hello, error')

await act(() => {
return mutate(key, undefined, true)
})
await act(() => mutate(key, undefined, true))
// initial -> first error -> mutate -> receive another error
// error won't be cleared during revalidation
expect(errors).toEqual([null, 'error', 'error'])
Expand Down

0 comments on commit 6f03890

Please sign in to comment.