diff --git a/.changeset/wise-squids-brush.md b/.changeset/wise-squids-brush.md new file mode 100644 index 000000000..c0ea228d9 --- /dev/null +++ b/.changeset/wise-squids-brush.md @@ -0,0 +1,5 @@ +--- +"@shopware-ag/meteor-component-library": patch +--- + +Announce mt-search as a real search input diff --git a/packages/component-library/src/components/navigation/mt-search/mt-search.interactive.stories.ts b/packages/component-library/src/components/navigation/mt-search/mt-search.interactive.stories.ts index fea600c5d..79adc21a2 100644 --- a/packages/component-library/src/components/navigation/mt-search/mt-search.interactive.stories.ts +++ b/packages/component-library/src/components/navigation/mt-search/mt-search.interactive.stories.ts @@ -1,8 +1,3 @@ -import { within, userEvent } from "@storybook/test"; -import { expect } from "@storybook/test"; - -import * as test from "@storybook/test"; - import meta, { type MtSearchMeta, type MtSearchStory } from "./mt-search.stories"; export default { @@ -10,23 +5,6 @@ export default { title: "Interaction Tests/Navigation/mt-search", } as MtSearchMeta; -export const TestInputValue: MtSearchStory = { - name: "Should keep input value", - args: { - change: test.fn(), - }, - play: async ({ args, canvasElement }) => { - // we can't use canvasElement because it is not available anymore - const canvas = within(canvasElement); - - await userEvent.type(canvas.getByRole("textbox"), "Shopware"); - await userEvent.click(canvas.getByText("hidden")); - - await expect((canvas.getByRole("textbox") as HTMLInputElement).value).toBe("Shopware"); - await expect(args.change).toHaveBeenCalledWith("Shopware"); - }, -}; - export const VisualTestDefaultSize: MtSearchStory = { name: "Render the default sized search", args: { diff --git a/packages/component-library/src/components/navigation/mt-search/mt-search.spec.ts b/packages/component-library/src/components/navigation/mt-search/mt-search.spec.ts new file mode 100644 index 000000000..ea2858fa4 --- /dev/null +++ b/packages/component-library/src/components/navigation/mt-search/mt-search.spec.ts @@ -0,0 +1,117 @@ +import { render, screen } from "@testing-library/vue"; +import MtSearch from "./mt-search.vue"; +import { userEvent } from "@storybook/test"; + +describe("mt-search", () => { + it("changes the value when typing in the search", async () => { + // ARRANGE + const handler = vi.fn(); + + render(MtSearch, { + props: { + modelValue: "", + "onUpdate:modelValue": handler, + }, + }); + + // ACT + await userEvent.type(screen.getByRole("searchbox"), "Hello"); + + // ASSERT + expect(screen.getByRole("searchbox")).toHaveValue("Hello"); + expect(handler).toHaveBeenCalledWith("Hello"); + }); + + it("emits a change event when typing in the search and then removing the focus from the input", async () => { + // ARRANGE + const handler = vi.fn(); + + render(MtSearch, { + props: { + modelValue: "", + onChange: handler, + }, + }); + + // ACT + await userEvent.type(screen.getByRole("searchbox"), "Hello"); + await userEvent.tab(); + + // ASSERT + expect(screen.getByRole("searchbox")).toHaveValue("Hello"); + + expect(handler).toHaveBeenCalledWith("Hello"); + }); + + it("emits an empty string when clearing the search and then removing focus from the input", async () => { + // ARRANGE + const handler = vi.fn(); + + render(MtSearch, { + props: { + modelValue: "Hello", + onChange: handler, + }, + }); + + // ACT + await userEvent.clear(screen.getByRole("searchbox")); + await userEvent.tab(); + + // ASSERT + expect(screen.getByRole("searchbox")).toHaveValue(""); + expect(handler).toHaveBeenCalledWith(""); + }); + + it("has a default placeholder of search", async () => { + // ARRANGE + render(MtSearch); + + // ASSERT + expect(screen.getByRole("searchbox")).toHaveAttribute("placeholder", "Search"); + }); + + it("has the specified placeholder", async () => { + // ARRANGE + render(MtSearch, { + props: { + placeholder: "Find me", + }, + }); + + // ASSERT + expect(screen.getByRole("searchbox")).toHaveAttribute("placeholder", "Find me"); + }); + + it("disables the search", async () => { + // ARRANGE + render(MtSearch, { + props: { + disabled: true, + }, + }); + + // ASSERT + expect(screen.getByRole("searchbox")).toBeDisabled(); + }); + + it("does not change the value when the search is disabled", async () => { + // ARRANGE + const handler = vi.fn(); + + render(MtSearch, { + props: { + modelValue: "Hello", + disabled: true, + "onUpdate:modelValue": handler, + }, + }); + + // ACT + await userEvent.type(screen.getByRole("searchbox"), "World"); + + // ASSERT + expect(screen.getByRole("searchbox")).toHaveValue("Hello"); + expect(handler).not.toHaveBeenCalled(); + }); +}); diff --git a/packages/component-library/src/components/navigation/mt-search/mt-search.vue b/packages/component-library/src/components/navigation/mt-search/mt-search.vue index 04b77ad32..3bbba0c3e 100644 --- a/packages/component-library/src/components/navigation/mt-search/mt-search.vue +++ b/packages/component-library/src/components/navigation/mt-search/mt-search.vue @@ -3,14 +3,18 @@ - + @@ -67,11 +71,11 @@ defineEmits<{ } .mt-search--size-default { - padding: 0.75rem 1rem; + padding: var(--scale-size-12) var(--scale-size-16); } .mt-search--size-small { - padding: 0.25rem 1rem; + padding: var(--scale-size-4) var(--scale-size-16); } .mt-search__input { @@ -84,9 +88,17 @@ defineEmits<{ line-height: var(--font-line-height-xs); color: var(--color-text-primary-default); outline: none; + appearance: none; -webkit-appearance: none; -moz-appearance: none; + &::-webkit-search-cancel-button, + &::-webkit-search-decoration, + &::-webkit-search-results-button, + &::-webkit-search-results-decoration { + display: none; + } + &::placeholder { color: var(--color-text-secondary-default); }