Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

test: enable <StrictMode/> for testing #2721

Draft
wants to merge 3 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
178 changes: 178 additions & 0 deletions test/old-tests.test.tsx
@@ -0,0 +1,178 @@
import React, { useEffect, useState } from 'react'
import {
createKey,
createResponse,
executeWithoutBatching,
renderWithConfig,
sleep
} from './utils'
import useSWR from 'swr'
import { act, fireEvent, screen } from '@testing-library/react'

describe('old tests - only kept as reference', () => {
// https://codesandbox.io/s/concurrent-swr-case-ii-lr6x4u
it.skip('should do state updates in transitions', async () => {
const key1 = createKey()
const key2 = createKey()

const log = []

function Counter() {
const [count, setCount] = React.useState(0)

React.useEffect(() => {
const interval = setInterval(() => {
setCount(x => x + 1)
}, 20)
return () => clearInterval(interval)
}, [])

log.push(count)

return <>{count}</>
}

function Body() {
useSWR(key2, () => createResponse(true, { delay: 1000 }), {
revalidateOnFocus: false,
revalidateOnReconnect: false,
dedupingInterval: 0,
suspense: true
})
return null
}

function Page() {
const { data } = useSWR(key1, () => createResponse(true, { delay: 50 }), {
revalidateOnFocus: false,
revalidateOnReconnect: false,
dedupingInterval: 0
})

return (
<>
<Counter />
{data ? <Body /> : null}
</>
)
}

await executeWithoutBatching(async () => {
renderWithConfig(<Page />)
await sleep(500)
})
})

it.skip('should not trigger the onLoadingSlow and onSuccess event after component unmount', async () => {
const key = createKey()
let loadingSlow = null,
success = null
function Page() {
const { data } = useSWR(key, () => createResponse('SWR'), {
onLoadingSlow: loadingKey => {
loadingSlow = loadingKey
},
onSuccess: (_, successKey) => {
success = successKey
},
loadingTimeout: 100
})
return <div>hello, {data}</div>
}

function App() {
const [on, toggle] = useState(true)
return (
<div id="app" onClick={() => toggle(s => !s)}>
{on && <Page />}
</div>
)
}

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

fireEvent.click(screen.getByText('hello,'))
await act(() => sleep(200))
expect(success).toEqual(null)
expect(loadingSlow).toEqual(null)
})

it.skip('should not trigger the onError and onErrorRetry event after component unmount', async () => {
const key = createKey()
let retry = null,
failed = null
function Page() {
const { data } = useSWR(key, () => createResponse(new Error('error!')), {
onError: (_, errorKey) => {
failed = errorKey
},
onErrorRetry: (_, errorKey) => {
retry = errorKey
},
dedupingInterval: 0
})
return (
<div>
<>hello, {data}</>
</div>
)
}

function App() {
const [on, toggle] = useState(true)
return (
<div id="app" onClick={() => toggle(s => !s)}>
{on && <Page />}
</div>
)
}

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

fireEvent.click(screen.getByText('hello,'))
await act(() => sleep(200))
expect(retry).toEqual(null)
expect(failed).toEqual(null)
})
// https://github.com/vercel/swr/pull/1003
it.skip('should not dedupe synchronous mutations', async () => {
const mutationRecivedValues = []
const renderRecivedValues = []

const key = createKey()
function Component() {
const { data, mutate: boundMutate } = useSWR(key, () => 0)

useEffect(() => {
setTimeout(() => {
// let's mutate twice, synchronously
boundMutate(v => {
mutationRecivedValues.push(v) // should be 0
return 1
}, false)
boundMutate(v => {
mutationRecivedValues.push(v) // should be 1
return 2
}, false)
}, 1)
// the mutate function is guaranteed to be the same reference
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [])

renderRecivedValues.push(data) // should be 0 -> 2, never render 1 in between
return null
}

renderWithConfig(<Component />)

await executeWithoutBatching(() => sleep(50))
expect(mutationRecivedValues).toEqual([0, 1])
expect(renderRecivedValues).toEqual([undefined, 0, 1, 2])
})
})
26 changes: 19 additions & 7 deletions test/use-swr-cache.test.tsx
@@ -1,5 +1,5 @@
import { act, fireEvent, screen } from '@testing-library/react'
import { useState, StrictMode } from 'react'
import { useState, StrictMode, Profiler } from 'react'
import useSWR, { useSWRConfig, SWRConfig, mutate as globalMutate } from 'swr'
import {
sleep,
Expand Down Expand Up @@ -47,8 +47,11 @@ describe('useSWR - cache provider', () => {

function Page() {
const { data } = useSWR(key, fetcher)
renderedValues.push(data)
return <div>{data}</div>
return (
<Profiler id={key} onRender={() => renderedValues.push(data)}>
<div>{data}</div>
</Profiler>
)
}

renderWithConfig(<Page />, {
Expand Down Expand Up @@ -171,8 +174,13 @@ describe('useSWR - cache provider', () => {
screen.getByText('1')
unmount()
expect(focusFn).toBeCalled()
expect(unsubscribeFocusFn).toBeCalledTimes(1)
expect(unsubscribeReconnectFn).toBeCalledTimes(1)
/**
* production mode
* expect(unsubscribeFocusFn).toBeCalledTimes(1)
* expect(unsubscribeReconnectFn).toBeCalledTimes(1)
*/
expect(unsubscribeFocusFn).toBeCalledTimes(2)
expect(unsubscribeReconnectFn).toBeCalledTimes(2)
})

it('should work with revalidateOnFocus', async () => {
Expand Down Expand Up @@ -335,9 +343,13 @@ describe('useSWR - cache provider', () => {
}

renderWithConfig(<Page />)
expect(createCacheProvider).toBeCalledTimes(1)
/**
* production mode
* expect(createCacheProvider).toBeCalledTimes(1)
* */
expect(createCacheProvider).toBeCalledTimes(2)
act(() => rerender({}))
expect(createCacheProvider).toBeCalledTimes(1)
expect(createCacheProvider).toBeCalledTimes(2)
})
})

Expand Down
61 changes: 1 addition & 60 deletions test/use-swr-concurrent-rendering.test.tsx
@@ -1,11 +1,5 @@
import { screen, fireEvent, act } from '@testing-library/react'
import {
createKey,
createResponse,
sleep,
executeWithoutBatching,
renderWithConfig
} from './utils'
import { createKey, createResponse, sleep, renderWithConfig } from './utils'
import React from 'react'

import useSWR from 'swr'
Expand Down Expand Up @@ -69,57 +63,4 @@ describe('useSWR - concurrent rendering', () => {
await act(() => sleep(120))
screen.getByText(`isPending:0,data:${newKey}`)
})

// https://codesandbox.io/s/concurrent-swr-case-ii-lr6x4u
it.skip('should do state updates in transitions', async () => {
const key1 = createKey()
const key2 = createKey()

const log = []

function Counter() {
const [count, setCount] = React.useState(0)

React.useEffect(() => {
const interval = setInterval(() => {
setCount(x => x + 1)
}, 20)
return () => clearInterval(interval)
}, [])

log.push(count)

return <>{count}</>
}

function Body() {
useSWR(key2, () => createResponse(true, { delay: 1000 }), {
revalidateOnFocus: false,
revalidateOnReconnect: false,
dedupingInterval: 0,
suspense: true
})
return null
}

function Page() {
const { data } = useSWR(key1, () => createResponse(true, { delay: 50 }), {
revalidateOnFocus: false,
revalidateOnReconnect: false,
dedupingInterval: 0
})

return (
<>
<Counter />
{data ? <Body /> : null}
</>
)
}

await executeWithoutBatching(async () => {
renderWithConfig(<Page />)
await sleep(500)
})
})
})