From c4103e937daa87db95fb1e697554f94dbb0fab09 Mon Sep 17 00:00:00 2001 From: Ku6epXBOCTuK Date: Mon, 9 Feb 2026 09:57:39 +0500 Subject: [PATCH] test: make tests less fragile --- .../unit/components/layout/AppHeader.test.ts | 7 +++---- tests/unit/components/layout/Card.test.ts | 6 +++--- .../unit/components/layout/InputGroup.test.ts | 7 ++++--- .../components/layout/SettingsGrid.test.ts | 7 ++++--- .../components/layout/SettingsRow.test.ts | 6 +++--- .../components/panel/PreviewControls.test.ts | 4 ++-- .../components/text/TextInlineEdit.test.ts | 6 +++--- tests/unit/components/text/TextInput.test.ts | 21 ++++++++----------- .../unit/components/text/TextManager.test.ts | 7 +++---- tests/unit/components/ui/Button.test.ts | 21 +++++++++---------- tests/unit/components/ui/RangeSlider.test.ts | 7 +++---- tests/unit/routes/page.test.ts | 5 ++--- 12 files changed, 49 insertions(+), 55 deletions(-) diff --git a/tests/unit/components/layout/AppHeader.test.ts b/tests/unit/components/layout/AppHeader.test.ts index 6115eba..5c15c72 100644 --- a/tests/unit/components/layout/AppHeader.test.ts +++ b/tests/unit/components/layout/AppHeader.test.ts @@ -1,6 +1,6 @@ import AppHeader from "$components/layout/AppHeader.svelte"; import { themeState } from "$states/theme.svelte"; -import { fireEvent, render } from "@testing-library/svelte"; +import { fireEvent, render, screen } from "@testing-library/svelte"; import { beforeEach, describe, expect, it } from "vitest"; describe("AppHeader.svelte", () => { @@ -9,10 +9,9 @@ describe("AppHeader.svelte", () => { }); it("should toggle theme on button click", async () => { - const { container } = render(AppHeader); + render(AppHeader); - const toggleButton = container.querySelector("button"); - if (!toggleButton) throw new Error("Toggle button not found"); + const toggleButton = screen.getByRole("button", { name: /toggle theme/i }); themeState.theme = "dark"; await fireEvent.click(toggleButton); diff --git a/tests/unit/components/layout/Card.test.ts b/tests/unit/components/layout/Card.test.ts index 001fe54..6b8efe2 100644 --- a/tests/unit/components/layout/Card.test.ts +++ b/tests/unit/components/layout/Card.test.ts @@ -1,11 +1,11 @@ -import { render } from "@testing-library/svelte"; +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); - const card = document.querySelector(".card"); - expect(card).toBeInTheDocument(); + expect(screen.getByText("Test Title")).toBeInTheDocument(); + expect(screen.getByTestId("card-content")).toBeInTheDocument(); }); }); diff --git a/tests/unit/components/layout/InputGroup.test.ts b/tests/unit/components/layout/InputGroup.test.ts index 8c44cb7..2e05e72 100644 --- a/tests/unit/components/layout/InputGroup.test.ts +++ b/tests/unit/components/layout/InputGroup.test.ts @@ -1,11 +1,12 @@ -import { render } from "@testing-library/svelte"; +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); - const inputGroup = document.querySelector(".input-group"); - expect(inputGroup).toBeInTheDocument(); + expect(screen.getByTestId("input1")).toBeInTheDocument(); + expect(screen.getByTestId("input2")).toBeInTheDocument(); + expect(screen.getByTestId("button")).toBeInTheDocument(); }); }); diff --git a/tests/unit/components/layout/SettingsGrid.test.ts b/tests/unit/components/layout/SettingsGrid.test.ts index fd05cd7..1a35ced 100644 --- a/tests/unit/components/layout/SettingsGrid.test.ts +++ b/tests/unit/components/layout/SettingsGrid.test.ts @@ -1,11 +1,12 @@ -import { render } from "@testing-library/svelte"; +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); - const settingsGrid = document.querySelector(".settings-grid"); - expect(settingsGrid).toBeInTheDocument(); + expect(screen.getByTestId("item1")).toBeInTheDocument(); + expect(screen.getByTestId("item2")).toBeInTheDocument(); + expect(screen.getByTestId("item3")).toBeInTheDocument(); }); }); diff --git a/tests/unit/components/layout/SettingsRow.test.ts b/tests/unit/components/layout/SettingsRow.test.ts index c00b910..2cdd607 100644 --- a/tests/unit/components/layout/SettingsRow.test.ts +++ b/tests/unit/components/layout/SettingsRow.test.ts @@ -1,11 +1,11 @@ -import { render } from "@testing-library/svelte"; +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); - const settingRow = document.querySelector(".setting-row"); - expect(settingRow).toBeInTheDocument(); + expect(screen.getByText("Test Label")).toBeInTheDocument(); + expect(screen.getByTestId("test-input")).toBeInTheDocument(); }); }); diff --git a/tests/unit/components/panel/PreviewControls.test.ts b/tests/unit/components/panel/PreviewControls.test.ts index ffc46dc..a09e18d 100644 --- a/tests/unit/components/panel/PreviewControls.test.ts +++ b/tests/unit/components/panel/PreviewControls.test.ts @@ -1,5 +1,5 @@ import PreviewControls from "$components/panel/PreviewControls.svelte"; -import { cleanup, render } from "@testing-library/svelte"; +import { cleanup, render, screen } from "@testing-library/svelte"; import { afterEach, describe, expect, it } from "vitest"; afterEach(() => { @@ -16,7 +16,7 @@ describe("PreviewControls.svelte", () => { }, }); - const buttons = document.querySelectorAll("button"); + const buttons = screen.getAllByRole("button"); expect(buttons.length).toBeGreaterThan(0); }); }); diff --git a/tests/unit/components/text/TextInlineEdit.test.ts b/tests/unit/components/text/TextInlineEdit.test.ts index f484eeb..0f731f3 100644 --- a/tests/unit/components/text/TextInlineEdit.test.ts +++ b/tests/unit/components/text/TextInlineEdit.test.ts @@ -1,5 +1,5 @@ import TextInlineEdit from "$components/text/TextInlineEdit.svelte"; -import { cleanup, render } from "@testing-library/svelte"; +import { cleanup, render, screen } from "@testing-library/svelte"; import { afterEach, describe, expect, it } from "vitest"; afterEach(() => { @@ -16,7 +16,7 @@ describe("TextInlineEdit.svelte", () => { }, }); - const input = document.querySelector("input[type='text']"); + const input = screen.getByRole("textbox"); expect(input).toBeInTheDocument(); expect(input).toHaveValue("Test text"); }); @@ -30,7 +30,7 @@ describe("TextInlineEdit.svelte", () => { }, }); - const input = document.querySelector("input[type='text']"); + const input = screen.getByRole("textbox"); expect(input).toHaveValue(""); }); }); diff --git a/tests/unit/components/text/TextInput.test.ts b/tests/unit/components/text/TextInput.test.ts index aba724e..0fe533e 100644 --- a/tests/unit/components/text/TextInput.test.ts +++ b/tests/unit/components/text/TextInput.test.ts @@ -1,10 +1,10 @@ import TextInput from "$components/text/TextInput.svelte"; -import { fireEvent, render } from "@testing-library/svelte"; +import { fireEvent, render, screen } from "@testing-library/svelte"; import { describe, expect, it, vi } from "vitest"; describe("TextInput.svelte", () => { it("should render with initial value", () => { - const { container } = render(TextInput, { + render(TextInput, { props: { text: "Test text", onenter: vi.fn(), @@ -12,13 +12,13 @@ describe("TextInput.svelte", () => { }, }); - const input = container.querySelector("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 { container } = render(TextInput, { + render(TextInput, { props: { text: "Initial", onenter: vi.fn(), @@ -26,8 +26,7 @@ describe("TextInput.svelte", () => { }, }); - const input = container.querySelector("input"); - if (!input) throw new Error("Input element not found"); + const input = screen.getByRole("textbox", { name: /test input/i }); await fireEvent.input(input, { target: { value: "Updated text" } }); expect(input).toHaveValue("Updated text"); @@ -35,7 +34,7 @@ describe("TextInput.svelte", () => { it("should call onenter when Enter key is pressed", async () => { const onenter = vi.fn(); - const { container } = render(TextInput, { + render(TextInput, { props: { text: "Test", onenter, @@ -43,8 +42,7 @@ describe("TextInput.svelte", () => { }, }); - const input = container.querySelector("input"); - if (!input) throw new Error("Input element not found"); + const input = screen.getByRole("textbox", { name: /test input/i }); await fireEvent.keyDown(input, { key: "Enter" }); expect(onenter).toHaveBeenCalledTimes(1); @@ -52,7 +50,7 @@ describe("TextInput.svelte", () => { it("should not call onenter when other keys are pressed", async () => { const onenter = vi.fn(); - const { container } = render(TextInput, { + render(TextInput, { props: { text: "Test", onenter, @@ -60,8 +58,7 @@ describe("TextInput.svelte", () => { }, }); - const input = container.querySelector("input"); - if (!input) throw new Error("Input element not found"); + const input = screen.getByRole("textbox", { name: /test input/i }); await fireEvent.keyDown(input, { key: "Escape" }); await fireEvent.keyDown(input, { key: "Tab" }); diff --git a/tests/unit/components/text/TextManager.test.ts b/tests/unit/components/text/TextManager.test.ts index e3ffbf2..aa7ec00 100644 --- a/tests/unit/components/text/TextManager.test.ts +++ b/tests/unit/components/text/TextManager.test.ts @@ -1,6 +1,6 @@ import TextManager from "$components/text/TextManager.svelte"; import { textsState } from "$states/texts.svelte"; -import { fireEvent, render, screen, waitFor } from "@testing-library/svelte"; +import { fireEvent, render, screen, waitFor, within } from "@testing-library/svelte"; import { beforeEach, describe, expect, it, vi } from "vitest"; describe("TextManager.svelte", () => { @@ -98,9 +98,8 @@ describe("TextManager.svelte", () => { const textItems = screen.queryAllByRole("listitem"); expect(textItems).toHaveLength(1); - const inputs = textItems[0].querySelectorAll('input[type="text"]'); - expect(inputs).toHaveLength(1); - expect(inputs[0]).toHaveValue("Test text"); + const input = within(textItems[0]).getByRole("textbox"); + expect(input).toHaveValue("Test text"); }); it("should call textsState.removeText when delete button is clicked", () => { diff --git a/tests/unit/components/ui/Button.test.ts b/tests/unit/components/ui/Button.test.ts index 3ffe1e7..2fa3c42 100644 --- a/tests/unit/components/ui/Button.test.ts +++ b/tests/unit/components/ui/Button.test.ts @@ -5,7 +5,7 @@ import MockIcon from "./MockIcon.svelte"; describe("Button.svelte", () => { it("should render with icon and label", () => { - const { container } = render(Button, { + render(Button, { props: { icon: MockIcon, label: "Test Button", @@ -14,23 +14,23 @@ describe("Button.svelte", () => { }); expect(screen.getByText("Test Button")).toBeInTheDocument(); - expect(container.querySelector("svg")).toBeInTheDocument(); + expect(screen.getByRole("button", { name: /test button/i })).toBeInTheDocument(); }); it("should render with icon only", () => { - const { container } = render(Button, { + render(Button, { props: { icon: MockIcon, ariaLabel: "Test button", }, }); - expect(container.querySelector("svg")).toBeInTheDocument(); + expect(screen.getByRole("button", { name: /test button/i })).toBeInTheDocument(); }); it("should call onclick handler", async () => { const onclick = vi.fn(); - const { container } = render(Button, { + render(Button, { props: { icon: MockIcon, label: "Click me", @@ -39,15 +39,14 @@ describe("Button.svelte", () => { }, }); - const button = container.querySelector("button"); - if (!button) throw new Error("Button element not found"); + const button = screen.getByRole("button", { name: /test button/i }); await fireEvent.click(button); expect(onclick).toHaveBeenCalledTimes(1); }); it("should be disabled when disabled prop is true", () => { - const { container } = render(Button, { + render(Button, { props: { icon: MockIcon, label: "Disabled", @@ -56,12 +55,12 @@ describe("Button.svelte", () => { }, }); - const button = container.querySelector("button"); + const button = screen.getByRole("button", { name: /test button/i }); expect(button).toBeDisabled(); }); it("should not be disabled by default", () => { - const { container } = render(Button, { + render(Button, { props: { icon: MockIcon, label: "Enabled", @@ -69,7 +68,7 @@ describe("Button.svelte", () => { }, }); - const button = container.querySelector("button"); + const button = screen.getByRole("button", { name: /test button/i }); expect(button).not.toBeDisabled(); }); }); diff --git a/tests/unit/components/ui/RangeSlider.test.ts b/tests/unit/components/ui/RangeSlider.test.ts index 3aef977..91f300b 100644 --- a/tests/unit/components/ui/RangeSlider.test.ts +++ b/tests/unit/components/ui/RangeSlider.test.ts @@ -1,19 +1,18 @@ import RangeSlider from "$components/ui/RangeSlider.svelte"; -import { fireEvent, render } from "@testing-library/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(); - const { container } = render(RangeSlider, { + render(RangeSlider, { props: { value: 50, onchange, }, }); - const slider = container.querySelector("input[type='range']"); - if (!slider) throw new Error("Slider element not found"); + const slider = screen.getByRole("slider"); await fireEvent.change(slider, { target: { value: "75" } }); expect(onchange).toHaveBeenCalledTimes(1); diff --git a/tests/unit/routes/page.test.ts b/tests/unit/routes/page.test.ts index 9eeae5a..57eb975 100644 --- a/tests/unit/routes/page.test.ts +++ b/tests/unit/routes/page.test.ts @@ -1,11 +1,10 @@ -import { render } from "@testing-library/svelte"; +import { render, screen } from "@testing-library/svelte"; import { describe, expect, it } from "vitest"; import PageTest from "./PageTest.svelte"; describe("+page.svelte", () => { it("should render without crashing", () => { render(PageTest); - const mainGrid = document.querySelector(".main-grid"); - expect(mainGrid).toBeInTheDocument(); + expect(screen.getByText("Тексты панелей")).toBeInTheDocument(); }); });