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(svelte-query): Better createMutation tests #7773

Merged
merged 1 commit into from
Jul 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<script lang="ts">
import { QueryClient } from '@tanstack/query-core'
import { createInfiniteQuery } from '../../src/index'
import type { QueryObserverResult } from '@tanstack/query-core'
import type { Writable } from 'svelte/store'

export let states: Writable<Array<QueryObserverResult>>

const queryClient = new QueryClient()

const query = createInfiniteQuery(
{
queryKey: ['test'],
queryFn: () => Promise.resolve({ count: 1 }),
select: (data) => ({
pages: data.pages.map((x) => `count: ${x.count}`),
pageParams: data.pageParams,
}),
getNextPageParam: () => undefined,
initialPageParam: 0,
},
queryClient,
)

$: states.update((prev) => [...prev, $query])
</script>

<div>{$query.data?.pages.join(',')}</div>
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { describe, expect, test } from 'vitest'
import { render, waitFor } from '@testing-library/svelte'
import { get, writable } from 'svelte/store'
import BaseExample from './BaseExample.svelte'
import SelectExample from './SelectExample.svelte'
import type { Writable } from 'svelte/store'
import type { QueryObserverResult } from '@tanstack/query-core'

Expand Down Expand Up @@ -93,4 +94,32 @@ describe('createInfiniteQuery', () => {
fetchStatus: 'idle',
})
})

test('Select a part of the data', async () => {
const statesStore: Writable<Array<QueryObserverResult>> = writable([])

const rendered = render(SelectExample, {
props: {
states: statesStore,
},
})

await waitFor(() => {
expect(rendered.queryByText('count: 1')).toBeInTheDocument()
})

const states = get(statesStore)

expect(states).toHaveLength(2)

expect(states[0]).toMatchObject({
data: undefined,
isSuccess: false,
})

expect(states[1]).toMatchObject({
data: { pages: ['count: 1'] },
isSuccess: true,
})
})
})
15 changes: 0 additions & 15 deletions packages/svelte-query/tests/createMutation/BaseExample.svelte

This file was deleted.

24 changes: 24 additions & 0 deletions packages/svelte-query/tests/createMutation/FailureExample.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<script lang="ts">
import { writable } from 'svelte/store'
import { QueryClient } from '@tanstack/query-core'
import { setQueryClientContext } from '../../src/context'
import { createMutation } from '../../src/createMutation'

export let mutationFn: (value: {
count: number
}) => Promise<{ count: number }>

const count = writable(0)

const queryClient = new QueryClient()
setQueryClientContext(queryClient)

const mutation = createMutation({ mutationFn: mutationFn })
</script>

<button on:click={() => $mutation.mutate({ count: ++$count })}>Mutate</button>

<div>Data: {$mutation.data?.count}</div>
<div>Status: {$mutation.status}</div>
<div>Failure Count: {$mutation.failureCount}</div>
<div>Failure Reason: {$mutation.failureReason}</div>
28 changes: 28 additions & 0 deletions packages/svelte-query/tests/createMutation/OnSuccessExample.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<script lang="ts">
import { writable } from 'svelte/store'
import { QueryClient } from '@tanstack/query-core'
import { setQueryClientContext } from '../../src/context'
import { createMutation } from '../../src/createMutation'

export let onSuccessMock: any
export let onSettledMock: any

const count = writable(0)

const queryClient = new QueryClient()
setQueryClientContext(queryClient)

const mutation = createMutation({
mutationFn: (vars: { count: number }) => Promise.resolve(vars.count),
onSuccess: (data) => {
onSuccessMock(data)
},
onSettled: (data) => {
onSettledMock(data)
},
})
</script>

<button on:click={() => $mutation.mutate({ count: ++$count })}>Mutate</button>

<div>Count: {$count}</div>
21 changes: 21 additions & 0 deletions packages/svelte-query/tests/createMutation/ResetExample.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<script lang="ts">
import { QueryClient } from '@tanstack/query-core'
import { setQueryClientContext } from '../../src/context'
import { createMutation } from '../../src/createMutation'

const queryClient = new QueryClient()
setQueryClientContext(queryClient)

const mutation = createMutation({
mutationFn: () => {
const err = new Error('Expected mock error')
err.stack = ''
return Promise.reject(err)
},
})
</script>

<button on:click={() => $mutation.reset()}>Reset</button>
<button on:click={() => $mutation.mutate()}>Mutate</button>

<div>Error: {$mutation.error?.message}</div>
103 changes: 94 additions & 9 deletions packages/svelte-query/tests/createMutation/createMutation.test.ts
Original file line number Diff line number Diff line change
@@ -1,23 +1,108 @@
import { describe, expect, test, vi } from 'vitest'
import { fireEvent, render, waitFor } from '@testing-library/svelte'
import BaseExample from './BaseExample.svelte'
import { sleep } from '../utils'
import ResetExample from './ResetExample.svelte'
import OnSuccessExample from './OnSuccessExample.svelte'
import FailureExample from './FailureExample.svelte'

describe('createMutation', () => {
test('Call mutate and check function runs', async () => {
const mutationFn = vi.fn()
test('Able to reset `error`', async () => {
const rendered = render(ResetExample)

const rendered = render(BaseExample, {
await waitFor(() => {
expect(rendered.queryByText('Error: undefined')).toBeInTheDocument()
})

fireEvent.click(rendered.getByRole('button', { name: /Mutate/i }))

await waitFor(() => {
expect(
rendered.queryByText('Error: Expected mock error'),
).toBeInTheDocument()
})

fireEvent.click(rendered.getByRole('button', { name: /Reset/i }))

await waitFor(() => {
expect(rendered.queryByText('Error: undefined')).toBeInTheDocument()
})
})

test('Able to call `onSuccess` and `onSettled` after each successful mutate', async () => {
const onSuccessMock = vi.fn()
const onSettledMock = vi.fn()

const rendered = render(OnSuccessExample, {
props: {
options: {
mutationFn,
},
onSuccessMock,
onSettledMock,
},
})

fireEvent.click(rendered.getByRole('button'))
await waitFor(() => {
expect(rendered.queryByText('Count: 0')).toBeInTheDocument()
})

fireEvent.click(rendered.getByRole('button', { name: /Mutate/i }))
fireEvent.click(rendered.getByRole('button', { name: /Mutate/i }))
fireEvent.click(rendered.getByRole('button', { name: /Mutate/i }))

await waitFor(() => {
expect(rendered.queryByText('Count: 3')).toBeInTheDocument()
})

await waitFor(() => {
expect(onSuccessMock).toHaveBeenCalledTimes(3)
})

expect(onSuccessMock).toHaveBeenCalledWith(1)
expect(onSuccessMock).toHaveBeenCalledWith(2)
expect(onSuccessMock).toHaveBeenCalledWith(3)

await waitFor(() => {
expect(mutationFn).toHaveBeenCalledTimes(1)
expect(onSettledMock).toHaveBeenCalledTimes(3)
})

expect(onSettledMock).toHaveBeenCalledWith(1)
expect(onSettledMock).toHaveBeenCalledWith(2)
expect(onSettledMock).toHaveBeenCalledWith(3)
})

test('Set correct values for `failureReason` and `failureCount` on multiple mutate calls', async () => {
type Value = { count: number }

const mutationFn = vi.fn<(value: Value) => Promise<Value>>()

mutationFn.mockImplementationOnce(() => {
return Promise.reject(`Expected mock error`)
})

mutationFn.mockImplementation(async (value) => {
await sleep(5)
return Promise.resolve(value)
})

const rendered = render(FailureExample, {
props: {
mutationFn,
},
})

await waitFor(() => rendered.queryByText('Data: undefined'))

fireEvent.click(rendered.getByRole('button', { name: /Mutate/i }))
await waitFor(() => rendered.getByText('Data: undefined'))
await waitFor(() => rendered.getByText('Status: error'))
await waitFor(() => rendered.getByText('Failure Count: 1'))
await waitFor(() =>
rendered.getByText('Failure Reason: Expected mock error'),
)

fireEvent.click(rendered.getByRole('button', { name: /Mutate/i }))
await waitFor(() => rendered.getByText('Status: pending'))
await waitFor(() => rendered.getByText('Status: success'))
await waitFor(() => rendered.getByText('Data: 2'))
await waitFor(() => rendered.getByText('Failure Count: 0'))
await waitFor(() => rendered.getByText('Failure Reason: null'))
})
})
Loading