Skip to content

Commit

Permalink
feat: add edge-runtime environment
Browse files Browse the repository at this point in the history
  • Loading branch information
promer94 committed Jun 30, 2022
1 parent 1bbe5b9 commit 965fade
Show file tree
Hide file tree
Showing 13 changed files with 169 additions and 28 deletions.
3 changes: 2 additions & 1 deletion docs/config/index.md
Expand Up @@ -153,13 +153,14 @@ export default defineConfig({

### environment

- **Type:** `'node' | 'jsdom' | 'happy-dom'`
- **Type:** `'node' | 'jsdom' | 'happy-dom' | 'edge-runtime'`
- **Default:** `'node'`

The environment that will be used for testing. The default environment in Vitest
is a Node.js environment. If you are building a web application, you can use
browser-like environment through either [`jsdom`](https://github.com/jsdom/jsdom)
or [`happy-dom`](https://github.com/capricorn86/happy-dom) instead.
If you are building edge functions, you can use [`edge-runtime`](https://edge-runtime.vercel.app/packages/vm) environment

By adding a `@vitest-environment` docblock or comment at the top of the file,
you can specify another environment to be used for all tests in that file:
Expand Down
7 changes: 7 additions & 0 deletions packages/vitest/LICENSE.md
Expand Up @@ -465,6 +465,13 @@ Repository: git://github.com/kpdecker/jsdiff.git
---------------------------------------

## eastasianwidth
License: MIT
By: Masaki Komagata
Repository: git://github.com/komagata/eastasianwidth.git

---------------------------------------

## emoji-regex
License: MIT
By: Mathias Bynens
Expand Down
1 change: 1 addition & 0 deletions packages/vitest/package.json
Expand Up @@ -94,6 +94,7 @@
},
"devDependencies": {
"@antfu/install-pkg": "^0.1.0",
"@edge-runtime/vm": "1.1.0-beta.10",
"@sinonjs/fake-timers": "^9.1.2",
"@types/diff": "^5.0.2",
"@types/jsdom": "^16.2.14",
Expand Down
24 changes: 24 additions & 0 deletions packages/vitest/src/integrations/env/edge-runtime.ts
@@ -0,0 +1,24 @@
import { importModule } from 'local-pkg'
import type { Environment } from '../../types'
import { populateGlobal } from './utils'

export default <Environment>({
name: 'edge-runtime',
async setup(global) {
const { EdgeVM } = await importModule('@edge-runtime/vm') as typeof import('@edge-runtime/vm')
const vm = new EdgeVM({
extend: (context) => {
context.global = context
context.Buffer = Buffer
return context
},
})
const { keys, originals } = populateGlobal(global, vm.context, { bindFunctions: true })
return {
teardown(global) {
keys.forEach(key => delete global[key])
originals.forEach((v, k) => global[k] = v)
},
}
},
})
10 changes: 10 additions & 0 deletions packages/vitest/src/integrations/env/index.ts
@@ -1,9 +1,19 @@
import node from './node'
import jsdom from './jsdom'
import happy from './happy-dom'
import edge from './edge-runtime'

export const environments = {
node,
jsdom,
'happy-dom': happy,
'edge-runtime': edge,
}

export const envs = Object.keys(environments)

export const envNpm = {
'jsdom': 'jsdom',
'happy-dom': 'happy-dom',
'edge-runtime': '@edge-runtime/vm',
}
4 changes: 3 additions & 1 deletion packages/vitest/src/node/cli-api.ts
@@ -1,4 +1,5 @@
import type { UserConfig as ViteUserConfig } from 'vite'
import { envNpm } from '../integrations/env'
import type { UserConfig } from '../types'
import { ensurePackageInstalled } from '../utils'
import { createVitest } from './create'
Expand Down Expand Up @@ -37,7 +38,8 @@ export async function startVitest(cliFilters: string[], options: CliOptions, vit
}

if (ctx.config.environment && ctx.config.environment !== 'node') {
if (!await ensurePackageInstalled(ctx.config.environment)) {
const packName = envNpm[ctx.config.environment]
if (!await ensurePackageInstalled(packName)) {
process.exitCode = 1
return false
}
Expand Down
3 changes: 1 addition & 2 deletions packages/vitest/src/runtime/entry.ts
@@ -1,6 +1,7 @@
import { promises as fs } from 'fs'
import type { BuiltinEnvironment, ResolvedConfig } from '../types'
import { getWorkerState, resetModules } from '../utils'
import { envs } from '../integrations/env'
import { setupGlobalEnv, withEnv } from './setup'
import { startTests } from './run'

Expand All @@ -9,8 +10,6 @@ export async function run(files: string[], config: ResolvedConfig): Promise<void

const workerState = getWorkerState()

const envs = ['node', 'jsdom', 'happy-dom']

// if calling from a worker, there will always be one file
// if calling with no-threads, this will be the whole suite
const filesWithEnv = await Promise.all(files.map(async (file) => {
Expand Down
4 changes: 2 additions & 2 deletions packages/vitest/src/types/config.ts
Expand Up @@ -8,7 +8,7 @@ import type { Reporter } from './reporter'
import type { SnapshotStateOptions } from './snapshot'
import type { Arrayable } from './general'

export type BuiltinEnvironment = 'node' | 'jsdom' | 'happy-dom'
export type BuiltinEnvironment = 'node' | 'jsdom' | 'happy-dom' | 'edge-runtime'

export type ApiConfig = Pick<CommonServerOptions, 'port' | 'strictPort' | 'host'>

Expand Down Expand Up @@ -98,7 +98,7 @@ export interface InlineConfig {
/**
* Running environment
*
* Supports 'node', 'jsdom', 'happy-dom'
* Supports 'node', 'jsdom', 'happy-dom', 'edge-runtime'
*
* @default 'node'
*/
Expand Down
96 changes: 74 additions & 22 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

14 changes: 14 additions & 0 deletions test/vite-edge/package.json
@@ -0,0 +1,14 @@
{
"name": "@vitest/test-edge-runtime",
"type": "module",
"private": true,
"scripts": {
"test": "vitest",
"coverage": "vitest run --coverage"
},
"devDependencies": {
"@edge-runtime/vm": "1.1.0-beta.10",
"@vitest/web-worker": "workspace:*",
"vitest": "workspace:*"
}
}
19 changes: 19 additions & 0 deletions test/vite-edge/test/edge.test.ts
@@ -0,0 +1,19 @@
/**
* @vitest-environment edge-runtime
*/
import { describe, expect, it } from 'vitest'
describe('edge runtime api', () => {
it('TextEncoder references the same global Uint8Array constructor', () => {
expect(new TextEncoder().encode('abc')).toBeInstanceOf(Uint8Array)
})

it('allows to run fetch', async () => {
const response = await fetch('https://vitest.dev')
expect(response.status).toEqual(200)
})

it('allows to run crypto', async () => {
const array = new Uint32Array(10)
expect(crypto.getRandomValues(array)).toHaveLength(array.length)
})
})
5 changes: 5 additions & 0 deletions test/vite-edge/test/node.test.ts
@@ -0,0 +1,5 @@
import { expect, test } from 'vitest'

test('node env should not have crypto', () => {
expect(global).not.toHaveProperty('crypto')
})

0 comments on commit 965fade

Please sign in to comment.