diff --git a/tests/unit/errorHandler.test.ts b/tests/unit/errorHandler.test.ts deleted file mode 100644 index 8960357..0000000 --- a/tests/unit/errorHandler.test.ts +++ /dev/null @@ -1,109 +0,0 @@ -import { AppError } from "$lib/error.types"; -import { createError, formatError, logError } from "$lib/utils/errorUtils"; -import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; - -describe("errorHandler", () => { - let consoleErrorSpy: any; - - beforeEach(() => { - consoleErrorSpy = vi.spyOn(console, "error").mockImplementation(() => {}); - }); - - afterEach(() => { - consoleErrorSpy.mockClear(); - vi.restoreAllMocks(); - }); - - describe("formatError", () => { - it("should handle AppError", () => { - const error = new AppError("Test error", "TEST_ERROR", true); - const result = formatError(error); - - expect(result).toBe("Произошла ошибка: Test error"); - }); - - it("should handle standard Error objects", () => { - const error = new Error("Standard error message"); - const result = formatError(error, "Custom prefix"); - - expect(result).toBe("Custom prefix: Standard error message"); - }); - - it("should handle string errors", () => { - const result = formatError("String error", "Custom prefix"); - - expect(result).toBe("Custom prefix: String error"); - }); - - it("should handle unknown error types", () => { - const result = formatError({ some: "object" }, "Custom prefix"); - - expect(result).toBe("Custom prefix: Произошла неизвестная ошибка"); - }); - - it("should use default message when none provided", () => { - const result = formatError({ some: "object" }); - - expect(result).toBe("Произошла ошибка: Произошла неизвестная ошибка"); - }); - }); - - describe("createError", () => { - it("should create AppError with default recoverable flag", () => { - const error = createError("Test message", "TEST_CODE"); - - expect(error).toBeInstanceOf(AppError); - expect(error.message).toBe("Test message"); - expect(error.code).toBe("TEST_CODE"); - }); - - it("should create AppError with details", () => { - const details = { some: "additional info" }; - const error = createError("Test message", "TEST_CODE", details); - - expect(error.details).toBe(details); - }); - }); - - describe("logError", () => { - it("should log error with context", () => { - const error = new Error("Test error"); - const context = "Test context"; - - logError(error, context); - - expect(consoleErrorSpy).toHaveBeenCalledWith("Error occurred:", { - error, - context, - timestamp: expect.any(String), - stack: error.stack, - }); - }); - - it("should log error without context", () => { - const error = new Error("Test error"); - - logError(error); - - expect(consoleErrorSpy).toHaveBeenCalledWith("Error occurred:", { - error, - context: undefined, - timestamp: expect.any(String), - stack: error.stack, - }); - }); - - it("should handle non-Error objects", () => { - const error = "String error"; - - logError(error, "Test context"); - - expect(consoleErrorSpy).toHaveBeenCalledWith("Error occurred:", { - error, - context: "Test context", - timestamp: expect.any(String), - stack: undefined, - }); - }); - }); -}); diff --git a/tests/unit/errorTypes.test.ts b/tests/unit/errorTypes.test.ts new file mode 100644 index 0000000..2be963e --- /dev/null +++ b/tests/unit/errorTypes.test.ts @@ -0,0 +1,207 @@ +import { AppError, ImageError, TextError, CanvasError, StorageError } from "$lib/error.types"; +import { describe, expect, it } from "vitest"; + +describe("error.types", () => { + describe("AppError", () => { + it("should create AppError with message and code", () => { + const error = new AppError("Test error message", "TEST_CODE"); + + expect(error).toBeInstanceOf(Error); + expect(error).toBeInstanceOf(AppError); + expect(error.name).toBe("AppError"); + expect(error.message).toBe("Test error message"); + expect(error.code).toBe("TEST_CODE"); + expect(error.details).toBeUndefined(); + }); + + it("should create AppError with message, code and details", () => { + const details = { userId: 123, action: "test" }; + const error = new AppError("Test error message", "TEST_CODE", details); + + expect(error.details).toEqual(details); + expect(error.message).toBe("Test error message"); + expect(error.code).toBe("TEST_CODE"); + }); + + it("should have stack trace", () => { + const error = new AppError("Test error", "TEST_CODE"); + + expect(error.stack).toBeDefined(); + expect(typeof error.stack).toBe("string"); + }); + + it("should be throwable and catchable", () => { + expect(() => { + throw new AppError("Test error", "TEST_CODE"); + }).toThrow(AppError); + }); + + it("should be catchable as Error", () => { + expect(() => { + throw new AppError("Test error", "TEST_CODE"); + }).toThrow(Error); + }); + }); + + describe("ImageError", () => { + it("should create ImageError with message", () => { + const error = new ImageError("Image loading failed"); + + expect(error).toBeInstanceOf(Error); + expect(error).toBeInstanceOf(AppError); + expect(error).toBeInstanceOf(ImageError); + expect(error.name).toBe("AppError"); + expect(error.message).toBe("Image loading failed"); + expect(error.code).toBe("IMAGE_ERROR"); + }); + + it("should have correct error code", () => { + const error = new ImageError("Test"); + + expect(error.code).toBe("IMAGE_ERROR"); + }); + + it("should be identifiable as ImageError", () => { + const error = new ImageError("Test"); + + expect(error instanceof ImageError).toBe(true); + }); + }); + + describe("TextError", () => { + it("should create TextError with message", () => { + const error = new TextError("Text validation failed"); + + expect(error).toBeInstanceOf(Error); + expect(error).toBeInstanceOf(AppError); + expect(error).toBeInstanceOf(TextError); + expect(error.name).toBe("AppError"); + expect(error.message).toBe("Text validation failed"); + expect(error.code).toBe("TEXT_ERROR"); + }); + + it("should have correct error code", () => { + const error = new TextError("Test"); + + expect(error.code).toBe("TEXT_ERROR"); + }); + + it("should be identifiable as TextError", () => { + const error = new TextError("Test"); + + expect(error instanceof TextError).toBe(true); + }); + }); + + describe("CanvasError", () => { + it("should create CanvasError with message", () => { + const error = new CanvasError("Canvas rendering failed"); + + expect(error).toBeInstanceOf(Error); + expect(error).toBeInstanceOf(AppError); + expect(error).toBeInstanceOf(CanvasError); + expect(error.name).toBe("AppError"); + expect(error.message).toBe("Canvas rendering failed"); + expect(error.code).toBe("CANVAS_ERROR"); + }); + + it("should have correct error code", () => { + const error = new CanvasError("Test"); + + expect(error.code).toBe("CANVAS_ERROR"); + }); + + it("should be identifiable as CanvasError", () => { + const error = new CanvasError("Test"); + + expect(error instanceof CanvasError).toBe(true); + }); + }); + + describe("StorageError", () => { + it("should create StorageError with message", () => { + const error = new StorageError("Storage operation failed"); + + expect(error).toBeInstanceOf(Error); + expect(error).toBeInstanceOf(AppError); + expect(error).toBeInstanceOf(StorageError); + expect(error.name).toBe("AppError"); + expect(error.message).toBe("Storage operation failed"); + expect(error.code).toBe("STORAGE_ERROR"); + }); + + it("should have correct error code", () => { + const error = new StorageError("Test"); + + expect(error.code).toBe("STORAGE_ERROR"); + }); + + it("should be identifiable as StorageError", () => { + const error = new StorageError("Test"); + + expect(error instanceof StorageError).toBe(true); + }); + }); + + describe("ErrorType union", () => { + it("should accept all error types", () => { + const errors: Array = [ + new AppError("Test", "TEST"), + new ImageError("Test"), + new TextError("Test"), + new CanvasError("Test"), + new StorageError("Test"), + ]; + + errors.forEach(error => { + expect(error).toBeInstanceOf(AppError); + expect(error).toBeInstanceOf(Error); + }); + }); + + it("should allow type narrowing with instanceof", () => { + const errors: Array = [ + new ImageError("Test"), + new TextError("Test"), + ]; + + const imageErrors = errors.filter(e => e instanceof ImageError); + const textErrors = errors.filter(e => e instanceof TextError); + + expect(imageErrors).toHaveLength(1); + expect(textErrors).toHaveLength(1); + }); + }); + + describe("Error handling patterns", () => { + it("should handle errors in try-catch blocks", () => { + let caughtError: AppError | null = null; + + try { + throw new ImageError("Image failed to load"); + } catch (error) { + if (error instanceof AppError) { + caughtError = error; + } + } + + expect(caughtError).not.toBeNull(); + expect(caughtError?.code).toBe("IMAGE_ERROR"); + }); + + it("should preserve error details through error handling", () => { + const originalError = new AppError("Test", "TEST", { id: 123 }); + let caughtError: AppError | null = null; + + try { + throw originalError; + } catch (error) { + if (error instanceof AppError) { + caughtError = error; + } + } + + expect(caughtError?.details).toEqual({ id: 123 }); + }); + }); +});