import { f as BaseReporter, r as icons, t as colors } from "./helpers-C1bD1eod.js";
import { ErrorsPrinter } from "@japa/errors-printer";
import { stripVTControlCharacters } from "node:util";
import { relative } from "node:path";
import string from "@poppinss/string";
var DotReporter = class extends BaseReporter {
	onTestEnd(payload) {
		let output = "";
		if (payload.isTodo) output = colors.cyan(icons.info);
		else if (payload.hasError) output = colors.red(icons.cross);
		else if (payload.isSkipped) output = colors.yellow(icons.bullet);
		else if (payload.isFailing) output = colors.magenta(icons.squareSmallFilled);
		else output = colors.green(icons.tick);
		process.stdout.write(`${output}`);
	}
	async end() {
		console.log("");
		await this.printSummary(this.runner.getSummary());
	}
};
var SpecReporter = class extends BaseReporter {
	#isFirstLoneTest = true;
	#getTestIcon(payload) {
		if (payload.isTodo) return colors.cyan(icons.info);
		if (payload.hasError) return colors.red(icons.cross);
		if (payload.isSkipped) return colors.yellow(icons.bullet);
		if (payload.isFailing) return colors.magenta(icons.squareSmallFilled);
		return colors.green(icons.tick);
	}
	#getTestMessage(payload) {
		const message = payload.title.expanded;
		if (payload.isTodo) return colors.blue(message);
		if (payload.hasError) return colors.red(message);
		if (payload.isSkipped) return colors.yellow(message);
		if (payload.isFailing) return colors.magenta(message);
		return colors.grey(message);
	}
	#getSubText(payload) {
		if (payload.isSkipped && payload.skipReason) return colors.dim(`${icons.branch} ${colors.italic(payload.skipReason)}`);
		if (!payload.isFailing) return;
		if (payload.hasError) {
			const message = payload.errors.find((error) => error.phase === "test")?.error.message ?? `Test marked with ".fails()" must finish with an error`;
			return colors.dim(`${icons.branch} ${colors.italic(message)}`);
		}
		if (payload.failReason) return colors.dim(`${icons.branch} ${colors.italic(payload.failReason)}`);
		const testErrorMessage = payload.errors.find((error) => error.phase === "test");
		if (testErrorMessage && testErrorMessage.error) return colors.dim(`${icons.branch} ${colors.italic(testErrorMessage.error.message)}`);
	}
	#getRelativeFilename(fileName) {
		return relative(process.cwd(), fileName);
	}
	#printTest(payload) {
		const icon = this.#getTestIcon(payload);
		const message = this.#getTestMessage(payload);
		const prefix = payload.isPinned ? colors.yellow("[PINNED] ") : "";
		const indentation = this.currentFileName || this.currentGroupName ? "  " : "";
		const duration = colors.dim(`(${string.milliseconds.format(Number(payload.duration.toFixed(2)))})`);
		const retries = payload.retryAttempt && payload.retryAttempt > 1 ? colors.dim(`(x${payload.retryAttempt}) `) : "";
		let subText = this.#getSubText(payload);
		subText = subText ? `\n${indentation}  ${subText}` : "";
		console.log(`${indentation}${icon} ${prefix}${retries}${message} ${duration}${subText}`);
	}
	#printGroup(payload) {
		const title = this.currentSuiteName !== "default" ? `${this.currentSuiteName} / ${payload.title}` : payload.title;
		const suffix = this.currentFileName ? colors.dim(` (${this.#getRelativeFilename(this.currentFileName)})`) : "";
		console.log(`\n${title}${suffix}`);
	}
	onTestStart() {
		if (this.currentFileName && this.#isFirstLoneTest) console.log(`\n${colors.dim(this.#getRelativeFilename(this.currentFileName))}`);
		this.#isFirstLoneTest = false;
	}
	onTestEnd(payload) {
		this.#printTest(payload);
	}
	onGroupStart(payload) {
		this.#isFirstLoneTest = false;
		this.#printGroup(payload);
	}
	onGroupEnd() {
		this.#isFirstLoneTest = true;
	}
	async end() {
		const summary = this.runner.getSummary();
		await this.printSummary(summary);
	}
};
const isNonErrorSymbol = Symbol("isNonError");
function defineProperty(object, key, value) {
	Object.defineProperty(object, key, {
		value,
		writable: false,
		enumerable: false,
		configurable: false
	});
}
function stringify(value) {
	if (value === void 0) return "undefined";
	if (value === null) return "null";
	if (typeof value === "string") return value;
	if (typeof value === "number" || typeof value === "boolean") return String(value);
	if (typeof value === "bigint") return `${value}n`;
	if (typeof value === "symbol") return value.toString();
	if (typeof value === "function") return `[Function${value.name ? ` ${value.name}` : " (anonymous)"}]`;
	if (value instanceof Error) try {
		return String(value);
	} catch {
		return "<Unserializable error>";
	}
	try {
		return JSON.stringify(value);
	} catch {
		try {
			return String(value);
		} catch {
			return "<Unserializable value>";
		}
	}
}
var NonError = class NonError extends Error {
	constructor(value, { superclass: Superclass = Error } = {}) {
		if (NonError.isNonError(value)) return value;
		if (value instanceof Error) throw new TypeError("Do not pass Error instances to NonError. Throw the error directly instead.");
		super(`Non-error value: ${stringify(value)}`);
		if (Superclass !== Error) Object.setPrototypeOf(this, Superclass.prototype);
		defineProperty(this, "name", "NonError");
		defineProperty(this, isNonErrorSymbol, true);
		defineProperty(this, "isNonError", true);
		defineProperty(this, "value", value);
	}
	static isNonError(value) {
		return value?.[isNonErrorSymbol] === true;
	}
	static #handleCallback(callback, arguments_) {
		try {
			const result = callback(...arguments_);
			if (result && typeof result.then === "function") return (async () => {
				try {
					return await result;
				} catch (error) {
					if (error instanceof Error) throw error;
					throw new NonError(error);
				}
			})();
			return result;
		} catch (error) {
			if (error instanceof Error) throw error;
			throw new NonError(error);
		}
	}
	static try(callback) {
		return NonError.#handleCallback(callback, []);
	}
	static wrap(callback) {
		return (...arguments_) => NonError.#handleCallback(callback, arguments_);
	}
	static [Symbol.hasInstance](instance) {
		return NonError.isNonError(instance);
	}
};
const list = [
	Error,
	EvalError,
	RangeError,
	ReferenceError,
	SyntaxError,
	TypeError,
	URIError,
	AggregateError,
	globalThis.DOMException,
	globalThis.AssertionError,
	globalThis.SystemError
].filter(Boolean).map((constructor) => [constructor.name, constructor]);
const errorConstructors = new Map(list);
const errorFactories = /* @__PURE__ */ new Map();
const errorProperties = [
	{
		property: "name",
		enumerable: false
	},
	{
		property: "message",
		enumerable: false
	},
	{
		property: "stack",
		enumerable: false
	},
	{
		property: "code",
		enumerable: true
	},
	{
		property: "cause",
		enumerable: false
	},
	{
		property: "errors",
		enumerable: false
	}
];
const toJsonWasCalled = /* @__PURE__ */ new WeakSet();
const toJSON = (from) => {
	toJsonWasCalled.add(from);
	const json = from.toJSON();
	toJsonWasCalled.delete(from);
	return json;
};
const newError = (name) => {
	const factory = errorFactories.get(name);
	if (factory) return factory();
	const ErrorConstructor = errorConstructors.get(name) ?? Error;
	return ErrorConstructor === AggregateError ? new ErrorConstructor([]) : new ErrorConstructor();
};
const destroyCircular = ({ from, seen, to, forceEnumerable, maxDepth, depth, useToJSON, serialize }) => {
	if (!to) if (Array.isArray(from)) to = [];
	else if (!serialize && isErrorLike(from)) to = newError(from.name);
	else to = {};
	seen.push(from);
	if (depth >= maxDepth) return to;
	if (useToJSON && typeof from.toJSON === "function" && !toJsonWasCalled.has(from)) return toJSON(from);
	const continueDestroyCircular = (value) => destroyCircular({
		from: value,
		seen: [...seen],
		forceEnumerable,
		maxDepth,
		depth: depth + 1,
		useToJSON,
		serialize
	});
	for (const [key, value] of Object.entries(from)) {
		if (value && value instanceof Uint8Array && value.constructor.name === "Buffer") {
			to[key] = serialize ? "[object Buffer]" : value;
			continue;
		}
		if (value !== null && typeof value === "object" && typeof value.pipe === "function") {
			to[key] = serialize ? "[object Stream]" : value;
			continue;
		}
		if (typeof value === "function") {
			if (!serialize) to[key] = value;
			continue;
		}
		if (serialize && typeof value === "bigint") {
			to[key] = `${value}n`;
			continue;
		}
		if (!value || typeof value !== "object") {
			try {
				to[key] = value;
			} catch {}
			continue;
		}
		if (!seen.includes(value)) {
			to[key] = continueDestroyCircular(value);
			continue;
		}
		to[key] = "[Circular]";
	}
	if (serialize || to instanceof Error) {
		for (const { property, enumerable } of errorProperties) if (from[property] !== void 0 && from[property] !== null) Object.defineProperty(to, property, {
			value: isErrorLike(from[property]) || Array.isArray(from[property]) ? continueDestroyCircular(from[property]) : from[property],
			enumerable: forceEnumerable ? true : enumerable,
			configurable: true,
			writable: true
		});
	}
	return to;
};
function serializeError(value, options = {}) {
	const { maxDepth = Number.POSITIVE_INFINITY, useToJSON = true } = options;
	if (typeof value === "object" && value !== null) return destroyCircular({
		from: value,
		seen: [],
		forceEnumerable: true,
		maxDepth,
		depth: 0,
		useToJSON,
		serialize: true
	});
	if (typeof value === "function") value = "<Function>";
	return destroyCircular({
		from: new NonError(value),
		seen: [],
		forceEnumerable: true,
		maxDepth,
		depth: 0,
		useToJSON,
		serialize: true
	});
}
function isErrorLike(value) {
	return Boolean(value) && typeof value === "object" && typeof value.name === "string" && typeof value.message === "string" && typeof value.stack === "string";
}
var NdJSONReporter = class extends BaseReporter {
	#getRelativeFilename(fileName) {
		return relative(process.cwd(), fileName);
	}
	#serializeErrors(errors) {
		return errors.map((error) => ({
			phase: error.phase,
			error: serializeError(error.error)
		}));
	}
	onTestEnd(payload) {
		console.log(JSON.stringify({
			event: "test:end",
			filePath: this.currentFileName,
			relativePath: this.currentFileName ? this.#getRelativeFilename(this.currentFileName) : void 0,
			title: payload.title,
			duration: payload.duration,
			failReason: payload.failReason,
			isFailing: payload.isFailing,
			skipReason: payload.skipReason,
			isSkipped: payload.isSkipped,
			isTodo: payload.isTodo,
			isPinned: payload.isPinned,
			retryAttempt: payload.retryAttempt,
			retries: payload.retries,
			errors: this.#serializeErrors(payload.errors)
		}));
	}
	onGroupStart(payload) {
		console.log(JSON.stringify({
			event: "group:start",
			title: payload.title
		}));
	}
	onGroupEnd(payload) {
		JSON.stringify({
			event: "group:end",
			title: payload.title,
			errors: this.#serializeErrors(payload.errors)
		});
	}
	onSuiteStart(payload) {
		console.log(JSON.stringify({
			event: "suite:start",
			...payload
		}));
	}
	onSuiteEnd(payload) {
		console.log(JSON.stringify({
			event: "suite:end",
			name: payload.name,
			hasError: payload.hasError,
			errors: this.#serializeErrors(payload.errors)
		}));
	}
	async end() {
		const summary = this.runner.getSummary();
		console.log(JSON.stringify({
			aggregates: summary.aggregates,
			duration: summary.duration,
			failedTestsTitles: summary.failedTestsTitles,
			hasError: summary.hasError
		}));
	}
};
var GithubReporter = class extends BaseReporter {
	escapeMessage(value) {
		return value.replace(/%/g, "%25").replace(/\r/g, "%0D").replace(/\n/g, "%0A");
	}
	escapeProperty(value) {
		return value.replace(/%/g, "%25").replace(/\r/g, "%0D").replace(/\n/g, "%0A").replace(/:/g, "%3A").replace(/,/g, "%2C");
	}
	formatMessage({ command, properties, message }) {
		let result = `::${command}`;
		Object.entries(properties).forEach(([k, v], i) => {
			result += i === 0 ? " " : ",";
			result += `${k}=${this.escapeProperty(v)}`;
		});
		result += `::${this.escapeMessage(message)}`;
		return result;
	}
	async getErrorAnnotation(printer, error) {
		const parsedError = await printer.parseError(error.error);
		if (!("frames" in parsedError)) return;
		const mainFrame = parsedError.frames.find((frame) => frame.type === "app");
		if (!mainFrame) return;
		return this.formatMessage({
			command: "error",
			properties: {
				file: string.toUnixSlash(relative(process.cwd(), mainFrame.fileName)),
				title: error.title,
				line: String(mainFrame.lineNumber),
				column: String(mainFrame.columnNumber)
			},
			message: stripVTControlCharacters(parsedError.message)
		});
	}
	async end() {
		const summary = this.runner.getSummary();
		const errorsList = this.aggregateErrors(summary);
		const errorPrinter = new ErrorsPrinter(this.options);
		for (let error of errorsList) {
			const formatted = await this.getErrorAnnotation(errorPrinter, error);
			if (formatted) console.log(`\n${formatted}`);
		}
	}
};
const spec = (options) => {
	return {
		name: "spec",
		handler: (...args) => new SpecReporter(options).boot(...args)
	};
};
const dot = (options) => {
	return {
		name: "dot",
		handler: (...args) => new DotReporter(options).boot(...args)
	};
};
const ndjson = (options) => {
	return {
		name: "ndjson",
		handler: (...args) => new NdJSONReporter(options).boot(...args)
	};
};
const github = (options) => {
	return {
		name: "github",
		handler: (...args) => new GithubReporter(options).boot(...args)
	};
};
export { spec as i, github as n, ndjson as r, dot as t };
