mirror of
https://github.com/Kir-Antipov/mc-publish.git
synced 2024-11-21 16:00:59 -05:00
Implemented ErrorBuilder
class
This commit is contained in:
parent
20e88826d4
commit
1d8d9fdb7c
3 changed files with 171 additions and 0 deletions
77
src/utils/errors/error-builder.ts
Normal file
77
src/utils/errors/error-builder.ts
Normal file
|
@ -0,0 +1,77 @@
|
|||
import { Logger, NULL_LOGGER } from "@/utils/logging";
|
||||
import { FailMode } from "./fail-mode";
|
||||
|
||||
/**
|
||||
* A class for building and handling errors based on a given mode.
|
||||
*/
|
||||
export class ErrorBuilder {
|
||||
/**
|
||||
* The logger to use for logging errors.
|
||||
*/
|
||||
private readonly _logger: Logger;
|
||||
|
||||
/**
|
||||
* The accumulated errors.
|
||||
*/
|
||||
private readonly _errors: Error[];
|
||||
|
||||
/**
|
||||
* Constructs a new {@link ErrorBuilder} instance.
|
||||
*
|
||||
* @param logger - The logger to use for logging errors.
|
||||
*/
|
||||
constructor(logger?: Logger) {
|
||||
this._logger = logger || NULL_LOGGER;
|
||||
this._errors = [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if any errors have been appended.
|
||||
*
|
||||
* @returns `true` if there are errors; otherwise, `false`.
|
||||
*/
|
||||
get hasErrors(): boolean {
|
||||
return this._errors.length > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends an error to the builder, handling it according to the provided mode.
|
||||
*
|
||||
* @param error - The error to append.
|
||||
* @param mode - The mode to use when handling the error. Defaults to `SKIP` if not provided.
|
||||
*/
|
||||
append(error: Error, mode?: FailMode): void {
|
||||
switch (mode ?? FailMode.SKIP) {
|
||||
case FailMode.WARN:
|
||||
this._logger.error(error);
|
||||
break;
|
||||
case FailMode.SKIP:
|
||||
this._logger.error(error);
|
||||
this._errors.push(error);
|
||||
break;
|
||||
default:
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds an `AggregateError` from the errors appended so far.
|
||||
*
|
||||
* @returns The built error, or `undefined` if no errors have been appended.
|
||||
*/
|
||||
build(): Error | undefined {
|
||||
return this.hasErrors ? new AggregateError(this._errors) : undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds an `AggregateError` from the errors appended so far, and throw it.
|
||||
*
|
||||
* @throws The built error, if any errors have been appended.
|
||||
*/
|
||||
throwIfHasErrors(): void | never {
|
||||
const error = this.build();
|
||||
if (error) {
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,6 +1,7 @@
|
|||
export { isError } from "./error";
|
||||
export { ArgumentError } from "./argument-error";
|
||||
export { ArgumentNullError } from "./argument-null-error";
|
||||
export { ErrorBuilder } from "./error-builder";
|
||||
export { FailMode } from "./fail-mode";
|
||||
export { SoftError, isSoftError } from "./soft-error";
|
||||
export { FileNotFoundError } from "./file-not-found-error";
|
||||
|
|
93
tests/unit/utils/errors/error-builder.spec.ts
Normal file
93
tests/unit/utils/errors/error-builder.spec.ts
Normal file
|
@ -0,0 +1,93 @@
|
|||
import { FailMode } from "@/utils/errors/fail-mode";
|
||||
import { Logger } from "@/utils/logging/logger";
|
||||
import { ErrorBuilder } from "@/utils/errors/error-builder";
|
||||
|
||||
describe("ErrorBuilder", () => {
|
||||
describe("hasErrors", () => {
|
||||
test("returns false if no errors were appended to the builder", () => {
|
||||
const builder = new ErrorBuilder();
|
||||
|
||||
expect(builder.hasErrors).toBe(false);
|
||||
});
|
||||
|
||||
test("returns true if errors were appended to the builder", () => {
|
||||
const builder = new ErrorBuilder();
|
||||
builder.append(new Error());
|
||||
|
||||
expect(builder.hasErrors).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe("append", () => {
|
||||
it("appends an error and logs it when mode is SKIP", () => {
|
||||
const logger = { error: jest.fn() } as unknown as Logger;
|
||||
const builder = new ErrorBuilder(logger);
|
||||
const error = new Error("Test error");
|
||||
|
||||
builder.append(error, FailMode.SKIP);
|
||||
|
||||
expect(logger.error).toHaveBeenCalledTimes(1);
|
||||
expect(logger.error).toHaveBeenCalledWith(error);
|
||||
expect(builder.hasErrors).toBe(true);
|
||||
});
|
||||
|
||||
it("processes an error and logs it when mode is WARN", () => {
|
||||
const logger = { error: jest.fn() } as unknown as Logger;
|
||||
const builder = new ErrorBuilder(logger);
|
||||
const error = new Error("Test error");
|
||||
|
||||
builder.append(error, FailMode.WARN);
|
||||
|
||||
expect(logger.error).toHaveBeenCalledTimes(1);
|
||||
expect(logger.error).toHaveBeenCalledWith(error);
|
||||
expect(builder.hasErrors).toBe(false);
|
||||
});
|
||||
|
||||
it("throws error immediately when mode is FAIL", () => {
|
||||
const logger = { error: jest.fn() } as unknown as Logger;
|
||||
const builder = new ErrorBuilder(logger);
|
||||
const error = new Error("Test error");
|
||||
|
||||
expect(() => builder.append(error, FailMode.FAIL)).toThrow(error);
|
||||
|
||||
expect(logger.error).not.toHaveBeenCalled();
|
||||
expect(builder.hasErrors).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe("build", () => {
|
||||
it("returns undefined when there are no errors", () => {
|
||||
const builder = new ErrorBuilder();
|
||||
|
||||
expect(builder.build()).toBeUndefined();
|
||||
});
|
||||
|
||||
it("returns an AggregateError when there are errors", () => {
|
||||
const error = new Error("Test error");
|
||||
const builder = new ErrorBuilder();
|
||||
|
||||
builder.append(error);
|
||||
const builtError = builder.build();
|
||||
|
||||
expect(builtError).toBeInstanceOf(AggregateError);
|
||||
expect((builtError as AggregateError).errors).toEqual([error]);
|
||||
});
|
||||
});
|
||||
|
||||
describe("throwIfHasErrors", () => {
|
||||
it("does not throw when there are no errors", () => {
|
||||
const builder = new ErrorBuilder();
|
||||
|
||||
expect(() => builder.throwIfHasErrors()).not.toThrow();
|
||||
});
|
||||
|
||||
it("throws an AggregateError when there are errors", () => {
|
||||
const error = new Error("Test error");
|
||||
const builder = new ErrorBuilder();
|
||||
|
||||
builder.append(error);
|
||||
|
||||
expect(() => builder.throwIfHasErrors()).toThrow(new AggregateError([error]));
|
||||
});
|
||||
});
|
||||
});
|
Loading…
Reference in a new issue