Skip to content

Commit 608a14e

Browse files
authored
feat(e2e): silence server logs and allow customising log level (#1735)
1 parent 44edbea commit 608a14e

5 files changed

Lines changed: 87 additions & 2 deletions

File tree

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
export default defineEventHandler(() => {
2+
console.log('[test] server-log-marker')
3+
return { ok: true }
4+
})
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import { fileURLToPath } from 'node:url'
2+
import { $fetch, clearServerLogs, getServerLogs, setup } from '@nuxt/test-utils/e2e'
3+
import { describe, expect, it, vi } from 'vitest'
4+
5+
await setup({
6+
rootDir: fileURLToPath(new URL('../', import.meta.url)),
7+
})
8+
9+
describe('server log capture', () => {
10+
it('captures console.log output from a server route', async () => {
11+
clearServerLogs()
12+
await $fetch('/api/log-test')
13+
await vi.waitFor(() => {
14+
expect(getServerLogs().some(line => line.includes('[test] server-log-marker'))).toBe(true)
15+
})
16+
})
17+
18+
it('clearServerLogs empties the buffer', async () => {
19+
await $fetch('/api/log-test')
20+
await vi.waitFor(() => {
21+
expect(getServerLogs().length).toBeGreaterThan(0)
22+
})
23+
clearServerLogs()
24+
expect(getServerLogs()).toHaveLength(0)
25+
})
26+
})

src/e2e/context.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,13 @@ export function createTestContext(options: Partial<TestOptions>): TestContext {
2727
browserOptions: {
2828
type: 'chromium' as const,
2929
},
30+
captureServerLogs: true,
3031
} satisfies Partial<TestOptions>)
3132

33+
if (process.env.NUXT_TEST_LOG_LEVEL) {
34+
_options.logLevel = Number(process.env.NUXT_TEST_LOG_LEVEL)
35+
}
36+
3237
if (!_options.dev) {
3338
_options.env!.NODE_ENV ||= 'production'
3439
}
@@ -52,6 +57,7 @@ export function createTestContext(options: Partial<TestOptions>): TestContext {
5257
return setTestContext({
5358
options: _options as TestOptions,
5459
url: withTrailingSlash(_options.host),
60+
serverLogs: [],
5561
})
5662
}
5763

src/e2e/server.ts

Lines changed: 38 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,26 +10,36 @@ const globalFetch = globalThis.fetch || _fetch
1010

1111
export interface StartServerOptions {
1212
env?: Record<string, unknown>
13+
/**
14+
* Overrides the consola log level for the server subprocess.
15+
* Defaults to `TestOptions.logLevel` (which itself defaults to `1`).
16+
*/
17+
logLevel?: number
1318
}
1419

1520
export async function startServer(options: StartServerOptions = {}) {
1621
const ctx = useTestContext()
1722
await stopServer()
23+
ctx.serverLogs = []
1824
const host = '127.0.0.1'
1925
const port = ctx.options.port || (await getRandomPort(host))
2026
ctx.url = `http://${host}:${port}/`
27+
const capture = ctx.options.captureServerLogs !== false
28+
const stdio = capture ? 'pipe' : 'inherit'
29+
const logLevel = String(options.logLevel ?? ctx.options.logLevel)
2130
if (ctx.options.dev) {
2231
ctx.serverProcess = x('nuxi', ['_dev'], {
2332
throwOnError: true,
2433
nodeOptions: {
2534
cwd: ctx.nuxt!.options.rootDir,
26-
stdio: 'inherit',
35+
stdio,
2736
env: {
2837
...process.env,
2938
_PORT: String(port), // Used by internal _dev command
3039
PORT: String(port),
3140
HOST: host,
3241
NODE_ENV: 'development',
42+
CONSOLA_LEVEL: logLevel,
3343
...ctx.options.env,
3444
...options.env,
3545
},
@@ -49,12 +59,13 @@ export async function startServer(options: StartServerOptions = {}) {
4959
{
5060
throwOnError: true,
5161
nodeOptions: {
52-
stdio: 'inherit',
62+
stdio,
5363
env: {
5464
...process.env,
5565
PORT: String(port),
5666
HOST: host,
5767
NODE_ENV: 'test',
68+
CONSOLA_LEVEL: logLevel,
5869
...ctx.options.env,
5970
...options.env,
6071
},
@@ -63,6 +74,14 @@ export async function startServer(options: StartServerOptions = {}) {
6374
)
6475
}
6576

77+
if (capture) {
78+
;(async () => {
79+
for await (const line of ctx.serverProcess!) {
80+
ctx.serverLogs.push(line)
81+
}
82+
})().catch(() => {})
83+
}
84+
6685
await waitForServer({ host, port, dev: ctx.options.dev })
6786
}
6887

@@ -137,6 +156,23 @@ export async function stopServer() {
137156
}
138157
}
139158

159+
/**
160+
* Returns the lines captured from the server subprocess's stdout/stderr since
161+
* the last `startServer()` call (or `clearServerLogs()`).
162+
* Only populated when `captureServerLogs` is `true` (the default).
163+
*/
164+
export function getServerLogs(): string[] {
165+
return useTestContext().serverLogs
166+
}
167+
168+
/**
169+
* Clears the captured server log lines. Useful between requests when you want
170+
* to assert only on the logs produced by a specific operation.
171+
*/
172+
export function clearServerLogs(): void {
173+
useTestContext().serverLogs = []
174+
}
175+
140176
export function fetch(path: string, options?: RequestInit) {
141177
return globalFetch(url(path), options)
142178
}

src/e2e/types.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,14 @@ export interface TestOptions {
7777
*/
7878
port?: number
7979
env?: StartServerOptions['env']
80+
/**
81+
* Whether to capture server process output instead of inheriting stdio.
82+
* When `true` (default), server stdout/stderr is suppressed from the console
83+
* and accessible via `getServerLogs()`. Set to `false` to restore the old
84+
* inherit-stdio behaviour (useful when debugging a test locally).
85+
* @default true
86+
*/
87+
captureServerLogs?: boolean
8088
}
8189

8290
export interface TestContext {
@@ -86,6 +94,11 @@ export interface TestContext {
8694
url?: string
8795
serverProcess?: ReturnType<typeof exec>
8896
mockFn?: (...args: unknown[]) => unknown
97+
/**
98+
* Lines emitted to the server subprocess's stdout/stderr, in order.
99+
* Only populated when `options.captureServerLogs` is `true`.
100+
*/
101+
serverLogs: string[]
89102
/**
90103
* Functions to run on the vitest `afterAll` hook.
91104
* Useful for removing anything created during the test.

0 commit comments

Comments
 (0)