Use svelte-inline-compile library to add more unit tests (mostly slot prop)

This brings the number of tests from 381 => 424 which I'm pleased with.

It'd be nice to replace my TestRenderer tests with this but it's not worth the effort.
This commit is contained in:
Ryan Gossiaux
2021-12-30 15:43:39 -10:00
parent 72b0b838e4
commit 3ff520d72d
8 changed files with 1223 additions and 1500 deletions

View File

@@ -14,6 +14,8 @@ import {
assertActiveElement, assertActiveElement,
assertDialog, assertDialog,
assertDialogDescription, assertDialogDescription,
assertDialogOverlay,
assertDialogTitle,
DialogState, DialogState,
getByText, getByText,
getDialog, getDialog,
@@ -24,6 +26,7 @@ import {
import { click, Keys, press } from "$lib/test-utils/interactions"; import { click, Keys, press } from "$lib/test-utils/interactions";
import Transition from "$lib/components/transitions/TransitionRoot.svelte"; import Transition from "$lib/components/transitions/TransitionRoot.svelte";
import { tick } from "svelte"; import { tick } from "svelte";
import svelte from "svelte-inline-compile";
let mockId = 0; let mockId = 0;
jest.mock("../../hooks/use-id", () => { jest.mock("../../hooks/use-id", () => {
@@ -105,41 +108,29 @@ describe("Rendering", () => {
}) })
); );
// TODO: render prop tests! it(
'Dialog should have slot props',
suppressConsoleLogs(async () => {
render(svelte`
<script>
let isOpen = false;
</script>
<button id="trigger" on:click={() => isOpen = (true)}>
Trigger
</button>
<Dialog open={isOpen} on:close={(e) => isOpen = e.detail} let:open>
<pre>{JSON.stringify({open})}</pre>
<TestTabSentinel />
</Dialog>
`)
// it( assertDialog({ state: DialogState.InvisibleUnmounted })
// 'should be possible to render a Dialog using a render prop',
// suppressConsoleLogs(async () => {
// function Example() {
// let [isOpen, setIsOpen] = useState(false)
// return ( await click(document.getElementById('trigger'))
// <>
// <button id= "trigger" onClick = {() => setIsOpen(true)
// }>
// Trigger
// < /button>
// < Dialog open = { isOpen } onClose = { setIsOpen } >
// { data => (
// <>
// <pre>{ JSON.stringify(data) } < /pre>
// < TabSentinel />
// </>
// )
// }
// </Dialog>
// < />
// )
// }
// render(<Example />)
// assertDialog({ state: DialogState.InvisibleUnmounted }) assertDialog({ state: DialogState.Visible, textContent: JSON.stringify({ open: true }) })
})
// await click(document.getElementById('trigger')) )
// assertDialog({ state: DialogState.Visible, textContent: JSON.stringify({ open: true }) })
// })
// )
it('should be possible to always render the Dialog if we provide it a `static` prop (and enable focus trapping based on `open`)', async () => { it('should be possible to always render the Dialog if we provide it a `static` prop (and enable focus trapping based on `open`)', async () => {
let focusCounter = jest.fn() let focusCounter = jest.fn()
@@ -235,91 +226,85 @@ describe("Rendering", () => {
}) })
) )
}) })
// TODO: more render prop tests! describe('DialogOverlay', () => {
it(
'DialogOverlay should have slot props',
suppressConsoleLogs(async () => {
let overlay = jest.fn().mockReturnValue(null)
render(svelte`
<script>
let isOpen = false;
</script>
<button id="trigger" on:click={() => isOpen = !isOpen}>
Trigger
</button>
<Dialog open={isOpen} on:close={(e) => isOpen = e.detail}>
<DialogOverlay let:open>{overlay({ open })}</DialogOverlay>
<TestTabSentinel />
</Dialog>
`)
// describe('Dialog.Overlay', () => { assertDialogOverlay({
// it( state: DialogState.InvisibleUnmounted,
// 'should be possible to render Dialog.Overlay using a render prop', attributes: { id: 'headlessui-dialog-overlay-2' },
// suppressConsoleLogs(async () => { })
// let overlay = jest.fn().mockReturnValue(null)
// function Example() {
// let [isOpen, setIsOpen] = useState(false)
// return (
// <>
// <button id="trigger" onClick={() => setIsOpen(v => !v)}>
// Trigger
// </button>
// <Dialog open={isOpen} onClose={setIsOpen}>
// <Dialog.Overlay>{overlay}</Dialog.Overlay>
// <TabSentinel />
// </Dialog>
// </>
// )
// }
// render(<Example />) await click(document.getElementById('trigger'))
// assertDialogOverlay({ assertDialogOverlay({
// state: DialogState.InvisibleUnmounted, state: DialogState.Visible,
// attributes: { id: 'headlessui-dialog-overlay-2' }, attributes: { id: 'headlessui-dialog-overlay-2' },
// }) })
expect(overlay).toHaveBeenCalledWith({ open: true })
})
)
})
// await click(document.getElementById('trigger')) describe('DialogTitle', () => {
it(
'DialogTitle should have slot props',
suppressConsoleLogs(async () => {
render(svelte`
<Dialog open={true} on:close={console.log}>
<DialogTitle let:open>{JSON.stringify({ open })}</DialogTitle>
<TestTabSentinel />
</Dialog>
`)
// assertDialogOverlay({ assertDialog({
// state: DialogState.Visible, state: DialogState.Visible,
// attributes: { id: 'headlessui-dialog-overlay-2' }, attributes: { id: 'headlessui-dialog-1' },
// }) })
// expect(overlay).toHaveBeenCalledWith({ open: true }) assertDialogTitle({
// }) state: DialogState.Visible,
// ) textContent: JSON.stringify({ open: true }),
// }) })
})
)
})
// describe('Dialog.Title', () => { describe('DialogDescription', () => {
// it( it(
// 'should be possible to render Dialog.Title using a render prop', 'DialogDescription should have slot props',
// suppressConsoleLogs(async () => { suppressConsoleLogs(async () => {
// render( render(svelte`
// <Dialog open={true} onClose={console.log}> <Dialog open={true} on:close={console.log}>
// <Dialog.Title>{JSON.stringify}</Dialog.Title> <DialogDescription let:open>{JSON.stringify({ open })}</DialogDescription>
// <TabSentinel /> <TestTabSentinel />
// </Dialog> </Dialog>
// ) `)
// assertDialog({ assertDialog({
// state: DialogState.Visible, state: DialogState.Visible,
// attributes: { id: 'headlessui-dialog-1' }, attributes: { id: 'headlessui-dialog-1' },
// }) })
// assertDialogTitle({ assertDialogDescription({
// state: DialogState.Visible, state: DialogState.Visible,
// textContent: JSON.stringify({ open: true }), textContent: JSON.stringify({ open: true }),
// }) })
// }) })
// ) )
// }) })
// describe('Dialog.Description', () => {
// it(
// 'should be possible to render Dialog.Description using a render prop',
// suppressConsoleLogs(async () => {
// render(
// <Dialog open={true} onClose={console.log}>
// <Dialog.Description>{JSON.stringify}</Dialog.Description>
// <TabSentinel />
// </Dialog>
// )
// assertDialog({
// state: DialogState.Visible,
// attributes: { id: 'headlessui-dialog-1' },
// })
// assertDialogDescription({
// state: DialogState.Visible,
// textContent: JSON.stringify({ open: true }),
// })
// })
// )
// })
}) })
describe('Composition', () => { describe('Composition', () => {
@@ -469,7 +454,7 @@ describe('Keyboard interactions', () => {
describe('Mouse interactions', () => { describe('Mouse interactions', () => {
it( it(
'should be possible to close a Dialog using a click on the Dialog.Overlay', 'should be possible to close a Dialog using a click on the DialogOverlay',
suppressConsoleLogs(async () => { suppressConsoleLogs(async () => {
render( render(
TestRenderer, { TestRenderer, {
@@ -497,7 +482,7 @@ describe('Mouse interactions', () => {
) )
it( it(
'should not close the Dialog when clicking on contents of the Dialog.Overlay', 'should not close the Dialog when clicking on contents of the DialogOverlay',
suppressConsoleLogs(async () => { suppressConsoleLogs(async () => {
render( render(
TestRenderer, { TestRenderer, {
@@ -588,7 +573,7 @@ describe('Mouse interactions', () => {
) )
it( it(
'should stop propagating click events when clicking on the Dialog.Overlay', 'should stop propagating click events when clicking on the DialogOverlay',
suppressConsoleLogs(async () => { suppressConsoleLogs(async () => {
let wrapperFn = jest.fn() let wrapperFn = jest.fn()
render( render(
@@ -610,7 +595,7 @@ describe('Mouse interactions', () => {
// Verify that the wrapper function has not been called yet // Verify that the wrapper function has not been called yet
expect(wrapperFn).toHaveBeenCalledTimes(0) expect(wrapperFn).toHaveBeenCalledTimes(0)
// Click the Dialog.Overlay to close the Dialog // Click the DialogOverlay to close the Dialog
await click(getDialogOverlay()) await click(getDialogOverlay())
// Verify it is closed // Verify it is closed
@@ -688,7 +673,7 @@ describe('Nesting', () => {
strategy | action strategy | action
${'with `Escape`'} | ${() => press(Keys.Escape)} ${'with `Escape`'} | ${() => press(Keys.Escape)}
${'with `Outside Click`'} | ${() => click(document.body)} ${'with `Outside Click`'} | ${() => click(document.body)}
${'with `Click on Dialog.Overlay`'} | ${() => click(getDialogOverlays().pop()!)} ${'with `Click on DialogOverlay`'} | ${() => click(getDialogOverlays().pop()!)}
`( `(
'should be possible to open nested Dialog components and close them $strategy', 'should be possible to open nested Dialog components and close them $strategy',
async ({ action }) => { async ({ action }) => {

View File

@@ -14,6 +14,7 @@ import {
import { click, Keys, MouseButton, press } from "$lib/test-utils/interactions"; import { click, Keys, MouseButton, press } from "$lib/test-utils/interactions";
import { Transition, TransitionChild } from "../transitions"; import { Transition, TransitionChild } from "../transitions";
import TransitionDebug from "./_TransitionDebug.svelte"; import TransitionDebug from "./_TransitionDebug.svelte";
import svelte from "svelte-inline-compile";
let mockId = 0; let mockId = 0;
jest.mock("../../hooks/use-id", () => { jest.mock("../../hooks/use-id", () => {
@@ -72,240 +73,178 @@ describe("Safe guards", () => {
}); });
describe("Rendering", () => { describe("Rendering", () => {
// describe('Disclosure', () => { describe('Disclosure', () => {
// it( it(
// 'should be possible to render a Disclosure using a render prop', 'should render a Disclosure with slot props',
// suppressConsoleLogs(async () => { suppressConsoleLogs(async () => {
// render( render(svelte`
// <Disclosure> <Disclosure let:open>
// {({ open }) => ( <DisclosureButton>Trigger</DisclosureButton>
// <> <DisclosurePanel>Panel is: {open ? 'open' : 'closed'}</DisclosurePanel>
// <DisclosureButton>Trigger</DisclosureButton> </Disclosure>
// <DisclosurePanel>Panel is: {open ? 'open' : 'closed'}</DisclosurePanel> `)
// </>
// )}
// </Disclosure>
// )
// assertDisclosureButton({ assertDisclosureButton({
// state: DisclosureState.InvisibleUnmounted, state: DisclosureState.InvisibleUnmounted,
// attributes: { id: 'headlessui-disclosure-button-1' }, attributes: { id: 'headlessui-disclosure-button-1' },
// }) })
// assertDisclosurePanel({ state: DisclosureState.InvisibleUnmounted }) assertDisclosurePanel({ state: DisclosureState.InvisibleUnmounted })
// await click(getDisclosureButton()) await click(getDisclosureButton())
// assertDisclosureButton({ assertDisclosureButton({
// state: DisclosureState.Visible, state: DisclosureState.Visible,
// attributes: { id: 'headlessui-disclosure-button-1' }, attributes: { id: 'headlessui-disclosure-button-1' },
// }) })
// assertDisclosurePanel({ state: DisclosureState.Visible, textContent: 'Panel is: open' }) assertDisclosurePanel({ state: DisclosureState.Visible, textContent: 'Panel is: open' })
// }) })
// ) )
// it('should be possible to render a Disclosure in an open state by default', async () => { it('should be possible to render a Disclosure in an open state by default', async () => {
// render( render(svelte`
// <Disclosure defaultOpen> <Disclosure defaultOpen let:open>
// {({ open }) => ( <DisclosureButton>Trigger</DisclosureButton>
// <> <DisclosurePanel>Panel is: {open ? 'open' : 'closed'}</DisclosurePanel>
// <DisclosureButton>Trigger</DisclosureButton> </Disclosure>
// <DisclosurePanel>Panel is: {open ? 'open' : 'closed'}</DisclosurePanel> `)
// </>
// )}
// </Disclosure>
// )
// assertDisclosureButton({ assertDisclosureButton({
// state: DisclosureState.Visible, state: DisclosureState.Visible,
// attributes: { id: 'headlessui-disclosure-button-1' }, attributes: { id: 'headlessui-disclosure-button-1' },
// }) })
// assertDisclosurePanel({ state: DisclosureState.Visible, textContent: 'Panel is: open' }) assertDisclosurePanel({ state: DisclosureState.Visible, textContent: 'Panel is: open' })
// await click(getDisclosureButton()) await click(getDisclosureButton())
// assertDisclosureButton({ state: DisclosureState.InvisibleUnmounted }) assertDisclosureButton({ state: DisclosureState.InvisibleUnmounted })
// }) })
// it( it(
// 'should expose a close function that closes the disclosure', 'should expose a close function that closes the disclosure',
// suppressConsoleLogs(async () => { suppressConsoleLogs(async () => {
// render( render(svelte`
// <Disclosure> <Disclosure let:close>
// {({ close }) => ( <DisclosureButton>Trigger</DisclosureButton>
// <> <DisclosurePanel>
// <DisclosureButton>Trigger</DisclosureButton> <button on:click={() => close()}>Close me</button>
// <DisclosurePanel> </DisclosurePanel>
// <button onClick={() => close()}>Close me</button> </Disclosure>
// </DisclosurePanel> `)
// </>
// )}
// </Disclosure>
// )
// // Focus the button // Focus the button
// getDisclosureButton()?.focus() getDisclosureButton()?.focus()
// // Ensure the button is focused // Ensure the button is focused
// assertActiveElement(getDisclosureButton()) assertActiveElement(getDisclosureButton())
// // Open the disclosure // Open the disclosure
// await click(getDisclosureButton()) await click(getDisclosureButton())
// // Ensure we can click the close button // Ensure we can click the close button
// await click(getByText('Close me')) await click(getByText('Close me'))
// // Ensure the disclosure is closed // Ensure the disclosure is closed
// assertDisclosurePanel({ state: DisclosureState.InvisibleUnmounted }) assertDisclosurePanel({ state: DisclosureState.InvisibleUnmounted })
// // Ensure the DisclosureButton got the restored focus // Ensure the DisclosureButton got the restored focus
// assertActiveElement(getByText('Trigger')) assertActiveElement(getByText('Trigger'))
// }) })
// ) )
// it( it(
// 'should expose a close function that closes the disclosure and restores to a specific element', 'should expose a close function that closes the disclosure and restores to a specific element',
// suppressConsoleLogs(async () => { suppressConsoleLogs(async () => {
// render( render(svelte`
// <> <button id="test">restoreable</button>
// <button id="test">restoreable</button> <Disclosure let:close>
// <Disclosure> <DisclosureButton>Trigger</DisclosureButton>
// {({ close }) => ( <DisclosurePanel>
// <> <button on:click={() => close(document.getElementById('test'))}>
// <DisclosureButton>Trigger</DisclosureButton> Close me
// <DisclosurePanel> </button>
// <button onClick={() => close(document.getElementById('test')!)}> </DisclosurePanel>
// Close me </Disclosure>
// </button> `)
// </DisclosurePanel>
// </>
// )}
// </Disclosure>
// </>
// )
// // Focus the button // Focus the button
// getDisclosureButton()?.focus() getDisclosureButton()?.focus()
// // Ensure the button is focused // Ensure the button is focused
// assertActiveElement(getDisclosureButton()) assertActiveElement(getDisclosureButton())
// // Open the disclosure // Open the disclosure
// await click(getDisclosureButton()) await click(getDisclosureButton())
// // Ensure we can click the close button // Ensure we can click the close button
// await click(getByText('Close me')) await click(getByText('Close me'))
// // Ensure the disclosure is closed // Ensure the disclosure is closed
// assertDisclosurePanel({ state: DisclosureState.InvisibleUnmounted }) assertDisclosurePanel({ state: DisclosureState.InvisibleUnmounted })
// // Ensure the restoreable button got the restored focus // Ensure the restoreable button got the restored focus
// assertActiveElement(getByText('restoreable')) assertActiveElement(getByText('restoreable'))
// }) })
// ) )
})
// it(
// 'should expose a close function that closes the disclosure and restores to a ref',
// suppressConsoleLogs(async () => {
// function Example() {
// let elementRef = useRef(null)
// return (
// <>
// <button ref={elementRef}>restoreable</button>
// <Disclosure>
// {({ close }) => (
// <>
// <DisclosureButton>Trigger</DisclosureButton>
// <DisclosurePanel>
// <button onClick={() => close(elementRef)}>Close me</button>
// </DisclosurePanel>
// </>
// )}
// </Disclosure>
// </>
// )
// }
// render(<Example />)
// // Focus the button
// getDisclosureButton()?.focus()
// // Ensure the button is focused
// assertActiveElement(getDisclosureButton())
// // Open the disclosure
// await click(getDisclosureButton())
// // Ensure we can click the close button
// await click(getByText('Close me'))
// // Ensure the disclosure is closed
// assertDisclosurePanel({ state: DisclosureState.InvisibleUnmounted })
// // Ensure the restoreable button got the restored focus
// assertActiveElement(getByText('restoreable'))
// })
// )
// })
describe("DisclosureButton", () => { describe("DisclosureButton", () => {
// it( it(
// 'should be possible to render a DisclosureButton using a render prop', 'should render a DisclosureButton with slot props',
// suppressConsoleLogs(async () => { suppressConsoleLogs(async () => {
// render( render(svelte`
// <Disclosure> <Disclosure let:open>
// <DisclosureButton>{JSON.stringify}</DisclosureButton> <DisclosureButton>{JSON.stringify({ open })}</DisclosureButton>
// <DisclosurePanel></DisclosurePanel> <DisclosurePanel></DisclosurePanel>
// </Disclosure> </Disclosure>
// ) `)
// assertDisclosureButton({ assertDisclosureButton({
// state: DisclosureState.InvisibleUnmounted, state: DisclosureState.InvisibleUnmounted,
// attributes: { id: 'headlessui-disclosure-button-1' }, attributes: { id: 'headlessui-disclosure-button-1' },
// textContent: JSON.stringify({ open: false }), textContent: JSON.stringify({ open: false }),
// }) })
// assertDisclosurePanel({ state: DisclosureState.InvisibleUnmounted }) assertDisclosurePanel({ state: DisclosureState.InvisibleUnmounted })
// await click(getDisclosureButton()) await click(getDisclosureButton())
// assertDisclosureButton({ assertDisclosureButton({
// state: DisclosureState.Visible, state: DisclosureState.Visible,
// attributes: { id: 'headlessui-disclosure-button-1' }, attributes: { id: 'headlessui-disclosure-button-1' },
// textContent: JSON.stringify({ open: true }), textContent: JSON.stringify({ open: true }),
// }) })
// assertDisclosurePanel({ state: DisclosureState.Visible }) assertDisclosurePanel({ state: DisclosureState.Visible })
// }) })
// ) )
// it( it(
// 'should be possible to render a DisclosureButton using a render prop and an `as` prop', 'should be possible to render a DisclosureButton using a render prop and an `as` prop',
// suppressConsoleLogs(async () => { suppressConsoleLogs(async () => {
// render( render(svelte`
// <Disclosure> <Disclosure>
// <DisclosureButton as="div" role="button"> <DisclosureButton as="div" role="button" let:open>
// {JSON.stringify} {JSON.stringify({ open })}
// </DisclosureButton> </DisclosureButton>
// <DisclosurePanel /> <DisclosurePanel />
// </Disclosure> </Disclosure>
// ) `)
// assertDisclosureButton({ assertDisclosureButton({
// state: DisclosureState.InvisibleUnmounted, state: DisclosureState.InvisibleUnmounted,
// attributes: { id: 'headlessui-disclosure-button-1' }, attributes: { id: 'headlessui-disclosure-button-1' },
// textContent: JSON.stringify({ open: false }), textContent: JSON.stringify({ open: false }),
// }) })
// assertDisclosurePanel({ state: DisclosureState.InvisibleUnmounted }) assertDisclosurePanel({ state: DisclosureState.InvisibleUnmounted })
// await click(getDisclosureButton()) await click(getDisclosureButton())
// assertDisclosureButton({ assertDisclosureButton({
// state: DisclosureState.Visible, state: DisclosureState.Visible,
// attributes: { id: 'headlessui-disclosure-button-1' }, attributes: { id: 'headlessui-disclosure-button-1' },
// textContent: JSON.stringify({ open: true }), textContent: JSON.stringify({ open: true }),
// }) })
// assertDisclosurePanel({ state: DisclosureState.Visible }) assertDisclosurePanel({ state: DisclosureState.Visible })
// }) })
// ) )
describe('`type` attribute', () => { describe('`type` attribute', () => {
it('should set the `type` to "button" by default', async () => { it('should set the `type` to "button" by default', async () => {
@@ -354,34 +293,34 @@ describe("Rendering", () => {
}) })
describe('DisclosurePanel', () => { describe('DisclosurePanel', () => {
// it( it(
// 'should be possible to render DisclosurePanel using a render prop', 'should render a DisclosurePanel with slot props',
// suppressConsoleLogs(async () => { suppressConsoleLogs(async () => {
// render( render(svelte`
// <Disclosure> <Disclosure>
// <DisclosureButton>Trigger</DisclosureButton> <DisclosureButton>Trigger</DisclosureButton>
// <DisclosurePanel>{JSON.stringify}</DisclosurePanel> <DisclosurePanel let:open>{JSON.stringify({ open })}</DisclosurePanel>
// </Disclosure> </Disclosure>
// ) `)
// assertDisclosureButton({ assertDisclosureButton({
// state: DisclosureState.InvisibleUnmounted, state: DisclosureState.InvisibleUnmounted,
// attributes: { id: 'headlessui-disclosure-button-1' }, attributes: { id: 'headlessui-disclosure-button-1' },
// }) })
// assertDisclosurePanel({ state: DisclosureState.InvisibleUnmounted }) assertDisclosurePanel({ state: DisclosureState.InvisibleUnmounted })
// await click(getDisclosureButton()) await click(getDisclosureButton())
// assertDisclosureButton({ assertDisclosureButton({
// state: DisclosureState.Visible, state: DisclosureState.Visible,
// attributes: { id: 'headlessui-disclosure-button-1' }, attributes: { id: 'headlessui-disclosure-button-1' },
// }) })
// assertDisclosurePanel({ assertDisclosurePanel({
// state: DisclosureState.Visible, state: DisclosureState.Visible,
// textContent: JSON.stringify({ open: true }), textContent: JSON.stringify({ open: true }),
// }) })
// }) })
// ) )
it('should be possible to always render the DisclosurePanel if we provide it a `static` prop', () => { it('should be possible to always render the DisclosurePanel if we provide it a `static` prop', () => {
render( render(
@@ -427,114 +366,70 @@ describe("Rendering", () => {
assertDisclosurePanel({ state: DisclosureState.InvisibleHidden }) assertDisclosurePanel({ state: DisclosureState.InvisibleHidden })
}) })
// it( it(
// 'should expose a close function that closes the disclosure', 'should expose a close function that closes the disclosure',
// suppressConsoleLogs(async () => { suppressConsoleLogs(async () => {
// render( render(svelte`
// <Disclosure> <Disclosure>
// <DisclosureButton>Trigger</DisclosureButton> <DisclosureButton>Trigger</DisclosureButton>
// <DisclosurePanel> <DisclosurePanel let:close>
// {({ close }) => <button onClick={() => close()}>Close me</button>} <button on:click={() => close()}>Close me</button>
// </DisclosurePanel> </DisclosurePanel>
// </Disclosure> </Disclosure>
// ) `)
// // Focus the button // Focus the button
// getDisclosureButton()?.focus() getDisclosureButton()?.focus()
// // Ensure the button is focused // Ensure the button is focused
// assertActiveElement(getDisclosureButton()) assertActiveElement(getDisclosureButton())
// // Open the disclosure // Open the disclosure
// await click(getDisclosureButton()) await click(getDisclosureButton())
// // Ensure we can click the close button // Ensure we can click the close button
// await click(getByText('Close me')) await click(getByText('Close me'))
// // Ensure the disclosure is closed // Ensure the disclosure is closed
// assertDisclosurePanel({ state: DisclosureState.InvisibleUnmounted }) assertDisclosurePanel({ state: DisclosureState.InvisibleUnmounted })
// // Ensure the DisclosureButton got the restored focus // Ensure the DisclosureButton got the restored focus
// assertActiveElement(getByText('Trigger')) assertActiveElement(getByText('Trigger'))
// }) })
// ) )
// it( it(
// 'should expose a close function that closes the disclosure and restores to a specific element', 'should expose a close function that closes the disclosure and restores to a specific element',
// suppressConsoleLogs(async () => { suppressConsoleLogs(async () => {
// render( render(svelte`
// <> <button id="test">restoreable</button>
// <button id="test">restoreable</button> <Disclosure>
// <Disclosure> <DisclosureButton>Trigger</DisclosureButton>
// <DisclosureButton>Trigger</DisclosureButton> <DisclosurePanel let:close>
// <DisclosurePanel> <button on:click={() => close(document.getElementById('test'))}>Close me</button>
// {({ close }) => ( </DisclosurePanel>
// <button onClick={() => close(document.getElementById('test')!)}>Close me</button> </Disclosure>
// )} `)
// </DisclosurePanel>
// </Disclosure>
// </>
// )
// // Focus the button // Focus the button
// getDisclosureButton()?.focus() getDisclosureButton()?.focus()
// // Ensure the button is focused // Ensure the button is focused
// assertActiveElement(getDisclosureButton()) assertActiveElement(getDisclosureButton())
// // Open the disclosure // Open the disclosure
// await click(getDisclosureButton()) await click(getDisclosureButton())
// // Ensure we can click the close button // Ensure we can click the close button
// await click(getByText('Close me')) await click(getByText('Close me'))
// // Ensure the disclosure is closed // Ensure the disclosure is closed
// assertDisclosurePanel({ state: DisclosureState.InvisibleUnmounted }) assertDisclosurePanel({ state: DisclosureState.InvisibleUnmounted })
// // Ensure the restoreable button got the restored focus // Ensure the restoreable button got the restored focus
// assertActiveElement(getByText('restoreable')) assertActiveElement(getByText('restoreable'))
// }) })
// ) )
// it(
// 'should expose a close function that closes the disclosure and restores to a ref',
// suppressConsoleLogs(async () => {
// function Example() {
// let elementRef = useRef(null)
// return (
// <>
// <button ref={elementRef}>restoreable</button>
// <Disclosure>
// <DisclosureButton>Trigger</DisclosureButton>
// <DisclosurePanel>
// {({ close }) => <button onClick={() => close(elementRef)}>Close me</button>}
// </DisclosurePanel>
// </Disclosure>
// </>
// )
// }
// render(<Example />)
// // Focus the button
// getDisclosureButton()?.focus()
// // Ensure the button is focused
// assertActiveElement(getDisclosureButton())
// // Open the disclosure
// await click(getDisclosureButton())
// // Ensure we can click the close button
// await click(getByText('Close me'))
// // Ensure the disclosure is closed
// assertDisclosurePanel({ state: DisclosureState.InvisibleUnmounted })
// // Ensure the restoreable button got the restored focus
// assertActiveElement(getByText('restoreable'))
// })
// )
}) })
}) })

View File

@@ -15,6 +15,8 @@ import {
assertListboxButton, assertListboxButton,
assertListboxButtonLinkedWithListbox, assertListboxButtonLinkedWithListbox,
assertListboxButtonLinkedWithListboxLabel, assertListboxButtonLinkedWithListboxLabel,
assertListboxLabel,
assertListboxLabelLinkedWithListbox,
assertListboxOption, assertListboxOption,
assertNoActiveListboxOption, assertNoActiveListboxOption,
assertNoSelectedListboxOption, assertNoSelectedListboxOption,
@@ -45,6 +47,7 @@ import ManagedListbox from "./_ManagedListbox.svelte";
import Button from "$lib/internal/elements/Button.svelte"; import Button from "$lib/internal/elements/Button.svelte";
import Div from "$lib/internal/elements/Div.svelte"; import Div from "$lib/internal/elements/Div.svelte";
import Span from "$lib/internal/elements/Span.svelte"; import Span from "$lib/internal/elements/Span.svelte";
import svelte from "svelte-inline-compile";
let mockId = 0; let mockId = 0;
jest.mock('../../hooks/use-id', () => { jest.mock('../../hooks/use-id', () => {
@@ -103,41 +106,37 @@ describe('safeguards', () => {
describe('Rendering', () => { describe('Rendering', () => {
describe('Listbox', () => { describe('Listbox', () => {
// it( it(
// 'should be possible to render a Listbox using a render prop', 'should render a Listbox using slot props',
// suppressConsoleLogs(async () => { suppressConsoleLogs(async () => {
// render( render(svelte`
// <Listbox value={undefined} onChange={console.log}> <Listbox value={undefined} on:change={console.log} let:open>
// {({ open }) => ( <ListboxButton>Trigger</ListboxButton>
// <> {#if open}
// <ListboxButton>Trigger</ListboxButton> <ListboxOptions>
// {open && ( <ListboxOption value="a">Option A</ListboxOption>
// <ListboxOptions> <ListboxOption value="b">Option B</ListboxOption>
// <ListboxOption value="a">Option A</ListboxOption> <ListboxOption value="c">Option C</ListboxOption>
// <ListboxOption value="b">Option B</ListboxOption> </ListboxOptions>
// <ListboxOption value="c">Option C</ListboxOption> {/if}
// </ListboxOptions> </Listbox>
// )} `)
// </>
// )}
// </Listbox>
// )
// assertListboxButton({ assertListboxButton({
// state: ListboxState.InvisibleUnmounted, state: ListboxState.InvisibleUnmounted,
// attributes: { id: 'headlessui-listbox-button-1' }, attributes: { id: 'headlessui-listbox-button-1' },
// }) })
// assertListbox({ state: ListboxState.InvisibleUnmounted }) assertListbox({ state: ListboxState.InvisibleUnmounted })
// await click(getListboxButton()) await click(getListboxButton())
// assertListboxButton({ assertListboxButton({
// state: ListboxState.Visible, state: ListboxState.Visible,
// attributes: { id: 'headlessui-listbox-button-1' }, attributes: { id: 'headlessui-listbox-button-1' },
// }) })
// assertListbox({ state: ListboxState.Visible }) assertListbox({ state: ListboxState.Visible })
// }) })
// ) )
it( it(
'should be possible to disable a Listbox', 'should be possible to disable a Listbox',
@@ -182,142 +181,142 @@ describe('Rendering', () => {
}) })
describe('ListboxLabel', () => { describe('ListboxLabel', () => {
// it( it(
// 'should be possible to render a ListboxLabel using a render prop', 'should be possible to render a ListboxLabel using a render prop',
// suppressConsoleLogs(async () => { suppressConsoleLogs(async () => {
// render( render(svelte`
// <Listbox value={ undefined } onChange = { console.log } > <Listbox value={undefined} on:change={console.log}>
// <ListboxLabel>{ JSON.stringify } < /ListboxLabel> <ListboxLabel let:open let:disabled>{JSON.stringify({ open, disabled })}</ListboxLabel>
// < ListboxButton > Trigger < /ListboxButton> <ListboxButton>Trigger</ListboxButton>
// < ListboxOptions > <ListboxOptions>
// <ListboxOption value="a" > Option A < /ListboxOption> <ListboxOption value="a"> Option A </ListboxOption>
// < ListboxOption value = "b" > Option B < /ListboxOption> <ListboxOption value="b"> Option B </ListboxOption>
// < ListboxOption value = "c" > Option C < /ListboxOption> <ListboxOption value="c"> Option C </ListboxOption>
// < /ListboxOptions> </ListboxOptions>
// < /Listbox> </Listbox>
// ) `)
// assertListboxButton({ assertListboxButton({
// state: ListboxState.InvisibleUnmounted, state: ListboxState.InvisibleUnmounted,
// attributes: { id: 'headlessui-listbox-button-2' }, attributes: { id: 'headlessui-listbox-button-2' },
// }) })
// assertListboxLabel({ assertListboxLabel({
// attributes: { id: 'headlessui-listbox-label-1' }, attributes: { id: 'headlessui-listbox-label-1' },
// textContent: JSON.stringify({ open: false, disabled: false }), textContent: JSON.stringify({ open: false, disabled: false }),
// }) })
// assertListbox({ state: ListboxState.InvisibleUnmounted }) assertListbox({ state: ListboxState.InvisibleUnmounted })
// await click(getListboxButton()) await click(getListboxButton())
// assertListboxLabel({ assertListboxLabel({
// attributes: { id: 'headlessui-listbox-label-1' }, attributes: { id: 'headlessui-listbox-label-1' },
// textContent: JSON.stringify({ open: true, disabled: false }), textContent: JSON.stringify({ open: true, disabled: false }),
// }) })
// assertListbox({ state: ListboxState.Visible }) assertListbox({ state: ListboxState.Visible })
// assertListboxLabelLinkedWithListbox() assertListboxLabelLinkedWithListbox()
// assertListboxButtonLinkedWithListboxLabel() assertListboxButtonLinkedWithListboxLabel()
// }) })
// ) )
// it( it(
// 'should be possible to render a ListboxLabel using a render prop and an `as` prop', 'should be possible to render a ListboxLabel with slot props and an `as` prop',
// suppressConsoleLogs(async () => { suppressConsoleLogs(async () => {
// render( render(svelte`
// <Listbox value={ undefined } onChange = { console.log } > <Listbox value={undefined} on:change={console.log}>
// <ListboxLabel as="p" > { JSON.stringify } < /ListboxLabel> <ListboxLabel as="p" let:open let:disabled>{JSON.stringify({ open, disabled })}</ListboxLabel>
// < ListboxButton > Trigger < /ListboxButton> <ListboxButton>Trigger</ListboxButton>
// < ListboxOptions > <ListboxOptions>
// <ListboxOption value="a" > Option A < /ListboxOption> <ListboxOption value="a">Option A</ListboxOption>
// < ListboxOption value = "b" > Option B < /ListboxOption> <ListboxOption value="b">Option B</ListboxOption>
// < ListboxOption value = "c" > Option C < /ListboxOption> <ListboxOption value="c">Option C</ListboxOption>
// < /ListboxOptions> </ListboxOptions>
// < /Listbox> </Listbox>
// ) `)
// assertListboxLabel({ assertListboxLabel({
// attributes: { id: 'headlessui-listbox-label-1' }, attributes: { id: 'headlessui-listbox-label-1' },
// textContent: JSON.stringify({ open: false, disabled: false }), textContent: JSON.stringify({ open: false, disabled: false }),
// tag: 'p', tag: 'p',
// }) })
// assertListbox({ state: ListboxState.InvisibleUnmounted }) assertListbox({ state: ListboxState.InvisibleUnmounted })
// await click(getListboxButton()) await click(getListboxButton())
// assertListboxLabel({ assertListboxLabel({
// attributes: { id: 'headlessui-listbox-label-1' }, attributes: { id: 'headlessui-listbox-label-1' },
// textContent: JSON.stringify({ open: true, disabled: false }), textContent: JSON.stringify({ open: true, disabled: false }),
// tag: 'p', tag: 'p',
// }) })
// assertListbox({ state: ListboxState.Visible }) assertListbox({ state: ListboxState.Visible })
// }) })
// ) )
}); });
describe("ListboxButton", () => { describe("ListboxButton", () => {
// it( it(
// 'should be possible to render a ListboxButton using a render prop', 'should render a ListboxButton with slot props',
// suppressConsoleLogs(async () => { suppressConsoleLogs(async () => {
// render( render(svelte`
// <Listbox value={ undefined } onChange = { console.log } > <Listbox value={undefined} on:change={console.log}>
// <ListboxButton>{ JSON.stringify } < /ListboxButton> <ListboxButton let:open let:disabled>{JSON.stringify({ open, disabled})}</ListboxButton>
// < ListboxOptions > <ListboxOptions>
// <ListboxOption value="a" > Option A < /ListboxOption> <ListboxOption value="a">Option A </ListboxOption>
// < ListboxOption value = "b" > Option B < /ListboxOption> <ListboxOption value="b">Option B </ListboxOption>
// < ListboxOption value = "c" > Option C < /ListboxOption> <ListboxOption value="c">Option C </ListboxOption>
// < /ListboxOptions> </ListboxOptions>
// < /Listbox> </Listbox>
// ) `)
// assertListboxButton({ assertListboxButton({
// state: ListboxState.InvisibleUnmounted, state: ListboxState.InvisibleUnmounted,
// attributes: { id: 'headlessui-listbox-button-1' }, attributes: { id: 'headlessui-listbox-button-1' },
// textContent: JSON.stringify({ open: false, disabled: false }), textContent: JSON.stringify({ open: false, disabled: false }),
// }) })
// assertListbox({ state: ListboxState.InvisibleUnmounted }) assertListbox({ state: ListboxState.InvisibleUnmounted })
// await click(getListboxButton()) await click(getListboxButton())
// assertListboxButton({ assertListboxButton({
// state: ListboxState.Visible, state: ListboxState.Visible,
// attributes: { id: 'headlessui-listbox-button-1' }, attributes: { id: 'headlessui-listbox-button-1' },
// textContent: JSON.stringify({ open: true, disabled: false }), textContent: JSON.stringify({ open: true, disabled: false }),
// }) })
// assertListbox({ state: ListboxState.Visible }) assertListbox({ state: ListboxState.Visible })
// }) })
// ) )
// it( it(
// 'should be possible to render a ListboxButton using a render prop and an `as` prop', 'should be possible to render a ListboxButton using a render prop and an `as` prop',
// suppressConsoleLogs(async () => { suppressConsoleLogs(async () => {
// render( render(svelte`
// <Listbox value={ undefined } onChange = { console.log } > <Listbox value={undefined} onChange={console.log}>
// <ListboxButton as="div" role = "button" > <ListboxButton as="div" role="button" let:open let:disabled>
// { JSON.stringify } {JSON.stringify({ open, disabled })}
// < /ListboxButton> </ListboxButton>
// < ListboxOptions > <ListboxOptions>
// <ListboxOption value="a" > Option A < /ListboxOption> <ListboxOption value="a">Option A</ListboxOption>
// < ListboxOption value = "b" > Option B < /ListboxOption> <ListboxOption value="b">Option B</ListboxOption>
// < ListboxOption value = "c" > Option C < /ListboxOption> <ListboxOption value="c">Option C</ListboxOption>
// < /ListboxOptions> </ListboxOptions>
// < /Listbox> </Listbox>
// ) `)
// assertListboxButton({ assertListboxButton({
// state: ListboxState.InvisibleUnmounted, state: ListboxState.InvisibleUnmounted,
// attributes: { id: 'headlessui-listbox-button-1' }, attributes: { id: 'headlessui-listbox-button-1' },
// textContent: JSON.stringify({ open: false, disabled: false }), textContent: JSON.stringify({ open: false, disabled: false }),
// }) })
// assertListbox({ state: ListboxState.InvisibleUnmounted }) assertListbox({ state: ListboxState.InvisibleUnmounted })
// await click(getListboxButton()) await click(getListboxButton())
// assertListboxButton({ assertListboxButton({
// state: ListboxState.Visible, state: ListboxState.Visible,
// attributes: { id: 'headlessui-listbox-button-1' }, attributes: { id: 'headlessui-listbox-button-1' },
// textContent: JSON.stringify({ open: true, disabled: false }), textContent: JSON.stringify({ open: true, disabled: false }),
// }) })
// assertListbox({ state: ListboxState.Visible }) assertListbox({ state: ListboxState.Visible })
// }) })
// ) )
it( it(
'should be possible to render a ListboxButton and a ListboxLabel and see them linked together', 'should be possible to render a ListboxButton and a ListboxLabel and see them linked together',
@@ -393,41 +392,37 @@ describe('Rendering', () => {
}) })
describe('ListboxOptions', () => { describe('ListboxOptions', () => {
// it( it(
// 'should be possible to render ListboxOptions using a render prop', 'should render ListboxOptions with slot props',
// suppressConsoleLogs(async () => { suppressConsoleLogs(async () => {
// render( render(svelte`
// <Listbox value={undefined} onChange={console.log}> <Listbox value={undefined} on:change={console.log}>
// <ListboxButton>Trigger</ListboxButton> <ListboxButton>Trigger</ListboxButton>
// <ListboxOptions> <ListboxOptions let:open>
// {data => ( <ListboxOption value="a">{JSON.stringify({ open })}</ListboxOption>
// <> </ListboxOptions>
// <ListboxOption value="a">{JSON.stringify(data)}</ListboxOption> </Listbox>
// </> `)
// )}
// </ListboxOptions>
// </Listbox>
// )
// assertListboxButton({ assertListboxButton({
// state: ListboxState.InvisibleUnmounted, state: ListboxState.InvisibleUnmounted,
// attributes: { id: 'headlessui-listbox-button-1' }, attributes: { id: 'headlessui-listbox-button-1' },
// }) })
// assertListbox({ state: ListboxState.InvisibleUnmounted }) assertListbox({ state: ListboxState.InvisibleUnmounted })
// await click(getListboxButton()) await click(getListboxButton())
// assertListboxButton({ assertListboxButton({
// state: ListboxState.Visible, state: ListboxState.Visible,
// attributes: { id: 'headlessui-listbox-button-1' }, attributes: { id: 'headlessui-listbox-button-1' },
// }) })
// assertListbox({ assertListbox({
// state: ListboxState.Visible, state: ListboxState.Visible,
// textContent: JSON.stringify({ open: true }), textContent: JSON.stringify({ open: true }),
// }) })
// assertActiveElement(getListbox()) assertActiveElement(getListbox())
// }) })
// ) )
it('should be possible to always render the ListboxOptions if we provide it a `static` prop', () => { it('should be possible to always render the ListboxOptions if we provide it a `static` prop', () => {
render( render(
@@ -472,38 +467,40 @@ describe('Rendering', () => {
}) })
}) })
// describe('ListboxOption', () => { describe('ListboxOption', () => {
// it( it(
// 'should be possible to render a ListboxOption using a render prop', 'should render a ListboxOption with slot props',
// suppressConsoleLogs(async () => { suppressConsoleLogs(async () => {
// render( render(svelte`
// <Listbox value={undefined} onChange={console.log}> <Listbox value={undefined} on:change={console.log}>
// <ListboxButton>Trigger</ListboxButton> <ListboxButton>Trigger</ListboxButton>
// <ListboxOptions> <ListboxOptions>
// <ListboxOption value="a">{JSON.stringify}</ListboxOption> <ListboxOption value="a" let:active let:selected let:disabled>
// </ListboxOptions> {JSON.stringify({ active, selected, disabled })}
// </Listbox> </ListboxOption>
// ) </ListboxOptions>
</Listbox>
`)
// assertListboxButton({ assertListboxButton({
// state: ListboxState.InvisibleUnmounted, state: ListboxState.InvisibleUnmounted,
// attributes: { id: 'headlessui-listbox-button-1' }, attributes: { id: 'headlessui-listbox-button-1' },
// }) })
// assertListbox({ state: ListboxState.InvisibleUnmounted }) assertListbox({ state: ListboxState.InvisibleUnmounted })
// await click(getListboxButton()) await click(getListboxButton())
// assertListboxButton({ assertListboxButton({
// state: ListboxState.Visible, state: ListboxState.Visible,
// attributes: { id: 'headlessui-listbox-button-1' }, attributes: { id: 'headlessui-listbox-button-1' },
// }) })
// assertListbox({ assertListbox({
// state: ListboxState.Visible, state: ListboxState.Visible,
// textContent: JSON.stringify({ active: false, selected: false, disabled: false }), textContent: JSON.stringify({ active: false, selected: false, disabled: false }),
// }) })
// }) })
// ) )
// }) })
}) })
describe('Rendering composition', () => { describe('Rendering composition', () => {

View File

@@ -10,6 +10,7 @@ import Button from "$lib/internal/elements/Button.svelte";
import Div from "$lib/internal/elements/Div.svelte"; import Div from "$lib/internal/elements/Div.svelte";
import Form from "$lib/internal/elements/Form.svelte"; import Form from "$lib/internal/elements/Form.svelte";
import Span from "$lib/internal/elements/Span.svelte"; import Span from "$lib/internal/elements/Span.svelte";
import svelte from "svelte-inline-compile";
let mockId = 0; let mockId = 0;
jest.mock('../../hooks/use-id', () => { jest.mock('../../hooks/use-id', () => {
@@ -66,110 +67,106 @@ describe('Safe guards', () => {
}) })
describe('Rendering', () => { describe('Rendering', () => {
// describe('Menu', () => { describe('Menu', () => {
// it( it(
// 'should be possible to render a Menu using a render prop', 'Menu should have slot props',
// suppressConsoleLogs(async () => { suppressConsoleLogs(async () => {
// render( render(svelte`
// <Menu> <Menu let:open>
// {({ open }) => ( <MenuButton>Trigger</MenuButton>
// <> {#if open}
// <Menu.Button>Trigger</Menu.Button> <MenuItems>
// {open && ( <MenuItem as="a">Item A</MenuItem>
// <Menu.Items> <MenuItem as="a">Item B</MenuItem>
// <Menu.Item as="a">Item A</Menu.Item> <MenuItem as="a">Item C</MenuItem>
// <Menu.Item as="a">Item B</Menu.Item> </MenuItems>
// <Menu.Item as="a">Item C</Menu.Item> {/if}
// </Menu.Items> </Menu>
// )} `)
// </>
// )}
// </Menu>
// )
// assertMenuButton({ assertMenuButton({
// state: MenuState.InvisibleUnmounted, state: MenuState.InvisibleUnmounted,
// attributes: { id: 'headlessui-menu-button-1' }, attributes: { id: 'headlessui-menu-button-1' },
// }) })
// assertMenu({ state: MenuState.InvisibleUnmounted }) assertMenu({ state: MenuState.InvisibleUnmounted })
// await click(getMenuButton()) await click(getMenuButton())
// assertMenuButton({ assertMenuButton({
// state: MenuState.Visible, state: MenuState.Visible,
// attributes: { id: 'headlessui-menu-button-1' }, attributes: { id: 'headlessui-menu-button-1' },
// }) })
// assertMenu({ state: MenuState.Visible }) assertMenu({ state: MenuState.Visible })
// }) })
// ) )
// }) })
describe('Menu.Button', () => { describe('MenuButton', () => {
// it( it(
// 'should be possible to render a Menu.Button using a render prop', 'MenuButton should have slot props',
// suppressConsoleLogs(async () => { suppressConsoleLogs(async () => {
// render( render(svelte`
// <Menu> <Menu>
// <Menu.Button>{JSON.stringify}</Menu.Button> <MenuButton let:open>{open}</MenuButton>
// <Menu.Items> <MenuItems>
// <Menu.Item as="a">Item A</Menu.Item> <MenuItem as="a">Item A</MenuItem>
// <Menu.Item as="a">Item B</Menu.Item> <MenuItem as="a">Item B</MenuItem>
// <Menu.Item as="a">Item C</Menu.Item> <MenuItem as="a">Item C</MenuItem>
// </Menu.Items> </MenuItems>
// </Menu> </Menu>
// ) `)
// assertMenuButton({ assertMenuButton({
// state: MenuState.InvisibleUnmounted, state: MenuState.InvisibleUnmounted,
// attributes: { id: 'headlessui-menu-button-1' }, attributes: { id: 'headlessui-menu-button-1' },
// textContent: JSON.stringify({ open: false }), textContent: "false",
// }) })
// assertMenu({ state: MenuState.InvisibleUnmounted }) assertMenu({ state: MenuState.InvisibleUnmounted })
// await click(getMenuButton()) await click(getMenuButton())
// assertMenuButton({ assertMenuButton({
// state: MenuState.Visible, state: MenuState.Visible,
// attributes: { id: 'headlessui-menu-button-1' }, attributes: { id: 'headlessui-menu-button-1' },
// textContent: JSON.stringify({ open: true }), textContent: "true",
// }) })
// assertMenu({ state: MenuState.Visible }) assertMenu({ state: MenuState.Visible })
// }) })
// ) )
// it( it(
// 'should be possible to render a Menu.Button using a render prop and an `as` prop', 'MenuButton should have slot props and support an `as` prop',
// suppressConsoleLogs(async () => { suppressConsoleLogs(async () => {
// render( render(svelte`
// <Menu> <Menu>
// <Menu.Button as="div" role="button"> <MenuButton as="div" role="button" let:open>
// {JSON.stringify} {open}
// </Menu.Button> </MenuButton>
// <Menu.Items> <MenuItems>
// <Menu.Item as="a">Item A</Menu.Item> <MenuItem as="a">Item A</MenuItem>
// <Menu.Item as="a">Item B</Menu.Item> <MenuItem as="a">Item B</MenuItem>
// <Menu.Item as="a">Item C</Menu.Item> <MenuItem as="a">Item C</MenuItem>
// </Menu.Items> </MenuItems>
// </Menu> </Menu>
// ) `)
// assertMenuButton({ assertMenuButton({
// state: MenuState.InvisibleUnmounted, state: MenuState.InvisibleUnmounted,
// attributes: { id: 'headlessui-menu-button-1' }, attributes: { id: 'headlessui-menu-button-1' },
// textContent: JSON.stringify({ open: false }), textContent: "false",
// }) })
// assertMenu({ state: MenuState.InvisibleUnmounted }) assertMenu({ state: MenuState.InvisibleUnmounted })
// await click(getMenuButton()) await click(getMenuButton())
// assertMenuButton({ assertMenuButton({
// state: MenuState.Visible, state: MenuState.Visible,
// attributes: { id: 'headlessui-menu-button-1' }, attributes: { id: 'headlessui-menu-button-1' },
// textContent: JSON.stringify({ open: true }), textContent: "true",
// }) })
// assertMenu({ state: MenuState.Visible }) assertMenu({ state: MenuState.Visible })
// }) })
// ) )
describe('`type` attribute', () => { describe('`type` attribute', () => {
it('should set the `type` to "button" by default', async () => { it('should set the `type` to "button" by default', async () => {
@@ -214,43 +211,39 @@ describe('Rendering', () => {
}) })
}) })
describe('Menu.Items', () => { describe('MenuItems', () => {
// it( it(
// 'should be possible to render Menu.Items using a render prop', 'MenuItems should have slot props',
// suppressConsoleLogs(async () => { suppressConsoleLogs(async () => {
// render( render(svelte`
// <Menu> <Menu>
// <Menu.Button>Trigger</Menu.Button> <MenuButton>Trigger</MenuButton>
// <Menu.Items> <MenuItems let:open>
// {data => ( <MenuItem as="a">{open}</MenuItem>
// <> </MenuItems>
// <Menu.Item as="a">{JSON.stringify(data)}</Menu.Item> </Menu>
// </> `)
// )}
// </Menu.Items>
// </Menu>
// )
// assertMenuButton({ assertMenuButton({
// state: MenuState.InvisibleUnmounted, state: MenuState.InvisibleUnmounted,
// attributes: { id: 'headlessui-menu-button-1' }, attributes: { id: 'headlessui-menu-button-1' },
// }) })
// assertMenu({ state: MenuState.InvisibleUnmounted }) assertMenu({ state: MenuState.InvisibleUnmounted })
// await click(getMenuButton()) await click(getMenuButton())
// assertMenuButton({ assertMenuButton({
// state: MenuState.Visible, state: MenuState.Visible,
// attributes: { id: 'headlessui-menu-button-1' }, attributes: { id: 'headlessui-menu-button-1' },
// }) })
// assertMenu({ assertMenu({
// state: MenuState.Visible, state: MenuState.Visible,
// textContent: JSON.stringify({ open: true }), textContent: "true",
// }) })
// }) })
// ) )
it('should be possible to always render the Menu.Items if we provide it a `static` prop', () => { it('should be possible to always render the MenuItems if we provide it a `static` prop', () => {
render( render(
TestRenderer, { TestRenderer, {
allProps: [ allProps: [
@@ -269,7 +262,7 @@ describe('Rendering', () => {
expect(getMenu()).not.toBe(null) expect(getMenu()).not.toBe(null)
}) })
it('should be possible to use a different render strategy for the Menu.Items', async () => { it('should be possible to use a different render strategy for the MenuItems', async () => {
render( render(
TestRenderer, { TestRenderer, {
allProps: [ allProps: [
@@ -293,38 +286,38 @@ describe('Rendering', () => {
}) })
}) })
// describe('Menu.Item', () => { describe('MenuItem', () => {
// it( it(
// 'should be possible to render a Menu.Item using a render prop', 'MenuItem should have slot props',
// suppressConsoleLogs(async () => { suppressConsoleLogs(async () => {
// render( render(svelte`
// <Menu> <Menu>
// <Menu.Button>Trigger</Menu.Button> <MenuButton>Trigger</MenuButton>
// <Menu.Items> <MenuItems>
// <Menu.Item as="a">{JSON.stringify}</Menu.Item> <MenuItem as="a" let:active let:disabled>{JSON.stringify({ active, disabled })}</MenuItem>
// </Menu.Items> </MenuItems>
// </Menu> </Menu>
// ) `)
// assertMenuButton({ assertMenuButton({
// state: MenuState.InvisibleUnmounted, state: MenuState.InvisibleUnmounted,
// attributes: { id: 'headlessui-menu-button-1' }, attributes: { id: 'headlessui-menu-button-1' },
// }) })
// assertMenu({ state: MenuState.InvisibleUnmounted }) assertMenu({ state: MenuState.InvisibleUnmounted })
// await click(getMenuButton()) await click(getMenuButton())
// assertMenuButton({ assertMenuButton({
// state: MenuState.Visible, state: MenuState.Visible,
// attributes: { id: 'headlessui-menu-button-1' }, attributes: { id: 'headlessui-menu-button-1' },
// }) })
// assertMenu({ assertMenu({
// state: MenuState.Visible, state: MenuState.Visible,
// textContent: JSON.stringify({ active: false, disabled: false }), textContent: JSON.stringify({ active: false, disabled: false }),
// }) })
// }) })
// ) )
// }) })
}) })
describe('Rendering composition', () => { describe('Rendering composition', () => {
@@ -421,7 +414,7 @@ describe('Rendering composition', () => {
) )
it( it(
'should mark all the elements between Menu.Items and Menu.Item with role none', 'should mark all the elements between MenuItems and MenuItem with role none',
suppressConsoleLogs(async () => { suppressConsoleLogs(async () => {
render render
render( render(
@@ -472,7 +465,7 @@ describe('Rendering composition', () => {
describe('Composition', () => { describe('Composition', () => {
it.skip( it.skip(
'should be possible to wrap the Menu.Items with a Transition component', 'should be possible to wrap the MenuItems with a Transition component',
suppressConsoleLogs(async () => { suppressConsoleLogs(async () => {
let orderFn = jest.fn() let orderFn = jest.fn()
render( render(
@@ -525,7 +518,7 @@ describe('Composition', () => {
) )
it.skip( it.skip(
'should be possible to wrap the Menu.Items with a Transition.Child component', 'should be possible to wrap the MenuItems with a Transition.Child component',
suppressConsoleLogs(async () => { suppressConsoleLogs(async () => {
let orderFn = jest.fn() let orderFn = jest.fn()
render( render(

View File

@@ -10,6 +10,7 @@ import Span from "$lib/internal/elements/Span.svelte";
import { Transition, TransitionChild } from "$lib/components/transitions"; import { Transition, TransitionChild } from "$lib/components/transitions";
import TransitionDebug from "$lib/components/disclosure/_TransitionDebug.svelte"; import TransitionDebug from "$lib/components/disclosure/_TransitionDebug.svelte";
import Portal from "$lib/components/portal/Portal.svelte"; import Portal from "$lib/components/portal/Portal.svelte";
import svelte from "svelte-inline-compile";
let mockId = 0; let mockId = 0;
jest.mock('../../hooks/use-id', () => { jest.mock('../../hooks/use-id', () => {
@@ -119,216 +120,158 @@ describe('Rendering', () => {
}) })
describe('Popover', () => { describe('Popover', () => {
// it( it(
// 'should be possible to render a Popover using a render prop', 'should render a Popover with slot props',
// suppressConsoleLogs(async () => { suppressConsoleLogs(async () => {
// render( render(svelte`
// <Popover> <Popover let:open>
// {({ open }) => ( <PopoverButton>Trigger</PopoverButton>
// <> <PopoverPanel>Panel is: {open ? 'open' : 'closed'}</PopoverPanel>
// <Popover.Button>Trigger</Popover.Button> </Popover>
// <Popover.Panel>Panel is: {open ? 'open' : 'closed'}</Popover.Panel> `)
// </>
// )}
// </Popover>
// )
// assertPopoverButton({ assertPopoverButton({
// state: PopoverState.InvisibleUnmounted, state: PopoverState.InvisibleUnmounted,
// attributes: { id: 'headlessui-popover-button-1' }, attributes: { id: 'headlessui-popover-button-1' },
// }) })
// assertPopoverPanel({ state: PopoverState.InvisibleUnmounted }) assertPopoverPanel({ state: PopoverState.InvisibleUnmounted })
// await click(getPopoverButton()) await click(getPopoverButton())
// assertPopoverButton({ assertPopoverButton({
// state: PopoverState.Visible, state: PopoverState.Visible,
// attributes: { id: 'headlessui-popover-button-1' }, attributes: { id: 'headlessui-popover-button-1' },
// }) })
// assertPopoverPanel({ state: PopoverState.Visible, textContent: 'Panel is: open' }) assertPopoverPanel({ state: PopoverState.Visible, textContent: 'Panel is: open' })
// }) })
// ) )
// it( it(
// 'should expose a close function that closes the popover', 'should expose a close function that closes the popover',
// suppressConsoleLogs(async () => { suppressConsoleLogs(async () => {
// render( render(svelte`
// <Popover> <Popover let:close>
// {({ close }) => ( <PopoverButton>Trigger</PopoverButton>
// <> <PopoverPanel>
// <Popover.Button>Trigger</Popover.Button> <button on:click={() => close()}>Close me</button>
// <Popover.Panel> </PopoverPanel>
// <button onClick={() => close()}>Close me</button> </Popover>
// </Popover.Panel> `)
// </>
// )}
// </Popover>
// )
// // Focus the button // Focus the button
// getPopoverButton()?.focus() getPopoverButton()?.focus()
// // Ensure the button is focused // Ensure the button is focused
// assertActiveElement(getPopoverButton()) assertActiveElement(getPopoverButton())
// // Open the popover // Open the popover
// await click(getPopoverButton()) await click(getPopoverButton())
// // Ensure we can click the close button // Ensure we can click the close button
// await click(getByText('Close me')) await click(getByText('Close me'))
// // Ensure the popover is closed // Ensure the popover is closed
// assertPopoverPanel({ state: PopoverState.InvisibleUnmounted }) assertPopoverPanel({ state: PopoverState.InvisibleUnmounted })
// // Ensure the Popover.Button got the restored focus // Ensure the PopoverButton got the restored focus
// assertActiveElement(getByText('Trigger')) assertActiveElement(getByText('Trigger'))
// }) })
// ) )
// it( it(
// 'should expose a close function that closes the popover and restores to a specific element', 'should expose a close function that closes the popover and restores to a specific element',
// suppressConsoleLogs(async () => { suppressConsoleLogs(async () => {
// render( render(svelte`
// <> <button id="test">restoreable</button>
// <button id="test">restoreable</button> <Popover let:close>
// <Popover> <PopoverButton>Trigger</PopoverButton>
// {({ close }) => ( <PopoverPanel>
// <> <button on:click={() => close(document.getElementById('test'))}>
// <Popover.Button>Trigger</Popover.Button> Close me
// <Popover.Panel> </button>
// <button onClick={() => close(document.getElementById('test')!)}> </PopoverPanel>
// Close me </Popover>
// </button> `)
// </Popover.Panel>
// </>
// )}
// </Popover>
// </>
// )
// // Focus the button // Focus the button
// getPopoverButton()?.focus() getPopoverButton()?.focus()
// // Ensure the button is focused // Ensure the button is focused
// assertActiveElement(getPopoverButton()) assertActiveElement(getPopoverButton())
// // Open the popover // Open the popover
// await click(getPopoverButton()) await click(getPopoverButton())
// // Ensure we can click the close button // Ensure we can click the close button
// await click(getByText('Close me')) await click(getByText('Close me'))
// // Ensure the popover is closed // Ensure the popover is closed
// assertPopoverPanel({ state: PopoverState.InvisibleUnmounted }) assertPopoverPanel({ state: PopoverState.InvisibleUnmounted })
// // Ensure the restoreable button got the restored focus // Ensure the restoreable button got the restored focus
// assertActiveElement(getByText('restoreable')) assertActiveElement(getByText('restoreable'))
// }) })
// ) )
// it(
// 'should expose a close function that closes the popover and restores to a ref',
// suppressConsoleLogs(async () => {
// function Example() {
// let elementRef = useRef(null)
// return (
// <>
// <button ref={elementRef}>restoreable</button>
// <Popover>
// {({ close }) => (
// <>
// <Popover.Button>Trigger</Popover.Button>
// <Popover.Panel>
// <button onClick={() => close(elementRef)}>Close me</button>
// </Popover.Panel>
// </>
// )}
// </Popover>
// </>
// )
// }
// render(<Example />)
// // Focus the button
// getPopoverButton()?.focus()
// // Ensure the button is focused
// assertActiveElement(getPopoverButton())
// // Open the popover
// await click(getPopoverButton())
// // Ensure we can click the close button
// await click(getByText('Close me'))
// // Ensure the popover is closed
// assertPopoverPanel({ state: PopoverState.InvisibleUnmounted })
// // Ensure the restoreable button got the restored focus
// assertActiveElement(getByText('restoreable'))
// })
// )
}) })
describe('Popover.Button', () => { describe('PopoverButton', () => {
// it( it(
// 'should be possible to render a Popover.Button using a render prop', 'should render a PopoverButton with slot props',
// suppressConsoleLogs(async () => { suppressConsoleLogs(async () => {
// render( render(svelte`
// <Popover> <Popover>
// <Popover.Button>{JSON.stringify}</Popover.Button> <PopoverButton let:open>{JSON.stringify({open})}</PopoverButton>
// <Popover.Panel></Popover.Panel> <PopoverPanel></PopoverPanel>
// </Popover> </Popover>
// ) `)
// assertPopoverButton({ assertPopoverButton({
// state: PopoverState.InvisibleUnmounted, state: PopoverState.InvisibleUnmounted,
// attributes: { id: 'headlessui-popover-button-1' }, attributes: { id: 'headlessui-popover-button-1' },
// textContent: JSON.stringify({ open: false }), textContent: JSON.stringify({ open: false }),
// }) })
// assertPopoverPanel({ state: PopoverState.InvisibleUnmounted }) assertPopoverPanel({ state: PopoverState.InvisibleUnmounted })
// await click(getPopoverButton()) await click(getPopoverButton())
// assertPopoverButton({ assertPopoverButton({
// state: PopoverState.Visible, state: PopoverState.Visible,
// attributes: { id: 'headlessui-popover-button-1' }, attributes: { id: 'headlessui-popover-button-1' },
// textContent: JSON.stringify({ open: true }), textContent: JSON.stringify({ open: true }),
// }) })
// assertPopoverPanel({ state: PopoverState.Visible }) assertPopoverPanel({ state: PopoverState.Visible })
// }) })
// ) )
// it( it(
// 'should be possible to render a Popover.Button using a render prop and an `as` prop', 'should render a PopoverButton with a slot prop and use an `as` prop',
// suppressConsoleLogs(async () => { suppressConsoleLogs(async () => {
// render( render(svelte`
// <Popover> <Popover>
// <Popover.Button as="div" role="button"> <PopoverButton as="div" role="button" let:open>
// {JSON.stringify} {JSON.stringify({ open })}
// </Popover.Button> </PopoverButton>
// <Popover.Panel /> <PopoverPanel />
// </Popover> </Popover>
// ) `)
// assertPopoverButton({ assertPopoverButton({
// state: PopoverState.InvisibleUnmounted, state: PopoverState.InvisibleUnmounted,
// attributes: { id: 'headlessui-popover-button-1' }, attributes: { id: 'headlessui-popover-button-1' },
// textContent: JSON.stringify({ open: false }), textContent: JSON.stringify({ open: false }),
// }) })
// assertPopoverPanel({ state: PopoverState.InvisibleUnmounted }) assertPopoverPanel({ state: PopoverState.InvisibleUnmounted })
// await click(getPopoverButton()) await click(getPopoverButton())
// assertPopoverButton({ assertPopoverButton({
// state: PopoverState.Visible, state: PopoverState.Visible,
// attributes: { id: 'headlessui-popover-button-1' }, attributes: { id: 'headlessui-popover-button-1' },
// textContent: JSON.stringify({ open: true }), textContent: JSON.stringify({ open: true }),
// }) })
// assertPopoverPanel({ state: PopoverState.Visible }) assertPopoverPanel({ state: PopoverState.Visible })
// }) })
// ) )
describe('`type` attribute', () => { describe('`type` attribute', () => {
it('should set the `type` to "button" by default', async () => { it('should set the `type` to "button" by default', async () => {
@@ -370,37 +313,37 @@ describe('Rendering', () => {
}) })
}) })
describe('Popover.Panel', () => { describe('PopoverPanel', () => {
// it( it(
// 'should be possible to render Popover.Panel using a render prop', 'should render PopoverPanel with slot props',
// suppressConsoleLogs(async () => { suppressConsoleLogs(async () => {
// render( render(svelte`
// <Popover> <Popover>
// <Popover.Button>Trigger</Popover.Button> <PopoverButton>Trigger</PopoverButton>
// <Popover.Panel>{JSON.stringify}</Popover.Panel> <PopoverPanel let:open>{JSON.stringify({ open })}</PopoverPanel>
// </Popover> </Popover>
// ) `)
// assertPopoverButton({ assertPopoverButton({
// state: PopoverState.InvisibleUnmounted, state: PopoverState.InvisibleUnmounted,
// attributes: { id: 'headlessui-popover-button-1' }, attributes: { id: 'headlessui-popover-button-1' },
// }) })
// assertPopoverPanel({ state: PopoverState.InvisibleUnmounted }) assertPopoverPanel({ state: PopoverState.InvisibleUnmounted })
// await click(getPopoverButton()) await click(getPopoverButton())
// assertPopoverButton({ assertPopoverButton({
// state: PopoverState.Visible, state: PopoverState.Visible,
// attributes: { id: 'headlessui-popover-button-1' }, attributes: { id: 'headlessui-popover-button-1' },
// }) })
// assertPopoverPanel({ assertPopoverPanel({
// state: PopoverState.Visible, state: PopoverState.Visible,
// textContent: JSON.stringify({ open: true }), textContent: JSON.stringify({ open: true }),
// }) })
// }) })
// ) )
it('should be possible to always render the Popover.Panel if we provide it a `static` prop', () => { it('should be possible to always render the PopoverPanel if we provide it a `static` prop', () => {
render( render(
TestRenderer, { TestRenderer, {
allProps: [ allProps: [
@@ -415,7 +358,7 @@ describe('Rendering', () => {
expect(getPopoverPanel()).not.toBe(null) expect(getPopoverPanel()).not.toBe(null)
}) })
it('should be possible to use a different render strategy for the Popover.Panel', async () => { it('should be possible to use a different render strategy for the PopoverPanel', async () => {
render( render(
TestRenderer, { TestRenderer, {
allProps: [ allProps: [
@@ -477,7 +420,7 @@ describe('Rendering', () => {
// TODO: This test doesn't work but I'm also not totally sure it should... // TODO: This test doesn't work but I'm also not totally sure it should...
// calling element.focus in the browser doesn't seem to call the window focus handler // calling element.focus in the browser doesn't seem to call the window focus handler
it.skip( it.skip(
'should close the Popover, when Popover.Panel has the focus prop and you focus the open button', 'should close the Popover, when PopoverPanel has the focus prop and you focus the open button',
suppressConsoleLogs(async () => { suppressConsoleLogs(async () => {
render( render(
TestRenderer, { TestRenderer, {
@@ -573,120 +516,76 @@ describe('Rendering', () => {
}) })
) )
// it( it(
// 'should expose a close function that closes the popover', 'should expose a close function that closes the popover',
// suppressConsoleLogs(async () => { suppressConsoleLogs(async () => {
// render( render(svelte`
// <Popover> <Popover>
// <Popover.Button>Trigger</Popover.Button> <PopoverButton>Trigger</PopoverButton>
// <Popover.Panel> <PopoverPanel let:close>
// {({ close }) => <button onClick={() => close()}>Close me</button>} <button on:click={() => close()}>Close me</button>
// </Popover.Panel> </PopoverPanel>
// </Popover> </Popover>
// ) `)
// // Focus the button // Focus the button
// getPopoverButton()?.focus() getPopoverButton()?.focus()
// // Ensure the button is focused // Ensure the button is focused
// assertActiveElement(getPopoverButton()) assertActiveElement(getPopoverButton())
// // Open the popover // Open the popover
// await click(getPopoverButton()) await click(getPopoverButton())
// // Ensure we can click the close button // Ensure we can click the close button
// await click(getByText('Close me')) await click(getByText('Close me'))
// // Ensure the popover is closed // Ensure the popover is closed
// assertPopoverPanel({ state: PopoverState.InvisibleUnmounted }) assertPopoverPanel({ state: PopoverState.InvisibleUnmounted })
// // Ensure the Popover.Button got the restored focus // Ensure the PopoverButton got the restored focus
// assertActiveElement(getByText('Trigger')) assertActiveElement(getByText('Trigger'))
// }) })
// ) )
// it( it(
// 'should expose a close function that closes the popover and restores to a specific element', 'should expose a close function that closes the popover and restores to a specific element',
// suppressConsoleLogs(async () => { suppressConsoleLogs(async () => {
// render( render(svelte`
// <> <button id="test">restoreable</button>
// <button id="test">restoreable</button> <Popover>
// <Popover> <PopoverButton>Trigger</PopoverButton>
// <Popover.Button>Trigger</Popover.Button> <PopoverPanel let:close>
// <Popover.Panel> <button on:click={() => close(document.getElementById('test'))}>Close me</button>
// {({ close }) => ( </PopoverPanel>
// <button onClick={() => close(document.getElementById('test')!)}>Close me</button> </Popover>
// )} `)
// </Popover.Panel>
// </Popover>
// </>
// )
// // Focus the button // Focus the button
// getPopoverButton()?.focus() getPopoverButton()?.focus()
// // Ensure the button is focused // Ensure the button is focused
// assertActiveElement(getPopoverButton()) assertActiveElement(getPopoverButton())
// // Open the popover // Open the popover
// await click(getPopoverButton()) await click(getPopoverButton())
// // Ensure we can click the close button // Ensure we can click the close button
// await click(getByText('Close me')) await click(getByText('Close me'))
// // Ensure the popover is closed // Ensure the popover is closed
// assertPopoverPanel({ state: PopoverState.InvisibleUnmounted }) assertPopoverPanel({ state: PopoverState.InvisibleUnmounted })
// // Ensure the restoreable button got the restored focus // Ensure the restoreable button got the restored focus
// assertActiveElement(getByText('restoreable')) assertActiveElement(getByText('restoreable'))
// }) })
// ) )
// it(
// 'should expose a close function that closes the popover and restores to a ref',
// suppressConsoleLogs(async () => {
// function Example() {
// let elementRef = useRef(null)
// return (
// <>
// <button ref={elementRef}>restoreable</button>
// <Popover>
// <Popover.Button>Trigger</Popover.Button>
// <Popover.Panel>
// {({ close }) => <button onClick={() => close(elementRef)}>Close me</button>}
// </Popover.Panel>
// </Popover>
// </>
// )
// }
// render(<Example />)
// // Focus the button
// getPopoverButton()?.focus()
// // Ensure the button is focused
// assertActiveElement(getPopoverButton())
// // Open the popover
// await click(getPopoverButton())
// // Ensure we can click the close button
// await click(getByText('Close me'))
// // Ensure the popover is closed
// assertPopoverPanel({ state: PopoverState.InvisibleUnmounted })
// // Ensure the restoreable button got the restored focus
// assertActiveElement(getByText('restoreable'))
// })
// )
}) })
}) })
describe('Composition', () => { describe('Composition', () => {
it( it(
'should be possible to wrap the Popover.Panel with a Transition component', 'should be possible to wrap the PopoverPanel with a Transition component',
suppressConsoleLogs(async () => { suppressConsoleLogs(async () => {
let orderFn = jest.fn() let orderFn = jest.fn()
render( render(
@@ -889,7 +788,7 @@ describe('Keyboard interactions', () => {
) )
it( it(
'should close the Popover by pressing `Enter` on a Popover.Button inside a Popover.Panel', 'should close the Popover by pressing `Enter` on a PopoverButton inside a PopoverPanel',
suppressConsoleLogs(async () => { suppressConsoleLogs(async () => {
render( render(
TestRenderer, { TestRenderer, {
@@ -926,7 +825,7 @@ describe('Keyboard interactions', () => {
describe('`Escape` key', () => { describe('`Escape` key', () => {
it( it(
'should close the Popover menu, when pressing escape on the Popover.Button', 'should close the Popover menu, when pressing escape on the PopoverButton',
suppressConsoleLogs(async () => { suppressConsoleLogs(async () => {
render( render(
TestRenderer, { TestRenderer, {
@@ -962,7 +861,7 @@ describe('Keyboard interactions', () => {
) )
it( it(
'should close the Popover menu, when pressing escape on the Popover.Panel', 'should close the Popover menu, when pressing escape on the PopoverPanel',
suppressConsoleLogs(async () => { suppressConsoleLogs(async () => {
render( render(
TestRenderer, { TestRenderer, {
@@ -1006,7 +905,7 @@ describe('Keyboard interactions', () => {
) )
it( it(
'should be possible to close a sibling Popover when pressing escape on a sibling Popover.Button', 'should be possible to close a sibling Popover when pressing escape on a sibling PopoverButton',
suppressConsoleLogs(async () => { suppressConsoleLogs(async () => {
render( render(
TestRenderer, { TestRenderer, {
@@ -1059,7 +958,7 @@ describe('Keyboard interactions', () => {
describe('`Tab` key', () => { describe('`Tab` key', () => {
it( it(
'should be possible to Tab through the panel contents onto the next Popover.Button', 'should be possible to Tab through the panel contents onto the next PopoverButton',
suppressConsoleLogs(async () => { suppressConsoleLogs(async () => {
render( render(
TestRenderer, { TestRenderer, {
@@ -1261,7 +1160,7 @@ describe('Keyboard interactions', () => {
) )
it( it(
'should close the Popover when the Popover.Panel has a focus prop', 'should close the Popover when the PopoverPanel has a focus prop',
suppressConsoleLogs(async () => { suppressConsoleLogs(async () => {
render( render(
TestRenderer, { TestRenderer, {
@@ -1297,7 +1196,7 @@ describe('Keyboard interactions', () => {
) )
it( it(
'should close the Popover when the Popover.Panel has a focus prop (Popover.Panel uses a Portal)', 'should close the Popover when the PopoverPanel has a focus prop (PopoverPanel uses a Portal)',
suppressConsoleLogs(async () => { suppressConsoleLogs(async () => {
render( render(
TestRenderer, { TestRenderer, {
@@ -1343,7 +1242,7 @@ describe('Keyboard interactions', () => {
) )
it( it(
'should close the Popover when the Popover.Panel has a focus prop (Popover.Panel uses a Portal), and focus the next focusable item in line', 'should close the Popover when the PopoverPanel has a focus prop (PopoverPanel uses a Portal), and focus the next focusable item in line',
suppressConsoleLogs(async () => { suppressConsoleLogs(async () => {
render( render(
TestRenderer, { TestRenderer, {
@@ -1473,7 +1372,7 @@ describe('Keyboard interactions', () => {
) )
it( it(
'should focus the previous Popover.Button when Shift+Tab on the second Popover.Button', 'should focus the previous PopoverButton when Shift+Tab on the second PopoverButton',
suppressConsoleLogs(async () => { suppressConsoleLogs(async () => {
render( render(
TestRenderer, { TestRenderer, {
@@ -1509,19 +1408,19 @@ describe('Keyboard interactions', () => {
// Ensure the popover is now closed // Ensure the popover is now closed
assertPopoverButton({ state: PopoverState.InvisibleUnmounted }, getByText('Trigger 2')) assertPopoverButton({ state: PopoverState.InvisibleUnmounted }, getByText('Trigger 2'))
// Ensure the second Popover.Button is focused // Ensure the second PopoverButton is focused
assertActiveElement(getByText('Trigger 2')) assertActiveElement(getByText('Trigger 2'))
// Tab backwards // Tab backwards
await press(shift(Keys.Tab)) await press(shift(Keys.Tab))
// Ensure the first Popover.Button is open // Ensure the first PopoverButton is open
assertActiveElement(getByText('Trigger 1')) assertActiveElement(getByText('Trigger 1'))
}) })
) )
it( it(
'should focus the Popover.Button when pressing Shift+Tab when we focus inside the Popover.Panel', 'should focus the PopoverButton when pressing Shift+Tab when we focus inside the PopoverPanel',
suppressConsoleLogs(async () => { suppressConsoleLogs(async () => {
render( render(
TestRenderer, { TestRenderer, {
@@ -1548,7 +1447,7 @@ describe('Keyboard interactions', () => {
// Tab out of the Panel // Tab out of the Panel
await press(shift(Keys.Tab)) await press(shift(Keys.Tab))
// Ensure the Popover.Button is focused again // Ensure the PopoverButton is focused again
assertActiveElement(getPopoverButton()) assertActiveElement(getPopoverButton())
// Ensure the Popover is closed // Ensure the Popover is closed
@@ -1558,7 +1457,7 @@ describe('Keyboard interactions', () => {
) )
it( it(
'should focus the Popover.Button when pressing Shift+Tab when we focus inside the Popover.Panel (inside a Portal)', 'should focus the PopoverButton when pressing Shift+Tab when we focus inside the PopoverPanel (inside a Portal)',
suppressConsoleLogs(async () => { suppressConsoleLogs(async () => {
render( render(
TestRenderer, { TestRenderer, {
@@ -1587,7 +1486,7 @@ describe('Keyboard interactions', () => {
// Tab out of the Panel // Tab out of the Panel
await press(shift(Keys.Tab)) await press(shift(Keys.Tab))
// Ensure the Popover.Button is focused again // Ensure the PopoverButton is focused again
assertActiveElement(getPopoverButton()) assertActiveElement(getPopoverButton())
// Ensure the Popover is closed // Ensure the Popover is closed
@@ -1597,7 +1496,7 @@ describe('Keyboard interactions', () => {
) )
it( it(
'should be possible to focus the last item in the Popover.Panel when pressing Shift+Tab on the next Popover.Button', 'should be possible to focus the last item in the PopoverPanel when pressing Shift+Tab on the next PopoverButton',
suppressConsoleLogs(async () => { suppressConsoleLogs(async () => {
render( render(
TestRenderer, { TestRenderer, {
@@ -1637,7 +1536,7 @@ describe('Keyboard interactions', () => {
assertPopoverButton({ state: PopoverState.Visible }) assertPopoverButton({ state: PopoverState.Visible })
assertPopoverPanel({ state: PopoverState.Visible }) assertPopoverPanel({ state: PopoverState.Visible })
// Press shift+tab, to move focus to the last item in the Popover.Panel // Press shift+tab, to move focus to the last item in the PopoverPanel
await press(shift(Keys.Tab), getByText('Trigger 2')) await press(shift(Keys.Tab), getByText('Trigger 2'))
// Verify we are focusing the last link of the first Popover // Verify we are focusing the last link of the first Popover
@@ -1646,7 +1545,7 @@ describe('Keyboard interactions', () => {
) )
it( it(
"should be possible to focus the last item in the Popover.Panel when pressing Shift+Tab on the next Popover.Button (using Portal's)", "should be possible to focus the last item in the PopoverPanel when pressing Shift+Tab on the next PopoverButton (using Portal's)",
suppressConsoleLogs(async () => { suppressConsoleLogs(async () => {
render( render(
TestRenderer, { TestRenderer, {
@@ -1690,7 +1589,7 @@ describe('Keyboard interactions', () => {
assertPopoverButton({ state: PopoverState.Visible }) assertPopoverButton({ state: PopoverState.Visible })
assertPopoverPanel({ state: PopoverState.Visible }) assertPopoverPanel({ state: PopoverState.Visible })
// Press shift+tab, to move focus to the last item in the Popover.Panel // Press shift+tab, to move focus to the last item in the PopoverPanel
await press(shift(Keys.Tab), getByText('Trigger 2')) await press(shift(Keys.Tab), getByText('Trigger 2'))
// Verify we are focusing the last link of the first Popover // Verify we are focusing the last link of the first Popover
@@ -1852,7 +1751,7 @@ describe('Keyboard interactions', () => {
) )
it( it(
'should close the Popover by pressing `Space` on a Popover.Button inside a Popover.Panel', 'should close the Popover by pressing `Space` on a PopoverButton inside a PopoverPanel',
suppressConsoleLogs(async () => { suppressConsoleLogs(async () => {
render( render(
TestRenderer, { TestRenderer, {
@@ -2170,7 +2069,7 @@ describe('Mouse interactions', () => {
) )
it( it(
'should be possible to close the Popover by clicking on a Popover.Button inside a Popover.Panel', 'should be possible to close the Popover by clicking on a PopoverButton inside a PopoverPanel',
suppressConsoleLogs(async () => { suppressConsoleLogs(async () => {
render( render(
TestRenderer, { TestRenderer, {
@@ -2205,7 +2104,7 @@ describe('Mouse interactions', () => {
) )
it( it(
'should not close the Popover when clicking on a focusable element inside a static Popover.Panel', 'should not close the Popover when clicking on a focusable element inside a static PopoverPanel',
suppressConsoleLogs(async () => { suppressConsoleLogs(async () => {
let clickFn = jest.fn() let clickFn = jest.fn()
@@ -2236,7 +2135,7 @@ describe('Mouse interactions', () => {
) )
it( it(
'should not close the Popover when clicking on a non-focusable element inside a static Popover.Panel', 'should not close the Popover when clicking on a non-focusable element inside a static PopoverPanel',
suppressConsoleLogs(async () => { suppressConsoleLogs(async () => {
render( render(
TestRenderer, { TestRenderer, {
@@ -2262,7 +2161,7 @@ describe('Mouse interactions', () => {
) )
it( it(
'should close the Popover when clicking outside of a static Popover.Panel', 'should close the Popover when clicking outside of a static PopoverPanel',
suppressConsoleLogs(async () => { suppressConsoleLogs(async () => {
render( render(
TestRenderer, { TestRenderer, {

View File

@@ -13,6 +13,7 @@ import TestRenderer from "$lib/test-utils/TestRenderer.svelte";
import { click, Keys, press, shift } from "$lib/test-utils/interactions"; import { click, Keys, press, shift } from "$lib/test-utils/interactions";
import Button from "$lib/internal/elements/Button.svelte"; import Button from "$lib/internal/elements/Button.svelte";
import ManagedRadioGroup from "./_ManagedRadioGroup.svelte"; import ManagedRadioGroup from "./_ManagedRadioGroup.svelte";
import svelte from "svelte-inline-compile";
let mockId = 0; let mockId = 0;
jest.mock('../../hooks/use-id', () => { jest.mock('../../hooks/use-id', () => {
@@ -123,169 +124,159 @@ describe('Rendering', () => {
assertNotFocusable(getByText('Dine in')) assertNotFocusable(getByText('Dine in'))
}) })
// it('should guarantee the radio option order after a few unmounts', async () => { // TODO: fix this test!
// function Example() { it.skip('should guarantee the radio option order after a few unmounts', async () => {
// let [showFirst, setShowFirst] = useState(false) render(svelte`
// let [active, setActive] = useState() <script>
let showFirst = false;
let active;
</script>
<button on:click={() => showFirst = !showFirst}>Toggle</button>
<RadioGroup value={active} on:change={(e) => active = e.detail}>
<RadioGroupLabel>Pizza Delivery</RadioGroupLabel>
{#if showFirst}
<RadioGroupOption value="pickup">Pickup</RadioGroupOption>
{/if}
<RadioGroupOption value="home-delivery">Home delivery</RadioGroupOption>
<RadioGroupOption value="dine-in">Dine in</RadioGroupOption>
</RadioGroup>
`)
// return ( await click(getByText('Toggle')) // Render the pickup again
// <>
// <button onClick={() => setShowFirst(v => !v)}>Toggle</button>
// <RadioGroup value={active} onChange={setActive}>
// <RadioGroup.Label>Pizza Delivery</RadioGroup.Label>
// {showFirst && <RadioGroup.Option value="pickup">Pickup</RadioGroup.Option>}
// <RadioGroup.Option value="home-delivery">Home delivery</RadioGroup.Option>
// <RadioGroup.Option value="dine-in">Dine in</RadioGroup.Option>
// </RadioGroup>
// </>
// )
// }
// render(<Example />) await press(Keys.Tab) // Focus first element
assertActiveElement(getByText('Pickup'))
// await click(getByText('Toggle')) // Render the pickup again await press(Keys.ArrowUp) // Loop around
assertActiveElement(getByText('Dine in'))
// await press(Keys.Tab) // Focus first element await press(Keys.ArrowUp) // Up again
// assertActiveElement(getByText('Pickup')) assertActiveElement(getByText('Home delivery'))
})
// await press(Keys.ArrowUp) // Loop around it('should be possible to disable a RadioGroup', async () => {
// assertActiveElement(getByText('Dine in')) let changeFn = jest.fn()
// await press(Keys.ArrowUp) // Up again render(svelte`
// assertActiveElement(getByText('Home delivery')) <script>
// }) let disabled = true;
</script>
<button on:click={() => disabled = !disabled}>Toggle</button>
<RadioGroup value={undefined} on:change={changeFn} {disabled}>
<RadioGroupLabel>Pizza Delivery</RadioGroupLabel>
<RadioGroupOption value="pickup">Pickup</RadioGroupOption>
<RadioGroupOption value="home-delivery">Home delivery</RadioGroupOption>
<RadioGroupOption value="dine-in">Dine in</RadioGroupOption>
<RadioGroupOption value="slot-prop" data-value="slot-prop" let:checked let:disabled let:active>
{JSON.stringify({ checked, disabled, active })}
</RadioGroupOption>
</RadioGroup>
`)
// it('should be possible to disable a RadioGroup', async () => {
// let changeFn = jest.fn()
// function Example() { // Try to click one a few options
// let [disabled, setDisabled] = useState(true) await click(getByText('Pickup'))
// return ( await click(getByText('Dine in'))
// <>
// <button onClick={() => setDisabled(v => !v)}>Toggle</button>
// <RadioGroup value={undefined} onChange={changeFn} disabled={disabled}>
// <RadioGroup.Label>Pizza Delivery</RadioGroup.Label>
// <RadioGroup.Option value="pickup">Pickup</RadioGroup.Option>
// <RadioGroup.Option value="home-delivery">Home delivery</RadioGroup.Option>
// <RadioGroup.Option value="dine-in">Dine in</RadioGroup.Option>
// <RadioGroup.Option value="render-prop" data-value="render-prop">
// {JSON.stringify}
// </RadioGroup.Option>
// </RadioGroup>
// </>
// )
// }
// render(<Example />) // Verify that the RadioGroupOption gets the disabled state
expect(document.querySelector('[data-value="slot-prop"]')).toHaveTextContent(
JSON.stringify({
checked: false,
disabled: true,
active: false,
})
)
// // Try to click one a few options // Make sure that the onChange handler never got called
// await click(getByText('Pickup')) expect(changeFn).toHaveBeenCalledTimes(0)
// await click(getByText('Dine in'))
// // Verify that the RadioGroup.Option gets the disabled state // Make sure that all the options get an `aria-disabled`
// expect(document.querySelector('[data-value="render-prop"]')).toHaveTextContent( let options = getRadioGroupOptions()
// JSON.stringify({ expect(options).toHaveLength(4)
// checked: false, for (let option of options) expect(option).toHaveAttribute('aria-disabled', 'true')
// disabled: true,
// active: false,
// })
// )
// // Make sure that the onChange handler never got called // Toggle the disabled state
// expect(changeFn).toHaveBeenCalledTimes(0) await click(getByText('Toggle'))
// // Make sure that all the options get an `aria-disabled` // Verify that the RadioGroupOption gets the disabled state
// let options = getRadioGroupOptions() expect(document.querySelector('[data-value="slot-prop"]')).toHaveTextContent(
// expect(options).toHaveLength(4) JSON.stringify({
// for (let option of options) expect(option).toHaveAttribute('aria-disabled', 'true') checked: false,
disabled: false,
active: false,
})
)
// // Toggle the disabled state // Try to click one a few options
// await click(getByText('Toggle')) await click(getByText('Pickup'))
// // Verify that the RadioGroup.Option gets the disabled state // Make sure that the onChange handler got called
// expect(document.querySelector('[data-value="render-prop"]')).toHaveTextContent( expect(changeFn).toHaveBeenCalledTimes(1)
// JSON.stringify({ })
// checked: false,
// disabled: false,
// active: false,
// })
// )
// // Try to click one a few options it('should be possible to disable a RadioGroupOption', async () => {
// await click(getByText('Pickup')) let changeFn = jest.fn()
// // Make sure that the onChange handler got called render(svelte`
// expect(changeFn).toHaveBeenCalledTimes(1) <script>
// }) let disabled = true;
</script>
<button on:click={() => disabled = !disabled}>Toggle</button>
<RadioGroup value={undefined} on:change={changeFn}>
<RadioGroupLabel>Pizza Delivery</RadioGroupLabel>
<RadioGroupOption value="pickup">Pickup</RadioGroupOption>
<RadioGroupOption value="home-delivery">Home delivery</RadioGroupOption>
<RadioGroupOption value="dine-in">Dine in</RadioGroupOption>
<RadioGroupOption value="slot-prop" {disabled} data-value="slot-prop" let:checked let:disabled let:active>
{JSON.stringify({ checked, disabled, active })}
</RadioGroupOption>
</RadioGroup>
`)
// it('should be possible to disable a RadioGroup.Option', async () => { // Try to click the disabled option
// let changeFn = jest.fn() await click(document.querySelector('[data-value="slot-prop"]'))
// function Example() { // Verify that the RadioGroupOption gets the disabled state
// let [disabled, setDisabled] = useState(true) expect(document.querySelector('[data-value="slot-prop"]')).toHaveTextContent(
// return ( JSON.stringify({
// <> checked: false,
// <button onClick={() => setDisabled(v => !v)}>Toggle</button> disabled: true,
// <RadioGroup value={undefined} onChange={changeFn}> active: false,
// <RadioGroup.Label>Pizza Delivery</RadioGroup.Label> })
// <RadioGroup.Option value="pickup">Pickup</RadioGroup.Option> )
// <RadioGroup.Option value="home-delivery">Home delivery</RadioGroup.Option>
// <RadioGroup.Option value="dine-in">Dine in</RadioGroup.Option>
// <RadioGroup.Option value="render-prop" disabled={disabled} data-value="render-prop">
// {JSON.stringify}
// </RadioGroup.Option>
// </RadioGroup>
// </>
// )
// }
// render(<Example />) // Make sure that the onChange handler never got called
expect(changeFn).toHaveBeenCalledTimes(0)
// // Try to click the disabled option // Make sure that the option with value "slot-prop" gets an `aria-disabled`
// await click(document.querySelector('[data-value="render-prop"]')) let options = getRadioGroupOptions()
expect(options).toHaveLength(4)
for (let option of options) {
if (option.dataset.value) {
expect(option).toHaveAttribute('aria-disabled', 'true')
} else {
expect(option).not.toHaveAttribute('aria-disabled')
}
}
// // Verify that the RadioGroup.Option gets the disabled state // Toggle the disabled state
// expect(document.querySelector('[data-value="render-prop"]')).toHaveTextContent( await click(getByText('Toggle'))
// JSON.stringify({
// checked: false,
// disabled: true,
// active: false,
// })
// )
// // Make sure that the onChange handler never got called // Verify that the RadioGroupOption gets the disabled state
// expect(changeFn).toHaveBeenCalledTimes(0) expect(document.querySelector('[data-value="slot-prop"]')).toHaveTextContent(
JSON.stringify({
checked: false,
disabled: false,
active: false,
})
)
// // Make sure that the option with value "render-prop" gets an `aria-disabled` // Try to click one a few options
// let options = getRadioGroupOptions() await click(document.querySelector('[data-value="slot-prop"]'))
// expect(options).toHaveLength(4)
// for (let option of options) {
// if (option.dataset.value) {
// expect(option).toHaveAttribute('aria-disabled', 'true')
// } else {
// expect(option).not.toHaveAttribute('aria-disabled')
// }
// }
// // Toggle the disabled state // Make sure that the onChange handler got called
// await click(getByText('Toggle')) expect(changeFn).toHaveBeenCalledTimes(1)
})
// // Verify that the RadioGroup.Option gets the disabled state
// expect(document.querySelector('[data-value="render-prop"]')).toHaveTextContent(
// JSON.stringify({
// checked: false,
// disabled: false,
// active: false,
// })
// )
// // Try to click one a few options
// await click(document.querySelector('[data-value="render-prop"]'))
// // Make sure that the onChange handler got called
// expect(changeFn).toHaveBeenCalledTimes(1)
// })
// })
}) })

View File

@@ -13,6 +13,7 @@ import Div from "$lib/internal/elements/Div.svelte";
import Span from "$lib/internal/elements/Span.svelte"; import Span from "$lib/internal/elements/Span.svelte";
import ManagedSwitch from "./_ManagedSwitch.svelte"; import ManagedSwitch from "./_ManagedSwitch.svelte";
import { click, Keys, press } from "$lib/test-utils/interactions"; import { click, Keys, press } from "$lib/test-utils/interactions";
import svelte from "svelte-inline-compile";
jest.mock("../../hooks/use-id"); jest.mock("../../hooks/use-id");
describe("Safe guards", () => { describe("Safe guards", () => {
@@ -24,27 +25,25 @@ describe("Safe guards", () => {
}); });
describe("Rendering", () => { describe("Rendering", () => {
// TODO: handle these render prop (slot prop) tests it('(on) Switch should have a slot prop', () => {
render(svelte`
<Switch checked={true} on:change={console.log} let:checked>
<span>{checked ? 'On' : 'Off'}</span>
</Switch>
`)
// it('should be possible to render an (on) Switch using a render prop', () => { assertSwitch({ state: SwitchState.On, textContent: 'On' })
// render(TestRenderer, { })
// <Switch checked={true} onChange={console.log}>
// {({ checked }) => <span>{checked ? 'On' : 'Off'}</span>}
// </Switch>
// )
// assertSwitch({ state: SwitchState.On, textContent: 'On' }) it('(off) Switch should have a slot prop', () => {
// }) render(svelte`
<Switch checked={false} on:change={console.log} let:checked>
<span>{checked ? 'On' : 'Off'}</span>
</Switch>
`)
// it('should be possible to render an (off) Switch using a render prop', () => { assertSwitch({ state: SwitchState.Off, textContent: 'Off' })
// render( })
// <Switch checked={false} onChange={console.log}>
// {({ checked }) => <span>{checked ? 'On' : 'Off'}</span>}
// </Switch>
// )
// assertSwitch({ state: SwitchState.Off, textContent: 'Off' })
// })
it("should be possible to render an (on) Switch using an `as` prop", () => { it("should be possible to render an (on) Switch using an `as` prop", () => {
render(TestRenderer, { render(TestRenderer, {

View File

@@ -5,6 +5,7 @@ import { Tab, TabGroup, TabList, TabPanel, TabPanels } from ".";
import { assertActiveElement, assertTabs, getByText, getTabs } from "$lib/test-utils/accessibility-assertions"; import { assertActiveElement, assertTabs, getByText, getTabs } from "$lib/test-utils/accessibility-assertions";
import { click, Keys, press, shift } from "$lib/test-utils/interactions"; import { click, Keys, press, shift } from "$lib/test-utils/interactions";
import Button from "$lib/internal/elements/Button.svelte"; import Button from "$lib/internal/elements/Button.svelte";
import svelte from "svelte-inline-compile";
let mockId = 0; let mockId = 0;
jest.mock('../../hooks/use-id', () => { jest.mock('../../hooks/use-id', () => {
@@ -59,7 +60,7 @@ describe('safeguards', () => {
}) })
describe('Rendering', () => { describe('Rendering', () => {
it('should be possible to render the Tab.Panels first, then the Tab.List', async () => { it('should be possible to render the TabPanels first, then the TabList', async () => {
render( render(
TestRenderer, { TestRenderer, {
allProps: [ allProps: [
@@ -81,229 +82,192 @@ describe('Rendering', () => {
assertTabs({ active: 0 }) assertTabs({ active: 0 })
}) })
// describe('`renderProps`', () => { describe('`slot props`', () => {
// it('should expose the `selectedIndex` on the `Tab.Group` component', async () => { it('should expose the `selectedIndex` on the `TabGroup` component', async () => {
// render( render(svelte`
// <Tab.Group> <TabGroup let:selectedIndex>
// {data => ( <pre id="exposed">{JSON.stringify({ selectedIndex })}</pre>
// <>
// <pre id="exposed">{JSON.stringify(data)}</pre>
// <Tab.List> <TabList>
// <Tab>Tab 1</Tab> <Tab>Tab 1</Tab>
// <Tab>Tab 2</Tab> <Tab>Tab 2</Tab>
// <Tab>Tab 3</Tab> <Tab>Tab 3</Tab>
// </Tab.List> </TabList>
// <Tab.Panels> <TabPanels>
// <Tab.Panel>Content 1</Tab.Panel> <TabPanel>Content 1</TabPanel>
// <Tab.Panel>Content 2</Tab.Panel> <TabPanel>Content 2</TabPanel>
// <Tab.Panel>Content 3</Tab.Panel> <TabPanel>Content 3</TabPanel>
// </Tab.Panels> </TabPanels>
// </> </TabGroup>
// )} `)
// </Tab.Group>
// )
// expect(document.getElementById('exposed')).toHaveTextContent( expect(document.getElementById('exposed')).toHaveTextContent(
// JSON.stringify({ selectedIndex: 0 }) JSON.stringify({ selectedIndex: 0 })
// ) )
// await click(getByText('Tab 2')) await click(getByText('Tab 2'))
// expect(document.getElementById('exposed')).toHaveTextContent( expect(document.getElementById('exposed')).toHaveTextContent(
// JSON.stringify({ selectedIndex: 1 }) JSON.stringify({ selectedIndex: 1 })
// ) )
// }) })
// it('should expose the `selectedIndex` on the `Tab.List` component', async () => { it('should expose the `selectedIndex` on the `TabList` component', async () => {
// render( render(svelte`
// <Tab.Group> <TabGroup>
// <Tab.List> <TabList let:selectedIndex>
// {data => ( <pre id="exposed">{ JSON.stringify({ selectedIndex }) }</pre>
// <> <Tab>Tab 1</Tab>
// <pre id="exposed">{JSON.stringify(data)}</pre> <Tab>Tab 2</Tab>
// <Tab>Tab 1</Tab> <Tab>Tab 3</Tab>
// <Tab>Tab 2</Tab> </TabList>
// <Tab>Tab 3</Tab> <TabPanels>
// </> <TabPanel>Content 1</TabPanel>
// )} <TabPanel>Content 2</TabPanel>
// </Tab.List> <TabPanel>Content 3</TabPanel>
</TabPanels>
</TabGroup>
`)
// <Tab.Panels> expect(document.getElementById('exposed')).toHaveTextContent(
// <Tab.Panel>Content 1</Tab.Panel> JSON.stringify({ selectedIndex: 0 })
// <Tab.Panel>Content 2</Tab.Panel> )
// <Tab.Panel>Content 3</Tab.Panel>
// </Tab.Panels>
// </Tab.Group>
// )
// expect(document.getElementById('exposed')).toHaveTextContent( await click(getByText('Tab 2'))
// JSON.stringify({ selectedIndex: 0 })
// )
// await click(getByText('Tab 2')) expect(document.getElementById('exposed')).toHaveTextContent(
JSON.stringify({ selectedIndex: 1 })
)
})
// expect(document.getElementById('exposed')).toHaveTextContent( it('should expose the `selectedIndex` on the `TabPanels` component', async () => {
// JSON.stringify({ selectedIndex: 1 }) render(svelte`
// ) <TabGroup>
// }) <TabList>
<Tab>Tab 1</Tab>
<Tab>Tab 2</Tab>
<Tab>Tab 3</Tab>
</TabList>
// it('should expose the `selectedIndex` on the `Tab.Panels` component', async () => { <TabPanels let:selectedIndex>
// render( <pre id="exposed">{ JSON.stringify({ selectedIndex }) }</pre>
// <Tab.Group> <TabPanel>Content 1</TabPanel>
// <Tab.List> <TabPanel>Content 2</TabPanel>
// <Tab>Tab 1</Tab> <TabPanel>Content 3</TabPanel>
// <Tab>Tab 2</Tab> </TabPanels>
// <Tab>Tab 3</Tab> </TabGroup>
// </Tab.List> `)
// <Tab.Panels> expect(document.getElementById('exposed')).toHaveTextContent(
// {data => ( JSON.stringify({ selectedIndex: 0 })
// <> )
// <pre id="exposed">{JSON.stringify(data)}</pre>
// <Tab.Panel>Content 1</Tab.Panel>
// <Tab.Panel>Content 2</Tab.Panel>
// <Tab.Panel>Content 3</Tab.Panel>
// </>
// )}
// </Tab.Panels>
// </Tab.Group>
// )
// expect(document.getElementById('exposed')).toHaveTextContent( await click(getByText('Tab 2'))
// JSON.stringify({ selectedIndex: 0 })
// )
// await click(getByText('Tab 2')) expect(document.getElementById('exposed')).toHaveTextContent(
JSON.stringify({ selectedIndex: 1 })
)
})
// expect(document.getElementById('exposed')).toHaveTextContent( it('should expose the `selected` state on the `Tab` components', async () => {
// JSON.stringify({ selectedIndex: 1 }) render(svelte`
// ) <TabGroup>
// }) <TabList>
<Tab let:selected>
<pre data-tab={0}>{JSON.stringify({selected})}</pre>
<span>Tab 1</span>
</Tab>
<Tab let:selected>
<pre data-tab={1}>{JSON.stringify({selected})}</pre>
<span>Tab 2</span>
</Tab>
<Tab let:selected>
<pre data-tab={2}>{JSON.stringify({selected})}</pre>
<span>Tab 3</span>
</Tab>
</TabList>
// it('should expose the `selected` state on the `Tab` components', async () => { <TabPanels>
// render( <TabPanel>Content 1</TabPanel>
// <Tab.Group> <TabPanel>Content 2</TabPanel>
// <Tab.List> <TabPanel>Content 3</TabPanel>
// <Tab> </TabPanels>
// {data => ( </TabGroup>
// <> `)
// <pre data-tab={0}>{JSON.stringify(data)}</pre>
// <span>Tab 1</span>
// </>
// )}
// </Tab>
// <Tab>
// {data => (
// <>
// <pre data-tab={1}>{JSON.stringify(data)}</pre>
// <span>Tab 2</span>
// </>
// )}
// </Tab>
// <Tab>
// {data => (
// <>
// <pre data-tab={2}>{JSON.stringify(data)}</pre>
// <span>Tab 3</span>
// </>
// )}
// </Tab>
// </Tab.List>
// <Tab.Panels> expect(document.querySelector('[data-tab="0"]')).toHaveTextContent(
// <Tab.Panel>Content 1</Tab.Panel> JSON.stringify({ selected: true })
// <Tab.Panel>Content 2</Tab.Panel> )
// <Tab.Panel>Content 3</Tab.Panel> expect(document.querySelector('[data-tab="1"]')).toHaveTextContent(
// </Tab.Panels> JSON.stringify({ selected: false })
// </Tab.Group> )
// ) expect(document.querySelector('[data-tab="2"]')).toHaveTextContent(
JSON.stringify({ selected: false })
)
// expect(document.querySelector('[data-tab="0"]')).toHaveTextContent( await click(getTabs()[1])
// JSON.stringify({ selected: true })
// )
// expect(document.querySelector('[data-tab="1"]')).toHaveTextContent(
// JSON.stringify({ selected: false })
// )
// expect(document.querySelector('[data-tab="2"]')).toHaveTextContent(
// JSON.stringify({ selected: false })
// )
// await click(getTabs()[1]) expect(document.querySelector('[data-tab="0"]')).toHaveTextContent(
JSON.stringify({ selected: false })
)
expect(document.querySelector('[data-tab="1"]')).toHaveTextContent(
JSON.stringify({ selected: true })
)
expect(document.querySelector('[data-tab="2"]')).toHaveTextContent(
JSON.stringify({ selected: false })
)
})
// expect(document.querySelector('[data-tab="0"]')).toHaveTextContent( it('should expose the `selected` state on the `TabPanel` components', async () => {
// JSON.stringify({ selected: false }) render(svelte`
// ) <TabGroup>
// expect(document.querySelector('[data-tab="1"]')).toHaveTextContent( <TabList>
// JSON.stringify({ selected: true }) <Tab>Tab 1</Tab>
// ) <Tab>Tab 2</Tab>
// expect(document.querySelector('[data-tab="2"]')).toHaveTextContent( <Tab>Tab 3</Tab>
// JSON.stringify({ selected: false }) </TabList>
// )
// })
// it('should expose the `selected` state on the `Tab.Panel` components', async () => { <TabPanels>
// render( <TabPanel unmount={false} let:selected>
// <Tab.Group> <pre data-panel={0}>{JSON.stringify({ selected })}</pre>
// <Tab.List> <span> Content 1 </span>
// <Tab>Tab 1</Tab> </TabPanel>
// <Tab>Tab 2</Tab> <TabPanel unmount={false} let:selected>
// <Tab>Tab 3</Tab> <pre data-panel={1}>{JSON.stringify({ selected })}</pre>
// </Tab.List> <span> Content 2 </span>
</TabPanel>
<TabPanel unmount={false} let:selected>
<pre data-panel={2}>{JSON.stringify({ selected })}</pre>
<span> Content 3 </span>
</TabPanel>
</TabPanels>
</TabGroup>
`)
// <Tab.Panels> expect(document.querySelector('[data-panel="0"]')).toHaveTextContent(
// <Tab.Panel unmount={false}> JSON.stringify({ selected: true })
// {data => ( )
// <> expect(document.querySelector('[data-panel="1"]')).toHaveTextContent(
// <pre data-panel={0}>{JSON.stringify(data)}</pre> JSON.stringify({ selected: false })
// <span>Content 1</span> )
// </> expect(document.querySelector('[data-panel="2"]')).toHaveTextContent(
// )} JSON.stringify({ selected: false })
// </Tab.Panel> )
// <Tab.Panel unmount={false}>
// {data => (
// <>
// <pre data-panel={1}>{JSON.stringify(data)}</pre>
// <span>Content 2</span>
// </>
// )}
// </Tab.Panel>
// <Tab.Panel unmount={false}>
// {data => (
// <>
// <pre data-panel={2}>{JSON.stringify(data)}</pre>
// <span>Content 3</span>
// </>
// )}
// </Tab.Panel>
// </Tab.Panels>
// </Tab.Group>
// )
// expect(document.querySelector('[data-panel="0"]')).toHaveTextContent( await click(getByText('Tab 2'))
// JSON.stringify({ selected: true })
// )
// expect(document.querySelector('[data-panel="1"]')).toHaveTextContent(
// JSON.stringify({ selected: false })
// )
// expect(document.querySelector('[data-panel="2"]')).toHaveTextContent(
// JSON.stringify({ selected: false })
// )
// await click(getByText('Tab 2')) expect(document.querySelector('[data-panel="0"]')).toHaveTextContent(
JSON.stringify({ selected: false })
// expect(document.querySelector('[data-panel="0"]')).toHaveTextContent( )
// JSON.stringify({ selected: false }) expect(document.querySelector('[data-panel="1"]')).toHaveTextContent(
// ) JSON.stringify({ selected: true })
// expect(document.querySelector('[data-panel="1"]')).toHaveTextContent( )
// JSON.stringify({ selected: true }) expect(document.querySelector('[data-panel="2"]')).toHaveTextContent(
// ) JSON.stringify({ selected: false })
// expect(document.querySelector('[data-panel="2"]')).toHaveTextContent( )
// JSON.stringify({ selected: false }) })
// ) })
// })
// })
describe('`defaultIndex`', () => { describe('`defaultIndex`', () => {
it('should jump to the nearest tab when the defaultIndex is out of bounds (-2)', async () => { it('should jump to the nearest tab when the defaultIndex is out of bounds (-2)', async () => {