mirror of
https://github.com/oven-sh/bun
synced 2026-02-02 23:18:47 +00:00
Compare commits
4 Commits
codex/fix-
...
test-ecosy
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
57916d9426 | ||
|
|
cf9ebff4e3 | ||
|
|
2f1733b48f | ||
|
|
bfe979946e |
@@ -24,6 +24,8 @@ function* findTests(dir, query) {
|
||||
for (const entry of readdirSync(resolve(dir), { encoding: "utf-8", withFileTypes: true })) {
|
||||
const path = resolve(dir, entry.name);
|
||||
if (entry.isDirectory()) {
|
||||
// Do not run ecosystem tests here
|
||||
if (entry.name === "ecosystem") continue;
|
||||
yield* findTests(path, query);
|
||||
} else if (entry.name.includes(".test.")) {
|
||||
yield path;
|
||||
|
||||
81
test/ecosystem.ts
Normal file
81
test/ecosystem.ts
Normal file
@@ -0,0 +1,81 @@
|
||||
// Since ecosystem tests can be flaky, this file is responsible for running the tests
|
||||
// in the `ecosystem` directory and figuring out if things are broken or not.
|
||||
|
||||
import { spawnSync, Glob } from "bun";
|
||||
import { join } from "node:path";
|
||||
import { EOL } from "node:os";
|
||||
import { bunEnv, bunExe } from "harness";
|
||||
|
||||
const cwd = join(import.meta.dir, "ecosystem");
|
||||
const [...patterns] = process.argv.slice(2);
|
||||
const globs = patterns.length ? patterns.map(pattern => new Glob(pattern)) : [new Glob("**/*.test.ts")];
|
||||
const files = globs.flatMap(glob => [...glob.scanSync({ cwd })]);
|
||||
|
||||
if (!files.length) {
|
||||
throw "No tests found";
|
||||
}
|
||||
|
||||
for (const file of files) {
|
||||
runTest(file);
|
||||
}
|
||||
|
||||
function runTest(file: string) {
|
||||
const { exitCode, stderr } = spawnSync({
|
||||
cwd,
|
||||
cmd: [bunExe(), "test", file],
|
||||
env: bunEnv,
|
||||
stdout: "ignore",
|
||||
stderr: "pipe",
|
||||
});
|
||||
|
||||
const buffer: string[] = [];
|
||||
const names: Set<string> = new Set();
|
||||
const results: { type: string; name: string; logs: string }[] = [];
|
||||
|
||||
for (const line of stderr.toString().split(EOL)) {
|
||||
const text = stripAnsi(line);
|
||||
|
||||
let type: string | undefined;
|
||||
if (text.startsWith("(pass)") || text.startsWith("✓")) {
|
||||
type = "pass";
|
||||
} else if (text.startsWith("(fail)") || text.startsWith("✖")) {
|
||||
type = "fail";
|
||||
} else if (text.startsWith("(todo)") || text.startsWith("✏")) {
|
||||
type = "todo";
|
||||
} else if (text.startsWith("(skip)") || text.startsWith("⏩")) {
|
||||
type = "skip";
|
||||
} else if (!text.startsWith("minimalloc:")) {
|
||||
buffer.push(line);
|
||||
}
|
||||
|
||||
if (type) {
|
||||
const eol = text.lastIndexOf("[");
|
||||
const name = text.substring(7, eol ? eol - 1 : undefined);
|
||||
if (names.has(name)) {
|
||||
continue;
|
||||
}
|
||||
names.add(name);
|
||||
results.push({
|
||||
type,
|
||||
name,
|
||||
logs: buffer.join("\n"),
|
||||
});
|
||||
buffer.length = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (results.length === 1 && results[0].type === "todo") {
|
||||
return;
|
||||
}
|
||||
|
||||
let summary = "";
|
||||
for (const { type, name } of results.sort((a, b) => a.type.localeCompare(b.type))) {
|
||||
summary += `(${type}) ${name}\n`;
|
||||
}
|
||||
|
||||
console.log(file, summary);
|
||||
}
|
||||
|
||||
function stripAnsi(text: string): string {
|
||||
return text.replace(/\x1B\[\d+m/g, "");
|
||||
}
|
||||
1027
test/ecosystem/__snapshots__/harness.ts.snap
Normal file
1027
test/ecosystem/__snapshots__/harness.ts.snap
Normal file
File diff suppressed because it is too large
Load Diff
10
test/ecosystem/astro.test.ts
Normal file
10
test/ecosystem/astro.test.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
import { runTests } from "./harness";
|
||||
|
||||
runTests({
|
||||
package: "astro",
|
||||
repository: "https://github.com/withastro/astro",
|
||||
ref: "astro@3.6.3",
|
||||
paths: ["packages/astro/test/**/*.spec.js"],
|
||||
runner: "jest",
|
||||
todo: true, // error: workspace dependency "astro-benchmark" not found
|
||||
});
|
||||
10
test/ecosystem/body-parser.test.ts
Normal file
10
test/ecosystem/body-parser.test.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
import { runTests } from "./harness";
|
||||
|
||||
runTests({
|
||||
package: "body-parser",
|
||||
repository: "https://github.com/expressjs/body-parser",
|
||||
ref: "1.20.2",
|
||||
paths: ["test/*.js"],
|
||||
runner: "mocha",
|
||||
todo: true, // crashes
|
||||
});
|
||||
9
test/ecosystem/chalk.test.ts
Normal file
9
test/ecosystem/chalk.test.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
import { runTests } from "./harness";
|
||||
|
||||
runTests({
|
||||
package: "chalk",
|
||||
repository: "https://github.com/chalk/chalk",
|
||||
ref: "v5.3.0",
|
||||
paths: ["test/*.js"],
|
||||
runner: "ava",
|
||||
});
|
||||
9
test/ecosystem/classnames.test.ts
Normal file
9
test/ecosystem/classnames.test.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
import { runTests } from "./harness";
|
||||
|
||||
runTests({
|
||||
package: "classnames",
|
||||
repository: "https://github.com/JedWatson/classnames",
|
||||
ref: "v2.3.2",
|
||||
paths: ["tests/*.js"],
|
||||
runner: "mocha",
|
||||
});
|
||||
13
test/ecosystem/clickhouse.test.ts
Normal file
13
test/ecosystem/clickhouse.test.ts
Normal file
@@ -0,0 +1,13 @@
|
||||
import { runTests } from "./harness";
|
||||
|
||||
runTests({
|
||||
package: "clickhouse-js",
|
||||
repository: "https://github.com/ClickHouse/clickhouse-js",
|
||||
ref: "0.2.6",
|
||||
paths: ["packages/client-node/__tests__/unit/**/*.test.ts"],
|
||||
runner: "jest",
|
||||
todo: true,
|
||||
// Cannot find module "@test/utils"
|
||||
// expect.toThrowError is not a function
|
||||
// TypeError: ES Modules cannot be stubbed (?)
|
||||
});
|
||||
10
test/ecosystem/colors.test.ts
Normal file
10
test/ecosystem/colors.test.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
import { runTests } from "./harness";
|
||||
|
||||
runTests({
|
||||
package: "colors",
|
||||
repository: "https://github.com/Marak/colors.js",
|
||||
ref: "074a0f8ed0c31c35d13d28632bd8a049ff136fb6", // Jan 7 2022
|
||||
paths: ["tests/*.js"],
|
||||
runner: "script",
|
||||
todo: true, // lockfile is too old
|
||||
});
|
||||
10
test/ecosystem/commander.test.ts
Normal file
10
test/ecosystem/commander.test.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
import { runTests } from "./harness";
|
||||
|
||||
runTests({
|
||||
package: "commander",
|
||||
repository: "https://github.com/tj/commander.js",
|
||||
ref: "v11.1.0",
|
||||
paths: ["tests/*.test.js"],
|
||||
runner: "jest",
|
||||
todo: true, // ASSERTION FAILED: !m_errorInfoMaterialized
|
||||
});
|
||||
10
test/ecosystem/cookie-parser.test.ts
Normal file
10
test/ecosystem/cookie-parser.test.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
import { runTests } from "./harness";
|
||||
|
||||
runTests({
|
||||
package: "cookie-parser",
|
||||
repository: "https://github.com/expressjs/cookie-parser",
|
||||
ref: "1.4.6",
|
||||
paths: ["test/*.js"],
|
||||
runner: "mocha",
|
||||
todo: true, // times out
|
||||
});
|
||||
9
test/ecosystem/elysia.test.ts
Normal file
9
test/ecosystem/elysia.test.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
import { runTests } from "./harness";
|
||||
|
||||
runTests({
|
||||
package: "elysia",
|
||||
repository: "https://github.com/elysiajs/elysia",
|
||||
ref: "0.7",
|
||||
paths: ["test/**/*.ts"],
|
||||
runner: "jest",
|
||||
});
|
||||
10
test/ecosystem/express.test.ts
Normal file
10
test/ecosystem/express.test.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
import { runTests } from "./harness";
|
||||
|
||||
runTests({
|
||||
package: "express",
|
||||
repository: "https://github.com/expressjs/express",
|
||||
ref: "2a00da2067b7017f769c9100205a2a5f267a884b", // June 4 2023
|
||||
paths: ["test/acceptance/*.js"],
|
||||
runner: "mocha",
|
||||
todo: true, // Too many errors
|
||||
});
|
||||
12
test/ecosystem/glob.test.ts
Normal file
12
test/ecosystem/glob.test.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
import { runTests } from "./harness";
|
||||
|
||||
runTests({
|
||||
package: "glob",
|
||||
repository: "https://github.com/isaacs/node-glob",
|
||||
ref: "v10.3.10",
|
||||
paths: ["test/*.ts"],
|
||||
runner: "tap",
|
||||
todo: true,
|
||||
// t.pipe is not a function (test runner)
|
||||
// expect() must be called in a test
|
||||
});
|
||||
12
test/ecosystem/got.test.ts
Normal file
12
test/ecosystem/got.test.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
import { runTests } from "./harness";
|
||||
|
||||
runTests({
|
||||
package: "got",
|
||||
repository: "https://github.com/sindresorhus/got",
|
||||
ref: "v14.0.0",
|
||||
paths: ["test/*.ts"],
|
||||
runner: "ava",
|
||||
todo: true,
|
||||
// need to implement more of ava runner
|
||||
// also crashes
|
||||
});
|
||||
100
test/ecosystem/harness.ts
Normal file
100
test/ecosystem/harness.ts
Normal file
@@ -0,0 +1,100 @@
|
||||
import { spawnSync, Glob } from "bun";
|
||||
import { join, resolve } from "node:path";
|
||||
import { mkdtempSync, symlinkSync } from "node:fs";
|
||||
import { tmpdir } from "node:os";
|
||||
import { describe, test } from "bun:test";
|
||||
import { bunEnv, bunExe } from "harness";
|
||||
|
||||
export type TestOptions = {
|
||||
package: string;
|
||||
repository: string;
|
||||
ref: string | null;
|
||||
paths: string[];
|
||||
runner: "jest" | "vitest" | "ava" | "mocha" | "qunit" | "tap" | "utest" | "uvu" | "script";
|
||||
skip?: boolean | string;
|
||||
todo?: boolean | string;
|
||||
cmds?: string[][];
|
||||
};
|
||||
|
||||
export function runTests({ package: name, repository, ref, paths, runner, skip, todo, cmds }: TestOptions): void {
|
||||
if (todo) {
|
||||
test.todo(name, () => {});
|
||||
return;
|
||||
} else if (skip) {
|
||||
test.skip(name, () => {});
|
||||
return;
|
||||
}
|
||||
|
||||
describe(name, () => {
|
||||
const run = import(join(import.meta.dir, "runner", `${runner}.js`));
|
||||
const tmp = mkdtempSync(join(tmpdir(), `${name.replace(/\//g, "-")}-`));
|
||||
const cwd = join(tmp, "node_modules", name);
|
||||
|
||||
{
|
||||
const target = ref ? `${repository}#${ref}` : repository;
|
||||
const { exitCode } = spawnSync({
|
||||
cwd: tmp,
|
||||
cmd: [bunExe(), "install", target],
|
||||
env: bunEnv,
|
||||
stdout: "pipe",
|
||||
stderr: "pipe",
|
||||
});
|
||||
|
||||
if (exitCode !== 0) {
|
||||
throw `bun install ${target}`;
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
const { exitCode } = spawnSync({
|
||||
cwd,
|
||||
cmd: [bunExe(), "install"],
|
||||
env: bunEnv,
|
||||
stdout: "inherit",
|
||||
stderr: "inherit",
|
||||
});
|
||||
|
||||
if (exitCode !== 0) {
|
||||
throw "bun install";
|
||||
}
|
||||
}
|
||||
|
||||
for (const cmd of cmds ?? []) {
|
||||
if (cmd[0] === "bun") {
|
||||
cmd[0] = bunExe();
|
||||
}
|
||||
const { exitCode } = spawnSync({
|
||||
cwd,
|
||||
cmd,
|
||||
env: bunEnv,
|
||||
stdout: "inherit",
|
||||
stderr: "inherit",
|
||||
});
|
||||
|
||||
if (exitCode !== 0) {
|
||||
throw cmd.join(" ");
|
||||
}
|
||||
}
|
||||
|
||||
for (const path of paths) {
|
||||
const tests = [...new Glob(path).scanSync({ cwd })];
|
||||
|
||||
if (!tests.length) {
|
||||
throw `No tests found: ${path}`;
|
||||
}
|
||||
|
||||
for (const test of tests) {
|
||||
const absolutePath = resolve(cwd, test);
|
||||
|
||||
if (!test.includes(".test.") && !test.includes(".spec.")) {
|
||||
symlinkSync(absolutePath, absolutePath.replace(/\.(c|m)?(j|t)sx?$/, ".test.ts"));
|
||||
}
|
||||
|
||||
describe(test, async () => {
|
||||
const runner = await run;
|
||||
await runner.run(absolutePath);
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
13
test/ecosystem/hono.test.ts
Normal file
13
test/ecosystem/hono.test.ts
Normal file
@@ -0,0 +1,13 @@
|
||||
import { runTests } from "./harness";
|
||||
|
||||
runTests({
|
||||
package: "hono",
|
||||
repository: "https://github.com/honojs/hono",
|
||||
ref: "v3.10.3",
|
||||
paths: ["src/**/*.test.ts"],
|
||||
runner: "jest",
|
||||
todo: true,
|
||||
// expectTypeOf is not a function
|
||||
// toThrowError is undefined
|
||||
// Can't find variable: caches
|
||||
});
|
||||
10
test/ecosystem/inquirer.test.ts
Normal file
10
test/ecosystem/inquirer.test.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
import { runTests } from "./harness";
|
||||
|
||||
runTests({
|
||||
package: "inquirer",
|
||||
repository: "https://github.com/SBoudrias/Inquirer.js",
|
||||
ref: "@inquirer/core@5.1.0",
|
||||
paths: ["packages/**/*.test.mts"],
|
||||
runner: "vitest",
|
||||
todo: true, // hangs
|
||||
});
|
||||
10
test/ecosystem/lodash.test.ts
Normal file
10
test/ecosystem/lodash.test.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
import { runTests } from "./harness";
|
||||
|
||||
runTests({
|
||||
package: "lodash",
|
||||
repository: "https://github.com/lodash/lodash",
|
||||
ref: "aa18212085c52fc106d075319637b8729e0f179f", // Sep 27 2023
|
||||
paths: ["test/*.spec.js"],
|
||||
runner: "jest",
|
||||
todo: true,
|
||||
});
|
||||
10
test/ecosystem/moment.test.ts
Normal file
10
test/ecosystem/moment.test.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
import { runTests } from "./harness";
|
||||
|
||||
runTests({
|
||||
package: "moment",
|
||||
repository: "https://github.com/moment/moment",
|
||||
ref: "v2.29.4",
|
||||
paths: ["src/test/moment/*.js"],
|
||||
runner: "qunit",
|
||||
todo: true, // Implement `qunit` runner
|
||||
});
|
||||
13
test/ecosystem/mongodb.test.ts
Normal file
13
test/ecosystem/mongodb.test.ts
Normal file
@@ -0,0 +1,13 @@
|
||||
import { runTests } from "./harness";
|
||||
|
||||
runTests({
|
||||
package: "mongodb",
|
||||
repository: "https://github.com/mongodb/node-mongodb-native",
|
||||
ref: "v6.3.0",
|
||||
paths: ["test/unit/**/*.test.ts"],
|
||||
runner: "mocha",
|
||||
todo: true,
|
||||
// SyntaxError: export 'Document' not found in 'bson' (module/import issue?)
|
||||
// ReferenceError: Can't find variable: context (test runner issue)
|
||||
// error: /bin/sh: ./node_modules/.bin/ts-node: No such file or directory (bun install issue?)
|
||||
});
|
||||
10
test/ecosystem/mysql.test.ts
Normal file
10
test/ecosystem/mysql.test.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
import { runTests } from "./harness";
|
||||
|
||||
runTests({
|
||||
package: "mysql",
|
||||
repository: "https://github.com/mysqljs/mysql",
|
||||
ref: "dc9c152a87ec51a1f647447268917243d2eab1fd", // Mar 13 2022
|
||||
paths: ["test/unit/**/*.js"],
|
||||
runner: "utest",
|
||||
todo: true, // TypeError: Module is not a function (near '...test...')
|
||||
});
|
||||
10
test/ecosystem/mysql2.test.ts
Normal file
10
test/ecosystem/mysql2.test.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
import { runTests } from "./harness";
|
||||
|
||||
runTests({
|
||||
package: "mysql2",
|
||||
repository: "https://github.com/sidorares/node-mysql2",
|
||||
ref: "v3.6.5",
|
||||
paths: ["test/unit/**/*.js"],
|
||||
runner: "utest",
|
||||
todo: true, // TypeError: Module is not a function (near '...test...')
|
||||
});
|
||||
10
test/ecosystem/next.test.ts
Normal file
10
test/ecosystem/next.test.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
import { runTests } from "./harness";
|
||||
|
||||
runTests({
|
||||
package: "nextjs-project",
|
||||
repository: "https://github.com/vercel/next.js",
|
||||
ref: "v14.0.3",
|
||||
paths: ["test/unit/**/*.test.ts", "test/e2e/**/*.test.ts"],
|
||||
runner: "jest",
|
||||
todo: true, // fatal: not in a git directory
|
||||
});
|
||||
10
test/ecosystem/nuxt.test.ts
Normal file
10
test/ecosystem/nuxt.test.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
import { runTests } from "./harness";
|
||||
|
||||
runTests({
|
||||
package: "nuxt-framework",
|
||||
repository: "https://github.com/nuxt/nuxt",
|
||||
ref: "v3.8.2",
|
||||
paths: ["test/**/*.test.ts"],
|
||||
runner: "jest",
|
||||
todo: true, // error: workspace dependency "@nuxt/webpack-builder" not found
|
||||
});
|
||||
10
test/ecosystem/pg.test.ts
Normal file
10
test/ecosystem/pg.test.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
import { runTests } from "./harness";
|
||||
|
||||
runTests({
|
||||
package: "node-postgres",
|
||||
repository: "https://github.com/brianc/node-postgres",
|
||||
ref: "pg@8.11.3",
|
||||
paths: ["packages/pg/test/unit/connection-parameters/*.js"],
|
||||
runner: "mocha",
|
||||
todo: true, // https://github.com/oven-sh/bun/issues/7360
|
||||
});
|
||||
10
test/ecosystem/postgres.test.ts
Normal file
10
test/ecosystem/postgres.test.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
import { runTests } from "./harness";
|
||||
|
||||
runTests({
|
||||
package: "postgres",
|
||||
repository: "https://github.com/porsager/postgres",
|
||||
ref: "v3.4.3",
|
||||
paths: ["tests/index.js"],
|
||||
runner: "mocha",
|
||||
todo: true,
|
||||
});
|
||||
9
test/ecosystem/prettier.test.ts
Normal file
9
test/ecosystem/prettier.test.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
import { runTests } from "./harness";
|
||||
|
||||
runTests({
|
||||
package: "prettier",
|
||||
repository: "https://github.com/prettier/prettier",
|
||||
ref: "3.1.0",
|
||||
paths: ["tests/unit/*.js"],
|
||||
runner: "jest",
|
||||
});
|
||||
10
test/ecosystem/redis.test.ts
Normal file
10
test/ecosystem/redis.test.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
import { runTests } from "./harness";
|
||||
|
||||
runTests({
|
||||
package: "redis",
|
||||
repository: "https://github.com/redis/node-redis",
|
||||
ref: "redis@4.6.11",
|
||||
paths: ["packages/client/lib/**/*.spec.ts"],
|
||||
runner: "mocha",
|
||||
todo: true, // https://github.com/oven-sh/bun/issues/7360
|
||||
});
|
||||
10
test/ecosystem/rimraf.test.ts
Normal file
10
test/ecosystem/rimraf.test.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
import { runTests } from "./harness";
|
||||
|
||||
runTests({
|
||||
package: "rimraf",
|
||||
repository: "https://github.com/isaacs/rimraf",
|
||||
ref: "v5.0.5",
|
||||
paths: ["test/**/*.ts"],
|
||||
runner: "tap",
|
||||
todo: true, // Too many errors
|
||||
});
|
||||
49
test/ecosystem/runner/ava.js
Normal file
49
test/ecosystem/runner/ava.js
Normal file
@@ -0,0 +1,49 @@
|
||||
export async function run(path) {
|
||||
const jest = Bun.jest(path);
|
||||
const { expect, mock } = jest;
|
||||
|
||||
// https://github.com/avajs/ava/blob/main/docs/03-assertions.md
|
||||
const t = {
|
||||
is(actual, expected) {
|
||||
expect(actual).toBe(expected);
|
||||
},
|
||||
not(actual, expected) {
|
||||
expect(actual).not.toBe(expected);
|
||||
},
|
||||
deepEqual(actual, expected) {
|
||||
expect(actual).toEqual(expected);
|
||||
},
|
||||
throws(fn, expected) {
|
||||
if (expected.message) {
|
||||
expect(fn).toThrow(expected.message);
|
||||
} else {
|
||||
expect(fn).toThrow(expected);
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
for (const fn of Object.values(t)) {
|
||||
hideFromStack(fn);
|
||||
}
|
||||
|
||||
mock.module("ava", () => {
|
||||
return {
|
||||
default: (title, fn) => {
|
||||
jest.test(title, async () => {
|
||||
await fn(t);
|
||||
});
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
await import(path);
|
||||
}
|
||||
|
||||
function hideFromStack(fn) {
|
||||
Object.defineProperty(fn, "name", {
|
||||
value: "::bunternal::",
|
||||
configurable: true,
|
||||
enumerable: true,
|
||||
writable: true,
|
||||
});
|
||||
}
|
||||
6
test/ecosystem/runner/jest.js
Normal file
6
test/ecosystem/runner/jest.js
Normal file
@@ -0,0 +1,6 @@
|
||||
export async function run(path) {
|
||||
for (const [key, value] of Object.entries(Bun.jest(path))) {
|
||||
globalThis[key] = value;
|
||||
}
|
||||
await import(path);
|
||||
}
|
||||
9
test/ecosystem/runner/mocha.js
Normal file
9
test/ecosystem/runner/mocha.js
Normal file
@@ -0,0 +1,9 @@
|
||||
export async function run(path) {
|
||||
const jest = Bun.jest(path);
|
||||
for (const [key, value] of Object.entries(jest)) {
|
||||
globalThis[key] = value;
|
||||
}
|
||||
globalThis.before = jest.beforeAll;
|
||||
globalThis.after = jest.afterAll;
|
||||
await import(path);
|
||||
}
|
||||
124
test/ecosystem/runner/qunit.js
Normal file
124
test/ecosystem/runner/qunit.js
Normal file
@@ -0,0 +1,124 @@
|
||||
export async function run(path) {
|
||||
const jest = Bun.jest(path);
|
||||
const { expect, mock } = jest;
|
||||
|
||||
// https://api.qunitjs.com/config/
|
||||
const config = {};
|
||||
|
||||
// https://api.qunitjs.com/assert/
|
||||
const assert = {
|
||||
async(count) {
|
||||
throw new Error("Not implemented: async");
|
||||
},
|
||||
deepEqual(actual, expected) {
|
||||
expect(actual).toStrictEqual(expected);
|
||||
},
|
||||
equal(actual, expected) {
|
||||
expect(actual).toEqual(expected);
|
||||
},
|
||||
expect(amount) {
|
||||
// TODO
|
||||
},
|
||||
false(actual) {
|
||||
expect(actual).toBeFalse();
|
||||
},
|
||||
notDeepEqual(actual, expected) {
|
||||
expect(actual).not.toStrictEqual(expected);
|
||||
},
|
||||
notEqual(actual, expected) {
|
||||
expect(actual).not.toEqual(expected);
|
||||
},
|
||||
notOk(actual) {
|
||||
expect(actual).toBeFalsy();
|
||||
},
|
||||
notPropContains(actual, expected) {
|
||||
throw new Error("Not implemented: notPropContains");
|
||||
},
|
||||
notPropEqual(actual, expected) {
|
||||
throw new Error("Not implemented: notPropEqual");
|
||||
},
|
||||
notStrictEqual(actual, expected) {
|
||||
expect(actual).not.toStrictEqual(expected);
|
||||
},
|
||||
ok(actual) {
|
||||
expect(actual).toBeTruthy();
|
||||
},
|
||||
propContains(actual, expected) {
|
||||
throw new Error("Not implemented: propContains");
|
||||
},
|
||||
propEqual(actual, expected) {
|
||||
throw new Error("Not implemented: propEqual");
|
||||
},
|
||||
pushResult(resultInfo) {
|
||||
throw new Error("Not implemented: pushResult");
|
||||
},
|
||||
rejects(actual, expected) {
|
||||
expect(actual).rejects.toThrow(expected);
|
||||
},
|
||||
step(label) {
|
||||
throw new Error("Not implemented: step");
|
||||
},
|
||||
strictEqual(actual, expected) {
|
||||
expect(actual).toStrictEqual(expected);
|
||||
},
|
||||
throws(actual, expected) {
|
||||
expect(actual).toThrow(expected);
|
||||
},
|
||||
raises(actual, expected) {
|
||||
expect(actual).toThrow(expected);
|
||||
},
|
||||
timeout() {
|
||||
// TODO
|
||||
},
|
||||
true(actual) {
|
||||
expect(actual).toBeTrue();
|
||||
},
|
||||
verifySteps(steps) {
|
||||
throw new Error("Not implemented: verifySteps");
|
||||
},
|
||||
};
|
||||
|
||||
let module = "";
|
||||
const QUnit = {
|
||||
config,
|
||||
test(name, fn) {
|
||||
if (module) {
|
||||
name = `${module} > ${name}`;
|
||||
}
|
||||
jest.test(name, () => fn(assert));
|
||||
},
|
||||
module(name, fn) {
|
||||
if (fn) {
|
||||
module = "";
|
||||
jest.describe(name, () => fn(assert));
|
||||
} else {
|
||||
module = name;
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
for (const fn of Object.values(QUnit)) {
|
||||
hideFromStack(fn);
|
||||
}
|
||||
|
||||
globalThis.QUnit = QUnit;
|
||||
mock.module("qunit", () => {
|
||||
const module = {
|
||||
default: QUnit,
|
||||
...QUnit,
|
||||
};
|
||||
|
||||
return module;
|
||||
});
|
||||
|
||||
await import(path);
|
||||
}
|
||||
|
||||
function hideFromStack(fn) {
|
||||
Object.defineProperty(fn, "name", {
|
||||
value: "::bunternal::",
|
||||
configurable: true,
|
||||
enumerable: true,
|
||||
writable: true,
|
||||
});
|
||||
}
|
||||
9
test/ecosystem/runner/script.js
Normal file
9
test/ecosystem/runner/script.js
Normal file
@@ -0,0 +1,9 @@
|
||||
import { basename } from "node:path";
|
||||
|
||||
export async function run(path) {
|
||||
const { test, expect } = Bun.jest(path);
|
||||
|
||||
test(basename(path), async () => {
|
||||
expect(import(path)).resolves.not.toThrow();
|
||||
});
|
||||
}
|
||||
282
test/ecosystem/runner/tap.js
Normal file
282
test/ecosystem/runner/tap.js
Normal file
@@ -0,0 +1,282 @@
|
||||
import { spawnSync } from "bun";
|
||||
import { tmpdir } from "node:os";
|
||||
import { join } from "node:path";
|
||||
import { linkSync, mkdirSync, mkdtempSync, symlinkSync, writeFileSync } from "node:fs";
|
||||
|
||||
export async function run(path) {
|
||||
const jest = Bun.jest(path);
|
||||
const { expect, mock } = jest;
|
||||
|
||||
// https://node-tap.org/api/
|
||||
// https://github.com/tapjs/tapjs/blob/511019b2ac0fa014370154c3a341a0e632f50b19/src/asserts/src/index.ts
|
||||
const t = {
|
||||
plan(count) {
|
||||
// expect.assertions(count);
|
||||
},
|
||||
equal(actual, expected) {
|
||||
expect(actual).toBe(expected);
|
||||
},
|
||||
notEqual(actual, expected) {
|
||||
expect(actual).not.toBe(expected);
|
||||
},
|
||||
deepEqual(actual, expected) {
|
||||
expect(actual).toEqual(expected);
|
||||
},
|
||||
notDeepEqual(actual, expected) {
|
||||
expect(actual).not.toEqual(expected);
|
||||
},
|
||||
fail(message) {
|
||||
expect.fail(message);
|
||||
},
|
||||
pass(message) {
|
||||
// ...
|
||||
},
|
||||
// https://github.com/tapjs/tapjs/blob/511019b2ac0fa014370154c3a341a0e632f50b19/src/asserts/src/index.ts
|
||||
ok(value) {
|
||||
expect(value).toBeTruthy();
|
||||
},
|
||||
notOk(value) {
|
||||
expect(value).toBeFalsy();
|
||||
},
|
||||
equal(actual, expected) {
|
||||
expect(actual).toBe(expected);
|
||||
},
|
||||
not(actual, expected) {
|
||||
expect(actual).not.toBe(expected);
|
||||
},
|
||||
type(actual, expected) {
|
||||
if (actual in ["undefined", "boolean", "number", "string", "symbol", "function", "object"]) {
|
||||
expect(typeof actual).toBe(expected);
|
||||
} else {
|
||||
expect(actual).toBeInstanceOf(expected);
|
||||
}
|
||||
},
|
||||
same(actual, expected) {
|
||||
expect(actual).toEqual(expected);
|
||||
},
|
||||
notSame(actual, expected) {
|
||||
expect(actual).not.toEqual(expected);
|
||||
},
|
||||
strictSame(actual, expected) {
|
||||
expect(actual).toStrictEqual(expected);
|
||||
},
|
||||
strictNotSame(actual, expected) {
|
||||
expect(actual).not.toStrictEqual(expected);
|
||||
},
|
||||
has(actual, expected) {
|
||||
throw new Error("Not implemented: has");
|
||||
},
|
||||
notHas(actual, expected) {
|
||||
throw new Error("Not implemented: notHas");
|
||||
},
|
||||
hasStrict(actual, expected) {
|
||||
throw new Error("Not implemented: hasStrict");
|
||||
},
|
||||
notHasStrict(actual, expected) {
|
||||
throw new Error("Not implemented: notHasStrict");
|
||||
},
|
||||
match(actual, expected) {
|
||||
if (typeof expected === "string" || expected instanceof RegExp) {
|
||||
expect(actual).toMatch(expected);
|
||||
} else {
|
||||
expect(actual).toMatchObject(expected);
|
||||
}
|
||||
},
|
||||
notMatch(actual, expected) {
|
||||
if (typeof expected === "string" || expected instanceof RegExp) {
|
||||
expect(actual).not.toMatch(expected);
|
||||
} else {
|
||||
expect(actual).not.toMatchObject(expected);
|
||||
}
|
||||
},
|
||||
matchOnly(actual, expected) {
|
||||
throw new Error("Not implemented: matchOnly");
|
||||
},
|
||||
notMatchOnly(actual, expected) {
|
||||
throw new Error("Not implemented: notMatchOnly");
|
||||
},
|
||||
matchOnlyStrict(actual, expected) {
|
||||
throw new Error("Not implemented: matchOnlyStrict");
|
||||
},
|
||||
notMatchOnlyStrict(actual, expected) {
|
||||
throw new Error("Not implemented: notMatchOnlyStrict");
|
||||
},
|
||||
matchStrict(actual, expected) {
|
||||
throw new Error("Not implemented: matchStrict");
|
||||
},
|
||||
notMatchStrict(actual, expected) {
|
||||
throw new Error("Not implemented: notMatchStrict");
|
||||
},
|
||||
hasProp(actual, expected) {
|
||||
throw new Error("Not implemented: hasProp");
|
||||
},
|
||||
hasOwnProp(actual, expected) {
|
||||
throw new Error("Not implemented: hasOwnProp");
|
||||
},
|
||||
hasProps(actual, expected) {
|
||||
throw new Error("Not implemented: hasProps");
|
||||
},
|
||||
hasOwnProps(actual, expected) {
|
||||
throw new Error("Not implemented: hasOwnProps");
|
||||
},
|
||||
hasOwnPropsOnly(actual, expected) {
|
||||
throw new Error("Not implemented: hasOwnPropsOnly");
|
||||
},
|
||||
throws(fn, expected) {
|
||||
expect(fn).toThrow(expected);
|
||||
},
|
||||
doesNotThrow(fn, expected) {
|
||||
expect(fn).not.toThrow(expected);
|
||||
},
|
||||
rejects(fnOrPromise, expected) {
|
||||
const promise = typeof fnOrPromise === "function" ? fnOrPromise() : fnOrPromise;
|
||||
expect(promise).rejects.toThrow(expected);
|
||||
},
|
||||
resolves(fnOrPromise, expected) {
|
||||
const promise = typeof fnOrPromise === "function" ? fnOrPromise() : fnOrPromise;
|
||||
expect(promise).resolves.toEqual(expected);
|
||||
},
|
||||
resolveMatch(fnOrPromise, expected) {
|
||||
const promise = typeof fnOrPromise === "function" ? fnOrPromise() : fnOrPromise;
|
||||
expect(promise).resolves.toMatch(expected);
|
||||
},
|
||||
emits(emitter, event) {
|
||||
throw new Error("Not implemented: emits");
|
||||
},
|
||||
error(err) {
|
||||
expect(err).toBeInstanceOf(Error);
|
||||
},
|
||||
// https://github.com/tapjs/tapjs/blob/511019b2ac0fa014370154c3a341a0e632f50b19/src/mock/src/index.ts
|
||||
mock(name, mocks) {
|
||||
jest.mock(name, mocks);
|
||||
return require(name);
|
||||
},
|
||||
mockImport(name, mocks) {
|
||||
jest.mock(name, mocks);
|
||||
return import(name);
|
||||
},
|
||||
mockRequire(name, mocks) {
|
||||
jest.mock(name, mocks);
|
||||
return require(name);
|
||||
},
|
||||
mockAll(name, mocks) {
|
||||
jest.mock(name, mocks);
|
||||
},
|
||||
// https://github.com/tapjs/tapjs/blob/main/src/snapshot/src/index.ts
|
||||
matchSnapshot(expected) {
|
||||
expect(expected).toMatchSnapshot();
|
||||
},
|
||||
resolveMatchSnapshot(fnOrPromise) {
|
||||
const promise = typeof fnOrPromise === "function" ? fnOrPromise() : fnOrPromise;
|
||||
expect(promise).resolves.toMatchSnapshot();
|
||||
},
|
||||
// https://github.com/tapjs/tapjs/tree/511019b2ac0fa014370154c3a341a0e632f50b19/src/fixture
|
||||
fixture(type, content) {
|
||||
return {
|
||||
type,
|
||||
content,
|
||||
};
|
||||
},
|
||||
testdir(content) {
|
||||
const cwd = mkdtempSync(join(tmpdir(), "tap-testdir-"));
|
||||
const write = (path, content) => {
|
||||
if (typeof content === "string") {
|
||||
writeFileSync(join(cwd, path), content);
|
||||
} else if (typeof content === "object") {
|
||||
if ("type" in content && "content" in content) {
|
||||
const { type, content: value } = content;
|
||||
if (type === "file") {
|
||||
writeFileSync(join(cwd, path), content);
|
||||
} else if (type === "dir") {
|
||||
mkdirSync(join(cwd, path));
|
||||
} else if (type === "symlink") {
|
||||
symlinkSync(join(cwd, path), value);
|
||||
} else if (type === "link") {
|
||||
linkSync(join(cwd, path), value);
|
||||
} else {
|
||||
throw new Error(`Not implemented fixture: ${type}`);
|
||||
}
|
||||
} else {
|
||||
if (path) {
|
||||
mkdirSync(join(cwd, path));
|
||||
}
|
||||
for (const [filename, entry] of Object.entries(content)) {
|
||||
write(join(path, filename), entry);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
write("", content);
|
||||
},
|
||||
// https://github.com/tapjs/tapjs/tree/511019b2ac0fa014370154c3a341a0e632f50b19/src/spawn
|
||||
spawn(cmd, args, { cwd, env }) {
|
||||
spawnSync({
|
||||
cmd: [cmd, ...args],
|
||||
cwd,
|
||||
env,
|
||||
});
|
||||
},
|
||||
// ...
|
||||
comment(message) {
|
||||
// ...
|
||||
},
|
||||
test(name, fn, options) {
|
||||
// if (typeof fn !== "function") {
|
||||
// if (fn.skip) {
|
||||
// jest.skip(name, () => {});
|
||||
// return;
|
||||
// }
|
||||
// fn = options;
|
||||
// }
|
||||
jest.test(name, () => {
|
||||
fn(t);
|
||||
});
|
||||
},
|
||||
before(fn) {
|
||||
jest.beforeAll(() => fn(t));
|
||||
},
|
||||
beforeEach(fn) {
|
||||
jest.beforeEach(() => fn(t));
|
||||
},
|
||||
after(fn) {
|
||||
jest.afterAll(() => fn(t));
|
||||
},
|
||||
afterEach(fn) {
|
||||
jest.afterEach(() => fn(t));
|
||||
},
|
||||
teardown(fn) {
|
||||
jest.afterAll(() => fn(t));
|
||||
},
|
||||
end() {
|
||||
// ...
|
||||
},
|
||||
};
|
||||
|
||||
for (const fn of Object.values(t)) {
|
||||
hideFromStack(fn);
|
||||
}
|
||||
|
||||
mock.module("tap", () => {
|
||||
const module = {
|
||||
default: t,
|
||||
...t,
|
||||
};
|
||||
|
||||
for (const fn of Object.values(module)) {
|
||||
hideFromStack(fn);
|
||||
}
|
||||
|
||||
return module;
|
||||
});
|
||||
|
||||
await import(path);
|
||||
}
|
||||
|
||||
function hideFromStack(fn) {
|
||||
Object.defineProperty(fn, "name", {
|
||||
value: "::bunternal::",
|
||||
configurable: true,
|
||||
enumerable: true,
|
||||
writable: true,
|
||||
});
|
||||
}
|
||||
21
test/ecosystem/runner/utest.js
Normal file
21
test/ecosystem/runner/utest.js
Normal file
@@ -0,0 +1,21 @@
|
||||
// https://www.npmjs.com/package/utest
|
||||
|
||||
export async function run(path) {
|
||||
const { mock, describe, test } = Bun.jest(path);
|
||||
|
||||
mock.module("utest", () => {
|
||||
return {
|
||||
default: (title, tests) => {
|
||||
describe(title, () => {
|
||||
for (const [name, fn] of Object.entries(tests)) {
|
||||
test(name, async () => {
|
||||
await fn();
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
await import(path);
|
||||
}
|
||||
201
test/ecosystem/runner/uvu.js
Normal file
201
test/ecosystem/runner/uvu.js
Normal file
@@ -0,0 +1,201 @@
|
||||
export async function run(path) {
|
||||
const jest = Bun.jest(path);
|
||||
const { expect, mock } = jest;
|
||||
|
||||
// https://github.com/lukeed/uvu/blob/master/docs/api.uvu.md
|
||||
const suite = (name, context, fn) => {
|
||||
if (typeof context === "function") {
|
||||
fn = context;
|
||||
context = {};
|
||||
}
|
||||
const tests = [];
|
||||
const skips = [];
|
||||
const onlys = [];
|
||||
const beforeAlls = [];
|
||||
const beforeEachs = [];
|
||||
const afterAlls = [];
|
||||
const afterEachs = [];
|
||||
const result = {
|
||||
name,
|
||||
context,
|
||||
test(name, fn) {
|
||||
tests.push([name, fn]);
|
||||
return result;
|
||||
},
|
||||
skip(name, fn) {
|
||||
skips.push([name, fn]);
|
||||
return result;
|
||||
},
|
||||
only(name, fn) {
|
||||
onlys.push([name, fn]);
|
||||
return result;
|
||||
},
|
||||
before: createCallable({
|
||||
default: fn => beforeAlls.push(fn),
|
||||
each: fn => beforeEachs.push(fn),
|
||||
}),
|
||||
after: createCallable({
|
||||
default: fn => afterAlls.push(fn),
|
||||
each: fn => afterEachs.push(fn),
|
||||
}),
|
||||
run() {
|
||||
jest.describe(name, () => {
|
||||
if (typeof fn === "function") {
|
||||
fn(context);
|
||||
}
|
||||
for (const fn of beforeAlls) {
|
||||
jest.beforeAll(() => fn(context));
|
||||
}
|
||||
for (const fn of beforeEachs) {
|
||||
jest.beforeEach(() => fn(context));
|
||||
}
|
||||
for (const fn of afterAlls) {
|
||||
jest.afterAll(() => fn(context));
|
||||
}
|
||||
for (const fn of afterEachs) {
|
||||
jest.afterEach(() => fn(context));
|
||||
}
|
||||
for (const [name, fn] of tests) {
|
||||
jest.test(name, () => fn(context));
|
||||
}
|
||||
for (const [name, fn] of skips) {
|
||||
jest.test.skip(name, () => fn(context));
|
||||
}
|
||||
for (const [name, fn] of onlys) {
|
||||
jest.test.only(name, () => fn(context));
|
||||
}
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
for (const fn of Object.values(result)) {
|
||||
if (typeof fn === "function") {
|
||||
hideFromStack(fn);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
// https://github.com/lukeed/uvu/blob/master/docs/api.assert.md
|
||||
const assert = {
|
||||
ok: value => {
|
||||
expect(value).toBeTruthy();
|
||||
},
|
||||
is: createCallable({
|
||||
default: (value, expected) => expect(value).toBe(expected),
|
||||
not: (value, expected) => expect(value).not.toBe(expected),
|
||||
}),
|
||||
equal: (value, expected) => {
|
||||
expect(value).toEqual(expected);
|
||||
},
|
||||
type: (value, expected) => {
|
||||
expect(typeof value).toBe(expected);
|
||||
},
|
||||
instance: (value, expected) => {
|
||||
expect(value).toBeInstanceOf(expected);
|
||||
},
|
||||
match: (value, expected) => {
|
||||
expect(value).toMatch(expected);
|
||||
},
|
||||
snapshot: (value, expected) => {
|
||||
expect(value).toBe(expected); // ?
|
||||
},
|
||||
fixture: (value, expected) => {
|
||||
expect(value).toBe(expected); // ?
|
||||
},
|
||||
throws: (fn, expected) => {
|
||||
if (!expected) {
|
||||
expect(fn).toThrow();
|
||||
} else if (typeof expected === "string" || expected instanceof RegExp) {
|
||||
expect(fn).toThrow(expected);
|
||||
} else if (typeof expected === "function") {
|
||||
try {
|
||||
fn();
|
||||
} catch (error) {
|
||||
if (!expected(error)) {
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
expect.unreachable();
|
||||
}
|
||||
},
|
||||
unreachable: () => {
|
||||
expect.unreachable();
|
||||
},
|
||||
not: createCallable({
|
||||
default: value => expect(value).toBeFalsy(),
|
||||
ok: value => expect(value).toBeFalsy(),
|
||||
equal: (value, expected) => expect(value).not.toEqual(expected),
|
||||
type: (value, expected) => expect(typeof value).not.toBe(expected),
|
||||
instance: (value, expected) => expect(value).not.toBeInstanceOf(expected),
|
||||
match: (value, expected) => expect(value).not.toMatch(expected),
|
||||
snapshot: (value, expected) => expect(value).not.toBe(expected), // ?
|
||||
fixture: (value, expected) => expect(value).not.toBe(expected), // ?
|
||||
throws: (fn, expected) => {
|
||||
if (!expected) {
|
||||
expect(fn).not.toThrow();
|
||||
} else if (typeof expected === "string" || expected instanceof RegExp) {
|
||||
expect(fn).not.toThrow(expected);
|
||||
} else if (typeof expected === "function") {
|
||||
try {
|
||||
fn();
|
||||
} catch (error) {
|
||||
if (expected(error)) {
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
expect.unreachable();
|
||||
}
|
||||
},
|
||||
}),
|
||||
};
|
||||
|
||||
for (const fn of Object.values(assert)) {
|
||||
hideFromStack(fn);
|
||||
}
|
||||
|
||||
mock.module("uvu", () => {
|
||||
return {
|
||||
suite: (name, fn) => {
|
||||
const result = suite(name, fn);
|
||||
return createCallable({
|
||||
default: (name, fn) => result.test(name, fn),
|
||||
...result,
|
||||
});
|
||||
},
|
||||
test: (name, fn) => suite("").test(name, fn),
|
||||
};
|
||||
});
|
||||
|
||||
mock.module("uvu/assert", () => {
|
||||
return {
|
||||
default: assert,
|
||||
...assert,
|
||||
};
|
||||
});
|
||||
|
||||
await import(path);
|
||||
}
|
||||
|
||||
function createCallable(options) {
|
||||
const { default: fn, ...fns } = options;
|
||||
let result = (...args) => fn(...args);
|
||||
for (const [name, fn] of Object.entries(fns)) {
|
||||
if (typeof fn === "function") {
|
||||
result[name] = fn;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
function hideFromStack(fn) {
|
||||
Object.defineProperty(fn, "name", {
|
||||
value: "::bunternal::",
|
||||
configurable: true,
|
||||
enumerable: true,
|
||||
writable: true,
|
||||
});
|
||||
}
|
||||
6
test/ecosystem/runner/vitest.js
Normal file
6
test/ecosystem/runner/vitest.js
Normal file
@@ -0,0 +1,6 @@
|
||||
export async function run(path) {
|
||||
for (const [key, value] of Object.entries(Bun.jest(path))) {
|
||||
globalThis[key] = value;
|
||||
}
|
||||
await import(path);
|
||||
}
|
||||
9
test/ecosystem/semver.test.ts
Normal file
9
test/ecosystem/semver.test.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
import { runTests } from "./harness";
|
||||
|
||||
runTests({
|
||||
package: "semver",
|
||||
repository: "https://github.com/npm/node-semver",
|
||||
ref: "6240d75a7c620b0a222f05969a91fdc3dc2be0fb", // Nov 2023
|
||||
paths: ["test/functions/*.js", "test/integration/*.js", "test/ranges/*.js", "test/bin/*.js"],
|
||||
runner: "tap",
|
||||
});
|
||||
10
test/ecosystem/superagent.test.ts
Normal file
10
test/ecosystem/superagent.test.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
import { runTests } from "./harness";
|
||||
|
||||
runTests({
|
||||
package: "superagent", // used by `express` for testing
|
||||
repository: "https://github.com/ladjs/superagent",
|
||||
ref: "v8.1.2",
|
||||
paths: ["test/*.js"],
|
||||
runner: "mocha",
|
||||
todo: true,
|
||||
});
|
||||
10
test/ecosystem/supertest.test.ts
Normal file
10
test/ecosystem/supertest.test.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
import { runTests } from "./harness";
|
||||
|
||||
runTests({
|
||||
package: "supertest", // used by `express` for testing
|
||||
repository: "https://github.com/ladjs/supertest",
|
||||
ref: "v6.3.3",
|
||||
paths: ["test/*.js"],
|
||||
runner: "mocha",
|
||||
todo: true,
|
||||
});
|
||||
10
test/ecosystem/underscore.test.ts
Normal file
10
test/ecosystem/underscore.test.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
import { runTests } from "./harness";
|
||||
|
||||
runTests({
|
||||
package: "underscore",
|
||||
repository: "https://github.com/jashkenas/underscore",
|
||||
ref: "1.13.6",
|
||||
paths: ["test/*.js"],
|
||||
runner: "qunit",
|
||||
todo: true, // Too many errors
|
||||
});
|
||||
9
test/ecosystem/uuid.test.ts
Normal file
9
test/ecosystem/uuid.test.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
import { runTests } from "./harness";
|
||||
|
||||
runTests({
|
||||
package: "uuid",
|
||||
repository: "https://github.com/uuidjs/uuid",
|
||||
ref: "v9.0.1",
|
||||
paths: ["test/unit/*.test.js"],
|
||||
runner: "jest",
|
||||
});
|
||||
10
test/ecosystem/vite.test.ts
Normal file
10
test/ecosystem/vite.test.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
import { runTests } from "./harness";
|
||||
|
||||
runTests({
|
||||
package: "@vitejs/vite-monorepo",
|
||||
repository: "https://github.com/vitejs/vite",
|
||||
ref: "v5.0.3",
|
||||
paths: ["packages/create-vite/__tests__/**/*.spec.ts", "packages/vite/src/node/__tests__/**/*.spec.ts"],
|
||||
runner: "jest",
|
||||
todo: true, // error: workspace dependency "vite" not found
|
||||
});
|
||||
10
test/ecosystem/yargs.test.ts
Normal file
10
test/ecosystem/yargs.test.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
import { runTests } from "./harness";
|
||||
|
||||
runTests({
|
||||
package: "yargs",
|
||||
repository: "https://github.com/yargs/yargs",
|
||||
ref: "v17.7.2",
|
||||
paths: ["test/*.cjs"],
|
||||
runner: "mocha",
|
||||
todo: true, // TypeError: path.charCodeAt is not a function
|
||||
});
|
||||
11
test/ecosystem/zx.test.ts
Normal file
11
test/ecosystem/zx.test.ts
Normal file
@@ -0,0 +1,11 @@
|
||||
import { runTests } from "./harness";
|
||||
|
||||
runTests({
|
||||
package: "zx",
|
||||
repository: "https://github.com/google/zx",
|
||||
ref: "7.2.3",
|
||||
paths: ["test/*.test.js"],
|
||||
runner: "uvu",
|
||||
cmds: [["bun", "run", "build"]],
|
||||
todo: true, // Too many problems
|
||||
});
|
||||
@@ -181,3 +181,7 @@ export function ignoreMimallocWarning({
|
||||
Response.prototype.text = origResponseText;
|
||||
});
|
||||
}
|
||||
|
||||
export function randomPort() {
|
||||
return Math.floor(Math.random() * (65535 - 1024) + 1024);
|
||||
}
|
||||
|
||||
105
test/integration/vite.test.ts
Normal file
105
test/integration/vite.test.ts
Normal file
@@ -0,0 +1,105 @@
|
||||
import { describe, test, expect, afterEach } from "bun:test";
|
||||
import { PipedSubprocess, Subprocess, spawn } from "bun";
|
||||
import { join } from "node:path";
|
||||
import { tmpdir } from "node:os";
|
||||
import { existsSync, mkdtempSync } from "node:fs";
|
||||
import { bunExe, bunEnv, randomPort } from "harness";
|
||||
|
||||
describe.each(["vanilla", "vanilla-ts", "react", "react-ts"])("vite/%s", (template: string) => {
|
||||
const tmp = mkdtempSync(join(tmpdir(), `vite-${template}-`));
|
||||
const cwd = join(tmp, template);
|
||||
|
||||
let subprocess: Subprocess | undefined;
|
||||
|
||||
afterEach(() => {
|
||||
subprocess?.kill();
|
||||
});
|
||||
|
||||
test(
|
||||
"bunx create-vite",
|
||||
async () => {
|
||||
subprocess = spawn({
|
||||
cwd: tmp,
|
||||
cmd: [bunExe(), "--bun", "x", "create-vite", template, "--template", template],
|
||||
env: bunEnv,
|
||||
stdout: "inherit",
|
||||
stderr: "inherit",
|
||||
});
|
||||
expect(subprocess.exited).resolves.toBe(0);
|
||||
expect(existsSync(cwd)).toBeTrue();
|
||||
expect(existsSync(join(cwd, "package.json"))).toBeTrue();
|
||||
},
|
||||
{
|
||||
timeout: 15_000,
|
||||
},
|
||||
);
|
||||
|
||||
test(
|
||||
"bun install",
|
||||
async () => {
|
||||
subprocess = spawn({
|
||||
cwd,
|
||||
cmd: [bunExe(), "install"],
|
||||
env: bunEnv,
|
||||
stdout: "inherit",
|
||||
stderr: "inherit",
|
||||
});
|
||||
expect(subprocess.exited).resolves.toBe(0);
|
||||
expect(existsSync(join(cwd, "bun.lockb"))).toBeTrue();
|
||||
expect(existsSync(join(cwd, "node_modules"))).toBeTrue();
|
||||
},
|
||||
{
|
||||
timeout: 15_000,
|
||||
},
|
||||
);
|
||||
|
||||
test("bun run build", () => {
|
||||
subprocess = spawn({
|
||||
cwd,
|
||||
cmd: [bunExe(), "--bun", "run", "build"],
|
||||
env: bunEnv,
|
||||
stdout: "inherit",
|
||||
stderr: "inherit",
|
||||
});
|
||||
expect(subprocess.exited).resolves.toBe(0);
|
||||
expect(existsSync(join(cwd, "dist"))).toBeTrue();
|
||||
expect(existsSync(join(cwd, "dist", "index.html"))).toBeTrue();
|
||||
});
|
||||
|
||||
test.each(["preview", "dev"])(
|
||||
"bun run %s",
|
||||
async subcommand => {
|
||||
subprocess = spawn({
|
||||
cwd,
|
||||
cmd: [bunExe(), "--bun", "run", subcommand, "--port", `${randomPort()}`, "--strict-port", "true"],
|
||||
env: bunEnv,
|
||||
stdout: "pipe",
|
||||
stderr: "inherit",
|
||||
});
|
||||
const { stdout } = subprocess as PipedSubprocess;
|
||||
|
||||
let url: string | undefined;
|
||||
for await (const chunk of stdout) {
|
||||
process.stdout.write(chunk);
|
||||
const text = Buffer.from(chunk).toString();
|
||||
const match = text.match(/(http:\/\/[^\s]+)/gim);
|
||||
if (match?.length) {
|
||||
url = match[0];
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!url) {
|
||||
throw new Error("Failed to find server URL from stdout");
|
||||
}
|
||||
|
||||
for (let i = 0; i < 100; i++) {
|
||||
const response = await fetch(url);
|
||||
expect(response.text()).resolves.toStartWith("<!doctype html>");
|
||||
expect(response.status).toBe(200);
|
||||
}
|
||||
},
|
||||
{
|
||||
timeout: 60_000,
|
||||
},
|
||||
);
|
||||
});
|
||||
Reference in New Issue
Block a user