style: add eslint and prettier, fix style errors

This commit is contained in:
2026-02-13 09:59:19 +05:00
parent 5d6159fe29
commit 387c1751c6
101 changed files with 14596 additions and 12946 deletions
+10 -10
View File
@@ -1,10 +1,10 @@
import CropInline from "$components/image/CropInline.svelte";
import { render } from "@testing-library/svelte";
import { describe, expect, it } from "vitest";
describe("CropInline.svelte", () => {
it("should render without crashing", () => {
const { container } = render(CropInline);
expect(container).toBeInTheDocument();
});
});
import CropInline from "$components/image/CropInline.svelte";
import { render } from "@testing-library/svelte";
import { describe, expect, it } from "vitest";
describe("CropInline.svelte", () => {
it("should render without crashing", () => {
const { container } = render(CropInline);
expect(container).toBeInTheDocument();
});
});
@@ -1,9 +1,9 @@
import ImageManager from "$components/image/ImageManager.svelte";
import { render } from "@testing-library/svelte";
import { describe, it } from "vitest";
describe("ImageManager.svelte", () => {
it("should render without crashing", () => {
render(ImageManager);
});
});
import ImageManager from "$components/image/ImageManager.svelte";
import { render } from "@testing-library/svelte";
import { describe, it } from "vitest";
describe("ImageManager.svelte", () => {
it("should render without crashing", () => {
render(ImageManager);
});
});
+25 -25
View File
@@ -1,25 +1,25 @@
import AppHeader from "$components/layout/AppHeader.svelte";
import { themeState } from "$states/theme.svelte";
import { render, screen } from "@testing-library/svelte";
import userEvent from "@testing-library/user-event";
import { beforeEach, describe, expect, it } from "vitest";
describe("AppHeader.svelte", () => {
beforeEach(() => {
themeState.current = "dark";
});
it("should toggle theme on button click", async () => {
const user = userEvent.setup();
render(AppHeader);
const toggleButton = screen.getByRole("button", { name: /toggle theme/i });
themeState.current = "dark";
await user.click(toggleButton);
expect(themeState.current).toBe("light");
await user.click(toggleButton);
expect(themeState.current).toBe("dark");
});
});
import AppHeader from "$components/layout/AppHeader.svelte";
import { themeState } from "$states/theme.svelte";
import { render, screen } from "@testing-library/svelte";
import userEvent from "@testing-library/user-event";
import { beforeEach, describe, expect, it } from "vitest";
describe("AppHeader.svelte", () => {
beforeEach(() => {
themeState.current = "dark";
});
it("should toggle theme on button click", async () => {
const user = userEvent.setup();
render(AppHeader);
const toggleButton = screen.getByRole("button", { name: /toggle theme/i });
themeState.current = "dark";
await user.click(toggleButton);
expect(themeState.current).toBe("light");
await user.click(toggleButton);
expect(themeState.current).toBe("dark");
});
});
+11 -11
View File
@@ -1,11 +1,11 @@
import { render, screen } from "@testing-library/svelte";
import { describe, expect, it } from "vitest";
import CardTest from "./CardTest.svelte";
describe("Card.svelte", () => {
it("should render without crashing", () => {
render(CardTest);
expect(screen.getByText("Test Title")).toBeInTheDocument();
expect(screen.getByTestId("card-content")).toBeInTheDocument();
});
});
import { render, screen } from "@testing-library/svelte";
import { describe, expect, it } from "vitest";
import CardTest from "./CardTest.svelte";
describe("Card.svelte", () => {
it("should render without crashing", () => {
render(CardTest);
expect(screen.getByText("Test Title")).toBeInTheDocument();
expect(screen.getByTestId("card-content")).toBeInTheDocument();
});
});
+7 -7
View File
@@ -1,7 +1,7 @@
<script>
import Card from "$components/layout/Card.svelte";
</script>
<Card title="Test Title">
<div data-testid="card-content">Test content</div>
</Card>
<script>
import Card from "$components/layout/Card.svelte";
</script>
<Card title="Test Title">
<div data-testid="card-content">Test content</div>
</Card>
+12 -12
View File
@@ -1,12 +1,12 @@
import { render, screen } from "@testing-library/svelte";
import { describe, expect, it } from "vitest";
import InputGroupTest from "./InputGroupTest.svelte";
describe("InputGroup.svelte", () => {
it("should render without crashing", () => {
render(InputGroupTest);
expect(screen.getByTestId("input1")).toBeInTheDocument();
expect(screen.getByTestId("input2")).toBeInTheDocument();
expect(screen.getByTestId("button")).toBeInTheDocument();
});
});
import { render, screen } from "@testing-library/svelte";
import { describe, expect, it } from "vitest";
import InputGroupTest from "./InputGroupTest.svelte";
describe("InputGroup.svelte", () => {
it("should render without crashing", () => {
render(InputGroupTest);
expect(screen.getByTestId("input1")).toBeInTheDocument();
expect(screen.getByTestId("input2")).toBeInTheDocument();
expect(screen.getByTestId("button")).toBeInTheDocument();
});
});
@@ -1,9 +1,9 @@
<script>
import InputGroup from "$components/layout/InputGroup.svelte";
</script>
<InputGroup>
<input type="text" data-testid="input1" />
<input type="text" data-testid="input2" />
<button data-testid="button">Кнопка</button>
</InputGroup>
<script>
import InputGroup from "$components/layout/InputGroup.svelte";
</script>
<InputGroup>
<input type="text" data-testid="input1" />
<input type="text" data-testid="input2" />
<button data-testid="button">Кнопка</button>
</InputGroup>
+10 -10
View File
@@ -1,10 +1,10 @@
import PanelBar from "$components/layout/PanelBar.svelte";
import { render } from "@testing-library/svelte";
import { describe, expect, it } from "vitest";
describe("PanelBar.svelte", () => {
it("should render without crashing", () => {
const { container } = render(PanelBar);
expect(container).toBeInTheDocument();
});
});
import PanelBar from "$components/layout/PanelBar.svelte";
import { render } from "@testing-library/svelte";
import { describe, expect, it } from "vitest";
describe("PanelBar.svelte", () => {
it("should render without crashing", () => {
const { container } = render(PanelBar);
expect(container).toBeInTheDocument();
});
});
@@ -1,12 +1,12 @@
import { render, screen } from "@testing-library/svelte";
import { describe, expect, it } from "vitest";
import SettingsGridTest from "./SettingsGridTest.svelte";
describe("SettingsGrid.svelte", () => {
it("should render without crashing", () => {
render(SettingsGridTest);
expect(screen.getByTestId("item1")).toBeInTheDocument();
expect(screen.getByTestId("item2")).toBeInTheDocument();
expect(screen.getByTestId("item3")).toBeInTheDocument();
});
});
import { render, screen } from "@testing-library/svelte";
import { describe, expect, it } from "vitest";
import SettingsGridTest from "./SettingsGridTest.svelte";
describe("SettingsGrid.svelte", () => {
it("should render without crashing", () => {
render(SettingsGridTest);
expect(screen.getByTestId("item1")).toBeInTheDocument();
expect(screen.getByTestId("item2")).toBeInTheDocument();
expect(screen.getByTestId("item3")).toBeInTheDocument();
});
});
@@ -1,9 +1,9 @@
<script>
import SettingsGrid from "$components/layout/SettingsGrid.svelte";
</script>
<SettingsGrid>
<div data-testid="item1">Item 1</div>
<div data-testid="item2">Item 2</div>
<div data-testid="item3">Item 3</div>
</SettingsGrid>
<script>
import SettingsGrid from "$components/layout/SettingsGrid.svelte";
</script>
<SettingsGrid>
<div data-testid="item1">Item 1</div>
<div data-testid="item2">Item 2</div>
<div data-testid="item3">Item 3</div>
</SettingsGrid>
@@ -1,11 +1,11 @@
import { render, screen } from "@testing-library/svelte";
import { describe, expect, it } from "vitest";
import SettingsRowTest from "./SettingsRowTest.svelte";
describe("SettingsRow.svelte", () => {
it("should render without crashing", () => {
render(SettingsRowTest);
expect(screen.getByText("Test Label")).toBeInTheDocument();
expect(screen.getByTestId("test-input")).toBeInTheDocument();
});
});
import { render, screen } from "@testing-library/svelte";
import { describe, expect, it } from "vitest";
import SettingsRowTest from "./SettingsRowTest.svelte";
describe("SettingsRow.svelte", () => {
it("should render without crashing", () => {
render(SettingsRowTest);
expect(screen.getByText("Test Label")).toBeInTheDocument();
expect(screen.getByTestId("test-input")).toBeInTheDocument();
});
});
@@ -1,7 +1,7 @@
<script>
import SettingsRow from "$components/layout/SettingsRow.svelte";
</script>
<SettingsRow label="Test Label">
<input type="text" data-testid="test-input" />
</SettingsRow>
<script>
import SettingsRow from "$components/layout/SettingsRow.svelte";
</script>
<SettingsRow label="Test Label">
<input type="text" data-testid="test-input" />
</SettingsRow>
+10 -10
View File
@@ -1,10 +1,10 @@
import TextBar from "$components/layout/TextBar.svelte";
import { render } from "@testing-library/svelte";
import { describe, expect, it } from "vitest";
describe("TextBar.svelte", () => {
it("should render without crashing", () => {
const { container } = render(TextBar);
expect(container).toBeInTheDocument();
});
});
import TextBar from "$components/layout/TextBar.svelte";
import { render } from "@testing-library/svelte";
import { describe, expect, it } from "vitest";
describe("TextBar.svelte", () => {
it("should render without crashing", () => {
const { container } = render(TextBar);
expect(container).toBeInTheDocument();
});
});
+32 -32
View File
@@ -1,32 +1,32 @@
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", () => {
it("should render without crashing", () => {
const { container } = render(Preview, {
props: {
text: "Test text",
stage: undefined,
},
});
expect(container).toBeInTheDocument();
});
it("should have stage element", () => {
const { container } = render(Preview, {
props: {
text: "Test",
stage: undefined,
},
});
const stage = container.querySelector("canvas");
expect(stage).toBeInTheDocument();
});
});
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", () => {
it("should render without crashing", () => {
const { container } = render(Preview, {
props: {
text: "Test text",
stage: undefined,
},
});
expect(container).toBeInTheDocument();
});
it("should have stage element", () => {
const { container } = render(Preview, {
props: {
text: "Test",
stage: undefined,
},
});
const stage = container.querySelector("canvas");
expect(stage).toBeInTheDocument();
});
});
+14 -14
View File
@@ -1,14 +1,14 @@
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";
describe("PreviewAll.svelte", () => {
beforeEach(() => {
textsState.texts.length = 0;
});
it("should render without crashing", () => {
render(PreviewAll);
});
});
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";
describe("PreviewAll.svelte", () => {
beforeEach(() => {
textsState.texts.length = 0;
});
it("should render without crashing", () => {
render(PreviewAll);
});
});
@@ -1,46 +1,46 @@
import { SlideDirection } from "$lib/constants";
import { render, screen } from "@testing-library/svelte";
import userEvent from "@testing-library/user-event";
import { describe, expect, it } from "vitest";
import PreviewControlsTest from "./PreviewControlsTest.svelte";
describe("PreviewControls logic", () => {
it("should increment current and update direction on next click", async () => {
const user = userEvent.setup();
render(PreviewControlsTest, { props: { current: 0, max: 3 } });
const nextBtn = screen.getByRole("button", { name: /next slide/i });
await user.click(nextBtn);
expect(screen.getByTestId("current").textContent).toBe("1");
expect(screen.getByTestId("direction").textContent).toBe(SlideDirection.NEXT);
});
it("should decrement current on prev click", async () => {
const user = userEvent.setup();
render(PreviewControlsTest, { props: { current: 2, max: 3 } });
const prevBtn = screen.getByRole("button", { name: /previous slide/i });
await user.click(prevBtn);
expect(screen.getByTestId("current").textContent).toBe("1");
});
it("should handle boundaries and disable buttons", async () => {
const user = userEvent.setup();
render(PreviewControlsTest, { props: { current: 0, max: 2 } });
const prevBtn = screen.getByRole("button", { name: /previous slide/i });
const nextBtn = screen.getByRole("button", { name: /next slide/i });
expect(prevBtn).toBeDisabled();
await user.click(nextBtn);
expect(screen.getByTestId("current").textContent).toBe("1");
expect(nextBtn).toBeDisabled();
expect(prevBtn).not.toBeDisabled();
});
});
import { SlideDirection } from "$lib/constants";
import { render, screen } from "@testing-library/svelte";
import userEvent from "@testing-library/user-event";
import { describe, expect, it } from "vitest";
import PreviewControlsTest from "./PreviewControlsTest.svelte";
describe("PreviewControls logic", () => {
it("should increment current and update direction on next click", async () => {
const user = userEvent.setup();
render(PreviewControlsTest, { props: { current: 0, max: 3 } });
const nextBtn = screen.getByRole("button", { name: /next slide/i });
await user.click(nextBtn);
expect(screen.getByTestId("current").textContent).toBe("1");
expect(screen.getByTestId("direction").textContent).toBe(SlideDirection.NEXT);
});
it("should decrement current on prev click", async () => {
const user = userEvent.setup();
render(PreviewControlsTest, { props: { current: 2, max: 3 } });
const prevBtn = screen.getByRole("button", { name: /previous slide/i });
await user.click(prevBtn);
expect(screen.getByTestId("current").textContent).toBe("1");
});
it("should handle boundaries and disable buttons", async () => {
const user = userEvent.setup();
render(PreviewControlsTest, { props: { current: 0, max: 2 } });
const prevBtn = screen.getByRole("button", { name: /previous slide/i });
const nextBtn = screen.getByRole("button", { name: /next slide/i });
expect(prevBtn).toBeDisabled();
await user.click(nextBtn);
expect(screen.getByTestId("current").textContent).toBe("1");
expect(nextBtn).toBeDisabled();
expect(prevBtn).not.toBeDisabled();
});
});
@@ -1,13 +1,13 @@
<script lang="ts">
import PreviewControls from "$components/panel/PreviewControls.svelte";
import { SlideDirection } from "$lib/constants";
let { current = 0, max = 5 } = $props();
let direction = $state(SlideDirection.NEXT);
</script>
<PreviewControls bind:current bind:direction {max} />
<div data-testid="current">{current}</div>
<div data-testid="direction">{direction}</div>
<script lang="ts">
import PreviewControls from "$components/panel/PreviewControls.svelte";
import { SlideDirection } from "$lib/constants";
let { current = 0, max = 5 } = $props();
let direction = $state(SlideDirection.NEXT);
</script>
<PreviewControls bind:current bind:direction {max} />
<div data-testid="current">{current}</div>
<div data-testid="direction">{direction}</div>
+103 -102
View File
@@ -1,102 +1,103 @@
import PreviewManager from "$components/panel/PreviewManager.svelte";
import { downloadService } from "$services/downloadService";
import { konvaStageState } from "$states/konvaStage.svelte";
import { STATE_DATA } from "$states/persisted.svelte";
import { textsState } from "$states/texts.svelte";
import { render, screen, waitFor } from "@testing-library/svelte";
import userEvent from "@testing-library/user-event";
import { beforeEach, describe, expect, it, vi } from "vitest";
vi.mock("$services/downloadService", () => ({
downloadService: {
downloadAll: vi.fn(),
downloadPanel: vi.fn(),
},
}));
vi.mock("./Preview.svelte", () => ({
default: { render: () => ({}) },
}));
describe("PreviewManager Integration", () => {
beforeEach(() => {
vi.clearAllMocks();
textsState[STATE_DATA] = [];
});
it("should show empty state by aria-label when no texts", () => {
render(PreviewManager);
expect(screen.getByLabelText(/Empty texts info/i)).toBeInTheDocument();
});
it("should toggle navigation buttons availability based on texts length", async () => {
textsState[STATE_DATA] = ["1", "2"];
render(PreviewManager);
const nextBtn = screen.getByRole("button", { name: /next slide/i });
const prevBtn = screen.getByRole("button", { name: /previous slide/i });
expect(nextBtn).not.toBeDisabled();
expect(prevBtn).toBeDisabled();
});
it("should send correct data to downloadAll service", async () => {
const user = userEvent.setup();
textsState[STATE_DATA] = ["Apple", "Banana"];
render(PreviewManager);
await user.click(screen.getByRole("button", { name: /download all/i }));
expect(downloadService.downloadAll).toHaveBeenCalledWith(
expect.arrayContaining([
expect.objectContaining({ filename: "Apple" }),
expect.objectContaining({ filename: "Banana" }),
]),
);
});
it("should call downloadPanel with current active text", async () => {
const user = userEvent.setup();
textsState[STATE_DATA] = ["First", "Second"];
konvaStageState.stage = { node: { id: "stage-ref" } } as any;
render(PreviewManager);
// Переходим на второй слайд
await user.click(screen.getByRole("button", { name: /next slide/i }));
await user.click(screen.getByRole("button", { name: /download current/i }));
expect(downloadService.downloadPanel).toHaveBeenCalledWith(expect.anything(), "Second");
});
it("should return to empty state when texts are removed", async () => {
textsState[STATE_DATA] = ["Temp"];
render(PreviewManager);
expect(screen.queryByLabelText(/Empty texts info/i)).not.toBeInTheDocument();
textsState[STATE_DATA] = [];
await waitFor(() => {
expect(screen.getByLabelText(/Empty texts info/i)).toBeInTheDocument();
});
});
it("should automatically correct current index on items deletion", async () => {
const user = userEvent.setup();
textsState[STATE_DATA] = ["1", "2", "3"];
render(PreviewManager);
// Уходим на последний слайд
await user.click(screen.getByRole("button", { name: /next slide/i }));
await user.click(screen.getByRole("button", { name: /next slide/i }));
// Удаляем элементы. Индекс должен упасть с 2 до 0
textsState[STATE_DATA] = ["Only one left"];
await waitFor(() => {
// Проверяем, что кнопка "Next" заблокировалась (значит мы на последнем/единственном)
expect(screen.getByRole("button", { name: /next slide/i })).toBeDisabled();
expect(screen.getByRole("button", { name: /previous slide/i })).toBeDisabled();
});
});
});
import PreviewManager from "$components/panel/PreviewManager.svelte";
import { downloadService } from "$services/downloadService";
import { konvaStageState } from "$states/konvaStage.svelte";
import { STATE_DATA } from "$states/persisted.svelte";
import { textsState } from "$states/texts.svelte";
import { render, screen, waitFor } from "@testing-library/svelte";
import userEvent from "@testing-library/user-event";
import type { Stage } from "svelte-konva";
import { beforeEach, describe, expect, it, vi } from "vitest";
vi.mock("$services/downloadService", () => ({
downloadService: {
downloadAll: vi.fn(),
downloadPanel: vi.fn(),
},
}));
vi.mock("./Preview.svelte", () => ({
default: { render: () => ({}) },
}));
describe("PreviewManager Integration", () => {
beforeEach(() => {
vi.clearAllMocks();
textsState[STATE_DATA] = [];
});
it("should show empty state by aria-label when no texts", () => {
render(PreviewManager);
expect(screen.getByLabelText(/Empty texts info/i)).toBeInTheDocument();
});
it("should toggle navigation buttons availability based on texts length", async () => {
textsState[STATE_DATA] = ["1", "2"];
render(PreviewManager);
const nextBtn = screen.getByRole("button", { name: /next slide/i });
const prevBtn = screen.getByRole("button", { name: /previous slide/i });
expect(nextBtn).not.toBeDisabled();
expect(prevBtn).toBeDisabled();
});
it("should send correct data to downloadAll service", async () => {
const user = userEvent.setup();
textsState[STATE_DATA] = ["Apple", "Banana"];
render(PreviewManager);
await user.click(screen.getByRole("button", { name: /download all/i }));
expect(downloadService.downloadAll).toHaveBeenCalledWith(
expect.arrayContaining([
expect.objectContaining({ filename: "Apple" }),
expect.objectContaining({ filename: "Banana" }),
]),
);
});
it("should call downloadPanel with current active text", async () => {
const user = userEvent.setup();
textsState[STATE_DATA] = ["First", "Second"];
konvaStageState.stage = { node: { id: "stage-ref" } } as unknown as Stage;
render(PreviewManager);
// Переходим на второй слайд
await user.click(screen.getByRole("button", { name: /next slide/i }));
await user.click(screen.getByRole("button", { name: /download current/i }));
expect(downloadService.downloadPanel).toHaveBeenCalledWith(expect.anything(), "Second");
});
it("should return to empty state when texts are removed", async () => {
textsState[STATE_DATA] = ["Temp"];
render(PreviewManager);
expect(screen.queryByLabelText(/Empty texts info/i)).not.toBeInTheDocument();
textsState[STATE_DATA] = [];
await waitFor(() => {
expect(screen.getByLabelText(/Empty texts info/i)).toBeInTheDocument();
});
});
it("should automatically correct current index on items deletion", async () => {
const user = userEvent.setup();
textsState[STATE_DATA] = ["1", "2", "3"];
render(PreviewManager);
// Уходим на последний слайд
await user.click(screen.getByRole("button", { name: /next slide/i }));
await user.click(screen.getByRole("button", { name: /next slide/i }));
// Удаляем элементы. Индекс должен упасть с 2 до 0
textsState[STATE_DATA] = ["Only one left"];
await waitFor(() => {
// Проверяем, что кнопка "Next" заблокировалась (значит мы на последнем/единственном)
expect(screen.getByRole("button", { name: /next slide/i })).toBeDisabled();
expect(screen.getByRole("button", { name: /previous slide/i })).toBeDisabled();
});
});
});
+13 -13
View File
@@ -1,13 +1,13 @@
import TextConfig from "$components/text/TextConfig.svelte";
import { cleanup, render } from "@testing-library/svelte";
import { afterEach, describe, it } from "vitest";
afterEach(() => {
cleanup();
});
describe("TextConfig.svelte", () => {
it("should render without crashing", () => {
render(TextConfig);
});
});
import TextConfig from "$components/text/TextConfig.svelte";
import { cleanup, render } from "@testing-library/svelte";
import { afterEach, describe, it } from "vitest";
afterEach(() => {
cleanup();
});
describe("TextConfig.svelte", () => {
it("should render without crashing", () => {
render(TextConfig);
});
});
@@ -1,36 +1,36 @@
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", () => {
it("should render with initial text", () => {
render(TextInlineEdit, {
props: {
id: 1,
text: "Test text",
ondelete: () => {},
},
});
const input = screen.getByRole("textbox");
expect(input).toBeInTheDocument();
expect(input).toHaveValue("Test text");
});
it("should render with empty text", () => {
render(TextInlineEdit, {
props: {
id: 1,
text: "",
ondelete: () => {},
},
});
const input = screen.getByRole("textbox");
expect(input).toHaveValue("");
});
});
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", () => {
it("should render with initial text", () => {
render(TextInlineEdit, {
props: {
id: 1,
text: "Test text",
ondelete: () => {},
},
});
const input = screen.getByRole("textbox");
expect(input).toBeInTheDocument();
expect(input).toHaveValue("Test text");
});
it("should render with empty text", () => {
render(TextInlineEdit, {
props: {
id: 1,
text: "",
ondelete: () => {},
},
});
const input = screen.getByRole("textbox");
expect(input).toHaveValue("");
});
});
+61 -61
View File
@@ -1,61 +1,61 @@
import TextInput from "$components/text/TextInput.svelte";
import { render, screen } from "@testing-library/svelte";
import userEvent from "@testing-library/user-event";
import { describe, expect, it, vi } from "vitest";
describe("TextInput.svelte", () => {
it("should render with initial value", () => {
render(TextInput, {
props: {
text: "Test text",
onenter: vi.fn(),
ariaLabel: "Test input",
},
});
const input = screen.getByRole("textbox", { name: /test input/i });
expect(input).toBeInTheDocument();
expect(input).toHaveValue("Test text");
});
it("should update value on input", async () => {
const user = userEvent.setup();
render(TextInput, {
props: {
text: "Initial",
onenter: vi.fn(),
ariaLabel: "Test input",
},
});
const input = screen.getByRole("textbox", { name: /test input/i });
await user.clear(input);
await user.type(input, "Updated text");
expect(input).toHaveValue("Updated text");
});
it("should call onenter only on Enter key and not on others", async () => {
const user = userEvent.setup();
const onenterSpy = vi.fn();
render(TextInput, {
props: {
text: "test",
onenter: onenterSpy,
ariaLabel: "Test input",
},
});
const input = screen.getByRole("textbox", { name: /test input/i });
await user.type(input, "abc");
expect(onenterSpy).not.toHaveBeenCalled();
await user.keyboard("{Escape}");
expect(onenterSpy).not.toHaveBeenCalled();
await user.type(input, "{Enter}");
expect(onenterSpy).toHaveBeenCalledTimes(1);
});
});
import TextInput from "$components/text/TextInput.svelte";
import { render, screen } from "@testing-library/svelte";
import userEvent from "@testing-library/user-event";
import { describe, expect, it, vi } from "vitest";
describe("TextInput.svelte", () => {
it("should render with initial value", () => {
render(TextInput, {
props: {
text: "Test text",
onenter: vi.fn(),
ariaLabel: "Test input",
},
});
const input = screen.getByRole("textbox", { name: /test input/i });
expect(input).toBeInTheDocument();
expect(input).toHaveValue("Test text");
});
it("should update value on input", async () => {
const user = userEvent.setup();
render(TextInput, {
props: {
text: "Initial",
onenter: vi.fn(),
ariaLabel: "Test input",
},
});
const input = screen.getByRole("textbox", { name: /test input/i });
await user.clear(input);
await user.type(input, "Updated text");
expect(input).toHaveValue("Updated text");
});
it("should call onenter only on Enter key and not on others", async () => {
const user = userEvent.setup();
const onenterSpy = vi.fn();
render(TextInput, {
props: {
text: "test",
onenter: onenterSpy,
ariaLabel: "Test input",
},
});
const input = screen.getByRole("textbox", { name: /test input/i });
await user.type(input, "abc");
expect(onenterSpy).not.toHaveBeenCalled();
await user.keyboard("{Escape}");
expect(onenterSpy).not.toHaveBeenCalled();
await user.type(input, "{Enter}");
expect(onenterSpy).toHaveBeenCalledTimes(1);
});
});
+60 -60
View File
@@ -1,60 +1,60 @@
import TextManager from "$components/text/TextManager.svelte";
import { textsState } from "$states/texts.svelte";
import { render, screen } from "@testing-library/svelte";
import userEvent from "@testing-library/user-event";
import { beforeEach, describe, expect, it } from "vitest";
describe("TextManager", () => {
beforeEach(() => {
textsState.clear();
});
it("should add text to state and clear input on button click", async () => {
const user = userEvent.setup();
render(TextManager);
const input = screen.getByRole("textbox", { name: /input new text/i });
const addButton = screen.getByRole("button", { name: /add text/i });
await user.type(input, "New Note");
await user.click(addButton);
expect(textsState.texts).toHaveLength(1);
expect(textsState.texts[0].text).toBe("New Note");
expect(input).toHaveValue("");
});
it("should add text on enter key", async () => {
const user = userEvent.setup();
render(TextManager);
const input = screen.getByRole("textbox", { name: /input new text/i });
await user.type(input, "Enter Note{Enter}");
expect(textsState.texts).toHaveLength(1);
expect(textsState.texts[0].text).toBe("Enter Note");
});
it("should display all items from state", async () => {
textsState.addText("First");
textsState.addText("Second");
render(TextManager);
const items = screen.getAllByRole("listitem");
expect(items).toHaveLength(2);
});
it("should remove text from state when delete button is clicked", async () => {
const user = userEvent.setup();
textsState.addText("To be deleted");
render(TextManager);
const deleteBtn = screen.getByRole("button", { name: /delete/i });
await user.click(deleteBtn);
expect(textsState.texts).toHaveLength(0);
});
});
import TextManager from "$components/text/TextManager.svelte";
import { textsState } from "$states/texts.svelte";
import { render, screen } from "@testing-library/svelte";
import userEvent from "@testing-library/user-event";
import { beforeEach, describe, expect, it } from "vitest";
describe("TextManager", () => {
beforeEach(() => {
textsState.clear();
});
it("should add text to state and clear input on button click", async () => {
const user = userEvent.setup();
render(TextManager);
const input = screen.getByRole("textbox", { name: /input new text/i });
const addButton = screen.getByRole("button", { name: /add text/i });
await user.type(input, "New Note");
await user.click(addButton);
expect(textsState.texts).toHaveLength(1);
expect(textsState.texts[0].text).toBe("New Note");
expect(input).toHaveValue("");
});
it("should add text on enter key", async () => {
const user = userEvent.setup();
render(TextManager);
const input = screen.getByRole("textbox", { name: /input new text/i });
await user.type(input, "Enter Note{Enter}");
expect(textsState.texts).toHaveLength(1);
expect(textsState.texts[0].text).toBe("Enter Note");
});
it("should display all items from state", async () => {
textsState.addText("First");
textsState.addText("Second");
render(TextManager);
const items = screen.getAllByRole("listitem");
expect(items).toHaveLength(2);
});
it("should remove text from state when delete button is clicked", async () => {
const user = userEvent.setup();
textsState.addText("To be deleted");
render(TextManager);
const deleteBtn = screen.getByRole("button", { name: /delete/i });
await user.click(deleteBtn);
expect(textsState.texts).toHaveLength(0);
});
});
+43 -44
View File
@@ -1,44 +1,43 @@
import { TextAlign } from "$lib/constants";
import { render, screen } from "@testing-library/svelte";
import userEvent from "@testing-library/user-event";
import { describe, expect, it } from "vitest";
import AlignmentTest from "./AlignmentTest.svelte";
describe("Alignment.svelte", () => {
it("should update state for every button by clicking in sequence", async () => {
const user = userEvent.setup();
render(AlignmentTest);
const buttons = screen.getAllByRole("radio");
const stateDisplay = screen.getByTestId("align-value");
const allButtonsToClick = [...buttons, buttons[0]];
for (const button of allButtonsToClick) {
const label = button.getAttribute("aria-label")?.toLowerCase() || "";
await user.click(button);
const finalValue = stateDisplay.textContent?.toLowerCase() || "";
expect(label).toContain(finalValue);
}
});
it("should have initial state from props", () => {
render(AlignmentTest, { props: { align: TextAlign.RIGHT } });
expect(screen.getByTestId("align-value").textContent).toBe(TextAlign.RIGHT);
});
it("should sync with initial state and change state", async () => {
const user = userEvent.setup();
const { rerender } = render(AlignmentTest, { props: { align: TextAlign.RIGHT } });
const stateDisplay = screen.getByTestId("align-value");
expect(stateDisplay.textContent).toBe(TextAlign.RIGHT);
await rerender({ align: TextAlign.CENTER });
const centerBtn = screen.getByRole("radio", { name: new RegExp(TextAlign.CENTER, "i") });
expect(centerBtn).toBeChecked();
});
});
import { TextAlign } from "$lib/constants";
import { render, screen } from "@testing-library/svelte";
import userEvent from "@testing-library/user-event";
import { describe, expect, it } from "vitest";
import AlignmentTest from "./AlignmentTest.svelte";
describe("Alignment.svelte", () => {
it("should update state for every button by clicking in sequence", async () => {
const user = userEvent.setup();
render(AlignmentTest);
const buttons = screen.getAllByRole("radio");
const stateDisplay = screen.getByTestId("align-value");
const allButtonsToClick = [...buttons, buttons[0]];
for (const button of allButtonsToClick) {
const label = button.getAttribute("aria-label")?.toLowerCase() || "";
await user.click(button);
const finalValue = stateDisplay.textContent?.toLowerCase() || "";
expect(label).toContain(finalValue);
}
});
it("should have initial state from props", () => {
render(AlignmentTest, { props: { align: TextAlign.RIGHT } });
expect(screen.getByTestId("align-value").textContent).toBe(TextAlign.RIGHT);
});
it("should sync with initial state and change state", async () => {
const { rerender } = render(AlignmentTest, { props: { align: TextAlign.RIGHT } });
const stateDisplay = screen.getByTestId("align-value");
expect(stateDisplay.textContent).toBe(TextAlign.RIGHT);
await rerender({ align: TextAlign.CENTER });
const centerBtn = screen.getByRole("radio", { name: new RegExp(TextAlign.CENTER, "i") });
expect(centerBtn).toBeChecked();
});
});
+11 -11
View File
@@ -1,11 +1,11 @@
<script lang="ts">
import Alignment from "$components/ui/Alignment.svelte";
import { TextAlign } from "$lib/constants";
let { align = TextAlign.LEFT } = $props();
</script>
<Alignment bind:align />
<div data-testid="align-value">{align}</div>
<script lang="ts">
import Alignment from "$components/ui/Alignment.svelte";
import { TextAlign } from "$lib/constants";
let { align = TextAlign.LEFT } = $props();
</script>
<Alignment bind:align />
<div data-testid="align-value">{align}</div>
+43 -43
View File
@@ -1,43 +1,43 @@
import Badge from "$components/ui/Badge.svelte";
import { render, screen } from "@testing-library/svelte";
import { describe, expect, it } from "vitest";
describe("Badge.svelte", () => {
it("should render with string text", () => {
render(Badge, {
props: {
text: "Test Badge",
},
});
expect(screen.getByText("Test Badge")).toBeInTheDocument();
});
it("should render with number text", () => {
render(Badge, {
props: {
text: 42,
},
});
expect(screen.getByText("42")).toBeInTheDocument();
});
it("should render with empty string", () => {
render(Badge, {
props: {
text: "",
},
});
});
it("should render with zero", () => {
render(Badge, {
props: {
text: 0,
},
});
expect(screen.getByText("0")).toBeInTheDocument();
});
});
import Badge from "$components/ui/Badge.svelte";
import { render, screen } from "@testing-library/svelte";
import { describe, expect, it } from "vitest";
describe("Badge.svelte", () => {
it("should render with string text", () => {
render(Badge, {
props: {
text: "Test Badge",
},
});
expect(screen.getByText("Test Badge")).toBeInTheDocument();
});
it("should render with number text", () => {
render(Badge, {
props: {
text: 42,
},
});
expect(screen.getByText("42")).toBeInTheDocument();
});
it("should render with empty string", () => {
render(Badge, {
props: {
text: "",
},
});
});
it("should render with zero", () => {
render(Badge, {
props: {
text: 0,
},
});
expect(screen.getByText("0")).toBeInTheDocument();
});
});
+95 -95
View File
@@ -1,95 +1,95 @@
import Button from "$components/ui/Button.svelte";
import { render, screen } from "@testing-library/svelte";
import userEvent from "@testing-library/user-event";
import { describe, expect, it, vi } from "vitest";
import MockIcon from "./MockIcon.svelte";
describe("Button.svelte", () => {
it("should render with icon and label", () => {
render(Button, {
props: {
icon: MockIcon,
label: "Test Button",
ariaLabel: "Test button",
},
});
expect(screen.getByText("Test Button")).toBeInTheDocument();
expect(screen.getByRole("button", { name: /test button/i })).toBeInTheDocument();
});
it("should render with icon only", () => {
render(Button, {
props: {
icon: MockIcon,
ariaLabel: "Test button",
},
});
const button = screen.getByRole("button", { name: /test button/i });
expect(button).toBeInTheDocument();
expect(button.textContent.trim()).toBe("");
});
it("should call onclick handler", async () => {
const onclick = vi.fn();
const user = userEvent.setup();
render(Button, {
props: {
icon: MockIcon,
label: "Click me",
onclick,
ariaLabel: "Test button",
},
});
const button = screen.getByRole("button", { name: /test button/i });
await user.click(button);
expect(onclick).toHaveBeenCalledTimes(1);
});
it("should not throw error when clicked without onclick prop", async () => {
const user = userEvent.setup();
render(Button, {
props: {
icon: MockIcon,
label: "Click me",
ariaLabel: "Test button",
},
});
const button = screen.getByRole("button", { name: /test button/i });
expect(() => user.click(button)).not.toThrow();
});
it("should be disabled when disabled prop is true", () => {
render(Button, {
props: {
icon: MockIcon,
label: "Disabled",
disabled: true,
ariaLabel: "Test button",
},
});
const button = screen.getByRole("button", { name: /test button/i });
expect(button).toBeDisabled();
});
it("should not be disabled by default", () => {
render(Button, {
props: {
icon: MockIcon,
label: "Enabled",
ariaLabel: "Test button",
},
});
const button = screen.getByRole("button", { name: /test button/i });
expect(button).not.toBeDisabled();
});
});
import Button from "$components/ui/Button.svelte";
import { render, screen } from "@testing-library/svelte";
import userEvent from "@testing-library/user-event";
import { describe, expect, it, vi } from "vitest";
import MockIcon from "./MockIcon.svelte";
describe("Button.svelte", () => {
it("should render with icon and label", () => {
render(Button, {
props: {
icon: MockIcon,
label: "Test Button",
ariaLabel: "Test button",
},
});
expect(screen.getByText("Test Button")).toBeInTheDocument();
expect(screen.getByRole("button", { name: /test button/i })).toBeInTheDocument();
});
it("should render with icon only", () => {
render(Button, {
props: {
icon: MockIcon,
ariaLabel: "Test button",
},
});
const button = screen.getByRole("button", { name: /test button/i });
expect(button).toBeInTheDocument();
expect(button.textContent.trim()).toBe("");
});
it("should call onclick handler", async () => {
const onclick = vi.fn();
const user = userEvent.setup();
render(Button, {
props: {
icon: MockIcon,
label: "Click me",
onclick,
ariaLabel: "Test button",
},
});
const button = screen.getByRole("button", { name: /test button/i });
await user.click(button);
expect(onclick).toHaveBeenCalledTimes(1);
});
it("should not throw error when clicked without onclick prop", async () => {
const user = userEvent.setup();
render(Button, {
props: {
icon: MockIcon,
label: "Click me",
ariaLabel: "Test button",
},
});
const button = screen.getByRole("button", { name: /test button/i });
expect(() => user.click(button)).not.toThrow();
});
it("should be disabled when disabled prop is true", () => {
render(Button, {
props: {
icon: MockIcon,
label: "Disabled",
disabled: true,
ariaLabel: "Test button",
},
});
const button = screen.getByRole("button", { name: /test button/i });
expect(button).toBeDisabled();
});
it("should not be disabled by default", () => {
render(Button, {
props: {
icon: MockIcon,
label: "Enabled",
ariaLabel: "Test button",
},
});
const button = screen.getByRole("button", { name: /test button/i });
expect(button).not.toBeDisabled();
});
});
+13 -13
View File
@@ -1,13 +1,13 @@
import ColorPicker from "$components/ui/ColorPicker.svelte";
import { render } from "@testing-library/svelte";
import { describe, it } from "vitest";
describe("ColorPicker.svelte", () => {
it("should render without crashing", () => {
render(ColorPicker, {
props: {
value: "#ffffff",
},
});
});
});
import ColorPicker from "$components/ui/ColorPicker.svelte";
import { render } from "@testing-library/svelte";
import { describe, it } from "vitest";
describe("ColorPicker.svelte", () => {
it("should render without crashing", () => {
render(ColorPicker, {
props: {
value: "#ffffff",
},
});
});
});
+3 -3
View File
@@ -1,3 +1,3 @@
<svg data-testid="mock-icon" viewBox="0 0 24 24">
<circle cx="12" cy="12" r="10" />
</svg>
<svg data-testid="mock-icon" viewBox="0 0 24 24">
<circle cx="12" cy="12" r="10" />
</svg>

Before

Width:  |  Height:  |  Size: 96 B

After

Width:  |  Height:  |  Size: 93 B

+21 -21
View File
@@ -1,21 +1,21 @@
import RangeSlider from "$components/ui/RangeSlider.svelte";
import { fireEvent, render, screen } from "@testing-library/svelte";
import { describe, expect, it, vi } from "vitest";
describe("RangeSlider.svelte", () => {
it("should call onchange handler", async () => {
const onchange = vi.fn();
render(RangeSlider, {
props: {
value: 50,
onchange,
},
});
const slider = screen.getByRole("slider");
await fireEvent.change(slider, { target: { value: "75" } });
expect(onchange).toHaveBeenCalledTimes(1);
});
});
import RangeSlider from "$components/ui/RangeSlider.svelte";
import { fireEvent, render, screen } from "@testing-library/svelte";
import { describe, expect, it, vi } from "vitest";
describe("RangeSlider.svelte", () => {
it("should call onchange handler", async () => {
const onchange = vi.fn();
render(RangeSlider, {
props: {
value: 50,
onchange,
},
});
const slider = screen.getByRole("slider");
await fireEvent.change(slider, { target: { value: "75" } });
expect(onchange).toHaveBeenCalledTimes(1);
});
});
+13 -13
View File
@@ -1,13 +1,13 @@
import SelectFont from "$components/ui/SelectFont.svelte";
import { render } from "@testing-library/svelte";
import { describe, it } from "vitest";
describe("SelectFont.svelte", () => {
it("should render without crashing", () => {
render(SelectFont, {
props: {
value: "Arial",
},
});
});
});
import SelectFont from "$components/ui/SelectFont.svelte";
import { render } from "@testing-library/svelte";
import { describe, it } from "vitest";
describe("SelectFont.svelte", () => {
it("should render without crashing", () => {
render(SelectFont, {
props: {
value: "Arial",
},
});
});
});