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
feat: expose querykey getter and fix some querykey stuff #3302
Changes from 48 commits
5392463
8638767
bc702cc
5b55386
2711978
30dcc40
d77f3c8
36ffd96
0a97a6b
217db37
964da9c
90a9173
dc92dcf
5813e19
366107d
c1d4497
c909673
4efa3a8
778859d
7770be8
e9f03e1
cca2d30
8b937df
c9b59bd
44179fd
2d25187
d06701a
4b4e12f
377e271
c8b8ee8
cdc5808
dd8062e
04d5333
c92eb39
c1b162e
c8e3ed7
0e519e2
60afce2
72b5ab6
6f195da
d60dea3
f566339
5adc7ec
957a78c
f025343
3ceba17
05f5c8d
88b8052
943fdeb
bb26bc1
1396478
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,178 @@ | ||
import { getServerAndReactClient } from './__reactHelpers'; | ||
import { useIsFetching } from '@tanstack/react-query'; | ||
import { render, waitFor } from '@testing-library/react'; | ||
import { initTRPC } from '@trpc/server'; | ||
import { konn } from 'konn/dist-cjs'; | ||
import React from 'react'; | ||
import { z } from 'zod'; | ||
|
||
type Post = { | ||
id: number; | ||
text: string; | ||
}; | ||
|
||
const defaultPost = { id: 0, text: 'new post' }; | ||
const ctx = konn() | ||
.beforeEach(() => { | ||
const t = initTRPC.create(); | ||
|
||
const posts: Post[] = [defaultPost]; | ||
|
||
const appRouter = t.router({ | ||
post: t.router({ | ||
byId: t.procedure | ||
.input( | ||
z.object({ | ||
id: z.number(), | ||
}), | ||
) | ||
.query(({ input }) => posts.find((post) => post.id === input.id)), | ||
all: t.procedure.query(() => posts), | ||
}), | ||
}); | ||
|
||
return getServerAndReactClient(appRouter); | ||
}) | ||
.afterEach(async (ctx) => { | ||
await ctx?.close?.(); | ||
}) | ||
.done(); | ||
|
||
describe('getQueryKeys', () => { | ||
test('no input', async () => { | ||
const { proxy, App } = ctx; | ||
|
||
function MyComponent() { | ||
const happy1 = proxy.post.all.getQueryKey(undefined, 'query'); | ||
const happy2 = proxy.post.all.getQueryKey(); | ||
|
||
// @ts-expect-error - post.all has no input | ||
const sad = proxy.post.all.getQueryKey('foo'); | ||
|
||
return ( | ||
<> | ||
<pre data-testid="qKey1">{JSON.stringify(happy1)}</pre> | ||
<pre data-testid="qKey2">{JSON.stringify(happy2)}</pre> | ||
</> | ||
); | ||
} | ||
|
||
const utils = render( | ||
<App> | ||
<MyComponent /> | ||
</App>, | ||
); | ||
|
||
await waitFor(() => { | ||
expect(utils.getByTestId('qKey1')).toHaveTextContent( | ||
JSON.stringify([['post', 'all'], { type: 'query' }]), | ||
); | ||
expect(utils.getByTestId('qKey2')).toHaveTextContent( | ||
JSON.stringify([['post', 'all']]), | ||
); | ||
}); | ||
}); | ||
|
||
test('with input', async () => { | ||
const { proxy, App } = ctx; | ||
|
||
function MyComponent() { | ||
const happy1 = proxy.post.byId.getQueryKey({ id: 1 }, 'query'); | ||
|
||
// doesn't really make sense but should still work | ||
const happyIsh = proxy.post.byId.getQueryKey({ id: 1 }); | ||
|
||
// @ts-expect-error - post.byId has required input | ||
const sad = proxy.post.byId.getQueryKey(undefined, 'query'); | ||
|
||
return ( | ||
<> | ||
<pre data-testid="qKey1">{JSON.stringify(happy1)}</pre> | ||
<pre data-testid="qKey2">{JSON.stringify(happyIsh)}</pre> | ||
</> | ||
); | ||
} | ||
|
||
const utils = render( | ||
<App> | ||
<MyComponent /> | ||
</App>, | ||
); | ||
|
||
await waitFor(() => { | ||
expect(utils.getByTestId('qKey1')).toHaveTextContent( | ||
JSON.stringify([['post', 'byId'], { input: { id: 1 }, type: 'query' }]), | ||
); | ||
expect(utils.getByTestId('qKey2')).toHaveTextContent( | ||
JSON.stringify([['post', 'byId'], { input: { id: 1 } }]), | ||
); | ||
}); | ||
}); | ||
|
||
test('on router', async () => { | ||
const { proxy, App } = ctx; | ||
|
||
function MyComponent() { | ||
const happy = proxy.post.getQueryKey(); | ||
|
||
// @ts-expect-error - router has no input | ||
const sad = proxy.post.getQueryKey('foo'); | ||
|
||
return ( | ||
<div> | ||
<pre data-testid="qKey">{JSON.stringify(happy)}</pre> | ||
</div> | ||
); | ||
} | ||
|
||
const utils = render( | ||
<App> | ||
<MyComponent /> | ||
</App>, | ||
); | ||
|
||
await waitFor(() => { | ||
expect(utils.getByTestId('qKey')).toHaveTextContent( | ||
JSON.stringify([['post']]), | ||
); | ||
}); | ||
}); | ||
|
||
test('forwarded to a real method', async () => { | ||
const { proxy, App } = ctx; | ||
|
||
function MyComponent() { | ||
proxy.post.all.useQuery(); | ||
|
||
const qKey = proxy.post.all.getQueryKey(undefined, 'query'); | ||
const isFetching = useIsFetching(qKey); | ||
|
||
return <div>{isFetching}</div>; | ||
} | ||
|
||
const utils = render( | ||
<App> | ||
<MyComponent /> | ||
</App>, | ||
); | ||
|
||
// should be fetching initially, and then not | ||
expect(utils.container).toHaveTextContent('1'); | ||
await waitFor(() => { | ||
expect(utils.container).toHaveTextContent('0'); | ||
}); | ||
}); | ||
|
||
test('outside of the react context', () => { | ||
const { proxy } = ctx; | ||
|
||
const all = proxy.post.all.getQueryKey(undefined, 'query'); | ||
const byId = proxy.post.byId.getQueryKey({ id: 1 }, 'query'); | ||
|
||
expect(all).toEqual([['post', 'all'], { type: 'query' }]); | ||
expect(byId).toEqual([ | ||
['post', 'byId'], | ||
{ input: { id: 1 }, type: 'query' }, | ||
]); | ||
}); | ||
}); |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -186,7 +186,7 @@ describe('invalidateQueries()', () => { | |
<button | ||
data-testid="invalidate-4-predicate" | ||
onClick={() => { | ||
utils.invalidate({ | ||
utils.invalidate(undefined, { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Isn't this changing the behaviour? 🤔 Looks like a breaking change? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I mean yea theoretically although it wasnt working before so its more of a fix? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Mentioned this here: https://discord.com/channels/867764511159091230/1055437438266392646/1055450208424706099 We always take the first arg as input no matter what the types said so any filters applied would actually end up being supressed |
||
predicate(opts) { | ||
const { queryKey } = opts; | ||
const [path, input] = queryKey; | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Breaking chaange?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See above