Skip to content

Commit

Permalink
Improve test (vercel#1725)
Browse files Browse the repository at this point in the history
* test: improve test coverage

* ci
  • Loading branch information
promer94 authored and nevilm-lt committed Apr 22, 2022
1 parent 581e0e4 commit 9fd7e92
Show file tree
Hide file tree
Showing 7 changed files with 401 additions and 102 deletions.
71 changes: 61 additions & 10 deletions infinite/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,13 +71,66 @@ export const infinite = (<Data, Error>(useSWRNext: SWRHook) =>
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [firstPageKey])

// Actual SWR hook to load all pages in one fetcher.
const swr = useSWRNext<Data[], Error>(
firstPageKey ? INFINITE_PREFIX + firstPageKey : null,
async () => {
// get the revalidate context
const [forceRevalidateAll, originalData] =
cache.get(contextCacheKey) || []
if (firstPageKey) {
// If the key has been changed, we keep the current page size if persistSize is enabled
cache.set(
pageSizeCacheKey,
persistSize ? lastPageSizeRef.current : initialSize
)
}

// `initialSize` isn't allowed to change during the lifecycle
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [firstPageKey])

// Actual SWR hook to load all pages in one fetcher.
const swr = useSWRNext<Data[], Error>(
firstPageKey ? INFINITE_PREFIX + firstPageKey : null,
async () => {
// get the revalidate context
const [forceRevalidateAll, originalData] =
cache.get(contextCacheKey) || []

// return an array of page data
const data: Data[] = []

const pageSize = resolvePageSize()

let previousPageData = null
for (let i = 0; i < pageSize; ++i) {
const [pageKey, pageArgs] = serialize(getKey(i, previousPageData))

if (!pageKey) {
// `pageKey` is falsy, stop fetching new pages.
break
}

// Get the cached page data.
let pageData = cache.get(pageKey)

// should fetch (or revalidate) if:
// - `revalidateAll` is enabled
// - `mutate()` called
// - the cache is missing
// - it's the first page and it's not the initial render
// - cache for that page has changed
const shouldFetchPage =
revalidateAll ||
forceRevalidateAll ||
isUndefined(pageData) ||
(revalidateFirstPage && !i && !isUndefined(dataRef.current)) ||
(originalData &&
!isUndefined(originalData[i]) &&
!config.compare(originalData[i], pageData))

if (fn && shouldFetchPage) {
pageData = await fn(...pageArgs)
cache.set(pageKey, pageData)
}

data.push(pageData)
previousPageData = pageData
}

// return an array of page data
const data: Data[] = []
Expand All @@ -86,9 +139,7 @@ export const infinite = (<Data, Error>(useSWRNext: SWRHook) =>

let previousPageData = null
for (let i = 0; i < pageSize; ++i) {
const [pageKey, pageArgs] = serialize(
getKey ? getKey(i, previousPageData) : null
)
const [pageKey] = serialize(getKey(i, previousPageData))

if (!pageKey) {
// `pageKey` is falsy, stop fetching new pages.
Expand Down
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -74,8 +74,8 @@
"@testing-library/jest-dom": "5.14.1",
"@testing-library/react": "12.0.0",
"@types/react": "17.0.20",
"@typescript-eslint/eslint-plugin": "4.31.0",
"@typescript-eslint/parser": "4.31.0",
"@typescript-eslint/eslint-plugin": "5.8.0",
"@typescript-eslint/parser": "5.8.0",
"bunchee": "1.7.1",
"eslint": "7.32.0",
"eslint-config-prettier": "6.5.0",
Expand Down
10 changes: 5 additions & 5 deletions src/utils/config.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
import { stableHash } from './hash'
import { initCache } from './cache'
import { preset } from './web-preset'
import { slowConnection } from './env'
import {
import type {
PublicConfiguration,
FullConfiguration,
RevalidatorOptions,
Revalidator,
ScopedMutator,
Cache
} from '../types'
import { stableHash } from './hash'
import { initCache } from './cache'
import { preset } from './web-preset'
import { slowConnection } from './env'
import { isUndefined, noop, mergeObjects } from './helper'

// error retry
Expand Down
77 changes: 75 additions & 2 deletions test/use-swr-infinite.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,18 +15,58 @@ describe('useSWRInfinite', () => {
it('should render the first page component', async () => {
const key = createKey()
function Page() {
const { data } = useSWRInfinite(
const { data, error, isValidating } = useSWRInfinite(
index => `page-${index}-${key}`,
infiniteKey => createResponse(infiniteKey)
)

return <div>data:{data}</div>
return (
<div>
<div>data:{data}</div>
<div>error:{error}</div>
<div>isValidating:{isValidating.toString()}</div>
</div>
)
}

renderWithConfig(<Page />)
screen.getByText('data:')

await screen.findByText(`data:page-0-${key}`)
await screen.findByText(`error:`)
await screen.findByText(`isValidating:false`)
})

it('should not render anything if getKey throw error and call mutate wont cause error', async () => {
function Page() {
const { data, error, isValidating, mutate } = useSWRInfinite(
() => {
throw new Error('error')
},
infiniteKey => createResponse(infiniteKey)
)

return (
<div>
<div onClick={() => mutate()}>data:{data}</div>
<div>error:{error}</div>
<div>isValidating:{isValidating.toString()}</div>
</div>
)
}

renderWithConfig(<Page />)
screen.getByText('data:')

await screen.findByText(`data:`)
await screen.findByText(`error:`)
await screen.findByText(`isValidating:false`)

fireEvent.click(screen.getByText('data:'))

await screen.findByText(`data:`)
await screen.findByText(`error:`)
await screen.findByText(`isValidating:false`)
})

it('should render the multiple pages', async () => {
Expand Down Expand Up @@ -720,6 +760,39 @@ describe('useSWRInfinite', () => {
expect(loggedValues).toEqual([1])
})

it('setSize should only accept number', async () => {
const key = createKey()
function Comp() {
const { data, size, setSize } = useSWRInfinite(
index => [key, index],
(_, index) => createResponse(`page ${index}`)
)

return (
<>
<div
onClick={() => {
// load next page
// @ts-ignore
setSize('2')
}}
>
data:{data}
</div>
<div>size:{size}</div>
</>
)
}
renderWithConfig(<Comp></Comp>)
await screen.findByText('data:page 0')
await screen.findByText('size:1')

fireEvent.click(screen.getByText('data:page 0'))

await screen.findByText('data:page 0')
await screen.findByText('size:1')
})

it('should correctly set size when setSize receives a callback', async () => {
const key = createKey()

Expand Down
17 changes: 17 additions & 0 deletions test/use-swr-key.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,23 @@ describe('useSWR - key', () => {
await screen.findByText(`${baseKey}-second`)
})

it('should not fetch if the function key throws an error', async () => {
let value = 0
const fetcher = jest.fn(() => value++)
const key = () => {
throw new Error('error')
}

function Page() {
const { data } = useSWR(key, fetcher)
return <div>{`key-${data}`}</div>
}

renderWithConfig(<Page />)
await screen.findByText(`key-undefined`)
expect(fetcher).toBeCalledTimes(0)
})

it('should cleanup state when key turns to empty', async () => {
const key = createKey()
function Page() {
Expand Down
Loading

0 comments on commit 9fd7e92

Please sign in to comment.