Skip to content

Commit c2de5bb

Browse files
authored
feat: bun support (#1970)
Adds `bun` test target
1 parent d93589a commit c2de5bb

5 files changed

Lines changed: 114 additions & 3 deletions

File tree

package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,7 @@
218218
"doc-check": "node src/index.js doc-check",
219219
"spell-check": "node src/index.js spell-check",
220220
"test:node": "node src/index.js test -t node --cov",
221+
"test:bun": "node src/index.js test -t bun",
221222
"test:deno": "node src/index.js test -t deno",
222223
"test:chrome": "node src/index.js test -t browser --cov",
223224
"test:chrome-webworker": "node src/index.js test -t webworker",
@@ -242,6 +243,7 @@
242243
"@types/mocha": "^10.0.0",
243244
"@types/node": "^24.12.2",
244245
"@typescript-eslint/parser": "^8.32.1",
246+
"bun": "^1.3.14",
245247
"buffer": "^6.0.3",
246248
"bytes": "^3.1.0",
247249
"c8": "^11.0.0",

src/cmds/test.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ export default {
6161
alias: 't',
6262
describe: 'In which target environment to execute the tests',
6363
array: true,
64-
choices: ['node', 'deno', 'browser', 'webworker', 'electron-main', 'electron-renderer', 'react-native-android', 'react-native-ios'],
64+
choices: ['node', 'bun', 'deno', 'browser', 'webworker', 'electron-main', 'electron-renderer', 'react-native-android', 'react-native-ios'],
6565
default: userConfig.test.target
6666
},
6767
watch: {

src/test/bun.js

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
import { createRequire } from 'node:module'
2+
import path from 'node:path'
3+
import { fileURLToPath } from 'node:url'
4+
import { execa } from 'execa'
5+
import fs from 'fs-extra'
6+
import merge from '../utils/merge-options.js'
7+
import { killIfProcessHangs } from './utils.js'
8+
9+
const require = createRequire(import.meta.url)
10+
const __dirname = path.dirname(fileURLToPath(import.meta.url))
11+
12+
const mochaPackageFile = require.resolve('mocha/package.json')
13+
const mochaManifest = fs.readJSONSync(mochaPackageFile)
14+
const mochaBinary = path.join(path.dirname(mochaPackageFile), mochaManifest.bin._mocha)
15+
16+
const bunPackageFile = require.resolve('bun/package.json')
17+
const bunManifest = fs.readJSONSync(bunPackageFile)
18+
const bunBinary = path.join(path.dirname(bunPackageFile), bunManifest.bin.bun)
19+
20+
/**
21+
* @typedef {import("execa").Options} ExecaOptions
22+
* @typedef {import('../types.js').TestOptions} TestOptions
23+
* @typedef {import('../types.js').GlobalOptions} GlobalOptions
24+
*/
25+
26+
/**
27+
* @param {TestOptions & GlobalOptions} argv
28+
* @param {ExecaOptions} execaOptions
29+
*/
30+
export default async function testBun (argv, execaOptions) {
31+
const progress = argv.progress ? ['--reporter=progress'] : []
32+
const files = argv.files.length > 0
33+
? argv.files
34+
: [
35+
'test/bun.*js',
36+
'test/node.*js',
37+
'test/**/*.spec.*js',
38+
'test/bun.*ts',
39+
'test/node.*ts',
40+
'test/**/*.spec.*ts'
41+
]
42+
43+
const args = [
44+
mochaBinary,
45+
...files,
46+
...progress,
47+
'--ui', 'bdd',
48+
'--require', 'source-map-support/register',
49+
`--timeout=${argv.timeout}`,
50+
'--color', 'true'
51+
]
52+
53+
if (argv.grep) {
54+
args.push(`--grep=${argv.grep}`)
55+
}
56+
57+
if (argv.watch) {
58+
args.push('--watch')
59+
}
60+
61+
if (argv.bail) {
62+
args.push('--bail')
63+
}
64+
65+
if (argv['--']) {
66+
args.push(...argv['--'])
67+
}
68+
69+
// before hook
70+
const before = await argv.fileConfig.test.before(argv)
71+
const beforeEnv = before && before.env ? before.env : {}
72+
73+
// run mocha
74+
const proc = execa(bunBinary, args,
75+
merge(
76+
{
77+
env: {
78+
AEGIR_RUNNER: 'bun',
79+
NODE_ENV: process.env.NODE_ENV || 'test',
80+
...beforeEnv
81+
},
82+
preferLocal: true,
83+
localDir: path.join(__dirname, '../..'),
84+
stdio: argv.cov ? 'pipe' : 'inherit',
85+
forceKillAfterDelay: 1_000
86+
},
87+
execaOptions
88+
)
89+
)
90+
91+
await killIfProcessHangs(proc, argv)
92+
93+
// after hook
94+
await argv.fileConfig.test.after(argv, before)
95+
}

src/test/index.js

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { execa } from 'execa'
22
import pMap from 'p-map'
33
import browser from './browser.js'
4+
import bun from './bun.js'
45
import deno from './deno.js'
56
import electron from './electron.js'
67
import node from './node.js'
@@ -11,6 +12,7 @@ import rn from './react-native.js'
1112
*/
1213
const NO_BUILD = [
1314
'node',
15+
'bun',
1416
'deno',
1517
'electron-main',
1618
'electron-renderer'
@@ -80,6 +82,18 @@ const TASKS = [
8082
*/
8183
enabled: (ctx) => ctx.target.includes('deno')
8284
},
85+
{
86+
title: 'test bun',
87+
/**
88+
* @param {TestOptions & GlobalOptions} opts
89+
* @param {ExecaOptions} execaOptions
90+
*/
91+
task: (opts, execaOptions) => bun({ ...opts, runner: 'bun' }, execaOptions),
92+
/**
93+
* @param {TestOptions & GlobalOptions} ctx
94+
*/
95+
enabled: (ctx) => ctx.target.includes('bun')
96+
},
8397
{
8498
title: 'test browser',
8599
/**

src/types.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -221,7 +221,7 @@ interface TestOptions {
221221
/**
222222
* In which target environment to execute the tests
223223
*/
224-
target: Array<'node' | 'deno' | 'browser' | 'webworker' | 'electron-main' | 'electron-renderer' | 'react-native-android' | 'react-native-ios'>
224+
target: Array<'node' | 'bun' | 'deno' | 'browser' | 'webworker' | 'electron-main' | 'electron-renderer' | 'react-native-android' | 'react-native-ios'>
225225
/**
226226
* Watch files for changes and rerun tests
227227
*/
@@ -257,7 +257,7 @@ interface TestOptions {
257257
/**
258258
* Runner environment
259259
*/
260-
runner: 'node' | 'deno' | 'browser' | 'webworker' | 'electron-main' | 'electron-renderer' | 'react-native-android' | 'react-native-ios'
260+
runner: 'node' | 'bun' | 'deno' | 'browser' | 'webworker' | 'electron-main' | 'electron-renderer' | 'react-native-android' | 'react-native-ios'
261261
/**
262262
* Browser options
263263
*/

0 commit comments

Comments
 (0)