diff --git a/packages/allure-cucumberjs/src/CucumberAllureInterface.ts b/packages/allure-cucumberjs/src/CucumberAllureInterface.ts index 43d3736e1..06374cba9 100644 --- a/packages/allure-cucumberjs/src/CucumberAllureInterface.ts +++ b/packages/allure-cucumberjs/src/CucumberAllureInterface.ts @@ -2,6 +2,7 @@ import { Allure, AllureStep, AllureTest, + AttachmentOptions, ContentType, ExecutableItemWrapper, isPromise, @@ -61,14 +62,14 @@ export class CucumberAllureInterface extends Allure { this.step(name, () => {}); // todo status } - attachment(name: string, content: Buffer | string, type: ContentType) { - const file = this.reporter.writeAttachment(content, type); - this.currentExecutable.addAttachment(name, type, file); + attachment(name: string, content: Buffer | string, options: ContentType | string | AttachmentOptions) { + const file = this.reporter.writeAttachment(content, options); + this.currentExecutable.addAttachment(name, options, file); } - testAttachment(name: string, content: Buffer | string, type: ContentType) { - const file = this.reporter.writeAttachment(content, type); - this.currentTest.addAttachment(name, type, file); + testAttachment(name: string, content: Buffer | string, options: ContentType | string | AttachmentOptions) { + const file = this.reporter.writeAttachment(content, options); + this.currentTest.addAttachment(name, options, file); } addParameter(name: string, value: string): void { diff --git a/packages/allure-cucumberjs/src/CucumberJSAllureReporter.ts b/packages/allure-cucumberjs/src/CucumberJSAllureReporter.ts index 14a72f8a7..a4eeb9af1 100644 --- a/packages/allure-cucumberjs/src/CucumberJSAllureReporter.ts +++ b/packages/allure-cucumberjs/src/CucumberJSAllureReporter.ts @@ -5,6 +5,7 @@ import { AllureRuntime, AllureStep, AllureTest, + AttachmentOptions, ContentType, ExecutableItemWrapper, LabelName @@ -239,7 +240,9 @@ export class CucumberJSAllureFormatter extends Formatter { if (step.argument !== undefined) { if (step.argument.content !== undefined) { - const file = this.allureRuntime.writeAttachment(step.argument.content, ContentType.TEXT); + const file = this.allureRuntime.writeAttachment(step.argument.content, { + contentType: ContentType.TEXT, + }); allureStep.addAttachment("Text", ContentType.TEXT, file); } if (step.argument.rows !== undefined) { @@ -249,7 +252,7 @@ export class CucumberJSAllureFormatter extends Formatter { cell => cell.value.replace(/\t/g, " ") ).join("\t") ).join("\n"), - ContentType.TSV + { contentType: ContentType.TSV } ); allureStep.addAttachment("Table", ContentType.TSV, file); } @@ -264,7 +267,7 @@ export class CucumberJSAllureFormatter extends Formatter { if ([ContentType.JPEG, ContentType.PNG, ContentType.WEBM].indexOf(type) >= 0) { content = Buffer.from(content, "base64"); } - const file = this.allureRuntime.writeAttachment(content, type); + const file = this.allureRuntime.writeAttachment(content, { contentType: type }); this.currentStep.addAttachment("attached", type, file); } @@ -315,8 +318,8 @@ export class CucumberJSAllureFormatter extends Formatter { return null; } - writeAttachment(content: Buffer | string, type: ContentType): string { - return this.allureRuntime.writeAttachment(content, type); + writeAttachment(content: Buffer | string, options: ContentType | string | AttachmentOptions): string { + return this.allureRuntime.writeAttachment(content, options); } } diff --git a/packages/allure-jasmine/src/JasmineAllureReporter.ts b/packages/allure-jasmine/src/JasmineAllureReporter.ts index d2f36eea1..01608186a 100644 --- a/packages/allure-jasmine/src/JasmineAllureReporter.ts +++ b/packages/allure-jasmine/src/JasmineAllureReporter.ts @@ -3,6 +3,7 @@ import { AllureRuntime, AllureStep, AllureTest, + AttachmentOptions, ContentType, ExecutableItemWrapper, isPromise, @@ -65,8 +66,8 @@ export class JasmineAllureReporter implements jasmine.CustomReporter { return this.runningExecutable; } - writeAttachment(content: Buffer | string, type: ContentType): string { - return this.runtime.writeAttachment(content, type); + writeAttachment(content: Buffer | string, options: ContentType | string | AttachmentOptions): string { + return this.runtime.writeAttachment(content, options); } jasmineStarted(suiteInfo: jasmine.SuiteInfo): void { @@ -315,9 +316,9 @@ export class JasmineAllureInterface extends Allure { this.step(name, () => {}); // todo status } - attachment(name: string, content: Buffer | string, type: ContentType) { - const file = this.reporter.writeAttachment(content, type); - this.currentExecutable.addAttachment(name, type, file); + attachment(name: string, content: Buffer | string, options: ContentType | string | AttachmentOptions) { + const file = this.reporter.writeAttachment(content, options); + this.currentExecutable.addAttachment(name, options, file); } } diff --git a/packages/allure-js-commons/index.ts b/packages/allure-js-commons/index.ts index fefc4ad57..8d67f744a 100644 --- a/packages/allure-js-commons/index.ts +++ b/packages/allure-js-commons/index.ts @@ -8,6 +8,7 @@ export { AllureStep } from "./src/ExecutableItemWrapper"; export { isPromise } from "./src/isPromise"; export { Allure, StepInterface } from "./src/Allure"; export { + AttachmentOptions, Attachment, Category, StepResult, diff --git a/packages/allure-js-commons/src/Allure.ts b/packages/allure-js-commons/src/Allure.ts index 20483fdd7..e462d78d7 100644 --- a/packages/allure-js-commons/src/Allure.ts +++ b/packages/allure-js-commons/src/Allure.ts @@ -1,4 +1,4 @@ -import { Category, LinkType, Status } from "./model"; +import { AttachmentOptions, Category, LinkType, Status } from "./model"; import { ContentType } from "./model"; import { LabelName } from "./model"; import { AllureTest } from "./AllureTest"; @@ -63,7 +63,11 @@ export abstract class Allure { this.currentExecutable.descriptionHtml = html; } - public abstract attachment(name: string, content: Buffer | string, type: ContentType): void; + public abstract attachment( + name: string, + content: Buffer | string, + options: ContentType | string | AttachmentOptions + ): void; public owner(owner: string): void { this.label(LabelName.OWNER, owner); diff --git a/packages/allure-js-commons/src/AllureRuntime.ts b/packages/allure-js-commons/src/AllureRuntime.ts index c948f5645..2c477af37 100644 --- a/packages/allure-js-commons/src/AllureRuntime.ts +++ b/packages/allure-js-commons/src/AllureRuntime.ts @@ -1,4 +1,4 @@ -import { Category, ContentType, TestResult, TestResultContainer } from "./model"; +import { AttachmentOptions, Category, ContentType, TestResult, TestResultContainer } from "./model"; import { v4 as randomUUID } from "uuid"; import { IAllureConfig } from "./AllureConfig"; import { AllureGroup } from "./AllureGroup"; @@ -28,8 +28,11 @@ export class AllureRuntime { this.writer.writeGroup(result); } - writeAttachment(content: Buffer | string, contentType: ContentType): string { - const extension = typeToExtension(contentType); + writeAttachment(content: Buffer | string, options: ContentType | string | AttachmentOptions) { + if (typeof options === "string") { + options = { contentType: options }; + } + const extension = typeToExtension(options); const fileName = `${randomUUID()}-attachment.${extension}`; this.writer.writeAttachment(fileName, content); return fileName; diff --git a/packages/allure-js-commons/src/ExecutableItemWrapper.ts b/packages/allure-js-commons/src/ExecutableItemWrapper.ts index 1fde6d647..f2705ba40 100644 --- a/packages/allure-js-commons/src/ExecutableItemWrapper.ts +++ b/packages/allure-js-commons/src/ExecutableItemWrapper.ts @@ -1,4 +1,5 @@ import { + AttachmentOptions, StatusDetails, StepResult, FixtureResult, @@ -58,9 +59,11 @@ export class ExecutableItemWrapper { this.info.parameters.push({ name, value }); } - public addAttachment(name: string, type: ContentType, fileName: string) { - // eslint-disable-next-line object-shorthand - this.info.attachments.push({ name, type, source: fileName }); + public addAttachment(name: string, options: ContentType | string | AttachmentOptions, fileName: string) { + if (typeof options === "string") { + options = { contentType: options }; + } + this.info.attachments.push({ name, type: options.contentType, source: fileName }); } public startStep(name: string, start?: number): AllureStep { diff --git a/packages/allure-js-commons/src/model.ts b/packages/allure-js-commons/src/model.ts index d4799ce59..0882d37e3 100644 --- a/packages/allure-js-commons/src/model.ts +++ b/packages/allure-js-commons/src/model.ts @@ -4,6 +4,11 @@ export interface Attachment { source: string } +export interface AttachmentOptions { + contentType: ContentType | string, + fileExtension?: string; +} + export interface Label { name: LabelName | string value: string @@ -121,7 +126,6 @@ export enum LabelName { LANGUAGE = "language", } -/* eslint-disable no-undef */ export enum Severity { BLOCKER = "blocker", CRITICAL = "critical", diff --git a/packages/allure-js-commons/src/writers/utils.ts b/packages/allure-js-commons/src/writers/utils.ts index af16fc608..d89c4b166 100644 --- a/packages/allure-js-commons/src/writers/utils.ts +++ b/packages/allure-js-commons/src/writers/utils.ts @@ -1,7 +1,10 @@ -import { ContentType } from "../model"; +import { AttachmentOptions, ContentType } from "../model"; -export function typeToExtension(type: ContentType): string { - switch (type) { +export function typeToExtension(options: AttachmentOptions): string { + if (options.fileExtension) { + return options.fileExtension; + } + switch (options.contentType) { case ContentType.TEXT: return "txt"; case ContentType.XML: @@ -25,5 +28,5 @@ export function typeToExtension(type: ContentType): string { case ContentType.JPEG: return "jpg"; } - throw new Error(`Unrecognized extension: ${type}`); + throw new Error(`Unrecognized extension: ${options.contentType}`); } diff --git a/packages/allure-mocha/src/AllureReporter.ts b/packages/allure-mocha/src/AllureReporter.ts index d8bd927fd..0ce181352 100644 --- a/packages/allure-mocha/src/AllureReporter.ts +++ b/packages/allure-mocha/src/AllureReporter.ts @@ -3,6 +3,7 @@ import { AllureRuntime, AllureStep, AllureTest, + AttachmentOptions, ContentType, ExecutableItemWrapper, LabelName, @@ -134,8 +135,8 @@ export class AllureReporter { this.endTest(status, { message: error.message, trace: error.stack }); } - public writeAttachment(content: Buffer | string, type: ContentType): string { - return this.allureRuntime.writeAttachment(content, type); + public writeAttachment(content: Buffer | string, options: ContentType | string | AttachmentOptions): string { + return this.allureRuntime.writeAttachment(content, options); } public pushStep(step: AllureStep): void { diff --git a/packages/allure-mocha/src/MochaAllure.ts b/packages/allure-mocha/src/MochaAllure.ts index c30657fb7..68f4413e5 100644 --- a/packages/allure-mocha/src/MochaAllure.ts +++ b/packages/allure-mocha/src/MochaAllure.ts @@ -3,6 +3,7 @@ import { AllureRuntime, AllureStep, AllureTest, + AttachmentOptions, ContentType, ExecutableItemWrapper, isPromise, @@ -60,14 +61,18 @@ export class MochaAllure extends Allure { }); // todo status } - public attachment(name: string, content: Buffer | string, type: ContentType): void { - const file = this.reporter.writeAttachment(content, type); - this.currentExecutable.addAttachment(name, type, file); + public attachment(name: string, content: Buffer | string, options: ContentType | string | AttachmentOptions): void { + const file = this.reporter.writeAttachment(content, options); + this.currentExecutable.addAttachment(name, options, file); } - public testAttachment(name: string, content: Buffer | string, type: ContentType): void { - const file = this.reporter.writeAttachment(content, type); - this.currentTest.addAttachment(name, type, file); + public testAttachment( + name: string, + content: Buffer | string, + options: ContentType | string | AttachmentOptions + ): void { + const file = this.reporter.writeAttachment(content, options); + this.currentTest.addAttachment(name, options, file); } public get currentTest(): AllureTest { diff --git a/packages/allure-mocha/test/fixtures/specs/attachment.ts b/packages/allure-mocha/test/fixtures/specs/attachment.ts index 2f138451f..5759d6eb1 100644 --- a/packages/allure-mocha/test/fixtures/specs/attachment.ts +++ b/packages/allure-mocha/test/fixtures/specs/attachment.ts @@ -16,5 +16,9 @@ class AttachmentSubSuite { allure.attachment("step 2 attachment 2", "step 2 attachment 2 content", ContentType.TEXT); }); allure.testAttachment("test attachment 2", "{ \"key\": \"value\" }", ContentType.JSON); + allure.testAttachment("custom-attachment", "{}", { + contentType: "application/vnd.something.custom", + fileExtension: "json", + }); } } diff --git a/packages/allure-mocha/test/specs/attachments.ts b/packages/allure-mocha/test/specs/attachments.ts index b8c8699a1..fdaf9f6a8 100644 --- a/packages/allure-mocha/test/specs/attachments.ts +++ b/packages/allure-mocha/test/specs/attachments.ts @@ -15,11 +15,14 @@ class AttachmentsSuite { expect(test).not.eq(undefined); expect(test.status).eq(Status.PASSED); - expect(test.attachments).length(2); + expect(test.attachments).length(3); expect(test.attachments[0].name).eq("test attachment 1"); expect(test.attachments[0].type).eq("text/plain"); expect(test.attachments[1].name).eq("test attachment 2"); expect(test.attachments[1].type).eq("application/json"); + expect(test.attachments[2].name).eq("custom-attachment"); + expect(test.attachments[2].type).eq("application/vnd.something.custom"); + expect(test.attachments[2].source).matches(/\.json$/); expect(test.steps).length(2);