diff --git a/docs/content/3.docs/4.advanced/5.testing.md b/docs/content/3.docs/4.advanced/5.testing.md
new file mode 100644
index 0000000000..8f7dcbf207
--- /dev/null
+++ b/docs/content/3.docs/4.advanced/5.testing.md
@@ -0,0 +1,190 @@
+# Testing
+
+::alert{icon=👉}
+Test utils are still in development and the API and behavior may change. Currently it's for module authors to preview but not yet ready for testing production apps.
+::
+
+In Nuxt 3, we have a rewritten version of `@nuxt/test-utils` available as `@nuxt/test-utils-edge`. We support [Vitest](https://github.com/vitest-dev/vitest) and [Jest](https://jestjs.io/) as the test runner.
+
+## Installation
+
+```bash
+yarn add --dev @nuxt/test-utils-edge vitest
+```
+
+## Setup
+
+In each describe block where you are taking advantage of the `@nuxt/test-utils` helper methods, you will need to set up the test context before beginning.
+
+```ts
+import { describe, test } from 'vitest'
+import { setup, $fetch } from '@nuxt/test-utils-edge'
+
+describe('My test', () => {
+ await setup({
+ // test context options
+ })
+
+ test('my test', () => {
+ // ...
+ })
+})
+```
+
+Behind the scenes, `setup` performs a number of tasks in `beforeAll`, `beforeEach`, `afterEach` and `afterAll` to setup the Nuxt test environment correctly.
+
+## Options
+
+### Nuxt configuration
+
+#### rootDir
+
+Path to a directory with a Nuxt app to be put under test.
+
+* Type: `string`
+* Default: `'.'`
+
+#### configFile
+
+Name of the configuration file.
+
+* Type: `string`
+* Default: `'nuxt.config'
+
+
+
+### Setup timings
+
+#### setupTimeout
+
+The amount of time (in milliseconds) to allow for `setupTest` to complete its work (which could include building or generating files for a Nuxt application, depending on the options that are passed).
+
+* Type: `number`
+* Default: `60000`
+
+### Features to enable
+
+#### server
+
+Whether to launch a server to respond to requests in the test suite.
+
+* Type: `boolean`
+* Default: `true`
+
+#### build
+
+Whether to run a separate build step.
+
+* Type: `boolean`
+* Default: `true` (`false` if `browser` or `server` is disabled)
+
+#### browser
+
+Under the hood, Nuxt test utils uses [`playwright`](https://playwright.dev/) to carry out browser testing. If this option is set, a browser will be launched and can be controlled in the subsequent test suite. (More info can be found [here](/api-reference/browser-testing).)
+
+* Type: `boolean`
+* Default: `false`
+
+#### browserOptions
+
+* Type: `object` with the following properties
+ * **type**: The type of browser to launch - either `chromium`, `firefox` or `webkit`
+ * **launch**: `object` of options that will be passed to playwright when launching the browser. See [full API reference](https://playwright.dev/#version=master&path=docs%2Fapi.md&q=browsertypelaunchoptions).
+
+#### runner
+
+Specify the runner for the test suite. Currently [Vitest](https://vitest.dev/) is recommend.
+
+* Type: `'vitest' | 'jest'`
+* Default: `'vitest'`
+
+## APIs
+
+### APIs for rendering testing
+
+#### $fetch(url)
+
+Get the HTML of a server-rendered page.
+
+```ts
+import { $fetch } from '@nuxt/test-utils'
+
+const html = await $fetch('/')
+```
+
+#### fetch(url)
+
+Get the response of a server-rendered page.
+
+```ts
+import { fetch } from '@nuxt/test-utils'
+
+const res = await fetch('/')
+const { body, headers } = res
+```
+
+#### url(path)
+
+Get the full URL for a given page (including the port the test server is running on.)
+
+```ts
+import { url } from '@nuxt/test-utils'
+
+const pageUrl = url('/page')
+// 'http://localhost:6840/page'
+```
+
+## Testing Modules
+
+### Fixture Setup
+
+To test the modules we create, we could setup some Nuxt apps as fixtures and test their behaviors. For example, we can create a simple Nuxt app under `./test/fixture` with the configuration like:
+
+```ts
+// nuxt.config.js
+import { defineNuxtConfig } from 'nuxt3'
+import MyModule from '../../src'
+
+export default defineNuxtConfig({
+ modules: [
+ MyModule
+ ]
+})
+```
+
+### Tests Setup
+
+We can create a test file and use the `rootDir` to test the fixture.
+
+```ts
+// basic.test.js
+import { describe, it } from 'vitest'
+import { setup, $fetch } from '@nuxt/test-utils-edge'
+
+describe('ssr', async () => {
+ await setup({
+ rootDir: fileURLToPath(new URL('./fixture', import.meta.url)),
+ })
+
+ it('renders the index page', async () => {
+ // Get response to a server-rendered page with `$fetch`.
+ const html = await $fetch('/')
+
+ expect(html).toContain('A Link')
+ })
+})
+```
+
+For more usage, please reference to our [tests for Nuxt 3 framework](https://github.com/nuxt/framework/blob/main/test/basic.test.ts).
+
+## Testing in a browser
+
+::alert{icon=🚧}
+We are working on it, stay tuned!
+::
diff --git a/packages/test-utils/src/context.ts b/packages/test-utils/src/context.ts
index 5f3faad37d..d203f865b4 100644
--- a/packages/test-utils/src/context.ts
+++ b/packages/test-utils/src/context.ts
@@ -12,8 +12,8 @@ export function createTestContext (options: Partial): TestContext {
setupTimeout: 60000,
dev: !!JSON.parse(process.env.NUXT_TEST_DEV || 'false'),
logLevel: 1,
- server: options.browser,
- build: options.browser || options.server,
+ server: true,
+ build: (options.browser !== false) || (options.server !== false),
nuxtConfig: {},
// TODO: auto detect based on process.env
runner: 'vitest',