diff --git a/packages/bits-ui/src/lib/bits/alert-dialog/components/alert-dialog-content.svelte b/packages/bits-ui/src/lib/bits/alert-dialog/components/alert-dialog-content.svelte index 2e2cd9536..725f66715 100644 --- a/packages/bits-ui/src/lib/bits/alert-dialog/components/alert-dialog-content.svelte +++ b/packages/bits-ui/src/lib/bits/alert-dialog/components/alert-dialog-content.svelte @@ -60,6 +60,7 @@ enabled={present.current} onEscapeKeydown={(e) => { onEscapeKeydown(e); + if (e.defaultPrevented) return; contentState.root.closeDialog(); }} > diff --git a/packages/bits-ui/src/lib/bits/combobox/components/combobox-content.svelte b/packages/bits-ui/src/lib/bits/combobox/components/combobox-content.svelte index 30f754001..5472c7d6b 100644 --- a/packages/bits-ui/src/lib/bits/combobox/components/combobox-content.svelte +++ b/packages/bits-ui/src/lib/bits/combobox/components/combobox-content.svelte @@ -49,8 +49,8 @@ contentState.root.closeMenu(); }} onEscapeKeydown={(e) => { - // TODO: users should be able to cancel this onEscapeKeydown(e); + if (e.defaultPrevented) return contentState.root.closeMenu(); }} onMountAutoFocus={(e) => e.preventDefault()} diff --git a/packages/bits-ui/src/lib/bits/context-menu/components/context-menu-content.svelte b/packages/bits-ui/src/lib/bits/context-menu/components/context-menu-content.svelte index eb158ba5c..7b797064e 100644 --- a/packages/bits-ui/src/lib/bits/context-menu/components/context-menu-content.svelte +++ b/packages/bits-ui/src/lib/bits/context-menu/components/context-menu-content.svelte @@ -68,8 +68,8 @@ contentState.parentMenu.onClose(); }} onEscapeKeydown={(e) => { - // TODO: users should be able to cancel this onEscapeKeydown(e); + if (e.defaultPrevented) return; contentState.parentMenu.onClose(); }} trapped diff --git a/packages/bits-ui/src/lib/bits/dialog/components/dialog-content.svelte b/packages/bits-ui/src/lib/bits/dialog/components/dialog-content.svelte index 64f1da3b6..beb04ee93 100644 --- a/packages/bits-ui/src/lib/bits/dialog/components/dialog-content.svelte +++ b/packages/bits-ui/src/lib/bits/dialog/components/dialog-content.svelte @@ -54,6 +54,7 @@ enabled={present.current} onEscapeKeydown={(e) => { onEscapeKeydown(e); + if (e.defaultPrevented) return contentState.root.closeDialog(); }} > diff --git a/packages/bits-ui/src/lib/bits/dropdown-menu/components/dropdown-menu-content.svelte b/packages/bits-ui/src/lib/bits/dropdown-menu/components/dropdown-menu-content.svelte index b803e4572..03bc3231a 100644 --- a/packages/bits-ui/src/lib/bits/dropdown-menu/components/dropdown-menu-content.svelte +++ b/packages/bits-ui/src/lib/bits/dropdown-menu/components/dropdown-menu-content.svelte @@ -64,8 +64,8 @@ contentState.parentMenu.onClose(); }} onEscapeKeydown={(e) => { - // TODO: users should be able to cancel this onEscapeKeydown(e); + if (e.defaultPrevented) return; contentState.parentMenu.onClose(); }} trapped diff --git a/packages/bits-ui/src/lib/bits/link-preview/components/link-preview-content.svelte b/packages/bits-ui/src/lib/bits/link-preview/components/link-preview-content.svelte index 2a8e10150..10dd6fe7c 100644 --- a/packages/bits-ui/src/lib/bits/link-preview/components/link-preview-content.svelte +++ b/packages/bits-ui/src/lib/bits/link-preview/components/link-preview-content.svelte @@ -57,8 +57,8 @@ contentState.root.immediateClose(); }} onEscapeKeydown={(e) => { - // TODO: users should be able to cancel this onEscapeKeydown?.(e); + if (e.defaultPrevented) return; contentState.root.immediateClose(); }} onMountAutoFocus={(e) => e.preventDefault()} diff --git a/packages/bits-ui/src/lib/bits/menu/components/menu-content.svelte b/packages/bits-ui/src/lib/bits/menu/components/menu-content.svelte index 53e81f159..7bb87fd7a 100644 --- a/packages/bits-ui/src/lib/bits/menu/components/menu-content.svelte +++ b/packages/bits-ui/src/lib/bits/menu/components/menu-content.svelte @@ -62,8 +62,8 @@ contentState.parentMenu.onClose(); }} onEscapeKeydown={(e) => { - // TODO: users should be able to cancel this onEscapeKeydown(e); + if (e.defaultPrevented) return; contentState.parentMenu.onClose(); }} trapped diff --git a/packages/bits-ui/src/lib/bits/menu/components/menu-sub-content.svelte b/packages/bits-ui/src/lib/bits/menu/components/menu-sub-content.svelte index 482e8f73e..c5b8d512a 100644 --- a/packages/bits-ui/src/lib/bits/menu/components/menu-sub-content.svelte +++ b/packages/bits-ui/src/lib/bits/menu/components/menu-sub-content.svelte @@ -90,6 +90,7 @@ onEscapeKeydown={(e) => { // TODO: users should be able to cancel this onEscapeKeydown(e); + if (e.defaultPrevented) return; subContentState.parentMenu.onClose(); }} onFocusOutside={(e) => { diff --git a/packages/bits-ui/src/lib/bits/navigation-menu/components/navigation-menu-content.svelte b/packages/bits-ui/src/lib/bits/navigation-menu/components/navigation-menu-content.svelte index 7944eea29..380ae1a54 100644 --- a/packages/bits-ui/src/lib/bits/navigation-menu/components/navigation-menu-content.svelte +++ b/packages/bits-ui/src/lib/bits/navigation-menu/components/navigation-menu-content.svelte @@ -16,6 +16,9 @@ ref = $bindable(null), id = useId(), forceMount = false, + onEscapeKeydown, + onInteractOutside, + onFocusOutside, ...restProps }: ContentProps = $props(); @@ -42,13 +45,25 @@ {#snippet presence()} contentState.onEscapeKeydown(e)} + onEscapeKeydown={(e) => { + onEscapeKeydown?.(e); + if (e.defaultPrevented) return; + contentState.onEscapeKeydown(e); + }} > { + onInteractOutside?.(e); + if (e.defaultPrevented) return; + contentState.onInteractOutside(e); + }} + onFocusOutside={(e) => { + onFocusOutside?.(e); + if (e.defaultPrevented) return; + contentState.onFocusOutside(e); + }} > {#snippet children({ props: dismissableProps })} {#if child} diff --git a/packages/bits-ui/src/lib/bits/popover/components/popover-content.svelte b/packages/bits-ui/src/lib/bits/popover/components/popover-content.svelte index d470d04f6..ab7f089c2 100644 --- a/packages/bits-ui/src/lib/bits/popover/components/popover-content.svelte +++ b/packages/bits-ui/src/lib/bits/popover/components/popover-content.svelte @@ -39,8 +39,8 @@ contentState.root.close(); }} onEscapeKeydown={(e) => { - // TODO: users should be able to cancel this onEscapeKeydown(e); + if (e.defaultPrevented) return contentState.root.close(); }} onDestroyAutoFocus={(e) => { diff --git a/packages/bits-ui/src/lib/bits/select/components/select-content-impl.svelte b/packages/bits-ui/src/lib/bits/select/components/select-content-impl.svelte index 626861813..bc381a667 100644 --- a/packages/bits-ui/src/lib/bits/select/components/select-content-impl.svelte +++ b/packages/bits-ui/src/lib/bits/select/components/select-content-impl.svelte @@ -26,8 +26,7 @@ const contentState = context; - // eslint-disable-next-line unused-imports/no-unused-vars, ts/no-unused-vars - const { children, child, ...restWithoutChildren } = restProps; + const { children: _c, child: _ch, ...restWithoutChildren } = restProps; { - // TODO: users should be able to cancel this onEscapeKeydown(e); + if (e.defaultPrevented) return; contentState.root.handleClose(); }} > diff --git a/packages/bits-ui/src/lib/bits/tooltip/components/tooltip-content.svelte b/packages/bits-ui/src/lib/bits/tooltip/components/tooltip-content.svelte index 2e6286d3d..011f4417b 100644 --- a/packages/bits-ui/src/lib/bits/tooltip/components/tooltip-content.svelte +++ b/packages/bits-ui/src/lib/bits/tooltip/components/tooltip-content.svelte @@ -57,8 +57,8 @@ contentState.root.handleClose(); }} onEscapeKeydown={(e) => { - // TODO: users should be able to cancel this onEscapeKeydown?.(e); + if (e.defaultPrevented) return; contentState.root.handleClose(); }} onMountAutoFocus={(e) => e.preventDefault()} diff --git a/packages/bits-ui/src/lib/bits/utilities/escape-layer/useEscapeLayer.svelte.ts b/packages/bits-ui/src/lib/bits/utilities/escape-layer/useEscapeLayer.svelte.ts index 70b0a4c24..6b115965d 100644 --- a/packages/bits-ui/src/lib/bits/utilities/escape-layer/useEscapeLayer.svelte.ts +++ b/packages/bits-ui/src/lib/bits/utilities/escape-layer/useEscapeLayer.svelte.ts @@ -44,10 +44,11 @@ export class EscapeLayerState { #onkeydown = (e: KeyboardEvent) => { if (e.key !== kbd.ESCAPE || !isResponsibleEscapeLayer(this)) return; + const clonedEvent = new KeyboardEvent(e.type, e); e.preventDefault(); const behaviorType = this.#behaviorType.current; if (behaviorType !== "close" && behaviorType !== "defer-otherwise-close") return; - this.#onEscapeProp.current(e); + this.#onEscapeProp.current(clonedEvent); }; } diff --git a/packages/bits-ui/src/tests/accordion/Accordion.spec.ts b/packages/bits-ui/src/tests/accordion/Accordion.spec.ts index 14f439af4..0e33e36b6 100644 --- a/packages/bits-ui/src/tests/accordion/Accordion.spec.ts +++ b/packages/bits-ui/src/tests/accordion/Accordion.spec.ts @@ -60,12 +60,12 @@ const itemsWithDisabled = items.map((item) => { }); describe("accordion - single", () => { - it("has no accessibility violations", async () => { + it("should have no accessibility violations", async () => { const { container } = render(AccordionSingleTest as any, { items }); expect(await axe(container)).toHaveNoViolations(); }); - it("has bits data attrs", async () => { + it("should have bits data attrs", async () => { const { getByTestId } = render(AccordionTestIsolated); const root = getByTestId("root"); const trigger = getByTestId("trigger"); @@ -79,7 +79,7 @@ describe("accordion - single", () => { expect(trigger).toHaveAttribute("data-accordion-trigger"); }); - it("has expected data attributes", async () => { + it("should have expected data attributes", async () => { const user = setupUserEvents(); const { getByTestId } = render(AccordionSingleTest as any, { items: itemsWithDisabled }); const itemEls = items.map((item) => getByTestId(`${item.value}-item`)); @@ -99,7 +99,7 @@ describe("accordion - single", () => { expect(triggerEls[1]).toHaveAttribute("data-disabled"); }); - it("disables everything when the `disabled` prop is true", async () => { + it("should disable everything when the `disabled` prop is true", async () => { const user = setupUserEvents(); const { getByTestId } = render(AccordionSingleTest as any, { items, @@ -120,7 +120,7 @@ describe("accordion - single", () => { expect(triggerEls[2]).toHaveAttribute("data-disabled"); }); - it("displays content when an item is expanded", async () => { + it("should display content when an item is expanded", async () => { const user = setupUserEvents(); const { getByTestId } = render(AccordionSingleTest as any, { items }); @@ -138,7 +138,7 @@ describe("accordion - single", () => { } }); - it("expands only one item at a time when `multiple` is false", async () => { + it("should expand only one item at a time when `multiple` is false", async () => { const user = setupUserEvents(); const { getByTestId } = render(AccordionSingleTest as any, { items }); @@ -160,7 +160,7 @@ describe("accordion - single", () => { expect(openItems.length).toBe(1); }); - it("expands when the trigger is focused and `Enter` key is pressed", async () => { + it("should expand when the trigger is focused and `Enter` key is pressed", async () => { const user = setupUserEvents(); const { getByTestId } = render(AccordionSingleTest as any, { items, @@ -181,7 +181,7 @@ describe("accordion - single", () => { } }); - it("expands when the trigger is focused and `Space` key is pressed", async () => { + it("should expand when the trigger is focused and `Space` key is pressed", async () => { const user = setupUserEvents(); const { getByTestId } = render(AccordionSingleTest as any, { items, @@ -202,7 +202,7 @@ describe("accordion - single", () => { } }); - it("focuses the next item when `ArrowDown` key is pressed", async () => { + it("should focus the next item when `ArrowDown` key is pressed", async () => { const user = setupUserEvents(); const { getByTestId } = render(AccordionSingleTest as any, { items }); @@ -218,7 +218,7 @@ describe("accordion - single", () => { expect(triggers[0]).toHaveFocus(); }); - it("focuses the previous item when the `ArrowUp` key is pressed", async () => { + it("should focus the previous item when the `ArrowUp` key is pressed", async () => { const user = setupUserEvents(); const { getByTestId } = render(AccordionSingleTest as any, { items }); @@ -234,7 +234,7 @@ describe("accordion - single", () => { expect(triggers[0]).toHaveFocus(); }); - it("focuses the first item when the `Home` key is pressed", async () => { + it("should focus the first item when the `Home` key is pressed", async () => { const user = setupUserEvents(); const { getByTestId } = render(AccordionSingleTest as any, { items }); @@ -247,7 +247,7 @@ describe("accordion - single", () => { } }); - it("focuses the last item when the `End` key is pressed", async () => { + it("should focus the last item when the `End` key is pressed", async () => { const user = setupUserEvents(); const { getByTestId } = render(AccordionSingleTest as any, { items }); @@ -260,7 +260,7 @@ describe("accordion - single", () => { } }); - it("respects the `disabled` prop for items", async () => { + it("should respect the `disabled` prop for items", async () => { const user = setupUserEvents(); const { getByTestId } = render(AccordionSingleTest as any, { items: itemsWithDisabled }); @@ -272,7 +272,7 @@ describe("accordion - single", () => { expect(triggers[2]).toHaveFocus(); }); - it("respects the `level` prop for headers", async () => { + it("should respect the `level` prop for headers", async () => { const itemsWithLevel = items.map((item, i) => { if (i === 0) { return { ...item, level: 1 } as const; @@ -288,7 +288,7 @@ describe("accordion - single", () => { expect(headers[1]).toHaveAttribute("aria-level", "3"); }); - it("updates the `bind:value` prop when the value changes", async () => { + it("should update the `bind:value` prop when the value changes", async () => { const user = setupUserEvents(); const { getByTestId } = render(AccordionSingleTestControlledSvelte as any, { items }); const trigger = getByTestId("item-1-trigger"); @@ -301,7 +301,7 @@ describe("accordion - single", () => { expect(value).toHaveTextContent("item-1"); }); - it('handles programatic changes to the "value" prop', async () => { + it('should handle programatic changes to the "value" prop', async () => { const user = setupUserEvents(); const { getByTestId } = render(AccordionSingleTestControlledSvelte as any, { items }); const updateButton = getByTestId("update-value"); @@ -323,12 +323,12 @@ describe("accordion - single", () => { // describe("accordion - multiple", () => { - it("has no accessibility violations", async () => { + it("should have no accessibility violations", async () => { const { container } = render(AccordionMultiTest as any, { items }); expect(await axe(container)).toHaveNoViolations(); }); - it("has expected data attributes", async () => { + it("should have expected data attributes", async () => { const user = setupUserEvents(); const { getByTestId } = render(AccordionMultiTest as any, { items: itemsWithDisabled }); const itemEls = items.map((item) => getByTestId(`${item.value}-item`)); @@ -347,7 +347,7 @@ describe("accordion - multiple", () => { expect(triggerEls[1]).toHaveAttribute("data-disabled"); }); - it("disables everything when the `disabled` prop is true", async () => { + it("should disable everything when the `disabled` prop is true", async () => { const user = setupUserEvents(); const { getByTestId } = render(AccordionMultiTest as any, { items, @@ -368,7 +368,7 @@ describe("accordion - multiple", () => { expect(triggerEls[2]).toHaveAttribute("data-disabled"); }); - it("displays content when an item is expanded", async () => { + it("should display content when an item is expanded", async () => { const user = setupUserEvents(); const { getByTestId } = render(AccordionMultiTest as any, { items }); @@ -387,7 +387,7 @@ describe("accordion - multiple", () => { } }); - it("expands multiple items", async () => { + it("should allow expanding multiple items", async () => { const user = setupUserEvents(); const { getByTestId } = render(AccordionMultiTest as any, { items, @@ -410,7 +410,7 @@ describe("accordion - multiple", () => { expect(openItems.length).toBe(4); }); - it("expands when the trigger is focused and `Enter` key is pressed", async () => { + it("should expand when the trigger is focused and `Enter` key is pressed", async () => { const user = setupUserEvents(); const { getByTestId } = render(AccordionMultiTest as any, { items, @@ -431,7 +431,7 @@ describe("accordion - multiple", () => { } }); - it("expands when the trigger is focused and `Space` key is pressed", async () => { + it("should expand when the trigger is focused and `Space` key is pressed", async () => { const user = setupUserEvents(); const { getByTestId } = render(AccordionMultiTest as any, { items, @@ -453,7 +453,7 @@ describe("accordion - multiple", () => { } }); - it("focuses the next item when `ArrowDown` key is pressed", async () => { + it("should focus the next item when `ArrowDown` key is pressed", async () => { const user = setupUserEvents(); const { getByTestId } = render(AccordionMultiTest as any, { items }); @@ -469,7 +469,7 @@ describe("accordion - multiple", () => { expect(triggers[0]).toHaveFocus(); }); - it("focuses the previous item when the `ArrowUp` key is pressed", async () => { + it("should focus the previous item when the `ArrowUp` key is pressed", async () => { const user = setupUserEvents(); const { getByTestId } = render(AccordionMultiTest as any, { items }); @@ -485,7 +485,7 @@ describe("accordion - multiple", () => { expect(triggers[0]).toHaveFocus(); }); - it("focuses the first item when the `Home` key is pressed", async () => { + it("should focus the first item when the `Home` key is pressed", async () => { const user = setupUserEvents(); const { getByTestId } = render(AccordionMultiTest as any, { items }); @@ -498,7 +498,7 @@ describe("accordion - multiple", () => { } }); - it("focuses the last item when the `End` key is pressed", async () => { + it("should focus the last item when the `End` key is pressed", async () => { const user = setupUserEvents(); const { getByTestId } = render(AccordionMultiTest as any, { items }); @@ -511,7 +511,7 @@ describe("accordion - multiple", () => { } }); - it("respects the `disabled` prop for items", async () => { + it("should respect the `disabled` prop for items", async () => { const user = setupUserEvents(); const { getByTestId } = render(AccordionMultiTest as any, { items: itemsWithDisabled }); @@ -523,7 +523,7 @@ describe("accordion - multiple", () => { expect(triggers[2]).toHaveFocus(); }); - it("respects the `level` prop for headers", async () => { + it("should respect the `level` prop for headers", async () => { const itemsWithLevel = items.map((item, i) => { if (i === 0) { return { ...item, level: 1 } as const; @@ -539,7 +539,7 @@ describe("accordion - multiple", () => { expect(headers[1]).toHaveAttribute("aria-level", "3"); }); - it("updates the `bind:value` prop when the value changes", async () => { + it("should update the `bind:value` prop when the value changes", async () => { const user = setupUserEvents(); const { getByTestId, queryByTestId } = render(AccordionMultiTestControlled as any, { items, @@ -554,7 +554,7 @@ describe("accordion - multiple", () => { expect(queryByTestId("value")).toHaveTextContent("item-1"); }); - it('handles programatic changes to the "value" prop', async () => { + it('should handle programatic changes to the "value" prop', async () => { const user = setupUserEvents(); const { getByTestId, queryByTestId } = render(AccordionMultiTestControlled as any, { items, diff --git a/packages/bits-ui/src/tests/alert-dialog/AlertDialog.spec.ts b/packages/bits-ui/src/tests/alert-dialog/AlertDialog.spec.ts index 2f1e78640..57c338083 100644 --- a/packages/bits-ui/src/tests/alert-dialog/AlertDialog.spec.ts +++ b/packages/bits-ui/src/tests/alert-dialog/AlertDialog.spec.ts @@ -53,12 +53,12 @@ async function open(props: AlertDialogTestProps = {}) { } describe("alert dialog", () => { - it("has no accessibility violations", async () => { + it("should have no accessibility violations", async () => { const { container } = render(AlertDialogTest); expect(await axe(container)).toHaveNoViolations(); }); - it("has bits data attrs", async () => { + it("should have bits data attrs", async () => { const { getByTestId } = render(AlertDialogTest, { open: true }); const parts = ["trigger", "overlay", "cancel", "title", "description", "content"]; @@ -68,7 +68,7 @@ describe("alert dialog", () => { } }); - it("has expected data attributes", async () => { + it("should have expected data attributes", async () => { const { getByTestId } = await open(); const overlay = getByTestId("overlay"); @@ -77,23 +77,23 @@ describe("alert dialog", () => { expect(content).toHaveAttribute("data-state", "open"); }); - it("opens when the trigger is clicked", async () => { + it("should open when the trigger is clicked", async () => { await open(); }); - it("focuses the cancel button by default when opened", async () => { + it("should focus the cancel button by default when opened", async () => { const { cancel } = await open(); expect(cancel).toHaveFocus(); }); - it("closes when the cancel button is clicked", async () => { + it("should close when the cancel button is clicked", async () => { const { getByTestId, queryByTestId, user } = await open(); const cancel = getByTestId("cancel"); await user.click(cancel); expectIsClosed(queryByTestId); }); - it("closes when the `Escape` key is pressed", async () => { + it("should close when the `Escape` key is pressed", async () => { const { queryByTestId, user, getByTestId } = await open(); await user.keyboard(kbd.ESCAPE); @@ -101,7 +101,7 @@ describe("alert dialog", () => { expect(getByTestId("trigger")).toHaveFocus(); }); - it("doesn't close when the overlay is clicked", async () => { + it("should not close when the overlay is clicked", async () => { const { getByTestId, queryByTestId, user } = await open(); await sleep(100); @@ -113,14 +113,14 @@ describe("alert dialog", () => { expect(contentAfter2).not.toBeNull(); }); - it("attaches to body when using portal element", async () => { + it("should attach to body when using portal element", async () => { await open(); const content = screen.getByTestId("content"); expect(content.parentElement).toEqual(document.body); }); - it("doesnt attached to body when portal is disabled", async () => { + it("should attach to body when portal is disabled", async () => { await open({ portalProps: { disabled: true, @@ -130,7 +130,7 @@ describe("alert dialog", () => { expect(content.parentElement).not.toEqual(document.body); }); - it("portals to the target if passed as a prop", async () => { + it("should portal to the target if passed as a prop", async () => { await open({ portalProps: { to: "#portalTarget", @@ -141,14 +141,14 @@ describe("alert dialog", () => { expect(content.parentElement).toEqual(portalTarget); }); - it("doesnt close when content is clicked", async () => { + it("should not close when content is clicked", async () => { const { user, getByTestId, queryByTestId } = await open(); const content = getByTestId("content"); await user.click(content); await expectIsOpen(queryByTestId); }); - it("respects binding to the `open` prop", async () => { + it("should respect binding to the `open` prop", async () => { const { getByTestId, queryByTestId, user } = setup(); const trigger = getByTestId("trigger"); @@ -165,7 +165,7 @@ describe("alert dialog", () => { await expectIsOpen(queryByTestId); }); - it("respects the `interactOutsideBehavior: 'ignore'` prop", async () => { + it("should respect the `interactOutsideBehavior: 'ignore'` prop", async () => { const { getByTestId, queryByTestId, user } = await open({ contentProps: { interactOutsideBehavior: "ignore", @@ -179,7 +179,7 @@ describe("alert dialog", () => { await expectIsOpen(queryByTestId); }); - it("respects the the `escapeKeydownBehavior: 'ignore'` prop", async () => { + it("should respect the the `escapeKeydownBehavior: 'ignore'` prop", async () => { const { user, getByTestId, queryByTestId } = await open({ contentProps: { escapeKeydownBehavior: "ignore", diff --git a/packages/bits-ui/src/tests/avatar/Avatar.spec.ts b/packages/bits-ui/src/tests/avatar/Avatar.spec.ts index 703a2571f..85bfdad7e 100644 --- a/packages/bits-ui/src/tests/avatar/Avatar.spec.ts +++ b/packages/bits-ui/src/tests/avatar/Avatar.spec.ts @@ -7,12 +7,12 @@ import AvatarTest from "./AvatarTest.svelte"; const src = "https://github.com/huntabyte.png"; describe("avatar", () => { - it("has no accessibility violations", async () => { + it("should have no accessibility violations", async () => { const { container } = render(AvatarTest, { src }); expect(await axe(container)).toHaveNoViolations(); }); - it("has bits data attrs", async () => { + it("should have bits data attrs", async () => { const { getByTestId } = render(AvatarTest); const root = getByTestId("root"); const image = getByTestId("image"); @@ -22,13 +22,13 @@ describe("avatar", () => { expect(fallback).toHaveAttribute("data-avatar-fallback"); }); - it("renders the image with the correct src", async () => { + it("should render the image with the correct src", async () => { const { getByAltText } = render(AvatarTest, { src }); const avatar = getByAltText("huntabyte"); expect(avatar).toHaveAttribute("src", "https://github.com/huntabyte.png"); }); - it("renders the fallback when an invalid image src is provided", async () => { + it("should render the fallback when an invalid image src is provided", async () => { const { getByAltText, getByText } = render(AvatarTest, { src: "invalid" }); const avatar = getByAltText("huntabyte"); expect(avatar).not.toBeVisible(); @@ -36,7 +36,7 @@ describe("avatar", () => { expect(fallback).toBeVisible(); }); - it("removes the avatar when the src is removed", async () => { + it("should remove the avatar when the src is removed", async () => { const user = userEvent.setup(); const { getByAltText, getByTestId, getByText } = render(AvatarTest, { src }); const avatar = getByAltText("huntabyte"); diff --git a/packages/bits-ui/src/tests/calendar/Calendar.spec.ts b/packages/bits-ui/src/tests/calendar/Calendar.spec.ts index d7b303953..84b9a992d 100644 --- a/packages/bits-ui/src/tests/calendar/Calendar.spec.ts +++ b/packages/bits-ui/src/tests/calendar/Calendar.spec.ts @@ -37,33 +37,33 @@ function setupMulti(props: Partial = {}) { } describe("calendar", () => { - it("has no accessibility violations", async () => { + it("should have no accessibility violations", async () => { const { container } = render(CalendarTest); expect(await axe(container)).toHaveNoViolations(); }); - it("respects a default value if provided - `CalendarDate`", async () => { + it("should respect a default value if provided - `CalendarDate`", async () => { const { calendar, getByTestId } = setup({ value: calendarDate }); expect(getSelectedDay(calendar)).toHaveTextContent(String(calendarDate.day)); expect(getByTestId("heading")).toHaveTextContent("January 1980"); }); - it("respects a default value if provided - `CalendarDateTime`", async () => { + it("should respect a default value if provided - `CalendarDateTime`", async () => { const { calendar, getByTestId } = setup({ value: calendarDateTime }); expect(getSelectedDay(calendar)).toHaveTextContent(String(calendarDateTime.day)); expect(getByTestId("heading")).toHaveTextContent("January 1980"); }); - it("respects a default value if provided - `ZonedDateTime`", async () => { + it("should respect a default value if provided - `ZonedDateTime`", async () => { const { calendar, getByTestId } = setup({ value: zonedDateTime }); expect(getSelectedDay(calendar)).toHaveTextContent(String(zonedDateTime.day)); expect(getByTestId("heading")).toHaveTextContent("January 1980"); }); - it("properly binds to `value` - `CalendarDate`", async () => { + it("should bind to `value` - `CalendarDate`", async () => { const { getByTestId, user } = setup({ value: calendarDate }); const addDayBtn = getByTestId("add-day"); @@ -80,7 +80,7 @@ describe("calendar", () => { expect(valueEl).toHaveTextContent("1981-02-21"); }); - it("properly binds to `value` - `CalendarDateTime`", async () => { + it("should bind to `value` - `CalendarDateTime`", async () => { const { getByTestId, user } = setup({ value: calendarDateTime }); const addDayBtn = getByTestId("add-day"); @@ -114,7 +114,7 @@ describe("calendar", () => { expect(valueEl).toHaveTextContent("1981-02-21"); }); - it("navigates the months forward using the next button", async () => { + it("should navigate the months forward using the next button", async () => { const { getByTestId, user } = setup({ value: calendarDate }); const heading = getByTestId("heading"); @@ -127,7 +127,7 @@ describe("calendar", () => { expect(heading).toHaveTextContent("January 1981"); }); - it("navigates the months backwards using the prev button", async () => { + it("should navigate the months backwards using the prev button", async () => { const { getByTestId, user } = setup({ value: calendarDate }); const heading = getByTestId("heading"); @@ -145,7 +145,7 @@ describe("calendar", () => { expect(heading).toHaveTextContent("January 1979"); }); - it("allows dates to be deselected by clicking the selected date", async () => { + it("should allow dates to be deselected by clicking the selected date", async () => { const { getByTestId, user, calendar } = setup({ value: calendarDate, }); @@ -160,7 +160,7 @@ describe("calendar", () => { expect(value).toHaveTextContent("undefined"); }); - it.each([kbd.ENTER, kbd.SPACE])("allows deselection with %s key", async (key) => { + it.each([kbd.ENTER, kbd.SPACE])("should allow deselection with %s key", async (key) => { const { getByTestId, user, calendar } = setup({ value: calendarDate, }); @@ -175,7 +175,7 @@ describe("calendar", () => { expect(value).toHaveTextContent("undefined"); }); - it("allows selection with mouse", async () => { + it("should allow selection with mouse", async () => { const { getByTestId, user } = setup({ placeholder: zonedDateTime, }); @@ -188,7 +188,7 @@ describe("calendar", () => { expect(getByTestId("value")).toHaveTextContent(newDate.toString()); }); - it.each([kbd.SPACE, kbd.ENTER])("allows selection with %s key", async (key) => { + it.each([kbd.SPACE, kbd.ENTER])("should allow selection with %s key", async (key) => { const { getByTestId, user } = setup({ placeholder: zonedDateTime, }); @@ -202,7 +202,7 @@ describe("calendar", () => { expect(getByTestId("value")).toHaveTextContent(newDate.toString()); }); - it("displays multiple months when `numberOfMonths` is greater than 1", async () => { + it("should display multiple months when `numberOfMonths` is greater than 1", async () => { const { getByTestId, calendar, user } = setup({ value: calendarDateTime, numberOfMonths: 2, @@ -240,7 +240,7 @@ describe("calendar", () => { expect(firstMonthDay).not.toHaveAttribute("data-value", firstMonthDayDateStr); }); - it("properly handles `pagedNavigation` with multiple months", async () => { + it("should handles `pagedNavigation` with multiple months", async () => { const { getByTestId, calendar, user } = setup({ value: calendarDateTime, numberOfMonths: 2, @@ -279,7 +279,7 @@ describe("calendar", () => { expect(firstMonthDay).not.toHaveAttribute("data-value", firstMonthDayDateStr); }); - it("always renders six weeks when `fixedWeeks` is `true`", async () => { + it("should renders six weeks when `fixedWeeks` is `true`", async () => { const { getByTestId, calendar, user } = setup({ value: calendarDate, fixedWeeks: true, @@ -380,7 +380,7 @@ describe("calendar", () => { expect(heading).toHaveTextContent("March 1980"); }); - it("does not navigate after `maxValue` (with keyboard)", async () => { + it("should not navigate after `maxValue` (with keyboard)", async () => { const { getByTestId, user } = setup({ value: calendarDate, maxValue: new CalendarDate(1980, 3, 31), @@ -429,7 +429,7 @@ describe("calendar", () => { expect(heading).toHaveTextContent("March 1980"); }); - it("does not navigate before `minValue` (with keyboard)", async () => { + it("should not navigate before `minValue` (with keyboard)", async () => { const { getByTestId, user } = setup({ value: calendarDate, minValue: new CalendarDate(1979, 12, 1), @@ -459,7 +459,7 @@ describe("calendar", () => { expect(heading).toHaveTextContent("December 1979"); }); - it("handles unavailable dates appropriately", async () => { + it("should handle unavailable dates appropriately", async () => { const { getByTestId, user } = setup({ placeholder: calendarDate, isDateUnavailable: (date) => { @@ -475,7 +475,7 @@ describe("calendar", () => { expect(thirdDayInMonth).not.toHaveAttribute("data-selected"); }); - it("doesnt allow focus or interaction when `disabled` is `true`", async () => { + it("should not allow focus or interaction when `disabled` is `true`", async () => { const { getByTestId, user } = setup({ placeholder: calendarDate, disabled: true, @@ -502,7 +502,7 @@ describe("calendar", () => { expect(tenthDayOfMonth).not.toHaveFocus(); }); - it("prevents selection but allows focus when `readonly` is `true`", async () => { + it("should prevent selection but allows focus when `readonly` is `true`", async () => { const { getByTestId, user } = setup({ placeholder: calendarDate, readonly: true, @@ -525,7 +525,7 @@ describe("calendar", () => { expect(tenthDayOfMonth).toHaveFocus(); }); - it("formats the weekday labels correctly - `'narrow'`", async () => { + it("should format the weekday labels correctly - `'narrow'`", async () => { const { getByTestId } = setup({ placeholder: calendarDate, weekdayFormat: "narrow", @@ -536,7 +536,7 @@ describe("calendar", () => { } }); - it("formats the weekday labels correctly - `'short'`", async () => { + it("should format the weekday labels correctly - `'short'`", async () => { const { getByTestId } = setup({ placeholder: calendarDate, weekdayFormat: "short", @@ -547,7 +547,7 @@ describe("calendar", () => { } }); - it("formats the weekday labels correctly - `'long'`", async () => { + it("should format the weekday labels correctly - `'long'`", async () => { const { getByTestId } = setup({ placeholder: calendarDate, weekdayFormat: "long", @@ -560,7 +560,7 @@ describe("calendar", () => { }); describe("calendar - `multiple`", () => { - it("handles default value when `value` prop is provided - `CalendarDate[]`", async () => { + it("should handle default value when `value` prop is provided - `CalendarDate[]`", async () => { const d1 = new CalendarDate(1980, 1, 2); const d2 = new CalendarDate(1980, 1, 5); @@ -574,7 +574,7 @@ describe("calendar - `multiple`", () => { expect(selectedDays[1]).toHaveTextContent(String(d2.day)); }); - it("handles default value when `value` prop is provided - `CalendarDateTime[]`", async () => { + it("should handle default value when `value` prop is provided - `CalendarDateTime[]`", async () => { const d1 = new CalendarDateTime(1980, 1, 2); const d2 = new CalendarDateTime(1980, 1, 5); @@ -588,7 +588,7 @@ describe("calendar - `multiple`", () => { expect(selectedDays[1]).toHaveTextContent(String(d2.day)); }); - it("handles default value when `value` prop is provided - `ZonedDateTime[]`", async () => { + it("should handle default value when `value` prop is provided - `ZonedDateTime[]`", async () => { const d1 = toZoned(new CalendarDateTime(1980, 1, 2), "America/New_York"); const d2 = toZoned(new CalendarDateTime(1980, 1, 5), "America/New_York"); @@ -602,7 +602,7 @@ describe("calendar - `multiple`", () => { expect(selectedDays[1]).toHaveTextContent(String(d2.day)); }); - it("sets placeholder to last value in `value` prop", async () => { + it("should set placeholder to last value in `value` prop", async () => { const d1 = new CalendarDate(1980, 1, 2); const d2 = new CalendarDate(1980, 5, 5); @@ -615,7 +615,7 @@ describe("calendar - `multiple`", () => { expect(getByTestId("heading")).toHaveTextContent("May 1980"); }); - it("allows deselection", async () => { + it("should allow deselection", async () => { const d1 = new CalendarDate(1980, 1, 2); const d2 = new CalendarDate(1980, 1, 5); @@ -628,7 +628,7 @@ describe("calendar - `multiple`", () => { expect(getSelectedDays(calendar).length).toBe(1); }); - it("prevents deselection when only one date is selected and `preventDeselect` is `true`", async () => { + it("should prevent deselection when only one date is selected and `preventDeselect` is `true`", async () => { const d1 = new CalendarDate(1980, 1, 2); const { calendar, user } = setupMulti({ diff --git a/packages/bits-ui/src/tests/checkbox/Checkbox.spec.ts b/packages/bits-ui/src/tests/checkbox/Checkbox.spec.ts index 1575261a0..8d1d23ad6 100644 --- a/packages/bits-ui/src/tests/checkbox/Checkbox.spec.ts +++ b/packages/bits-ui/src/tests/checkbox/Checkbox.spec.ts @@ -22,32 +22,32 @@ function setup(props?: Checkbox.RootProps) { } describe("checkbox", () => { - it("has no accessibility violations", async () => { + it("should have no accessibility violations", async () => { const { container } = render(CheckboxTest); expect(await axe(container)).toHaveNoViolations(); }); - it("has bits data attrs", async () => { + it("should have bits data attrs", async () => { const { root } = setup(); expect(root).toHaveAttribute("data-checkbox-root"); }); - it("doesn't render the checkbox input if a name prop isnt passed", async () => { + it("should not render the checkbox input if a name prop isnt passed", async () => { const { input } = setup({ name: "" }); expect(input).not.toBeInTheDocument(); }); - it("renders the checkbox input if a name prop is passed", async () => { + it("should render the checkbox input if a name prop is passed", async () => { const { input } = setup({ name: "checkbox" }); expect(input).toBeInTheDocument(); }); - it('defaults the value to "on", when no value prop is passed', async () => { + it('should default the value to "on", when no value prop is passed', async () => { const { input } = setup(); expect(input).toHaveAttribute("value", "on"); }); - it("can be indeterminate", async () => { + it("should be able to be indeterminate", async () => { const { getByTestId, root, input } = setup({ checked: "indeterminate" }); const indicator = getByTestId("indicator"); expect(root).toHaveAttribute("data-state", "indeterminate"); @@ -58,7 +58,7 @@ describe("checkbox", () => { expect(indicator).not.toHaveTextContent("false"); }); - it("toggles when clicked", async () => { + it("should toggle when clicked", async () => { const { getByTestId, root, input, user } = setup(); const indicator = getByTestId("indicator"); expect(root).toHaveAttribute("data-state", "unchecked"); @@ -76,7 +76,7 @@ describe("checkbox", () => { expect(indicator).not.toHaveTextContent("indeterminate"); }); - it("toggles when the `Space` key is pressed", async () => { + it("should toggle when the `Space` key is pressed", async () => { const { root, input, user } = setup(); expect(root).toHaveAttribute("data-state", "unchecked"); expect(root).toHaveAttribute("aria-checked", "false"); @@ -88,7 +88,7 @@ describe("checkbox", () => { expect(input.checked).toBe(true); }); - it("does not toggle when the `Enter` key is pressed", async () => { + it("should not toggle when the `Enter` key is pressed", async () => { const { getByTestId, root, input, user } = setup(); const indicator = getByTestId("indicator"); expect(root).toHaveAttribute("data-state", "unchecked"); diff --git a/packages/bits-ui/src/tests/collapsible/Collapsible.spec.ts b/packages/bits-ui/src/tests/collapsible/Collapsible.spec.ts index 92eed39ed..947c9bf0c 100644 --- a/packages/bits-ui/src/tests/collapsible/Collapsible.spec.ts +++ b/packages/bits-ui/src/tests/collapsible/Collapsible.spec.ts @@ -23,26 +23,26 @@ function setup(props?: Collapsible.RootProps) { } describe("collapsible", () => { - it("has no accessibility violations", async () => { + it("should have no accessibility violations", async () => { const { container } = render(CollapsibleTest); expect(await axe(container)).toHaveNoViolations(); }); - it("has bits data attrs", async () => { + it("should have bits data attrs", async () => { const { root, trigger, content } = setup(); expect(root).toHaveAttribute("data-collapsible-root"); expect(trigger).toHaveAttribute("data-collapsible-trigger"); expect(content).toHaveAttribute("data-collapsible-content"); }); - it("content is hidden when `open` is false", async () => { + it("should hide content when `open` is false", async () => { const { root, trigger, content } = setup(); expect(root).not.toBeNull(); expect(trigger).not.toBeNull(); expect(content).not.toBeVisible(); }); - it("toggles the `open` state when clicked", async () => { + it("should toggle the `open` state when clicked", async () => { const { user, trigger, content } = setup(); expect(content).not.toBeVisible(); await user.click(trigger); @@ -51,7 +51,7 @@ describe("collapsible", () => { expect(content).not.toBeVisible(); }); - it("respects binds to the `open` prop", async () => { + it("should respect binds to the `open` prop", async () => { const { getByTestId, user, trigger, binding } = setup({ open: false }); expect(binding).toHaveTextContent("false"); await user.click(trigger); diff --git a/packages/bits-ui/src/tests/combobox/Combobox.spec.ts b/packages/bits-ui/src/tests/combobox/Combobox.spec.ts index ef9e08ea8..f41287ed2 100644 --- a/packages/bits-ui/src/tests/combobox/Combobox.spec.ts +++ b/packages/bits-ui/src/tests/combobox/Combobox.spec.ts @@ -146,26 +146,26 @@ async function openMultiple( const OPEN_KEYS = [kbd.ARROW_DOWN, kbd.ARROW_UP]; describe("combobox - single", () => { - it("has no accessibility violations", async () => { + it("should have noaccessibility violations", async () => { const { container } = render(ComboboxTest); expect(await axe(container)).toHaveNoViolations(); }); - it("opens on click", async () => { + it("should open on click", async () => { await openSingle(); }); - it.each(OPEN_KEYS)("opens on %s keydown", async (key) => { + it.each(OPEN_KEYS)("should open on %s keydown", async (key) => { await openSingle({}, key); }); - it("applies the appropriate `aria-labelledby` attribute to the group", async () => { + it("should applie the appropriate `aria-labelledby` attribute to the group", async () => { const { group, groupLabel } = await openSingle(); expect(group).toHaveAttribute("aria-labelledby", groupLabel.id); }); - it("selects item with the enter key", async () => { + it("should select item with the enter key", async () => { const { user, input } = await openSingle(); await user.keyboard(kbd.ARROW_DOWN); await user.keyboard(kbd.ENTER); @@ -173,38 +173,38 @@ describe("combobox - single", () => { expect(input).toHaveValue("B"); }); - it("renders an input if the `name` prop is passed", async () => { + it("should render an input if the `name` prop is passed", async () => { const { getHiddenInput } = setupSingle(); expect(getHiddenInput()).toBeInTheDocument(); }); - it("doesn't render an input if the `name` prop isn't passed or is an empty string/undefined", async () => { + it("should not render an input if the `name` prop isn't passed or is an empty string/undefined", async () => { const { getHiddenInput } = setupSingle({ name: "" }); expect(getHiddenInput()).not.toBeInTheDocument(); }); - it("syncs the value prop to the hidden input", async () => { + it("should sync the value prop to the hidden input", async () => { const { getHiddenInput } = setupSingle({ value: "test" }); expect(getHiddenInput()).toHaveValue("test"); }); - it("syncs the required prop to the hidden input", async () => { + it("should sync the required prop to the hidden input", async () => { const { getHiddenInput } = setupSingle({ required: true }); expect(getHiddenInput()).toHaveAttribute("required"); }); - it("syncs the disabled prop to the hidden input", async () => { + it("should sync the disabled prop to the hidden input", async () => { const { getHiddenInput } = setupSingle({ disabled: true }); expect(getHiddenInput()).toHaveAttribute("disabled"); }); - it("closes on escape keydown", async () => { + it("should close on escape keydown", async () => { const { user, getContent } = await openSingle(); await user.keyboard(kbd.ESCAPE); expect(getContent()).toBeNull(); }); - it("closes on outside click", async () => { + it("should close on outside click", async () => { const { user, getContent, outside } = await openSingle(); await sleep(100); await user.click(outside); @@ -212,12 +212,12 @@ describe("combobox - single", () => { expect(getContent()).toBeNull(); }); - it("portals to the body by default", async () => { + it("should portal to the body by default", async () => { const { content } = await openSingle(); expect(content.parentElement?.parentElement).toBe(document.body); }); - it("portals to a custom element if specified", async () => { + it("should portal to a custom element if specified", async () => { const { content, getByTestId } = await openSingle({ portalProps: { to: "#portal-target" }, }); @@ -225,13 +225,13 @@ describe("combobox - single", () => { expect(content.parentElement?.parentElement).toBe(portalTarget); }); - it("does not portal if `disabled` is passed as portal prop", async () => { + it("should not portal if `disabled` is passed as portal prop", async () => { const { content, getByTestId } = await openSingle({ portalProps: { disabled: true } }); const main = getByTestId("main"); expect(content.parentElement?.parentElement).toBe(main); }); - it("respects binding the `open` prop", async () => { + it("should respect binding the `open` prop", async () => { const { getContent, user, openBinding } = await openSingle(); expect(openBinding).toHaveTextContent("true"); await user.click(openBinding); @@ -242,14 +242,14 @@ describe("combobox - single", () => { await waitFor(() => expect(getContent()).not.toBeNull()); }); - it("respects binding the `value` prop", async () => { + it("should respect binding the `value` prop", async () => { const { user, valueBinding } = await openSingle({ value: "1" }); expect(valueBinding).toHaveTextContent("1"); await user.click(valueBinding); expect(valueBinding).toHaveTextContent("empty"); }); - it("selects items when clicked", async () => { + it("should select items when clicked", async () => { const { getByTestId, user, queryByTestId, input, getHiddenInput } = await openSingle(); const [item1] = getItems(getByTestId); expect(queryByTestId("1-indicator")).toBeNull(); @@ -261,7 +261,7 @@ describe("combobox - single", () => { expect(queryByTestId("1-indicator")).not.toBeNull(); }); - it("navigates through the items using the keyboard (loop = false)", async () => { + it("should navigate through the items using the keyboard (loop = false)", async () => { const { getByTestId, user } = await openSingle({}, kbd.ARROW_DOWN); const [item0, item1, item2, item3] = getItems(getByTestId); @@ -285,7 +285,7 @@ describe("combobox - single", () => { expectHighlighted(item0!); }); - it("navigates through the items using the keyboard (loop = true)", async () => { + it("should navigate through the items using the keyboard (loop = true)", async () => { const { getByTestId, user } = await openSingle( { loop: true, @@ -317,7 +317,7 @@ describe("combobox - single", () => { expectHighlighted(item3!); }); - it("allows items to be selected using the keyboard", async () => { + it("should allow items to be selected using the keyboard", async () => { const { getByTestId, user, input, getHiddenInput } = await openSingle({}, kbd.ARROW_DOWN); const [item0, item1, item2, item3] = getItems(getByTestId); @@ -333,7 +333,7 @@ describe("combobox - single", () => { expectSelected(item3!); }); - it("applies the `data-highlighted` attribute on mouseover", async () => { + it("should apply the `data-highlighted` attribute on mouseover", async () => { const { getByTestId, user } = await openSingle({}, kbd.ARROW_DOWN); const [item1, item2] = getItems(getByTestId); await user.hover(item1!); @@ -343,7 +343,7 @@ describe("combobox - single", () => { expectNotHighlighted(item1!); }); - it("starts keyboard navigation at the highlighted item even if hovered with mouse", async () => { + it("should start keyboard navigation at the highlighted item even if hovered with mouse", async () => { const { getByTestId, user, input } = await openSingle({}, kbd.ARROW_DOWN); const [item1, item2, item3] = getItems(getByTestId); await user.click(input); @@ -357,7 +357,7 @@ describe("combobox - single", () => { expectNotHighlighted(item2!); }); - it("selects a default item when provided", async () => { + it("should select a default item when provided", async () => { const { getByTestId, queryByTestId, input, getHiddenInput } = await openSingle({ value: "2", inputProps: { @@ -371,7 +371,7 @@ describe("combobox - single", () => { expectSelected(item2!); }); - it("allows navigating after navigating to the bottom, closing, and reopening the menu", async () => { + it("should allow navigating after navigating to the bottom, closing, and reopening the menu", async () => { const { getByTestId, user, getContent } = await openSingle(); const [item0, item1, item2, item3] = getItems(getByTestId); expectHighlighted(item0!); @@ -399,32 +399,32 @@ describe("combobox - single", () => { // MULTIPLE //////////////////////////////////// describe("combobox - multiple", () => { - it("has no accessibility violations", async () => { + it("should have no accessibility violations", async () => { const { container } = render(ComboboxMultiTest); expect(await axe(container)).toHaveNoViolations(); }); - it("opens on click", async () => { + it("should open on click", async () => { await openMultiple(); }); - it.each(OPEN_KEYS)("opens on %s keydown", async (key) => { + it.each(OPEN_KEYS)("should open on %s keydown", async (key) => { await openMultiple({}, key); }); - it("selects item with the enter key", async () => { + it("should select item with the enter key", async () => { const { user, input } = await openMultiple(); await user.keyboard(kbd.ARROW_DOWN); await user.keyboard(kbd.ENTER); expect(input).toHaveValue("B"); }); - it("renders a hidden input if the `name` prop is passed", async () => { + it("should render a hidden input if the `name` prop is passed", async () => { const { getHiddenInputs } = setupMultiple(); expect(getHiddenInputs()).toHaveLength(1); }); - it("renders a hidden input for each value in the `value` array, each with the same `name` prop", async () => { + it("should render a hidden input for each value in the `value` array, each with the same `name` prop", async () => { const { getHiddenInputs } = setupMultiple({ value: ["a", "b"] }); const hiddenInputs = getHiddenInputs(); expect(hiddenInputs).toHaveLength(2); @@ -432,7 +432,7 @@ describe("combobox - multiple", () => { expect(hiddenInputs[1]).toHaveAttribute("name", "test"); }); - it("syncs the value prop to the hidden inputs", async () => { + it("should sync the value prop to the hidden inputs", async () => { const { getHiddenInputs } = setupMultiple({ value: ["a", "b"] }); const hiddenInputs = getHiddenInputs(); expect(hiddenInputs).toHaveLength(2); @@ -440,7 +440,7 @@ describe("combobox - multiple", () => { expect(hiddenInputs[1]).toHaveValue("b"); }); - it("syncs the required prop to the hidden inputs", async () => { + it("should sync the required prop to the hidden inputs", async () => { const { getHiddenInputs } = setupMultiple({ required: true, value: ["a", "b"] }); const hiddenInputs = getHiddenInputs(); expect(hiddenInputs).toHaveLength(2); @@ -450,7 +450,7 @@ describe("combobox - multiple", () => { } }); - it("syncs the disabled prop to the hidden inputs", async () => { + it("should sync the disabled prop to the hidden inputs", async () => { const { getHiddenInputs } = setupMultiple({ disabled: true, value: ["a", "b"] }); const hiddenInputs = getHiddenInputs(); expect(hiddenInputs).toHaveLength(2); @@ -460,13 +460,13 @@ describe("combobox - multiple", () => { } }); - it("closes on escape keydown", async () => { + it("should close on escape keydown", async () => { const { user, getContent } = await openMultiple(); await user.keyboard(kbd.ESCAPE); expect(getContent()).toBeNull(); }); - it("closes on outside click", async () => { + it("should close on outside click", async () => { const { user, getContent, outside } = await openMultiple(); await sleep(100); await user.click(outside); @@ -474,12 +474,12 @@ describe("combobox - multiple", () => { expect(getContent()).toBeNull(); }); - it("portals to the body by default", async () => { + it("should portal to the body by default", async () => { const { content } = await openMultiple(); expect(content.parentElement?.parentElement).toBe(document.body); }); - it("portals to a custom element if specified", async () => { + it("should portal to a custom element if specified", async () => { const { content, getByTestId } = await openMultiple({ portalProps: { to: "#portal-target" }, }); @@ -487,13 +487,13 @@ describe("combobox - multiple", () => { expect(content.parentElement?.parentElement).toBe(portalTarget); }); - it("does not portal if `disabled` is passed as portal prop", async () => { + it("should not portal if `disabled` is passed as portal prop", async () => { const { content, getByTestId } = await openMultiple({ portalProps: { disabled: true } }); const main = getByTestId("main"); expect(content.parentElement?.parentElement).toBe(main); }); - it("respects binding the `open` prop", async () => { + it("should respect binding the `open` prop", async () => { const { getContent, getByTestId, user, openBinding } = await openMultiple(); expect(openBinding).toHaveTextContent("true"); await user.click(openBinding); @@ -504,14 +504,14 @@ describe("combobox - multiple", () => { await waitFor(() => expect(getContent()).not.toBeNull()); }); - it("respects binding the `value` prop", async () => { + it("should respect binding the `value` prop", async () => { const { user, valueBinding } = await openMultiple({ value: ["1", "2"] }); expect(valueBinding.textContent).toEqual("1,2"); await user.click(valueBinding); expect(valueBinding.textContent).toEqual("empty"); }); - it("selects items when clicked", async () => { + it("should select items when clicked", async () => { const { getByTestId, user, queryByTestId, input, getHiddenInputs } = await openMultiple(); const [item] = getItems(getByTestId); await waitFor(() => expect(queryByTestId("1-indicator")).toBeNull()); @@ -525,7 +525,7 @@ describe("combobox - multiple", () => { await waitFor(() => expect(queryByTestId("1-indicator")).not.toBeNull()); }); - it("navigates through the items using the keyboard (loop = false)", async () => { + it("should navigate through the items using the keyboard (loop = false)", async () => { const { getByTestId, user } = await openMultiple({}, kbd.ARROW_DOWN); const [item0, item1, item2, item3] = getItems(getByTestId); @@ -549,7 +549,7 @@ describe("combobox - multiple", () => { expectHighlighted(item0!); }); - it("navigates through the items using the keyboard (loop = true)", async () => { + it("should navigate through the items using the keyboard (loop = true)", async () => { const { getByTestId, user } = await openMultiple( { loop: true, @@ -581,7 +581,7 @@ describe("combobox - multiple", () => { expectHighlighted(item3!); }); - it("allows items to be selected using the keyboard", async () => { + it("should allow items to be selected using the keyboard", async () => { const { getByTestId, user, input, getHiddenInputs } = await openMultiple( {}, kbd.ARROW_DOWN @@ -602,7 +602,7 @@ describe("combobox - multiple", () => { expectSelected(item3!); }); - it("allows multiple items to be selected using the keyboard", async () => { + it("should allow multiple items to be selected using the keyboard", async () => { const { getByTestId, user, input, getHiddenInputs } = await openMultiple( {}, kbd.ARROW_DOWN @@ -627,7 +627,7 @@ describe("combobox - multiple", () => { expectNotSelected([item0!, item1!]); }); - it("applies the `data-highlighted` attribute on mouseover", async () => { + it("should apply the `data-highlighted` attribute on mouseover", async () => { const { getByTestId, user } = await openMultiple({}, kbd.ARROW_DOWN); const [item1, item2] = getItems(getByTestId); await user.hover(item1!); @@ -637,7 +637,7 @@ describe("combobox - multiple", () => { expectNotHighlighted(item1!); }); - it("selects a default item when provided", async () => { + it("should select a default item when provided", async () => { const { getByTestId, queryByTestId, input, container, getHiddenInputs } = await openMultiple({ value: ["2"], diff --git a/packages/bits-ui/src/tests/context-menu/ContextMenu.spec.ts b/packages/bits-ui/src/tests/context-menu/ContextMenu.spec.ts index c6f78358d..e35856ce7 100644 --- a/packages/bits-ui/src/tests/context-menu/ContextMenu.spec.ts +++ b/packages/bits-ui/src/tests/context-menu/ContextMenu.spec.ts @@ -12,23 +12,31 @@ const kbd = getTestKbd(); */ function setup(props: ContextMenuTestProps = {}) { const user = setupUserEvents(); - const { getByTestId, queryByTestId } = render(ContextMenuTest, { ...props }); - const trigger = getByTestId("trigger"); + const returned = render(ContextMenuTest, { ...props }); + const trigger = returned.getByTestId("trigger"); + function getContent() { + return returned.queryByTestId("content"); + } + + function getSubContent() { + return returned.queryByTestId("sub-content"); + } return { - getByTestId, - queryByTestId, + ...returned, + getContent, + getSubContent, user, trigger, }; } async function open(props: ContextMenuTestProps = {}) { - const { getByTestId, queryByTestId, user, trigger } = setup(props); - const content = queryByTestId("content"); - expect(content).toBeNull(); + const { getByTestId, queryByTestId, user, trigger, getContent, ...returned } = setup(props); + + expect(getContent()).toBeNull(); await user.pointer([{ target: trigger }, { keys: "[MouseRight]", target: trigger }]); - expect(queryByTestId("content")).not.toBeNull(); - return { getByTestId, queryByTestId, user, trigger }; + expect(getContent()).not.toBeNull(); + return { getByTestId, queryByTestId, user, trigger, getContent, ...returned }; } async function openSubmenu(props: Awaited>) { @@ -37,6 +45,7 @@ async function openSubmenu(props: Awaited>) { await user.keyboard(kbd.ARROW_DOWN); await waitFor(() => expect(queryByTestId("sub-trigger")).toHaveFocus()); + expect(queryByTestId("sub-content")).toBeNull(); await user.keyboard(kbd.ARROW_RIGHT); expect(queryByTestId("sub-content")).not.toBeNull(); @@ -51,12 +60,12 @@ async function openSubmenu(props: Awaited>) { } describe("context menu", () => { - it("has no accessibility violations", async () => { + it("should have no accessibility violations", async () => { const { container } = render(ContextMenuTest); expect(await axe(container)).toHaveNoViolations(); }); - it("has bits data attrs", async () => { + it("should have bits data attrs", async () => { const { user, trigger, getByTestId } = setup(); await user.pointer([{ target: trigger }, { keys: "[MouseRight]", target: trigger }]); @@ -84,28 +93,25 @@ describe("context menu", () => { expect(subContent).toHaveAttribute(`data-menu-sub-content`); }); - it("opens when right-clicked & respects binding", async () => { - const { getByTestId, queryByTestId, user, trigger } = setup(); + it("should open when right-clicked & respects binding", async () => { + const { getByTestId, getContent, user, trigger } = setup(); const binding = getByTestId("binding"); expect(binding).toHaveTextContent("false"); await user.pointer([{ target: trigger }, { keys: "[MouseRight]", target: trigger }]); - expect(queryByTestId("content")).not.toBeNull(); + expect(getContent()).not.toBeNull(); expect(binding).toHaveTextContent("true"); }); - it("manages focus correctly when opened with pointer", async () => { + it("should manage focus correctly when opened with pointer", async () => { cleanup(); const { queryByTestId, user } = await open(); - const item = queryByTestId("item"); expect(item).not.toHaveFocus(); - await user.keyboard(kbd.ARROW_DOWN); - expect(item).toHaveFocus(); }); - it("opens submenu with keyboard on subtrigger", async () => { + it("should open submenu with keyboard on subtrigger", async () => { const { getByTestId, queryByTestId, user } = await open(); await user.keyboard(kbd.ARROW_DOWN); @@ -118,7 +124,7 @@ describe("context menu", () => { await waitFor(() => expect(getByTestId("sub-item")).toHaveFocus()); }); - it("toggles the checkbox item when clicked & respects binding", async () => { + it("should toggle the checkbox item when clicked & respects binding", async () => { const { getByTestId, user, trigger } = await open(); const checkedBinding = getByTestId("checked-binding"); const indicator = getByTestId("checkbox-indicator"); @@ -138,7 +144,7 @@ describe("context menu", () => { expect(getByTestId("checkbox-indicator")).toHaveTextContent("true"); }); - it("toggles checkbox items within submenus when clicked & respects binding", async () => { + it("should toggle checkbox items within submenus when clicked & respects binding", async () => { const props = await open(); const { getByTestId, user, trigger } = props; await openSubmenu(props); @@ -162,8 +168,8 @@ describe("context menu", () => { expect(getByTestId("sub-checkbox-indicator")).toHaveTextContent("true"); }); - it("checks the radio item when clicked & respects binding", async () => { - const { getByTestId, queryByTestId, user, trigger } = await open(); + it("should check the radio item when clicked & respects binding", async () => { + const { getByTestId, queryByTestId, getContent, user, trigger } = await open(); const radioBinding = getByTestId("radio-binding"); expect(radioBinding).toHaveTextContent(""); const radioItem1 = getByTestId("radio-item"); @@ -179,14 +185,14 @@ describe("context menu", () => { expect(queryByTestId("radio-indicator-2")).toHaveTextContent("true"); await user.keyboard(kbd.ESCAPE); - expect(queryByTestId("content")).toBeNull(); + expect(getContent()).toBeNull(); await user.click(radioBinding); expect(radioBinding).toHaveTextContent(""); await user.pointer([{ target: trigger }, { keys: "[MouseRight]", target: trigger }]); }); - it("skips over disabled items when navigating with the keyboard", async () => { - const { user, getByTestId, queryByTestId } = await open(); + it("should skip disabled items when navigating with the keyboard", async () => { + const { user, queryByTestId } = await open(); await user.keyboard(kbd.ARROW_DOWN); await user.keyboard(kbd.ARROW_DOWN); await waitFor(() => expect(queryByTestId("sub-trigger")).toHaveFocus()); @@ -196,7 +202,7 @@ describe("context menu", () => { expect(queryByTestId("disabled-item-2")).not.toHaveFocus(); }); - it("doesnt loop through the menu items when the `loop` prop is set to false", async () => { + it("should not loop through the menu items when the `loop` prop is set to false", async () => { const { user, queryByTestId } = await open({ contentProps: { loop: false, @@ -217,7 +223,7 @@ describe("context menu", () => { await waitFor(() => expect(queryByTestId("item")).not.toHaveFocus()); }); - it("loops through the menu items when the `loop` prop is set to true", async () => { + it("should loop through the menu items when the `loop` prop is set to true", async () => { const { user, getByTestId } = await open({ contentProps: { loop: true, @@ -239,41 +245,41 @@ describe("context menu", () => { await waitFor(() => expect(getByTestId("item")).toHaveFocus()); }); - it("closes the menu on escape", async () => { - const { queryByTestId, user } = await open(); + it("should close the menu on escape", async () => { + const { user, getContent } = await open(); await user.keyboard(kbd.ESCAPE); - expect(queryByTestId("content")).toBeNull(); + expect(getContent()).toBeNull(); }); - it("respects the `escapeKeydownBehavior: 'ignore'` prop", async () => { - const { queryByTestId, user } = await open({ + it("should respect the `escapeKeydownBehavior: 'ignore'` prop", async () => { + const { getContent, user } = await open({ contentProps: { escapeKeydownBehavior: "ignore", }, }); await user.keyboard(kbd.ESCAPE); - expect(queryByTestId("content")).not.toBeNull(); + expect(getContent()).not.toBeNull(); }); - it("respects the `interactOutsideBehavior: 'ignore'` prop", async () => { - const { queryByTestId, user, getByTestId } = await open({ + it("should respect the `interactOutsideBehavior: 'ignore'` prop", async () => { + const { getContent, user, getByTestId } = await open({ contentProps: { interactOutsideBehavior: "ignore", }, }); const outside = getByTestId("outside"); await user.click(outside); - expect(queryByTestId("content")).not.toBeNull(); + expect(getContent()).not.toBeNull(); }); - it("portals to the body if a `to` prop is not passed to the Portal", async () => { + it("should portal to the body if a `to` prop is not passed to the Portal", async () => { const { getByTestId } = await open(); const content = getByTestId("content"); const wrapper = content.parentElement; expect(wrapper?.parentElement).toEqual(document.body); }); - it("portals to the portal target if a valid `to` prop is passed to the portal", async () => { + it("should portal to the portal target if a valid `to` prop is passed to the portal", async () => { const { getByTestId } = await open({ portalProps: { to: "#portal-target", @@ -285,7 +291,7 @@ describe("context menu", () => { expect(wrapper?.parentElement).toEqual(portalTarget); }); - it("does not portal if `disabled: true` is passed to the Portal", async () => { + it("should not portal if `disabled: true` is passed to the Portal", async () => { const { getByTestId } = await open({ portalProps: { disabled: true, diff --git a/packages/bits-ui/src/tests/date-field/DateField.spec.ts b/packages/bits-ui/src/tests/date-field/DateField.spec.ts index b90e46914..1cff87793 100644 --- a/packages/bits-ui/src/tests/date-field/DateField.spec.ts +++ b/packages/bits-ui/src/tests/date-field/DateField.spec.ts @@ -35,12 +35,12 @@ function setup(props: DateFieldTestProps = {}) { } describe("date field", () => { - it("has no axe violations", async () => { + it("should have no axe violations", async () => { const { container } = setup(); expect(await axe(container)).toHaveNoViolations(); }); - it("populates segment with value - `CalendarDate`", async () => { + it("should populate segment with value - `CalendarDate`", async () => { const { month, day, year, value } = setup({ value: calendarDate, }); @@ -51,7 +51,7 @@ describe("date field", () => { expect(value).toHaveTextContent(calendarDate.toString()); }); - it("populates segment with value - `CalendarDateTime`", async () => { + it("should populate segment with value - `CalendarDateTime`", async () => { const { month, day, year, value, getByTestId } = setup({ value: calendarDateTime, }); @@ -64,7 +64,7 @@ describe("date field", () => { expect(value).toHaveTextContent(calendarDate.toString()); }); - it("populates segment with value - `ZonedDateTime`", async () => { + it("should populate segment with value - `ZonedDateTime`", async () => { const { month, day, year, value, getByTestId } = setup({ value: zonedDateTime, }); @@ -79,7 +79,7 @@ describe("date field", () => { expect(value).toHaveTextContent(calendarDate.toString()); }); - it("changes segment positioning based on `locale`", async () => { + it("should change segment positioning based on `locale`", async () => { const { input } = setup({ locale: "en-UK", }); @@ -94,7 +94,7 @@ describe("date field", () => { expect(thirdSeg).toHaveTextContent("yyyy"); }); - it("doesnt show the day period for locales that don't use them", async () => { + it("should not show the day period for locales that don't use them", async () => { const { queryByTestId } = setup({ locale: "en-UK", value: calendarDateTime, @@ -102,20 +102,20 @@ describe("date field", () => { expect(queryByTestId("dayPeriod")).toBeNull(); }); - it("does show the day period for locales that do use them", async () => { + it("should show the day period for locales that do use them", async () => { const { queryByTestId } = setup({ value: calendarDateTime, }); expect(queryByTestId("dayPeriod")).not.toBeNull(); }); - it("focuses first segment on label click", async () => { + it("should focus first segment on label click", async () => { const { user, label, month } = setup(); await user.click(label); expect(month).toHaveFocus(); }); - it("focuses segments on click", async () => { + it("should focus segments on click", async () => { const { user, day, month, year, getByTestId } = setup({ value: zonedDateTime, }); @@ -132,7 +132,7 @@ describe("date field", () => { } }); - it("incremenets segment on arrow up", async () => { + it("should increment segment on arrow up", async () => { const { user, day, month, year, getByTestId } = setup({ value: zonedDateTime, granularity: "second", @@ -166,7 +166,7 @@ describe("date field", () => { expect(second).toHaveTextContent(cycle("second")); }); - it("decrements segment on arrow down", async () => { + it("should decrement segment on arrow down", async () => { const { user, day, month, year, getByTestId } = setup({ value: zonedDateTime, granularity: "second", @@ -200,7 +200,7 @@ describe("date field", () => { expect(second).toHaveTextContent(cycle("second")); }); - it("navigates segments using the arrow keys", async () => { + it("should navigate segments using the arrow keys", async () => { const { getByTestId, user, day, month, year } = setup({ value: zonedDateTime, granularity: "second", @@ -234,7 +234,7 @@ describe("date field", () => { expect(month).toHaveFocus(); }); - it("navigates the segments using tab", async () => { + it("should navigate the segments using tab", async () => { const { getByTestId, user, day, month, year } = setup({ value: zonedDateTime, granularity: "second", @@ -258,7 +258,7 @@ describe("date field", () => { } }); - it("prevents interaction when `disabled`", async () => { + it("should prevent interaction when `disabled`", async () => { const { user, getByTestId, day, month, year } = setup({ value: zonedDateTime, granularity: "second", @@ -285,7 +285,7 @@ describe("date field", () => { } }); - it("prevents modification when `readonly`", async () => { + it("should prevent modification when `readonly`", async () => { const { user, getByTestId, day, month, year } = setup({ value: zonedDateTime, granularity: "second", @@ -306,7 +306,7 @@ describe("date field", () => { } }); - it("correctly marks the field as invalid if the value is invalid", async () => { + it("should marks the field as invalid if the value is invalid", async () => { const { getByTestId, day, month, year, input, label, user } = setup({ granularity: "second", isDateUnavailable: (date) => date.day === 19, @@ -345,7 +345,7 @@ describe("date field", () => { expect(label).toHaveAttribute("data-invalid"); }); - it("adjusts the hour cycle with the `hourCycle` prop", async () => { + it("should adjust the hour cycle with the `hourCycle` prop", async () => { const { getByTestId, queryByTestId, user } = setup({ value: zonedDateTime, hourCycle: 24, @@ -360,7 +360,7 @@ describe("date field", () => { expect(hour).toHaveTextContent("13"); }); - it("overrides the default displayed segments with the `granularity` prop - `'day'`", async () => { + it("should override the default displayed segments with the `granularity` prop - `'day'`", async () => { const { queryByTestId, month, day, year } = setup({ value: calendarDateTime, granularity: "day", @@ -377,7 +377,7 @@ describe("date field", () => { } }); - it("overrides the default displayed segments with the `granularity` prop - `'minute'`", async () => { + it("should override the default displayed segments with the `granularity` prop - `'minute'`", async () => { const { queryByTestId, getByTestId, month, day, year } = setup({ value: calendarDateTime, granularity: "minute", @@ -399,7 +399,7 @@ describe("date field", () => { } }); - it("changes the value when the dayPeriod segment is changed", async () => { + it("should change the value when the dayPeriod segment is changed", async () => { const { getByTestId, user, value } = setup({ value: calendarDateTime, }); @@ -415,7 +415,7 @@ describe("date field", () => { expect(value).toHaveTextContent("1980-01-20T00:30"); }); - it("takes you all the way through the segment with spamming 3", async () => { + it("should go all the way through the segment with spamming 3", async () => { const { getByTestId, user, month, day, year } = setup({ value: zonedDateTime, granularity: "second", @@ -444,7 +444,7 @@ describe("date field", () => { expect(getDayPeriod()).toHaveFocus(); }); - it("fully overwrites on first click and type - `month`", async () => { + it("should overwrite on first click and type - `month`", async () => { const { user, month } = setup({ value: zonedDateTime, granularity: "second", @@ -457,7 +457,7 @@ describe("date field", () => { expect(month).toHaveTextContent("3"); }); - it("fully overwrites on first click and type - `day`", async () => { + it("should fully overwrite on first click and type - `day`", async () => { const { user, day } = setup({ value: zonedDateTime, granularity: "second", @@ -470,7 +470,7 @@ describe("date field", () => { expect(day).toHaveTextContent("1"); }); - it("fully overwrites on first click and type - `year`", async () => { + it("should overwrite on first click and type - `year`", async () => { const { user, year } = setup({ value: zonedDateTime, granularity: "second", @@ -483,7 +483,7 @@ describe("date field", () => { expect(year).toHaveTextContent("1"); }); - it("fully overwrites on first click and type - `hour`", async () => { + it("should overwrite on first click and type - `hour`", async () => { const { user, getByTestId } = setup({ value: zonedDateTime, granularity: "second", @@ -497,7 +497,7 @@ describe("date field", () => { expect(hour).toHaveTextContent("1"); }); - it("fully overwrites on first click and type - `minute`", async () => { + it("should overwrite on first click and type - `minute`", async () => { const { user, getByTestId } = setup({ value: zonedDateTime, granularity: "second", @@ -511,7 +511,7 @@ describe("date field", () => { expect(minute).toHaveTextContent("1"); }); - it("fully overwrites on first click and type - `second`", async () => { + it("should overwrite on first click and type - `second`", async () => { const { user, getByTestId } = setup({ value: zonedDateTime, granularity: "second", @@ -525,7 +525,7 @@ describe("date field", () => { expect(second).toHaveTextContent("1"); }); - it("moves to the previous segment when backspace is pressed while empty - `day`", async () => { + it("should move to the previous segment when backspace is pressed while empty - `day`", async () => { const { user, day, month } = setup({ value: zonedDateTime, granularity: "second", @@ -543,7 +543,7 @@ describe("date field", () => { expect(month).toHaveFocus(); }); - it("moves to the previous segment when backspace is pressed while empty - `year`", async () => { + it("should to the previous segment when backspace is pressed while empty - `year`", async () => { const { user, year, day } = setup({ value: zonedDateTime, granularity: "second", @@ -577,7 +577,7 @@ describe("date field", () => { } }); - it("displays correct timezone with ZonedDateTime value - absolute -> local", async () => { + it("should display correct timezone with ZonedDateTime value - absolute -> local", async () => { const { getByTestId } = setup({ value: parseAbsoluteToLocal("2023-10-12T12:30:00Z"), }); diff --git a/packages/bits-ui/src/tests/date-range-field/DateRangeField.spec.ts b/packages/bits-ui/src/tests/date-range-field/DateRangeField.spec.ts index 0152a0c10..dbd86b6a4 100644 --- a/packages/bits-ui/src/tests/date-range-field/DateRangeField.spec.ts +++ b/packages/bits-ui/src/tests/date-range-field/DateRangeField.spec.ts @@ -50,12 +50,12 @@ function setup(props: DateRangeFieldTestProps = {}) { } describe("date range field", () => { - it("has no axe violations", async () => { + it("should have no axe violations", async () => { const { container } = setup(); expect(await axe(container)).toHaveNoViolations(); }); - it("populates segment with value - `CalendarDate`", async () => { + it("should populate segment with value - `CalendarDate`", async () => { const { start, end } = setup({ value: calendarDate, }); @@ -71,7 +71,7 @@ describe("date range field", () => { expect(end.value).toHaveTextContent(calendarDate.end.toString()); }); - it("populates segment with value - `CalendarDateTime`", async () => { + it("should populate segment with value - `CalendarDateTime`", async () => { const { start, end, getByTestId } = setup({ value: calendarDateTime, granularity: "second", @@ -98,7 +98,7 @@ describe("date range field", () => { expect(end.value).toHaveTextContent(calendarDateTime.end.toString()); }); - it("populates segment with value - `ZonedDateTime`", async () => { + it("should populate segment with value - `ZonedDateTime`", async () => { const { start, end, getByTestId } = setup({ value: zonedDateTime, granularity: "second", @@ -125,7 +125,7 @@ describe("date range field", () => { expect(end.value).toHaveTextContent(calendarDateTime.end.toString()); }); - it("navigates between the fields", async () => { + it("should navigate between the fields", async () => { const { getByTestId, user } = setup({ value: calendarDate, }); @@ -156,7 +156,7 @@ describe("date range field", () => { } }); - it("navigates between the fields - right to left", async () => { + it("should navigate between the fields - right to left", async () => { const { getByTestId, user } = setup({ value: calendarDate, }); @@ -187,7 +187,7 @@ describe("date range field", () => { } }); - it("binds to the value", async () => { + it("should respect `bind:value` to the value", async () => { const { start, end, user } = setup({ value: calendarDate, }); @@ -200,7 +200,7 @@ describe("date range field", () => { expect(end.value).toHaveTextContent(calendarDate.end.toString()); }); - it("renders an input for the start and end", async () => { + it("should render an input for the start and end", async () => { const { container } = setup({ startProps: { name: "start-hidden-input", diff --git a/packages/bits-ui/src/tests/dialog/Dialog.spec.ts b/packages/bits-ui/src/tests/dialog/Dialog.spec.ts index e5bc37eb9..b87bee892 100644 --- a/packages/bits-ui/src/tests/dialog/Dialog.spec.ts +++ b/packages/bits-ui/src/tests/dialog/Dialog.spec.ts @@ -51,12 +51,12 @@ async function open(props: DialogTestProps = {}) { } describe("dialog", () => { - it("has no accessibility violations", async () => { + it("should have no accessibility violations", async () => { const { container } = render(DialogTest); expect(await axe(container)).toHaveNoViolations(); }); - it("has bits data attrs", async () => { + it("should have bits data attrs", async () => { const { getByTestId } = render(DialogTest, { open: true }); const parts = ["trigger", "overlay", "close", "title", "description", "content"]; @@ -66,7 +66,7 @@ describe("dialog", () => { } }); - it("has expected data attributes", async () => { + it("should have expected data attributes", async () => { const { getByTestId } = await open(); const overlay = getByTestId("overlay"); @@ -75,18 +75,18 @@ describe("dialog", () => { expect(content).toHaveAttribute("data-state", "open"); }); - it("opens when the trigger is clicked", async () => { + it("should open when the trigger is clicked", async () => { await open(); }); - it("closes when the close button is clicked", async () => { + it("should close when the close button is clicked", async () => { const { getByTestId, queryByTestId, user } = await open(); const close = getByTestId("close"); await user.click(close); expectIsClosed(queryByTestId); }); - it("closes when the `Escape` key is pressed", async () => { + it("should close when the `Escape` key is pressed", async () => { const { queryByTestId, user, getByTestId } = await open(); await user.keyboard(kbd.ESCAPE); @@ -94,7 +94,7 @@ describe("dialog", () => { expect(getByTestId("trigger")).toHaveFocus(); }); - it("closes when the overlay is clicked", async () => { + it("should close when the overlay is clicked", async () => { const { getByTestId, queryByTestId, user } = await open(); await sleep(100); @@ -106,14 +106,14 @@ describe("dialog", () => { expect(contentAfter2).toBeNull(); }); - it("attaches to body when using portal element", async () => { + it("should portal to body when using portal element", async () => { await open(); const content = screen.getByTestId("content"); expect(content.parentElement).toEqual(document.body); }); - it("doesnt attached to body when portal is disabled", async () => { + it("should not portal to body when portal is disabled", async () => { await open({ portalProps: { disabled: true, @@ -123,7 +123,7 @@ describe("dialog", () => { expect(content.parentElement).not.toEqual(document.body); }); - it("portals to the target if passed as a prop", async () => { + it("should portal to the target if passed as a prop", async () => { await open({ portalProps: { to: "#portalTarget", @@ -134,20 +134,20 @@ describe("dialog", () => { expect(content.parentElement).toEqual(portalTarget); }); - it("focuses first focusable item upon opening", async () => { + it("should focus first focusable item upon opening", async () => { const { getByTestId } = await open(); const closeButton = getByTestId("close"); expect(document.activeElement).toBe(closeButton); }); - it("doesnt close when content is clicked", async () => { + it("should not close when content is clicked", async () => { const { user, getByTestId, queryByTestId } = await open(); const content = getByTestId("content"); await user.click(content); await expectIsOpen(queryByTestId); }); - it("respects binding to the `open` prop", async () => { + it("should respect binding to the `open` prop", async () => { const { getByTestId, queryByTestId, user } = setup(); const trigger = getByTestId("trigger"); @@ -164,7 +164,7 @@ describe("dialog", () => { await expectIsOpen(queryByTestId); }); - it("respects the `interactOutsideBehavior: 'ignore'` prop", async () => { + it("should respect the `interactOutsideBehavior: 'ignore'` prop", async () => { const { getByTestId, queryByTestId, user } = await open({ contentProps: { interactOutsideBehavior: "ignore", @@ -178,7 +178,7 @@ describe("dialog", () => { await expectIsOpen(queryByTestId); }); - it("respects the the `escapeKeydownBehavior: 'ignore'` prop", async () => { + it("should respect the the `escapeKeydownBehavior: 'ignore'` prop", async () => { const { user, getByTestId, queryByTestId } = await open({ contentProps: { escapeKeydownBehavior: "ignore", diff --git a/packages/bits-ui/src/tests/dropdown-menu/DropdownMenu.spec.ts b/packages/bits-ui/src/tests/dropdown-menu/DropdownMenu.spec.ts index e1c47c158..c461f721d 100644 --- a/packages/bits-ui/src/tests/dropdown-menu/DropdownMenu.spec.ts +++ b/packages/bits-ui/src/tests/dropdown-menu/DropdownMenu.spec.ts @@ -67,12 +67,12 @@ async function openSubmenu(props: Awaited>) { } describe("dropdown menu", () => { - it("has no accessibility violations", async () => { + it("should have no accessibility violations", async () => { const { container } = render(DropdownMenuTest); expect(await axe(container)).toHaveNoViolations(); }); - it("has bits data attrs", async () => { + it("should have bits data attrs", async () => { const { user, trigger, getByTestId } = setup(); await user.click(trigger); @@ -100,11 +100,11 @@ describe("dropdown menu", () => { expect(subContent).toHaveAttribute(`data-menu-sub-content`); }); - it.each(OPEN_KEYS)("opens when %s is pressed & respects binding", async (key) => { + it.each(OPEN_KEYS)("should open when %s is pressed & respects binding", async (key) => { await openWithKbd({}, key); }); - it("opens when clicked & respects binding", async () => { + it("should open when clicked & respects binding", async () => { const { getByTestId, queryByTestId, user, trigger } = setup(); const binding = getByTestId("binding"); expect(binding).toHaveTextContent("false"); @@ -113,7 +113,7 @@ describe("dropdown menu", () => { expect(binding).toHaveTextContent("true"); }); - it("manages focus correctly when opened with pointer", async () => { + it("should manage focus correctly when opened with pointer", async () => { const { getByTestId, user } = await openWithPointer(); const item = getByTestId("item"); @@ -123,7 +123,7 @@ describe("dropdown menu", () => { expect(item).toHaveFocus(); }); - it("manages focus correctly when opened with keyboard", async () => { + it("should manage focus correctly when opened with keyboard", async () => { const { user, getByTestId, queryByTestId, trigger } = setup(); expect(queryByTestId("content")).toBeNull(); @@ -136,7 +136,7 @@ describe("dropdown menu", () => { await waitFor(() => expect(item).toHaveFocus()); }); - it("opens submenu with keyboard on subtrigger", async () => { + it("should open submenu with keyboard on subtrigger", async () => { const { getByTestId, queryByTestId, user } = await openWithKbd(); await user.keyboard(kbd.ARROW_DOWN); @@ -148,7 +148,7 @@ describe("dropdown menu", () => { await waitFor(() => expect(getByTestId("sub-item")).toHaveFocus()); }); - it("toggles the checkbox item when clicked & respects binding", async () => { + it("should toggle the checkbox item when clicked & respects binding", async () => { const { getByTestId, user, trigger } = await openWithPointer(); const checkedBinding = getByTestId("checked-binding"); const indicator = getByTestId("checkbox-indicator"); @@ -168,7 +168,7 @@ describe("dropdown menu", () => { expect(getByTestId("checkbox-indicator")).toHaveTextContent("true"); }); - it("toggles checkbox items within submenus when clicked & respects binding", async () => { + it("should toggle checkbox items within submenus when clicked & respects binding", async () => { const props = await openWithKbd(); const { getByTestId, user, trigger } = props; await openSubmenu(props); @@ -194,7 +194,7 @@ describe("dropdown menu", () => { expect(getByTestId("sub-checkbox-indicator")).toHaveTextContent("true"); }); - it("checks the radio item when clicked & respects binding", async () => { + it("should check the radio item when clicked & respects binding", async () => { const { getByTestId, queryByTestId, user, trigger } = await openWithPointer(); const radioBinding = getByTestId("radio-binding"); expect(radioBinding).toHaveTextContent(""); @@ -219,7 +219,7 @@ describe("dropdown menu", () => { await user.click(trigger); }); - it("skips over disabled items when navigating with the keyboard", async () => { + it("should skip over disabled items when navigating with the keyboard", async () => { const { user, getByTestId } = await openWithKbd(); await user.keyboard(kbd.ARROW_DOWN); await waitFor(() => expect(getByTestId("sub-trigger")).toHaveFocus()); @@ -229,7 +229,7 @@ describe("dropdown menu", () => { expect(getByTestId("disabled-item-2")).not.toHaveFocus(); }); - it("doesnt loop through the menu items when the `loop` prop is set to false/undefined", async () => { + it("should not loop through the menu items when the `loop` prop is set to false/undefined", async () => { const { user, getByTestId } = await openWithKbd({ contentProps: { loop: false, @@ -249,7 +249,7 @@ describe("dropdown menu", () => { await waitFor(() => expect(getByTestId("item")).not.toHaveFocus()); }); - it("loops through the menu items when the `loop` prop is set to true", async () => { + it("should loop through the menu items when the `loop` prop is set to true", async () => { const { user, getByTestId } = await openWithKbd({ contentProps: { loop: true, @@ -270,13 +270,13 @@ describe("dropdown menu", () => { await waitFor(() => expect(getByTestId("item")).toHaveFocus()); }); - it("closes the menu on escape", async () => { + it("should close the menu on escape", async () => { const { queryByTestId, user } = await openWithKbd(); await user.keyboard(kbd.ESCAPE); expect(queryByTestId("content")).toBeNull(); }); - it("respects the `escapeKeydownBehavior` prop", async () => { + it("should respect the `escapeKeydownBehavior` prop", async () => { const { queryByTestId, user } = await openWithKbd({ contentProps: { escapeKeydownBehavior: "ignore", @@ -286,7 +286,7 @@ describe("dropdown menu", () => { expect(queryByTestId("content")).not.toBeNull(); }); - it("respects the `interactOutsideBehavior` prop", async () => { + it("should respect the `interactOutsideBehavior` prop", async () => { const { queryByTestId, user, getByTestId } = await openWithPointer({ contentProps: { interactOutsideBehavior: "ignore", @@ -297,13 +297,13 @@ describe("dropdown menu", () => { expect(queryByTestId("content")).not.toBeNull(); }); - it("portals to the body if a `portal` prop is not passed", async () => { + it("should portal to the body if a `portal` prop is not passed", async () => { const { getByTestId } = await openWithPointer(); const content = getByTestId("content"); expect(content.parentElement?.parentElement).toEqual(document.body); }); - it("portals to the portal target if a valid `portal` prop is passed", async () => { + it("should portal to the portal target if a valid `portal` prop is passed", async () => { const { getByTestId } = await openWithPointer({ portalProps: { to: "#portal-target", @@ -314,7 +314,7 @@ describe("dropdown menu", () => { expect(content.parentElement?.parentElement).toEqual(portalTarget); }); - it("does not portal if `disabled` is passed to the portal", async () => { + it("should not portal if `disabled` is passed to the portal", async () => { const { getByTestId } = await openWithPointer({ portalProps: { disabled: true, @@ -327,7 +327,7 @@ describe("dropdown menu", () => { expect(contentWrapper?.parentElement).toEqual(ogContainer); }); - it("can prevent autofocusing first item with `onMountAutoFocus` prop", async () => { + it("should allow preventing autofocusing first item with `onMountAutoFocus` prop", async () => { const { getByTestId } = await openWithKbd({ contentProps: { onMountAutoFocus: (e) => { diff --git a/packages/bits-ui/src/tests/label/Label.spec.ts b/packages/bits-ui/src/tests/label/Label.spec.ts index 57ec9e6d8..cd36885fa 100644 --- a/packages/bits-ui/src/tests/label/Label.spec.ts +++ b/packages/bits-ui/src/tests/label/Label.spec.ts @@ -5,24 +5,24 @@ import { describe, it } from "vitest"; import LabelTest from "./LabelTest.svelte"; describe("label", () => { - it("has no accessibility violations", async () => { + it("should have no accessibility violations", async () => { const { container } = render(LabelTest); expect(await axe(container)).toHaveNoViolations(); }); - it("has bits data attrs", async () => { + it("should have bits data attrs", async () => { const { getByTestId } = render(LabelTest); const root = getByTestId("label"); expect(root).toHaveAttribute("data-label-root"); }); - it("renders the label text", async () => { + it("should render the label text", async () => { const { getByTestId } = render(LabelTest); const label = getByTestId("label"); expect(label).toHaveTextContent("Label"); }); - it("focuses the associated input on click", async () => { + it("should focus the associated input on click", async () => { const user = userEvent.setup(); const { getByTestId } = render(LabelTest); await user.click(getByTestId("label")); diff --git a/packages/bits-ui/src/tests/link-preview/LinkPreview.spec.ts b/packages/bits-ui/src/tests/link-preview/LinkPreview.spec.ts index 49109ea35..f4b31c560 100644 --- a/packages/bits-ui/src/tests/link-preview/LinkPreview.spec.ts +++ b/packages/bits-ui/src/tests/link-preview/LinkPreview.spec.ts @@ -23,12 +23,12 @@ async function open(props: LinkPreviewTestProps = {}) { } describe("link preview", () => { - it("has no accessibility violations", async () => { + it("should have no accessibility violations", async () => { const { container } = render(LinkPreviewTest); expect(await axe(container)).toHaveNoViolations(); }); - it("has bits data attrs", async () => { + it("should have bits data attrs", async () => { const { getByTestId } = await open(); const parts = ["trigger", "content"]; @@ -38,13 +38,13 @@ describe("link preview", () => { } }); - it("opens on hover", async () => { + it("should open on hover", async () => { const { user, content } = await open(); await user.click(content); expect(content).toBeVisible(); }); - it.skip("closes on escape keydown", async () => { + it("should close on escape keydown", async () => { const mockEsc = vi.fn(); const { user, content, queryByTestId } = await open({ contentProps: { @@ -61,15 +61,16 @@ describe("link preview", () => { const { user, getByTestId, queryByTestId } = await open(); const outside = getByTestId("outside"); await user.hover(outside); + await user.hover(outside); await waitFor(() => expect(queryByTestId("content")).toBeNull()); }); - it("portals to the body by default", async () => { + it("should portal to the body by default", async () => { const { content } = await open(); expect(content.parentElement?.parentElement).toBe(document.body); }); - it("portals to a custom element if specified", async () => { + it("should portal to a custom element if specified", async () => { const { content, getByTestId } = await open({ portalProps: { to: "#portal-target", @@ -79,13 +80,13 @@ describe("link preview", () => { expect(content.parentElement?.parentElement).toBe(portalTarget); }); - it("does not portal if `disabled` is passed as portal prop", async () => { + it("should not portal if `disabled` is passed as portal prop", async () => { const { content, getByTestId } = await open({ portalProps: { disabled: true } }); const main = getByTestId("main"); expect(content.parentElement?.parentElement).toBe(main); }); - it("respects the close on escape prop", async () => { + it("should respect the `escapeKeydownBehavior` prop", async () => { const { content, user, queryByTestId } = await open({ contentProps: { escapeKeydownBehavior: "ignore", @@ -96,7 +97,7 @@ describe("link preview", () => { expect(queryByTestId("content")).not.toBeNull(); }); - it("respects the close on outside click prop", async () => { + it("should respect the `interactOutsideBehavior` prop", async () => { const { content, user, queryByTestId, getByTestId } = await open({ contentProps: { interactOutsideBehavior: "ignore", @@ -108,7 +109,7 @@ describe("link preview", () => { expect(queryByTestId("content")).not.toBeNull(); }); - it("respects binding the open prop", async () => { + it("should respect binding the open prop", async () => { const { queryByTestId, getByTestId, user } = await open({ contentProps: { interactOutsideBehavior: "ignore", diff --git a/packages/bits-ui/src/tests/menubar/Menubar.spec.ts b/packages/bits-ui/src/tests/menubar/Menubar.spec.ts index b0240c3a9..cc02c5866 100644 --- a/packages/bits-ui/src/tests/menubar/Menubar.spec.ts +++ b/packages/bits-ui/src/tests/menubar/Menubar.spec.ts @@ -21,12 +21,12 @@ function setup(props: Menubar.RootProps = {}, menuId: string = "1") { } describe("menubar", () => { - it("has no accessibility violations", async () => { + it("should have no accessibility violations", async () => { const { container } = render(MenubarTest); expect(await axe(container)).toHaveNoViolations(); }); - it.skip("has bits data attrs", async () => { + it.skip("should have bits data attrs", async () => { const menuId = "1"; const { user, trigger, getByTestId, queryByTestId } = setup({}, menuId); await user.click(trigger); @@ -64,7 +64,7 @@ describe("menubar", () => { expect(subContent).toHaveAttribute(`data-menu-sub-content`); }); - it("navigates triggers within the menubar using arrow keys", async () => { + it("should navigate triggers within the menubar using arrow keys", async () => { const { user, trigger, getByTestId } = setup({}, "1"); trigger.focus(); await user.keyboard(kbd.ARROW_RIGHT); @@ -77,7 +77,7 @@ describe("menubar", () => { expect(getByTestId("1-trigger")).toHaveFocus(); }); - it("respects the loop prop", async () => { + it("should respect the loop prop", async () => { const { user, trigger, getByTestId } = setup({ loop: false }, "1"); trigger.focus(); await user.keyboard(kbd.ARROW_RIGHT); diff --git a/packages/bits-ui/src/tests/pagination/Pagination.spec.ts b/packages/bits-ui/src/tests/pagination/Pagination.spec.ts index b1242dbe1..500a74d7c 100644 --- a/packages/bits-ui/src/tests/pagination/Pagination.spec.ts +++ b/packages/bits-ui/src/tests/pagination/Pagination.spec.ts @@ -36,12 +36,12 @@ function getValue(el: HTMLElement) { } describe("pagination", () => { - it("no accessibility violations", async () => { + it("should have no accessibility violations", async () => { const { container } = render(PaginationTest); expect(await axe(container)).toHaveNoViolations(); }); - it("previous and Next button should work accordingly", async () => { + it("should navigate previous and Next button accordingly", async () => { const { root, prev, next, user } = setup(); expect(getValue(root)).toBe("1"); diff --git a/packages/bits-ui/src/tests/pin-input/PinInput.spec.ts b/packages/bits-ui/src/tests/pin-input/PinInput.spec.ts index e7bb0087c..78f9bd10c 100644 --- a/packages/bits-ui/src/tests/pin-input/PinInput.spec.ts +++ b/packages/bits-ui/src/tests/pin-input/PinInput.spec.ts @@ -29,28 +29,28 @@ function setup(props: Partial = {}) { } describe("Pin Input", () => { - it("has no accessibility violations", async () => { + it("should have no accessibility violations", async () => { const { container } = render(PinInputTest); expect(await axe(container)).toHaveNoViolations(); }); - it("syncs the `name` prop to the hidden input", async () => { + it("should sync the `name` prop to the hidden input", async () => { const { hiddenInput } = setup({ name: "test" }); expect(hiddenInput).toHaveAttribute("name", "test"); }); - it("syncs the `value` prop to the hidden input", async () => { + it("should sync the `value` prop to the hidden input", async () => { const value = "123456"; const { hiddenInput } = setup({ value }); expect(hiddenInput).toHaveValue(value); }); - it("syncs the `disabled` prop to the hidden input", async () => { + it("should sync the `disabled` prop to the hidden input", async () => { const { hiddenInput } = setup({ disabled: true }); await waitFor(() => expect(hiddenInput).toHaveAttribute("disabled", "")); }); - it("respects binding to the `value` prop", async () => { + it("should respect binding to the `value` prop", async () => { let initialValue = "123456"; const { hiddenInput, binding, user } = setup({ value: initialValue, @@ -62,7 +62,7 @@ describe("Pin Input", () => { expect(binding).toHaveTextContent("999999"); }); - it("sets the appropriate `isActive` prop on each cell", async () => { + it("should set the appropriate `isActive` prop on each cell", async () => { const { user, hiddenInput, cells } = setup(); await user.click(hiddenInput); @@ -87,7 +87,7 @@ describe("Pin Input", () => { expect(cells[5]).toHaveTextContent("6"); }); - it("handles backspace appropriately", async () => { + it("should handle backspace appropriately", async () => { const { user, hiddenInput, cells } = setup(); await user.click(hiddenInput); @@ -103,7 +103,7 @@ describe("Pin Input", () => { expect(cells[2]).not.toHaveAttribute("data-active"); }); - it("fires the `onComplete` callback when the input is complete", async () => { + it("should fire the `onComplete` callback when the input is complete", async () => { const mockComplete = vi.fn(); const { user, hiddenInput } = setup({ onComplete: mockComplete, diff --git a/packages/bits-ui/src/tests/popover/Popover.spec.ts b/packages/bits-ui/src/tests/popover/Popover.spec.ts index b96949db3..92ae955b3 100644 --- a/packages/bits-ui/src/tests/popover/Popover.spec.ts +++ b/packages/bits-ui/src/tests/popover/Popover.spec.ts @@ -1,42 +1,43 @@ import { render, waitFor } from "@testing-library/svelte/svelte5"; -import { userEvent } from "@testing-library/user-event"; import { axe } from "jest-axe"; import { describe, it } from "vitest"; import { getTestKbd, setupUserEvents } from "../utils.js"; import PopoverTest, { type PopoverTestProps } from "./PopoverTest.svelte"; -import { sleep } from "$lib/internal/sleep.js"; const kbd = getTestKbd(); function setup(props: PopoverTestProps = {}) { const user = setupUserEvents(); const returned = render(PopoverTest, { ...props }); - const { getByTestId } = returned; + const { getByTestId, queryByTestId } = returned; const trigger = getByTestId("trigger"); - return { trigger, user, ...returned }; + function getContent() { + return queryByTestId("content"); + } + return { trigger, user, getContent, ...returned }; } async function open(props: PopoverTestProps = {}, openWith: "click" | (string & {}) = "click") { - const { trigger, getByTestId, queryByTestId, user } = setup(props); - expect(queryByTestId("content")).toBeNull(); + const { trigger, getByTestId, queryByTestId, user, getContent, ...returned } = setup(props); + expect(getContent()).toBeNull(); if (openWith === "click") { await user.click(trigger); } else { trigger.focus(); await user.keyboard(openWith); } - await waitFor(() => expect(queryByTestId("content")).not.toBeNull()); + await waitFor(() => expect(getContent()).not.toBeNull()); const content = getByTestId("content"); - return { trigger, getByTestId, queryByTestId, user, content }; + return { trigger, getByTestId, queryByTestId, user, content, getContent, ...returned }; } describe("popover", () => { - it("has no accessibility violations", async () => { + it("should have no accessibility violations", async () => { const { container } = render(PopoverTest); expect(await axe(container)).toHaveNoViolations(); }); - it("has bits data attrs", async () => { + it("should have bits data attrs", async () => { const { getByTestId } = await open(); const parts = ["trigger", "content", "close", "arrow"]; @@ -46,53 +47,53 @@ describe("popover", () => { } }); - it("opens on click", async () => { + it("should open on click", async () => { await open(); }); - it("opens on enter", async () => { + it("should open on enter", async () => { await open({}, kbd.ENTER); }); - it("opens on space", async () => { + it("should open on space", async () => { await open({}, kbd.SPACE); }); - it("closes on escape keydown by default", async () => { - const { user, queryByTestId } = await open(); + it("should close on escape keydown by default", async () => { + const { user, getContent } = await open(); await user.keyboard(kbd.ESCAPE); - expect(queryByTestId("content")).toBeNull(); + expect(getContent()).toBeNull(); }); - it("closes on outside click by default", async () => { - const { user, queryByTestId, getByTestId } = await open(); + it("should close on outside click by default", async () => { + const { user, getContent, getByTestId } = await open(); const outside = getByTestId("outside"); await user.click(outside); - expect(queryByTestId("content")).toBeNull(); + expect(getContent()).toBeNull(); }); - it("closes when the close button is clicked", async () => { - const { user, queryByTestId, getByTestId } = await open(); + it("should close when the close button is clicked", async () => { + const { user, getContent, getByTestId } = await open(); const close = getByTestId("close"); await user.click(close); - expect(queryByTestId("content")).toBeNull(); + expect(getContent()).toBeNull(); }); - it("portals to the body by default", async () => { + it("should portal to the body by default", async () => { const { content } = await open(); const contentWrapper = content.parentElement; expect(contentWrapper?.parentElement).toBe(document.body); }); - it("portals to a custom element if specified", async () => { + it("should portal to a custom element if specified", async () => { const { content, getByTestId } = await open({ portalProps: { to: "#portal-target" } }); const portalTarget = getByTestId("portal-target"); const contentWrapper = content.parentElement; expect(contentWrapper?.parentElement).toBe(portalTarget); }); - it("does not portal if `disabled` is passed to the portal ", async () => { + it("should not portal if `disabled` is passed to the portal ", async () => { const { content, getByTestId } = await open({ portalProps: { disabled: true, @@ -103,29 +104,47 @@ describe("popover", () => { expect(contentWrapper?.parentElement).toBe(main); }); - it("allows ignoring the escapeKeydownBehavior ", async () => { - const { user, queryByTestId } = await open({ + it("should allow ignoring the escapeKeydownBehavior ", async () => { + const { user, getContent } = await open({ contentProps: { escapeKeydownBehavior: "ignore", }, }); await user.keyboard(kbd.ESCAPE); - expect(queryByTestId("content")).not.toBeNull(); + expect(getContent()).not.toBeNull(); + }); + + it("should allow cancelling the `onEscapeKeydown` event", async () => { + let preventedCount = 0; + const { user, getContent } = await open({ + contentProps: { + escapeKeydownBehavior: "close", + onEscapeKeydown: (e) => { + if (preventedCount > 0) return; + e.preventDefault(); + preventedCount++; + }, + }, + }); + await user.keyboard(kbd.ESCAPE); + expect(getContent()).not.toBeNull(); + await user.keyboard(kbd.ESCAPE); + expect(getContent()).toBeNull(); }); - it("allows ignoring the interactOutsideBehavior", async () => { - const { user, queryByTestId, getByTestId } = await open({ + it("should allow ignoring the interactOutsideBehavior", async () => { + const { user, getContent, getByTestId } = await open({ contentProps: { interactOutsideBehavior: "ignore", }, }); const outside = getByTestId("outside"); await user.click(outside); - expect(queryByTestId("content")).not.toBeNull(); + expect(getContent()).not.toBeNull(); }); - it("respects binding the `open` prop", async () => { - const { queryByTestId, getByTestId, user } = await open({ + it("should allow binding the `open` prop", async () => { + const { getContent, getByTestId, user } = await open({ contentProps: { interactOutsideBehavior: "ignore", }, @@ -134,9 +153,9 @@ describe("popover", () => { expect(binding).toHaveTextContent("true"); await user.click(binding); expect(binding).toHaveTextContent("false"); - expect(queryByTestId("content")).toBeNull(); + expect(getContent()).toBeNull(); await user.click(binding); expect(binding).toHaveTextContent("true"); - expect(queryByTestId("content")).not.toBeNull(); + expect(getContent()).not.toBeNull(); }); }); diff --git a/packages/bits-ui/src/tests/progress/Progress.spec.ts b/packages/bits-ui/src/tests/progress/Progress.spec.ts index 9447a5d51..504f88794 100644 --- a/packages/bits-ui/src/tests/progress/Progress.spec.ts +++ b/packages/bits-ui/src/tests/progress/Progress.spec.ts @@ -14,27 +14,27 @@ function setup(props: Progress.RootProps = {}) { } describe("progress", () => { - it("has no accessibility violations", async () => { + it("should have no accessibility violations", async () => { const { container } = render(ProgressTest); expect(await axe(container)).toHaveNoViolations(); }); - it("has bits data attrs", async () => { + it("should have bits data attrs", async () => { const { root } = setup(); expect(root).toHaveAttribute("data-progress-root"); }); - it("respects the value prop", async () => { + it("should respect the value prop", async () => { const { root } = setup({ value: 50 }); expect(root).toHaveAttribute("aria-valuenow", "50"); }); - it("respects the max prop", async () => { + it("should respect the max prop", async () => { const { root } = setup({ max: 20 }); expect(root).toHaveAttribute("aria-valuemax", "20"); }); - it("reacts to updates to the value prop", async () => { + it("should react to updates to the value prop", async () => { const user = userEvent.setup(); const { getByTestId } = render(ProgressTest); const root = getByTestId("root"); diff --git a/packages/bits-ui/src/tests/radio-group/RadioGroup.spec.ts b/packages/bits-ui/src/tests/radio-group/RadioGroup.spec.ts index 79bab1a25..57400e74b 100644 --- a/packages/bits-ui/src/tests/radio-group/RadioGroup.spec.ts +++ b/packages/bits-ui/src/tests/radio-group/RadioGroup.spec.ts @@ -47,12 +47,12 @@ function randItem() { } describe("radio group", () => { - it("has no accessibility violations", async () => { + it("should have no accessibility violations", async () => { const { container } = render(RadioGroupTest); expect(await axe(container)).toHaveNoViolations(); }); - it("has bits data attrs", async () => { + it("should have bits data attrs", async () => { const { getByTestId } = render(RadioGroupTest, { items: [testItems[0] as Item], value: testItems[0]?.value, @@ -64,7 +64,7 @@ describe("radio group", () => { expect(item).toHaveAttribute("data-radio-group-item"); }); - it("changes the value when an item is clicked", async () => { + it("should change the value when an item is clicked", async () => { const { getByTestId, user } = setup(); for (const indicator of indicatorIds) { @@ -76,7 +76,7 @@ describe("radio group", () => { expect(getByTestId(indicatorIds[itemIdx] as string)).toHaveTextContent("true"); }); - it("doesnt change the value when a disabled item is clicked", async () => { + it("should not change the value when a disabled item is clicked", async () => { const { getByTestId, user } = setup({}, [...testItems, { value: "e", disabled: true }]); const item = getByTestId("e-item"); @@ -84,7 +84,7 @@ describe("radio group", () => { expect(getByTestId("e-indicator")).toHaveTextContent("false"); }); - it("navigates through the items using the keyboard", async () => { + it("should navigate through the items using the keyboard", async () => { const { getByTestId, user } = setup(); const item0 = getByTestId(itemIds[0] as string); @@ -107,7 +107,7 @@ describe("radio group", () => { await waitFor(() => expect(item0).toHaveFocus()); }); - it("respects the loop prop", async () => { + it("should respect the loop prop", async () => { const { getByTestId, user } = setup({ loop: false, }); @@ -125,7 +125,7 @@ describe("radio group", () => { await waitFor(() => expect(item3).toHaveFocus()); }); - it("respects the value prop & binding", async () => { + it("should respect the value prop & binding", async () => { const { getByTestId, user, queryByTestId } = setup({ value: "b", }); @@ -140,7 +140,7 @@ describe("radio group", () => { expect(bindingIndic2).toHaveTextContent("true"); }); - it("modifies keyboard navigation when the orientation is horizontal", async () => { + it("should modify keyboard navigation when the orientation is horizontal", async () => { const { getByTestId, user } = setup({ orientation: "horizontal", }); @@ -167,7 +167,7 @@ describe("radio group", () => { await waitFor(() => expect(item3).toHaveFocus()); }); - it("respects the loop prop when orientation is horizontal", async () => { + it("should respect the loop prop when orientation is horizontal", async () => { const { getByTestId, user } = setup({ loop: false, orientation: "horizontal", @@ -186,13 +186,13 @@ describe("radio group", () => { await waitFor(() => expect(item3).toHaveFocus()); }); - it("doesn't render an input if the `name` prop isn't passed", async () => { + it("should not render an input if the `name` prop isn't passed", async () => { const { input } = setup(); expect(input).not.toBeInTheDocument(); }); - it("renders an input if the `name` prop is passed", async () => { + it("should render an input if the `name` prop is passed", async () => { const { input } = setup({ name: "radio-group", }); @@ -200,7 +200,7 @@ describe("radio group", () => { expect(input).toBeInTheDocument(); }); - it("syncs the inputs value with the radio group value", async () => { + it("should syncs the inputs value with the radio group value", async () => { const { getByTestId, user, input } = setup({ name: "radio-group" }); await user.click(getByTestId("a-item")); @@ -209,7 +209,7 @@ describe("radio group", () => { expect(input).toHaveValue("b"); }); - it("makes the input required if the radio group is required", async () => { + it("should make the input required if the radio group is required", async () => { const { input } = setup({ required: true, name: "radio-group", @@ -218,7 +218,7 @@ describe("radio group", () => { expect(input).toHaveAttribute("required"); }); - it("disables the input if the radio group is disabled", async () => { + it("should make the input disabled if the radio group is disabled", async () => { const { input } = setup({ disabled: true, name: "radio-group", diff --git a/packages/bits-ui/src/tests/range-calendar/RangeCalendar.spec.ts b/packages/bits-ui/src/tests/range-calendar/RangeCalendar.spec.ts index f66233e2f..1c999e408 100644 --- a/packages/bits-ui/src/tests/range-calendar/RangeCalendar.spec.ts +++ b/packages/bits-ui/src/tests/range-calendar/RangeCalendar.spec.ts @@ -43,12 +43,12 @@ const SELECTED_DAY_SELECTOR = "[data-bits-day][data-selected]"; const SELECTED_ATTR = "data-selected"; describe("calendar", () => { - it("has no accessibility violations", async () => { + it("should have no accessibility violations", async () => { const { container } = render(RangeCalendarTest); expect(await axe(container)).toHaveNoViolations(); }); - it("respects a default value if provided - `CalendarDate`", async () => { + it("should respect a default value if provided - `CalendarDate`", async () => { const { calendar, getByTestId } = setup({ value: calendarDateRange }); const selectedDays = calendar.querySelectorAll(SELECTED_DAY_SELECTOR); @@ -58,7 +58,7 @@ describe("calendar", () => { expect(heading).toHaveTextContent("January 1980"); }); - it("respects a default value if provided - `CalendarDateTime`", async () => { + it("should respect a default value if provided - `CalendarDateTime`", async () => { const { calendar, getByTestId } = setup({ value: calendarDateTimeRange }); const selectedDays = calendar.querySelectorAll(SELECTED_DAY_SELECTOR); @@ -68,7 +68,7 @@ describe("calendar", () => { expect(heading).toHaveTextContent("January 1980"); }); - it("respects a default value if provided - `ZonedDateTime`", async () => { + it("should respect a default value if provided - `ZonedDateTime`", async () => { const { calendar, getByTestId } = setup({ value: zonedDateTimeRange }); const selectedDays = calendar.querySelectorAll(SELECTED_DAY_SELECTOR); @@ -78,7 +78,7 @@ describe("calendar", () => { expect(heading).toHaveTextContent("January 1980"); }); - it("resets range on select when a range is already selected", async () => { + it("should reset range on select when a range is already selected", async () => { const { getByTestId, calendar, user } = setup({ value: calendarDateRange, }); @@ -103,7 +103,7 @@ describe("calendar", () => { expect(getSelectedDays(calendar)).toHaveLength(3); }); - it("navigates the months forward using the next button", async () => { + it("should navigate the months forward using the next button", async () => { const { getByTestId, user } = setup({ value: calendarDateTimeRange }); const heading = getByTestId("heading"); @@ -116,7 +116,7 @@ describe("calendar", () => { expect(heading).toHaveTextContent("January 1981"); }); - it("navigates the months backwards using the prev button", async () => { + it("should navigate the months backwards using the prev button", async () => { const { getByTestId, user } = setup({ value: calendarDateTimeRange }); const heading = getByTestId("heading"); @@ -134,7 +134,7 @@ describe("calendar", () => { expect(heading).toHaveTextContent("January 1979"); }); - it("always renders six weeks when `fixedWeeks` is `true`", async () => { + it("should renders six weeks when `fixedWeeks` is `true`", async () => { const { getByTestId, calendar, user } = setup({ value: calendarDateTimeRange, fixedWeeks: true, @@ -201,7 +201,7 @@ describe("calendar", () => { expect(heading).toHaveTextContent("March 1980"); }); - it("does not navigate after `maxValue` (with keyboard)", async () => { + it("should not navigate after `maxValue` (with keyboard)", async () => { const { getByTestId, user } = setup({ value: calendarDateRange, maxValue: new CalendarDate(1980, 3, 31), @@ -250,7 +250,7 @@ describe("calendar", () => { expect(heading).toHaveTextContent("March 1980"); }); - it("does not navigate before `minValue` (with keyboard)", async () => { + it("should not navigate before `minValue` (with keyboard)", async () => { const { getByTestId, user } = setup({ value: calendarDateRange, minValue: new CalendarDate(1979, 12, 1), @@ -280,7 +280,7 @@ describe("calendar", () => { expect(heading).toHaveTextContent("December 1979"); }); - it("handles unavailable dates appropriately", async () => { + it("should handle unavailable dates appropriately", async () => { const { getByTestId, user } = setup({ placeholder: calendarDateRange.start, isDateUnavailable: (date) => { @@ -296,7 +296,7 @@ describe("calendar", () => { expect(thirdDayInMonth).not.toHaveAttribute(SELECTED_ATTR); }); - it("formats the weekday labels correctly - `'narrow'`", async () => { + it("should format the weekday labels correctly - `'narrow'`", async () => { const { getByTestId } = setup({ placeholder: calendarDateRange.start, weekdayFormat: "narrow", @@ -307,7 +307,7 @@ describe("calendar", () => { } }); - it("formats the weekday labels correctly - `'short'`", async () => { + it("should format the weekday labels correctly - `'short'`", async () => { const { getByTestId } = setup({ placeholder: calendarDateRange.start, weekdayFormat: "short", @@ -318,7 +318,7 @@ describe("calendar", () => { } }); - it("formats the weekday labels correctly - `'long'`", async () => { + it("should format the weekday labels correctly - `'long'`", async () => { const { getByTestId } = setup({ placeholder: calendarDateRange.start, weekdayFormat: "long", diff --git a/packages/bits-ui/src/tests/select/Select.spec.ts b/packages/bits-ui/src/tests/select/Select.spec.ts index 0cdf31baf..8d6686e98 100644 --- a/packages/bits-ui/src/tests/select/Select.spec.ts +++ b/packages/bits-ui/src/tests/select/Select.spec.ts @@ -64,12 +64,12 @@ async function open( const OPEN_KEYS = [kbd.ENTER, kbd.SPACE, kbd.ARROW_DOWN, kbd.ARROW_UP]; describe("select", () => { - it("has no accessibility violations", async () => { + it("should have no accessibility violations", async () => { const { container } = render(SelectTest); expect(await axe(container)).toHaveNoViolations(); }); - it("has bits data attrs", async () => { + it("should have bits data attrs", async () => { const { getByTestId } = await open(); const parts = ["content", "trigger", "value", "group-label", "group", "viewport"]; @@ -85,11 +85,11 @@ describe("select", () => { expect(itemText).toHaveAttribute("data-select-item-text"); }); - it("opens on click", async () => { + it("should open on click", async () => { await open(); }); - it.each(OPEN_KEYS)("opens on %s keydown", async (key) => { + it.each(OPEN_KEYS)("should open on %s keydown", async (key) => { await open({}, key); }); @@ -101,19 +101,19 @@ describe("select", () => { expect(getByTestId("value")).toHaveTextContent("B"); }); - it("renders a `select` element when used within a form", async () => {}); + it("should render a `select` element when used within a form", async () => {}); - it("syncs the name with the hidden select", async () => { + it("should sync the name with the hidden select", async () => { const { select } = setup({ name: "test" }); expect(select).toBeInTheDocument(); }); - it("syncs the name prop to the hidden select", async () => { + it("should sync the name prop to the hidden select", async () => { const { select } = setup({ name: "test" }); expect(select).toHaveAttribute("name", "test"); }); - it("syncs the value prop to the hidden select", async () => { + it("should sync the value prop to the hidden select", async () => { const { getByTestId, queryByTestId, select, trigger, user, container } = setup({ value: "2", }); @@ -131,7 +131,7 @@ describe("select", () => { await waitFor(() => expect(queryByTestId("content")).toBeNull()); }); - it("submits the select value with the form", async () => { + it("should submit the select value with the form", async () => { const onSubmit = vi.fn(); const { getByTestId, user, trigger } = setup({ name: "test", onSubmit }); @@ -155,23 +155,23 @@ describe("select", () => { expect(onSubmit).toHaveBeenCalledWith("2"); }); - it("syncs the required prop to the hidden select", async () => { + it("should sync the required prop to the hidden select", async () => { const { select } = setup({ required: true }); expect(select).toHaveAttribute("required"); }); - it("syncs the disabled prop to the hidden select", async () => { + it("should sync the disabled prop to the hidden select", async () => { const { select } = setup({ disabled: true }); expect(select).toHaveAttribute("disabled"); }); - it("closes on escape keydown", async () => { + it("should close on escape keydown", async () => { const { user, queryByTestId } = await open(); await user.keyboard(kbd.ESCAPE); expect(queryByTestId("content")).toBeNull(); }); - it("closes on outside click", async () => { + it("should close on outside click", async () => { const onInteractOutsideStart = vi.fn(); const { getByTestId } = await open({ contentProps: { @@ -183,13 +183,13 @@ describe("select", () => { await waitFor(() => expect(onInteractOutsideStart).toHaveBeenCalled()); }); - it("portals to the body by default", async () => { + it("should portal to the body by default", async () => { const { content } = await open(); const contentWrapper = content?.parentElement; expect(contentWrapper?.parentElement).toBe(document.body); }); - it("portals to a custom element if specified", async () => { + it("should portal to a custom element if specified", async () => { const { content, getByTestId } = await open({ portalProps: { to: "#portal-target", @@ -200,14 +200,14 @@ describe("select", () => { expect(contentWrapper?.parentElement).toBe(portalTarget); }); - it("does not portal if `disabled` is passed to the portal", async () => { + it("should not portal if `disabled` is passed to the portal", async () => { const { content, getByTestId } = await open({ portalProps: { disabled: true } }); const form = getByTestId("form"); const contentWrapper = content?.parentElement; expect(contentWrapper?.parentElement).toBe(form); }); - it("respects the `escapeKeydownBehavior` prop", async () => { + it("should respect the `escapeKeydownBehavior` prop", async () => { const { user, queryByTestId } = await open({ contentProps: { escapeKeydownBehavior: "ignore", @@ -217,7 +217,7 @@ describe("select", () => { await waitFor(() => expect(queryByTestId("content")).not.toBeNull()); }); - it("respects the `interactOutsideBehavior` prop", async () => { + it("should respect the `interactOutsideBehavior` prop", async () => { const { user, queryByTestId, getByTestId } = await open({ contentProps: { interactOutsideBehavior: "ignore", @@ -229,7 +229,7 @@ describe("select", () => { await waitFor(() => expect(queryByTestId("content")).not.toBeNull()); }); - it("respects binding the `open` prop", async () => { + it("should respect binding the `open` prop", async () => { const { queryByTestId, getByTestId, user } = await open({ contentProps: { interactOutsideBehavior: "ignore", @@ -245,7 +245,7 @@ describe("select", () => { await waitFor(() => expect(queryByTestId("content")).not.toBeNull()); }); - it("respects binding the `value` prop", async () => { + it("should respect binding the `value` prop", async () => { const { getByTestId, user } = await open({ value: "1" }); const binding = getByTestId("value-binding"); expect(binding).toHaveTextContent("1"); @@ -253,7 +253,7 @@ describe("select", () => { await waitFor(() => expect(binding).toHaveTextContent("")); }); - it("selects items when clicked", async () => { + it("should select items when clicked", async () => { const { user, queryByTestId, trigger, container } = await open(); const item = queryByTestId("1") as HTMLElement; await waitFor(() => expect(queryByTestId("1-indicator")).toBeNull()); @@ -271,7 +271,7 @@ describe("select", () => { await waitFor(() => expect(queryByTestId("1-indicator")).not.toBeNull()); }); - it("navigates through the items using the keyboard", async () => { + it("should navigate through the items using the keyboard", async () => { const { user, queryByTestId } = await open({}, kbd.ENTER); await waitFor(() => expect(queryByTestId("1")).toHaveAttribute("data-highlighted")); @@ -289,7 +289,7 @@ describe("select", () => { await waitFor(() => expect(queryByTestId("1")).toHaveAttribute("data-highlighted")); }); - it("allows items to be selected using the keyboard", async () => { + it("should allow items to be selected using the keyboard", async () => { const { getByTestId, user, queryByTestId, trigger } = await open({}, kbd.ENTER); await user.keyboard(kbd.ARROW_DOWN); @@ -307,7 +307,7 @@ describe("select", () => { expect(queryByTestId("4")).toHaveAttribute("data-selected"); }); - it("applies the `data-highlighted` attribute on mouseover", async () => { + it("should apply the `data-highlighted` attribute on mouseover", async () => { const { getByTestId, user } = await open({}, kbd.ENTER); const item1 = getByTestId("1"); const item2 = getByTestId("2"); @@ -318,7 +318,7 @@ describe("select", () => { await waitFor(() => expect(item1).not.toHaveAttribute("data-highlighted")); }); - it("selects a default item when provided", async () => { + it("should select a default item when provided", async () => { const { getByTestId, queryByTestId, container } = await open({ value: "2", }); diff --git a/packages/bits-ui/src/tests/separator/Separator.spec.ts b/packages/bits-ui/src/tests/separator/Separator.spec.ts index ab5fb7d90..2e07c8159 100644 --- a/packages/bits-ui/src/tests/separator/Separator.spec.ts +++ b/packages/bits-ui/src/tests/separator/Separator.spec.ts @@ -14,12 +14,12 @@ function setup(props: Separator.RootProps = {}) { } describe("separator", () => { - it("has no accessibility violations", async () => { + it("should have no accessibility violations", async () => { const { container } = render(SeparatorTest); expect(await axe(container)).toHaveNoViolations(); }); - it("has bits data attrs", async () => { + it("should have bits data attrs", async () => { const { root } = setup(); expect(root).toHaveAttribute("data-separator-root"); }); diff --git a/packages/bits-ui/src/tests/slider/Slider.spec.ts b/packages/bits-ui/src/tests/slider/Slider.spec.ts index 14ed054d9..2192f98b8 100644 --- a/packages/bits-ui/src/tests/slider/Slider.spec.ts +++ b/packages/bits-ui/src/tests/slider/Slider.spec.ts @@ -30,13 +30,13 @@ function setup(props: SliderTestProps = {}, kind: "default" | "range" = "default } describe("slider (default)", () => { - it("no accessibility violations", async () => { + it("should haveno accessibility violations", async () => { const { container } = render(SliderTest); expect(await axe(container)).toHaveNoViolations(); }); - it("has a thumb positioned at 30% of the container", async () => { + it("should have a thumb positioned at 30% of the container", async () => { const { getByTestId } = setup(); const thumb = getByTestId("thumb"); @@ -44,7 +44,7 @@ describe("slider (default)", () => { expect(isCloseEnough(30, thumb.style.left)).toBeTruthy(); }); - it("has a range that covers from 0 to 30%", async () => { + it("should have a range that covers from 0 to 30%", async () => { const { getByTestId } = setup(); const range = getByTestId("range"); @@ -54,31 +54,37 @@ describe("slider (default)", () => { expect(isCloseEnough(70, range.style.right)).toBeTruthy(); }); - it.each([kbd.ARROW_RIGHT, kbd.ARROW_UP])("change by 1% when pressing %s", async (key) => { - const { getByTestId, user } = setup(); + it.each([kbd.ARROW_RIGHT, kbd.ARROW_UP])( + "should change by 1% when pressing %s", + async (key) => { + const { getByTestId, user } = setup(); - const thumb = getByTestId("thumb"); - const range = getByTestId("range"); + const thumb = getByTestId("thumb"); + const range = getByTestId("range"); - thumb.focus(); - await user.keyboard(key); + thumb.focus(); + await user.keyboard(key); - expectPercentage({ percentage: 31, thumb, range }); - }); + expectPercentage({ percentage: 31, thumb, range }); + } + ); - it.each([kbd.ARROW_LEFT, kbd.ARROW_DOWN])("change by 1% when pressing %s", async (key) => { - const { getByTestId, user } = setup(); + it.each([kbd.ARROW_LEFT, kbd.ARROW_DOWN])( + "should change by 1% when pressing %s", + async (key) => { + const { getByTestId, user } = setup(); - const thumb = getByTestId("thumb"); - const range = getByTestId("range"); - thumb.focus(); + const thumb = getByTestId("thumb"); + const range = getByTestId("range"); + thumb.focus(); - await user.keyboard(key); + await user.keyboard(key); - expectPercentage({ percentage: 29, thumb, range }); - }); + expectPercentage({ percentage: 29, thumb, range }); + } + ); - it("goes to minimum when pressing Home", async () => { + it("should go to minimum when pressing Home", async () => { const { getByTestId, user } = setup(); const thumb = getByTestId("thumb"); @@ -90,7 +96,7 @@ describe("slider (default)", () => { expectPercentage({ percentage: 0, thumb, range }); }); - it("goes to maximum when pressing End", async () => { + it("should go to maximum when pressing End", async () => { const { getByTestId, user } = setup(); const thumb = getByTestId("thumb"); const range = getByTestId("range"); @@ -103,13 +109,13 @@ describe("slider (default)", () => { }); describe("slider (range)", () => { - it("no accessibility violations", async () => { + it("should have no accessibility violations", async () => { const { container } = setup({}, "range"); expect(await axe(container)).toHaveNoViolations(); }); - it("has a thumb positioned at 20% of the container and one at 80%", async () => { + it("should have a thumb positioned at 20% of the container and one at 80%", async () => { const { getByTestId } = setup({}, "range"); const thumb0 = getByTestId("thumb-0"); @@ -120,7 +126,7 @@ describe("slider (range)", () => { expect(isCloseEnough(20, thumb0.style.left)).toBeTruthy(); expect(isCloseEnough(80, thumb1.style.left)).toBeTruthy(); }); - it("has a range that covers from 20% to 80%", async () => { + it("should have a range that covers from 20% to 80%", async () => { const { getByTestId } = setup({}, "range"); const range = getByTestId("range"); @@ -131,7 +137,7 @@ describe("slider (range)", () => { }); it.each([kbd.ARROW_RIGHT, kbd.ARROW_UP])( - "change by 1% when pressing %s (pressing on the first thumb)", + "should change by 1% when pressing %s (pressing on the first thumb)", async (key) => { const { getByTestId, user } = setup({}, "range"); @@ -147,7 +153,7 @@ describe("slider (range)", () => { ); it.each([kbd.ARROW_RIGHT, kbd.ARROW_UP])( - "change by 1% when pressing %s (pressing on the last thumb)", + "should change by 1% when pressing %s (pressing on the last thumb)", async (key) => { const { getByTestId, user } = setup({}, "range"); @@ -163,7 +169,7 @@ describe("slider (range)", () => { ); it.each([kbd.ARROW_LEFT, kbd.ARROW_DOWN])( - "change by 1% when pressing %s (pressing on the first thumb)", + "should change by 1% when pressing %s (pressing on the first thumb)", async (key) => { const { getByTestId, user } = setup({}, "range"); @@ -179,7 +185,7 @@ describe("slider (range)", () => { ); it.each([kbd.ARROW_LEFT, kbd.ARROW_DOWN])( - "change by 1% when pressing %s (pressing on the last thumb)", + "should change by 1% when pressing %s (pressing on the last thumb)", async (key) => { const { getByTestId, user } = setup({}, "range"); @@ -195,7 +201,7 @@ describe("slider (range)", () => { ); it.each([kbd.ARROW_RIGHT, kbd.ARROW_UP])( - "the handlers swap places when they overlap pressing %s (going up)", + "should swap handler places when they overlap pressing %s (going up)", async (key) => { const { getByTestId, user } = setup( { @@ -219,7 +225,7 @@ describe("slider (range)", () => { ); it.each([kbd.ARROW_LEFT, kbd.ARROW_DOWN])( - "the handlers swap places when they overlap pressing %s (going down)", + "should swap handler places when they overlap pressing %s (going down)", async (key) => { const { getByTestId, user } = setup( { @@ -242,7 +248,7 @@ describe("slider (range)", () => { } ); - it("thumb 0 goes to minimum when pressing Home", async () => { + it("should bring thumb to 0 to minimum when pressing Home", async () => { const { getByTestId, user } = setup({}, "range"); const thumb0 = getByTestId("thumb-0"); @@ -255,7 +261,7 @@ describe("slider (range)", () => { expectPercentages({ percentages: [0, 80], thumbs: [thumb0, thumb1], range }); }); - it("thumb 1 goes to maximum when pressing End", async () => { + it("should bring thumb 1 to maximum when pressing End", async () => { const { getByTestId, user } = setup({}, "range"); const thumb0 = getByTestId("thumb-0"); @@ -268,7 +274,7 @@ describe("slider (range)", () => { expectPercentages({ percentages: [20, 100], thumbs: [thumb0, thumb1], range }); }); - it("thumb 1 goes to minimum when pressing Home (thumbs swap places)", async () => { + it("should bring thumb 1 to minimum when pressing Home (thumbs swap places)", async () => { const { getByTestId, user } = setup({}, "range"); const thumb0 = getByTestId("thumb-0"); @@ -282,7 +288,7 @@ describe("slider (range)", () => { expect(thumb0).toHaveFocus(); }); - it("thumb 0 goes to maximum when pressing End (thumbs swap places)", async () => { + it("should bring thumb 0 to maximum when pressing End (thumbs swap places)", async () => { const { getByTestId, user } = setup({}, "range"); const thumb0 = getByTestId("thumb-0"); @@ -298,7 +304,7 @@ describe("slider (range)", () => { }); describe("slider (small min, max, step)", () => { - it("has a thumb positioned at 50% of the container", async () => { + it("should have a thumb positioned at 50% of the container", async () => { const { getByTestId } = setup({ value: [0.5], min: 0, @@ -312,43 +318,49 @@ describe("slider (small min, max, step)", () => { expect(isCloseEnough(50, thumb.style.left)).toBeTruthy(); }); - it.each([kbd.ARROW_RIGHT, kbd.ARROW_UP])("change by 1% when pressing %s", async (key) => { - const { getByTestId, user } = setup({ - value: [0.5], - min: 0, - max: 1, - step: 0.01, - }); - - const thumb = getByTestId("thumb"); - const range = getByTestId("range"); - - thumb.focus(); - await user.keyboard(key); + it.each([kbd.ARROW_RIGHT, kbd.ARROW_UP])( + "should change by 1% when pressing %s", + async (key) => { + const { getByTestId, user } = setup({ + value: [0.5], + min: 0, + max: 1, + step: 0.01, + }); + + const thumb = getByTestId("thumb"); + const range = getByTestId("range"); - expectPercentage({ percentage: 51, thumb, range }); - }); + thumb.focus(); + await user.keyboard(key); - it.each([kbd.ARROW_LEFT, kbd.ARROW_DOWN])("change by 10% when pressing %s", async (key) => { - const { getByTestId, user } = setup({ - value: [0.5], - min: 0, - max: 1, - step: 0.01, - }); + expectPercentage({ percentage: 51, thumb, range }); + } + ); - const thumb = getByTestId("thumb"); - const range = getByTestId("range"); + it.each([kbd.ARROW_LEFT, kbd.ARROW_DOWN])( + "should change by 10% when pressing %s", + async (key) => { + const { getByTestId, user } = setup({ + value: [0.5], + min: 0, + max: 1, + step: 0.01, + }); + + const thumb = getByTestId("thumb"); + const range = getByTestId("range"); - thumb.focus(); - await user.keyboard(key); + thumb.focus(); + await user.keyboard(key); - expectPercentage({ percentage: 49, thumb, range }); - }); + expectPercentage({ percentage: 49, thumb, range }); + } + ); }); describe("slider (negative min)", () => { - it("has a thumb positioned at 50% of the container", async () => { + it("should have a thumb positioned at 50% of the container", async () => { const { getByTestId } = setup({ value: [0], min: -50, @@ -362,39 +374,45 @@ describe("slider (negative min)", () => { expect(isCloseEnough(50, thumb.style.left)).toBeTruthy(); }); - it.each([kbd.ARROW_RIGHT, kbd.ARROW_UP])("change by 1% when pressing %s", async (key) => { - const { getByTestId, user } = setup({ - value: [0], - min: -50, - max: 50, - step: 1, - }); - - const thumb = getByTestId("thumb"); - const range = getByTestId("range"); - - thumb.focus(); - await user.keyboard(key); + it.each([kbd.ARROW_RIGHT, kbd.ARROW_UP])( + "should change by 1% when pressing %s", + async (key) => { + const { getByTestId, user } = setup({ + value: [0], + min: -50, + max: 50, + step: 1, + }); + + const thumb = getByTestId("thumb"); + const range = getByTestId("range"); - expectPercentage({ percentage: 51, thumb, range }); - }); + thumb.focus(); + await user.keyboard(key); - it.each([kbd.ARROW_LEFT, kbd.ARROW_DOWN])("change by 10% when pressing %s", async (key) => { - const { getByTestId, user } = setup({ - value: [0], - min: -50, - max: 50, - step: 1, - }); + expectPercentage({ percentage: 51, thumb, range }); + } + ); - const thumb = getByTestId("thumb"); - const range = getByTestId("range"); + it.each([kbd.ARROW_LEFT, kbd.ARROW_DOWN])( + "should change by 10% when pressing %s", + async (key) => { + const { getByTestId, user } = setup({ + value: [0], + min: -50, + max: 50, + step: 1, + }); + + const thumb = getByTestId("thumb"); + const range = getByTestId("range"); - thumb.focus(); - await user.keyboard(key); + thumb.focus(); + await user.keyboard(key); - expectPercentage({ percentage: 49, thumb, range }); - }); + expectPercentage({ percentage: 49, thumb, range }); + } + ); }); describe("slider (value=[5], min=0, max=10, step=1)", () => { @@ -405,13 +423,13 @@ describe("slider (value=[5], min=0, max=10, step=1)", () => { step: 1, }; - it("11 ticks are rendered", () => { + it("should render 11 ticks", () => { const { getAllByTestId } = setup(props); expect(getAllByTestId("tick")).toHaveLength(11); }); - it("ticks 0-5 have a data-bounded attribute", () => { + it("should have a data-bounded attribute on ticks 0-5", () => { const { getAllByTestId } = setup(props); const ticks = getAllByTestId("tick"); @@ -420,7 +438,7 @@ describe("slider (value=[5], min=0, max=10, step=1)", () => { } }); - it("ticks 6-10 have no data-bounded attribute", () => { + it("should not have a data-bounded attribute on ticks 6-10", () => { const { getAllByTestId } = setup(props); const ticks = getAllByTestId("tick"); @@ -431,7 +449,7 @@ describe("slider (value=[5], min=0, max=10, step=1)", () => { }); describe("slider (min=0, max=8, step=3)", () => { - it("3 ticks are rendered", () => { + it("should render 3 ticks", () => { const { getAllByTestId } = setup({ min: 0, max: 8, @@ -443,7 +461,7 @@ describe("slider (min=0, max=8, step=3)", () => { }); describe("slider (min=0, max=9, step=3)", () => { - it("4 ticks are rendered", () => { + it("should render 4 ticks", () => { const { getAllByTestId } = setup({ min: 0, max: 9, @@ -462,13 +480,13 @@ describe("slider (value=[3,6], min=0, max=10, step=3)", () => { step: 3, }; - it("4 ticks are rendered", () => { + it("should render 4 ticks", () => { const { getAllByTestId } = setup(props); expect(getAllByTestId("tick")).toHaveLength(4); }); - it("ticks 1,2 have a data-bounded attribute", () => { + it("should have a data-bounded attribute on ticks 1,2", () => { const { getAllByTestId } = setup(props); const ticks = getAllByTestId("tick"); @@ -477,7 +495,7 @@ describe("slider (value=[3,6], min=0, max=10, step=3)", () => { } }); - it("ticks 0,3 have no data-bounded attribute", () => { + it("should not have a data-bounded attribute on ticks 0,3", () => { const { getAllByTestId } = setup(props); const ticks = getAllByTestId("tick"); @@ -495,7 +513,7 @@ describe("slider changing options after building", () => { step: 1, }; - it("changing min", async () => { + it("should change the min", async () => { const { getAllByTestId, rerender } = setup(props); expect(getAllByTestId("tick")).toHaveLength(11); @@ -505,7 +523,7 @@ describe("slider changing options after building", () => { expect(getAllByTestId("tick")).toHaveLength(9); }); - it("changing max", async () => { + it("should change the max", async () => { const { getAllByTestId, rerender } = setup(props); expect(getAllByTestId("tick")).toHaveLength(11); @@ -515,7 +533,7 @@ describe("slider changing options after building", () => { expect(getAllByTestId("tick")).toHaveLength(9); }); - it("changing step", async () => { + it("should change the step", async () => { const { getAllByTestId, rerender } = setup(props); expect(getAllByTestId("tick")).toHaveLength(11); diff --git a/packages/bits-ui/src/tests/switch/Switch.spec.ts b/packages/bits-ui/src/tests/switch/Switch.spec.ts index 1f7297132..dd3d38478 100644 --- a/packages/bits-ui/src/tests/switch/Switch.spec.ts +++ b/packages/bits-ui/src/tests/switch/Switch.spec.ts @@ -24,23 +24,23 @@ function setup(props: Switch.RootProps = {}) { } describe("switch", () => { - it("has no accessibility violations", async () => { + it("should have no accessibility violations", async () => { const { container } = render(SwitchTest); expect(await axe(container)).toHaveNoViolations(); }); - it("has bits data attrs", async () => { + it("should have bits data attrs", async () => { const { root, thumb } = setup(); expect(root).toHaveAttribute("data-switch-root"); expect(thumb).toHaveAttribute("data-switch-thumb"); }); - it('defaults the value to "on", when no value prop is passed', async () => { + it('should default the value to "on", when no value prop is passed', async () => { const { input } = setup(); expect(input).toHaveAttribute("value", "on"); }); - it("toggles when clicked", async () => { + it("should toggle when clicked", async () => { const { user, root, input } = setup(); expect(root).toHaveAttribute("data-state", "unchecked"); expect(root).not.toHaveAttribute("data-checked"); @@ -51,7 +51,7 @@ describe("switch", () => { expect(input.checked).toBe(true); }); - it.each([kbd.ENTER, kbd.SPACE])("toggles when the `%s` key is pressed", async (key) => { + it.each([kbd.ENTER, kbd.SPACE])("should toggle when the `%s` key is pressed", async (key) => { const { user, root, input } = setup(); expect(root).toHaveAttribute("data-state", "unchecked"); expect(root).toHaveAttribute("aria-checked", "false"); @@ -88,7 +88,7 @@ describe("switch", () => { expect(newValue).toBe(true); }); - it("respects binding to the `checked` prop", async () => { + it("should respect binding to the `checked` prop", async () => { const { getByTestId, user, root, input } = setup(); const binding = getByTestId("binding"); expect(binding).toHaveTextContent("false"); @@ -98,12 +98,12 @@ describe("switch", () => { expect(input.checked).toBe(true); }); - it("doesnt include the input when the `name` prop isn't passed/undefined", async () => { + it("should not include the input when the `name` prop isn't passed/undefined", async () => { const { input } = setup({ name: undefined }); expect(input).not.toBeInTheDocument(); }); - it("renders the input when the `name` prop is passed", async () => { + it("should render the input when the `name` prop is passed", async () => { // passed by default const { input } = setup(); expect(input).toBeInTheDocument(); diff --git a/packages/bits-ui/src/tests/tabs/Tabs.spec.ts b/packages/bits-ui/src/tests/tabs/Tabs.spec.ts index 51824ce14..4572dd6b6 100644 --- a/packages/bits-ui/src/tests/tabs/Tabs.spec.ts +++ b/packages/bits-ui/src/tests/tabs/Tabs.spec.ts @@ -34,7 +34,7 @@ function setup(props: Partial = {}) { } describe("tabs", () => { - it("has no accessibility violations", async () => { + it("should have no accessibility violations", async () => { const { container } = render(TabsTest, { items: [ { @@ -47,7 +47,7 @@ describe("tabs", () => { expect(await axe(container)).toHaveNoViolations(); }); - it("has bits data attrs", async () => { + it("should have bits data attrs", async () => { const { getByTestId } = render(TabsTest, { items: [items[0] as Item], }); @@ -63,7 +63,7 @@ describe("tabs", () => { expect(content).toHaveAttribute("data-tabs-content"); }); - it("switches tabs on click", async () => { + it("should switch tabs on click", async () => { const { getByTestId, user } = setup(); const trigger1 = getByTestId("trigger-1"); @@ -94,7 +94,7 @@ describe("tabs", () => { expect(content3).not.toBeVisible(); }); - it("navigates the tabs with the keyboard", async () => { + it("should navigate the tabs with the keyboard", async () => { const { getByTestId, user } = setup(); const trigger1 = getByTestId("trigger-1"); @@ -136,7 +136,7 @@ describe("tabs", () => { expect(content3).toBeVisible(); }); - it("respects the loop prop", async () => { + it("should respect the loop prop", async () => { const { getByTestId, user } = setup({ loop: false }); const trigger1 = getByTestId("trigger-1"); @@ -153,7 +153,7 @@ describe("tabs", () => { expect(trigger3).toHaveFocus(); }); - it("respects the `activationMode: 'manual'` prop", async () => { + it("should respect the `activationMode: 'manual'` prop", async () => { const { getByTestId, user } = setup({ activationMode: "manual", }); @@ -178,7 +178,7 @@ describe("tabs", () => { expect(content1).toBeVisible(); }); - it("navigates using up & down when orientation is vertical", async () => { + it("should navigate using up & down when orientation is vertical", async () => { const { getByTestId, user } = setup({ orientation: "vertical", }); diff --git a/packages/bits-ui/src/tests/toggle-group/ToggleGroup.spec.ts b/packages/bits-ui/src/tests/toggle-group/ToggleGroup.spec.ts index 58c44078c..b5304a207 100644 --- a/packages/bits-ui/src/tests/toggle-group/ToggleGroup.spec.ts +++ b/packages/bits-ui/src/tests/toggle-group/ToggleGroup.spec.ts @@ -59,19 +59,19 @@ function setup(props: Partial = {}) { } describe("toggleGroup", () => { - it("has no accessibility violations", async () => { + it("should have no accessibility violations", async () => { const { container } = setup(); expect(await axe(container)).toHaveNoViolations(); }); - it("has bits data attrs", async () => { + it("should have bits data attrs", async () => { const { root, getByTestId } = setup(); const item = getByTestId("item-1"); expect(root).toHaveAttribute("data-toggle-group-root"); expect(item).toHaveAttribute("data-toggle-group-item"); }); - it("toggles when clicked", async () => { + it("should toggle when clicked", async () => { const { user, binding, getByTestId } = setup(); expect(binding).toHaveTextContent(""); const item = getByTestId("item-1"); @@ -82,7 +82,7 @@ describe("toggleGroup", () => { expect(binding).toHaveTextContent("2"); }); - it.each([kbd.ENTER, kbd.SPACE])("toggles when the %s key is pressed", async (key) => { + it.each([kbd.ENTER, kbd.SPACE])("should toggle when the %s key is pressed", async (key) => { const { user, binding, getByTestId } = setup(); expect(binding).toHaveTextContent(""); const item = getByTestId("item-1"); @@ -95,7 +95,7 @@ describe("toggleGroup", () => { expect(binding).toHaveTextContent("2"); }); - it("navigates between the items using the arrow keys", async () => { + it("should navigate between the items using the arrow keys", async () => { const { user, binding, getByTestId } = setup(); expect(binding).toHaveTextContent(""); const item1 = getByTestId("item-1"); @@ -111,7 +111,7 @@ describe("toggleGroup", () => { expect(item4).toHaveFocus(); }); - it("loops around when navigating with the arrow keys", async () => { + it("should loop around when navigating with the arrow keys", async () => { const { user, binding, getByTestId } = setup(); expect(binding).toHaveTextContent(""); const item1 = getByTestId("item-1"); @@ -123,7 +123,7 @@ describe("toggleGroup", () => { expect(item1).toHaveFocus(); }); - it("respects the loop prop", async () => { + it("should respect the loop prop", async () => { const { user, binding, getByTestId } = setup({ loop: false, }); @@ -160,7 +160,7 @@ describe("toggleGroup", () => { expect(newValue).toBe("2"); }); - it("respects binding to the `value` prop", async () => { + it("should respect binding to the `value` prop", async () => { const { getByTestId, user } = setup(); const binding = getByTestId("binding"); expect(binding).toHaveTextContent(""); @@ -171,7 +171,7 @@ describe("toggleGroup", () => { expect(item4).toHaveAttribute("data-state", "on"); }); - it("allows multiple items to be selected when `kind` is `'multiple'`", async () => { + it("should allow multiple items to be selected when `kind` is `'multiple'`", async () => { const { getByTestId, user } = setupMultiple(); const item1 = getByTestId("item-1"); const item2 = getByTestId("item-2"); diff --git a/packages/bits-ui/src/tests/toggle/Toggle.spec.ts b/packages/bits-ui/src/tests/toggle/Toggle.spec.ts index bcd110e83..cb1f9cc0c 100644 --- a/packages/bits-ui/src/tests/toggle/Toggle.spec.ts +++ b/packages/bits-ui/src/tests/toggle/Toggle.spec.ts @@ -20,17 +20,17 @@ function setup(props: Toggle.RootProps = {}) { } describe("toggle", () => { - it("has no accessibility violations", async () => { + it("should have no accessibility violations", async () => { const { container } = render(ToggleTest); expect(await axe(container)).toHaveNoViolations(); }); - it("has bits data attrs", async () => { + it("should have bits data attrs", async () => { const { root } = setup(); expect(root).toHaveAttribute("data-toggle-root"); }); - it("toggles when clicked", async () => { + it("should toggle when clicked", async () => { const { user, root } = setup(); expect(root).toHaveAttribute("data-state", "off"); expect(root).toHaveAttribute("aria-pressed", "false"); @@ -39,7 +39,7 @@ describe("toggle", () => { expect(root).toHaveAttribute("aria-pressed", "true"); }); - it.each([kbd.ENTER, kbd.SPACE])("toggles when the `%s` key is pressed", async (key) => { + it.each([kbd.ENTER, kbd.SPACE])("should toggle when the `%s` key is pressed", async (key) => { const { user, root } = setup(); expect(root).toHaveAttribute("data-state", "off"); expect(root).toHaveAttribute("aria-pressed", "false"); @@ -67,7 +67,7 @@ describe("toggle", () => { expect(newValue).toBe(true); }); - it("respects binding to the `pressed` prop", async () => { + it("should respect binding to the `pressed` prop", async () => { const { getByTestId, user, root } = setup(); const binding = getByTestId("binding"); expect(binding).toHaveTextContent("false"); diff --git a/packages/bits-ui/src/tests/toolbar/Toolbar.spec.ts b/packages/bits-ui/src/tests/toolbar/Toolbar.spec.ts index ec7f032c4..f1ef2d275 100644 --- a/packages/bits-ui/src/tests/toolbar/Toolbar.spec.ts +++ b/packages/bits-ui/src/tests/toolbar/Toolbar.spec.ts @@ -46,12 +46,12 @@ function setup(props: Partial = {}) { } describe("toolbar", () => { - it("has no accessibility violations", async () => { + it("should have no accessibility violations", async () => { const { container } = render(ToolbarTest); expect(await axe(container)).toHaveNoViolations(); }); - it("has bits data attrs", async () => { + it("should have bits data attrs", async () => { const { root, groupMultiple, @@ -70,7 +70,7 @@ describe("toolbar", () => { expect(button).toHaveAttribute("data-toolbar-button"); }); - it("navigates between the items using the arrow keys", async () => { + it("should navigate between the items using the arrow keys", async () => { const { user, groupMultipleItemBold, @@ -100,7 +100,7 @@ describe("toolbar", () => { await user.keyboard(kbd.ARROW_RIGHT); }); - it("loops around when navigating with the arrow keys", async () => { + it("should loop around when navigating with the arrow keys", async () => { const { user, groupMultipleItemBold, button } = setup(); groupMultipleItemBold.focus(); await user.keyboard(kbd.ARROW_LEFT); @@ -109,7 +109,7 @@ describe("toolbar", () => { expect(groupMultipleItemBold).toHaveFocus(); }); - it("respects the loop: false prop", async () => { + it("should respect the loop: false prop", async () => { const { user, groupMultipleItemBold, button } = setup({ loop: false, }); @@ -123,7 +123,7 @@ describe("toolbar", () => { expect(button).toHaveFocus(); }); - it("toolbar toogle group, type `'single'`, toggles when clicked", async () => { + it("should toggles when clicked when toolbar toogle group, type `'single'`", async () => { const { user, groupSingleItemLeft, groupSingleItemCenter, alignBinding } = setup(); expect(alignBinding).toHaveTextContent(""); await user.click(groupSingleItemLeft); @@ -133,7 +133,7 @@ describe("toolbar", () => { }); it.each([kbd.ENTER, kbd.SPACE])( - "toolbar toogle group, type `'single'`, toggles when the %s key is pressed", + "should toggles when the %s key is pressed when toolbar toogle group, type `'single'`", async (key) => { const { user, groupSingleItemLeft, groupSingleItemCenter, alignBinding } = setup(); expect(alignBinding).toHaveTextContent(""); @@ -146,7 +146,7 @@ describe("toolbar", () => { } ); - it("allows multiple items to be selected with toolbar toggle group type `'multiple'`", async () => { + it("should allow multiple items to be selected with toolbar toggle group type `'multiple'`", async () => { const { user, groupMultipleItemBold, @@ -167,7 +167,7 @@ describe("toolbar", () => { expect(styleBinding).toHaveTextContent(""); }); - it("toolbar toogle group items should be disabled then the `disabled` prop is set to true", async () => { + it("should disable group items when the `disabled` prop is set to true", async () => { const { groupMultipleItemBold, groupMultipleItemItalic, @@ -187,7 +187,7 @@ describe("toolbar", () => { expect(groupSingleItemRight).toBeDisabled(); }); - it("toolbar toogle groups should fire the `onChange` callback when changing", async () => { + it("should fire the `onChange` callback when changing", async () => { let newMultipleValue; function multipleOnValueChange(next: string[] | undefined) { newMultipleValue = next; @@ -210,7 +210,7 @@ describe("toolbar", () => { expect(newSingleValue).toBe("right"); }); - it("toolbar toogle groups respects binding to the `value` prop", async () => { + it("should respect binding to the `value` prop", async () => { const { user, groupMultipleItemItalic, groupSingleItemCenter, styleBinding, alignBinding } = setup(); expect(styleBinding).toHaveTextContent("bold"); @@ -231,16 +231,19 @@ describe("toolbar", () => { expect(groupSingleItemCenter).toHaveAttribute("aria-checked", "true"); }); - it.each(["link", "button"])("toolbar %s forwards click event", async (kind) => { - const { user, clickedBinding, [kind as keyof ReturnType]: el } = setup(); + it.each(["link", "button"])( + "should forward click event when the %s is clicked", + async (kind) => { + const { user, clickedBinding, [kind as keyof ReturnType]: el } = setup(); - expect(clickedBinding).toHaveTextContent(""); - await user.click(el as Element); - expect(clickedBinding).toHaveTextContent(kind); - }); + expect(clickedBinding).toHaveTextContent(""); + await user.click(el as Element); + expect(clickedBinding).toHaveTextContent(kind); + } + ); it.each([kbd.ENTER, kbd.SPACE])( - "toolbar button forwards click event when the %s key is pressed", + "should forward click event when the %s key is pressed", async (key) => { const { user, button, clickedBinding } = setup(); diff --git a/packages/bits-ui/src/tests/tooltip/Tooltip.spec.ts b/packages/bits-ui/src/tests/tooltip/Tooltip.spec.ts index 28a0de6bd..6f77dc0c6 100644 --- a/packages/bits-ui/src/tests/tooltip/Tooltip.spec.ts +++ b/packages/bits-ui/src/tests/tooltip/Tooltip.spec.ts @@ -25,12 +25,12 @@ async function open(props: Partial = {}) { } describe("tooltip", () => { - it("has no accessibility violations", async () => { + it("should have no accessibility violations", async () => { const { container } = setup(); expect(await axe(container)).toHaveNoViolations(); }); - it("has bits data attrs", async () => { + it("should have bits data attrs", async () => { const { getByTestId } = await open(); const parts = ["trigger", "content"]; @@ -40,20 +40,19 @@ describe("tooltip", () => { } }); - it("opens on hover", async () => { + it("should on hover", async () => { const { user, content } = await open(); await user.click(content); expect(content).toBeVisible(); }); - it.skip("closes on escape keydown", async () => { + it("should close on escape keydown", async () => { const { user, queryByTestId } = await open(); await user.keyboard(kbd.ESCAPE); - await sleep(100); expect(queryByTestId("content")).toBeNull(); }); - it.skip("closes when pointer moves outside the trigger and content", async () => { + it.skip("should close when pointer moves outside the trigger and content", async () => { const { user, getByTestId, queryByTestId, content } = await open(); const outside = getByTestId("outside") as HTMLElement; @@ -70,27 +69,27 @@ describe("tooltip", () => { await waitFor(() => expect(queryByTestId("content")).toBeNull()); }); - it("portals to the body by default", async () => { + it("should portal to the body by default", async () => { const { content } = await open(); const contentWrapper = content.parentElement; expect(contentWrapper?.parentElement).toBe(document.body); }); - it("portals to a custom element if specified", async () => { + it("should portal to a custom element if specified", async () => { const { content, getByTestId } = await open({ portalProps: { to: "#portal-target" } }); const portalTarget = getByTestId("portal-target"); const contentWrapper = content.parentElement; expect(contentWrapper?.parentElement).toBe(portalTarget); }); - it("does not portal if `disabled` is passed to the portal", async () => { + it("should not portal if `disabled` is passed to the portal", async () => { const { content, getByTestId } = await open({ portalProps: { disabled: true } }); const main = getByTestId("main"); const contentWrapper = content.parentElement; expect(contentWrapper?.parentElement).toBe(main); }); - it("allows ignoring escapeKeydownBehavior ", async () => { + it("should allow ignoring escapeKeydownBehavior ", async () => { const { content, user, queryByTestId } = await open({ contentProps: { escapeKeydownBehavior: "ignore", @@ -101,7 +100,7 @@ describe("tooltip", () => { expect(queryByTestId("content")).not.toBeNull(); }); - it("allows ignoring interactOutsideBehavior", async () => { + it("should allow ignoring interactOutsideBehavior", async () => { const { content, user, queryByTestId, getByTestId } = await open({ contentProps: { interactOutsideBehavior: "ignore", @@ -113,7 +112,7 @@ describe("tooltip", () => { expect(queryByTestId("content")).not.toBeNull(); }); - it("respects binding the open prop", async () => { + it("should respect binding the open prop", async () => { const { queryByTestId, getByTestId, user } = await open({ contentProps: { interactOutsideBehavior: "ignore",