Skip to content

Commit 5d86d53

Browse files
NicolappsConvex, Inc.
authored andcommitted
docs: Reorganize the convex-test page (#43434)
GitOrigin-RevId: 3f7d3924195712c7606f6a03372460b99b2c3c6b
1 parent d9d3a41 commit 5d86d53

File tree

1 file changed

+104
-97
lines changed

1 file changed

+104
-97
lines changed

npm-packages/docs/docs/testing/convex-test.mdx

Lines changed: 104 additions & 97 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ You can see more examples in the
2424
[test suite](https://github.com/get-convex/convex-test/tree/main/convex) of the
2525
convex-test library.
2626

27-
## Get Started
27+
## Get started
2828

2929
<StepByStep>
3030

@@ -54,11 +54,71 @@ convex-test library.
5454

5555
<Step title="Configure Vitest">
5656

57-
Add <JSDialectFileName name="vitest.config.mts" /> file to configure the test
57+
Add <JSDialectFileName name="vitest.config.ts" /> file to configure the test
5858
environment to better match the Convex runtime, and to inline the test library
5959
for better dependency tracking.
6060

61-
```ts title="vitest.config.mts"
61+
<Details summary={<>If your Convex functions are in a directory other than <code>convex</code></>}>
62+
If your project has a
63+
[different name or location configured](/production/project-configuration.mdx#changing-the-convex-folder-name-or-location)
64+
for the `convex/` folder in `convex.json`, you need to call
65+
[`import.meta.glob`](https://vitejs.dev/guide/features#glob-import) and pass the
66+
result as the second argument to `convexTest`.
67+
68+
The argument to `import.meta.glob` must be a glob pattern matching all the files
69+
containing your Convex functions. The paths are relative to the test file in
70+
which `import.meta.glob` is called. It's best to do this in one place in your
71+
custom functions folder:
72+
73+
```ts title="src/convex/test.setup.ts"
74+
/// <reference types="vite/client" />
75+
export const modules = import.meta.glob(
76+
"./**/!(*.*.*)*.*s"
77+
);
78+
```
79+
80+
This example glob pattern includes all files with a single extension ending in
81+
`s` (like `js` or `ts`) in the `src/convex` folder and any of its children.
82+
83+
Use the result in your tests:
84+
85+
```ts title="src/convex/messages.test.ts"
86+
import { convexTest } from "convex-test";
87+
import { test } from "vitest";
88+
import schema from "./schema";
89+
import { modules } from "./test.setup";
90+
91+
test("some behavior", async () => {
92+
const t = convexTest(schema, modules);
93+
// use `t`...
94+
});
95+
```
96+
</Details>
97+
98+
<Details summary="Set up multiple test environments (e.g. Convex + frontend)">
99+
If you want to use Vitest to test both your Convex functions and your React
100+
frontend, you might want to use multiple Vitest environments depending on the
101+
test file location via
102+
[environmentMatchGlobs](https://vitest.dev/config/#environmentmatchglobs):
103+
104+
```ts title="vitest.config.ts"
105+
import { defineConfig } from "vitest/config";
106+
107+
export default defineConfig({
108+
test: {
109+
environmentMatchGlobs: [
110+
// all tests in convex/ will run in edge-runtime
111+
["convex/**", "edge-runtime"],
112+
// all other tests use jsdom
113+
["**", "jsdom"],
114+
],
115+
server: { deps: { inline: ["convex-test"] } },
116+
},
117+
});
118+
```
119+
</Details>
120+
121+
```ts title="vitest.config.ts"
62122
import { defineConfig } from "vitest/config";
63123

64124
export default defineConfig({
@@ -112,10 +172,12 @@ convex-test library.
112172

113173
</StepByStep>
114174

115-
If you're not familiar with Vitest or Jest read the
175+
If you're not familiar with Vitest, read the
116176
[Vitest Getting Started docs](https://vitest.dev/guide) first.
117177

118-
## `convexTest`
178+
## Using convex-test
179+
180+
### Initialize `convexTest`
119181

120182
The library exports a `convexTest` function which should be called at the start
121183
of each of your tests. The function returns an object which is by convention
@@ -142,7 +204,7 @@ validation and for correct typing of
142204

143205
If you don't have a schema, call `convexTest()` with no argument.
144206

145-
## Calling functions with `t.query`, `t.mutation` and `t.action`
207+
### Call functions
146208

147209
Your test can call public and internal Convex [functions](/functions.mdx) in
148210
your project:
@@ -163,7 +225,7 @@ test("functions", async () => {
163225
});
164226
```
165227

166-
## Setting up and inspecting data and storage with `t.run`
228+
### Modify data outside of functions
167229

168230
Sometimes you might want to directly [write](/database/writing-data.mdx) to the
169231
mock database or [file storage](/file-storage.mdx) from your test, without
@@ -185,7 +247,7 @@ test("functions", async () => {
185247
});
186248
```
187249

188-
## Testing HTTP actions with `t.fetch`
250+
### HTTP actions
189251

190252
Your test can call [HTTP actions](/functions/http-actions.mdx) registered by
191253
your router:
@@ -203,7 +265,7 @@ test("functions", async () => {
203265
Mocking the global `fetch` function doesn't affect `t.fetch`, but you can use
204266
`t.fetch` in a `fetch` mock to route to your HTTP actions.
205267

206-
## Testing scheduled functions
268+
### Scheduled functions
207269

208270
One advantage of using a mock implementation running purely in JavaScript is
209271
that you can control time in the Vitest test environment. To test
@@ -293,7 +355,7 @@ test("mutation scheduling action scheduling action", async () => {
293355
Check out more examples in
294356
[this file](https://github.com/get-convex/convex-test/blob/main/convex/scheduler.test.ts).
295357

296-
## Testing authentication with `t.withIdentity`
358+
### Authentication
297359

298360
To test functions which depend on the current [authenticated](/auth.mdx) user
299361
identity you can create a version of the `t` accessor with given
@@ -322,33 +384,9 @@ test("authenticated functions", async () => {
322384
});
323385
```
324386

325-
## Mocking `fetch` calls
326-
327-
You can use Vitest's
328-
[vi.stubGlobal](https://vitest.dev/guide/mocking.html#globals) method:
329-
330-
```ts title="convex/ai.test.ts"
331-
import { expect, test, vi } from "vitest";
332-
import { convexTest } from "../index";
333-
import { api } from "./_generated/api";
334-
import schema from "./schema";
335-
336-
test("ai", async () => {
337-
const t = convexTest(schema);
338-
339-
vi.stubGlobal(
340-
"fetch",
341-
vi.fn(async () => ({ text: async () => "I am the overlord" }) as Response),
342-
);
343-
344-
const reply = await t.action(api.messages.sendAIMessage, { prompt: "hello" });
345-
expect(reply).toEqual("I am the overlord");
387+
## Vitest tips
346388

347-
vi.unstubAllGlobals();
348-
});
349-
```
350-
351-
## Asserting results
389+
### Asserting results
352390

353391
See Vitest's [Expect](https://vitest.dev/api/expect.html) reference.
354392

@@ -375,7 +413,33 @@ test("messages validation", async () => {
375413
});
376414
```
377415

378-
## Measuring test coverage
416+
### Mocking `fetch` calls
417+
418+
You can use Vitest's
419+
[vi.stubGlobal](https://vitest.dev/guide/mocking.html#globals) method:
420+
421+
```ts title="convex/ai.test.ts"
422+
import { expect, test, vi } from "vitest";
423+
import { convexTest } from "../index";
424+
import { api } from "./_generated/api";
425+
import schema from "./schema";
426+
427+
test("ai", async () => {
428+
const t = convexTest(schema);
429+
430+
vi.stubGlobal(
431+
"fetch",
432+
vi.fn(async () => ({ text: async () => "I am the overlord" }) as Response),
433+
);
434+
435+
const reply = await t.action(api.messages.sendAIMessage, { prompt: "hello" });
436+
expect(reply).toEqual("I am the overlord");
437+
438+
vi.unstubAllGlobals();
439+
});
440+
```
441+
442+
### Measuring test coverage
379443

380444
You can get a printout of the code coverage provided by your tests. Besides
381445
answering the question "how much of my code is covered by tests" it is also
@@ -393,69 +457,12 @@ install a required dependency the first time you run it.
393457
/>
394458
</p>
395459

396-
## Debugging tests
460+
### Debugging tests
397461

398462
You can attach a debugger to the running tests. Read the Vitest
399-
[Debugging docs](https://vitest.dev/guide/debugging.html) and then
400-
use&#32;<CodeWithCopyButton text="npm run test:debug" />.
401-
402-
## Multiple environments
403-
404-
If you want to use Vitest to test both your Convex functions and your React
405-
frontend, you might want to use multiple Vitest environments depending on the
406-
test file location via
407-
[environmentMatchGlobs](https://vitest.dev/config/#environmentmatchglobs):
408-
409-
```ts title="vitest.config.mts"
410-
import { defineConfig } from "vitest/config";
411-
412-
export default defineConfig({
413-
test: {
414-
environmentMatchGlobs: [
415-
// all tests in convex/ will run in edge-runtime
416-
["convex/**", "edge-runtime"],
417-
// all other tests use jsdom
418-
["**", "jsdom"],
419-
],
420-
server: { deps: { inline: ["convex-test"] } },
421-
},
422-
});
423-
```
424-
425-
## Custom `convex/` folder name or location
426-
427-
If your project has a
428-
[different name or location configured](/production/project-configuration.mdx#changing-the-convex-folder-name-or-location)
429-
for the `convex/` folder in `convex.json`, you need to call
430-
[`import.meta.glob`](https://vitejs.dev/guide/features#glob-import) and pass the
431-
result as the second argument to `convexTest`.
432-
433-
The argument to `import.meta.glob` must be a glob pattern matching all the files
434-
containing your Convex functions. The paths are relative to the test file in
435-
which `import.meta.glob` is called. It's best to do this in one place in your
436-
custom functions folder:
437-
438-
```ts title="src/convex/test.setup.ts"
439-
/// <reference types="vite/client" />
440-
export const modules = import.meta.glob("./**/!(*.*.*)*.*s");
441-
```
442-
443-
This example glob pattern includes all files with a single extension ending in
444-
`s` (like `js` or `ts`) in the `src/convex` folder and any of its children.
445-
446-
Use the result in your tests:
463+
[Debugging docs](https://vitest.dev/guide/debugging.html) and then use
447464

448-
```ts title="src/convex/messages.test.ts"
449-
import { convexTest } from "convex-test";
450-
import { test } from "vitest";
451-
import schema from "./schema";
452-
import { modules } from "./test.setup";
453-
454-
test("some behavior", async () => {
455-
const t = convexTest(schema, modules);
456-
// use `t`...
457-
});
458-
```
465+
<CodeWithCopyButton text="npm run test:debug" />.
459466

460467
## Limitations
461468

0 commit comments

Comments
 (0)