Small improvements to bun test (#3071)

* Change status icon for skipped tests from "-" to "»"

* Show file path instead of filename in `bun test`

* Emit collapsable logs when running `bun test` in Github Actions

https://docs.github.com/en/actions/using-workflows/workflow-commands-for-github-actions#grouping-log-lines

* Add fallback for test icons when emojis are not available

* Only check for GITHUB_ACTIONS when running `bun test`

* Emit error annotations when running `bun test` in Github Actions

https://docs.github.com/en/actions/using-workflows/workflow-commands-for-github-actions#setting-an-error-message

* Remove ANSI output from Github annotation, it doesn't work

* Remove outdated code from internal test runner

* Add GithubActionFormatter to handle cases where error name or message is already ANSI

* Fix formatting of test

* Fix #3070

* Implement `bun test --run-todo`

By default, `test.todo()` is no longer run, unless `--run-todo` is specified.

* Fix test that relies on test.todo() being run

* Support vitest-style test options

* Disable GITHUB_ACTION in test harness

* Add types for TestOptions

* Fix bug where test.skip() actually ran

* Implement `test.skipIf()` and `describe.skipIf()`

* Implement `test.runIf()`

* Move DiffFormatter to its own file

* Fix bug where Bun.inspect() would emit a Github annotation

* Introduce `bun test --only`, rename `--run-todo` to `--todo`

* Implement `test.if()`, `describe.if()`, and other test fixes

* Remove unwanted files from last commit

* Fix last reference to --run-todo

* Fix memory issues with printing github actions text

* Update bindings.zig

* Fix bug with `test.only()`

* Remove debug test

* Make the github annotations better

* Improve .vscode/launch.json

* Implement `expect().toBeNil()`

* Remove .only() from test

* Implement toBeBoolean(), toBeTrue(), toBeFalse()

* Add lots of matchers
* toBeNil()
* toBeBoolean()
* toBeTrue()
* toBeFalse()
* toBeNumber()
* toBeInteger()
* toBeFinite()
* toBePositive()
* toBeNegative()
* toBeWithin()
* toBeSymbol()
* toBeFunction()
* toBeDate()
* toBeString()
* toInclude()
* toStartWith()
* toEndWith()

* Fix #3135

* Reduce verbosity of test

* Fix snapshot bug

---------

Co-authored-by: Jarred Sumner <709451+Jarred-Sumner@users.noreply.github.com>
This commit is contained in:
Ashcon Partovi
2023-05-31 23:12:04 -07:00
committed by GitHub
parent 176fade220
commit e632941c52
25 changed files with 3408 additions and 748 deletions

View File

@@ -38,7 +38,7 @@ pub fn toUTF16Literal(comptime str: []const u8) []const u16 {
};
}
const OptionalUsize = std.meta.Int(.unsigned, @bitSizeOf(usize) - 1);
pub const OptionalUsize = std.meta.Int(.unsigned, @bitSizeOf(usize) - 1);
pub fn indexOfAny(self: string, comptime str: anytype) ?OptionalUsize {
inline for (str) |a| {
if (indexOfChar(self, a)) |i| {
@@ -689,6 +689,63 @@ pub fn endsWithAny(self: string, str: string) bool {
return false;
}
// Formats a string to be safe to output in a Github action.
// - Encodes "\n" as "%0A" to support multi-line strings.
// https://github.com/actions/toolkit/issues/193#issuecomment-605394935
// - Strips ANSI output as it will appear malformed.
pub fn githubActionWriter(writer: anytype, self: string) !void {
var offset: usize = 0;
const end = @truncate(u32, self.len);
while (offset < end) {
if (indexOfNewlineOrNonASCIIOrANSI(self, @truncate(u32, offset))) |i| {
const byte = self[i];
if (byte > 0x7F) {
offset += @max(wtf8ByteSequenceLength(byte), 1);
continue;
}
if (i > 0) {
try writer.writeAll(self[offset..i]);
}
var n: usize = 1;
if (byte == '\n') {
try writer.writeAll("%0A");
} else if (i + 1 < end) {
const next = self[i + 1];
if (byte == '\r' and next == '\n') {
n += 1;
try writer.writeAll("%0A");
} else if (byte == '\x1b' and next == '[') {
n += 1;
if (i + 2 < end) {
const remain = self[(i + 2)..@min(i + 5, end)];
if (indexOfChar(remain, 'm')) |j| {
n += j + 1;
}
}
}
}
offset = i + n;
} else {
try writer.writeAll(self[offset..end]);
break;
}
}
}
pub const GithubActionFormatter = struct {
text: string,
pub fn format(this: GithubActionFormatter, comptime _: []const u8, _: std.fmt.FormatOptions, writer: anytype) !void {
try githubActionWriter(writer, this.text);
}
};
pub fn githubAction(self: string) strings.GithubActionFormatter {
return GithubActionFormatter{
.text = self,
};
}
pub fn quotedWriter(writer: anytype, self: string) !void {
var remain = self;
if (strings.containsNewlineOrNonASCIIOrQuote(remain)) {
@@ -3179,6 +3236,44 @@ pub fn firstNonASCIIWithType(comptime Type: type, slice: Type) ?u32 {
return null;
}
pub fn indexOfNewlineOrNonASCIIOrANSI(slice_: []const u8, offset: u32) ?u32 {
const slice = slice_[offset..];
var remaining = slice;
if (remaining.len == 0)
return null;
if (comptime Environment.enableSIMD) {
while (remaining.len >= ascii_vector_size) {
const vec: AsciiVector = remaining[0..ascii_vector_size].*;
const cmp = @bitCast(AsciiVectorU1, (vec > max_16_ascii)) | @bitCast(AsciiVectorU1, (vec < min_16_ascii)) |
@bitCast(AsciiVectorU1, vec == @splat(ascii_vector_size, @as(u8, '\r'))) |
@bitCast(AsciiVectorU1, vec == @splat(ascii_vector_size, @as(u8, '\n'))) |
@bitCast(AsciiVectorU1, vec == @splat(ascii_vector_size, @as(u8, '\x1b')));
if (@reduce(.Max, cmp) > 0) {
const bitmask = @bitCast(AsciiVectorInt, cmp);
const first = @ctz(bitmask);
return @as(u32, first) + @intCast(u32, slice.len - remaining.len) + offset;
}
remaining = remaining[ascii_vector_size..];
}
if (comptime Environment.allow_assert) std.debug.assert(remaining.len < ascii_vector_size);
}
for (remaining) |*char_| {
const char = char_.*;
if (char > 127 or char < 0x20 or char == '\n' or char == '\r' or char == '\x1b') {
return @truncate(u32, (@ptrToInt(char_) - @ptrToInt(slice.ptr))) + offset;
}
}
return null;
}
pub fn indexOfNewlineOrNonASCII(slice_: []const u8, offset: u32) ?u32 {
return indexOfNewlineOrNonASCIICheckStart(slice_, offset, true);
}