Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions lib/reporter/chart.js
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,9 @@ function chartReport(results, options = { labelWidth: 45, printHeader: true }) {
process.stdout.write(styleText("bold", "\nSummary (vs. baseline):\n"));
}

const maxNameLength = Math.max(...results.map((r) => r.name.length));
const columnWidth = Math.max(maxNameLength, options.labelWidth ?? 45);

for (const result of results) {
let comment = "";

Expand All @@ -129,8 +132,6 @@ function chartReport(results, options = { labelWidth: 45, printHeader: true }) {
}
}

const columnWidth = options.labelWidth ?? 45;

drawBar(
result.name.padEnd(columnWidth),
result[primaryMetric],
Expand Down
5 changes: 1 addition & 4 deletions lib/reporter/text.js
Original file line number Diff line number Diff line change
Expand Up @@ -85,12 +85,9 @@ function textReport(results, options = {}) {
const maxNameLength = Math.max(...sortedResults.map((r) => r.name.length));

for (const result of sortedResults) {
const namePart = ` ${result.name}`;
const namePart = ` ${result.name.padEnd(maxNameLength)} `;
process.stdout.write(namePart);

const padding = maxNameLength - result.name.length + 2;
process.stdout.write(" ".repeat(padding));

if (result.baseline) {
process.stdout.write(styleText("magenta", "(baseline)"));
} else if (result.comparison !== undefined) {
Expand Down
258 changes: 150 additions & 108 deletions test/reporter.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,143 +14,185 @@ const {

const { analyze } = require("../lib/utils/analyze.js");

describe("chartReport outputs benchmark results as a bar chart", async (t) => {
let output = "";

before(async () => {
const originalStdoutWrite = process.stdout.write;
process.stdout.write = (data) => {
output += data;
};
describe("chartReport", () => {
describe("outputs benchmark results as a bar chart", async (t) => {
let output = "";

const suite = new Suite({
reporter: chartReport,
});
before(async () => {
const originalStdoutWrite = process.stdout.write;
process.stdout.write = (data) => {
output += data;
};

suite
.add("single with matcher", () => {
const pattern = /[123]/g;
const replacements = { 1: "a", 2: "b", 3: "c" };
const subject = "123123123123123123123123123123123123123123123123";
const r = subject.replace(pattern, (m) => replacements[m]);
assert.ok(r);
})
.add("multiple replaces", () => {
const subject = "123123123123123123123123123123123123123123123123";
const r = subject
.replace(/1/g, "a")
.replace(/2/g, "b")
.replace(/3/g, "c");
assert.ok(r);
const suite = new Suite({
reporter: chartReport,
});
await suite.run();

process.stdout.write = originalStdoutWrite;
});
suite
.add("single with matcher", () => {
const pattern = /[123]/g;
const replacements = { 1: "a", 2: "b", 3: "c" };
const subject = "123123123123123123123123123123123123123123123123";
const r = subject.replace(pattern, (m) => replacements[m]);
assert.ok(r);
})
.add("multiple replaces", () => {
const subject = "123123123123123123123123123123123123123123123123";
const r = subject
.replace(/1/g, "a")
.replace(/2/g, "b")
.replace(/3/g, "c");
assert.ok(r);
});
await suite.run();

it("should include bar chart chars", () => {
assert.ok(output.includes("█"));
});
process.stdout.write = originalStdoutWrite;
});

it("should include ops/sec", () => {
assert.ok(output.includes("ops/sec"));
});
it("should include bar chart chars", () => {
assert.ok(output.includes(""));
});

it("should include benchmark names", () => {
assert.ok(output.includes("single with matcher"));
assert.ok(output.includes("multiple replaces"));
});
it("should include ops/sec", () => {
assert.ok(output.includes("ops/sec"));
});

it("should include sample count", () => {
assert.ok(output.includes("samples"));
});
it("should include benchmark names", () => {
assert.ok(output.includes("single with matcher"));
assert.ok(output.includes("multiple replaces"));
});

it("should include Node.js version", () => {
const regex = /Node\.js version: v\d+\.\d+\.\d+/;
it("should include sample count", () => {
assert.ok(output.includes("samples"));
});

it("should include Node.js version", () => {
const regex = /Node\.js version: v\d+\.\d+\.\d+/;

assert.ok(output.match(regex));
assert.ok(output.match(regex));
});
});
});

describe("chartReport respects reporterOptions.printHeader", async (t) => {
let outputWithHeader = "";
let outputWithoutHeader = "";
describe("with long names", async (t) => {
let output = "";

before(async () => {
const originalStdoutWrite = process.stdout.write;
before(async () => {
const originalStdoutWrite = process.stdout.write;
process.stdout.write = (data) => {
output += data;
};

// Test with default settings (printHeader: true)
process.stdout.write = (data) => {
outputWithHeader += data;
};
const suite = new Suite({
reporter: chartReport,
});

const suiteWithHeader = new Suite({
reporter: chartReport,
reporterOptions: {
printHeader: true,
},
suite
.add("single with matcher looooooooooooooooooooooooooong", () => {
const pattern = /[123]/g;
const replacements = { 1: "a", 2: "b", 3: "c" };
const subject = "123123123123123123123123123123123123123123123123";
const r = subject.replace(pattern, (m) => replacements[m]);
assert.ok(r);
})
.add("multiple replaces", () => {
const subject = "123123123123123123123123123123123123123123123123";
const r = subject
.replace(/1/g, "a")
.replace(/2/g, "b")
.replace(/3/g, "c");
assert.ok(r);
});
await suite.run();

process.stdout.write = originalStdoutWrite;
});

suiteWithHeader.add("test benchmark", () => {
const a = 1 + 1;
assert.strictEqual(a, 2);
it("should pad out benchmark names", () => {
assert.ok(output.includes("oong | "));
assert.ok(output.includes("multiple replaces".padEnd(51)));
});
await suiteWithHeader.run();
});

// Test with printHeader: false
outputWithoutHeader = "";
process.stdout.write = (data) => {
outputWithoutHeader += data;
};
describe("respects reporterOptions.printHeader", async (t) => {
let outputWithHeader = "";
let outputWithoutHeader = "";

const suiteWithoutHeader = new Suite({
reporter: chartReport,
reporterOptions: {
printHeader: false,
},
});
before(async () => {
const originalStdoutWrite = process.stdout.write;

suiteWithoutHeader.add("test benchmark", () => {
const a = 1 + 1;
assert.strictEqual(a, 2);
});
await suiteWithoutHeader.run();
// Test with default settings (printHeader: true)
process.stdout.write = (data) => {
outputWithHeader += data;
};

process.stdout.write = originalStdoutWrite;
});
const suiteWithHeader = new Suite({
reporter: chartReport,
reporterOptions: {
printHeader: true,
},
});

it("should include Node.js version when printHeader is true", () => {
const regex = /Node\.js version: v\d+\.\d+\.\d+/;
assert.ok(outputWithHeader.match(regex));
});
suiteWithHeader.add("test benchmark", () => {
const a = 1 + 1;
assert.strictEqual(a, 2);
});
await suiteWithHeader.run();

it("should include Platform when printHeader is true", () => {
assert.ok(outputWithHeader.includes("Platform:"));
});
// Test with printHeader: false
outputWithoutHeader = "";
process.stdout.write = (data) => {
outputWithoutHeader += data;
};

it("should include CPU Cores when printHeader is true", () => {
assert.ok(outputWithHeader.includes("CPU Cores:"));
});
const suiteWithoutHeader = new Suite({
reporter: chartReport,
reporterOptions: {
printHeader: false,
},
});

it("should NOT include Node.js version when printHeader is false", () => {
const regex = /Node\.js version: v\d+\.\d+\.\d+/;
assert.ok(!outputWithoutHeader.match(regex));
});
suiteWithoutHeader.add("test benchmark", () => {
const a = 1 + 1;
assert.strictEqual(a, 2);
});
await suiteWithoutHeader.run();

it("should NOT include Platform when printHeader is false", () => {
assert.ok(!outputWithoutHeader.includes("Platform:"));
});
process.stdout.write = originalStdoutWrite;
});

it("should NOT include CPU Cores when printHeader is false", () => {
assert.ok(!outputWithoutHeader.includes("CPU Cores:"));
});
it("should include Node.js version when printHeader is true", () => {
const regex = /Node\.js version: v\d+\.\d+\.\d+/;
assert.ok(outputWithHeader.match(regex));
});

it("should include Platform when printHeader is true", () => {
assert.ok(outputWithHeader.includes("Platform:"));
});

it("should include CPU Cores when printHeader is true", () => {
assert.ok(outputWithHeader.includes("CPU Cores:"));
});

it("should NOT include Node.js version when printHeader is false", () => {
const regex = /Node\.js version: v\d+\.\d+\.\d+/;
assert.ok(!outputWithoutHeader.match(regex));
});

it("should NOT include Platform when printHeader is false", () => {
assert.ok(!outputWithoutHeader.includes("Platform:"));
});

it("should still include benchmark data with or without header", () => {
// Both outputs should still have benchmark bars and results
assert.ok(outputWithHeader.includes("█"));
assert.ok(outputWithoutHeader.includes("█"));
assert.ok(outputWithHeader.includes("test benchmark"));
assert.ok(outputWithoutHeader.includes("test benchmark"));
it("should NOT include CPU Cores when printHeader is false", () => {
assert.ok(!outputWithoutHeader.includes("CPU Cores:"));
});

it("should still include benchmark data with or without header", () => {
// Both outputs should still have benchmark bars and results
assert.ok(outputWithHeader.includes("█"));
assert.ok(outputWithoutHeader.includes("█"));
assert.ok(outputWithHeader.includes("test benchmark"));
assert.ok(outputWithoutHeader.includes("test benchmark"));
});
});
});

Expand Down
Loading