Allure Bun reference
These are the functions that you can use to integrate your Bun tests with Allure.
In most cases, Allure Bun provides two different ways to use a feature: the Runtime API and the Metadata API.
Runtime API: use Allure's functions to add certain data to the test result during its execution. This approach allows for constructing the data dynamically.
Note that it is recommended to call Allure's functions as close to the beginning of the test as possible. This way, the data will be added even if the test fails early.
Metadata API: add a metadata tag (beginning with
@) into the test name. Allure Bun will extract it and update the test result's data accordingly. When using this approach, the data is guaranteed to be added regardless of how the test itself runs.
Known limitations
Always place tests inside describe() blocks. Mixing root-level test() calls with describe() blocks in the same file produces the error allure-bun does not support concurrent tests. This is a known limitation: Bun defers describe() callbacks, which causes allure-bun's registration queue to diverge from execution order — the same ordering mechanism it uses to prevent concurrent test execution. test.skip and test.todo are exempt. Files that contain only root-level tests with no describe() blocks are also unaffected.
.only (on both test and describe) is not supported for the same reason: when only one test runs, allure-bun's queue expects the first registered test, not the .only test, and throws the same error.
Sync API
All functions in this reference are asynchronous and return a PromiseLike. If your test uses synchronous helpers or matcher integrations that do not support async, import from allure-js-commons/sync instead:
import * as allure from "allure-js-commons/sync";
import { describe, test } from "bun:test";
describe("example", () => {
test("Test Authentication", () => {
allure.step("check result", () => {
allure.parameter("mode", "sync");
});
});
});The sync facade is strict-sync only: step() must complete synchronously and must not return a Promise.
Metadata
Assign a test's description, links and other metadata.
Title
allure.displayName(name: string): PromiseLike<void>
Set the test's title.
import * as allure from "allure-js-commons";
import { describe, test } from "bun:test";
describe("example", () => {
test("Test Authentication", async () => {
await allure.displayName("Test Authentication!");
// ...
});
});Description
allure.description(markdown: string): PromiseLike<void>allure.descriptionHtml(html: string): PromiseLike<void>
Set the test's description.
Use description() for Markdown content. Any HTML formatting, if present, will be stripped for security purposes.
Use descriptionHtml() when you need to supply raw HTML directly instead of Markdown.
import * as allure from "allure-js-commons";
import { describe, test } from "bun:test";
describe("example", () => {
test("Test Authentication", async () => {
await allure.description("This test attempts to log into the website.");
// ...
});
});Owner
allure.owner(name: string): PromiseLike<void>@allure.label.owner:⟨VALUE⟩
Set the test's owner.
import * as allure from "allure-js-commons";
import { describe, test } from "bun:test";
describe("example", () => {
test("Test Authentication", async () => {
await allure.owner("John Doe");
// ...
});
});import { describe, test } from "bun:test";
describe("example", () => {
test("Test Authentication @allure.label.owner:JohnDoe", async () => {
// ...
});
});Tag
allure.tag(name: string): PromiseLike<void>allure.tags(...tagsList: string[]): PromiseLike<void>@allure.label.tag:⟨VALUE⟩
Set the test's tags.
import * as allure from "allure-js-commons";
import { describe, test } from "bun:test";
describe("example", () => {
test("Test Authentication", async () => {
await allure.tag("New UI");
await allure.tags("Essentials", "Authentication");
// ...
});
});import { describe, test } from "bun:test";
describe("example", () => {
test("Test Authentication @allure.label.tag:WebInterface @allure.label.tag:Authentication", async () => {
// ...
});
});Severity
allure.severity(name: string): PromiseLike<void>@allure.label.severity:⟨VALUE⟩
Set the test's severity.
Allowed values are: "trivial", "minor", "normal", "critical", and "blocker".
import * as allure from "allure-js-commons";
import { Severity } from "allure-js-commons";
import { describe, test } from "bun:test";
describe("example", () => {
test("Test Authentication", async () => {
await allure.severity(Severity.CRITICAL);
// ...
});
});import { describe, test } from "bun:test";
describe("example", () => {
test("Test Authentication @allure.label.severity:critical", async () => {
// ...
});
});Label
allure.label(name: LabelName | string, value: string): PromiseLike<void>allure.labels(...labelsList: Label[]): PromiseLike<void>@allure.label.⟨NAME⟩:⟨VALUE⟩
Set an arbitrary label for the test. This is the underlying implementation for many of Allure's other functions.
You can call label() multiple times to create an array of values under the given name.
import * as allure from "allure-js-commons";
import { describe, test } from "bun:test";
describe("example", () => {
test("Test Authentication", async () => {
await allure.label("microservice", "UI");
// ...
});
});import { describe, test } from "bun:test";
describe("example", () => {
test("Test Authentication @allure.label.microservice:UI", async () => {
// ...
});
});ID
allure.allureId(value: string): PromiseLike<void>@allure.id:⟨VALUE⟩
Set the test's ID.
import * as allure from "allure-js-commons";
import { describe, test } from "bun:test";
describe("example", () => {
test("Test Authentication", async () => {
await allure.allureId("123");
// ...
});
});import { describe, test } from "bun:test";
describe("example", () => {
test("Test Authentication @allure.id:123", async () => {
// ...
});
});Link
allure.link(url: string, name?: string, type?: LinkType | string): PromiseLike<void>allure.links(...linksList: Link[]): PromiseLike<void>allure.issue(url: string, name?: string): PromiseLike<void>allure.tms(url: string, name?: string): PromiseLike<void>
Add a link related to the test.
Based on the type (which can be any string, defaults to "link"), Allure will try to load a corresponding link template to process the URL, as defined by the links configuration option. If no template is found for the given type, the URL is left unmodified.
If the URL does not start with "http" or "https", it will be processed according to the links configuration option.
The name will be used as the link's text. If it is omitted, the URL will be used instead.
For convenience, Allure provides two shorthand functions with pre-selected link types: issue and tms.
import * as allure from "allure-js-commons";
import { describe, test } from "bun:test";
describe("example", () => {
test("Test Authentication", async () => {
await allure.issue("AUTH-123", "Related issue");
await allure.tms("TMS-456", "Related TMS issue");
await allure.link("JIRA-777", "Related Jira issue", "jira");
await allure.link("https://example.com/", "Project website");
// ...
});
});Behavior-based hierarchy
allure.epic(name: string): PromiseLike<void>allure.feature(name: string): PromiseLike<void>allure.story(name: string): PromiseLike<void>@allure.label.epic:⟨VALUE⟩@allure.label.feature:⟨VALUE⟩@allure.label.story:⟨VALUE⟩
Assign names of epics, features or user stories for a test, as part of Allure's behavior-based hierarchy.
import * as allure from "allure-js-commons";
import { describe, test } from "bun:test";
describe("example", () => {
test("Test Authentication", async () => {
await allure.epic("Web interface");
await allure.feature("Essential features");
await allure.story("Authentication");
// ...
});
});import { describe, test } from "bun:test";
describe("example", () => {
test(
"Test Authentication" +
" @allure.label.epic:WebInterface" +
" @allure.label.feature:EssentialFeatures" +
" @allure.label.story:Authentication",
async () => {
// ...
},
);
});Suite-based hierarchy
allure.parentSuite(name: string): PromiseLike<void>allure.suite(name: string): PromiseLike<void>allure.subSuite(name: string): PromiseLike<void>@allure.label.parentSuite:⟨VALUE⟩@allure.label.suite:⟨VALUE⟩@allure.label.subSuite:⟨VALUE⟩
Assign the names of parent suite, suite or sub-suite for a test, as part of Allure's suite-based hierarchy.
This overrides the corresponding levels of the default suites hierarchy, which Allure Bun creates based on the describe() arguments.
import * as allure from "allure-js-commons";
import { describe, test } from "bun:test";
describe("example", () => {
test("Test Authentication", async () => {
await allure.parentSuite("Tests for web interface");
await allure.suite("Tests for essential features");
await allure.subSuite("Tests for authentication");
// ...
});
});import { describe, test } from "bun:test";
describe("example", () => {
test(
"Test Authentication" +
" @allure.label.parentSuite:TestsForWebInterface" +
" @allure.label.suite:TestsForEssentialFeatures" +
" @allure.label.subSuite:TestsForAuthentication",
async () => {
// ...
},
);
});Test steps
allure.step<T = void>(name: string, body: (context: StepContext) => T | PromiseLike<T>): PromiseLike<T>allure.logStep(name: string, status?: Status, error?: Error): PromiseLike<void>
Define a test step or sub-step with the given name.
The step() function accepts an anonymous function as its second argument, which can be synchronous or asynchronous. The anonymous function can accept either no arguments or a single argument of type StepContext. This object provides the following methods:
displayName()— override the step name during its execution.parameter(name: string, value: string, mode?: "default" | "masked" | "hidden")— indicate arbitrary parameters used for the step. The third argument is the display mode (a plain string, not aParameterOptionsobject). Unlike the test-wideparameter(), step parameters do not support theexcludedoption.
To create a step without a body, call the logStep() function that accepts a name and an optional step status.
import * as allure from "allure-js-commons";
import { Status } from "allure-js-commons";
import { describe, test } from "bun:test";
describe("example", () => {
test("Test Authentication", async () => {
await allure.step("Step 1", async () => {
await allure.step("Sub-step 1", async (ctx) => {
await ctx.parameter("foo", "1");
// ...
});
await allure.step("Sub-step 2", async (ctx) => {
await ctx.parameter("foo", "2");
// ...
});
});
await allure.logStep("Step 2", Status.SKIPPED);
});
});Parametrized tests
allure.parameter(name: string, value: string, options?: ParameterOptions): PromiseLike<void>
The parametrized tests pattern in Bun can be implemented by calling the built-in test.each() function or by running a test() inside a loop. In both cases, Allure Report recognizes each iteration as a separate test run.
The values that distinguish one iteration from another are called test parameters. To display a parameter value in the test report, pass it to the parameter() function.
The options argument, if given, must be an object with two optional properties: excluded and mode.
If
excludedis set totrue, Allure will not use the parameter when comparing the current test result with previous ones in the history. See Common pitfall: a test's retries are displayed as separate tests.The
modeaffects how the parameter will be displayed in the report. Available options are:"default"(same as not specifying any mode) — the parameter and its value will be shown in a table along with other parameters."masked"— the parameter will be shown in the table, but its value will be hidden. Use this mode for passwords, tokens and other sensitive parameters."hidden"— the parameter and its value will not be shown in the test report.
Note that even when you use the
"masked"or"hidden"mode, it is still possible to extract the value from theallure-resultsdirectory if you publish it.
import * as allure from "allure-js-commons";
import { describe, test } from "bun:test";
describe("example", () => {
for (const login of ["johndoe", "[email protected]"]) {
test(`Test Authentication as ${login}`, async () => {
await allure.parameter("login", login);
await allure.parameter("time", new Date().toUTCString(), { excluded: true });
// ...
});
}
});import * as allure from "allure-js-commons";
import { describe, test } from "bun:test";
describe("example", () => {
test.each(["johndoe", "[email protected]"])("Test Authentication as %s", async (login) => {
await allure.parameter("login", login);
await allure.parameter("time", new Date().toUTCString(), { excluded: true });
// ...
});
});Attachments
allure.attachment(name: string, content: Buffer | Uint8Array | string, options: ContentType | string | AttachmentOptions): PromiseLike<void>allure.attachmentPath(name: string, path: string, options: ContentType | string | Omit<AttachmentOptions, "encoding">): PromiseLike<void>
Add an attachment to the test result under the given name. Pass either the content directly or the path from which the data will be read.
The options argument controls the media type of the content and the filename extension that will be used if a user downloads the attachment from the test report. You can either specify both options in an object (as shown for the image attachment below) or just specify the media type and let Allure deduce the appropriate filename extension automatically (as shown for the text attachment below). In either case, the media type can be a value from the ContentType enumeration or any string.
import * as allure from "allure-js-commons";
import { ContentType } from "allure-js-commons";
import { describe, test } from "bun:test";
describe("example", () => {
test("Test Authentication", async () => {
// ...
await allure.attachment("Text file", "This is the file content.", ContentType.TEXT);
await allure.attachmentPath("Screenshot", "/path/to/image.png", {
contentType: ContentType.PNG,
fileExtension: "png",
});
});
});