Skip to content

Commit

Permalink
feat: e2e sub-path export
Browse files Browse the repository at this point in the history
  • Loading branch information
johannschopplich committed Apr 12, 2024
1 parent 849a140 commit 27a69e7
Show file tree
Hide file tree
Showing 5 changed files with 75 additions and 40 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ A simple example could look like this:

```ts
import { describe, expect, it } from 'vitest'
import { $fetch } from 'nitro-test-utils'
import { $fetch } from 'nitro-test-utils/e2e'

describe('routes', () => {
it('responds successfully', async () => {
Expand Down
2 changes: 1 addition & 1 deletion build.config.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { defineBuildConfig } from 'unbuild'

export default defineBuildConfig({
entries: ['src/index', 'src/config', 'src/setup'],
entries: ['src/index', 'src/e2e', 'src/config', 'src/setup'],
externals: ['vite', 'vitest', 'vitest/config'],
clean: true,
declaration: true,
Expand Down
4 changes: 4 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,10 @@
"./config": {
"types": "./dist/config.d.mts",
"import": "./dist/config.mjs"
},
"./e2e": {
"types": "./dist/e2e.d.mts",
"import": "./dist/e2e.mjs"
}
},
"types": "./dist/index.d.ts",
Expand Down
61 changes: 61 additions & 0 deletions src/e2e.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import { joinURL } from 'ufo'
import { ofetch } from 'ofetch'
import type { FetchOptions, ResponseType } from 'ofetch'

export async function $fetch<T = any, R extends ResponseType = 'json'>(
url: string,
options?: FetchOptions<R>,
) {
const { inject } = await import('vitest')
const serverUrl = inject('nitroServerUrl')

const response = await ofetch.raw<T, R>(
joinURL(serverUrl, url),
mergeFetchOptions<R>(options, {
ignoreResponseError: true,
redirect: 'manual',
headers: {
accept: 'application/json',
},
}),
)

return {
body: response._data as T,
status: response.status,
headers: Object.fromEntries(response.headers.entries()),
}
}

export function mergeFetchOptions<R extends ResponseType = 'json'>(
input: FetchOptions<R> | undefined,
defaults: FetchOptions<R> | undefined,
): FetchOptions<R> {
const merged: FetchOptions<R> = {
...defaults,
...input,
}

// Merge params and query
if (defaults?.params && input?.params) {
merged.params = {
...defaults?.params,
...input?.params,
}
}
if (defaults?.query && input?.query) {
merged.query = {
...defaults?.query,
...input?.query,
}
}

// Merge headers
if (defaults?.headers && input?.headers) {
merged.headers = new Headers(defaults?.headers || {})
for (const [key, value] of new Headers(input?.headers || {}))
merged.headers.set(key, value)
}

return merged
}
46 changes: 8 additions & 38 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
import { resolve } from 'pathe'
import { joinURL } from 'ufo'
import { listen } from 'listhen'
import { ofetch } from 'ofetch'
import {
build,
copyPublicAssets,
Expand All @@ -11,9 +9,14 @@ import {
prerender,
} from 'nitropack'
import type { Listener } from 'listhen'
import type { FetchOptions, ResponseType } from 'ofetch'
import type { Nitro, NitroOptions } from 'nitropack'

declare module 'vitest' {
export interface ProvidedContext {
nitroServerUrl: string
}
}

export interface Context {
preset: NitroOptions['preset']
nitro?: Nitro
Expand All @@ -23,6 +26,8 @@ export interface Context {
isDev: boolean
}

export { $fetch } from './e2e'

export async function setupContext({
preset = 'node',
// eslint-disable-next-line node/prefer-global/process
Expand Down Expand Up @@ -88,38 +93,3 @@ export async function startServer(ctx: Context) {
await ctx.nitro.close()
}
}

export async function $fetch<T = any, R extends ResponseType = 'json'>(
url: string,
options?: FetchOptions<R>,
) {
const { inject } = await import('vitest')
const serverUrl = inject('nitroServerUrl')

const response = await ofetch.raw<T, R>(joinURL(serverUrl, url), {
...options,
ignoreResponseError: true,
redirect: 'manual',
headers: {
// Enforce Nitro error response in JSON when routes fail
accept: 'application/json',
...headersToObject(options?.headers),
},
})

return {
body: response._data as T,
status: response.status,
headers: Object.fromEntries(response.headers.entries()),
}
}

function headersToObject(headers?: HeadersInit) {
return Object.fromEntries(new Headers(headers).entries())
}

declare module 'vitest' {
export interface ProvidedContext {
nitroServerUrl: string
}
}

0 comments on commit 27a69e7

Please sign in to comment.