diff --git a/bun.lockb b/bun.lockb
index e2c25046e6..056f89de74 100755
Binary files a/bun.lockb and b/bun.lockb differ
diff --git a/packages/react/src/components/carousel/carousel.test.tsx b/packages/react/src/components/carousel/carousel.test.tsx
new file mode 100644
index 0000000000..cf3abe8568
--- /dev/null
+++ b/packages/react/src/components/carousel/carousel.test.tsx
@@ -0,0 +1,43 @@
+import { cleanup, render, screen, waitFor } from '@testing-library/react/pure'
+import { axe } from 'vitest-axe'
+import { Carousel, carouselAnatomy } from '.'
+import { getExports, getParts } from '../../setup-test'
+import { Basic as ComponentUnderTest } from './examples/basic'
+
+describe('Carousel / Parts & Exports', () => {
+ afterAll(() => {
+ cleanup()
+ })
+
+ render()
+
+ it.each(getParts(carouselAnatomy))('should render part %s', async (part) => {
+ expect(document.querySelector(part)).toBeInTheDocument()
+ })
+
+ it.each(getExports(carouselAnatomy))('should export %s', async (part) => {
+ expect(Carousel[part]).toBeDefined()
+ })
+})
+
+describe('Carousel', () => {
+ afterEach(() => {
+ cleanup()
+ })
+
+ it('should have no a11y violations', async () => {
+ const { container } = render()
+ const results = await axe(container)
+
+ expect(results).toHaveNoViolations()
+ })
+
+ it('should have the correct disabled / enabled states for control buttons', async () => {
+ render()
+ const prevButton = screen.getByRole('button', { name: 'Previous slide' })
+ const nextButton = screen.getByRole('button', { name: 'Next slide' })
+
+ await waitFor(() => expect(prevButton).toBeDisabled())
+ await waitFor(() => expect(nextButton).toBeEnabled())
+ })
+})
diff --git a/packages/react/src/components/carousel/examples/basic.tsx b/packages/react/src/components/carousel/examples/basic.tsx
index b742fa31ba..e1226dbf42 100644
--- a/packages/react/src/components/carousel/examples/basic.tsx
+++ b/packages/react/src/components/carousel/examples/basic.tsx
@@ -4,7 +4,7 @@ const images = Array(5).fill('https://picsum.photos/seed/a/500/300')
export const Basic = () => {
return (
-
+
Play or Pause
Previous
diff --git a/packages/react/src/components/carousel/tests/basic.tsx b/packages/react/src/components/carousel/tests/basic.tsx
deleted file mode 100644
index ab8f7072f6..0000000000
--- a/packages/react/src/components/carousel/tests/basic.tsx
+++ /dev/null
@@ -1,28 +0,0 @@
-import { Carousel } from '../'
-
-const images = Array(5).fill('https://picsum.photos/seed/a/500/300')
-
-export const ComponentUnderTest = (props: Carousel.RootProps) => {
- return (
-
-
- Previous
- Next
-
-
- {images.map((_, index) => (
-
- {index + 1}
-
- ))}
-
-
- {images.map((image, index) => (
-
-
-
- ))}
-
-
- )
-}
diff --git a/packages/react/src/components/carousel/tests/carousel.test.tsx b/packages/react/src/components/carousel/tests/carousel.test.tsx
deleted file mode 100644
index 0f69aee3f1..0000000000
--- a/packages/react/src/components/carousel/tests/carousel.test.tsx
+++ /dev/null
@@ -1,71 +0,0 @@
-import { cleanup, render, screen } from '@testing-library/react/pure'
-import user from '@testing-library/user-event'
-import { axe } from 'vitest-axe'
-import { Carousel, carouselAnatomy } from '../'
-import { getExports, getParts } from '../../../setup-test'
-import { ComponentUnderTest } from './basic'
-
-describe('Carousel / Parts & Exports', () => {
- afterAll(() => {
- cleanup()
- })
-
- render()
-
- it.each(getParts(carouselAnatomy))('should render part %s', async (part) => {
- expect(document.querySelector(part)).toBeInTheDocument()
- })
-
- it.each(getExports(carouselAnatomy))('should export %s', async (part) => {
- expect(Carousel[part]).toBeDefined()
- })
-})
-
-describe('Carousel', () => {
- afterEach(() => {
- cleanup()
- })
-
- it('should have no a11y violations', async () => {
- const { container } = render()
- const results = await axe(container)
-
- expect(results).toHaveNoViolations()
- })
-
- it('should have the correct disabled / enabled states for control buttons', async () => {
- render()
- const prevButton = screen.getByRole('button', { name: 'Previous Slide' })
- const nextButton = screen.getByRole('button', { name: 'Next Slide' })
-
- // first slide
- expect(prevButton).toBeDisabled()
- expect(nextButton).toBeEnabled()
-
- // second slide
- await user.click(nextButton)
- expect(prevButton).toBeEnabled()
- expect(nextButton).toBeEnabled()
-
- // last slide
- await user.click(nextButton)
- expect(prevButton).toBeEnabled()
- expect(nextButton).toBeDisabled()
- })
-
- it('goes to the indicated slide on indicator click', async () => {
- render()
- const indicators = screen.getAllByTestId('indicator')
- const slides = screen.getAllByTestId('item')
-
- expect(slides[0]).toHaveAttribute('data-current', '')
- expect(indicators[0]).toHaveAttribute('data-current', '')
-
- await user.click(indicators[2])
-
- expect(indicators[0]).not.toHaveAttribute('data-current', '')
- expect(slides[0]).not.toHaveAttribute('data-current', '')
- expect(indicators[2]).toHaveAttribute('data-current', '')
- expect(slides[2]).toHaveAttribute('data-current', '')
- })
-})
diff --git a/packages/react/src/setup-test.ts b/packages/react/src/setup-test.ts
index 3d8771f009..ead59f5857 100644
--- a/packages/react/src/setup-test.ts
+++ b/packages/react/src/setup-test.ts
@@ -6,10 +6,23 @@ import { vi } from 'vitest'
import 'vitest-axe/extend-expect'
const { window } = new JSDOM()
+/**
+ * IntersectionObserver
+ */
+const IntersectionObserverMock = vi.fn(() => ({
+ disconnect: vi.fn(),
+ observe: vi.fn(),
+ takeRecords: vi.fn(),
+ unobserve: vi.fn(),
+}))
+vi.stubGlobal('IntersectionObserver', IntersectionObserverMock)
+// biome-ignore lint/complexity/useLiteralKeys:
+window['IntersectionObserver'] = IntersectionObserverMock
vi.stubGlobal('ResizeObserver', ResizeObserver)
// biome-ignore lint/complexity/useLiteralKeys:
window['ResizeObserver'] = ResizeObserver
+
window.Element.prototype.scrollTo = () => {}
window.Element.prototype.scrollIntoView = () => {}
window.requestAnimationFrame = (cb) => setTimeout(cb, 1000 / 60)