mirror of
https://github.com/oven-sh/bun
synced 2026-02-09 10:28:47 +00:00
@@ -777,7 +777,9 @@ pub const DescribeScope = struct {
|
||||
tag: Tag = .pass,
|
||||
|
||||
pub fn isAllSkipped(this: *const DescribeScope) bool {
|
||||
return this.is_skip or @as(usize, this.skip_count) >= this.tests.items.len;
|
||||
if (this.is_skip) return true;
|
||||
const total = this.tests.items.len;
|
||||
return total > 0 and @as(usize, this.skip_count) >= total;
|
||||
}
|
||||
|
||||
pub fn push(new: *DescribeScope) void {
|
||||
@@ -1080,13 +1082,8 @@ pub const DescribeScope = struct {
|
||||
const end = @as(TestRunner.Test.ID, @truncate(tests.len));
|
||||
this.pending_tests = std.DynamicBitSetUnmanaged.initFull(allocator, end) catch unreachable;
|
||||
|
||||
if (end == 0) {
|
||||
// TODO: print the describe label when there are no tests
|
||||
return;
|
||||
}
|
||||
|
||||
// Step 2. Update the runner with the count of how many tests we have for this block
|
||||
this.test_id_start = Jest.runner.?.addTestCount(end);
|
||||
if (end > 0) this.test_id_start = Jest.runner.?.addTestCount(end);
|
||||
|
||||
const source: logger.Source = Jest.runner.?.files.items(.source)[file];
|
||||
|
||||
@@ -1102,6 +1099,19 @@ pub const DescribeScope = struct {
|
||||
this.pending_tests.deinit(allocator);
|
||||
return;
|
||||
}
|
||||
if (end == 0) {
|
||||
var runner = allocator.create(TestRunnerTask) catch unreachable;
|
||||
runner.* = .{
|
||||
.test_id = std.math.maxInt(TestRunner.Test.ID),
|
||||
.describe = this,
|
||||
.globalThis = globalObject,
|
||||
.source_file_path = source.path.text,
|
||||
};
|
||||
runner.ref.ref(globalObject.bunVM());
|
||||
|
||||
Jest.runner.?.enqueue(runner);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
while (i < end) : (i += 1) {
|
||||
@@ -1121,7 +1131,7 @@ pub const DescribeScope = struct {
|
||||
pub fn onTestComplete(this: *DescribeScope, globalThis: *JSC.JSGlobalObject, test_id: TestRunner.Test.ID, skipped: bool) void {
|
||||
// invalidate it
|
||||
this.current_test_id = std.math.maxInt(TestRunner.Test.ID);
|
||||
this.pending_tests.unset(test_id);
|
||||
if (test_id != std.math.maxInt(TestRunner.Test.ID)) this.pending_tests.unset(test_id);
|
||||
|
||||
if (!skipped) {
|
||||
if (this.runCallback(globalThis, .afterEach)) |err| {
|
||||
@@ -1221,6 +1231,14 @@ pub const TestRunnerTask = struct {
|
||||
jsc_vm.last_reported_error_for_dedupe = .zero;
|
||||
|
||||
const test_id = this.test_id;
|
||||
|
||||
if (test_id == std.math.maxInt(TestRunner.Test.ID)) {
|
||||
describe.onTestComplete(globalThis, test_id, true);
|
||||
Jest.runner.?.runNextTest();
|
||||
this.deinit();
|
||||
return false;
|
||||
}
|
||||
|
||||
var test_: TestScope = this.describe.tests.items[test_id];
|
||||
describe.current_test_id = test_id;
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@ it("shouldn't crash when async test runner callback throws", async () => {
|
||||
})
|
||||
`;
|
||||
|
||||
const test_dir = realpathSync(await mkdtemp(join(tmpdir(), "test")));
|
||||
const test_dir = await mkdtemp(join(tmp, "test"));
|
||||
try {
|
||||
await writeFile(join(test_dir, "bad.test.js"), code);
|
||||
const { stdout, stderr, exited } = spawn({
|
||||
@@ -247,7 +247,7 @@ test("test async exceptions fail tests", () => {
|
||||
});
|
||||
|
||||
`;
|
||||
const dir = join(tmpdir(), "test-throwing-bun");
|
||||
const dir = join(tmp, "test-throwing-bun");
|
||||
const filepath = join(dir, "test-throwing-eventemitter.test.js");
|
||||
rmSync(filepath, {
|
||||
force: true,
|
||||
@@ -259,7 +259,7 @@ test("test async exceptions fail tests", () => {
|
||||
writeFileSync(filepath, code);
|
||||
|
||||
const { stderr, exitCode } = spawnSync([bunExe(), "test", "test-throwing-eventemitter"], {
|
||||
cwd: realpathSync(dir),
|
||||
cwd: dir,
|
||||
env: bunEnv,
|
||||
});
|
||||
|
||||
@@ -277,7 +277,7 @@ test("test async exceptions fail tests", () => {
|
||||
});
|
||||
|
||||
it("should return non-zero exit code for invalid syntax", async () => {
|
||||
const test_dir = realpathSync(await mkdtemp(join(tmpdir(), "test")));
|
||||
const test_dir = await mkdtemp(join(tmp, "test"));
|
||||
try {
|
||||
await writeFile(join(test_dir, "bad.test.js"), "!!!");
|
||||
const { stdout, stderr, exited } = spawn({
|
||||
@@ -302,7 +302,7 @@ it("should return non-zero exit code for invalid syntax", async () => {
|
||||
});
|
||||
|
||||
it("invalid syntax counts towards bail", async () => {
|
||||
const test_dir = realpathSync(await mkdtemp(join(tmpdir(), "test")));
|
||||
const test_dir = await mkdtemp(join(tmp, "test"));
|
||||
try {
|
||||
await writeFile(join(test_dir, "bad1.test.js"), "!!!");
|
||||
await writeFile(join(test_dir, "bad2.test.js"), "!!!");
|
||||
@@ -483,7 +483,7 @@ it("test.todo", () => {
|
||||
stdout: "pipe",
|
||||
stderr: "pipe",
|
||||
env: bunEnv,
|
||||
cwd: realpathSync(dirname(path)),
|
||||
cwd: dirname(path),
|
||||
});
|
||||
const err = stderr!.toString();
|
||||
expect(err).toContain("this test is marked as todo but passes");
|
||||
@@ -504,7 +504,7 @@ it("test.todo doesnt cause exit code 1", () => {
|
||||
stdout: "pipe",
|
||||
stderr: "pipe",
|
||||
env: bunEnv,
|
||||
cwd: realpathSync(dirname(path)),
|
||||
cwd: dirname(path),
|
||||
});
|
||||
|
||||
const err = stderr!.toString();
|
||||
@@ -519,7 +519,7 @@ it("test timeouts when expected", () => {
|
||||
stdout: "pipe",
|
||||
stderr: "pipe",
|
||||
env: bunEnv,
|
||||
cwd: realpathSync(dirname(path)),
|
||||
cwd: dirname(path),
|
||||
});
|
||||
|
||||
const err = stderr!.toString();
|
||||
@@ -535,7 +535,7 @@ it("expect().toEqual() on objects with property indices doesn't print undefined"
|
||||
stdout: "pipe",
|
||||
stderr: "pipe",
|
||||
env: bunEnv,
|
||||
cwd: realpathSync(dirname(path)),
|
||||
cwd: dirname(path),
|
||||
});
|
||||
|
||||
let err = stderr!.toString();
|
||||
@@ -555,7 +555,7 @@ it("test --preload supports global lifecycle hooks", () => {
|
||||
stdout: "pipe",
|
||||
stderr: "pipe",
|
||||
env: bunEnv,
|
||||
cwd: realpathSync(dirname(path)),
|
||||
cwd: dirname(path),
|
||||
});
|
||||
expect(stdout.toString().trim()).toBe(
|
||||
`
|
||||
@@ -595,10 +595,52 @@ it("skip() and skipIf()", () => {
|
||||
stdout: "pipe",
|
||||
stderr: "pipe",
|
||||
env: bunEnv,
|
||||
cwd: realpathSync(dirname(path)),
|
||||
cwd: dirname(path),
|
||||
});
|
||||
const result = stdout!.toString();
|
||||
expect(result).not.toContain("unreachable");
|
||||
expect(result).toMatch(/reachable/);
|
||||
expect(result.match(/reachable/g)).toHaveLength(6);
|
||||
});
|
||||
|
||||
it("should run beforeAll() & afterAll() even without tests", async () => {
|
||||
const test_dir = await mkdtemp(join(tmp, "test-hooks-empty"));
|
||||
try {
|
||||
await writeFile(
|
||||
join(test_dir, "empty.test.js"),
|
||||
`
|
||||
beforeAll(() => console.log("???BEFORE ALL???"));
|
||||
afterAll(() => console.log("!!!AFTER ALL!!!"));
|
||||
|
||||
describe("empty", () => {
|
||||
beforeAll(() => console.log(">>>BEFORE ALL>>>"));
|
||||
afterAll(() => console.log("<<<AFTER ALL<<<"));
|
||||
});
|
||||
`,
|
||||
);
|
||||
const { stdout, stderr, exited } = spawn({
|
||||
cmd: [bunExe(), "test", "empty.test.js"],
|
||||
cwd: test_dir,
|
||||
stdout: null,
|
||||
stdin: "pipe",
|
||||
stderr: "pipe",
|
||||
env: bunEnv,
|
||||
});
|
||||
expect(stderr).toBeDefined();
|
||||
const err = await new Response(stderr).text();
|
||||
expect(err).toContain("0 pass");
|
||||
expect(err).toContain("0 fail");
|
||||
expect(stdout).toBeDefined();
|
||||
const out = await new Response(stdout).text();
|
||||
expect(out.split(/\r?\n/)).toEqual([
|
||||
"???BEFORE ALL???",
|
||||
">>>BEFORE ALL>>>",
|
||||
"<<<AFTER ALL<<<",
|
||||
"!!!AFTER ALL!!!",
|
||||
"",
|
||||
]);
|
||||
expect(await exited).toBe(0);
|
||||
} finally {
|
||||
await rm(test_dir, { force: true, recursive: true });
|
||||
}
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user