Port "Ensure correct DOM node order when performing focus actions"
tailwindlabs/headlessui#1038 This test didn't actually fail for me but w/e.
This commit is contained in:
		
							
								
								
									
										39
									
								
								src/lib/components/tabs/tabs.test.ts
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										39
									
								
								src/lib/components/tabs/tabs.test.ts
									
									
									
									
										vendored
									
									
								
							| @@ -83,6 +83,45 @@ describe('Rendering', () => { | |||||||
|     assertTabs({ active: 0 }) |     assertTabs({ active: 0 }) | ||||||
|   }) |   }) | ||||||
|  |  | ||||||
|  |   it('should guarantee the order of DOM nodes when performing actions', async () => { | ||||||
|  |     render(svelte` | ||||||
|  |       <script> | ||||||
|  |         let hide = false; | ||||||
|  |       </script> | ||||||
|  |  | ||||||
|  |       <button on:click={() => hide = !hide}>toggle</button> | ||||||
|  |       <TabGroup> | ||||||
|  |         <TabList> | ||||||
|  |           <Tab>Tab 1</Tab> | ||||||
|  |           {#if !hide} | ||||||
|  |             <Tab>Tab 2</Tab> | ||||||
|  |           {/if} | ||||||
|  |           <Tab>Tab 3</Tab> | ||||||
|  |         </TabList> | ||||||
|  |  | ||||||
|  |         <TabPanels> | ||||||
|  |           <TabPanel>Content 1</TabPanel> | ||||||
|  |           {#if !hide} | ||||||
|  |             <TabPanel>Content 2</TabPanel> | ||||||
|  |           {/if} | ||||||
|  |           <TabPanel>Content 3</TabPanel> | ||||||
|  |         </TabPanels> | ||||||
|  |       </TabGroup> | ||||||
|  |     `) | ||||||
|  |  | ||||||
|  |     await click(getByText('toggle')) // Remove Tab 2 | ||||||
|  |     await click(getByText('toggle')) // Re-add Tab 2 | ||||||
|  |  | ||||||
|  |     await press(Keys.Tab) | ||||||
|  |     assertTabs({ active: 0 }) | ||||||
|  |  | ||||||
|  |     await press(Keys.ArrowRight) | ||||||
|  |     assertTabs({ active: 1 }) | ||||||
|  |  | ||||||
|  |     await press(Keys.ArrowRight) | ||||||
|  |     assertTabs({ active: 2 }) | ||||||
|  |   }) | ||||||
|  |  | ||||||
|   describe('`slot props`', () => { |   describe('`slot props`', () => { | ||||||
|     it('should expose the `selectedIndex` on the `TabGroup` component', async () => { |     it('should expose the `selectedIndex` on the `TabGroup` component', async () => { | ||||||
|       render(svelte` |       render(svelte` | ||||||
|   | |||||||
| @@ -1359,12 +1359,8 @@ export function assertTabs( | |||||||
|     expect(list).toHaveAttribute("role", "tablist"); |     expect(list).toHaveAttribute("role", "tablist"); | ||||||
|     expect(list).toHaveAttribute("aria-orientation", orientation); |     expect(list).toHaveAttribute("aria-orientation", orientation); | ||||||
|  |  | ||||||
|     let activeTab = tabs.find( |     let activeTab = Array.from(list.querySelectorAll('[id^="headlessui-tabs-tab-"]'))[active] | ||||||
|       (tab) => tab.dataset.headlessuiIndex === "" + active |     let activePanel = panels.find(panel => panel.id === activeTab.getAttribute('aria-controls')) | ||||||
|     ); |  | ||||||
|     let activePanel = panels.find( |  | ||||||
|       (panel) => panel.dataset.headlessuiIndex === "" + active |  | ||||||
|     ); |  | ||||||
|  |  | ||||||
|     for (let tab of tabs) { |     for (let tab of tabs) { | ||||||
|       expect(tab).toHaveAttribute("id"); |       expect(tab).toHaveAttribute("id"); | ||||||
|   | |||||||
| @@ -16,10 +16,10 @@ let focusableSelector = [ | |||||||
|   .map( |   .map( | ||||||
|     process.env.NODE_ENV === "test" |     process.env.NODE_ENV === "test" | ||||||
|       ? // TODO: Remove this once JSDOM fixes the issue where an element that is |       ? // TODO: Remove this once JSDOM fixes the issue where an element that is | ||||||
|         // "hidden" can be the document.activeElement, because this is not possible |       // "hidden" can be the document.activeElement, because this is not possible | ||||||
|         // in real browsers. |       // in real browsers. | ||||||
|         (selector) => |       (selector) => | ||||||
|           `${selector}:not([tabindex='-1']):not([style*='display: none'])` |         `${selector}:not([tabindex='-1']):not([style*='display: none'])` | ||||||
|       : (selector) => `${selector}:not([tabindex='-1'])` |       : (selector) => `${selector}:not([tabindex='-1'])` | ||||||
|   ) |   ) | ||||||
|   .join(","); |   .join(","); | ||||||
| @@ -100,7 +100,13 @@ export function focusElement(element: HTMLElement | null) { | |||||||
|  |  | ||||||
| export function focusIn(container: HTMLElement | HTMLElement[], focus: Focus) { | export function focusIn(container: HTMLElement | HTMLElement[], focus: Focus) { | ||||||
|   let elements = Array.isArray(container) |   let elements = Array.isArray(container) | ||||||
|     ? container |     ? container.slice().sort((a, b) => { | ||||||
|  |       let position = a.compareDocumentPosition(b) | ||||||
|  |  | ||||||
|  |       if (position & Node.DOCUMENT_POSITION_FOLLOWING) return -1 | ||||||
|  |       if (position & Node.DOCUMENT_POSITION_PRECEDING) return 1 | ||||||
|  |       return 0 | ||||||
|  |     }) | ||||||
|     : getFocusableElements(container); |     : getFocusableElements(container); | ||||||
|   let active = document.activeElement as HTMLElement; |   let active = document.activeElement as HTMLElement; | ||||||
|  |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Ryan Gossiaux
					Ryan Gossiaux