mirror of
https://github.com/oven-sh/bun
synced 2026-02-17 06:12:08 +00:00
Compare commits
1 Commits
claude/clo
...
claude/fix
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
53282ab45b |
@@ -34,6 +34,19 @@ pub const JSXPragma = struct {
|
||||
}
|
||||
};
|
||||
|
||||
pub const CoverageIgnoreDirective = struct {
|
||||
kind: Kind,
|
||||
line: u32,
|
||||
end_line: u32 = 0, // For tracking the end of ignored ranges
|
||||
|
||||
pub const Kind = enum {
|
||||
ignore_next,
|
||||
ignore_if,
|
||||
ignore_else,
|
||||
ignore_file,
|
||||
};
|
||||
};
|
||||
|
||||
pub const JSONOptions = struct {
|
||||
/// Enable JSON-specific warnings/errors
|
||||
is_json: bool = false,
|
||||
@@ -150,6 +163,7 @@ fn NewLexer_(
|
||||
is_ascii_only: JSONBool = JSONBoolDefault,
|
||||
track_comments: bool = false,
|
||||
all_comments: std.ArrayList(logger.Range),
|
||||
coverage_ignore_directives: std.ArrayList(CoverageIgnoreDirective),
|
||||
|
||||
indent_info: if (json_options.guess_indentation)
|
||||
struct {
|
||||
@@ -247,19 +261,23 @@ fn NewLexer_(
|
||||
const all_comments = this.all_comments;
|
||||
const comments_to_preserve_before = this.comments_to_preserve_before;
|
||||
const temp_buffer_u16 = this.temp_buffer_u16;
|
||||
const coverage_ignore_directives = this.coverage_ignore_directives;
|
||||
this.* = original.*;
|
||||
|
||||
// make sure pointers are valid
|
||||
this.all_comments = all_comments;
|
||||
this.comments_to_preserve_before = comments_to_preserve_before;
|
||||
this.temp_buffer_u16 = temp_buffer_u16;
|
||||
this.coverage_ignore_directives = coverage_ignore_directives;
|
||||
|
||||
bun.debugAssert(all_comments.items.len >= original.all_comments.items.len);
|
||||
bun.debugAssert(comments_to_preserve_before.items.len >= original.comments_to_preserve_before.items.len);
|
||||
bun.debugAssert(temp_buffer_u16.items.len == 0 and original.temp_buffer_u16.items.len == 0);
|
||||
bun.debugAssert(coverage_ignore_directives.items.len >= original.coverage_ignore_directives.items.len);
|
||||
|
||||
this.all_comments.items.len = original.all_comments.items.len;
|
||||
this.comments_to_preserve_before.items.len = original.comments_to_preserve_before.items.len;
|
||||
this.coverage_ignore_directives.items.len = original.coverage_ignore_directives.items.len;
|
||||
}
|
||||
|
||||
/// Look ahead at the next n codepoints without advancing the iterator.
|
||||
@@ -286,6 +304,7 @@ fn NewLexer_(
|
||||
this.temp_buffer_u16.clearAndFree();
|
||||
this.all_comments.clearAndFree();
|
||||
this.comments_to_preserve_before.clearAndFree();
|
||||
this.coverage_ignore_directives.clearAndFree();
|
||||
}
|
||||
|
||||
fn decodeEscapeSequences(lexer: *LexerType, start: usize, text: string, comptime BufType: type, buf_: *BufType) !void {
|
||||
@@ -1887,6 +1906,11 @@ fn NewLexer_(
|
||||
}) catch unreachable;
|
||||
}
|
||||
|
||||
// Scan for Istanbul ignore directives (always active, not just for pragmas)
|
||||
if (comptime !is_json) {
|
||||
_ = lexer.scanIstanbulIgnoreDirective(text, lexer.loc());
|
||||
}
|
||||
|
||||
// tsconfig.json doesn't care about annotations
|
||||
if (comptime is_json)
|
||||
return;
|
||||
@@ -2017,6 +2041,58 @@ fn NewLexer_(
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// Scan for Istanbul ignore directives in comment text
|
||||
/// Returns true if an ignore directive was found
|
||||
fn scanIstanbulIgnoreDirective(noalias lexer: *LexerType, comment_text: string, comment_loc: logger.Loc) bool {
|
||||
// Look for "istanbul ignore" pattern in comment text
|
||||
// This handles both "/* istanbul ignore next */" and "// istanbul ignore next" patterns
|
||||
const trimmed = strings.trim(comment_text, " \t\r\n");
|
||||
|
||||
// Skip comment prefix (// or /* and */)
|
||||
var text = trimmed;
|
||||
if (strings.hasPrefix(text, "//")) {
|
||||
text = text[2..];
|
||||
} else if (strings.hasPrefix(text, "/*") and strings.hasSuffix(text, "*/")) {
|
||||
text = text[2 .. text.len - 2];
|
||||
}
|
||||
|
||||
text = strings.trim(text, " \t\r\n");
|
||||
|
||||
// Check for "istanbul ignore" prefix
|
||||
if (!strings.hasPrefix(text, "istanbul ignore")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
text = text["istanbul ignore".len..];
|
||||
text = strings.trim(text, " \t\r\n");
|
||||
|
||||
// Parse the directive type
|
||||
var directive_kind: ?CoverageIgnoreDirective.Kind = null;
|
||||
|
||||
if (strings.hasPrefix(text, "next")) {
|
||||
directive_kind = .ignore_next;
|
||||
} else if (strings.hasPrefix(text, "if")) {
|
||||
directive_kind = .ignore_if;
|
||||
} else if (strings.hasPrefix(text, "else")) {
|
||||
directive_kind = .ignore_else;
|
||||
} else if (strings.hasPrefix(text, "file")) {
|
||||
directive_kind = .ignore_file;
|
||||
}
|
||||
|
||||
if (directive_kind) |kind| {
|
||||
// Convert location to line number (0-based)
|
||||
const line_number = @as(u32, @intCast(lexer.source.lineColFromLoc(comment_loc).line));
|
||||
lexer.coverage_ignore_directives.append(.{
|
||||
.kind = kind,
|
||||
.line = line_number,
|
||||
}) catch return false; // Ignore error, just don't track this directive
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// TODO: implement this
|
||||
pub fn removeMultilineCommentIndent(_: *LexerType, _: string, text: string) string {
|
||||
return text;
|
||||
@@ -2038,6 +2114,7 @@ fn NewLexer_(
|
||||
.allocator = allocator,
|
||||
.comments_to_preserve_before = std.ArrayList(js_ast.G.Comment).init(allocator),
|
||||
.all_comments = std.ArrayList(logger.Range).init(allocator),
|
||||
.coverage_ignore_directives = std.ArrayList(CoverageIgnoreDirective).init(allocator),
|
||||
};
|
||||
lex.step();
|
||||
try lex.next();
|
||||
@@ -2054,6 +2131,7 @@ fn NewLexer_(
|
||||
.allocator = allocator,
|
||||
.comments_to_preserve_before = std.ArrayList(js_ast.G.Comment).init(allocator),
|
||||
.all_comments = std.ArrayList(logger.Range).init(allocator),
|
||||
.coverage_ignore_directives = std.ArrayList(CoverageIgnoreDirective).init(allocator),
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
const LinesHits = bun.collections.BabyList(u32);
|
||||
|
||||
/// Coverage ignore directive for Istanbul-style ignore comments
|
||||
pub const CoverageIgnoreDirective = bun.js_lexer.CoverageIgnoreDirective;
|
||||
|
||||
/// Our code coverage currently only deals with lines of code, not statements or branches.
|
||||
/// JSC doesn't expose function names in their coverage data, so we don't include that either :(.
|
||||
/// Since we only need to store line numbers, our job gets simpler
|
||||
@@ -359,6 +362,7 @@ pub const ByteRangeMapping = struct {
|
||||
line_offset_table: LineOffsetTable.List = .{},
|
||||
source_id: i32,
|
||||
source_url: bun.jsc.ZigString.Slice,
|
||||
coverage_ignore_directives: std.ArrayListUnmanaged(CoverageIgnoreDirective) = .{},
|
||||
|
||||
pub fn isLessThan(_: void, a: ByteRangeMapping, b: ByteRangeMapping) bool {
|
||||
return bun.strings.order(a.source_url.slice(), b.source_url.slice()) == .lt;
|
||||
@@ -368,6 +372,7 @@ pub const ByteRangeMapping = struct {
|
||||
|
||||
pub fn deinit(this: *ByteRangeMapping) void {
|
||||
this.line_offset_table.deinit(bun.default_allocator);
|
||||
this.coverage_ignore_directives.deinit(bun.default_allocator);
|
||||
}
|
||||
|
||||
pub threadlocal var map: ?*HashMap = null;
|
||||
@@ -404,6 +409,26 @@ pub const ByteRangeMapping = struct {
|
||||
return entry;
|
||||
}
|
||||
|
||||
/// Check if a line should be ignored based on coverage ignore directives
|
||||
fn shouldIgnoreLine(this: *const ByteRangeMapping, line: u32) bool {
|
||||
// Handle "ignore file" directive - if present, ignore entire file
|
||||
for (this.coverage_ignore_directives.items) |directive| {
|
||||
if (directive.kind == .ignore_file) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Handle "ignore next" directive - ignore the line immediately following the directive
|
||||
if (directive.kind == .ignore_next and line == directive.line + 1) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// TODO: Handle "ignore if" and "ignore else" - these require more complex logic
|
||||
// to understand the structure of if statements
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
pub fn generateReportFromBlocks(
|
||||
this: *ByteRangeMapping,
|
||||
allocator: std.mem.Allocator,
|
||||
@@ -468,10 +493,13 @@ pub const ByteRangeMapping = struct {
|
||||
min_line = @min(min_line, line);
|
||||
max_line = @max(max_line, line);
|
||||
|
||||
executable_lines.set(line);
|
||||
if (has_executed) {
|
||||
lines_which_have_executed.set(line);
|
||||
line_hits_slice[line] += 1;
|
||||
// Skip lines that should be ignored based on coverage directives
|
||||
if (!this.shouldIgnoreLine(line)) {
|
||||
executable_lines.set(line);
|
||||
if (has_executed) {
|
||||
lines_which_have_executed.set(line);
|
||||
line_hits_slice[line] += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -559,10 +587,13 @@ pub const ByteRangeMapping = struct {
|
||||
|
||||
const line: u32 = @as(u32, @intCast(point.original.lines));
|
||||
|
||||
executable_lines.set(line);
|
||||
if (has_executed) {
|
||||
lines_which_have_executed.set(line);
|
||||
line_hits_slice[line] += 1;
|
||||
// Skip lines that should be ignored based on coverage directives
|
||||
if (!this.shouldIgnoreLine(line)) {
|
||||
executable_lines.set(line);
|
||||
if (has_executed) {
|
||||
lines_which_have_executed.set(line);
|
||||
line_hits_slice[line] += 1;
|
||||
}
|
||||
}
|
||||
|
||||
min_line = @min(min_line, line);
|
||||
@@ -690,12 +721,111 @@ pub const ByteRangeMapping = struct {
|
||||
}
|
||||
|
||||
pub fn compute(source_contents: []const u8, source_id: i32, source_url: bun.jsc.ZigString.Slice) ByteRangeMapping {
|
||||
var coverage_ignore_directives = std.ArrayListUnmanaged(CoverageIgnoreDirective){};
|
||||
|
||||
// Parse the source code to extract coverage ignore directives
|
||||
parseIgnoreDirectives(source_contents, &coverage_ignore_directives) catch {};
|
||||
|
||||
return ByteRangeMapping{
|
||||
.line_offset_table = LineOffsetTable.generate(bun.jsc.VirtualMachine.get().allocator, source_contents, 0),
|
||||
.source_id = source_id,
|
||||
.source_url = source_url,
|
||||
.coverage_ignore_directives = coverage_ignore_directives,
|
||||
};
|
||||
}
|
||||
|
||||
/// Parse coverage ignore directives from source code comments
|
||||
fn parseIgnoreDirectives(source_contents: []const u8, directives: *std.ArrayListUnmanaged(CoverageIgnoreDirective)) !void {
|
||||
const allocator = bun.default_allocator;
|
||||
var line_number: u32 = 0;
|
||||
var i: usize = 0;
|
||||
|
||||
while (i < source_contents.len) {
|
||||
if (source_contents[i] == '\n') {
|
||||
line_number += 1;
|
||||
i += 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Look for comment starts
|
||||
if (i + 1 < source_contents.len) {
|
||||
// Single line comment
|
||||
if (source_contents[i] == '/' and source_contents[i + 1] == '/') {
|
||||
const comment_start = i;
|
||||
// Find end of line
|
||||
while (i < source_contents.len and source_contents[i] != '\n') {
|
||||
i += 1;
|
||||
}
|
||||
const comment_text = source_contents[comment_start..i];
|
||||
try parseIgnoreDirectiveFromComment(comment_text, line_number, directives, allocator);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Multi-line comment
|
||||
if (source_contents[i] == '/' and source_contents[i + 1] == '*') {
|
||||
const comment_start = i;
|
||||
i += 2; // Skip /*
|
||||
// Find end of comment
|
||||
while (i + 1 < source_contents.len and !(source_contents[i] == '*' and source_contents[i + 1] == '/')) {
|
||||
if (source_contents[i] == '\n') {
|
||||
line_number += 1;
|
||||
}
|
||||
i += 1;
|
||||
}
|
||||
if (i + 1 < source_contents.len) {
|
||||
i += 2; // Skip */
|
||||
const comment_text = source_contents[comment_start..i];
|
||||
try parseIgnoreDirectiveFromComment(comment_text, line_number, directives, allocator);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
i += 1;
|
||||
}
|
||||
}
|
||||
|
||||
/// Parse a single comment for ignore directives
|
||||
fn parseIgnoreDirectiveFromComment(comment_text: []const u8, line_number: u32, directives: *std.ArrayListUnmanaged(CoverageIgnoreDirective), allocator: std.mem.Allocator) !void {
|
||||
// Remove comment prefixes and whitespace
|
||||
const strings = bun.strings;
|
||||
var text = strings.trim(comment_text, " \t\r\n");
|
||||
|
||||
if (strings.hasPrefix(text, "//")) {
|
||||
text = text[2..];
|
||||
} else if (strings.hasPrefix(text, "/*") and strings.hasSuffix(text, "*/")) {
|
||||
text = text[2 .. text.len - 2];
|
||||
}
|
||||
|
||||
text = strings.trim(text, " \t\r\n");
|
||||
|
||||
// Check for "istanbul ignore" prefix
|
||||
if (!strings.hasPrefix(text, "istanbul ignore")) {
|
||||
return;
|
||||
}
|
||||
|
||||
text = text["istanbul ignore".len..];
|
||||
text = strings.trim(text, " \t\r\n");
|
||||
|
||||
// Parse directive type
|
||||
var directive_kind: ?CoverageIgnoreDirective.Kind = null;
|
||||
if (strings.hasPrefix(text, "next")) {
|
||||
directive_kind = .ignore_next;
|
||||
} else if (strings.hasPrefix(text, "if")) {
|
||||
directive_kind = .ignore_if;
|
||||
} else if (strings.hasPrefix(text, "else")) {
|
||||
directive_kind = .ignore_else;
|
||||
} else if (strings.hasPrefix(text, "file")) {
|
||||
directive_kind = .ignore_file;
|
||||
}
|
||||
|
||||
if (directive_kind) |kind| {
|
||||
try directives.append(allocator, .{
|
||||
.kind = kind,
|
||||
.line = line_number,
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
comptime {
|
||||
|
||||
@@ -589,3 +589,219 @@ Ran 1 test across 1 file."
|
||||
`);
|
||||
expect(result.exitCode).toBe(0);
|
||||
});
|
||||
|
||||
test("istanbul ignore next - single line comment", () => {
|
||||
const dir = tempDirWithFiles("cov", {
|
||||
"demo.ts": `
|
||||
export function covered() {
|
||||
return "covered";
|
||||
}
|
||||
|
||||
// istanbul ignore next
|
||||
export function ignored() {
|
||||
return "ignored";
|
||||
}
|
||||
|
||||
export function alsoIgnored() {
|
||||
return "also ignored";
|
||||
}
|
||||
`,
|
||||
"demo.test.ts": `
|
||||
import { test, expect } from "bun:test";
|
||||
import { covered, ignored, alsoIgnored } from "./demo";
|
||||
|
||||
test("should call all functions but ignore specified ones", () => {
|
||||
expect(covered()).toBe("covered");
|
||||
expect(ignored()).toBe("ignored");
|
||||
expect(alsoIgnored()).toBe("also ignored");
|
||||
});
|
||||
`,
|
||||
});
|
||||
|
||||
const result = Bun.spawnSync([bunExe(), "test", "--coverage"], {
|
||||
cwd: dir,
|
||||
env: {
|
||||
...bunEnv,
|
||||
},
|
||||
stdio: [null, null, "pipe"],
|
||||
});
|
||||
|
||||
let stderr = result.stderr.toString("utf-8");
|
||||
// Normalize output for cross-platform consistency
|
||||
stderr = normalizeBunSnapshot(stderr, dir);
|
||||
|
||||
// The ignored function should not appear in coverage
|
||||
expect(stderr).toContain("covered");
|
||||
expect(stderr).toContain("alsoIgnored");
|
||||
// Function coverage should be less than 100% due to ignored function
|
||||
expect(stderr).not.toContain("100.00");
|
||||
expect(result.exitCode).toBe(0);
|
||||
});
|
||||
|
||||
test("istanbul ignore next - multi-line comment", () => {
|
||||
const dir = tempDirWithFiles("cov", {
|
||||
"demo.ts": `
|
||||
export function covered() {
|
||||
return "covered";
|
||||
}
|
||||
|
||||
/* istanbul ignore next */
|
||||
export function ignored() {
|
||||
return "ignored";
|
||||
}
|
||||
`,
|
||||
"demo.test.ts": `
|
||||
import { test, expect } from "bun:test";
|
||||
import { covered, ignored } from "./demo";
|
||||
|
||||
test("should call all functions", () => {
|
||||
expect(covered()).toBe("covered");
|
||||
expect(ignored()).toBe("ignored");
|
||||
});
|
||||
`,
|
||||
});
|
||||
|
||||
const result = Bun.spawnSync([bunExe(), "test", "--coverage"], {
|
||||
cwd: dir,
|
||||
env: {
|
||||
...bunEnv,
|
||||
},
|
||||
stdio: [null, null, "pipe"],
|
||||
});
|
||||
|
||||
let stderr = result.stderr.toString("utf-8");
|
||||
// Normalize output for cross-platform consistency
|
||||
stderr = normalizeBunSnapshot(stderr, dir);
|
||||
|
||||
// Should show coverage but with the ignored function excluded
|
||||
expect(stderr).toContain("covered");
|
||||
expect(result.exitCode).toBe(0);
|
||||
});
|
||||
|
||||
test("istanbul ignore file", () => {
|
||||
const dir = tempDirWithFiles("cov", {
|
||||
"ignored-file.ts": `
|
||||
/* istanbul ignore file */
|
||||
export function shouldBeIgnored() {
|
||||
return "ignored";
|
||||
}
|
||||
|
||||
export function alsoIgnored() {
|
||||
return "also ignored";
|
||||
}
|
||||
`,
|
||||
"normal-file.ts": `
|
||||
export function shouldBeCovered() {
|
||||
return "covered";
|
||||
}
|
||||
`,
|
||||
"demo.test.ts": `
|
||||
import { test, expect } from "bun:test";
|
||||
import { shouldBeIgnored, alsoIgnored } from "./ignored-file";
|
||||
import { shouldBeCovered } from "./normal-file";
|
||||
|
||||
test("should call all functions", () => {
|
||||
expect(shouldBeIgnored()).toBe("ignored");
|
||||
expect(alsoIgnored()).toBe("also ignored");
|
||||
expect(shouldBeCovered()).toBe("covered");
|
||||
});
|
||||
`,
|
||||
});
|
||||
|
||||
const result = Bun.spawnSync([bunExe(), "test", "--coverage"], {
|
||||
cwd: dir,
|
||||
env: {
|
||||
...bunEnv,
|
||||
},
|
||||
stdio: [null, null, "pipe"],
|
||||
});
|
||||
|
||||
let stderr = result.stderr.toString("utf-8");
|
||||
// Normalize output for cross-platform consistency
|
||||
stderr = normalizeBunSnapshot(stderr, dir);
|
||||
|
||||
// Should only show coverage for normal-file.ts, not ignored-file.ts
|
||||
expect(stderr).toContain("normal-file.ts");
|
||||
expect(stderr).not.toContain("ignored-file.ts");
|
||||
expect(result.exitCode).toBe(0);
|
||||
});
|
||||
|
||||
test("istanbul ignore with reason", () => {
|
||||
const dir = tempDirWithFiles("cov", {
|
||||
"demo.ts": `
|
||||
export function covered() {
|
||||
return "covered";
|
||||
}
|
||||
|
||||
// istanbul ignore next: difficult to test in unit tests
|
||||
export function ignored() {
|
||||
return "ignored";
|
||||
}
|
||||
`,
|
||||
"demo.test.ts": `
|
||||
import { test, expect } from "bun:test";
|
||||
import { covered, ignored } from "./demo";
|
||||
|
||||
test("should call all functions", () => {
|
||||
expect(covered()).toBe("covered");
|
||||
expect(ignored()).toBe("ignored");
|
||||
});
|
||||
`,
|
||||
});
|
||||
|
||||
const result = Bun.spawnSync([bunExe(), "test", "--coverage"], {
|
||||
cwd: dir,
|
||||
env: {
|
||||
...bunEnv,
|
||||
},
|
||||
stdio: [null, null, "pipe"],
|
||||
});
|
||||
|
||||
let stderr = result.stderr.toString("utf-8");
|
||||
// Normalize output for cross-platform consistency
|
||||
stderr = normalizeBunSnapshot(stderr, dir);
|
||||
|
||||
// Should show coverage but with the ignored function excluded
|
||||
expect(stderr).toContain("covered");
|
||||
expect(result.exitCode).toBe(0);
|
||||
});
|
||||
|
||||
test("istanbul ignore next - lcov reporter", () => {
|
||||
const dir = tempDirWithFiles("cov", {
|
||||
"demo.ts": `
|
||||
export function covered() {
|
||||
return "covered";
|
||||
}
|
||||
|
||||
// istanbul ignore next
|
||||
export function ignored() {
|
||||
return "ignored";
|
||||
}
|
||||
`,
|
||||
"demo.test.ts": `
|
||||
import { test, expect } from "bun:test";
|
||||
import { covered, ignored } from "./demo";
|
||||
|
||||
test("should call all functions", () => {
|
||||
expect(covered()).toBe("covered");
|
||||
expect(ignored()).toBe("ignored");
|
||||
});
|
||||
`,
|
||||
});
|
||||
|
||||
const result = Bun.spawnSync([bunExe(), "test", "--coverage", "--coverage-reporter", "lcov"], {
|
||||
cwd: dir,
|
||||
env: {
|
||||
...bunEnv,
|
||||
},
|
||||
stdio: [null, null, "pipe"],
|
||||
});
|
||||
|
||||
let lcovContent = readFileSync(path.join(dir, "coverage", "lcov.info"), "utf-8");
|
||||
// Normalize LCOV content for cross-platform consistency
|
||||
lcovContent = normalizeBunSnapshot(lcovContent, dir);
|
||||
|
||||
// Should contain coverage data but with ignored lines excluded
|
||||
expect(lcovContent).toContain("demo.ts");
|
||||
expect(result.exitCode).toBe(0);
|
||||
});
|
||||
|
||||
12
test_istanbul_ignore.js
Normal file
12
test_istanbul_ignore.js
Normal file
@@ -0,0 +1,12 @@
|
||||
export function covered() {
|
||||
return "covered";
|
||||
}
|
||||
|
||||
// istanbul ignore next
|
||||
export function ignored() {
|
||||
return "ignored";
|
||||
}
|
||||
|
||||
export function alsoCovered() {
|
||||
return "also covered";
|
||||
}
|
||||
8
test_istanbul_ignore.test.js
Normal file
8
test_istanbul_ignore.test.js
Normal file
@@ -0,0 +1,8 @@
|
||||
import { test, expect } from "bun:test";
|
||||
import { covered, ignored, alsoCovered } from "./test_istanbul_ignore.js";
|
||||
|
||||
test("should call all functions", () => {
|
||||
expect(covered()).toBe("covered");
|
||||
expect(ignored()).toBe("ignored");
|
||||
expect(alsoCovered()).toBe("also covered");
|
||||
});
|
||||
Reference in New Issue
Block a user