From 5ef95c0dfe43b490d26d11df1834ed3650426176 Mon Sep 17 00:00:00 2001 From: Matyas Forian-Szabo Date: Tue, 4 Aug 2026 21:59:29 +0200 Subject: [PATCH 1/8] test: run the whole Vitest suite in a real browser MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The suite was split across two Vitest projects: a `web` project running most tests in jsdom, and a `browser` project running a handful of packages in a real Chromium via Playwright. jsdom's approximations meant tests could pass while the component was broken in a browser (no layout, no real focus, no computed styles), so the `browser` project now owns every `packages/**/__tests__` file and the jsdom project is gone. - collapse the `web` and `browser` projects into one `browser` project and drop the per-package include/exclude lists that kept them from double-running - delete `vitest.setup.ts` — its jsdom shims (the `ResizeObserver` mock and the hardcoded `16px` root font size) are unnecessary in a real browser - `vitest.setup.browser.ts` restores mocks after each test; jsdom's setup did this and browser tests need it too, otherwise a `console.warn` spy from one test observes the next one's output - stop excluding `src/**/__tests__/**` from the packages' `tsconfig.build.json` and have the root `tsconfig.json` extend `tsconfig.build.json`, so test files are type-checked with the same options as the source - collapse the two Vitest CI jobs into one Co-Authored-By: Claude Opus 5 (1M context) --- .github/workflows/pr-validation.yml | 21 +------ package.json | 9 +-- packages/debounce/tsconfig.build.json | 1 - packages/ui-a11y-utils/tsconfig.build.json | 1 - packages/ui-dom-utils/tsconfig.build.json | 1 - packages/ui-modal/tsconfig.build.json | 1 + packages/ui-theme-tokens/tsconfig.build.json | 1 - packages/ui-utils/tsconfig.build.json | 1 - packages/uid/tsconfig.build.json | 1 - tsconfig.json | 28 +-------- vitest.config.mts | 65 +++++--------------- vitest.setup.browser.ts | 7 +++ vitest.setup.ts | 54 ---------------- 13 files changed, 31 insertions(+), 160 deletions(-) delete mode 100644 vitest.setup.ts diff --git a/.github/workflows/pr-validation.yml b/.github/workflows/pr-validation.yml index 935b1d444b..5647ecccfa 100644 --- a/.github/workflows/pr-validation.yml +++ b/.github/workflows/pr-validation.yml @@ -22,23 +22,7 @@ jobs: - name: Lint code run: pnpm run lint:changes vitest-tests: - name: Vitest unit tests - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v6 - - uses: pnpm/action-setup@v6 - - uses: actions/setup-node@v6 - with: - node-version: '24' - cache: 'pnpm' - - name: Install dependencies - run: pnpm install --frozen-lockfile - - name: Bootstrap project - run: pnpm run bootstrap - - name: Run vitest unit tests - run: pnpm run test:vitest - vitest-browser-tests: - name: Vitest browser tests + name: Vitest tests runs-on: ubuntu-latest steps: - uses: actions/checkout@v6 @@ -54,7 +38,7 @@ jobs: - name: Bootstrap project run: pnpm run bootstrap - name: Run vitest browser tests - run: pnpm run test:browser + run: pnpm run test:vitest cypress: name: Cypress component tests runs-on: ubuntu-latest @@ -73,4 +57,3 @@ jobs: run: pnpm run bootstrap - name: Run Cypress components tests run: pnpm run cy:component - diff --git a/package.json b/package.json index 8377a9546d..1e8e3217e2 100644 --- a/package.json +++ b/package.json @@ -21,12 +21,9 @@ "dev": "pnpm -C packages/__docs__ start:watch", "dev:verbose": "DOCS_VERBOSE=1 pnpm dev", "cy:component": "cypress run --component", - "test:vitest": "vitest --watch=false --project web --project node", - "test:vitest-watch": "vitest --project web --project node", - "playwright:install": "playwright install chromium", - "test:browser": "pnpm run playwright:install && vitest --project browser --watch=false", - "test:browser-watch": "pnpm run playwright:install && vitest --project browser", - "test:browser-ui": "pnpm run playwright:install && vitest --project browser --browser.headless=false --ui", + "test:vitest": "playwright install chromium && vitest --watch=false --project browser --project node", + "test:vitest-watch": "playwright install chromium && vitest --project browser --project node", + "test:vitest-browser-ui": "playwright install chromium && vitest --project browser --browser.headless=false --ui", "lint": "pnpm -r --stream lint", "lint:changes": "pnpm run lint -- --since HEAD^", "lint:fix": "pnpm -r --stream lint:fix", diff --git a/packages/debounce/tsconfig.build.json b/packages/debounce/tsconfig.build.json index d913175169..3deeb236ec 100644 --- a/packages/debounce/tsconfig.build.json +++ b/packages/debounce/tsconfig.build.json @@ -6,7 +6,6 @@ "rootDir": "./src" }, "include": ["src"], - "exclude": ["src/**/__tests__/**/*"], "references": [ { "path": "../ui-babel-preset/tsconfig.build.json" diff --git a/packages/ui-a11y-utils/tsconfig.build.json b/packages/ui-a11y-utils/tsconfig.build.json index 7d54d18e6a..8e0b5aeb55 100644 --- a/packages/ui-a11y-utils/tsconfig.build.json +++ b/packages/ui-a11y-utils/tsconfig.build.json @@ -6,7 +6,6 @@ "rootDir": "./src" }, "include": ["src"], - "exclude": ["src/**/__tests__/**/*"], "references": [ { "path": "../console/tsconfig.build.json" }, { "path": "../ui-a11y-content/tsconfig.build.json" }, diff --git a/packages/ui-dom-utils/tsconfig.build.json b/packages/ui-dom-utils/tsconfig.build.json index 34e9bdac72..9f56a996ce 100644 --- a/packages/ui-dom-utils/tsconfig.build.json +++ b/packages/ui-dom-utils/tsconfig.build.json @@ -6,7 +6,6 @@ "rootDir": "./src" }, "include": ["src"], - "exclude": ["src/**/__tests__/**/*"], "references": [ { "path": "../ui-babel-preset/tsconfig.build.json" }, { "path": "../console/tsconfig.build.json" }, diff --git a/packages/ui-modal/tsconfig.build.json b/packages/ui-modal/tsconfig.build.json index 6bb917c4a1..e081e954ab 100644 --- a/packages/ui-modal/tsconfig.build.json +++ b/packages/ui-modal/tsconfig.build.json @@ -22,6 +22,7 @@ { "path": "../ui-babel-preset/tsconfig.build.json" }, { "path": "../ui-color-utils/tsconfig.build.json" }, { "path": "../ui-position/tsconfig.build.json" }, + { "path": "../ui-tooltip/tsconfig.build.json" }, { "path": "../ui-themes/tsconfig.build.json" } ] } diff --git a/packages/ui-theme-tokens/tsconfig.build.json b/packages/ui-theme-tokens/tsconfig.build.json index c8f73fb00f..3bde7b593c 100644 --- a/packages/ui-theme-tokens/tsconfig.build.json +++ b/packages/ui-theme-tokens/tsconfig.build.json @@ -6,7 +6,6 @@ "rootDir": "./src" }, "include": ["src"], - "exclude": ["src/**/__tests__/**/*"], "references": [ { "path": "../ui-babel-preset/tsconfig.build.json" diff --git a/packages/ui-utils/tsconfig.build.json b/packages/ui-utils/tsconfig.build.json index 26a05380fd..53018918ae 100644 --- a/packages/ui-utils/tsconfig.build.json +++ b/packages/ui-utils/tsconfig.build.json @@ -6,7 +6,6 @@ "rootDir": "./src" }, "include": ["src"], - "exclude": ["src/**/__tests__/**/*"], "references": [ { "path": "../ui-babel-preset/tsconfig.build.json" diff --git a/packages/uid/tsconfig.build.json b/packages/uid/tsconfig.build.json index d913175169..3deeb236ec 100644 --- a/packages/uid/tsconfig.build.json +++ b/packages/uid/tsconfig.build.json @@ -6,7 +6,6 @@ "rootDir": "./src" }, "include": ["src"], - "exclude": ["src/**/__tests__/**/*"], "references": [ { "path": "../ui-babel-preset/tsconfig.build.json" diff --git a/tsconfig.json b/tsconfig.json index 70e26a7989..41a7d51002 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,32 +1,8 @@ { - "compilerOptions": { - "pretty": false, - "module": "Node16", - "moduleResolution": "node16", - "declaration": true, - "declarationMap": true, - "emitDeclarationOnly": true, - "experimentalDecorators": true, - "allowJs": true, - "isolatedModules": true, - "jsx": "react-jsx", - "jsxImportSource": "@emotion/react", - "target": "ES6", - "esModuleInterop": true, - "skipLibCheck": true, - "forceConsistentCasingInFileNames": true, - "checkJs": false, - "noImplicitAny": true, - "strict": true, - "noImplicitReturns": true, - "noFallthroughCasesInSwitch": true, - "noUnusedLocals": true, - "noUnusedParameters": true, - "lib": ["ES2023", "DOM", "DOM.Iterable"], - "allowSyntheticDefaultImports": true - }, + "extends": "./tsconfig.build.json", "exclude": [ "regression-test", + "cypress.config.ts", "cypress", "node_modules", "**/__testfixtures__" diff --git a/vitest.config.mts b/vitest.config.mts index aec897ec5a..bdddb8cf46 100644 --- a/vitest.config.mts +++ b/vitest.config.mts @@ -24,7 +24,7 @@ /// -import { defineConfig, configDefaults } from 'vitest/config' +import { defineConfig } from 'vitest/config' import { playwright } from '@vitest/browser-playwright' import path from 'path' import fs from 'fs' @@ -37,6 +37,8 @@ const momentDir = path.dirname( ) const momentWithLocales = path.join(momentDir, 'min', 'moment-with-locales.js') + + // Build Vite resolve aliases for every @instructure/* workspace package, // pointing bare/subpath specifiers at TypeScript source. // This lets browser-mode tests run without pre-building the library — Vite @@ -86,9 +88,7 @@ function getWorkspaceAliases() { find: `${pkgName}/src`, replacement: path.join(pkgPath, 'src') }) - } - return aliases } @@ -108,31 +108,8 @@ export default defineConfig({ } ], projects: [ + // Node script tests { - // DOM-based unit tests - test: { - // Allows using APIs like Jest without importing them - globals: true, - include: ['**/__tests__/**/*.test.tsx'], - // these packages' tests run in the `browser` project, - // so exclude them here to avoid double-running. - exclude: [ - ...configDefaults.exclude, - 'packages/emotion/**', - 'packages/ui-a11y-content/**', - 'packages/ui-a11y-utils/**', - 'packages/ui-alerts/**', - 'packages/ui-avatar/**', - 'packages/ui-badge/**', - 'packages/ui-dialog/**' - ], - environment: 'jsdom', - setupFiles: './vitest.setup.ts', - name: { label: 'web', color: 'blue' } - } - }, - { - // tests for node scripts test: { globals: true, include: ['**/__node_tests__/**/*.test.{ts,tsx}'], @@ -140,30 +117,11 @@ export default defineConfig({ name: { label: 'node', color: 'magenta' } } }, + // Real browser tests { - // Real-browser component tests (Vitest browser mode via Playwright). - // Run just these with: pnpm exec vitest --project browser - resolve: { - alias: [ - // Bare `moment` -> the all-locales build (see above). Matches - // `moment` exactly, never `moment-timezone` or `moment/`. - { find: /^moment$/, replacement: momentWithLocales }, - // `moment/` -> resolved package dir (e.g. moment/locale/*). - { find: /^moment\/(.*)$/, replacement: path.join(momentDir, '$1') }, - ...getWorkspaceAliases() - ] - }, test: { globals: true, // TODO try to set it to false - include: [ - 'packages/emotion/**/__tests__/**/*.test.tsx', - 'packages/ui-a11y-content/**/__tests__/**/*.test.tsx', - 'packages/ui-a11y-utils/**/__tests__/**/*.test.tsx', - 'packages/ui-alerts/**/__tests__/**/*.test.tsx', - 'packages/ui-avatar/**/__tests__/**/*.test.tsx', - 'packages/ui-badge/**/__tests__/**/*.test.tsx', - 'packages/ui-dialog/**/__tests__/**/*.test.tsx' - ], + include: ['packages/**/__tests__/**/*.test.tsx'], setupFiles: './vitest.setup.browser.ts', name: { label: 'browser', color: 'green' }, browser: { @@ -173,9 +131,18 @@ export default defineConfig({ instances: [{ browser: 'chromium' }], screenshotFailures: false } + }, + resolve: { + alias: [ + // Bare `moment` -> the all-locales build. Matches + // `moment` exactly, never `moment-timezone` or `moment/`. + { find: /^moment$/, replacement: momentWithLocales }, + // `moment/` -> resolved package dir (e.g. moment/locale/*). + { find: /^moment\/(.*)$/, replacement: path.join(momentDir, '$1') }, + ...getWorkspaceAliases() + ] } } ] - } }) diff --git a/vitest.setup.browser.ts b/vitest.setup.browser.ts index 67f282f3c0..508e9c8187 100644 --- a/vitest.setup.browser.ts +++ b/vitest.setup.browser.ts @@ -24,6 +24,7 @@ // Setup for the `browser` project (real-browser tests via vitest-browser). import '@testing-library/jest-dom/vitest' +import { vi } from 'vitest' // @instructure/console only outputs logs if process.env.NODE_ENV !== 'production' // these messages are sometimes used in test assertions @@ -32,3 +33,9 @@ if (typeof globalThis.process === 'undefined') { } else if (!globalThis.process.env) { globalThis.process.env = { NODE_ENV: 'test' } } + +// Spies (e.g. on `console.warn`) would otherwise stay installed for the rest of +// the file, so a later test could see calls made by an earlier one. +afterEach(() => { + vi.restoreAllMocks() +}) diff --git a/vitest.setup.ts b/vitest.setup.ts deleted file mode 100644 index c8f2495163..0000000000 --- a/vitest.setup.ts +++ /dev/null @@ -1,54 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2015 - present Instructure, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -// https://www.npmjs.com/package/@testing-library/jest-dom#with-vitest -// this allows custom jest matchers to be used -import '@testing-library/jest-dom/vitest' -import { cleanup } from '@testing-library/react' -import { vi } from 'vitest' - -const originalResizeObserver = global.ResizeObserver - -beforeAll(() => { - const ResizeObserverMock = vi.fn(function () { - return { - observe: vi.fn(), - unobserve: vi.fn(), - disconnect: vi.fn() - } - }) - vi.stubGlobal('ResizeObserver', ResizeObserverMock) - // This is needed because getFontSize() reads the font size from here, and - // jest-dom does not give this a value, so getFontSize() will return NaN - document.documentElement.style.fontSize = '16px' -}) - -afterAll(() => { - global.ResizeObserver = originalResizeObserver -}) - -afterEach(() => { - cleanup() - vi.restoreAllMocks() -}) From ba509197db49e296bb9a8ec6b361f0d273b8b247 Mon Sep 17 00:00:00 2001 From: Matyas Forian-Szabo Date: Tue, 4 Aug 2026 22:15:09 +0200 Subject: [PATCH 2/8] test(many): convert every test to the vitest-browser API Mechanical, codemod-driven conversion of all 181 test files off React Testing Library and onto the vitest-browser API. No test's intent changes here; the follow-up commits deal with the cases that need real thought. The substitutions: - `render` now comes from `vitest-browser-react` and returns a promise, so every call becomes `await render(...)`. - `screen.getBy*` -> `page.getBy*(...).element()`, `getAllBy*` -> `.elements()`, `queryBy*` -> `.query()`; vitest-browser locators are lazy, so the `.element()` call is what actually resolves the node. - `userEvent` now comes from `vitest/browser` - `waitFor` -> `vi.waitFor` - `fireEvent` now comes from `@testing-library/dom` directly - `import '@testing-library/jest-dom'` and `import { describe, it, expect, ... } from 'vitest'` becomes an explicit Co-Authored-By: Claude Opus 5 (1M context) --- .../Billboard/__tests__/Billboard.test.tsx | 74 ++-- .../Breadcrumb/__tests__/Breadcrumb.test.tsx | 34 +- .../__tests__/BreadcrumbLink.test.tsx | 45 ++- .../BaseButton/__tests__/BaseButton.test.tsx | 188 +++++---- .../src/Button/__tests__/Button.test.tsx | 209 +++++----- .../__tests__/CloseButton.test.tsx | 16 +- .../__tests__/CondensedButton.test.tsx | 82 ++-- .../IconButton/__tests__/IconButton.test.tsx | 86 ++-- .../__tests__/ToggleButton.test.tsx | 66 +-- .../src/Byline/__tests__/Byline.test.tsx | 19 +- .../src/Calendar/__tests__/Calendar.test.tsx | 115 +++--- .../src/Calendar/__tests__/Day.test.tsx | 53 ++- .../src/Checkbox/__tests__/Checkbox.test.tsx | 70 ++-- .../__tests__/CheckboxFacade.test.tsx | 16 +- .../Checkbox/__tests__/ToggleFacade.test.tsx | 14 +- .../__tests__/CheckboxGroup.test.tsx | 38 +- .../__tests__/ColorContrast.test.tsx | 76 ++-- .../__tests__/ColorIndicator.test.tsx | 11 +- .../ColorMixer/__tests__/ColorMixer.test.tsx | 175 ++++---- .../__tests__/ColorPicker.test.tsx | 270 +++++++------ .../__tests__/ColorPreset.test.tsx | 52 +-- .../DateInput/__tests__/DateInput.test.tsx | 124 +++--- .../DateInput2/__tests__/DateInput2.test.tsx | 128 +++--- .../__tests__/DateTimeInput.test.tsx | 284 ++++++------- .../src/__tests__/addEventListener.test.tsx | 10 +- .../__tests__/addInputModeListener.test.tsx | 13 +- .../addPositionChangeListener.test.tsx | 9 +- .../src/__tests__/findTabbable.test.tsx | 12 +- .../__tests__/getCSSStyleDeclaration.test.tsx | 3 +- .../src/__tests__/getClassList.test.tsx | 10 +- .../src/__tests__/getFontSize.test.tsx | 10 +- .../src/__tests__/getOffsetParents.test.tsx | 8 +- .../src/__tests__/getScrollParents.test.tsx | 16 +- .../src/__tests__/isCustomElement.test.tsx | 2 +- .../src/__tests__/isVisible.test.tsx | 41 +- .../__tests__/requestAnimationFrame.test.tsx | 5 +- .../__tests__/DrawerContent.test.tsx | 26 +- .../__tests__/DrawerLayout.test.tsx | 38 +- .../__tests__/DrawerTray.test.tsx | 30 +- .../Drilldown/__tests__/Drilldown.test.tsx | 171 ++++---- .../__tests__/DrilldownGroup.test.tsx | 184 ++++----- .../__tests__/DrilldownOption.test.tsx | 135 +++---- .../__tests__/DrilldownPage.test.tsx | 85 ++-- .../__tests__/DrilldownSeparator.test.tsx | 13 +- .../src/Editable/__tests__/Editable.test.tsx | 70 ++-- .../__tests__/InPlaceEdit.test.tsx | 60 +-- .../v1/__tests__/Expandable.test.tsx | 29 +- .../src/FileDrop/__tests__/FileDrop.test.tsx | 27 +- .../ui-flex/src/Flex/__tests__/Flex.test.tsx | 57 ++- .../src/Flex/__tests__/FlexItem.test.tsx | 27 +- .../Focusable/__tests__/Focusable.test.tsx | 101 ++--- .../FormField/__tests__/FormField.test.tsx | 25 +- .../__tests__/FormFieldGroup.test.tsx | 55 +-- .../__tests__/FormFieldLabel.test.tsx | 17 +- .../__tests__/FormFieldLayout.test.tsx | 15 +- .../__tests__/FormFieldMessage.test.tsx | 14 +- .../__tests__/FormFieldMessages.test.tsx | 21 +- .../ui-grid/src/Grid/__tests__/Grid.test.tsx | 17 +- .../src/GridCol/__tests__/Grid.test.tsx | 9 +- .../src/Heading/__tests__/Heading.test.tsx | 19 +- .../__tests__/ApplyLocale.test.tsx | 9 +- .../ui-i18n/src/__tests__/DateTime.test.tsx | 3 +- .../ui-i18n/src/__tests__/Locale.test.tsx | 3 +- .../textDirectionContextConsumer.test.tsx | 18 +- .../__tests__/IconPropsProvider.test.tsx | 55 +-- .../ui-img/src/Img/__tests__/Img.test.tsx | 25 +- .../ui-link/src/Link/__tests__/Link.test.tsx | 166 ++++---- .../InlineList/__tests__/InlineList.test.tsx | 20 +- .../__tests__/InlineListItem.test.tsx | 18 +- .../ui-list/src/List/__tests__/List.test.tsx | 18 +- .../src/List/__tests__/ListItem.test.tsx | 14 +- .../ui-menu/src/Menu/__tests__/Menu.test.tsx | 96 ++--- .../src/Menu/__tests__/MenuItem.test.tsx | 81 ++-- .../src/Menu/__tests__/MenuItemGroup.test.tsx | 65 +-- .../src/Metric/__tests__/Metric.test.tsx | 30 +- .../__tests__/MetricGroup.test.tsx | 26 +- .../src/Modal/__tests__/Modal.test.tsx | 73 ++-- .../src/Modal/__tests__/ModalBody.test.tsx | 43 +- .../src/Modal/__tests__/ModalFooter.test.tsx | 10 +- .../src/Modal/__tests__/ModalHeader.test.tsx | 18 +- .../Transition/__tests__/Transition.test.tsx | 49 +-- .../src/AppNav/__tests__/AppNav.test.tsx | 33 +- .../src/AppNav/__tests__/Item.test.tsx | 33 +- .../__tests__/NumberInput.test.tsx | 94 ++--- .../src/Options/__tests__/Item.test.tsx | 46 ++- .../src/Options/__tests__/Options.test.tsx | 37 +- .../src/Mask/__tests__/Mask.test.tsx | 25 +- .../src/Overlay/__tests__/Overlay.test.tsx | 34 +- .../src/Pages/__tests__/Page.test.tsx | 7 +- .../src/Pages/__tests__/Pages.test.tsx | 25 +- .../Pagination/__tests__/Pagination.test.tsx | 378 ++++++++++-------- .../__tests__/PaginationArrowButton.test.tsx | 15 +- .../__tests__/PaginationButton.test.tsx | 27 +- .../__tests__/PaginationPageInput.test.tsx | 33 +- .../ui-pill/src/Pill/__tests__/Pill.test.tsx | 16 +- .../src/Popover/__tests__/Popover.test.tsx | 107 ++--- .../src/Portal/__tests__/Portal.test.tsx | 49 ++- .../src/Position/__tests__/Position.test.tsx | 130 +++--- .../mirrorHorizontalPlacement.test.tsx | 2 +- .../src/__tests__/mirrorPlacement.test.tsx | 2 +- .../__tests__/ProgressBar.test.tsx | 23 +- .../__tests__/ProgressCircle.test.tsx | 13 +- .../RadioInput/__tests__/RadioInput.test.tsx | 52 +-- .../__tests__/RadioInputGroup.test.tsx | 36 +- .../RangeInput/__tests__/RangeInput.test.tsx | 40 +- .../src/Rating/__tests__/Rating.test.tsx | 46 ++- .../RatingIcon/__tests__/RatingIcon.test.tsx | 19 +- .../__tests__/DeterministicIdContext.test.tsx | 33 +- .../src/__tests__/callRenderProp.test.tsx | 24 +- .../src/__tests__/getInteraction.test.tsx | 2 +- .../src/__tests__/omitProps.test.tsx | 2 +- .../src/__tests__/passthroughProps.test.tsx | 2 +- .../src/__tests__/pickProps.test.tsx | 2 +- .../src/__tests__/safeCloneElement.test.tsx | 22 +- .../src/__tests__/useDeterministicId.test.tsx | 65 +-- .../Responsive/__tests__/Responsive.test.tsx | 15 +- .../src/Select/__tests__/Select.test.tsx | 289 ++++++------- .../Selectable/__tests__/Selectable.test.tsx | 213 +++++----- .../__tests__/NavigationItem.test.tsx | 12 +- .../SideNavBar/__tests__/SideNavBar.test.tsx | 41 +- .../__tests__/SimpleSelect.test.tsx | 126 +++--- .../__tests__/SourceCodeEditor.test.tsx | 73 ++-- .../src/Spinner/__tests__/Spinner.test.tsx | 30 +- .../InlineSVG/__tests__/InlineSVG.test.tsx | 86 ++-- .../InlineSVG/__tests__/sanitizeSvg.test.tsx | 2 +- .../src/SVGIcon/__tests__/SVGIcon.test.tsx | 14 +- .../src/Table/__tests__/Table.test.tsx | 73 ++-- .../ui-tabs/src/Tabs/__tests__/Panel.test.tsx | 14 +- .../ui-tabs/src/Tabs/__tests__/Tab.test.tsx | 63 ++- .../ui-tabs/src/Tabs/__tests__/Tabs.test.tsx | 83 ++-- .../ui-tag/src/Tag/__tests__/Tag.test.tsx | 27 +- .../src/TextArea/__tests__/TextArea.test.tsx | 78 ++-- .../TextInput/__tests__/TextInput.test.tsx | 70 ++-- .../ui-text/src/Text/__tests__/Text.test.tsx | 10 +- .../ui-themes/src/__tests__/themes.test.tsx | 2 +- .../TimeSelect/__tests__/TimeSelect.test.tsx | 104 ++--- .../__tests__/ToggleDetails.test.tsx | 45 +-- .../__tests__/ToggleGroup.test.tsx | 41 +- .../src/Tooltip/__tests__/Tooltip.test.tsx | 49 ++- .../ui-tray/src/Tray/__tests__/Tray.test.tsx | 61 +-- .../__tests__/TreeBrowser.test.tsx | 122 +++--- .../TreeBrowser/__tests__/TreeButton.test.tsx | 37 +- .../__tests__/TreeCollection.test.tsx | 57 ++- .../TreeBrowser/__tests__/TreeNode.test.tsx | 15 +- .../__tests__/TruncateList.test.tsx | 17 +- .../__tests__/TruncateText.test.tsx | 17 +- .../TruncateText/__tests__/cleanData.test.tsx | 3 +- .../__tests__/cleanString.test.tsx | 3 +- .../__tests__/measureText.test.tsx | 35 +- .../ui-utils/src/__tests__/camelize.test.tsx | 2 +- .../src/__tests__/cloneArray.test.tsx | 2 +- .../__tests__/createChainedFunction.test.tsx | 3 +- .../src/__tests__/generateId.test.tsx | 2 +- packages/ui-utils/src/__tests__/hash.test.tsx | 2 +- .../ui-utils/src/__tests__/mergeDeep.test.tsx | 2 +- packages/ui-utils/src/__tests__/ms.test.tsx | 2 +- .../ui-utils/src/__tests__/parseUnit.test.tsx | 2 +- .../ui-utils/src/__tests__/pascalize.test.tsx | 2 +- packages/ui-utils/src/__tests__/px.test.tsx | 2 +- .../ui-utils/src/__tests__/safeHref.test.tsx | 3 +- .../src/__tests__/safeLinkProps.test.tsx | 3 +- .../ui-utils/src/__tests__/within.test.tsx | 2 +- .../__tests__/ContextView.test.tsx | 10 +- .../ui-view/src/View/__tests__/View.test.tsx | 64 +-- packages/uid/src/__tests__/uid.test.tsx | 2 +- 165 files changed, 4126 insertions(+), 3849 deletions(-) diff --git a/packages/ui-billboard/src/Billboard/__tests__/Billboard.test.tsx b/packages/ui-billboard/src/Billboard/__tests__/Billboard.test.tsx index b0d5af63fe..f8126399ea 100644 --- a/packages/ui-billboard/src/Billboard/__tests__/Billboard.test.tsx +++ b/packages/ui-billboard/src/Billboard/__tests__/Billboard.test.tsx @@ -22,13 +22,13 @@ * SOFTWARE. */ -import { fireEvent, render, screen } from '@testing-library/react' -import { vi } from 'vitest' -import userEvent from '@testing-library/user-event' import { IconUserLine } from '@instructure/ui-icons' import { Billboard } from '@instructure/ui-billboard/latest' import { runAxeCheck } from '@instructure/ui-axe-check' -import '@testing-library/jest-dom' +import { fireEvent } from '@testing-library/dom' +import { render } from 'vitest-browser-react' +import { page, userEvent } from 'vitest/browser' +import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest' const TEST_HEADING = 'test-heading' const TEST_MESSAGE = 'test-message' @@ -54,14 +54,14 @@ describe('', () => { consoleErrorMock.mockRestore() }) - it('should render', () => { - const { container } = render() + it('should render', async () => { + const { container } = await render() expect(container.firstChild).toBeInTheDocument() }) it('should be accessible', async () => { - const { container } = render( + const { container } = await render( ', () => { expect(axeCheck).toBe(true) }) - it('should render a heading with the correct tag', () => { - render() - const heading = screen.getByText(TEST_HEADING) + it('should render a heading with the correct tag', async () => { + await render() + const heading = page.getByText(TEST_HEADING).element() expect(heading).toBeInTheDocument() expect(heading.tagName).toBe('H2') }) - it('renders as a link if it has an href prop', () => { - render() + it('renders as a link if it has an href prop', async () => { + await render() - const link = screen.getByRole('link') + const link = page.getByRole('link').element() expect(link).toBeInTheDocument() expect(link).toHaveAttribute('href', TEST_LINK) }) - it('renders as a button and responds to onClick event', () => { + it('renders as a button and responds to onClick event', async () => { const onClick = vi.fn() - render() - const button = screen.getByRole('button') + await render() + const button = page.getByRole('button').element() fireEvent.click(button) @@ -105,18 +105,18 @@ describe('', () => { it('should render message when passed a node', async () => { const messageNode = {TEST_MESSAGE} - render() - const messageElement = screen.getByText(TEST_MESSAGE) + await render() + const messageElement = page.getByText(TEST_MESSAGE).element() expect(messageElement).toBeInTheDocument() expect(messageElement.tagName).toBe('SPAN') }) - it('should render message passed a function', () => { + it('should render message passed a function', async () => { const messageNode = {TEST_MESSAGE} - render( messageNode} />) - const messageElement = screen.getByText(TEST_MESSAGE) + await render( messageNode} />) + const messageElement = page.getByText(TEST_MESSAGE).element() expect(messageElement).toBeInTheDocument() expect(messageElement.tagName).toBe('SPAN') @@ -124,25 +124,25 @@ describe('', () => { }) describe('when disabled', () => { - it('should apply aria-disabled to link', () => { - render() - const link = screen.getByRole('link') + it('should apply aria-disabled to link', async () => { + await render() + const link = page.getByRole('link').element() expect(link).toHaveAttribute('aria-disabled', 'true') }) - it('should not be clickable', () => { - render() - const button = screen.getByRole('button') + it('should not be clickable', async () => { + await render() + const button = page.getByRole('button').element() expect(button).toHaveAttribute('aria-disabled', 'true') }) }) describe('when readOnly', () => { - it('should apply aria-disabled', () => { - render() - const link = screen.getByRole('link') + it('should apply aria-disabled', async () => { + await render() + const link = page.getByRole('link').element() expect(link).toHaveAttribute('aria-disabled', 'true') }) @@ -150,8 +150,8 @@ describe('', () => { it('should not be clickable', async () => { const onClick = vi.fn() - render() - const button = screen.getByRole('button') + await render() + const button = page.getByRole('button').element() await userEvent.click(button) @@ -160,17 +160,17 @@ describe('', () => { }) describe('when passing down props to View', () => { - it('should support an elementRef prop', () => { + it('should support an elementRef prop', async () => { const elementRef = vi.fn() - render() - const link = screen.getByRole('link') + await render() + const link = page.getByRole('link').element() expect(elementRef).toHaveBeenCalledWith(link) }) - it('should support an `as` prop', () => { - const { container } = render() + it('should support an `as` prop', async () => { + const { container } = await render() const billboardAsEm = container.querySelector('em') expect(billboardAsEm).toBeInTheDocument() diff --git a/packages/ui-breadcrumb/src/Breadcrumb/__tests__/Breadcrumb.test.tsx b/packages/ui-breadcrumb/src/Breadcrumb/__tests__/Breadcrumb.test.tsx index d4e89a563a..f5dfca33ed 100644 --- a/packages/ui-breadcrumb/src/Breadcrumb/__tests__/Breadcrumb.test.tsx +++ b/packages/ui-breadcrumb/src/Breadcrumb/__tests__/Breadcrumb.test.tsx @@ -22,10 +22,10 @@ * SOFTWARE. */ -import { render, screen } from '@testing-library/react' -import { vi } from 'vitest' import type { MockInstance } from 'vitest' -import '@testing-library/jest-dom' +import { render } from 'vitest-browser-react' +import { page } from 'vitest/browser' +import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest' import { runAxeCheck } from '@instructure/ui-axe-check' import { Breadcrumb } from '@instructure/ui-breadcrumb/latest' @@ -54,7 +54,7 @@ describe('', () => { }) it('should be accessible', async () => { - const { container } = render( + const { container } = await render( {TEST_TEXT_01} {TEST_TEXT_02} @@ -65,21 +65,21 @@ describe('', () => { expect(axeCheck).toBe(true) }) - it('should render the label as an aria-label attribute', () => { - render( + it('should render the label as an aria-label attribute', async () => { + await render( {TEST_TEXT_01} ) - const label = screen.getByLabelText(TEST_LABEL) + const label = page.getByLabelText(TEST_LABEL).element() expect(label).toBeInTheDocument() expect(label).toHaveAttribute('aria-label', TEST_LABEL) }) - it('should render an icon as a separator', () => { - const { container } = render( + it('should render an icon as a separator', async () => { + const { container } = await render( {TEST_TEXT_01} {TEST_TEXT_02} @@ -91,8 +91,8 @@ describe('', () => { expect(icon).toHaveAttribute('aria-hidden', 'true') }) - it('should add aria-current="page" to the last element by default', () => { - const { container } = render( + it('should add aria-current="page" to the last element by default', async () => { + const { container } = await render( {TEST_TEXT_01} {TEST_TEXT_02} @@ -106,8 +106,8 @@ describe('', () => { expect(lastLink).toHaveAttribute('aria-current', 'page') }) - it('should add aria-current="page" to the element if isCurrent is true', () => { - const { container } = render( + it('should add aria-current="page" to the element if isCurrent is true', async () => { + const { container } = await render( {TEST_TEXT_01} @@ -127,8 +127,8 @@ describe('', () => { // This test fails because the @instructure/ui-breadcrumb/latest import // resolves to compiled output where console.warn is stripped by the // babel preset (removeConsole in production builds). - // it('should throw a warning when multiple elements have isCurrent set to true', () => { - // render( + // it('should throw a warning when multiple elements have isCurrent set to true', async () => { + // await render( // // // {TEST_TEXT_01} @@ -144,8 +144,8 @@ describe('', () => { // ) // }) - it('should not add aria-current="page" to the last element if it set to false', () => { - const { container } = render( + it('should not add aria-current="page" to the last element if it set to false', async () => { + const { container } = await render( {TEST_TEXT_01} {TEST_TEXT_02} diff --git a/packages/ui-breadcrumb/src/Breadcrumb/__tests__/BreadcrumbLink.test.tsx b/packages/ui-breadcrumb/src/Breadcrumb/__tests__/BreadcrumbLink.test.tsx index 8ca1394242..bab9ec5239 100644 --- a/packages/ui-breadcrumb/src/Breadcrumb/__tests__/BreadcrumbLink.test.tsx +++ b/packages/ui-breadcrumb/src/Breadcrumb/__tests__/BreadcrumbLink.test.tsx @@ -22,9 +22,10 @@ * SOFTWARE. */ -import { fireEvent, render, screen } from '@testing-library/react' -import { vi } from 'vitest' -import '@testing-library/jest-dom' +import { fireEvent } from '@testing-library/dom' +import { render } from 'vitest-browser-react' +import { page } from 'vitest/browser' +import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest' import { runAxeCheck } from '@instructure/ui-axe-check' import { BreadcrumbLink } from '@instructure/ui-breadcrumb/latest' @@ -52,40 +53,44 @@ describe('', () => { consoleErrorMock.mockRestore() }) - it('should render an anchor tag when given a href prop', () => { - render({TEST_TEXT_01}) - const anchor = screen.getByRole('link') + it('should render an anchor tag when given a href prop', async () => { + await render( + {TEST_TEXT_01} + ) + const anchor = page.getByRole('link').element() expect(anchor).toHaveAttribute('href', TEST_LINK) }) - it('should render as a button and respond to onClick event', () => { + it('should render as a button and respond to onClick event', async () => { const onClick = vi.fn() - render({TEST_TEXT_01}) - const button = screen.getByRole('button') + await render( + {TEST_TEXT_01} + ) + const button = page.getByRole('button').element() fireEvent.click(button) expect(onClick).toHaveBeenCalledTimes(1) }) - it('should respond to mouseEnter event when provided with onMouseEnter prop', () => { + it('should respond to mouseEnter event when provided with onMouseEnter prop', async () => { const onMouseEnter = vi.fn() - render( + await render( {TEST_TEXT_01} ) - const link = screen.getByRole('link') + const link = page.getByRole('link').element() fireEvent.mouseEnter(link) expect(onMouseEnter).toHaveBeenCalledTimes(1) }) - it('should allow to prop to pass through', () => { - const { container } = render( + it('should allow to prop to pass through', async () => { + const { container } = await render( {TEST_TEXT_01} ) const link = container.querySelector('a') @@ -94,8 +99,8 @@ describe('', () => { expect(link).toHaveAttribute('to', TEST_TO) }) - it('should not render a link when not given an href prop', () => { - const { container } = render( + it('should not render a link when not given an href prop', async () => { + const { container } = await render( {TEST_TEXT_01} ) const elementWithHref = container.querySelector('[href]') @@ -108,8 +113,8 @@ describe('', () => { expect(span).toHaveTextContent(TEST_TEXT_01) }) - it('should not render a button when not given an onClick prop', () => { - const { container } = render( + it('should not render a button when not given an onClick prop', async () => { + const { container } = await render( {TEST_TEXT_01} ) const button = container.querySelector('button') @@ -121,7 +126,7 @@ describe('', () => { }) it('should meet a11y standards as a link', async () => { - const { container } = render( + const { container } = await render( {TEST_TEXT_01} ) const axeCheck = await runAxeCheck(container) @@ -130,7 +135,7 @@ describe('', () => { }) it('should meet a11y standards as a span', async () => { - const { container } = render( + const { container } = await render( {TEST_TEXT_01} ) const axeCheck = await runAxeCheck(container) diff --git a/packages/ui-buttons/src/BaseButton/__tests__/BaseButton.test.tsx b/packages/ui-buttons/src/BaseButton/__tests__/BaseButton.test.tsx index 6a14b42b08..04076a1056 100644 --- a/packages/ui-buttons/src/BaseButton/__tests__/BaseButton.test.tsx +++ b/packages/ui-buttons/src/BaseButton/__tests__/BaseButton.test.tsx @@ -22,10 +22,10 @@ * SOFTWARE. */ -import { render, screen, waitFor } from '@testing-library/react' -import { vi } from 'vitest' +import { render } from 'vitest-browser-react' +import { page, userEvent } from 'vitest/browser' +import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest' import type { MockInstance } from 'vitest' -import userEvent from '@testing-library/user-event' import { BaseButton } from '@instructure/ui-buttons/latest' import { runAxeCheck } from '@instructure/ui-axe-check' @@ -48,8 +48,8 @@ describe('', () => { consoleErrorMock.mockRestore() }) - it('should render a button and the children as button text', () => { - render(Hello World) + it('should render a button and the children as button text', async () => { + await render(Hello World) const button = document.querySelector('button') @@ -57,8 +57,8 @@ describe('', () => { expect(button).toHaveTextContent('Hello World') }) - it('should not error with a null child', () => { - render(Hello World{null}) + it('should not error with a null child', async () => { + await render(Hello World{null}) const button = document.querySelector('button') @@ -66,25 +66,29 @@ describe('', () => { expect(button).toHaveTextContent('Hello World') }) - it('should render a link styled as a button if href is provided', () => { - render(Hello World) + it('should render a link styled as a button if href is provided', async () => { + await render(Hello World) - const linkButton = screen.getByRole('link', { name: 'Hello World' }) + const linkButton = page.getByRole('link', { name: 'Hello World' }).element() expect(linkButton).toBeInTheDocument() expect(linkButton).toHaveAttribute('href', 'example.html') }) - it('should render as a link when `to` prop is provided', () => { - const { container } = render(Test) + it('should render as a link when `to` prop is provided', async () => { + const { container } = await render( + Test + ) const linkButton = container.querySelector('a') expect(linkButton!.getAttribute('to')).toBe('/example') }) - it('should render designated tag if `as` prop is specified', () => { - const { container } = render(Hello World) + it('should render designated tag if `as` prop is specified', async () => { + const { container } = await render( + Hello World + ) const button = container.querySelector('[type="button"]') @@ -93,10 +97,10 @@ describe('', () => { expect(button!.tagName).toBe('SPAN') }) - it('should set role="button"', () => { + it('should set role="button"', async () => { const onClick = vi.fn() - const { container } = render( + const { container } = await render( Hello World @@ -108,25 +112,25 @@ describe('', () => { expect(button).toHaveAttribute('role', 'button') }) - it('should set tabIndex="0"', () => { + it('should set tabIndex="0"', async () => { const onClick = vi.fn() - render( + await render( Hello World ) - const button = screen.getByRole('button', { name: 'Hello World' }) + const button = page.getByRole('button', { name: 'Hello World' }).element() expect(button).toBeInTheDocument() expect(button).toHaveAttribute('tabIndex', '0') }) - it('should not set tabIndex="0" when the element has it by default', () => { + it('should not set tabIndex="0" when the element has it by default', async () => { const onClick = vi.fn() - render( + await render( <> Hello Button @@ -136,36 +140,36 @@ describe('', () => { ) - const button = screen.getByRole('button', { name: 'Hello Button' }) + const button = page.getByRole('button', { name: 'Hello Button' }).element() expect(button).toBeInTheDocument() expect(button).not.toHaveAttribute('tabIndex') - const link = screen.getByRole('link', { name: 'Hello link' }) + const link = page.getByRole('link', { name: 'Hello link' }).element() expect(link).toBeInTheDocument() expect(link).not.toHaveAttribute('tabIndex') }) it('should pass down the type prop to the button element', async () => { const onClick = vi.fn() - render( + await render( Hello World ) - const button = screen.getByRole('button', { name: 'Hello World' }) + const button = page.getByRole('button', { name: 'Hello World' }).element() expect(button).toBeInTheDocument() expect(button).toHaveAttribute('type', 'submit') }) - it('should pass down an icon via the icon property', () => { + it('should pass down an icon via the icon property', async () => { const SomeIcon = () => ( ) - render(Hello World) + await render(Hello World) const icon = document.querySelector('svg') @@ -173,8 +177,8 @@ describe('', () => { }) it('focuses with the focus helper', async () => { - render(Hello World) - const button = screen.getByRole('button', { name: 'Hello World' }) + await render(Hello World) + const button = page.getByRole('button', { name: 'Hello World' }).element() button.focus() @@ -183,20 +187,20 @@ describe('', () => { it('should provide an elementRef prop', async () => { const elementRef = vi.fn() - render(Hello World) + await render(Hello World) - const button = screen.getByRole('button', { name: 'Hello World' }) + const button = page.getByRole('button', { name: 'Hello World' }).element() expect(elementRef).toHaveBeenCalledWith(button) }) - it('should not be underlined when disabled with a href', () => { - render( + it('should not be underlined when disabled with a href', async () => { + await render( Hello World ) - const button = screen.getByRole('link', { name: 'Hello World' }) + const button = page.getByRole('link', { name: 'Hello World' }).element() const styles = window.getComputedStyle(button) expect(styles.textDecoration).toContain('none') @@ -205,13 +209,13 @@ describe('', () => { describe('onClick', () => { it('should call onClick when clicked', async () => { const onClick = vi.fn() - render(Hello World) + await render(Hello World) - const button = screen.getByRole('button', { name: 'Hello World' }) + const button = page.getByRole('button', { name: 'Hello World' }).element() await userEvent.click(button) - await waitFor(() => { + await vi.waitFor(() => { expect(onClick).toHaveBeenCalledTimes(1) }) }) @@ -219,16 +223,16 @@ describe('', () => { it('should not call onClick when interaction is "disabled"', async () => { const onClick = vi.fn() - render( + await render( Hello World ) - const button = screen.getByRole('button', { name: 'Hello World' }) + const button = page.getByRole('button', { name: 'Hello World' }).element() await userEvent.click(button) - await waitFor(() => { + await vi.waitFor(() => { expect(onClick).not.toHaveBeenCalled() }) }) @@ -236,16 +240,16 @@ describe('', () => { it('should not call onClick when disabled is set"', async () => { const onClick = vi.fn() - render( + await render( Hello World ) - const button = screen.getByRole('button', { name: 'Hello World' }) + const button = page.getByRole('button', { name: 'Hello World' }).element() await userEvent.click(button) - await waitFor(() => { + await vi.waitFor(() => { expect(onClick).not.toHaveBeenCalled() }) }) @@ -253,16 +257,16 @@ describe('', () => { it('should not call onClick when interaction is "readonly"', async () => { const onClick = vi.fn() - render( + await render( Hello World ) - const button = screen.getByRole('button', { name: 'Hello World' }) + const button = page.getByRole('button', { name: 'Hello World' }).element() await userEvent.click(button) - await waitFor(() => { + await vi.waitFor(() => { expect(onClick).not.toHaveBeenCalled() }) }) @@ -270,16 +274,16 @@ describe('', () => { it('should not call onClick when readOnly is set', async () => { const onClick = vi.fn() - render( + await render( Hello World ) - const button = screen.getByRole('button', { name: 'Hello World' }) + const button = page.getByRole('button', { name: 'Hello World' }).element() await userEvent.click(button) - await waitFor(() => { + await vi.waitFor(() => { expect(onClick).not.toHaveBeenCalled() }) }) @@ -287,13 +291,13 @@ describe('', () => { it('should not call onClick when button is disabled and an href prop is provided', async () => { const onClick = vi.fn() - render(Hello World) + await render(Hello World) - const button = screen.getByRole('link', { name: 'Hello World' }) + const button = page.getByRole('link', { name: 'Hello World' }).element() await userEvent.click(button) - await waitFor(() => { + await vi.waitFor(() => { expect(onClick).not.toHaveBeenCalled() }) }) @@ -301,17 +305,17 @@ describe('', () => { it('should not call onClick when interaction is "readonly" and an href prop is provided', async () => { const onClick = vi.fn() - render( + await render( Hello World ) - const button = screen.getByRole('link', { name: 'Hello World' }) + const button = page.getByRole('link', { name: 'Hello World' }).element() await userEvent.click(button) - await waitFor(() => { + await vi.waitFor(() => { expect(onClick).not.toHaveBeenCalled() }) }) @@ -319,17 +323,17 @@ describe('', () => { it('should call onClick when space key is pressed if href is provided', async () => { const onClick = vi.fn() - render( + await render( Hello World ) - const button = screen.getByRole('link', { name: 'Hello World' }) + const button = page.getByRole('link', { name: 'Hello World' }).element() await userEvent.type(button, '{space}') - await waitFor(() => { + await vi.waitFor(() => { expect(onClick).toHaveBeenCalled() }) }) @@ -337,17 +341,17 @@ describe('', () => { it('should call onClick when enter key is pressed when not a button or link', async () => { const onClick = vi.fn() - render( + await render( Hello World ) - const button = screen.getByRole('button', { name: 'Hello World' }) + const button = page.getByRole('button', { name: 'Hello World' }).element() await userEvent.type(button, '{enter}') - await waitFor(() => { + await vi.waitFor(() => { expect(onClick).toHaveBeenCalled() }) }) @@ -355,17 +359,17 @@ describe('', () => { it('should not call onClick when interaction is "disabled" and space key is pressed', async () => { const onClick = vi.fn() - render( + await render( Hello World ) - const button = screen.getByRole('link', { name: 'Hello World' }) + const button = page.getByRole('link', { name: 'Hello World' }).element() await userEvent.type(button, '{space}') - await waitFor(() => { + await vi.waitFor(() => { expect(onClick).not.toHaveBeenCalled() }) }) @@ -373,16 +377,16 @@ describe('', () => { it('should not call onClick when interaction is "readonly" and space key is pressed', async () => { const onClick = vi.fn() - render( + await render( Hello World ) - const button = screen.getByRole('link', { name: 'Hello World' }) + const button = page.getByRole('link', { name: 'Hello World' }).element() await userEvent.type(button, '{space}') - await waitFor(() => { + await vi.waitFor(() => { expect(onClick).not.toHaveBeenCalled() }) }) @@ -390,18 +394,18 @@ describe('', () => { describe('when passing down props to View', () => { it("passes cursor='pointer' to View by default", async () => { - render(Hello World) + await render(Hello World) - const button = screen.getByRole('button', { name: 'Hello World' }) + const button = page.getByRole('button', { name: 'Hello World' }).element() const style = window.getComputedStyle(button) expect(style.cursor).toBe('pointer') }) it("passes cursor='not-allowed' to View when disabled", async () => { - render(Hello World) + await render(Hello World) - const button = screen.getByRole('button', { name: 'Hello World' }) + const button = page.getByRole('button', { name: 'Hello World' }).element() const style = window.getComputedStyle(button) expect(style.cursor).toBe('not-allowed') @@ -412,13 +416,13 @@ describe('', () => { it('should meet standards when onClick is given', async () => { const onClick = vi.fn() - render(Hello World) + await render(Hello World) - const button = screen.getByRole('button', { name: 'Hello World' }) + const button = page.getByRole('button', { name: 'Hello World' }).element() await userEvent.click(button) - await waitFor(async () => { + await vi.waitFor(async () => { const axeCheck = await runAxeCheck(button) expect(axeCheck).toBe(true) @@ -426,44 +430,52 @@ describe('', () => { }) describe('when disabled', () => { - it('sets the disabled attribute so that the button is not in tab order', () => { - render(Hello World) + it('sets the disabled attribute so that the button is not in tab order', async () => { + await render( + Hello World + ) - const button = screen.getByRole('button', { name: 'Hello World' }) + const button = page + .getByRole('button', { name: 'Hello World' }) + .element() expect(button).toHaveAttribute('disabled') }) }) describe('when readonly', () => { it('sets the disabled attribute so that the button is not in tab order', async () => { - render(Hello World) + await render( + Hello World + ) - const button = screen.getByRole('button', { name: 'Hello World' }) + const button = page + .getByRole('button', { name: 'Hello World' }) + .element() expect(button).toHaveAttribute('disabled') }) }) }) describe('href safety', () => { - it('strips javascript: schemes from href', () => { - render(Hi) - const el = screen.getByText('Hi').closest('a, button') + it('strips javascript: schemes from href', async () => { + await render(Hi) + const el = page.getByText('Hi').element().closest('a, button') expect(el).not.toHaveAttribute('href') }) - it('preserves safe https hrefs', () => { - render(Hi) - const link = screen.getByRole('link') + it('preserves safe https hrefs', async () => { + await render(Hi) + const link = page.getByRole('link').element() expect(link).toHaveAttribute('href', 'https://example.com') }) - it('defaults rel for target=_blank', () => { - render( + it('defaults rel for target=_blank', async () => { + await render( Hi ) - const link = screen.getByRole('link') + const link = page.getByRole('link').element() expect(link).toHaveAttribute('rel', 'noopener noreferrer') }) }) diff --git a/packages/ui-buttons/src/Button/__tests__/Button.test.tsx b/packages/ui-buttons/src/Button/__tests__/Button.test.tsx index a30504f273..e5dda955ae 100644 --- a/packages/ui-buttons/src/Button/__tests__/Button.test.tsx +++ b/packages/ui-buttons/src/Button/__tests__/Button.test.tsx @@ -22,10 +22,9 @@ * SOFTWARE. */ -import { render, screen, waitFor } from '@testing-library/react' -import { vi } from 'vitest' -import userEvent from '@testing-library/user-event' -import '@testing-library/jest-dom' +import { render } from 'vitest-browser-react' +import { page, userEvent } from 'vitest/browser' +import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest' import { runAxeCheck } from '@instructure/ui-axe-check' import { BaseButton, Button } from '@instructure/ui-buttons/latest' @@ -61,10 +60,10 @@ describe(') + await render() const button = document.querySelector('button') @@ -73,19 +72,19 @@ describe(') + await render() - const button = screen.getByRole('button') + const button = page.getByRole('button').element() expect(button).toBeInTheDocument() expect(button).toHaveAttribute('type', 'button') expect(button).toHaveTextContent('Hello World') }) - it('should provide a focused getter', () => { + it('should provide a focused getter', async () => { let componentRef: BaseButton | undefined - render( + await render( ) - const button = screen.getByRole('button', { name: 'Hello' }) + const button = page.getByRole('button', { name: 'Hello' }).element() button.focus() expect(componentRef?.focused).toBe(true) }) - it('should provide a focus function', () => { + it('should provide a focus function', async () => { let componentRef: BaseButton | undefined - render( + await render( ) - const button = screen.getByRole('button', { name: 'Hello' }) + const button = page.getByRole('button', { name: 'Hello' }).element() componentRef?.focus() expect(document.activeElement).toBe(button) }) - it('should pass the type attribute', () => { - render() + it('should pass the type attribute', async () => { + await render() - const button = screen.getByRole('button', { name: 'Hello' }) + const button = page.getByRole('button', { name: 'Hello' }).element() expect(button).toBeInTheDocument() expect(button).toHaveAttribute('type', 'submit') }) - it('should pass the `elementRef` prop', () => { + it('should pass the `elementRef` prop', async () => { const elementRef = vi.fn() - render() + await render() - const button = screen.getByRole('button', { name: 'Hello' }) + const button = page.getByRole('button', { name: 'Hello' }).element() expect(elementRef).toHaveBeenCalledWith(button) }) - it('should pass the `as` prop', () => { - const { container } = render() + it('should pass the `as` prop', async () => { + const { container } = await render() const button = container.querySelector('[type="button"]') @@ -150,52 +149,52 @@ describe(') + it('should set the disabled attribute when `interaction` is set to disabled', async () => { + await render() - const button = screen.getByRole('button', { name: 'Hello' }) + const button = page.getByRole('button', { name: 'Hello' }).element() expect(button).toHaveAttribute('disabled') }) - it('should set the disabled attribute when `disabled` is set', () => { - render() + it('should set the disabled attribute when `disabled` is set', async () => { + await render() - const button = screen.getByRole('button', { name: 'Hello' }) + const button = page.getByRole('button', { name: 'Hello' }).element() expect(button).toHaveAttribute('disabled') }) - it('should set the disabled attribute when `interaction` is set to readonly', () => { - render() + it('should set the disabled attribute when `interaction` is set to readonly', async () => { + await render() - const button = screen.getByRole('button', { name: 'Hello' }) + const button = page.getByRole('button', { name: 'Hello' }).element() expect(button).toHaveAttribute('disabled') }) - it('should set the disabled attribute when `readOnly` is set', () => { - render() + it('should set the disabled attribute when `readOnly` is set', async () => { + await render() - const button = screen.getByRole('button', { name: 'Hello' }) + const button = page.getByRole('button', { name: 'Hello' }).element() expect(button).toHaveAttribute('disabled') }) - it('should pass the `href` prop', () => { - render() + it('should pass the `href` prop', async () => { + await render() - const linkButton = screen.getByRole('link', { name: 'Hello' }) + const linkButton = page.getByRole('link', { name: 'Hello' }).element() expect(linkButton).toBeInTheDocument() expect(linkButton).toHaveAttribute('href', '#') }) - it('should pass the `renderIcon` prop', () => { - render() + it('should pass the `renderIcon` prop', async () => { + await render() const svgIcon = document.querySelector(iconSelector) - const button = screen.getByRole('button', { name: 'Hello' }) + const button = page.getByRole('button', { name: 'Hello' }).element() expect(button).toBeInTheDocument() expect(svgIcon).toBeInTheDocument() @@ -203,45 +202,45 @@ describe(') + await render() - const button = screen.getByRole('button', { name: 'Hello' }) + const button = page.getByRole('button', { name: 'Hello' }).element() await userEvent.click(button) - await waitFor(() => { + await vi.waitFor(() => { expect(onClick).toHaveBeenCalledTimes(1) }) }) - it('should render the children as button text', () => { - render() + it('should render the children as button text', async () => { + await render() - const button = screen.getByRole('button') + const button = page.getByRole('button').element() expect(button).toBeInTheDocument() expect(button).toHaveTextContent('Hello World') }) - it('should not error with a null child', () => { - render() + it('should not error with a null child', async () => { + await render() - const button = screen.getByRole('button', { name: 'Hello World' }) + const button = page.getByRole('button', { name: 'Hello World' }).element() expect(button).toBeInTheDocument() }) - it('should render a link styled as a button if href is provided', () => { - render() + it('should render a link styled as a button if href is provided', async () => { + await render() - const button = screen.getAllByRole('link', { name: 'Hello World' }) + const button = page.getByRole('link', { name: 'Hello World' }).elements() expect(button).toHaveLength(1) expect(button[0]).toHaveAttribute('href', 'example.html') }) - it('should render as a link when `to` prop is provided', () => { - const { container } = render() + it('should render as a link when `to` prop is provided', async () => { + const { container } = await render() const linkButton = container.querySelector('a') @@ -249,8 +248,8 @@ describe(') + it('should render designated tag if `as` prop is specified', async () => { + const { container } = await render() const button = container.querySelector('[type="button"]') @@ -259,9 +258,9 @@ describe(' @@ -272,37 +271,37 @@ describe(' ) - const button = screen.getByRole('button') + const button = page.getByRole('button').element() expect(button).toBeInTheDocument() expect(button).toHaveAttribute('tabIndex', '0') }) - it('should pass down the type prop to the button element', () => { + it('should pass down the type prop to the button element', async () => { const onClick = vi.fn() - render( + await render( ) - const button = screen.getByRole('button') + const button = page.getByRole('button').element() expect(button).toBeInTheDocument() expect(button).toHaveAttribute('type', 'submit') }) - it('focuses with the focus helper', () => { + it('focuses with the focus helper', async () => { const onFocus = vi.fn() - render() + await render() - const button = screen.getByRole('button') + const button = page.getByRole('button').element() button.focus() @@ -313,13 +312,13 @@ describe(') + await render() - const button = screen.getByRole('button', { name: 'Hello World' }) + const button = page.getByRole('button', { name: 'Hello World' }).element() await userEvent.click(button) - await waitFor(() => { + await vi.waitFor(() => { expect(onClick).toHaveBeenCalled() }) }) @@ -327,16 +326,16 @@ describe(' ) - const button = screen.getByRole('button', { name: 'Hello World' }) + const button = page.getByRole('button', { name: 'Hello World' }).element() await userEvent.click(button) - await waitFor(() => { + await vi.waitFor(() => { expect(onClick).not.toHaveBeenCalled() }) }) @@ -344,16 +343,16 @@ describe(' ) - const button = screen.getByRole('button', { name: 'Hello World' }) + const button = page.getByRole('button', { name: 'Hello World' }).element() await userEvent.click(button) - await waitFor(() => { + await vi.waitFor(() => { expect(onClick).not.toHaveBeenCalled() }) }) @@ -361,13 +360,13 @@ describe(') + await render() - const button = screen.getByRole('link', { name: 'Hello World' }) + const button = page.getByRole('link', { name: 'Hello World' }).element() await userEvent.click(button) - await waitFor(() => { + await vi.waitFor(() => { expect(onClick).not.toHaveBeenCalled() }) }) @@ -375,16 +374,16 @@ describe(' ) - const button = screen.getByRole('link', { name: 'Hello World' }) + const button = page.getByRole('link', { name: 'Hello World' }).element() await userEvent.click(button) - await waitFor(() => { + await vi.waitFor(() => { expect(onClick).not.toHaveBeenCalled() }) }) @@ -392,16 +391,16 @@ describe(' ) - const button = screen.getByRole('link', { name: 'Hello World' }) + const button = page.getByRole('link', { name: 'Hello World' }).element() await userEvent.type(button, '{space}') - await waitFor(() => { + await vi.waitFor(() => { expect(onClick).toHaveBeenCalled() }) }) @@ -409,16 +408,16 @@ describe(' ) - const button = screen.getByRole('button', { name: 'Hello World' }) + const button = page.getByRole('button', { name: 'Hello World' }).element() await userEvent.type(button, '{enter}') - await waitFor(() => { + await vi.waitFor(() => { expect(onClick).toHaveBeenCalled() }) }) @@ -426,16 +425,16 @@ describe(' ) - const button = screen.getByRole('link', { name: 'Hello World' }) + const button = page.getByRole('link', { name: 'Hello World' }).element() await userEvent.type(button, '{spaec}') - await waitFor(() => { + await vi.waitFor(() => { expect(onClick).not.toHaveBeenCalled() }) }) @@ -443,16 +442,16 @@ describe(' ) - const button = screen.getByRole('link', { name: 'Hello World' }) + const button = page.getByRole('link', { name: 'Hello World' }).element() await userEvent.type(button, '{space}') - await waitFor(() => { + await vi.waitFor(() => { expect(onClick).not.toHaveBeenCalled() }) }) @@ -461,13 +460,13 @@ describe(') + await render() - const button = screen.getByRole('button', { name: 'Hello World' }) + const button = page.getByRole('button', { name: 'Hello World' }).element() await userEvent.click(button) - await waitFor(async () => { + await vi.waitFor(async () => { const axeCheck = await runAxeCheck(button) expect(axeCheck).toBe(true) @@ -475,20 +474,24 @@ describe(') + it('sets the disabled attribute so that the button is not in tab order', async () => { + await render() - const button = screen.getByRole('button', { name: 'Hello World' }) + const button = page + .getByRole('button', { name: 'Hello World' }) + .element() expect(button).toHaveAttribute('disabled') }) }) describe('when readOnly', () => { - it('sets the disabled attribute so that the button is not in tab order', () => { - render() + it('sets the disabled attribute so that the button is not in tab order', async () => { + await render() - const button = screen.getByRole('button', { name: 'Hello World' }) + const button = page + .getByRole('button', { name: 'Hello World' }) + .element() expect(button).toHaveAttribute('disabled') }) diff --git a/packages/ui-buttons/src/CloseButton/__tests__/CloseButton.test.tsx b/packages/ui-buttons/src/CloseButton/__tests__/CloseButton.test.tsx index 77bcb9cb5e..ebb4991ec6 100644 --- a/packages/ui-buttons/src/CloseButton/__tests__/CloseButton.test.tsx +++ b/packages/ui-buttons/src/CloseButton/__tests__/CloseButton.test.tsx @@ -22,9 +22,9 @@ * SOFTWARE. */ -import { render, screen, waitFor } from '@testing-library/react' -import { vi } from 'vitest' -import userEvent from '@testing-library/user-event' +import { render } from 'vitest-browser-react' +import { page, userEvent } from 'vitest/browser' +import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest' import { CloseButton } from '@instructure/ui-buttons/latest' describe('', () => { @@ -42,9 +42,9 @@ describe('', () => { }) it('should render with x icon', async () => { - render() + await render() - const button = screen.getByRole('button') + const button = page.getByRole('button').element() const icon = document.querySelector('svg') @@ -57,13 +57,13 @@ describe('', () => { it('should pass the `onClick` prop', async () => { const onClick = vi.fn() - render() + await render() - const button = screen.getByRole('button') + const button = page.getByRole('button').element() await userEvent.click(button) - await waitFor(() => { + await vi.waitFor(() => { expect(onClick).toHaveBeenCalledTimes(1) }) }) diff --git a/packages/ui-buttons/src/CondensedButton/__tests__/CondensedButton.test.tsx b/packages/ui-buttons/src/CondensedButton/__tests__/CondensedButton.test.tsx index 245fdf45b0..9a2cc0ae23 100644 --- a/packages/ui-buttons/src/CondensedButton/__tests__/CondensedButton.test.tsx +++ b/packages/ui-buttons/src/CondensedButton/__tests__/CondensedButton.test.tsx @@ -22,9 +22,9 @@ * SOFTWARE. */ -import { render, screen, waitFor } from '@testing-library/react' -import { vi } from 'vitest' -import userEvent from '@testing-library/user-event' +import { render } from 'vitest-browser-react' +import { page, userEvent } from 'vitest/browser' +import { describe, it, expect, vi } from 'vitest' import { CondensedButton } from '@instructure/ui-buttons/latest' describe('', () => { @@ -40,10 +40,10 @@ describe('', () => { ) const iconSelector = 'svg[data-title="myIcon"]' - it('should render children', () => { + it('should render children', async () => { const children = 'Hello world' - render({children}) + await render({children}) const button = document.querySelector('button') @@ -51,10 +51,10 @@ describe('', () => { expect(button).toHaveTextContent(children) }) - it('should provide a focused getter', () => { + it('should provide a focused getter', async () => { let componentRef: CondensedButton | undefined - render( + await render( { componentRef = component @@ -63,17 +63,17 @@ describe('', () => { Hello ) - const button = screen.getByRole('button', { name: 'Hello' }) + const button = page.getByRole('button', { name: 'Hello' }).element() button.focus() expect(componentRef?.focused).toBe(true) }) - it('should provide a focus function', () => { + it('should provide a focus function', async () => { let componentRef: CondensedButton | undefined - render( + await render( { componentRef = component @@ -82,17 +82,17 @@ describe('', () => { Hello ) - const button = screen.getByRole('button', { name: 'Hello' }) + const button = page.getByRole('button', { name: 'Hello' }).element() componentRef?.focus() expect(document.activeElement).toBe(button) }) - it('should pass the type attribute', () => { - render(Hello) + it('should pass the type attribute', async () => { + await render(Hello) - const button = screen.getByRole('button', { name: 'Hello' }) + const button = page.getByRole('button', { name: 'Hello' }).element() expect(button).toBeInTheDocument() expect(button).toHaveAttribute('type', 'submit') @@ -100,14 +100,16 @@ describe('', () => { it('should pass the `elementRef` prop', async () => { const elementRef = vi.fn() - render(Hello) - const button = screen.getByRole('button', { name: 'Hello' }) + await render( + Hello + ) + const button = page.getByRole('button', { name: 'Hello' }).element() expect(elementRef).toHaveBeenCalledWith(button) }) - it('should pass the `as` prop', () => { - const { container } = render( + it('should pass the `as` prop', async () => { + const { container } = await render( Hello ) @@ -118,52 +120,56 @@ describe('', () => { expect(button!.tagName).toBe('LI') }) - it('should set the disabled attribute when `interaction` is set to disabled', () => { - render(Hello) + it('should set the disabled attribute when `interaction` is set to disabled', async () => { + await render( + Hello + ) - const button = screen.getByRole('button', { name: 'Hello' }) + const button = page.getByRole('button', { name: 'Hello' }).element() expect(button).toHaveAttribute('disabled') }) - it('should set the disabled attribute when `disabled` is set', () => { - render(Hello) + it('should set the disabled attribute when `disabled` is set', async () => { + await render(Hello) - const button = screen.getByRole('button', { name: 'Hello' }) + const button = page.getByRole('button', { name: 'Hello' }).element() expect(button).toHaveAttribute('disabled') }) - it('should set the disabled attribute when `interaction` is set to readonly', () => { - render(Hello) + it('should set the disabled attribute when `interaction` is set to readonly', async () => { + await render( + Hello + ) - const button = screen.getByRole('button', { name: 'Hello' }) + const button = page.getByRole('button', { name: 'Hello' }).element() expect(button).toHaveAttribute('disabled') }) - it('should set the disabled attribute when `readOnly` is set', () => { - render(Hello) + it('should set the disabled attribute when `readOnly` is set', async () => { + await render(Hello) - const button = screen.getByRole('button', { name: 'Hello' }) + const button = page.getByRole('button', { name: 'Hello' }).element() expect(button).toHaveAttribute('disabled') }) - it('should pass the `href` prop', () => { - render(Hello) + it('should pass the `href` prop', async () => { + await render(Hello) - const linkButton = screen.getByRole('link', { name: 'Hello' }) + const linkButton = page.getByRole('link', { name: 'Hello' }).element() expect(linkButton).toBeInTheDocument() expect(linkButton).toHaveAttribute('href', '#') }) it('should pass the `renderIcon` prop', async () => { - render(Hello) + await render(Hello) const svgIcon = document.querySelector(iconSelector) - const button = screen.getByRole('button', { name: 'Hello' }) + const button = page.getByRole('button', { name: 'Hello' }).element() expect(button).toBeInTheDocument() expect(svgIcon).toBeInTheDocument() @@ -171,13 +177,13 @@ describe('', () => { it('should pass the `onClick` prop', async () => { const onClick = vi.fn() - render(Hello) + await render(Hello) - const button = screen.getByRole('button', { name: 'Hello' }) + const button = page.getByRole('button', { name: 'Hello' }).element() await userEvent.click(button) - await waitFor(() => { + await vi.waitFor(() => { expect(onClick).toHaveBeenCalledTimes(1) }) }) diff --git a/packages/ui-buttons/src/IconButton/__tests__/IconButton.test.tsx b/packages/ui-buttons/src/IconButton/__tests__/IconButton.test.tsx index 067b915f66..059d1c2dbb 100644 --- a/packages/ui-buttons/src/IconButton/__tests__/IconButton.test.tsx +++ b/packages/ui-buttons/src/IconButton/__tests__/IconButton.test.tsx @@ -22,9 +22,9 @@ * SOFTWARE. */ -import { render, screen, waitFor } from '@testing-library/react' -import { vi } from 'vitest' -import userEvent from '@testing-library/user-event' +import { render } from 'vitest-browser-react' +import { page, userEvent } from 'vitest/browser' +import { describe, it, expect, vi } from 'vitest' import { IconButton } from '@instructure/ui-buttons/latest' describe('', () => { @@ -40,30 +40,34 @@ describe('', () => { ) const iconSelector = 'svg[data-title="myIcon"]' - it('should render an icon when provided as the `children` prop', () => { - render({icon}) + it('should render an icon when provided as the `children` prop', async () => { + await render( + {icon} + ) const svgIcon = document.querySelector(iconSelector) - const button = screen.getByRole('button') + const button = page.getByRole('button').element() expect(button).toBeInTheDocument() expect(svgIcon).toBeInTheDocument() expect(button).toHaveTextContent('some action') }) - it('should render an icon when provided as the `renderIcon` prop', () => { - render() + it('should render an icon when provided as the `renderIcon` prop', async () => { + await render( + + ) const svgIcon = document.querySelector(iconSelector) - const button = screen.getByRole('button') + const button = page.getByRole('button').element() expect(button).toBeInTheDocument() expect(svgIcon).toBeInTheDocument() }) - it('should provide a focused getter', () => { + it('should provide a focused getter', async () => { let componentRef: IconButton | undefined - render( + await render( ', () => { }} /> ) - const button = screen.getByRole('button') + const button = page.getByRole('button').element() button.focus() expect(componentRef?.focused).toBe(true) }) - it('should provide a focus function', () => { + it('should provide a focus function', async () => { let componentRef: IconButton | undefined - render( + await render( ', () => { }} /> ) - const button = screen.getByRole('button') + const button = page.getByRole('button').element() componentRef?.focus() expect(document.activeElement).toBe(button) }) - it('should pass the `href` prop', () => { - render( + it('should pass the `href` prop', async () => { + await render( ) - const linkButton = screen.getByRole('link') + const linkButton = page.getByRole('link').element() expect(linkButton).toBeInTheDocument() expect(linkButton).toHaveAttribute('href', '#') }) - it('should pass the `type` prop', () => { - render( + it('should pass the `type` prop', async () => { + await render( ) - const button = screen.getByRole('button') + const button = page.getByRole('button').element() expect(button).toBeInTheDocument() expect(button).toHaveAttribute('type', 'reset') }) - it('should pass the `elementRef` prop', () => { + it('should pass the `elementRef` prop', async () => { const elementRef = vi.fn() - render( + await render( ) - const button = screen.getByRole('button') + const button = page.getByRole('button').element() expect(elementRef).toHaveBeenCalledWith(button) }) - it('should pass the `as` prop', () => { - const { container } = render( + it('should pass the `as` prop', async () => { + const { container } = await render( ) const button = container.querySelector('[type="button"]') @@ -147,46 +151,46 @@ describe('', () => { expect(button!.tagName).toBe('LI') }) - it('should set the disabled attribute when `interaction` is set to disabled', () => { - render( + it('should set the disabled attribute when `interaction` is set to disabled', async () => { + await render( ) - const button = screen.getByRole('button') + const button = page.getByRole('button').element() expect(button).toHaveAttribute('disabled') }) - it('should set the disabled attribute when `disabled` is set', () => { - render( + it('should set the disabled attribute when `disabled` is set', async () => { + await render( ) - const button = screen.getByRole('button') + const button = page.getByRole('button').element() expect(button).toHaveAttribute('disabled') }) - it('should set the disabled attribute when `interaction` is set to readonly', () => { - render( + it('should set the disabled attribute when `interaction` is set to readonly', async () => { + await render( ) - const button = screen.getByRole('button') + const button = page.getByRole('button').element() expect(button).toHaveAttribute('disabled') }) - it('should set the disabled attribute when `readOnly` is set', () => { - render( + it('should set the disabled attribute when `readOnly` is set', async () => { + await render( ) - const button = screen.getByRole('button') + const button = page.getByRole('button').element() expect(button).toHaveAttribute('disabled') }) @@ -194,18 +198,18 @@ describe('', () => { it('should pass the `onClick` prop', async () => { const onClick = vi.fn() - render( + await render( ) - const button = screen.getByRole('button') + const button = page.getByRole('button').element() await userEvent.click(button) - await waitFor(() => { + await vi.waitFor(() => { expect(onClick).toHaveBeenCalledTimes(1) }) }) diff --git a/packages/ui-buttons/src/ToggleButton/__tests__/ToggleButton.test.tsx b/packages/ui-buttons/src/ToggleButton/__tests__/ToggleButton.test.tsx index f2acf644cc..44dcb4a1b2 100644 --- a/packages/ui-buttons/src/ToggleButton/__tests__/ToggleButton.test.tsx +++ b/packages/ui-buttons/src/ToggleButton/__tests__/ToggleButton.test.tsx @@ -22,9 +22,9 @@ * SOFTWARE. */ -import { render, screen, waitFor } from '@testing-library/react' -import { vi } from 'vitest' -import userEvent from '@testing-library/user-event' +import { render } from 'vitest-browser-react' +import { page, userEvent } from 'vitest/browser' +import { describe, it, expect, vi } from 'vitest' import { ToggleButton } from '@instructure/ui-buttons/latest' describe('', () => { @@ -35,8 +35,8 @@ describe('', () => { ) const iconSelector = 'svg[data-title="myIcon"]' - it('should render', () => { - render( + it('should render', async () => { + await render( ', () => { status="pressed" /> ) - const button = screen.getByRole('button') + const button = page.getByRole('button').element() const svgIcon = document.querySelector(iconSelector) - const tooltip = screen.getByRole('tooltip') + const tooltip = page.getByRole('tooltip').element() expect(button).toBeInTheDocument() expect(button).toHaveTextContent('This is a screen reader label') @@ -55,8 +55,8 @@ describe('', () => { expect(tooltip).toHaveTextContent('This is tooltip content') }) - it('should set `aria-pressed` to `true` if `status` is `pressed`', () => { - render( + it('should set `aria-pressed` to `true` if `status` is `pressed`', async () => { + await render( ', () => { status="pressed" /> ) - const button = screen.getByRole('button') + const button = page.getByRole('button').element() expect(button).toHaveAttribute('aria-pressed', 'true') }) - it('should set `aria-pressed` to `false` if `status` is `unpressed`', () => { - render( + it('should set `aria-pressed` to `false` if `status` is `unpressed`', async () => { + await render( ', () => { status="unpressed" /> ) - const button = screen.getByRole('button') + const button = page.getByRole('button').element() expect(button).toHaveAttribute('aria-pressed', 'false') }) - it('should render an icon', () => { - render( + it('should render an icon', async () => { + await render( ', () => { status="pressed" /> ) - const button = screen.getByRole('button') + const button = page.getByRole('button').element() const svgIcon = document.querySelector(iconSelector) expect(button).toBeInTheDocument() expect(svgIcon).toBeInTheDocument() }) - it('should pass the `as` prop', () => { - const { container } = render( + it('should pass the `as` prop', async () => { + const { container } = await render( ', () => { expect(button!.tagName).toBe('LI') }) - it('should set the disabled attribute when `interaction` prop is set to disabled', () => { - render( + it('should set the disabled attribute when `interaction` prop is set to disabled', async () => { + await render( ', () => { status="pressed" /> ) - const button = screen.getByRole('button') + const button = page.getByRole('button').element() expect(button).toHaveAttribute('disabled') }) - it('should set the disabled attribute when `disabled` prop is set', () => { - render( + it('should set the disabled attribute when `disabled` prop is set', async () => { + await render( ', () => { status="pressed" /> ) - const button = screen.getByRole('button') + const button = page.getByRole('button').element() expect(button).toHaveAttribute('disabled') }) - it('should set the disabled attribute when `interaction` prop is set to readonly', () => { - render( + it('should set the disabled attribute when `interaction` prop is set to readonly', async () => { + await render( ', () => { status="pressed" /> ) - const button = screen.getByRole('button') + const button = page.getByRole('button').element() expect(button).toHaveAttribute('disabled') }) - it('should set the disabled attribute when `readOnly` prop is set', () => { - render( + it('should set the disabled attribute when `readOnly` prop is set', async () => { + await render( ', () => { status="pressed" /> ) - const button = screen.getByRole('button') + const button = page.getByRole('button').element() expect(button).toHaveAttribute('disabled') }) @@ -178,7 +178,7 @@ describe('', () => { it('should pass the `onClick` prop', async () => { const onClick = vi.fn() - render( + await render( ', () => { status="pressed" /> ) - const button = screen.getByRole('button') + const button = page.getByRole('button').element() await userEvent.click(button) - await waitFor(() => { + await vi.waitFor(() => { expect(onClick).toHaveBeenCalledTimes(1) }) }) diff --git a/packages/ui-byline/src/Byline/__tests__/Byline.test.tsx b/packages/ui-byline/src/Byline/__tests__/Byline.test.tsx index 05f3a1a04e..ad5bedc83f 100644 --- a/packages/ui-byline/src/Byline/__tests__/Byline.test.tsx +++ b/packages/ui-byline/src/Byline/__tests__/Byline.test.tsx @@ -23,13 +23,22 @@ */ import { ComponentType } from 'react' -import { render, screen } from '@testing-library/react' -import { vi } from 'vitest' import { runAxeCheck } from '@instructure/ui-axe-check' import { Byline } from '@instructure/ui-byline/latest' import type { BylineProps } from '@instructure/ui-byline/latest' import { View } from '@instructure/ui-view/latest' -import '@testing-library/jest-dom' +import { render } from 'vitest-browser-react' +import { page } from 'vitest/browser' +import { + describe, + it, + expect, + beforeAll, + afterAll, + beforeEach, + afterEach, + vi +} from 'vitest' const TEST_TITLE = 'Test-title' const TEST_DESCRIPTION = 'Test-description' @@ -109,8 +118,8 @@ describe('', () => { ) renderByline({ description: descriptionElement }) - const clickableHeading = screen.getByText(TEST_HEADING) - const descriptionText = screen.getByText(TEST_PARAGRAPH) + const clickableHeading = page.getByText(TEST_HEADING).element() + const descriptionText = page.getByText(TEST_PARAGRAPH).element() expect(clickableHeading.tagName).toBe('A') expect(clickableHeading).toHaveAttribute('href', TEST_LINK) diff --git a/packages/ui-calendar/src/Calendar/__tests__/Calendar.test.tsx b/packages/ui-calendar/src/Calendar/__tests__/Calendar.test.tsx index d36365b7ee..8c3edfe5c5 100644 --- a/packages/ui-calendar/src/Calendar/__tests__/Calendar.test.tsx +++ b/packages/ui-calendar/src/Calendar/__tests__/Calendar.test.tsx @@ -22,10 +22,9 @@ * SOFTWARE. */ -import { render, screen, waitFor } from '@testing-library/react' -import userEvent from '@testing-library/user-event' -import { vi } from 'vitest' -import '@testing-library/jest-dom' +import { render } from 'vitest-browser-react' +import { page, userEvent } from 'vitest/browser' +import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest' import { Calendar } from '@instructure/ui-calendar/latest' import type { CalendarDayProps } from '@instructure/ui-calendar/latest' @@ -72,14 +71,14 @@ describe('', () => { describe('with minimal config', () => { it('should render 44 buttons without config', async () => { - render() + await render() const buttons = document.getElementsByTagName('button') expect(buttons.length).toEqual(44) }) it('should render proper week names by default', async () => { - const { container } = render() + const { container } = await render() const thead = container.querySelector('thead') expect(thead).toHaveTextContent( @@ -88,7 +87,7 @@ describe('', () => { }) it('should render proper week names if locale is set', async () => { - const { container } = render( + const { container } = await render( ) const thead = container.querySelector('thead') @@ -99,7 +98,7 @@ describe('', () => { }) it('should disable days properly', async () => { - const { container } = render( + const { container } = await render( ', () => { }) it('should indicate selected day', async () => { - render( + await render( ', () => { /> ) - const selectedDay = screen.queryByText('22 December 2023, Selected') + const selectedDay = page.getByText('22 December 2023, Selected').query() ?.parentElement?.parentElement expect(selectedDay).toBeDefined() @@ -138,7 +137,7 @@ describe('', () => { }) it('should render children', async () => { - const { container } = render( + const { container } = await render( {generateDays()} @@ -154,7 +153,7 @@ describe('', () => { it(`should warn if the correct number of children are not provided`, async () => { const count = Calendar.DAY_COUNT - 1 - render( + await render( {generateDays(count)} @@ -169,7 +168,7 @@ describe('', () => { }) it('should render weekday labels', async () => { - const { container, rerender } = render( + const { container, rerender } = await render( {generateDays()} @@ -193,7 +192,7 @@ describe('', () => { ] // Set prop: renderWeekdayLabels - rerender( + await rerender( ', () => { }) it('should warn if 7 weekday labels are not provided', async () => { - render( + await render( {generateDays()} @@ -227,7 +226,7 @@ describe('', () => { }) it('should format the weekday labels and days correctly', async () => { - const { container } = render( + const { container } = await render( {generateDays()} @@ -256,7 +255,7 @@ describe('', () => { ) - const { rerender } = render( + const { rerender } = await render( ', () => { {generateDays()} ) - const month = screen.getByText('March') - const year = screen.getByText('2019') + const month = page.getByText('March').element() + const year = page.getByText('2019').element() expect(month).toBeInTheDocument() expect(year).toBeInTheDocument() // Set prop: renderNavigationLabel - rerender( + await rerender( navLabel} @@ -281,30 +280,34 @@ describe('', () => { {generateDays()} ) - const updatedMonth = screen.getByText('March') - const updatedYear = screen.getByText('2019') + const updatedMonth = page.getByText('March').element() + const updatedYear = page.getByText('2019').element() expect(updatedMonth).toBeInTheDocument() expect(updatedYear).toBeInTheDocument() }) it('should render next and prev buttons', async () => { - const { rerender } = render( + const { rerender } = await render( {generateDays()} ) - const defaultPrevButton = screen.getByRole('button', { - name: /^Previous month/ - }) - const defaultNextButton = screen.getByRole('button', { - name: /^Next month/ - }) + const defaultPrevButton = page + .getByRole('button', { + name: /^Previous month/ + }) + .element() + const defaultNextButton = page + .getByRole('button', { + name: /^Next month/ + }) + .element() expect(defaultPrevButton).toBeInTheDocument() expect(defaultNextButton).toBeInTheDocument() - rerender( + await rerender( test-prev} @@ -314,13 +317,13 @@ describe('', () => { {generateDays()} ) - const customPrevButton = screen.getByText('test-prev') - const customNextButton = screen.getByText('test-next') + const customPrevButton = page.getByText('test-prev').element() + const customNextButton = page.getByText('test-next').element() expect(customPrevButton).toBeInTheDocument() expect(customNextButton).toBeInTheDocument() - rerender( + await rerender( } @@ -330,8 +333,8 @@ describe('', () => { {generateDays()} ) - const funcPrevButton = screen.getByText('func-test-prev') - const funcNextButton = screen.getByText('func-test-next') + const funcPrevButton = page.getByText('func-test-prev').element() + const funcNextButton = page.getByText('func-test-next').element() expect(funcPrevButton).toBeInTheDocument() expect(funcNextButton).toBeInTheDocument() @@ -341,7 +344,7 @@ describe('', () => { const onRequestRenderPrevMonth = vi.fn() const onRequestRenderNextMonth = vi.fn() - render( + await render( prev month} @@ -354,8 +357,8 @@ describe('', () => { ) - const prevButton = screen.getByText('prev month') - const nextButton = screen.getByText('next month') + const prevButton = page.getByText('prev month').element() + const nextButton = page.getByText('next month').element() expect(onRequestRenderPrevMonth).not.toHaveBeenCalled() expect(onRequestRenderNextMonth).not.toHaveBeenCalled() @@ -363,7 +366,7 @@ describe('', () => { await userEvent.click(prevButton) await userEvent.click(nextButton) - await waitFor(() => { + await vi.waitFor(() => { expect(onRequestRenderPrevMonth).toHaveBeenCalledTimes(1) expect(onRequestRenderNextMonth).toHaveBeenCalledTimes(1) }) @@ -371,7 +374,7 @@ describe('', () => { describe('when role="listbox"', () => { it('should set role="listbox" on table root and role="presentation" on the correct elements', async () => { - const { container } = render( + const { container } = await render( ', () => { }) it("should link each day with it's weekday header via `aria-describedby`", async () => { - const { container } = render( + const { container } = await render( ', () => { }) it('should set role="option" and aria-selected on each day', async () => { - const { container } = render( + const { container } = await render( ', () => { }) it('should announce selected state via accessible label when selectedLabel is provided', async () => { - const { container } = render( + const { container } = await render( ', () => { describe('when role="table" (default)', () => { it('should set role="button" on each day and not set aria-selected', async () => { - const { container } = render( + const { container } = await render( ', () => { }) it('should announce selected state via accessible label when selectedLabel is provided', async () => { - const { container } = render( + const { container } = await render( ', () => { }) it('should render root as designated by the `as` prop', async () => { - render( + await render( ', () => { {generateDays()} ) - const calendar = screen.getByRole('list') + const calendar = page.getByRole('list').element() expect(calendar.tagName).toBe('UL') expect(calendar).toHaveTextContent(weekdayLabels.join('')) }) describe('navigation button targetMonthSrLabel', () => { - it('should include the target month in the default button screen reader labels', () => { - render( + it('should include the target month in the default button screen reader labels', async () => { + await render( ', () => { ) expect( - screen.getByRole('button', { name: 'Previous month, November 2023' }) + page + .getByRole('button', { name: 'Previous month, November 2023' }) + .element() ).toBeInTheDocument() expect( - screen.getByRole('button', { name: 'Next month, January 2024' }) + page.getByRole('button', { name: 'Next month, January 2024' }).element() ).toBeInTheDocument() }) - it('should pass targetMonthSrLabel to function render props', () => { - render( + it('should pass targetMonthSrLabel to function render props', async () => { + await render( ', () => { ) expect( - screen.getByRole('button', { name: 'Go to November 2023' }) + page.getByRole('button', { name: 'Go to November 2023' }).element() ).toBeInTheDocument() expect( - screen.getByRole('button', { name: 'Go to January 2024' }) + page.getByRole('button', { name: 'Go to January 2024' }).element() ).toBeInTheDocument() }) }) diff --git a/packages/ui-calendar/src/Calendar/__tests__/Day.test.tsx b/packages/ui-calendar/src/Calendar/__tests__/Day.test.tsx index 64aebd0e4c..e79d6b59f4 100644 --- a/packages/ui-calendar/src/Calendar/__tests__/Day.test.tsx +++ b/packages/ui-calendar/src/Calendar/__tests__/Day.test.tsx @@ -22,15 +22,14 @@ * SOFTWARE. */ -import { render, screen, waitFor } from '@testing-library/react' -import userEvent from '@testing-library/user-event' -import { vi } from 'vitest' -import '@testing-library/jest-dom' +import { render } from 'vitest-browser-react' +import { page, userEvent } from 'vitest/browser' +import { describe, it, expect, vi } from 'vitest' import { CalendarDay as Day } from '@instructure/ui-calendar/latest' describe('Day', () => { it('should render children', async () => { - const { rerender } = render( + const { rerender } = await render( { 8 ) - const child = screen.getByText('8') + const child = page.getByText('8').element() expect(child).toBeInTheDocument() - rerender( + await rerender( { 31 ) - const childUpdated = screen.getByText('31') + const childUpdated = page.getByText('31').element() expect(childUpdated).toBeInTheDocument() }) it('should have an accessible label', async () => { const label = '1 August 2019 Friday' - const { container } = render( + const { container } = await render( 8 @@ -73,7 +72,7 @@ describe('Day', () => { }) it('should set aria-current="date" when `isToday`', async () => { - const { container, rerender } = render( + const { container, rerender } = await render( { expect(today).toHaveAttribute('aria-current', 'date') - rerender( + await rerender( { }) it('should not set aria-selected without a role', async () => { - const { container, rerender } = render( + const { container, rerender } = await render( { expect(day).not.toHaveAttribute('aria-selected') - rerender( + await rerender( { }) it('should set aria-selected="true/false" when `isSelected` and `role` is `option` or `gridcell`', async () => { - const { container, rerender } = render( + const { container, rerender } = await render( { const day = container.querySelector('[class*="-calendarDay"]') expect(day).toHaveAttribute('aria-selected', 'false') - rerender( + await rerender( { const daySelected = container.querySelector('[class*="-calendarDay"]') expect(daySelected).toHaveAttribute('aria-selected', 'true') - rerender( + await rerender( { const dayCell = container.querySelector('[class*="-calendarDay"]') expect(dayCell).toHaveAttribute('aria-selected', 'false') - rerender( + await rerender( { const onClick = vi.fn() const date = '2019-08-02' - const { container } = render( + const { container } = await render( { await userEvent.click(day!) - await waitFor(() => { + await vi.waitFor(() => { const args = onClick.mock.calls[0][1] expect(onClick).toHaveBeenCalledTimes(1) @@ -218,7 +217,7 @@ describe('Day', () => { const onKeyDown = vi.fn() const date = '2019-08-02' - const { container } = render( + const { container } = await render( { await userEvent.type(day, '{enter}') - await waitFor(() => { + await vi.waitFor(() => { const args = onKeyDown.mock.calls[0][1] expect(onKeyDown).toHaveBeenCalledTimes(1) @@ -245,7 +244,7 @@ describe('Day', () => { it('should apply disabled when interaction is `disabled`', async () => { const onClick = vi.fn() - const { container } = render( + const { container } = await render( { await userEvent.click(day) - await waitFor(() => { + await vi.waitFor(() => { expect(onClick).not.toHaveBeenCalled() expect(day).toHaveAttribute('disabled') }) @@ -271,7 +270,7 @@ describe('Day', () => { const elementRef = (el: Element | null) => { element = el } - const { container } = render( + const { container } = await render( { describe('element type', () => { it('should render as a span by default', async () => { - const { container } = render( + const { container } = await render( { }) it('should render as a button when onClick is provided', async () => { - const { container } = render( + const { container } = await render( { }) it('default elementTypes should be overwritten when `as` prop is set', async () => { - const { container } = render( + const { container } = await render( ', () => { it('renders an input with type "checkbox"', () => { renderCheckbox() - const inputElem = screen.getByRole('checkbox') + const inputElem = page.getByRole('checkbox').element() expect(inputElem).toBeInTheDocument() expect(inputElem.tagName).toBe('INPUT') @@ -90,7 +90,7 @@ describe('', () => { expect(svgElement).not.toBeInTheDocument() await userEvent.click(checkboxElement!) - await waitFor(() => { + await vi.waitFor(() => { const svgElementAfterClick = container.querySelector('svg') expect(svgElementAfterClick).toBeInTheDocument() }) @@ -99,7 +99,7 @@ describe('', () => { it('`simple` variant supports indeterminate/mixed state', () => { renderCheckbox({ variant: 'simple', indeterminate: true }) - const inputElem = screen.getByRole('checkbox') + const inputElem = page.getByRole('checkbox').element() expect(inputElem).toBeInTheDocument() expect(inputElem).toHaveAttribute('aria-checked', 'mixed') @@ -108,7 +108,7 @@ describe('', () => { it('should provide an inputRef prop', async () => { const inputRef = vi.fn() renderCheckbox({ inputRef }) - const input = screen.getByRole('checkbox') + const input = page.getByRole('checkbox').element() expect(inputRef).toHaveBeenCalledWith(input) }) @@ -118,11 +118,11 @@ describe('', () => { const onClick = vi.fn() const onChange = vi.fn() renderCheckbox({ onClick, onChange }) - const checkboxElement = screen.getByRole('checkbox') + const checkboxElement = page.getByRole('checkbox').element() await userEvent.click(checkboxElement) - await waitFor(() => { + await vi.waitFor(() => { expect(onClick).toHaveBeenCalled() expect(onChange).toHaveBeenCalled() }) @@ -132,11 +132,11 @@ describe('', () => { const onClick = vi.fn() const onChange = vi.fn() renderCheckbox({ onClick, onChange, disabled: true }) - const checkboxElement = screen.getByRole('checkbox') + const checkboxElement = page.getByRole('checkbox').element() fireEvent.click(checkboxElement) - await waitFor(() => { + await vi.waitFor(() => { expect(onClick).not.toHaveBeenCalled() expect(onChange).not.toHaveBeenCalled() expect(checkboxElement).toBeDisabled() @@ -147,11 +147,11 @@ describe('', () => { const onClick = vi.fn() const onChange = vi.fn() renderCheckbox({ onClick, onChange, readOnly: true }) - const checkboxElement = screen.getByRole('checkbox') + const checkboxElement = page.getByRole('checkbox').element() fireEvent.click(checkboxElement) - await waitFor(() => { + await vi.waitFor(() => { expect(onClick).not.toHaveBeenCalled() expect(onChange).not.toHaveBeenCalled() expect(checkboxElement).not.toBeDisabled() @@ -160,7 +160,7 @@ describe('', () => { it('when focused, readOnly checkbox is focusable', async () => { renderCheckbox({ readOnly: true }) - const checkboxElement = screen.getByRole('checkbox') + const checkboxElement = page.getByRole('checkbox').element() checkboxElement.focus() @@ -170,11 +170,11 @@ describe('', () => { it('calls onChange when enter key is pressed', async () => { const onChange = vi.fn() renderCheckbox({ onChange }) - const checkboxElement = screen.getByRole('checkbox') + const checkboxElement = page.getByRole('checkbox').element() await userEvent.type(checkboxElement, '{enter}') - await waitFor(() => { + await vi.waitFor(() => { expect(onChange).toHaveBeenCalled() }) }) @@ -186,7 +186,7 @@ describe('', () => { await userEvent.tab() await userEvent.tab() - await waitFor(() => { + await vi.waitFor(() => { expect(onBlur).toHaveBeenCalled() }) }) @@ -197,15 +197,15 @@ describe('', () => { await userEvent.tab() - await waitFor(() => { + await vi.waitFor(() => { expect(onFocus).toHaveBeenCalled() }) }) - it('focuses with the focus helper', () => { + it('focuses with the focus helper', async () => { const checkboxRef = createRef() - render() - const checkboxElement = screen.getByRole('checkbox') + await render() + const checkboxElement = page.getByRole('checkbox').element() expect(checkboxElement).not.toHaveFocus() @@ -217,11 +217,11 @@ describe('', () => { it('calls onMouseOver', async () => { const onMouseOver = vi.fn() renderCheckbox({ onMouseOver }) - const checkboxElement = screen.getByRole('checkbox') + const checkboxElement = page.getByRole('checkbox').element() await userEvent.hover(checkboxElement) - await waitFor(() => { + await vi.waitFor(() => { expect(onMouseOver).toHaveBeenCalled() }) }) @@ -229,12 +229,12 @@ describe('', () => { it('calls onMouseOut', async () => { const onMouseOut = vi.fn() renderCheckbox({ onMouseOut }) - const checkboxElement = screen.getByRole('checkbox') + const checkboxElement = page.getByRole('checkbox').element() await userEvent.hover(checkboxElement) await userEvent.unhover(checkboxElement) - await waitFor(() => { + await vi.waitFor(() => { expect(onMouseOut).toHaveBeenCalled() }) }) @@ -242,19 +242,19 @@ describe('', () => { it('reflects checked state changes via data-checked attribute', async () => { renderCheckbox({ defaultChecked: false }) - const input = screen.getByRole('checkbox') + const input = page.getByRole('checkbox').element() expect(input).toHaveAttribute('data-checked', 'false') await userEvent.click(input) - await waitFor(() => { + await vi.waitFor(() => { expect(input).toHaveAttribute('data-checked', 'true') }) }) it('sets data-checked to mixed when indeterminate', () => { renderCheckbox({ indeterminate: true }) - const input = screen.getByRole('checkbox') + const input = page.getByRole('checkbox').element() expect(input).toHaveAttribute('data-checked', 'mixed') }) @@ -263,14 +263,14 @@ describe('', () => { renderCheckbox({ messages: [{ type: 'error', text: 'This field is required' }] }) - const input = screen.getByRole('checkbox') + const input = page.getByRole('checkbox').element() expect(input).toHaveAttribute('aria-invalid', 'true') }) it('should not set aria-invalid when there are no error messages', () => { renderCheckbox({ messages: [{ type: 'hint', text: 'This is a hint' }] }) - const input = screen.getByRole('checkbox') + const input = page.getByRole('checkbox').element() expect(input).not.toHaveAttribute('aria-invalid') }) @@ -291,14 +291,14 @@ describe('', () => { }) it('associates messages with the checkbox as its description, not its accessible name', async () => { - render( + await render( ) - const input = screen.getByRole('checkbox') + const input = page.getByRole('checkbox').element() const describedById = input.getAttribute('aria-describedby') expect(describedById).toBeTruthy() @@ -314,8 +314,8 @@ describe('', () => { }) it('does not set aria-labelledby when there are no messages', async () => { - render() - const input = screen.getByRole('checkbox') + await render() + const input = page.getByRole('checkbox').element() expect(input).not.toHaveAttribute('aria-labelledby') }) diff --git a/packages/ui-checkbox/src/Checkbox/__tests__/CheckboxFacade.test.tsx b/packages/ui-checkbox/src/Checkbox/__tests__/CheckboxFacade.test.tsx index 290b0dd607..ece61e6a65 100644 --- a/packages/ui-checkbox/src/Checkbox/__tests__/CheckboxFacade.test.tsx +++ b/packages/ui-checkbox/src/Checkbox/__tests__/CheckboxFacade.test.tsx @@ -22,9 +22,9 @@ * SOFTWARE. */ -import { render, screen } from '@testing-library/react' -import { vi } from 'vitest' -import '@testing-library/jest-dom' +import { render } from 'vitest-browser-react' +import { page } from 'vitest/browser' +import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest' import { runAxeCheck } from '@instructure/ui-axe-check' import { CheckboxFacade } from '@instructure/ui-checkbox/latest' @@ -50,15 +50,17 @@ describe('', () => { consoleErrorMock.mockRestore() }) - it('should render', () => { - render({TEST_TEXT}) - const facade = screen.getByText(TEST_TEXT) + it('should render', async () => { + await render({TEST_TEXT}) + const facade = page.getByText(TEST_TEXT).element() expect(facade).toBeInTheDocument() }) it('should meet a11y standards', async () => { - const { container } = render({TEST_TEXT}) + const { container } = await render( + {TEST_TEXT} + ) const axeCheck = await runAxeCheck(container) expect(axeCheck).toBe(true) diff --git a/packages/ui-checkbox/src/Checkbox/__tests__/ToggleFacade.test.tsx b/packages/ui-checkbox/src/Checkbox/__tests__/ToggleFacade.test.tsx index bca71237ff..5f24cd6fea 100644 --- a/packages/ui-checkbox/src/Checkbox/__tests__/ToggleFacade.test.tsx +++ b/packages/ui-checkbox/src/Checkbox/__tests__/ToggleFacade.test.tsx @@ -22,9 +22,9 @@ * SOFTWARE. */ -import { render, screen } from '@testing-library/react' -import { vi } from 'vitest' -import '@testing-library/jest-dom' +import { render } from 'vitest-browser-react' +import { page } from 'vitest/browser' +import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest' import { runAxeCheck } from '@instructure/ui-axe-check' import { ToggleFacade } from '@instructure/ui-checkbox/latest' @@ -50,15 +50,15 @@ describe('', () => { consoleErrorMock.mockRestore() }) - it('should render', () => { - render({TEST_TEXT}) - const facade = screen.getByText(TEST_TEXT) + it('should render', async () => { + await render({TEST_TEXT}) + const facade = page.getByText(TEST_TEXT).element() expect(facade).toBeInTheDocument() }) it('should meet a11y standards', async () => { - const { container } = render({TEST_TEXT}) + const { container } = await render({TEST_TEXT}) const axeCheck = await runAxeCheck(container) expect(axeCheck).toBe(true) diff --git a/packages/ui-checkbox/src/CheckboxGroup/__tests__/CheckboxGroup.test.tsx b/packages/ui-checkbox/src/CheckboxGroup/__tests__/CheckboxGroup.test.tsx index e3957fca36..1c3dc61eb7 100644 --- a/packages/ui-checkbox/src/CheckboxGroup/__tests__/CheckboxGroup.test.tsx +++ b/packages/ui-checkbox/src/CheckboxGroup/__tests__/CheckboxGroup.test.tsx @@ -22,10 +22,10 @@ * SOFTWARE. */ -import { fireEvent, render, screen, waitFor } from '@testing-library/react' -import { vi } from 'vitest' -import userEvent from '@testing-library/user-event' -import '@testing-library/jest-dom' +import { fireEvent } from '@testing-library/dom' +import { render } from 'vitest-browser-react' +import { page, userEvent } from 'vitest/browser' +import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest' import { runAxeCheck } from '@instructure/ui-axe-check' import { Checkbox, CheckboxGroup } from '@instructure/ui-checkbox/latest' @@ -75,7 +75,7 @@ describe('', () => { it('adds the name props to all Checkbox types', () => { renderCheckboxGroup({ name: TEST_NAME }) - const checkboxes = screen.getAllByRole('checkbox') + const checkboxes = page.getByRole('checkbox').elements() expect(checkboxes.length).toBe(2) expect(checkboxes[0]).toHaveAttribute('name', TEST_NAME) @@ -86,7 +86,7 @@ describe('', () => { const { container } = renderCheckboxGroup({ messages: [{ text: TEST_ERROR_MESSAGE, type: 'error' }] }) - const group = screen.getByRole('group') + const group = page.getByRole('group').element() const ariaDesc = group.getAttribute('aria-describedby') const messageById = container.querySelector(`[id="${ariaDesc}"]`) @@ -107,11 +107,11 @@ describe('', () => { it('does not call the onChange prop when disabled', async () => { const onChange = vi.fn() renderCheckboxGroup({ onChange, disabled: true }) - const checkboxElement = screen.getAllByRole('checkbox')[0] + const checkboxElement = page.getByRole('checkbox').elements()[0] fireEvent.click(checkboxElement) - await waitFor(() => { + await vi.waitFor(() => { expect(onChange).not.toHaveBeenCalled() expect(checkboxElement).toBeDisabled() }) @@ -120,11 +120,11 @@ describe('', () => { it('does not call the onChange prop when readOnly', async () => { const onChange = vi.fn() renderCheckboxGroup({ onChange, readOnly: true }) - const checkboxElement = screen.getAllByRole('checkbox')[0] + const checkboxElement = page.getByRole('checkbox').elements()[0] fireEvent.click(checkboxElement) - await waitFor(() => { + await vi.waitFor(() => { expect(onChange).not.toHaveBeenCalled() expect(checkboxElement).not.toBeDisabled() }) @@ -133,14 +133,14 @@ describe('', () => { it('should not update the value when the value prop is set', async () => { const onChange = vi.fn() renderCheckboxGroup({ onChange, value: ['tester'] }) - const checkboxes = screen.getAllByRole('checkbox') + const checkboxes = page.getByRole('checkbox').elements() expect(checkboxes[0]).not.toBeChecked() expect(checkboxes[1]).not.toBeChecked() await userEvent.click(checkboxes[0]) - await waitFor(() => { + await vi.waitFor(() => { expect(onChange).toHaveBeenCalledWith(['tester', 'test-value-1']) expect(checkboxes[0]).not.toBeChecked() expect(checkboxes[1]).not.toBeChecked() @@ -150,7 +150,7 @@ describe('', () => { it('should add the checkbox value to the value list when it is checked', async () => { const onChange = vi.fn() renderCheckboxGroup({ onChange }) - const checkboxes = screen.getAllByRole('checkbox') + const checkboxes = page.getByRole('checkbox').elements() expect(checkboxes[0]).not.toBeChecked() expect(checkboxes[1]).not.toBeChecked() @@ -158,7 +158,7 @@ describe('', () => { await userEvent.click(checkboxes[0]) await userEvent.click(checkboxes[1]) - await waitFor(() => { + await vi.waitFor(() => { expect(checkboxes[0]).toBeChecked() expect(checkboxes[1]).toBeChecked() expect(onChange).toHaveBeenCalledWith([TEST_VALUE_1, TEST_VALUE_2]) @@ -168,7 +168,7 @@ describe('', () => { it('should check the checkboxes based on the defaultValue prop', () => { const defaultValue = [TEST_VALUE_2] renderCheckboxGroup({ defaultValue }) - const checkboxes = screen.getAllByRole('checkbox') + const checkboxes = page.getByRole('checkbox').elements() expect(checkboxes[0]).not.toBeChecked() expect(checkboxes[1]).toBeChecked() @@ -178,14 +178,14 @@ describe('', () => { const onChange = vi.fn() const defaultValue = [TEST_VALUE_1, TEST_VALUE_2] renderCheckboxGroup({ onChange, defaultValue }) - const checkboxes = screen.getAllByRole('checkbox') + const checkboxes = page.getByRole('checkbox').elements() expect(checkboxes[0]).toBeChecked() expect(checkboxes[1]).toBeChecked() await userEvent.click(checkboxes[0]) - await waitFor(() => { + await vi.waitFor(() => { expect(checkboxes[0]).not.toBeChecked() expect(checkboxes[1]).toBeChecked() expect(onChange).toHaveBeenCalledWith([TEST_VALUE_2]) @@ -196,14 +196,14 @@ describe('', () => { const onChange = vi.fn() const defaultValue = [TEST_VALUE_2] renderCheckboxGroup({ onChange, defaultValue }) - const checkboxes = screen.getAllByRole('checkbox') + const checkboxes = page.getByRole('checkbox').elements() expect(checkboxes[0]).not.toBeChecked() expect(checkboxes[1]).toBeChecked() await userEvent.click(checkboxes[0]) - await waitFor(() => { + await vi.waitFor(() => { expect(checkboxes[0]).toBeChecked() expect(checkboxes[1]).toBeChecked() expect(onChange).toHaveBeenCalledWith([TEST_VALUE_2, TEST_VALUE_1]) diff --git a/packages/ui-color-picker/src/ColorContrast/__tests__/ColorContrast.test.tsx b/packages/ui-color-picker/src/ColorContrast/__tests__/ColorContrast.test.tsx index ebee475c96..670d076906 100644 --- a/packages/ui-color-picker/src/ColorContrast/__tests__/ColorContrast.test.tsx +++ b/packages/ui-color-picker/src/ColorContrast/__tests__/ColorContrast.test.tsx @@ -22,9 +22,9 @@ * SOFTWARE. */ -import { render, screen } from '@testing-library/react' -import { vi } from 'vitest' -import '@testing-library/jest-dom' +import { render } from 'vitest-browser-react' +import { page } from 'vitest/browser' +import { describe, it, expect, vi } from 'vitest' import { runAxeCheck } from '@instructure/ui-axe-check' import { contrast } from '@instructure/ui-color-utils' @@ -52,7 +52,7 @@ describe('', () => { describe('elementRef prop', () => { it('should provide ref', async () => { const elementRef = vi.fn() - const { container } = render( + const { container } = await render( ', () => { describe('labels are displayed:', () => { Object.entries(testLabels).forEach(([label, text]) => { it(label, async () => { - const { container } = render( + const { container } = await render( ) @@ -78,47 +78,57 @@ describe('', () => { describe('labelLevel prop', () => { it('should render label as div when labelLevel is not provided', async () => { - render() + await render() - const heading = screen.queryByRole('heading', { - name: testLabels.label - }) + const heading = page + .getByRole('heading', { + name: testLabels.label + }) + .query() expect(heading).not.toBeInTheDocument() - const labelText = screen.getByText(testLabels.label) + const labelText = page.getByText(testLabels.label).element() expect(labelText).toBeInTheDocument() expect(labelText.tagName.toLowerCase()).toBe('div') }) it('should render label as Heading when labelLevel is provided', async () => { - render() + await render( + + ) - const heading = screen.getByRole('heading', { - name: testLabels.label, - level: 2 - }) + const heading = page + .getByRole('heading', { + name: testLabels.label, + level: 2 + }) + .element() expect(heading).toBeInTheDocument() }) it('should render correct heading level', async () => { - const { rerender } = render( + const { rerender } = await render( ) - let heading = screen.getByRole('heading', { - name: testLabels.label, - level: 3 - }) + let heading = page + .getByRole('heading', { + name: testLabels.label, + level: 3 + }) + .element() expect(heading).toBeInTheDocument() - rerender( + await rerender( ) - heading = screen.getByRole('heading', { - name: testLabels.label, - level: 1 - }) + heading = page + .getByRole('heading', { + name: testLabels.label, + level: 1 + }) + .element() expect(heading).toBeInTheDocument() }) }) @@ -128,7 +138,7 @@ describe('', () => { const color1 = '#fff' const color2 = '#088' - const { container } = render( + const { container } = await render( ', () => { const color1 = '#fff' const color2 = '#00888880' - const { container } = render( + const { container } = await render( ', () => { describe('withoutColorPreview prop', () => { it('should be false by default, should display preview', async () => { - const { container } = render( + const { container } = await render( ) @@ -171,7 +181,7 @@ describe('', () => { }) it('should hide preview', async () => { - const { container } = render( + const { container } = await render( ) @@ -195,7 +205,7 @@ describe('', () => { ) => { describe(title, () => { it(`normal text should ${expectedResult.normal.toLowerCase()}`, async () => { - const { container } = render( + const { container } = await render( ', () => { }) it(`large text should ${expectedResult.large.toLowerCase()}`, async () => { - const { container } = render( + const { container } = await render( ', () => { }) it(`graphics should ${expectedResult.graphics.toLowerCase()}`, async () => { - const { container } = render( + const { container } = await render( ', () => { describe('should be accessible', () => { it('a11y', async () => { - const { container } = render( + const { container } = await render( ) const axeCheck = await runAxeCheck(container) diff --git a/packages/ui-color-picker/src/ColorIndicator/__tests__/ColorIndicator.test.tsx b/packages/ui-color-picker/src/ColorIndicator/__tests__/ColorIndicator.test.tsx index b24b056629..839b4c6eac 100644 --- a/packages/ui-color-picker/src/ColorIndicator/__tests__/ColorIndicator.test.tsx +++ b/packages/ui-color-picker/src/ColorIndicator/__tests__/ColorIndicator.test.tsx @@ -22,9 +22,8 @@ * SOFTWARE. */ -import { render } from '@testing-library/react' -import { vi } from 'vitest' -import '@testing-library/jest-dom' +import { render } from 'vitest-browser-react' +import { describe, it, expect, vi } from 'vitest' import { runAxeCheck } from '@instructure/ui-axe-check' import { ColorIndicator } from '@instructure/ui-color-picker/latest' @@ -32,7 +31,9 @@ describe('', () => { describe('elementRef prop', () => { it('should provide ref', async () => { const elementRef = vi.fn() - const { container } = render() + const { container } = await render( + + ) expect(elementRef).toHaveBeenCalledWith(container.firstChild) }) @@ -40,7 +41,7 @@ describe('', () => { describe('should be accessible', () => { it('a11y', async () => { - const { container } = render() + const { container } = await render() const axeCheck = await runAxeCheck(container) expect(axeCheck).toBe(true) diff --git a/packages/ui-color-picker/src/ColorMixer/__tests__/ColorMixer.test.tsx b/packages/ui-color-picker/src/ColorMixer/__tests__/ColorMixer.test.tsx index 5906950f2e..d9378481a3 100644 --- a/packages/ui-color-picker/src/ColorMixer/__tests__/ColorMixer.test.tsx +++ b/packages/ui-color-picker/src/ColorMixer/__tests__/ColorMixer.test.tsx @@ -22,10 +22,9 @@ * SOFTWARE. */ -import { render, screen, waitFor } from '@testing-library/react' -import { userEvent } from '@testing-library/user-event' -import { vi } from 'vitest' -import '@testing-library/jest-dom' +import { render } from 'vitest-browser-react' +import { page, userEvent } from 'vitest/browser' +import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest' import { runAxeCheck } from '@instructure/ui-axe-check' import { deepEqual } from '@instructure/ui-utils' @@ -81,7 +80,7 @@ describe('', () => { describe('elementRef prop', () => { it('should provide ref', async () => { const elementRef = vi.fn() - const { container } = render( + const { container } = await render( ', () => { describe('labels are displayed:', () => { it('should render input labels', async () => { - const { container } = render( + const { container } = await render( ', () => { }) it('should render explanation labels', async () => { - render( + await render( ', () => { onChange={vi.fn()} /> ) - const sliders = screen.getAllByRole('slider') - const palette = screen.getByRole('button') + const sliders = page.getByRole('slider').elements() + const palette = page.getByRole('button').element() expect(sliders[0]).toHaveAttribute( 'aria-label', @@ -146,7 +145,7 @@ describe('', () => { describe('should be accessible', () => { it('a11y', async () => { - const { container } = render( + const { container } = await render( ', () => { describe('edge cases for color value', () => { Object.entries(edgeColorValues).forEach(([label, color]) => { it(label, async () => { - render( + await render( ', () => { /> ) - const inputs = screen.getAllByRole('textbox') + const inputs = page.getByRole('textbox').elements() const [r, g, b, a] = inputs.map((input) => Number(input.getAttribute('value')) ) @@ -185,7 +184,7 @@ describe('', () => { Object.entries(differentHexColorValues).forEach(([length, color]) => { it(`mount with ${length}-character hex color`, async () => { const colorInput = color - render( + await render( ', () => { /> ) - const inputs = screen.getAllByRole('textbox') + const inputs = page.getByRole('textbox').elements() const [r, g, b, a] = inputs.map((input) => Number(input.getAttribute('value')) ) @@ -206,7 +205,7 @@ describe('', () => { }) it('mount with invalid hex color', async () => { - render( + await render( ', () => { /> ) - const inputs = screen.getAllByRole('textbox') + const inputs = page.getByRole('textbox').elements() const [r, g, b, a] = inputs.map((input: any) => Number(input.getAttribute('value')) ) const colorHex = conversions.colorToHex8({ r, g, b, a }) expect(colorHex).toBe('#000000FF') - await waitFor(() => { + await vi.waitFor(() => { expect(consoleWarningMock.mock.calls[0][0]).toEqual( expect.stringContaining( 'Warning: [ColorMixer] The passed color value is not valid.' @@ -236,7 +235,7 @@ describe('', () => { describe('hue slider', () => { it('should not call onChange when the `tab` key is pressed', async () => { const onChange = vi.fn() - render( + await render( ', () => { /> ) - const colorSlider = screen.getByRole('slider', { - name: testScreenReaderLabels.colorSliderNavigationExplanationScreenReaderLabel - }) + const colorSlider = page + .getByRole('slider', { + name: testScreenReaderLabels.colorSliderNavigationExplanationScreenReaderLabel + }) + .element() colorSlider.focus() await userEvent.tab() - await waitFor(() => { + await vi.waitFor(() => { expect(onChange).not.toHaveBeenCalled() }) }) it('onChange should not be call when component is disabled', async () => { const onChange = vi.fn() - render( + await render( ', () => { onChange={onChange} /> ) - const colorSlider = screen.getByRole('slider', { - name: testScreenReaderLabels.colorSliderNavigationExplanationScreenReaderLabel - }) + const colorSlider = page + .getByRole('slider', { + name: testScreenReaderLabels.colorSliderNavigationExplanationScreenReaderLabel + }) + .element() await userEvent.type(colorSlider, '{arrowright}') - await waitFor(() => { + await vi.waitFor(() => { expect(onChange).not.toHaveBeenCalled() }) }) @@ -282,7 +285,7 @@ describe('', () => { describe('alpha slider', () => { it('should not call onChange when a `tab` key press is received', async () => { const onChange = vi.fn() - render( + await render( ', () => { onChange={onChange} /> ) - const alphaSlider = screen.getByRole('slider', { - name: testScreenReaderLabels.alphaSliderNavigationExplanationScreenReaderLabel - }) + const alphaSlider = page + .getByRole('slider', { + name: testScreenReaderLabels.alphaSliderNavigationExplanationScreenReaderLabel + }) + .element() alphaSlider.focus() await userEvent.tab() - await waitFor(() => { + await vi.waitFor(() => { expect(onChange).not.toHaveBeenCalled() }) }) it('should not call onChange when the component is disabled', async () => { const onChange = vi.fn() - render( + await render( ', () => { /> ) - const alphaSlider = screen.getByRole('slider', { - name: testScreenReaderLabels.alphaSliderNavigationExplanationScreenReaderLabel - }) + const alphaSlider = page + .getByRole('slider', { + name: testScreenReaderLabels.alphaSliderNavigationExplanationScreenReaderLabel + }) + .element() await userEvent.type(alphaSlider, '{arrowright}') - await waitFor(() => { + await vi.waitFor(() => { expect(onChange).not.toHaveBeenCalled() }) }) @@ -329,7 +336,7 @@ describe('', () => { it('the alpha slider does not show when withAlpha is false', async () => { const onChange = vi.fn() - render( + await render( ', () => { onChange={onChange} /> ) - const alphaSlider = screen.queryByRole('slider', { - name: testScreenReaderLabels.alphaSliderNavigationExplanationScreenReaderLabel - }) + const alphaSlider = page + .getByRole('slider', { + name: testScreenReaderLabels.alphaSliderNavigationExplanationScreenReaderLabel + }) + .query() expect(alphaSlider).not.toBeInTheDocument() }) @@ -348,7 +357,7 @@ describe('', () => { it('the alpha slider does not show when withAlpha is not set', async () => { const onChange = vi.fn() - render( + await render( ', () => { onChange={onChange} /> ) - const alphaSlider = screen.queryByRole('slider', { - name: testScreenReaderLabels.alphaSliderNavigationExplanationScreenReaderLabel - }) + const alphaSlider = page + .getByRole('slider', { + name: testScreenReaderLabels.alphaSliderNavigationExplanationScreenReaderLabel + }) + .query() expect(alphaSlider).not.toBeInTheDocument() }) @@ -366,7 +377,7 @@ describe('', () => { it('should set the disabled attribute when `disabled` is set', async () => { const onChange = vi.fn() - render( + await render( ', () => { onChange={onChange} /> ) - const alphaSlider = screen.queryByRole('slider', { - name: testScreenReaderLabels.alphaSliderNavigationExplanationScreenReaderLabel - }) + const alphaSlider = page + .getByRole('slider', { + name: testScreenReaderLabels.alphaSliderNavigationExplanationScreenReaderLabel + }) + .query() expect(alphaSlider).toHaveAttribute('disabled') }) @@ -388,7 +401,7 @@ describe('', () => { it('should set the disabled attribute when `disabled` is set', async () => { const onChange = vi.fn() - render( + await render( ', () => { onChange={onChange} /> ) - const colorPalette = screen.queryByRole('button', { - name: testScreenReaderLabels.colorPaletteNavigationExplanationScreenReaderLabel - }) + const colorPalette = page + .getByRole('button', { + name: testScreenReaderLabels.colorPaletteNavigationExplanationScreenReaderLabel + }) + .query() expect(colorPalette).toHaveAttribute('disabled') }) @@ -408,7 +423,7 @@ describe('', () => { describe('color input', () => { it('the alpha input exsits when `withAlpha` is set', async () => { - const { container } = render( + const { container } = await render( ', () => { const alphaInput = container.querySelector( 'span[class$="-RGBAInput__aInput"]' ) - const alphaInputScreenReaderLabel = screen.getByText( - testInputLabels.rgbAlphaInputScreenReaderLabel - ) + const alphaInputScreenReaderLabel = page + .getByText(testInputLabels.rgbAlphaInputScreenReaderLabel) + .element() expect(alphaInput).toBeInTheDocument() expect(alphaInputScreenReaderLabel).toBeInTheDocument() }) it('the alpha input does not exsit when `withAlpha` is not set', async () => { - const { container } = render( + const { container } = await render( ', () => { const alphaInput = container.querySelector( 'span[class$="-RGBAInput__aInput"]' ) - const alphaInputScreenReaderLabel = screen.queryByText( - testInputLabels.rgbAlphaInputScreenReaderLabel - ) + const alphaInputScreenReaderLabel = page + .getByText(testInputLabels.rgbAlphaInputScreenReaderLabel) + .query() expect(alphaInput).not.toBeInTheDocument() expect(alphaInputScreenReaderLabel).not.toBeInTheDocument() @@ -451,7 +466,7 @@ describe('', () => { it('should not call onChange when `disabled` is set and get the input', async () => { const fakeValue = '234234' const onChange = vi.fn() - render( + await render( ', () => { onChange={onChange} /> ) - const inputs = screen.getAllByRole('textbox') + const inputs = page.getByRole('textbox').elements() expect(inputs.length).toBe(4) await userEvent.type(inputs[0], fakeValue) @@ -468,13 +483,13 @@ describe('', () => { await userEvent.type(inputs[2], fakeValue) await userEvent.type(inputs[3], fakeValue) - await waitFor(() => { + await vi.waitFor(() => { expect(onChange).not.toHaveBeenCalled() }) }) it('should set the disabled attribute when `disabled` and `withAlpha` is set', async () => { - render( + await render( ', () => { onChange={vi.fn()} /> ) - const inputs = screen.getAllByRole('textbox') + const inputs = page.getByRole('textbox').elements() expect(inputs.length).toBe(4) inputs.forEach((input) => { @@ -492,7 +507,7 @@ describe('', () => { }) it('should set the disabled attribute when `disabled` is set', async () => { - render( + await render( ', () => { onChange={vi.fn()} /> ) - const inputs = screen.getAllByRole('textbox') + const inputs = page.getByRole('textbox').elements() expect(inputs.length).toBe(3) inputs.forEach((input) => { @@ -510,7 +525,7 @@ describe('', () => { it('should not accept letter character', async () => { const invalidColor = 'adfafas' - render( + await render( ', () => { onChange={vi.fn()} /> ) - const inputs = screen.getAllByRole('textbox') + const inputs = page.getByRole('textbox').elements() expect(inputs.length).toBe(4) await userEvent.type(inputs[0], invalidColor) @@ -526,7 +541,7 @@ describe('', () => { await userEvent.type(inputs[2], invalidColor) await userEvent.type(inputs[3], invalidColor) - await waitFor(() => { + await vi.waitFor(() => { expect(inputs[0]).not.toHaveValue(invalidColor) expect(inputs[1]).not.toHaveValue(invalidColor) expect(inputs[2]).not.toHaveValue(invalidColor) @@ -536,7 +551,7 @@ describe('', () => { it('should not accept negative value', async () => { const invalidColor = '-10' - render( + await render( ', () => { onChange={vi.fn()} /> ) - const inputs = screen.getAllByRole('textbox') + const inputs = page.getByRole('textbox').elements() expect(inputs.length).toBe(4) await userEvent.type(inputs[0], invalidColor) @@ -552,7 +567,7 @@ describe('', () => { await userEvent.type(inputs[2], invalidColor) await userEvent.type(inputs[3], invalidColor) - await waitFor(() => { + await vi.waitFor(() => { expect(inputs[0]).not.toHaveValue(invalidColor) expect(inputs[1]).not.toHaveValue(invalidColor) expect(inputs[2]).not.toHaveValue(invalidColor) @@ -562,21 +577,21 @@ describe('', () => { it('should not accept value that bigger than 255', async () => { const invalidColor = '300' - render( + await render( ) - const inputs = screen.getAllByRole('textbox') + const inputs = page.getByRole('textbox').elements() expect(inputs.length).toBe(3) await userEvent.type(inputs[0], invalidColor) await userEvent.type(inputs[1], invalidColor) await userEvent.type(inputs[2], invalidColor) - await waitFor(() => { + await vi.waitFor(() => { expect(inputs[0]).not.toHaveValue(invalidColor) expect(inputs[1]).not.toHaveValue(invalidColor) expect(inputs[2]).not.toHaveValue(invalidColor) @@ -585,7 +600,7 @@ describe('', () => { it('for alpha input, should not accept value that bigger than 100', async () => { const invalidColor = '101' - render( + await render( ', () => { onChange={vi.fn()} /> ) - const inputs = screen.getAllByRole('textbox') + const inputs = page.getByRole('textbox').elements() expect(inputs.length).toBe(4) await userEvent.type(inputs[3], invalidColor) - await waitFor(() => { + await vi.waitFor(() => { expect(inputs[3]).not.toHaveValue(invalidColor) }) }) diff --git a/packages/ui-color-picker/src/ColorPicker/__tests__/ColorPicker.test.tsx b/packages/ui-color-picker/src/ColorPicker/__tests__/ColorPicker.test.tsx index edde8350d9..cec0c6afc4 100644 --- a/packages/ui-color-picker/src/ColorPicker/__tests__/ColorPicker.test.tsx +++ b/packages/ui-color-picker/src/ColorPicker/__tests__/ColorPicker.test.tsx @@ -22,10 +22,10 @@ * SOFTWARE. */ -import { render, screen, waitFor, fireEvent } from '@testing-library/react' -import { userEvent } from '@testing-library/user-event' -import { vi } from 'vitest' -import '@testing-library/jest-dom' +import { fireEvent } from '@testing-library/dom' +import { render } from 'vitest-browser-react' +import { page, userEvent } from 'vitest/browser' +import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest' import { runAxeCheck } from '@instructure/ui-axe-check' import conversions from '@instructure/ui-color-utils' @@ -67,7 +67,7 @@ describe('', () => { describe('simple input mode', () => { it('should render correctly', async () => { - const { container } = render() + const { container } = await render() expect(container.firstChild).toBeInTheDocument() }) @@ -75,80 +75,82 @@ describe('', () => { const color = '#FFF' const onChange = vi.fn() - const { rerender } = render( + const { rerender } = await render( ) - const input = screen.getByRole('textbox') + const input = page.getByRole('textbox').element() expect(input).toHaveValue('FFF') // set new value - rerender() + await rerender( + + ) - const inputUpdated = screen.getByRole('textbox') + const inputUpdated = page.getByRole('textbox').element() expect(inputUpdated).toHaveValue('FFF555') }) it('should accept 3 digit hex code', async () => { const color = '0CB' - render() + await render() - const input = screen.getByRole('textbox') + const input = page.getByRole('textbox').element() await userEvent.type(input, color) fireEvent.blur(input) - await waitFor(() => { + await vi.waitFor(() => { expect(input).toHaveValue(color) }) }) it('should accept 6 digit hex code', async () => { const color = '0CBF2D' - render() + await render() - const input = screen.getByRole('textbox') + const input = page.getByRole('textbox').element() await userEvent.type(input, color) fireEvent.blur(input) - await waitFor(() => { + await vi.waitFor(() => { expect(input).toHaveValue(color) }) }) it('should not accept not valid hex code', async () => { const color = 'WWWZZZ' - render() + await render() - const input = screen.getByRole('textbox') + const input = page.getByRole('textbox').element() await userEvent.type(input, color) fireEvent.blur(input) - await waitFor(() => { + await vi.waitFor(() => { expect(input).not.toHaveValue(color) }) }) it('should not allow more than 6 characters', async () => { const color = '0CBF2D1234567' - render() + await render() - const input = screen.getByRole('textbox') + const input = page.getByRole('textbox').element() await userEvent.type(input, color) fireEvent.blur(input) - await waitFor(() => { + await vi.waitFor(() => { expect(input).toHaveValue('0CBF2D') }) }) it('should not allow input when disabled', async () => { - render() + await render() - const input = screen.getByRole('textbox') + const input = page.getByRole('textbox').element() expect(input).toHaveAttribute('disabled') }) @@ -160,7 +162,7 @@ describe('', () => { it(`should check contrast correctly when color has enough contrast [contrastStrength=${contrastStrength}]`, async () => { //oxford in canvas color palette, should be valid with all contrast strenght checkers const colorToCheck = '394B58' - const { container } = render( + const { container } = await render( ', () => { }} /> ) - const input = screen.getByRole('textbox') + const input = page.getByRole('textbox').element() await userEvent.type(input, colorToCheck) fireEvent.blur(input) - await waitFor(() => { + await vi.waitFor(() => { expect(input).toHaveValue(colorToCheck) const successIconWrapper = container.querySelector( @@ -189,7 +191,7 @@ describe('', () => { it(`should check contrast correctly when color does not have enough contrast [contrastStrength=${contrastStrength}, isStrict=false]`, async () => { //porcelain in canvas color palette, it should be failing even the min check const colorToCheck = 'F5F5F5' - const { container } = render( + const { container } = await render( ', () => { }} /> ) - const input = screen.getByRole('textbox') + const input = page.getByRole('textbox').element() await userEvent.type(input, colorToCheck) fireEvent.blur(input) - await waitFor(() => { + await vi.waitFor(() => { expect(input).toHaveValue(colorToCheck) const warningIconWrapper = container.querySelector( @@ -218,7 +220,7 @@ describe('', () => { it(`should check contrast correctly when color does not have enough contrast [contrastStrength=${contrastStrength}, isStrict=true]`, async () => { //porcelain in canvas color palette, it should be failing even the min check const colorToCheck = 'F5F5F5' - const { container } = render( + const { container } = await render( ', () => { }} /> ) - const input = screen.getByRole('textbox') + const input = page.getByRole('textbox').element() await userEvent.type(input, colorToCheck) fireEvent.blur(input) - await waitFor(() => { + await vi.waitFor(() => { expect(input).toHaveValue(colorToCheck) const errorIconWrapper = container.querySelector( @@ -246,7 +248,7 @@ describe('', () => { it(`should display success message when contrast is met [contrastStrength=${contrastStrength}]`, async () => { const colorToCheck = '394B58' - render( + await render( ', () => { }} /> ) - const input = screen.getByRole('textbox') + const input = page.getByRole('textbox').element() await userEvent.type(input, colorToCheck) fireEvent.blur(input) - await waitFor(() => { - const successMessage = screen.getByText( - 'I am a contrast success message' - ) + await vi.waitFor(() => { + const successMessage = page + .getByText('I am a contrast success message') + .element() expect(input).toHaveValue(colorToCheck) expect(successMessage).toBeInTheDocument() @@ -274,7 +276,7 @@ describe('', () => { it(`should display error message when contrast is not met [contrastStrength=${contrastStrength}, isStrict=false]`, async () => { const colorToCheck = 'F5F5F5' - render( + await render( ', () => { }} /> ) - const input = screen.getByRole('textbox') + const input = page.getByRole('textbox').element() await userEvent.type(input, colorToCheck) fireEvent.blur(input) - await waitFor(() => { - const warningMessage = screen.getByText( - 'I am a contrast warning message' - ) + await vi.waitFor(() => { + const warningMessage = page + .getByText('I am a contrast warning message') + .element() expect(input).toHaveValue(colorToCheck) expect(warningMessage).toBeInTheDocument() @@ -302,7 +304,7 @@ describe('', () => { it(`should display error message when contrast is not met [contrastStrength=${contrastStrength}, isStrict=true]`, async () => { const colorToCheck = 'F5F5F5' - render( + await render( ', () => { }} /> ) - const input = screen.getByRole('textbox') + const input = page.getByRole('textbox').element() await userEvent.type(input, colorToCheck) fireEvent.blur(input) - await waitFor(() => { - const errorMessage = screen.getByText('I am a contrast error message') + await vi.waitFor(() => { + const errorMessage = page + .getByText('I am a contrast error message') + .element() expect(input).toHaveValue(colorToCheck) expect(errorMessage).toBeInTheDocument() @@ -329,20 +333,20 @@ describe('', () => { it('should call onChange', async () => { const onChange = vi.fn() - render() + await render() - const input = screen.getByRole('textbox') + const input = page.getByRole('textbox').element() fireEvent.change(input, { target: { value: 'FFF' } }) fireEvent.blur(input) - await waitFor(() => { + await vi.waitFor(() => { expect(onChange).toHaveBeenLastCalledWith('#FFF') }) }) it('should display message when ColorPicker is a required field', async () => { - render( + await render( [ @@ -353,33 +357,37 @@ describe('', () => { ]} /> ) - const input = screen.getByRole('textbox') + const input = page.getByRole('textbox').element() fireEvent.focus(input) fireEvent.blur(input) - await waitFor(() => { - const requiredMessage = screen.getByText('I am a required message') + await vi.waitFor(() => { + const requiredMessage = page + .getByText('I am a required message') + .element() expect(requiredMessage).toBeInTheDocument() }) }) it('should display message when color is invalid', async () => { - render( + await render( [ { type: 'error', text: 'I am an invalid color message' } ]} /> ) - const input = screen.getByRole('textbox') + const input = page.getByRole('textbox').element() await userEvent.type(input, 'F') fireEvent.blur(input) - await waitFor(() => { - const errorMessage = screen.getByText('I am an invalid color message') + await vi.waitFor(() => { + const errorMessage = page + .getByText('I am an invalid color message') + .element() expect(errorMessage).toBeInTheDocument() }) @@ -387,75 +395,75 @@ describe('', () => { it('should provide an inputRef prop', async () => { const inputRef = vi.fn() - render() - const input = screen.getByRole('textbox') + await render() + const input = page.getByRole('textbox').element() expect(inputRef).toHaveBeenCalledWith(input) }) describe('paste behavior', () => { it('should strip leading # from pasted value', async () => { - render() - const input = screen.getByRole('textbox') as HTMLInputElement + await render() + const input = page.getByRole('textbox').element() as HTMLInputElement fireEvent.paste(input, { clipboardData: { getData: () => '#FF0000' } }) - await waitFor(() => { + await vi.waitFor(() => { expect(input).toHaveValue('FF0000') }) }) it('should block pasted value that exceeds 6 characters', async () => { - render() - const input = screen.getByRole('textbox') as HTMLInputElement + await render() + const input = page.getByRole('textbox').element() as HTMLInputElement fireEvent.paste(input, { clipboardData: { getData: () => 'FF00001' } }) - await waitFor(() => { + await vi.waitFor(() => { expect(input).toHaveValue('') }) }) it('should block pasted value with invalid hex characters', async () => { - render() - const input = screen.getByRole('textbox') as HTMLInputElement + await render() + const input = page.getByRole('textbox').element() as HTMLInputElement fireEvent.paste(input, { clipboardData: { getData: () => 'ZZZZZZ' } }) - await waitFor(() => { + await vi.waitFor(() => { expect(input).toHaveValue('') }) }) it('should replace entirely selected text when pasting', async () => { - render() - const input = screen.getByRole('textbox') as HTMLInputElement + await render() + const input = page.getByRole('textbox').element() as HTMLInputElement fireEvent.change(input, { target: { value: 'FF0000' } }) - await waitFor(() => expect(input).toHaveValue('FF0000')) + await vi.waitFor(() => expect(input).toHaveValue('FF0000')) input.setSelectionRange(0, 6) fireEvent.paste(input, { clipboardData: { getData: () => 'AABBCC' } }) - await waitFor(() => { + await vi.waitFor(() => { expect(input).toHaveValue('AABBCC') }) }) it('should replace partially selected text when pasting', async () => { - render() - const input = screen.getByRole('textbox') as HTMLInputElement + await render() + const input = page.getByRole('textbox').element() as HTMLInputElement fireEvent.change(input, { target: { value: 'FF0000' } }) - await waitFor(() => expect(input).toHaveValue('FF0000')) + await vi.waitFor(() => expect(input).toHaveValue('FF0000')) // select the two middle zeros (positions 2–4), paste FF → FFFF00 input.setSelectionRange(2, 4) @@ -463,58 +471,58 @@ describe('', () => { clipboardData: { getData: () => 'FF' } }) - await waitFor(() => { + await vi.waitFor(() => { expect(input).toHaveValue('FFFF00') }) }) it('should insert pasted text at cursor start position', async () => { - render() - const input = screen.getByRole('textbox') as HTMLInputElement + await render() + const input = page.getByRole('textbox').element() as HTMLInputElement fireEvent.change(input, { target: { value: '0000' } }) - await waitFor(() => expect(input).toHaveValue('0000')) + await vi.waitFor(() => expect(input).toHaveValue('0000')) input.setSelectionRange(0, 0) fireEvent.paste(input, { clipboardData: { getData: () => 'FF' } }) - await waitFor(() => { + await vi.waitFor(() => { expect(input).toHaveValue('FF0000') }) }) it('should insert pasted text at cursor middle position', async () => { - render() - const input = screen.getByRole('textbox') as HTMLInputElement + await render() + const input = page.getByRole('textbox').element() as HTMLInputElement fireEvent.change(input, { target: { value: 'FF00' } }) - await waitFor(() => expect(input).toHaveValue('FF00')) + await vi.waitFor(() => expect(input).toHaveValue('FF00')) input.setSelectionRange(2, 2) fireEvent.paste(input, { clipboardData: { getData: () => 'AB' } }) - await waitFor(() => { + await vi.waitFor(() => { expect(input).toHaveValue('FFAB00') }) }) it('should insert pasted text at cursor end position', async () => { - render() - const input = screen.getByRole('textbox') as HTMLInputElement + await render() + const input = page.getByRole('textbox').element() as HTMLInputElement fireEvent.change(input, { target: { value: '0000' } }) - await waitFor(() => expect(input).toHaveValue('0000')) + await vi.waitFor(() => expect(input).toHaveValue('0000')) input.setSelectionRange(4, 4) fireEvent.paste(input, { clipboardData: { getData: () => 'FF' } }) - await waitFor(() => { + await vi.waitFor(() => { expect(input).toHaveValue('0000FF') }) }) @@ -523,7 +531,7 @@ describe('', () => { describe('complex mode', () => { it('should display trigger button', async () => { - const { container } = render( + const { container } = await render( ', () => { const buttonWrapper = container.querySelector( 'div[class$="-colorPicker__colorMixerButtonWrapper"]' ) - const button = screen.getByRole('button') + const button = page.getByRole('button').element() expect(buttonWrapper).toBeInTheDocument() expect(button).toBeInTheDocument() }) it('should open popover when trigger is clicked', async () => { - render( + await render( ', () => { }} /> ) - const trigger = screen.getByRole('button') + const trigger = page.getByRole('button').element() expect(trigger).toBeInTheDocument() expect(trigger).toHaveAttribute('aria-expanded', 'false') fireEvent.click(trigger) - await waitFor(() => { - const buttons = screen.getAllByRole('button') + await vi.waitFor(() => { + const buttons = page.getByRole('button').elements() const popoverContent = document.querySelector( 'div[class$="-colorPicker__popoverContent"]' ) @@ -572,7 +580,7 @@ describe('', () => { }) it('should display the color mixer', async () => { - render( + await render( ', () => { }} /> ) - const trigger = screen.getByRole('button') + const trigger = page.getByRole('button').element() fireEvent.click(trigger) - await waitFor(() => { - const redInput = screen.getByLabelText('Red input') - const blueInput = screen.getByLabelText('Blue input') - const greenInput = screen.getByLabelText('Green input') + await vi.waitFor(() => { + const redInput = page.getByLabelText('Red input').element() + const blueInput = page.getByLabelText('Blue input').element() + const greenInput = page.getByLabelText('Green input').element() expect(redInput).toBeInTheDocument() expect(blueInput).toBeInTheDocument() @@ -607,7 +615,7 @@ describe('', () => { it('should display the correct color in the colormixer when the input is prefilled', async () => { const color = '0374B5' - render( + await render( ', () => { }} /> ) - const input = screen.getByRole('textbox') - const trigger = screen.getByRole('button') + const input = page.getByRole('textbox').element() + const trigger = page.getByRole('button').element() await userEvent.type(input, color) fireEvent.blur(input) fireEvent.click(trigger) - await waitFor(() => { - const redInput = screen.getByLabelText('Red input') as HTMLInputElement - const blueInput = screen.getByLabelText( - 'Blue input' - ) as HTMLInputElement - const greenInput = screen.getByLabelText( - 'Green input' - ) as HTMLInputElement + await vi.waitFor(() => { + const redInput = page + .getByLabelText('Red input') + .element() as HTMLInputElement + const blueInput = page + .getByLabelText('Blue input') + .element() as HTMLInputElement + const greenInput = page + .getByLabelText('Green input') + .element() as HTMLInputElement const convertedColor = conversions.colorToRGB(`#${color}`) const actualColor = { @@ -656,7 +666,7 @@ describe('', () => { it('should trigger onChange when selected color is added from colorMixer', async () => { const onChange = vi.fn() const rgb = { r: 131, g: 6, b: 25, a: 1 } - render( + await render( ', () => { /> ) - const trigger = screen.getByRole('button') + const trigger = page.getByRole('button').element() fireEvent.click(trigger) - await waitFor(() => { - const addBtn = screen.getByRole('button', { name: 'add' }) - const redInput = screen.getByLabelText('Red input') as HTMLInputElement - const greenInput = screen.getByLabelText( - 'Green input' - ) as HTMLInputElement - const blueInput = screen.getByLabelText( - 'Blue input' - ) as HTMLInputElement + await vi.waitFor(() => { + const addBtn = page.getByRole('button', { name: 'add' }).element() + const redInput = page + .getByLabelText('Red input') + .element() as HTMLInputElement + const greenInput = page + .getByLabelText('Green input') + .element() as HTMLInputElement + const blueInput = page + .getByLabelText('Blue input') + .element() as HTMLInputElement fireEvent.change(redInput, { target: { value: `${rgb.r}` } }) fireEvent.change(greenInput, { target: { value: `${rgb.g}` } }) @@ -703,7 +715,7 @@ describe('', () => { describe('custom popover mode', () => { it('should throw warning if children and settings object are passed too', async () => { - render( + await render( ', () => { ) - await waitFor(() => { + await vi.waitFor(() => { expect(consoleWarningMock.mock.calls[0][0]).toEqual( expect.stringContaining( 'Warning: You should either use children, colorMixerSettings or neither, not both. In this case, the colorMixerSettings will be ignored.' @@ -724,9 +736,9 @@ describe('', () => { }) it('should display trigger button', async () => { - render({() =>
}
) + await render({() =>
}
) - const trigger = screen.getByRole('button') + const trigger = page.getByRole('button').element() expect(trigger).toBeInTheDocument() expect(trigger).toHaveAttribute('data-popover-trigger', 'true') }) @@ -734,7 +746,7 @@ describe('', () => { describe('should be accessible', () => { it('a11y', async () => { - const { container } = render() + const { container } = await render() const axeCheck = await runAxeCheck(container) expect(axeCheck).toBe(true) diff --git a/packages/ui-color-picker/src/ColorPreset/__tests__/ColorPreset.test.tsx b/packages/ui-color-picker/src/ColorPreset/__tests__/ColorPreset.test.tsx index ba34294191..1b064c291e 100644 --- a/packages/ui-color-picker/src/ColorPreset/__tests__/ColorPreset.test.tsx +++ b/packages/ui-color-picker/src/ColorPreset/__tests__/ColorPreset.test.tsx @@ -22,9 +22,9 @@ * SOFTWARE. */ -import { render, screen, waitFor } from '@testing-library/react' -import { userEvent } from '@testing-library/user-event' -import { vi } from 'vitest' +import { render } from 'vitest-browser-react' +import { page, userEvent } from 'vitest/browser' +import { describe, it, expect, vi } from 'vitest' import { ColorPreset } from '@instructure/ui-color-picker/latest' import type { ColorPresetProps } from '@instructure/ui-color-picker/latest' @@ -80,8 +80,8 @@ describe('', () => { colorScreenReaderLabel: mockScreenReaderLabel } - render() - const buttons = screen.getAllByRole('button') + await render() + const buttons = page.getByRole('button').elements() buttons.forEach((button, index) => { const expectedColor = testValue.colors[index] @@ -90,8 +90,8 @@ describe('', () => { }) it('should default to using the hex code as aria-label when colorScreenReaderLabel is not provided', async () => { - render() - const buttons = screen.getAllByRole('button') + await render() + const buttons = page.getByRole('button').elements() buttons.forEach((button, index) => { const expectedColor = testValue.colors[index] @@ -102,7 +102,7 @@ describe('', () => { describe('elementRef prop', () => { it('should provide ref', async () => { const elementRef = vi.fn() - const { container } = render( + const { container } = await render( ) @@ -112,9 +112,9 @@ describe('', () => { describe('label prop', () => { it('should display title', async () => { - render() + await render() - const title = screen.getByText('This is a title') + const title = page.getByText('This is a title').element() expect(title).toBeInTheDocument() }) @@ -122,11 +122,11 @@ describe('', () => { describe('colors prop', () => { it('should render tooltips for all colors', async () => { - render() + await render() const testColors = testValue.colors - const indicators = screen.getAllByRole('button') - const tooltips = screen.getAllByRole('tooltip') + const indicators = page.getByRole('button').elements() + const tooltips = page.getByRole('tooltip').elements() expect(indicators.length).toBe(testColors.length) expect(tooltips.length).toBe(testColors.length) @@ -139,7 +139,7 @@ describe('', () => { }) it('should not render component when colors not provided and not modifiable', async () => { - render() + await render() const colorPreset = document.querySelector('span[class$="-colorPreset"]') @@ -150,13 +150,13 @@ describe('', () => { describe('onSelect prop', () => { it('should fire with color hex when indicator clicked', async () => { const onSelect = vi.fn() - render() + await render() - const indicators = screen.getAllByRole('button') + const indicators = page.getByRole('button').elements() await userEvent.click(indicators[1]) - await waitFor(() => { + await vi.waitFor(() => { expect(onSelect).toHaveBeenCalledWith(testValue.colors[1]) }) }) @@ -164,27 +164,27 @@ describe('', () => { it('should fire with color hex when transparent indicator clicked', async () => { const testColor = '#12345678' const onSelect = vi.fn() - render( + await render( ) - const indicators = screen.getAllByRole('button') + const indicators = page.getByRole('button').elements() await userEvent.click(indicators[0]) - await waitFor(() => { + await vi.waitFor(() => { expect(onSelect).toHaveBeenCalledWith(testColor) }) }) it('should not fire when disabled prop is set', async () => { const onSelect = vi.fn() - render() + await render() - const indicators = screen.getAllByRole('button') + const indicators = page.getByRole('button').elements() await userEvent.click(indicators[1]) - await waitFor(() => { + await vi.waitFor(() => { expect(onSelect).not.toHaveBeenCalled() }) }) @@ -192,13 +192,13 @@ describe('', () => { describe('colorMixerSettings prop', () => { it('displays "new color" button', async () => { - render( + await render( ) - const buttons = screen.getAllByRole('button') + const buttons = page.getByRole('button').elements() expect(buttons[0]).toHaveTextContent( testColorMixerSettings.addNewPresetButtonScreenReaderLabel @@ -206,7 +206,7 @@ describe('', () => { }) it('renders color menus for all indicators', async () => { - render( + await render( ', () => { }) it('should render an input', async () => { - const { container } = render() + const { container } = await render() const dateInput = container.querySelector('input') expect(dateInput).toBeInTheDocument() @@ -78,7 +86,7 @@ describe('', () => { }) it('should render an input label', async () => { - const { container } = render() + const { container } = await render() const label = container.querySelector('label') @@ -88,7 +96,7 @@ describe('', () => { it('should render an input placeholder', async () => { const placeholder = 'Placeholder' - render( + await render( ', () => { value="" /> ) - const dateInput = screen.getByLabelText('Choose a date') + const dateInput = page.getByLabelText('Choose a date').element() expect(dateInput).toHaveAttribute('placeholder', placeholder) }) it('should render a calendar icon with screen reader label', async () => { const iconLabel = 'Calendar icon Label' - const { container } = render( + const { container } = await render( ', () => { /> ) const calendarIcon = container.querySelector('svg[name="Calendar"]') - const calendarLabel = screen.getByText(iconLabel) + const calendarLabel = page.getByText(iconLabel).element() expect(calendarIcon).toBeInTheDocument() expect(calendarLabel).toBeInTheDocument() @@ -132,7 +140,7 @@ describe('', () => { it('refs should return the underlying component', async () => { const inputRef = vi.fn() const ref: React.Ref = { current: null } - const { container } = render( + const { container } = await render( ', () => { it('should render a custom calendar icon with screen reader label', async () => { const iconLabel = 'Calendar icon Label' - const { container } = render( + const { container } = await render( ', () => { /> ) const calendarIcon = container.querySelector('svg[name="Heart"]') - const calendarLabel = screen.getByText(iconLabel) + const calendarLabel = page.getByText(iconLabel).element() expect(calendarIcon).toBeInTheDocument() expect(calendarLabel).toBeInTheDocument() }) it('should not show calendar table by default', async () => { - render() - const calendarTable = screen.queryByRole('table') + await render() + const calendarTable = page.getByRole('table').query() expect(calendarTable).not.toBeInTheDocument() }) it('should show calendar table when calendar button is clicked', async () => { - render() - const calendarButton = screen.getByRole('button') + await render() + const calendarButton = page.getByRole('button').element() expect(calendarButton).toBeInTheDocument() await userEvent.click(calendarButton) - await waitFor(() => { - const calendarTable = screen.queryByRole('table') + await vi.waitFor(() => { + const calendarTable = page.getByRole('table').query() expect(calendarTable).toBeInTheDocument() }) }) @@ -201,7 +209,7 @@ describe('', () => { const nextMonthLabel = 'Next month' const prevMonthLabel = 'Previous month' - render( + await render( ', () => { value="" /> ) - const calendarButton = screen.getByRole('button') + const calendarButton = page.getByRole('button').element() await userEvent.click(calendarButton) - await waitFor(() => { - const prevMonthButton = screen.getByRole('button', { - name: new RegExp(`^${prevMonthLabel}`) - }) - const nextMonthButton = screen.getByRole('button', { - name: new RegExp(`^${nextMonthLabel}`) - }) + await vi.waitFor(() => { + const prevMonthButton = page + .getByRole('button', { + name: new RegExp(`^${prevMonthLabel}`) + }) + .element() + const nextMonthButton = page + .getByRole('button', { + name: new RegExp(`^${nextMonthLabel}`) + }) + .element() expect(prevMonthButton).toBeInTheDocument() expect(nextMonthButton).toBeInTheDocument() @@ -243,7 +255,7 @@ describe('', () => { it('should programmatically set and render the initial value', async () => { const value = '26/03/2024' - render( + await render( ', () => { value={value} /> ) - const dateInput = screen.getByLabelText('Choose a date') + const dateInput = page.getByLabelText('Choose a date').element() expect(dateInput).toHaveValue(value) expect(dateInput).toBeInTheDocument() @@ -266,7 +278,7 @@ describe('', () => { it('should set interaction type to disabled', async () => { const interactionDisabled = 'disabled' - const { container } = render( + const { container } = await render( ', () => { it('should set interaction type to readonly', async () => { const interactionReadOnly = 'readonly' - const { container } = render( + const { container } = await render( ', () => { /> ) const dateInput = container.querySelector('input') - const calendarButton = screen.getByRole('button') + const calendarButton = page.getByRole('button').element() expect(dateInput).toHaveAttribute(interactionReadOnly) expect(calendarButton).toBeInTheDocument() await userEvent.click(calendarButton) - await waitFor(() => { - const calendarTable = screen.queryByRole('table') + await vi.waitFor(() => { + const calendarTable = page.getByRole('table').query() expect(calendarTable).not.toBeInTheDocument() }) }) it('should set required', async () => { - const { container } = render( + const { container } = await render( ', () => { it('should call onBlur', async () => { const onBlur = vi.fn() - render( + await render( ', () => { onBlur={onBlur} /> ) - const dateInput = screen.getByLabelText('Choose a date') + const dateInput = page.getByLabelText('Choose a date').element() fireEvent.blur(dateInput) - await waitFor(() => { + await vi.waitFor(() => { expect(onBlur).toHaveBeenCalled() }) }) @@ -385,19 +397,19 @@ describe('', () => { ) } - render() + await render() - expect(screen.queryByText(errorMsg)).not.toBeInTheDocument() + expect(page.getByText(errorMsg).query()).not.toBeInTheDocument() - const dateInput = screen.getByLabelText(LABEL_TEXT) + const dateInput = page.getByLabelText(LABEL_TEXT).element() await userEvent.click(dateInput) await userEvent.type(dateInput, 'Not a date') dateInput.blur() - await waitFor(() => { - expect(screen.getByText(errorMsg)).toBeInTheDocument() + await vi.waitFor(() => { + expect(page.getByText(errorMsg).element()).toBeInTheDocument() }) }) @@ -410,7 +422,7 @@ describe('', () => { { type: 'screenreader-only', text: 'Screenreader' } ] - render( + await render( ', () => { /> ) - expect(screen.getByText('TypeLess')).toBeVisible() - expect(screen.getByText('Error')).toBeVisible() - expect(screen.getByText('Success')).toBeVisible() - expect(screen.getByText('Hint')).toBeVisible() + expect(page.getByText('TypeLess').element()).toBeVisible() + expect(page.getByText('Error').element()).toBeVisible() + expect(page.getByText('Success').element()).toBeVisible() + expect(page.getByText('Hint').element()).toBeVisible() - const screenreaderMessage = screen.getByText('Screenreader') + const screenreaderMessage = page.getByText('Screenreader').element() expect(screenreaderMessage).toBeInTheDocument() expect(screenreaderMessage).toHaveClass(/screenReaderContent/) }) @@ -438,7 +450,7 @@ describe('', () => { it('should render date picker dialog with proper role and ARIA label', async () => { const datePickerLabel = 'Date picker' - render( + await render( ', () => { /> ) - const calendarButton = screen.getByRole('button', { name: 'Calendar' }) + const calendarButton = page + .getByRole('button', { name: 'Calendar' }) + .element() await userEvent.click(calendarButton) - await waitFor(() => { - const dialog = screen.getByRole('dialog', { name: datePickerLabel }) + await vi.waitFor(() => { + const dialog = page + .getByRole('dialog', { name: datePickerLabel }) + .element() expect(dialog).toBeInTheDocument() expect(dialog).toHaveAttribute('aria-label', datePickerLabel) }) diff --git a/packages/ui-date-input/src/DateInput2/__tests__/DateInput2.test.tsx b/packages/ui-date-input/src/DateInput2/__tests__/DateInput2.test.tsx index 78fe60e373..7c16e17659 100644 --- a/packages/ui-date-input/src/DateInput2/__tests__/DateInput2.test.tsx +++ b/packages/ui-date-input/src/DateInput2/__tests__/DateInput2.test.tsx @@ -22,10 +22,18 @@ * SOFTWARE. */ import { useState } from 'react' -import { fireEvent, render, screen, waitFor } from '@testing-library/react' -import { vi, MockInstance } from 'vitest' -import userEvent from '@testing-library/user-event' -import '@testing-library/jest-dom' +import { fireEvent } from '@testing-library/dom' +import { render } from 'vitest-browser-react' +import { page, userEvent } from 'vitest/browser' +import { + describe, + it, + expect, + beforeEach, + afterEach, + vi, + MockInstance +} from 'vitest' import { HeartInstUIIcon } from '@instructure/ui-icons' import { DateInput2 } from '@instructure/ui-date-input/latest' @@ -68,7 +76,7 @@ describe('', () => { }) it('should render an input', async () => { - const { container } = render() + const { container } = await render() const dateInput = container.querySelector('input') expect(dateInput).toBeInTheDocument() @@ -76,7 +84,7 @@ describe('', () => { }) it('should render an input label', async () => { - const { container } = render() + const { container } = await render() const label = container.querySelector('label') @@ -86,7 +94,7 @@ describe('', () => { it('should render an input placeholder', async () => { const placeholder = 'Placeholder' - render( + await render( ', () => { value="" /> ) - const dateInput = screen.getByLabelText('Choose a date') + const dateInput = page.getByLabelText('Choose a date').element() expect(dateInput).toHaveAttribute('placeholder', placeholder) }) it('should render a calendar icon with screen reader label', async () => { const iconLabel = 'Calendar icon Label' - const { container } = render( + const { container } = await render( ', () => { /> ) const calendarIcon = container.querySelector('svg[name="Calendar"]') - const calendarLabel = screen.getByText(iconLabel) + const calendarLabel = page.getByText(iconLabel).element() expect(calendarIcon).toBeInTheDocument() expect(calendarLabel).toBeInTheDocument() @@ -126,7 +134,7 @@ describe('', () => { it('refs should return the underlying component', async () => { const inputRef = vi.fn() const ref: React.Ref = { current: null } - const { container } = render( + const { container } = await render( ', () => { it('should render a custom calendar icon with screen reader label', async () => { const iconLabel = 'Calendar icon Label' - const { container } = render( + const { container } = await render( ', () => { /> ) const calendarIcon = container.querySelector('svg[name="Heart"]') - const calendarLabel = screen.getByText(iconLabel) + const calendarLabel = page.getByText(iconLabel).element() expect(calendarIcon).toBeInTheDocument() expect(calendarLabel).toBeInTheDocument() }) it('should not show calendar table by default', async () => { - render() - const calendarTable = screen.queryByRole('table') + await render() + const calendarTable = page.getByRole('table').query() expect(calendarTable).not.toBeInTheDocument() }) it('should show calendar table when calendar button is clicked', async () => { - render() - const calendarButton = screen.getByRole('button') + await render() + const calendarButton = page.getByRole('button').element() expect(calendarButton).toBeInTheDocument() await userEvent.click(calendarButton) - await waitFor(() => { - const calendarTable = screen.queryByRole('table') + await vi.waitFor(() => { + const calendarTable = page.getByRole('table').query() expect(calendarTable).toBeInTheDocument() }) }) @@ -191,7 +199,7 @@ describe('', () => { const nextMonthLabel = 'Next month' const prevMonthLabel = 'Previous month' - render( + await render( ', () => { value="" /> ) - const calendarButton = screen.getByRole('button') + const calendarButton = page.getByRole('button').element() await userEvent.click(calendarButton) - await waitFor(() => { - const prevMonthButton = screen.getByRole('button', { - name: prevMonthLabel - }) - const nextMonthButton = screen.getByRole('button', { - name: nextMonthLabel - }) + await vi.waitFor(() => { + const prevMonthButton = page + .getByRole('button', { + name: prevMonthLabel + }) + .element() + const nextMonthButton = page + .getByRole('button', { + name: nextMonthLabel + }) + .element() expect(prevMonthButton).toBeInTheDocument() expect(nextMonthButton).toBeInTheDocument() - const prevButtonLabel = screen.getByText(prevMonthLabel) - const nextButtonLabel = screen.getByText(nextMonthLabel) + const prevButtonLabel = page.getByText(prevMonthLabel).element() + const nextButtonLabel = page.getByText(nextMonthLabel).element() expect(prevButtonLabel).toBeInTheDocument() expect(nextButtonLabel).toBeInTheDocument() @@ -237,7 +249,7 @@ describe('', () => { it('should programmatically set and render the initial value', async () => { const value = '26/03/2024' - render( + await render( ', () => { value={value} /> ) - const dateInput = screen.getByLabelText('Choose a date') + const dateInput = page.getByLabelText('Choose a date').element() expect(dateInput).toHaveValue(value) expect(dateInput).toBeInTheDocument() @@ -258,7 +270,7 @@ describe('', () => { it('should set interaction type to disabled', async () => { const interactionDisabled = 'disabled' - const { container } = render( + const { container } = await render( ', () => { it('should set interaction type to readonly', async () => { const interactionReadOnly = 'readonly' - const { container } = render( + const { container } = await render( ', () => { /> ) const dateInput = container.querySelector('input') - const calendarButton = screen.getByRole('button') + const calendarButton = page.getByRole('button').element() expect(dateInput).toHaveAttribute(interactionReadOnly) expect(calendarButton).toBeInTheDocument() await userEvent.click(calendarButton) - await waitFor(() => { - const calendarTable = screen.queryByRole('table') + await vi.waitFor(() => { + const calendarTable = page.getByRole('table').query() expect(calendarTable).not.toBeInTheDocument() }) }) it('should set required', async () => { - const { container } = render( + const { container } = await render( ', () => { it('should call onBlur', async () => { const onBlur = vi.fn() - render( + await render( ', () => { onBlur={onBlur} /> ) - const dateInput = screen.getByLabelText('Choose a date') + const dateInput = page.getByLabelText('Choose a date').element() fireEvent.blur(dateInput) - await waitFor(() => { + await vi.waitFor(() => { expect(onBlur).toHaveBeenCalled() }) }) @@ -367,19 +379,19 @@ describe('', () => { ) } - render() + await render() - expect(screen.queryByText(errorMsg)).not.toBeInTheDocument() + expect(page.getByText(errorMsg).query()).not.toBeInTheDocument() - const dateInput = screen.getByLabelText(LABEL_TEXT) + const dateInput = page.getByLabelText(LABEL_TEXT).element() await userEvent.click(dateInput) await userEvent.type(dateInput, 'Not a date') dateInput.blur() - await waitFor(() => { - expect(screen.getByText(errorMsg)).toBeInTheDocument() + await vi.waitFor(() => { + expect(page.getByText(errorMsg).element()).toBeInTheDocument() }) }) @@ -392,7 +404,7 @@ describe('', () => { { type: 'screenreader-only', text: 'Screenreader' } ] - render( + await render( ', () => { /> ) - expect(screen.getByText('TypeLess')).toBeVisible() - expect(screen.getByText('Error')).toBeVisible() - expect(screen.getByText('Success')).toBeVisible() - expect(screen.getByText('Hint')).toBeVisible() + expect(page.getByText('TypeLess').element()).toBeVisible() + expect(page.getByText('Error').element()).toBeVisible() + expect(page.getByText('Success').element()).toBeVisible() + expect(page.getByText('Hint').element()).toBeVisible() - const screenreaderMessage = screen.getByText('Screenreader') + const screenreaderMessage = page.getByText('Screenreader').element() expect(screenreaderMessage).toBeInTheDocument() expect(screenreaderMessage).toHaveClass(/screenReaderContent/) }) @@ -418,7 +430,7 @@ describe('', () => { it('should render date picker dialog with proper role and ARIA label', async () => { const datePickerLabel = 'Date picker' - render( + await render( ', () => { /> ) - const calendarButton = screen.getByRole('button', { name: 'Calendar' }) + const calendarButton = page + .getByRole('button', { name: 'Calendar' }) + .element() await userEvent.click(calendarButton) - await waitFor(() => { - const dialog = screen.getByRole('dialog', { name: datePickerLabel }) + await vi.waitFor(() => { + const dialog = page + .getByRole('dialog', { name: datePickerLabel }) + .element() expect(dialog).toBeInTheDocument() expect(dialog).toHaveAttribute('aria-label', datePickerLabel) }) diff --git a/packages/ui-date-time-input/src/DateTimeInput/__tests__/DateTimeInput.test.tsx b/packages/ui-date-time-input/src/DateTimeInput/__tests__/DateTimeInput.test.tsx index 6e9f63822e..7be152fd91 100644 --- a/packages/ui-date-time-input/src/DateTimeInput/__tests__/DateTimeInput.test.tsx +++ b/packages/ui-date-time-input/src/DateTimeInput/__tests__/DateTimeInput.test.tsx @@ -22,12 +22,12 @@ * SOFTWARE. */ -import { fireEvent, render, screen, waitFor } from '@testing-library/react' -import { vi } from 'vitest' -import userEvent from '@testing-library/user-event' import { DateTimeInput } from '@instructure/ui-date-time-input/latest' import { ApplyLocale, DateTime } from '@instructure/ui-i18n' -import '@testing-library/jest-dom' +import { fireEvent } from '@testing-library/dom' +import { render } from 'vitest-browser-react' +import { page, userEvent } from 'vitest/browser' +import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest' describe('', () => { let consoleWarningMock: ReturnType @@ -48,12 +48,12 @@ describe('', () => { consoleErrorMock.mockRestore() }) - it('should use the default value', () => { + it('should use the default value', async () => { const locale = 'en-US' const timezone = 'US/Eastern' const dateTime = DateTime.parse('2017-05-01T17:30Z', locale, timezone) - render( + await render( ', () => { defaultValue={dateTime.toISOString()} /> ) - const dateInput = screen.getByLabelText('date-input') - const timeInput = screen.getByLabelText('time-input') + const dateInput = page.getByLabelText('date-input').element() + const timeInput = page.getByLabelText('time-input').element() expect(dateInput).toHaveValue('5/1/2017') expect(timeInput).toHaveValue('1:30 PM') }) - it('should use the value', () => { + it('should use the value', async () => { const onChange = vi.fn() const locale = 'en-US' const timezone = 'US/Eastern' const dateTime = DateTime.parse('2017-05-01T23:30Z', locale, timezone) - render( + await render( ', () => { onChange={onChange} /> ) - const dateInput = screen.getByLabelText('date-input') - const timeInput = screen.getByLabelText('time-input') + const dateInput = page.getByLabelText('date-input').element() + const timeInput = page.getByLabelText('time-input').element() expect(dateInput).toHaveValue('5/1/2017') expect(timeInput).toHaveValue('7:30 PM') }) - it('should prefer value to defaultValue', () => { + it('should prefer value to defaultValue', async () => { const locale = 'en-US' const timezone = 'US/Eastern' const value = DateTime.parse('2017-05-01T17:30Z', locale, timezone) const defaultValue = DateTime.parse('2016-04-01T17:00Z', locale, timezone) const onChange = vi.fn() - render( + await render( ', () => { onChange={onChange} /> ) - const dateInput = screen.getByLabelText('date-input') - const timeInput = screen.getByLabelText('time-input') + const dateInput = page.getByLabelText('date-input').element() + const timeInput = page.getByLabelText('time-input').element() expect(dateInput).toHaveValue('5/1/2017') expect(timeInput).toHaveValue('1:30 PM') }) - it('should set time to local midnight when only date is set', () => { + it('should set time to local midnight when only date is set', async () => { const locale = 'en-US' const timezone = 'US/Eastern' const dateObj = DateTime.parse('2017-04-01T18:30Z', locale, timezone) const date = dateObj.toISOString().split('T')[0] - render( + await render( ', () => { defaultValue={date} /> ) - const dateInput = screen.getByLabelText('date-input') - const timeInput = screen.getByLabelText('time-input') + const dateInput = page.getByLabelText('date-input').element() + const timeInput = page.getByLabelText('time-input').element() expect(dateInput).toHaveValue('4/1/2017') expect(timeInput).toHaveValue('12:00 AM') @@ -178,7 +178,7 @@ describe('', () => { it('should call invalidDateTimeMessage if time is set w/o a date and is required', async () => { const invalidDateTimeMessage = vi.fn((_rawd) => 'whoops') - const { container } = render( + const { container } = await render( ', () => { invalidDateTimeMessage={invalidDateTimeMessage} /> ) - const timeInput = screen.getByLabelText('time-input *') + const timeInput = page.getByLabelText('time-input *').element() await userEvent.type(timeInput, '1:00 PM') fireEvent.blur(timeInput) - await waitFor(() => { + await vi.waitFor(() => { expect(container).toHaveTextContent('whoops') expect(invalidDateTimeMessage).toHaveBeenCalled() }) @@ -210,7 +210,7 @@ describe('', () => { it('should not call invalidDateTimeMessage if time is set w/o a date', async () => { const invalidDateTimeMessage = vi.fn((_rawd) => 'whoops') - render( + await render( ', () => { invalidDateTimeMessage={invalidDateTimeMessage} /> ) - const timeInput = screen.getByLabelText('time-input') + const timeInput = page.getByLabelText('time-input').element() await userEvent.type(timeInput, '1:00 PM{enter}') - await waitFor(() => { - const errorMessages = screen.queryByText('whoops') + await vi.waitFor(() => { + const errorMessages = page.getByText('whoops').query() expect(errorMessages).not.toBeInTheDocument() expect(invalidDateTimeMessage).not.toHaveBeenCalled() @@ -246,7 +246,7 @@ describe('', () => { const timezone = 'US/Eastern' const defaultValue = DateTime.parse('2017-05-01T17:00', locale, timezone) - render( + await render( ', () => { defaultValue={defaultValue.toISOString()} /> ) - const timeInput = screen.getByLabelText('time-input') + const timeInput = page.getByLabelText('time-input').element() fireEvent.change(timeInput, { target: { value: '3:00 AM' } }) fireEvent.keyDown(timeInput, { key: 'Enter', code: 'Enter' }) fireEvent.blur(timeInput) - await waitFor(() => { + await vi.waitFor(() => { expect(onChange).toHaveBeenCalled() expect(onChange.mock.calls[0][0].target.value).toMatch('3:00 AM') }) }) - it('should show correct message when TimeInput value changes', () => { - const { container } = render( + it('should show correct message when TimeInput value changes', async () => { + const { container } = await render( ', () => { defaultValue="2018-01-18T13:00" /> ) - const timeInput = screen.getByLabelText('time-input') + const timeInput = page.getByLabelText('time-input').element() fireEvent.change(timeInput, { target: { value: '5:00 PM' } }) fireEvent.keyDown(timeInput, { key: 'Enter', code: 'Enter' }) @@ -305,12 +305,12 @@ describe('', () => { expect(container).toHaveTextContent('Thursday, January 18, 2018 5:00 PM') }) - it('should show the formatted date-time message', () => { + it('should show the formatted date-time message', async () => { const locale = 'en-US' const timezone = 'US/Eastern' const defaultValue = DateTime.parse('2017-05-01T17:30Z', locale, timezone) - const { container } = render( + const { container } = await render( ', () => { expect(container).toHaveTextContent('Monday, May 1, 2017 1:30 PM') }) - it('should show the formatted date-time message in the proper locale', () => { + it('should show the formatted date-time message in the proper locale', async () => { const timezone = 'US/Eastern' const locale = 'fr' const defaultValue = DateTime.parse('2017-05-01T17:30Z', locale, timezone) - const { container } = render( + const { container } = await render( ', () => { expect(container).toHaveTextContent('1 mai 2017 13:30') }) - it('should provide the html elements for date and time input', () => { + it('should provide the html elements for date and time input', async () => { let dref let tref - render( + await render( ', () => { }} /> ) - const dateInput = screen.getByLabelText('date-input') - const timeInput = screen.getByLabelText('time-input') + const dateInput = page.getByLabelText('date-input').element() + const timeInput = page.getByLabelText('time-input').element() expect(dateInput).toEqual(dref) expect(timeInput).toEqual(tref) }) - it('should update message when value prop changes', () => { + it('should update message when value prop changes', async () => { const onChange = vi.fn() const locale = 'en-US' const timezone = 'US/Eastern' @@ -416,14 +416,14 @@ describe('', () => { onChange } - const { container, rerender } = render() + const { container, rerender } = await render() expect(container).toHaveTextContent('May 1, 2017 1:30 PM') - rerender() + await rerender() expect(container).toHaveTextContent('March 29, 2018 12:30 PM') }) - it('should update message when locale changed', () => { + it('should update message when locale changed', async () => { const onChange = vi.fn() const locale = 'en-US' const timezone = 'US/Eastern' @@ -447,14 +447,14 @@ describe('', () => { value: dateTime.toISOString() } - const { container, rerender } = render() + const { container, rerender } = await render() expect(container).toHaveTextContent('May 1, 2017 1:30 PM') - rerender() + await rerender() expect(container).toHaveTextContent('1 mai 2017 13:30') }) - it('should update message when timezone changed', () => { + it('should update message when timezone changed', async () => { const onChange = vi.fn() const locale = 'en-US' const timezone = 'US/Eastern' @@ -477,15 +477,15 @@ describe('', () => { value: dateTime.toISOString() } - const { container, rerender } = render() + const { container, rerender } = await render() expect(container).toHaveTextContent('May 1, 2017 1:30 PM') - rerender() + await rerender() expect(container).toHaveTextContent('May 1, 2017 7:30 PM') }) it('should show error message if initial value is invalid', async () => { - const { container } = render( + const { container } = await render( ', () => { value="totally not a date" /> ) - const dateInput = screen.getByLabelText('date-input') + const dateInput = page.getByLabelText('date-input').element() fireEvent.blur(dateInput) - await waitFor(() => { + await vi.waitFor(() => { expect(container).toHaveTextContent('whoops') }) }) it('should show error message if initial defaultValue is invalid', async () => { - const { container } = render( + const { container } = await render( ', () => { defaultValue="totally not a date" /> ) - const dateInput = screen.getByLabelText('date-input') + const dateInput = page.getByLabelText('date-input').element() fireEvent.blur(dateInput) - await waitFor(() => { + await vi.waitFor(() => { expect(container).toHaveTextContent('whoops') }) }) @@ -554,14 +554,14 @@ describe('', () => { timezone, value: dateTime.toISOString() } - const { container, rerender } = render() + const { container, rerender } = await render() expect(container).toHaveTextContent('May 1, 2017 1:30 PM') - rerender() - const dateInput = screen.getByLabelText('date-input') + await rerender() + const dateInput = page.getByLabelText('date-input').element() fireEvent.blur(dateInput) - await waitFor(() => { + await vi.waitFor(() => { expect(container).toHaveTextContent('whoops') }) }) @@ -586,19 +586,19 @@ describe('', () => { timezone, value: dateTime.toISOString() } - const { container, rerender } = render() + const { container, rerender } = await render() expect(container).toHaveTextContent('May 1, 2017 1:30 PM') - rerender( + await rerender( ) - const dateInput = screen.getByLabelText('date-input') + const dateInput = page.getByLabelText('date-input').element() fireEvent.blur(dateInput) - await waitFor(() => { + await vi.waitFor(() => { expect(container).toHaveTextContent('May 1, 2017 1:30 PM') expect(container).toHaveTextContent('message_text') }) @@ -624,28 +624,28 @@ describe('', () => { timezone, value: dateTime.toISOString() } - const { container, rerender } = render( + const { container, rerender } = await render( ) expect(container).not.toHaveTextContent('2017') - rerender( + await rerender( ) - const dateInput = screen.getByLabelText('date-input') + const dateInput = page.getByLabelText('date-input').element() fireEvent.blur(dateInput) - await waitFor(() => { + await vi.waitFor(() => { expect(container).not.toHaveTextContent('2017') expect(container).toHaveTextContent('message_text') }) - rerender( + await rerender( ', () => { /> ) - fireEvent.blur(screen.getByLabelText('date-input')) + fireEvent.blur(page.getByLabelText('date-input').element()) - await waitFor(() => { + await vi.waitFor(() => { expect(container).toHaveTextContent('2017') expect(container).toHaveTextContent('message_text') }) }) - it('should read locale and timezone from context', () => { + it('should read locale and timezone from context', async () => { const onChange = vi.fn() const dateTime = DateTime.parse('2017-05-01T17:30Z', 'en-US', 'GMT') - const { container } = render( + const { container } = await render( // Africa/Nairobi is GMT +3 ', () => { } // locale string: French format gives DD/MM/YYYY - const { rerender } = render() - const dateInput = screen.getByLabelText('date-input') + const { rerender } = await render( + + ) + const dateInput = page.getByLabelText('date-input').element() expect(dateInput).toHaveValue('01/05/2017') // custom { parser, formatter } object - rerender( + await rerender( ', () => { /> ) - await waitFor(() => { + await vi.waitFor(() => { expect(dateInput).toHaveValue('2017/05/01') }) }) @@ -756,13 +758,13 @@ describe('', () => { timezone: 'US/Eastern' } - const { container, rerender } = render() + const { container, rerender } = await render() expect(container).toHaveTextContent('Monday, May 1, 2017 1:30 PM') - rerender() - fireEvent.blur(screen.getByLabelText('date-input')) + await rerender() + fireEvent.blur(page.getByLabelText('date-input').element()) - await waitFor(() => { + await vi.waitFor(() => { expect(container).toHaveTextContent('5/1/2017, 1:30 PM') }) }) @@ -787,18 +789,18 @@ describe('', () => { timezone, value: dateTime.toISOString() } - const { container, rerender } = render() + const { container, rerender } = await render() expect(container).toHaveTextContent('May 1, 2017 1:30 PM') const newDateStr = '2022-03-29T19:00Z' - rerender() - const dateInput = screen.getByLabelText('date-input') - const timeInput = screen.getByLabelText('time-input') + await rerender() + const dateInput = page.getByLabelText('date-input').element() + const timeInput = page.getByLabelText('time-input').element() fireEvent.blur(dateInput) - await waitFor(() => { + await vi.waitFor(() => { expect(dateInput).toHaveValue('3/29/2022') expect(timeInput).toHaveValue('3:00 PM') }) @@ -807,7 +809,7 @@ describe('', () => { it("should throw warning if date select and initialTimeForNewDate prop's value is not HH:MM", async () => { const initialTimeForNewDate = 'WRONG_FORMAT' - render( + await render( ', () => { /> ) - const dateInput = screen.getByLabelText('date-input') + const dateInput = page.getByLabelText('date-input').element() fireEvent.change(dateInput, { target: { value: 'May 1, 2017' } }) fireEvent.keyDown(dateInput, { key: 'Enter', code: 'Enter' }) fireEvent.blur(dateInput) - await waitFor(() => { + await vi.waitFor(() => { expect(consoleErrorMock.mock.calls[0][0]).toBe( `Warning: [DateTimeInput] initialTimeForNewDate prop is not in the correct format. Please use HH:MM format.` ) @@ -842,7 +844,7 @@ describe('', () => { it('should throw warning if initialTimeForNewDate prop hour and minute values are not in interval', async () => { const initialTimeForNewDate = '99:99' - render( + await render( ', () => { initialTimeForNewDate={initialTimeForNewDate} /> ) - const dateInput = screen.getByLabelText('date-input') + const dateInput = page.getByLabelText('date-input').element() fireEvent.change(dateInput, { target: { value: 'May 1, 2017' } }) fireEvent.keyDown(dateInput, { key: 'Enter', code: 'Enter' }) fireEvent.blur(dateInput) - await waitFor(() => { + await vi.waitFor(() => { expect(consoleErrorMock.mock.calls[0][0]).toEqual( expect.stringContaining( `Warning: [DateTimeInput] 0 <= hour < 24 and 0 <= minute < 60 for initialTimeForNewDate prop.` @@ -881,7 +883,7 @@ describe('', () => { const initialTimeForNewDate = '16:16' const defaultValue = '2018-01-18T13:30' - const { container } = render( + const { container } = await render( ', () => { initialTimeForNewDate={initialTimeForNewDate} /> ) - const timeInput = screen.getByLabelText('time-input') + const timeInput = page.getByLabelText('time-input').element() expect(timeInput).toHaveValue('1:30 PM') expect(container).toHaveTextContent('Thursday, January 18, 2018 1:30 PM') @@ -912,7 +914,7 @@ describe('', () => { // ("LL" by default) as a hint. This test verifies that typing an ISO date string // still works correctly after the switch to DateInput v2. const onChange = vi.fn() - render( + await render( ', () => { onChange={onChange} /> ) - const dateInput = screen.getByLabelText('date-input') + const dateInput = page.getByLabelText('date-input').element() await userEvent.type(dateInput, '2017-05-01') fireEvent.blur(dateInput) - await waitFor(() => { + await vi.waitFor(() => { expect(onChange).toHaveBeenCalled() expect(onChange.mock.calls[0][1]).toContain('2017-05-01') expect(dateInput).toHaveValue('5/1/2017') @@ -954,7 +956,7 @@ describe('', () => { const locale = 'en-US' const timezone = 'US/Eastern' - render( + await render( ', () => { /> ) - const calendarButton = screen.getByRole('button', { name: 'Open calendar' }) + const calendarButton = page + .getByRole('button', { name: 'Open calendar' }) + .element() await userEvent.click(calendarButton) - await waitFor(() => { + await vi.waitFor(() => { expect( - screen.getByRole('button', { name: '15 May 2017' }) + page.getByRole('button', { name: '15 May 2017' }).element() ).toBeInTheDocument() }) - await userEvent.click(screen.getByRole('button', { name: '15 May 2017' })) + await userEvent.click( + page.getByRole('button', { name: '15 May 2017' }).element() + ) - await waitFor(() => { - expect(screen.getByLabelText('date-input')).toHaveValue('5/15/2017') - expect(screen.getByLabelText('time-input')).toHaveValue('1:30 PM') + await vi.waitFor(() => { + expect(page.getByLabelText('date-input').element()).toHaveValue( + '5/15/2017' + ) + expect(page.getByLabelText('time-input').element()).toHaveValue('1:30 PM') expect(onChange).toHaveBeenCalled() expect(onChange.mock.calls[0][1]).toContain('2017-05-15') }) @@ -999,7 +1007,7 @@ describe('', () => { // before onRequestValidateDate. DateTimeInput must handle this correctly: the // displayed value should be normalized and onChange should fire with the correct ISO. const onChange = vi.fn() - render( + await render( ', () => { onChange={onChange} /> ) - const dateInput = screen.getByLabelText('date-input') + const dateInput = page.getByLabelText('date-input').element() await userEvent.type(dateInput, 'May 1 2017') fireEvent.blur(dateInput) - await waitFor(() => { + await vi.waitFor(() => { expect(dateInput).toHaveValue('5/1/2017') expect(onChange).toHaveBeenCalled() expect(onChange.mock.calls[0][1]).toContain('2017-05-01') @@ -1036,7 +1044,7 @@ describe('', () => { // (default 'LL'). The tests below document the regression: these inputs were // accepted in v1 but are currently rejected in v2. They should pass once fixed. const renderComponent = (onChange = vi.fn()) => - render( + await render( ', () => { it('should accept abbreviated month name (ll format: "Sep 4, 1986")', async () => { const onChange = vi.fn() renderComponent(onChange) - const dateInput = screen.getByLabelText('date-input') + const dateInput = page.getByLabelText('date-input').element() await userEvent.type(dateInput, 'Sep 4, 1986') fireEvent.blur(dateInput) - await waitFor(() => { - expect(screen.queryByText('whoops')).not.toBeInTheDocument() + await vi.waitFor(() => { + expect(page.getByText('whoops').query()).not.toBeInTheDocument() expect(onChange).toHaveBeenCalled() expect(onChange.mock.calls[0][1]).toContain('1986-09-04') }) @@ -1073,13 +1081,13 @@ describe('', () => { it('should accept numeric date with leading zeros (L format: "09/04/1986")', async () => { const onChange = vi.fn() renderComponent(onChange) - const dateInput = screen.getByLabelText('date-input') + const dateInput = page.getByLabelText('date-input').element() await userEvent.type(dateInput, '09/04/1986') fireEvent.blur(dateInput) - await waitFor(() => { - expect(screen.queryByText('whoops')).not.toBeInTheDocument() + await vi.waitFor(() => { + expect(page.getByText('whoops').query()).not.toBeInTheDocument() expect(onChange).toHaveBeenCalled() expect(onChange.mock.calls[0][1]).toContain('1986-09-04') }) @@ -1088,13 +1096,13 @@ describe('', () => { it('should accept numeric date without leading zeros (l format: "9/4/1986")', async () => { const onChange = vi.fn() renderComponent(onChange) - const dateInput = screen.getByLabelText('date-input') + const dateInput = page.getByLabelText('date-input').element() await userEvent.type(dateInput, '9/4/1986') fireEvent.blur(dateInput) - await waitFor(() => { - expect(screen.queryByText('whoops')).not.toBeInTheDocument() + await vi.waitFor(() => { + expect(page.getByText('whoops').query()).not.toBeInTheDocument() expect(onChange).toHaveBeenCalled() expect(onChange.mock.calls[0][1]).toContain('1986-09-04') }) @@ -1103,13 +1111,13 @@ describe('', () => { it('should accept date with time component (LLL format: "September 4, 1986 8:30 PM")', async () => { const onChange = vi.fn() renderComponent(onChange) - const dateInput = screen.getByLabelText('date-input') + const dateInput = page.getByLabelText('date-input').element() await userEvent.type(dateInput, 'September 4, 1986 8:30 PM') fireEvent.blur(dateInput) - await waitFor(() => { - expect(screen.queryByText('whoops')).not.toBeInTheDocument() + await vi.waitFor(() => { + expect(page.getByText('whoops').query()).not.toBeInTheDocument() expect(onChange).toHaveBeenCalled() expect(onChange.mock.calls[0][1]).toContain('1986-09-05') }) @@ -1117,7 +1125,7 @@ describe('', () => { }) it('should render the year picker in the calendar when withYearPicker is set', async () => { - render( + await render( ', () => { /> ) - const calendarButton = screen.getByRole('button', { name: 'Open calendar' }) + const calendarButton = page + .getByRole('button', { name: 'Open calendar' }) + .element() await userEvent.click(calendarButton) - await waitFor(() => { - const yearPicker = screen.getByRole('combobox', { - description: 'Pick a year' - }) + await vi.waitFor(() => { + const yearPicker = page + .getByRole('combobox', { + description: 'Pick a year' + }) + .element() expect(yearPicker).toBeInTheDocument() expect(yearPicker).toHaveValue('2017') }) @@ -1155,7 +1167,7 @@ describe('', () => { it('should call consumer onChange exactly once when typing a short-format date and blurring', async () => { const onChange = vi.fn() - render( + await render( ', () => { onChange={onChange} /> ) - const dateInput = screen.getByLabelText('date-input') + const dateInput = page.getByLabelText('date-input').element() await userEvent.type(dateInput, '9/1/2017') fireEvent.blur(dateInput) - await waitFor(() => { + await vi.waitFor(() => { expect(dateInput).toHaveValue('9/1/2017') expect(onChange).toHaveBeenCalledTimes(1) expect(onChange.mock.calls[0][1]).toContain('2017-09-01') @@ -1200,8 +1212,8 @@ describe('', () => { invalidDateTimeMessage: 'whoops' } as const - it('uses datePlaceholder when provided', () => { - render( + it('uses datePlaceholder when provided', async () => { + await render( ', () => { datePlaceholder="Pick a date" /> ) - expect(screen.getByLabelText('date-input')).toHaveAttribute( + expect(page.getByLabelText('date-input').element()).toHaveAttribute( 'placeholder', 'Pick a date' ) }) - it('shows built-in format hint when datePlaceholder is omitted', () => { - render( + it('shows built-in format hint when datePlaceholder is omitted', async () => { + await render( ) expect( - screen.getByLabelText('date-input').getAttribute('placeholder') + page.getByLabelText('date-input').element().getAttribute('placeholder') ).toBeTruthy() }) }) diff --git a/packages/ui-dom-utils/src/__tests__/addEventListener.test.tsx b/packages/ui-dom-utils/src/__tests__/addEventListener.test.tsx index dc720285b3..3a58ccf1a7 100644 --- a/packages/ui-dom-utils/src/__tests__/addEventListener.test.tsx +++ b/packages/ui-dom-utils/src/__tests__/addEventListener.test.tsx @@ -22,16 +22,16 @@ * SOFTWARE. */ -import { fireEvent, render } from '@testing-library/react' -import { vi } from 'vitest' -import '@testing-library/jest-dom' +import { fireEvent } from '@testing-library/dom' +import { render } from 'vitest-browser-react' +import { describe, it, expect, vi } from 'vitest' import { addEventListener } from '../addEventListener.js' describe('addEventListener', () => { - it('should add an event listener and provide a remove method', () => { + it('should add an event listener and provide a remove method', async () => { const callback = vi.fn() - const { container } = render(
) + const { container } = await render(
) const node = container.firstChild as HTMLDivElement const listener = addEventListener(node, 'click', callback) diff --git a/packages/ui-dom-utils/src/__tests__/addInputModeListener.test.tsx b/packages/ui-dom-utils/src/__tests__/addInputModeListener.test.tsx index d9a936304c..d2da2c21c3 100644 --- a/packages/ui-dom-utils/src/__tests__/addInputModeListener.test.tsx +++ b/packages/ui-dom-utils/src/__tests__/addInputModeListener.test.tsx @@ -22,16 +22,17 @@ * SOFTWARE. */ -import { render, fireEvent, screen } from '@testing-library/react' -import { vi } from 'vitest' -import '@testing-library/jest-dom' +import { fireEvent } from '@testing-library/dom' +import { render } from 'vitest-browser-react' +import { page } from 'vitest/browser' +import { describe, it, expect, vi } from 'vitest' import { addInputModeListener } from '../addInputModeListener.js' describe('addInputModeListener', () => { - it('should handle input mode changes', () => { + it('should handle input mode changes', async () => { const handleInputModeChange = vi.fn() - render( + await render(
@@ -42,7 +43,7 @@ describe('addInputModeListener', () => { onInputModeChange: handleInputModeChange }) - const button = screen.getByRole('button', { name: 'hello' }) + const button = page.getByRole('button', { name: 'hello' }).element() fireEvent.mouseUp(button) expect(inputModeListener.isKeyboardMode()).toBe(false) diff --git a/packages/ui-dom-utils/src/__tests__/addPositionChangeListener.test.tsx b/packages/ui-dom-utils/src/__tests__/addPositionChangeListener.test.tsx index 38d5494fa3..5ede997b8e 100644 --- a/packages/ui-dom-utils/src/__tests__/addPositionChangeListener.test.tsx +++ b/packages/ui-dom-utils/src/__tests__/addPositionChangeListener.test.tsx @@ -22,9 +22,8 @@ * SOFTWARE. */ -import { render, waitFor } from '@testing-library/react' -import { vi } from 'vitest' -import '@testing-library/jest-dom' +import { render } from 'vitest-browser-react' +import { describe, it, expect, vi } from 'vitest' import { addPositionChangeListener } from '../addPositionChangeListener.js' const mockRect = { @@ -44,7 +43,7 @@ describe('addPositionChangeListener', () => { const callback = vi.fn() Element.prototype.getBoundingClientRect = vi.fn(() => mockRect as DOMRect) - const { container } = render(
) + const { container } = await render(
) const node = container.firstChild as HTMLDivElement const listener = addPositionChangeListener(node, callback) @@ -54,7 +53,7 @@ describe('addPositionChangeListener', () => { return { ...mockRect, top: 200 } as DOMRect }) - await waitFor(() => { + await vi.waitFor(() => { expect(callback).toHaveBeenCalledTimes(1) expect(typeof listener.remove).toBe('function') }) diff --git a/packages/ui-dom-utils/src/__tests__/findTabbable.test.tsx b/packages/ui-dom-utils/src/__tests__/findTabbable.test.tsx index e069cf049b..be3626ba67 100644 --- a/packages/ui-dom-utils/src/__tests__/findTabbable.test.tsx +++ b/packages/ui-dom-utils/src/__tests__/findTabbable.test.tsx @@ -22,14 +22,14 @@ * SOFTWARE. */ -import { render } from '@testing-library/react' -import '@testing-library/jest-dom' +import { render } from 'vitest-browser-react' +import { describe, it, expect } from 'vitest' import { findTabbable } from '../findTabbable.js' describe('findTabbable', () => { describe('tabbable content', () => { - it('should find tabbable descendants', () => { - const { container } = render( + it('should find tabbable descendants', async () => { + const { container } = await render(
Tabbable
Not Tabbable
@@ -48,9 +48,9 @@ describe('findTabbable', () => { }) describe('tabbable root', () => { - it('should search the root node when shouldSearchRootNode is set', () => { + it('should search the root node when shouldSearchRootNode is set', async () => { const shouldSearchRootNode = true - const { container } = render( + const { container } = await render( diff --git a/packages/ui-dom-utils/src/__tests__/getCSSStyleDeclaration.test.tsx b/packages/ui-dom-utils/src/__tests__/getCSSStyleDeclaration.test.tsx index 9f1f7241ed..7e561bb4e7 100644 --- a/packages/ui-dom-utils/src/__tests__/getCSSStyleDeclaration.test.tsx +++ b/packages/ui-dom-utils/src/__tests__/getCSSStyleDeclaration.test.tsx @@ -22,8 +22,7 @@ * SOFTWARE. */ -import '@testing-library/jest-dom' -import { vi } from 'vitest' +import { describe, it, expect, vi } from 'vitest' import { getCSSStyleDeclaration } from '../getCSSStyleDeclaration.js' describe('getCSSStyleDeclaration', () => { diff --git a/packages/ui-dom-utils/src/__tests__/getClassList.test.tsx b/packages/ui-dom-utils/src/__tests__/getClassList.test.tsx index 4327a8e9ce..ee7dd092f8 100644 --- a/packages/ui-dom-utils/src/__tests__/getClassList.test.tsx +++ b/packages/ui-dom-utils/src/__tests__/getClassList.test.tsx @@ -22,13 +22,15 @@ * SOFTWARE. */ -import { render } from '@testing-library/react' -import '@testing-library/jest-dom' +import { render } from 'vitest-browser-react' +import { describe, it, expect } from 'vitest' import { getClassList } from '../getClassList.js' describe('getClassList', () => { - it('should provide classlist methods', () => { - const { container } = render(Test) + it('should provide classlist methods', async () => { + const { container } = await render( + Test + ) const node = container.firstChild as HTMLElement const classes = getClassList(node) diff --git a/packages/ui-dom-utils/src/__tests__/getFontSize.test.tsx b/packages/ui-dom-utils/src/__tests__/getFontSize.test.tsx index eaa28dee30..18d4fb43f8 100644 --- a/packages/ui-dom-utils/src/__tests__/getFontSize.test.tsx +++ b/packages/ui-dom-utils/src/__tests__/getFontSize.test.tsx @@ -22,13 +22,15 @@ * SOFTWARE. */ -import { render } from '@testing-library/react' -import '@testing-library/jest-dom' +import { render } from 'vitest-browser-react' +import { describe, it, expect } from 'vitest' import { getFontSize } from '../getFontSize.js' describe('getFontSize', () => { - it('should return font size as a number', () => { - const { container } = render(Test) + it('should return font size as a number', async () => { + const { container } = await render( + Test + ) const node = container.firstChild expect(getFontSize(node)).toBe(17) diff --git a/packages/ui-dom-utils/src/__tests__/getOffsetParents.test.tsx b/packages/ui-dom-utils/src/__tests__/getOffsetParents.test.tsx index 3dfbd04996..58c5bbf47a 100644 --- a/packages/ui-dom-utils/src/__tests__/getOffsetParents.test.tsx +++ b/packages/ui-dom-utils/src/__tests__/getOffsetParents.test.tsx @@ -22,8 +22,8 @@ * SOFTWARE. */ -import { render } from '@testing-library/react' -import '@testing-library/jest-dom' +import { render } from 'vitest-browser-react' +import { describe, it, expect, beforeEach } from 'vitest' import { getScrollParents } from '../getScrollParents.js' describe('getScrollParents', () => { @@ -71,8 +71,8 @@ describe('getScrollParents', () => {
) - beforeEach(() => { - render(node) + beforeEach(async () => { + await render(node) }) it('should find scroll parent for inline elements', () => { diff --git a/packages/ui-dom-utils/src/__tests__/getScrollParents.test.tsx b/packages/ui-dom-utils/src/__tests__/getScrollParents.test.tsx index f57f2a3604..3b80c2f6f3 100644 --- a/packages/ui-dom-utils/src/__tests__/getScrollParents.test.tsx +++ b/packages/ui-dom-utils/src/__tests__/getScrollParents.test.tsx @@ -22,8 +22,8 @@ * SOFTWARE. */ -import { render } from '@testing-library/react' -import '@testing-library/jest-dom' +import { render } from 'vitest-browser-react' +import { describe, it, expect } from 'vitest' import { getOffsetParents } from '../getOffsetParents.js' describe('getOffsetParents', () => { @@ -57,8 +57,8 @@ describe('getOffsetParents', () => {
) - it('should find offset parent for inline elements', () => { - const { getByTestId } = render(node) + it('should find offset parent for inline elements', async () => { + const { getByTestId } = await render(node) const child = getByTestId('child-1') const parent = getByTestId('child_1_wrapper_parent') const offsetParents = getOffsetParents(child) @@ -66,16 +66,16 @@ describe('getOffsetParents', () => { expect(offsetParents[0]).toBe(parent) }) - it('should ignore static parents when absolute', () => { - const { getByTestId } = render(node) + it('should ignore static parents when absolute', async () => { + const { getByTestId } = await render(node) const child = getByTestId('child-2') const offsetParents = getOffsetParents(child) expect(offsetParents.length).toBe(3) }) - it('should handle fixed', () => { - const { getByTestId } = render(node) + it('should handle fixed', async () => { + const { getByTestId } = await render(node) const child = getByTestId('child-3') const offsetParents = getOffsetParents(child) diff --git a/packages/ui-dom-utils/src/__tests__/isCustomElement.test.tsx b/packages/ui-dom-utils/src/__tests__/isCustomElement.test.tsx index f705ad90c7..8535bf47e7 100644 --- a/packages/ui-dom-utils/src/__tests__/isCustomElement.test.tsx +++ b/packages/ui-dom-utils/src/__tests__/isCustomElement.test.tsx @@ -22,7 +22,7 @@ * SOFTWARE. */ -import '@testing-library/jest-dom' +import { describe, it, expect, beforeAll } from 'vitest' import { isDefinedCustomElement } from '../isDefinedCustomElement.js' class TestElement extends HTMLElement {} diff --git a/packages/ui-dom-utils/src/__tests__/isVisible.test.tsx b/packages/ui-dom-utils/src/__tests__/isVisible.test.tsx index e145d891b7..7c69760b12 100644 --- a/packages/ui-dom-utils/src/__tests__/isVisible.test.tsx +++ b/packages/ui-dom-utils/src/__tests__/isVisible.test.tsx @@ -22,64 +22,65 @@ * SOFTWARE. */ -import { render, screen } from '@testing-library/react' -import '@testing-library/jest-dom' +import { render } from 'vitest-browser-react' +import { page } from 'vitest/browser' +import { describe, it, expect } from 'vitest' import { isVisible } from '../isVisible.js' describe('isVisible', () => { - it('should recognize visible elements', () => { - render(
Hello world!
) - const element = screen.getByTestId('test') + it('should recognize visible elements', async () => { + await render(
Hello world!
) + const element = page.getByTestId('test').element() expect(isVisible(element)).toBe(true) }) - it('should recognize elements with display: none', () => { - render( + it('should recognize elements with display: none', async () => { + await render(
Hello world!
) - const element = screen.getByTestId('test').firstChild + const element = page.getByTestId('test').element().firstChild expect(isVisible(element)).toBe(false) }) - it('should recognize elements hidden with clip', () => { + it('should recognize elements hidden with clip', async () => { const style: React.CSSProperties = { position: 'absolute', overflow: 'hidden', clip: 'rect(0,0,0,0)' } - render( + await render(
Hello world!
) - const element = screen.getByTestId('test').firstChild + const element = page.getByTestId('test').element().firstChild expect(isVisible(element)).toBe(false) }) - it('should recognize clipped elements that are not hidden', () => { + it('should recognize clipped elements that are not hidden', async () => { const style: React.CSSProperties = { position: 'absolute', overflow: 'hidden', clip: 'rect(0,0,10px,0)' } - render( + await render(
Hello world!
) - const element = screen.getByTestId('test').firstChild + const element = page.getByTestId('test').element().firstChild expect(isVisible(element)).toBe(true) }) - it('should recursively check parent visibility', () => { + it('should recursively check parent visibility', async () => { const style: React.CSSProperties = { visibility: 'hidden' } - render( + await render(
@@ -88,15 +89,15 @@ describe('isVisible', () => {
) - const element = screen.getByTestId('test-2') + const element = page.getByTestId('test-2').element() expect(isVisible(element, false)).toBe(true) expect(isVisible(element)).toBe(false) }) - it('should not recursively check text nodes', () => { + it('should not recursively check text nodes', async () => { const style: React.CSSProperties = { visibility: 'hidden' } - render( + await render(
@@ -105,7 +106,7 @@ describe('isVisible', () => {
) - const element = screen.getByTestId('test-2').firstChild + const element = page.getByTestId('test-2').element().firstChild expect(isVisible(element, false)).toBe(true) expect(isVisible(element)).toBe(false) diff --git a/packages/ui-dom-utils/src/__tests__/requestAnimationFrame.test.tsx b/packages/ui-dom-utils/src/__tests__/requestAnimationFrame.test.tsx index 4217172fcb..4f9d92d7e8 100644 --- a/packages/ui-dom-utils/src/__tests__/requestAnimationFrame.test.tsx +++ b/packages/ui-dom-utils/src/__tests__/requestAnimationFrame.test.tsx @@ -22,8 +22,7 @@ * SOFTWARE. */ -import { waitFor } from '@testing-library/react' -import { vi } from 'vitest' +import { describe, it, expect, vi } from 'vitest' import { requestAnimationFrame } from '../requestAnimationFrame.js' describe('requestAnimationFrame', () => { @@ -31,7 +30,7 @@ describe('requestAnimationFrame', () => { const callback = vi.fn() const raf = requestAnimationFrame(callback) - await waitFor(() => { + await vi.waitFor(() => { expect(callback).toHaveBeenCalledTimes(1) expect(typeof raf.cancel).toBe('function') }) diff --git a/packages/ui-drawer-layout/src/DrawerLayout/__tests__/DrawerContent.test.tsx b/packages/ui-drawer-layout/src/DrawerLayout/__tests__/DrawerContent.test.tsx index 8a039040d9..4dc6b80d6c 100644 --- a/packages/ui-drawer-layout/src/DrawerLayout/__tests__/DrawerContent.test.tsx +++ b/packages/ui-drawer-layout/src/DrawerLayout/__tests__/DrawerContent.test.tsx @@ -22,16 +22,18 @@ * SOFTWARE. */ -import { render, screen, waitFor } from '@testing-library/react' -import { vi } from 'vitest' -import '@testing-library/jest-dom' +import { render } from 'vitest-browser-react' +import { page } from 'vitest/browser' +import { describe, it, expect, vi } from 'vitest' import { DrawerContent } from '@instructure/ui-drawer-layout/latest' describe('', () => { it('should render', async () => { - render(Hello World) - const drawerContent = screen.getByLabelText('DrawerContentTest') + await render( + Hello World + ) + const drawerContent = page.getByLabelText('DrawerContentTest').element() expect(drawerContent).toBeInTheDocument() expect(drawerContent).toHaveTextContent('Hello World') @@ -39,29 +41,29 @@ describe('', () => { it('should call the content ref', async () => { const contentRef = vi.fn() - render( + await render( Hello World ) - const drawerContent = screen.getByLabelText('DrawerContentTest') + const drawerContent = page.getByLabelText('DrawerContentTest').element() expect(contentRef).toHaveBeenCalledWith(drawerContent) }) it('should not transition on mount, just on update', async () => { - const { rerender } = render( + const { rerender } = await render( Hello World ) - const drawerContent = screen.getByLabelText('DrawerContentTest') + const drawerContent = page.getByLabelText('DrawerContentTest').element() const styleOnMount = getComputedStyle(drawerContent) expect(styleOnMount.transition).toBe('') - rerender(Hello World) + await rerender(Hello World) - await waitFor(() => { - const drawerContentUpdated = screen.getByLabelText('test') + await vi.waitFor(() => { + const drawerContentUpdated = page.getByLabelText('test').element() const updatedStyle = getComputedStyle(drawerContentUpdated) expect(updatedStyle.transition).not.toBe('') diff --git a/packages/ui-drawer-layout/src/DrawerLayout/__tests__/DrawerLayout.test.tsx b/packages/ui-drawer-layout/src/DrawerLayout/__tests__/DrawerLayout.test.tsx index 4fbdbc1f08..10d7c35388 100644 --- a/packages/ui-drawer-layout/src/DrawerLayout/__tests__/DrawerLayout.test.tsx +++ b/packages/ui-drawer-layout/src/DrawerLayout/__tests__/DrawerLayout.test.tsx @@ -22,16 +22,18 @@ * SOFTWARE. */ -import { render, screen, waitFor, fireEvent, act } from '@testing-library/react' -import { vi } from 'vitest' +import { fireEvent } from '@testing-library/dom' +import { render } from 'vitest-browser-react' +import { page } from 'vitest/browser' +import { describe, it, expect, vi } from 'vitest' import DrawerLayoutFixture from '../v2/__fixtures__/DrawerLayout.fixture.js' import { Button } from '@instructure/ui-buttons/latest' import { DrawerLayout } from '@instructure/ui-drawer-layout/latest' import { View } from '@instructure/ui-view/latest' describe('', () => { - it('should render', () => { - const { container } = render() + it('should render', async () => { + const { container } = await render() const layout = container.querySelector('div[class$="-drawerLayout"]') @@ -39,11 +41,11 @@ describe('', () => { }) it('should render a DrawerTray and DrawerContent', async () => { - const { container } = render( + const { container } = await render( ) - const tray = screen.getByText('Hello from tray') + const tray = page.getByText('Hello from tray').element() const contentWrapper = container.querySelector( 'div[class$="drawerLayout__content"]' ) @@ -55,7 +57,7 @@ describe('', () => { describe('DrawerTray a11y role', () => { it('should have role="dialog" in overlay mode', async () => { - render( + await render( @@ -68,14 +70,14 @@ describe('', () => { ) - await waitFor(() => { - const drawerTray = screen.getByLabelText('a tray test') + await vi.waitFor(() => { + const drawerTray = page.getByLabelText('a tray test').element() expect(drawerTray).toHaveAttribute('role', 'dialog') }) }) it('should have role="region" when not in overlay mode', async () => { - render( + await render( @@ -88,8 +90,8 @@ describe('', () => { ) - await waitFor(() => { - const drawerTray = screen.getByLabelText('a tray test') + await vi.waitFor(() => { + const drawerTray = page.getByLabelText('a tray test').element() expect(drawerTray).toHaveAttribute('role', 'region') }) }) @@ -126,16 +128,16 @@ describe('', () => { ) - const { rerender } = render() - expect(screen.getByText(msg)).toBeInTheDocument() + const { rerender } = await render() + expect(page.getByText(msg).element()).toBeInTheDocument() await act(() => new Promise((resolve) => requestAnimationFrame(resolve))) fireEvent.keyUp(document, { keyCode: 27 }) // ESC key - await waitFor(() => { + await vi.waitFor(() => { expect(onDismiss).toHaveBeenCalled() }) - rerender() - await waitFor(() => { - expect(screen.queryByText(msg)).not.toBeInTheDocument() + await rerender() + await vi.waitFor(() => { + expect(page.getByText(msg).query()).not.toBeInTheDocument() }) }) }) diff --git a/packages/ui-drawer-layout/src/DrawerLayout/__tests__/DrawerTray.test.tsx b/packages/ui-drawer-layout/src/DrawerLayout/__tests__/DrawerTray.test.tsx index 649c2c9300..3fe5a52a3f 100644 --- a/packages/ui-drawer-layout/src/DrawerLayout/__tests__/DrawerTray.test.tsx +++ b/packages/ui-drawer-layout/src/DrawerLayout/__tests__/DrawerTray.test.tsx @@ -22,15 +22,15 @@ * SOFTWARE. */ -import { render, screen, waitFor } from '@testing-library/react' -import { vi } from 'vitest' -import '@testing-library/jest-dom' +import { render } from 'vitest-browser-react' +import { page } from 'vitest/browser' +import { describe, it, expect, vi } from 'vitest' import { DrawerTray } from '@instructure/ui-drawer-layout/latest' describe('', () => { it('should render tray content when open', async () => { - render( + await render( ', () => { }} /> ) - const drawerTray = screen.getByLabelText('DrawerTray Example') + const drawerTray = page.getByLabelText('DrawerTray Example').element() expect(drawerTray).toBeInTheDocument() expect(drawerTray).toHaveTextContent('Hello from layout tray') @@ -47,7 +47,7 @@ describe('', () => { it('should call the contentRef', async () => { const contentRef = vi.fn() - render( + await render( ', () => { }} /> ) - const drawerTray = screen.getByLabelText('DrawerTray Example') + const drawerTray = page.getByLabelText('DrawerTray Example').element() expect(contentRef).toHaveBeenCalledWith(drawerTray.parentElement) }) @@ -65,7 +65,7 @@ describe('', () => { it('should call onOpen', async () => { const onOpen = vi.fn() - const { rerender } = render( + const { rerender } = await render( ', () => { expect(onOpen).not.toHaveBeenCalled() // set prop open - rerender( + await rerender( ', () => { /> ) - await waitFor(() => { + await vi.waitFor(() => { expect(onOpen).toHaveBeenCalled() }) }) it('should call onOpen when open initially', async () => { const onOpen = vi.fn() - render( + await render( ', () => { /> ) - await waitFor(() => { + await vi.waitFor(() => { expect(onOpen).toHaveBeenCalled() }) }) @@ -116,7 +116,7 @@ describe('', () => { it('should call onClose', async () => { const onClose = vi.fn() - const { rerender } = render( + const { rerender } = await render( ', () => { expect(onClose).not.toHaveBeenCalled() // set prop open - rerender( + await rerender( ', () => { /> ) - await waitFor(() => { + await vi.waitFor(() => { expect(onClose).toHaveBeenCalled() }) }) diff --git a/packages/ui-drilldown/src/Drilldown/__tests__/Drilldown.test.tsx b/packages/ui-drilldown/src/Drilldown/__tests__/Drilldown.test.tsx index b19a96fb62..a39c0e2c78 100644 --- a/packages/ui-drilldown/src/Drilldown/__tests__/Drilldown.test.tsx +++ b/packages/ui-drilldown/src/Drilldown/__tests__/Drilldown.test.tsx @@ -22,10 +22,9 @@ * SOFTWARE. */ -import { render, screen, waitFor } from '@testing-library/react' -import { vi } from 'vitest' -import userEvent from '@testing-library/user-event' -import '@testing-library/jest-dom' +import { render } from 'vitest-browser-react' +import { page, userEvent } from 'vitest/browser' +import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest' import { runAxeCheck } from '@instructure/ui-axe-check' import { CheckInstUIIcon } from '@instructure/ui-icons' @@ -61,7 +60,7 @@ describe('', () => { describe('rootPageId prop', () => { it('should set the initial page and render it', async () => { - render( + await render( Option-01 @@ -72,9 +71,9 @@ describe('', () => { ) - const drilldown = screen.getByRole('menu') - const options = screen.getAllByRole('menuitem') - const rootlessOption = screen.queryByText('Option-01') + const drilldown = page.getByRole('menu').element() + const options = page.getByRole('menuitem').elements() + const rootlessOption = page.getByText('Option-01').query() expect(drilldown).toBeInTheDocument() expect(rootlessOption).not.toBeInTheDocument() @@ -87,15 +86,15 @@ describe('', () => { describe('children prop', () => { it('should not allow non-DrilldownPage children', async () => { - render( + await render(
DIV-child
) - const drilldown = screen.queryByRole('menu') - const options = screen.queryAllByRole('menuitem') - const notAllowedChild = screen.queryByText('DIV-child') + const drilldown = page.getByRole('menu').query() + const options = page.getByRole('menuitem').elements() + const notAllowedChild = page.getByText('DIV-child').query() expect(drilldown).not.toBeInTheDocument() expect(options.length).toBe(0) @@ -105,7 +104,7 @@ describe('', () => { it('should not crash for weird option ids', async () => { const onSelect = vi.fn() const weirdID = 'some"_weird!@#$%^&*()\\|`id' - render( + await render( {data.map((option) => ( @@ -121,10 +120,10 @@ describe('', () => { ) - const option_1 = screen.getByTestId(weirdID + 'opt_1') + const option_1 = page.getByTestId(weirdID + 'opt_1').element() await userEvent.click(option_1) - await waitFor(() => { + await vi.waitFor(() => { expect(onSelect).toHaveBeenCalled() }) }) @@ -132,7 +131,7 @@ describe('', () => { describe('id prop', () => { it('should put id attr on the drilldown', async () => { - render( + await render( Option @@ -140,7 +139,7 @@ describe('', () => { ) - const drilldown = screen.getByRole('menu') + const drilldown = page.getByRole('menu').element() expect(drilldown).toBeInTheDocument() expect(drilldown).toHaveAttribute('id', 'testId') @@ -149,7 +148,7 @@ describe('', () => { describe('label prop', () => { it('should be added as aria-label', async () => { - render( + await render( Option @@ -157,7 +156,7 @@ describe('', () => { ) - const drilldown = screen.getByRole('menu') + const drilldown = page.getByRole('menu').element() expect(drilldown).toBeInTheDocument() expect(drilldown).toHaveAttribute('aria-label', 'testLabel') @@ -166,7 +165,7 @@ describe('', () => { describe('disabled prop', () => { it('should disable all options', async () => { - render( + await render( Option @@ -175,7 +174,7 @@ describe('', () => { ) - const options = screen.getAllByRole('menuitem') + const options = page.getByRole('menuitem').elements() expect(options.length).toBe(4) // header action + 3 options @@ -185,7 +184,7 @@ describe('', () => { }) it('should not allow selection if the main Drilldown is disabled', async () => { - render( + await render( @@ -194,8 +193,10 @@ describe('', () => { ) - const optionItemContainer = screen.getByLabelText('Disabled Option') - const optionContent = screen.getByText('Disabled Option') + const optionItemContainer = page + .getByLabelText('Disabled Option') + .element() + const optionContent = page.getByText('Disabled Option').element() expect(optionItemContainer).toHaveAttribute('aria-checked', 'false') @@ -205,7 +206,7 @@ describe('', () => { }) it('should always allow back navigation even if the page is disabled', async () => { - render( + await render( @@ -221,19 +222,19 @@ describe('', () => { ) // 1. Navigate to the disabled page - await userEvent.click(screen.getByText('Go to Disabled Page')) - expect(screen.getByText('Disabled Page')).toBeInTheDocument() + await userEvent.click(page.getByText('Go to Disabled Page').element()) + expect(page.getByText('Disabled Page').element()).toBeInTheDocument() - await userEvent.click(screen.getByText('Back')) + await userEvent.click(page.getByText('Back').element()) // 4. Verify we have successfully navigated back - expect(screen.getByText('First Page')).toBeInTheDocument() + expect(page.getByText('First Page').element()).toBeInTheDocument() }) }) describe('as prop', () => { it('should be "ul" by default', async () => { - const { container } = render( + const { container } = await render( Option @@ -246,7 +247,7 @@ describe('', () => { }) it('should render as passed element', async () => { - const { container } = render( + const { container } = await render( Option @@ -261,7 +262,7 @@ describe('', () => { describe('role prop', () => { it('should be "menu" by default', async () => { - const { container } = render( + const { container } = await render( Option @@ -274,7 +275,7 @@ describe('', () => { }) it('should apply passed role', async () => { - const { container } = render( + const { container } = await render( Option @@ -291,14 +292,14 @@ describe('', () => { it('should give back the drilldown element when there is no trigger', async () => { const elementRef = vi.fn() - render( + await render( Option ) - const drilldown = screen.getByRole('menu') + const drilldown = page.getByRole('menu').element() expect(drilldown).toBeInTheDocument() expect(elementRef).toHaveBeenCalledWith(drilldown) @@ -306,7 +307,7 @@ describe('', () => { it('should give back the Popover root when drilldown has trigger and is closed', async () => { const elementRef = vi.fn() - const { container } = render( + const { container } = await render( ', () => { ) - const trigger = screen.getByText('Toggle') + const trigger = page.getByText('Toggle').element() const positionId = trigger.getAttribute('data-position-target') const drilldownRoot = container.querySelector( `span[data-position="${positionId}"]` @@ -329,7 +330,7 @@ describe('', () => { it('should give back the the Popover root when drilldown has trigger and is open', async () => { const elementRef = vi.fn() - const { container } = render( + const { container } = await render( ', () => { ) - const trigger = screen.getByText('Toggle') + const trigger = page.getByText('Toggle').element() const positionId = trigger.getAttribute('data-position-target') const drilldownRoot = container.querySelector( `span[data-position="${positionId}"]` @@ -355,21 +356,21 @@ describe('', () => { describe('drilldownRef prop', () => { it('should give back the drilldown element when there is no trigger', async () => { const drilldownRef = vi.fn() - render( + await render( Option ) - const drilldown = screen.getByRole('menu') + const drilldown = page.getByRole('menu').element() expect(drilldownRef).toHaveBeenCalledWith(drilldown) }) it("shouldn't be called when drilldown has trigger and is closed", async () => { const drilldownRef = vi.fn() - render( + await render( ', () => { it('should give back the drilldown element when drilldown has trigger and is open', async () => { const drilldownRef = vi.fn() - render( + await render( ', () => { ) - const drilldown = screen.getByRole('menu') + const drilldown = page.getByRole('menu').element() expect(drilldownRef).toHaveBeenCalledWith(drilldown) }) @@ -407,7 +408,7 @@ describe('', () => { describe('popoverRef prop', () => { it('should not be called when there is no trigger', async () => { const popoverRef = vi.fn() - render( + await render( Option @@ -420,7 +421,7 @@ describe('', () => { it('should give back the Popover component when drilldown has trigger and is closed', async () => { const popoverRef = vi.fn() - const { container } = render( + const { container } = await render( ', () => { ) - const trigger = screen.getByText('Toggle') + const trigger = page.getByText('Toggle').element() const positionId = trigger.getAttribute('data-position-target') const popoverRoot = container.querySelector( `span[data-position="${positionId}"]` @@ -446,7 +447,7 @@ describe('', () => { it('should give back the Popover component when drilldown has trigger and is open', async () => { const popoverRef = vi.fn() - const { container } = render( + const { container } = await render( ', () => { ) - const trigger = screen.getByText('Toggle') + const trigger = page.getByText('Toggle').element() const positionId = trigger.getAttribute('data-position-target') const popoverRoot = container.querySelector( `span[data-position="${positionId}"]` @@ -475,7 +476,7 @@ describe('', () => { describe('onSelect prop', () => { it('should fire when option is selected', async () => { const onSelect = vi.fn() - render( + await render( {data.map((option) => ( @@ -491,11 +492,11 @@ describe('', () => { ) - const option_1 = screen.getByTestId('opt_1') + const option_1 = page.getByTestId('opt_1').element() await userEvent.click(option_1) - await waitFor(() => { + await vi.waitFor(() => { expect(onSelect).toHaveBeenCalled() const args = onSelect.mock.calls[0][1] @@ -517,7 +518,7 @@ describe('', () => { it('should not fire when drilldown is disabled', async () => { const onSelect = vi.fn() - render( + await render( {data.map((option) => ( @@ -532,11 +533,11 @@ describe('', () => { ) - const option_1 = screen.getByTestId('opt_1') + const option_1 = page.getByTestId('opt_1').element() await userEvent.click(option_1) - await waitFor(() => { + await vi.waitFor(() => { expect(onSelect).not.toHaveBeenCalled() }) }) @@ -544,14 +545,14 @@ describe('', () => { describe('with a trigger', () => { it('should not show content by default', async () => { - render( + await render( click me}> Option 0 ) - const option_0 = screen.queryByText('Option 0') + const option_0 = page.getByText('Option 0').query() expect(option_0).not.toBeInTheDocument() }) @@ -561,7 +562,7 @@ describe('', () => { container.setAttribute('data-testid', 'container') document.body.appendChild(container) - render( + await render( ', () => { ) - const optionsContainer = screen.getByTestId('container') - const trigger = screen.getByRole('button') + const optionsContainer = page.getByTestId('container').element() + const trigger = page.getByRole('button').element() expect(optionsContainer).not.toHaveTextContent('Option 0') await userEvent.click(trigger) - await waitFor(() => { - const updatedOptionsContainer = screen.getByTestId('container') + await vi.waitFor(() => { + const updatedOptionsContainer = page.getByTestId('container').element() expect(updatedOptionsContainer).toHaveTextContent('Option 0') }) }) it('should have an aria-haspopup attribute', async () => { - render( + await render( Options}> Option 0 ) - const trigger = screen.getByRole('button') + const trigger = page.getByRole('button').element() expect(trigger).toHaveAttribute('aria-haspopup') }) it('should call onToggle when Drilldown is opened', async () => { const onToggle = vi.fn() - render( + await render( Options} @@ -613,11 +614,11 @@ describe('', () => { ) - const trigger = screen.getByRole('button') + const trigger = page.getByRole('button').element() await userEvent.click(trigger) - await waitFor(() => { + await vi.waitFor(() => { expect(onToggle).toHaveBeenCalled() const args = onToggle.mock.calls[0][1] @@ -635,7 +636,7 @@ describe('', () => { it('should call onToggle when Drilldown is closed', async () => { const onToggle = vi.fn() - render( + await render( Options} @@ -647,11 +648,11 @@ describe('', () => { ) - const trigger = screen.getByRole('button') + const trigger = page.getByRole('button').element() await userEvent.click(trigger) - await waitFor(() => { + await vi.waitFor(() => { expect(onToggle).toHaveBeenCalled() const args = onToggle.mock.calls[0][1] @@ -669,7 +670,7 @@ describe('', () => { describe('placement prop', () => { it('should be passed to Popover', async () => { let popoverRef: Popover | null = null - render( + await render( Toggle} @@ -692,7 +693,7 @@ describe('', () => { describe('defaultShow prop', () => { it('should display Popover on render', async () => { - render( + await render( Toggle} @@ -703,7 +704,7 @@ describe('', () => {
) - const popoverContent = screen.getByText('Option') + const popoverContent = page.getByText('Option').element() expect(popoverContent).toBeVisible() }) @@ -712,7 +713,7 @@ describe('', () => { describe('show prop', () => { it('should display popover', async () => { const onToggle = vi.fn() - render( + await render( Toggle} @@ -724,7 +725,7 @@ describe('', () => { ) - const popoverContent = screen.getByText('Option') + const popoverContent = page.getByText('Option').element() expect(popoverContent).toBeVisible() }) @@ -734,7 +735,7 @@ describe('', () => { it('should be passed to Popover', async () => { let popoverRef: Popover | null = null const onFocus = vi.fn() - render( + await render( Toggle} @@ -759,7 +760,7 @@ describe('', () => { it('should be passed to Popover', async () => { let popoverRef: Popover | null = null const onMouseOver = vi.fn() - render( + await render( Toggle} @@ -783,7 +784,7 @@ describe('', () => { describe('shouldContainFocus prop', () => { it('should be passed to Popover', async () => { let popoverRef: Popover | null = null - render( + await render( Toggle} @@ -807,7 +808,7 @@ describe('', () => { describe('shouldReturnFocus prop', () => { it('should be passed to Popover', async () => { let popoverRef: Popover | null = null - render( + await render( Toggle} @@ -831,7 +832,7 @@ describe('', () => { describe('withArrow prop', () => { it('should be passed to Popover', async () => { let popoverRef: Popover | null = null - render( + await render( Toggle} @@ -855,7 +856,7 @@ describe('', () => { describe('offsetX prop', () => { it('should be passed to Popover', async () => { let popoverRef: Popover | null = null - render( + await render( Toggle} @@ -879,7 +880,7 @@ describe('', () => { describe('offsetY prop', () => { it('should be passed to Popover', async () => { let popoverRef: Popover | null = null - render( + await render( Toggle} @@ -903,7 +904,7 @@ describe('', () => { describe('positionContainerDisplay prop', () => { it('should be passed to Popover', async () => { let popoverRef: Popover | null = null - render( + await render( Toggle} @@ -926,7 +927,7 @@ describe('', () => { describe('for a11y', () => { it('should be accessible', async () => { - const { container } = render( + const { container } = await render( ', () => { }) it('should meet a11y standarts when drilldown is open', async () => { - const { container } = render( + const { container } = await render( Option 0 diff --git a/packages/ui-drilldown/src/Drilldown/__tests__/DrilldownGroup.test.tsx b/packages/ui-drilldown/src/Drilldown/__tests__/DrilldownGroup.test.tsx index 80b5a811cb..14035a1c2a 100644 --- a/packages/ui-drilldown/src/Drilldown/__tests__/DrilldownGroup.test.tsx +++ b/packages/ui-drilldown/src/Drilldown/__tests__/DrilldownGroup.test.tsx @@ -22,11 +22,9 @@ * SOFTWARE. */ -import { render, screen, waitFor } from '@testing-library/react' -import { vi } from 'vitest' - -import userEvent from '@testing-library/user-event' -import '@testing-library/jest-dom' +import { render } from 'vitest-browser-react' +import { page, userEvent } from 'vitest/browser' +import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest' import { Drilldown } from '@instructure/ui-drilldown/latest' @@ -76,23 +74,23 @@ describe('', () => { ) } - render() + await render() - const selectedOption = screen.getByTestId('three') + const selectedOption = page.getByTestId('three').element() expect(selectedOption).toHaveAttribute('aria-checked', 'true') await userEvent.click(selectedOption) - await waitFor(() => { - const updatedSelectedOption = screen.getByTestId('three') + await vi.waitFor(() => { + const updatedSelectedOption = page.getByTestId('three').element() expect(updatedSelectedOption).toHaveAttribute('aria-checked', 'true') }) }) it("shouldn't render non-DrilldownGroup children", async () => { - render( + await render( @@ -101,8 +99,8 @@ describe('', () => { ) - const nonGroupChild = screen.queryByTestId('testDiv') - const childText = screen.queryByText('Div') + const nonGroupChild = page.getByTestId('testDiv').query() + const childText = page.getByText('Div').query() expect(nonGroupChild).not.toBeInTheDocument() expect(childText).not.toBeInTheDocument() @@ -110,7 +108,7 @@ describe('', () => { it('elementRef should return ref to the group', async () => { const elementRef = vi.fn() - const { container } = render( + const { container } = await render( @@ -126,7 +124,7 @@ describe('', () => { describe('renderGroupTitle', () => { it('should display', async () => { - render( + await render( @@ -135,13 +133,13 @@ describe('', () => { ) - const title = screen.getByText('Group Title') + const title = page.getByText('Group Title').element() expect(title).toBeInTheDocument() }) it('should display, if function is provided', async () => { - render( + await render( 'Group Title'}> @@ -150,7 +148,7 @@ describe('', () => { ) - const title = screen.getByText('Group Title') + const title = page.getByText('Group Title').element() expect(title).toBeInTheDocument() }) @@ -158,7 +156,7 @@ describe('', () => { describe('separators', () => { it("shouldn't display, when group is first and/or last item", async () => { - const { container } = render( + const { container } = await render( @@ -173,7 +171,7 @@ describe('', () => { }) it('should display by default, if group is between other items', async () => { - const { container } = render( + const { container } = await render( Option @@ -190,7 +188,7 @@ describe('', () => { }) it("shouldn't display extra separator between groups", async () => { - const { container } = render( + const { container } = await render( Option @@ -212,7 +210,7 @@ describe('', () => { describe('disabled prop', () => { it('should disable all items in the group', async () => { - const { container } = render( + const { container } = await render( Option @@ -236,7 +234,7 @@ describe('', () => { }) it('should not allow selection if the Drilldown.Group is disabled', async () => { - render( + await render( @@ -245,8 +243,10 @@ describe('', () => { ) - const optionItemContainer = screen.getByLabelText('Disabled Option') - const optionContent = screen.getByText('Disabled Option') + const optionItemContainer = page + .getByLabelText('Disabled Option') + .element() + const optionContent = page.getByText('Disabled Option').element() expect(optionItemContainer).toHaveAttribute('aria-checked', 'false') @@ -258,7 +258,7 @@ describe('', () => { describe('role prop', () => { it('should be "group" by default', async () => { - const { container } = render( + const { container } = await render( @@ -274,7 +274,7 @@ describe('', () => { }) it('should render the group with passed role', async () => { - const { container } = render( + const { container } = await render( @@ -292,7 +292,7 @@ describe('', () => { describe('as prop', () => { it('should inherit Drilldown\'s "ul" by default', async () => { - const { container } = render( + const { container } = await render( @@ -312,7 +312,7 @@ describe('', () => { }) it('should inherit Drilldown\'s "as" prop', async () => { - const { container } = render( + const { container } = await render( @@ -332,7 +332,7 @@ describe('', () => { }) it('should render the group as other element', async () => { - const { container } = render( + const { container } = await render( @@ -354,7 +354,7 @@ describe('', () => { describe('selectableType', () => { it('if not set, should render role="menuitem" options without icon by default', async () => { - const { container } = render( + const { container } = await render( @@ -371,7 +371,7 @@ describe('', () => { }) it('value "single" should render role="menuitemradio" options with icon', async () => { - const { container } = render( + const { container } = await render( @@ -388,7 +388,7 @@ describe('', () => { }) it('value "multiple" should render role="menuitemcheckbox" options with icon', async () => { - const { container } = render( + const { container } = await render( @@ -408,7 +408,7 @@ describe('', () => { describe('defaultSelected', () => { describe('if not provided', () => { it('all group options has to be unselected', async () => { - render( + await render( @@ -425,7 +425,7 @@ describe('', () => { ) - const options = screen.getAllByRole('menuitemcheckbox') + const options = page.getByRole('menuitemcheckbox').elements() expect(options.length).toBe(3) options.forEach((option) => { @@ -434,7 +434,7 @@ describe('', () => { }) it('all checkboxes should not be visible', async () => { - const { container } = render( + const { container } = await render( @@ -464,7 +464,7 @@ describe('', () => { describe('if provided', () => { it('all selected checkboxes should be visible', async () => { const selectedValues = ['item1', 'item3'] - const { container } = render( + const { container } = await render( ', () => { ) - const options = screen.getAllByRole('menuitemcheckbox') + const options = page.getByRole('menuitemcheckbox').elements() const icons = container.querySelectorAll('svg[name="Check"]') expect(options[0]).toHaveAttribute('aria-checked', 'true') @@ -499,7 +499,7 @@ describe('', () => { it("should be overridden by the Option's own defaultSelected", async () => { const selectedValues = ['item1', 'item3'] - render( + await render( ', () => { ) - const options = screen.getAllByRole('menuitemcheckbox') + const options = page.getByRole('menuitemcheckbox').elements() expect(options[0]).toHaveAttribute('aria-checked', 'true') // from the group, expect(options[1]).toHaveAttribute('aria-checked', 'true') // from own prop, @@ -538,7 +538,7 @@ describe('', () => { describe('for "single" selectableType', () => { it('the selected option should be checked', async () => { const selectedValues = ['item2'] - render( + await render( ', () => { ) - const options = screen.getAllByRole('menuitemradio') + const options = page.getByRole('menuitemradio').elements() expect(options[0]).toHaveAttribute('aria-checked', 'false') expect(options[1]).toHaveAttribute('aria-checked', 'true') @@ -568,7 +568,7 @@ describe('', () => { it("should throw error if multiple items are selected, and shouldn't select any item", async () => { const selectedValues = ['item1', 'item3'] - render( + await render( ', () => { ) - const options = screen.getAllByRole('menuitemradio') + const options = page.getByRole('menuitemradio').elements() expect(options[0]).toHaveAttribute('aria-checked', 'false') expect(options[1]).toHaveAttribute('aria-checked', 'false') @@ -604,7 +604,7 @@ describe('', () => { describe('selection', () => { it('should fire "onSelect" callback', async () => { const onSelect = vi.fn() - render( + await render( ', () => { ) - const option2 = screen.getByText('Option 2') + const option2 = page.getByText('Option 2').element() await userEvent.click(option2) - await waitFor(() => { + await vi.waitFor(() => { expect(onSelect).toHaveBeenCalledTimes(1) const args = onSelect.mock.calls[0][1] @@ -652,8 +652,8 @@ describe('', () => { }) describe('selectedOptions', () => { - it('should warn if selectableType="single" but multiple values are passed', () => { - render( + it('should warn if selectableType="single" but multiple values are passed', async () => { + await render( ', () => { }) it('should prevent user selection if selectedOptions provided', async () => { - render( + await render( ', () => { ) - const options = screen.getAllByRole('menuitemcheckbox') + const options = page.getByRole('menuitemcheckbox').elements() expect(options[0]).toHaveAttribute('aria-checked', 'true') expect(options[1]).toHaveAttribute('aria-checked', 'false') - await userEvent.click(screen.getByText('C2')) + await userEvent.click(page.getByText('C2').element()) expect(options[0]).toHaveAttribute('aria-checked', 'true') expect(options[1]).toHaveAttribute('aria-checked', 'false') }) it('should preserve user changes in uncontrolled groups when selectedOptions props change', async () => { - const { rerender } = render( + const { rerender } = await render( ', () => { ) - const options = screen.getAllByRole('menuitemcheckbox') + const options = page.getByRole('menuitemcheckbox').elements() expect(options[0]).toHaveAttribute('aria-checked', 'true') // C1 controlled expect(options[1]).toHaveAttribute('aria-checked', 'false') // C2 controlled @@ -749,14 +749,14 @@ describe('', () => { expect(options[3]).toHaveAttribute('aria-checked', 'false') // D2 uncontrolled // user changes uncontrolled group (select D2) - await userEvent.click(screen.getByText('D2')) + await userEvent.click(page.getByText('D2').element()) expect(options[0]).toHaveAttribute('aria-checked', 'true') // C1 controlled expect(options[1]).toHaveAttribute('aria-checked', 'false') // C2 controlled expect(options[2]).toHaveAttribute('aria-checked', 'true') // D1 uncontrolled expect(options[3]).toHaveAttribute('aria-checked', 'true') // D2 uncontrolled // controlled selectedOptions prop changes - rerender( + await rerender( ', () => { }, optionProps: { value: 'val1', defaultSelected: false } }) - expect(screen.getByTestId(TEST_ID)).toHaveAttribute( + expect(page.getByTestId(TEST_ID).element()).toHaveAttribute( 'aria-checked', 'true' ) // selectedOptions prop wins @@ -840,7 +840,7 @@ describe('', () => { }, optionProps: { value: 'val1', defaultSelected: false } }) - expect(screen.getByTestId(TEST_ID)).toHaveAttribute( + expect(page.getByTestId(TEST_ID).element()).toHaveAttribute( 'aria-checked', 'true' ) // selectedOptions prop wins @@ -854,7 +854,7 @@ describe('', () => { }, optionProps: { value: 'val1', defaultSelected: false } }) - expect(screen.getByTestId(TEST_ID)).toHaveAttribute( + expect(page.getByTestId(TEST_ID).element()).toHaveAttribute( 'aria-checked', 'false' ) // selectedOptions prop wins @@ -868,7 +868,7 @@ describe('', () => { }, optionProps: { value: 'val1', defaultSelected: true } }) - expect(screen.getByTestId(TEST_ID)).toHaveAttribute( + expect(page.getByTestId(TEST_ID).element()).toHaveAttribute( 'aria-checked', 'false' ) // selectedOptions prop wins @@ -881,7 +881,7 @@ describe('', () => { }, optionProps: { value: 'val1', defaultSelected: false } }) - expect(screen.getByTestId(TEST_ID)).toHaveAttribute( + expect(page.getByTestId(TEST_ID).element()).toHaveAttribute( 'aria-checked', 'false' ) // option default wins @@ -894,7 +894,7 @@ describe('', () => { }, optionProps: { value: 'val1', defaultSelected: true } }) - expect(screen.getByTestId(TEST_ID)).toHaveAttribute( + expect(page.getByTestId(TEST_ID).element()).toHaveAttribute( 'aria-checked', 'true' ) // option default wins @@ -907,7 +907,7 @@ describe('', () => { }, optionProps: { value: 'val1', defaultSelected: false } }) - expect(screen.getByTestId(TEST_ID)).toHaveAttribute( + expect(page.getByTestId(TEST_ID).element()).toHaveAttribute( 'aria-checked', 'true' ) // selectedOptions prop wins @@ -920,7 +920,7 @@ describe('', () => { }, optionProps: { value: 'val1', defaultSelected: true } }) - expect(screen.getByTestId(TEST_ID)).toHaveAttribute( + expect(page.getByTestId(TEST_ID).element()).toHaveAttribute( 'aria-checked', 'false' ) // selectedOptions prop wins @@ -934,7 +934,7 @@ describe('', () => { }, optionProps: { value: 'val1' } }) - expect(screen.getByTestId(TEST_ID)).toHaveAttribute( + expect(page.getByTestId(TEST_ID).element()).toHaveAttribute( 'aria-checked', 'true' ) // selectedOptions prop wins @@ -948,7 +948,7 @@ describe('', () => { }, optionProps: { value: 'val1' } }) - expect(screen.getByTestId(TEST_ID)).toHaveAttribute( + expect(page.getByTestId(TEST_ID).element()).toHaveAttribute( 'aria-checked', 'false' ) // selectedOptions prop wins @@ -997,8 +997,8 @@ describe('', () => { ) - it('should overwrite previous selectedOptions prop selections', () => { - const { rerender } = render( + it('should overwrite previous selectedOptions prop selections', async () => { + const { rerender } = await render( getDrilldownComponent({ groupProps: { selectedOptions: ['val1', 'val2'] @@ -1009,20 +1009,20 @@ describe('', () => { }) ) - expect(screen.getByTestId(TEST_ID_1)).toHaveAttribute( + expect(page.getByTestId(TEST_ID_1).element()).toHaveAttribute( 'aria-checked', 'true' ) - expect(screen.getByTestId(TEST_ID_2)).toHaveAttribute( + expect(page.getByTestId(TEST_ID_2).element()).toHaveAttribute( 'aria-checked', 'true' ) - expect(screen.getByTestId(TEST_ID_3)).toHaveAttribute( + expect(page.getByTestId(TEST_ID_3).element()).toHaveAttribute( 'aria-checked', 'false' ) - rerender( + await rerender( getDrilldownComponent({ groupProps: { selectedOptions: ['val3'] @@ -1033,22 +1033,22 @@ describe('', () => { }) ) - expect(screen.getByTestId(TEST_ID_1)).toHaveAttribute( + expect(page.getByTestId(TEST_ID_1).element()).toHaveAttribute( 'aria-checked', 'false' ) - expect(screen.getByTestId(TEST_ID_2)).toHaveAttribute( + expect(page.getByTestId(TEST_ID_2).element()).toHaveAttribute( 'aria-checked', 'false' ) - expect(screen.getByTestId(TEST_ID_3)).toHaveAttribute( + expect(page.getByTestId(TEST_ID_3).element()).toHaveAttribute( 'aria-checked', 'true' ) }) - it('should overwrite group default selection and option default selection', () => { - const { rerender } = render( + it('should overwrite group default selection and option default selection', async () => { + const { rerender } = await render( getDrilldownComponent({ groupProps: { selectedOptions: ['val1'], @@ -1060,21 +1060,21 @@ describe('', () => { }) ) - expect(screen.getByTestId(TEST_ID_1)).toHaveAttribute( + expect(page.getByTestId(TEST_ID_1).element()).toHaveAttribute( 'aria-checked', 'true' ) - expect(screen.getByTestId(TEST_ID_2)).toHaveAttribute( + expect(page.getByTestId(TEST_ID_2).element()).toHaveAttribute( 'aria-checked', 'false' ) - expect(screen.getByTestId(TEST_ID_3)).toHaveAttribute( + expect(page.getByTestId(TEST_ID_3).element()).toHaveAttribute( 'aria-checked', 'false' ) // Set prop: selectedOptions - rerender( + await rerender( getDrilldownComponent({ groupProps: { selectedOptions: [], @@ -1086,22 +1086,22 @@ describe('', () => { }) ) - expect(screen.getByTestId(TEST_ID_1)).toHaveAttribute( + expect(page.getByTestId(TEST_ID_1).element()).toHaveAttribute( 'aria-checked', 'false' ) - expect(screen.getByTestId(TEST_ID_2)).toHaveAttribute( + expect(page.getByTestId(TEST_ID_2).element()).toHaveAttribute( 'aria-checked', 'false' ) - expect(screen.getByTestId(TEST_ID_3)).toHaveAttribute( + expect(page.getByTestId(TEST_ID_3).element()).toHaveAttribute( 'aria-checked', 'false' ) }) - it('should overwrite group default selection and option default selection when selectedOptions provided', () => { - const { rerender } = render( + it('should overwrite group default selection and option default selection when selectedOptions provided', async () => { + const { rerender } = await render( getDrilldownComponent({ groupProps: { defaultSelected: ['val2'] @@ -1112,21 +1112,21 @@ describe('', () => { }) ) - expect(screen.getByTestId(TEST_ID_1)).toHaveAttribute( + expect(page.getByTestId(TEST_ID_1).element()).toHaveAttribute( 'aria-checked', 'false' ) - expect(screen.getByTestId(TEST_ID_2)).toHaveAttribute( + expect(page.getByTestId(TEST_ID_2).element()).toHaveAttribute( 'aria-checked', 'true' ) - expect(screen.getByTestId(TEST_ID_3)).toHaveAttribute( + expect(page.getByTestId(TEST_ID_3).element()).toHaveAttribute( 'aria-checked', 'true' ) // Set new prop: selectedOptions - rerender( + await rerender( getDrilldownComponent({ groupProps: { selectedOptions: [], @@ -1138,15 +1138,15 @@ describe('', () => { }) ) - expect(screen.getByTestId(TEST_ID_1)).toHaveAttribute( + expect(page.getByTestId(TEST_ID_1).element()).toHaveAttribute( 'aria-checked', 'false' ) - expect(screen.getByTestId(TEST_ID_2)).toHaveAttribute( + expect(page.getByTestId(TEST_ID_2).element()).toHaveAttribute( 'aria-checked', 'false' ) - expect(screen.getByTestId(TEST_ID_3)).toHaveAttribute( + expect(page.getByTestId(TEST_ID_3).element()).toHaveAttribute( 'aria-checked', 'false' ) diff --git a/packages/ui-drilldown/src/Drilldown/__tests__/DrilldownOption.test.tsx b/packages/ui-drilldown/src/Drilldown/__tests__/DrilldownOption.test.tsx index 02ea24a707..98d4491814 100644 --- a/packages/ui-drilldown/src/Drilldown/__tests__/DrilldownOption.test.tsx +++ b/packages/ui-drilldown/src/Drilldown/__tests__/DrilldownOption.test.tsx @@ -22,10 +22,9 @@ * SOFTWARE. */ -import { render, screen, waitFor } from '@testing-library/react' -import { vi } from 'vitest' -import userEvent from '@testing-library/user-event' -import '@testing-library/jest-dom' +import { render } from 'vitest-browser-react' +import { page, userEvent } from 'vitest/browser' +import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest' import { CheckInstUIIcon } from '@instructure/ui-icons' @@ -51,7 +50,7 @@ describe('', () => { }) it('should allow setting "selected" property on Options', async () => { - render( + await render( @@ -65,7 +64,7 @@ describe('', () => { ) - const selectedOption = screen.getByLabelText('Option - 2') + const selectedOption = page.getByLabelText('Option - 2').element() expect(selectedOption).toBeInTheDocument() expect(selectedOption).toHaveAttribute('id', 'groupOption02') @@ -74,7 +73,7 @@ describe('', () => { describe('id prop', () => { it('should throw warning the id is not provided', async () => { - render( + await render( {/* @ts-expect-error: Testing behavior when `id` is missing */} @@ -92,7 +91,7 @@ describe('', () => { }) it('should throw warning the id is duplicated', async () => { - render( + await render( Option1 @@ -110,7 +109,7 @@ describe('', () => { }) it('should not render the options with duplicated id', async () => { - render( + await render( Option1 @@ -119,8 +118,8 @@ describe('', () => { ) - const menuitems = screen.queryAllByRole('menuitem') - const option = screen.queryByText('Option2') + const menuitems = page.getByRole('menuitem').elements() + const option = page.getByText('Option2').query() expect(menuitems.length).toBe(0) expect(option).not.toBeInTheDocument() @@ -129,7 +128,7 @@ describe('', () => { describe('children function prop', () => { it('should throw warning if it returns nothing', async () => { - render( + await render( {() => null} @@ -148,7 +147,7 @@ describe('', () => { it('should provide props as parameters', async () => { const childrenFunction = vi.fn(() => 'Option') - render( + await render( {childrenFunction} @@ -167,7 +166,7 @@ describe('', () => { describe('elementRef prop', () => { it('should give back to ref for the option wrapper (Options.Item)', async () => { const elementRef = vi.fn() - const { container } = render( + const { container } = await render( @@ -184,7 +183,7 @@ describe('', () => { describe('subPageId prop', () => { it('should display arrow icon', async () => { - const { container } = render( + const { container } = await render( @@ -200,7 +199,7 @@ describe('', () => { }) it('should indicate subpage fo SR', async () => { - render( + await render( @@ -209,7 +208,7 @@ describe('', () => { ) - const option = screen.getByLabelText('Option') + const option = page.getByLabelText('Option').element() expect(option).toHaveAttribute('role', 'menuitem') expect(option).toHaveAttribute('aria-haspopup', 'true') @@ -218,7 +217,7 @@ describe('', () => { describe('disabled prop', () => { it('should mark option as disabled for SR', async () => { - render( + await render( @@ -227,13 +226,13 @@ describe('', () => { ) - const option = screen.getByLabelText('Option') + const option = page.getByLabelText('Option').element() expect(option).toHaveAttribute('aria-disabled', 'true') }) it('should not allow selection if the Drilldown.Option itself is disabled', async () => { - render( + await render( @@ -244,8 +243,10 @@ describe('', () => { ) - const optionItemContainer = screen.getByLabelText('Disabled Option') - const optionContent = screen.getByText('Disabled Option') + const optionItemContainer = page + .getByLabelText('Disabled Option') + .element() + const optionContent = page.getByText('Disabled Option').element() expect(optionItemContainer).toHaveAttribute('aria-checked', 'false') @@ -257,7 +258,7 @@ describe('', () => { describe('href prop', () => { it('should display option as link', async () => { - render( + await render( @@ -266,14 +267,14 @@ describe('', () => { ) - const option = screen.getByLabelText('Option') + const option = page.getByLabelText('Option').element() expect(option.tagName).toBe('A') expect(option).toHaveAttribute('href', '/helloWorld') }) it('should throw warning if subPageId is provided too', async () => { - render( + await render( @@ -282,7 +283,7 @@ describe('', () => { ) - const option = screen.getByLabelText('Option') + const option = page.getByLabelText('Option').element() const expectedErrorMessage = 'Warning: Drilldown.Option with id "option1" has subPageId, so it will ignore the "href" property.' @@ -296,7 +297,7 @@ describe('', () => { }) it('should throw warning if option is in selectable group', async () => { - render( + await render( @@ -307,7 +308,7 @@ describe('', () => { ) - const option = screen.getByLabelText('Option') + const option = page.getByLabelText('Option').element() const expectedErrorMessage = 'Warning: Drilldown.Option with id "groupOption01" is in a selectable group, so it will ignore the "href" property.' @@ -323,14 +324,14 @@ describe('', () => { describe('as prop', () => { it('should render option as `li` by default', async () => { - render( + await render( Option ) - const option = screen.getByLabelText('Option') + const option = page.getByLabelText('Option').element() const wrapper = option.parentElement expect(option).toHaveAttribute('id', 'option1') @@ -338,7 +339,7 @@ describe('', () => { }) it('should force option to be `li` while the parent is "ul" or "ol"', async () => { - render( + await render( @@ -347,7 +348,7 @@ describe('', () => { ) - const option = screen.getByLabelText('Option') + const option = page.getByLabelText('Option').element() const wrapper = option.parentElement expect(option).toHaveAttribute('id', 'option1') @@ -355,7 +356,7 @@ describe('', () => { }) it('should render option as specified html element, when the parent in non-list element', async () => { - render( + await render( @@ -364,7 +365,7 @@ describe('', () => { ) - const option = screen.getByLabelText('Option') + const option = page.getByLabelText('Option').element() const wrapper = option.parentElement expect(option).toHaveAttribute('id', 'option1') @@ -374,20 +375,20 @@ describe('', () => { describe('role prop', () => { it('should be "menuitem" by default', async () => { - render( + await render( Option ) - const option = screen.getByLabelText('Option') + const option = page.getByLabelText('Option').element() expect(option).toHaveAttribute('role', 'menuitem') }) it('should be applied on prop', async () => { - render( + await render( @@ -396,7 +397,7 @@ describe('', () => { ) - const option = screen.getByLabelText('Option') + const option = page.getByLabelText('Option').element() expect(option).toHaveAttribute('role', 'presentation') }) @@ -404,7 +405,7 @@ describe('', () => { describe('renderLabelInfo prop', () => { it('should display tag next to the label', async () => { - const { container } = render( + const { container } = await render( @@ -421,7 +422,7 @@ describe('', () => { it('as function should have option props as params', async () => { const infoFunction = vi.fn(() => 'Info') - render( + await render( @@ -443,7 +444,7 @@ describe('', () => { describe('renderBeforeLabel prop', () => { it('should display icon before the label', async () => { - const { container } = render( + const { container } = await render( ', () => { it('as function should have option props as params', async () => { const beforeLabelFunction = vi.fn(() => ) - render( + await render( ', () => { }) it('should throw warning if it is in selectable group', async () => { - render( + await render( @@ -512,7 +513,7 @@ describe('', () => { describe('renderAfterLabel prop', () => { it('should display icon before the label', async () => { - const { container } = render( + const { container } = await render( ', () => { it('as function should have option props as params', async () => { const beforeLabelFunction = vi.fn(() => ) - render( + await render( ', () => { }) it('should throw warning if it has subPageId', async () => { - render( + await render( ', () => { describe('description prop', () => { it('should display description under the option', async () => { - render( + await render( @@ -592,13 +593,13 @@ describe('', () => { ) - const description = screen.getByText('This is a description.') + const description = page.getByText('This is a description.').element() expect(description).toBeInTheDocument() }) it('as a function should display description under the option', async () => { - render( + await render( ', () => { ) - const description = screen.getByText('This is a description.') + const description = page.getByText('This is a description.').element() expect(description).toBeInTheDocument() }) @@ -618,7 +619,7 @@ describe('', () => { describe('descriptionRole prop', () => { it('should set the role of description', async () => { - render( + await render( ', () => { ) - const description = screen.getByText('This is a description.') + const description = page.getByText('This is a description.').element() expect(description).toHaveAttribute('role', 'button') }) @@ -640,7 +641,7 @@ describe('', () => { describe('onOptionClick callback', () => { it('should fire on click with correct params', async () => { const onOptionClick = vi.fn() - render( + await render( @@ -649,11 +650,11 @@ describe('', () => { ) - const option = screen.getByText('Option') + const option = page.getByText('Option').element() await userEvent.click(option) - await waitFor(() => { + await vi.waitFor(() => { expect(onOptionClick).toHaveBeenCalledTimes(1) const args = onOptionClick.mock.calls[0][1] @@ -670,7 +671,7 @@ describe('', () => { }) it('should provide goToPreviousPage method that throws a warning, if there is no previous page', async () => { - render( + await render( ', () => { ) - const option = screen.getByText('Option') + const option = page.getByText('Option').element() await userEvent.click(option) - await waitFor(() => { + await vi.waitFor(() => { const expectedErrorMessage = 'Warning: There is no previous page to go to. The current page history is: [page0].' @@ -701,7 +702,7 @@ describe('', () => { describe('provide goToPage method', () => { it("should throws warning if page doesn't exist", async () => { - render( + await render( ', () => { ) - const option = screen.getByText('Option') + const option = page.getByText('Option').element() await userEvent.click(option) - await waitFor(() => { + await vi.waitFor(() => { const expectedErrorMessage = 'Warning: Cannot go to page because page with id: "page1" doesn\'t exist.' @@ -731,7 +732,7 @@ describe('', () => { }) it('should throws warning if if no page id is provided', async () => { - render( + await render( ', () => { ) - const option = screen.getByText('Option') + const option = page.getByText('Option').element() await userEvent.click(option) - await waitFor(() => { + await vi.waitFor(() => { const expectedErrorMessage = 'Warning: Cannot go to page because there was no page id provided.' @@ -762,7 +763,7 @@ describe('', () => { }) it('should throws warning if parameter is not string', async () => { - render( + await render( ', () => { ) - const option = screen.getByText('Option') + const option = page.getByText('Option').element() await userEvent.click(option) - await waitFor(() => { + await vi.waitFor(() => { const expectedErrorMessage = 'Warning: Cannot go to page because parameter newPageId has to be string (valid page id). Current newPageId is "object".' diff --git a/packages/ui-drilldown/src/Drilldown/__tests__/DrilldownPage.test.tsx b/packages/ui-drilldown/src/Drilldown/__tests__/DrilldownPage.test.tsx index 147b79d813..4994bd57f0 100644 --- a/packages/ui-drilldown/src/Drilldown/__tests__/DrilldownPage.test.tsx +++ b/packages/ui-drilldown/src/Drilldown/__tests__/DrilldownPage.test.tsx @@ -22,10 +22,9 @@ * SOFTWARE. */ -import { render, screen, waitFor } from '@testing-library/react' -import { vi } from 'vitest' -import userEvent from '@testing-library/user-event' -import '@testing-library/jest-dom' +import { render } from 'vitest-browser-react' +import { page, userEvent } from 'vitest/browser' +import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest' import { Drilldown } from '@instructure/ui-drilldown/latest' @@ -49,21 +48,21 @@ describe('', () => { }) it("shouldn't render non-DrilldownPage children", async () => { - render( + await render(
Div
) - const nonPageChild = screen.queryByText('DIV') + const nonPageChild = page.getByText('DIV').query() expect(nonPageChild).not.toBeInTheDocument() }) describe('header title', () => { it('should be displayed in the header', async () => { - const { container } = render( + const { container } = await render( Option @@ -73,27 +72,27 @@ describe('', () => { const titleContainer = container.querySelector( '[id^="DrilldownHeader-Title-Label_"]' ) - const title = screen.queryByText('HeaderTitleString') + const title = page.getByText('HeaderTitleString').query() expect(titleContainer).toBeInTheDocument() expect(title).toBeInTheDocument() }) it('should be displayed when function is passed', async () => { - render( + await render( 'HeaderTitleFunction'}> Option ) - const title = screen.queryByText('HeaderTitleFunction') + const title = page.getByText('HeaderTitleFunction').query() expect(title).toBeInTheDocument() }) it("shouldn't be displayed when function has no return value", async () => { - const { container } = render( + const { container } = await render( null}> Option @@ -112,7 +111,7 @@ describe('', () => { describe('header action label', () => { it('should be displayed in the header', async () => { - render( + await render( ', () => { ) - const actionLabel = screen.queryByText('HeaderActionLabelString') + const actionLabel = page.getByText('HeaderActionLabelString').query() expect(actionLabel).toBeInTheDocument() }) it('should be displayed when function is passed', async () => { - render( + await render( ', () => { ) - const actionLabel = screen.queryByText('HeaderActionLabelFunction') + const actionLabel = page.getByText('HeaderActionLabelFunction').query() expect(actionLabel).toBeInTheDocument() }) it("shouldn't be displayed when function has no return value", async () => { - const { container } = render( + const { container } = await render( null}> Option @@ -162,7 +161,7 @@ describe('', () => { it('should fire header action callback', async () => { const actionCallback = vi.fn() - render( + await render( ', () => { ) - const actionLabel = screen.getByText('ActionWithCallback') + const actionLabel = page.getByText('ActionWithCallback').element() await userEvent.click(actionLabel) - await waitFor(() => { + await vi.waitFor(() => { expect(actionCallback).toHaveBeenCalled() }) }) @@ -185,20 +184,20 @@ describe('', () => { describe('header back navigation', () => { it('should not be displayed on root page', async () => { - render( + await render( Option ) - const label = screen.queryByText('HeaderBackString') + const label = page.getByText('HeaderBackString').query() expect(label).not.toBeInTheDocument() }) it('should be displayed on subpages', async () => { - render( + await render( @@ -210,12 +209,12 @@ describe('', () => { ) - const option = screen.getByText('Option') + const option = page.getByText('Option').element() await userEvent.click(option) - await waitFor(() => { - const label = screen.queryByText('HeaderBackString') + await vi.waitFor(() => { + const label = page.getByText('HeaderBackString').query() expect(label).toBeInTheDocument() }) @@ -223,7 +222,7 @@ describe('', () => { it('should be displayed when function is passed, and can use former page title', async () => { const pageTitle = 'Page Title' - render( + await render( @@ -240,12 +239,12 @@ describe('', () => { ) - const option = screen.getByText('Option') + const option = page.getByText('Option').element() await userEvent.click(option) - await waitFor(() => { - const label = screen.queryByText(`Back to ${pageTitle}`) + await vi.waitFor(() => { + const label = page.getByText(`Back to ${pageTitle}`).query() expect(label).toBeInTheDocument() }) @@ -254,7 +253,7 @@ describe('', () => { describe('header separator', () => { it('should not be displayed, if no item is on the header', async () => { - const { container } = render( + const { container } = await render( Option @@ -269,7 +268,7 @@ describe('', () => { }) it('should be displayed, if there are items in the header', async () => { - const { container } = render( + const { container } = await render( Option @@ -284,7 +283,7 @@ describe('', () => { }) it('should not be displayed, if withoutHeaderSeparator is set', async () => { - const { container } = render( + const { container } = await render( Option @@ -301,14 +300,14 @@ describe('', () => { describe('disabled prop', () => { it('should make all options disabled', async () => { - render( + await render( Option ) - const allOptions = screen.getAllByRole('menuitem') + const allOptions = page.getByRole('menuitem').elements() allOptions.forEach((option) => { expect(option).toHaveAttribute('aria-disabled', 'true') @@ -316,7 +315,7 @@ describe('', () => { }) it('should not allow selection if the Drilldown.Page is disabled', async () => { - render( + await render( @@ -325,8 +324,10 @@ describe('', () => { ) - const optionItemContainer = screen.getByLabelText('Disabled Option') - const optionContent = screen.getByText('Disabled Option') + const optionItemContainer = page + .getByLabelText('Disabled Option') + .element() + const optionContent = page.getByText('Disabled Option').element() expect(optionItemContainer).toHaveAttribute('aria-checked', 'false') @@ -336,7 +337,7 @@ describe('', () => { }) it("shouldn't make header Back options disabled", async () => { - render( + await render( @@ -352,13 +353,13 @@ describe('', () => { ) - const subPageOption = screen.getByText('Option1') + const subPageOption = page.getByText('Option1').element() await userEvent.click(subPageOption) - await waitFor(() => { - const option2 = screen.getByLabelText('Option2') - const backOption = screen.getByLabelText('HeaderBackString') + await vi.waitFor(() => { + const option2 = page.getByLabelText('Option2').element() + const backOption = page.getByLabelText('HeaderBackString').element() expect(option2).toHaveAttribute('role', 'menuitem') expect(option2).toHaveAttribute('aria-disabled', 'true') diff --git a/packages/ui-drilldown/src/Drilldown/__tests__/DrilldownSeparator.test.tsx b/packages/ui-drilldown/src/Drilldown/__tests__/DrilldownSeparator.test.tsx index 12551a45b9..401cd34643 100644 --- a/packages/ui-drilldown/src/Drilldown/__tests__/DrilldownSeparator.test.tsx +++ b/packages/ui-drilldown/src/Drilldown/__tests__/DrilldownSeparator.test.tsx @@ -22,28 +22,29 @@ * SOFTWARE. */ -import { render, screen } from '@testing-library/react' -import '@testing-library/jest-dom' +import { render } from 'vitest-browser-react' +import { page } from 'vitest/browser' +import { describe, it, expect } from 'vitest' import { Drilldown } from '@instructure/ui-drilldown/latest' describe('', () => { it('should render', async () => { - render( + await render( ) - const separator = screen.getByTestId('separator1') + const separator = page.getByTestId('separator1').element() expect(separator).toBeVisible() expect(separator.getAttribute('class')).toContain('-separator') }) it('should not render children', async () => { - render( + await render( @@ -52,7 +53,7 @@ describe('', () => { ) - const separatorChild = screen.queryByText('Children') + const separatorChild = page.getByText('Children').query() expect(separatorChild).not.toBeInTheDocument() }) diff --git a/packages/ui-editable/src/Editable/__tests__/Editable.test.tsx b/packages/ui-editable/src/Editable/__tests__/Editable.test.tsx index 7d73a2bf21..a9c3cbc245 100644 --- a/packages/ui-editable/src/Editable/__tests__/Editable.test.tsx +++ b/packages/ui-editable/src/Editable/__tests__/Editable.test.tsx @@ -22,13 +22,13 @@ * SOFTWARE. */ -import { fireEvent, render, screen, waitFor } from '@testing-library/react' -import { vi } from 'vitest' import type { MockInstance } from 'vitest' -import userEvent from '@testing-library/user-event' import { Editable } from '@instructure/ui-editable/latest' import type { EditableRenderProps } from '../v1/props' -import '@testing-library/jest-dom' +import { fireEvent } from '@testing-library/dom' +import { render } from 'vitest-browser-react' +import { page, userEvent } from 'vitest/browser' +import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest' const TEXT_VIEW = 'text-view' const TEXT_EDIT = 'text-edit' @@ -88,10 +88,12 @@ describe('', () => { }) it('should render view mode', async () => { - render() + await render( + + ) const currentMode = childRender.mock.calls[0][0].mode - const viewModeText = screen.getByText(TEXT_VIEW) - const editButton = screen.getByRole('button', { name: TEXT_EDIT }) + const viewModeText = page.getByText(TEXT_VIEW).element() + const editButton = page.getByRole('button', { name: TEXT_EDIT }).element() expect(childRender).toHaveBeenCalled() expect(currentMode).toBe('view') @@ -101,10 +103,12 @@ describe('', () => { }) it('should render edit mode', async () => { - render() + await render( + + ) const currentMode = childRender.mock.calls[0][0].mode - const inputForEdit = screen.getByTestId('edit-mode-input') - const editButton = screen.getByRole('button', { name: TEXT_EDIT }) + const inputForEdit = page.getByTestId('edit-mode-input').element() + const editButton = page.getByRole('button', { name: TEXT_EDIT }).element() expect(childRender).toHaveBeenCalled() expect(currentMode).toBe('edit') @@ -113,18 +117,18 @@ describe('', () => { expect(editButton).toBeInTheDocument() }) - it('should change to edit mode on button click', () => { + it('should change to edit mode on button click', async () => { const onChangeModeSpy = vi.fn() - render( + await render( ) - const viewModeText = screen.getByText(TEXT_VIEW) - const editButton = screen.getByRole('button') + const viewModeText = page.getByText(TEXT_VIEW).element() + const editButton = page.getByRole('button').element() expect(viewModeText).toBeInTheDocument() @@ -136,58 +140,58 @@ describe('', () => { it('should change to edit mode on component click', async () => { const onChangeModeSpy = vi.fn() - render( + await render( ) - const childContainer = screen.getByTestId('child-container') + const childContainer = page.getByTestId('child-container').element() await userEvent.click(childContainer) - await waitFor(() => expect(onChangeModeSpy).toHaveBeenCalledWith('edit')) + await vi.waitFor(() => expect(onChangeModeSpy).toHaveBeenCalledWith('edit')) }) it('should set the button to visible on mouse over', async () => { const onChangeModeSpy = vi.fn() - render( + await render( ) - const editButton = screen.getByRole('button') + const editButton = page.getByRole('button').element() expect(editButton).toHaveClass('test-hidden') fireEvent.mouseOver(editButton) - await waitFor(() => { + await vi.waitFor(() => { expect(editButton).toHaveClass('test-visible') }) fireEvent.mouseOut(editButton) - await waitFor(() => { + await vi.waitFor(() => { expect(editButton).toHaveClass('test-hidden') }) }) - it('should change to view mode on editor blur', () => { + it('should change to view mode on editor blur', async () => { const onChangeModeSpy = vi.fn() - render( + await render( ) - const inputForEdit = screen.getByTestId('edit-mode-input') + const inputForEdit = page.getByTestId('edit-mode-input').element() fireEvent.focus(inputForEdit) fireEvent.blur(inputForEdit) @@ -195,27 +199,27 @@ describe('', () => { expect(onChangeModeSpy).toHaveBeenCalledWith('view') }) - it('should change to view mode on escape', () => { + it('should change to view mode on escape', async () => { const onChangeModeSpy = vi.fn() - render( + await render( ) - const inputForEdit = screen.getByTestId('edit-mode-input') + const inputForEdit = page.getByTestId('edit-mode-input').element() fireEvent.keyUp(inputForEdit, { key: 'Escape', code: 'Escape' }) expect(onChangeModeSpy).toHaveBeenCalledWith('view') }) - it('should call onChange when the user is finished editing', () => { + it('should call onChange when the user is finished editing', async () => { const onChangeSpy = vi.fn() - const { rerender } = render( + const { rerender } = await render( ', () => { onChange={onChangeSpy} /> ) - const inputForEdit = screen.getByTestId('edit-mode-input') + const inputForEdit = page.getByTestId('edit-mode-input').element() fireEvent.change(inputForEdit, { target: { value: 'updated_value' } }) expect(onChangeSpy).not.toHaveBeenCalled() // Simulate mode prop change - rerender( + await rerender( ', () => { expect(onChangeSpy).toHaveBeenCalledWith('updated_value') }) - it('should warn if readOnly + mode="edit"', () => { + it('should warn if readOnly + mode="edit"', async () => { const consoleWarningSpy = vi .spyOn(console, 'warn') .mockImplementation(() => {}) - render( + await render( ', () => { consoleErrorMock.mockRestore() }) - it('should render view mode', () => { - render( + it('should render view mode', async () => { + await render( ', () => { renderEditButton={renderEditButton} /> ) - const viewModeText = screen.getByText(VIEWER_TEXT) - const editButton = screen.getByRole('button') + const viewModeText = page.getByText(VIEWER_TEXT).element() + const editButton = page.getByRole('button').element() expect(viewModeText).toBeInTheDocument() expect(editButton).toBeInTheDocument() expect(editButton).toHaveTextContent(EDIT_BUTTON_TEXT) }) - it('should render view mode with string button label', () => { - const { container } = render( + it('should render view mode with string button label', async () => { + const { container } = await render( ', () => { renderEditButton={renderEditButton} /> ) - const viewModeText = screen.getByText(VIEWER_TEXT) - const editButton = screen.getByRole('button') + const viewModeText = page.getByText(VIEWER_TEXT).element() + const editButton = page.getByRole('button').element() const buttonLabel = container.querySelector( "[class$='-screenReaderContent']" ) as HTMLElement @@ -117,8 +117,8 @@ describe('', () => { expect(buttonLabel).toHaveTextContent(EDIT_BUTTON_TEXT) }) - it('should render edit mode', () => { - render( + it('should render edit mode', async () => { + await render( ', () => { renderEditButton={renderEditButton} /> ) - const inputForEdit = screen.getByTestId('input-editor') + const inputForEdit = page.getByTestId('input-editor').element() expect(inputForEdit).toBeInTheDocument() expect(document.activeElement).toBe(inputForEdit) }) - it('should render a custom edit button', () => { + it('should render a custom edit button', async () => { const customButtonText = 'custom-button-text' - render( + await render( ', () => { }} /> ) - const viewModeText = screen.getByText(VIEWER_TEXT) - const customEditButton = screen.getByTestId('custom_button') + const viewModeText = page.getByText(VIEWER_TEXT).element() + const customEditButton = page.getByTestId('custom_button').element() expect(viewModeText).toBeInTheDocument() expect(customEditButton).toBeInTheDocument() expect(customEditButton).toHaveTextContent(customButtonText) }) - it('should switch mode to edit via props, and focus the editor', () => { - const { rerender, container } = render( + it('should switch mode to edit via props, and focus the editor', async () => { + const { rerender, container } = await render( ', () => { renderEditButton={renderEditButton} /> ) - const viewModeText = screen.getByText(VIEWER_TEXT) + const viewModeText = page.getByText(VIEWER_TEXT).element() expect(viewModeText).toBeInTheDocument() // Simulate mode prop change - rerender( + await rerender( ', () => { renderEditButton={renderEditButton} /> ) - const inputForEdit = screen.getByTestId('input-editor') + const inputForEdit = page.getByTestId('input-editor').element() expect(container).not.toHaveTextContent(VIEWER_TEXT) expect(inputForEdit).toBeInTheDocument() expect(document.activeElement).toBe(inputForEdit) }) - it('should switch mode to view via props, and focus the edit button', () => { - const { rerender, container } = render( + it('should switch mode to view via props, and focus the edit button', async () => { + const { rerender, container } = await render( ', () => { renderEditButton={renderEditButton} /> ) - const inputForEdit = screen.getByTestId('input-editor') + const inputForEdit = page.getByTestId('input-editor').element() expect(container).not.toHaveTextContent(VIEWER_TEXT) expect(inputForEdit).toBeInTheDocument() // Simulate mode prop change - rerender( + await rerender( ', () => { const inputForEditAfterModeChange = container.querySelector( "[id='input-editor']" ) - const editButton = screen.getByRole('button') + const editButton = page.getByRole('button').element() expect(container).toHaveTextContent(VIEWER_TEXT) expect(inputForEditAfterModeChange).not.toBeInTheDocument() @@ -222,7 +222,7 @@ describe('', () => { }) it('should meet a11y standards in view mode', async () => { - const { container } = render( + const { container } = await render( ', () => { }) it('should meet a11y standards in edit mode', async () => { - const { container } = render( + const { container } = await render( ', () => { - it('should set expanded to false by default', () => { + it('should set expanded to false by default', async () => { type RenderArgs = { expanded: boolean } const renderContent = vi.fn((_args: RenderArgs) =>
hello
) - render() + await render() expect(renderContent.mock.calls[0][0].expanded).toBe(false) }) - it('should correctly provide the aria-expanded attribute', () => { + it('should correctly provide the aria-expanded attribute', async () => { type RenderArgs = { getToggleProps: () => { 'aria-expanded': boolean } } @@ -48,7 +49,7 @@ describe('', () => { return
Toggle
}) - render() + await render() const ariaExpanded = renderContent.mock.calls[0][0].getToggleProps()['aria-expanded'] @@ -56,7 +57,7 @@ describe('', () => { expect(ariaExpanded).toBe(false) }) - it('should provide the toggle and details with a shared, unique id', () => { + it('should provide the toggle and details with a shared, unique id', async () => { const renderContent = vi.fn(({ getToggleProps, getDetailsProps }) => ( <>
Toggle
@@ -64,7 +65,7 @@ describe('', () => { )) - render() + await render() const toggleProps = renderContent.mock.calls[0][0].getToggleProps() const detailsProps = renderContent.mock.calls[0][0].getDetailsProps() @@ -77,18 +78,18 @@ describe('', () => { expect(toggleId).toEqual(detailsId) }) - it('should call onToggle when onClick is called', () => { + it('should call onToggle when onClick is called', async () => { const onToggle = vi.fn() const renderContent = vi.fn(({ getToggleProps }) => ( )) - render( + await render( ) - const toggleButton = screen.getByText('Toggle') + const toggleButton = page.getByText('Toggle').element() fireEvent.click(toggleButton) expect(onToggle).toHaveBeenCalledWith( @@ -97,12 +98,12 @@ describe('', () => { ) }) - it('should set expanded to true when defaultExpanded is true', () => { + it('should set expanded to true when defaultExpanded is true', async () => { const renderContent = vi.fn(({ expanded }) => (
{expanded ? 'Expanded' : 'Collapsed'}
)) - render() + await render() expect(renderContent.mock.calls[0][0].expanded).toBe(true) }) diff --git a/packages/ui-file-drop/src/FileDrop/__tests__/FileDrop.test.tsx b/packages/ui-file-drop/src/FileDrop/__tests__/FileDrop.test.tsx index 0ce399a3df..d566789cf9 100644 --- a/packages/ui-file-drop/src/FileDrop/__tests__/FileDrop.test.tsx +++ b/packages/ui-file-drop/src/FileDrop/__tests__/FileDrop.test.tsx @@ -22,18 +22,17 @@ * SOFTWARE. */ -import { render } from '@testing-library/react' -import { vi } from 'vitest' import { runAxeCheck } from '@instructure/ui-axe-check' import { FileDrop } from '@instructure/ui-file-drop/latest' import type { FileDropProps } from '@instructure/ui-file-drop/latest' import { act } from 'react' -import '@testing-library/jest-dom' +import { render } from 'vitest-browser-react' +import { describe, it, expect, vi } from 'vitest' describe('', () => { it('should focus the input when focus is called', async () => { let inputEl: HTMLInputElement | null | undefined - const { container } = render( + const { container } = await render( { @@ -50,7 +49,7 @@ describe('', () => { it('should provide an inputRef prop', async () => { const inputRef = vi.fn() - const { container } = render( + const { container } = await render( ) const input = container.querySelector('input[class$="-fileDrop__input"]') @@ -59,21 +58,21 @@ describe('', () => { }) it('should render', async () => { - const { container } = render() + const { container } = await render() const fileDrop = container.querySelector('[class$="-fileDrop__input"]') expect(fileDrop).toBeInTheDocument() }) it('should meet a11y standards', async () => { - const { container } = render() + const { container } = await render() const axeCheck = await runAxeCheck(container) expect(axeCheck).toBe(true) }) describe('interactions', async () => { it('should functionally disable the input if `interaction` is set to disabled', async () => { - const { container } = render( + const { container } = await render( ) const fileDrop = container.querySelector('[class$="-fileDrop__input"]') @@ -82,7 +81,7 @@ describe('', () => { }) it('should functionally disable the input if `disabled` is set', async () => { - const { container } = render( + const { container } = await render( ) const fileDrop = container.querySelector('[class$="-fileDrop__input"]') @@ -91,7 +90,7 @@ describe('', () => { }) it('should functionally disable the input if `interaction` is set to readonly', async () => { - const { container } = render( + const { container } = await render( ) const fileDrop = container.querySelector('[class$="-fileDrop__input"]') @@ -100,7 +99,7 @@ describe('', () => { }) it('should functionally disable the input if `readOnly` is set', async () => { - const { container } = render( + const { container } = await render( ) const fileDrop = container.querySelector('[class$="-fileDrop__input"]') @@ -112,7 +111,7 @@ describe('', () => { describe('label handling', async () => { it('renders element label directly', async () => { const label =
This is an element label
- const { container } = render() + const { container } = await render() const renderedLabel = container.querySelector('[id="test-id"]') @@ -131,7 +130,7 @@ describe('', () => { return null } - render() + await render() expect(typeof result.isDragAccepted).toBe('boolean') expect(typeof result.isDragRejected).toBe('boolean') @@ -149,7 +148,7 @@ describe('', () => { return null } - render() + await render() expect(result.isDragAccepted).toBe(false) expect(result.isDragRejected).toBe(false) diff --git a/packages/ui-flex/src/Flex/__tests__/Flex.test.tsx b/packages/ui-flex/src/Flex/__tests__/Flex.test.tsx index 3b1d24f584..173cfee8bb 100644 --- a/packages/ui-flex/src/Flex/__tests__/Flex.test.tsx +++ b/packages/ui-flex/src/Flex/__tests__/Flex.test.tsx @@ -22,16 +22,15 @@ * SOFTWARE. */ -import { render, screen, waitFor } from '@testing-library/react' -import { vi } from 'vitest' - -import '@testing-library/jest-dom' +import { render } from 'vitest-browser-react' +import { page } from 'vitest/browser' +import { describe, it, expect, vi } from 'vitest' import { runAxeCheck } from '@instructure/ui-axe-check' import { Flex } from '@instructure/ui-flex/latest' describe('', () => { it('should render Flex.Items as children', async () => { - const { container } = render( + const { container } = await render( Flex item 1 Flex item 2 @@ -47,7 +46,7 @@ describe('', () => { }) it('should render other markup as children', async () => { - const { container } = render( + const { container } = await render(
foo
bar
@@ -61,21 +60,21 @@ describe('', () => { }) it('should render children when children is a function', async () => { - render({() =>
hello world
}
) - const child = screen.getByText('hello world') + await render({() =>
hello world
}
) + const child = page.getByText('hello world').element() expect(child).toBeInTheDocument() }) it('should render no markup if there are no children', async () => { - const { container } = render() + const { container } = await render() const flex = container.querySelector('[class*="flex"]') expect(flex).not.toBeInTheDocument() }) it('should accept width and height as props', async () => { - const { container } = render( + const { container } = await render( Flex item 1 Flex item 2 @@ -91,7 +90,7 @@ describe('', () => { }) it('should set flex-direction with the direction property', async () => { - const { container } = render( + const { container } = await render( Flex item 1 Flex item 2 @@ -104,7 +103,7 @@ describe('', () => { }) it('should render an inline-flex container with the display property', async () => { - const { container } = render( + const { container } = await render( Flex item 1 Flex item 2 @@ -119,7 +118,7 @@ describe('', () => { }) it('should set align-items with the alignItems property', async () => { - const { container } = render( + const { container } = await render( Flex item 1 Flex item 2 @@ -132,7 +131,7 @@ describe('', () => { }) it('should set justify-content with the justifyItems property', async () => { - const { container } = render( + const { container } = await render( Flex item 1 Flex item 2 @@ -145,7 +144,7 @@ describe('', () => { }) it('should set flex-wrap with the wrap property', async () => { - const { container } = render( + const { container } = await render( Flex item 1 Flex item 2 @@ -158,14 +157,14 @@ describe('', () => { }) it('should let Flex.Items align themselves with the align property', async () => { - const { container } = render( + const { container } = await render( Flex item 1 Flex item 2 ) const flex = container.querySelector('[class*="flex"]')! - const item = screen.getByText('Flex item 1') + const item = page.getByText('Flex item 1').element() const flexStyle = window.getComputedStyle(flex) const itemStyle = window.getComputedStyle(item) @@ -175,14 +174,14 @@ describe('', () => { }) it('should let Flex.Items flex-grow with the shouldGrow property', async () => { - render( + await render( Flex item 1 Flex item 2 ) - const item1 = screen.getByText('Flex item 1') - const item2 = screen.getByText('Flex item 2') + const item1 = page.getByText('Flex item 1').element() + const item2 = page.getByText('Flex item 2').element() const item1Style = window.getComputedStyle(item1) const item2Style = window.getComputedStyle(item2) @@ -192,14 +191,14 @@ describe('', () => { }) it('should let Flex.Items flex-shrink with the shouldShrink property', async () => { - render( + await render( Flex item 1 Flex item 2 ) - const item1 = screen.getByText('Flex item 1') - const item2 = screen.getByText('Flex item 2') + const item1 = page.getByText('Flex item 1').element() + const item2 = page.getByText('Flex item 2').element() const item1Style = window.getComputedStyle(item1) const item2Style = window.getComputedStyle(item2) @@ -209,15 +208,15 @@ describe('', () => { }) it('should set flex-basis and min-width on Flex.Items with the size property', async () => { - render( + await render( Flex item 1 Flex item 2 Flex item 3 ) - const item2 = screen.getByText('Flex item 2') - const item3 = screen.getByText('Flex item 3') + const item2 = page.getByText('Flex item 2').element() + const item3 = page.getByText('Flex item 3').element() const item2Style = window.getComputedStyle(item2) const item3Style = window.getComputedStyle(item3) @@ -230,20 +229,20 @@ describe('', () => { it('should support an elementRef prop', async () => { const elementRef = vi.fn() - const { container } = render( + const { container } = await render( Flex item ) const flex = container.querySelector('[class*="flex"]') - await waitFor(() => { + await vi.waitFor(() => { expect(elementRef).toHaveBeenCalledWith(flex) }) }) it('should meet a11y standards', async () => { - const { container } = render( + const { container } = await render( Flex item 1 Flex item 2 diff --git a/packages/ui-flex/src/Flex/__tests__/FlexItem.test.tsx b/packages/ui-flex/src/Flex/__tests__/FlexItem.test.tsx index cf4f724977..d95430ff45 100644 --- a/packages/ui-flex/src/Flex/__tests__/FlexItem.test.tsx +++ b/packages/ui-flex/src/Flex/__tests__/FlexItem.test.tsx @@ -22,16 +22,15 @@ * SOFTWARE. */ -import { render, waitFor, screen } from '@testing-library/react' -import { vi } from 'vitest' - -import '@testing-library/jest-dom' +import { render } from 'vitest-browser-react' +import { page } from 'vitest/browser' +import { describe, it, expect, vi } from 'vitest' import { runAxeCheck } from '@instructure/ui-axe-check' import { FlexItem as Item } from '@instructure/ui-flex/latest' describe('', () => { it('should render children', async () => { - const { container } = render(Flex item 1) + const { container } = await render(Flex item 1) const item = container.querySelector('[class*="-flexItem"]') expect(item).toBeInTheDocument() @@ -41,33 +40,33 @@ describe('', () => { it('should support an elementRef prop', async () => { const elementRef = vi.fn() - const { container } = render( + const { container } = await render( Flex item 2 ) const item = container.querySelector('[class*="-flexItem"]') - await waitFor(() => { + await vi.waitFor(() => { expect(elementRef).toHaveBeenCalledWith(item) }) }) it('should meet a11y standards', async () => { - const { container } = render(Flex item 3) + const { container } = await render(Flex item 3) const axeCheck = await runAxeCheck(container) expect(axeCheck).toBe(true) }) describe('order prop', () => { - it('should apply `order` CSS when passed', () => { - render(Item with order) - const item = screen.getByText('Item with order') + it('should apply `order` CSS when passed', async () => { + await render(Item with order) + const item = page.getByText('Item with order').element() expect(item).toHaveStyle('order: 2') }) - it('should not apply `order` CSS when prop is undefined', () => { - render(Item without order) - const item = screen.getByText('Item without order') + it('should not apply `order` CSS when prop is undefined', async () => { + await render(Item without order) + const item = page.getByText('Item without order').element() expect(item).not.toHaveStyle({ order: expect.anything() }) }) }) diff --git a/packages/ui-focusable/src/Focusable/__tests__/Focusable.test.tsx b/packages/ui-focusable/src/Focusable/__tests__/Focusable.test.tsx index 5ed45433f2..1cd40af407 100644 --- a/packages/ui-focusable/src/Focusable/__tests__/Focusable.test.tsx +++ b/packages/ui-focusable/src/Focusable/__tests__/Focusable.test.tsx @@ -23,11 +23,10 @@ */ import { Component } from 'react' -import { render, screen, waitFor } from '@testing-library/react' -import userEvent from '@testing-library/user-event' -import { vi } from 'vitest' import type { MockInstance } from 'vitest' -import '@testing-library/jest-dom' +import { render } from 'vitest-browser-react' +import { page, userEvent } from 'vitest/browser' +import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest' import { Focusable } from '../index.js' import type { FocusableRenderOptions } from '../props' @@ -53,8 +52,8 @@ describe('', () => { }) it('should render', async () => { - render({() => }) - const button = screen.getByRole('button') + await render({() => }) + const button = page.getByRole('button').element() expect(button).toBeInTheDocument() expect(button).toHaveTextContent('hello world') @@ -62,7 +61,7 @@ describe('', () => { it('should call children function with focused when element receives focus', async () => { const renderSpy = vi.fn() - render( + await render( {(args) => { renderSpy(args) @@ -70,9 +69,9 @@ describe('', () => { }} ) - const focusable = screen.getByRole('button') + const focusable = page.getByRole('button').element() - await waitFor(() => { + await vi.waitFor(() => { const args = renderSpy.mock.lastCall![0] expect(args).toHaveProperty('focused', false) @@ -83,7 +82,7 @@ describe('', () => { await userEvent.type(focusable, '{enter}') await focusable.focus() - await waitFor(() => { + await vi.waitFor(() => { const args = renderSpy.mock.lastCall![0] expect(document.activeElement).toBe(focusable) @@ -94,7 +93,7 @@ describe('', () => { await focusable.blur() - await waitFor(() => { + await vi.waitFor(() => { const args = renderSpy.mock.lastCall![0] expect(document.activeElement).not.toBe(focusable) @@ -111,13 +110,13 @@ describe('', () => {
)) - render() - const firstFocusable = screen.getByText('Click') + await render() + const firstFocusable = page.getByText('Click').element() expect(firstFocusable.tagName).toBe('A') expect(firstFocusable).not.toHaveFocus() - await waitFor(() => { + await vi.waitFor(() => { const args = renderSpy.mock.lastCall![0] expect(args.focused).toBe(false) @@ -126,12 +125,12 @@ describe('', () => { await firstFocusable.focus() - const nextFocusable = screen.getByRole('textbox') + const nextFocusable = page.getByRole('textbox').element() expect(nextFocusable.tagName).toBe('INPUT') expect(nextFocusable).toHaveFocus() - await waitFor(() => { + await vi.waitFor(() => { const args = renderSpy.mock.lastCall![0] expect(args.focused).toBe(true) expect(args.focusable).toBe(nextFocusable) @@ -139,12 +138,12 @@ describe('', () => { await nextFocusable.blur() - const lastFocusable = screen.getByText('Click') + const lastFocusable = page.getByText('Click').element() expect(lastFocusable.tagName).toBe('A') expect(lastFocusable).not.toHaveFocus() - await waitFor(() => { + await vi.waitFor(() => { const args = renderSpy.mock.lastCall![0] expect(args.focused).toBe(false) expect(args.focusable).toBe(lastFocusable) @@ -154,12 +153,12 @@ describe('', () => { it('should maintain focus when the focus element changes', async () => { const renderSpy = vi.fn(() => Click) - const { rerender } = render() - const firstFocusable = screen.getByText('Click') + const { rerender } = await render() + const firstFocusable = page.getByText('Click').element() await firstFocusable.focus() - await waitFor(() => { + await vi.waitFor(() => { const lastCall = renderSpy.mock.lastCall as | [{ focused: boolean; focusable: HTMLElement }] | undefined @@ -172,14 +171,14 @@ describe('', () => { // Set prop: render const nextRenderSpy = vi.fn(() => ) - rerender() + await rerender() - const nextFocusable = screen.getByText('Click') + const nextFocusable = page.getByText('Click').element() expect(nextFocusable.tagName).toBe('BUTTON') expect(nextFocusable).toHaveFocus() - await waitFor(() => { + await vi.waitFor(() => { const nextLastCall = nextRenderSpy.mock.lastCall as | [{ focused: boolean; focusable: HTMLElement }] | undefined @@ -194,7 +193,7 @@ describe('', () => { it('should update the focus element correctly', async () => { const renderSpy = vi.fn() - const { rerender } = render( + const { rerender } = await render( {(args) => { renderSpy(args) @@ -203,11 +202,11 @@ describe('', () => { ) - const firstButton = screen.getByText('foo') + const firstButton = page.getByText('foo').element() await firstButton.focus() - await waitFor(() => { + await vi.waitFor(() => { const args = renderSpy.mock.lastCall![0] expect(args.focused).toBe(true) @@ -215,14 +214,14 @@ describe('', () => { await firstButton.blur() - await waitFor(() => { + await vi.waitFor(() => { const args = renderSpy.mock.lastCall![0] expect(args.focused).toBe(false) }) // Set child - rerender( + await rerender( {(args: FocusableRenderOptions) => { renderSpy(args) @@ -234,11 +233,11 @@ describe('', () => { }} ) - const secondButton = screen.getByText('bar') + const secondButton = page.getByText('bar').element() await secondButton.focus() - await waitFor(() => { + await vi.waitFor(() => { const args = renderSpy.mock.lastCall![0] expect(args.focused).toBe(true) @@ -246,7 +245,7 @@ describe('', () => { }) it('should warn when there is more than one focusable descendant', async () => { - render( + await render( {() => { return ( @@ -271,7 +270,7 @@ describe('', () => { }) it('should warn when there are no focusable descendants', async () => { - render( + await render( {() => { return hello! @@ -291,7 +290,7 @@ describe('', () => { it('should attach event listener correctly even when the focusable element is not the root', async () => { const renderSpy = vi.fn() - render( + await render( {(args) => { renderSpy(args) @@ -308,9 +307,9 @@ describe('', () => { ) - const button = screen.getByRole('button') + const button = page.getByRole('button').element() - await waitFor(() => { + await vi.waitFor(() => { const args = renderSpy.mock.lastCall![0] expect(args.focused).toBe(false) @@ -318,7 +317,7 @@ describe('', () => { await button.focus() - await waitFor(() => { + await vi.waitFor(() => { const args = renderSpy.mock.lastCall![0] expect(args.focused).toBe(true) @@ -327,7 +326,7 @@ describe('', () => { it('should provide a focus method', async () => { let focusable: Focusable - render( + await render( { focusable = el @@ -339,7 +338,7 @@ describe('', () => { await focusable!.focus() - const button = screen.getByText('hello world') + const button = page.getByText('hello world').element() expect(button).toHaveFocus() }) @@ -347,7 +346,7 @@ describe('', () => { it('should provide a focused getter', async () => { let focusableInstance: any - render( + await render( {(args) => { focusableInstance = args @@ -355,13 +354,13 @@ describe('', () => { }} ) - const button = screen.getByText('Click me') + const button = page.getByText('Click me').element() expect(focusableInstance?.focused).toBe(false) await button.focus() - await waitFor(() => { + await vi.waitFor(() => { expect(focusableInstance?.focused).toBe(true) expect(button).toHaveFocus() }) @@ -390,19 +389,21 @@ describe('', () => { ) } } - const { rerender, container } = render() + const { rerender, container } = await render( + + ) const initialInput = container.querySelector('input') - await waitFor(() => { + await vi.waitFor(() => { expect(initialInput).toHaveValue('false_A') }) // Set Prop: changeValue - rerender() + await rerender() await inputRef!.focus() - await waitFor(() => { + await vi.waitFor(() => { expect(inputRef).toHaveValue('true_B') }) }) @@ -463,22 +464,22 @@ describe('', () => { } } - const { container } = render() + const { container } = await render() const input = container.querySelector('input') - await waitFor(() => { + await vi.waitFor(() => { expect(focusableRef!.focused).toBe(false) }) await userEvent.click(labelRef!) - await waitFor(() => { + await vi.waitFor(() => { expect(input).toHaveFocus() }) await userEvent.click(buttonRef!) - await waitFor(() => { + await vi.waitFor(() => { expect(input).not.toHaveFocus() }) }) diff --git a/packages/ui-form-field/src/FormField/__tests__/FormField.test.tsx b/packages/ui-form-field/src/FormField/__tests__/FormField.test.tsx index 8320d5fbb0..19f0fc3588 100644 --- a/packages/ui-form-field/src/FormField/__tests__/FormField.test.tsx +++ b/packages/ui-form-field/src/FormField/__tests__/FormField.test.tsx @@ -22,12 +22,11 @@ * SOFTWARE. */ -import { render, screen } from '@testing-library/react' -import { vi } from 'vitest' import { runAxeCheck } from '@instructure/ui-axe-check' import { FormField } from '@instructure/ui-form-field/latest' -import { userEvent } from '@testing-library/user-event' -import '@testing-library/jest-dom' +import { render } from 'vitest-browser-react' +import { page, userEvent } from 'vitest/browser' +import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest' describe('', () => { let consoleWarningMock: ReturnType @@ -48,36 +47,36 @@ describe('', () => { consoleErrorMock.mockRestore() }) - it('should render', () => { - render() - const formField = screen.getByText('foo').closest('label') + it('should render', async () => { + await render() + const formField = page.getByText('foo').element().closest('label') expect(formField).toBeInTheDocument() }) - it('passes props through to FormField', () => { - render() - const formField = screen.getByText('foo').closest('label') + it('passes props through to FormField', async () => { + await render() + const formField = page.getByText('foo').element().closest('label') expect(formField).toHaveAttribute('data-automation', 'baz') }) it('should meet a11y standards', async () => { - const { container } = render() + const { container } = await render() const axeCheck = await runAxeCheck(container) expect(axeCheck).toBe(true) }) it('should focus the control with the supplied id', async () => { const user = userEvent.setup() - render( + await render( ) - const label = screen.getByText('labelText').closest('label')! + const label = page.getByText('labelText').element().closest('label')! await user.click(label) const input = document.getElementById('foo')! expect(input).toHaveFocus() diff --git a/packages/ui-form-field/src/FormFieldGroup/__tests__/FormFieldGroup.test.tsx b/packages/ui-form-field/src/FormFieldGroup/__tests__/FormFieldGroup.test.tsx index 238f666d6a..77452e278b 100644 --- a/packages/ui-form-field/src/FormFieldGroup/__tests__/FormFieldGroup.test.tsx +++ b/packages/ui-form-field/src/FormFieldGroup/__tests__/FormFieldGroup.test.tsx @@ -22,12 +22,12 @@ * SOFTWARE. */ -import { render, screen } from '@testing-library/react' -import { vi } from 'vitest' import { runAxeCheck } from '@instructure/ui-axe-check' import { FormFieldGroup } from '@instructure/ui-form-field/latest' import type { FormMessage } from '@instructure/ui-form-field/latest' -import '@testing-library/jest-dom' +import { render } from 'vitest-browser-react' +import { page } from 'vitest/browser' +import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest' describe('', () => { let consoleWarningMock: ReturnType @@ -48,8 +48,8 @@ describe('', () => { consoleErrorMock.mockRestore() }) - it('should render', () => { - const { container } = render( + it('should render', async () => { + const { container } = await render(
} />) + const { container } = await render( + hello
} /> + ) expect(container).toHaveTextContent('hello') }) it('should allow methods as labels', async () => { const renderLabel = vi.fn() - render() + await render() expect(renderLabel).toHaveBeenCalled() }) it('should allow methods as values', async () => { const renderValue = vi.fn() - render() + await render() expect(renderValue).toHaveBeenCalled() }) diff --git a/packages/ui-metric/src/MetricGroup/__tests__/MetricGroup.test.tsx b/packages/ui-metric/src/MetricGroup/__tests__/MetricGroup.test.tsx index 3a1ccdd5ad..9e0869bd7e 100644 --- a/packages/ui-metric/src/MetricGroup/__tests__/MetricGroup.test.tsx +++ b/packages/ui-metric/src/MetricGroup/__tests__/MetricGroup.test.tsx @@ -22,9 +22,9 @@ * SOFTWARE. */ -import { render, screen } from '@testing-library/react' -import '@testing-library/jest-dom' -import { vi } from 'vitest' +import { render } from 'vitest-browser-react' +import { page } from 'vitest/browser' +import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest' import { runAxeCheck } from '@instructure/ui-axe-check' import { MetricGroup } from '@instructure/ui-metric/latest' @@ -43,7 +43,7 @@ describe('', () => { }) it('should render children', async () => { - const { container } = render( + const { container } = await render( @@ -55,7 +55,7 @@ describe('', () => { }) it('passes props through to MetricGroup element', async () => { - render( + await render( @@ -63,13 +63,13 @@ describe('', () => { ) - const metric = screen.getByTestId('metric-group') + const metric = page.getByTestId('metric-group').element() expect(metric).toHaveAttribute('data-automation', 'foo') }) describe('for a11y', () => { it('should meet standards', async () => { - const { container } = render( + const { container } = await render( @@ -82,41 +82,41 @@ describe('', () => { }) it('should have role=grid with aria-readonly=true', async () => { - render( + await render( ) - const grids = screen.getAllByRole('grid') + const grids = page.getByRole('grid').elements() expect(grids.length).toBe(1) expect(grids[0]).toHaveAttribute('aria-readonly', 'true') }) it('should have role=row', async () => { - render( + await render( ) - const rows = screen.getAllByRole('row') + const rows = page.getByRole('row').elements() expect(rows.length).toBe(3) }) it('should have role=gridcell', async () => { - render( + await render( ) - const cells = screen.getAllByRole('gridcell') + const cells = page.getByRole('gridcell').elements() expect(cells.length).toBe(3) }) diff --git a/packages/ui-modal/src/Modal/__tests__/Modal.test.tsx b/packages/ui-modal/src/Modal/__tests__/Modal.test.tsx index fad5d99bdc..750ccf57f4 100644 --- a/packages/ui-modal/src/Modal/__tests__/Modal.test.tsx +++ b/packages/ui-modal/src/Modal/__tests__/Modal.test.tsx @@ -23,9 +23,18 @@ */ import { Component } from 'react' -import { render, waitFor } from '@testing-library/react' -import { vi } from 'vitest' -import userEvent from '@testing-library/user-event' +import { render } from 'vitest-browser-react' +import { userEvent } from 'vitest/browser' +import { + describe, + it, + expect, + beforeAll, + afterAll, + beforeEach, + afterEach, + vi +} from 'vitest' import { Modal, ModalBody, @@ -68,8 +77,8 @@ describe.skip('', () => { window.scroll = originalScroll }) - it('should render nothing and have a node with no parent when closed', () => { - const { container } = render( + it('should render nothing and have a node with no parent when closed', async () => { + const { container } = await render( Foo Bar Baz @@ -80,7 +89,7 @@ describe.skip('', () => { it('should apply theme overrides when open', async () => { const testFont = 'test-font' const bodyText = 'Modal-body-text' - const { findByText, findByRole } = render( + const { findByText, findByRole } = await render( ', () => { }) it('should render its own positioning context if constrained to parent', async () => { - const { findByRole } = render( + const { findByRole } = await render( ', () => { }) it("should not inherit its parent's font color", async () => { - const { findByRole } = render( + const { findByRole } = await render(
', () => { }) it('should pass `as` prop to the dialog', async () => { - const { findByRole, rerender } = render( + const { findByRole, rerender } = await render( Foo Bar Baz @@ -149,7 +158,7 @@ describe.skip('', () => { expect(dialog).toBeInTheDocument() expect(dialog.tagName).toBe('SPAN') - rerender( + await rerender( Foo Bar Baz @@ -161,7 +170,7 @@ describe.skip('', () => { it('should handle null children', async () => { const bodyText = 'Modal-body-text' - const { findByText } = render( + const { findByText } = await render( {null} {bodyText} @@ -175,7 +184,7 @@ describe.skip('', () => { it('should handle custom children', async () => { const bodyText = 'Modal-body-text' - const { findByText } = render( + const { findByText } = await render( This is a custom child {bodyText} @@ -189,7 +198,7 @@ describe.skip('', () => { }) it('should apply the aria attributes', async () => { - const { findByRole } = render( + const { findByRole } = await render( Foo Bar Baz @@ -205,7 +214,7 @@ describe.skip('', () => { const onEntering = vi.fn() const onEntered = vi.fn() - const { findByRole } = render( + const { findByRole } = await render( ', () => { expect(dialog).toBeInTheDocument() - await waitFor(() => { + await vi.waitFor(() => { expect(onEnter).toHaveBeenCalled() expect(onEntering).toHaveBeenCalled() expect(onEntered).toHaveBeenCalled() @@ -231,7 +240,7 @@ describe.skip('', () => { it('should support onOpen prop', async () => { const onOpen = vi.fn() - const { findByRole } = render( + const { findByRole } = await render( ', () => { expect(dialog).toBeInTheDocument() - await waitFor(() => { + await vi.waitFor(() => { expect(onOpen).toHaveBeenCalled() }) }) @@ -253,7 +262,7 @@ describe.skip('', () => { it('should support onClose prop', async () => { const onClose = vi.fn() - const { findByRole, rerender } = render( + const { findByRole, rerender } = await render( ', () => { expect(dialog).toBeInTheDocument() - rerender( + await rerender( ', () => { ) - await waitFor(() => { + await vi.waitFor(() => { expect(onClose).toHaveBeenCalled() }) }) it('should dismiss when overlay clicked by default', async () => { const onDismiss = vi.fn() - const { findByText } = render( + const { findByText } = await render( ', () => { expect(modalBody).toBeInTheDocument() await userEvent.click(document.body) - await waitFor(() => { + await vi.waitFor(() => { expect(onDismiss).toHaveBeenCalled() }) }) @@ -309,7 +318,7 @@ describe.skip('', () => { const onDismiss = vi.fn() const onClickOuter = vi.fn() - const { findByRole, getByTestId } = render( + const { findByRole, getByTestId } = await render(
@@ -355,7 +364,7 @@ describe.skip('', () => { describe('children validation', () => { it('should pass validation when children are valid', async () => { - const { findByRole } = render( + const { findByRole } = await render( Hello World Foo Bar Baz @@ -375,7 +384,7 @@ describe.skip('', () => { let bodyRef: ModalBody | null = null let footerRef: ModalFooter | null = null - const { findByRole } = render( + const { findByRole } = await render( ', () => { it('should pass overflow to Modal.Body', async () => { let bodyRef: ModalBody | null = null - const { findByRole } = render( + const { findByRole } = await render( { @@ -460,18 +469,18 @@ describe.skip('', () => { } it('should focus closeButton by default', async () => { - const { findByText } = render() + const { findByText } = await render() const closeButton = await findByText('Close') expect(closeButton).toBeInTheDocument() - await waitFor(() => { + await vi.waitFor(() => { expect(document.activeElement).toBe(closeButton) }) }) it('should take a prop for finding default focus', async () => { - const { findByTestId } = render( + const { findByTestId } = await render( ', () => { ) const input = await findByTestId('input-first') - await waitFor(() => { + await vi.waitFor(() => { expect(input).toHaveFocus() }) }) diff --git a/packages/ui-modal/src/Modal/__tests__/ModalBody.test.tsx b/packages/ui-modal/src/Modal/__tests__/ModalBody.test.tsx index dda44e9613..794ab43937 100644 --- a/packages/ui-modal/src/Modal/__tests__/ModalBody.test.tsx +++ b/packages/ui-modal/src/Modal/__tests__/ModalBody.test.tsx @@ -22,9 +22,8 @@ * SOFTWARE. */ -import { render, waitFor } from '@testing-library/react' -import { vi, beforeEach, afterEach } from 'vitest' -import '@testing-library/jest-dom' +import { render } from 'vitest-browser-react' +import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest' import { color2hex } from '@instructure/ui-color-utils' import canvas from '@instructure/ui-themes' @@ -37,7 +36,7 @@ const BODY_TEXT = 'Modal-body-text' describe('', () => { it('should render', async () => { - const { findByText } = render({BODY_TEXT}) + const { findByText } = await render({BODY_TEXT}) const modalBody = await findByText(BODY_TEXT) expect(modalBody).toBeInTheDocument() @@ -47,7 +46,7 @@ describe('', () => { const themeVariables = canvas.newTheme.components.ModalBody( canvas.newTheme.semantics(canvas.newTheme.primitives) ) - const { findByText } = render( + const { findByText } = await render( {BODY_TEXT} ) const modalBody = await findByText(BODY_TEXT) @@ -61,7 +60,7 @@ describe('', () => { }) it('should set the same width and height as the parent when overflow is set to fit', async () => { - const { findByText } = render( + const { findByText } = await render(
{BODY_TEXT}
@@ -84,26 +83,26 @@ describe('', () => { allProps.forEach((prop) => { if (prop in allowedProps) { - it(`should allow the '${prop}' prop`, () => { + it(`should allow the '${prop}' prop`, async () => { const consoleErrorSpy = vi .spyOn(console, 'error') .mockImplementation(() => {}) const props = { [prop]: allowedProps[prop] } - render() + await render() expect(consoleErrorSpy).not.toHaveBeenCalled() consoleErrorSpy.mockRestore() }) } else { - it(`should NOT allow the '${prop}' prop`, () => { + it(`should NOT allow the '${prop}' prop`, async () => { const expectedErrorMessage = `prop '${prop}' is not allowed.` const consoleErrorSpy = vi .spyOn(console, 'error') .mockImplementation(() => {}) const props = { [prop]: 'NOT_ALLOWED_VALUE' } - render() + await render() expect(consoleErrorSpy).toHaveBeenCalledWith( expect.stringContaining(expectedErrorMessage), @@ -164,15 +163,15 @@ describe('', () => { it('is a tab stop when scrollable and it has no focusable children', async () => { mockScrollable(true) - const { findByText } = render({BODY_TEXT}) + const { findByText } = await render({BODY_TEXT}) const body = await findByText(BODY_TEXT) - await waitFor(() => expect(body).toHaveAttribute('tabindex', '0')) + await vi.waitFor(() => expect(body).toHaveAttribute('tabindex', '0')) }) it('is not a tab stop when scrollable but it has a focusable child', async () => { mockScrollable(true) - const { findByText } = render( + const { findByText } = await render( {BODY_TEXT} @@ -180,34 +179,34 @@ describe('', () => { ) const body = await findByText(BODY_TEXT) - await waitFor(() => expect(body).not.toHaveAttribute('tabindex')) + await vi.waitFor(() => expect(body).not.toHaveAttribute('tabindex')) }) it('is not a tab stop when it is not scrollable', async () => { mockScrollable(false) - const { findByText } = render({BODY_TEXT}) + const { findByText } = await render({BODY_TEXT}) const body = await findByText(BODY_TEXT) - await waitFor(() => expect(body).toBeInTheDocument()) + await vi.waitFor(() => expect(body).toBeInTheDocument()) expect(body).not.toHaveAttribute('tabindex') }) it('drops the tab stop when a focusable child is added later', async () => { mockScrollable(true) - const { findByText, rerender } = render( + const { findByText, rerender } = await render( {BODY_TEXT} ) const body = await findByText(BODY_TEXT) - await waitFor(() => expect(body).toHaveAttribute('tabindex', '0')) + await vi.waitFor(() => expect(body).toHaveAttribute('tabindex', '0')) - rerender( + await rerender( {BODY_TEXT} ) - await waitFor(() => expect(body).not.toHaveAttribute('tabindex')) + await vi.waitFor(() => expect(body).not.toHaveAttribute('tabindex')) }) it('labels the scrollable body from the header with a space between adjacent text nodes', async () => { @@ -216,7 +215,7 @@ describe('', () => { // renders: a decorative "IgniteAI" text node immediately followed by the // title, with no whitespace between them. The body's aria-label must not // collapse these into "IgniteAI Nutrition Facts". - const { findByText } = render( + const { findByText } = await render( ', () => { ) const body = await findByText(BODY_TEXT) - await waitFor(() => + await vi.waitFor(() => expect(body).toHaveAttribute( 'aria-label', 'IgniteAI AI Nutrition Facts' diff --git a/packages/ui-modal/src/Modal/__tests__/ModalFooter.test.tsx b/packages/ui-modal/src/Modal/__tests__/ModalFooter.test.tsx index b5db07378e..ac1c65997d 100644 --- a/packages/ui-modal/src/Modal/__tests__/ModalFooter.test.tsx +++ b/packages/ui-modal/src/Modal/__tests__/ModalFooter.test.tsx @@ -22,8 +22,8 @@ * SOFTWARE. */ -import { render } from '@testing-library/react' -import '@testing-library/jest-dom' +import { render } from 'vitest-browser-react' +import { describe, it, expect } from 'vitest' import canvas from '@instructure/ui-themes' import { color2hex } from '@instructure/ui-color-utils' @@ -34,7 +34,9 @@ const FOOTER_TEXT = 'Modal-footer-text' describe('', () => { it('should render', async () => { - const { findByText } = render({FOOTER_TEXT}) + const { findByText } = await render( + {FOOTER_TEXT} + ) const modalFooter = await findByText(FOOTER_TEXT) expect(modalFooter).toBeInTheDocument() @@ -44,7 +46,7 @@ describe('', () => { const themeVariables = canvas.newTheme.components.ModalFooter( canvas.newTheme.semantics(canvas.newTheme.primitives) ) - const { findByText } = render( + const { findByText } = await render( {FOOTER_TEXT} ) const modalFooter = await findByText(FOOTER_TEXT) diff --git a/packages/ui-modal/src/Modal/__tests__/ModalHeader.test.tsx b/packages/ui-modal/src/Modal/__tests__/ModalHeader.test.tsx index c53fe24d22..87c8a7d2c9 100644 --- a/packages/ui-modal/src/Modal/__tests__/ModalHeader.test.tsx +++ b/packages/ui-modal/src/Modal/__tests__/ModalHeader.test.tsx @@ -22,8 +22,8 @@ * SOFTWARE. */ -import { render } from '@testing-library/react' -import '@testing-library/jest-dom' +import { render } from 'vitest-browser-react' +import { describe, it, expect } from 'vitest' import canvas from '@instructure/ui-themes' import { color2hex } from '@instructure/ui-color-utils' @@ -34,7 +34,9 @@ const HEADER_TEXT = 'Modal-footer-text' describe('', () => { it('should render', async () => { - const { findByText } = render({HEADER_TEXT}) + const { findByText } = await render( + {HEADER_TEXT} + ) const modalHeader = await findByText(HEADER_TEXT) expect(modalHeader).toBeInTheDocument() @@ -44,7 +46,7 @@ describe('', () => { const themeVariables = canvas.newTheme.components.ModalHeader( canvas.newTheme.semantics(canvas.newTheme.primitives) ) - const { findByText } = render( + const { findByText } = await render( {HEADER_TEXT} ) const modalHeader = await findByText(HEADER_TEXT) @@ -67,7 +69,9 @@ describe('', () => { const themeVariables = canvas.newTheme.components.ModalHeader( canvas.newTheme.semantics(canvas.newTheme.primitives) ) - const { findByText } = render({HEADER_TEXT}) + const { findByText } = await render( + {HEADER_TEXT} + ) const modalHeader = await findByText(HEADER_TEXT) const modalHeaderStyle = window.getComputedStyle(modalHeader) @@ -81,7 +85,7 @@ describe('', () => { const themeVariables = canvas.newTheme.components.ModalHeader( canvas.newTheme.semantics(canvas.newTheme.primitives) ) - const { findByText } = render( + const { findByText } = await render( {HEADER_TEXT} ) const modalHeader = await findByText(HEADER_TEXT) @@ -97,7 +101,7 @@ describe('', () => { const themeVariables = canvas.newTheme.components.ModalHeader( canvas.newTheme.semantics(canvas.newTheme.primitives) ) - const { findByText } = render( + const { findByText } = await render( {HEADER_TEXT} ) const modalHeader = await findByText(HEADER_TEXT) diff --git a/packages/ui-motion/src/Transition/__tests__/Transition.test.tsx b/packages/ui-motion/src/Transition/__tests__/Transition.test.tsx index 4263cc488e..e7cb896197 100644 --- a/packages/ui-motion/src/Transition/__tests__/Transition.test.tsx +++ b/packages/ui-motion/src/Transition/__tests__/Transition.test.tsx @@ -23,14 +23,9 @@ */ import { Component, createRef, RefObject } from 'react' -import { - render, - waitFor, - waitForElementToBeRemoved -} from '@testing-library/react' -import { vi } from 'vitest' import type { MockInstance } from 'vitest' -import '@testing-library/jest-dom' +import { render } from 'vitest-browser-react' +import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest' import { Transition } from '../index.js' import { getClassNames } from '../styles.js' @@ -88,8 +83,8 @@ describe('', () => { ] const expectTypeClass = function (type: TransitionType) { - it(`should correctly apply classes for '${type}' with html element`, () => { - const { getByText } = render( + it(`should correctly apply classes for '${type}' with html element`, async () => { + const { getByText } = await render(
hello
@@ -99,8 +94,8 @@ describe('', () => { expect(element).toHaveClass(getClass(type, 'entered')) }) - it(`should correctly apply classes for '${type}' with Component`, () => { - const { getByText } = render( + it(`should correctly apply classes for '${type}' with Component`, async () => { + const { getByText } = await render( @@ -118,7 +113,7 @@ describe('', () => { it('should correctly apply enter and exit classes', async () => { const type = 'fade' - const { getByText, rerender } = render( + const { getByText, rerender } = await render(
hello
@@ -127,19 +122,19 @@ describe('', () => { expect(element).toHaveClass(getClass(type, 'entered')) - rerender( + await rerender(
hello
) - await waitFor(() => { + await vi.waitFor(() => { expect(element).toHaveClass(getClass(type, 'exited')) }) }) it('should remove component from DOM when `unmountOnExit` is set', async () => { - const { getByText, rerender } = render( + const { getByText, rerender } = await render(
hello
@@ -147,7 +142,7 @@ describe('', () => { expect(getByText('hello')).toBeInTheDocument() - rerender( + await rerender(
hello
@@ -159,7 +154,7 @@ describe('', () => { it('should not execute enter transition with `transitionEnter` set to false', async () => { const onEntering = vi.fn() - const { rerender } = render( + const { rerender } = await render( ', () => { ) - rerender( + await rerender( ', () => { ) - await waitFor(() => { + await vi.waitFor(() => { expect(onEntering).not.toHaveBeenCalled() }) }) @@ -189,7 +184,7 @@ describe('', () => { it('should not execute exit transition with `transitionExit` set to false', async () => { const onExiting = vi.fn() - const { rerender } = render( + const { rerender } = await render( ', () => { ) - rerender( + await rerender( ', () => { ) - await waitFor(() => { + await vi.waitFor(() => { expect(onExiting).not.toHaveBeenCalled() }) }) @@ -221,7 +216,7 @@ describe('', () => { const onEntering = vi.fn() const onEntered = vi.fn() - render( + await render( ', () => { ) - await waitFor(() => { + await vi.waitFor(() => { expect(onEnter).toHaveBeenCalled() expect(onEntering).toHaveBeenCalled() expect(onEntered).toHaveBeenCalled() @@ -245,7 +240,7 @@ describe('', () => { const onExiting = vi.fn() const onExited = vi.fn() - const { rerender } = render( + const { rerender } = await render( ', () => { ) - rerender( + await rerender( ', () => { ) - await waitFor(() => { + await vi.waitFor(() => { expect(onExit).toHaveBeenCalled() expect(onExiting).toHaveBeenCalled() expect(onExited).toHaveBeenCalled() diff --git a/packages/ui-navigation/src/AppNav/__tests__/AppNav.test.tsx b/packages/ui-navigation/src/AppNav/__tests__/AppNav.test.tsx index b98f2d6329..d07289add5 100644 --- a/packages/ui-navigation/src/AppNav/__tests__/AppNav.test.tsx +++ b/packages/ui-navigation/src/AppNav/__tests__/AppNav.test.tsx @@ -22,8 +22,9 @@ * SOFTWARE. */ -import { render, screen } from '@testing-library/react' -import { vi } from 'vitest' +import { render } from 'vitest-browser-react' +import { page } from 'vitest/browser' +import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest' import { AppNav } from '@instructure/ui-navigation/latest' describe('', () => { @@ -42,7 +43,7 @@ describe('', () => { describe('for a11y', () => { it('should render a nav element with an aria-label', async () => { - const { container } = render( + const { container } = await render( ', () => { }) it('should render a semantic list of items', async () => { - render( + await render( ', () => { ) - const list = screen.getAllByRole('list') - const items = screen.getAllByRole('listitem') - const link = screen.getAllByRole('link') - const button = screen.getAllByRole('button') + const list = page.getByRole('list').elements() + const items = page.getByRole('listitem').elements() + const link = page.getByRole('link').elements() + const button = page.getByRole('button').elements() expect(list.length).toBe(1) expect(items.length).toBe(2) @@ -88,7 +89,7 @@ describe('', () => { }) it('should render with a single item', async () => { - render( + await render( ', () => { ) - const list = screen.getAllByRole('list') - const items = screen.getAllByRole('listitem') - const link = screen.getAllByRole('link') + const list = page.getByRole('list').elements() + const items = page.getByRole('listitem').elements() + const link = page.getByRole('link').elements() expect(list.length).toBe(1) expect(items.length).toBe(1) @@ -109,7 +110,7 @@ describe('', () => { describe('with rendered content', () => { it('should render content after the navigation', async () => { - render( + await render( I am rendered after!} @@ -125,7 +126,7 @@ describe('', () => { /> ) - const button = screen.getByRole('button') + const button = page.getByRole('button').element() expect(button).toHaveTextContent('I am rendered after!') }) @@ -133,7 +134,7 @@ describe('', () => { describe('with item truncation', () => { it('should pass a custom label to the menu trigger', async () => { - render( + await render( ', () => { ) - const items = screen.getAllByRole('listitem') + const items = page.getByRole('listitem').elements() expect(items.length).toBe(3) expect(items[2]).toHaveTextContent('I am sooo custom!') diff --git a/packages/ui-navigation/src/AppNav/__tests__/Item.test.tsx b/packages/ui-navigation/src/AppNav/__tests__/Item.test.tsx index ff467a318d..e691cc6da6 100644 --- a/packages/ui-navigation/src/AppNav/__tests__/Item.test.tsx +++ b/packages/ui-navigation/src/AppNav/__tests__/Item.test.tsx @@ -22,10 +22,9 @@ * SOFTWARE. */ -import { render, screen, waitFor } from '@testing-library/react' -import { vi } from 'vitest' -import userEvent from '@testing-library/user-event' -import '@testing-library/jest-dom' +import { render } from 'vitest-browser-react' +import { page, userEvent } from 'vitest/browser' +import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest' import { runAxeCheck } from '@instructure/ui-axe-check' import { ScreenReaderContent } from '@instructure/ui-a11y-content' @@ -58,14 +57,14 @@ describe('', () => { }) it('should render label text', async () => { - render() - const item = screen.getByRole('link') + await render() + const item = page.getByRole('link').element() expect(item).toHaveTextContent('Some label') }) it('should render an icon/image/etc.', async () => { - const { container } = render( + const { container } = await render( Some label} @@ -73,9 +72,9 @@ describe('', () => { /> ) - const iconTitle = screen.getByTitle('Some icon') + const iconTitle = page.getByTitle('Some icon').element() const iconSvg = container.querySelector('svg') - const item = screen.getByRole('link') + const item = page.getByRole('link').element() expect(iconTitle).toBeInTheDocument() expect(iconSvg).toBeInTheDocument() @@ -85,15 +84,15 @@ describe('', () => { }) it('should render content after the label text to accommodate badges, etc.', async () => { - render( + await render( I am rendered after!} /> ) - const item = screen.getByRole('link') - const after = screen.getByText('I am rendered after!') + const item = page.getByRole('link').element() + const after = page.getByText('I am rendered after!').element() expect(item).toBeInTheDocument() expect(item).toHaveTextContent('Some label') @@ -104,19 +103,19 @@ describe('', () => { it('should respond to an onClick event', async () => { const onClick = vi.fn() - render() + await render() - const button = screen.getByRole('button') + const button = page.getByRole('button').element() await userEvent.click(button) - await waitFor(() => { + await vi.waitFor(() => { expect(onClick).toHaveBeenCalledTimes(1) }) }) it('should output a console error if icon is used with non-screenreader label text', async () => { - render( + await render( ', () => { }) it('should meet a11y standards', async () => { - const { container } = render( + const { container } = await render( Some label} diff --git a/packages/ui-number-input/src/NumberInput/__tests__/NumberInput.test.tsx b/packages/ui-number-input/src/NumberInput/__tests__/NumberInput.test.tsx index 3f8e35f416..dc358fe498 100644 --- a/packages/ui-number-input/src/NumberInput/__tests__/NumberInput.test.tsx +++ b/packages/ui-number-input/src/NumberInput/__tests__/NumberInput.test.tsx @@ -22,16 +22,14 @@ * SOFTWARE. */ -import { render, screen, waitFor } from '@testing-library/react' -import userEvent from '@testing-library/user-event' -import { vi } from 'vitest' - import { NumberInput } from '@instructure/ui-number-input/latest' import { ChevronUpInstUIIcon, ChevronDownInstUIIcon } from '@instructure/ui-icons' -import '@testing-library/jest-dom' +import { render } from 'vitest-browser-react' +import { page, userEvent } from 'vitest/browser' +import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest' describe('', () => { let consoleWarningMock: ReturnType @@ -54,22 +52,26 @@ describe('', () => { it('sets value on the input', async () => { const onChange = vi.fn() - render() - const input = screen.getByRole('spinbutton') + await render( + + ) + const input = page.getByRole('spinbutton').element() expect(input).toHaveValue(42) }) it('should accept a number for the value', async () => { const onChange = vi.fn() - render() - const input = screen.getByRole('spinbutton') + await render( + + ) + const input = page.getByRole('spinbutton').element() expect(input).toHaveValue(42) }) it('displays the label', async () => { - const { container } = render() + const { container } = await render() const label = container.querySelector( 'span[class$="-formFieldLayout__label"]' ) @@ -79,8 +81,8 @@ describe('', () => { it('passes the input element to inputRef', async () => { const inputRef = vi.fn() - render() - const input = screen.getByRole('spinbutton') + await render() + const input = page.getByRole('spinbutton').element() expect(inputRef).toHaveBeenCalledTimes(1) expect(inputRef).toHaveBeenCalledWith(input) @@ -88,12 +90,12 @@ describe('', () => { it('passes change events to onChange handler', async () => { const onChange = vi.fn() - render() - const input = screen.getByRole('spinbutton') + await render() + const input = page.getByRole('spinbutton').element() await userEvent.type(input, '5') - await waitFor(() => { + await vi.waitFor(() => { const event = onChange.mock.calls[0][0] const args = onChange.mock.calls[0][1] expect(onChange).toHaveBeenCalledTimes(1) @@ -104,42 +106,42 @@ describe('', () => { it('passes keyboard events to the onKeyDown handler', async () => { const onKeyDown = vi.fn() - render() - const input = screen.getByRole('spinbutton') + await render() + const input = page.getByRole('spinbutton').element() await userEvent.type(input, '5') - await waitFor(() => { + await vi.waitFor(() => { expect(onKeyDown).toHaveBeenCalledTimes(1) }) }) it('passes blur events to onBlur handler', async () => { const onBlur = vi.fn() - render() + await render() await userEvent.tab() await userEvent.tab() - await waitFor(() => { + await vi.waitFor(() => { expect(onBlur).toHaveBeenCalledTimes(1) }) }) it('passes focus events to onFocus handler', async () => { const onFocus = vi.fn() - render() - const input = screen.getByRole('spinbutton') + await render() + const input = page.getByRole('spinbutton').element() input.focus() - await waitFor(() => { + await vi.waitFor(() => { expect(onFocus).toHaveBeenCalledTimes(1) }) }) it('shows arrow spinbuttons by default', async () => { - const { container } = render() + const { container } = await render() const buttons = container.querySelectorAll( 'button[class$="-numberInput_arrow"]' ) @@ -148,7 +150,7 @@ describe('', () => { }) it('hides arrow spinbuttons when showArrows is false', async () => { - const { container } = render( + const { container } = await render( ) const buttons = container.querySelectorAll( @@ -160,7 +162,7 @@ describe('', () => { it('calls onIncrement when up arrow spinbutton is clicked', async () => { const onIncrement = vi.fn() - const { container } = render( + const { container } = await render( ) const buttons = container.querySelectorAll( @@ -169,14 +171,14 @@ describe('', () => { await userEvent.click(buttons[0]) - await waitFor(() => { + await vi.waitFor(() => { expect(onIncrement).toHaveBeenCalledTimes(1) }) }) it('does not call onIncrement when `interaction` is set to readonly', async () => { const onIncrement = vi.fn() - const { container } = render( + const { container } = await render( ', () => { await userEvent.click(buttons[0]) - await waitFor(() => { + await vi.waitFor(() => { expect(onIncrement).toHaveBeenCalledTimes(0) }) }) it('does not call onIncrement when `readOnly` is set', async () => { const onIncrement = vi.fn() - const { container } = render( + const { container } = await render( ) const buttons = container.querySelectorAll( @@ -205,14 +207,14 @@ describe('', () => { await userEvent.click(buttons[0]) - await waitFor(() => { + await vi.waitFor(() => { expect(onIncrement).toHaveBeenCalledTimes(0) }) }) it('calls onDecrement when down arrow spinbutton is clicked', async () => { const onDecrement = vi.fn() - const { container } = render( + const { container } = await render( ) @@ -222,14 +224,14 @@ describe('', () => { await userEvent.click(buttons[1]) - await waitFor(() => { + await vi.waitFor(() => { expect(onDecrement).toHaveBeenCalledTimes(1) }) }) it('does not call onDecrement when `interaction` is set to readonly', async () => { const onDecrement = vi.fn() - const { container } = render( + const { container } = await render( ', () => { await userEvent.click(buttons[1]) - await waitFor(() => { + await vi.waitFor(() => { expect(onDecrement).toHaveBeenCalledTimes(0) }) }) it('does not call onDecrement when `readOnly` is set', async () => { const onDecrement = vi.fn() - const { container } = render( + const { container } = await render( ) const buttons = container.querySelectorAll( @@ -258,14 +260,14 @@ describe('', () => { await userEvent.click(buttons[1]) - await waitFor(() => { + await vi.waitFor(() => { expect(onDecrement).toHaveBeenCalledTimes(0) }) }) it('puts inputMode prop to input', async () => { - render() - const input = screen.getByRole('spinbutton') + await render() + const input = page.getByRole('spinbutton').element() expect(input).toHaveAttribute('inputMode', 'decimal') }) @@ -273,7 +275,7 @@ describe('', () => { it('renders custom interactive icons', async () => { const onDecrement = vi.fn() const onIncrement = vi.fn() - const { container } = render( + const { container } = await render( ', () => { ) await userEvent.click(buttons[0]) - await waitFor(() => { + await vi.waitFor(() => { expect(onIncrement).toHaveBeenCalledTimes(1) }) await userEvent.click(buttons[1]) - await waitFor(() => { + await vi.waitFor(() => { expect(onDecrement).toHaveBeenCalledTimes(1) }) }) it('associates messages with the input as its description, not its accessible name', async () => { - render( + await render( ) - const input = screen.getByRole('spinbutton') + const input = page.getByRole('spinbutton').element() const describedById = input.getAttribute('aria-describedby') expect(describedById).toBeTruthy() @@ -328,8 +330,8 @@ describe('', () => { }) it('does not override the accessible name with aria-labelledby when there are no messages', async () => { - render() - const input = screen.getByRole('spinbutton') + await render() + const input = page.getByRole('spinbutton').element() expect(input).not.toHaveAttribute('aria-labelledby') }) diff --git a/packages/ui-options/src/Options/__tests__/Item.test.tsx b/packages/ui-options/src/Options/__tests__/Item.test.tsx index 2326231309..9a5921d0ef 100644 --- a/packages/ui-options/src/Options/__tests__/Item.test.tsx +++ b/packages/ui-options/src/Options/__tests__/Item.test.tsx @@ -22,17 +22,15 @@ * SOFTWARE. */ -import { render, screen, waitFor } from '@testing-library/react' -import { vi, expect } from 'vitest' -import userEvent from '@testing-library/user-event' - -import '@testing-library/jest-dom' +import { render } from 'vitest-browser-react' +import { page, userEvent } from 'vitest/browser' +import { describe, it, expect, vi } from 'vitest' import { IconCheckSolid } from '@instructure/ui-icons' import { Options, OptionItem as Item } from '@instructure/ui-options/latest' describe('', () => { it('should render', async () => { - const { container } = render() + const { container } = await render() const optionItem = container.querySelector('[class$="-optionItem"]') expect(optionItem).toBeInTheDocument() @@ -44,7 +42,7 @@ describe('', () => { }) it('should not render as a list item by default', async () => { - const { container } = render(Hello World) + const { container } = await render(Hello World) const item = container.querySelector('[class$="-optionItem"]') @@ -53,7 +51,7 @@ describe('', () => { }) it('should render designated tag if `as` prop is specified', async () => { - const { container } = render(Hello World) + const { container } = await render(Hello World) const item = container.querySelector('[class$="-optionItem"]') @@ -62,7 +60,7 @@ describe('', () => { }) it('should render children properly', async () => { - const { container } = render( + const { container } = await render( Hello World @@ -75,17 +73,17 @@ describe('', () => { }) it('should render role attributes appropriately when given a role', async () => { - const { container } = render(Hello World) + const { container } = await render(Hello World) const item = container.querySelector('[class$="-optionItem"]') - const child = screen.getByRole('option') + const child = page.getByRole('option').element() expect(item).toHaveAttribute('role', 'none') expect(child).toBeInTheDocument() }) it('should render description properly', async () => { - const { container } = render( + const { container } = await render( Hello World @@ -100,19 +98,19 @@ describe('', () => { }) it('should render role attributes for description', async () => { - render( + await render( Hello World ) - const description = screen.getByRole('comment') + const description = page.getByRole('comment').element() expect(description).toBeInTheDocument() expect(description).toHaveTextContent('Some text as description') }) it('should pass props through to label', async () => { - const { container } = render( + const { container } = await render( Hello World @@ -130,7 +128,9 @@ describe('', () => { it('should pass event handlers through to label', async () => { const onClick = vi.fn() - const { container } = render(Hello World) + const { container } = await render( + Hello World + ) const optionItem = container.querySelector('[class$="-optionItem"]') const optionItemContainer = container.querySelector( @@ -138,18 +138,18 @@ describe('', () => { ) await userEvent.click(optionItem!) - await waitFor(() => { + await vi.waitFor(() => { expect(onClick).not.toHaveBeenCalled() }) await userEvent.click(optionItemContainer!) - await waitFor(() => { + await vi.waitFor(() => { expect(onClick).toHaveBeenCalledTimes(1) }) }) it('should render content before label', async () => { - const { container } = render( + const { container } = await render( }>Hello World ) @@ -163,7 +163,7 @@ describe('', () => { }) it('should render content after label', async () => { - const { container } = render( + const { container } = await render( }>Hello World ) @@ -177,7 +177,7 @@ describe('', () => { }) it('should render nested lists', async () => { - const { container } = render( + const { container } = await render( Sub item @@ -200,7 +200,9 @@ describe('', () => { }) it('should render as link with href prop', async () => { - const { container } = render(Hello World) + const { container } = await render( + Hello World + ) const link = container.querySelector('[class$="-optionItem__container"]') diff --git a/packages/ui-options/src/Options/__tests__/Options.test.tsx b/packages/ui-options/src/Options/__tests__/Options.test.tsx index 7f0c4f0863..d86954ff87 100644 --- a/packages/ui-options/src/Options/__tests__/Options.test.tsx +++ b/packages/ui-options/src/Options/__tests__/Options.test.tsx @@ -22,15 +22,16 @@ * SOFTWARE. */ -import { render, screen } from '@testing-library/react' -import { vi, expect } from 'vitest' +import { render } from 'vitest-browser-react' +import { page } from 'vitest/browser' +import { describe, it, expect, vi } from 'vitest' import { runAxeCheck } from '@instructure/ui-axe-check' import { Options } from '@instructure/ui-options/latest' describe('', () => { it('should render', async () => { - const { container } = render() + const { container } = await render() const options = container.querySelector('div[class*="-options"]') @@ -38,13 +39,13 @@ describe('', () => { }) it('should render items', async () => { - render( + await render( Option one Option two ) - const items = screen.getAllByRole('listitem') + const items = page.getByRole('listitem').elements() expect(items.length).toBe(2) }) @@ -52,31 +53,31 @@ describe('', () => { it('should provide elementRef', async () => { const elementRef = vi.fn() - render( + await render( Option one Option two ) - const optionList = screen.getByRole('list') + const optionList = page.getByRole('list').element() expect(elementRef).toHaveBeenCalledWith(optionList) }) it('should render designated tag if `as` prop is specified', async () => { - render( + await render( Option one Option two ) - const optionList = screen.getByRole('list') + const optionList = page.getByRole('list').element() expect(optionList.tagName).toBe('OL') }) it('should render children as listitems when appropriate', async () => { - const { container } = render( + const { container } = await render( Option one Option two @@ -90,7 +91,7 @@ describe('', () => { }) it('should pass props through to list', async () => { - const { container } = render( + const { container } = await render( Option one Option two @@ -103,7 +104,7 @@ describe('', () => { }) it('should render root with appropriate role', async () => { - const { container } = render( + const { container } = await render( Option one Option two @@ -115,15 +116,15 @@ describe('', () => { }) it('should allow null children', async () => { - render() + await render() - const options = screen.getByRole('list') + const options = page.getByRole('list').element() expect(options).toBeInTheDocument() }) it('should render nested options properly', async () => { - const { container } = render( + const { container } = await render( Option one Option two @@ -139,7 +140,7 @@ describe('', () => { expect(allLists.length).toBe(2) expect(allItems.length).toBe(5) - const outerList = screen.getByTestId('outer-list') + const outerList = page.getByTestId('outer-list').element() expect(outerList).toHaveTextContent('Option one Option two') const nestedLabel = outerList.querySelector( @@ -148,7 +149,7 @@ describe('', () => { expect(nestedLabel).toBeInTheDocument() expect(nestedLabel).toHaveTextContent('Nested list') - const nestedList = screen.getByTestId('nested-list') + const nestedList = page.getByTestId('nested-list').element() expect(nestedList).toHaveTextContent('Nested option one Nested option two') const nestedListItems = nestedList!.querySelectorAll('[class$=-optionItem]') @@ -160,7 +161,7 @@ describe('', () => { describe('for a11y', () => { it('should be accessible with links', async () => { - const { container } = render( + const { container } = await render( Option Option link diff --git a/packages/ui-overlays/src/Mask/__tests__/Mask.test.tsx b/packages/ui-overlays/src/Mask/__tests__/Mask.test.tsx index 443738cb39..a69a63dd2f 100644 --- a/packages/ui-overlays/src/Mask/__tests__/Mask.test.tsx +++ b/packages/ui-overlays/src/Mask/__tests__/Mask.test.tsx @@ -22,11 +22,10 @@ * SOFTWARE. */ -import { render, waitFor } from '@testing-library/react' -import { vi } from 'vitest' -import userEvent from '@testing-library/user-event' import { Mask } from '@instructure/ui-overlays/latest' -import '@testing-library/jest-dom' +import { render } from 'vitest-browser-react' +import { userEvent } from 'vitest/browser' +import { describe, it, expect, beforeAll, afterAll, vi } from 'vitest' describe('', () => { let originalScroll: any @@ -44,18 +43,18 @@ describe('', () => { window.scroll = originalScroll }) - it('should render', () => { - render() + it('should render', async () => { + await render() const mask = document.querySelector("span[class$='-mask']") expect(mask).toBeInTheDocument() }) - it('should have tabIndex -1 when onClick is provided', () => { + it('should have tabIndex -1 when onClick is provided', async () => { const onClick = vi.fn() - render() + await render() const mask = document.querySelector("span[class$='-mask']") expect(mask).toHaveAttribute('tabindex', '-1') @@ -64,19 +63,19 @@ describe('', () => { it('should call onClick prop when clicked', async () => { const onClick = vi.fn() - render() + await render() const mask = document.querySelector("span[class$='-mask']") await userEvent.click(mask!) - await waitFor(() => { + await vi.waitFor(() => { expect(onClick).toHaveBeenCalled() }) }) - it('should apply fullscreen CSS when prop is true', () => { - render() + it('should apply fullscreen CSS when prop is true', async () => { + await render() const mask = document.querySelector("span[class$='-mask']") expect(mask).toHaveStyle('position: fixed') @@ -85,7 +84,7 @@ describe('', () => { it('should provide an elementRef', async () => { const elementRef = vi.fn() - render() + await render() const mask = document.querySelector("span[class$='-mask']") expect(elementRef).toHaveBeenCalledWith(mask) diff --git a/packages/ui-overlays/src/Overlay/__tests__/Overlay.test.tsx b/packages/ui-overlays/src/Overlay/__tests__/Overlay.test.tsx index 4bb4eb6c41..5cbf7acd0e 100644 --- a/packages/ui-overlays/src/Overlay/__tests__/Overlay.test.tsx +++ b/packages/ui-overlays/src/Overlay/__tests__/Overlay.test.tsx @@ -22,26 +22,26 @@ * SOFTWARE. */ -import { render, screen, waitFor } from '@testing-library/react' -import { vi } from 'vitest' import { Overlay } from '@instructure/ui-overlays/latest' -import '@testing-library/jest-dom' +import { render } from 'vitest-browser-react' +import { page } from 'vitest/browser' +import { describe, it, expect, vi } from 'vitest' describe('', () => { - it('should render nothing when closed', () => { - render() - const overlay = screen.queryByText('Overlay Example') + it('should render nothing when closed', async () => { + await render() + const overlay = page.getByText('Overlay Example').query() expect(overlay).not.toBeInTheDocument() }) - it('should render children when open', () => { - render( + it('should render children when open', async () => { + await render( Hello World ) - const overlay = screen.getByRole('dialog') + const overlay = page.getByRole('dialog').element() expect(overlay).toHaveTextContent('Hello World') }) @@ -51,7 +51,7 @@ describe('', () => { const onEntering = vi.fn() const onEntered = vi.fn() - render( + await render( ', () => { /> ) - await waitFor(() => { + await vi.waitFor(() => { expect(onEnter).toHaveBeenCalled() expect(onEntering).toHaveBeenCalled() expect(onEntered).toHaveBeenCalled() @@ -72,9 +72,9 @@ describe('', () => { it('should support onOpen prop', async () => { const onOpen = vi.fn() - render() + await render() - await waitFor(() => { + await vi.waitFor(() => { expect(onOpen).toHaveBeenCalled() }) }) @@ -82,13 +82,15 @@ describe('', () => { it('should support onClose prop', async () => { const onClose = vi.fn() - const { rerender } = render( + const { rerender } = await render( ) - rerender() + await rerender( + + ) - await waitFor(() => { + await vi.waitFor(() => { expect(onClose).toHaveBeenCalled() }) }) diff --git a/packages/ui-pages/src/Pages/__tests__/Page.test.tsx b/packages/ui-pages/src/Pages/__tests__/Page.test.tsx index 467fea28e9..88d309b96a 100644 --- a/packages/ui-pages/src/Pages/__tests__/Page.test.tsx +++ b/packages/ui-pages/src/Pages/__tests__/Page.test.tsx @@ -22,11 +22,10 @@ * SOFTWARE. */ -import { render } from '@testing-library/react' -import { vi, expect } from 'vitest' import type { MockInstance } from 'vitest' -import '@testing-library/jest-dom' +import { render } from 'vitest-browser-react' +import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest' import { PagesPage as Page } from '@instructure/ui-pages/latest' describe('', () => { @@ -44,7 +43,7 @@ describe('', () => { }) it('should render with a function as child', async () => { - const { container } = render( + const { container } = await render( {() => { return ( diff --git a/packages/ui-pages/src/Pages/__tests__/Pages.test.tsx b/packages/ui-pages/src/Pages/__tests__/Pages.test.tsx index 729e12781e..cfb8481903 100644 --- a/packages/ui-pages/src/Pages/__tests__/Pages.test.tsx +++ b/packages/ui-pages/src/Pages/__tests__/Pages.test.tsx @@ -22,12 +22,11 @@ * SOFTWARE. */ -import { render, waitFor } from '@testing-library/react' -import { vi, expect } from 'vitest' import type { MockInstance } from 'vitest' -import '@testing-library/jest-dom' -import userEvent from '@testing-library/user-event' +import { render } from 'vitest-browser-react' +import { userEvent } from 'vitest/browser' +import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest' import { Pages, PagesPage as Page } from '@instructure/ui-pages/latest' describe('', () => { @@ -45,7 +44,7 @@ describe('', () => { }) it('should render', async () => { - const { container } = render( + const { container } = await render( {() => 'Foo'} {() => 'Bar'} @@ -57,7 +56,7 @@ describe('', () => { }) it('should render a Page', async () => { - const { container } = render( + const { container } = await render( {() => 'Hello World'} @@ -68,7 +67,7 @@ describe('', () => { }) it('should render the 0th Page by default', async () => { - const { container } = render( + const { container } = await render( {() => 'Foo'} {() => 'Bar'} @@ -80,7 +79,7 @@ describe('', () => { }) it('should render the active Page', async () => { - const { container } = render( + const { container } = await render( {}}> {() => 'Foo'} {() => 'Bar'} @@ -93,13 +92,13 @@ describe('', () => { it('should pass history and navigateToPreviousPage to Page', async () => { const pageSpy = vi.fn() - render( + await render( {pageSpy} ) - await waitFor(() => { + await vi.waitFor(() => { const args = pageSpy.mock.calls[0] expect(pageSpy).toHaveBeenCalledTimes(1) @@ -111,7 +110,7 @@ describe('', () => { it('should fire onPageIndexChange event', async () => { const onPageIndexChange = vi.fn() - const { container, rerender } = render( + const { container, rerender } = await render( {() => 'Foo'} @@ -121,7 +120,7 @@ describe('', () => { ) // Set prop: activePageIndex - rerender( + await rerender( {() => 'Foo'} @@ -134,7 +133,7 @@ describe('', () => { await userEvent.click(button) - await waitFor(() => { + await vi.waitFor(() => { expect(onPageIndexChange).toHaveBeenCalledTimes(1) expect(onPageIndexChange).toHaveBeenCalledWith(0, 1) }) diff --git a/packages/ui-pagination/src/Pagination/__tests__/Pagination.test.tsx b/packages/ui-pagination/src/Pagination/__tests__/Pagination.test.tsx index 39912aa0db..004181a16e 100644 --- a/packages/ui-pagination/src/Pagination/__tests__/Pagination.test.tsx +++ b/packages/ui-pagination/src/Pagination/__tests__/Pagination.test.tsx @@ -22,10 +22,10 @@ * SOFTWARE. */ -import { render, screen, waitFor } from '@testing-library/react' -import { vi } from 'vitest' +import { render } from 'vitest-browser-react' +import { page, userEvent } from 'vitest/browser' +import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest' import { runAxeCheck } from '@instructure/ui-axe-check' -import userEvent from '@testing-library/user-event' import { View } from '@instructure/ui-view/latest' import { Pagination, PaginationButton } from '@instructure/ui-pagination/latest' @@ -61,10 +61,10 @@ describe('', () => { }) it('should render all pages buttons', async () => { - render({buildPages(5)}) + await render({buildPages(5)}) - const buttons = screen.getAllByRole('button') - const pagination = screen.getByRole('navigation') + const buttons = page.getByRole('button').elements() + const pagination = page.getByRole('navigation').element() expect(buttons.length).toEqual(5) expect(pagination).toHaveTextContent('#0#1#2#3#4') @@ -72,7 +72,7 @@ describe('', () => { describe('with 5 or less pages', () => { it('should not render next/prev buttons', async () => { - render( + await render( ', () => { ) - const pagination = screen.queryByText('Example') - const nextButton = screen.queryByText('Next') - const prevButton = screen.queryByText('Prev') + const pagination = page.getByText('Example').query() + const nextButton = page.getByText('Next').query() + const prevButton = page.getByText('Prev').query() expect(pagination).toBeInTheDocument() expect(nextButton).not.toBeInTheDocument() @@ -93,7 +93,7 @@ describe('', () => { }) it('should not render first/last buttons', async () => { - render( + await render( ', () => { ) - const pagination = screen.queryByText('Example') - const firstButton = screen.queryByText('First') - const lastButton = screen.queryByText('Last') + const pagination = page.getByText('Example').query() + const firstButton = page.getByText('First').query() + const lastButton = page.getByText('Last').query() expect(pagination).toBeInTheDocument() expect(firstButton).not.toBeInTheDocument() @@ -119,7 +119,7 @@ describe('', () => { describe('should meet a11y standards', () => { it('by default', async () => { - const { container } = render( + const { container } = await render( {buildPages(5)} @@ -129,7 +129,7 @@ describe('', () => { }) it('by default with more pages', async () => { - const { container } = render( + const { container } = await render( {buildPages(8)} @@ -139,7 +139,7 @@ describe('', () => { }) it('with first/last arrows', async () => { - const { container } = render( + const { container } = await render( ', () => { }) it('with disabled arrows', async () => { - const { container } = render( + const { container } = await render( ', () => { }) it('should render page buttons', async () => { - render( + await render( {buildPages(5)} ) - const buttons = screen.getAllByRole('button') - const pagination = screen.getByRole('navigation') + const buttons = page.getByRole('button').elements() + const pagination = page.getByRole('navigation').element() expect(buttons.length).toEqual(5) expect(pagination).toHaveTextContent('#0#1#2#3#4') }) it('should render a single page button', async () => { - render( + await render( {buildPages(1)} ) - const buttons = screen.getAllByRole('button') - const pagination = screen.getByRole('navigation') + const buttons = page.getByRole('button').elements() + const pagination = page.getByRole('navigation').element() expect(buttons.length).toEqual(1) expect(pagination).toHaveTextContent('#0') }) it('should render nothing if there are no pages', async () => { - render() - const pagination = screen.getByRole('navigation') - const buttons = screen.queryAllByRole('button') + await render( + + ) + const pagination = page.getByRole('navigation').element() + const buttons = page.getByRole('button').elements() expect(pagination).toBeInTheDocument() expect(buttons.length).toEqual(0) }) it('should truncate pages to context', async () => { - render( + await render( {buildPages(9, 3)} ) - const pagination = screen.getByRole('navigation') - const allButtons = screen.queryAllByRole('button') - const paginationButtons = screen.getAllByRole('button', { name: /^#\d$/ }) + const pagination = page.getByRole('navigation').element() + const allButtons = page.getByRole('button').elements() + const paginationButtons = page + .getByRole('button', { name: /^#\d$/ }) + .elements() const ellipses = document.querySelectorAll('li[aria-hidden="true"]') expect(pagination).toBeInTheDocument() @@ -232,15 +236,17 @@ describe('', () => { }) it('should truncate start', async () => { - render( + await render( {buildPages(9, 8)} ) - const pagination = screen.getByRole('navigation') - const allButtons = screen.queryAllByRole('button') - const paginationButtons = screen.getAllByRole('button', { name: /^#\d$/ }) + const pagination = page.getByRole('navigation').element() + const allButtons = page.getByRole('button').elements() + const paginationButtons = page + .getByRole('button', { name: /^#\d$/ }) + .elements() const ellipses = document.querySelectorAll('li[aria-hidden="true"]') expect(pagination).toBeInTheDocument() @@ -255,15 +261,17 @@ describe('', () => { }) it('should truncate end', async () => { - render( + await render( {buildPages(6)} ) - const pagination = screen.getByRole('navigation') - const allButtons = screen.queryAllByRole('button') - const paginationButtons = screen.getAllByRole('button', { name: /^#\d$/ }) + const pagination = page.getByRole('navigation').element() + const allButtons = page.getByRole('button').elements() + const paginationButtons = page + .getByRole('button', { name: /^#\d$/ }) + .elements() const ellipses = document.querySelectorAll('li[aria-hidden="true"]') expect(pagination).toBeInTheDocument() @@ -278,18 +286,22 @@ describe('', () => { }) it('should omit ellipses when bounds included in context', async () => { - render( + await render( {buildPages(7, 2)} ) - const pagination = screen.getByRole('navigation') - const allButtons = screen.queryAllByRole('button') - const paginationButtons = screen.getAllByRole('button', { name: /^#\d$/ }) - const ellipses = screen.queryAllByText('…', { - selector: '[aria-hidden="true"]' - }) + const pagination = page.getByRole('navigation').element() + const allButtons = page.getByRole('button').elements() + const paginationButtons = page + .getByRole('button', { name: /^#\d$/ }) + .elements() + const ellipses = page + .getByText('…', { + selector: '[aria-hidden="true"]' + }) + .elements() expect(pagination).toBeInTheDocument() expect(pagination).toHaveTextContent('Prev#0#1#2#3#4#5#6Next') @@ -301,30 +313,32 @@ describe('', () => { describe('when updating with the FIRST page becoming current', () => { it('should move focus from the Previous Page button to the first page button', async () => { - const { rerender } = render( + const { rerender } = await render( {buildPages(7, 1)} ) - const prevButton = screen.getByRole('button', { name: 'Previous' }) + const prevButton = page + .getByRole('button', { name: 'Previous' }) + .element() prevButton.focus() expect(prevButton).toHaveFocus() // Set children: buildPages(7, 0) - rerender( + await rerender( {buildPages(7, 0)} ) - const button0 = screen.getByRole('button', { name: '#0' }) + const button0 = page.getByRole('button', { name: '#0' }).element() expect(button0).toHaveFocus() }) it('should move focus from the First Page button to the first page button', async () => { - const { rerender } = render( + const { rerender } = await render( ', () => { ) - const firstButton = screen.getByRole('button', { name: 'First' }) + const firstButton = page.getByRole('button', { name: 'First' }).element() firstButton.focus() expect(firstButton).toHaveFocus() // Set children: buildPages(7, 0) - rerender( + await rerender( ', () => { {buildPages(7, 0)} ) - const button0 = screen.getByRole('button', { name: '#0' }) + const button0 = page.getByRole('button', { name: '#0' }).element() expect(button0).toHaveFocus() }) it('should not change focus when the Previous Page button did not have focus', async () => { - const { rerender } = render( + const { rerender } = await render( {buildPages(7, 1)} ) - const button1 = screen.getByRole('button', { name: '#1' }) + const button1 = page.getByRole('button', { name: '#1' }).element() button1.focus() expect(button1).toHaveFocus() - rerender( + await rerender( {buildPages(7, 0)} @@ -381,7 +395,7 @@ describe('', () => { }) it('should not change focus when the First Page button did not have focus', async () => { - const { rerender } = render( + const { rerender } = await render( ', () => { {buildPages(7, 1)} ) - const button1 = screen.getByRole('button', { name: '#1' }) + const button1 = page.getByRole('button', { name: '#1' }).element() button1.focus() expect(button1).toHaveFocus() - rerender( + await rerender( ', () => { }) it('should not continue to change focus on subsequent updates', async () => { - const { rerender } = render( + const { rerender } = await render( {buildPages(7, 1)} ) - const prevButton = screen.getByRole('button', { name: 'Previous' }) + const prevButton = page + .getByRole('button', { name: 'Previous' }) + .element() prevButton.focus() expect(prevButton).toHaveFocus() // Set children: buildPages(7, 0) - rerender( + await rerender( {buildPages(7, 0)} ) - const button1 = screen.getByRole('button', { name: '#1' }) + const button1 = page.getByRole('button', { name: '#1' }).element() button1.focus() expect(button1).toHaveFocus() // Set children: buildPages(7, 0) - rerender( + await rerender( {buildPages(7, 0)} @@ -450,29 +466,29 @@ describe('', () => { describe('when updating with the LAST page becoming current', () => { it('should move focus from the Next Page button to the last page button', async () => { - const { rerender } = render( + const { rerender } = await render( {buildPages(7, 5)} ) - const nextButton = screen.getByRole('button', { name: 'Next' }) + const nextButton = page.getByRole('button', { name: 'Next' }).element() nextButton.focus() expect(nextButton).toHaveFocus() // Set children: buildPages(7, 6) - rerender( + await rerender( {buildPages(7, 6)} ) - const button6 = screen.getByRole('button', { name: '#6' }) + const button6 = page.getByRole('button', { name: '#6' }).element() expect(button6).toHaveFocus() }) it('should move focus from the Last Page button to the last page button', async () => { - const { rerender } = render( + const { rerender } = await render( ', () => { {buildPages(7, 4)} ) - const lastButton = screen.getByRole('button', { name: 'Last' }) + const lastButton = page.getByRole('button', { name: 'Last' }).element() lastButton.focus() expect(lastButton).toHaveFocus() // Set children: buildPages(7, 6) - rerender( + await rerender( ', () => { {buildPages(7, 6)} ) - const button6 = screen.getByRole('button', { name: '#6' }) + const button6 = page.getByRole('button', { name: '#6' }).element() expect(button6).toHaveFocus() }) it('should not change focus when the Next Page button did not have focus', async () => { - const { rerender } = render( + const { rerender } = await render( {buildPages(7, 5)} ) - const button5 = screen.getByRole('button', { name: '#5' }) + const button5 = page.getByRole('button', { name: '#5' }).element() button5.focus() expect(button5).toHaveFocus() // Set children: buildPages(7, 5) - rerender( + await rerender( {buildPages(7, 5)} @@ -528,7 +544,7 @@ describe('', () => { }) it('should not change focus when the Last Page button did not have focus', async () => { - const { rerender } = render( + const { rerender } = await render( ', () => { {buildPages(7, 5)} ) - const button5 = screen.getByRole('button', { name: '#5' }) + const button5 = page.getByRole('button', { name: '#5' }).element() button5.focus() expect(button5).toHaveFocus() // Set children: buildPages(7, 6) - rerender( + await rerender( ', () => { }) it('should not continue to change focus on subsequent updates', async () => { - const { rerender } = render( + const { rerender } = await render( {buildPages(7, 5)} ) - const nextButton = screen.getByRole('button', { name: 'Next' }) + const nextButton = page.getByRole('button', { name: 'Next' }).element() nextButton.focus() expect(nextButton).toHaveFocus() // Set children: buildPages(7, 6) - rerender( + await rerender( {buildPages(7, 6)} ) - const button5 = screen.getByRole('button', { name: '#5' }) + const button5 = page.getByRole('button', { name: '#5' }).element() button5.focus() expect(button5).toHaveFocus() // Set children: buildPages(7, 6) - rerender( + await rerender( {buildPages(7, 6)} @@ -597,34 +613,40 @@ describe('', () => { describe('arrows', () => { describe('should render', () => { it('only the stepper arrows when available', async () => { - const { rerender } = render( + const { rerender } = await render( {buildPages(6)} ) - const prevButton = screen.queryByRole('button', { name: 'Previous' }) - const nextButton = screen.queryByRole('button', { name: 'Next' }) + const prevButton = page + .getByRole('button', { name: 'Previous' }) + .query() + const nextButton = page.getByRole('button', { name: 'Next' }).query() expect(prevButton).not.toBeInTheDocument() expect(nextButton).toBeInTheDocument() // Set children: buildPages(6, 5) - rerender( + await rerender( {buildPages(6, 5)} ) - const prevButtonUpdated = screen.queryByRole('button', { - name: 'Previous' - }) - const nextButtonUpdated = screen.queryByRole('button', { name: 'Next' }) + const prevButtonUpdated = page + .getByRole('button', { + name: 'Previous' + }) + .query() + const nextButtonUpdated = page + .getByRole('button', { name: 'Next' }) + .query() expect(prevButtonUpdated).toBeInTheDocument() expect(nextButtonUpdated).not.toBeInTheDocument() }) it('the First and Last arrows withFirstAndLastButton', async () => { - const { rerender } = render( + const { rerender } = await render( ', () => { {buildPages(6)} ) - const firstButton = screen.queryByRole('button', { name: 'First' }) - const lastButton = screen.queryByRole('button', { name: 'Last' }) + const firstButton = page.getByRole('button', { name: 'First' }).query() + const lastButton = page.getByRole('button', { name: 'Last' }).query() expect(firstButton).not.toBeInTheDocument() expect(lastButton).toBeInTheDocument() // Set children: buildPages(6, 5) - rerender( + await rerender( ', () => { {buildPages(6, 5)} ) - const firstButtonUpdated = screen.queryByRole('button', { - name: 'First' - }) - const lastButtonUpdated = screen.queryByRole('button', { name: 'Last' }) + const firstButtonUpdated = page + .getByRole('button', { + name: 'First' + }) + .query() + const lastButtonUpdated = page + .getByRole('button', { name: 'Last' }) + .query() expect(firstButtonUpdated).toBeInTheDocument() expect(lastButtonUpdated).not.toBeInTheDocument() }) it('the disabled arrows with showDisabledButtons', async () => { - const { rerender } = render( + const { rerender } = await render( ', () => { ) - const firstButton = screen.getByRole('button', { name: 'First' }) - const prevButton = screen.getByRole('button', { name: 'Previous' }) - const nextButton = screen.getByRole('button', { name: 'Next' }) - const lastButton = screen.getByRole('button', { name: 'Last' }) + const firstButton = page + .getByRole('button', { name: 'First' }) + .element() + const prevButton = page + .getByRole('button', { name: 'Previous' }) + .element() + const nextButton = page.getByRole('button', { name: 'Next' }).element() + const lastButton = page.getByRole('button', { name: 'Last' }).element() expect(firstButton).toBeDisabled() expect(prevButton).toBeDisabled() @@ -691,7 +721,7 @@ describe('', () => { // Go to last item // Set children: buildPages(6, 5) - rerender( + await rerender( ', () => { {buildPages(6, 5)} ) - const firstButtonUpdated = screen.getByRole('button', { name: 'First' }) - const prevButtonUpdated = screen.getByRole('button', { - name: 'Previous' - }) - const nextButtonUpdated = screen.getByRole('button', { name: 'Next' }) - const lastButtonUpdated = screen.getByRole('button', { name: 'Last' }) + const firstButtonUpdated = page + .getByRole('button', { name: 'First' }) + .element() + const prevButtonUpdated = page + .getByRole('button', { + name: 'Previous' + }) + .element() + const nextButtonUpdated = page + .getByRole('button', { name: 'Next' }) + .element() + const lastButtonUpdated = page + .getByRole('button', { name: 'Last' }) + .element() expect(firstButtonUpdated).not.toBeDisabled() expect(prevButtonUpdated).not.toBeDisabled() @@ -719,31 +757,35 @@ describe('', () => { }) it('should not continue to change focus on subsequent updates', async () => { - const { rerender } = render( + const { rerender } = await render( {buildPages(6)} ) - const prevButton = screen.queryByRole('button', { name: 'Previous' }) + const prevButton = page.getByRole('button', { name: 'Previous' }).query() expect(prevButton).not.toBeInTheDocument() - const nextButton = screen.queryByRole('button', { name: 'Next' }) + const nextButton = page.getByRole('button', { name: 'Next' }).query() expect(nextButton).toBeInTheDocument() // Set children: buildPages(6, 5) - rerender( + await rerender( {buildPages(6, 5)} ) - const prevButtonUpdated = screen.queryByRole('button', { - name: 'Previous' - }) + const prevButtonUpdated = page + .getByRole('button', { + name: 'Previous' + }) + .query() expect(prevButtonUpdated).toBeInTheDocument() - const nextButtonUpdated = screen.queryByRole('button', { name: 'Next' }) + const nextButtonUpdated = page + .getByRole('button', { name: 'Next' }) + .query() expect(nextButtonUpdated).not.toBeInTheDocument() }) @@ -764,7 +806,7 @@ describe('', () => { ) const props = { [prop]: 'foo' } - render( + await render( ', () => { {buildPages(6)} ) - await waitFor(() => { + await vi.waitFor(() => { expect(consoleErrorMock.mock.calls[0][0]).toMatch( expectedErrorMessageRegExp ) @@ -784,7 +826,7 @@ describe('', () => { it(`should allow the '${prop}' prop`, async () => { const props = { [prop]: allowedProps[prop] } - render( + await render( ', () => { {buildPages(6)} ) - await waitFor(() => { + await vi.waitFor(() => { expect(consoleErrorMock).not.toHaveBeenCalled() }) }) @@ -805,7 +847,7 @@ describe('', () => { it(`should pass down the elementRef prop`, async () => { const elementRef = vi.fn() - const { container } = render( + const { container } = await render( ', () => { it('should navigate to adjacent pages', async () => { const onClick = vi.fn() - render( + await render( {[ ...buildPages(6, 5), @@ -831,11 +873,11 @@ describe('', () => { ]} ) - const nextButton = screen.getByRole('button', { name: 'Next' }) + const nextButton = page.getByRole('button', { name: 'Next' }).element() await userEvent.click(nextButton) - await waitFor(() => { + await vi.waitFor(() => { expect(onClick).toHaveBeenCalled() }) }) @@ -843,7 +885,7 @@ describe('', () => { describe('input variant', () => { it('should display number input', async () => { - const { container } = render( + const { container } = await render( ', () => { }) it('should display all arrow buttons', async () => { - render( + await render( ', () => { ) - const firstButton = screen.getByRole('button', { name: 'First' }) - const prevButton = screen.getByRole('button', { name: 'Prev' }) - const nextButton = screen.getByRole('button', { name: 'Next' }) - const lastButton = screen.getByRole('button', { name: 'Last' }) + const firstButton = page.getByRole('button', { name: 'First' }).element() + const prevButton = page.getByRole('button', { name: 'Prev' }).element() + const nextButton = page.getByRole('button', { name: 'Next' }).element() + const lastButton = page.getByRole('button', { name: 'Last' }).element() expect(firstButton).toBeVisible() expect(prevButton).toBeVisible() @@ -884,7 +926,7 @@ describe('', () => { }) it('should pass label', async () => { - const { container } = render( + const { container } = await render( ', () => { }) it('should pass ScreenReaderLabel', async () => { - const { container } = render( + const { container } = await render( ', () => { const onClick1 = vi.fn() const onClick2 = vi.fn() - const { container } = render( + const { container } = await render( ', () => { await userEvent.type(numberInput!, '2{enter}') - await waitFor(() => { + await vi.waitFor(() => { expect(onClick2).toHaveBeenCalled() }) }) it('should update page number when currentPage changes', async () => { - const { container, rerender } = render( + const { container, rerender } = await render( ', () => { expect(numberInput).toHaveValue(4) - rerender( + await rerender( ', () => { }) it('should disable the input when disabled', async () => { - const { container } = render( + const { container } = await render( ', () => { }) describe('with minimal config', () => { - it('should render the correct pages - 1', () => { - const { container } = render( + it('should render the correct pages - 1', async () => { + const { container } = await render( ', () => { ) expect(container.firstChild).toHaveTextContent('12…9Next Page') }) - it('should render the correct pages - 2', () => { - const { container } = render( + it('should render the correct pages - 2', async () => { + const { container } = await render( ', () => { 'Previous Page1…456…9Next Page' ) }) - it('should render the correct pages - 3', () => { - const { container } = render( + it('should render the correct pages - 3', async () => { + const { container } = await render( ', () => { 'Previous Page123456789Next Page' ) }) - it('should render the correct pages - 4', () => { - const { container } = render( + it('should render the correct pages - 4', async () => { + const { container } = await render( ', () => { 'Previous Page12…456…89Next Page' ) }) - it('should render the correct pages - 5', () => { - const { container } = render( + it('should render the correct pages - 5', async () => { + const { container } = await render( ', () => { 'Previous Page123456789Next Page' ) }) - it('should render the correct pages - 6', () => { - const { container } = render( + it('should render the correct pages - 6', async () => { + const { container } = await render( ', () => { 'Previous Page123456789Next Page' ) }) - it('should render the correct pages - 7', () => { - const { container } = render( + it('should render the correct pages - 7', async () => { + const { container } = await render( ', () => { ) expect(container.firstChild).toHaveTextContent('123…789Next Page') }) - it('should render the correct ellipsis', () => { - const { container } = render( + it('should render the correct ellipsis', async () => { + const { container } = await render( ', () => { ) expect(container.firstChild).toHaveTextContent('123<->789Next Page') }) - it('should render custom buttons', () => { + it('should render custom buttons', async () => { const pageMap = ['A-G', 'H-J', 'K-M', 'N-Q', 'R-Z'] - const { container } = render( + const { container } = await render( ', () => { ) expect(container.firstChild).toHaveTextContent('A-GH-JK-MN-QR-Z') }) - it('should render huge "totalPageNumber"s properly', () => { - const { container } = render( + it('should render huge "totalPageNumber"s properly', async () => { + const { container } = await render( ', () => { 'Previous Page1…567756785679…1000000000000000Next Page' ) }) - it('should render first and last buttons', () => { - const { container } = render( + it('should render first and last buttons', async () => { + const { container } = await render( ', () => { 'First PagePrevious Page1…456…100Next PageLast Page' ) }) - it('should render every page if boundary and sibling counts are big enough', () => { - const { container } = render( + it('should render every page if boundary and sibling counts are big enough', async () => { + const { container } = await render( ', () => { }) it('should add aria-label when screenReaderLabelPageButton is set', async () => { - render( + await render( ', () => { } /> ) - const paginationButtons = screen.getAllByRole('button', { name: /\d$/ }) + const paginationButtons = page + .getByRole('button', { name: /\d$/ }) + .elements() for (let i: number = 0; i < paginationButtons.length; i++) { expect(paginationButtons[i]).toHaveAttribute( diff --git a/packages/ui-pagination/src/Pagination/__tests__/PaginationArrowButton.test.tsx b/packages/ui-pagination/src/Pagination/__tests__/PaginationArrowButton.test.tsx index 140e7c7bf6..924bcbe430 100644 --- a/packages/ui-pagination/src/Pagination/__tests__/PaginationArrowButton.test.tsx +++ b/packages/ui-pagination/src/Pagination/__tests__/PaginationArrowButton.test.tsx @@ -22,17 +22,16 @@ * SOFTWARE. */ -import { render, screen } from '@testing-library/react' -import { vi } from 'vitest' - -import '@testing-library/jest-dom' +import { render } from 'vitest-browser-react' +import { page } from 'vitest/browser' +import { describe, it, expect, vi } from 'vitest' import { PaginationArrowButton } from '../v2/PaginationArrowButton/index.js' describe('', () => { it('should render', async () => { - render() + await render() - const button = screen.getByRole('button', { name: 'Label' }) + const button = page.getByRole('button', { name: 'Label' }).element() expect(button).toBeInTheDocument() }) @@ -40,14 +39,14 @@ describe('', () => { it('should provide a ref to the button element', async () => { const buttonRef = vi.fn() - render( + await render( ) - const button = screen.getByRole('button', { name: 'Label' }) + const button = page.getByRole('button', { name: 'Label' }).element() expect(buttonRef).toHaveBeenCalledWith(button) }) diff --git a/packages/ui-pagination/src/Pagination/__tests__/PaginationButton.test.tsx b/packages/ui-pagination/src/Pagination/__tests__/PaginationButton.test.tsx index c5d2fb926d..a581c63bea 100644 --- a/packages/ui-pagination/src/Pagination/__tests__/PaginationButton.test.tsx +++ b/packages/ui-pagination/src/Pagination/__tests__/PaginationButton.test.tsx @@ -22,54 +22,53 @@ * SOFTWARE. */ -import { render, screen, waitFor } from '@testing-library/react' -import { vi } from 'vitest' - -import '@testing-library/jest-dom' +import { render } from 'vitest-browser-react' +import { page } from 'vitest/browser' +import { describe, it, expect, vi } from 'vitest' import { PaginationButton } from '@instructure/ui-pagination/latest' describe('', () => { it('should designate current page', async () => { - render(1) - const button = screen.getByRole('button', { name: '1' }) + await render(1) + const button = page.getByRole('button', { name: '1' }).element() expect(button).toHaveAttribute('aria-current', 'page') }) it('should navigate using button when onClick provided', async () => { const onClick = vi.fn() - render(1) + await render(1) - const button = screen.getByRole('button', { name: '1' }) + const button = page.getByRole('button', { name: '1' }).element() button.click() - await waitFor(() => { + await vi.waitFor(() => { expect(onClick).toHaveBeenCalled() }) }) it('should disable navigation to current page', async () => { const onClick = vi.fn() - render( + await render( 1 ) - const button = screen.getByRole('button', { name: '1' }) + const button = page.getByRole('button', { name: '1' }).element() button.click() - await waitFor(() => { + await vi.waitFor(() => { expect(onClick).not.toHaveBeenCalled() }) }) it('should navigate using link when href provided', async () => { - render( + await render( 1 ) - const button = screen.getByRole('link') + const button = page.getByRole('link').element() expect(button).toHaveAttribute('href', 'https://instructure.design/') }) diff --git a/packages/ui-pagination/src/Pagination/__tests__/PaginationPageInput.test.tsx b/packages/ui-pagination/src/Pagination/__tests__/PaginationPageInput.test.tsx index edbd48731d..f4eead7ec3 100644 --- a/packages/ui-pagination/src/Pagination/__tests__/PaginationPageInput.test.tsx +++ b/packages/ui-pagination/src/Pagination/__tests__/PaginationPageInput.test.tsx @@ -22,10 +22,9 @@ * SOFTWARE. */ -import { render, screen } from '@testing-library/react' -import { vi } from 'vitest' - -import '@testing-library/jest-dom' +import { render } from 'vitest-browser-react' +import { page } from 'vitest/browser' +import { describe, it, expect, vi } from 'vitest' import { PaginationPageInput } from '../v2/PaginationPageInput/index.js' const defaultSRLabel = (currentPage: number, numberOfPages: number) => @@ -34,7 +33,7 @@ const defaultSRLabel = (currentPage: number, numberOfPages: number) => describe('', () => { it('should render', async () => { const defaultOnChange = vi.fn() - render( + await render( ', () => { screenReaderLabel={defaultSRLabel} /> ) - const input = screen.getByRole('spinbutton') + const input = page.getByRole('spinbutton').element() expect(input).toBeInTheDocument() expect(input.tagName).toBe('INPUT') @@ -50,7 +49,7 @@ describe('', () => { it('should display the current page number', async () => { const defaultOnChange = vi.fn() - render( + await render( ', () => { screenReaderLabel={defaultSRLabel} /> ) - const input = screen.getByRole('spinbutton') + const input = page.getByRole('spinbutton').element() expect(input).toHaveAttribute('value', '4') }) it('should correctly update page number', async () => { const defaultOnChange = vi.fn() - const { rerender } = render( + const { rerender } = await render( ', () => { screenReaderLabel={defaultSRLabel} /> ) - const input = screen.getByRole('spinbutton') + const input = page.getByRole('spinbutton').element() expect(input).toHaveAttribute('value', '4') // Set currentPageIndex: 6 - rerender( + await rerender( ', () => { it("shouldn't display the arrow keys of NumberInput", async () => { const defaultOnChange = vi.fn() - const { container } = render( + const { container } = await render( ', () => { screenReaderLabel={defaultSRLabel} /> ) - const arrowButtons = screen.queryAllByRole('button') + const arrowButtons = page.getByRole('button').elements() expect(arrowButtons.length).toBe(0) const arrowKeys = container.querySelectorAll('svg') @@ -108,7 +107,7 @@ describe('', () => { it("should disable the input on 'disabled'", async () => { const defaultOnChange = vi.fn() - render( + await render( ', () => { disabled /> ) - const input = screen.getByRole('spinbutton') + const input = page.getByRole('spinbutton').element() expect(input).toHaveAttribute('disabled') }) it('should set the ScreenReaderLabel for the input', async () => { const defaultOnChange = vi.fn() - const { container } = render( + const { container } = await render( ', () => { it('should display the number of pages in the label', async () => { const defaultOnChange = vi.fn() - const { container } = render( + const { container } = await render( ', () => { it('should render', async () => { - const { container } = render(Overdue) + const { container } = await render(Overdue) const pill = container.querySelector('div[class$="-pill"]') expect(pill).toBeInTheDocument() @@ -39,20 +39,22 @@ describe('', () => { }) it('should display text', async () => { - const { container } = render(Overdue) + const { container } = await render(Overdue) expect(container).toHaveTextContent('Overdue') }) it('should display status text', async () => { - const { container } = render(Overdue) + const { container } = await render( + Overdue + ) expect(container).toHaveTextContent('Statuslabel:') expect(container).toHaveTextContent('Overdue') }) it('should render icon text', async () => { - const { container } = render( + const { container } = await render( } @@ -69,7 +71,7 @@ describe('', () => { }) it('should be accessible', async () => { - const { container } = render(Overdue) + const { container } = await render(Overdue) const axeCheck = await runAxeCheck(container) expect(axeCheck).toBe(true) diff --git a/packages/ui-popover/src/Popover/__tests__/Popover.test.tsx b/packages/ui-popover/src/Popover/__tests__/Popover.test.tsx index 5920d23be8..27e7370789 100644 --- a/packages/ui-popover/src/Popover/__tests__/Popover.test.tsx +++ b/packages/ui-popover/src/Popover/__tests__/Popover.test.tsx @@ -22,9 +22,10 @@ * SOFTWARE. */ -import { vi } from 'vitest' -import { fireEvent, render, screen, cleanup } from '@testing-library/react' -import '@testing-library/jest-dom' +import { fireEvent } from '@testing-library/dom' +import { render, cleanup } from 'vitest-browser-react' +import { page } from 'vitest/browser' +import { describe, it, expect, afterEach, vi } from 'vitest' import { Popover } from '@instructure/ui-popover/latest' import type { PopoverProps } from '@instructure/ui-popover/latest' @@ -39,18 +40,18 @@ describe('', () => { eventType: 'click' | 'focus' | 'mouseOver', eventInit?: Record ) { - it(`should show content on ${on}`, () => { + it(`should show content on ${on}`, async () => { const onValue: PopoverProps['on'] = [on] if (on === 'hover') { onValue.push('focus') } - render( + await render( Trigger}>

Popover Content

) - const trigger = screen.getByRole('button', { name: 'Trigger' }) + const trigger = page.getByRole('button', { name: 'Trigger' }).element() switch (eventType) { case 'click': @@ -66,7 +67,7 @@ describe('', () => { break } - expect(screen.getByText('Popover Content')).toBeInTheDocument() + expect(page.getByText('Popover Content').element()).toBeInTheDocument() }) } @@ -74,18 +75,18 @@ describe('', () => { handler: 'onClick' | 'onFocus' | 'onBlur', eventType: 'focusOut' | 'blur' | 'click' | 'focus' ) { - it(`should fire ${handler} handler for ${eventType} event`, () => { + it(`should fire ${handler} handler for ${eventType} event`, async () => { const handlerSpy = vi.fn() const props = { [handler]: handlerSpy } - render( + await render( Trigger}>

Popover content

) - const trigger = screen.getByRole('button', { name: 'Trigger' }) + const trigger = page.getByRole('button', { name: 'Trigger' }).element() switch (eventType) { case 'click': @@ -108,16 +109,18 @@ describe('', () => { }) } - it('should not render content by default', () => { - render( + it('should not render content by default', async () => { + await render(
Trigger button}>

Popover Title

) - const triggerButton = screen.getByRole('button', { name: 'Trigger button' }) - const popoverContent = screen.queryByText('Popover Title') + const triggerButton = page + .getByRole('button', { name: 'Trigger button' }) + .element() + const popoverContent = page.getByText('Popover Title').query() expect(triggerButton).toBeInTheDocument() expect(popoverContent).not.toBeInTheDocument() @@ -136,9 +139,9 @@ describe('', () => { testEventHandler('onBlur', 'focusOut') }) - it('should hide content when trigger is clicked', () => { + it('should hide content when trigger is clicked', async () => { const onHideContent = vi.fn() - render( + await render( onHideContent(o)} @@ -148,15 +151,17 @@ describe('', () => {

Popover Title

) - const triggerButton = screen.getByRole('button', { name: 'Trigger button' }) + const triggerButton = page + .getByRole('button', { name: 'Trigger button' }) + .element() expect(triggerButton).toBeInTheDocument() - expect(screen.queryByText('Popover Title')).not.toBeInTheDocument() + expect(page.getByText('Popover Title').query()).not.toBeInTheDocument() fireEvent.click(triggerButton) expect(onHideContent).not.toHaveBeenCalled() - expect(screen.queryByText('Popover Title')).toBeInTheDocument() + expect(page.getByText('Popover Title').query()).toBeInTheDocument() fireEvent.click(triggerButton) @@ -164,11 +169,11 @@ describe('', () => { expect(onHideContent).toHaveBeenCalledWith( expect.objectContaining({ documentClick: false }) ) - expect(screen.queryByText('Popover Title')).not.toBeInTheDocument() + expect(page.getByText('Popover Title').query()).not.toBeInTheDocument() }) - it('should show content if defaultIsShowingContent is true', () => { - render( + it('should show content if defaultIsShowingContent is true', async () => { + await render( ', () => {

Popover content

) - const popoverContent = screen.queryByText('Popover content') + const popoverContent = page.getByText('Popover content').query() expect(popoverContent).toBeInTheDocument() }) describe('controlled', () => { - it('should show content by default if isShowingContent is true', () => { - render( + it('should show content by default if isShowingContent is true', async () => { + await render( ', () => {

Popover content

) - const popoverContent = screen.queryByText('Popover content') + const popoverContent = page.getByText('Popover content').query() expect(popoverContent).toBeInTheDocument() }) - it('should not show content if isShowingContent prop is false', () => { - render( + it('should not show content if isShowingContent prop is false', async () => { + await render( ', () => {

Popover content

) - const triggerButton = screen.getByRole('button', { name: 'Trigger' }) - const popoverContent = screen.queryByText('Popover content') + const triggerButton = page + .getByRole('button', { name: 'Trigger' }) + .element() + const popoverContent = page.getByText('Popover content').query() expect(triggerButton).toBeInTheDocument() expect(popoverContent).not.toBeInTheDocument() }) - it('should show content if isShowingContent prop is true', () => { - render( + it('should show content if isShowingContent prop is true', async () => { + await render( ', () => {

Popover content

) - const popoverContent = screen.queryByText('Popover content') + const popoverContent = page.getByText('Popover content').query() expect(popoverContent).toBeInTheDocument() }) - it('should call onShowContent', () => { + it('should call onShowContent', async () => { const onShowContent = vi.fn() - render( + await render( ', () => {

Popover content

) - const trigger = screen.getByRole('button', { name: 'Trigger' }) + const trigger = page.getByRole('button', { name: 'Trigger' }).element() fireEvent.click(trigger) expect(onShowContent).toHaveBeenCalledTimes(1) }) - it('should call onHideContent', () => { + it('should call onHideContent', async () => { const onHideContent = vi.fn() - render( + await render( ', () => {

Popover content

) - const trigger = screen.getByRole('button', { name: 'Trigger' }) + const trigger = page.getByRole('button', { name: 'Trigger' }).element() fireEvent.click(trigger) expect(onHideContent).toHaveBeenCalledWith({ documentClick: false }) }) - it('should not show content on click', () => { - render( + it('should not show content on click', async () => { + await render( ', () => {

Popover content

) - const triggerButton = screen.getByRole('button', { name: 'Trigger' }) + const triggerButton = page + .getByRole('button', { name: 'Trigger' }) + .element() fireEvent.click(triggerButton) - const popoverContent = screen.queryByText('Popover content') + const popoverContent = page.getByText('Popover content').query() expect(popoverContent).not.toBeInTheDocument() }) }) - it('should pass positionContainerDisplay prop to Position', () => { - render( + it('should pass positionContainerDisplay prop to Position', async () => { + await render( Trigger} @@ -309,7 +318,7 @@ describe('', () => { describe('shouldScrollContent', () => { it('does not wrap content when the prop is unset', async () => { - render( + await render( ', () => {

Popover content

) - const content = await screen.findByTestId('content') + const content = await page.getByTestId('content').element() expect(content.closest('[class*="popover__scrollContainer"]')).toBeNull() }) it('wraps content in an overflow:auto + auto-fit max-height container when set', async () => { - render( + await render( ', () => {

Popover content

) - const content = await screen.findByTestId('content') + const content = await page.getByTestId('content').element() const wrapper = content.closest( '[class*="popover__scrollContainer"]' ) as HTMLElement diff --git a/packages/ui-portal/src/Portal/__tests__/Portal.test.tsx b/packages/ui-portal/src/Portal/__tests__/Portal.test.tsx index 9c3c0f12af..ec65422682 100644 --- a/packages/ui-portal/src/Portal/__tests__/Portal.test.tsx +++ b/packages/ui-portal/src/Portal/__tests__/Portal.test.tsx @@ -22,24 +22,23 @@ * SOFTWARE. */ -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 { render } from 'vitest-browser-react' +import { page, userEvent } from 'vitest/browser' +import { describe, it, expect, vi } from 'vitest' import { runAxeCheck } from '@instructure/ui-axe-check' import { Portal } from '../index.js' describe(``, () => { it('should render', async () => { - render(Hello World) - const portal = screen.getByText('Hello World') + await render(Hello World) + const portal = page.getByText('Hello World').element() expect(portal).toBeInTheDocument() }) it('should be accessible', async () => { - const { container } = render( + const { container } = await render( Hello World @@ -51,19 +50,19 @@ describe(``, () => { it('should support onOpen prop', async () => { const onOpen = vi.fn() - render( + await render( Hello World ) - const portal = screen.getByTestId('portal') + const portal = page.getByTestId('portal').element() expect(onOpen).toHaveBeenCalledWith(portal) }) it('should support onClose prop', async () => { const onClose = vi.fn() - const { rerender } = render( + const { rerender } = await render( Hello World @@ -71,7 +70,7 @@ describe(``, () => { expect(onClose).not.toHaveBeenCalled() - rerender( + await rerender( Hello World @@ -82,44 +81,44 @@ describe(``, () => { it('should add a dir attribute to the root DOM node', async () => { const onOpen = vi.fn() - render( + await render( Hello World ) - const portal = screen.getByTestId('portal') + const portal = page.getByTestId('portal').element() expect(portal).toHaveAttribute('dir', 'ltr') }) it('should not render if children are empty', async () => { - render() - const portal = screen.queryByTestId('portal') + await render() + const portal = page.getByTestId('portal').query() expect(portal).not.toBeInTheDocument() }) describe('without a mountNode prop', () => { it('should render nothing when closed', async () => { - render(Hello World) - const portal = screen.queryByTestId('portal') + await render(Hello World) + const portal = page.getByTestId('portal').query() expect(portal).not.toBeInTheDocument() }) it('should render children and have a node with a parent when open', async () => { const onKeyDown = vi.fn() - render( + await render( ) - const portal = screen.getByTestId('portal') - const button = screen.getByRole('button', { name: 'Hello World' }) + const portal = page.getByTestId('portal').element() + const button = page.getByRole('button', { name: 'Hello World' }).element() await userEvent.type(button, '{enter}') - await waitFor(() => { + await vi.waitFor(() => { expect(onKeyDown).toHaveBeenCalled() }) @@ -129,7 +128,7 @@ describe(``, () => { describe('when a mountNode prop is provided', () => { it('should render nothing when closed', async () => { - render( + await render(
document.getElementById('portal-mount-node')!} @@ -140,7 +139,7 @@ describe(``, () => {
) - const portal = screen.queryByTestId('portal') + const portal = page.getByTestId('portal').query() expect(portal).not.toBeInTheDocument() }) @@ -150,12 +149,12 @@ describe(``, () => { mountNode.setAttribute('id', 'portal-mount-node') document.body.appendChild(mountNode) - render( + await render( Hello World ) - const portal = screen.getByTestId('portal') + const portal = page.getByTestId('portal').element() expect(portal.parentElement).toBe(mountNode) expect(mountNode.parentElement).toBe(document.body) diff --git a/packages/ui-position/src/Position/__tests__/Position.test.tsx b/packages/ui-position/src/Position/__tests__/Position.test.tsx index 26b77fe48a..356a9a8ccd 100644 --- a/packages/ui-position/src/Position/__tests__/Position.test.tsx +++ b/packages/ui-position/src/Position/__tests__/Position.test.tsx @@ -22,9 +22,9 @@ * SOFTWARE. */ -import { render, screen, waitFor } from '@testing-library/react' -import { vi } from 'vitest' -import '@testing-library/jest-dom' +import { render } from 'vitest-browser-react' +import { page } from 'vitest/browser' +import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest' import { within } from '@instructure/ui-utils' import { Position } from '../index.js' @@ -37,8 +37,8 @@ describe('', () => { overflow: 'auto' } - it('should render', () => { - render( + it('should render', async () => { + await render(
', () => {
) - const target = screen.getByTestId('target-btn') - const content = screen.getByTestId('content') + const target = page.getByTestId('target-btn').element() + const content = page.getByTestId('content').element() expect(target).toBeInTheDocument() expect(target).toHaveTextContent('Target') @@ -62,8 +62,8 @@ describe('', () => { expect(content).toHaveTextContent('Content') }) - it('should absolutely position content', () => { - render( + it('should absolutely position content', async () => { + await render(
', () => {
) - const content = screen.getByTestId('content') + const content = page.getByTestId('content').element() const style = window.getComputedStyle(content) expect(style.position).toBe('absolute') @@ -86,7 +86,7 @@ describe('', () => { it('should render right of target', async () => { const onPositionChanged = vi.fn() - render( + await render(
', () => {
) - const target = screen.getByTestId('target') - const content = screen.getByTestId('content') + const target = page.getByTestId('target').element() + const content = page.getByTestId('content').element() - await waitFor(() => { + await vi.waitFor(() => { expect(onPositionChanged).toHaveBeenCalled() }) @@ -119,7 +119,7 @@ describe('', () => { it('should render below target', async () => { const onPositionChanged = vi.fn() - render( + await render(
', () => {
) - const target = screen.getByTestId('target') - const content = screen.getByTestId('content') + const target = page.getByTestId('target').element() + const content = page.getByTestId('content').element() - await waitFor(() => { + await vi.waitFor(() => { expect(onPositionChanged).toHaveBeenCalled() }) @@ -152,7 +152,7 @@ describe('', () => { it('should render left of target', async () => { const onPositionChanged = vi.fn() - render( + await render(
', () => {
) - const target = screen.getByTestId('target') - const content = screen.getByTestId('content') + const target = page.getByTestId('target').element() + const content = page.getByTestId('content').element() - await waitFor(() => { + await vi.waitFor(() => { expect(onPositionChanged).toHaveBeenCalled() }) @@ -185,7 +185,7 @@ describe('', () => { it('should render above target', async () => { const onPositionChanged = vi.fn() - render( + await render(
', () => {
) - const target = screen.getByTestId('target') - const content = screen.getByTestId('content') + const target = page.getByTestId('target').element() + const content = page.getByTestId('content').element() - await waitFor(() => { + await vi.waitFor(() => { expect(onPositionChanged).toHaveBeenCalled() }) @@ -216,7 +216,7 @@ describe('', () => { it('should center vertically', async () => { const onPositionChanged = vi.fn() - render( + await render(
', () => {
) - const target = screen.getByTestId('target') - const content = screen.getByTestId('content') + const target = page.getByTestId('target').element() + const content = page.getByTestId('content').element() - await waitFor(() => { + await vi.waitFor(() => { expect(onPositionChanged).toHaveBeenCalled() }) @@ -252,7 +252,7 @@ describe('', () => { it('should center horizontally', async () => { const onPositionChanged = vi.fn() - render( + await render(
', () => {
) - const target = screen.getByTestId('target') - const content = screen.getByTestId('content') + const target = page.getByTestId('target').element() + const content = page.getByTestId('content').element() - await waitFor(() => { + await vi.waitFor(() => { expect(onPositionChanged).toHaveBeenCalled() }) @@ -290,7 +290,7 @@ describe('', () => { it('should re-position below target', async () => { const onPositionChanged = vi.fn() - render( + await render(
mount
', () => {
) - const target = screen.getByTestId('target') - const content = screen.getByTestId('content') + const target = page.getByTestId('target').element() + const content = page.getByTestId('content').element() - await waitFor(() => { + await vi.waitFor(() => { expect(onPositionChanged).toHaveBeenCalled() }) @@ -334,7 +334,7 @@ describe('', () => { it('should re-position above target', async () => { const onPositionChanged = vi.fn() - render( + await render(
mount
', () => {
) - const target = screen.getByTestId('target') - const content = screen.getByTestId('content') + const target = page.getByTestId('target').element() + const content = page.getByTestId('content').element() - await waitFor(() => { + await vi.waitFor(() => { expect(onPositionChanged).toHaveBeenCalled() }) @@ -378,7 +378,7 @@ describe('', () => { it('should re-position after target', async () => { const onPositionChanged = vi.fn() - render( + await render(
mount
', () => {
) - const target = screen.getByTestId('target') - const content = screen.getByTestId('content') + const target = page.getByTestId('target').element() + const content = page.getByTestId('content').element() - await waitFor(() => { + await vi.waitFor(() => { expect(onPositionChanged).toHaveBeenCalled() }) @@ -422,7 +422,7 @@ describe('', () => { it('should re-position before target', async () => { const onPositionChanged = vi.fn() - render( + await render(
mount
', () => {
) - const target = screen.getByTestId('target') - const content = screen.getByTestId('content') + const target = page.getByTestId('target').element() + const content = page.getByTestId('content').element() - await waitFor(() => { + await vi.waitFor(() => { expect(onPositionChanged).toHaveBeenCalled() }) @@ -476,7 +476,7 @@ describe('', () => { }) it('should position correctly', async () => { - render( + await render(
', () => {
) - const target = screen.getByTestId('target') - const content = screen.getByTestId('content') + const target = page.getByTestId('target').element() + const content = page.getByTestId('content').element() - await waitFor(() => { + await vi.waitFor(() => { expect(content.getBoundingClientRect().top).toEqual( target.getBoundingClientRect().bottom ) @@ -500,7 +500,7 @@ describe('', () => { }) it('should position correctly with mountNode', async () => { - render( + await render(
mount
', () => {
) - const target = screen.getByTestId('target') - const content = screen.getByTestId('content') + const target = page.getByTestId('target').element() + const content = page.getByTestId('content').element() - await waitFor(() => { + await vi.waitFor(() => { expect(content.getBoundingClientRect().top).toEqual( target.getBoundingClientRect().bottom ) @@ -537,8 +537,8 @@ describe('', () => { }) describe('containerDisplay prop', () => { - it('should apply "inline-block"', () => { - const { container } = render( + it('should apply "inline-block"', async () => { + const { container } = await render(
', () => { expect(style.display).toEqual('inline-block') }) - it('should apply "block"', () => { - const { container } = render( + it('should apply "block"', async () => { + const { container } = await render(
', () => { }) it('writes --ui-position-available-{height,width} on the content node', async () => { - render( + await render( ', () => {
Content
) - const content = screen.getByTestId('content') - await waitFor(() => { + const content = page.getByTestId('content').element() + await vi.waitFor(() => { expect( content.style.getPropertyValue('--ui-position-available-height') ).not.toBe('') diff --git a/packages/ui-position/src/__tests__/mirrorHorizontalPlacement.test.tsx b/packages/ui-position/src/__tests__/mirrorHorizontalPlacement.test.tsx index a5f4aff9de..de81418407 100644 --- a/packages/ui-position/src/__tests__/mirrorHorizontalPlacement.test.tsx +++ b/packages/ui-position/src/__tests__/mirrorHorizontalPlacement.test.tsx @@ -28,7 +28,7 @@ import { placementPropValues, PlacementValueArray } from '../PositionPropTypes.js' -import '@testing-library/jest-dom' +import { describe, it, expect } from 'vitest' const mirrorHorizontallyAsArrayMap = [ ['top'], diff --git a/packages/ui-position/src/__tests__/mirrorPlacement.test.tsx b/packages/ui-position/src/__tests__/mirrorPlacement.test.tsx index 39e1389785..b3fb4d0820 100644 --- a/packages/ui-position/src/__tests__/mirrorPlacement.test.tsx +++ b/packages/ui-position/src/__tests__/mirrorPlacement.test.tsx @@ -28,7 +28,7 @@ import { placementPropValues, PlacementValueArray } from '../PositionPropTypes.js' -import '@testing-library/jest-dom' +import { describe, it, expect } from 'vitest' const mirrorVertiallyAsArrayMap = [ ['bottom'], diff --git a/packages/ui-progress/src/ProgressBar/__tests__/ProgressBar.test.tsx b/packages/ui-progress/src/ProgressBar/__tests__/ProgressBar.test.tsx index 8fd3a1ced4..c457e6ecec 100644 --- a/packages/ui-progress/src/ProgressBar/__tests__/ProgressBar.test.tsx +++ b/packages/ui-progress/src/ProgressBar/__tests__/ProgressBar.test.tsx @@ -22,15 +22,14 @@ * SOFTWARE. */ -import { render } from '@testing-library/react' - -import '@testing-library/jest-dom' +import { render } from 'vitest-browser-react' +import { describe, it, expect } from 'vitest' import { runAxeCheck } from '@instructure/ui-axe-check' import { ProgressBar } from '@instructure/ui-progress/latest' describe('', () => { it('should render', async () => { - const { container } = render( + const { container } = await render( ', () => { }) it('should render a progress element with correct aria attributes', async () => { - const { container } = render( + const { container } = await render( ', () => { }) it('should render a progress element with an aria-label attribute', async () => { - const { container } = render( + const { container } = await render( ', () => { it('should format the displayed text', async () => { const current = 30 const max = 60 - const { container } = render( + const { container } = await render( ', () => { }) it('should meet a11y standards', async () => { - const { container } = render( + const { container } = await render( ', () => { expect(axeCheck).toBe(true) }) - it('should not render the value inside when the prop is set to false', () => { + it('should not render the value inside when the prop is set to false', async () => { const valueNow = 33 - const { container } = render( + const { container } = await render( ', () => { expect(progressMeter).not.toHaveTextContent('33%') }) - it('should render the value inside when the prop is set', () => { + it('should render the value inside when the prop is set', async () => { const valueNow = 33 - const { container } = render( + const { container } = await render( ', () => { it('should render', async () => { - const { container } = render( + const { container } = await render( ', () => { }) it('should render a progress element with correct aria attributes', async () => { - const { container } = render( + const { container } = await render( ', () => { it('should format the displayed text', async () => { const current = 30 const max = 60 - const { container } = render( + const { container } = await render( ', () => { }) it('should meet a11y standards', async () => { - const { container } = render( + const { container } = await render( ', () => { }) it('renders an input with type "radio"', async () => { - const { container } = render( + const { container } = await render( ) @@ -66,7 +66,7 @@ describe('', () => { it('should provide an inputRef prop', async () => { const inputRef = vi.fn() - const { container } = render( + const { container } = await render( ', () => { it('responds to onClick event', async () => { const onClick = vi.fn() - const { container } = render( + const { container } = await render( ', () => { await userEvent.click(input!) - await waitFor(() => { + await vi.waitFor(() => { expect(onClick).toHaveBeenCalled() }) }) @@ -104,7 +104,7 @@ describe('', () => { it('does not respond to onClick event when disabled', async () => { const onClick = vi.fn() - const { container } = render( + const { container } = await render( ', () => { fireEvent.click(input!) - await waitFor(() => { + await vi.waitFor(() => { expect(onClick).not.toHaveBeenCalled() expect(input).toBeDisabled() }) @@ -127,7 +127,7 @@ describe('', () => { it('does not respond to onClick event when readOnly', async () => { const onClick = vi.fn() - const { container } = render( + const { container } = await render( ', () => { fireEvent.click(input!) - await waitFor(() => { + await vi.waitFor(() => { expect(onClick).not.toHaveBeenCalled() expect(input).not.toBeDisabled() expect(input).toHaveAttribute('readonly') @@ -151,7 +151,7 @@ describe('', () => { it('responds to onChange event', async () => { const onChange = vi.fn() - const { container } = render( + const { container } = await render( ', () => { await userEvent.click(input!) - await waitFor(() => { + await vi.waitFor(() => { expect(onChange).toHaveBeenCalled() }) }) @@ -172,7 +172,7 @@ describe('', () => { it('does not respond to onChange event when disabled', async () => { const onChange = vi.fn() - const { container } = render( + const { container } = await render( ', () => { fireEvent.click(input!) - await waitFor(() => { + await vi.waitFor(() => { expect(onChange).not.toHaveBeenCalled() }) }) @@ -194,7 +194,7 @@ describe('', () => { it('does not respond to onChange event when readOnly', async () => { const onChange = vi.fn() - const { container } = render( + const { container } = await render( ', () => { fireEvent.click(input!) - await waitFor(() => { + await vi.waitFor(() => { expect(onChange).not.toHaveBeenCalled() }) }) @@ -216,7 +216,7 @@ describe('', () => { it('responds to onBlur event', async () => { const onBlur = vi.fn() - const { container } = render( + const { container } = await render( ', () => { fireEvent.focusOut(input!) - await waitFor(() => { + await vi.waitFor(() => { expect(onBlur).toHaveBeenCalled() }) }) @@ -237,7 +237,7 @@ describe('', () => { it('responds to onFocus event', async () => { const onFocus = vi.fn() - const { container } = render( + const { container } = await render( ', () => { fireEvent.focus(input!) - await waitFor(() => { + await vi.waitFor(() => { expect(onFocus).toHaveBeenCalled() }) }) it('sets input to checked when selected', async () => { - const { container } = render( + const { container } = await render( ', () => { it('focuses with the focus helper', async () => { let ref: RadioInputHandle - const { container } = render( + const { container } = await render( ', () => { ref!.focus() - await waitFor(() => { + await vi.waitFor(() => { expect(document.activeElement).toBe(input) }) }) @@ -292,7 +292,7 @@ describe('', () => { describe('for a11y', () => { it('simple variant should meet a11y standards', async () => { - const { container } = render( + const { container } = await render( ', () => { }) it('adds the name props to all RadioInput types', async () => { - const { container } = render( + const { container } = await render( @@ -66,7 +66,7 @@ describe('', () => { it('calls the onChange prop', async () => { const onChange = vi.fn() - const { container } = render( + const { container } = await render( ', () => { await userEvent.click(input!) - await waitFor(() => { + await vi.waitFor(() => { expect(onChange).toHaveBeenCalled() }) }) it('does not call the onChange prop when disabled', async () => { const onChange = vi.fn() - const { container } = render( + const { container } = await render( ', () => { fireEvent.click(input!) - await waitFor(() => { + await vi.waitFor(() => { expect(onChange).not.toHaveBeenCalled() expect(input).toBeDisabled() }) @@ -112,7 +112,7 @@ describe('', () => { it('does not call the onChange prop when readOnly', async () => { const onChange = vi.fn() - const { container } = render( + const { container } = await render( ', () => { fireEvent.click(input!) - await waitFor(() => { + await vi.waitFor(() => { expect(onChange).not.toHaveBeenCalled() expect(input).not.toBeDisabled() expect(input).toHaveAttribute('readonly') @@ -136,7 +136,7 @@ describe('', () => { }) it('should not update the value when the value prop is set', async () => { - const { container } = render( + const { container } = await render( ', () => { await userEvent.click(banana!) - await waitFor(() => { + await vi.waitFor(() => { expect(orange).toHaveAttribute('checked') }) }) it('adds the correct tabindex to RadioInputs when none are checked', async () => { - const { container } = render( + const { container } = await render( @@ -176,7 +176,7 @@ describe('', () => { }) it('adds the correct tabindex to RadioInputs when checked', async () => { - const { container } = render( + const { container } = await render( ', () => { describe('for a11y', () => { it('should meet a11y standards', async () => { - const { container } = render( + const { container } = await render( @@ -209,8 +209,8 @@ describe('', () => { }) }) - it('adds the correct ARIA attributes', () => { - const { container } = render( + it('adds the correct ARIA attributes', async () => { + const { container } = await render( ', () => { it('renders an input with type "range"', async () => { - const { container } = render( + const { container } = await render( ', () => { }) it('displays the default value', async () => { - const { container } = render( + const { container } = await render( ', () => { }) it('sets input value to default value', async () => { - const { container } = render( + const { container } = await render( ', () => { }) it('sets input value to controlled value', async () => { - const { container } = render( + const { container } = await render( ', () => { it('should provide an inputRef prop', async () => { const inputRef = vi.fn() - const { container } = render( + const { container } = await render( ', () => { }) it('sets min value', async () => { - render( + await render( ', () => { displayValue={false} /> ) - const input = screen.getByLabelText('Opacity') + const input = page.getByLabelText('Opacity').element() expect(input).toHaveAttribute('min', '25') }) it('sets max value', async () => { - render( + await render( ', () => { /> ) - const input = screen.getByLabelText('Opacity') + const input = page.getByLabelText('Opacity').element() expect(input).toHaveAttribute('max', '75') }) it('sets step value', async () => { - render( + await render( ', () => { displayValue={false} /> ) - const input = screen.getByLabelText('Opacity') + const input = page.getByLabelText('Opacity').element() expect(input).toHaveAttribute('step', '5') }) it('formats the value displayed', async () => { - const { container } = render( + const { container } = await render( ', () => { }) it('hides the value when displayValue is false', async () => { - const { container } = render( + const { container } = await render( ', () => { describe('for a11y', () => { it('should meet standards', async () => { - const { container } = render( + const { container } = await render( ', () => { }) it('associates messages with the input as its description, not its accessible name', async () => { - const { container } = render( + const { container } = await render( ', () => { }) it('does not override the accessible name with aria-labelledby when there are no messages', async () => { - const { container } = render( + const { container } = await render( ) const input = container.querySelector('input')! @@ -247,7 +247,7 @@ describe('', () => { }) it('formats the aria-valuetext attribute', async () => { - const { container } = render( + const { container } = await render( ', () => { - it('should render the correct number of icons', () => { - const { container } = render() + it('should render the correct number of icons', async () => { + const { container } = await render( + + ) const icons = container.querySelectorAll('svg') expect(icons).toHaveLength(5) }) - it('should handle a valueMax of zero', () => { - const { container } = render() + it('should handle a valueMax of zero', async () => { + const { container } = await render( + + ) const icons = container.querySelectorAll('svg') expect(icons).toHaveLength(3) }) - it('should fill the correct number of icons', () => { - const { container } = render( + it('should fill the correct number of icons', async () => { + const { container } = await render( ', () => { expect(filledIcons).toHaveLength(4) }) - it('never renders more than `iconCount` icons', () => { - const { container } = render( + it('never renders more than `iconCount` icons', async () => { + const { container } = await render( ', () => { expect(icons).toHaveLength(5) }) - it('should render screen reader text to give context', () => { - const { container } = render( + it('should render screen reader text to give context', async () => { + const { container } = await render( ', () => { }) it('should meet a11y standards', async () => { - const { container } = render() + const { container } = await render( + + ) const axeCheck = await runAxeCheck(container) expect(axeCheck).toBe(true) @@ -105,7 +109,7 @@ describe('', () => { .filter((prop) => prop !== 'children') .forEach((prop) => { if (Object.keys(allowedProps).indexOf(prop) < 0) { - it(`should NOT allow the '${prop}' prop`, () => { + it(`should NOT allow the '${prop}' prop`, async () => { const consoleErrorSpy = vi .spyOn(console, 'error') .mockImplementation(() => {}) @@ -114,7 +118,9 @@ describe('', () => { [prop]: 'foo' } - render() + await render( + + ) expect(consoleErrorSpy).toHaveBeenCalledWith( expect.stringContaining(expectedErrorMessage), expect.any(String) @@ -123,13 +129,15 @@ describe('', () => { consoleErrorSpy.mockRestore() }) } else { - it(`should allow the '${prop}' prop`, () => { + it(`should allow the '${prop}' prop`, async () => { const props = { [prop]: allowedProps[prop] } const consoleErrorSpy = vi .spyOn(console, 'error') .mockImplementation(() => {}) - render() + await render( + + ) expect(consoleErrorSpy).not.toHaveBeenCalled() consoleErrorSpy.mockRestore() diff --git a/packages/ui-rating/src/RatingIcon/__tests__/RatingIcon.test.tsx b/packages/ui-rating/src/RatingIcon/__tests__/RatingIcon.test.tsx index 0c3346af80..d4678aa2eb 100644 --- a/packages/ui-rating/src/RatingIcon/__tests__/RatingIcon.test.tsx +++ b/packages/ui-rating/src/RatingIcon/__tests__/RatingIcon.test.tsx @@ -22,10 +22,9 @@ * SOFTWARE. */ -import { render, waitFor } from '@testing-library/react' -import { vi } from 'vitest' import type { MockInstance } from 'vitest' -import '@testing-library/jest-dom' +import { render } from 'vitest-browser-react' +import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest' import { InstUISettingsProvider } from '@instructure/emotion' import { runAxeCheck } from '@instructure/ui-axe-check' @@ -52,7 +51,7 @@ describe('', () => { }) it('transitions when filled on render and animateFill is true', async () => { - const { container } = render( + const { container } = await render( ', () => { ) - await waitFor( + await vi.waitFor( () => { const icon = container.querySelector('svg') const iconWrapper = container.querySelector( @@ -82,7 +81,7 @@ describe('', () => { }) it('transitions when filled after render and animateFill is true', async () => { - const { container, rerender } = render( + const { container, rerender } = await render( ', () => { ) - await waitFor( + await vi.waitFor( () => { const icon = container.querySelector('svg') const iconWrapper = container.querySelector( @@ -109,7 +108,7 @@ describe('', () => { { timeout: 500 } ) - rerender( + await rerender( ', () => { ) - await waitFor( + await vi.waitFor( () => { const icon = container.querySelector('svg') const iconWrapper = container.querySelector( @@ -139,7 +138,7 @@ describe('', () => { }) it('should meet a11y standards', async () => { - const { container } = render() + const { container } = await render() const axeCheck = await runAxeCheck(container) expect(axeCheck).toBe(true) diff --git a/packages/ui-react-utils/src/__tests__/DeterministicIdContext.test.tsx b/packages/ui-react-utils/src/__tests__/DeterministicIdContext.test.tsx index c4958ba1ce..62e2ebf6a3 100644 --- a/packages/ui-react-utils/src/__tests__/DeterministicIdContext.test.tsx +++ b/packages/ui-react-utils/src/__tests__/DeterministicIdContext.test.tsx @@ -24,8 +24,9 @@ import { Component } from 'react' -import { render, screen } from '@testing-library/react' -import '@testing-library/jest-dom' +import { render } from 'vitest-browser-react' +import { page } from 'vitest/browser' +import { describe, it, expect } from 'vitest' import { withDeterministicId, @@ -62,16 +63,16 @@ const uniqueIds = (el: Element) => { } describe('DeterministicIdContext', () => { - it('can be found and tested with ReactTestUtils', () => { - render() - const testComponent = screen.getByTestId('test-component') + it('can be found and tested with ReactTestUtils', async () => { + await render() + const testComponent = page.getByTestId('test-component').element() expect(testComponent).toBeInTheDocument() expect(testComponent.id).toBeDefined() }) - it('should generate unique ids without Provider wrapper', () => { - render( + it('should generate unique ids without Provider wrapper', async () => { + await render(
@@ -80,13 +81,13 @@ describe('DeterministicIdContext', () => {
) - const el = screen.getByTestId('test-components') + const el = page.getByTestId('test-components').element() expect(uniqueIds(el)).toBe(true) }) - it('should generate unique ids when components are rendered both out and inside of provider', () => { - render( + it('should generate unique ids when components are rendered both out and inside of provider', async () => { + await render(
@@ -97,12 +98,12 @@ describe('DeterministicIdContext', () => {
) - const el = screen.getByTestId('test-components') + const el = page.getByTestId('test-components').element() expect(uniqueIds(el)).toBe(true) }) - it('should generate unique ids with provider only', () => { + it('should generate unique ids with provider only', async () => { const Wrapper = ({ children }: any) => { return ( @@ -115,17 +116,17 @@ describe('DeterministicIdContext', () => { children.push() } - render({children}) - const el = screen.getByTestId('wrapper') + await render({children}) + const el = page.getByTestId('wrapper').element() expect(uniqueIds(el)).toBe(true) }) - it('should use a global object for ID counter', () => { + it('should use a global object for ID counter', async () => { const instUIInstanceCounter = '__INSTUI_GLOBAL_INSTANCE_COUNTER__' const counterValue = 345 globalThis[instUIInstanceCounter].set('TestComponent', counterValue) - render( + await render(
diff --git a/packages/ui-react-utils/src/__tests__/callRenderProp.test.tsx b/packages/ui-react-utils/src/__tests__/callRenderProp.test.tsx index 8d7350ab69..096d49b574 100644 --- a/packages/ui-react-utils/src/__tests__/callRenderProp.test.tsx +++ b/packages/ui-react-utils/src/__tests__/callRenderProp.test.tsx @@ -24,8 +24,8 @@ import { Component } from 'react' -import { render } from '@testing-library/react' -import '@testing-library/jest-dom' +import { render } from 'vitest-browser-react' +import { describe, it, expect } from 'vitest' import { callRenderProp } from '../callRenderProp.js' @@ -54,7 +54,7 @@ describe('callRenderProp', () => { expect(callRenderProp()).toStrictEqual() }) - it('React classes', () => { + it('React classes', async () => { class Foo extends Component { render() { return
hello
@@ -64,22 +64,22 @@ describe('callRenderProp', () => { const Result = callRenderProp(Foo) expect(Result).toStrictEqual() - const { getByText } = render(Result) + const { getByText } = await render(Result) expect(getByText('hello')).toBeInTheDocument() }) - it('functions', () => { + it('functions', async () => { const Baz = function () { return 'some text' } const result = callRenderProp(Baz) - const { getByText } = render(
{result}
) + const { getByText } = await render(
{result}
) expect(getByText('some text')).toBeInTheDocument() }) - it('fat arrow functions', () => { + it('fat arrow functions', async () => { const Baz = () => 'some text' // in this test we are trying to test that it works with fat arrow functions, @@ -93,23 +93,23 @@ describe('callRenderProp', () => { const result = callRenderProp(Baz) - const { getByText } = render(
{result}
) + const { getByText } = await render(
{result}
) expect(getByText('some text')).toBeInTheDocument() }) describe('passing props', () => { - it('should pass props correctly to functions', () => { + it('should pass props correctly to functions', async () => { const someFunc = ({ shape }: { shape: string }) =>
{shape}
const result = callRenderProp(someFunc, { shape: 'rectangle' }) - const { getByText } = render(
{result}
) + const { getByText } = await render(
{result}
) expect(getByText('rectangle')).toBeInTheDocument() }) - it('should pass props correctly to React classes', () => { + it('should pass props correctly to React classes', async () => { type FooProps = { shape?: string } class Foo extends Component { static defaultProps = { @@ -123,7 +123,7 @@ describe('callRenderProp', () => { const result = callRenderProp(Foo, { shape: 'rectangle' }) - const { getByText } = render(
{result}
) + const { getByText } = await render(
{result}
) expect(getByText('rectangle')).toBeInTheDocument() }) diff --git a/packages/ui-react-utils/src/__tests__/getInteraction.test.tsx b/packages/ui-react-utils/src/__tests__/getInteraction.test.tsx index 96fd0267a3..0eee5eb87c 100644 --- a/packages/ui-react-utils/src/__tests__/getInteraction.test.tsx +++ b/packages/ui-react-utils/src/__tests__/getInteraction.test.tsx @@ -22,7 +22,7 @@ * SOFTWARE. */ -import '@testing-library/jest-dom' +import { describe, it, expect } from 'vitest' import { getInteraction, InteractionType } from '../getInteraction.js' describe('getInteraction', () => { diff --git a/packages/ui-react-utils/src/__tests__/omitProps.test.tsx b/packages/ui-react-utils/src/__tests__/omitProps.test.tsx index 3ee14f3edf..ad61d6b01b 100644 --- a/packages/ui-react-utils/src/__tests__/omitProps.test.tsx +++ b/packages/ui-react-utils/src/__tests__/omitProps.test.tsx @@ -22,7 +22,7 @@ * SOFTWARE. */ -import '@testing-library/jest-dom' +import { describe, it, expect } from 'vitest' import { omitProps } from '../omitProps.js' describe('omitProps', () => { diff --git a/packages/ui-react-utils/src/__tests__/passthroughProps.test.tsx b/packages/ui-react-utils/src/__tests__/passthroughProps.test.tsx index 8696634118..2808ae0497 100644 --- a/packages/ui-react-utils/src/__tests__/passthroughProps.test.tsx +++ b/packages/ui-react-utils/src/__tests__/passthroughProps.test.tsx @@ -22,7 +22,7 @@ * SOFTWARE. */ -import '@testing-library/jest-dom' +import { describe, it, expect } from 'vitest' import { passthroughProps } from '../passthroughProps.js' describe('passthroughProps', () => { diff --git a/packages/ui-react-utils/src/__tests__/pickProps.test.tsx b/packages/ui-react-utils/src/__tests__/pickProps.test.tsx index b0f481cd14..cb4fb3ccf1 100644 --- a/packages/ui-react-utils/src/__tests__/pickProps.test.tsx +++ b/packages/ui-react-utils/src/__tests__/pickProps.test.tsx @@ -22,7 +22,7 @@ * SOFTWARE. */ -import '@testing-library/jest-dom' +import { describe, it, expect } from 'vitest' import { pickProps } from '../pickProps.js' describe('pickProps', () => { diff --git a/packages/ui-react-utils/src/__tests__/safeCloneElement.test.tsx b/packages/ui-react-utils/src/__tests__/safeCloneElement.test.tsx index ea6e3f47ad..eb360d7bb9 100644 --- a/packages/ui-react-utils/src/__tests__/safeCloneElement.test.tsx +++ b/packages/ui-react-utils/src/__tests__/safeCloneElement.test.tsx @@ -23,11 +23,11 @@ */ import { ReactElement, ReactNode } from 'react' -import { vi } from 'vitest' import { createChainedFunction } from '@instructure/ui-utils' -import { render, screen } from '@testing-library/react' -import '@testing-library/jest-dom' +import { render } from 'vitest-browser-react' +import { page } from 'vitest/browser' +import { describe, it, expect, vi } from 'vitest' import { safeCloneElement } from '../safeCloneElement.js' @@ -44,11 +44,11 @@ describe('safeCloneElement', () => { return safeCloneElement(element, props, children) } - it('should preserve refs', () => { + it('should preserve refs', async () => { const origRef = vi.fn() const cloneRef = vi.fn() - render( + await render( } props={{ ref: cloneRef }} /> ) @@ -56,37 +56,37 @@ describe('safeCloneElement', () => { expect(cloneRef).toHaveBeenCalled() }) - it('should preserve event handlers', () => { + it('should preserve event handlers', async () => { const onClickA = vi.fn() const onClickB = vi.fn() - render( + await render( } props={{ onClick: onClickB }} /> ) - const button = screen.getByRole('button') + const button = page.getByRole('button').element() button.click() expect(onClickA).toHaveBeenCalled() expect(onClickB).toHaveBeenCalled() }) - it('should preserve already chained functions', () => { + it('should preserve already chained functions', async () => { const onClickA = vi.fn() const onClickB = vi.fn() const onClickC = vi.fn() - render( + await render( } props={{ onClick: createChainedFunction(onClickB, onClickC) }} /> ) - const button = screen.getByRole('button') + const button = page.getByRole('button').element() button.click() expect(onClickA).toHaveBeenCalled() diff --git a/packages/ui-react-utils/src/__tests__/useDeterministicId.test.tsx b/packages/ui-react-utils/src/__tests__/useDeterministicId.test.tsx index 026e1432b8..06509250af 100644 --- a/packages/ui-react-utils/src/__tests__/useDeterministicId.test.tsx +++ b/packages/ui-react-utils/src/__tests__/useDeterministicId.test.tsx @@ -22,8 +22,9 @@ * SOFTWARE. */ -import { render, screen } from '@testing-library/react' -import '@testing-library/jest-dom' +import { render } from 'vitest-browser-react' +import { page } from 'vitest/browser' +import { describe, it, expect } from 'vitest' import { useDeterministicId, @@ -74,38 +75,38 @@ const uniqueIds = (el: Element) => { } describe('useDeterministicId', () => { - it('should generate a deterministic ID', () => { - render() - const element = screen.getByTestId('test-component') + it('should generate a deterministic ID', async () => { + await render() + const element = page.getByTestId('test-component').element() expect(element).toBeInTheDocument() expect(element.id).toBe('TestComponent___0') }) - it('should generate unique IDs for multiple instances', () => { - render( + it('should generate unique IDs for multiple instances', async () => { + await render(
) - const container = screen.getByTestId('container') + const container = page.getByTestId('container').element() expect(uniqueIds(container)).toBe(true) }) - it('should support custom instance names', () => { - render() - const container = screen.getByTestId('test-component') + it('should support custom instance names', async () => { + await render() + const container = page.getByTestId('test-component').element() expect(container.id).toBe('MyComponent___0') expect(container.querySelector('label')?.id).toBe('MyComponent-label___0') expect(container.querySelector('input')?.id).toBe('MyComponent-input___0') }) - it('should generate unique IDs without Provider wrapper', () => { - render( + it('should generate unique IDs without Provider wrapper', async () => { + await render(
@@ -114,13 +115,13 @@ describe('useDeterministicId', () => {
) - const el = screen.getByTestId('test-components') + const el = page.getByTestId('test-components').element() expect(uniqueIds(el)).toBe(true) }) - it('should generate unique IDs when components are rendered both outside and inside of provider', () => { - render( + it('should generate unique IDs when components are rendered both outside and inside of provider', async () => { + await render(
@@ -131,12 +132,12 @@ describe('useDeterministicId', () => {
) - const el = screen.getByTestId('test-components') + const el = page.getByTestId('test-components').element() expect(uniqueIds(el)).toBe(true) }) - it('should generate unique IDs with Provider only', () => { + it('should generate unique IDs with Provider only', async () => { const Wrapper = ({ children }: any) => { return ( @@ -149,18 +150,18 @@ describe('useDeterministicId', () => { children.push() } - render({children}) - const el = screen.getByTestId('wrapper') + await render({children}) + const el = page.getByTestId('wrapper').element() expect(uniqueIds(el)).toBe(true) }) - it('should use the global instance counter', () => { + it('should use the global instance counter', async () => { const instUIInstanceCounter = '__INSTUI_GLOBAL_INSTANCE_COUNTER__' const counterValue = 500 globalThis[instUIInstanceCounter].set('GlobalTestComponent', counterValue) - render( + await render(
@@ -172,21 +173,21 @@ describe('useDeterministicId', () => { expect(instanceCounter.get('GlobalTestComponent')).toBe(counterValue + 3) }) - it('should generate sequential IDs for the same component', () => { - const { rerender } = render( + it('should generate sequential IDs for the same component', async () => { + const { rerender } = await render(
) - rerender( + await rerender(
) - const allElements = screen.getAllByTestId('test-component') + const allElements = page.getByTestId('test-component').elements() expect(allElements).toHaveLength(2) // IDs should be sequential @@ -196,7 +197,7 @@ describe('useDeterministicId', () => { expect(ids[0]).not.toBe(ids[1]) }) - it('should work correctly with nested components', () => { + it('should work correctly with nested components', async () => { const ParentComponent = () => { const deterministicId = useDeterministicId('ParentComponent') return ( @@ -207,14 +208,14 @@ describe('useDeterministicId', () => { ) } - render() - const parent = screen.getByTestId('parent') + await render() + const parent = page.getByTestId('parent').element() expect(parent.id).toBe('ParentComponent___0') expect(uniqueIds(parent)).toBe(true) }) - it('should handle multiple calls to the same deterministicId function', () => { + it('should handle multiple calls to the same deterministicId function', async () => { const MultiCallComponent = () => { const deterministicId = useDeterministicId('MultiCallComponent') const id1 = deterministicId() @@ -230,8 +231,8 @@ describe('useDeterministicId', () => { ) } - render() - const container = screen.getByTestId('multi-call') + await render() + const container = page.getByTestId('multi-call').element() const ids = Array.from(container.children).map((el) => el.id) expect(ids).toHaveLength(3) diff --git a/packages/ui-responsive/src/Responsive/__tests__/Responsive.test.tsx b/packages/ui-responsive/src/Responsive/__tests__/Responsive.test.tsx index 8f8acc8a8f..5f75c5cbe7 100644 --- a/packages/ui-responsive/src/Responsive/__tests__/Responsive.test.tsx +++ b/packages/ui-responsive/src/Responsive/__tests__/Responsive.test.tsx @@ -22,10 +22,9 @@ * SOFTWARE. */ -import { render } from '@testing-library/react' -import { vi, expect } from 'vitest' import type { MockInstance } from 'vitest' -import '@testing-library/jest-dom' +import { render } from 'vitest-browser-react' +import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest' import { deepEqual } from '@instructure/ui-utils' import { Responsive } from '@instructure/ui-responsive/latest' @@ -46,7 +45,7 @@ describe('', () => { it('should call render with the correct matches', async () => { const renderSpy = vi.fn() - render( + await render(
', () => { medium: { options: [1, 2, 3], icons: { edit: true, flag: false } }, large: { margin: 'small', label: 'hello world', describedBy: 'fakeId' } } - render( + await render(
', () => { }) it('should warn when more than one breakpoint is applied and a prop value is overwritten', async () => { - render( + await render(
', () => { it('should call render prop only once', async () => { const renderSpy = vi.fn() - render( + await render(
', () => { it('should apply the `display` prop', async () => { const renderSpy = vi.fn() - const { container } = render( + const { container } = await render(
', () => { it('should not crash for weird option ids', async () => { const weirdID = 'some_`w@ei:r|!@#$%^&*(()|\\.l/d"id' vi.useFakeTimers() - const { container } = render( + const { container } = await render( {getOptions()} ) const input = container.querySelector('input') @@ -346,7 +345,7 @@ describe('{getOptions()} ) const input = container.querySelector('input') @@ -354,7 +353,7 @@ describe(' {}}> {getOptions()} @@ -367,7 +366,7 @@ describe('+1}> {getOptions()} @@ -380,7 +379,7 @@ describe('', () => { expect(input).toHaveAccessibleName('Multiple Select') // the pill keeps its own "Remove ..." accessible name - const pill = screen.getByRole('button', { name: 'Remove foo' }) + const pill = page.getByRole('button', { name: 'Remove foo' }).element() expect(pill).toHaveAccessibleName('Remove foo') }) }) it('should render an input and a list', async () => { - const { container } = render( + const { container } = await render( ) - const select = screen.getByTestId('subidubi') - const label = screen.getByLabelText('Choose an option') + const select = page.getByTestId('subidubi').element() + const label = page.getByLabelText('Choose an option').element() const input = container.querySelector('input[id^="Select_"]') - const list = screen.getByRole('listbox') + const list = page.getByRole('listbox').element() - const options = screen.getAllByRole('option') + const options = page.getByRole('option').elements() const optionsCount = defaultOptions.length expect(select).toBeInTheDocument() @@ -434,7 +433,7 @@ describe(' ungrouped option one @@ -447,8 +446,8 @@ describe(' ) - const groups = screen.getAllByRole('group') - const groupLabel = screen.getByText('Group one') + const groups = page.getByRole('group').elements() + const groupLabel = page.getByText('Group one').element() expect(groupLabel).toHaveAttribute('role', 'presentation') expect(groups[0].getAttribute('aria-labelledby')).toEqual( @@ -458,30 +457,30 @@ describe(' valid
invalid
) - const invalidChild = screen.queryByText('invalid') + const invalidChild = page.getByText('invalid').query() expect(invalidChild).not.toBeInTheDocument() }) it('should provide a focus method', async () => { const ref = createRef {getOptions()} ) - const input = screen.getByLabelText('Choose an option') + const input = page.getByLabelText('Choose an option').element() ref.current?.focus() - await waitFor(() => { + await vi.waitFor(() => { expect(document.activeElement).toBe(input) }) }) @@ -489,7 +488,7 @@ describe('() - render( + await render( @@ -498,22 +497,24 @@ describe(') + it('should render with a generated id by default', async () => { + const { container } = await render( + ) const input = container.querySelector('input[id^="customSelect"]') @@ -522,129 +523,133 @@ describe(') - const input = screen.getByLabelText('Choose an option') + it('should render readonly when interaction="enabled" with no onInputChange', async () => { + await render( {}} />) - const input = screen.getByLabelText('Choose an option') + it('should not render readonly when interaction="enabled" with onInputChange', async () => { + await render( + {}} /> ) - const input = screen.getByLabelText('Choose an option') + const input = page.getByLabelText('Choose an option').element() expect(input).toHaveAttribute('readonly') expect(input).not.toHaveAttribute('disabled') }) - it('should render disabled when interaction="disabled"', () => { - render( + it('should render disabled when interaction="disabled"', async () => { + await render( ) - const input = screen.getByLabelText('Choose an option') + it('should not render readonly when disabled', async () => { + await render( + ) - const input = screen.getByLabelText('Choose an option *') + it('should render required when isRequired={true}', async () => { + await render() - const input = screen.getByLabelText('Choose an option') + await render( {getOptions(defaultOptions[1])} ) - const input = screen.getByLabelText('Choose an option') + const input = page.getByLabelText('Choose an option').element() expect(input).toHaveAttribute('aria-activedescendant', defaultOptions[1]) }) - it('should not set aria-activedescendant when not showing options', () => { - render( + it('should not set aria-activedescendant when not showing options', async () => { + await render( ) - const input = screen.getByLabelText('Choose an option') + const input = page.getByLabelText('Choose an option').element() expect(input).not.toHaveAttribute('aria-activedescendant') }) - it('should allow assistive text', () => { - render( + it('should allow assistive text', async () => { + await render( ) - const input = screen.getByLabelText('Choose an option') - const assistiveText = screen.getByText('hello world') + const input = page.getByLabelText('Choose an option').element() + const assistiveText = page.getByText('hello world').element() const assistiveTextId = assistiveText.getAttribute('id') expect(input).toHaveAttribute('aria-describedby', assistiveTextId) }) - it('should allow custom props to pass through', () => { - render( + it('should allow custom props to pass through', async () => { + await render( ) - const input = screen.getByLabelText('Choose an option') + const input = page.getByLabelText('Choose an option').element() expect(input).toHaveAttribute('data-custom-attr', 'true') }) - it('should allow override of autoComplete prop', () => { - const { rerender } = render( + it('should allow override of autoComplete prop', async () => { + const { rerender } = await render( ) - const input = screen.getByLabelText('Choose an option') + const input = page.getByLabelText('Choose an option').element() expect(input).toHaveAttribute('autocomplete', 'off') - rerender( + await rerender( @@ -656,21 +661,21 @@ describe(' {getOptions()} ) - const input = screen.getByLabelText('Choose an option') + const input = page.getByLabelText('Choose an option').element() - await waitFor(() => { + await vi.waitFor(() => { expect(inputRef).toHaveBeenCalledWith(input) }) }) it("should not render option's before content in input field when isOptionContentAppliedToInput is set to false", async () => { - const { container } = render( + const { container } = await render( ', () => { }) it("should render option's before content in input field when isOptionContentAppliedToInput is set to true", async () => { - const { container } = render( + const { container } = await render( ', () => { }) it("should render option's after content in input field when isOptionContentAppliedToInput is set to true", async () => { - const { container } = render( + const { container } = await render( ', () => { }) it("should render option's after content in input field when isOptionContentAppliedToInput is set to true but renderAfterInput is also set", async () => { - const { container } = render( + const { container } = await render( ', () => { }) it("should render option's before content in input field when isOptionContentAppliedToInput is set to true and both optionBeforeContent and optionAfterContent are provided", async () => { - const { container } = render( + const { container } = await render( ', () => { }) it('should render arrow in input field when isOptionContentAppliedToInput is set to true but inputValue is not set', async () => { - const { container } = render( + const { container } = await render( ', () => { }) it("should render option's before content input field when isOptionContentAppliedToInput is set to true with group options", async () => { - const { container } = render( + const { container } = await render( ', () => { }) it("should render option's after content input field when isOptionContentAppliedToInput is set to true with group options", async () => { - const { container } = render( + const { container } = await render( {getOptions(undefined, defaultOptions[1])} ) - const options = screen.getAllByRole('option') + const options = page.getByRole('option').elements() expect(options[1].getAttribute('aria-selected')).toEqual('true') }) - it('should set aria-disabled on options when isDisabled={true}', () => { - render( + it('should set aria-disabled on options when isDisabled={true}', async () => { + await render( ) - const options = screen.getAllByRole('option') + const options = page.getByRole('option').elements() expect(options[0]).not.toHaveAttribute('aria-disabled') expect(options[2]).toHaveAttribute('aria-disabled', 'true') }) it('should set list element role to "listbox"', async () => { - render( + await render( ) - const listbox = screen.getByRole('listbox') + const listbox = page.getByRole('listbox').element() expect(listbox).toBeInTheDocument() expect(listbox.tagName).toBe('UL') @@ -976,7 +981,7 @@ describe('', () => { ) - const listbox = screen.getByRole('listbox') + const listbox = page.getByRole('listbox').element() - await waitFor(() => { + await vi.waitFor(() => { expect(listRef).toHaveBeenCalledWith(listbox) }) }) @@ -999,7 +1004,7 @@ describe('', () => { ) const icon = container.querySelector('svg[name="ChevronDown"]') - const label = screen.getByText('Choose an option') + const label = page.getByText('Choose an option').element() expect(icon).toBeInTheDocument() expect(label).toBeInTheDocument() await userEvent.click(label) - await waitFor(() => { + await vi.waitFor(() => { expect(onRequestShowOptions).toHaveBeenCalledTimes(1) }) await userEvent.click(icon!) - await waitFor(() => { + await vi.waitFor(() => { expect(onRequestShowOptions).toHaveBeenCalledTimes(2) }) - rerender( + await rerender( ', () => { it('when input is clicked', async () => { const onRequestShowOptions = vi.fn() - const { rerender } = render( + const { rerender } = await render( ) - const input = screen.getByLabelText('Choose an option') + const input = page.getByLabelText('Choose an option').element() await userEvent.click(input) - await waitFor(() => { + await vi.waitFor(() => { expect(onRequestShowOptions).toHaveBeenCalledTimes(1) }) - rerender( + await rerender( ', () => { it('when up/down arrows are pressed', async () => { const onRequestShowOptions = vi.fn() - render( + await render( ) - const input = screen.getByLabelText('Choose an option') + const input = page.getByLabelText('Choose an option').element() await userEvent.type(input, '{arrowdown}') - await waitFor(() => { + await vi.waitFor(() => { expect(onRequestShowOptions).toHaveBeenCalledTimes(1) }) await userEvent.type(input, '{arrowup}') - await waitFor(() => { + await vi.waitFor(() => { expect(onRequestShowOptions).toHaveBeenCalledTimes(2) }) }) @@ -1102,7 +1107,7 @@ describe('', () => { ) - const input = screen.getByLabelText('Choose an option') + const input = page.getByLabelText('Choose an option').element() await userEvent.type(input, '{space}') - await waitFor(() => { + await vi.waitFor(() => { expect(onRequestShowOptions).toHaveBeenCalledTimes(1) }) - rerender( + await rerender( ', () => { it('when root is clicked and isShowingOptions is true', async () => { const onRequestHideOptions = vi.fn() - const { container } = render( + const { container } = await render( ', () => { it('when root is clicked and isShowingOptions is false should NOT fire onRequestHideOptions', async () => { const onRequestHideOptions = vi.fn() - render( + await render( ) - const label = screen.getByText('Choose an option') + const label = page.getByText('Choose an option').element() expect(label).toBeInTheDocument() await userEvent.click(label) - await waitFor(() => { + await vi.waitFor(() => { expect(onRequestHideOptions).not.toHaveBeenCalled() }) }) @@ -1192,7 +1197,7 @@ describe('', () => { ) - const input = screen.getByLabelText('Choose an option') + const input = page.getByLabelText('Choose an option').element() await userEvent.click(input) - await waitFor(() => { + await vi.waitFor(() => { expect(onRequestHideOptions).toHaveBeenCalledTimes(1) }) - rerender( + await rerender( ) await userEvent.click(input) - await waitFor(() => { + await vi.waitFor(() => { expect(onRequestHideOptions).toHaveBeenCalledTimes(1) }) }) @@ -1227,7 +1232,7 @@ describe('', () => { ) - const input = screen.getByLabelText('Choose an option') + const input = page.getByLabelText('Choose an option').element() await userEvent.type(input, '{esc}') - await waitFor(() => { + await vi.waitFor(() => { expect(onRequestHideOptions).toHaveBeenCalledTimes(1) }) }) @@ -1250,7 +1255,7 @@ describe('', () => { {getOptions()} ) - const options = screen.getAllByRole('option') + const options = page.getByRole('option').elements() await userEvent.hover(options[0]) - await waitFor(() => { + await vi.waitFor(() => { expect(onRequestHighlightOption).toHaveBeenCalledWith( expect.anything(), expect.objectContaining({ @@ -1272,7 +1277,7 @@ describe('', () => { it('should fire onInputChange when input is typed in', async () => { const onInputChange = vi.fn() - render( + await render( ) - const input = screen.getByLabelText('Choose an option') + const input = page.getByLabelText('Choose an option').element() await userEvent.type(input, 'h') - await waitFor(() => { + await vi.waitFor(() => { expect(onInputChange).toHaveBeenCalled() }) }) @@ -1304,16 +1309,16 @@ describe(' {getOptions()} ) - const input = screen.getByLabelText('Choose an option') + const input = page.getByLabelText('Choose an option').element() input.focus() - await waitFor(() => { + await vi.waitFor(() => { expect(onFocus).toHaveBeenCalled() }) }) diff --git a/packages/ui-selectable/src/Selectable/__tests__/Selectable.test.tsx b/packages/ui-selectable/src/Selectable/__tests__/Selectable.test.tsx index 32efa98735..c282320aa7 100644 --- a/packages/ui-selectable/src/Selectable/__tests__/Selectable.test.tsx +++ b/packages/ui-selectable/src/Selectable/__tests__/Selectable.test.tsx @@ -22,10 +22,9 @@ * SOFTWARE. */ -import { render, screen, waitFor } from '@testing-library/react' -import { vi } from 'vitest' -import userEvent from '@testing-library/user-event' -import '@testing-library/jest-dom' +import { render } from 'vitest-browser-react' +import { page, userEvent } from 'vitest/browser' +import { describe, it, expect, vi } from 'vitest' import { Selectable } from '../index.js' import { SelectableRender } from '../props.js' @@ -52,7 +51,7 @@ describe('', () => { ) it('should focus trigger when label is clicked', async () => { - render( + await render( {(selectable) => ( @@ -73,14 +72,14 @@ describe('', () => { )} ) - const label = screen.getByText('Selectable') - const input = screen.getByRole('combobox') + const label = page.getByText('Selectable').element() + const input = page.getByRole('combobox').element() expect(document.activeElement).not.toBe(input) await userEvent.click(label) - await waitFor(() => { + await vi.waitFor(() => { expect(document.activeElement).toBe(input) }) }) @@ -89,7 +88,7 @@ describe('', () => { const onFocus = vi.fn() const onBlur = vi.fn() - render( + await render( {(selectable) => ( @@ -112,14 +111,14 @@ describe('', () => { )} ) - const label = screen.getByText('Selectable') - const input = screen.getByRole('combobox') + const label = page.getByText('Selectable').element() + const input = page.getByRole('combobox').element() expect(document.activeElement).not.toBe(input) await userEvent.click(label) - await waitFor(() => { + await vi.waitFor(() => { expect(onFocus).toHaveBeenCalledTimes(1) expect(onBlur).not.toHaveBeenCalled() }) @@ -130,7 +129,7 @@ describe('', () => { const onMouseDown = vi.fn() const onRequestHideOptions = vi.fn() - render( + await render( ', () => { )} ) - const input = screen.getByRole('combobox') - const list = screen.getByRole('listbox') + const input = page.getByRole('combobox').element() + const list = page.getByRole('listbox').element() input.focus() await userEvent.click(list) - await waitFor(() => { + await vi.waitFor(() => { expect(document.activeElement).toBe(input) expect(onClick).toHaveBeenCalledTimes(1) expect(onMouseDown).toHaveBeenCalledTimes(1) @@ -173,7 +172,7 @@ describe('', () => { const onMouseDown = vi.fn() const onRequestHideOptions = vi.fn() - render( + await render( ', () => { )} ) - const input = screen.getByRole('combobox') - const option = screen.getByText('foo') + const input = page.getByRole('combobox').element() + const option = page.getByText('foo').element() input.focus() await userEvent.click(option) - await waitFor(() => { + await vi.waitFor(() => { expect(document.activeElement).toBe(input) expect(onClick).toHaveBeenCalledTimes(1) expect(onMouseDown).toHaveBeenCalledTimes(1) @@ -223,7 +222,7 @@ describe('', () => { const onClick = vi.fn() const onKeyDown = vi.fn() - render( + await render( {(selectable) => ( @@ -251,12 +250,12 @@ describe('', () => { )} ) - const button = screen.getByText('Selected') + const button = page.getByText('Selected').element() await userEvent.click(button) await userEvent.type(button, '{enter}') - await waitFor(() => { + await vi.waitFor(() => { expect(onClick).toHaveBeenCalled() expect(onMouseDown).toHaveBeenCalled() expect(onKeyDown).toHaveBeenCalled() @@ -268,7 +267,7 @@ describe('', () => { it('when label is clicked', async () => { const onRequestShowOptions = vi.fn() - const { rerender } = render( + const { rerender } = await render( ', () => { {(selectable) => getSelectable(selectable)} ) - const label = screen.getByText('Selectable') + const label = page.getByText('Selectable').element() await userEvent.click(label) - await waitFor(() => { + await vi.waitFor(() => { expect(onRequestShowOptions).toHaveBeenCalledTimes(1) }) // Set isShowingOptions: - rerender( + await rerender( ', () => { await userEvent.click(label) - await waitFor(() => { + await vi.waitFor(() => { expect(onRequestShowOptions).toHaveBeenCalledTimes(1) }) }) @@ -304,7 +303,7 @@ describe('', () => { it('when input is clicked', async () => { const onRequestShowOptions = vi.fn() - const { rerender } = render( + const { rerender } = await render( ', () => { {(selectable) => getSelectable(selectable)} ) - const input = screen.getByRole('combobox') + const input = page.getByRole('combobox').element() await userEvent.click(input) - await waitFor(() => { + await vi.waitFor(() => { expect(onRequestShowOptions).toHaveBeenCalledTimes(1) }) - rerender( + await rerender( ', () => { await userEvent.click(input) - await waitFor(() => { + await vi.waitFor(() => { expect(onRequestShowOptions).toHaveBeenCalledTimes(1) }) }) @@ -339,7 +338,7 @@ describe('', () => { it('when up/down arrows are pressed', async () => { const onRequestShowOptions = vi.fn() - render( + await render( ', () => { {(selectable) => getSelectable(selectable)} ) - const input = screen.getByRole('combobox') + const input = page.getByRole('combobox').element() await userEvent.type(input, '{arrowdown}') - await waitFor(() => { + await vi.waitFor(() => { expect(onRequestShowOptions).toHaveBeenCalledTimes(1) }) await userEvent.type(input, '{arrowup}') - await waitFor(() => { + await vi.waitFor(() => { expect(onRequestShowOptions).toHaveBeenCalledTimes(2) }) }) @@ -363,16 +362,16 @@ describe('', () => { it('when space is pressed', async () => { const onRequestShowOptions = vi.fn() - const { rerender } = render( + const { rerender } = await render( {(selectable) => getSelectable(selectable)} ) - const input = screen.getByRole('combobox') + const input = page.getByRole('combobox').element() await userEvent.type(input, '{space}') - rerender( + await rerender( ', () => { ) await userEvent.type(input, '{space}') - await waitFor(() => { + await vi.waitFor(() => { expect(onRequestShowOptions).toHaveBeenCalledTimes(1) }) }) @@ -392,7 +391,7 @@ describe('', () => { it('when label is clicked', async () => { const onRequestHideOptions = vi.fn() - const { rerender } = render( + const { rerender } = await render( ', () => { {(selectable) => getSelectable(selectable)} ) - const label = screen.getByText('Selectable') + const label = page.getByText('Selectable').element() await userEvent.click(label) - await waitFor(() => { + await vi.waitFor(() => { expect(onRequestHideOptions).toHaveBeenCalledTimes(1) }) - rerender( + await rerender( ', () => { ) await userEvent.click(label) - await waitFor(() => { + await vi.waitFor(() => { expect(onRequestHideOptions).toHaveBeenCalledTimes(1) }) }) @@ -425,7 +424,7 @@ describe('', () => { it('when input is clicked', async () => { const onRequestHideOptions = vi.fn() - const { rerender } = render( + const { rerender } = await render( ', () => { {(selectable) => getSelectable(selectable)} ) - const input = screen.getByRole('combobox') + const input = page.getByRole('combobox').element() await userEvent.click(input) - await waitFor(() => { + await vi.waitFor(() => { expect(onRequestHideOptions).toHaveBeenCalledTimes(1) }) - rerender( + await rerender( ', () => { ) await userEvent.click(input) - await waitFor(() => { + await vi.waitFor(() => { expect(onRequestHideOptions).toHaveBeenCalledTimes(1) }) }) @@ -461,7 +460,7 @@ describe('', () => { it('should provide prop getter for root element', async () => { const renderSpy = vi.fn() - render( + await render( {(selectable) => { renderSpy(selectable) @@ -474,7 +473,7 @@ describe('', () => { }) it('should allow custom props to pass through', async () => { - render( + await render( {(selectable) => ( ', () => { )} ) - const root = screen.getByText('Selectable').closest('span') + const root = page.getByText('Selectable').element().closest('span') expect(root).toHaveAttribute('data-custom-attr', 'true') expect(root).toHaveClass('customClass') @@ -505,7 +504,7 @@ describe('', () => { const onClick = vi.fn() const onRequestShowOptions = vi.fn() - render( + await render( {(selectable) => ( @@ -518,10 +517,10 @@ describe('', () => { )} ) - const input = screen.getByRole('combobox') + const input = page.getByRole('combobox').element() await userEvent.click(input) - await waitFor(() => { + await vi.waitFor(() => { expect(onClick).toHaveBeenCalledTimes(1) expect(onRequestShowOptions).toHaveBeenCalledTimes(1) }) @@ -532,7 +531,7 @@ describe('', () => { it('should provide prop getter for label element', async () => { const renderSpy = vi.fn() - render( + await render( {(selectable) => { renderSpy(selectable) @@ -545,7 +544,7 @@ describe('', () => { }) it('should set htmlFor prop', async () => { - render( + await render( {(selectable) => ( @@ -559,8 +558,8 @@ describe('', () => { )} ) - const label = screen.getByText('Selectable') - const input = screen.getByRole('combobox') + const label = page.getByText('Selectable').element() + const input = page.getByRole('combobox').element() expect(label).toHaveAttribute('for', input.getAttribute('id')) }) @@ -568,7 +567,7 @@ describe('', () => { it('should set htmlFor prop with custom defined id', async () => { const customId = 'CustomSelect' - render( + await render( {(selectable) => ( @@ -582,15 +581,15 @@ describe('', () => { )} ) - const label = screen.getByText('Selectable') - const input = screen.getByRole('combobox') + const label = page.getByText('Selectable').element() + const input = page.getByRole('combobox').element() expect(input).toHaveAttribute('id', customId) expect(label).toHaveAttribute('for', customId) }) it('should allow custom props to pass through', async () => { - render( + await render( {(selectable) => ( @@ -612,7 +611,7 @@ describe('', () => { )} ) - const label = screen.getByText('Selectable') + const label = page.getByText('Selectable').element() expect(label).toHaveAttribute('data-custom-attr', 'true') expect(label).toHaveClass('customClass') @@ -624,7 +623,7 @@ describe('', () => { it('should provide prop getter for trigger element', async () => { const renderSpy = vi.fn() - render( + await render( {(selectable) => { renderSpy(selectable) @@ -636,7 +635,7 @@ describe('', () => { }) it('should set appropriate prop defaults', async () => { - const { container } = render( + const { container } = await render( {(selectable) => ( @@ -648,7 +647,7 @@ describe('', () => { ) const input = container.querySelector('input') - const desc = screen.getByText('description') + const desc = page.getByText('description').element() expect(input).toHaveAttribute('aria-haspopup', 'listbox') expect(input).toHaveAttribute('aria-describedby', desc.id) @@ -656,7 +655,7 @@ describe('', () => { }) it('should set appropriate props based on isShowingOptions', async () => { - const { container, rerender } = render( + const { container, rerender } = await render( {(selectable) => ( @@ -667,13 +666,13 @@ describe('', () => { ) const input = container.querySelector('input') - const list = screen.getByRole('listbox') + const list = page.getByRole('listbox').element() expect(input).toHaveAttribute('aria-expanded', 'false') expect(input).not.toHaveAttribute('aria-controls') // Set prop: isShowingOptions true - rerender( + await rerender( {(selectable) => ( @@ -689,7 +688,7 @@ describe('', () => { }) it('should set appropriate props based on highlightedOptionId', async () => { - const { container, rerender } = render( + const { container, rerender } = await render( {(selectable) => ( @@ -704,12 +703,12 @@ describe('', () => { ) const input = container.querySelector('input') - const options = screen.getAllByRole('option') + const options = page.getByRole('option').elements() expect(input).not.toHaveAttribute('aria-activedescendant') // Set prop: highlightedOptionId - rerender( + await rerender( ', () => { expect(input).toHaveAttribute('aria-activedescendant', options[0].id) // Set prop: highlightedOptionId - rerender( + await rerender( ', () => { expect(input).toHaveAttribute('aria-activedescendant', options[1].id) // Set prop: isShowingOptions - rerender( + await rerender( ', () => { }) it('should allow custom props to pass through', async () => { - const { container } = render( + const { container } = await render( {(selectable) => ( @@ -796,7 +795,7 @@ describe('', () => { }) it('should allow props to be overridden', async () => { - const { container } = render( + const { container } = await render( {(selectable) => ( @@ -820,7 +819,7 @@ describe('', () => { it('should provide a ref to the text input', async () => { const inputRef = vi.fn() - const { container } = render( + const { container } = await render( {(selectable) => ( @@ -840,7 +839,7 @@ describe('', () => { }) it('should allow role and aria-autocomplete props to be overridden', async () => { - const { container } = render( + const { container } = await render( {(selectable) => ( @@ -866,7 +865,7 @@ describe('', () => { const onRequestShowOptions = vi.fn() - render( + await render( {(selectable) => ( @@ -879,7 +878,7 @@ describe('', () => { )} ) - const input = screen.getByRole('combobox') + const input = page.getByRole('combobox').element() await input.click() expect(onClick).toHaveBeenCalledTimes(1) @@ -891,7 +890,7 @@ describe('', () => { it('should provide prop getter for trigger element', async () => { const renderSpy = vi.fn() - render( + await render( {(selectable) => { renderSpy(selectable) @@ -905,7 +904,7 @@ describe('', () => { }) it('should set appropriate prop defaults', async () => { - const { container } = render( + const { container } = await render( {(selectable) => ( @@ -922,7 +921,7 @@ describe('', () => { }) it('should set appropriate props when readOnly', async () => { - render( + await render( {(selectable) => ( @@ -934,7 +933,7 @@ describe('', () => { )} ) - const input = screen.getByRole('combobox') + const input = page.getByRole('combobox').element() expect(input).toHaveAttribute('aria-autocomplete', 'none') expect(input).toHaveAttribute('readOnly') @@ -942,7 +941,7 @@ describe('', () => { }) it('should allow props to be overridden', async () => { - const { container } = render( + const { container } = await render( {(selectable) => ( @@ -964,7 +963,7 @@ describe('', () => { }) it('should allow custom props to pass through', async () => { - const { container } = render( + const { container } = await render( {(selectable) => ( @@ -994,7 +993,7 @@ describe('', () => { it('should provide prop getter for list element', async () => { const renderSpy = vi.fn() - render( + await render( {(selectable) => { renderSpy(selectable) @@ -1008,7 +1007,7 @@ describe('', () => { }) it('should set appropriate prop defaults', async () => { - const { container } = render( + const { container } = await render( {(selectable) => ( @@ -1025,7 +1024,7 @@ describe('', () => { }) it('should allow custom props to pass through', async () => { - const { container } = render( + const { container } = await render( {(selectable) => ( @@ -1053,7 +1052,7 @@ describe('', () => { it('should provide prop getter for option element', async () => { const renderSpy = vi.fn() - render( + await render( {(selectable) => { renderSpy(selectable) @@ -1067,7 +1066,7 @@ describe('', () => { }) it('should set appropriate prop defaults', async () => { - render( + await render( {(selectable) => ( @@ -1083,7 +1082,7 @@ describe('', () => { )} ) - const option = screen.getByText(defaultOptions[0]) + const option = page.getByText(defaultOptions[0]).element() expect(option.tagName).toBe('LI') expect(option).toHaveAttribute('role', 'option') @@ -1091,7 +1090,7 @@ describe('', () => { }) it('should set aria-selected based on selectedOptionId', async () => { - const { container, rerender } = render( + const { container, rerender } = await render( {(selectable) => ( @@ -1114,7 +1113,7 @@ describe('', () => { expect(options[2]).toHaveAttribute('aria-selected', 'false') // Set prop: selectedOptionId - rerender( + await rerender( {(selectable) => ( @@ -1137,7 +1136,7 @@ describe('', () => { }) it('should allow custom props to pass through', async () => { - render( + await render( {(selectable) => ( @@ -1161,7 +1160,7 @@ describe('', () => { )} ) - const option = screen.getByText(defaultOptions[0]) + const option = page.getByText(defaultOptions[0]).element() expect(option.tagName).toBe('LI') expect(option).toHaveAttribute('data-custom-attr', 'true') @@ -1173,7 +1172,7 @@ describe('', () => { const onClick = vi.fn() const onRequestSelectOption = vi.fn() - render( + await render( ', () => { )} ) - const option_0 = screen.getByText(defaultOptions[0]) - const option_1 = screen.getByText(defaultOptions[1]) + const option_0 = page.getByText(defaultOptions[0]).element() + const option_1 = page.getByText(defaultOptions[1]).element() await userEvent.click(option_0) await userEvent.click(option_1) - await waitFor(() => { + await vi.waitFor(() => { expect(onRequestSelectOption).toHaveBeenCalledTimes(2) expect(onClick).toHaveBeenCalledTimes(2) }) @@ -1212,7 +1211,7 @@ describe('', () => { it('should provide prop getter for disabled option element', async () => { const renderSpy = vi.fn() - render( + await render( {(selectable) => { renderSpy(selectable) @@ -1226,7 +1225,7 @@ describe('', () => { }) it('should set aria-disabled prop', async () => { - render( + await render( {(selectable) => ( @@ -1250,7 +1249,7 @@ describe('', () => { )} ) - const option = screen.getByText(defaultOptions[0]) + const option = page.getByText(defaultOptions[0]).element() expect(option.tagName).toBe('LI') expect(option).toHaveAttribute('aria-disabled', 'true') @@ -1261,7 +1260,7 @@ describe('', () => { it('should provide prop getter for description element', async () => { const renderSpy = vi.fn() - render( + await render( {(selectable) => { renderSpy(selectable) diff --git a/packages/ui-side-nav-bar/src/SideNavBar/__tests__/NavigationItem.test.tsx b/packages/ui-side-nav-bar/src/SideNavBar/__tests__/NavigationItem.test.tsx index ef4b2318fe..33b7544f04 100644 --- a/packages/ui-side-nav-bar/src/SideNavBar/__tests__/NavigationItem.test.tsx +++ b/packages/ui-side-nav-bar/src/SideNavBar/__tests__/NavigationItem.test.tsx @@ -22,9 +22,9 @@ * SOFTWARE. */ -import { render, screen } from '@testing-library/react' -import { vi } from 'vitest' -import '@testing-library/jest-dom' +import { render } from 'vitest-browser-react' +import { page } from 'vitest/browser' +import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest' import { runAxeCheck } from '@instructure/ui-axe-check' import { IconAdminLine } from '@instructure/ui-icons' @@ -45,10 +45,10 @@ describe('', () => { }) it('should render', async () => { - const { container } = render( + const { container } = await render( } label="Admin" href="#" /> ) - const navItem = screen.getByRole('link') + const navItem = page.getByRole('link').element() const icon = container.querySelector('svg') expect(icon).toBeInTheDocument() @@ -61,7 +61,7 @@ describe('', () => { }) it('should meet a11y standards', async () => { - const { container } = render( + const { container } = await render( } label="Dashboard" href="#" /> ) const axeCheck = await runAxeCheck(container) diff --git a/packages/ui-side-nav-bar/src/SideNavBar/__tests__/SideNavBar.test.tsx b/packages/ui-side-nav-bar/src/SideNavBar/__tests__/SideNavBar.test.tsx index f5ded4f023..a6dec241dc 100644 --- a/packages/ui-side-nav-bar/src/SideNavBar/__tests__/SideNavBar.test.tsx +++ b/packages/ui-side-nav-bar/src/SideNavBar/__tests__/SideNavBar.test.tsx @@ -22,10 +22,9 @@ * SOFTWARE. */ -import { render, screen, waitFor } from '@testing-library/react' -import userEvent from '@testing-library/user-event' -import { vi } from 'vitest' -import '@testing-library/jest-dom' +import { render } from 'vitest-browser-react' +import { page, userEvent } from 'vitest/browser' +import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest' import { Badge } from '@instructure/ui-badge/latest' import { IconAdminLine, IconDashboardLine } from '@instructure/ui-icons' @@ -48,7 +47,7 @@ describe('', () => { }) it('should render', async () => { - const { container } = render( + const { container } = await render( ', () => { /> ) - const nav = screen.getByRole('navigation') + const nav = page.getByRole('navigation').element() const icons = container.querySelectorAll('svg') expect(icons.length).toBe(2) @@ -77,7 +76,7 @@ describe('', () => { }) it('should not crash with valid React elements', async () => { - render( + await render( ', () => { /> ) - const navElements = screen.getAllByRole('listitem') + const navElements = page.getByRole('listitem').elements() expect(navElements[0]).toHaveTextContent('test123') expect(navElements[1]).toHaveTextContent('Dashboard') }) it('should render a single semantic nav element', async () => { - render( + await render( ', () => { /> ) - const nav = screen.getByRole('navigation') - const navElements = screen.getAllByRole('listitem') + const nav = page.getByRole('navigation').element() + const navElements = page.getByRole('listitem').elements() expect(nav).toBeInTheDocument() expect(nav.tagName).toBe('NAV') @@ -125,7 +124,7 @@ describe('', () => { }) it('should render a semantic list for the nav content', async () => { - render( + await render( ', () => { /> ) - const list = screen.getAllByRole('list') - const navElements = screen.getAllByRole('listitem') + const list = page.getByRole('list').elements() + const navElements = page.getByRole('listitem').elements() expect(list[0].tagName).toBe('UL') expect(list.length).toBe(1) @@ -158,7 +157,7 @@ describe('', () => { }) it('should switch aria-expanded when the Toggle SideNavBar button is clicked', async () => { - render( + await render( ', () => { /> ) - const nav = screen.getByRole('navigation') - const toggleBtn = screen.getByRole('button') + const nav = page.getByRole('navigation').element() + const toggleBtn = page.getByRole('button').element() expect(nav).toHaveTextContent('Minimize SideNavBar') expect(toggleBtn).toHaveAttribute('aria-expanded', 'true') await userEvent.click(toggleBtn) - await waitFor(() => { - const updatedToggleBtn = screen.getByRole('button') - const updatedNav = screen.getByRole('navigation') + await vi.waitFor(() => { + const updatedToggleBtn = page.getByRole('button').element() + const updatedNav = page.getByRole('navigation').element() expect(updatedNav).toHaveTextContent('Expand SideNavBar') expect(updatedToggleBtn).toHaveAttribute('aria-expanded', 'false') @@ -200,7 +199,7 @@ describe('', () => { }) it('should meet a11y standards', async () => { - const { container } = render( + const { container } = await render( ', () => { }) it('should render an input and a list', async () => { - render( + await render( {getOptions()} ) - const input = screen.getByLabelText('Choose an option') - const listInitial = screen.queryByRole('listbox') + const input = page.getByLabelText('Choose an option').element() + const listInitial = page.getByRole('listbox').query() expect(listInitial).not.toBeInTheDocument() expect(input).toBeInTheDocument() await userEvent.click(input) - await waitFor(() => { - const list = screen.queryByRole('listbox') + await vi.waitFor(() => { + const list = page.getByRole('listbox').query() expect(list).toBeInTheDocument() }) }) it('should render groups', async () => { - render( + await render( ungrouped option one @@ -99,13 +107,13 @@ describe('', () => { ) - const input = screen.getByLabelText('Choose an option') + const input = page.getByLabelText('Choose an option').element() await userEvent.click(input) - await waitFor(() => { - const groups = screen.getAllByRole('group') - const labelOne = screen.getByText('Group one') + await vi.waitFor(() => { + const groups = page.getByRole('group').elements() + const labelOne = page.getByText('Group one').element() const labelOneID = labelOne.getAttribute('id') expect(groups.length).toBe(2) @@ -115,7 +123,7 @@ describe('', () => { }) it('should ignore invalid children', async () => { - render( + await render( valid @@ -123,12 +131,12 @@ describe('', () => {
invalid
) - const input = screen.getByLabelText('Choose an option') + const input = page.getByLabelText('Choose an option').element() await userEvent.click(input) - await waitFor(() => { - const invalidChild = screen.queryByText('invalid') + await vi.waitFor(() => { + const invalidChild = page.getByText('invalid').query() expect(invalidChild).not.toBeInTheDocument() }) @@ -136,57 +144,59 @@ describe('', () => { it('should fire onFocus when input gains focus', async () => { const onFocus = vi.fn() - render( + await render( {getOptions()} ) - const input = screen.getByLabelText('Choose an option') + const input = page.getByLabelText('Choose an option').element() input.focus() - await waitFor(() => { + await vi.waitFor(() => { expect(onFocus).toHaveBeenCalled() }) }) describe('input', () => { it('should render with a custom id if given', async () => { - render() - const input = screen.getByLabelText('Choose an option') + await render( + + ) + const input = page.getByLabelText('Choose an option').element() expect(input).toHaveAttribute('id', 'customSelect') }) it('should always render readonly', async () => { - render( + await render( ) - const input = screen.getByLabelText('Choose an option') + const input = page.getByLabelText('Choose an option').element() expect(input).toHaveAttribute('readonly') expect(input).not.toHaveAttribute('disabled') }) it('should render disabled when interaction="disabled"', async () => { - render( + await render( ) - const input = screen.getByLabelText('Choose an option') + const input = page.getByLabelText('Choose an option').element() expect(input).toHaveAttribute('disabled') expect(input).not.toHaveAttribute('readonly') }) it('should render required when isRequired={true}', async () => { - render() - const input = screen.getByLabelText('Choose an option *') + await render() + const input = page.getByLabelText('Choose an option *').element() expect(input).toHaveAttribute('required') }) it('should allow assistive text', async () => { - render( + await render( ', () => { {getOptions()} ) - const input = screen.getByLabelText('Choose an option') - const assistiveText = screen.getByText('hello world') + const input = page.getByLabelText('Choose an option').element() + const assistiveText = page.getByText('hello world').element() const assistiveTextID = assistiveText.getAttribute('id') expect(input).toHaveAttribute('aria-describedby', assistiveTextID) }) it('should allow custom props to pass through', async () => { - render( + await render( {getOptions()} ) - const input = screen.getByLabelText('Choose an option') + const input = page.getByLabelText('Choose an option').element() expect(input).toHaveAttribute('data-custom-attr', 'true') }) @@ -215,12 +225,12 @@ describe('', () => { it('should provide a ref to the input element', async () => { const inputRef = vi.fn() - render( + await render( {getOptions()} ) - const input = screen.getByLabelText('Choose an option') + const input = page.getByLabelText('Choose an option').element() expect(inputRef).toHaveBeenCalledWith(input) }) @@ -231,7 +241,7 @@ describe('', () => { )) - render( + await render( ', () => { ) - const input = screen.getByLabelText('Choose an option') + const input = page.getByLabelText('Choose an option').element() await userEvent.click(input) - await waitFor(() => { - const optionIcons = screen.getAllByTestId('option-icon') + await vi.waitFor(() => { + const optionIcons = page.getByTestId('option-icon').elements() expect(optionIcons.length).toBe(2) expect(renderBeforeLabel).toHaveBeenCalledTimes(2) @@ -284,17 +294,17 @@ describe('', () => { describe('list', () => { it('should set aria-disabled on options when isDisabled={true}', async () => { - render( + await render( {getOptions(defaultOptions[2])} ) - const input = screen.getByLabelText('Choose an option') + const input = page.getByLabelText('Choose an option').element() await userEvent.click(input) - await waitFor(() => { - const options = screen.getAllByRole('option') + await vi.waitFor(() => { + const options = page.getByRole('option').elements() expect(options[0]).not.toHaveAttribute('aria-disabled') expect(options[2]).toHaveAttribute('aria-disabled', 'true') @@ -304,17 +314,17 @@ describe('', () => { it('should provide a ref to the list element', async () => { const listRef = vi.fn() - render( + await render( {getOptions()} ) - const input = screen.getByLabelText('Choose an option') + const input = page.getByLabelText('Choose an option').element() await userEvent.click(input) - await waitFor(() => { - const listbox = screen.getByRole('listbox') + await vi.waitFor(() => { + const listbox = page.getByRole('listbox').element() expect(listRef).toHaveBeenCalledWith(listbox) }) @@ -340,18 +350,20 @@ describe('', () => { ) } - it('should clear selection if selected option does not exist in updated options', () => { + it('should clear selection if selected option does not exist in updated options', async () => { const { rerender } = renderSimpleSelect(initialOptions) - const input = screen.getByRole('combobox', { name: 'Choose an option' }) + const input = page + .getByRole('combobox', { name: 'Choose an option' }) + .element() fireEvent.click(input) - const fooOption = screen.getByRole('option', { name: 'foo' }) + const fooOption = page.getByRole('option', { name: 'foo' }).element() fireEvent.click(fooOption) expect(input).toHaveValue('foo') - rerender( + await rerender( {getOptions(updatedOptions)} @@ -360,18 +372,20 @@ describe('', () => { expect(input).toHaveValue('') }) - it('should persist selected option if it exists in updated options', () => { + it('should persist selected option if it exists in updated options', async () => { const { rerender } = renderSimpleSelect(initialOptions) - const input = screen.getByRole('combobox', { name: 'Choose an option' }) + const input = page + .getByRole('combobox', { name: 'Choose an option' }) + .element() fireEvent.click(input) - const barOption = screen.getByRole('option', { name: 'bar' }) + const barOption = page.getByRole('option', { name: 'bar' }).element() fireEvent.click(barOption) expect(input).toHaveValue('bar') - rerender( + await rerender( {getOptions(updatedOptions)} diff --git a/packages/ui-source-code-editor/src/SourceCodeEditor/__tests__/SourceCodeEditor.test.tsx b/packages/ui-source-code-editor/src/SourceCodeEditor/__tests__/SourceCodeEditor.test.tsx index 4726b0d33c..7be1456f84 100644 --- a/packages/ui-source-code-editor/src/SourceCodeEditor/__tests__/SourceCodeEditor.test.tsx +++ b/packages/ui-source-code-editor/src/SourceCodeEditor/__tests__/SourceCodeEditor.test.tsx @@ -21,18 +21,17 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ -import { render, screen, waitFor } from '@testing-library/react' -import userEvent from '@testing-library/user-event' -import { vi } from 'vitest' import type { MockInstance } from 'vitest' -import '@testing-library/jest-dom' +import { render } from 'vitest-browser-react' +import { page, userEvent } from 'vitest/browser' +import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest' import { SourceCodeEditor } from '@instructure/ui-source-code-editor/latest' describe('', () => { describe('syntax highlight', () => { it('should highlight jsx code', async () => { - const { container } = render( + const { container } = await render( ', () => { }) it('should link editor element to label using aria-labelledby attribute', async () => { - const { container } = render( + const { container } = await render( ', () => { }) it('should be applied on load', async () => { - render() - const input = screen.getByRole('textbox') + await render() + const input = page.getByRole('textbox').element() expect(input).toHaveTextContent('hello') }) @@ -92,8 +91,8 @@ describe('', () => { describe('spellcheck', () => { it('should set `spellcheck="true"` on the input', async () => { - render() - const input = screen.getByRole('textbox') + await render() + const input = page.getByRole('textbox').element() expect(input).toHaveAttribute('spellcheck', 'true') }) @@ -102,7 +101,7 @@ describe('', () => { describe('readOnly', () => { it('should still update value when value prop changes', async () => { const onChange = vi.fn() - const { rerender } = render( + const { rerender } = await render( ', () => { onChange={onChange} /> ) - const input = screen.getByRole('textbox') + const input = page.getByRole('textbox').element() expect(input).not.toHaveTextContent('hello world') - rerender( + await rerender( ', () => { /> ) - const inputUpdated = screen.getByRole('textbox') + const inputUpdated = page.getByRole('textbox').element() expect(inputUpdated).toHaveTextContent('hello world') }) it('should still be focusable', async () => { let elementRef: SourceCodeEditor | null = null - render( + await render( ', () => { }} /> ) - const input = screen.getByRole('textbox') + const input = page.getByRole('textbox').element() elementRef!.focus() - await waitFor(() => { + await vi.waitFor(() => { expect(input).toHaveFocus() expect(document.activeElement).toBe(input) }) @@ -151,16 +150,16 @@ describe('', () => { describe('editable turned off', () => { it('should set `contenteditable` to false', async () => { - render() + await render() - const input = screen.getByRole('textbox') + const input = page.getByRole('textbox').element() expect(input).toHaveAttribute('contenteditable', 'false') }) it('should not be focusable', async () => { let elementRef: HTMLDivElement | null = null - render( + await render( ', () => { /> ) - const input = screen.getByRole('textbox') + const input = page.getByRole('textbox').element() elementRef!.focus() - await waitFor(() => { + await vi.waitFor(() => { expect(elementRef).not.toHaveFocus() expect(document.activeElement).not.toBe(input) }) @@ -183,7 +182,7 @@ describe('', () => { describe('lineNumbers', () => { it('should display line numbers', async () => { - const { container } = render( + const { container } = await render( ', () => { describe('foldGutter', () => { it('should display fold icons', async () => { - render( + await render( { @@ -214,14 +213,14 @@ describe('', () => { /> ) - const gutterIcon = screen.getByTitle('Fold line') + const gutterIcon = page.getByTitle('Fold line').element() expect(gutterIcon).toBeInTheDocument() expect(gutterIcon).toBeVisible() }) it('should fold lines on click', async () => { - const { container } = render( + const { container } = await render( { @@ -231,13 +230,13 @@ describe('', () => { /> ) const editor = container.querySelector('[class$="-codeEditor"]') - const gutterIcon = screen.getByTitle('Fold line') + const gutterIcon = page.getByTitle('Fold line').element() expect(gutterIcon).toBeInTheDocument() await userEvent.click(gutterIcon) - const unfoldIcons = screen.getAllByTitle('Unfold line') + const unfoldIcons = page.getByTitle('Unfold line').elements() expect(editor).not.toHaveTextContent("console.log('foo')") expect(unfoldIcons[1]).toBeVisible() @@ -246,7 +245,7 @@ describe('', () => { describe('highlightActiveLine', () => { it('should not highlight line by default', async () => { - const { container } = render( + const { container } = await render( ) const allLines = container.querySelectorAll('[class="cm-line"]')! @@ -255,7 +254,7 @@ describe('', () => { }) it('should highlight line when true', async () => { - const { container } = render( + const { container } = await render( ', () => { describe('highlightActiveLineGutter', () => { it('should not highlight gutter element by default', async () => { - const { container } = render( + const { container } = await render( ', () => { }) it('should highlight gutter element when true', async () => { - const { container } = render( + const { container } = await render( ', () => { describe('direction', () => { it('rtl should apply', async () => { - render( + await render( ) - const input = screen.getByRole('textbox') + const input = page.getByRole('textbox').element() expect(input).toHaveAttribute('dir', 'rtl') }) @@ -313,7 +312,7 @@ describe('', () => { describe('label', () => { it('should be inserted in the ScreenReaderContent', async () => { - const { container } = render( + const { container } = await render( ', () => { describe('elementRef', () => { it('should return with the root element', async () => { const elementRef = vi.fn() - const { container } = render( + const { container } = await render( ', () => { describe('containerRef', () => { it('should return with the root element', async () => { const containerRef = vi.fn() - const { container } = render( + const { container } = await render( ', () => { }) it('should render', async () => { - const { container } = render() + const { container } = await render( + + ) const spinner = container.querySelector('div[class*="-spinner"]') expect(spinner).toBeInTheDocument() }) it('should render the title prop text in the SVG element title', async () => { - const { container } = render() + const { container } = await render( + + ) const spinner = container.querySelector('div[class*="-spinner"]') expect(spinner).toHaveTextContent('Loading') }) it('should meet a11y standards', async () => { - const { container } = render() + const { container } = await render( + + ) const axeCheck = await runAxeCheck(container) expect(axeCheck).toBe(true) }) @@ -70,7 +76,7 @@ describe('', () => { I have translated {children}. ) - const { container } = render( + const { container } = await render( Loading} size="small" /> ) @@ -83,14 +89,14 @@ describe('', () => { describe('with the delay prop', () => { it('should delay rendering', async () => { - render() + await render() - expect(screen.queryByText('Loading')).not.toBeInTheDocument() + expect(page.getByText('Loading').query()).not.toBeInTheDocument() - await waitFor( + await vi.waitFor( async () => { - const title = await screen.findByText('Loading') - const icon = await screen.findByRole('img') + const title = await page.getByText('Loading').element() + const icon = await page.getByRole('img').element() expect(title).toBeInTheDocument() expect(icon).toBeInTheDocument() diff --git a/packages/ui-svg-images/src/InlineSVG/__tests__/InlineSVG.test.tsx b/packages/ui-svg-images/src/InlineSVG/__tests__/InlineSVG.test.tsx index ae805c6009..32c8c03a79 100644 --- a/packages/ui-svg-images/src/InlineSVG/__tests__/InlineSVG.test.tsx +++ b/packages/ui-svg-images/src/InlineSVG/__tests__/InlineSVG.test.tsx @@ -22,29 +22,29 @@ * SOFTWARE. */ -import { render } from '@testing-library/react' -import '@testing-library/jest-dom' +import { render } from 'vitest-browser-react' +import { describe, it, expect } from 'vitest' import { InlineSVG } from '../index.js' const SVG_SRC = `` describe('', () => { - it('should render', () => { - const { container } = render() + it('should render', async () => { + const { container } = await render() const svg = container.querySelector('svg') expect(svg).toBeInTheDocument() }) - it('should have role "presentation" when no title is provided', () => { - const { container } = render() + it('should have role "presentation" when no title is provided', async () => { + const { container } = await render() const svg = container.querySelector('svg') expect(svg).toHaveAttribute('role', 'presentation') }) - it('should have role "img" when a title is provided', () => { - const { container } = render( + it('should have role "img" when a title is provided', async () => { + const { container } = await render( ) const svg = container.querySelector('svg') @@ -52,8 +52,8 @@ describe('', () => { expect(svg).toHaveAttribute('role', 'img') }) - it('should add a group with a role "presentation', () => { - const { container } = render( + it('should add a group with a role "presentation', async () => { + const { container } = await render( ) const group = container.querySelector('g') @@ -61,30 +61,32 @@ describe('', () => { expect(group).toHaveAttribute('role', 'presentation') }) - it('should not render title when no title prop is provided', () => { - const { container } = render() + it('should not render title when no title prop is provided', async () => { + const { container } = await render() const title = container.querySelector('title') expect(title).not.toBeInTheDocument() }) - it('should render title when title prop is provided', () => { - const { container } = render() + it('should render title when title prop is provided', async () => { + const { container } = await render( + + ) const title = container.querySelector('title') expect(title).toBeInTheDocument() expect(title).toHaveTextContent('Test Title') }) - it('should not render description when no description prop is provided', () => { - const { container } = render() + it('should not render description when no description prop is provided', async () => { + const { container } = await render() const description = container.querySelector('desc') expect(description).not.toBeInTheDocument() }) - it('should render description when description prop is provided', () => { - const { container } = render( + it('should render description when description prop is provided', async () => { + const { container } = await render( ) const description = container.querySelector('desc') @@ -93,16 +95,16 @@ describe('', () => { expect(description).toHaveTextContent('testIconDesc') }) - it('should produce null for "labelledBy" when no title or desc are provided', () => { - const { container } = render() + it('should produce null for "labelledBy" when no title or desc are provided', async () => { + const { container } = await render() const svg = container.querySelector('svg') expect(svg).toBeInTheDocument() expect(svg).not.toHaveAttribute('aria-labelledby') }) - it('should properly join ids when both title and desc attributes are provided', () => { - const { container } = render( + it('should properly join ids when both title and desc attributes are provided', async () => { + const { container } = await render( ', () => { expect(ids.length).toBe(2) }) - it('should set focusable to false by default', () => { - const { container } = render() + it('should set focusable to false by default', async () => { + const { container } = await render() const svg = container.querySelector('svg') expect(svg).toHaveAttribute('focusable', 'false') }) - it('should allow focusable to be overridden', () => { - const { container } = render() + it('should allow focusable to be overridden', async () => { + const { container } = await render( + + ) const svg = container.querySelector('svg') expect(svg).toHaveAttribute('focusable', 'true') }) - it('should correctly parse hyphenated attributes like stroke-width', () => { + it('should correctly parse hyphenated attributes like stroke-width', async () => { const svgWithHyphenatedAttrs = `` - const { container } = render() + const { container } = await render( + + ) const svg = container.querySelector('svg') expect(svg).toHaveAttribute('stroke-width', '2') expect(svg).toHaveAttribute('stroke-linecap', 'round') }) - it('should correctly parse unquoted attribute values (non-standard format)', () => { + it('should correctly parse unquoted attribute values (non-standard format)', async () => { const svgWithUnquotedAttrs = `` - const { container } = render() + const { container } = await render() const svg = container.querySelector('svg') expect(svg).toHaveAttribute('stroke', 'currentColor') @@ -148,38 +154,38 @@ describe('', () => { }) describe('sanitization', () => { - it('strips ` - const { container } = render() + const { container } = await render() const group = container.querySelector('g[role="presentation"]') expect(group?.innerHTML).not.toContain(' { + it('strips on* event-handler attributes from inner SVG content', async () => { const malicious = `` - const { container } = render() + const { container } = await render() const group = container.querySelector('g[role="presentation"]') expect(group?.innerHTML.toLowerCase()).not.toContain('onload') }) - it('strips javascript: schemes from xlink:href', () => { + it('strips javascript: schemes from xlink:href', async () => { const malicious = `` - const { container } = render() + const { container } = await render() const group = container.querySelector('g[role="presentation"]') expect(group?.innerHTML.toLowerCase()).not.toContain('javascript:') }) - it('strips on* attributes from the outer element', () => { + it('strips on* attributes from the outer element', async () => { const malicious = `` - const { container } = render() + const { container } = await render() const svg = container.querySelector('svg') expect(svg).not.toHaveAttribute('onload') }) - it('preserves the SVG when src is benign', () => { + it('preserves the SVG when src is benign', async () => { const benign = `` - const { container } = render() + const { container } = await render() const svg = container.querySelector('svg') expect(svg).toHaveAttribute('viewBox', '0 0 24 24') expect(svg?.querySelector('path')).toHaveAttribute('d', 'M0 0L10 10') diff --git a/packages/ui-svg-images/src/InlineSVG/__tests__/sanitizeSvg.test.tsx b/packages/ui-svg-images/src/InlineSVG/__tests__/sanitizeSvg.test.tsx index 9dd6b02493..3b28fe4e4d 100644 --- a/packages/ui-svg-images/src/InlineSVG/__tests__/sanitizeSvg.test.tsx +++ b/packages/ui-svg-images/src/InlineSVG/__tests__/sanitizeSvg.test.tsx @@ -22,7 +22,7 @@ * SOFTWARE. */ -import '@testing-library/jest-dom' +import { describe, it, expect, afterEach } from 'vitest' import DOMPurifySingleton from 'dompurify' import { sanitizeSvg } from '../sanitizeSvg.js' diff --git a/packages/ui-svg-images/src/SVGIcon/__tests__/SVGIcon.test.tsx b/packages/ui-svg-images/src/SVGIcon/__tests__/SVGIcon.test.tsx index a8e3ba99b6..3038008659 100644 --- a/packages/ui-svg-images/src/SVGIcon/__tests__/SVGIcon.test.tsx +++ b/packages/ui-svg-images/src/SVGIcon/__tests__/SVGIcon.test.tsx @@ -22,43 +22,43 @@ * SOFTWARE. */ -import { render } from '@testing-library/react' -import '@testing-library/jest-dom' +import { render } from 'vitest-browser-react' +import { describe, it, expect } from 'vitest' import { SVGIcon } from '../index.js' const SVG_SRC = `` describe('', () => { it('should render', async () => { - const { container } = render() + const { container } = await render() const svg = container.querySelector('svg') expect(svg).toBeInTheDocument() }) it('should set rotate to 0 by default', async () => { - const { container } = render() + const { container } = await render() const svg = container.querySelector('svg') expect(svg).toHaveAttribute('rotate', '0') }) it('should allow rotate prop to be overridden', async () => { - const { container } = render() + const { container } = await render() const svg = container.querySelector('svg') expect(svg).toHaveAttribute('rotate', '90') }) it('should set size', async () => { - const { container, rerender } = render( + const { container, rerender } = await render( ) const svg = container.querySelector('svg') const largeFontSize = window.getComputedStyle(svg!).fontSize // set prop: size - rerender() + await rerender() const svgUpdated = container.querySelector('svg') const smallFontSize = window.getComputedStyle(svgUpdated!).fontSize diff --git a/packages/ui-table/src/Table/__tests__/Table.test.tsx b/packages/ui-table/src/Table/__tests__/Table.test.tsx index 01da6e853c..235a16db6f 100644 --- a/packages/ui-table/src/Table/__tests__/Table.test.tsx +++ b/packages/ui-table/src/Table/__tests__/Table.test.tsx @@ -23,16 +23,23 @@ */ import { Component } from 'react' -import { render, screen, waitFor } from '@testing-library/react' -import { MockInstance, vi } from 'vitest' -import { userEvent } from '@testing-library/user-event' import { Table } from '@instructure/ui-table/latest' import type { TableProps, TableColHeaderProps } from '@instructure/ui-table/latest' import { runAxeCheck } from '@instructure/ui-axe-check' -import '@testing-library/jest-dom' +import { render } from 'vitest-browser-react' +import { page, userEvent } from 'vitest/browser' +import { + describe, + it, + expect, + beforeEach, + afterEach, + vi, + MockInstance +} from 'vitest' describe('', async () => { let consoleErrorMock: MockInstance @@ -47,7 +54,7 @@ describe('
', async () => { }) const renderTable = (props?: TableProps) => - render( + await render(
'Test table'} {...props}> @@ -84,7 +91,7 @@ describe('
', async () => { layout: 'fixed', caption: () => 'Test table' }) - const table = screen.getByRole('table') + const table = page.getByRole('table').element() expect(table).toHaveStyle({ tableLayout: 'fixed' }) }) @@ -94,7 +101,7 @@ describe('
', async () => { hover: true, caption: () => 'Test table' }) - const tableRows = screen.getAllByRole('row') + const tableRows = page.getByRole('row').elements() tableRows.forEach((tableRow) => { expect(tableRow).not.toHaveAttribute('border-left', 'none') @@ -104,7 +111,7 @@ describe('
', async () => { it('sets the scope of column header to col', async () => { await renderTable() - const columnHeaders = screen.getAllByRole('columnheader') + const columnHeaders = page.getByRole('columnheader').elements() columnHeaders.forEach((columnHeader) => { expect(columnHeader).toHaveAttribute('scope', 'col') @@ -113,7 +120,7 @@ describe('
', async () => { it('sets the scope of row header to row', async () => { renderTable() - const rowHeaders = screen.getAllByRole('rowheader') + const rowHeaders = page.getByRole('rowheader').elements() rowHeaders.forEach((rowHeader) => { expect(rowHeader).toHaveAttribute('scope', 'row') @@ -125,7 +132,7 @@ describe('
', async () => { layout: 'stacked', caption: () => 'Test table' }) - const stackedTable = screen.getByRole('table') + const stackedTable = page.getByRole('table').element() expect(stackedTable).toBeInTheDocument() expect(stackedTable).toHaveTextContent('RowHeader') @@ -134,29 +141,29 @@ describe('
', async () => { }) it('can handle non-existent head in stacked layout', async () => { - render( + await render(
'Test table'} layout="stacked">
) - const stackedTable = screen.getByRole('table') + const stackedTable = page.getByRole('table').element() expect(stackedTable).toBeInTheDocument() }) it('can handle empty head in stacked layout', async () => { - render( + await render( 'Test table'} layout="stacked">
) - const stackedTable = screen.getByRole('table') + const stackedTable = page.getByRole('table').element() expect(stackedTable).toBeInTheDocument() }) it('can handle invalid header in stacked layout', async () => { - render( + await render( 'Test table'} layout="stacked"> @@ -181,14 +188,14 @@ describe('
', async () => {
) - const stackedTable = screen.getByRole('table') + const stackedTable = page.getByRole('table').element() expect(stackedTable).toBeInTheDocument() expect(stackedTable).not.toHaveTextContent('Foo') }) it('does not crash for invalid children in stacked layout', async () => { - render( + await render( 'Test table'} layout="stacked"> test1 test @@ -220,7 +227,7 @@ describe('
', async () => {
) - const table = screen.getByRole('table') + const table = page.getByRole('table').element() expect(table).toBeInTheDocument() expect(table).toHaveTextContent('Foo') @@ -232,7 +239,7 @@ describe('', async () => { handlers = {}, layout: TableProps['layout'] = 'auto' ) => - render( + await render(
'Sortable table'} layout={layout}> @@ -281,11 +288,11 @@ describe('
', async () => { onRequestSort } ) - const button = screen.getByRole('button', { name: 'Foo' }) + const button = page.getByRole('button', { name: 'Foo' }).element() await userEvent.click(button) - await waitFor(() => { + await vi.waitFor(() => { expect(onRequestSort).toHaveBeenCalledTimes(1) }) }) @@ -301,12 +308,12 @@ describe('
', async () => { }, 'stacked' ) - const input = screen.getByRole('combobox') + const input = page.getByRole('combobox').element() await userEvent.click(input) - await waitFor(async () => { - const options = screen.getAllByRole('option') + await vi.waitFor(async () => { + const options = page.getByRole('option').elements() expect(options[0]).toHaveTextContent('Custom Text') expect(options[1]).toHaveTextContent('bar') @@ -334,7 +341,7 @@ describe('
', async () => { id: 'id', sortDirection: 'ascending' }) - const header = screen.getByRole('columnheader', { name: 'Foo' }) + const header = page.getByRole('columnheader', { name: 'Foo' }).element() expect(header).toHaveAttribute('aria-sort', 'ascending') }) @@ -344,7 +351,7 @@ describe('
', async () => { id: 'id', sortDirection: 'descending' }) - const header = screen.getByRole('columnheader', { name: 'Foo' }) + const header = page.getByRole('columnheader', { name: 'Foo' }).element() expect(header).toHaveAttribute('aria-sort', 'descending') }) @@ -353,7 +360,7 @@ describe('
', async () => { const caption = vi.fn((header: string, direction: string) => header ? `Movies, sorted by ${header} ${direction}` : 'Movies' ) - const { container } = render( + const { container } = await render(
@@ -384,7 +391,7 @@ describe('
', async () => { }) describe('when using custom components', () => { - it('should render wrapper HOCs', () => { + it('should render wrapper HOCs', async () => { class CustomTableCell extends Component { render() { return {this.props.children} @@ -401,7 +408,7 @@ describe('
', async () => { ) } } - const table = render( + const table = await render(
'Test custom table'}> @@ -420,7 +427,7 @@ describe('
', async () => {
) - const stackedTable = screen.getByRole('table') + const stackedTable = page.getByRole('table').element() expect(stackedTable).toBeInTheDocument() const { container } = table @@ -429,7 +436,7 @@ describe('', async () => { expect(container).toHaveTextContent('9.3') }) - it('should render fully custom components', () => { + it('should render fully custom components', async () => { class CustomTableCell extends Component { render() { return @@ -442,7 +449,7 @@ describe('
{this.props.children}
', async () => { } } - const table = render( + const table = await render(
'Test custom table'}> @@ -460,7 +467,7 @@ describe('
', async () => {
) - const stackedTable = screen.getByRole('table') + const stackedTable = page.getByRole('table').element() expect(stackedTable).toBeInTheDocument() const { container } = table diff --git a/packages/ui-tabs/src/Tabs/__tests__/Panel.test.tsx b/packages/ui-tabs/src/Tabs/__tests__/Panel.test.tsx index 8f076db8e9..620d893341 100644 --- a/packages/ui-tabs/src/Tabs/__tests__/Panel.test.tsx +++ b/packages/ui-tabs/src/Tabs/__tests__/Panel.test.tsx @@ -22,23 +22,25 @@ * SOFTWARE. */ -import { render, screen } from '@testing-library/react' +import { render } from 'vitest-browser-react' +import { page } from 'vitest/browser' +import { describe, it, expect } from 'vitest' import { TabsPanel as Panel } from '@instructure/ui-tabs/latest' describe('', () => { it('should render children', async () => { - render( + await render( Panel contents ) - const children = screen.getByText('Panel contents') + const children = page.getByText('Panel contents').element() expect(children).toBeInTheDocument() }) it('should have appropriate role attribute', async () => { - const { container } = render( + const { container } = await render( Panel contents @@ -49,7 +51,7 @@ describe('', () => { }) it('should not have tabIndex 0 by default', async () => { - const { container } = render( + const { container } = await render( Panel contents @@ -60,7 +62,7 @@ describe('', () => { }) it('should allow custom tabIndex', async () => { - const { container } = render( + const { container } = await render( Panel contents diff --git a/packages/ui-tabs/src/Tabs/__tests__/Tab.test.tsx b/packages/ui-tabs/src/Tabs/__tests__/Tab.test.tsx index f43a0c551e..571a30d86b 100644 --- a/packages/ui-tabs/src/Tabs/__tests__/Tab.test.tsx +++ b/packages/ui-tabs/src/Tabs/__tests__/Tab.test.tsx @@ -22,99 +22,98 @@ * SOFTWARE. */ -import { render, screen, waitFor } from '@testing-library/react' -import { vi } from 'vitest' -import userEvent from '@testing-library/user-event' -import '@testing-library/jest-dom' +import { render } from 'vitest-browser-react' +import { page, userEvent } from 'vitest/browser' +import { describe, it, expect, vi } from 'vitest' import { TabsTab as Tab } from '@instructure/ui-tabs/latest' describe('', () => { it('should render children', async () => { - render( + await render( Tab Label ) - const children = screen.getByText('Tab Label') + const children = page.getByText('Tab Label').element() expect(children).toBeInTheDocument() }) it('should have appropriate role attribute', async () => { - render( + await render( Tab Label ) - const tab = screen.getByRole('tab') + const tab = page.getByRole('tab').element() expect(tab).toBeInTheDocument() }) it('should have appropriate aria attributes', async () => { - render( + await render( Tab Label ) - const tab = screen.getByRole('tab') + const tab = page.getByRole('tab').element() expect(tab).not.toHaveAttribute('aria-selected') expect(tab).not.toHaveAttribute('aria-disabled') }) it('should set the aria-selected attribute', async () => { - render( + await render( Tab Label ) - const tab = screen.getByRole('tab') + const tab = page.getByRole('tab').element() expect(tab).toHaveAttribute('aria-selected', 'true') }) it('should set the aria-disabled attribute', async () => { - render( + await render( Tab Label ) - const tab = screen.getByRole('tab') + const tab = page.getByRole('tab').element() expect(tab).toHaveAttribute('aria-disabled', 'true') }) it('should set the tabindex to 0 when selected', async () => { - render( + await render( Tab Label ) - const tab = screen.getByRole('tab') + const tab = page.getByRole('tab').element() expect(tab).toHaveAttribute('tabindex', '0') }) it('should not set the tabindex when not selected', async () => { - render( + await render( Tab Label ) - const tab = screen.getByRole('tab') + const tab = page.getByRole('tab').element() expect(tab).not.toHaveAttribute('tabindex') }) it('should remove the tabindex attribute when disabled', async () => { - render( + await render( Tab Label ) - const tab = screen.getByRole('tab') + const tab = page.getByRole('tab').element() expect(tab).not.toHaveAttribute('tabindex') }) @@ -123,16 +122,16 @@ describe('', () => { const onClick = vi.fn() const index = 2 - render( + await render( Tab Label ) - const tab = screen.getByRole('tab') + const tab = page.getByRole('tab').element() await userEvent.click(tab) - await waitFor(() => { + await vi.waitFor(() => { expect(onClick).toHaveBeenCalled() const args = onClick.mock.calls[0][1] @@ -143,16 +142,16 @@ describe('', () => { it('should NOT call onClick when clicked and tab is disabled', async () => { const onClick = vi.fn() - render( + await render( Tab Label ) - const tab = screen.getByRole('tab') + const tab = page.getByRole('tab').element() await userEvent.click(tab) - await waitFor(() => { + await vi.waitFor(() => { expect(onClick).not.toHaveBeenCalled() }) }) @@ -161,7 +160,7 @@ describe('', () => { const onKeyDown = vi.fn() const index = 2 - render( + await render( ', () => { Tab Label ) - const tab = screen.getByRole('tab') + const tab = page.getByRole('tab').element() await userEvent.type(tab, '{enter}') - await waitFor(() => { + await vi.waitFor(() => { expect(onKeyDown).toHaveBeenCalled() const args = onKeyDown.mock.calls[0][1] @@ -187,7 +186,7 @@ describe('', () => { it('should NOT call onKeyDown when keys are pressed and tab is disabled', async () => { const onKeyDown = vi.fn() - render( + await render( ', () => { Tab Label ) - const tab = screen.getByRole('tab') + const tab = page.getByRole('tab').element() await userEvent.type(tab, '{enter}') - await waitFor(() => { + await vi.waitFor(() => { expect(onKeyDown).not.toHaveBeenCalled() }) }) diff --git a/packages/ui-tabs/src/Tabs/__tests__/Tabs.test.tsx b/packages/ui-tabs/src/Tabs/__tests__/Tabs.test.tsx index 78d2eb378a..4897a97786 100644 --- a/packages/ui-tabs/src/Tabs/__tests__/Tabs.test.tsx +++ b/packages/ui-tabs/src/Tabs/__tests__/Tabs.test.tsx @@ -23,11 +23,10 @@ */ import { useState } from 'react' -import { render, screen, waitFor } from '@testing-library/react' -import { vi } from 'vitest' import type { MockInstance } from 'vitest' -import userEvent from '@testing-library/user-event' -import '@testing-library/jest-dom' +import { render } from 'vitest-browser-react' +import { page, userEvent } from 'vitest/browser' +import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest' import { runAxeCheck } from '@instructure/ui-axe-check' import { Tabs } from '@instructure/ui-tabs/latest' @@ -89,8 +88,8 @@ describe('', () => { consoleWarningMock.mockRestore() }) - it('should render the correct number of panels', () => { - const { container } = render( + it('should render the correct number of panels', async () => { + const { container } = await render( Tab 1 content Tab 2 content @@ -105,7 +104,7 @@ describe('', () => { }) it('should render with null children', async () => { - const { container } = render( + const { container } = await render( Tab 1 content Tab 2 content @@ -121,13 +120,13 @@ describe('', () => { }) it('should be okay with rendering without any children', async () => { - render() + await render() expect(consoleErrorMock).not.toHaveBeenCalled() }) it('should render correct number of tabs', async () => { - render( + await render( Tab 1 content Tab 2 content @@ -136,13 +135,13 @@ describe('', () => { ) - const tabs = screen.getAllByRole('tab') + const tabs = page.getByRole('tab').elements() expect(tabs.length).toBe(3) }) - it('should render same content for other tabs as for the active one', () => { - const { container } = render( + it('should render same content for other tabs as for the active one', async () => { + const { container } = await render( CONTENT @@ -154,12 +153,12 @@ describe('', () => { ) - const tabContent = screen.getByText('CONTENT') + const tabContent = page.getByText('CONTENT').element() expect(container).toBeInTheDocument() expect(tabContent).toBeInTheDocument() - const childContent = screen.queryByText('Child') + const childContent = page.getByText('Child').query() expect(childContent).toBeNull() }) @@ -167,24 +166,26 @@ describe('', () => { it('should render the same content in second tab when selected', async () => { const onIndexChange = vi.fn() - const { container } = render() + const { container } = await render( + + ) expect(container).toBeInTheDocument() - const secondTab = screen.getAllByRole('tab')[1] + const secondTab = page.getByRole('tab').elements()[1] await userEvent.click(secondTab) - await waitFor(() => { + await vi.waitFor(() => { expect(onIndexChange).toHaveBeenCalledWith(1) }) - const panelContent = screen.queryByText('CONTENT') + const panelContent = page.getByText('CONTENT').query() expect(panelContent).toBeInTheDocument() }) - it('should warn if multiple active tabs exist', () => { - const { container } = render( + it('should warn if multiple active tabs exist', async () => { + const { container } = await render( Tab 1 content @@ -206,7 +207,7 @@ describe('', () => { }) it('should default to selecting the first tab', async () => { - const { container } = render( + const { container } = await render( {tab1Content} {tab2Content} @@ -220,14 +221,14 @@ describe('', () => { ) expect(panelsContainer).toHaveTextContent(tab1Content) - expect(screen.getByText(tab1Content)).toBeVisible() + expect(page.getByText(tab1Content).element()).toBeVisible() expect(panelsContainer).not.toHaveTextContent(tab2Content) expect(panelsContainer).not.toHaveTextContent(tab3Content) }) it('should honor the isSelected prop', async () => { - const { container } = render( + const { container } = await render( {tab1Content} @@ -243,14 +244,14 @@ describe('', () => { ) expect(panelsContainer).toHaveTextContent(tab2Content) - expect(screen.getByText(tab2Content)).toBeVisible() + expect(page.getByText(tab2Content).element()).toBeVisible() expect(panelsContainer).not.toHaveTextContent(tab1Content) expect(panelsContainer).not.toHaveTextContent(tab3Content) }) it('should not allow selecting a disabled tab', async () => { - const { container } = render( + const { container } = await render( Tab 1 content Tab 2 content @@ -265,7 +266,7 @@ describe('', () => { const panels = container.querySelectorAll('[role="tabpanel"]') expect(panelsContainer).toHaveTextContent(tab1Content) - expect(screen.getByText(tab1Content)).toBeVisible() + expect(page.getByText(tab1Content).element()).toBeVisible() expect(panelsContainer).not.toHaveTextContent(tab2Content) expect(panelsContainer).not.toHaveTextContent(tab3Content) @@ -279,7 +280,7 @@ describe('', () => { it('should call onRequestTabChange when selection changes via click', async () => { const onChange = vi.fn() - render( + await render( Tab 1 content @@ -292,11 +293,11 @@ describe('', () => { ) - const secondTab = screen.getByText('Second Tab') + const secondTab = page.getByText('Second Tab').element() await userEvent.click(secondTab) - await waitFor(() => { + await vi.waitFor(() => { expect(onChange).toHaveBeenCalled() const args = onChange.mock.calls[0][1] @@ -307,7 +308,7 @@ describe('', () => { }) it('should focus the selected tab when shouldFocusOnRender is set', async () => { - render( + await render( Tab 1 content @@ -318,16 +319,16 @@ describe('', () => { ) - const secondTab = screen.getByText('Second Tab') + const secondTab = page.getByText('Second Tab').element() - await waitFor(() => { + await vi.waitFor(() => { expect(document.activeElement).toBe(secondTab) }) }) it('should not call onRequestTabChange when clicking a disabled tab', async () => { const onChange = vi.fn() - render( + await render( Tab 1 content Tab 2 content @@ -336,17 +337,17 @@ describe('', () => { ) - const thirdTab = screen.getByText('Third Tab') + const thirdTab = page.getByText('Third Tab').element() await userEvent.click(thirdTab) - await waitFor(() => { + await vi.waitFor(() => { expect(onChange).not.toHaveBeenCalled() }) }) it('should meet a11y standards when set to the secondary variant', async () => { - const { container } = render( + const { container } = await render( Tab 1 content Tab 2 content @@ -361,7 +362,7 @@ describe('', () => { }) it('should meet a11y standards when set to the default variant', async () => { - const { container } = render( + const { container } = await render( Tab 1 content Tab 2 content @@ -376,7 +377,7 @@ describe('', () => { }) it('should link tabs with the corresponding panels via ids', async () => { - const { container } = render( + const { container } = await render( Tab 1 content Tab 2 content @@ -385,7 +386,7 @@ describe('', () => { ) - const firstTab = screen.getByText('First Tab') + const firstTab = page.getByText('First Tab').element() const firstPanel = container.querySelectorAll('[role="tabpanel"]')[0] expect(firstTab).toHaveAttribute('aria-controls', firstPanel.id) @@ -394,7 +395,7 @@ describe('', () => { describe('with duplicate-named tabs', () => { it('should still render the correct number of panels', async () => { - const { container } = render( + const { container } = await render( Contents of first tab. Contents of second tab. @@ -411,7 +412,7 @@ describe('', () => { describe('with nodes as tab titles', () => { it('should still render the correct number of panels', async () => { - const { container } = render( + const { container } = await render( }>Contents of first tab. }> diff --git a/packages/ui-tag/src/Tag/__tests__/Tag.test.tsx b/packages/ui-tag/src/Tag/__tests__/Tag.test.tsx index f92007deab..fdb2625848 100644 --- a/packages/ui-tag/src/Tag/__tests__/Tag.test.tsx +++ b/packages/ui-tag/src/Tag/__tests__/Tag.test.tsx @@ -23,10 +23,9 @@ */ import { ComponentType } from 'react' -import { render, screen, waitFor } from '@testing-library/react' -import { userEvent } from '@testing-library/user-event' -import '@testing-library/jest-dom' -import { vi } from 'vitest' +import { render } from 'vitest-browser-react' +import { page, userEvent } from 'vitest/browser' +import { describe, it, expect, beforeAll, afterAll, vi } from 'vitest' import { runAxeCheck } from '@instructure/ui-axe-check' import type { ViewProps } from '@instructure/ui-view/latest' @@ -56,21 +55,23 @@ describe('', async () => { }) it('should display text', async () => { - render() - const tag = screen.getByText('Summer') + await render() + const tag = page.getByText('Summer').element() expect(tag).toBeInTheDocument() }) it('should render as a button and respond to onClick event', async () => { const onClick = vi.fn() - render() + await render( + + ) - const button = screen.getByTestId('summer-button') + const button = page.getByTestId('summer-button').element() await userEvent.click(button) - await waitFor(() => { + await vi.waitFor(() => { expect(onClick).toHaveBeenCalledTimes(1) expect(button.tagName).toBe('BUTTON') }) @@ -78,7 +79,7 @@ describe('', async () => { it('should render a close icon when it is dismissible and clickable', async () => { const onClick = vi.fn() - const { container } = render( + const { container } = await render( ) const icon = container.querySelector('svg') @@ -87,7 +88,7 @@ describe('', async () => { }) it('should meet a11y standards', async () => { - const { container } = render() + const { container } = await render() const axeCheck = await runAxeCheck(container) expect(axeCheck).toBe(true) @@ -110,7 +111,7 @@ describe('', async () => { .spyOn(console, 'error') .mockImplementation(() => {}) - render() + await render() const warning = `Warning: [Tag] prop '${prop}' is not allowed.` expect(consoleError.mock.calls[0][0]).toBe(warning) @@ -121,7 +122,7 @@ describe('', async () => { const props = { [prop]: allowedProps[prop] } const consoleError = vi.spyOn(console, 'error') - render() + await render() expect(consoleError).not.toHaveBeenCalled() consoleError.mockRestore() diff --git a/packages/ui-text-area/src/TextArea/__tests__/TextArea.test.tsx b/packages/ui-text-area/src/TextArea/__tests__/TextArea.test.tsx index ce70deab46..25498c82ff 100644 --- a/packages/ui-text-area/src/TextArea/__tests__/TextArea.test.tsx +++ b/packages/ui-text-area/src/TextArea/__tests__/TextArea.test.tsx @@ -22,13 +22,13 @@ * SOFTWARE. */ -import { fireEvent, render, screen, waitFor } from '@testing-library/react' -import { vi } from 'vitest' -import userEvent from '@testing-library/user-event' import { runAxeCheck } from '@instructure/ui-axe-check' import { TextArea } from '@instructure/ui-text-area/latest' import type { TextAreaElement } from '../v2/index' -import '@testing-library/jest-dom' +import { fireEvent } from '@testing-library/dom' +import { render } from 'vitest-browser-react' +import { page, userEvent } from 'vitest/browser' +import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest' describe('TextArea', () => { let consoleWarningMock: ReturnType @@ -50,14 +50,18 @@ describe('TextArea', () => { }) it('should accept a default value', async () => { - render(