diff --git a/package-lock.json b/package-lock.json
index 00c2e746ec..2705ce1ae8 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -43725,14 +43725,70 @@
"prop-types": "^15.8.1"
},
"devDependencies": {
+ "@instructure/ui-axe-check": "9.2.0",
"@instructure/ui-babel-preset": "9.2.0",
- "@instructure/ui-test-utils": "9.2.0"
+ "@testing-library/jest-dom": "^6.4.5",
+ "@testing-library/react": "^15.0.7",
+ "@testing-library/user-event": "^14.5.2",
+ "vitest": "^1.6.0"
},
"peerDependencies": {
"react": ">=16.8 <=18",
"react-dom": ">=16.8 <=18"
}
},
+ "packages/ui-portal/node_modules/@testing-library/dom": {
+ "version": "10.3.1",
+ "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-10.3.1.tgz",
+ "integrity": "sha512-q/WL+vlXMpC0uXDyfsMtc1rmotzLV8Y0gq6q1gfrrDjQeHoeLrqHbxdPvPNAh1i+xuJl7+BezywcXArz7vLqKQ==",
+ "dev": true,
+ "dependencies": {
+ "@babel/code-frame": "^7.10.4",
+ "@babel/runtime": "^7.12.5",
+ "@types/aria-query": "^5.0.1",
+ "aria-query": "5.3.0",
+ "chalk": "^4.1.0",
+ "dom-accessibility-api": "^0.5.9",
+ "lz-string": "^1.5.0",
+ "pretty-format": "^27.0.2"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "packages/ui-portal/node_modules/@testing-library/react": {
+ "version": "15.0.7",
+ "resolved": "https://registry.npmjs.org/@testing-library/react/-/react-15.0.7.tgz",
+ "integrity": "sha512-cg0RvEdD1TIhhkm1IeYMQxrzy0MtUNfa3minv4MjbgcYzJAZ7yD0i0lwoPOTPr+INtiXFezt2o8xMSnyHhEn2Q==",
+ "dev": true,
+ "dependencies": {
+ "@babel/runtime": "^7.12.5",
+ "@testing-library/dom": "^10.0.0",
+ "@types/react-dom": "^18.0.0"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "peerDependencies": {
+ "@types/react": "^18.0.0",
+ "react": "^18.0.0",
+ "react-dom": "^18.0.0"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "packages/ui-portal/node_modules/aria-query": {
+ "version": "5.3.0",
+ "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.0.tgz",
+ "integrity": "sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==",
+ "dev": true,
+ "dependencies": {
+ "dequal": "^2.0.3"
+ }
+ },
"packages/ui-position": {
"name": "@instructure/ui-position",
"version": "9.2.0",
diff --git a/packages/ui-portal/package.json b/packages/ui-portal/package.json
index 2279a5a5b9..0044321746 100644
--- a/packages/ui-portal/package.json
+++ b/packages/ui-portal/package.json
@@ -23,8 +23,12 @@
},
"license": "MIT",
"devDependencies": {
+ "@instructure/ui-axe-check": "9.2.0",
"@instructure/ui-babel-preset": "9.2.0",
- "@instructure/ui-test-utils": "9.2.0"
+ "@testing-library/jest-dom": "^6.4.5",
+ "@testing-library/react": "^15.0.7",
+ "@testing-library/user-event": "^14.5.2",
+ "vitest": "^1.6.0"
},
"dependencies": {
"@babel/runtime": "^7.24.5",
diff --git a/packages/ui-portal/src/Portal/__tests__/Portal.test.tsx b/packages/ui-portal/src/Portal/__new-tests__/Portal.test.tsx
similarity index 55%
rename from packages/ui-portal/src/Portal/__tests__/Portal.test.tsx
rename to packages/ui-portal/src/Portal/__new-tests__/Portal.test.tsx
index 458a8fbc24..74e37b6684 100644
--- a/packages/ui-portal/src/Portal/__tests__/Portal.test.tsx
+++ b/packages/ui-portal/src/Portal/__new-tests__/Portal.test.tsx
@@ -24,114 +24,127 @@
*/
import React from 'react'
-import { find, expect, mount, stub } from '@instructure/ui-test-utils'
+import { vi } from 'vitest'
+import { render, screen, waitFor } from '@testing-library/react'
+import userEvent from '@testing-library/user-event'
+import '@testing-library/jest-dom'
+import { runAxeCheck } from '@instructure/ui-axe-check'
import { Portal } from '../index'
-describe(``, async () => {
+describe(``, () => {
it('should render', async () => {
- await mount(Hello World)
- const portal = await find(':contains(Hello World)')
- expect(portal.getDOMNode()).to.exist()
+ render(Hello World)
+ const portal = screen.getByText('Hello World')
+
+ expect(portal).toBeInTheDocument()
})
it('should be accessible', async () => {
- await mount(
-
+ const { container } = render(
+
Hello World
)
- const portal = await find('#portal')
- expect(await portal.accessible()).to.be.true()
+ const axeCheck = await runAxeCheck(container)
+
+ expect(axeCheck).toBe(true)
})
it('should support onOpen prop', async () => {
- const onOpen = stub()
- await mount(
-
+ const onOpen = vi.fn()
+ render(
+
Hello World
)
+ const portal = screen.getByTestId('portal')
- const portal = await find('#portal')
-
- expect(onOpen).to.have.been.calledWith(portal.getDOMNode())
+ expect(onOpen).toHaveBeenCalledWith(portal)
})
it('should support onClose prop', async () => {
- const onClose = stub()
-
- const subject = await mount(
+ const onClose = vi.fn()
+ const { rerender } = render(
Hello World
)
- await subject.setProps({ open: false })
+ expect(onClose).not.toHaveBeenCalled()
+
+ rerender(
+
+ Hello World
+
+ )
- expect(onClose).to.have.been.called()
+ expect(onClose).toHaveBeenCalled()
})
it('should add a dir attribute to the root DOM node', async () => {
- const onOpen = stub()
- await mount(
-
+ const onOpen = vi.fn()
+ render(
+
Hello World
)
- const portal = await find('#portal')
- expect(portal.getAttribute('dir')).to.equal('ltr')
+ const portal = screen.getByTestId('portal')
+
+ expect(portal).toHaveAttribute('dir', 'ltr')
})
it('should not render if children are empty', async () => {
- await mount()
- const portal = await find('#portal', { expectEmpty: true })
- expect(portal).to.not.exist()
+ render()
+ const portal = screen.queryByTestId('portal')
+
+ expect(portal).not.toBeInTheDocument()
})
describe('without a mountNode prop', () => {
it('should render nothing when closed', async () => {
- await mount(Hello World)
- const portal = await find('#portal', { expectEmpty: true })
- expect(portal).to.not.exist()
+ render(Hello World)
+ const portal = screen.queryByTestId('portal')
+
+ expect(portal).not.toBeInTheDocument()
})
it('should render children and have a node with a parent when open', async () => {
- const onKeyDown = stub()
-
- await mount(
-
+ const onKeyDown = vi.fn()
+ render(
+
)
+ const portal = screen.getByTestId('portal')
+ const button = screen.getByRole('button', { name: 'Hello World' })
- const portal = await find('#portal')
- const button = await find('button:label(Hello World)')
-
- await button.keyDown('Enter')
+ await userEvent.type(button, '{enter}')
- expect(onKeyDown).to.have.been.called()
+ await waitFor(() => {
+ expect(onKeyDown).toHaveBeenCalled()
+ })
- expect(portal.getParentNode()).to.equal(button.getOwnerDocument().body)
+ expect(portal).toContainElement(button)
})
})
describe('when a mountNode prop is provided', () => {
it('should render nothing when closed', async () => {
- await mount(
+ render(
document.getElementById('portal-mount-node')!}
- id="portal"
+ data-testid="portal"
>
Hello World
)
- const portal = await find('#portal', { expectEmpty: true })
+ const portal = screen.queryByTestId('portal')
- expect(portal).to.not.exist()
+ expect(portal).not.toBeInTheDocument()
})
it('should render children and have a node with a parent when open', async () => {
@@ -139,15 +152,15 @@ describe(``, async () => {
mountNode.setAttribute('id', 'portal-mount-node')
document.body.appendChild(mountNode)
- await mount(
-
+ render(
+
Hello World
)
+ const portal = screen.getByTestId('portal')
- const portal = await find('#portal')
-
- expect(portal).to.have.exactly(1).ancestors('#portal-mount-node')
+ expect(portal.parentElement).toBe(mountNode)
+ expect(mountNode.parentElement).toBe(document.body)
})
})
})
diff --git a/packages/ui-portal/tsconfig.build.json b/packages/ui-portal/tsconfig.build.json
index a1f0615094..405820b9e7 100644
--- a/packages/ui-portal/tsconfig.build.json
+++ b/packages/ui-portal/tsconfig.build.json
@@ -7,26 +7,12 @@
},
"include": ["src"],
"references": [
- {
- "path": "../ui-babel-preset/tsconfig.build.json"
- },
- {
- "path": "../ui-test-utils/tsconfig.build.json"
- },
- {
- "path": "../shared-types/tsconfig.build.json"
- },
- {
- "path": "../ui-i18n/tsconfig.build.json"
- },
- {
- "path": "../ui-prop-types/tsconfig.build.json"
- },
- {
- "path": "../ui-react-utils/tsconfig.build.json"
- },
- {
- "path": "../ui-dom-utils/tsconfig.build.json"
- }
+ { "path": "../ui-babel-preset/tsconfig.build.json" },
+ { "path": "../shared-types/tsconfig.build.json" },
+ { "path": "../ui-i18n/tsconfig.build.json" },
+ { "path": "../ui-prop-types/tsconfig.build.json" },
+ { "path": "../ui-react-utils/tsconfig.build.json" },
+ { "path": "../ui-dom-utils/tsconfig.build.json" },
+ { "path": "../ui-axe-check/tsconfig.build.json" }
]
}