Skip to content

Commit

Permalink
test: refactor use-swr-config-callbacks.test.tsx
Browse files Browse the repository at this point in the history
  • Loading branch information
koba04 committed Jan 26, 2021
1 parent 489d9f4 commit 59d37fc
Showing 1 changed file with 60 additions and 57 deletions.
117 changes: 60 additions & 57 deletions test/use-swr-config-callbacks.test.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,21 @@
import { act, render, screen, fireEvent } from '@testing-library/react'
import React from 'react'
import useSWR from '../src'
import { sleep } from './utils'
import { sleep, createResponse } from './utils'

describe('useSWR - config callbacks', () => {
it('should trigger the onSuccess event with the latest version of the onSuccess callback', async () => {
let state = null
let count = 0
let promise

function Page(props: { text: string }) {
const { data, revalidate } = useSWR(
'config callbacks - onSuccess',
() => new Promise(res => setTimeout(() => res(count++), 200)),
() => {
promise = createResponse(count++)
return promise
},
{ onSuccess: () => (state = props.text) }
)
return (
Expand All @@ -20,11 +24,9 @@ describe('useSWR - config callbacks', () => {
</div>
)
}
const { container, rerender } = render(<Page text={'a'} />)
const { rerender } = render(<Page text={'a'} />)
// the onSuccess callback does not trigger yet, the state still null.
expect(container.firstChild.textContent).toMatchInlineSnapshot(
`"hello, , a"`
)
expect(screen.getByText('hello, , a')).toBeInTheDocument()
expect(state).toEqual(null)

await screen.findByText('hello, 0, a')
Expand All @@ -33,33 +35,31 @@ describe('useSWR - config callbacks', () => {

// props changed, but the onSuccess callback does not trigger yet, `state` is same as before
rerender(<Page text={'b'} />)
expect(container.firstChild.textContent).toMatchInlineSnapshot(
`"hello, 0, b"`
)
expect(screen.getByText('hello, 0, b')).toBeInTheDocument()
expect(state).toEqual('a')

// trigger revalidation, this would re-trigger the onSuccess callback
fireEvent.click(container.firstElementChild)
fireEvent.click(screen.getByText(/hello/))

await act(() => promise)
expect(screen.getByText('hello, 1, b')).toBeInTheDocument()

await act(() => sleep(201))
expect(container.firstChild.textContent).toMatchInlineSnapshot(
`"hello, 1, b"`
)
// the onSuccess callback should capture the latest `props.text`
expect(state).toEqual('b')
})

it('should trigger the onError event with the latest version of the onError callback', async () => {
let state = null
let count = 0
let promise

function Page(props: { text: string }) {
const { data, revalidate, error } = useSWR(
'config callbacks - onError',
() =>
new Promise((_, rej) =>
setTimeout(() => rej(new Error(`Error: ${count++}`)), 200)
),
() => {
promise = createResponse(new Error(`Error: ${count++}`))
return promise
},
{ onError: () => (state = props.text) }
)
if (error)
Expand All @@ -75,43 +75,49 @@ describe('useSWR - config callbacks', () => {
)
}

const { container, rerender } = render(<Page text="a" />)
const { rerender } = render(<Page text="a" />)

expect(container.firstChild.textContent).toMatchInlineSnapshot(
`"hello, , a"`
)
expect(screen.getByText('hello, , a')).toBeInTheDocument()
expect(state).toEqual(null)
await screen.findByText('Error: 0')

expect(state).toEqual('a')

// props changed, but the onError callback doese not trigger yet.
rerender(<Page text="b" />)
expect(container.firstChild.textContent).toMatchInlineSnapshot(`"Error: 0"`)
expect(container.firstElementChild.getAttribute('title')).toEqual('b')
expect(screen.getByText('Error: 0')).toBeInTheDocument()
expect(screen.getByTitle('b')).toBeInTheDocument()
expect(state).toEqual('a')
fireEvent.click(container.firstElementChild)
await act(() => sleep(210))
fireEvent.click(screen.getByTitle('b'))

try {
await act(() => promise)
} catch (e) {
// expect an error
}

expect(container.firstChild.textContent).toMatchInlineSnapshot(`"Error: 1"`)
expect(container.firstElementChild.getAttribute('title')).toEqual('b')
expect(screen.getByText('Error: 1')).toBeInTheDocument()
expect(screen.getByTitle('b')).toBeInTheDocument()
expect(state).toEqual('b')
})

it('should trigger the onErrorRetry event with the latest version of the onErrorRetry callback', async () => {
let state = null
let count = 0
let promise
let revalidatePromise

function Page(props: { text: string }) {
const { data, error } = useSWR(
'config callbacks - onErrorRetry',
() =>
new Promise((_, rej) =>
setTimeout(() => rej(new Error(`Error: ${count++}`)), 200)
),
() => {
promise = createResponse(new Error(`Error: ${count++}`))
return promise
},
{
onErrorRetry: (_, __, ___, revalidate, revalidateOpts) => {
state = props.text
setTimeout(() => revalidate(revalidateOpts), 100)
revalidatePromise = revalidate(revalidateOpts)
}
}
)
Expand All @@ -123,45 +129,48 @@ describe('useSWR - config callbacks', () => {
)
}

const { container, rerender } = render(<Page text="a" />)
expect(container.firstChild.textContent).toMatchInlineSnapshot(
`"hello, , a"`
)
const { rerender } = render(<Page text="a" />)
expect(screen.getByText('hello, , a')).toBeInTheDocument()
expect(state).toEqual(null)

await screen.findByText('Error: 0')
expect(container.firstElementChild.getAttribute('title')).toEqual('a')
expect(screen.getByTitle('a')).toBeInTheDocument()
expect(state).toEqual('a')

// since the onErrorRetry schedule a timer to trigger revalidation, update props.text now
rerender(<Page text="b" />)
// not revalidate yet.
expect(container.firstChild.textContent).toMatchInlineSnapshot(`"Error: 0"`)
expect(container.firstElementChild.getAttribute('title')).toEqual('b')
expect(screen.getByText('Error: 0')).toBeInTheDocument()
expect(screen.getByTitle('b')).toBeInTheDocument()
expect(state).toEqual('a')

await act(() => sleep(350))
expect(container.firstChild.textContent).toMatchInlineSnapshot(`"Error: 1"`)
expect(container.firstElementChild.getAttribute('title')).toEqual('b')
await act(() => revalidatePromise)
expect(screen.getByText('Error: 1')).toBeInTheDocument()
expect(screen.getByTitle('b')).toBeInTheDocument()
expect(state).toEqual('b')
})

it('should trigger the onLoadingSlow and onSuccess event with the lastest version of the callbacks', async () => {
const LOADING_TIMEOUT = 5
let state = null
let count = 0
let promise

function Page(props: { text: string }) {
const { data } = useSWR(
'config callbacks - onLoadingSlow',
() => new Promise(res => setTimeout(() => res(count++), 200)),
() => {
promise = createResponse(count++, { delay: LOADING_TIMEOUT * 2 })
return promise
},
{
onLoadingSlow: () => {
state = props.text
},
onSuccess: () => {
state = props.text
},
loadingTimeout: 100
loadingTimeout: LOADING_TIMEOUT
}
)
return (
Expand All @@ -171,24 +180,18 @@ describe('useSWR - config callbacks', () => {
)
}

const { container, rerender } = render(<Page text="a" />)
const { rerender } = render(<Page text="a" />)

expect(container.firstChild.textContent).toMatchInlineSnapshot(
`"hello, , a"`
)
expect(screen.getByText('hello, , a')).toBeInTheDocument()
expect(state).toEqual(null)

await act(() => sleep(101))
expect(container.firstChild.textContent).toMatchInlineSnapshot(
`"hello, , a"`
)
await act(() => sleep(LOADING_TIMEOUT))
expect(screen.getByText('hello, , a')).toBeInTheDocument()
expect(state).toEqual('a')
rerender(<Page text="b" />)

await act(() => sleep(100))
expect(container.firstChild.textContent).toMatchInlineSnapshot(
`"hello, 0, b"`
)
await act(() => promise)
expect(screen.getByText('hello, 0, b')).toBeInTheDocument()
expect(state).toEqual('b')
})
})

0 comments on commit 59d37fc

Please sign in to comment.