Skip to content

Commit

Permalink
refactor: add ValidationError.code
Browse files Browse the repository at this point in the history
  • Loading branch information
schoero committed Sep 1, 2024
1 parent 72d0abc commit 99c31f2
Show file tree
Hide file tree
Showing 6 changed files with 90 additions and 2 deletions.
1 change: 0 additions & 1 deletion src/pdf/table.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ export interface PDFTable {
/** Horizontal start position of the table. */
}


export interface PDFRow {
/** Table columns. */
columns: PDFColumn[];
Expand Down
15 changes: 15 additions & 0 deletions src/shared/errors.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { describe, expect, it } from "vitest";

import { getErrorCodeByMessage, ValidationErrors } from "swissqrbill:errors";
import { } from "swissqrbill:shared:cleaner.js";


describe("getErrorCodeByMessage", () => {

it("should return the correct error code", () => {
const key = "ACCOUNT_IS_QR_IBAN_BUT_REFERENCE_IS_MISSING";
expect(getErrorCodeByMessage(ValidationErrors[key])).toBe(key);
});


});
20 changes: 19 additions & 1 deletion src/shared/errors.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,33 @@
/** A {@link ValidationError} is thrown when the data provided to swissqrbill is invalid. */
export class ValidationError extends Error {
constructor(message: string, params?: { [name: string]: string; }) {

/** A stable error code that can be used to identify the error programmatically. */
public code: keyof typeof ValidationErrors;

/** @internal */
constructor(message: ValidationErrors, params?: { [name: string]: string; }) {

const messageWithParams = params
? resolveMessageParams(message, params)
: message;

super(messageWithParams);

this.name = "ValidationError";
this.code = getErrorCodeByMessage(message);

}
}

/** @internal */
export function getErrorCodeByMessage(message: string): keyof typeof ValidationErrors {
const errorCodes = Object.keys(ValidationErrors);
const errorCode = errorCodes.find(key => ValidationErrors[key] === message);

return errorCode as keyof typeof ValidationErrors;
}

/** @internal */
export function resolveMessageParams(message: string, params: { [name: string]: string; }): string {
return Object.entries(params).reduce((message, [key, value]) => {
return message.replace(`{${key}}`, value);
Expand Down
29 changes: 29 additions & 0 deletions tests/integration/validation-error.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { describe, expect, it } from "vitest";

import { ValidationError, ValidationErrors } from "swissqrbill:errors";
import { cleanData } from "swissqrbill:shared:cleaner";
import { validateData } from "swissqrbill:shared:validator";
import { missingCreditor } from "swissqrbill:tests:data/invalid-data";
import { getValidationError } from "swissqrbill:tests:utils/errors";


describe("errors", () => {

it("should be of instance 'Error' and 'ValidationError'", async () => {
expect(getValidationError(() => validateData(cleanData(missingCreditor)))).toBeInstanceOf(Error);
expect(getValidationError(() => validateData(cleanData(missingCreditor)))).toBeInstanceOf(ValidationError);
});

it("should have an error code", async () => {
const code = "CREDITOR_IS_UNDEFINED";
expect(getValidationError(() => validateData(cleanData(missingCreditor)))?.code).toBeDefined();
expect(getValidationError(() => validateData(cleanData(missingCreditor)))?.code).toBe(code);
});

it("should have an error message", async () => {
const code = "CREDITOR_IS_UNDEFINED";
expect(getValidationError(() => validateData(cleanData(missingCreditor)))?.message).toBeDefined();
expect(getValidationError(() => validateData(cleanData(missingCreditor)))?.message).toBe(ValidationErrors[code]);
});

});
15 changes: 15 additions & 0 deletions tests/utils/errors.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { describe, expect, it } from "vitest";

import { ValidationError, ValidationErrors } from "swissqrbill:errors";

import { getValidationError } from "./errors";


describe("error", () => {

it("should return the caught error", () => {
expect(getValidationError(() => { throw new ValidationError(ValidationErrors.ACCOUNT_LENGTH_IS_INVALID); })).toBeInstanceOf(Error);
expect(getValidationError(() => { throw new ValidationError(ValidationErrors.ACCOUNT_LENGTH_IS_INVALID); })?.message).toBe(ValidationErrors.ACCOUNT_LENGTH_IS_INVALID);
});

});
12 changes: 12 additions & 0 deletions tests/utils/errors.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { ValidationError } from "swissqrbill:errors";


export function getValidationError(fn: (...params: unknown[]) => unknown): ValidationError | undefined {
try {
fn();
} catch (error){
if(error instanceof ValidationError){
return error;
}
}
}

0 comments on commit 99c31f2

Please sign in to comment.