chore: update eslint config, update tests, constants

This commit is contained in:
2026-02-17 17:40:38 +05:00
parent c6d16ca9c2
commit 185e80ae0e
21 changed files with 224 additions and 112 deletions
@@ -4,6 +4,13 @@ exports[`Application Constants Logic > Global Contract (Snapshot) > should match
{
"DEFAULT_TEXT_ALIGN": "center",
"IMAGE_SETTINGS": {
"BRIGHTNESS_MAX": 100,
"BRIGHTNESS_MIN": 0,
"CONTRAST_MAX": 150,
"CONTRAST_MIN": 50,
"DEFAULT_BACKGROUND_IMAGE": "./backgrounds/b1.jpg",
"DEFAULT_BRIGHTNESS": 100,
"DEFAULT_CONTRAST": 100,
"MAX_FILE_SIZE": 10485760,
"SUPPORTED_FORMATS": [
"image/jpeg",
@@ -14,7 +21,6 @@ exports[`Application Constants Logic > Global Contract (Snapshot) > should match
],
},
"PANEL_SETTINGS": {
"DEFAULT_BACKGROUND_IMAGE": "./backgrounds/b1.jpg",
"PANEL_HEIGHT_DEFAULT": 100,
"PANEL_HEIGHT_MAX": 200,
"PANEL_WIDTH": 320,
@@ -42,6 +48,7 @@ exports[`Application Constants Logic > Global Contract (Snapshot) > should match
"MAX_TEXT_LENGTH": 100,
"PADDING_X_DEFAULT": 10,
"PADDING_X_MAX": 100,
"PADDING_X_MIN": 0,
"TEXT_COLOR_DEFAULT": "#ffffff",
"VERTICAL_OFFSET_MAX": 100,
"VERTICAL_OFFSET_MIN": -100,
@@ -1,9 +1,11 @@
import ImageManager from "$components/image/ImageManager.svelte";
import { render } from "@testing-library/svelte";
import { describe, it } from "vitest";
import { describe, expect, it } from "vitest";
describe("ImageManager.svelte", () => {
it("should render without crashing", () => {
render(ImageManager);
const { container } = render(ImageManager);
expect(container).toBeTruthy();
});
});
+4 -4
View File
@@ -2,11 +2,11 @@ import Preview from "$components/panel/Preview.svelte";
import { cleanup, render } from "@testing-library/svelte";
import { afterEach, describe, expect, it } from "vitest";
afterEach(() => {
cleanup();
});
describe("Preview.svelte", () => {
afterEach(() => {
cleanup();
});
it("should render without crashing", () => {
const { container } = render(Preview, {
props: {
@@ -1,14 +1,11 @@
import PreviewAll from "$components/panel/PreviewAll.svelte";
import { textsState } from "$states/texts.svelte";
import { render } from "@testing-library/svelte";
import { beforeEach, describe, it } from "vitest";
import { describe, expect, it } from "vitest";
describe("PreviewAll.svelte", () => {
beforeEach(() => {
textsState.texts.length = 0;
});
it("should render without crashing", () => {
render(PreviewAll);
const { container } = render(PreviewAll);
expect(container).toBeTruthy();
});
});
@@ -1,13 +1,11 @@
import TextConfig from "$components/text/TextConfig.svelte";
import { cleanup, render } from "@testing-library/svelte";
import { afterEach, describe, it } from "vitest";
afterEach(() => {
cleanup();
});
import { render } from "@testing-library/svelte";
import { describe, expect, it } from "vitest";
describe("TextConfig.svelte", () => {
it("should render without crashing", () => {
render(TextConfig);
const { container } = render(TextConfig);
expect(container).toBeTruthy();
});
});
@@ -2,11 +2,11 @@ import TextInlineEdit from "$components/text/TextInlineEdit.svelte";
import { cleanup, render, screen } from "@testing-library/svelte";
import { afterEach, describe, expect, it } from "vitest";
afterEach(() => {
cleanup();
});
describe("TextInlineEdit.svelte", () => {
afterEach(() => {
cleanup();
});
it("should render with initial text", () => {
render(TextInlineEdit, {
props: {
+3 -1
View File
@@ -24,11 +24,13 @@ describe("Badge.svelte", () => {
});
it("should render with empty string", () => {
render(Badge, {
const { container } = render(Badge, {
props: {
text: "",
},
});
expect(container.textContent?.trim()).toBe("");
});
it("should render with zero", () => {
+3 -2
View File
@@ -1,6 +1,6 @@
import ColorPicker from "$components/ui/ColorPicker.svelte";
import { render } from "@testing-library/svelte";
import { describe, it } from "vitest";
import { render, screen } from "@testing-library/svelte";
import { describe, expect, it } from "vitest";
describe("ColorPicker.svelte", () => {
it("should render without crashing", () => {
@@ -9,5 +9,6 @@ describe("ColorPicker.svelte", () => {
value: "#ffffff",
},
});
expect(screen.getByRole("button")).toBeInTheDocument();
});
});
+3 -2
View File
@@ -1,6 +1,6 @@
import SelectFont from "$components/ui/SelectFont.svelte";
import { render } from "@testing-library/svelte";
import { describe, it } from "vitest";
import { render, screen } from "@testing-library/svelte";
import { describe, expect, it } from "vitest";
describe("SelectFont.svelte", () => {
it("should render without crashing", () => {
@@ -9,5 +9,6 @@ describe("SelectFont.svelte", () => {
value: "Arial",
},
});
expect(screen.getByRole("combobox")).toBeInTheDocument();
});
});
+1 -1
View File
@@ -57,7 +57,7 @@ describe("Application Constants Logic", () => {
describe("Assets Existence", () => {
it("should verify that the default background image exists", () => {
const { DEFAULT_BACKGROUND_IMAGE } = Constants.PANEL_SETTINGS;
const { DEFAULT_BACKGROUND_IMAGE } = Constants.IMAGE_SETTINGS;
const relativePath = DEFAULT_BACKGROUND_IMAGE.replace(/^\.\//, "");
const fullPath = path.resolve(process.cwd(), "static", relativePath);
+10 -13
View File
@@ -2,7 +2,7 @@ import { DownloadService, type DownloadItem } from "$services/downloadService";
import { saveAs } from "file-saver";
import JSZip from "jszip";
import type { Stage } from "konva/lib/Stage";
import { beforeEach, describe, expect, it, vi } from "vitest";
import { assert, beforeEach, describe, expect, it, vi } from "vitest";
vi.mock("file-saver", () => {
return {
@@ -58,10 +58,9 @@ describe("DownloadService", () => {
"test-panel-1.png",
);
expect(result.success).toBe(false);
if (!result.success) {
expect(result.error).toContain("Konva Stage не найден или не поддерживает toBlob");
}
assert(result.success === false);
expect(result.error).toContain("Konva Stage не найден или не поддерживает toBlob");
});
it("should handle blob creation failure", async () => {
@@ -71,10 +70,9 @@ describe("DownloadService", () => {
const result = await service.downloadPanel(mockKonvaStage, "test-panel-1.png");
expect(result.success).toBe(false);
if (!result.success) {
expect(result.error).toContain("Не удалось создать изображение");
}
assert(result.success === false);
expect(result.error).toContain("Не удалось создать изображение");
});
});
@@ -122,10 +120,9 @@ describe("DownloadService", () => {
];
const result = await service.downloadAll(panels);
expect(result.success).toBe(false);
if (!result.success) {
expect(result.error).toContain("Ошибка сохранения архива");
}
assert(result.success === false);
expect(result.error).toContain("Ошибка сохранения архива");
});
});
});
+52 -52
View File
@@ -1,5 +1,5 @@
import { PANEL_SETTINGS } from "$lib/constants";
import { imageConfigState, ImageConfigState } from "$states/imageConfig.svelte";
import { imageState } from "$states/image.svelte";
import { beforeEach, describe, expect, it, vi } from "vitest";
type ImageEventHandler = ((this: HTMLImageElement, ev?: Event) => void) | null;
@@ -61,15 +61,15 @@ vi.stubGlobal(
},
);
describe("ImageConfigState", () => {
describe("imageState", () => {
beforeEach(() => {
lastOnload = null;
lastOnerror = null;
imageConfigState.reset();
imageState.reset();
});
it("should create new instance with default values", () => {
const newState = new ImageConfigState();
const newState = new imageState();
expect(newState.image).toBeUndefined();
expect(newState.imageLink).toBe("");
expect(newState.imageReady).toBe(false);
@@ -81,136 +81,136 @@ describe("ImageConfigState", () => {
});
it("should initialize with default background image", async () => {
await imageConfigState.uploadImageByLink(PANEL_SETTINGS.DEFAULT_BACKGROUND_IMAGE);
await imageState.uploadImageByLink(PANEL_SETTINGS.DEFAULT_BACKGROUND_IMAGE);
expect(imageConfigState.imageReady).toBe(true);
expect(imageConfigState.image).toBeDefined();
expect(imageConfigState.imageLink).toBe(PANEL_SETTINGS.DEFAULT_BACKGROUND_IMAGE);
expect(imageState.imageReady).toBe(true);
expect(imageState.image).toBeDefined();
expect(imageState.imageLink).toBe(PANEL_SETTINGS.DEFAULT_BACKGROUND_IMAGE);
});
it("should handle manual image upload correctly", async () => {
const testLink = "https://example.com/test.png";
const uploadPromise = imageConfigState.uploadImageByLink(testLink);
const uploadPromise = imageState.uploadImageByLink(testLink);
expect(imageConfigState.imageReady).toBe(false);
expect(imageState.imageReady).toBe(false);
await uploadPromise;
expect(imageConfigState.imageReady).toBe(true);
expect(imageConfigState.imageLink).toBe(testLink);
expect(imageState.imageReady).toBe(true);
expect(imageState.imageLink).toBe(testLink);
});
it("should reset state to defaults", async () => {
await imageConfigState.uploadImageByLink("some-image.png");
imageConfigState.cropLeft = 100;
await imageState.uploadImageByLink("some-image.png");
imageState.cropLeft = 100;
imageConfigState.reset();
imageState.reset();
expect(imageConfigState.imageReady).toBe(false);
expect(imageConfigState.imageLink).toBe("");
expect(imageConfigState.cropLeft).toBe(0);
expect(imageConfigState.image).toBeUndefined();
expect(imageState.imageReady).toBe(false);
expect(imageState.imageLink).toBe("");
expect(imageState.cropLeft).toBe(0);
expect(imageState.image).toBeUndefined();
});
it("should handle image loading error", async () => {
await expect(imageConfigState.uploadImageByLink("error-link")).rejects.toThrow(
await expect(imageState.uploadImageByLink("error-link")).rejects.toThrow(
"Failed to load image",
);
expect(imageConfigState.imageReady).toBe(false);
expect(imageState.imageReady).toBe(false);
});
it("should abort previous upload when new upload starts", async () => {
const upload1 = imageConfigState.uploadImageByLink("test1.jpg");
const upload2 = imageConfigState.uploadImageByLink("test2.jpg");
const upload1 = imageState.uploadImageByLink("test1.jpg");
const upload2 = imageState.uploadImageByLink("test2.jpg");
await expect(upload1).rejects.toThrow("Aborted");
await expect(upload2).resolves.toBeUndefined();
expect(imageConfigState.imageLink).toBe("test2.jpg");
expect(imageState.imageLink).toBe("test2.jpg");
});
it("should cleanup previous image before loading new one", async () => {
await imageConfigState.uploadImageByLink("test1.jpg");
const firstImage = imageConfigState.image;
await imageState.uploadImageByLink("test1.jpg");
const firstImage = imageState.image;
await imageConfigState.uploadImageByLink("test2.jpg");
await imageState.uploadImageByLink("test2.jpg");
expect(firstImage?.onload).toBeNull();
expect(firstImage?.onerror).toBeNull();
});
it("should set crop values", () => {
imageConfigState.cropLeft = 10;
imageConfigState.cropTop = 20;
imageConfigState.cropRight = 30;
imageConfigState.cropBottom = 40;
imageState.cropLeft = 10;
imageState.cropTop = 20;
imageState.cropRight = 30;
imageState.cropBottom = 40;
expect(imageConfigState.cropLeft).toBe(10);
expect(imageConfigState.cropTop).toBe(20);
expect(imageConfigState.cropRight).toBe(30);
expect(imageConfigState.cropBottom).toBe(40);
expect(imageState.cropLeft).toBe(10);
expect(imageState.cropTop).toBe(20);
expect(imageState.cropRight).toBe(30);
expect(imageState.cropBottom).toBe(40);
});
it("should cleanup image event handlers on reset", async () => {
await imageConfigState.uploadImageByLink("test.jpg");
const img = imageConfigState.image;
await imageState.uploadImageByLink("test.jpg");
const img = imageState.image;
imageConfigState.reset();
imageState.reset();
expect(img?.onload).toBeNull();
expect(img?.onerror).toBeNull();
});
it("should abort ongoing upload on reset", async () => {
const upload = imageConfigState.uploadImageByLink("test.jpg");
const upload = imageState.uploadImageByLink("test.jpg");
imageConfigState.reset();
imageState.reset();
await expect(upload).rejects.toThrow("Aborted");
});
it("should cleanup resources on destroy", async () => {
await imageConfigState.uploadImageByLink("test.jpg");
const img = imageConfigState.image;
await imageState.uploadImageByLink("test.jpg");
const img = imageState.image;
imageConfigState.destroy();
imageState.destroy();
expect(imageConfigState.image).toBeUndefined();
expect(imageState.image).toBeUndefined();
expect(img?.onload).toBeNull();
expect(img?.onerror).toBeNull();
});
it("should abort ongoing upload on destroy", async () => {
const upload = imageConfigState.uploadImageByLink("test.jpg");
const upload = imageState.uploadImageByLink("test.jpg");
imageConfigState.destroy();
imageState.destroy();
await expect(upload).rejects.toThrow("Aborted");
});
it("should cover aborted onload branch", async () => {
const promise = imageConfigState.uploadImageByLink("test.png");
const promise = imageState.uploadImageByLink("test.png");
imageConfigState.destroy();
imageState.destroy();
if (lastOnload) {
lastOnload.call(new Image() as HTMLImageElement, new Event("load"));
}
await expect(promise).rejects.toThrow();
expect(imageConfigState.imageReady).toBe(false);
expect(imageState.imageReady).toBe(false);
});
it("should cover aborted onerror branch", async () => {
const promise = imageConfigState.uploadImageByLink("test.png");
const promise = imageState.uploadImageByLink("test.png");
imageConfigState.destroy();
imageState.destroy();
if (lastOnerror) {
lastOnerror.call(new Image() as HTMLImageElement, new Event("load"));
}
await expect(promise).rejects.toThrow();
expect(imageConfigState.imageReady).toBe(false);
expect(imageState.imageReady).toBe(false);
});
});
+14 -7
View File
@@ -1,7 +1,7 @@
import { STATE_DATA, withPersistence } from "$states/persisted.svelte";
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
import { afterAll, afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
const localStorageMock = (() => {
function createMock() {
let store: Record<string, string> = {};
return {
getItem: vi.fn((key: string) => store[key] || null),
@@ -15,13 +15,20 @@ const localStorageMock = (() => {
store = {};
}),
};
})();
Object.defineProperty(globalThis, "localStorage", {
value: localStorageMock,
});
}
describe("persisted.svelte", () => {
let localStorageMock: ReturnType<typeof createMock>;
beforeAll(() => {
localStorageMock = createMock();
vi.stubGlobal("localStorage", localStorageMock);
});
afterAll(() => {
vi.unstubAllGlobals();
});
beforeEach(() => {
localStorageMock.clear();
vi.clearAllMocks();