From 6836e997305bbb5d899e1e5de196f584685456ad Mon Sep 17 00:00:00 2001 From: Kyle Tsang <6854874+kyletsang@users.noreply.github.com> Date: Mon, 22 Jul 2024 23:20:41 -0700 Subject: [PATCH 1/5] fix(Offcanvas): do not trigger Navbar onToggle when closing (#6829) --- src/NavbarOffcanvas.tsx | 9 ++++++++- src/Offcanvas.tsx | 17 ++--------------- 2 files changed, 10 insertions(+), 16 deletions(-) diff --git a/src/NavbarOffcanvas.tsx b/src/NavbarOffcanvas.tsx index dee2c4c8fc..a24d4f0088 100644 --- a/src/NavbarOffcanvas.tsx +++ b/src/NavbarOffcanvas.tsx @@ -1,20 +1,27 @@ import * as React from 'react'; import { useContext } from 'react'; +import useEventCallback from '@restart/hooks/useEventCallback'; import Offcanvas, { OffcanvasProps } from './Offcanvas'; import NavbarContext from './NavbarContext'; export type NavbarOffcanvasProps = Omit; const NavbarOffcanvas = React.forwardRef( - (props, ref) => { + ({ onHide, ...props }, ref) => { const context = useContext(NavbarContext); + const handleHide = useEventCallback(() => { + context?.onToggle?.(); + onHide?.(); + }); + return ( ); }, diff --git a/src/Offcanvas.tsx b/src/Offcanvas.tsx index c272c3bf05..2035d80c5e 100644 --- a/src/Offcanvas.tsx +++ b/src/Offcanvas.tsx @@ -3,14 +3,7 @@ import useBreakpoint from '@restart/hooks/useBreakpoint'; import useEventCallback from '@restart/hooks/useEventCallback'; import PropTypes from 'prop-types'; import * as React from 'react'; -import { - useCallback, - useContext, - useEffect, - useMemo, - useRef, - useState, -} from 'react'; +import { useCallback, useEffect, useMemo, useRef, useState } from 'react'; import BaseModal, { ModalProps as BaseModalProps, ModalHandle, @@ -19,7 +12,6 @@ import Fade from './Fade'; import OffcanvasBody from './OffcanvasBody'; import OffcanvasToggling from './OffcanvasToggling'; import ModalContext from './ModalContext'; -import NavbarContext from './NavbarContext'; import OffcanvasHeader from './OffcanvasHeader'; import OffcanvasTitle from './OffcanvasTitle'; import { BsPrefixRefForwardingComponent } from './helpers'; @@ -235,8 +227,8 @@ const Offcanvas: BsPrefixRefForwardingComponent<'div', OffcanvasProps> = ) => { const modalManager = useRef(); bsPrefix = useBootstrapPrefix(bsPrefix, 'offcanvas'); - const { onToggle } = useContext(NavbarContext) || {}; const [showOffcanvas, setShowOffcanvas] = useState(false); + const handleHide = useEventCallback(onHide); const hideResponsiveOffcanvas = useBreakpoint( (responsive as any) || 'xs', @@ -249,11 +241,6 @@ const Offcanvas: BsPrefixRefForwardingComponent<'div', OffcanvasProps> = setShowOffcanvas(responsive ? show && !hideResponsiveOffcanvas : show); }, [show, responsive, hideResponsiveOffcanvas]); - const handleHide = useEventCallback(() => { - onToggle?.(); - onHide?.(); - }); - const modalContext = useMemo( () => ({ onHide: handleHide, From 0952140e2fb118537410c819d15eaedb423cdc0f Mon Sep 17 00:00:00 2001 From: Pablo <61226966+zarzas980@users.noreply.github.com> Date: Tue, 23 Jul 2024 08:23:56 +0200 Subject: [PATCH 2/5] docs: fix mistake with grid example (#6826) --- www/docs/examples/Grid/Ordering.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/www/docs/examples/Grid/Ordering.js b/www/docs/examples/Grid/Ordering.js index 667a6864ed..33b8aa72d7 100644 --- a/www/docs/examples/Grid/Ordering.js +++ b/www/docs/examples/Grid/Ordering.js @@ -7,8 +7,8 @@ function OrderingExample() { First, but unordered - Second, but last - Third, but second + Second, but last + Third, but second ); From 9b8bcd783c65632f43cb3fc544547a93ed670c1b Mon Sep 17 00:00:00 2001 From: Box Date: Tue, 23 Jul 2024 02:26:19 -0400 Subject: [PATCH 3/5] fix(Fade): fix ref warning for react 18.3+ (#6820) --- src/Fade.tsx | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/Fade.tsx b/src/Fade.tsx index c5d5a79714..1595246a56 100644 --- a/src/Fade.tsx +++ b/src/Fade.tsx @@ -8,6 +8,7 @@ import Transition, { ENTERING, } from 'react-transition-group/Transition'; import { TransitionCallbacks } from '@restart/ui/types'; +import { getReactVersion } from '@restart/ui/utils'; import transitionEndListener from './transitionEndListener'; import triggerBrowserReflow from './triggerBrowserReflow'; import TransitionWrapper from './TransitionWrapper'; @@ -113,13 +114,16 @@ const Fade = React.forwardRef, FadeProps>( [onEnter], ); + const { major } = getReactVersion(); + const childRef = major >= 19 ? (children as any).props.ref : (children as any).ref; + return ( {(status: TransitionStatus, innerProps: Record) => React.cloneElement(children, { From 5cfa9895b52a68a6596cdea8822fffe985c0df66 Mon Sep 17 00:00:00 2001 From: Kyle Tsang <6854874+kyletsang@users.noreply.github.com> Date: Sat, 10 Aug 2024 21:18:40 -0700 Subject: [PATCH 4/5] chore: switch to vitest (#6832) --- .github/workflows/ci.yml | 23 +- package.json | 44 +- test/.eslintrc | 14 +- test/AccordionButtonSpec.tsx | 46 +- test/AccordionSpec.tsx | 111 +- test/AlertSpec.tsx | 104 +- test/BadgeSpec.tsx | 42 +- test/BootstrapModalManagerSpec.ts | 42 +- test/BreadcrumbItemSpec.tsx | 100 +- test/BreadcrumbSpec.tsx | 34 +- test/ButtonGroupSpec.tsx | 28 +- test/ButtonSpec.tsx | 87 +- test/ButtonToolbarSpec.tsx | 15 +- test/CardImgSpec.tsx | 37 +- test/CardSpec.tsx | 46 +- test/CarouselCaptionSpec.tsx | 28 +- test/CarouselSpec.tsx | 544 +++---- test/CloseButtonSpec.tsx | 38 +- test/ColSpec.tsx | 74 +- test/CollapseSpec.tsx | 126 +- test/ContainerSpec.tsx | 34 +- test/DropdownButtonSpec.tsx | 62 +- test/DropdownItemSpec.tsx | 79 +- test/DropdownMenuSpec.tsx | 129 +- test/DropdownMousedownSpec.tsx | 25 - test/DropdownSpec.tsx | 203 ++- test/DropdownToggleSpec.tsx | 32 +- test/FadeSpec.tsx | 76 +- test/FeedbackSpec.tsx | 32 +- test/FigureCaptionSpec.tsx | 27 +- test/FigureSpec.tsx | 55 +- test/FloatingLabelSpec.tsx | 27 +- test/FormCheckSpec.tsx | 187 ++- test/FormControlFeedbackSpec.tsx | 34 +- test/FormControlSpec.tsx | 98 +- test/FormGroupSpec.tsx | 40 +- test/FormLabelSpec.tsx | 91 +- test/FormRangeSpec.tsx | 34 +- test/FormSelectSpec.tsx | 68 +- test/FormSpec.tsx | 32 +- test/FormTextSpec.tsx | 31 +- test/ImageSpec.tsx | 48 +- test/InputGroupSpec.tsx | 27 +- test/ListGroupItemSpec.tsx | 131 +- test/ListGroupSpec.tsx | 67 +- test/ModalBodySpec.tsx | 25 +- test/ModalFooterSpec.tsx | 36 +- test/ModalHeaderSpec.tsx | 65 +- test/ModalSpec.tsx | 215 +-- test/ModalTitleSpec.tsx | 36 +- test/NavDropdownSpec.tsx | 46 +- test/NavItemSpec.tsx | 32 +- test/NavLinkSpec.tsx | 47 +- test/NavSpec.tsx | 97 +- test/NavbarBrandSpec.tsx | 21 +- test/NavbarOffcanvasSpec.tsx | 23 +- test/NavbarSpec.tsx | 191 ++- test/NavbarToggleSpec.tsx | 8 +- test/OffcanvasSpec.tsx | 125 +- test/OverlaySpec.tsx | 18 +- test/OverlayTriggerSpec.tsx | 302 ++-- test/PageItemSpec.tsx | 47 +- test/PaginationSpec.tsx | 22 +- test/PlaceholderButtonSpec.tsx | 10 +- test/PlaceholderSpec.tsx | 12 +- test/PopoverSpec.tsx | 22 +- test/ProgressBarSpec.tsx | 186 +-- test/RatioSpec.tsx | 38 +- test/RowSpec.tsx | 60 +- test/SpinnerSpec.tsx | 46 +- test/SplitButtonSpec.tsx | 90 +- test/StackSpec.tsx | 10 +- test/TabContentSpec.tsx | 4 +- test/TableSpec.tsx | 60 +- test/TabsSpec.tsx | 148 +- test/ThemeProviderSpec.tsx | 43 +- test/ToastBodySpec.tsx | 8 +- test/ToastContainerSpec.tsx | 15 +- test/ToastHeaderSpec.tsx | 19 +- test/ToastSpec.tsx | 127 +- test/ToggleButtonGroupSpec.tsx | 154 +- test/ToggleButtonSpec.tsx | 13 +- test/TooltipSpec.tsx | 18 +- test/createChainedFunctionSpec.ts | 34 +- test/createUtilityClassesSpec.ts | 47 +- test/getInitialPopperStylesSpec.ts | 6 +- test/{helpers.js => helpers.ts} | 13 +- test/helpersSpec.ts | 9 +- test/index.js | 63 - test/tsconfig.json | 2 +- test/useOverlayOffsetSpec.tsx | 11 +- vitest.config.ts | 21 + vitest.setup.ts | 4 + yarn.lock | 2159 +++++++++++++++------------- 94 files changed, 4019 insertions(+), 4041 deletions(-) delete mode 100644 test/DropdownMousedownSpec.tsx rename test/{helpers.js => helpers.ts} (67%) delete mode 100644 test/index.js create mode 100644 vitest.config.ts create mode 100644 vitest.setup.ts diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f347632c22..8832dbfec8 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -4,13 +4,9 @@ on: push: branches: - master - - bs3-dev - - bs4-dev pull_request: branches: - master - - bs3-dev - - bs4-dev permissions: contents: read @@ -21,7 +17,7 @@ jobs: runs-on: ${{ matrix.os }} strategy: matrix: - browser: [ChromeHeadless, FirefoxHeadless] + browser: [chromium, firefox] os: [ubuntu-latest, windows-latest, macOS-latest] steps: - name: Checkout @@ -33,25 +29,16 @@ jobs: node-version: 20.x cache: yarn - - name: Update Brew (macOS) - if: matrix.os == 'macOS-latest' - run: brew update - - - name: Install Chrome (macOS) - if: matrix.os == 'macOS-latest' && matrix.browser == 'ChromeHeadless' - run: brew install --cask google-chrome - - - name: Install Firefox (macOS) - if: matrix.os == 'macOS-latest' && matrix.browser == 'FirefoxHeadless' - run: brew install --cask firefox - - name: Install Dependencies run: yarn bootstrap env: YARN_CACHE_FOLDER: .cache/yarn + - name: Install Playwright Browsers + run: yarn playwright install --with-deps + - name: Run Tests - run: yarn test + run: yarn test --browser.name=${{ env.BROWSER }} --browser.headless env: BROWSER: ${{ matrix.browser }} diff --git a/package.json b/package.json index 8ef65e0571..d4c4ed659f 100644 --- a/package.json +++ b/package.json @@ -46,9 +46,9 @@ "prepublishOnly": "npm run build", "release": "rollout", "start": "yarn --cwd www start", - "tdd": "karma start", + "tdd": "vitest", "test": "npm run lint && npm run test-browser", - "test-browser": "cross-env NODE_ENV=test karma start --single-run", + "test-browser": "vitest --run", "prepare": "husky" }, "lint-staged": { @@ -81,22 +81,20 @@ "@babel/register": "^7.22.15", "@react-bootstrap/babel-preset": "^2.2.0", "@react-bootstrap/eslint-config": "^3.0.0", - "@testing-library/dom": "^10.1.0", + "@testing-library/dom": "^10.4.0", "@testing-library/react": "^16.0.0", - "@types/chai": "^4.3.16", "@types/invariant": "^2.2.37", "@types/mocha": "^10.0.6", "@types/prop-types": "^15.7.12", - "@types/react": "^18.2.66", - "@types/react-dom": "^18.2.22", - "@types/sinon": "^17.0.3", - "@types/sinon-chai": "^3.2.12", + "@types/react": "^18.3.3", + "@types/react-dom": "^18.3.0", "@types/warning": "^3.0.3", "@typescript-eslint/eslint-plugin": "^7.13.0", "@typescript-eslint/parser": "^7.13.0", + "@vitejs/plugin-react": "^4.3.1", + "@vitest/browser": "^2.0.4", "babel-loader": "^9.1.3", "babel-plugin-istanbul": "^6.1.1", - "chai": "^4.3.10", "chalk": "^4.1.2", "cherry-pick": "^0.5.0", "codecov": "^3.8.3", @@ -110,34 +108,21 @@ "eslint-import-resolver-webpack": "^0.13.8", "eslint-plugin-import": "^2.29.0", "eslint-plugin-jsx-a11y": "^6.8.0", - "eslint-plugin-mocha": "^10.4.3", "eslint-plugin-prettier": "^5.1.3", "eslint-plugin-react": "^7.34.2", "execa": "^5.1.1", "fs-extra": "^10.1.0", "husky": "^9.0.11", - "karma": "^6.4.3", - "karma-chrome-launcher": "^3.2.0", - "karma-cli": "^2.0.0", - "karma-coverage": "^2.2.1", - "karma-firefox-launcher": "^2.1.3", - "karma-mocha": "^2.0.1", - "karma-mocha-reporter": "^2.2.5", - "karma-sinon-chai": "^2.0.2", - "karma-sourcemap-loader": "^0.4.0", - "karma-webpack": "^5.0.1", "lint-staged": "^15.2.7", "lodash": "^4.17.21", - "mocha": "^10.4.0", + "playwright": "^1.45.3", "prettier": "^3.3.2", "process": "^0.11.10", - "react": "^18.2.0", - "react-dom": "^18.2.0", - "sinon": "^18.0.0", - "sinon-chai": "^3.7.0", - "typescript": "^5.4.5", - "util": "^0.12.5", - "webpack": "^5.92.0" + "react": "^18.3.1", + "react-dom": "^18.3.1", + "typescript": "^5.5.4", + "vitest": "^2.0.4", + "webpack": "^5.93.0" }, "peerDependencies": { "@types/react": ">=16.14.8", @@ -154,5 +139,6 @@ }, "release": { "conventionalCommits": true - } + }, + "packageManager": "yarn@1.22.19+sha1.4ba7fc5c6e704fce2066ecbfb0b0d8976fe62447" } diff --git a/test/.eslintrc b/test/.eslintrc index 521fb70a71..46d6cde164 100644 --- a/test/.eslintrc +++ b/test/.eslintrc @@ -1,20 +1,10 @@ { - "env": { - "mocha": true - }, - "globals": { - "assert": true, - "expect": true, - "sinon": true - }, - "plugins": ["mocha"], "rules": { "no-script-url": 0, "no-unused-expressions": 0, "padded-blocks": 0, "react/no-multi-comp": 0, "react/prop-types": 0, - "mocha/no-exclusive-tests": 2, - "max-classes-per-file": "off" - } + "max-classes-per-file": "off", + }, } diff --git a/test/AccordionButtonSpec.tsx b/test/AccordionButtonSpec.tsx index 605030a8ed..725610c0db 100644 --- a/test/AccordionButtonSpec.tsx +++ b/test/AccordionButtonSpec.tsx @@ -1,48 +1,42 @@ -import { fireEvent, render } from '@testing-library/react'; -import sinon from 'sinon'; +import { describe, expect, it, vi } from 'vitest'; +import { fireEvent, render, screen } from '@testing-library/react'; import AccordionButton from '../src/AccordionButton'; import Accordion from '../src/Accordion'; describe('', () => { it('Should have button as default component', () => { - const { getByTestId } = render( - , + render(); + expect(screen.getByTestId('test-accordion-button').tagName).toEqual( + 'BUTTON', ); - getByTestId('test-accordion-button') - .tagName.toLowerCase() - .should.equal('button'); - getByTestId('test-accordion-button') - .getAttribute('type')! - .should.equal('button'); + expect( + screen.getByTestId('test-accordion-button').getAttribute('type'), + ).toEqual('button'); }); it('Should allow rendering as different component', () => { - const { getByTestId } = render( - , - ); - getByTestId('test-accordion-button') - .tagName.toLowerCase() - .should.equal('div'); + render(); + expect(screen.getByTestId('test-accordion-button').tagName).toEqual('DIV'); }); it('Should call onClick', () => { - const onClickSpy = sinon.spy(); - const { getByTestId } = render( - , - ); - fireEvent.click(getByTestId('btn')); + const onClickSpy = vi.fn(); + render(); + fireEvent.click(screen.getByTestId('btn')); - onClickSpy.should.be.calledOnce; + expect(onClickSpy).toBeCalledTimes(1); }); it('Should have toggled aria-expanded attribute in alwaysOpen accordion', () => { - const onClickSpy = sinon.spy(); - const { getByTestId } = render( + const onClickSpy = vi.fn(); + render( , ); - fireEvent.click(getByTestId('btn')); - getByTestId('btn').getAttribute('aria-expanded')!.should.equal('true'); + fireEvent.click(screen.getByTestId('btn')); + expect(screen.getByTestId('btn').getAttribute('aria-expanded')).toEqual( + 'true', + ); }); }); diff --git a/test/AccordionSpec.tsx b/test/AccordionSpec.tsx index 9c5ffc74e1..e899f23fd8 100644 --- a/test/AccordionSpec.tsx +++ b/test/AccordionSpec.tsx @@ -1,7 +1,5 @@ -import { fireEvent, render, waitFor } from '@testing-library/react'; -import sinon from 'sinon'; -import { expect } from 'chai'; - +import { describe, expect, it, vi } from 'vitest'; +import { fireEvent, render, screen, waitFor } from '@testing-library/react'; import Accordion from '../src/Accordion'; import AccordionCollapse from '../src/AccordionCollapse'; import Dropdown from '../src/Dropdown'; @@ -10,21 +8,21 @@ import Nav from '../src/Nav'; describe('', () => { it('should output a div', () => { - const { getByTestId } = render(); + render(); - getByTestId('test').tagName.toLowerCase().should.equal('div'); + expect(screen.getByTestId('test').tagName).toEqual('DIV'); }); it('should render flush prop', () => { - const { getByTestId } = render(); + render(); - const node = getByTestId('test'); - node.classList.contains('accordion').should.be.true; - node.classList.contains('accordion-flush').should.be.true; + const node = screen.getByTestId('test'); + expect(node.classList).toContain('accordion'); + expect(node.classList).toContain('accordion-flush'); }); it('should output a h1', () => { - const { getByTestId } = render( + render( Hi @@ -33,11 +31,11 @@ describe('', () => { , ); - getByTestId('test-collapse').tagName.toLowerCase().should.equal('h1'); + expect(screen.getByTestId('test-collapse').tagName).toEqual('H1'); }); it('should only have second item collapsed', () => { - const { getByTestId } = render( + render( @@ -50,14 +48,16 @@ describe('', () => { , ); - expect(getByTestId('item-0').querySelector('.show')).to.exist; - expect(getByTestId('item-1').querySelector('.collapse')).to.exist; + expect(screen.getByTestId('item-0').querySelector('.show')).toBeTruthy(); + expect( + screen.getByTestId('item-1').querySelector('.collapse'), + ).toBeTruthy(); }); it('should expand next item and collapse current item on click', async () => { - const onClickSpy = sinon.spy(); + const onClickSpy = vi.fn(); - const { getByTestId, getByText } = render( + render( @@ -72,24 +72,26 @@ describe('', () => { , ); - fireEvent.click(getByText('Button item 1')); + fireEvent.click(screen.getByText('Button item 1')); - onClickSpy.should.be.calledOnce; + expect(onClickSpy).toBeCalledTimes(1); - expect(getByTestId('item-0').querySelector('.collapse')).to.exist; + expect( + screen.getByTestId('item-0').querySelector('.collapse'), + ).toBeTruthy(); - const item1 = getByTestId('item-1'); - expect(item1.querySelector('.collapsing')).to.exist; + const item1 = screen.getByTestId('item-1'); + expect(item1.querySelector('.collapsing')).toBeTruthy(); - await waitFor(() => expect(item1.querySelector('.show')).to.exist, { + await waitFor(() => expect(item1.querySelector('.show')).toBeTruthy(), { container: item1, }); }); it('should collapse current item on click', async () => { - const onClickSpy = sinon.spy(); + const onClickSpy = vi.fn(); - const { getByTestId, getByText } = render( + render( @@ -104,14 +106,16 @@ describe('', () => { , ); - fireEvent.click(getByText('Button item 0')); + fireEvent.click(screen.getByText('Button item 0')); - onClickSpy.should.be.calledOnce; + expect(onClickSpy).toBeCalledTimes(1); - expect(getByTestId('item-1').querySelector('.collapse')).to.exist; + expect( + screen.getByTestId('item-1').querySelector('.collapse'), + ).toBeTruthy(); - const item0 = getByTestId('item-0'); - expect(item0.querySelector('.collapsing')).to.exist; + const item0 = screen.getByTestId('item-0'); + expect(item0.querySelector('.collapsing')).toBeTruthy(); await waitFor(() => expect(item0.querySelector('.show')).to.not.exist, { container: item0, }); @@ -119,7 +123,7 @@ describe('', () => { // https://github.com/react-bootstrap/react-bootstrap/issues/4176 it('Should not close accordion when child dropdown clicked', () => { - const { getByTestId, getByText } = render( + render( @@ -137,14 +141,15 @@ describe('', () => { , ); - fireEvent.click(getByText('Dropdown Action')); + fireEvent.click(screen.getByText('Dropdown Action')); - expect(getByTestId('item-0').querySelector('.accordion-collapse.show')).to - .exist; + expect( + screen.getByTestId('item-0').querySelector('.accordion-collapse.show'), + ).toBeTruthy(); }); it('Should not close accordion when child ListGroup clicked', () => { - const { getByTestId, getByText } = render( + render( @@ -159,14 +164,15 @@ describe('', () => { , ); - fireEvent.click(getByText('List Group Item 1')); + fireEvent.click(screen.getByText('List Group Item 1')); - expect(getByTestId('item-0').querySelector('.accordion-collapse.show')).to - .exist; + expect( + screen.getByTestId('item-0').querySelector('.accordion-collapse.show'), + ).toBeTruthy(); }); it('Should not close accordion when child Nav clicked', () => { - const { getByTestId, getByText } = render( + render( @@ -181,16 +187,17 @@ describe('', () => { , ); - fireEvent.click(getByText('Nav Link Item 0')); + fireEvent.click(screen.getByText('Nav Link Item 0')); - expect(getByTestId('item-0').querySelector('.accordion-collapse.show')).to - .exist; + expect( + screen.getByTestId('item-0').querySelector('.accordion-collapse.show'), + ).toBeTruthy(); }); it('should allow multiple items to stay open', () => { - const onSelectSpy = sinon.spy(); + const onSelectSpy = vi.fn(); - const { getByText } = render( + render( header0 @@ -203,14 +210,14 @@ describe('', () => { , ); - fireEvent.click(getByText('header0')); - fireEvent.click(getByText('header1')); + fireEvent.click(screen.getByText('header0')); + fireEvent.click(screen.getByText('header1')); - onSelectSpy.should.be.calledWith(['0', '1']); + expect(onSelectSpy).toHaveBeenCalledWith(['0', '1'], expect.anything()); }); it('should remove only one of the active indices', () => { - const onSelectSpy = sinon.spy(); + const onSelectSpy = vi.fn(); const { getByText } = render( ', () => { fireEvent.click(getByText('header1')); - onSelectSpy.should.be.calledWith(['0']); + expect(onSelectSpy).toHaveBeenCalledWith(['0'], expect.anything()); }); it('should pass transition callbacks to underlying AccordionCollapse', async () => { - const increment = sinon.spy(); + const increment = vi.fn(); const { getByText } = render( @@ -258,11 +265,11 @@ describe('', () => { fireEvent.click(getByText('header0')); // Wait for body to open. - await waitFor(() => increment.callCount.should.equal(3)); + await waitFor(() => expect(increment).toBeCalledTimes(3)); fireEvent.click(getByText('header0')); // Wait for body to close. - await waitFor(() => increment.callCount.should.equal(6)); + await waitFor(() => expect(increment).toBeCalledTimes(6)); }); }); diff --git a/test/AlertSpec.tsx b/test/AlertSpec.tsx index 25ab6c44ef..3408863f9d 100644 --- a/test/AlertSpec.tsx +++ b/test/AlertSpec.tsx @@ -1,116 +1,122 @@ import * as React from 'react'; -import sinon from 'sinon'; -import { expect } from 'chai'; -import { fireEvent, render } from '@testing-library/react'; +import { describe, expect, it, vi } from 'vitest'; +import { fireEvent, render, screen } from '@testing-library/react'; import Alert from '../src/Alert'; describe('', () => { it('Should output a alert with message', () => { - const { getByTestId } = render( + render( Message , ); - getByTestId('test-alert').children.length.should.equal(1); - getByTestId('test-alert') - .children[0].tagName.toLowerCase() - .should.equal('strong'); + expect(screen.getByTestId('test-alert').children.length).toEqual(1); + expect(screen.getByTestId('test-alert').children[0].tagName).toEqual( + 'STRONG', + ); }); it('Should have dismissible style', () => { - const { getByTestId } = render( + render( Message , ); - getByTestId('test-alert').classList.contains('alert-dismissible').should.be - .true; + expect(screen.getByTestId('test-alert').classList).toContain( + 'alert-dismissible', + ); }); it('Should call onClose callback on dismiss click', () => { - const onCloseSpy = sinon.spy(); - const { getByLabelText } = render( + const onCloseSpy = vi.fn(); + render( Message , ); - fireEvent.click(getByLabelText('Close alert')); - onCloseSpy.should.be.calledOnce; + fireEvent.click(screen.getByLabelText('Close alert')); + expect(onCloseSpy).toHaveBeenCalledTimes(1); }); it('Should default to variant="primary"', () => { - const { getByTestId } = render( - Message, + render(Message); + expect(screen.getByTestId('test-alert').classList).toContain( + 'alert-primary', ); - getByTestId('test-alert').classList.contains('alert-primary').should.be - .true; }); it('Should use variant class', () => { - const { getByTestId } = render( + render( Message , ); - getByTestId('test-alert').classList.contains('alert-danger').should.be.true; + expect(screen.getByTestId('test-alert').classList).toContain( + 'alert-danger', + ); }); it('Should not have variant class when variant=null', () => { - const { getByTestId } = render( + render( Message , ); - getByTestId('test-alert').classList.contains('alert-primary').should.not.be - .true; + expect(screen.getByTestId('test-alert').classList).not.toContain( + 'alert-primary', + ); }); it('should forward refs to the alert', () => { const ref = React.createRef(); - const { getByTestId } = render( + render( message , ); - getByTestId('test-alert').tagName.toLowerCase().should.equal('div'); + expect(screen.getByTestId('test-alert').tagName).toEqual('DIV'); }); it('should not have fade class when transition=false', () => { - const { getByTestId } = render( + render( Message , ); - getByTestId('test-alert').classList.contains('fade').should.not.be.true; + expect(screen.getByTestId('test-alert').classList).not.toContain('fade'); }); it('should spread props to alert when transition=false', () => { const alertId = 'alert-id'; - const { getByTestId } = render( + render( Message , ); - getByTestId('test-alert').getAttribute('id')!.should.equal(alertId); + expect(screen.getByTestId('test-alert').getAttribute('id')).toEqual( + alertId, + ); }); it('should spread props to alert when transition=true', () => { const alertId = 'alert-id'; - const { getByTestId } = render( + render( Message , ); - getByTestId('test-alert').getAttribute('id')!.should.equal(alertId); + expect(screen.getByTestId('test-alert').getAttribute('id')).toEqual( + alertId, + ); }); it('should use Fade when transition=true', () => { - const { getByTestId } = render( + render( Message , ); - getByTestId('test-alert').classList.contains('fade').should.be.true; + expect(screen.getByTestId('test-alert').classList).toContain('fade'); }); it('should render null when transition and show are false', () => { @@ -124,52 +130,54 @@ describe('', () => { Message , ); - expect(container.innerHTML).equals(''); + expect(container.innerHTML).toEqual(''); }); it('should render close button variant', () => { - const { getByLabelText } = render( + render( Message , ); - getByLabelText('Close alert').classList.contains('btn-close-white').should - .be.true; + expect(screen.getByLabelText('Close alert').classList).toContain( + 'btn-close-white', + ); }); describe('Web Accessibility', () => { it('Should have alert role', () => { - const { getByTestId } = render( - Message, + render(Message); + expect(screen.getByTestId('test-alert').getAttribute('role')).toEqual( + 'alert', ); - getByTestId('test-alert').getAttribute('role')!.should.equal('alert'); }); }); describe('Alert alert-heading', () => { it('Should have alert-heading', () => { - const { getByTestId } = render( + render( Well done Message , ); - getByTestId('test-alert').classList.contains('alert-heading').should.be - .true; + expect(screen.getByTestId('test-alert').classList).toContain( + 'alert-heading', + ); }); it('Should have div styled as an h4 by default', () => { - const { getByTestId } = render( + render( Well done Message , ); - getByTestId('test-alert').classList.contains('h4').should.be.true; + expect(screen.getByTestId('test-alert').classList).toContain('h4'); }); it('Should support Heading as as prop', () => { - const { getByTestId } = render( + render( Well done @@ -177,7 +185,7 @@ describe('', () => { Message , ); - getByTestId('test-alert').tagName.toLowerCase().should.equal('h1'); + expect(screen.getByTestId('test-alert').tagName).toEqual('H1'); }); }); }); diff --git a/test/BadgeSpec.tsx b/test/BadgeSpec.tsx index e75809524e..add4020a95 100644 --- a/test/BadgeSpec.tsx +++ b/test/BadgeSpec.tsx @@ -1,60 +1,60 @@ -import { render } from '@testing-library/react'; - +import { describe, expect, it } from 'vitest'; +import { render, screen } from '@testing-library/react'; import Badge from '../src/Badge'; describe('Badge', () => { it('Should render correctly', () => { - const { getByTestId } = render( + render( Message , ); - const badge = getByTestId('test'); - badge.innerText.should.equal('Message'); - badge.classList.contains('badge').should.be.true; - badge.classList.contains('bg-primary').should.be.true; - badge.classList.contains('rounded-pill').should.be.true; + const badge = screen.getByTestId('test'); + expect(badge.innerText).toEqual('Message'); + expect(badge.classList).toContain('badge'); + expect(badge.classList).toContain('bg-primary'); + expect(badge.classList).toContain('rounded-pill'); }); it('should support custom `as`', () => { - const { getByTestId } = render( + render( Message , ); - const badge = getByTestId('test'); - badge.tagName.toLowerCase().should.equal('a'); - badge.getAttribute('href')!.should.equal('#'); + const badge = screen.getByTestId('test'); + expect(badge.tagName).toEqual('A'); + expect(badge.getAttribute('href')).toEqual('#'); }); it('Should default to bg="primary"', () => { - const { getByTestId } = render(Message); + render(Message); - const badge = getByTestId('test'); - badge.classList.contains('bg-primary').should.be.true; + const badge = screen.getByTestId('test'); + expect(badge.classList).toContain('bg-primary'); }); it('Should use bg class', () => { - const { getByTestId } = render( + render( Message , ); - const badge = getByTestId('test'); - badge.classList.contains('bg-danger').should.be.true; + const badge = screen.getByTestId('test'); + expect(badge.classList).toContain('bg-danger'); }); it('Should not have bg class when bg=null', () => { - const { getByTestId } = render( + render( Message , ); - const badge = getByTestId('test'); - badge.classList.contains('bg-primary').should.be.false; + const badge = screen.getByTestId('test'); + expect(badge.classList).not.toContain('bg-primary'); }); }); diff --git a/test/BootstrapModalManagerSpec.ts b/test/BootstrapModalManagerSpec.ts index 170ef850dc..598f6383b8 100644 --- a/test/BootstrapModalManagerSpec.ts +++ b/test/BootstrapModalManagerSpec.ts @@ -1,10 +1,16 @@ -import { expect } from 'chai'; -import getScrollbarSize from 'dom-helpers/scrollbarSize'; +import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'; +import ModalManager from '@restart/ui/ModalManager'; import { injectCss } from './helpers'; import BootstrapModalManager, { getSharedManager, } from '../src/BootstrapModalManager'; +const SCROLLBAR_SIZE = 10; + +vi.spyOn(ModalManager.prototype, 'getScrollbarWidth').mockImplementation( + () => SCROLLBAR_SIZE, +); + const createModal = () => ({ dialog: null, backdrop: null }); describe('BootstrapModalManager', () => { @@ -41,11 +47,11 @@ describe('BootstrapModalManager', () => { manager.add(modal); - expect(manager.modals.length).to.equal(1); - expect(manager.modals[0]).to.equal(modal); + expect(manager.modals.length).toEqual(1); + expect(manager.modals[0]).toEqual(modal); - expect(manager.state).to.eql({ - scrollBarWidth: 0, + expect(manager.state).toEqual({ + scrollBarWidth: SCROLLBAR_SIZE, style: { overflow: '', paddingRight: '', @@ -55,19 +61,19 @@ describe('BootstrapModalManager', () => { it('should return a shared modal manager', () => { const localManager = getSharedManager(); - localManager.should.exist; + expect(localManager).toBeDefined(); }); it('should return a same modal manager if called twice', () => { let localManager = getSharedManager(); - localManager.should.exist; + expect(localManager).toBeDefined(); const modal = createModal(); localManager.add(modal as any); - localManager.modals.length.should.equal(1); + expect(localManager.modals).toHaveLength(1); localManager = getSharedManager(); - localManager.modals.length.should.equal(1); + expect(localManager.modals).toHaveLength(1); localManager.remove(modal as any); }); @@ -93,8 +99,8 @@ describe('BootstrapModalManager', () => { const modal = createModal(); manager.add(modal); - expect(document.body.style.paddingRight).to.equal( - `${getScrollbarSize() + 20}px`, + expect(document.body.style.paddingRight).toEqual( + `${SCROLLBAR_SIZE + 20}px`, ); }); @@ -103,8 +109,8 @@ describe('BootstrapModalManager', () => { new BootstrapModalManager({ isRTL: true }).add(modal as any); - expect(document.body.style.paddingLeft).to.equal( - `${getScrollbarSize() + 20}px`, + expect(document.body.style.paddingLeft).toEqual( + `${SCROLLBAR_SIZE + 20}px`, ); }); @@ -113,12 +119,12 @@ describe('BootstrapModalManager', () => { document.body.style.overflow = 'scroll'; - expect(document.body.style.overflow).to.equal('scroll'); + expect(document.body.style.overflow).toEqual('scroll'); manager.add(modal); manager.remove(modal); - expect(document.body.style.overflow).to.equal('scroll'); + expect(document.body.style.overflow).toEqual('scroll'); document.body.style.overflow = ''; }); @@ -127,13 +133,13 @@ describe('BootstrapModalManager', () => { document.body.style.overflow = 'scroll'; - expect(document.body.style.overflow).to.equal('scroll'); + expect(document.body.style.overflow).toEqual('scroll'); const localManager = new BootstrapModalManager({ isRTL: true }); localManager.add(modal as any); localManager.remove(modal as any); - expect(document.body.style.overflow).to.equal('scroll'); + expect(document.body.style.overflow).toEqual('scroll'); document.body.style.overflow = ''; }); }); diff --git a/test/BreadcrumbItemSpec.tsx b/test/BreadcrumbItemSpec.tsx index 287ab1c704..30c40c2c50 100644 --- a/test/BreadcrumbItemSpec.tsx +++ b/test/BreadcrumbItemSpec.tsx @@ -1,7 +1,5 @@ -import sinon from 'sinon'; -import { render, fireEvent } from '@testing-library/react'; -import { expect } from 'chai'; - +import { describe, expect, it, vi } from 'vitest'; +import { fireEvent, render, screen } from '@testing-library/react'; import Breadcrumb from '../src/Breadcrumb'; import Button from '../src/Button'; @@ -11,61 +9,59 @@ describe('', () => { Crumb, ); - container.querySelectorAll('button.active').length.should.equal(0); + expect(container.querySelectorAll('button.active').length).toEqual(0); }); it('Should render `li` with no children as inner element when active.', () => { - const { queryAllByRole, getByText } = render( - Active Crumb, - ); + render(Active Crumb); - queryAllByRole('listitem').length.should.equal(1); - getByText('Active Crumb').should.exist; + expect(screen.queryAllByRole('listitem').length).toEqual(1); + expect(screen.getByText('Active Crumb')).toBeTruthy(); }); it('Should render `li` with no children as inner element when active and has href', () => { - const { queryAllByRole, getByText } = render( + render( Active Crumb , ); - queryAllByRole('listitem').length.should.equal(1); - getByText('Active Crumb').should.exist; + expect(screen.queryAllByRole('listitem').length).toEqual(1); + expect(screen.getByText('Active Crumb')).toBeTruthy(); }); it('Should add custom classes onto `li` wrapper element', () => { - const { getByTestId } = render( + render( a , ); - const item = getByTestId('test'); - item.classList.contains('custom-one').should.be.true; - item.classList.contains('custom-two').should.be.true; + const item = screen.getByTestId('test'); + expect(item.classList).toContain('custom-one'); + expect(item.classList).toContain('custom-two'); }); it('Should add aria-current to active element', () => { - const { queryAllByRole } = render( - Active Crumb, - ); + render(Active Crumb); - queryAllByRole('listitem', { current: 'page' }).length.should.equal(1); + expect( + screen.queryAllByRole('listitem', { current: 'page' }).length, + ).toEqual(1); }); it('Should spread additional props onto inner element', () => { - const handleClick = sinon.spy(); + const handleClick = vi.fn(); - const { getByRole } = render( + render( Crumb , ); - fireEvent.click(getByRole('button')); + fireEvent.click(screen.getByRole('button')); - handleClick.should.have.been.calledOnce; + expect(handleClick).toHaveBeenCalledTimes(1); }); it('Should apply id onto the li element', () => { @@ -75,22 +71,22 @@ describe('', () => { , ); - container.querySelectorAll('#test-link-id').length.should.equal(1); + expect(container.querySelectorAll('#test-link-id').length).toEqual(1); }); it('Should apply `href` property onto `a` inner element', () => { - const { getByRole } = render( + render( Crumb , ); - const href = getByRole('link').getAttribute('href') || ''; - href.should.equal('http://getbootstrap.com/components/#breadcrumbs'); + const href = screen.getByRole('link').getAttribute('href') || ''; + expect(href).toEqual('http://getbootstrap.com/components/#breadcrumbs'); }); it('Should apply `title` property onto `a` inner element', () => { - const { getByTitle } = render( + render( ', () => { , ); - getByTitle('test-title').should.exist; + expect(screen.getByTitle('test-title')).toBeTruthy(); }); it('Should not apply properties for inner `anchor` onto `li` wrapper element', () => { @@ -109,12 +105,14 @@ describe('', () => { , ); - container.querySelectorAll('li[href="/hi"]').length.should.equal(0); - container.querySelectorAll('li[title="test-title"]').length.should.equal(0); + expect(container.querySelectorAll('li[href="/hi"]').length).toEqual(0); + expect(container.querySelectorAll('li[title="test-title"]').length).toEqual( + 0, + ); }); it('Should set `target` attribute on `anchor`', () => { - const { getByRole } = render( + render( ', () => { Crumb , ); - expect(getByRole('link').getAttribute('target')).to.be.equal('_blank'); + expect(screen.getByRole('link').getAttribute('target')).to.be.equal( + '_blank', + ); }); it('Should have li as default component', () => { - const { getByTestId } = render(); + render(); - getByTestId('test').tagName.toLowerCase().should.equal('li'); + expect(screen.getByTestId('test').tagName).toEqual('LI'); }); it('Should be able to customize inner link element', () => { const { container } = render(); - container.querySelectorAll('a').length.should.equal(0); - container.querySelectorAll('button').length.should.equal(1); + expect(container.querySelectorAll('a').length).toEqual(0); + expect(container.querySelectorAll('button').length).toEqual(1); }); it('Should be able to pass props to the customized inner link element', () => { - const { getByRole } = render( - , - ); + render(); - expect(getByRole('button').getAttribute('type')).to.be.equal('submit'); + expect(screen.getByRole('button').getAttribute('type')).to.be.equal( + 'submit', + ); }); it('Should be able to pass attributes to the link element', () => { - const { getByRole } = render( - Crumb, - ); + render(Crumb); - expect(getByRole('button').getAttribute('foo')).to.be.equal('bar'); + expect(screen.getByRole('button').getAttribute('foo')).to.be.equal('bar'); }); it('Should be able to pass attributes to the li element', () => { - const { getByRole } = render( - Crumb, - ); + render(Crumb); - expect(getByRole('listitem').getAttribute('data-foo')).to.be.equal('bar'); + expect(screen.getByRole('listitem').getAttribute('data-foo')).to.be.equal( + 'bar', + ); }); }); diff --git a/test/BreadcrumbSpec.tsx b/test/BreadcrumbSpec.tsx index a3b39adb1b..c3f2ee08bd 100644 --- a/test/BreadcrumbSpec.tsx +++ b/test/BreadcrumbSpec.tsx @@ -1,28 +1,26 @@ -import { render } from '@testing-library/react'; - +import { describe, expect, it } from 'vitest'; +import { render, screen } from '@testing-library/react'; import Breadcrumb from '../src/Breadcrumb'; describe('', () => { it('Should apply id to the wrapper ol element', () => { const { container } = render(); - container.querySelectorAll('#custom-id').length.should.equal(1); + expect(container.querySelectorAll('#custom-id').length).toEqual(1); }); it('Should have breadcrumb class inside ol', () => { - const { getByRole } = render(); + render(); - getByRole('list').classList.contains('breadcrumb').should.be.true; + expect(screen.getByRole('list').classList).toContain('breadcrumb'); }); it('Should have custom classes', () => { - const { getByTestId } = render( - , - ); + render(); - const breadcrumb = getByTestId('test'); - breadcrumb.classList.contains('custom-one').should.be.true; - breadcrumb.classList.contains('custom-two').should.be.true; + const breadcrumb = screen.getByTestId('test'); + expect(breadcrumb.classList).toContain('custom-one'); + expect(breadcrumb.classList).toContain('custom-two'); }); it('Should not have a navigation role', () => { @@ -30,19 +28,19 @@ describe('', () => { , ); - container.querySelectorAll('ol[role="navigation"]').length.should.equal(0); + expect(container.querySelectorAll('ol[role="navigation"]').length).toEqual( + 0, + ); }); it('Should have an aria-label in ol', () => { - const { getByLabelText } = render( - , - ); - getByLabelText('breadcrumb').should.exist; + render(); + expect(screen.getByLabelText('breadcrumb')).toBeTruthy(); }); it('Should have nav as default component', () => { - const { getByTestId } = render(); + render(); - getByTestId('test').tagName.toLowerCase().should.equal('nav'); + expect(screen.getByTestId('test').tagName).toEqual('NAV'); }); }); diff --git a/test/ButtonGroupSpec.tsx b/test/ButtonGroupSpec.tsx index 19fdff9a2b..ea2d03cf41 100644 --- a/test/ButtonGroupSpec.tsx +++ b/test/ButtonGroupSpec.tsx @@ -1,50 +1,50 @@ -import { render } from '@testing-library/react'; - +import { describe, expect, it } from 'vitest'; +import { render, screen } from '@testing-library/react'; import ButtonGroup from '../src/ButtonGroup'; import Button from '../src/Button'; describe('ButtonGroup', () => { it('Should output a button group', () => { - const { getByRole } = render( + render( , ); - getByRole('group').should.exist; + expect(screen.getByRole('group')).toBeDefined(); }); it('Should add size', () => { - const { getByRole } = render( + render( , ); - getByRole('group').classList.contains('btn-group-lg').should.be.true; + expect(screen.getByRole('group').classList).toContain('btn-group-lg'); }); it('Should add vertical variation', () => { - const { getByRole } = render( + render( , ); - const group = getByRole('group'); - group.classList.contains('btn-group-vertical').should.be.true; - group.classList.contains('btn-group').should.be.false; + const group = screen.getByRole('group'); + expect(group.classList).toContain('btn-group-vertical'); + expect(group.classList).not.toContain('btn-group'); }); it('Should have div as default component', () => { - const { getByRole } = render(); + render(); - getByRole('group').tagName.toLowerCase().should.equal('div'); + expect(screen.getByRole('group').tagName).toEqual('DIV'); }); it('Should allow component tag customization', () => { - const { getByRole } = render(); + render(); - getByRole('group').tagName.toLowerCase().should.equal('article'); + expect(screen.getByRole('group').tagName).toEqual('ARTICLE'); }); }); diff --git a/test/ButtonSpec.tsx b/test/ButtonSpec.tsx index 47a13526eb..f59df978e8 100644 --- a/test/ButtonSpec.tsx +++ b/test/ButtonSpec.tsx @@ -1,27 +1,26 @@ import * as React from 'react'; -import { fireEvent, render } from '@testing-library/react'; -import { expect } from 'chai'; -import sinon from 'sinon'; +import { describe, expect, it, vi } from 'vitest'; +import { fireEvent, render, screen } from '@testing-library/react'; import Button from '../src/Button'; describe('); + render(); - getByRole('button').should.exist; + expect(screen.getByRole('button')).toBeTruthy(); }); it('Should have type=button by default', () => { - const { getByRole } = render(); + render(); - expect(getByRole('button').getAttribute('type')).to.be.equal('button'); + expect(screen.getByRole('button').getAttribute('type')).toEqual('button'); }); it('Should show the type if passed one', () => { - const { getByRole } = render(); + render(); - expect(getByRole('button').getAttribute('type')).to.be.equal('submit'); + expect(screen.getByRole('button').getAttribute('type')).toEqual('submit'); }); it('Should show the type if explicitly passed in when "as" is used', () => { @@ -31,7 +30,7 @@ describe(', ); - expect(getByTestId('test').getAttribute('type')).to.be.equal('submit'); + expect(getByTestId('test').getAttribute('type')).toEqual('submit'); }); it('Should not have default type=button when "as" is used', () => { @@ -52,7 +51,7 @@ describe('); + render(); - expect(getByRole('button').getAttribute('href')).to.be.equal(href); + expect(screen.getByRole('button').getAttribute('href')).toEqual(href); }); it('Should call onClick callback', () => { - const onClick = sinon.spy(); + const onClick = vi.fn(); - const { getByRole } = render(); + render(); - fireEvent.click(getByRole('button')); + fireEvent.click(screen.getByRole('button')); - onClick.should.have.been.calledOnce; + expect(onClick).toHaveBeenCalledTimes(1); }); it('Should be disabled', () => { - const { getByRole } = render(); + render(); - getByRole('button').matches('[disabled]').should.be.true; + expect(screen.getByRole('button').matches('[disabled]')).toEqual(true); }); it('Should be disabled link', () => { - const { getByRole } = render( + render( , ); - getByRole('button').classList.contains('disabled').should.be.true; + expect(screen.getByRole('button').classList).toContain('disabled'); }); it('Should apply variant class', () => { - const { getByRole } = render(); + render(); - getByRole('button').classList.contains('btn-danger').should.be.true; + expect(screen.getByRole('button').classList).toContain('btn-danger'); }); it('Should have size class', () => { - const { getByRole } = render(); + render(); - getByRole('button').classList.contains('btn-lg').should.be.true; + expect(screen.getByRole('button').classList).toContain('btn-lg'); }); it('Should honour additional classes passed in, adding not overriding', () => { - const { getByRole } = render( + render( , ); - const button = getByRole('button'); - button.classList.contains('bob').should.be.true; - button.classList.contains('btn-danger').should.be.true; + const button = screen.getByRole('button'); + expect(button.classList).toContain('bob'); + expect(button.classList).toContain('btn-danger'); }); it('Should default to variant="primary"', () => { - const { getByRole } = render(); + render(); - getByRole('button').classList.contains('btn-primary').should.be.true; + expect(screen.getByRole('button').classList).toContain('btn-primary'); }); it('Should remove default variant', () => { - const { getByRole } = render(); + render(); - getByRole('button').classList.contains('btn-primary').should.be.false; + expect(screen.getByRole('button').classList).not.toContain('btn-primary'); }); it('Should not output null variant', () => { - const { getByRole } = render(); + render(); - getByRole('button').classList.contains('btn-null').should.be.false; + expect(screen.getByRole('button').classList).not.toContain('btn-null'); }); it('Should not output empty variant', () => { - const { getByRole } = render(); + render(); - getByRole('button').classList.contains('btn-').should.be.false; + expect(screen.getByRole('button').classList).not.toContain('btn-'); }); it('Should be active', () => { - const { getByRole } = render(); + render(); - getByRole('button').classList.contains('active').should.be.true; + expect(screen.getByRole('button').classList).toContain('active'); }); it('Should allow a custom prefix', () => { - const { getByRole } = render( + render( , ); - const button = getByRole('button'); - button.classList.contains('my-btn').should.be.true; - button.classList.contains('my-btn-danger').should.be.true; + const button = screen.getByRole('button'); + expect(button.classList).toContain('my-btn'); + expect(button.classList).toContain('my-btn-danger'); }); }); diff --git a/test/ButtonToolbarSpec.tsx b/test/ButtonToolbarSpec.tsx index 369cd14805..0cfcb4ad68 100644 --- a/test/ButtonToolbarSpec.tsx +++ b/test/ButtonToolbarSpec.tsx @@ -1,28 +1,29 @@ -import { render } from '@testing-library/react'; +import { describe, expect, it } from 'vitest'; +import { render, screen } from '@testing-library/react'; import Button from '../src/Button'; import ButtonToolbar from '../src/ButtonToolbar'; describe('ButtonToolbar', () => { it('Should output a button toolbar', () => { - const { getByRole } = render( + render( , ); - getByRole('toolbar').classList.contains('btn-toolbar').should.be.true; + expect(screen.getByRole('toolbar').classList).toContain('btn-toolbar'); }); it('Should allow a custom prefix', () => { - const { getByRole } = render( + render( , ); - const toolbar = getByRole('toolbar'); - toolbar.classList.contains('my-custom-toolbar').should.be.true; - toolbar.classList.contains('btn-toolbar').should.be.false; + const toolbar = screen.getByRole('toolbar'); + expect(toolbar.classList).toContain('my-custom-toolbar'); + expect(toolbar.classList).not.toContain('btn-toolbar'); }); }); diff --git a/test/CardImgSpec.tsx b/test/CardImgSpec.tsx index f5bfbafe10..8ba48ad8c7 100644 --- a/test/CardImgSpec.tsx +++ b/test/CardImgSpec.tsx @@ -1,53 +1,52 @@ -import { render } from '@testing-library/react'; -import { expect } from 'chai'; - +import { describe, expect, it } from 'vitest'; +import { render, screen } from '@testing-library/react'; import CardImg from '../src/CardImg'; describe('', () => { it('should output an img', () => { - const { getByRole } = render(); + render(); - getByRole('img').should.exist; + expect(screen.getByRole('img')).toBeTruthy(); }); it('should pass down src to img', () => { const url = 'http://fakeurl.com/pic.jpg'; - const { getByRole } = render(); + render(); - expect(getByRole('img').getAttribute('src')).to.be.equal(url); + expect(screen.getByRole('img').getAttribute('src')).to.be.equal(url); }); it('Should have img as default component', () => { - const { getByRole } = render(); + render(); - getByRole('img').should.exist; + expect(screen.getByRole('img')).toBeTruthy(); }); it('accepts as prop', () => { - const { getByRole } = render(img); + render(img); - const card = getByRole('figure'); - card.tagName.toLowerCase().should.equal('figure'); - card.classList.contains('card-img').should.equal(true); + const card = screen.getByRole('figure'); + expect(card.tagName).toEqual('FIGURE'); + expect(card.classList).toContain('card-img'); }); describe('variants', () => { it('null', () => { - const { getByRole } = render(); + render(); - getByRole('img').classList.contains('card-img').should.be.true; + expect(screen.getByRole('img').classList).toContain('card-img'); }); it('top', () => { - const { getByRole } = render(); + render(); - getByRole('img').classList.contains('card-img-top').should.be.true; + expect(screen.getByRole('img').classList).toContain('card-img-top'); }); it('bottom', () => { - const { getByRole } = render(); + render(); - getByRole('img').classList.contains('card-img-bottom').should.be.true; + expect(screen.getByRole('img').classList).toContain('card-img-bottom'); }); }); }); diff --git a/test/CardSpec.tsx b/test/CardSpec.tsx index 12ecb00814..ff663abe6e 100644 --- a/test/CardSpec.tsx +++ b/test/CardSpec.tsx @@ -1,58 +1,56 @@ -import { render } from '@testing-library/react'; - +import { describe, expect, it } from 'vitest'; +import { render, screen } from '@testing-library/react'; import Card from '../src/Card'; describe('', () => { it('should output a div', () => { - const { getByText } = render(Card); - getByText('Card').tagName.toLowerCase().should.equal('div'); - getByText('Card').classList.contains('card').should.be.true; + render(Card); + expect(screen.getByText('Card').tagName).toEqual('DIV'); + expect(screen.getByText('Card').classList).toContain('card'); }); it('should have additional classes', () => { - const { getByText } = render(Card); - getByText('Card').classList.contains('custom-class').should.be.true; + render(Card); + expect(screen.getByText('Card').classList).toContain('custom-class'); }); it('accepts a bg prop', () => { - const { getByText } = render(Card); - getByText('Card').classList.contains('bg-primary').should.be.true; + render(Card); + expect(screen.getByText('Card').classList).toContain('bg-primary'); }); it('accepts a text prop', () => { - const { getByText } = render(Card); - getByText('Card').classList.contains('text-success').should.be.true; + render(Card); + expect(screen.getByText('Card').classList).toContain('text-success'); }); it('accepts a border prop', () => { - const { getByText } = render(Card); - getByText('Card').classList.contains('border-danger').should.be.true; + render(Card); + expect(screen.getByText('Card').classList).toContain('border-danger'); }); it('should render children', () => { - const { getByTestId } = render( + render(

hello

, ); - getByTestId('test-card').children.length.should.equal(1); - getByTestId('test-card') - .children[0].tagName.toLowerCase() - .should.equal('p'); + expect(screen.getByTestId('test-card').children.length).toEqual(1); + expect(screen.getByTestId('test-card').children[0].tagName).toEqual('P'); }); it('accepts as prop', () => { - const { getByText } = render(body); - getByText('body').tagName.toLowerCase().should.equal('section'); + render(body); + expect(screen.getByText('body').tagName).toEqual('SECTION'); }); it('allows for the body shorthand', () => { - const { getByText } = render(test); - getByText('test').classList.contains('card-body').should.be.true; + render(test); + expect(screen.getByText('test').classList).toContain('card-body'); }); it('Should have div as default component', () => { - const { getByTestId } = render(); - getByTestId('default-test').tagName.toLowerCase().should.equal('div'); + render(); + expect(screen.getByTestId('default-test').tagName).toEqual('DIV'); }); }); diff --git a/test/CarouselCaptionSpec.tsx b/test/CarouselCaptionSpec.tsx index 2890627c8b..abc7f25a9a 100644 --- a/test/CarouselCaptionSpec.tsx +++ b/test/CarouselCaptionSpec.tsx @@ -1,31 +1,29 @@ -import { render } from '@testing-library/react'; - +import { describe, expect, it } from 'vitest'; +import { render, screen } from '@testing-library/react'; import Carousel from '../src/Carousel'; describe('', () => { it('uses "div" by default', () => { - const { getByTestId, getByText } = render( + render( Children , ); - const captionWrapper = getByTestId('test'); - captionWrapper.tagName.toLowerCase().should.equal('div'); - captionWrapper.classList.contains('carousel-caption').should.be.true; - captionWrapper.classList.contains('custom-class').should.be.true; + const captionWrapper = screen.getByTestId('test'); + expect(captionWrapper.tagName).toEqual('DIV'); + expect(captionWrapper.classList).toContain('carousel-caption'); + expect(captionWrapper.classList).toContain('custom-class'); - const content = getByText('Children'); - content.tagName.toLowerCase().should.equal('strong'); + const content = screen.getByText('Children'); + expect(content.tagName).toEqual('STRONG'); }); it('should allow custom elements instead of "div"', () => { - const { getByTestId } = render( - , - ); + render(); - const caption = getByTestId('test'); - caption.tagName.toLowerCase().should.equal('section'); - caption.classList.contains('carousel-caption').should.be.true; + const caption = screen.getByTestId('test'); + expect(caption.tagName).toEqual('SECTION'); + expect(caption.classList).toContain('carousel-caption'); }); }); diff --git a/test/CarouselSpec.tsx b/test/CarouselSpec.tsx index 5d4d4bcc4a..8c1eb53a81 100644 --- a/test/CarouselSpec.tsx +++ b/test/CarouselSpec.tsx @@ -1,14 +1,12 @@ import * as React from 'react'; -import { Simulate } from 'react-dom/test-utils'; +import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'; import { act, fireEvent, render, - RenderResult, + screen, waitFor, } from '@testing-library/react'; -import sinon from 'sinon'; - import Carousel, { CarouselRef } from '../src/Carousel'; import ThemeProvider from '../src/ThemeProvider'; @@ -44,28 +42,26 @@ describe('', () => { }); it('should show the first item by default and render all', () => { - const { getAllByTestId, container } = render({items}); - - const carouselItems = getAllByTestId(CarouselItemTestId); - carouselItems[0].classList.contains('active').should.be.true; - carouselItems[1].classList.contains('active').should.be.false; - container - .querySelectorAll('.carousel-indicators > button') - .should.have.lengthOf(items.length); + const { container } = render({items}); + + const carouselItems = screen.getAllByTestId(CarouselItemTestId); + expect(carouselItems[0].classList).toContain('active'); + expect(carouselItems[1].classList).not.toContain('active'); + expect( + container.querySelectorAll('.carousel-indicators > button'), + ).toHaveLength(items.length); }); it('should show the correct item with defaultActiveIndex', () => { - const { getAllByTestId } = render( - {items}, - ); + render({items}); - const carouselItems = getAllByTestId(CarouselItemTestId); - carouselItems[0].classList.contains('active').should.be.false; - carouselItems[1].classList.contains('active').should.be.true; + const carouselItems = screen.getAllByTestId(CarouselItemTestId); + expect(carouselItems[0].classList).not.toContain('active'); + expect(carouselItems[1].classList).toContain('active'); }); it('should handle falsy children', () => { - const { getAllByTestId, container } = render( + const { container } = render( {null} @@ -79,16 +75,16 @@ describe('', () => { , ); - const carouselItems = getAllByTestId(CarouselItemTestId); - carouselItems[0].classList.contains('active').should.be.true; - carouselItems[0].innerText.should.be.equal('Item 1 content'); - container - .querySelectorAll('.carousel-indicators > button') - .should.have.lengthOf(2); + const carouselItems = screen.getAllByTestId(CarouselItemTestId); + expect(carouselItems[0].classList).toContain('active'); + expect(carouselItems[0].innerText).toEqual('Item 1 content'); + expect( + container.querySelectorAll('.carousel-indicators > button'), + ).toHaveLength(2); }); it('should call onSelect when indicator selected', () => { - const onSelect = sinon.spy(); + const onSelect = vi.fn(); const { getByLabelText } = render( @@ -98,7 +94,8 @@ describe('', () => { fireEvent.click(getByLabelText('Slide 1')); - onSelect.should.be.calledOnceWith(0); + expect(onSelect).toHaveBeenCalledOnce(); + expect(onSelect).toHaveBeenCalledWith(0, expect.anything()); }); it('should render custom indicator labels', () => { @@ -115,13 +112,14 @@ describe('', () => { ); for (let i = 0; i < indicatorLabels.length; i++) { - getByLabelText(indicatorLabels[i], { selector: '[aria-label]' }).should - .exist; + expect( + getByLabelText(indicatorLabels[i], { selector: '[aria-label]' }), + ).toBeDefined(); } }); it('should render variant', () => { - const { getByTestId } = render( + render( ', () => { , ); - const carousel = getByTestId('test'); - carousel.classList.contains('carousel').should.be.true; - carousel.classList.contains('carousel-dark').should.be.true; + const carousel = screen.getByTestId('test'); + expect(carousel.classList).toContain('carousel'); + expect(carousel.classList).toContain('carousel-dark'); }); describe('ref testing', () => { it('should allow refs to be attached and expose next, prev functions', async () => { const ref = React.createRef(); - const onSelectSpy = sinon.spy(); - const onSlidSpy = sinon.spy(); + const onSelectSpy = vi.fn(); + const onSlidSpy = vi.fn(); render( ', () => { , ); - ref.current!.should.have.property('next'); - ref.current!.should.have.property('prev'); - ref.current!.should.have.property('element').and.instanceOf(HTMLElement); + expect(ref.current).toHaveProperty('next'); + expect(ref.current).toHaveProperty('prev'); + expect(ref.current).toHaveProperty('element'); act(() => { ref.current!.next(); }); - await waitFor(() => onSelectSpy.should.have.been.calledOnce); - await waitFor(() => onSlidSpy.should.have.been.calledWith(2, 'start')); + await waitFor(() => expect(onSelectSpy).toHaveBeenCalledOnce()); + await waitFor(() => expect(onSlidSpy).toHaveBeenCalledWith(2, 'start')); act(() => { ref.current!.next(); }); - await waitFor(() => onSelectSpy.should.have.been.calledTwice); + await waitFor(() => expect(onSelectSpy).toHaveBeenCalledTimes(2)); }); }); it(`should call onSlide with previous index and direction`, () => { - const onEventSpy = sinon.spy(); + const onEventSpy = vi.fn(); const { getByLabelText } = render( @@ -188,11 +186,11 @@ describe('', () => { }), ); - onEventSpy.should.be.calledWith(0, 'end'); + expect(onEventSpy).toHaveBeenCalledWith(0, 'end'); }); it(`should call onSlide with next index and direction`, () => { - const onEventSpy = sinon.spy(); + const onEventSpy = vi.fn(); const { getByLabelText } = render( @@ -206,11 +204,11 @@ describe('', () => { }), ); - onEventSpy.should.be.calledWith(items.length - 1, 'start'); + expect(onEventSpy).toHaveBeenCalledWith(items.length - 1, 'start'); }); it(`should call onSlid with previous index and direction`, async () => { - const onEventSpy = sinon.spy(); + const onEventSpy = vi.fn(); const { getByLabelText } = render( @@ -224,11 +222,11 @@ describe('', () => { }), ); - await waitFor(() => onEventSpy.should.be.calledWith(0, 'end')); + await waitFor(() => expect(onEventSpy).toHaveBeenCalledWith(0, 'end')); }); it(`should call onSlid with next index and direction`, async () => { - const onEventSpy = sinon.spy(); + const onEventSpy = vi.fn(); const { getByLabelText } = render( @@ -243,7 +241,7 @@ describe('', () => { ); await waitFor(() => - onEventSpy.should.be.calledWith(items.length - 1, 'start'), + expect(onEventSpy).toHaveBeenCalledWith(items.length - 1, 'start'), ); }); @@ -255,9 +253,9 @@ describe('', () => { , ); - container - .querySelectorAll('a.carousel-control-prev') - .should.have.lengthOf(1); + expect( + container.querySelectorAll('a.carousel-control-prev'), + ).toHaveLength(1); }); it('should show next button control on the last image if wrap is true', () => { @@ -269,9 +267,9 @@ describe('', () => { , ); - container - .querySelectorAll('a.carousel-control-next') - .should.have.lengthOf(1); + expect( + container.querySelectorAll('a.carousel-control-next'), + ).toHaveLength(1); }); it('should not show the prev button on the first image if wrap is false', () => { @@ -281,9 +279,9 @@ describe('', () => { , ); - container - .querySelectorAll('a.carousel-control-prev') - .should.have.lengthOf(0); + expect( + container.querySelectorAll('a.carousel-control-prev'), + ).toHaveLength(0); }); it('should not show the next button on the last image if wrap is false', () => { @@ -295,14 +293,14 @@ describe('', () => { , ); - container - .querySelectorAll('a.carousel-control-next') - .should.have.lengthOf(0); + expect( + container.querySelectorAll('a.carousel-control-next'), + ).toHaveLength(0); }); }); it('should allow the user to specify a previous and next icon', () => { - const { getByTestId } = render( + render( ', () => { , ); - getByTestId('prev-icon').classList.contains('ficon-left').should.be.true; - getByTestId('next-icon').classList.contains('ficon-right').should.be.true; + expect(screen.getByTestId('prev-icon').classList).toContain('ficon-left'); + expect(screen.getByTestId('next-icon').classList).toContain('ficon-right'); }); it('should allow user to specify a previous and next SR label', () => { @@ -333,9 +331,9 @@ describe('', () => { const labels = container.querySelectorAll('.visually-hidden'); - labels.should.have.lengthOf(2); - labels[0].innerText.should.contain('Previous awesomeness'); - labels[1].innerText.should.contain('Next awesomeness'); + expect(labels).toHaveLength(2); + expect(labels[0].innerText).toContain('Previous awesomeness'); + expect(labels[1].innerText).toContain('Next awesomeness'); }); it('should not render labels when values are null or undefined', () => { @@ -352,17 +350,12 @@ describe('', () => { , ); - container - .querySelectorAll('.visually-hidden') - .should.have.lengthOf( - 0, - `should not render labels for value ${falsyValue}`, - ); + expect(container.querySelectorAll('.visually-hidden')).toHaveLength(0); }); }); it('should transition properly when slide animation is disabled', () => { - const spy = sinon.spy(); + const spy = vi.fn(); const { container } = render( {items} @@ -373,13 +366,13 @@ describe('', () => { container.querySelector('a.carousel-control-next')!, ); - spy.should.have.been.calledOnce; + expect(spy).toHaveBeenCalledOnce(); fireEvent.click( container.querySelector('a.carousel-control-prev')!, ); - spy.should.have.been.calledTwice; + expect(spy).toHaveBeenCalledTimes(2); }); it('should render on update, active item > new child length', () => { @@ -387,9 +380,11 @@ describe('', () => { {items}, ); - queryAllByLabelText(/Slide/, { - selector: '.carousel-indicators > button', - }).should.have.lengthOf(items.length); + expect( + queryAllByLabelText(/Slide/, { + selector: '.carousel-indicators > button', + }), + ).toHaveLength(items.length); const fewerItems = items.slice(2); @@ -397,38 +392,42 @@ describe('', () => { {fewerItems}, ); - queryAllByLabelText(/Slide/, { - selector: '.carousel-indicators > button', - }).should.have.lengthOf(fewerItems.length); + expect( + queryAllByLabelText(/Slide/, { + selector: '.carousel-indicators > button', + }), + ).toHaveLength(fewerItems.length); - queryAllByText(/Item \d content/, { - selector: 'div.carousel-item', - }).should.have.lengthOf(fewerItems.length); + expect( + queryAllByText(/Item \d content/, { + selector: 'div.carousel-item', + }), + ).toHaveLength(fewerItems.length); }); it('should render correctly when fade is set', () => { - const { getByTestId } = render( + render( {items} , ); - getByTestId('test').classList.contains('carousel-fade').should.be.true; + expect(screen.getByTestId('test').classList).toContain('carousel-fade'); }); describe('automatic traversal', () => { - let clock: sinon.SinonFakeTimers; + let clock: ReturnType; beforeEach(() => { - clock = sinon.useFakeTimers(); + clock = vi.useFakeTimers(); }); afterEach(() => { - clock.restore(); + clock.useRealTimers(); }); it('should go through the items after given seconds', () => { - const onSelectSpy = sinon.spy(); + const onSelectSpy = vi.fn(); const interval = 500; render( @@ -438,14 +437,14 @@ describe('', () => { ); act(() => { - clock.tick(interval * 1.5); + clock.advanceTimersByTime(interval * 1.5); }); - onSelectSpy.should.have.been.calledOnce; + expect(onSelectSpy).toHaveBeenCalledOnce(); }); it('should go through the items given the specified intervals', () => { - const onSelectSpy = sinon.spy(); + const onSelectSpy = vi.fn(); render( Item 1 content @@ -457,41 +456,42 @@ describe('', () => { // but short enough to not trigger auto-play to occur twice // (since the interval for the second item should be `5000`) act(() => { - clock.tick(1100); + clock.advanceTimersByTime(1100); }); - onSelectSpy.should.have.been.calledOnceWith(1); + expect(onSelectSpy).toHaveBeenCalledOnce(); + expect(onSelectSpy).toHaveBeenCalledWith(1, undefined); }); it('should stop going through items on hover and continue afterwards', () => { - const onSelectSpy = sinon.spy(); + const onSelectSpy = vi.fn(); const interval = 500; - const { getByTestId } = render( + render( {items} , ); - const carousel = getByTestId('test'); + const carousel = screen.getByTestId('test'); fireEvent.mouseOver(carousel); act(() => { - clock.tick(interval * 1.5); + clock.advanceTimersByTime(interval * 1.5); }); - onSelectSpy.should.not.have.been.called; + expect(onSelectSpy).not.toHaveBeenCalled(); fireEvent.mouseOut(carousel); act(() => { - clock.tick(interval * 1.5); + clock.advanceTimersByTime(interval * 1.5); }); - onSelectSpy.should.have.been.calledOnce; + expect(onSelectSpy).toHaveBeenCalledOnce(); }); it('should ignore hover if the prop is passed', () => { - const onSelectSpy = sinon.spy(); + const onSelectSpy = vi.fn(); const interval = 500; - const { getByTestId } = render( + render( ', () => { , ); - fireEvent.mouseOver(getByTestId('test')); + fireEvent.mouseOver(screen.getByTestId('test')); act(() => { - clock.tick(interval * 1.5); + clock.advanceTimersByTime(interval * 1.5); }); - onSelectSpy.should.have.been.calledOnce; + expect(onSelectSpy).toHaveBeenCalledOnce(); }); it('should stop going through the items after unmounting', () => { - const onSelectSpy = sinon.spy(); + const onSelectSpy = vi.fn(); const interval = 500; const { unmount } = render( @@ -522,44 +522,48 @@ describe('', () => { unmount(); act(() => { - clock.tick(interval * 1.5); + clock.advanceTimersByTime(interval * 1.5); }); - onSelectSpy.should.not.have.been.called; + expect(onSelectSpy).not.toHaveBeenCalled(); }); }); describe('wrapping', () => { - let clock: sinon.SinonFakeTimers; + let clock: ReturnType; beforeEach(() => { - clock = sinon.useFakeTimers(); + clock = vi.useFakeTimers(); }); afterEach(() => { - clock.restore(); + clock.useRealTimers(); }); it('should wrap to last from first', () => { - const onSelectSpy = sinon.spy(); + const onSelectSpy = vi.fn(); - const { getByTestId } = render( + render( {items} , ); - fireEvent.keyDown(getByTestId('test'), { + fireEvent.keyDown(screen.getByTestId('test'), { key: 'ArrowLeft', }); - clock.tick(50); + clock.advanceTimersByTime(50); - onSelectSpy.should.have.been.calledOnceWith(items.length - 1); + expect(onSelectSpy).toHaveBeenCalledOnce(); + expect(onSelectSpy).toHaveBeenCalledWith( + items.length - 1, + expect.anything(), + ); }); it('should wrap from first to last', () => { - const onSelectSpy = sinon.spy(); + const onSelectSpy = vi.fn(); - const { getByTestId } = render( + render( ', () => { , ); - fireEvent.keyDown(getByTestId('test'), { + fireEvent.keyDown(screen.getByTestId('test'), { key: 'ArrowRight', }); - clock.tick(50); - onSelectSpy.should.have.been.calledOnceWith(0); + clock.advanceTimersByTime(50); + expect(onSelectSpy).toHaveBeenCalledOnce(); + expect(onSelectSpy).toHaveBeenCalledWith(0, expect.anything()); }); [ @@ -593,9 +598,9 @@ describe('', () => { }, ].forEach(({ caseName, activeIndex, eventPayload }) => { it(`should not wrap with wrap unset for ${caseName}`, () => { - const onSelectSpy = sinon.spy(); + const onSelectSpy = vi.fn(); - const { getByTestId, getAllByTestId } = render( + render( ', () => { , ); - const carousel = getByTestId('test'); + const carousel = screen.getByTestId('test'); fireEvent.keyDown(carousel, eventPayload); - clock.tick(50); + clock.advanceTimersByTime(50); - const carouselItems = getAllByTestId(CarouselItemTestId); - carouselItems[activeIndex].classList.contains('active').should.be.true; - onSelectSpy.should.not.have.been.called; + const carouselItems = screen.getAllByTestId(CarouselItemTestId); + expect(carouselItems[activeIndex].classList).toContain('active'); + expect(onSelectSpy).not.toHaveBeenCalled(); }); }); }); describe('keyboard events', () => { - let clock: sinon.SinonFakeTimers; + let clock: ReturnType; beforeEach(() => { - clock = sinon.useFakeTimers(); + clock = vi.useFakeTimers(); }); afterEach(() => { - clock.restore(); + clock.useRealTimers(); }); it('should go back for the keyboard event ArrowLeft', () => { - const onSelectSpy = sinon.spy(); + const onSelectSpy = vi.fn(); - const { getByTestId } = render( + render( {items} , ); - fireEvent.keyDown(getByTestId('test'), { + fireEvent.keyDown(screen.getByTestId('test'), { key: 'ArrowLeft', }); - clock.tick(50); - onSelectSpy.should.have.been.calledOnceWith(0); + clock.advanceTimersByTime(50); + expect(onSelectSpy).toHaveBeenCalledOnce(); + expect(onSelectSpy).toHaveBeenCalledWith(0, expect.anything()); }); it('should go forward for the keyboard event ArrowRight', () => { - const onSelectSpy = sinon.spy(); + const onSelectSpy = vi.fn(); - const { getByTestId } = render( + render( {items} , ); - fireEvent.keyDown(getByTestId('test'), { + fireEvent.keyDown(screen.getByTestId('test'), { key: 'ArrowRight', }); - clock.tick(50); - onSelectSpy.should.have.been.calledOnceWith(2); + clock.advanceTimersByTime(50); + expect(onSelectSpy).toHaveBeenCalledOnce(); + expect(onSelectSpy).toHaveBeenCalledWith(2, expect.anything()); }); it('should ignore keyEvents when the keyboard is disabled', () => { - const onSelectSpy = sinon.spy(); + const onSelectSpy = vi.fn(); - const { getByTestId } = render( + render( ', () => { , ); - fireEvent.keyDown(getByTestId('test'), { + fireEvent.keyDown(screen.getByTestId('test'), { key: 'ArrowRight', }); - clock.tick(50); - onSelectSpy.should.not.have.been.called; + clock.advanceTimersByTime(50); + expect(onSelectSpy).not.toHaveBeenCalled(); }); it('should handle a defined custom key event', () => { - const onKeyDownSpy = sinon.spy(); + const onKeyDownSpy = vi.fn(); - const { getByTestId } = render( + render( {items} , ); - fireEvent.keyDown(getByTestId('test'), { + fireEvent.keyDown(screen.getByTestId('test'), { key: 'ArrowUp', }); - clock.tick(50); - onKeyDownSpy.should.have.been.calledOnce; + clock.advanceTimersByTime(50); + expect(onKeyDownSpy).toHaveBeenCalledOnce(); }); ['ArrowUp', 'ArrowRightLeft', 'Onwards'].forEach((key) => { it('should do nothing for non left or right keys', () => { - const onSelectSpy = sinon.spy(); + const onSelectSpy = vi.fn(); - const { getByTestId } = render( + render( {items} , ); - fireEvent.keyDown(getByTestId('test'), { + fireEvent.keyDown(screen.getByTestId('test'), { key, }); - clock.tick(50); - sinon.assert.notCalled(onSelectSpy); + clock.advanceTimersByTime(50); + expect(onSelectSpy).not.toHaveBeenCalled(); }); }); }); describe('mouse events', () => { - let clock: sinon.SinonFakeTimers; + let clock: ReturnType; beforeEach(() => { - clock = sinon.useFakeTimers(); + clock = vi.useFakeTimers(); }); afterEach(() => { - clock.restore(); + clock.useRealTimers(); }); it('should handle a defined mouse over event', () => { - const onMouseOverSpy = sinon.spy(); + const onMouseOverSpy = vi.fn(); - const { getByTestId } = render( + render( ', () => { , ); - fireEvent.mouseOver(getByTestId('test')); - clock.tick(1500); - onMouseOverSpy.should.have.been.calledOnce; + fireEvent.mouseOver(screen.getByTestId('test')); + clock.advanceTimersByTime(1500); + expect(onMouseOverSpy).toHaveBeenCalledOnce(); }); it('should handle a defined mouse out event', () => { - const onMouseOutSpy = sinon.spy(); + const onMouseOutSpy = vi.fn(); - const { getByTestId } = render( + render( {items} , ); - fireEvent.mouseOut(getByTestId('test')); - clock.tick(50); - onMouseOutSpy.should.have.been.calledOnce; + fireEvent.mouseOut(screen.getByTestId('test')); + clock.advanceTimersByTime(50); + expect(onMouseOutSpy).toHaveBeenCalledOnce(); }); }); describe('touch events', () => { - let clock: sinon.SinonFakeTimers, - renderResult: RenderResult, + let clock: ReturnType, carousel: HTMLElement, - onSelectSpy: sinon.SinonSpy, - onTouchStartSpy: sinon.SinonSpy, - onTouchMoveSpy: sinon.SinonSpy, - onTouchEndSpy: sinon.SinonSpy; + onSelectSpy: ReturnType, + onTouchStartSpy: ReturnType, + onTouchMoveSpy: ReturnType, + onTouchEndSpy: ReturnType; beforeEach(() => { - onSelectSpy = sinon.spy(); - onTouchStartSpy = sinon.spy(); - onTouchMoveSpy = sinon.spy(); - onTouchEndSpy = sinon.spy(); + onSelectSpy = vi.fn(); + onTouchStartSpy = vi.fn(); + onTouchMoveSpy = vi.fn(); + onTouchEndSpy = vi.fn(); - renderResult = render( + render( ', () => { , ); - carousel = renderResult.getByTestId('carousel-test'); + carousel = screen.getByTestId('carousel-test'); - clock = sinon.useFakeTimers(); + clock = vi.useFakeTimers(); }); afterEach(() => { - clock.restore(); + clock.useRealTimers(); }); function generateTouchEvents(params: { @@ -808,69 +814,66 @@ describe('', () => { }): void { const { target, startX, endX } = params; - /** - * Below code is not working on Firefox due to Touch is not defined error. - * Maybe related to {@link https://bugzilla.mozilla.org/show_bug.cgi?id=1693172}? - * - * To avoid issue we are going to use {@link import('react-dom').Simulate} (used by enzyme internally) - */ - - // fireEvent.touchStart(target, { - // touches: [new Touch({ identifier: 1, target, clientX: startX })], - // }); - // fireEvent.touchMove(target, { - // touches: [new Touch({ identifier: 1, target, clientX: endX })], - // }); - // fireEvent.touchEnd(target); - - act(() => { - Simulate.touchStart(target, { - touches: [{ identifier: 1, target, clientX: startX }] as never, - }); - Simulate.touchMove(target, { - touches: [{ identifier: 1, target, clientX: endX }] as never, - }); - - Simulate.touchEnd(target); + fireEvent.touchStart(target, { + touches: [ + new Touch({ + identifier: 1, + target, + clientX: startX, + }), + ], + }); + fireEvent.touchMove(target, { + touches: [ + new Touch({ + identifier: 1, + target, + clientX: endX, + }), + ], }); + + fireEvent.touchEnd(target); } it('should swipe right', () => { generateTouchEvents({ target: carousel, startX: 50, endX: 0 }); act(() => { - clock.tick(50); + clock.advanceTimersByTime(50); }); - onSelectSpy.should.have.been.calledOnceWith(2); + expect(onSelectSpy).toHaveBeenCalledOnce(); + expect(onSelectSpy).toHaveBeenCalledWith(2, expect.anything()); }); it('should swipe left', () => { generateTouchEvents({ target: carousel, startX: 0, endX: 50 }); act(() => { - clock.tick(50); + clock.advanceTimersByTime(50); }); - onSelectSpy.should.have.been.calledOnceWith(0); + expect(onSelectSpy).toHaveBeenCalledOnce(); + expect(onSelectSpy).toHaveBeenCalledWith(0, expect.anything()); }); it('should not swipe if swipe detected is under the swipe threshold', () => { generateTouchEvents({ target: carousel, startX: 0, endX: 35 }); act(() => { - clock.tick(50); + clock.advanceTimersByTime(50); }); - onSelectSpy.should.not.have.been.called; + expect(onSelectSpy).not.toHaveBeenCalled(); }); it('should handle a custom touch start and end event', () => { generateTouchEvents({ target: carousel, startX: 50, endX: 0 }); act(() => { - clock.tick(50); + clock.advanceTimersByTime(50); }); - onTouchStartSpy.should.have.been.calledOnce; - onTouchMoveSpy.should.have.been.calledOnce; - onTouchEndSpy.should.have.been.calledOnce; + expect(onTouchStartSpy).toHaveBeenCalledOnce(); + expect(onTouchMoveSpy).toHaveBeenCalledOnce(); + expect(onTouchEndSpy).toHaveBeenCalledOnce(); }); it('should handle a custom multi-touch move event', () => { @@ -883,19 +886,19 @@ describe('', () => { // ], // }); - Simulate.touchMove(carousel, { + fireEvent.touchMove(carousel, { touches: [ - { identifier: 1, target: carousel, clientX: 0 }, - { identifier: 1, target: carousel, clientX: 50 }, - ] as never, + new Touch({ identifier: 1, target: carousel, clientX: 0 }), + new Touch({ identifier: 1, target: carousel, clientX: 50 }), + ], }); - clock.tick(50); - onTouchMoveSpy.should.have.been.calledOnce; + clock.advanceTimersByTime(50); + expect(onTouchMoveSpy).toHaveBeenCalledOnce(); }); it('should do nothing with disabled touch right', () => { - const { getByTestId, container } = render( + const { container } = render( ', () => { , ); - const noTouchCarousel = getByTestId('test'); + const noTouchCarousel = screen.getByTestId('test'); generateTouchEvents({ target: noTouchCarousel, startX: 50, endX: 0 }); act(() => { - clock.tick(50); + clock.advanceTimersByTime(50); }); - onSelectSpy.should.not.have.been.called; + expect(onSelectSpy).not.toHaveBeenCalled(); const carouselItems = container.querySelectorAll('.carousel-item'); - carouselItems.should.have.lengthOf(3); + expect(carouselItems).toHaveLength(3); - carouselItems[1].classList.contains('active').should.be.true; + expect(carouselItems[1].classList).toContain('active'); }); }); describe('callback tests', () => { - let clock: sinon.SinonFakeTimers; + let clock: ReturnType; beforeEach(() => { - clock = sinon.useFakeTimers(); + clock = vi.useFakeTimers(); }); afterEach(() => { - clock.restore(); + clock.useRealTimers(); }); it('should call onSlide when slide animation is disabled', () => { - const onSlideSpy = sinon.spy(); - const onSelectSpy = sinon.spy(); + const onSlideSpy = vi.fn(); + const onSelectSpy = vi.fn(); const { container } = render( @@ -948,23 +951,23 @@ describe('', () => { ); act(() => { - clock.tick(150); + clock.advanceTimersByTime(150); }); - onSlideSpy.should.have.been.calledOnce; + expect(onSlideSpy).toHaveBeenCalledOnce(); fireEvent.click( container.querySelector('a.carousel-control-prev')!, ); act(() => { - clock.tick(150); + clock.advanceTimersByTime(150); }); - onSlideSpy.should.have.been.calledTwice; + expect(onSlideSpy).toHaveBeenCalledTimes(2); }); it('should call onSlid when slide animation is disabled', () => { - const onSlidSpy = sinon.spy(); - const onSelectSpy = sinon.spy(); + const onSlidSpy = vi.fn(); + const onSelectSpy = vi.fn(); const { container } = render( @@ -976,21 +979,21 @@ describe('', () => { container.querySelector('a.carousel-control-next')!, ); act(() => { - clock.tick(150); + clock.advanceTimersByTime(150); }); - onSlidSpy.should.have.been.calledOnce; + expect(onSlidSpy).toHaveBeenCalledOnce(); fireEvent.click( container.querySelector('a.carousel-control-prev')!, ); act(() => { - clock.tick(150); + clock.advanceTimersByTime(150); }); - onSlidSpy.should.have.been.calledTwice; + expect(onSlidSpy).toHaveBeenCalledTimes(2); }); it('should transition/call onSelect once if previous arrow double clicked', () => { - const onSelectSpy = sinon.spy(); + const onSelectSpy = vi.fn(); const { container } = render( {items}, @@ -1003,13 +1006,13 @@ describe('', () => { fireEvent.click(prev); act(() => { - clock.tick(1000); + clock.advanceTimersByTime(1000); }); - onSelectSpy.should.have.been.calledOnce; + expect(onSelectSpy).toHaveBeenCalledOnce(); }); it('should transition/call onSelect once if next arrow double clicked', () => { - const onSelectSpy = sinon.spy(); + const onSelectSpy = vi.fn(); const { container } = render( {items}, @@ -1022,27 +1025,27 @@ describe('', () => { fireEvent.click(next); act(() => { - clock.tick(1000); + clock.advanceTimersByTime(1000); }); - onSelectSpy.should.have.been.calledOnce; + expect(onSelectSpy).toHaveBeenCalledOnce(); }); }); describe('RTL', () => { - let clock: sinon.SinonFakeTimers; + let clock: ReturnType; beforeEach(() => { - clock = sinon.useFakeTimers(); + clock = vi.useFakeTimers(); }); afterEach(() => { - clock.restore(); + clock.useRealTimers(); }); it('should slide in correct direction on ArrowLeft when dir=rtl', () => { - const onSelectSpy = sinon.spy(); + const onSelectSpy = vi.fn(); - const { getByTestId } = render( + render( {items} @@ -1050,20 +1053,21 @@ describe('', () => { , ); - fireEvent.keyDown(getByTestId('test'), { + fireEvent.keyDown(screen.getByTestId('test'), { key: 'ArrowLeft', }); act(() => { - clock.tick(50); + clock.advanceTimersByTime(50); }); - onSelectSpy.should.have.been.calledOnceWith(2); + expect(onSelectSpy).toHaveBeenCalledOnce(); + expect(onSelectSpy).toHaveBeenCalledWith(2, expect.anything()); }); it('should slide in correct direction on ArrowLeft when dir=rtl', () => { - const onSelectSpy = sinon.spy(); + const onSelectSpy = vi.fn(); - const { getByTestId } = render( + render( {items} @@ -1071,18 +1075,19 @@ describe('', () => { , ); - fireEvent.keyDown(getByTestId('test'), { + fireEvent.keyDown(screen.getByTestId('test'), { key: 'ArrowRight', }); act(() => { - clock.tick(50); + clock.advanceTimersByTime(50); }); - onSelectSpy.should.have.been.calledOnceWith(0); + expect(onSelectSpy).toHaveBeenCalledOnce(); + expect(onSelectSpy).toHaveBeenCalledWith(0, expect.anything()); }); it('should slide in correct direction automatically when dir=rtl', () => { - const onSelectSpy = sinon.spy(); + const onSelectSpy = vi.fn(); const interval = 300; render( @@ -1094,10 +1099,11 @@ describe('', () => { ); act(() => { - clock.tick(interval * 1.5); + clock.advanceTimersByTime(interval * 1.5); }); - onSelectSpy.should.have.been.calledOnceWith(0); + expect(onSelectSpy).toHaveBeenCalledOnce(); + expect(onSelectSpy).toHaveBeenCalledWith(0, undefined); }); }); }); diff --git a/test/CloseButtonSpec.tsx b/test/CloseButtonSpec.tsx index d2d972e740..981f76c5f3 100644 --- a/test/CloseButtonSpec.tsx +++ b/test/CloseButtonSpec.tsx @@ -1,47 +1,49 @@ -import { fireEvent, render } from '@testing-library/react'; -import { expect } from 'chai'; -import sinon from 'sinon'; - +import { describe, expect, it, vi } from 'vitest'; +import { fireEvent, render, screen } from '@testing-library/react'; import CloseButton from '../src/CloseButton'; describe('', () => { it('Should output a button', () => { - const { getAllByRole } = render(); + render(); - getAllByRole('button').should.have.lengthOf(1); + expect(screen.getAllByRole('button')).toHaveLength(1); }); it('Should have type=button by default', () => { - const { getByRole } = render(); + render(); - expect(getByRole('button').getAttribute('type')).to.be.equal('button'); + expect(screen.getByRole('button').getAttribute('type')).toEqual('button'); }); it('Should have class .btn-close', () => { - const { getByRole } = render(); + render(); - getByRole('button').classList.contains('btn-close'); + expect(screen.getByRole('button').classList).toContain('btn-close'); }); it('Should call onClick callback', () => { - const onClickSpy = sinon.spy(); + const onClickSpy = vi.fn(); - const { getByRole } = render(); + render(); - fireEvent.click(getByRole('button')); + fireEvent.click(screen.getByRole('button')); - onClickSpy.should.have.been.calledOnce; + expect(onClickSpy).toHaveBeenCalledOnce(); }); it('Should have a aria-label defaulted to "Close"', () => { - const { getByLabelText } = render(); + render(); - getByLabelText('Close', { selector: '[aria-label]' }).should.exist; + expect( + screen.getByLabelText('Close', { selector: '[aria-label]' }), + ).toBeTruthy(); }); it('Should allow override of aria-label', () => { - const { getByLabelText } = render(); + render(); - getByLabelText('My Close', { selector: '[aria-label]' }).should.exist; + expect( + screen.getByLabelText('My Close', { selector: '[aria-label]' }), + ).toBeTruthy(); }); }); diff --git a/test/ColSpec.tsx b/test/ColSpec.tsx index bb25b1013d..3317abfb3e 100644 --- a/test/ColSpec.tsx +++ b/test/ColSpec.tsx @@ -1,36 +1,36 @@ -import { render } from '@testing-library/react'; +import { describe, expect, it } from 'vitest'; +import { render, screen } from '@testing-library/react'; import { ThemeProvider } from '../src'; - import Col from '../src/Col'; describe('Col', () => { it('Should include "col" when there are no sizes', () => { - const { getByText } = render(Column); - getByText('Column').classList.contains('col').should.be.true; + render(Column); + expect(screen.getByText('Column').classList).toContain('col'); }); it('Should include "col" when xs is true', () => { - const { getByText } = render(Column); - getByText('Column').classList.contains('col').should.be.true; + render(Column); + expect(screen.getByText('Column').classList).toContain('col'); render(Column2); - getByText('Column2').classList.contains('col').should.be.true; + expect(screen.getByText('Column2').classList).toContain('col'); }); it('Should include sizes', () => { - const { getByText } = render( + render( Column , ); - getByText('Column').classList.length.should.equal(3); - getByText('Column').classList.contains('col-4').should.be.true; - getByText('Column').classList.contains('col-md-8').should.be.true; - getByText('Column').classList.contains('col-lg-12').should.be.true; + expect(screen.getByText('Column').classList).toHaveLength(3); + expect(screen.getByText('Column').classList).toContain('col-4'); + expect(screen.getByText('Column').classList).toContain('col-md-8'); + expect(screen.getByText('Column').classList).toContain('col-lg-12'); }); it('Should include offsets', () => { - const { getByText } = render( + render( { Column , ); - getByText('Column').classList.length.should.equal(5); - getByText('Column').classList.contains('col-md-8').should.be.true; - getByText('Column').classList.contains('order-md-1').should.be.true; - getByText('Column').classList.contains('col-4').should.be.true; - getByText('Column').classList.contains('offset-1').should.be.true; - getByText('Column').classList.contains('order-lg-last').should.be.true; + expect(screen.getByText('Column').classList).toHaveLength(5); + expect(screen.getByText('Column').classList).toContain('col-md-8'); + expect(screen.getByText('Column').classList).toContain('order-md-1'); + expect(screen.getByText('Column').classList).toContain('col-4'); + expect(screen.getByText('Column').classList).toContain('offset-1'); + expect(screen.getByText('Column').classList).toContain('order-lg-last'); }); it('Should allow span to be null', () => { - const { getByText } = render( + render( // @ts-ignore Column , ); - getByText('Column').classList.contains('col-6').should.be.true; - getByText('Column').classList.contains('order-md-1').should.be.true; - getByText('Column').classList.contains('col-md').should.equal(false); + expect(screen.getByText('Column').classList).toContain('col-6'); + expect(screen.getByText('Column').classList).toContain('order-md-1'); + expect(screen.getByText('Column').classList).not.toContain('col-md'); }); it('Should allow span to be false', () => { - const { getByText } = render( + render( Column , ); - getByText('Column').classList.contains('col-6').should.be.true; - getByText('Column').classList.contains('order-md-1').should.be.true; - getByText('Column').classList.contains('col-md').should.equal(false); + expect(screen.getByText('Column').classList).toContain('col-6'); + expect(screen.getByText('Column').classList).toContain('order-md-1'); + expect(screen.getByText('Column').classList).not.toContain('col-md'); }); it('Should allow span to be auto', () => { - const { getByText } = render( + render( Column , ); - getByText('Column').classList.contains('col-md-auto').should.be.true; - getByText('Column').classList.contains('col-lg-auto').should.be.true; + expect(screen.getByText('Column').classList).toContain('col-md-auto'); + expect(screen.getByText('Column').classList).toContain('col-lg-auto'); }); it('Should have div as default component', () => { - const { getByText } = render(Column); - getByText('Column').tagName.toLowerCase().should.equal('div'); + render(Column); + expect(screen.getByText('Column').tagName).toEqual('DIV'); }); it('should allow custom breakpoints', () => { - const { getByText } = render( + render( test , ); - getByText('test').classList.contains('col-custom-3').should.be.true; + expect(screen.getByText('test').classList).toContain('col-custom-3'); }); it('should allow custom breakpoints smaller than default "xs"', () => { - const { getByText } = render( + render( test @@ -103,7 +103,7 @@ describe('Col', () => { , ); - getByText('test').classList.contains('col-3').should.be.true; - getByText('test').classList.contains('col-xs-2').should.be.true; + expect(screen.getByText('test').classList).toContain('col-3'); + expect(screen.getByText('test').classList).toContain('col-xs-2'); }); }); diff --git a/test/CollapseSpec.tsx b/test/CollapseSpec.tsx index f9152cd786..8fd076f82f 100644 --- a/test/CollapseSpec.tsx +++ b/test/CollapseSpec.tsx @@ -1,8 +1,6 @@ import * as React from 'react'; -import { render, RenderResult, waitFor } from '@testing-library/react'; -import sinon from 'sinon'; -import { expect } from 'chai'; - +import { beforeEach, describe, expect, it, vi } from 'vitest'; +import { render, screen, RenderResult, waitFor } from '@testing-library/react'; import Collapse, { CollapseProps } from '../src/Collapse'; describe('', () => { @@ -43,7 +41,7 @@ describe('', () => { } } - const onEnteringSpy = sinon.spy(); + const onEnteringSpy = vi.fn(); const { rerender } = render( @@ -57,22 +55,22 @@ describe('', () => { , ); - onEnteringSpy.should.have.been.calledOnce; + expect(onEnteringSpy).toHaveBeenCalledOnce(); }); it('Should default to collapsed', () => { - const { getByTestId } = render( - Panel content, - ); + render(Panel content); - getByTestId('test').classList.contains('show').should.be.false; - getByTestId('status-hide').should.exist; + expect(screen.getByTestId('test').classList).not.toContain('show'); + expect(screen.getByTestId('status-hide')).toBeDefined(); }); it('Should have collapse class', () => { - const { getByTestId } = render(Panel content); + render(Panel content); - getByTestId('collapse-component').classList.contains('collapse'); + expect(screen.getByTestId('collapse-component').classList).toContain( + 'collapse', + ); }); describe('from collapsed to expanded', () => { @@ -85,60 +83,63 @@ describe('', () => { it('Should have collapsing class', () => { renderResult.rerender(Panel content); - renderResult - .getByTestId('collapse-component') - .classList.contains('collapsing'); + expect(screen.getByTestId('collapse-component').classList).toContain( + 'collapsing', + ); }); - it('Should set initial 0px height', (done) => { - const node = renderResult.getByTestId('collapse-component'); + it('Should set initial 0px height', async () => { + const onEnterSpy = vi.fn(); + const node = screen.getByTestId('collapse-component'); - expect(node.style.height).to.be.equal(''); + expect(node.style.height).toEqual(''); renderResult.rerender( { - expect(node.style.height).to.be.equal('0px'); - done(); + expect(node.style.height).toEqual('0px'); + onEnterSpy(); }} > Panel content , ); + + await waitFor(() => expect(onEnterSpy).toHaveBeenCalled()); }); it('Should set node to height', () => { - const node = renderResult.getByTestId('collapse-component'); + const node = screen.getByTestId('collapse-component'); - expect(node.style.height).to.be.equal(''); + expect(node.style.height).toEqual(''); renderResult.rerender(Panel content); - expect(node.style.height).to.be.equal(`${node.scrollHeight}px`); + expect(node.style.height).toEqual(`${node.scrollHeight}px`); }); it('Should transition from collapsing to not collapsing', async () => { - const node = renderResult.getByTestId('collapse-component'); + const node = screen.getByTestId('collapse-component'); renderResult.rerender(Panel content); - node.classList.contains('collapsing').should.be.true; + expect(node.classList).toContain('collapsing'); - await waitFor(() => node.classList.contains('collapse').should.be.true); - node.classList.contains('show').should.be.true; + await waitFor(() => expect(node.classList).toContain('collapse')); + expect(node.classList).toContain('show'); }); it('Should clear height after transition complete', async () => { - const node = renderResult.getByTestId('collapse-component'); + const node = screen.getByTestId('collapse-component'); - expect(node.style.height).to.be.equal(''); + expect(node.style.height).toEqual(''); renderResult.rerender(Panel content); - expect(node.style.height).to.be.equal(`${node.scrollHeight}px`); + expect(node.style.height).toEqual(`${node.scrollHeight}px`); - await waitFor(() => expect(node.style.height).to.be.equal('')); + await waitFor(() => expect(node.style.height).toEqual('')); }); }); @@ -152,84 +153,85 @@ describe('', () => { it('Should have collapsing class', () => { renderResult.rerender(Panel content); - const node = renderResult.getByTestId('collapse-component'); - node.classList.contains('collapsing').should.be.true; + const node = screen.getByTestId('collapse-component'); + expect(node.classList).toContain('collapsing'); }); - it('Should set initial height', (done) => { - const node = renderResult.getByTestId('collapse-component'); + it('Should set initial height', async () => { + const onExitSpy = vi.fn(); + const node = screen.getByTestId('collapse-component'); - expect(node.style.height).to.be.equal(''); + expect(node.style.height).toEqual(''); renderResult.rerender( { - expect(node.style.height).to.be.equal('15px'); - done(); + expect(node.style.height).toEqual('15px'); + onExitSpy(); }} > Panel content , ); + + await waitFor(() => expect(onExitSpy).toHaveBeenCalled()); }); it('Should set node to height', () => { - const node = renderResult.getByTestId('collapse-component'); + const node = screen.getByTestId('collapse-component'); - expect(node.style.height).to.be.equal(''); + expect(node.style.height).toEqual(''); renderResult.rerender(Panel content); - expect(node.style.height).to.be.equal(''); + expect(node.style.height).toEqual(''); }); it('Should transition from collapsing to not collapsing', async () => { - const node = renderResult.getByTestId('collapse-component'); + const node = screen.getByTestId('collapse-component'); renderResult.rerender(Panel content); - node.classList.contains('collapsing').should.be.true; + expect(node.classList).toContain('collapsing'); - await waitFor(() => node.classList.contains('collapse').should.be.true); + await waitFor(() => expect(node.classList).toContain('collapse')); }); it('Should have no height after transition complete', async () => { - const node = renderResult.getByTestId('collapse-component'); + const node = screen.getByTestId('collapse-component'); - expect(node.style.height).to.be.equal(''); + expect(node.style.height).toEqual(''); renderResult.rerender(Panel content); - await waitFor(() => expect(node.style.height).to.be.equal('')); + await waitFor(() => expect(node.style.height).toEqual('')); }); }); describe('expanded', () => { it('Should have collapse and in class', () => { - const { getByTestId } = render(Panel content); + render(Panel content); - const node = getByTestId('collapse-component'); - node.classList.contains('collapse').should.be.true; - node.classList.contains('show').should.be.true; + const node = screen.getByTestId('collapse-component'); + expect(node.classList).toContain('collapse'); + expect(node.classList).toContain('show'); }); }); describe('dimension', () => { it('Should not have width in class', () => { - const { getByTestId } = render(Panel content); + render(Panel content); - const node = getByTestId('collapse-component'); - node.className.includes('width').should.be.false; + const node = screen.getByTestId('collapse-component'); + expect(node.className.includes('width')).toEqual(false); }); it('Should have collapse-horizontal in class', () => { - const { getByTestId } = render( - 'width'}>Panel content, - ); + render( 'width'}>Panel content); - const node = getByTestId('collapse-component'); - node.classList.contains('collapse-horizontal').should.be.true; + const node = screen.getByTestId('collapse-component'); + expect(node.classList).toContain('collapse-horizontal'); }); }); @@ -241,7 +243,7 @@ describe('', () => { , ); - getByRole('menuitem', { expanded: true }).should.exist; + expect(getByRole('menuitem', { expanded: true })).toBeDefined(); }); it('sets aria-expanded false when collapsed', () => { @@ -251,7 +253,7 @@ describe('', () => { , ); - getByRole('menuitem', { expanded: false }).should.exist; + expect(getByRole('menuitem', { expanded: false })).toBeDefined(); }); }); }); diff --git a/test/ContainerSpec.tsx b/test/ContainerSpec.tsx index 83f3cde7e1..3715a6c1fc 100644 --- a/test/ContainerSpec.tsx +++ b/test/ContainerSpec.tsx @@ -1,38 +1,38 @@ -import { render } from '@testing-library/react'; - +import { describe, expect, it } from 'vitest'; +import { render, screen } from '@testing-library/react'; import Container from '../src/Container'; describe('', () => { it('should render props correctly', () => { - const { getByText } = render( - Container, - ); - getByText('Container').classList.contains('whatever').should.be.true; + render(Container); + expect(screen.getByText('Container').classList).toContain('whatever'); }); it('turns grid into "full-width" layout via "fluid" property set', () => { - const { getByText } = render(Container); - getByText('Container').classList.contains('container-fluid').should.be.true; + render(Container); + expect(screen.getByText('Container').classList).toContain( + 'container-fluid', + ); }); it('Should include size breakpoint class when fluid is set to sm, md, lg or xl', () => { - const { getByText } = render(Container); - getByText('Container').classList.contains('container-sm').should.be.true; + render(Container); + expect(screen.getByText('Container').classList).toContain('container-sm'); }); it('allows custom elements instead of "div"', () => { - const { getByText } = render(Container); - getByText('Container').classList.contains('container').should.be.true; - getByText('Container').tagName.toLowerCase().should.equal('section'); + render(Container); + expect(screen.getByText('Container').classList).toContain('container'); + expect(screen.getByText('Container').tagName).toEqual('SECTION'); }); it('Should have div as default component', () => { - const { getByText } = render(Container); - getByText('Container').tagName.toLowerCase().should.equal('div'); + render(Container); + expect(screen.getByText('Container').tagName).toEqual('DIV'); }); it('should allow custom breakpoints', () => { - const { getByText } = render(test); - getByText('test').classList.contains('container-custom').should.be.true; + render(test); + expect(screen.getByText('test').classList).toContain('container-custom'); }); }); diff --git a/test/DropdownButtonSpec.tsx b/test/DropdownButtonSpec.tsx index 755f14041b..08c5afa274 100644 --- a/test/DropdownButtonSpec.tsx +++ b/test/DropdownButtonSpec.tsx @@ -1,11 +1,11 @@ -import { render, fireEvent } from '@testing-library/react'; -import sinon from 'sinon'; +import { describe, expect, it, vi } from 'vitest'; +import { fireEvent, render, screen } from '@testing-library/react'; import DropdownButton from '../src/DropdownButton'; import DropdownItem from '../src/DropdownItem'; describe('', () => { it('renders a toggle with the title prop', () => { - const { getByTestId } = render( + render( Item 1 Item 2 @@ -13,7 +13,9 @@ describe('', () => { Item 4 , ); - getByTestId('test-id').textContent!.should.equal('Simple Dropdown'); + expect(screen.getByTestId('test-id').textContent).toEqual( + 'Simple Dropdown', + ); }); it('renders single DropdownItem child', () => { @@ -22,7 +24,7 @@ describe('', () => { Item 1 , ); - getByText('Item 1'); + expect(getByText('Item 1')).toBeDefined(); }); it('forwards align="end" to the Dropdown', () => { @@ -33,11 +35,11 @@ describe('', () => { ); const menu = container.querySelector('div[x-placement]'); - menu!.classList.contains('dropdown-menu-end').should.be.true; + expect(menu!.classList).toContain('dropdown-menu-end'); }); it('passes variant and size to the toggle', () => { - const { getByTestId } = render( + render( ', () => { , ); - const button = getByTestId('test-id').firstElementChild!; - button.classList.contains('btn-success').should.be.true; - button.classList.contains('btn-sm').should.be.true; + const button = screen.getByTestId('test-id').firstElementChild!; + expect(button.classList).toContain('btn-success'); + expect(button.classList).toContain('btn-sm'); }); it('passes menuVariant to dropdown menu', () => { @@ -61,13 +63,13 @@ describe('', () => { ); const menu = container.querySelector('div[x-placement]'); - menu!.classList.contains('dropdown-menu-dark').should.be.true; + expect(menu!.classList).toContain('dropdown-menu-dark'); }); it('forwards onSelect handler to DropdownItems', () => { - const onSelectSpy = sinon.spy(); + const onSelectSpy = vi.fn(); - const { getByTestId } = render( + render( ', () => { , ); - fireEvent.click(getByTestId('key1')); - onSelectSpy.should.be.calledWith('1'); - fireEvent.click(getByTestId('key2')); - onSelectSpy.should.be.calledWith('2'); - fireEvent.click(getByTestId('key3')); - onSelectSpy.should.be.calledWith('3'); + fireEvent.click(screen.getByTestId('key1')); + expect(onSelectSpy).toHaveBeenCalledWith('1', expect.anything()); + fireEvent.click(screen.getByTestId('key2')); + expect(onSelectSpy).toHaveBeenCalledWith('2', expect.anything()); + fireEvent.click(screen.getByTestId('key3')); + expect(onSelectSpy).toHaveBeenCalledWith('3', expect.anything()); - onSelectSpy.should.be.calledThrice; + expect(onSelectSpy).toBeCalledTimes(3); }); it('does not close when onToggle is controlled', () => { - const onSelectSpy = sinon.spy(); + const onSelectSpy = vi.fn(); - const { container, getByTestId } = render( + const { container } = render( ', () => { , ); - fireEvent.click(getByTestId('test-id').firstElementChild!); - fireEvent.click(getByTestId('key1')); + fireEvent.click(screen.getByTestId('test-id').firstElementChild!); + fireEvent.click(screen.getByTestId('key1')); - onSelectSpy.should.have.been.calledWith(false); + expect(onSelectSpy).toHaveBeenCalledWith(false, expect.anything()); const menu = container.querySelector('div[x-placement]'); - menu!.should.exist; + expect(menu).toBeDefined(); }); it('Should pass disabled to button', () => { @@ -127,17 +129,17 @@ describe('', () => { , ); - container.querySelector('button[disabled]')!.should.exist; + expect(container.querySelector('button[disabled]')).toBeDefined(); }); it('should pass bsPrefix to the button', () => { - const { getByTestId } = render( + render( Item 1 , ); - const button = getByTestId('test-id').firstElementChild!; - button.classList.contains('my-button-primary').should.be.true; + const button = screen.getByTestId('test-id').firstElementChild!; + expect(button.classList).toContain('my-button-primary'); }); }); diff --git a/test/DropdownItemSpec.tsx b/test/DropdownItemSpec.tsx index 6ca5cd1c0f..b3ac47180f 100644 --- a/test/DropdownItemSpec.tsx +++ b/test/DropdownItemSpec.tsx @@ -1,78 +1,73 @@ -import { render, fireEvent } from '@testing-library/react'; -import sinon from 'sinon'; - +import { describe, expect, it, vi } from 'vitest'; +import { fireEvent, render, screen } from '@testing-library/react'; import Button from '../src/Button'; import Dropdown from '../src/Dropdown'; describe('', () => { it('renders divider', () => { - const { getByRole } = render(); - getByRole('separator'); + render(); + screen.getByRole('separator'); }); it('renders divider className and style', () => { - const { getByRole } = render( + render( , ); - const node = getByRole('separator'); - node.className.should.match(/\bfoo bar dropdown-divider\b/); - node.style.height.should.equal('100px'); + const node = screen.getByRole('separator'); + expect(node.className).toMatch(/\bfoo bar dropdown-divider\b/); + expect(node.style.height).toEqual('100px'); }); it('renders header', () => { - const { getByRole } = render( - Header text, - ); + render(Header text); - getByRole('heading').textContent!.should.equal('Header text'); + expect(screen.getByRole('heading').textContent).toEqual('Header text'); }); it('renders header className and style', () => { - const { getByText } = render( + render( Header text , ); - const node = getByText('Header text'); - node.className.should.match(/\bfoo bar dropdown-header\b/); + const node = screen.getByText('Header text'); + expect(node.className).toMatch(/\bfoo bar dropdown-header\b/); }); it('renders Dropdown.ItemText', () => { - const { getByText } = render( - My text, - ); + render(My text); - getByText('My text').className.should.equal('dropdown-item-text'); + expect(screen.getByText('My text').className).toEqual('dropdown-item-text'); }); it('renders Dropdown.ItemText className and style', () => { - const { getByText } = render( + render( My text , ); - const node = getByText('My text'); - node.className.should.match(/\bfoo bar dropdown-item-text\b/); - node.style.height.should.equal('100px'); + const node = screen.getByText('My text'); + expect(node.className).toMatch(/\bfoo bar dropdown-item-text\b/); + expect(node.style.height).toEqual('100px'); }); it('renders menu item link', () => { - const onKeyDownSpy = sinon.spy(); + const onKeyDownSpy = vi.fn(); - const { getByText } = render( + render( Item , ); - const node = getByText('Item'); - node.getAttribute('href')!.should.equal('/herpa-derpa'); + const node = screen.getByText('Item'); + expect(node.getAttribute('href')!).toEqual('/herpa-derpa'); fireEvent.keyDown(node, { key: 'a' }); - onKeyDownSpy.should.be.called; + expect(onKeyDownSpy).toHaveBeenCalled(); }); it('should render as a button when set', () => { @@ -80,15 +75,13 @@ describe('', () => { , ); - getByTestId('item').classList.should.contain([ - 'dropdown-item', - 'btn', - 'btn-success', - ]); + expect(getByTestId('item').classList).toContain('dropdown-item'); + expect(getByTestId('item').classList).toContain('btn'); + expect(getByTestId('item').classList).toContain('btn-success'); }); it('should pass through props', () => { - const { getByText } = render( + render( ', () => { , ); - const node = getByText('Title'); - node.className.should.match(/\btest-class\b/); - node.style.height.should.equal('100px'); - node.getAttribute('href')!.should.equal('#hi-mom!'); - node.getAttribute('title')!.should.equal('hi mom!'); + const node = screen.getByText('Title'); + expect(node.className).toMatch(/\btest-class\b/); + expect(node.style.height).toEqual('100px'); + expect(node.getAttribute('href')).toEqual('#hi-mom!'); + expect(node.getAttribute('title')).toEqual('hi mom!'); }); it('Should set target attribute on anchor', () => { - const { getByText } = render( - Title, - ); - getByText('Title').getAttribute('target')!.should.equal('_blank'); + render(Title); + expect(screen.getByText('Title').getAttribute('target')).toEqual('_blank'); }); }); diff --git a/test/DropdownMenuSpec.tsx b/test/DropdownMenuSpec.tsx index cd2e9c8cae..b4ab183556 100644 --- a/test/DropdownMenuSpec.tsx +++ b/test/DropdownMenuSpec.tsx @@ -1,4 +1,6 @@ -import { render } from '@testing-library/react'; +import { describe, expect, it } from 'vitest'; +import { fireEvent, render, screen } from '@testing-library/react'; +import Dropdown from '../src/Dropdown'; import DropdownItem from '../src/DropdownItem'; import DropdownMenu, { getDropdownMenuPlacement } from '../src/DropdownMenu'; @@ -13,8 +15,7 @@ describe('', () => { , ); - container.firstElementChild!.classList.contains('dropdown-menu').should.be - .true; + expect(container.firstElementChild!.classList).toContain('dropdown-menu'); }); it('Should pass props to dropdown', () => { @@ -24,8 +25,7 @@ describe('', () => { , ); - container.firstElementChild!.classList.contains('new-fancy-class').should.be - .true; + expect(container.firstElementChild!.classList).toContain('new-fancy-class'); }); it('applies align="end"', () => { @@ -35,8 +35,9 @@ describe('', () => { , ); - container.firstElementChild!.classList.contains('dropdown-menu-end').should - .be.true; + expect(container.firstElementChild!.classList).toContain( + 'dropdown-menu-end', + ); }); it('renders on mount with prop', () => { @@ -46,8 +47,7 @@ describe('', () => { , ); - container.firstElementChild!.classList.contains('dropdown-menu').should.be - .true; + expect(container.firstElementChild!.classList).toContain('dropdown-menu'); }); it('does not add any extra classes when align="start"', () => { @@ -57,7 +57,9 @@ describe('', () => { , ); - container.firstElementChild!.className.should.equal('dropdown-menu show'); + expect(container.firstElementChild!.className).toEqual( + 'dropdown-menu show', + ); }); it('adds responsive start alignment classes', () => { @@ -66,10 +68,12 @@ describe('', () => { Item , ); - container.firstElementChild!.classList.contains('dropdown-menu-end').should - .be.true; - container.firstElementChild!.classList.contains('dropdown-menu-lg-start') - .should.be.true; + expect(container.firstElementChild!.classList).toContain( + 'dropdown-menu-end', + ); + expect(container.firstElementChild!.classList).toContain( + 'dropdown-menu-lg-start', + ); }); it('adds responsive end alignment classes', () => { @@ -79,9 +83,11 @@ describe('', () => { , ); - container.firstElementChild!.classList.contains('dropdown-menu-lg-end') - .should.be.true; - container.querySelector('[data-bs-popper="static"]')!.should.exist; + expect(container.firstElementChild!.classList).toContain( + 'dropdown-menu-lg-end', + ); + + expect(container.querySelector('[data-bs-popper="static"]')).toBeDefined(); }); it('allows custom responsive alignment classes', () => { @@ -91,8 +97,9 @@ describe('', () => { , ); - container.firstElementChild!.classList.contains('dropdown-menu-custom-end') - .should.be.true; + expect(container.firstElementChild!.classList).toContain( + 'dropdown-menu-custom-end', + ); }); it('should render variant', () => { @@ -102,63 +109,103 @@ describe('', () => { , ); - container.firstElementChild!.classList.contains('dropdown-menu-dark').should - .be.true; + expect(container.firstElementChild!.classList).toContain( + 'dropdown-menu-dark', + ); + }); + + it('does not flicker when rootCloseEvent is set to "mousedown" and toggle button is clicked', () => { + const { container } = render( + + + Dropdown Button + + + Action + + , + ); + // Click the toggle button to open the menu + fireEvent.click(screen.getByTestId('dropdown-toggle')); + // The menu should now be in the DOM + expect(container.firstElementChild!.classList).toContain('show'); + // Click the toggle button again to close the menu + fireEvent.click(screen.getByTestId('dropdown-toggle')); + // The menu should no longer be in the DOM + expect(container.firstElementChild!.classList).not.toContain('show'); }); describe('getDropdownMenuPlacement', () => { it('should return top placement', () => { - getDropdownMenuPlacement(false, 'up', false).should.equal('top-start'); - getDropdownMenuPlacement(true, 'up', false).should.equal('top-end'); - getDropdownMenuPlacement(true, 'up-centered', false).should.equal('top'); + expect(getDropdownMenuPlacement(false, 'up', false)).toEqual('top-start'); + expect(getDropdownMenuPlacement(true, 'up', false)).toEqual('top-end'); + expect(getDropdownMenuPlacement(true, 'up-centered', false)).toEqual( + 'top', + ); }); it('should return top placement for RTL', () => { - getDropdownMenuPlacement(false, 'up', true).should.equal('top-end'); - getDropdownMenuPlacement(true, 'up', true).should.equal('top-start'); - getDropdownMenuPlacement(true, 'up-centered', true).should.equal('top'); + expect(getDropdownMenuPlacement(false, 'up', true)).toEqual('top-end'); + expect(getDropdownMenuPlacement(true, 'up', true)).toEqual('top-start'); + expect(getDropdownMenuPlacement(true, 'up-centered', true)).toEqual( + 'top', + ); }); it('should return end placement', () => { - getDropdownMenuPlacement(false, 'end', false).should.equal('right-start'); - getDropdownMenuPlacement(true, 'end', false).should.equal('right-end'); + expect(getDropdownMenuPlacement(false, 'end', false)).toEqual( + 'right-start', + ); + expect(getDropdownMenuPlacement(true, 'end', false)).toEqual('right-end'); }); it('should return end placement for RTL', () => { - getDropdownMenuPlacement(false, 'end', true).should.equal('left-start'); - getDropdownMenuPlacement(true, 'end', true).should.equal('left-end'); + expect(getDropdownMenuPlacement(false, 'end', true)).toEqual( + 'left-start', + ); + expect(getDropdownMenuPlacement(true, 'end', true)).toEqual('left-end'); }); it('should return bottom placement', () => { - getDropdownMenuPlacement(false, 'down', false).should.equal( + expect(getDropdownMenuPlacement(false, 'down', false)).toEqual( 'bottom-start', ); - getDropdownMenuPlacement(true, 'down', false).should.equal('bottom-end'); - getDropdownMenuPlacement(true, 'down-centered', false).should.equal( + expect(getDropdownMenuPlacement(true, 'down', false)).toEqual( + 'bottom-end', + ); + expect(getDropdownMenuPlacement(true, 'down-centered', false)).toEqual( 'bottom', ); }); it('should return bottom placement for RTL', () => { - getDropdownMenuPlacement(false, 'down', true).should.equal('bottom-end'); - getDropdownMenuPlacement(true, 'down', true).should.equal('bottom-start'); - getDropdownMenuPlacement(true, 'down-centered', true).should.equal( + expect(getDropdownMenuPlacement(false, 'down', true)).toEqual( + 'bottom-end', + ); + expect(getDropdownMenuPlacement(true, 'down', true)).toEqual( + 'bottom-start', + ); + expect(getDropdownMenuPlacement(true, 'down-centered', true)).toEqual( 'bottom', ); }); it('should return start placement', () => { - getDropdownMenuPlacement(false, 'start', false).should.equal( + expect(getDropdownMenuPlacement(false, 'start', false)).toEqual( 'left-start', ); - getDropdownMenuPlacement(true, 'start', false).should.equal('left-end'); + expect(getDropdownMenuPlacement(true, 'start', false)).toEqual( + 'left-end', + ); }); it('should return start placement for RTL', () => { - getDropdownMenuPlacement(false, 'start', true).should.equal( + expect(getDropdownMenuPlacement(false, 'start', true)).toEqual( 'right-start', ); - getDropdownMenuPlacement(true, 'start', true).should.equal('right-end'); + expect(getDropdownMenuPlacement(true, 'start', true)).toEqual( + 'right-end', + ); }); }); }); diff --git a/test/DropdownMousedownSpec.tsx b/test/DropdownMousedownSpec.tsx deleted file mode 100644 index 096ad0da79..0000000000 --- a/test/DropdownMousedownSpec.tsx +++ /dev/null @@ -1,25 +0,0 @@ -import { render, fireEvent, screen } from '@testing-library/react'; -import Dropdown from '../src/Dropdown'; - -describe('', () => { - it('does not flicker when rootCloseEvent is set to "mousedown" and toggle button is clicked', () => { - const { container } = render( - - - Dropdown Button - - - Action - - , - ); - // Click the toggle button to open the menu - fireEvent.click(screen.getByTestId('dropdown-toggle')); - // The menu should now be in the DOM - container.firstElementChild!.classList.contains('show').should.be.true; - // Click the toggle button again to close the menu - fireEvent.click(screen.getByTestId('dropdown-toggle')); - // The menu should no longer be in the DOM - container.firstElementChild!.classList.contains('show').should.be.false; - }); -}); diff --git a/test/DropdownSpec.tsx b/test/DropdownSpec.tsx index 4ca5fe22f2..83e9990f8c 100644 --- a/test/DropdownSpec.tsx +++ b/test/DropdownSpec.tsx @@ -1,8 +1,6 @@ -import { render, fireEvent } from '@testing-library/react'; -import sinon from 'sinon'; -import { expect } from 'chai'; import * as React from 'react'; - +import { describe, expect, it, vi } from 'vitest'; +import { fireEvent, render, screen } from '@testing-library/react'; import Dropdown from '../src/Dropdown'; import { DropDirection } from '../src/DropdownContext'; import InputGroup from '../src/InputGroup'; @@ -24,7 +22,7 @@ describe('', () => { it('renders div with dropdown class', () => { const { container } = render(simpleDropdown); - container.firstElementChild!.classList.should.contain(['dropdown']); + expect(container.firstElementChild!.classList).toContain('dropdown'); }); ['up', 'end', 'start'].forEach((dir: DropDirection) => { @@ -35,8 +33,8 @@ describe('', () => { , ); - container.firstElementChild!.classList.should.not.contain(['dropdown']); - container.firstElementChild!.classList.should.contain([`drop${dir}`]); + expect(container.firstElementChild!.classList).not.toContain('dropdown'); + expect(container.firstElementChild!.classList).toContain(`drop${dir}`); }); }); @@ -47,8 +45,8 @@ describe('', () => { , ); - container.firstElementChild!.classList.should.not.contain(['dropdown']); - container.firstElementChild!.classList.should.contain([`dropdown-center`]); + expect(container.firstElementChild!.classList).not.toContain('dropdown'); + expect(container.firstElementChild!.classList).toContain('dropdown-center'); }); it('renders div with drop=up-centered', () => { @@ -58,19 +56,16 @@ describe('', () => { , ); - container.firstElementChild!.classList.should.not.contain(['dropdown']); - container.firstElementChild!.classList.should.contain([ - 'dropup-center', - 'dropup', - ]); + expect(container.firstElementChild!.classList).not.toContain('dropdown'); + expect(container.firstElementChild!.classList).toContain('dropup-center'); + expect(container.firstElementChild!.classList).toContain('dropup'); }); it('renders toggle with Dropdown.Toggle', () => { - const { getByText } = render(simpleDropdown); + render(simpleDropdown); - const toggle = getByText('Child Title'); - toggle.getAttribute('aria-expanded')!.should.equal('false'); - toggle.id.should.be.ok; + const toggle = screen.getByText('Child Title'); + expect(toggle.getAttribute('aria-expanded')).toEqual('false'); }); it('forwards align="end" to menu', () => { @@ -92,29 +87,30 @@ describe('', () => { , ); - container.querySelector('[data-align="end"]')!.should.exist; + expect(container.querySelector('[data-align="end"]')).toBeDefined(); }); it('toggles open/closed when clicked', () => { - const { container, getByText, getByTestId } = render(simpleDropdown); + const { container } = render(simpleDropdown); const dropdown = container.firstElementChild!; - const toggle = getByText('Child Title'); + const toggle = screen.getByText('Child Title'); - dropdown.classList.should.not.contain(['show']); + expect(dropdown.classList).not.toContain('show'); fireEvent.click(toggle); - dropdown.classList.should.contain(['show']); + expect(dropdown.classList).toContain('show'); - getByTestId('menu').classList.should.contain(['dropdown-menu', 'show']); + expect(screen.getByTestId('menu').classList).toContain('dropdown-menu'); + expect(screen.getByTestId('menu').classList).toContain('show'); fireEvent.click(toggle); - dropdown.classList.should.not.contain(['show']); - toggle.getAttribute('aria-expanded')!.should.equal('false'); + expect(dropdown.classList).not.toContain('show'); + expect(toggle.getAttribute('aria-expanded')).toEqual('false'); }); it('closes when child Dropdown.Item is selected', () => { - const onToggleSpy = sinon.spy(); + const onToggleSpy = vi.fn(); - const { container, getByTestId } = render( + const { container } = render( Child Title @@ -128,14 +124,14 @@ describe('', () => { , ); - container.firstElementChild!.classList.should.contain(['show']); + expect(container.firstElementChild!.classList).toContain('show'); - fireEvent.click(getByTestId('item1')); - onToggleSpy.should.have.been.calledWith(false); + fireEvent.click(screen.getByTestId('item1')); + expect(onToggleSpy).toHaveBeenCalledWith(false, expect.anything()); }); it('has aria-labelledby same id as toggle button', () => { - const { getByTestId } = render( + render( Toggle @@ -144,50 +140,50 @@ describe('', () => { , ); - getByTestId('toggle').id.should.equal( - getByTestId('menu').getAttribute('aria-labelledby'), + expect(screen.getByTestId('toggle').id).toEqual( + screen.getByTestId('menu').getAttribute('aria-labelledby'), ); }); describe('DOM event and source passed to onToggle', () => { it('passes open, event, and source correctly when opened with click', () => { - const onToggleSpy = sinon.spy(); - const { getByText } = render( - {dropdownChildren}, - ); + const onToggleSpy = vi.fn(); + render({dropdownChildren}); - onToggleSpy.should.not.have.been.called; + expect(onToggleSpy).not.toHaveBeenCalled(); - fireEvent.click(getByText('Child Title')); + fireEvent.click(screen.getByText('Child Title')); - onToggleSpy.should.have.been.calledOnce; - onToggleSpy.getCall(0).args.length.should.equal(2); - onToggleSpy.getCall(0).args[0].should.equal(true); - onToggleSpy.getCall(0).args[1].source.should.equal('click'); + expect(onToggleSpy).toHaveBeenCalledOnce(); + expect(onToggleSpy).toHaveBeenCalledWith( + true, + expect.objectContaining({ source: 'click' }), + ); }); it('passes open, event, and source correctly when closed with click', () => { - const onToggleSpy = sinon.spy(); - const { getByText } = render( + const onToggleSpy = vi.fn(); + render( {dropdownChildren} , ); - const toggle = getByText('Child Title'); + const toggle = screen.getByText('Child Title'); - onToggleSpy.should.not.have.been.called; + expect(onToggleSpy).not.toHaveBeenCalled(); fireEvent.click(toggle); - onToggleSpy.getCall(0).args.length.should.equal(2); - onToggleSpy.getCall(0).args[0].should.equal(false); - onToggleSpy.getCall(0).args[1].source.should.equal('click'); + expect(onToggleSpy).toHaveBeenCalledWith( + false, + expect.objectContaining({ source: 'click' }), + ); }); it('passes open, event, and source correctly when child selected', () => { - const onToggleSpy = sinon.spy(); - const { getByTestId } = render( + const onToggleSpy = vi.fn(); + render( Toggle @@ -198,21 +194,22 @@ describe('', () => { , ); - fireEvent.click(getByTestId('toggle')); + fireEvent.click(screen.getByTestId('toggle')); - onToggleSpy.should.have.been.called; + expect(onToggleSpy).toHaveBeenCalledOnce(); - fireEvent.click(getByTestId('item1')); + fireEvent.click(screen.getByTestId('item1')); - onToggleSpy.should.have.been.calledTwice; - onToggleSpy.getCall(1).args.length.should.equal(2); - onToggleSpy.getCall(1).args[0].should.equal(false); - onToggleSpy.getCall(1).args[1].source.should.equal('select'); + expect(onToggleSpy).toHaveBeenCalledTimes(2); + expect(onToggleSpy).toHaveBeenCalledWith( + false, + expect.objectContaining({ source: 'select' }), + ); }); it('passes open, event, and source correctly when opened with keydown', () => { - const onToggleSpy = sinon.spy(); - const { getByTestId } = render( + const onToggleSpy = vi.fn(); + render( Toggle @@ -223,24 +220,23 @@ describe('', () => { , ); - fireEvent.keyDown(getByTestId('toggle'), { key: 'ArrowDown' }); + fireEvent.keyDown(screen.getByTestId('toggle'), { key: 'ArrowDown' }); - onToggleSpy.should.have.been.calledOnce; - onToggleSpy.getCall(0).args.length.should.equal(2); - onToggleSpy.getCall(0).args[0].should.equal(true); - onToggleSpy.getCall(0).args[1].source.should.equal('keydown'); + expect(onToggleSpy).toHaveBeenCalledOnce(); + expect(onToggleSpy).toHaveBeenCalledWith( + true, + expect.objectContaining({ source: 'keydown' }), + ); }); it('Should render .show on the dropdown toggle when outside an InputGroup', () => { - const { getByText } = render( - {dropdownChildren}, - ); - getByText('Child Title').classList.contains('show').should.be.true; + render({dropdownChildren}); + expect(screen.getByText('Child Title').classList).toContain('show'); }); }); it('should use each components bsPrefix', () => { - const { getByTestId } = render( + render( Child Title @@ -251,13 +247,14 @@ describe('', () => { , ); - getByTestId('dropdown').classList.should.contain(['show', 'my-dropdown']); - getByTestId('toggle').classList.should.contain(['my-toggle']); - getByTestId('menu').classList.should.contain(['my-menu']); + expect(screen.getByTestId('dropdown').classList).toContain('show'); + expect(screen.getByTestId('dropdown').classList).toContain('my-dropdown'); + expect(screen.getByTestId('toggle').classList).toContain('my-toggle'); + expect(screen.getByTestId('menu').classList).toContain('my-menu'); }); it('Should have div as default component', () => { - const { getByTestId } = render( + render( Child Title @@ -268,7 +265,7 @@ describe('', () => { , ); - getByTestId('dropdown').tagName.should.equal('DIV'); + expect(screen.getByTestId('dropdown').tagName).toEqual('DIV'); }); it('Should also accept a custom component', () => { @@ -284,41 +281,41 @@ describe('', () => { ref, ) =>
, ); - const { getByTestId } = render( + render( Example Item , ); - getByTestId('menu').id.should.equal('custom-component'); + expect(screen.getByTestId('menu').id).toEqual('custom-component'); }); describe('InputGroup Dropdowns', () => { it('should not render a .dropdown element when inside input group', () => { - const { queryByTestId } = render( + render( {dropdownChildren} , ); - expect(queryByTestId('dropdown')!).not.to.exist; + expect(screen.queryByTestId('dropdown')).toBeNull(); }); it('should render .show on the dropdown toggle', () => { - const { getByText } = render( + render( {dropdownChildren} , ); - getByText('Child Title').classList.contains('show').should.be.true; + expect(screen.getByText('Child Title').classList).toContain('show'); }); }); describe('autoClose behaviour', () => { describe('autoClose="true"', () => { it('should close on outer click', () => { - const onToggleSpy = sinon.spy(); + const onToggleSpy = vi.fn(); render( @@ -331,15 +328,15 @@ describe('', () => { fireEvent.click(document.body); - onToggleSpy.should.have.been.calledWith(false); + expect(onToggleSpy).toHaveBeenCalledWith(false, expect.anything()); }); }); describe('autoClose="inside"', () => { it('should close on child selection', () => { - const onToggleSpy = sinon.spy(); + const onToggleSpy = vi.fn(); - const { getByTestId } = render( + render( Toggle @@ -348,13 +345,13 @@ describe('', () => { , ); - fireEvent.click(getByTestId('item1')); + fireEvent.click(screen.getByTestId('item1')); - onToggleSpy.should.have.been.calledWith(false); + expect(onToggleSpy).toHaveBeenCalledWith(false, expect.anything()); }); it('should not close on outer click', () => { - const onToggleSpy = sinon.spy(); + const onToggleSpy = vi.fn(); render( @@ -367,15 +364,15 @@ describe('', () => { fireEvent.click(document.body); - onToggleSpy.should.not.have.been.called; + expect(onToggleSpy).not.toHaveBeenCalled(); }); }); describe('autoClose="outside"', () => { it('should not close on child selection', () => { - const onToggleSpy = sinon.spy(); + const onToggleSpy = vi.fn(); - const { getByTestId } = render( + render( Toggle @@ -384,13 +381,13 @@ describe('', () => { , ); - fireEvent.click(getByTestId('item1')); + fireEvent.click(screen.getByTestId('item1')); - onToggleSpy.should.not.have.been.called; + expect(onToggleSpy).not.toHaveBeenCalled(); }); it('should close on outer click', () => { - const onToggleSpy = sinon.spy(); + const onToggleSpy = vi.fn(); render( @@ -403,15 +400,15 @@ describe('', () => { fireEvent.click(document.body); - onToggleSpy.should.be.calledWith(false); + expect(onToggleSpy).toHaveBeenCalledWith(false, expect.anything()); }); }); describe('autoClose="false"', () => { it('should not close on child selection', () => { - const onToggleSpy = sinon.spy(); + const onToggleSpy = vi.fn(); - const { getByTestId } = render( + render( Toggle @@ -420,13 +417,13 @@ describe('', () => { , ); - fireEvent.click(getByTestId('item1')); + fireEvent.click(screen.getByTestId('item1')); - onToggleSpy.should.not.have.been.called; + expect(onToggleSpy).not.toHaveBeenCalled(); }); it('should not close on outer click', () => { - const onToggleSpy = sinon.spy(); + const onToggleSpy = vi.fn(); render( @@ -439,7 +436,7 @@ describe('', () => { fireEvent.click(document.body); - onToggleSpy.should.not.have.been.called; + expect(onToggleSpy).not.toHaveBeenCalled(); }); }); }); diff --git a/test/DropdownToggleSpec.tsx b/test/DropdownToggleSpec.tsx index 67533e0a9f..03e0ded81b 100644 --- a/test/DropdownToggleSpec.tsx +++ b/test/DropdownToggleSpec.tsx @@ -1,30 +1,30 @@ -import { render, fireEvent } from '@testing-library/react'; -import sinon from 'sinon'; +import { describe, expect, it, vi } from 'vitest'; +import { fireEvent, render, screen } from '@testing-library/react'; import DropdownToggle from '../src/DropdownToggle'; describe('', () => { it('renders toggle button', () => { - const { getByText } = render( - herpa derpa, - ); + render(herpa derpa); - const toggle = getByText('herpa derpa'); - toggle.getAttribute('aria-expanded')!.should.equal('false'); - toggle.classList.should.contain(['dropdown-toggle', 'btn', 'btn-primary']); + const toggle = screen.getByText('herpa derpa'); + expect(toggle.getAttribute('aria-expanded')).toEqual('false'); + expect(toggle.classList).toContain('dropdown-toggle'); + expect(toggle.classList).toContain('btn'); + expect(toggle.classList).toContain('btn-primary'); }); it('renders children', () => { - const { getByText } = render( + render(

herpa derpa

, ); - getByText('herpa derpa').should.exist; + expect(screen.getByText('herpa derpa')).toBeDefined(); }); it('forwards onClick handler', () => { - const onClickSpy = sinon.spy(); + const onClickSpy = vi.fn(); const { container } = render( ', () => { ); fireEvent.click(container.firstElementChild!); - onClickSpy.should.be.called; + expect(onClickSpy).toHaveBeenCalled(); }); it('forwards id', () => { const { container } = render(); - container.firstElementChild!.id.should.equal('testid'); + expect(container.firstElementChild!.id).toEqual('testid'); }); it('does not forward bsPrefix', () => { @@ -51,9 +51,9 @@ describe('', () => { id="test-id" />, ); - container.firstElementChild!.classList.should.contain([ + expect(container.firstElementChild!.classList).toContain( 'my-custom-bsPrefix', - 'btn', - ]); + ); + expect(container.firstElementChild!.classList).toContain('btn'); }); }); diff --git a/test/FadeSpec.tsx b/test/FadeSpec.tsx index b722c7b427..1a1f32eca4 100644 --- a/test/FadeSpec.tsx +++ b/test/FadeSpec.tsx @@ -1,7 +1,6 @@ import * as React from 'react'; -import { Transition } from 'react-transition-group'; -import { render } from '@testing-library/react'; -import sinon from 'sinon'; +import { describe, expect, it, vi } from 'vitest'; +import { render, screen, waitFor } from '@testing-library/react'; import Fade, { FadeProps } from '../src/Fade'; @@ -9,18 +8,11 @@ describe('Fade', () => { class Component extends React.Component< React.PropsWithChildren> > { - fade: Transition | null = null; - render() { const { children, ...props } = this.props; return ( - (this.fade = r)} - data-testid="fade-component" - {...props} - {...this.state} - > +
{children} @@ -39,7 +31,7 @@ describe('Fade', () => { }); it('should work with a class component as children', () => { - const onEnteringSpy = sinon.spy(); + const onEnteringSpy = vi.fn(); class InnerComponent extends React.Component { render() { @@ -47,72 +39,76 @@ describe('Fade', () => { } } - const { getByTestId } = render( + render( , ); - const node = getByTestId('test'); - node.classList.contains('fade').should.be.true; - node.classList.contains('show').should.be.true; + const node = screen.getByTestId('test'); + expect(node.classList).toContain('fade'); + expect(node.classList).toContain('show'); }); it('Should default to hidden', () => { - const { getByTestId } = render(Panel content); + render(Panel content); - getByTestId('status-hide').should.exist; + expect(screen.getByTestId('status-hide')).toBeDefined(); }); it('Should always have the "fade" class', () => { - const { getByTestId } = render(Panel content); + render(Panel content); - getByTestId('status-hide').should.exist; - getByTestId('fade-component').classList.contains('fade').should.be.true; + expect(screen.getByTestId('status-hide')).toBeDefined(); + expect(screen.getByTestId('fade-component').classList).toContain('fade'); }); - it('Should add "in" class when entering', (done) => { - const { getByTestId, rerender } = render( - Panel content, - ); + it('Should add "in" class when entering', () => { + const onEnteringSpy = vi.fn(); + + const { rerender } = render(Panel content); - getByTestId('status-hide').should.exist; + expect(screen.getByTestId('status-hide')).toBeDefined(); rerender( { - const node = getByTestId('fade-component'); - node.classList.contains('fade').should.be.true; - node.classList.contains('show').should.be.true; - done(); + const node = screen.getByTestId('fade-component'); + expect(node.classList).toContain('fade'); + expect(node.classList).toContain('show'); + onEnteringSpy(); }} > Panel content , ); + + waitFor(() => expect(onEnteringSpy).toHaveBeenCalled()); }); - it('Should remove "in" class when exiting', (done) => { - const { getByTestId, rerender } = render( - Panel content, - ); + it('Should remove "in" class when exiting', () => { + const onEnteringSpy = vi.fn(); - const node = getByTestId('fade-component'); - node.classList.contains('fade').should.be.true; - node.classList.contains('show').should.be.true; + const { rerender } = render(Panel content); + + const node = screen.getByTestId('fade-component'); + expect(node.classList).toContain('fade'); + expect(node.classList).toContain('show'); rerender( { - node.classList.contains('fade').should.be.true; - node.classList.contains('show').should.be.false; - done(); + expect(node.classList).toContain('fade'); + expect(node.classList).not.toContain('show'); + onEnteringSpy(); }} > Panel content , ); + + waitFor(() => expect(onEnteringSpy).toHaveBeenCalled()); }); }); diff --git a/test/FeedbackSpec.tsx b/test/FeedbackSpec.tsx index 43f561d998..90ec9319e4 100644 --- a/test/FeedbackSpec.tsx +++ b/test/FeedbackSpec.tsx @@ -1,43 +1,35 @@ -import { render } from '@testing-library/react'; - +import { describe, expect, it } from 'vitest'; +import { render, screen } from '@testing-library/react'; import Feedback from '../src/Feedback'; describe('', () => { it('Should have div as default component', () => { - const { getByTestId } = render(); + render(); - getByTestId('test').tagName.toLowerCase().should.equal('div'); + expect(screen.getByTestId('test').tagName).toEqual('DIV'); }); it('Should render valid feedback', () => { - const { getByTestId } = render( - , - ); + render(); - getByTestId('test').classList.contains('valid-feedback').should.be.true; + expect(screen.getByTestId('test').classList).toContain('valid-feedback'); }); it('Should render invalid feedback', () => { - const { getByTestId } = render( - , - ); + render(); - getByTestId('test').classList.contains('invalid-feedback').should.be.true; + expect(screen.getByTestId('test').classList).toContain('invalid-feedback'); }); it('Should render valid feedback tooltip', () => { - const { getByTestId } = render( - , - ); + render(); - getByTestId('test').classList.contains('valid-tooltip').should.be.true; + expect(screen.getByTestId('test').classList).toContain('valid-tooltip'); }); it('Should render invalid feedback tooltip', () => { - const { getByTestId } = render( - , - ); + render(); - getByTestId('test').classList.contains('invalid-tooltip').should.be.true; + expect(screen.getByTestId('test').classList).toContain('invalid-tooltip'); }); }); diff --git a/test/FigureCaptionSpec.tsx b/test/FigureCaptionSpec.tsx index 2f235e8de6..a09d8256e1 100644 --- a/test/FigureCaptionSpec.tsx +++ b/test/FigureCaptionSpec.tsx @@ -1,41 +1,42 @@ -import { render } from '@testing-library/react'; +import { describe, expect, it } from 'vitest'; +import { render, screen } from '@testing-library/react'; import Figure from '../src/Figure'; describe('', () => { it('uses "figcaption" by default', () => { - const { getByTestId } = render( + render(
Caption
, ); - getByTestId('test-figure').tagName.toLowerCase().should.equal('figcaption'); + expect(screen.getByTestId('test-figure').tagName).toEqual('FIGCAPTION'); }); it('has "figure-caption" class', () => { - const { getByTestId } = render( - Caption, + render(Caption); + expect(screen.getByTestId('test-figure').classList).toContain( + 'figure-caption', ); - getByTestId('test-figure').classList.contains('figure-caption').should.be - .true; }); it('Should merge additional classes passed in', () => { - const { getByTestId } = render( + render( Caption , ); - getByTestId('test-figure').classList.contains('bob').should.be.true; - getByTestId('test-figure').classList.contains('figure-caption').should.be - .true; + expect(screen.getByTestId('test-figure').classList).toContain('bob'); + expect(screen.getByTestId('test-figure').classList).toContain( + 'figure-caption', + ); }); it('allows custom elements instead of "figcaption"', () => { - const { getByTestId } = render( + render( Caption , ); - getByTestId('test-figure').tagName.toLowerCase().should.equal('section'); + expect(screen.getByTestId('test-figure').tagName).toEqual('SECTION'); }); }); diff --git a/test/FigureSpec.tsx b/test/FigureSpec.tsx index 8f7fc6bc73..d9d4a61d12 100644 --- a/test/FigureSpec.tsx +++ b/test/FigureSpec.tsx @@ -1,73 +1,64 @@ -import { render } from '@testing-library/react'; -import { expect } from 'chai'; - +import { describe, expect, it } from 'vitest'; +import { render, screen } from '@testing-library/react'; import Figure from '../src/Figure'; describe('Figure', () => { describe('General', () => { it('should be a Figure', () => { - const { getByTestId } = render(
); + render(
); - getByTestId('test').tagName.toLowerCase().should.equal('figure'); + expect(screen.getByTestId('test').tagName).toEqual('FIGURE'); }); }); describe('Figure.Image', () => { it('should be an image', () => { - const { getByTestId } = render(); + render(); - getByTestId('test').tagName.toLowerCase().should.equal('img'); + expect(screen.getByTestId('test').tagName).toEqual('IMG'); }); it('should provide src and alt prop', () => { - const { getByTestId } = render( + render( , ); - const image = getByTestId('test'); - expect(image.getAttribute('src')).to.be.equal('image.jpg'); - expect(image.getAttribute('alt')).to.be.equal('this is alt'); + const image = screen.getByTestId('test'); + expect(image.getAttribute('src')).toEqual('image.jpg'); + expect(image.getAttribute('alt')).toEqual('this is alt'); }); it('should have correct class when fluid prop is set', () => { - const { getByTestId } = render(); + render(); - getByTestId('test').classList.contains('img-fluid').should.be.true; + expect(screen.getByTestId('test').classList).toContain('img-fluid'); }); it('should not override class when rounded prop is set', () => { - const { getByTestId } = render( - , - ); + render(); - const image = getByTestId('test'); - image.classList.contains('figure-img').should.be.true; - image.classList.contains('img-fluid').should.be.true; - image.classList.contains('rounded').should.be.true; + const image = screen.getByTestId('test'); + expect(image.classList).toContain('figure-img'); + expect(image.classList).toContain('img-fluid'); + expect(image.classList).toContain('rounded'); }); it('should have correct class when rounded prop is set', () => { - const { getByTestId } = render( - , - ); + render(); - getByTestId('test').classList.contains('rounded').should.be.true; + expect(screen.getByTestId('test').classList).toContain('rounded'); }); it('should have correct class when roundedCircle prop is set', () => { - const { getByTestId } = render( - , - ); + render(); - getByTestId('test').classList.contains('rounded-circle').should.be.true; + expect(screen.getByTestId('test').classList).toContain('rounded-circle'); }); it('should have correct class when thumbnail prop is set', () => { - const { getByTestId } = render( - , - ); + render(); - getByTestId('test').classList.contains('img-thumbnail').should.be.true; + expect(screen.getByTestId('test').classList).toContain('img-thumbnail'); }); }); }); diff --git a/test/FloatingLabelSpec.tsx b/test/FloatingLabelSpec.tsx index af1ebb2f68..d6c3b85b10 100644 --- a/test/FloatingLabelSpec.tsx +++ b/test/FloatingLabelSpec.tsx @@ -1,42 +1,41 @@ -import { render } from '@testing-library/react'; -import { expect } from 'chai'; - +import { describe, expect, it } from 'vitest'; +import { render, screen } from '@testing-library/react'; import FloatingLabel from '../src/FloatingLabel'; import Form from '../src/Form'; describe('', () => { it('should render correctly', () => { - const { getByText, getByRole, getByTestId } = render( + render( , ); - getByTestId('test').classList.contains('form-floating').should.be.true; - getByText('MyLabel').should.exist; - getByRole('textbox').should.exist; + expect(screen.getByTestId('test').classList).toContain('form-floating'); + expect(screen.getByText('MyLabel')).toBeDefined(); + expect(screen.getByRole('textbox')).toBeDefined(); }); it('should pass controlId to input and label', () => { - const { getByRole, getByText } = render( + render( , ); - expect(getByRole('textbox').getAttribute('id')).to.be.equal('MyId'); - expect(getByText('MyLabel').getAttribute('for')).to.be.equal('MyId'); + expect(screen.getByRole('textbox').getAttribute('id')).toEqual('MyId'); + expect(screen.getByText('MyLabel').getAttribute('for')).toEqual('MyId'); }); it('should support "as"', () => { - const { getByTestId } = render( + render( , ); - const label = getByTestId('test'); - label.tagName.toLowerCase().should.be.equal('span'); - label.classList.contains('form-floating').should.be.true; + const label = screen.getByTestId('test'); + expect(label.tagName).toEqual('SPAN'); + expect(label.classList).toContain('form-floating'); }); }); diff --git a/test/FormCheckSpec.tsx b/test/FormCheckSpec.tsx index 56c5e89910..90f9391334 100644 --- a/test/FormCheckSpec.tsx +++ b/test/FormCheckSpec.tsx @@ -1,11 +1,12 @@ -import { render } from '@testing-library/react'; import * as React from 'react'; +import { describe, expect, it } from 'vitest'; +import { render, screen } from '@testing-library/react'; import FormCheck from '../src/FormCheck'; import Switch from '../src/Switch'; describe('', () => { it('should render correctly', () => { - const { getByTestId, container } = render( + const { container } = render( ', () => { />, ); - const element = getByTestId('test-id'); + const element = screen.getByTestId('test-id'); - element.parentElement!.classList.length.should.equal(2); - element.parentElement!.classList.contains('form-check').should.be.true; - element.parentElement!.classList.contains('my-checkbox').should.be.true; + expect(element.parentElement!.classList).toHaveLength(2); + expect(element.parentElement!.classList).toContain('form-check'); + expect(element.parentElement!.classList).toContain('my-checkbox'); - element.id.should.equal('foo'); - element.classList.length.should.equal(1); - element.classList.contains('form-check-input').should.be.true; - element.getAttribute('name')!.should.equal('foo'); - element.getAttribute('type')!.should.equal('checkbox'); - element.getAttribute('value')!.should.equal('foo'); - element.getAttribute('checked')!.should.equal(''); + expect(element.id).toEqual('foo'); + expect(element.classList).toHaveLength(1); + expect(element.classList).toContain('form-check-input'); + expect(element.getAttribute('name')).toEqual('foo'); + expect(element.getAttribute('type')).toEqual('checkbox'); + expect(element.getAttribute('value')).toEqual('foo'); + expect(element.getAttribute('checked')).toEqual(''); const labels = container.getElementsByTagName('label'); - labels.length.should.equal(1); + expect(labels).toHaveLength(1); const label = labels[0]; - label.classList.length.should.equal(1); - label.classList.contains('form-check-label').should.be.true; - label.getAttribute('for')!.should.equal('foo'); - label.innerText.should.equal('My label'); + expect(label.classList).toHaveLength(1); + expect(label.classList).toContain('form-check-label'); + expect(label.getAttribute('for')).toEqual('foo'); + expect(label.innerText).toEqual('My label'); }); it('should render radio correctly', () => { - const { getByTestId, container } = render( + const { container } = render( ', () => { />, ); - const element = getByTestId('test-id'); + const element = screen.getByTestId('test-id'); - element.parentElement!.classList.length.should.equal(2); - element.parentElement!.classList.contains('form-check').should.be.true; - element.parentElement!.classList.contains('my-radio').should.be.true; + expect(element.parentElement!.classList).toHaveLength(2); + expect(element.parentElement!.classList).toContain('form-check'); + expect(element.parentElement!.classList).toContain('my-radio'); - element.id.should.equal('foo'); - element.classList.length.should.equal(1); - element.classList.contains('form-check-input').should.be.true; - element.getAttribute('name')!.should.equal('foo'); - element.getAttribute('type')!.should.equal('radio'); - element.getAttribute('value')!.should.equal('foo'); - element.getAttribute('checked')!.should.equal(''); + expect(element.id).toEqual('foo'); + expect(element.classList).toHaveLength(1); + expect(element.classList).toContain('form-check-input'); + expect(element.getAttribute('name')).toEqual('foo'); + expect(element.getAttribute('type')).toEqual('radio'); + expect(element.getAttribute('value')).toEqual('foo'); + expect(element.getAttribute('checked')).toEqual(''); const labels = container.getElementsByTagName('label'); - labels.length.should.equal(1); + expect(labels).toHaveLength(1); const label = labels[0]; - label.classList.length.should.equal(1); - label.classList.contains('form-check-label').should.be.true; - label.getAttribute('for')!.should.equal('foo'); - label.innerText.should.equal('My label'); + expect(label.classList).toHaveLength(1); + expect(label.classList).toContain('form-check-label'); + expect(label.getAttribute('for')).toEqual('foo'); + expect(label.innerText).toEqual('My label'); }); it('should support inline', () => { @@ -82,8 +83,8 @@ describe('', () => { container: { firstElementChild: element }, } = render(); - element!.classList.length.should.equal(2); - element!.classList.contains('form-check-inline').should.be.true; + expect(element!.classList).toHaveLength(2); + expect(element!.classList).toContain('form-check-inline'); }); it('should support in reverse', () => { @@ -91,26 +92,24 @@ describe('', () => { container: { firstElementChild: element }, } = render(); - element!.classList.length.should.equal(2); - element!.classList.contains('form-check-reverse').should.be.true; + expect(element!.classList).toHaveLength(2); + expect(element!.classList).toContain('form-check-reverse'); }); it('should support isValid', () => { - const { getByTestId } = render(); + render(); - const element = getByTestId('test-id'); - element.classList.length.should.equal(2); - element.classList.contains('is-valid').should.be.true; + const element = screen.getByTestId('test-id'); + expect(element!.classList).toHaveLength(2); + expect(element.classList).toContain('is-valid'); }); it('should support isInvalid', () => { - const { getByTestId } = render( - , - ); + render(); - const element = getByTestId('test-id'); - element.classList.length.should.equal(2); - element.classList.contains('is-invalid').should.be.true; + const element = screen.getByTestId('test-id'); + expect(element!.classList).toHaveLength(2); + expect(element.classList).toContain('is-invalid'); }); it('should support ref forwarding', () => { @@ -128,7 +127,7 @@ describe('', () => { } render(); - input.tagName.toLowerCase().should.equal('input'); + expect(input.tagName).toEqual('INPUT'); }); it('should not render bsPrefix if no label is specified', () => { @@ -136,11 +135,11 @@ describe('', () => { , ); - container.getElementsByClassName('form-check').length.should.equal(0); + expect(container.getElementsByClassName('form-check')).toHaveLength(0); }); it('should support type switch', () => { - const { getByTestId, container } = render( + const { container } = render( ', () => { />, ); - const element = getByTestId('test-id'); + const element = screen.getByTestId('test-id'); - element.parentElement!.classList.length.should.equal(2); - element.parentElement!.classList.contains('form-check').should.be.true; - element.parentElement!.classList.contains('form-switch').should.be.true; + expect(element.parentElement!.classList).toHaveLength(2); + expect(element.parentElement!.classList).toContain('form-check'); + expect(element.parentElement!.classList).toContain('form-switch'); - element.id.should.equal('switch-id'); - element.classList.length.should.equal(1); - element.classList.contains('form-check-input').should.be.true; - element.id.should.equal('switch-id'); - element.getAttribute('type')!.should.equal('checkbox'); + expect(element.id).toEqual('switch-id'); + expect(element.classList).toHaveLength(1); + expect(element.classList).toContain('form-check-input'); + expect(element.id).toEqual('switch-id'); + expect(element.getAttribute('type')).toEqual('checkbox'); const labels = container.getElementsByTagName('label'); - labels.length.should.equal(1); + expect(labels).toHaveLength(1); const label = labels[0]; - label.classList.length.should.equal(1); - label.classList.contains('form-check-label').should.be.true; - label.getAttribute('for')!.should.equal('switch-id'); - label.innerText.should.equal('My label'); + expect(label.classList).toHaveLength(1); + expect(label.classList).toContain('form-check-label'); + expect(label.getAttribute('for')).toEqual('switch-id'); + expect(label.innerText).toEqual('My label'); }); it('should support Switch', () => { - const { getByTestId, container } = render( + const { container } = render( , ); - const element = getByTestId('test-id'); + const element = screen.getByTestId('test-id'); - element.parentElement!.classList.length.should.equal(2); - element.parentElement!.classList.contains('form-check').should.be.true; - element.parentElement!.classList.contains('form-switch').should.be.true; + expect(element.parentElement!.classList).toHaveLength(2); + expect(element.parentElement!.classList).toContain('form-check'); + expect(element.parentElement!.classList).toContain('form-switch'); - element.id.should.equal('switch-id'); - element.classList.length.should.equal(1); - element.classList.contains('form-check-input').should.be.true; - element.id.should.equal('switch-id'); - element.getAttribute('type')!.should.equal('checkbox'); + expect(element.id).toEqual('switch-id'); + expect(element.classList).toHaveLength(1); + expect(element.classList).toContain('form-check-input'); + expect(element.id).toEqual('switch-id'); + expect(element.getAttribute('type')).toEqual('checkbox'); const labels = container.getElementsByTagName('label'); - labels.length.should.equal(1); + expect(labels).toHaveLength(1); const label = labels[0]; - label.classList.length.should.equal(1); - label.classList.contains('form-check-label').should.be.true; - label.getAttribute('for')!.should.equal('switch-id'); - label.innerText.should.equal('My label'); + expect(label.classList).toHaveLength(1); + expect(label.classList).toContain('form-check-label'); + expect(label.getAttribute('for')).toEqual('switch-id'); + expect(label.innerText).toEqual('My label'); }); it('should support "as"', () => { const Surrogate = ({ className = '', ...rest }) => ( ); - const { getByTestId } = render( - , - ); + render(); - const element = getByTestId('test-id'); - element.classList.length.should.equal(2); - element.classList.contains('extraClass').should.be.true; + const element = screen.getByTestId('test-id'); + expect(element.classList).toHaveLength(2); + expect(element.classList).toContain('extraClass'); }); it('Should render valid feedback properly', () => { @@ -215,8 +212,8 @@ describe('', () => { ); const feedbacks = container.getElementsByClassName('valid-feedback'); - feedbacks.length.should.equal(1); - feedbacks[0].textContent!.should.equal('test'); + expect(feedbacks).toHaveLength(1); + expect(feedbacks[0].textContent!).toEqual('test'); }); it('Should render invalid feedback properly', () => { @@ -225,8 +222,8 @@ describe('', () => { ); const feedbacks = container.getElementsByClassName('invalid-feedback'); - feedbacks.length.should.equal(1); - feedbacks[0].textContent!.should.equal('test'); + expect(feedbacks).toHaveLength(1); + expect(feedbacks[0].textContent).toEqual('test'); }); it('Should render valid feedback tooltip properly', () => { @@ -240,8 +237,8 @@ describe('', () => { ); const feedbacks = container.getElementsByClassName('valid-tooltip'); - feedbacks.length.should.equal(1); - feedbacks[0].textContent!.should.equal('test'); + expect(feedbacks).toHaveLength(1); + expect(feedbacks[0].textContent).toEqual('test'); }); it('Should render invalid feedback tooltip properly', () => { @@ -255,7 +252,7 @@ describe('', () => { ); const feedbacks = container.getElementsByClassName('invalid-tooltip'); - feedbacks.length.should.equal(1); - feedbacks[0].textContent!.should.equal('test'); + expect(feedbacks).toHaveLength(1); + expect(feedbacks[0].textContent).toEqual('test'); }); }); diff --git a/test/FormControlFeedbackSpec.tsx b/test/FormControlFeedbackSpec.tsx index 6caf87d3f6..d82db87a3e 100644 --- a/test/FormControlFeedbackSpec.tsx +++ b/test/FormControlFeedbackSpec.tsx @@ -1,34 +1,34 @@ -import { render } from '@testing-library/react'; -import React from 'react'; - +import * as React from 'react'; +import { describe, expect, it } from 'vitest'; +import { render, screen } from '@testing-library/react'; import FormControl from '../src/FormControl'; import FormGroup from '../src/FormGroup'; describe('', () => { it('should render default success', () => { - const { getByTestId } = render( + render( , ); - const element = getByTestId('test-id'); - element.classList.length.should.equal(1); - element.classList.contains('valid-feedback').should.be.true; + const element = screen.getByTestId('test-id'); + expect(element.classList).toHaveLength(1); + expect(element.classList).toContain('valid-feedback'); }); it('should render default error', () => { - const { getByTestId } = render( + render( , ); - const element = getByTestId('test-id'); - element.classList.length.should.equal(1); - element.classList.contains('invalid-feedback').should.be.true; + const element = screen.getByTestId('test-id'); + expect(element.classList).toHaveLength(1); + expect(element.classList).toContain('invalid-feedback'); }); it('should render custom component', () => { @@ -38,13 +38,11 @@ describe('', () => { } } - const { getByTestId } = render( - , - ); + render(); - const element = getByTestId('test-id'); - element.id.should.equal('my-component'); - element.classList.length.should.equal(1); - element.classList.contains('valid-feedback').should.be.true; + const element = screen.getByTestId('test-id'); + expect(element.id).toEqual('my-component'); + expect(element.classList).toHaveLength(1); + expect(element.classList).toContain('valid-feedback'); }); }); diff --git a/test/FormControlSpec.tsx b/test/FormControlSpec.tsx index 2f87b92756..762244aa24 100644 --- a/test/FormControlSpec.tsx +++ b/test/FormControlSpec.tsx @@ -1,14 +1,12 @@ import * as React from 'react'; -import { render } from '@testing-library/react'; - +import { describe, expect, it } from 'vitest'; +import { render, screen } from '@testing-library/react'; import FormControl from '../src/FormControl'; import FormGroup from '../src/FormGroup'; -import { shouldWarn } from './helpers'; - describe('', () => { it('should render correctly', () => { - const { getByTestId } = render( + render( ', () => { />, ); - const element = getByTestId('test-id'); - element.tagName.toLowerCase().should.equal('input'); - element.id.should.equal('foo'); - element.classList.length.should.equal(2); - element.classList.contains('form-control').should.be.true; - element.classList.contains('my-control').should.be.true; - element.getAttribute('name')!.should.equal('bar'); - element.getAttribute('type')!.should.equal('text'); + const element = screen.getByTestId('test-id'); + expect(element.tagName).toEqual('INPUT'); + expect(element.id).toEqual('foo'); + expect(element.classList).toHaveLength(2); + expect(element.classList).toContain('form-control'); + expect(element.classList).toContain('my-control'); + expect(element.getAttribute('name')).toEqual('bar'); + expect(element.getAttribute('type')).toEqual('text'); }); it('should support textarea', () => { - const { getByTestId } = render( - , - ); + render(); - getByTestId('test-id').tagName.toLowerCase().should.equal('textarea'); + expect(screen.getByTestId('test-id').tagName).toEqual('TEXTAREA'); }); it('should support plaintext inputs', () => { - const { getByTestId } = render( - , - ); + render(); - const element = getByTestId('test-id'); - element.classList.length.should.equal(1); - element.classList.contains('form-control-plaintext').should.be.true; + const element = screen.getByTestId('test-id'); + expect(element.classList).toHaveLength(1); + expect(element.classList).toContain('form-control-plaintext'); }); it('should support plaintext inputs with size', () => { - const { getByTestId } = render( - , - ); + render(); - const element = getByTestId('test-id'); - element.classList.length.should.equal(2); - element.classList.contains('form-control-sm').should.be.true; + const element = screen.getByTestId('test-id'); + expect(element.classList).toHaveLength(2); + expect(element.classList).toContain('form-control-sm'); }); it('should support type=color', () => { - const { getByTestId } = render( - , - ); + render(); - getByTestId('test-id').getAttribute('type')!.should.equal('color'); + expect(screen.getByTestId('test-id').getAttribute('type')).toEqual('color'); }); it('should use controlId for id', () => { - const { getByTestId } = render( + render( , ); - getByTestId('test-id').id.should.equal('foo'); + expect(screen.getByTestId('test-id').id).toEqual('foo'); }); it('should prefer explicit id', () => { - shouldWarn('ignored'); - - const { getByTestId } = render( + render( , ); - getByTestId('test-id').id.should.equal('bar'); + expect(screen.getByTestId('test-id').id).toEqual('bar'); }); it('should support ref forwarding', () => { @@ -104,35 +92,31 @@ describe('', () => { } render(); - input.tagName.toLowerCase().should.to.equal('input'); + expect(input.tagName).toEqual('INPUT'); }); it('should properly display size of FormControl', () => { - const { getByTestId } = render( - , - ); + render(); - const element = getByTestId('test-id'); - element.classList.length.should.equal(2); - element.classList.contains('form-control-lg').should.be.true; + const element = screen.getByTestId('test-id'); + expect(element.classList).toHaveLength(2); + expect(element.classList).toContain('form-control-lg'); }); it('should properly display html size of FormControl', () => { - const { getByTestId } = render( - , - ); + render(); - getByTestId('test-id').getAttribute('size')!.should.equal('42'); + expect(screen.getByTestId('test-id').getAttribute('size')).toEqual('42'); }); it('Should have input as default component', () => { - const { getByTestId } = render(); + render(); - getByTestId('test-id').tagName.toLowerCase().should.equal('input'); + expect(screen.getByTestId('test-id').tagName).toEqual('INPUT'); }); it('should support numbers as values', () => { - const { getByTestId } = render( + render( undefined} @@ -140,11 +124,11 @@ describe('', () => { />, ); - getByTestId('test-id').getAttribute('value')!.should.equal('10'); + expect(screen.getByTestId('test-id').getAttribute('value')).toEqual('10'); }); it('should support an array of strings as values', () => { - const { getByTestId } = render( + render( undefined} @@ -152,6 +136,8 @@ describe('', () => { />, ); - getByTestId('test-id').getAttribute('value')!.should.equal('hello,world'); + expect(screen.getByTestId('test-id').getAttribute('value')).toEqual( + 'hello,world', + ); }); }); diff --git a/test/FormGroupSpec.tsx b/test/FormGroupSpec.tsx index 68c69d96d0..3681dce477 100644 --- a/test/FormGroupSpec.tsx +++ b/test/FormGroupSpec.tsx @@ -1,34 +1,34 @@ -import { render } from '@testing-library/react'; - +import { describe, expect, it } from 'vitest'; +import { render, screen } from '@testing-library/react'; import FormControl from '../src/FormControl'; import FormLabel from '../src/FormLabel'; import FormGroup from '../src/FormGroup'; describe('', () => { it('renders children', () => { - const { getByTestId } = render( + render( , ); - const element = getByTestId('test-id'); - element.childElementCount.should.equal(2); + const element = screen.getByTestId('test-id'); + expect(element.childElementCount).toEqual(2); const child1 = element.children[0]; - child1.tagName.toLowerCase().should.equal('span'); - child1.classList.length.should.equal(1); - child1.classList.contains('child1').should.be.true; + expect(child1.tagName).toEqual('SPAN'); + expect(child1.classList).toHaveLength(1); + expect(child1.classList).toContain('child1'); const child2 = element.children[1]; - child2.tagName.toLowerCase().should.equal('span'); - child2.classList.length.should.equal(1); - child2.classList.contains('child2').should.be.true; + expect(child2.tagName).toEqual('SPAN'); + expect(child2.classList).toHaveLength(1); + expect(child2.classList).toContain('child2'); }); it('provided controlId to label and control', () => { - const { getByTestId } = render( + render(
label @@ -37,20 +37,20 @@ describe('', () => { , ); - const element = getByTestId('test-id'); + const element = screen.getByTestId('test-id'); const label = element.getElementsByTagName('label'); - label.length.should.equal(1); - label[0].getAttribute('for')!.should.equal('my-control'); + expect(label).toHaveLength(1); + expect(label[0].getAttribute('for')).toEqual('my-control'); const input = element.getElementsByTagName('input'); - input.length.should.equal(1); - input[0].id.should.be.equal('my-control'); + expect(input).toHaveLength(1); + expect(input[0].id).toEqual('my-control'); }); it('Should have div as default component', () => { - const { getByTestId } = render(); + render(); - const element = getByTestId('test-id'); - element.tagName.toLowerCase().should.equal('div'); + const element = screen.getByTestId('test-id'); + expect(element.tagName).toEqual('DIV'); }); }); diff --git a/test/FormLabelSpec.tsx b/test/FormLabelSpec.tsx index 02660d2d1a..c38f28a380 100644 --- a/test/FormLabelSpec.tsx +++ b/test/FormLabelSpec.tsx @@ -1,13 +1,12 @@ import * as React from 'react'; -import { render } from '@testing-library/react'; +import { describe, expect, it } from 'vitest'; +import { render, screen } from '@testing-library/react'; import FormLabel from '../src/FormLabel'; import FormGroup from '../src/FormGroup'; -import { shouldWarn } from './helpers'; - describe('', () => { it('should render correctly', () => { - const { getByTestId } = render( + render( ', () => { />, ); - const element = getByTestId('test-id'); - element.tagName.toLowerCase().should.equal('label'); - element.classList.length.should.equal(2); - element.classList.contains('form-label').should.be.true; - element.classList.contains('my-control').should.be.true; - element.id.should.equal('foo'); - element.getAttribute('for')!.should.not.null; + const element = screen.getByTestId('test-id'); + expect(element.tagName).toEqual('LABEL'); + expect(element.classList).toHaveLength(2); + expect(element.classList).toContain('form-label'); + expect(element.classList).toContain('my-control'); + expect(element.id).toEqual('foo'); + expect(element.getAttribute('for')).not.toBeNull(); }); it('should use controlId for htmlFor', () => { - const { getByTestId } = render( + render( , ); - const element = getByTestId('test-id'); - element.getAttribute('for')!.should.equal('foo'); + const element = screen.getByTestId('test-id'); + expect(element.getAttribute('for')).toEqual('foo'); }); it('should render as a Col', () => { - const { getByTestId } = render( + render( Label , ); - const element = getByTestId('test-id'); - element.classList.length.should.equal(3); - element.classList.contains('form-label').should.be.true; - element.classList.contains('col-form-label').should.be.true; - element.classList.contains('col-sm-4').should.be.true; + const element = screen.getByTestId('test-id'); + expect(element.classList).toHaveLength(3); + expect(element.classList).toContain('form-label'); + expect(element.classList).toContain('col-form-label'); + expect(element.classList).toContain('col-sm-4'); }); it('should use controlId for htmlFor when render as Col', () => { - const { getByTestId } = render( + render( , ); - const element = getByTestId('test-id'); - element.classList.length.should.equal(3); - element.classList.contains('form-label').should.be.true; - element.classList.contains('col-form-label').should.be.true; - element.classList.contains('col-sm-4').should.be.true; - element.getAttribute('for')!.should.equal('foo'); + const element = screen.getByTestId('test-id'); + expect(element.classList).toHaveLength(3); + expect(element.classList).toContain('form-label'); + expect(element.classList).toContain('col-form-label'); + expect(element.classList).toContain('col-sm-4'); + expect(element.getAttribute('for')).toEqual('foo'); }); it('should respect visuallyHidden', () => { - const { getByTestId } = render( + render( Label , ); - const element = getByTestId('test-id'); - element.classList.length.should.equal(2); - element.classList.contains('visually-hidden').should.be.true; + const element = screen.getByTestId('test-id'); + expect(element.classList).toHaveLength(2); + expect(element.classList).toContain('visually-hidden'); }); it('should prefer explicit htmlFor', () => { - shouldWarn('ignored'); - - const { getByTestId } = render( + render( , ); - const element = getByTestId('test-id'); - element.getAttribute('for')!.should.equal('bar'); + const element = screen.getByTestId('test-id'); + expect(element.getAttribute('for')).toEqual('bar'); }); it('should support ref forwarding', () => { @@ -107,7 +104,7 @@ describe('', () => { } render(); - input.tagName.toLowerCase().should.to.equal('label'); + expect(input.tagName).toEqual('LABEL'); }); it('should support ref forwarding when rendered as a Col', () => { @@ -128,21 +125,21 @@ describe('', () => { } render(); - input.tagName.toLowerCase().should.to.equal('label'); + expect(input.tagName).toEqual('LABEL'); }); it('accepts as prop', () => { - const { getByTestId } = render( + render( body , ); - getByTestId('test-id').tagName.toLowerCase().should.equal('legend'); + expect(screen.getByTestId('test-id').tagName).toEqual('LEGEND'); }); it('should properly size itself when rendered as a Col', () => { - const { getByTestId } = render( + render(
Label @@ -156,10 +153,12 @@ describe('', () => {
, ); - getByTestId('test-1').classList.contains('col-form-label-sm').should.be - .true; - getByTestId('test-2').classList.contains('col-form-label').should.be.true; - getByTestId('test-3').classList.contains('col-form-label-lg').should.be - .true; + expect(screen.getByTestId('test-1').classList).toContain( + 'col-form-label-sm', + ); + expect(screen.getByTestId('test-2').classList).toContain('col-form-label'); + expect(screen.getByTestId('test-3').classList).toContain( + 'col-form-label-lg', + ); }); }); diff --git a/test/FormRangeSpec.tsx b/test/FormRangeSpec.tsx index 61451bb7fe..a8c19e5f00 100644 --- a/test/FormRangeSpec.tsx +++ b/test/FormRangeSpec.tsx @@ -1,11 +1,11 @@ -import { render } from '@testing-library/react'; - +import { describe, expect, it } from 'vitest'; +import { render, screen } from '@testing-library/react'; import FormRange from '../src/FormRange'; import FormGroup from '../src/FormGroup'; describe('', () => { it('should render correctly', () => { - const { getByTestId } = render( + render( ', () => { data-testid="test-id" />, ); - const element = getByTestId('test-id'); - element.tagName.toLowerCase().should.equal('input'); - element.id.should.equal('foo'); - element.classList.length.should.equal(2); - element.classList.contains('form-range').should.be.true; - element.classList.contains('my-control').should.be.true; - element.getAttribute('name')!.should.equal('bar'); - element.getAttribute('type')!.should.equal('range'); + const element = screen.getByTestId('test-id'); + expect(element.tagName).toEqual('INPUT'); + expect(element.id).toEqual('foo'); + expect(element.classList).toHaveLength(2); + expect(element.classList).toContain('form-range'); + expect(element.classList).toContain('my-control'); + expect(element.getAttribute('name')).toEqual('bar'); + expect(element.getAttribute('type')).toEqual('range'); }); it('should render controlId as id correctly', () => { - const { getByTestId } = render( + render( , ); - const element = getByTestId('test-id'); - element.id.should.equal('control-id'); + const element = screen.getByTestId('test-id'); + expect(element.id).toEqual('control-id'); }); it('should override controlId correctly', () => { - const { getByTestId } = render( + render( , ); - const element = getByTestId('test-id'); - element.id.should.equal('overridden-id'); + const element = screen.getByTestId('test-id'); + expect(element.id).toEqual('overridden-id'); }); }); diff --git a/test/FormSelectSpec.tsx b/test/FormSelectSpec.tsx index ae28f8174e..a1cabb3865 100644 --- a/test/FormSelectSpec.tsx +++ b/test/FormSelectSpec.tsx @@ -1,63 +1,55 @@ -import { render } from '@testing-library/react'; - +import { describe, expect, it } from 'vitest'; +import { render, screen } from '@testing-library/react'; import FormSelect from '../src/FormSelect'; import FormGroup from '../src/FormGroup'; describe('', () => { it('should render correctly', () => { - const { getByTestId } = render( + render( , ); - const element = getByTestId('test-id'); - element.tagName.toLowerCase().should.equal('select'); - element.classList.length.should.equal(2); - element.classList.contains('my-control').should.be.true; - element.classList.contains('form-select').should.be.true; - element.getAttribute('name')!.should.equal('bar'); + const element = screen.getByTestId('test-id'); + expect(element.tagName).toEqual('SELECT'); + expect(element.classList).toHaveLength(2); + expect(element.classList).toContain('my-control'); + expect(element.classList).toContain('form-select'); + expect(element.getAttribute('name')).toEqual('bar'); }); it('should render size correctly', () => { - const { getByTestId } = render( - , - ); + render(); - const element = getByTestId('test-id'); - element.classList.length.should.equal(2); - element.classList.contains('form-select-lg').should.be.true; + const element = screen.getByTestId('test-id'); + expect(element.classList).toHaveLength(2); + expect(element.classList).toContain('form-select-lg'); }); it('should render htmlSize correctly', () => { - const { getByTestId } = render( - , - ); + render(); - const element = getByTestId('test-id'); - element.getAttribute('size')!.should.equal('3'); + const element = screen.getByTestId('test-id'); + expect(element.getAttribute('size')).toEqual('3'); }); it('should render isValid correctly', () => { - const { getByTestId } = render( - , - ); + render(); - const element = getByTestId('test-id'); - element.classList.length.should.equal(2); - element.classList.contains('is-valid').should.be.true; + const element = screen.getByTestId('test-id'); + expect(element.classList).toHaveLength(2); + expect(element.classList).toContain('is-valid'); }); it('should render isInvalid correctly', () => { - const { getByTestId } = render( - , - ); + render(); - const element = getByTestId('test-id'); - element.classList.length.should.equal(2); - element.classList.contains('is-invalid').should.be.true; + const element = screen.getByTestId('test-id'); + expect(element.classList).toHaveLength(2); + expect(element.classList).toContain('is-invalid'); }); it('should render controlId correctly', () => { - const { getByTestId } = render( + render( @@ -65,12 +57,12 @@ describe('', () => { , ); - const element = getByTestId('test-id'); - element.id.should.equal('control-id'); + const element = screen.getByTestId('test-id'); + expect(element.id).toEqual('control-id'); }); it('should override controlId correctly', () => { - const { getByTestId } = render( + render( @@ -78,7 +70,7 @@ describe('', () => { , ); - const element = getByTestId('test-id'); - element.id.should.equal('overridden-id'); + const element = screen.getByTestId('test-id'); + expect(element.id).toEqual('overridden-id'); }); }); diff --git a/test/FormSpec.tsx b/test/FormSpec.tsx index a3f4fbe14f..d1fa02772b 100644 --- a/test/FormSpec.tsx +++ b/test/FormSpec.tsx @@ -1,36 +1,36 @@ -import { render } from '@testing-library/react'; - +import { describe, expect, it } from 'vitest'; +import { render, screen } from '@testing-library/react'; import Form from '../src/Form'; import FormGroup from '../src/FormGroup'; describe('
', () => { it('should support custom `as`', () => { - const { getByTestId } = render( + render( , ); - const form = getByTestId('test'); - form.tagName.toLowerCase().should.equal('fieldset'); - form.classList.length.should.equal(1); - form.classList.contains('my-form').should.be.true; - form.childElementCount.should.equal(1); - form.firstElementChild?.classList.length.should.equal(0); + const form = screen.getByTestId('test'); + expect(form.tagName).toEqual('FIELDSET'); + expect(form.classList).toHaveLength(1); + expect(form.classList).toContain('my-form'); + expect(form.childElementCount).toEqual(1); + expect(form.firstElementChild?.classList).toHaveLength(0); }); it('Should have form as default component', () => { - const { getByTestId } = render(
); + render(); - const form = getByTestId('test'); - form.tagName.toLowerCase().should.equal('form'); + const form = screen.getByTestId('test'); + expect(form.tagName).toEqual('FORM'); }); it('should have form class `was-validated` if validated', () => { - const { getByTestId } = render(); + render(); - const form = getByTestId('test'); - form.classList.length.should.equal(1); - form.classList.contains('was-validated').should.be.true; + const form = screen.getByTestId('test'); + expect(form.classList).toHaveLength(1); + expect(form.classList).toContain('was-validated'); }); }); diff --git a/test/FormTextSpec.tsx b/test/FormTextSpec.tsx index d768b43007..2d2084b576 100644 --- a/test/FormTextSpec.tsx +++ b/test/FormTextSpec.tsx @@ -1,34 +1,35 @@ -import { render } from '@testing-library/react'; +import { describe, expect, it } from 'vitest'; +import { render, screen } from '@testing-library/react'; import FormText from '../src/FormText'; describe('', () => { it('should render correctly', () => { - const { getByTestId } = render( + render( Help content , ); - const formText = getByTestId('foo'); - formText.classList.length.should.equal(2); - formText.classList.contains('form-text').should.be.true; - formText.classList.contains('my-form-text').should.be.true; - formText.innerText.should.equal('Help content'); + const formText = screen.getByTestId('foo'); + expect(formText.classList).toHaveLength(2); + expect(formText.classList).toContain('form-text'); + expect(formText.classList).toContain('my-form-text'); + expect(formText.innerText).toEqual('Help content'); }); it('Should have small as default component', () => { - const { getByTestId } = render(); + render(); - const formText = getByTestId('foo'); - formText.tagName.toLowerCase().should.equal('small'); + const formText = screen.getByTestId('foo'); + expect(formText.tagName).toEqual('SMALL'); }); it('Should have "form-text" & "text-muted" class', () => { - const { getByTestId } = render(); + render(); - const formText = getByTestId('foo'); - formText.classList.length.should.equal(2); - formText.classList.contains('form-text').should.be.true; - formText.classList.contains('text-muted').should.be.true; + const formText = screen.getByTestId('foo'); + expect(formText.classList).toHaveLength(2); + expect(formText.classList).toContain('form-text'); + expect(formText.classList).toContain('text-muted'); }); }); diff --git a/test/ImageSpec.tsx b/test/ImageSpec.tsx index 6249461b19..0a7321e0c3 100644 --- a/test/ImageSpec.tsx +++ b/test/ImageSpec.tsx @@ -1,52 +1,52 @@ -import { render } from '@testing-library/react'; - +import { describe, expect, it } from 'vitest'; +import { render, screen } from '@testing-library/react'; import Image from '../src/Image'; describe('Image', () => { it('should be an image', () => { - const { getByTestId } = render(); - getByTestId('test-image').tagName.toLowerCase().should.equal('img'); + render(); + expect(screen.getByTestId('test-image').tagName).toEqual('IMG'); }); it('should provide src and alt prop', () => { - const { getByTestId } = render( + render( this is alt, ); - getByTestId('test-image').getAttribute('src')!.should.equal('image.jpg'); - getByTestId('test-image').getAttribute('alt')!.should.equal('this is alt'); + expect(screen.getByTestId('test-image').getAttribute('src')).toEqual( + 'image.jpg', + ); + expect(screen.getByTestId('test-image').getAttribute('alt')).toEqual( + 'this is alt', + ); }); it('should have correct class when fluid prop is set', () => { - const { getByTestId } = render(); - getByTestId('test-image').classList.contains('img-fluid').should.be.true; + render(); + expect(screen.getByTestId('test-image').classList).toContain('img-fluid'); }); it('should not override class when rounded prop is set', () => { - const { getByTestId } = render( - , - ); - getByTestId('test-image').classList.contains('img-fluid').should.be.true; - getByTestId('test-image').classList.contains('rounded').should.be.true; + render(); + expect(screen.getByTestId('test-image').classList).toContain('img-fluid'); + expect(screen.getByTestId('test-image').classList).toContain('rounded'); }); it('should have correct class when rounded prop is set', () => { - const { getByTestId } = render(); - getByTestId('test-image').classList.contains('rounded').should.be.true; + render(); + expect(screen.getByTestId('test-image').classList).toContain('rounded'); }); it('should have correct class when roundedCircle prop is set', () => { - const { getByTestId } = render( - , + render(); + expect(screen.getByTestId('test-image').classList).toContain( + 'rounded-circle', ); - getByTestId('test-image').classList.contains('rounded-circle').should.be - .true; }); it('should have correct class when thumbnail prop is set', () => { - const { getByTestId } = render( - , + render(); + expect(screen.getByTestId('test-image').classList).toContain( + 'img-thumbnail', ); - getByTestId('test-image').classList.contains('img-thumbnail').should.be - .true; }); }); diff --git a/test/InputGroupSpec.tsx b/test/InputGroupSpec.tsx index ae4d058ba1..0d17940333 100644 --- a/test/InputGroupSpec.tsx +++ b/test/InputGroupSpec.tsx @@ -1,36 +1,33 @@ -import { render } from '@testing-library/react'; -import { expect } from 'chai'; - +import { describe, expect, it } from 'vitest'; +import { render, screen } from '@testing-library/react'; import InputGroup from '../src/InputGroup'; describe('', () => { it('Should have div as default component', () => { - const { getByTestId } = render(); + render(); - getByTestId('test').tagName.toLowerCase().should.equal('div'); + expect(screen.getByTestId('test').tagName).toEqual('DIV'); }); it('Should render size correctly', () => { - const { getByTestId } = render(); + render(); - getByTestId('test').classList.contains('input-group-sm').should.be.true; + expect(screen.getByTestId('test').classList).toContain('input-group-sm'); }); it('Should render hasValidation correctly', () => { - const { getByTestId } = render( - , - ); + render(); - getByTestId('test').classList.contains('has-validation').should.be.true; + expect(screen.getByTestId('test').classList).toContain('has-validation'); }); describe('', () => { it('Should forward props to underlying input element', () => { const name = 'foobar'; - const { getByRole } = render(); + render(); - expect(getByRole('checkbox').getAttribute('name')).to.be.equal(name); + expect(screen.getByRole('checkbox').getAttribute('name')).toEqual(name); }); }); @@ -38,9 +35,9 @@ describe('', () => { it('Should forward props to underlying input element', () => { const name = 'foobar'; - const { getByRole } = render(); + render(); - expect(getByRole('radio').getAttribute('name')).to.equal(name); + expect(screen.getByRole('radio').getAttribute('name')).toEqual(name); }); }); }); diff --git a/test/ListGroupItemSpec.tsx b/test/ListGroupItemSpec.tsx index f8d058df62..3248f5cc9b 100644 --- a/test/ListGroupItemSpec.tsx +++ b/test/ListGroupItemSpec.tsx @@ -1,108 +1,89 @@ -import { fireEvent, render } from '@testing-library/react'; -import { expect } from 'chai'; -import sinon from 'sinon'; -import { shouldWarn } from './helpers'; - +import { describe, expect, it, vi } from 'vitest'; +import { fireEvent, render, screen } from '@testing-library/react'; import ListGroupItem from '../src/ListGroupItem'; describe('', () => { it('should output a div', () => { - const { getByTestId } = render(); - - const item = getByTestId('test'); - item.tagName.toLowerCase().should.equal('div'); - item.classList.contains('list-group-item').should.be.true; + render(); - // .assertSingle('div.list-group-item'); + const item = screen.getByTestId('test'); + expect(item.tagName).toEqual('DIV'); + expect(item.classList).toContain('list-group-item'); }); it('accepts variants', () => { - const { getByTestId } = render( - , - ); + render(); - const item = getByTestId('test'); - item.classList.contains('list-group-item').should.be.true; - item.classList.contains('list-group-item-success').should.be.true; + const item = screen.getByTestId('test'); + expect(item.classList).toContain('list-group-item'); + expect(item.classList).toContain('list-group-item-success'); }); it('accepts active', () => { - const { getByTestId } = render(); + render(); - const item = getByTestId('test'); - item.classList.contains('list-group-item').should.be.true; - item.classList.contains('active').should.be.true; + const item = screen.getByTestId('test'); + expect(item.classList).toContain('list-group-item'); + expect(item.classList).toContain('active'); }); it('accepts disabled', () => { - const { getByTestId } = render( - , - ); + render(); - const item = getByTestId('test'); - item.classList.contains('list-group-item').should.be.true; - item.classList.contains('disabled').should.be.true; + const item = screen.getByTestId('test'); + expect(item.classList).toContain('list-group-item'); + expect(item.classList).toContain('disabled'); }); it('accepts as prop', () => { - const { getByTestId } = render( - , - ); + render(); - const item = getByTestId('test'); - item.tagName.toLowerCase().should.equal('span'); - item.classList.contains('list-group-item').should.be.true; + const item = screen.getByTestId('test'); + expect(item.tagName).toEqual('SPAN'); + expect(item.classList).toContain('list-group-item'); }); it('should not be focusable when disabled', () => { - const { getByTestId } = render( - , - ); + render(); - expect(getByTestId('test').getAttribute('tabindex')).to.equal('-1'); + expect(screen.getByTestId('test').getAttribute('tabindex')).toEqual('-1'); }); it('should respect user-specified tabIndex', () => { - const { getByTestId } = render( - , - ); + render(); - expect(getByTestId('test').getAttribute('tabindex')).to.equal('4'); + expect(screen.getByTestId('test').getAttribute('tabindex')).toEqual('4'); }); describe('actions', () => { it('renders a button', () => { - const { getByTestId } = render( - , - ); + render(); - const item = getByTestId('test'); - item.tagName.toLowerCase().should.equal('button'); - item.classList.contains('list-group-item-action').should.be.true; + const item = screen.getByTestId('test'); + expect(item.tagName).toEqual('BUTTON'); + expect(item.classList).toContain('list-group-item-action'); }); + it('renders an anchor', () => { - const { getByTestId } = render( - , - ); + render(); - const item = getByTestId('test'); - item.tagName.toLowerCase().should.equal('a'); - item.classList.contains('list-group-item-action').should.be.true; + const item = screen.getByTestId('test'); + expect(item.tagName).toEqual('A'); + expect(item.classList).toContain('list-group-item-action'); expect(item.getAttribute('href')).to.be.equal('/foo'); }); + it('renders a div and show warning', () => { - shouldWarn('together'); - const { getByTestId } = render( - , - ); + render(); - const item = getByTestId('test'); - item.tagName.toLowerCase().should.equal('div'); - item.classList.contains('list-group-item-action').should.be.false; - expect(item.getAttribute('href')).to.be.equal('/foo'); + const item = screen.getByTestId('test'); + expect(item.tagName).toEqual('DIV'); + expect(item.classList).not.toContain('list-group-item-action'); + expect(item.getAttribute('href')).toEqual('/foo'); }); + it('passes href to custom as components', () => { - const { getByTestId } = render( + render( ', () => { href="/foo" />, ); - const item = getByTestId('test'); - item.tagName.toLowerCase().should.equal('div'); - item.classList.contains('list-group-item-action').should.be.false; - expect(item.getAttribute('href')).to.be.equal('/foo'); + const item = screen.getByTestId('test'); + expect(item.tagName).toEqual('DIV'); + expect(item.classList).not.toContain('list-group-item-action'); + expect(item.getAttribute('href')).toEqual('/foo'); }); }); describe('onClick', () => { it('Should call on click', () => { - const onClickSpy = sinon.spy(); + const onClickSpy = vi.fn(); - const { getByTestId } = render( - , - ); + render(); - fireEvent.click(getByTestId('test')); - onClickSpy.should.have.been.calledOnce; + fireEvent.click(screen.getByTestId('test')); + expect(onClickSpy).toHaveBeenCalledOnce(); }); it('Should not call if disabled', () => { - const onClickSpy = sinon.spy(); + const onClickSpy = vi.fn(); - const { getByTestId } = render( + render( , ); - fireEvent.click(getByTestId('test')); - onClickSpy.should.not.have.been.called; + fireEvent.click(screen.getByTestId('test')); + expect(onClickSpy).not.toHaveBeenCalled(); }); }); }); diff --git a/test/ListGroupSpec.tsx b/test/ListGroupSpec.tsx index 08ed0ab177..479ec395cc 100644 --- a/test/ListGroupSpec.tsx +++ b/test/ListGroupSpec.tsx @@ -1,73 +1,62 @@ -import { render } from '@testing-library/react'; - +import { describe, expect, it } from 'vitest'; +import { render, screen } from '@testing-library/react'; import ListGroup from '../src/ListGroup'; -import { shouldWarn } from './helpers'; - describe('', () => { it('Should render correctly "list-group"', () => { - const { getByTestId } = render(); + render(); - const listGroup = getByTestId('test'); - listGroup.tagName.toLowerCase().should.equal('div'); - listGroup.classList.contains('list-group').should.be.true; + const listGroup = screen.getByTestId('test'); + expect(listGroup.tagName).toEqual('DIV'); + expect(listGroup.classList).toContain('list-group'); }); it('accepts children', () => { - const { getByTestId } = render( + render( hey! , ); - const listGroupItem = getByTestId('test'); - listGroupItem.classList.contains('list-group-item').should.be.true; + const listGroupItem = screen.getByTestId('test'); + expect(listGroupItem.classList).toContain('list-group-item'); }); it('accepts variant', () => { - const { getByTestId } = render( - , - ); + render(); - const listGroup = getByTestId('test'); - listGroup.classList.contains('list-group').should.be.true; - listGroup.classList.contains('list-group-flush').should.be.true; + const listGroup = screen.getByTestId('test'); + expect(listGroup.classList).toContain('list-group'); + expect(listGroup.classList).toContain('list-group-flush'); }); it('accepts global horizontal', () => { - const { getByTestId } = render(); + render(); - const listGroup = getByTestId('test'); - listGroup.classList.contains('list-group-horizontal').should.be.true; + const listGroup = screen.getByTestId('test'); + expect(listGroup.classList).toContain('list-group-horizontal'); }); (['sm', 'md', 'lg', 'xl', 'xxl', 'custom'] as const).forEach((breakpoint) => { it(`accepts responsive horizontal ${breakpoint} breakpoint`, () => { - const { getByTestId } = render( - , - ); + render(); - const listGroup = getByTestId('test'); + const listGroup = screen.getByTestId('test'); const breakpointClass = `list-group-horizontal-${breakpoint}`; - listGroup.classList.contains(breakpointClass).should.be.true; + expect(listGroup.classList).toContain(breakpointClass); }); }); - it('throws a warning if flush and horizontal are used', () => { - shouldWarn('together'); - render(); - }); - it('accepts as prop', () => { - const { getByTestId } = render(); + render(); - const listGroup = getByTestId('test'); - listGroup.tagName.toLowerCase().should.equal('ul'); - listGroup.classList.contains('list-group').should.be.true; + const listGroup = screen.getByTestId('test'); + expect(listGroup.tagName).toEqual('UL'); + expect(listGroup.classList).toContain('list-group'); }); it('should set active class on list item if activeKey set on parent', () => { - const { getByTestId } = render( + render( test @@ -75,17 +64,17 @@ describe('', () => { , ); - getByTestId('list-item').classList.contains('active').should.be.true; + expect(screen.getByTestId('list-item').classList).toContain('active'); }); it('should add numbered class', () => { - const { getByTestId } = render( + render( test , ); - const listGroup = getByTestId('list-group'); - listGroup.classList.contains('list-group-numbered').should.be.true; + const listGroup = screen.getByTestId('list-group'); + expect(listGroup.classList).toContain('list-group-numbered'); }); }); diff --git a/test/ModalBodySpec.tsx b/test/ModalBodySpec.tsx index 04eb464ba3..3675d2072c 100644 --- a/test/ModalBodySpec.tsx +++ b/test/ModalBodySpec.tsx @@ -1,28 +1,29 @@ +import { describe, expect, it } from 'vitest'; import { render } from '@testing-library/react'; -import Modal from '../src/Modal'; +import ModalBody from '../src/ModalBody'; -describe('Modal.Body', () => { +describe('ModalBody', () => { it('uses "div" by default', () => { const { getByTestId } = render( - + Content - , + , ); const elem = getByTestId('test-modal'); - elem.tagName.toLowerCase().should.equal('div'); - elem.classList.contains('modal-body').should.be.true; - elem.classList.contains('custom-class').should.be.true; - elem.querySelector('strong')!.textContent!.should.equal('Content'); + expect(elem.tagName).toEqual('DIV'); + expect(elem.classList).toContain('modal-body'); + expect(elem.classList).toContain('custom-class'); + expect(elem.querySelector('strong')!.textContent).toEqual('Content'); }); it('should allow custom elements instead of "div"', () => { const { getByTestId } = render( - + Content - , + , ); - getByTestId('test-modal').classList.contains('modal-body').should.be.true; - getByTestId('test-modal').tagName.toLowerCase().should.equal('section'); + expect(getByTestId('test-modal').classList).toContain('modal-body'); + expect(getByTestId('test-modal').tagName).toEqual('SECTION'); }); }); diff --git a/test/ModalFooterSpec.tsx b/test/ModalFooterSpec.tsx index 4e7977d9a1..56017c4527 100644 --- a/test/ModalFooterSpec.tsx +++ b/test/ModalFooterSpec.tsx @@ -1,29 +1,31 @@ -import { render } from '@testing-library/react'; +import { describe, expect, it } from 'vitest'; +import { render, screen } from '@testing-library/react'; +import ModalFooter from '../src/ModalFooter'; -import Modal from '../src/Modal'; - -describe('Modal.Footer', () => { +describe('ModalFooter', () => { it('uses "div" by default', () => { - const { getByTestId } = render( - + render( + Content - , + , ); - const elem = getByTestId('test-modal'); - elem.tagName.toLowerCase().should.equal('div'); - elem.classList.contains('modal-footer').should.be.true; - elem.classList.contains('custom-class').should.be.true; - elem.querySelector('strong')!.textContent!.should.equal('Content'); + const elem = screen.getByTestId('test-modal'); + expect(elem.tagName).toEqual('DIV'); + expect(elem.classList).toContain('modal-footer'); + expect(elem.classList).toContain('custom-class'); + expect(elem.querySelector('strong')!.textContent).toEqual('Content'); }); it('should allow custom elements instead of "div"', () => { - const { getByTestId } = render( - + render( + Content - , + , + ); + expect(screen.getByTestId('test-modal').classList).toContain( + 'modal-footer', ); - getByTestId('test-modal').classList.contains('modal-footer').should.be.true; - getByTestId('test-modal').tagName.toLowerCase().should.equal('section'); + expect(screen.getByTestId('test-modal').tagName).toEqual('SECTION'); }); }); diff --git a/test/ModalHeaderSpec.tsx b/test/ModalHeaderSpec.tsx index 044000aef4..2257f7c9fd 100644 --- a/test/ModalHeaderSpec.tsx +++ b/test/ModalHeaderSpec.tsx @@ -1,55 +1,54 @@ -import { render, fireEvent } from '@testing-library/react'; -import sinon from 'sinon'; +import { describe, expect, it, vi } from 'vitest'; +import { fireEvent, render, screen } from '@testing-library/react'; +import ModalHeader from '../src/ModalHeader'; -import Modal from '../src/Modal'; - -describe('Modal.Header', () => { +describe('ModalHeader', () => { it('uses "div" by default', () => { - const { getByTestId } = render( - + render( + Content - , + , ); - getByTestId('test-modal').tagName.toLowerCase().should.equal('div'); - getByTestId('test-modal').classList.contains('modal-header').should.be.true; - getByTestId('test-modal').classList.contains('custom-class').should.be.true; - getByTestId('test-modal') - .querySelector('strong')! - .textContent!.should.equal('Content'); + expect(screen.getByTestId('test-modal').tagName).toEqual('DIV'); + expect(screen.getByTestId('test-modal').classList).toContain( + 'modal-header', + ); + expect(screen.getByTestId('test-modal').classList).toContain( + 'custom-class', + ); + expect( + screen.getByTestId('test-modal').querySelector('strong')!.textContent, + ).toEqual('Content'); }); it('has closeButton without a containing Modal and renders', () => { - const { getByTestId } = render( - , - ); + render(); - getByTestId('test-modal').tagName.toLowerCase().should.equal('div'); - getByTestId('test-modal').querySelector('button')!.should.exist; + expect(screen.getByTestId('test-modal').tagName).toEqual('DIV'); + expect( + screen.getByTestId('test-modal').querySelector('button'), + ).toBeDefined(); }); it('Should trigger onHide when modal is closed', () => { - const onHideSpy = sinon.spy(); - const { getByTestId } = render( - , + const onHideSpy = vi.fn(); + render( + , ); - fireEvent.click(getByTestId('test-modal').querySelector('button')!); - onHideSpy.should.be.calledOnce; + fireEvent.click(screen.getByTestId('test-modal').querySelector('button')!); + expect(onHideSpy).toHaveBeenCalledOnce(); }); it('should render close button variant', () => { - const { getByTestId } = render( - , + render( + , ); - const button = getByTestId('test-modal').querySelector('button')!; + const button = screen.getByTestId('test-modal').querySelector('button')!; - button.should.exist; - button.classList.contains('btn-close-white').should.be.true; + expect(button).toBeDefined(); + expect(button.classList).toContain('btn-close-white'); }); }); diff --git a/test/ModalSpec.tsx b/test/ModalSpec.tsx index cbc52807b6..fcf2d63659 100644 --- a/test/ModalSpec.tsx +++ b/test/ModalSpec.tsx @@ -1,6 +1,5 @@ import * as React from 'react'; -import sinon from 'sinon'; -import { expect } from 'chai'; +import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'; import { fireEvent, render, screen, waitFor } from '@testing-library/react'; import ModalManager from '@restart/ui/ModalManager'; import Modal, { ModalProps } from '../src/Modal'; @@ -13,19 +12,19 @@ describe('', () => { Message , ); - ref.current!.dialog.should.exist; + expect(ref.current!.dialog).toBeDefined(); }); it('Should render the modal content', () => { - const { getByTestId } = render( + render( Message , ); - expect(getByTestId('modal').querySelector('strong')!.textContent).to.equal( - 'Message', - ); + expect( + screen.getByTestId('modal').querySelector('strong')!.textContent, + ).toEqual('Message'); }); it('Should sets `display: block` to `div.modal` when animation is false', () => { @@ -36,108 +35,108 @@ describe('', () => { , ); - expect(ref.current!.dialog.style.display).to.equal('block'); + expect(ref.current!.dialog.style.display).toEqual('block'); }); - it('Should close the modal when the modal dialog is clicked', (done) => { - const doneOp = () => { - done(); - }; + it('Should close the modal when the modal dialog is clicked', async () => { + const onHideSpy = vi.fn(); - const { getByRole } = render( - + render( + Message , ); // the modal-dialog element is pointer-events: none; - fireEvent.click(getByRole('dialog')); + fireEvent.click(screen.getByRole('dialog')); + + await waitFor(() => expect(onHideSpy).toHaveBeenCalled()); }); it('Should not close the modal when the "static" dialog is clicked', () => { - const onHideSpy = sinon.spy(); - const { getByTestId } = render( + const onHideSpy = vi.fn(); + render( Message , ); - fireEvent.click(getByTestId('modal')); - onHideSpy.should.not.have.been.called; + fireEvent.click(screen.getByTestId('modal')); + expect(onHideSpy).not.toHaveBeenCalled(); }); it('Should show "static" dialog animation when backdrop is clicked', () => { - const { getByRole } = render( + render( Message , ); - const modalDialog = getByRole('dialog'); + const modalDialog = screen.getByRole('dialog'); fireEvent.click(modalDialog); - getByRole('dialog').classList.contains('modal-static').should.be.true; + expect(screen.getByRole('dialog').classList).toContain('modal-static'); }); it('Should show "static" dialog animation when esc pressed and keyboard is false', () => { - const { getByRole } = render( + render( Message , ); - fireEvent.keyDown(getByRole('dialog'), { + fireEvent.keyDown(screen.getByRole('dialog'), { keyCode: 27, }); - getByRole('dialog').classList.contains('modal-static').should.be.true; + expect(screen.getByRole('dialog').classList).toContain('modal-static'); }); it('Should not show "static" dialog animation when esc pressed and keyboard is true', () => { - const { getByRole } = render( + render( Message , ); - fireEvent.keyDown(getByRole('dialog'), { + fireEvent.keyDown(screen.getByRole('dialog'), { keyCode: 27, }); - getByRole('dialog').classList.contains('modal-static').should.be.false; + expect(screen.getByRole('dialog').classList).not.toContain('modal-static'); }); it('Should not show "static" dialog animation modal backdrop is not "static"', () => { - const { getByTestId, getByRole } = render( + render( Message , ); - fireEvent.click(getByTestId('modal')); - getByRole('dialog').classList.contains('modal-static').should.be.false; + fireEvent.click(screen.getByTestId('modal')); + expect(screen.getByRole('dialog').classList).not.toContain('modal-static'); }); - it('Should close the modal when the modal close button is clicked', (done) => { - const doneOp = () => { - done(); - }; + it('Should close the modal when the modal close button is clicked', async () => { + const onHideSpy = vi.fn(); - const { getByTestId } = render( - + render( + Message , ); - fireEvent.click(getByTestId('close-btn').querySelector('button')!); + fireEvent.click(screen.getByTestId('close-btn').querySelector('button')!); + + await waitFor(() => expect(onHideSpy).toHaveBeenCalled()); }); it('Should pass className to the dialog', () => { - const { getByRole } = render( + render( Message , ); - getByRole('dialog').classList.contains('mymodal').should.be.true; + expect(screen.getByRole('dialog').classList).toContain('mymodal'); }); it('Should use backdropClassName to add classes to the backdrop', () => { @@ -147,104 +146,110 @@ describe('', () => { , ); - document - .querySelector('.modal-backdrop')! - .classList.contains('my-modal-backdrop').should.be.true; + expect(document.querySelector('.modal-backdrop')!.classList).toContain( + 'my-modal-backdrop', + ); }); it('Should pass size to the dialog', () => { - const { getByTestId } = render( + render( Message , ); - getByTestId('modal').classList.contains('modal-sm').should.be.true; + expect(screen.getByTestId('modal').classList).toContain('modal-sm'); }); it('Should pass fullscreen as bool to the dialog', () => { - const { getByTestId } = render( + render( Message , ); - getByTestId('modal').classList.contains('modal-fullscreen').should.be.true; + expect(screen.getByTestId('modal').classList).toContain('modal-fullscreen'); }); it('Should pass fullscreen as string to the dialog', () => { - const { getByTestId } = render( + render( Message , ); - getByTestId('modal').classList.contains('modal-fullscreen-sm-down').should - .be.true; + expect(screen.getByTestId('modal').classList).toContain( + 'modal-fullscreen-sm-down', + ); }); it('Should allow custom breakpoints for fullscreen', () => { - const { getByTestId } = render( + render( Message , ); - getByTestId('modal').classList.contains('modal-fullscreen-custom-down') - .should.be.true; + expect(screen.getByTestId('modal').classList).toContain( + 'modal-fullscreen-custom-down', + ); }); it('Should pass centered to the dialog', () => { - const { getByTestId } = render( + render( Message , ); - getByTestId('modal').classList.contains('modal-dialog-centered').should.be - .true; + expect(screen.getByTestId('modal').classList).toContain( + 'modal-dialog-centered', + ); }); it('Should pass scrollable to the dialog', () => { - const { getByTestId } = render( + render( Message , ); - getByTestId('modal').classList.contains('modal-dialog-scrollable').should.be - .true; + expect(screen.getByTestId('modal').classList).toContain( + 'modal-dialog-scrollable', + ); }); it('Should pass dialog style to the dialog', () => { - const { getByRole } = render( + render( Message , ); - getByRole('dialog').style.color.should.equal('red'); + expect(screen.getByRole('dialog').style.color).toEqual('red'); }); it('Should pass dialogClassName to the dialog', () => { - const { getByTestId } = render( + render( Message , ); - getByTestId('modal').classList.contains('my-dialog').should.be.true; + expect(screen.getByTestId('modal').classList).toContain('my-dialog'); }); it('Should pass contentClassName to .modal-content', () => { - const { getByTestId } = render( + render( Message , ); - const modalContent = getByTestId('modal').querySelector('.modal-content')!; - modalContent.classList.contains('my-content').should.be.true; + const modalContent = screen + .getByTestId('modal') + .querySelector('.modal-content')!; + expect(modalContent.classList).toContain('my-content'); }); it('Should use dialogAs', () => { @@ -259,11 +264,11 @@ describe('', () => { , ); - document.querySelector('.custom-dialog')!.should.exist; + expect(document.querySelector('.custom-dialog')).toBeDefined(); }); it('Should pass transition callbacks to Transition', async () => { - const increment = sinon.spy(); + const increment = vi.fn(); const Elem = () => { const [show, setShow] = React.useState(true); return ( @@ -286,18 +291,18 @@ describe('', () => { render(); - await waitFor(() => expect(increment.callCount).to.equal(6)); + await waitFor(() => expect(increment).toHaveBeenCalledTimes(6)); }); describe('cleanup', () => { - let offSpy; + let offSpy: ReturnType; beforeEach(() => { - offSpy = sinon.spy(window, 'removeEventListener'); + offSpy = vi.spyOn(window, 'removeEventListener'); }); afterEach(() => { - offSpy.restore(); + offSpy.mockReset(); }); it('should remove resize listener when unmounted', () => { @@ -318,39 +323,43 @@ describe('', () => { const { rerender } = render(); rerender(Foo); - offSpy.should.have.been.calledWith('resize'); + expect(offSpy).toHaveBeenCalledWith( + 'resize', + expect.anything(), + undefined, + ); }); }); it('Should close once it was clicked outside of the Modal', () => { - const onHideSpy = sinon.spy(); - const { getByRole } = render( + const onHideSpy = vi.fn(); + render( Message , ); - fireEvent.click(getByRole('dialog')); - onHideSpy.should.have.been.called; + fireEvent.click(screen.getByRole('dialog')); + expect(onHideSpy).toHaveBeenCalled(); }); it('Should not call onHide if the click target comes from inside the dialog', () => { - const onHideSpy = sinon.spy(); - const { getByTestId, getByRole } = render( + const onHideSpy = vi.fn(); + render( Message , ); - fireEvent.mouseDown(getByTestId('modal')); - fireEvent.mouseUp(getByRole('dialog')); - fireEvent.click(getByRole('dialog')); + fireEvent.mouseDown(screen.getByTestId('modal')); + fireEvent.mouseUp(screen.getByRole('dialog')); + fireEvent.click(screen.getByRole('dialog')); - onHideSpy.should.not.have.been.called; + expect(onHideSpy).not.toHaveBeenCalled(); }); it('Should set aria-labelledby to the role="dialog" element if aria-labelledby set', () => { - const { getByRole } = render( + render( Modal heading @@ -358,13 +367,13 @@ describe('', () => { , ); - expect(getByRole('dialog').getAttribute('aria-labelledby')).to.equal( + expect(screen.getByRole('dialog').getAttribute('aria-labelledby')).toEqual( 'modal-title', ); }); it('Should set aria-describedby to the role="dialog" element if aria-describedby set', () => { - const { getByRole } = render( + render( Modal heading @@ -372,14 +381,14 @@ describe('', () => { , ); - expect(getByRole('dialog').getAttribute('aria-describedby')).to.equal( + expect(screen.getByRole('dialog').getAttribute('aria-describedby')).toEqual( 'modal-title', ); }); it('Should set aria-label to the role="dialog" element if aria-label set', () => { const labelValue = 'modal-label'; - const { getByRole } = render( + render( Modal heading @@ -387,37 +396,39 @@ describe('', () => { , ); - expect(getByRole('dialog').getAttribute('aria-label')).to.equal(labelValue); + expect(screen.getByRole('dialog').getAttribute('aria-label')).toEqual( + labelValue, + ); }); it('Should call onEscapeKeyDown when keyboard is true', () => { - const onEscapeKeyDownSpy = sinon.spy(); - const { getByRole } = render( + const onEscapeKeyDownSpy = vi.fn(); + render( Message , ); - fireEvent.keyDown(getByRole('dialog'), { + fireEvent.keyDown(screen.getByRole('dialog'), { keyCode: 27, }); - onEscapeKeyDownSpy.should.have.been.called; + expect(onEscapeKeyDownSpy).toHaveBeenCalled(); }); it('Should not call onEscapeKeyDown when keyboard is false', () => { - const onEscapeKeyDownSpy = sinon.spy(); - const { getByRole } = render( + const onEscapeKeyDownSpy = vi.fn(); + render( Message , ); - fireEvent.keyDown(getByRole('dialog'), { + fireEvent.keyDown(screen.getByRole('dialog'), { keyCode: 27, }); - onEscapeKeyDownSpy.should.not.have.been.called; + expect(onEscapeKeyDownSpy).not.toHaveBeenCalled(); }); it('Should not hide modal when keyboard is false', async () => { @@ -442,7 +453,7 @@ describe('', () => { fireEvent.click(screen.getByRole('button')); const dialog = await screen.findByRole('dialog'); - expect(dialog).to.exist; + expect(dialog).toBeDefined(); // Escape key. fireEvent.keyDown(dialog, { @@ -460,11 +471,13 @@ describe('', () => { throw new Error('Dialog does not exist'); }); - it('Should use custom props manager if specified', (done) => { + it('Should use custom props manager if specified', async () => { + const addSpy = vi.fn(); + class MyModalManager extends ModalManager { // @ts-ignore add() { - done(); + addSpy(); } } @@ -477,5 +490,7 @@ describe('', () => { Message , ); + + await waitFor(() => expect(addSpy).toHaveBeenCalled()); }); }); diff --git a/test/ModalTitleSpec.tsx b/test/ModalTitleSpec.tsx index ec23ef0d79..0790c00d81 100644 --- a/test/ModalTitleSpec.tsx +++ b/test/ModalTitleSpec.tsx @@ -1,31 +1,31 @@ -import { render } from '@testing-library/react'; +import { describe, expect, it } from 'vitest'; +import { render, screen } from '@testing-library/react'; +import ModalTitle from '../src/ModalTitle'; -import Modal from '../src/Modal'; - -describe('Modal.Title', () => { +describe('ModalTitle', () => { it('uses "div" by default', () => { - const { getByTestId } = render( - + render( + Content - , + , ); - const elem = getByTestId('test-modal'); - elem.tagName.toLowerCase().should.equal('div'); - elem.classList.contains('h4').should.be.true; - elem.classList.contains('modal-title').should.be.true; - elem.classList.contains('custom-class').should.be.true; - elem.querySelector('strong')!.textContent!.should.equal('Content'); + const elem = screen.getByTestId('test-modal'); + expect(elem.tagName).toEqual('DIV'); + expect(elem.classList).toContain('h4'); + expect(elem.classList).toContain('modal-title'); + expect(elem.classList).toContain('custom-class'); + expect(elem.querySelector('strong')!.textContent!).toEqual('Content'); }); it('should allow custom elements instead of "div"', () => { - const { getByTestId } = render( - + render( + Content - , + , ); - getByTestId('test-modal').classList.contains('modal-title').should.be.true; - getByTestId('test-modal').tagName.toLowerCase().should.equal('h4'); + expect(screen.getByTestId('test-modal').classList).toContain('modal-title'); + expect(screen.getByTestId('test-modal').tagName).toEqual('H4'); }); }); diff --git a/test/NavDropdownSpec.tsx b/test/NavDropdownSpec.tsx index 9bfc18a47f..c36699364e 100644 --- a/test/NavDropdownSpec.tsx +++ b/test/NavDropdownSpec.tsx @@ -1,5 +1,5 @@ -import { render } from '@testing-library/react'; - +import { describe, expect, it } from 'vitest'; +import { render, screen } from '@testing-library/react'; import DropdownItem from '../src/DropdownItem'; import Nav from '../src/Nav'; import Navbar from '../src/Navbar'; @@ -7,7 +7,7 @@ import NavDropdown from '../src/NavDropdown'; describe('', () => { it('Should render li when in nav', () => { - const { getByTestId } = render( + render( ', () => { DropdownItem 2 content , ); - const navDropdownElem = getByTestId('test'); - navDropdownElem.classList.contains('dropdown').should.be.true; - navDropdownElem.classList.contains('test-class').should.be.true; + const navDropdownElem = screen.getByTestId('test'); + expect(navDropdownElem.classList).toContain('dropdown'); + expect(navDropdownElem.classList).toContain('test-class'); - navDropdownElem.firstElementChild!.classList.contains('nav-link').should.be - .true; - navDropdownElem.firstElementChild!.textContent!.should.equal('Title'); + expect(navDropdownElem.firstElementChild!.classList).toContain('nav-link'); + expect(navDropdownElem.firstElementChild!.textContent).toEqual('Title'); }); it('renders active toggle', () => { - const { getByTestId } = render( + render( ', () => { DropdownItem 2 content , ); - const navDropdownElem = getByTestId('test'); - navDropdownElem.firstElementChild!.classList.contains('active').should.be - .true; + const navDropdownElem = screen.getByTestId('test'); + expect(navDropdownElem.firstElementChild!.classList).toContain('active'); }); it('should handle child active state', () => { - const { getByTestId } = render( + render( , ); - getByTestId('test').textContent!.should.equal('DropdownItem 2 content'); + expect(screen.getByTestId('test').textContent).toEqual( + 'DropdownItem 2 content', + ); }); it('should pass the id to the NavLink element', () => { - const { getByTestId } = render( + render( DropdownItem 1 content , ); - getByTestId('test').firstElementChild!.id.should.equal('test-id'); + expect(screen.getByTestId('test').firstElementChild!.id).toEqual('test-id'); }); it('should support as as prop', () => { - const { getByTestId } = render( + render( Item 1 , ); - getByTestId('test').tagName.toLowerCase().should.equal('li'); + expect(screen.getByTestId('test').tagName).toEqual('LI'); }); it('passes menuVariant to dropdown menu', () => { @@ -86,7 +86,7 @@ describe('', () => { Item 1 , ); - document.querySelector('.dropdown-menu-dark')!.should.exist; + expect(document.querySelector('.dropdown-menu-dark')).toBeDefined(); }); it('sets data-bs-popper attribute on dropdown menu', () => { @@ -97,8 +97,8 @@ describe('', () => { , ); - document - .querySelectorAll('.dropdown-menu[data-bs-popper="static"]') - .length.should.equal(1); + expect( + document.querySelectorAll('.dropdown-menu[data-bs-popper="static"]'), + ).toHaveLength(1); }); }); diff --git a/test/NavItemSpec.tsx b/test/NavItemSpec.tsx index e9ad606ab5..29155e5155 100644 --- a/test/NavItemSpec.tsx +++ b/test/NavItemSpec.tsx @@ -1,35 +1,35 @@ -import { render } from '@testing-library/react'; - +import { describe, expect, it } from 'vitest'; +import { render, screen } from '@testing-library/react'; import NavItem from '../src/NavItem'; describe('', () => { it('should have div as default component', () => { - const { getByTestId } = render(); - const navItemElem = getByTestId('test'); + render(); + const navItemElem = screen.getByTestId('test'); - navItemElem.tagName.toLowerCase().should.equal('div'); - navItemElem.classList.contains('nav-item').should.be.true; + expect(navItemElem.tagName).toEqual('DIV'); + expect(navItemElem.classList).toContain('nav-item'); }); it('should allow custom elements instead of "div"', () => { - const { getByTestId } = render(); - const navItemElem = getByTestId('test'); + render(); + const navItemElem = screen.getByTestId('test'); - navItemElem.tagName.toLowerCase().should.equal('section'); - navItemElem.classList.contains('nav-item').should.be.true; + expect(navItemElem.tagName).toEqual('SECTION'); + expect(navItemElem.classList).toContain('nav-item'); }); it('should pass classNames down and render children', () => { - const { getByTestId } = render( + render( Children , ); - const navItemElem = getByTestId('test'); + const navItemElem = screen.getByTestId('test'); - navItemElem.classList.contains('nav-item').should.be.true; - navItemElem.classList.contains('custom-class').should.be.true; - navItemElem.classList.contains('and-other').should.be.true; - navItemElem.firstElementChild!.tagName.toLowerCase().should.equal('strong'); + expect(navItemElem.classList).toContain('nav-item'); + expect(navItemElem.classList).toContain('custom-class'); + expect(navItemElem.classList).toContain('and-other'); + expect(navItemElem.firstElementChild!.tagName).toEqual('STRONG'); }); }); diff --git a/test/NavLinkSpec.tsx b/test/NavLinkSpec.tsx index 9cdb7c7885..a0e9ab29a4 100644 --- a/test/NavLinkSpec.tsx +++ b/test/NavLinkSpec.tsx @@ -1,11 +1,10 @@ -import { render } from '@testing-library/react'; -import { expect } from 'chai'; - +import { describe, expect, it } from 'vitest'; +import { render, screen } from '@testing-library/react'; import NavLink from '../src/NavLink'; describe('', () => { it('renders correctly', () => { - const { getByTestId } = render( + render( ', () => { Children , ); - const navLinkElem = getByTestId('test'); - navLinkElem.classList.contains('nav-link').should.be.true; - navLinkElem.classList.contains('custom-class').should.be.true; - navLinkElem.getAttribute('href')!.should.equal('/some/unique-thing/'); - navLinkElem.getAttribute('title')!.should.equal('content'); - navLinkElem.firstElementChild!.tagName.toLowerCase().should.equal('strong'); + const navLinkElem = screen.getByTestId('test'); + expect(navLinkElem.classList).toContain('nav-link'); + expect(navLinkElem.classList).toContain('custom-class'); + expect(navLinkElem.getAttribute('href')).toEqual('/some/unique-thing/'); + expect(navLinkElem.getAttribute('title')).toEqual('content'); + expect(navLinkElem.firstElementChild!.tagName).toEqual('STRONG'); }); it('Should add active class', () => { - const { getByTestId } = render( + render( Item content , ); - const navLinkElem = getByTestId('test'); - navLinkElem.classList.contains('active').should.be.true; + const navLinkElem = screen.getByTestId('test'); + expect(navLinkElem.classList).toContain('active'); }); it('Should add disabled class', () => { - const { getByTestId } = render( + render( Item content , ); - const navLinkElem = getByTestId('test'); - navLinkElem.classList.contains('disabled').should.be.true; + const navLinkElem = screen.getByTestId('test'); + expect(navLinkElem.classList).toContain('disabled'); }); describe('Web Accessibility', () => { it('Should add aria-selected to the link when role is "tab"', () => { - const { getByTestId } = render( + render( Item content , ); - const navLinkElem = getByTestId('test'); - navLinkElem.tagName.toLowerCase().should.equal('a'); - navLinkElem.getAttribute('aria-selected')!.should.equal('true'); + const navLinkElem = screen.getByTestId('test'); + expect(navLinkElem.tagName).toEqual('A'); + expect(navLinkElem.getAttribute('aria-selected')).toEqual('true'); }); it('Should not add aria-selected to the link when role is not "tab"', () => { - const { getByTestId } = render( + render( Item content , ); - const navLinkElem = getByTestId('test'); - navLinkElem.tagName.toLowerCase().should.equal('a'); - expect(navLinkElem.getAttribute('aria-selected')).to.be.null; + const navLinkElem = screen.getByTestId('test'); + expect(navLinkElem.tagName).toEqual('A'); + expect(navLinkElem.getAttribute('aria-selected')).toBeNull(); }); }); }); diff --git a/test/NavSpec.tsx b/test/NavSpec.tsx index ac07decc66..b6a865d8a7 100644 --- a/test/NavSpec.tsx +++ b/test/NavSpec.tsx @@ -1,66 +1,65 @@ -import { fireEvent, render } from '@testing-library/react'; -import sinon from 'sinon'; +import { describe, expect, it, vi } from 'vitest'; +import { fireEvent, render, screen } from '@testing-library/react'; import CardHeader from '../src/CardHeader'; import Nav from '../src/Nav'; import Navbar from '../src/Navbar'; import NavDropdown from '../src/NavDropdown'; -import { shouldWarn } from './helpers'; describe('
, ); - containerRef.current.style.overflow.should.equal('scroll'); + expect(containerRef.current.style.overflow).toEqual('scroll'); }); it('should set responsive class', () => { - const { getByTestId } = render( + render( Message , ); - const offcanvasElem = getByTestId('test'); - offcanvasElem.classList.contains('offcanvas-lg').should.be.true; + const offcanvasElem = screen.getByTestId('test'); + expect(offcanvasElem.classList).toContain('offcanvas-lg'); }); it('should render offcanvas when show=false', () => { - const { getByTestId } = render( + render( Message , ); - const offcanvasElem = getByTestId('test'); + const offcanvasElem = screen.getByTestId('test'); expect(offcanvasElem.getAttribute('role')).to.not.exist; }); @@ -298,8 +301,8 @@ describe('', () => { return
Content
; }; - const onMountSpy = sinon.spy(); - const onUnmountSpy = sinon.spy(); + const onMountSpy = vi.fn(); + const onUnmountSpy = vi.fn(); const { unmount } = render( @@ -307,10 +310,10 @@ describe('', () => { , ); - onMountSpy.callCount.should.equal(1); + expect(onMountSpy).toHaveBeenCalledOnce(); unmount(); - onUnmountSpy.callCount.should.equal(1); + expect(onUnmountSpy).toHaveBeenCalledOnce(); }); }); diff --git a/test/OverlaySpec.tsx b/test/OverlaySpec.tsx index d92675722e..12527a2236 100644 --- a/test/OverlaySpec.tsx +++ b/test/OverlaySpec.tsx @@ -1,6 +1,6 @@ import * as React from 'react'; - -import { render } from '@testing-library/react'; +import { describe, expect, it } from 'vitest'; +import { render, screen } from '@testing-library/react'; import Overlay from '../src/Overlay'; import Popover from '../src/Popover'; @@ -13,32 +13,32 @@ describe('', () => { , ); - ref.current.id.should.equal('my-overlay'); + expect(ref.current.id).toEqual('my-overlay'); }); it('should use Fade internally if transition=true', () => { const ref = React.createRef(); - const { getByTestId } = render( + render( test , ); - const popoverElem = getByTestId('test'); - popoverElem.classList.contains('fade').should.be.true; + const popoverElem = screen.getByTestId('test'); + expect(popoverElem.classList).toContain('fade'); }); it('should not use Fade if transition=false', () => { const ref = React.createRef(); - const { getByTestId } = render( + render( test , ); - const popoverElem = getByTestId('test'); - popoverElem.classList.contains('fade').should.be.false; + const popoverElem = screen.getByTestId('test'); + expect(popoverElem.classList).not.toContain('fade'); }); }); diff --git a/test/OverlayTriggerSpec.tsx b/test/OverlayTriggerSpec.tsx index b6f7367089..06cab370ee 100644 --- a/test/OverlayTriggerSpec.tsx +++ b/test/OverlayTriggerSpec.tsx @@ -1,6 +1,6 @@ -import PropTypes from 'prop-types'; import * as React from 'react'; - +import PropTypes from 'prop-types'; +import { describe, expect, it, vi } from 'vitest'; import { act, fireEvent, @@ -9,11 +9,9 @@ import { waitFor, waitForElementToBeRemoved, } from '@testing-library/react'; -import sinon from 'sinon'; -import { expect } from 'chai'; import OverlayTrigger from '../src/OverlayTrigger'; -// import Popover from '../src/Popover'; -// import Tooltip from '../src/Tooltip'; +import Popover from '../src/Popover'; +import Tooltip from '../src/Tooltip'; describe('', () => { // Swallow extra props. @@ -32,7 +30,7 @@ describe('', () => { ); it('should not throw an error with StrictMode', () => { - const { getByTestId } = render( + render( test}> , ); - const buttonElem = getByTestId('test-button'); - buttonElem.should.exist; + const buttonElem = screen.getByTestId('test-button'); + expect(buttonElem).toBeDefined(); }); it('Should show after click trigger', () => { - const { queryByTestId, getByTestId } = render( + render( }> , ); - let overlayElem = queryByTestId('test-overlay'); - const buttonElem = getByTestId('test-button'); + let overlayElem = screen.queryByTestId('test-overlay'); + const buttonElem = screen.getByTestId('test-button'); - expect(overlayElem).to.be.null; + expect(overlayElem).toBeNull(); fireEvent.click(buttonElem); - overlayElem = queryByTestId('test-overlay'); - expect(overlayElem).to.not.be.null; + overlayElem = screen.queryByTestId('test-overlay'); + expect(overlayElem).not.toBeNull(); }); it('Should accept a function as an overlay render prop', () => { const overlay = () => ; - const { queryByTestId, getByTestId } = render( + render( , ); - let overlayElem = queryByTestId('test-overlay'); - const buttonElem = getByTestId('test-button'); + let overlayElem = screen.queryByTestId('test-overlay'); + const buttonElem = screen.getByTestId('test-button'); - expect(overlayElem).to.be.null; + expect(overlayElem).toBeNull(); fireEvent.click(buttonElem); - overlayElem = queryByTestId('test-overlay'); - expect(overlayElem).to.not.be.null; + overlayElem = screen.queryByTestId('test-overlay'); + expect(overlayElem).not.toBeNull(); }); it('Should show the tooltip when transitions are disabled', () => { const overlay = ({ className }: any) => ( ); - const { getByTestId, queryByTestId } = render( + render( ', () => { , ); - let overlayElem = queryByTestId('test-overlay'); - const buttonElem = getByTestId('test-button'); + let overlayElem = screen.queryByTestId('test-overlay'); + const buttonElem = screen.getByTestId('test-button'); - expect(overlayElem).to.be.null; + expect(overlayElem).toBeNull(); fireEvent.focus(buttonElem); - overlayElem = queryByTestId('test-overlay'); - expect(overlayElem).to.not.be.null; + overlayElem = screen.queryByTestId('test-overlay'); + expect(overlayElem).not.toBeNull(); - overlayElem!.classList.contains('show').should.be.true; + expect(overlayElem!.classList).toContain('show'); }); it('Should call OverlayTrigger onClick prop to child', () => { - const callback = sinon.spy(); + const callback = vi.fn(); - const { getByTestId } = render( + render( test} trigger="click"> , ); - const buttonElem = getByTestId('test-button'); + const buttonElem = screen.getByTestId('test-button'); fireEvent.click(buttonElem); - callback.should.have.been.called; + expect(callback).toHaveBeenCalled(); }); it('Should be controllable', () => { - const callback = sinon.spy(); + const callback = vi.fn(); - const { getByTestId } = render( + render( ', () => { , ); - const overlayElem = getByTestId('test-overlay'); - const buttonElem = getByTestId('test-button'); + const overlayElem = screen.getByTestId('test-overlay'); + const buttonElem = screen.getByTestId('test-button'); - overlayElem.classList.contains('show').should.be.true; + expect(overlayElem.classList).toContain('show'); fireEvent.click(buttonElem); - callback.should.have.been.calledOnce.and.calledWith(false); + expect(callback).toHaveBeenCalledOnce(); + expect(callback).toHaveBeenCalledWith(false); }); it('Should show after mouseover trigger', async () => { @@ -172,58 +171,57 @@ describe('', () => { const overlayElem = screen.queryByTestId('test-overlay'); const hoverElem = screen.getByTestId('test-hover'); - expect(overlayElem).to.be.null; + expect(overlayElem).toBeNull(); fireEvent.mouseOver(hoverElem); - await waitFor( - () => expect(screen.queryByTestId('test-overlay')).to.not.be.null, + await waitFor(() => + expect(screen.queryByTestId('test-overlay')).not.toBeNull(), ); fireEvent.mouseOut(hoverElem); - await waitFor( - () => expect(screen.queryByTestId('test-overlay')).to.be.null, + await waitFor(() => + expect(screen.queryByTestId('test-overlay')).toBeNull(), ); }); it('Should not set aria-describedby if the state is not show', () => { - const { getByTestId } = render( + render( }> , ); - const buttonElem = getByTestId('test-button'); + const buttonElem = screen.getByTestId('test-button'); - expect(buttonElem.getAttribute('aria-describedby')).to.be.null; + expect(buttonElem.getAttribute('aria-describedby')).toBeNull(); }); - // TODO: This test will block others from running - // it('Should set aria-describedby for tooltips if the state is show', async () => { - // const { getByTestId } = render( - // }> - // - // , - // ); - // const buttonElem = getByTestId('test-button'); + it('Should set aria-describedby for tooltips if the state is show', async () => { + render( + }> + + , + ); + const buttonElem = screen.getByTestId('test-button'); - // fireEvent.click(buttonElem); + fireEvent.click(buttonElem); - // // aria-describedby gets assigned after a slight delay - // await waitFor( - // () => buttonElem.getAttribute('aria-describedby')!.should.exist, - // ); + // aria-describedby gets assigned after a slight delay + await waitFor(() => + expect(buttonElem.getAttribute('aria-describedby')).toBeDefined(), + ); - // buttonElem.getAttribute('aria-describedby')!.should.equal('test-tooltip'); - // }); + expect(buttonElem.getAttribute('aria-describedby')).toEqual('test-tooltip'); + }); it('Should keep trigger handlers', () => { - const onClickSpy = sinon.spy(); - const { getByTestId } = render( + const onClickSpy = vi.fn(); + render(
', () => {
, ); - fireEvent.click(getByTestId('test-button')); + fireEvent.click(screen.getByTestId('test-button')); - onClickSpy.should.be.called; + expect(onClickSpy).toHaveBeenCalled(); }); it('Should maintain overlay classname', () => { - const { getByTestId, queryByTestId } = render( + render( test} @@ -253,20 +251,20 @@ describe('', () => { , ); - const buttonElem = getByTestId('test-button'); + const buttonElem = screen.getByTestId('test-button'); fireEvent.click(buttonElem); - const overlayElem = queryByTestId('test-overlay'); - overlayElem!.should.not.be.null; - overlayElem!.classList.contains('test-overlay').should.be.true; + const overlayElem = screen.queryByTestId('test-overlay'); + expect(overlayElem).not.toBeNull(); + expect(overlayElem!.classList).toContain('test-overlay'); }); it('Should pass transition callbacks to Transition', async () => { - const increment = sinon.spy(); - const onEnteredSpy = sinon.spy(); - const onExitedSpy = sinon.spy(); + const increment = vi.fn(); + const onEnteredSpy = vi.fn(); + const onExitedSpy = vi.fn(); - const { getByTestId } = render( + render( test} @@ -283,18 +281,18 @@ describe('', () => { , ); - fireEvent.click(getByTestId('test-button')); + fireEvent.click(screen.getByTestId('test-button')); await screen.findByTestId('test-overlay'); - await waitFor(() => onEnteredSpy.callCount.should.equal(1)); + await waitFor(() => expect(onEnteredSpy).toHaveBeenCalledOnce()); - fireEvent.click(getByTestId('test-button')); + fireEvent.click(screen.getByTestId('test-button')); - await waitForElementToBeRemoved(() => getByTestId('test-overlay')); + await waitForElementToBeRemoved(() => screen.getByTestId('test-overlay')); - await waitFor(() => onExitedSpy.callCount.should.equal(1)); - increment.callCount.should.equal(4); + await waitFor(() => expect(onExitedSpy).toHaveBeenCalledOnce()); + expect(increment).toHaveBeenCalledTimes(4); }); it('Should forward requested context', () => { @@ -302,7 +300,7 @@ describe('', () => { key: PropTypes.string, }; - const contextSpy = sinon.spy(); + const contextSpy = vi.fn(); class ContextReader extends React.Component { static contextTypes = contextTypes; @@ -331,60 +329,58 @@ describe('', () => { } } - const { getByTestId } = render(); - const buttonElem = getByTestId('test-button'); + render(); + const buttonElem = screen.getByTestId('test-button'); fireEvent.click(buttonElem); - contextSpy.calledWith('value').should.be.true; + expect(contextSpy).toHaveBeenCalledWith('value'); }); - // TODO: This test will block others from running - // it('Should handle popover trigger without warnings', async () => { - // const { getByTestId } = render( - // - // test - // - // } - // > - // - // , - // ); - - // const buttonElem = getByTestId('test-button'); - // fireEvent.click(buttonElem); - - // const overlay = await screen.findByTestId('test-overlay'); - // overlay.should.exist; - // }); - - // TODO: This test will block others from running - // it('Should handle tooltip trigger without warnings', async () => { - // const { getByTestId } = render( - // - // test - // - // } - // > - // - // , - // ); - - // const buttonElem = getByTestId('test-button'); - // fireEvent.click(buttonElem); - - // const overlay = await screen.findByTestId('test-overlay'); - // overlay.should.exist; - // }); + it('Should handle popover trigger without warnings', async () => { + render( + + test + + } + > + + , + ); + + const buttonElem = screen.getByTestId('test-button'); + fireEvent.click(buttonElem); + + const overlay = await screen.findByTestId('test-overlay'); + expect(overlay).toBeDefined(); + }); + + it('Should handle tooltip trigger without warnings', async () => { + render( + + test + + } + > + + , + ); + + const buttonElem = screen.getByTestId('test-button'); + fireEvent.click(buttonElem); + + const overlay = await screen.findByTestId('test-overlay'); + expect(overlay).toBeDefined(); + }); describe('rootClose', () => { [ @@ -401,7 +397,7 @@ describe('', () => { ].forEach((testCase) => { describe(testCase.label, () => { it('Should have correct show state', () => { - const { getByTestId } = render( + render( test} trigger="click" @@ -412,25 +408,25 @@ describe('', () => { , ); - const buttonElem = getByTestId('test-button'); + const buttonElem = screen.getByTestId('test-button'); fireEvent.click(buttonElem); - const overlayElem = getByTestId('test-overlay'); - overlayElem.classList.contains('show').should.be.true; + const overlayElem = screen.getByTestId('test-overlay'); + expect(overlayElem.classList).toContain('show'); // Need to click this way for it to propagate to document element. act(() => { document.documentElement.click(); }); - overlayElem.classList - .contains('show') - .should.equal(testCase.shownAfterClick); + expect(overlayElem.classList.contains('show')).toEqual( + testCase.shownAfterClick, + ); }); }); }); it('should hide after clicking on trigger', () => { - const { getByTestId } = render( + render( test} trigger="click" @@ -441,16 +437,16 @@ describe('', () => { , ); - const buttonElem = getByTestId('test-button'); + const buttonElem = screen.getByTestId('test-button'); fireEvent.click(buttonElem); - let overlayElem = getByTestId('test-overlay'); - overlayElem.classList.contains('show').should.be.true; + let overlayElem = screen.getByTestId('test-overlay'); + expect(overlayElem.classList).toContain('show'); // Need to click this way for it to propagate to document element. fireEvent.click(buttonElem); - overlayElem = getByTestId('test-overlay'); - overlayElem.classList.contains('show').should.be.false; + overlayElem = screen.getByTestId('test-overlay'); + expect(overlayElem.classList).not.toContain('show'); }); it('Should still be show a replaced overlay', () => { @@ -485,21 +481,21 @@ describe('', () => { }, ); - const { getByTestId } = render( + render( } trigger="click" rootClose> , ); - const buttonElem = getByTestId('test-button'); + const buttonElem = screen.getByTestId('test-button'); fireEvent.click(buttonElem); - const toBeReplacedElem = getByTestId('test-not-replaced'); + const toBeReplacedElem = screen.getByTestId('test-not-replaced'); fireEvent.click(toBeReplacedElem); - const replacedElem = getByTestId('test-replaced'); - replacedElem.classList.contains('show').should.be.true; + const replacedElem = screen.getByTestId('test-replaced'); + expect(replacedElem.classList).toContain('show'); }); }); }); diff --git a/test/PageItemSpec.tsx b/test/PageItemSpec.tsx index df0e8f4fc5..1ccde1b104 100644 --- a/test/PageItemSpec.tsx +++ b/test/PageItemSpec.tsx @@ -1,29 +1,27 @@ -import { render } from '@testing-library/react'; - +import { describe, expect, it } from 'vitest'; +import { render, screen } from '@testing-library/react'; import PageItem, { First } from '../src/PageItem'; describe('', () => { describe('', () => { it('should have expected default innerText', () => { - const { getByTestId } = render(); - const firstElem = getByTestId('test'); + render(); + const firstElem = screen.getByTestId('test'); - firstElem.classList.contains('page-link').should.be.true; + expect(firstElem.classList).toContain('page-link'); - firstElem.firstElementChild!.tagName.toLowerCase().should.equal('span'); - firstElem - .firstElementChild!.getAttribute('aria-hidden')! - .should.equal('true'); - firstElem.firstElementChild!.textContent!.should.equal('«'); + expect(firstElem.firstElementChild!.tagName).toEqual('SPAN'); + expect(firstElem.firstElementChild!.getAttribute('aria-hidden')).toEqual( + 'true', + ); + expect(firstElem.firstElementChild!.textContent).toEqual('«'); }); it('should have expected custom innerText', () => { const innerHTML = 'custom'; - const { getByTestId } = render( - {innerHTML}, - ); - const firstElem = getByTestId('test'); + render({innerHTML}); + const firstElem = screen.getByTestId('test'); - firstElem.firstElementChild!.textContent!.should.equal(innerHTML); + expect(firstElem.firstElementChild!.textContent).toEqual(innerHTML); }); it('should render a nested span if active is true', () => { @@ -31,13 +29,11 @@ describe('', () => { const pageItemElem = container.firstElementChild!; const pageItemInnerElem = pageItemElem.firstElementChild!; - pageItemElem.classList.contains('active').should.be.true; - pageItemInnerElem.classList.contains('page-link').should.be.true; + expect(pageItemElem.classList).toContain('active'); + expect(pageItemInnerElem.classList).toContain('page-link'); // check if nested span is rendered - pageItemInnerElem - .firstElementChild!.tagName.toLowerCase() - .should.equal('span'); + expect(pageItemInnerElem.firstElementChild!.tagName).toEqual('SPAN'); }); it('should render a span if disabled is true', () => { @@ -45,9 +41,8 @@ describe('', () => { const pageItemElem = container.firstElementChild!; const pageItemInnerElem = pageItemElem.firstElementChild!; - pageItemElem.classList.contains('disabled').should.be.true; - - pageItemInnerElem.classList.contains('page-link').should.be.true; + expect(pageItemElem.classList).toContain('disabled'); + expect(pageItemInnerElem.classList).toContain('page-link'); }); it('should apply className to the inner component if linkClassName is set', () => { @@ -57,7 +52,7 @@ describe('', () => { const pageItemElem = container.firstElementChild!; const pageItemInnerElem = pageItemElem.firstElementChild!; - pageItemInnerElem.classList.contains('custom-class-name').should.be.true; + expect(pageItemInnerElem.classList).toContain('custom-class-name'); }); it('should apply style to the inner component if linkStyle is set', () => { @@ -65,7 +60,7 @@ describe('', () => { const pageItemElem = container.firstElementChild!; const pageItemInnerElem = pageItemElem.firstElementChild!; - pageItemInnerElem.getAttribute('style')!.should.equal('color: red;'); + expect(pageItemInnerElem.getAttribute('style')).toEqual('color: red;'); }); it('should support custom anchor element', () => { @@ -77,7 +72,7 @@ describe('', () => { const { container } = render(); const pageItemElem = container.firstElementChild!; const pageItemInnerElem = pageItemElem.firstElementChild!; - pageItemInnerElem.getAttribute('data-anchor')!.should.equal('custom'); + expect(pageItemInnerElem.getAttribute('data-anchor')).toEqual('custom'); }); }); }); diff --git a/test/PaginationSpec.tsx b/test/PaginationSpec.tsx index 1d0c130c5d..b0d48cef36 100644 --- a/test/PaginationSpec.tsx +++ b/test/PaginationSpec.tsx @@ -1,25 +1,23 @@ -import { render } from '@testing-library/react'; -import React from 'react'; - +import * as React from 'react'; +import { describe, expect, it } from 'vitest'; +import { render, screen } from '@testing-library/react'; import Pagination from '../src/Pagination'; describe('', () => { it('should have class', () => { - const { getByTestId } = render( - Item content, - ); - const paginationElem = getByTestId('test'); - paginationElem.classList.contains('pagination').should.be.true; + render(Item content); + const paginationElem = screen.getByTestId('test'); + expect(paginationElem.classList).toContain('pagination'); }); it('should render correctly when size is set', () => { - const { getByTestId } = render( + render( Item content , ); - const paginationElem = getByTestId('test'); - paginationElem.classList.contains('pagination-sm').should.be.true; + const paginationElem = screen.getByTestId('test'); + expect(paginationElem.classList).toContain('pagination-sm'); }); it('sub-components should forward ref correctly', () => { @@ -30,6 +28,6 @@ describe('', () => { , ); - ref.current?.tagName.toLowerCase().should.be.equal('li'); + expect(ref.current?.tagName).toEqual('LI'); }); }); diff --git a/test/PlaceholderButtonSpec.tsx b/test/PlaceholderButtonSpec.tsx index 09efeb01b4..71f82d41e9 100644 --- a/test/PlaceholderButtonSpec.tsx +++ b/test/PlaceholderButtonSpec.tsx @@ -1,20 +1,22 @@ +import { describe, expect, it } from 'vitest'; import { render } from '@testing-library/react'; - import PlaceholderButton from '../src/PlaceholderButton'; describe('', () => { it('should render a placeholder', () => { const { container } = render(); - container.firstElementChild!.className.should.contain('placeholder'); + expect(container.firstElementChild!.className).toContain('placeholder'); }); it('should render size', () => { const { container } = render(); - container.firstElementChild!.className.should.contain('placeholder-lg'); + expect(container.firstElementChild!.className).toContain('placeholder-lg'); }); it('should render animation', () => { const { container } = render(); - container.firstElementChild!.className.should.contain('placeholder-glow'); + expect(container.firstElementChild!.className).toContain( + 'placeholder-glow', + ); }); }); diff --git a/test/PlaceholderSpec.tsx b/test/PlaceholderSpec.tsx index 9ee3159bd5..449ffeed98 100644 --- a/test/PlaceholderSpec.tsx +++ b/test/PlaceholderSpec.tsx @@ -1,25 +1,27 @@ +import { describe, expect, it } from 'vitest'; import { render } from '@testing-library/react'; - import Placeholder from '../src/Placeholder'; describe('', () => { it('should render a placeholder', () => { const { container } = render(); - container.firstElementChild!.className.should.contain('placeholder'); + expect(container.firstElementChild!.className).toContain('placeholder'); }); it('should render size', () => { const { container } = render(); - container.firstElementChild!.className.should.contain('placeholder-lg'); + expect(container.firstElementChild!.className).toContain('placeholder-lg'); }); it('should render animation', () => { const { container } = render(); - container.firstElementChild!.className.should.contain('placeholder-glow'); + expect(container.firstElementChild!.className).toContain( + 'placeholder-glow', + ); }); it('should render bg', () => { const { container } = render(); - container.firstElementChild!.className.should.contain('bg-primary'); + expect(container.firstElementChild!.className).toContain('bg-primary'); }); }); diff --git a/test/PopoverSpec.tsx b/test/PopoverSpec.tsx index a79ffdf66b..b0ebcdc0c4 100644 --- a/test/PopoverSpec.tsx +++ b/test/PopoverSpec.tsx @@ -1,10 +1,10 @@ -import { render } from '@testing-library/react'; - +import { describe, expect, it } from 'vitest'; +import { render, screen } from '@testing-library/react'; import Popover from '../src/Popover'; describe('Popover', () => { it('Should output a popover title and content', () => { - const { getByTestId } = render( + render( Popover title @@ -12,18 +12,18 @@ describe('Popover', () => { , ); - const popoverElem = getByTestId('test'); + const popoverElem = screen.getByTestId('test'); const popoverArrowElem = popoverElem.children[0]!; const popoverHeaderElem = popoverElem.children[1]!; const popoverBodyElem = popoverElem.children[2]!; - popoverElem.getAttribute('x-placement')!.should.equal('right'); - popoverElem.getAttribute('role')!.should.equal('tooltip'); - popoverElem.classList.contains('popover').should.be.true; - popoverElem.classList.contains('bs-popover-end').should.be.true; + expect(popoverElem.getAttribute('x-placement')).toEqual('right'); + expect(popoverElem.getAttribute('role')).toEqual('tooltip'); + expect(popoverElem.classList).toContain('popover'); + expect(popoverElem.classList).toContain('bs-popover-end'); - popoverArrowElem.classList.contains('popover-arrow').should.be.true; - popoverHeaderElem.classList.contains('popover-header').should.be.true; - popoverBodyElem.classList.contains('popover-body').should.be.true; + expect(popoverArrowElem.classList).toContain('popover-arrow'); + expect(popoverHeaderElem.classList).toContain('popover-header'); + expect(popoverBodyElem.classList).toContain('popover-body'); }); }); diff --git a/test/ProgressBarSpec.tsx b/test/ProgressBarSpec.tsx index 81418ada17..fa97dbcf24 100644 --- a/test/ProgressBarSpec.tsx +++ b/test/ProgressBarSpec.tsx @@ -1,24 +1,22 @@ -import { render } from '@testing-library/react'; - +import { describe, expect, it } from 'vitest'; +import { render, screen } from '@testing-library/react'; import ProgressBar from '../src/ProgressBar'; -import { shouldWarn } from './helpers'; describe('', () => { it('Should output a progress bar with wrapper', () => { - const { getByTestId } = render( - , - ); - const progressElem = getByTestId('test'); + render(); + + const progressElem = screen.getByTestId('test'); const innerProgressElem = progressElem.firstElementChild!; - progressElem.classList.contains('progress').should.be.true; - innerProgressElem.classList.contains('progress-bar').should.be.true; - innerProgressElem.getAttribute('role')!.should.equal('progressbar'); + expect(progressElem.classList).toContain('progress'); + expect(innerProgressElem.classList).toContain('progress-bar'); + expect(innerProgressElem.getAttribute('role')).toEqual('progressbar'); }); ['success', 'warning', 'info', 'danger'].forEach((variant) => { it(`Should have the variant="${variant}" class`, () => { - const { getByTestId } = render( + render( ', () => { variant={variant} />, ); - const innerProgressElem = getByTestId('test').firstElementChild!; - innerProgressElem.classList.contains(`bg-${variant}`); + const innerProgressElem = screen.getByTestId('test').firstElementChild!; + expect(innerProgressElem.classList).toContain(`bg-${variant}`); }); }); it('Should default to min:0, max:100', () => { - const { getByTestId } = render(); - const innerProgressElem = getByTestId('test').firstElementChild!; - innerProgressElem.getAttribute('aria-valuemin')!.should.equal('0'); - innerProgressElem.getAttribute('aria-valuemax')!.should.equal('100'); + render(); + const innerProgressElem = screen.getByTestId('test').firstElementChild!; + expect(innerProgressElem.getAttribute('aria-valuemin')).toEqual('0'); + expect(innerProgressElem.getAttribute('aria-valuemax')).toEqual('100'); }); it('Should have 0% computed width', () => { - const { getByTestId } = render( - , - ); - const innerProgressElem = getByTestId('test').firstElementChild!; - (innerProgressElem as HTMLElement).style.width.should.equal('0%'); + render(); + const innerProgressElem = screen.getByTestId('test').firstElementChild!; + expect((innerProgressElem as HTMLElement).style.width).toEqual('0%'); }); it('Should have 10% computed width', () => { - const { getByTestId } = render( - , - ); - const innerProgressElem = getByTestId('test').firstElementChild!; - (innerProgressElem as HTMLElement).style.width.should.equal('10%'); + render(); + const innerProgressElem = screen.getByTestId('test').firstElementChild!; + expect((innerProgressElem as HTMLElement).style.width).toEqual('10%'); }); it('Should have 100% computed width', () => { - const { getByTestId } = render( - , - ); - const innerProgressElem = getByTestId('test').firstElementChild!; - (innerProgressElem as HTMLElement).style.width.should.equal('100%'); + render(); + const innerProgressElem = screen.getByTestId('test').firstElementChild!; + expect((innerProgressElem as HTMLElement).style.width).toEqual('100%'); }); it('Should have 50% computed width with non-zero min', () => { - const { getByTestId } = render( - , - ); - const innerProgressElem = getByTestId('test').firstElementChild!; - (innerProgressElem as HTMLElement).style.width.should.equal('50%'); + render(); + const innerProgressElem = screen.getByTestId('test').firstElementChild!; + expect((innerProgressElem as HTMLElement).style.width).toEqual('50%'); }); it('Should not have label', () => { - const { getByTestId } = render( - , - ); - const innerProgressElem = getByTestId('test').firstElementChild!; - innerProgressElem.textContent!.should.equal(''); + render(); + const innerProgressElem = screen.getByTestId('test').firstElementChild!; + expect(innerProgressElem.textContent).toEqual(''); }); it('Should have label', () => { - const { getByTestId } = render( + render( ', () => { label="progress bar label" />, ); - const innerProgressElem = getByTestId('test').firstElementChild!; - innerProgressElem.textContent!.should.equal('progress bar label'); + const innerProgressElem = screen.getByTestId('test').firstElementChild!; + expect(innerProgressElem.textContent).toEqual('progress bar label'); }); it('Should have screen reader only label', () => { - const { getByTestId } = render( + render( ', () => { label="progress bar label" />, ); - const innerProgressElem = getByTestId('test').firstElementChild!; - - innerProgressElem.classList.contains('visually-hidden'); - innerProgressElem.textContent!.should.equal('progress bar label'); + const innerProgressElem = screen.getByTestId('test').firstElementChild!; + expect(innerProgressElem.firstElementChild!.classList).toContain( + 'visually-hidden', + ); + expect(innerProgressElem.textContent).toEqual('progress bar label'); }); it('Should have a label that is a React component', () => { const customLabel = My label; - const { getByTestId } = render( + render( ', () => { label={customLabel} />, ); - const innerProgressElem = getByTestId('test').firstElementChild!; - innerProgressElem.firstElementChild!.classList.contains('special-label') - .should.be.true; + const innerProgressElem = screen.getByTestId('test').firstElementChild!; + expect(innerProgressElem.firstElementChild!.classList).toContain( + 'special-label', + ); }); it('Should have screen reader only label that wraps a React component', () => { const customLabel = My label; - const { getByTestId } = render( + render( ', () => { visuallyHidden />, ); - const innerProgressElem = getByTestId('test').firstElementChild!; - innerProgressElem.firstElementChild!.classList.contains('visually-hidden') - .should.be.true; - innerProgressElem.firstElementChild!.firstElementChild!.classList.contains( - 'special-label', - ).should.be.true; + const innerProgressElem = screen.getByTestId('test').firstElementChild!; + expect(innerProgressElem.firstElementChild!.classList).toContain( + 'visually-hidden', + ); + expect( + innerProgressElem.firstElementChild!.firstElementChild!.classList, + ).toContain('special-label'); }); it('Should show striped bar', () => { - const { getByTestId } = render( - , - ); - const innerProgressElem = getByTestId('test').firstElementChild!; - innerProgressElem.classList.contains('progress-bar-striped'); + render(); + const innerProgressElem = screen.getByTestId('test').firstElementChild!; + expect(innerProgressElem.classList).toContain('progress-bar-striped'); }); it('Should show animated striped bar', () => { - const { getByTestId } = render( + render( , ); - const innerProgressElem = getByTestId('test').firstElementChild!; - innerProgressElem.classList.contains('progress-bar-striped'); - innerProgressElem.classList.contains('progress-bar-animated'); + const innerProgressElem = screen.getByTestId('test').firstElementChild!; + expect(innerProgressElem.classList).toContain('progress-bar-striped'); + expect(innerProgressElem.classList).toContain('progress-bar-animated'); }); it('Should show stacked bars', () => { - const { getByTestId } = render( + render( , ); - const innerProgressElem = getByTestId('test'); + const innerProgressElem = screen.getByTestId('test'); const bar1 = innerProgressElem.firstElementChild!; const bar2 = innerProgressElem.lastElementChild!; - bar1.classList.contains('progress-bar').should.be.true; - (bar1 as HTMLElement).style.width.should.equal('50%'); + expect(bar1.classList).toContain('progress-bar'); + expect((bar1 as HTMLElement).style.width).toEqual('50%'); - bar2.classList.contains('progress-bar').should.be.true; - (bar2 as HTMLElement).style.width.should.equal('30%'); + expect(bar2.classList).toContain('progress-bar'); + expect((bar2 as HTMLElement).style.width).toEqual('30%'); }); it('Should render animated and striped children in stacked bar too', () => { - const { getByTestId } = render( + render( , ); - const innerProgressElem = getByTestId('test'); + const innerProgressElem = screen.getByTestId('test'); const bar1 = innerProgressElem.firstElementChild!; const bar2 = innerProgressElem.lastElementChild!; - bar1.classList.contains('progress-bar').should.be.true; - bar1.classList.contains('progress-bar-striped').should.be.true; - bar1.classList.contains('progress-bar-animated').should.be.true; + expect(bar1.classList).toContain('progress-bar'); + expect(bar1.classList).toContain('progress-bar-striped'); + expect(bar1.classList).toContain('progress-bar-animated'); - bar2.classList.contains('progress-bar').should.be.true; - bar2.classList.contains('progress-bar-striped').should.be.true; - bar2.classList.contains('progress-bar-animated').should.be.false; + expect(bar2.classList).toContain('progress-bar'); + expect(bar2.classList).toContain('progress-bar-striped'); + expect(bar2.classList).not.toContain('progress-bar-animated'); }); it('Should forward className and style to nested bars', () => { - const { getByTestId } = render( + render( , ); - const innerProgressElem = getByTestId('test'); + const innerProgressElem = screen.getByTestId('test'); const bar1 = innerProgressElem.firstElementChild!; const bar2 = innerProgressElem.lastElementChild!; - bar1.classList.contains('progress-bar').should.be.true; - (bar2 as HTMLElement).style.minWidth.should.equal('10px'); - }); - - it('allows only ProgressBar in children', () => { - shouldWarn('Failed prop'); - - function NotProgressBar() { - return null; - } - function NotProgressBar2() { - return
asdf
; - } - - render( - - - - foo - - - , - ); + expect(bar1.classList).toContain('progress-bar'); + expect((bar2 as HTMLElement).style.minWidth).toEqual('10px'); }); }); diff --git a/test/RatioSpec.tsx b/test/RatioSpec.tsx index b9ea21643c..ac88f9f2e0 100644 --- a/test/RatioSpec.tsx +++ b/test/RatioSpec.tsx @@ -1,62 +1,62 @@ -import { render } from '@testing-library/react'; - +import { describe, expect, it } from 'vitest'; +import { render, screen } from '@testing-library/react'; import Ratio from '../src/Ratio'; describe('Ratio', () => { it('should contain `ratio-1x1` and custom class', () => { - const { getByTestId } = render( + render(
, ); - const ratioElem = getByTestId('test'); + const ratioElem = screen.getByTestId('test'); - ratioElem.classList.contains('custom-class').should.be.true; - ratioElem.classList.contains('ratio').should.be.true; - ratioElem.classList.contains('ratio-1x1').should.be.true; + expect(ratioElem.classList).toContain('custom-class'); + expect(ratioElem.classList).toContain('ratio'); + expect(ratioElem.classList).toContain('ratio-1x1'); }); it('should support custom ratios using percent for aspectRatio', () => { - const { getByTestId } = render( + render(
, ); - const ratioElem = getByTestId('test'); + const ratioElem = screen.getByTestId('test'); const styleAttr = ratioElem.getAttribute('style')!; - styleAttr.should.match(/--bs-aspect-ratio:[ ]*50%;/); + expect(styleAttr).toMatch(/--bs-aspect-ratio:[ ]*50%;/); }); it('should support custom ratios using fraction for aspectRatio', () => { - const { getByTestId } = render( + render(
, ); - const ratioElem = getByTestId('test'); + const ratioElem = screen.getByTestId('test'); const styleAttr = ratioElem.getAttribute('style')!; - styleAttr.should.match(/--bs-aspect-ratio:[ ]*50%;/); + expect(styleAttr).toMatch(/--bs-aspect-ratio:[ ]*50%;/); }); it('should support use 100% as custom ratio if aspectRatio is less than 0', () => { - const { getByTestId } = render( + render(
, ); - const ratioElem = getByTestId('test'); + const ratioElem = screen.getByTestId('test'); const styleAttr = ratioElem.getAttribute('style')!; - styleAttr.should.match(/--bs-aspect-ratio:[ ]*100%;/); + expect(styleAttr).toMatch(/--bs-aspect-ratio:[ ]*100%;/); }); it('should support aspectRatio greater than 100', () => { - const { getByTestId } = render( + render(
, ); - const ratioElem = getByTestId('test'); + const ratioElem = screen.getByTestId('test'); const styleAttr = ratioElem.getAttribute('style')!; - styleAttr.should.match(/--bs-aspect-ratio:[ ]*200%;/); + expect(styleAttr).toMatch(/--bs-aspect-ratio:[ ]*200%;/); }); }); diff --git a/test/RowSpec.tsx b/test/RowSpec.tsx index b1cb59be77..a191ef1dee 100644 --- a/test/RowSpec.tsx +++ b/test/RowSpec.tsx @@ -1,84 +1,84 @@ -import { render } from '@testing-library/react'; +import { describe, expect, it } from 'vitest'; +import { render, screen } from '@testing-library/react'; import { ThemeProvider } from '../src'; - import Row from '../src/Row'; describe('Row', () => { it('Should include "row" when there are no sizes', () => { - const { getByText } = render(Row); - getByText('Row').classList.contains('row').should.be.true; + render(Row); + expect(screen.getByText('Row').classList).toContain('row'); }); it('Should include sizes', () => { - const { getByText } = render( + render( Row , ); - getByText('Row').classList.contains('row-cols-md-8').should.be.true; - getByText('Row').classList.contains('row-cols-4').should.be.true; + expect(screen.getByText('Row').classList).toContain('row-cols-md-8'); + expect(screen.getByText('Row').classList).toContain('row-cols-4'); }); it('Should allow sizes as objects', () => { - const { getByText } = render( + render( Row , ); - getByText('Row').classList.contains('row-cols-md-8').should.be.true; - getByText('Row').classList.contains('row-cols-4').should.be.true; + expect(screen.getByText('Row').classList).toContain('row-cols-md-8'); + expect(screen.getByText('Row').classList).toContain('row-cols-4'); }); it('Should allow auto as size', () => { - const { getByText } = render( + render( Row , ); - getByText('Row').classList.contains('row-cols-md-auto').should.be.true; - getByText('Row').classList.contains('row-cols-auto').should.be.true; + expect(screen.getByText('Row').classList).toContain('row-cols-md-auto'); + expect(screen.getByText('Row').classList).toContain('row-cols-auto'); }); it('Should allow auto as size in object form', () => { - const { getByText } = render( + render( Row , ); - getByText('Row').classList.contains('row-cols-md-auto').should.be.true; - getByText('Row').classList.contains('row-cols-auto').should.be.true; + expect(screen.getByText('Row').classList).toContain('row-cols-md-auto'); + expect(screen.getByText('Row').classList).toContain('row-cols-auto'); }); it('uses "div" by default', () => { - const { getByText } = render( + render( Children , ); - const wrapper = getByText('Children').parentElement; - wrapper?.tagName.toLowerCase().should.equal('div'); - wrapper?.classList.contains('row').should.be.true; - wrapper?.classList.contains('custom-class').should.be.true; - getByText('Children').tagName.toLowerCase().should.equal('strong'); + const wrapper = screen.getByText('Children').parentElement; + expect(wrapper?.tagName).toEqual('DIV'); + expect(wrapper?.classList).toContain('row'); + expect(wrapper?.classList).toContain('custom-class'); + expect(screen.getByText('Children').tagName).toEqual('STRONG'); }); it('should allow custom elements instead of "div"', () => { - const { getByText } = render(Row); - getByText('Row').tagName.toLowerCase().should.equal('section'); - getByText('Row').classList.contains('row').should.be.true; + render(Row); + expect(screen.getByText('Row').tagName).toEqual('SECTION'); + expect(screen.getByText('Row').classList).toContain('row'); }); it('should allow custom breakpoints', () => { - const { getByText } = render( + render( test , ); - getByText('test').classList.contains('row-cols-custom-3').should.be.true; + expect(screen.getByText('test').classList).toContain('row-cols-custom-3'); }); it('should allow custom breakpoints smaller than default "xs"', () => { - const { getByText } = render( + render( test @@ -86,7 +86,7 @@ describe('Row', () => { , ); - getByText('test').classList.contains('row-cols-3').should.be.true; - getByText('test').classList.contains('row-cols-xs-2').should.be.true; + expect(screen.getByText('test').classList).toContain('row-cols-3'); + expect(screen.getByText('test').classList).toContain('row-cols-xs-2'); }); }); diff --git a/test/SpinnerSpec.tsx b/test/SpinnerSpec.tsx index f5c8847468..2408e6a3da 100644 --- a/test/SpinnerSpec.tsx +++ b/test/SpinnerSpec.tsx @@ -1,17 +1,15 @@ -import { render } from '@testing-library/react'; - +import { describe, expect, it } from 'vitest'; +import { render, screen } from '@testing-library/react'; import Spinner from '../src/Spinner'; describe('', () => { it('Should render a basic spinner correctly', () => { - const { getByTestId } = render( - , - ); - getByTestId('test').classList.contains('spinner-border').should.be.true; + render(); + expect(screen.getByTestId('test').classList).toContain('spinner-border'); }); it('Should render a spinner with a custom element, variant and size ', () => { - const { getByTestId } = render( + render( ', () => { size="sm" />, ); - const spinnerElem = getByTestId('test'); + const spinnerElem = screen.getByTestId('test'); - spinnerElem.tagName.toLowerCase().should.equal('span'); - spinnerElem.classList.contains('spinner-grow').should.be.true; - spinnerElem.classList.contains('spinner-grow-sm').should.be.true; - spinnerElem.classList.contains('text-primary').should.be.true; + expect(spinnerElem.tagName).toEqual('SPAN'); + expect(spinnerElem.classList).toContain('spinner-grow'); + expect(spinnerElem.classList).toContain('spinner-grow-sm'); + expect(spinnerElem.classList).toContain('text-primary'); }); it('Should render a spinner with other properties', () => { - const { getByTestId } = render( - , - ); - const spinnerElem = getByTestId('test'); + render(); + const spinnerElem = screen.getByTestId('test'); - spinnerElem.classList.contains('spinner-grow').should.be.true; - spinnerElem.getAttribute('role')!.should.equal('status'); + expect(spinnerElem.classList).toContain('spinner-grow'); + expect(spinnerElem.getAttribute('role')!).toEqual('status'); }); it('Should render child elements', () => { - const { getByTestId } = render( + render( , ); - const spinnerElem = getByTestId('test'); - spinnerElem.children.length.should.equal(1); + const spinnerElem = screen.getByTestId('test'); + expect(spinnerElem.children.length).toEqual(1); }); it('Should have div as default component', () => { - const { getByTestId } = render( - , - ); - const spinnerElem = getByTestId('test'); - spinnerElem.tagName.toLowerCase().should.equal('div'); + render(); + const spinnerElem = screen.getByTestId('test'); + expect(spinnerElem.tagName).toEqual('DIV'); }); }); diff --git a/test/SplitButtonSpec.tsx b/test/SplitButtonSpec.tsx index d0e3299728..606460ff1b 100644 --- a/test/SplitButtonSpec.tsx +++ b/test/SplitButtonSpec.tsx @@ -1,5 +1,5 @@ -import { fireEvent, render } from '@testing-library/react'; -import sinon from 'sinon'; +import { describe, expect, it, vi } from 'vitest'; +import { fireEvent, render, screen } from '@testing-library/react'; import SplitButton from '../src/SplitButton'; import DropdownItem from '../src/DropdownItem'; @@ -14,44 +14,48 @@ describe('', () => { ); it('should open the menu when dropdown button is clicked', () => { - const { getByTestId } = render(simple); - const splitButtonElem = getByTestId('test-wrapper'); + render(simple); + const splitButtonElem = screen.getByTestId('test-wrapper'); - splitButtonElem.classList.contains('show').should.be.false; + expect(splitButtonElem.classList).not.toContain('show'); fireEvent.click(splitButtonElem.children[1]); - splitButtonElem.classList.contains('show').should.be.true; + expect(splitButtonElem.classList).toContain('show'); }); it('should not open the menu when other button is clicked', () => { - const { getByTestId } = render(simple); - const splitButtonElem = getByTestId('test-wrapper'); + render(simple); + const splitButtonElem = screen.getByTestId('test-wrapper'); - splitButtonElem.classList.contains('show').should.be.false; + expect(splitButtonElem.classList).not.toContain('show'); fireEvent.click(splitButtonElem.children[0]); - splitButtonElem.classList.contains('show').should.be.false; + expect(splitButtonElem.classList).not.toContain('show'); }); - it('should invoke onClick when SplitButton.Button is clicked (prop)', (done) => { - const { getByTestId } = render( + it('should invoke onClick when SplitButton.Button is clicked (prop)', () => { + const onClickSpy = vi.fn(); + + render( done()} + onClick={onClickSpy} > Item 1 , ); - const splitButtonElem = getByTestId('test-wrapper'); + const splitButtonElem = screen.getByTestId('test-wrapper'); fireEvent.click(splitButtonElem.firstElementChild!); + + expect(onClickSpy).toHaveBeenCalled(); }); it('should not invoke onClick when SplitButton.Toggle is clicked (prop)', () => { - const onClickSpy = sinon.spy(); + const onClickSpy = vi.fn(); - const { getByTestId } = render( + render( ', () => { Item 1 , ); - const splitButtonElem = getByTestId('test-wrapper'); + const splitButtonElem = screen.getByTestId('test-wrapper'); fireEvent.click(splitButtonElem.children[1]); - onClickSpy.should.not.have.been.called; + expect(onClickSpy).not.toHaveBeenCalled(); }); it('Should pass disabled to both buttons', () => { - const { getByTestId } = render( + render( ', () => { Item 1 , ); - const splitButtonElem = getByTestId('test-wrapper'); + const splitButtonElem = screen.getByTestId('test-wrapper'); - splitButtonElem.getAttribute('disabled')!.should.exist; - splitButtonElem.children[0].getAttribute('disabled')!.should.exist; - splitButtonElem.children[1].getAttribute('disabled')!.should.exist; + expect(splitButtonElem.getAttribute('disabled')).toBeDefined(); + expect(splitButtonElem.children[0].getAttribute('disabled')).toBeDefined(); + expect(splitButtonElem.children[1].getAttribute('disabled')).toBeDefined(); }); it('Should set target attribute on anchor', () => { - const { getByTestId } = render( + render( ', () => { DropdownItem 1 content , ); - const splitButtonElem = getByTestId('test-wrapper'); - splitButtonElem.firstElementChild!.tagName.toLowerCase().should.equal('a'); - splitButtonElem - .firstElementChild!.getAttribute('href')! - .should.equal('/some/unique-thing/'); - splitButtonElem - .firstElementChild!.getAttribute('target')! - .should.equal('_blank'); + const splitButtonElem = screen.getByTestId('test-wrapper'); + expect(splitButtonElem.firstElementChild!.tagName).toEqual('A'); + expect(splitButtonElem.firstElementChild!.getAttribute('href')).toEqual( + '/some/unique-thing/', + ); + expect(splitButtonElem.firstElementChild!.getAttribute('target')).toEqual( + '_blank', + ); }); it('should set accessible label on toggle', () => { - const { getByText } = render(simple); - const toggleLabelElem = getByText('Toggle dropdown'); - toggleLabelElem.classList.contains('visually-hidden').should.be.true; + render(simple); + const toggleLabelElem = screen.getByText('Toggle dropdown'); + expect(toggleLabelElem.classList).toContain('visually-hidden'); }); it('should set aria-label on toggle from toggleLabel', () => { - const { getByText } = render( + render( Item 1 , ); - const labelElem = getByText('Label'); - labelElem.classList.contains('visually-hidden').should.be.true; + const labelElem = screen.getByText('Label'); + expect(labelElem.classList).toContain('visually-hidden'); }); it('should set type attribute from type', () => { - const { getByTestId } = render( + render( ', () => { Item 1 , ); - const splitButtonElem = getByTestId('test-wrapper'); - splitButtonElem - .firstElementChild!.getAttribute('type')! - .should.equal('submit'); + const splitButtonElem = screen.getByTestId('test-wrapper'); + expect(splitButtonElem.firstElementChild!.getAttribute('type')).toEqual( + 'submit', + ); }); }); diff --git a/test/StackSpec.tsx b/test/StackSpec.tsx index b677f272b5..4cae272257 100644 --- a/test/StackSpec.tsx +++ b/test/StackSpec.tsx @@ -1,25 +1,25 @@ +import { describe, expect, it } from 'vitest'; import { render } from '@testing-library/react'; - import Stack from '../src/Stack'; describe('', () => { it('should render a vertical stack by default', () => { const { container } = render(); - container.firstElementChild!.className.should.contain('vstack'); + expect(container.firstElementChild!.className).toContain('vstack'); }); it('should render direction', () => { const { container } = render(); - container.firstElementChild!.className.should.contain('hstack'); + expect(container.firstElementChild!.className).toContain('hstack'); }); it('should render gap', () => { const { container } = render(); - container.firstElementChild!.classList.contains('gap-2').should.be.true; + expect(container.firstElementChild!.classList).toContain('gap-2'); }); it('should render responsive gap', () => { const { container } = render(); - container.firstElementChild!.classList.contains('gap-md-2').should.be.true; + expect(container.firstElementChild!.classList).toContain('gap-md-2'); }); }); diff --git a/test/TabContentSpec.tsx b/test/TabContentSpec.tsx index fc2c7481c8..c364979c94 100644 --- a/test/TabContentSpec.tsx +++ b/test/TabContentSpec.tsx @@ -1,11 +1,11 @@ +import { describe, expect, it } from 'vitest'; import { render } from '@testing-library/react'; - import TabContent from '../src/TabContent'; describe('', () => { it('Should have div as default component', () => { const { container } = render(); - container.tagName.toLowerCase().should.equal('div'); + expect(container.tagName).toEqual('DIV'); }); }); diff --git a/test/TableSpec.tsx b/test/TableSpec.tsx index e55d77cb2d..8f997d820c 100644 --- a/test/TableSpec.tsx +++ b/test/TableSpec.tsx @@ -1,78 +1,76 @@ -import { render } from '@testing-library/react'; - +import { describe, expect, it } from 'vitest'; +import { render, screen } from '@testing-library/react'; import Table from '../src/Table'; describe('Table', () => { it('Should be a table', () => { - const { getByTestId } = render(); - const tableElem = getByTestId('test'); + render(
); + const tableElem = screen.getByTestId('test'); - tableElem.classList.contains('table').should.be.true; - tableElem.tagName.toLowerCase().should.equal('table'); + expect(tableElem.classList).toContain('table'); + expect(tableElem.tagName).toEqual('TABLE'); }); it('Should have correct class when using striped row', () => { - const { getByTestId } = render(
); - const tableElem = getByTestId('test'); + render(
); + const tableElem = screen.getByTestId('test'); - tableElem.classList.contains('table-striped').should.be.true; + expect(tableElem.classList).toContain('table-striped'); }); it('Should have correct class when using striped column', () => { - const { getByTestId } = render( -
, - ); - const tableElem = getByTestId('test'); + render(
); + const tableElem = screen.getByTestId('test'); - tableElem.classList.contains('table-striped-columns').should.be.true; + expect(tableElem.classList).toContain('table-striped-columns'); }); it('Should have correct class when hover', () => { - const { getByTestId } = render(
); - const tableElem = getByTestId('test'); + render(
); + const tableElem = screen.getByTestId('test'); - tableElem.classList.contains('table-hover').should.be.true; + expect(tableElem.classList).toContain('table-hover'); }); it('Should have correct class when bordered', () => { - const { getByTestId } = render(
); - const tableElem = getByTestId('test'); + render(
); + const tableElem = screen.getByTestId('test'); - tableElem.classList.contains('table-bordered').should.be.true; + expect(tableElem.classList).toContain('table-bordered'); }); it('Should have correct class when borderless', () => { - const { getByTestId } = render(
); - const tableElem = getByTestId('test'); + render(
); + const tableElem = screen.getByTestId('test'); - tableElem.classList.contains('table-borderless').should.be.true; + expect(tableElem.classList).toContain('table-borderless'); }); it('Should have correct class when small', () => { - const { getByTestId } = render(
); - const tableElem = getByTestId('test'); + render(
); + const tableElem = screen.getByTestId('test'); - tableElem.classList.contains('table-sm').should.be.true; + expect(tableElem.classList).toContain('table-sm'); }); it('Should have correct class when dark', () => { - const { getByTestId } = render(
); - const tableElem = getByTestId('test'); + render(
); + const tableElem = screen.getByTestId('test'); - tableElem.classList.contains('table-dark').should.be.true; + expect(tableElem.classList).toContain('table-dark'); }); it('Should have responsive wrapper', () => { const { container } = render(
); const tableElem = container.firstElementChild!; - tableElem!.classList.contains('table-responsive').should.be.true; + expect(tableElem.classList).toContain('table-responsive'); }); it('Should have responsive breakpoints', () => { const { container } = render(
); const tableElem = container.firstElementChild!; - tableElem!.classList.contains('table-responsive-sm').should.be.true; + expect(tableElem.classList).toContain('table-responsive-sm'); }); }); diff --git a/test/TabsSpec.tsx b/test/TabsSpec.tsx index 7260ed8ccf..79626bd99a 100644 --- a/test/TabsSpec.tsx +++ b/test/TabsSpec.tsx @@ -1,11 +1,8 @@ -import { fireEvent, render } from '@testing-library/react'; -import sinon from 'sinon'; - +import { describe, expect, it, vi } from 'vitest'; +import { fireEvent, render, screen } from '@testing-library/react'; import Tab from '../src/Tab'; import Tabs from '../src/Tabs'; -import { shouldWarn } from './helpers'; - const checkEventKey = (elem: Element, eventKey: string | number) => elem.getAttribute('data-rr-ui-event-key') === `${eventKey}` && elem.getAttribute('id') === `test-tab-${eventKey}` && @@ -13,7 +10,7 @@ const checkEventKey = (elem: Element, eventKey: string | number) => describe('', () => { it('Should show the correct tab and assign correct eventKeys', () => { - const { getByText } = render( + render( Tab 1 content @@ -23,23 +20,23 @@ describe('', () => { , ); - const firstTabButton = getByText('Tab 1 title'); - const firstTabContent = getByText('Tab 1 content'); - const secondTabButton = getByText('Tab 2 title'); + const firstTabButton = screen.getByText('Tab 1 title'); + const firstTabContent = screen.getByText('Tab 1 content'); + const secondTabButton = screen.getByText('Tab 2 title'); - firstTabButton.tagName.toLowerCase().should.equal('button'); - firstTabButton.classList.contains('active').should.be.true; - firstTabContent.classList.contains('active').should.be.true; + expect(firstTabButton.tagName).toEqual('BUTTON'); + expect(firstTabButton.classList).toContain('active'); + expect(firstTabContent.classList).toContain('active'); - secondTabButton.classList.contains('active').should.be.false; - secondTabButton.tagName.toLowerCase().should.equal('button'); + expect(secondTabButton.classList).not.toContain('active'); + expect(secondTabButton.tagName).toEqual('BUTTON'); - checkEventKey(firstTabButton, 1).should.be.true; - checkEventKey(secondTabButton, 2).should.be.true; + expect(checkEventKey(firstTabButton, 1)).toEqual(true); + expect(checkEventKey(secondTabButton, 2)).toEqual(true); }); it('should get defaultActiveKey (if null) from first child tab with eventKey', () => { - const { getByText } = render( + render( Tab 1 content @@ -50,22 +47,22 @@ describe('', () => { , ); - const firstTabButton = getByText('Tab 1 title'); - const firstTabContent = getByText('Tab 1 content'); - const secondTabButton = getByText('Tab 2 title'); + const firstTabButton = screen.getByText('Tab 1 title'); + const firstTabContent = screen.getByText('Tab 1 content'); + const secondTabButton = screen.getByText('Tab 2 title'); - firstTabButton.tagName.toLowerCase().should.equal('button'); - firstTabButton.classList.contains('active').should.be.true; - firstTabContent.classList.contains('active').should.be.true; + expect(firstTabButton.tagName).toEqual('BUTTON'); + expect(firstTabButton.classList).toContain('active'); + expect(firstTabContent.classList).toContain('active'); - secondTabButton.classList.contains('active').should.be.false; - secondTabButton.tagName.toLowerCase().should.equal('button'); + expect(secondTabButton.classList).not.toContain('active'); + expect(secondTabButton.tagName).toEqual('BUTTON'); }); it('Should allow tab title to have React components', () => { const tabTitle = React Tab 2; - const { getByText } = render( + render( Tab 1 content @@ -75,16 +72,13 @@ describe('', () => { , ); - getByText('React Tab 2').classList.contains('special-tab').should.be.true; + expect(screen.getByText('React Tab 2').classList).toContain('special-tab'); }); it('Should call onSelect when tab is selected', () => { - const onSelect = (key) => { - key.should.equal('2'); - }; - const onSelectSpy = sinon.spy(onSelect); + const onSelectSpy = vi.fn(); - const { getByText } = render( + render( Tab 1 content @@ -95,12 +89,12 @@ describe('', () => { , ); - fireEvent.click(getByText('Tab 2')); - onSelectSpy.should.have.been.called; + fireEvent.click(screen.getByText('Tab 2')); + expect(onSelectSpy).toHaveBeenCalledWith('2', expect.anything()); }); it('Should have children with the correct DOM properties', () => { - const { getByText } = render( + render( Tab 1 content @@ -110,21 +104,21 @@ describe('', () => { , ); - const firstTabContent = getByText('Tab 1 content'); - const secondTabContent = getByText('Tab 2 content'); + const firstTabContent = screen.getByText('Tab 1 content'); + const secondTabContent = screen.getByText('Tab 2 content'); - const firstTabTitle = getByText('Tab 1'); - const secondTabTitle = getByText('Tab 2'); + const firstTabTitle = screen.getByText('Tab 1'); + const secondTabTitle = screen.getByText('Tab 2'); - firstTabContent.classList.contains('custom').should.be.true; - secondTabContent.classList.contains('tcustom').should.be.false; + expect(firstTabContent.classList).toContain('custom'); + expect(secondTabContent.classList).not.toContain('tcustom'); - firstTabTitle.classList.contains('custom').should.be.false; - secondTabTitle.classList.contains('tcustom').should.be.true; + expect(firstTabTitle.classList).not.toContain('custom'); + expect(secondTabTitle.classList).toContain('tcustom'); }); it('Should pass variant to Nav', () => { - const { getByTestId } = render( + render( ', () => { , ); - getByTestId('test').classList.contains('nav-pills').should.be.true; + expect(screen.getByTestId('test').classList).toContain('nav-pills'); }); it('Should pass disabled to Nav', () => { - const onSelect = (e) => e; - const onSelectSpy = sinon.spy(onSelect); + const onSelectSpy = vi.fn(); - const { getByText } = render( + render( Tab 1 content @@ -157,15 +150,14 @@ describe('', () => { , ); - const secondTabTitle = getByText('Tab 2'); - secondTabTitle.classList.contains('disabled').should.be.true; + const secondTabTitle = screen.getByText('Tab 2'); + expect(secondTabTitle.classList).toContain('disabled'); - onSelectSpy.should.not.have.been.called; + expect(onSelectSpy).not.toHaveBeenCalled(); }); it('Should not render a Tab without a title', () => { - shouldWarn('Failed prop'); - const { getByTestId } = render( + render( {/* @ts-ignore */} Tab 1 content @@ -174,12 +166,12 @@ describe('', () => { , ); - const tabs = getByTestId('testid'); - tabs.children.should.have.length(1); + const tabs = screen.getByTestId('testid'); + expect(tabs.children).toHaveLength(1); }); it('Should render TabPane with role="tabpanel"', () => { - const { getAllByRole } = render( + render( Tab 1 content @@ -187,7 +179,7 @@ describe('', () => { , ); - getAllByRole('tabpanel').should.have.length(1); + expect(screen.getAllByRole('tabpanel')).toHaveLength(1); }); it('should have fade animation by default', () => { @@ -198,11 +190,11 @@ describe('', () => { , ); - getByRole('tabpanel').classList.contains('fade').should.be.true; + expect(getByRole('tabpanel').classList).toContain('fade'); }); it('Should omit Transition in TabPane if prop is false ', () => { - const { getByText } = render( + render( Tab 1 content @@ -212,15 +204,15 @@ describe('', () => { , ); - const firstTabContent = getByText('Tab 1 content'); - const secondTabContent = getByText('Tab 2 content'); + const firstTabContent = screen.getByText('Tab 1 content'); + const secondTabContent = screen.getByText('Tab 2 content'); - firstTabContent.classList.contains('fade').should.be.false; - secondTabContent.classList.contains('fade').should.be.true; + expect(firstTabContent.classList).not.toContain('fade'); + expect(secondTabContent.classList).toContain('fade'); }); it('Should pass fill to Nav', () => { - const { getByTestId } = render( + render( Tab 1 content @@ -231,11 +223,11 @@ describe('', () => { , ); - getByTestId('test').classList.contains('nav-fill').should.be.true; + expect(screen.getByTestId('test').classList).toContain('nav-fill'); }); it('Should pass justified to Nav', () => { - const { getByTestId } = render( + render( Tab 1 content @@ -246,18 +238,18 @@ describe('', () => { , ); - getByTestId('test').classList.contains('nav-justified').should.be.true; + expect(screen.getByTestId('test').classList).toContain('nav-justified'); }); }); -// describe('', () => { -// it('should throw error message on attempt to render', () => { -// expect(() => -// render( -// -// Tab 1 content -// , -// ), -// ).to.throw(); -// }); -// }); +describe('', () => { + it('should throw error message on attempt to render', () => { + expect(() => + render( + + Tab 1 content + , + ), + ).to.throw(); + }); +}); diff --git a/test/ThemeProviderSpec.tsx b/test/ThemeProviderSpec.tsx index bd7271a24b..1e216e99a7 100644 --- a/test/ThemeProviderSpec.tsx +++ b/test/ThemeProviderSpec.tsx @@ -1,6 +1,6 @@ import * as React from 'react'; - -import { render } from '@testing-library/react'; +import { describe, expect, it } from 'vitest'; +import { render, screen } from '@testing-library/react'; import ThemeProvider, { createBootstrapComponent } from '../src/ThemeProvider'; import Button from '../src/Button'; @@ -20,19 +20,19 @@ describe('', () => { ); it('should use HOC value', () => { - const { getByText } = render( + render(
, ); - const fooElem = getByText('foo val'); - fooElem.classList.contains(hocValue).should.be.true; - fooElem.tagName.toLowerCase().should.equal('p'); + const fooElem = screen.getByText('foo val'); + expect(fooElem.classList).toContain(hocValue); + expect(fooElem.tagName).toEqual('P'); }); it('should provide bsPrefix overrides', () => { - const { getByText } = render( + render(
@@ -40,37 +40,38 @@ describe('', () => {
, ); - const buttonElem = getByText('My label'); - buttonElem.tagName.toLowerCase().should.equal('button'); - buttonElem.classList.contains('my-btn').should.be.true; - buttonElem.classList.contains('my-btn-primary').should.be.true; + const buttonElem = screen.getByText('My label'); + expect(buttonElem.tagName).toEqual('BUTTON'); + expect(buttonElem.classList).toContain('my-btn'); + expect(buttonElem.classList).toContain('my-btn-primary'); - const fooElem = getByText('foo val'); - fooElem.tagName.toLowerCase().should.equal('p'); - fooElem.classList.contains('global-foo').should.be.true; + const fooElem = screen.getByText('foo val'); + expect(fooElem.tagName).toEqual('P'); + expect(fooElem.classList).toContain('global-foo'); }); it('should use prop bsPrefix first', () => { - const { getByText } = render( + render(
, ); - const fooElem = getByText('foo val'); - fooElem.tagName.toLowerCase().should.equal('p'); - fooElem.classList.contains('my-foo').should.be.true; + const fooElem = screen.getByText('foo val'); + expect(fooElem.tagName).toEqual('P'); + expect(fooElem.classList).toContain('my-foo'); }); it('should forward ref', () => { let ref; - const { getByText } = render( + render(
(ref = r)} />
, ); - // If the ref of rendered element has the correct bsPrefix, it means that it has been forwarded correctly - getByText('foo val').className.includes(ref.props.bsPrefix).should.be.true; + // If the ref of rendered element has the correct bsPrefix, it means that + // it has been forwarded correctly + expect(screen.getByText('foo val').className).toContain(ref.props.bsPrefix); }); }); diff --git a/test/ToastBodySpec.tsx b/test/ToastBodySpec.tsx index a5b3d01fbf..b42ac3a90a 100644 --- a/test/ToastBodySpec.tsx +++ b/test/ToastBodySpec.tsx @@ -1,4 +1,4 @@ -import * as React from 'react'; +import { describe, expect, it } from 'vitest'; import { render } from '@testing-library/react'; import Toast from '../src/Toast'; @@ -8,9 +8,7 @@ describe('Toast.Body', () => { const { container } = render( {content}, ); - container.firstElementChild!.classList.contains('custom-class').should.be - .true; - container.firstElementChild!.classList.contains('toast-body').should.be - .true; + expect(container.firstElementChild!.classList).toContain('custom-class'); + expect(container.firstElementChild!.classList).toContain('toast-body'); }); }); diff --git a/test/ToastContainerSpec.tsx b/test/ToastContainerSpec.tsx index 73d5ba83e8..1359904dfb 100644 --- a/test/ToastContainerSpec.tsx +++ b/test/ToastContainerSpec.tsx @@ -1,3 +1,4 @@ +import { describe, expect, it } from 'vitest'; import { render } from '@testing-library/react'; import ToastContainer, { ToastPosition } from '../src/ToastContainer'; @@ -16,25 +17,23 @@ const expectedClasses: Record> = { describe('ToastContainer', () => { it('should render a basic toast container', () => { const { container } = render(); - container.firstElementChild!.classList.contains('toast-container').should.be - .true; + expect(container.firstElementChild!.classList).toContain('toast-container'); }); it('should render the containerPosition', () => { const { container } = render( , ); - container.firstElementChild!.classList.contains('position-relative').should - .be.true; + expect(container.firstElementChild!.classList).toContain( + 'position-relative', + ); }); Object.keys(expectedClasses).forEach((position: ToastPosition) => { it(`should render position=${position}`, () => { const { container } = render(); - expectedClasses[position].map( - (className) => - container.firstElementChild!.classList.contains(className).should.be - .true, + expectedClasses[position].map((className) => + expect(container.firstElementChild!.classList).toContain(className), ); }); }); diff --git a/test/ToastHeaderSpec.tsx b/test/ToastHeaderSpec.tsx index 4393651aba..5160612c14 100644 --- a/test/ToastHeaderSpec.tsx +++ b/test/ToastHeaderSpec.tsx @@ -1,5 +1,5 @@ +import { describe, expect, it } from 'vitest'; import { render } from '@testing-library/react'; - import Toast from '../src/Toast'; describe('Toast.Header', () => { @@ -9,14 +9,13 @@ describe('Toast.Header', () => { content , ); - container.firstElementChild!.tagName.toLowerCase().should.equal('div'); + expect(container.firstElementChild!.tagName).toEqual('DIV'); - container - .firstElementChild!.firstElementChild!.tagName.toLowerCase() - .should.equal('strong'); + expect(container.firstElementChild!.firstElementChild!.tagName).toEqual( + 'STRONG', + ); - container.firstElementChild!.classList.contains('toast-header').should.be - .true; + expect(container.firstElementChild!.classList).toContain('toast-header'); }); it('should render close button variant', () => { @@ -25,8 +24,8 @@ describe('Toast.Header', () => { content , ); - container - .firstElementChild!.getElementsByTagName('button')[0] - .classList.contains('btn-close-white').should.be.true; + expect( + container.firstElementChild!.getElementsByTagName('button')[0].classList, + ).toContain('btn-close-white'); }); }); diff --git a/test/ToastSpec.tsx b/test/ToastSpec.tsx index f71ec96d4e..78a99d93b3 100644 --- a/test/ToastSpec.tsx +++ b/test/ToastSpec.tsx @@ -1,7 +1,6 @@ import * as React from 'react'; +import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'; import { act, fireEvent, render } from '@testing-library/react'; -import sinon from 'sinon'; -import { expect } from 'chai'; import Toast from '../src/Toast'; const getToast = ({ @@ -17,21 +16,20 @@ const getToast = ({ ); describe('', () => { - let clock; + let clock: ReturnType; beforeEach(() => { - clock = sinon.useFakeTimers(); + clock = vi.useFakeTimers(); }); afterEach(() => { - clock.restore(); + clock.useRealTimers(); }); it('should apply bg prop', () => { const { container } = render(Card); - container.firstElementChild!.classList.contains('bg-primary').should.be - .true; - container.firstElementChild!.classList.contains('toast').should.be.true; + expect(container.firstElementChild!.classList).toContain('bg-primary'); + expect(container.firstElementChild!.classList).toContain('toast'); }); it('should render an entire toast', () => { @@ -41,23 +39,22 @@ describe('', () => { , ); - ['fade', 'toast', 'show'].map( - (className) => - container.firstElementChild!.classList.contains(className).should.be - .true, + + ['fade', 'toast', 'show'].map((className) => + expect(container.firstElementChild!.classList).toContain(className), ); + ( [ ['role', 'alert'], ['aria-live', 'assertive'], - ['aria-atomic', true], + ['aria-atomic', 'true'], ] as const - ).map( - ([attrName, attrVal]) => - ( - container.firstElementChild!.attributes.getNamedItem(attrName)! - .textContent === `${attrVal}` - ).should.be.true, + ).map(([attrName, attrVal]) => + expect( + container.firstElementChild!.attributes.getNamedItem(attrName)! + .textContent, + ).toEqual(attrVal), ); }); @@ -69,15 +66,13 @@ describe('', () => { , ); - ['toast', 'show'].map( - (className) => - container.firstElementChild!.classList.contains(className).should.be - .true, + ['toast', 'show'].map((className) => + expect(container.firstElementChild!.classList).toContain(className), ); }); it('should trigger the onClose event after clicking on the close button', () => { - const onCloseSpy = sinon.spy(); + const onCloseSpy = vi.fn(); const { container } = render( @@ -88,35 +83,35 @@ describe('', () => { fireEvent.click( container.firstElementChild!.getElementsByTagName('button')[0], ); - onCloseSpy.should.have.been.calledOnce; + expect(onCloseSpy).toHaveBeenCalledOnce(); }); it('should trigger the onClose event after the autohide delay', () => { - const onCloseSpy = sinon.spy(); + const onCloseSpy = vi.fn(); render( header-content body-content , ); - clock.tick(1000); - onCloseSpy.should.have.been.calledOnce; + clock.advanceTimersByTime(1000); + expect(onCloseSpy).toHaveBeenCalledOnce(); }); it('should not trigger the onClose event if autohide is not set', () => { - const onCloseSpy = sinon.spy(); + const onCloseSpy = vi.fn(); render( header-content body-content , ); - clock.tick(3000); - onCloseSpy.should.not.to.have.been.called; + clock.advanceTimersByTime(3000); + expect(onCloseSpy).not.toHaveBeenCalled(); }); it('should clearTimeout after unmount', () => { - const onCloseSpy = sinon.spy(); + const onCloseSpy = vi.fn(); const { unmount } = render( header-content @@ -124,78 +119,78 @@ describe('', () => { , ); unmount(); - clock.tick(1000); - onCloseSpy.should.not.to.have.been.called; + clock.advanceTimersByTime(1000); + expect(onCloseSpy).not.toHaveBeenCalled(); }); it('should not reset autohide timer when element re-renders with same props', () => { - const onCloseSpy = sinon.spy(); + const onCloseSpy = vi.fn(); const toast = getToast({ onCloseSpy }); const { rerender } = render(toast); - clock.tick(250); + clock.advanceTimersByTime(250); // Trigger render with no props changes. rerender(toast); - clock.tick(300); - onCloseSpy.should.have.been.calledOnce; + clock.advanceTimersByTime(300); + expect(onCloseSpy).toHaveBeenCalledOnce(); }); it('should not reset autohide timer when delay is changed', () => { - const onCloseSpy = sinon.spy(); + const onCloseSpy = vi.fn(); const { rerender } = render(getToast({ delay: 500, onCloseSpy })); - clock.tick(250); + clock.advanceTimersByTime(250); rerender(getToast({ delay: 10000, onCloseSpy })); - clock.tick(300); - onCloseSpy.should.have.been.calledOnce; + clock.advanceTimersByTime(300); + expect(onCloseSpy).toHaveBeenCalledOnce(); }); it('should not reset autohide timer when onClosed is changed', () => { - const onCloseSpy = sinon.spy(); - const onCloseSpy2 = sinon.spy(); + const onCloseSpy = vi.fn(); + const onCloseSpy2 = vi.fn(); const { rerender } = render(getToast({ onCloseSpy })); - clock.tick(250); + clock.advanceTimersByTime(250); rerender(getToast({ onCloseSpy: onCloseSpy2 })); - clock.tick(300); - onCloseSpy.should.not.to.have.been.called; - onCloseSpy2.should.have.been.calledOnce; + clock.advanceTimersByTime(300); + expect(onCloseSpy).not.toHaveBeenCalled(); + expect(onCloseSpy2).toHaveBeenCalledOnce(); }); it('should not call onClose if autohide is changed from true to false', () => { - const onCloseSpy = sinon.spy(); + const onCloseSpy = vi.fn(); const { rerender } = render(getToast({ onCloseSpy, autohide: true })); - clock.tick(250); + clock.advanceTimersByTime(250); rerender(getToast({ onCloseSpy, autohide: false })); - clock.tick(300); - onCloseSpy.should.not.to.have.been.called; + clock.advanceTimersByTime(300); + expect(onCloseSpy).not.toHaveBeenCalled(); }); it('should not call onClose if show is changed from true to false', () => { - const onCloseSpy = sinon.spy(); + const onCloseSpy = vi.fn(); const { rerender } = render(getToast({ show: true, onCloseSpy })); act(() => { - clock.tick(100); + clock.advanceTimersByTime(100); }); rerender(getToast({ show: false, onCloseSpy })); act(() => { - clock.tick(300); + clock.advanceTimersByTime(300); }); - onCloseSpy.should.not.to.have.been.called; + expect(onCloseSpy).not.toHaveBeenCalled(); }); it('should render with bsPrefix', () => { @@ -205,12 +200,12 @@ describe('', () => { , ); - container.firstElementChild!.tagName.toLowerCase().should.equal('div'); - container.firstElementChild!.classList.contains('my-toast'); + expect(container.firstElementChild!.tagName).toEqual('DIV'); + expect(container.firstElementChild!.classList).toContain('my-toast'); }); - it('Should pass transition callbacks to Transition', (done) => { - const increment = sinon.spy(); + it('Should pass transition callbacks to Transition', () => { + const increment = vi.fn(); const Elem = () => { const [show, setShow] = React.useState(false); @@ -229,11 +224,7 @@ describe('', () => { }} onExit={increment} onExiting={increment} - onExited={() => { - increment(); - expect(increment.callCount).to.equal(6); - done(); - }} + onExited={increment} > Body @@ -244,12 +235,14 @@ describe('', () => { render(); act(() => { - clock.tick(250); + clock.advanceTimersByTime(250); }); // Trigger onExit. act(() => { - clock.tick(250); + clock.advanceTimersByTime(250); }); + + expect(increment).toHaveBeenCalledTimes(6); }); }); diff --git a/test/ToggleButtonGroupSpec.tsx b/test/ToggleButtonGroupSpec.tsx index 3f1804ffbb..19a08c2736 100644 --- a/test/ToggleButtonGroupSpec.tsx +++ b/test/ToggleButtonGroupSpec.tsx @@ -1,11 +1,10 @@ -import { render, fireEvent } from '@testing-library/react'; -import sinon from 'sinon'; - +import { describe, expect, it, vi } from 'vitest'; +import { fireEvent, render, screen } from '@testing-library/react'; import ToggleButtonGroup from '../src/ToggleButtonGroup'; describe('ToggleButtonGroup', () => { it('should render checkboxes', () => { - const { container, getByLabelText } = render( + const { container } = render( Option 1 @@ -19,12 +18,18 @@ describe('ToggleButtonGroup', () => { , ); - container.firstElementChild!.classList.length.should.equal(1); - container.firstElementChild!.classList.contains('btn-group').should.be.true; + expect(container.firstElementChild!.classList.length).toEqual(1); + expect(container.firstElementChild!.classList).toContain('btn-group'); - getByLabelText('Option 1')!.getAttribute('type')!.should.equal('checkbox'); - getByLabelText('Option 2')!.getAttribute('type')!.should.equal('checkbox'); - getByLabelText('Option 3')!.getAttribute('type')!.should.equal('checkbox'); + expect(screen.getByLabelText('Option 1')!.getAttribute('type')!).toEqual( + 'checkbox', + ); + expect(screen.getByLabelText('Option 2')!.getAttribute('type')!).toEqual( + 'checkbox', + ); + expect(screen.getByLabelText('Option 3')!.getAttribute('type')!).toEqual( + 'checkbox', + ); }); it('should render checkboxes vertically', () => { @@ -42,9 +47,10 @@ describe('ToggleButtonGroup', () => { , ); - container.firstElementChild!.classList.length.should.equal(1); - container.firstElementChild!.classList.contains('btn-group-vertical').should - .be.true; + expect(container.firstElementChild!.classList.length).toEqual(1); + expect(container.firstElementChild!.classList).toContain( + 'btn-group-vertical', + ); }); it('should render checkboxes vertically and small', () => { @@ -62,11 +68,11 @@ describe('ToggleButtonGroup', () => { , ); - container.firstElementChild!.classList.length.should.equal(2); - container.firstElementChild!.classList.contains('btn-group-vertical').should - .be.true; - container.firstElementChild!.classList.contains('btn-group-sm').should.be - .true; + expect(container.firstElementChild!.classList.length).toEqual(2); + expect(container.firstElementChild!.classList).toContain( + 'btn-group-vertical', + ); + expect(container.firstElementChild!.classList).toContain('btn-group-sm'); }); it('should render checkboxes vertically and large', () => { @@ -84,15 +90,15 @@ describe('ToggleButtonGroup', () => { , ); - container.firstElementChild!.classList.length.should.equal(2); - container.firstElementChild!.classList.contains('btn-group-vertical').should - .be.true; - container.firstElementChild!.classList.contains('btn-group-lg').should.be - .true; + expect(container.firstElementChild!.classList.length).toEqual(2); + expect(container.firstElementChild!.classList).toContain( + 'btn-group-vertical', + ); + expect(container.firstElementChild!.classList).toContain('btn-group-lg'); }); it('should render radios', () => { - const { container, getByLabelText } = render( + const { container } = render( Option 1 @@ -106,12 +112,18 @@ describe('ToggleButtonGroup', () => { , ); - container.firstElementChild!.classList.length.should.equal(1); - container.firstElementChild!.classList.contains('btn-group').should.be.true; + expect(container.firstElementChild!.classList.length).toEqual(1); + expect(container.firstElementChild!.classList).toContain('btn-group'); - getByLabelText('Option 1')!.getAttribute('type')!.should.equal('radio'); - getByLabelText('Option 2')!.getAttribute('type')!.should.equal('radio'); - getByLabelText('Option 3')!.getAttribute('type')!.should.equal('radio'); + expect(screen.getByLabelText('Option 1')!.getAttribute('type')).toEqual( + 'radio', + ); + expect(screen.getByLabelText('Option 2')!.getAttribute('type')).toEqual( + 'radio', + ); + expect(screen.getByLabelText('Option 3')!.getAttribute('type')).toEqual( + 'radio', + ); }); it('should render radios vertically', () => { @@ -129,9 +141,10 @@ describe('ToggleButtonGroup', () => { , ); - container.firstElementChild!.classList.length.should.equal(1); - container.firstElementChild!.classList.contains('btn-group-vertical').should - .be.true; + expect(container.firstElementChild!.classList.length).toEqual(1); + expect(container.firstElementChild!.classList).toContain( + 'btn-group-vertical', + ); }); it('should render radios vertically and small', () => { @@ -149,11 +162,11 @@ describe('ToggleButtonGroup', () => { , ); - container.firstElementChild!.classList.length.should.equal(2); - container.firstElementChild!.classList.contains('btn-group-vertical').should - .be.true; - container.firstElementChild!.classList.contains('btn-group-sm').should.be - .true; + expect(container.firstElementChild!.classList.length).toEqual(2); + expect(container.firstElementChild!.classList).toContain( + 'btn-group-vertical', + ); + expect(container.firstElementChild!.classList).toContain('btn-group-sm'); }); it('should render radios vertically and large', () => { @@ -171,15 +184,15 @@ describe('ToggleButtonGroup', () => { , ); - container.firstElementChild!.classList.length.should.equal(2); - container.firstElementChild!.classList.contains('btn-group-vertical').should - .be.true; - container.firstElementChild!.classList.contains('btn-group-lg').should.be - .true; + expect(container.firstElementChild!.classList.length).toEqual(2); + expect(container.firstElementChild!.classList).toContain( + 'btn-group-vertical', + ); + expect(container.firstElementChild!.classList).toContain('btn-group-lg'); }); it('should select initial values', () => { - const { getByLabelText } = render( + render( Option 1 @@ -193,13 +206,19 @@ describe('ToggleButtonGroup', () => { , ); - (getByLabelText('Option 1') as HTMLInputElement)!.checked.should.be.true; - (getByLabelText('Option 2') as HTMLInputElement)!.checked.should.be.false; - (getByLabelText('Option 3') as HTMLInputElement)!.checked.should.be.true; + expect( + (screen.getByLabelText('Option 1') as HTMLInputElement)!.checked, + ).toEqual(true); + expect( + (screen.getByLabelText('Option 2') as HTMLInputElement)!.checked, + ).toEqual(false); + expect( + (screen.getByLabelText('Option 3') as HTMLInputElement)!.checked, + ).toEqual(true); }); it('should disable radios', () => { - const { getByText, getByLabelText } = render( + render( Option 1 @@ -213,18 +232,25 @@ describe('ToggleButtonGroup', () => { , ); - (getByLabelText('Option 1') as HTMLInputElement)!.disabled.should.be.true; - (getByLabelText('Option 2') as HTMLInputElement)!.disabled.should.be.true; - (getByLabelText('Option 3') as HTMLInputElement)!.disabled.should.be.false; + expect( + (screen.getByLabelText('Option 1') as HTMLInputElement)!.disabled, + ).toEqual(true); + expect( + (screen.getByLabelText('Option 2') as HTMLInputElement)!.disabled, + ).toEqual(true); + expect( + (screen.getByLabelText('Option 3') as HTMLInputElement)!.disabled, + ).toEqual(false); + + expect(screen.getByText('Option 1').classList).toContain('disabled'); - getByText('Option 1').classList.contains('disabled').should.be.true; - getByText('Option 2').classList.contains('disabled').should.be.true; - getByText('Option 3').classList.contains('disabled').should.be.false; + expect(screen.getByText('Option 2').classList).toContain('disabled'); + expect(screen.getByText('Option 3').classList).not.toContain('disabled'); }); it('should return an array of values', () => { - const spy = sinon.spy(); - const { getByLabelText } = render( + const spy = vi.fn(); + render( Option 1 @@ -238,13 +264,13 @@ describe('ToggleButtonGroup', () => { , ); - fireEvent.click(getByLabelText('Option 2')); - spy.should.have.been.calledWith([2]); + fireEvent.click(screen.getByLabelText('Option 2')); + expect(spy).toHaveBeenCalledWith([2], expect.anything()); }); it('should return a single value', () => { - const spy = sinon.spy(); - const { getByLabelText } = render( + const spy = vi.fn(); + render( Option 1 @@ -258,13 +284,13 @@ describe('ToggleButtonGroup', () => { , ); - fireEvent.click(getByLabelText('Option 2')); - spy.should.have.been.calledWith(2); + fireEvent.click(screen.getByLabelText('Option 2')); + expect(spy).toHaveBeenCalledWith(2, expect.anything()); }); it('should filter out value when deselected', () => { - const spy = sinon.spy(); - const { getByLabelText } = render( + const spy = vi.fn(); + render( { , ); - fireEvent.click(getByLabelText('Option 1')); - spy.should.have.been.calledWith([2]); + fireEvent.click(screen.getByLabelText('Option 1')); + expect(spy).toHaveBeenCalledWith([2], expect.anything()); }); }); diff --git a/test/ToggleButtonSpec.tsx b/test/ToggleButtonSpec.tsx index 072700142b..a900e95626 100644 --- a/test/ToggleButtonSpec.tsx +++ b/test/ToggleButtonSpec.tsx @@ -1,7 +1,6 @@ import * as React from 'react'; -import { render } from '@testing-library/react'; -import { expect } from 'chai'; - +import { describe, expect, it } from 'vitest'; +import { render, screen } from '@testing-library/react'; import ToggleButton from '../src/ToggleButton'; describe('ToggleButton', () => { @@ -13,7 +12,7 @@ describe('ToggleButton', () => { , ); - ref.current!.tagName.should.equal('LABEL'); + expect(ref.current!.tagName).toEqual('LABEL'); }); it('should add an inputRef', () => { @@ -24,16 +23,16 @@ describe('ToggleButton', () => { , ); - ref.current!.tagName.should.equal('INPUT'); + expect(ref.current!.tagName).toEqual('INPUT'); }); it('should not have a role on the label button', () => { - const { getByText } = render( + render( Option , ); - expect(getByText('Option').getAttribute('role')).to.not.exist; + expect(screen.getByText('Option').getAttribute('role')).not.toBeTruthy(); }); }); diff --git a/test/TooltipSpec.tsx b/test/TooltipSpec.tsx index 8dac76615e..52945b946a 100644 --- a/test/TooltipSpec.tsx +++ b/test/TooltipSpec.tsx @@ -1,21 +1,21 @@ -import { render } from '@testing-library/react'; +import { describe, expect, it } from 'vitest'; +import { render, screen } from '@testing-library/react'; import Tooltip from '../src/Tooltip'; describe('Tooltip', () => { it('Should output a tooltip with content', () => { - const { getByTestId } = render( + render( Tooltip Content , ); - getByTestId('test-tooltip').classList.should.contains([ - 'tooltip', - 'bs-tooltip-end', - ]); + const classList = screen.getByTestId('test-tooltip').classList; + expect(classList).toContain('tooltip'); + expect(classList).toContain('bs-tooltip-end'); - getByTestId('test-tooltip') - .getAttribute('x-placement')! - .should.equal('right'); + expect( + screen.getByTestId('test-tooltip').getAttribute('x-placement')!, + ).toEqual('right'); }); }); diff --git a/test/createChainedFunctionSpec.ts b/test/createChainedFunctionSpec.ts index daa5684a6c..6075429368 100644 --- a/test/createChainedFunctionSpec.ts +++ b/test/createChainedFunctionSpec.ts @@ -1,32 +1,32 @@ /* eslint-disable no-new-func */ -import { expect } from 'chai'; -import sinon from 'sinon'; +import { describe, expect, it, vi } from 'vitest'; import createChainedFunction from '../src/createChainedFunction'; describe('createChainedFunction', () => { it('returns null with no arguments', () => { - expect(createChainedFunction()).to.equal(null); + expect(createChainedFunction()).toEqual(null); }); it('returns original function when single function is provided', () => { - const func1 = sinon.stub(); - createChainedFunction(func1).should.equal(func1); + const func1 = vi.fn(); + expect(createChainedFunction(func1)).toEqual(func1); }); it('wraps two functions with another that invokes both when called', () => { - const func1 = sinon.stub(); - const func2 = sinon.stub(); + const func1 = vi.fn(); + const func2 = vi.fn(); const chained = createChainedFunction(func1, func2); - chained.should.not.equal(func1).and.should.not.equal(func2); + expect(chained).not.toEqual(func1); + expect(chained).not.toEqual(func2); - func1.should.not.have.been.called; - func2.should.not.have.been.called; + expect(func1).not.toHaveBeenCalled(); + expect(func2).not.toHaveBeenCalled(); chained(); - func1.should.have.been.calledOnce; - func2.should.have.been.calledOnce; + expect(func1).toHaveBeenCalledOnce(); + expect(func2).toHaveBeenCalledOnce(); }); it('wraps multiple functions and invokes them in the order provided', () => { @@ -36,7 +36,7 @@ describe('createChainedFunction', () => { const func3 = () => results.push(3); const chained = createChainedFunction(func1, func2, func3); chained(); - results.should.eql([1, 2, 3]); + expect(results).toEqual([1, 2, 3]); }); it('forwards arguments to all chained functions', () => { @@ -46,8 +46,8 @@ describe('createChainedFunction', () => { }; const func = (arg1: any, arg2: any) => { - arg1.should.equal(in1); - arg2.should.equal(in2); + expect(arg1).toEqual(in1); + expect(arg2).toEqual(in2); }; const chained = createChainedFunction(func, func, func); @@ -57,7 +57,7 @@ describe('createChainedFunction', () => { it('throws when func is not provided', () => { expect(() => { createChainedFunction({ herpa: 'derpa' }); - }).to.throw(/Invalid Argument Type/); + }).toThrow(/Invalid Argument Type/); }); it('works with new Function call', () => { @@ -66,6 +66,6 @@ describe('createChainedFunction', () => { const func2 = new Function('results', 'results.push(2);'); const chained = createChainedFunction(func1, func2); chained(results); - results.should.eql([1, 2]); + expect(results).toEqual([1, 2]); }); }); diff --git a/test/createUtilityClassesSpec.ts b/test/createUtilityClassesSpec.ts index f41597d5e9..968b56e606 100644 --- a/test/createUtilityClassesSpec.ts +++ b/test/createUtilityClassesSpec.ts @@ -1,3 +1,4 @@ +import { describe, expect, it } from 'vitest'; import createUtilityClasses from '../src/createUtilityClasses'; describe('createUtilityClassName', () => { @@ -6,7 +7,7 @@ describe('createUtilityClassName', () => { gap: undefined, }); - classList.length.should.equal(0); + expect(classList).toHaveLength(0); }); it('should handle falsy values', () => { @@ -14,8 +15,8 @@ describe('createUtilityClassName', () => { gap: 0, }); - classList.length.should.equal(1); - classList.should.include.all.members(['gap-0']); + expect(classList).toHaveLength(1); + expect(classList).toEqual(expect.arrayContaining(['gap-0'])); }); it('should handle responsive falsy values', () => { @@ -23,8 +24,8 @@ describe('createUtilityClassName', () => { gap: { xs: 0, md: 0 }, }); - classList.length.should.equal(2); - classList.should.include.all.members(['gap-0', 'gap-md-0']); + expect(classList).toHaveLength(2); + expect(classList).toEqual(expect.arrayContaining(['gap-0', 'gap-md-0'])); }); it('should return `utilityName-value` when value is a primitive', () => { @@ -32,8 +33,8 @@ describe('createUtilityClassName', () => { gap: 2, }); - classList.length.should.equal(1); - classList.should.include.all.members(['gap-2']); + expect(classList).toHaveLength(1); + expect(classList).toEqual(expect.arrayContaining(['gap-2'])); }); it('should return responsive class when value is a responsive type', () => { @@ -41,8 +42,10 @@ describe('createUtilityClassName', () => { gap: { xs: 2, lg: 3, xxl: 4 }, }); - classList.length.should.equal(3); - classList.should.include.all.members(['gap-2', 'gap-lg-3', 'gap-xxl-4']); + expect(classList).toHaveLength(3); + expect(classList).toEqual( + expect.arrayContaining(['gap-2', 'gap-lg-3', 'gap-xxl-4']), + ); }); it('should return multiple classes', () => { @@ -51,15 +54,17 @@ describe('createUtilityClassName', () => { text: { xs: 'start', md: 'end', xl: 'start' }, }); - classList.length.should.equal(6); - classList.should.include.all.members([ - 'gap-2', - 'gap-lg-3', - 'gap-xxl-4', - 'text-start', - 'text-md-end', - 'text-xl-start', - ]); + expect(classList).toHaveLength(6); + expect(classList).toEqual( + expect.arrayContaining([ + 'gap-2', + 'gap-lg-3', + 'gap-xxl-4', + 'text-start', + 'text-md-end', + 'text-xl-start', + ]), + ); }); it('should handle custom breakpoints', () => { @@ -70,7 +75,9 @@ describe('createUtilityClassName', () => { ['xs', 'custom'], ); - classList.length.should.equal(2); - classList.should.include.all.members(['gap-2', 'gap-custom-3']); + expect(classList).toHaveLength(2); + expect(classList).toEqual( + expect.arrayContaining(['gap-2', 'gap-custom-3']), + ); }); }); diff --git a/test/getInitialPopperStylesSpec.ts b/test/getInitialPopperStylesSpec.ts index 8d6ca13382..00a698fe6c 100644 --- a/test/getInitialPopperStylesSpec.ts +++ b/test/getInitialPopperStylesSpec.ts @@ -1,9 +1,9 @@ -import { expect } from 'chai'; +import { describe, expect, it } from 'vitest'; import getInitialPopperStyles from '../src/getInitialPopperStyles'; describe('getInitialPopperStyles', () => { it('defaults to absolute positioning when no strategy is provided', () => { - expect(getInitialPopperStyles()).to.eql({ + expect(getInitialPopperStyles()).toEqual({ position: 'absolute', top: '0', left: '0', @@ -13,7 +13,7 @@ describe('getInitialPopperStyles', () => { }); it('sets the position to the provided strategy', () => { - expect(getInitialPopperStyles('fixed')).to.eql({ + expect(getInitialPopperStyles('fixed')).toEqual({ position: 'fixed', top: '0', left: '0', diff --git a/test/helpers.js b/test/helpers.ts similarity index 67% rename from test/helpers.js rename to test/helpers.ts index 345bac2ae2..edf887abb6 100644 --- a/test/helpers.js +++ b/test/helpers.ts @@ -1,11 +1,8 @@ -export function shouldWarn(about) { - console.error.expected.push(about); -} - -let style; -let seen = []; +let style: any; +let seen: string[] = []; -export function injectCss(rules) { +// eslint-disable-next-line import/prefer-default-export +export function injectCss(rules: string) { if (seen.indexOf(rules) !== -1) { return; } @@ -13,7 +10,7 @@ export function injectCss(rules) { style = style || (function iife() { - let _style = document.createElement('style'); + const _style = document.createElement('style'); _style.appendChild(document.createTextNode('')); document.head.appendChild(_style); return _style; diff --git a/test/helpersSpec.ts b/test/helpersSpec.ts index cc6778e0d3..4ee697983a 100644 --- a/test/helpersSpec.ts +++ b/test/helpersSpec.ts @@ -1,21 +1,22 @@ +import { describe, expect, it } from 'vitest'; import { getOverlayDirection } from '../src/helpers'; describe('Helpers', () => { describe('getOverlayDirection', () => { it('should return start for left', () => { - getOverlayDirection('left', false).should.equal('start'); + expect(getOverlayDirection('left', false)).toEqual('start'); }); it('should return end for left in RTL', () => { - getOverlayDirection('left', true).should.equal('end'); + expect(getOverlayDirection('left', true)).toEqual('end'); }); it('should return end for right', () => { - getOverlayDirection('right', false).should.equal('end'); + expect(getOverlayDirection('right', false)).toEqual('end'); }); it('should return start for right in RTL', () => { - getOverlayDirection('right', true).should.equal('start'); + expect(getOverlayDirection('right', true)).toEqual('start'); }); }); }); diff --git a/test/index.js b/test/index.js deleted file mode 100644 index eaa267d891..0000000000 --- a/test/index.js +++ /dev/null @@ -1,63 +0,0 @@ -import deprecated from 'prop-types-extra/lib/deprecated'; -import Util from 'util'; - -// Resolves "Error: Warning: The current testing environment is not configured to support act(...)" -global.IS_REACT_ACT_ENVIRONMENT = true; - -beforeEach(() => { - sinon.stub(console, 'error').callsFake((msg, ...args) => { - let expected = false; - - // When using the new JSX transform, React uses a different checkPropTypes - // function that exists within react-jsx-dev-runtime.development.js that - // sends in a string message with args. In contrast, without the JSX transform, - // React (react.development.js) uses checkPropTypes from the prop-types package - // and this formats the string prior to calling console.error. - // We're going to need to format the string ourselves and check it. - let formattedStr = msg; - if (args.length) { - formattedStr = Util.format(msg, ...args); - } - - console.error.expected.forEach((about) => { - if (formattedStr.indexOf(about) !== -1) { - console.error.warned[about] = true; - expected = true; - } - }); - - if (expected) { - return; - } - - console.error.threw = true; - throw new Error(formattedStr); - }); - - console.error.expected = []; - console.error.warned = Object.create(null); - console.error.threw = false; -}); - -afterEach(() => { - if (!console.error.threw && console.error.expected.length) { - expect(console.error.warned).to.have.keys(console.error.expected); - } - - console.error.restore(); - - deprecated._resetWarned(); -}); - -describe('Process environment for tests', () => { - it('should not be production for React console warnings', () => { - expect(process.env.NODE_ENV).to.not.equal('production'); - }); -}); - -// Ensure all files in src folder are loaded for proper code coverage analysis. -const srcContext = require.context('../src', true, /.*\.js$/); -srcContext.keys().forEach(srcContext); - -const testsContext = require.context('.', true, /Spec$/); -testsContext.keys().forEach(testsContext); diff --git a/test/tsconfig.json b/test/tsconfig.json index 70f09e08ca..8a30a39fc7 100644 --- a/test/tsconfig.json +++ b/test/tsconfig.json @@ -2,7 +2,7 @@ "extends": "..", "compilerOptions": { "jsx": "react-jsx", - "types": ["mocha", "chai", "sinon", "sinon-chai"], + "lib": ["DOM", "ESNext"], "rootDir": ".." }, "include": ["../src", ".", "../tests"] diff --git a/test/useOverlayOffsetSpec.tsx b/test/useOverlayOffsetSpec.tsx index de107ab3e5..89d901ee84 100644 --- a/test/useOverlayOffsetSpec.tsx +++ b/test/useOverlayOffsetSpec.tsx @@ -1,8 +1,7 @@ import * as React from 'react'; +import { describe, expect, it } from 'vitest'; import { useImperativeHandle } from 'react'; import { render } from '@testing-library/react'; -import { expect } from 'chai'; - import { Offset } from '@restart/ui/usePopper'; import Popover from '../src/Popover'; import Tooltip from '../src/Tooltip'; @@ -34,7 +33,7 @@ describe('useOverlayOffset', () => { ); const offset = ref.current.modifiers[0].options.offset(); - expect(offset).to.eql([0, 8]); + expect(offset).toEqual([0, 8]); }); it('should apply custom offset', () => { @@ -47,7 +46,7 @@ describe('useOverlayOffset', () => { ); const offset = ref.current.modifiers[0].options.offset(); - expect(offset).to.eql([200, 200]); + expect(offset).toEqual([200, 200]); }); it('should have offset of [0, 6] for Tooltips', () => { @@ -60,7 +59,7 @@ describe('useOverlayOffset', () => { ); const offset = ref.current.modifiers[0].options.offset(); - expect(offset).to.eql([0, 6]); + expect(offset).toEqual([0, 6]); }); it('should have offset of [0, 0] for any overlay', () => { @@ -73,6 +72,6 @@ describe('useOverlayOffset', () => { ); const offset = ref.current.modifiers[0].options.offset(); - expect(offset).to.eql([0, 0]); + expect(offset).toEqual([0, 0]); }); }); diff --git a/vitest.config.ts b/vitest.config.ts new file mode 100644 index 0000000000..bb4ea4990d --- /dev/null +++ b/vitest.config.ts @@ -0,0 +1,21 @@ +import { defineConfig } from 'vitest/config'; +import react from '@vitejs/plugin-react'; + +export default defineConfig({ + define: { + // eslint-disable-next-line @typescript-eslint/naming-convention + __DEV__: true, + }, + plugins: [react()], + test: { + include: ['test/**/*Spec.ts', 'test/**/*Spec.tsx'], + setupFiles: ['vitest.setup.ts'], + browser: { + enabled: true, + name: 'chromium', + provider: 'playwright', + // https://playwright.dev + providerOptions: {}, + }, + }, +}); diff --git a/vitest.setup.ts b/vitest.setup.ts new file mode 100644 index 0000000000..e01cebc1b7 --- /dev/null +++ b/vitest.setup.ts @@ -0,0 +1,4 @@ +import { cleanup } from '@testing-library/react'; +import { afterEach } from 'vitest'; + +afterEach(cleanup); diff --git a/yarn.lock b/yarn.lock index 991ae68f03..0ef353ec9a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -65,7 +65,7 @@ resolved "https://registry.yarnpkg.com/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz#bd9154aec9983f77b3a034ecaa015c2e4201f6cf" integrity sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA== -"@ampproject/remapping@^2.2.0": +"@ampproject/remapping@^2.2.0", "@ampproject/remapping@^2.3.0": version "2.3.0" resolved "https://registry.yarnpkg.com/@ampproject/remapping/-/remapping-2.3.0.tgz#ed441b6fa600072520ce18b43d2c8cc8caecc7f4" integrity sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw== @@ -97,11 +97,24 @@ "@babel/highlight" "^7.23.4" chalk "^2.4.2" +"@babel/code-frame@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.24.7.tgz#882fd9e09e8ee324e496bd040401c6f046ef4465" + integrity sha512-BcYH1CVJBO9tvyIZ2jVeXgSIMvGZ2FDRvDdOIVQyuklNKSsx+eppDEBq/g47Ayw+RqNFE+URvOShmf+f/qwAlA== + dependencies: + "@babel/highlight" "^7.24.7" + picocolors "^1.0.0" + "@babel/compat-data@^7.22.6", "@babel/compat-data@^7.23.5": version "7.23.5" resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.23.5.tgz#ffb878728bb6bdcb6f4510aa51b1be9afb8cfd98" integrity sha512-uU27kfDRlhfKl+w1U6vp16IuvSLtjAxdArVXPa9BvLkrr7CYIsxH5adpHObeAGY/41+syctUWOZ140a2Rvkgjw== +"@babel/compat-data@^7.24.8": + version "7.24.9" + resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.24.9.tgz#53eee4e68f1c1d0282aa0eb05ddb02d033fc43a0" + integrity sha512-e701mcfApCJqMMueQI0Fb68Amflj83+dvAvHawoBpAz+GDjCIyGHzNwnefjsWJ3xiYAqqiQFoWbspGYBdb2/ng== + "@babel/core@^7.12.10", "@babel/core@^7.12.3", "@babel/core@^7.13.8", "@babel/core@^7.23.5": version "7.24.0" resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.24.0.tgz#56cbda6b185ae9d9bed369816a8f4423c5f2ff1b" @@ -123,6 +136,27 @@ json5 "^2.2.3" semver "^6.3.1" +"@babel/core@^7.24.5": + version "7.24.9" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.24.9.tgz#dc07c9d307162c97fa9484ea997ade65841c7c82" + integrity sha512-5e3FI4Q3M3Pbr21+5xJwCv6ZT6KmGkI0vw3Tozy5ODAQFTIWe37iT8Cr7Ice2Ntb+M3iSKCEWMB1MBgKrW3whg== + dependencies: + "@ampproject/remapping" "^2.2.0" + "@babel/code-frame" "^7.24.7" + "@babel/generator" "^7.24.9" + "@babel/helper-compilation-targets" "^7.24.8" + "@babel/helper-module-transforms" "^7.24.9" + "@babel/helpers" "^7.24.8" + "@babel/parser" "^7.24.8" + "@babel/template" "^7.24.7" + "@babel/traverse" "^7.24.8" + "@babel/types" "^7.24.9" + convert-source-map "^2.0.0" + debug "^4.1.0" + gensync "^1.0.0-beta.2" + json5 "^2.2.3" + semver "^6.3.1" + "@babel/eslint-parser@^7.18.9", "@babel/eslint-parser@^7.22.5": version "7.23.10" resolved "https://registry.yarnpkg.com/@babel/eslint-parser/-/eslint-parser-7.23.10.tgz#2d4164842d6db798873b40e0c4238827084667a2" @@ -151,6 +185,16 @@ "@jridgewell/trace-mapping" "^0.3.17" jsesc "^2.5.1" +"@babel/generator@^7.24.8", "@babel/generator@^7.24.9": + version "7.24.10" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.24.10.tgz#a4ab681ec2a78bbb9ba22a3941195e28a81d8e76" + integrity sha512-o9HBZL1G2129luEUlG1hB4N/nlYNWHnpwlND9eOMclRqqu1YDy2sSYVCFUZwl8I1Gxh+QSRrP2vD7EpUmFVXxg== + dependencies: + "@babel/types" "^7.24.9" + "@jridgewell/gen-mapping" "^0.3.5" + "@jridgewell/trace-mapping" "^0.3.25" + jsesc "^2.5.1" + "@babel/helper-annotate-as-pure@^7.22.5": version "7.22.5" resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.22.5.tgz#e7f06737b197d580a01edf75d97e2c8be99d3882" @@ -176,6 +220,17 @@ lru-cache "^5.1.1" semver "^6.3.1" +"@babel/helper-compilation-targets@^7.24.8": + version "7.24.8" + resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.24.8.tgz#b607c3161cd9d1744977d4f97139572fe778c271" + integrity sha512-oU+UoqCHdp+nWVDkpldqIQL/i/bvAv53tRqLG/s+cOXxe66zOYLU7ar/Xs3LdmBihrUMEUhwu6dMZwbNOYDwvw== + dependencies: + "@babel/compat-data" "^7.24.8" + "@babel/helper-validator-option" "^7.24.8" + browserslist "^4.23.1" + lru-cache "^5.1.1" + semver "^6.3.1" + "@babel/helper-create-class-features-plugin@^7.18.6", "@babel/helper-create-class-features-plugin@^7.22.15", "@babel/helper-create-class-features-plugin@^7.23.6": version "7.24.0" resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.24.0.tgz#fc7554141bdbfa2d17f7b4b80153b9b090e5d158" @@ -241,6 +296,13 @@ resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz#96159db61d34a29dba454c959f5ae4a649ba9167" integrity sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA== +"@babel/helper-environment-visitor@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.24.7.tgz#4b31ba9551d1f90781ba83491dd59cf9b269f7d9" + integrity sha512-DoiN84+4Gnd0ncbBOM9AZENV4a5ZiL39HYMyZJGZ/AZEykHYdJw0wW3kdcsh9/Kn+BRXHLkkklZ51ecPKmI1CQ== + dependencies: + "@babel/types" "^7.24.7" + "@babel/helper-function-name@^7.22.5", "@babel/helper-function-name@^7.23.0": version "7.23.0" resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz#1f9a3cdbd5b2698a670c30d2735f9af95ed52759" @@ -249,6 +311,14 @@ "@babel/template" "^7.22.15" "@babel/types" "^7.23.0" +"@babel/helper-function-name@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.24.7.tgz#75f1e1725742f39ac6584ee0b16d94513da38dd2" + integrity sha512-FyoJTsj/PEUWu1/TYRiXTIHc8lbw+TDYkZuoE43opPS5TrI7MyONBE1oNvfguEXAD9yhQRrVBnXdXzSLQl9XnA== + dependencies: + "@babel/template" "^7.24.7" + "@babel/types" "^7.24.7" + "@babel/helper-hoist-variables@^7.22.5": version "7.22.5" resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz#c01a007dac05c085914e8fb652b339db50d823bb" @@ -256,6 +326,13 @@ dependencies: "@babel/types" "^7.22.5" +"@babel/helper-hoist-variables@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.24.7.tgz#b4ede1cde2fd89436397f30dc9376ee06b0f25ee" + integrity sha512-MJJwhkoGy5c4ehfoRyrJ/owKeMl19U54h27YYftT0o2teQ3FJ3nQUf/I3LlJsX4l3qlw7WRXUmiyajvHXoTubQ== + dependencies: + "@babel/types" "^7.24.7" + "@babel/helper-member-expression-to-functions@^7.22.15", "@babel/helper-member-expression-to-functions@^7.23.0": version "7.23.0" resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.23.0.tgz#9263e88cc5e41d39ec18c9a3e0eced59a3e7d366" @@ -270,6 +347,14 @@ dependencies: "@babel/types" "^7.22.15" +"@babel/helper-module-imports@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.24.7.tgz#f2f980392de5b84c3328fc71d38bd81bbb83042b" + integrity sha512-8AyH3C+74cgCVVXow/myrynrAGv+nTVg5vKu2nZph9x7RcRwzmh0VFallJuFTZ9mx6u4eSdXZfcOzSqTUm0HCA== + dependencies: + "@babel/traverse" "^7.24.7" + "@babel/types" "^7.24.7" + "@babel/helper-module-transforms@^7.23.3": version "7.23.3" resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.23.3.tgz#d7d12c3c5d30af5b3c0fcab2a6d5217773e2d0f1" @@ -281,6 +366,17 @@ "@babel/helper-split-export-declaration" "^7.22.6" "@babel/helper-validator-identifier" "^7.22.20" +"@babel/helper-module-transforms@^7.24.9": + version "7.24.9" + resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.24.9.tgz#e13d26306b89eea569180868e652e7f514de9d29" + integrity sha512-oYbh+rtFKj/HwBQkFlUzvcybzklmVdVV3UU+mN7n2t/q3yGHbuVdNxyFvSBO1tfvjyArpHNcWMAzsSPdyI46hw== + dependencies: + "@babel/helper-environment-visitor" "^7.24.7" + "@babel/helper-module-imports" "^7.24.7" + "@babel/helper-simple-access" "^7.24.7" + "@babel/helper-split-export-declaration" "^7.24.7" + "@babel/helper-validator-identifier" "^7.24.7" + "@babel/helper-optimise-call-expression@^7.22.5": version "7.22.5" resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.22.5.tgz#f21531a9ccbff644fdd156b4077c16ff0c3f609e" @@ -293,6 +389,11 @@ resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.0.tgz#945681931a52f15ce879fd5b86ce2dae6d3d7f2a" integrity sha512-9cUznXMG0+FxRuJfvL82QlTqIzhVW9sL0KjMPHhAOOvpQGL8QtdxnBKILjBqxlHyliz0yCa1G903ZXI/FuHy2w== +"@babel/helper-plugin-utils@^7.24.7": + version "7.24.8" + resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.8.tgz#94ee67e8ec0e5d44ea7baeb51e571bd26af07878" + integrity sha512-FFWx5142D8h2Mgr/iPVGH5G7w6jDn4jUSpZTyDnQO0Yn7Ks2Kuz6Pci8H6MPCoUJegd/UZQ3tAvfLCxQSnWWwg== + "@babel/helper-remap-async-to-generator@^7.22.20": version "7.22.20" resolved "https://registry.yarnpkg.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.22.20.tgz#7b68e1cb4fa964d2996fd063723fb48eca8498e0" @@ -318,6 +419,14 @@ dependencies: "@babel/types" "^7.22.5" +"@babel/helper-simple-access@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.24.7.tgz#bcade8da3aec8ed16b9c4953b74e506b51b5edb3" + integrity sha512-zBAIvbCMh5Ts+b86r/CjU+4XGYIs+R1j951gxI3KmmxBMhCg4oQMsv6ZXQ64XOm/cvzfU1FmoCyt6+owc5QMYg== + dependencies: + "@babel/traverse" "^7.24.7" + "@babel/types" "^7.24.7" + "@babel/helper-skip-transparent-expression-wrappers@^7.22.5": version "7.22.5" resolved "https://registry.yarnpkg.com/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.22.5.tgz#007f15240b5751c537c40e77abb4e89eeaaa8847" @@ -332,21 +441,43 @@ dependencies: "@babel/types" "^7.22.5" +"@babel/helper-split-export-declaration@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.24.7.tgz#83949436890e07fa3d6873c61a96e3bbf692d856" + integrity sha512-oy5V7pD+UvfkEATUKvIjvIAH/xCzfsFVw7ygW2SI6NClZzquT+mwdTfgfdbUiceh6iQO0CHtCPsyze/MZ2YbAA== + dependencies: + "@babel/types" "^7.24.7" + "@babel/helper-string-parser@^7.23.4": version "7.23.4" resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.23.4.tgz#9478c707febcbbe1ddb38a3d91a2e054ae622d83" integrity sha512-803gmbQdqwdf4olxrX4AJyFBV/RTr3rSmOj0rKwesmzlfhYNDEs+/iOcznzpNWlJlIlTJC2QfPFcHB6DlzdVLQ== +"@babel/helper-string-parser@^7.24.8": + version "7.24.8" + resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.24.8.tgz#5b3329c9a58803d5df425e5785865881a81ca48d" + integrity sha512-pO9KhhRcuUyGnJWwyEgnRJTSIZHiT+vMD0kPeD+so0l7mxkMT19g3pjY9GTnHySck/hDzq+dtW/4VgnMkippsQ== + "@babel/helper-validator-identifier@^7.22.20": version "7.22.20" resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz#c4ae002c61d2879e724581d96665583dbc1dc0e0" integrity sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A== +"@babel/helper-validator-identifier@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.7.tgz#75b889cfaf9e35c2aaf42cf0d72c8e91719251db" + integrity sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w== + "@babel/helper-validator-option@^7.22.15", "@babel/helper-validator-option@^7.23.5": version "7.23.5" resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.23.5.tgz#907a3fbd4523426285365d1206c423c4c5520307" integrity sha512-85ttAOMLsr53VgXkTbkx8oA6YTfT4q7/HzXSLEYmjcSTJPMPQtvq1BD79Byep5xMUYbGRzEpDsjUf3dyp54IKw== +"@babel/helper-validator-option@^7.24.8": + version "7.24.8" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.24.8.tgz#3725cdeea8b480e86d34df15304806a06975e33d" + integrity sha512-xb8t9tD1MHLungh/AIoWYN+gVHaB9kwlu8gffXGSt3FFEIT7RjS+xWbc2vUD1UTZdIpKj/ab3rdqJ7ufngyi2Q== + "@babel/helper-wrap-function@^7.22.20": version "7.22.20" resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.22.20.tgz#15352b0b9bfb10fc9c76f79f6342c00e3411a569" @@ -365,6 +496,14 @@ "@babel/traverse" "^7.24.0" "@babel/types" "^7.24.0" +"@babel/helpers@^7.24.8": + version "7.24.8" + resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.24.8.tgz#2820d64d5d6686cca8789dd15b074cd862795873" + integrity sha512-gV2265Nkcz7weJJfvDoAEVzC1e2OTDpkGbEsebse8koXUJUXPsCMi7sRo/+SPMuMZ9MtUPnGwITTnQnU5YjyaQ== + dependencies: + "@babel/template" "^7.24.7" + "@babel/types" "^7.24.8" + "@babel/highlight@^7.23.4": version "7.23.4" resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.23.4.tgz#edaadf4d8232e1a961432db785091207ead0621b" @@ -374,6 +513,21 @@ chalk "^2.4.2" js-tokens "^4.0.0" +"@babel/highlight@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.24.7.tgz#a05ab1df134b286558aae0ed41e6c5f731bf409d" + integrity sha512-EStJpq4OuY8xYfhGVXngigBJRWxftKX9ksiGDnmlY3o7B/V7KIAc9X4oiK87uPJSc/vs5L869bem5fhZa8caZw== + dependencies: + "@babel/helper-validator-identifier" "^7.24.7" + chalk "^2.4.2" + js-tokens "^4.0.0" + picocolors "^1.0.0" + +"@babel/parser@^7.1.0", "@babel/parser@^7.20.7", "@babel/parser@^7.24.7", "@babel/parser@^7.24.8": + version "7.24.8" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.24.8.tgz#58a4dbbcad7eb1d48930524a3fd93d93e9084c6f" + integrity sha512-WzfbgXOkGzZiXXCqk43kKwZjzwx4oulxZi3nq2TYL9mOjQv6kYwul9mz6ID36njuL7Xkp6nJEfok848Zj10j/w== + "@babel/parser@^7.14.7", "@babel/parser@^7.24.0": version "7.24.0" resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.24.0.tgz#26a3d1ff49031c53a97d03b604375f028746a9ac" @@ -900,6 +1054,20 @@ dependencies: "@babel/plugin-transform-react-jsx" "^7.22.5" +"@babel/plugin-transform-react-jsx-self@^7.24.5": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.24.7.tgz#66bff0248ea0b549972e733516ffad577477bdab" + integrity sha512-fOPQYbGSgH0HUp4UJO4sMBFjY6DuWq+2i8rixyUMb3CdGixs/gccURvYOAhajBdKDoGajFr3mUq5rH3phtkGzw== + dependencies: + "@babel/helper-plugin-utils" "^7.24.7" + +"@babel/plugin-transform-react-jsx-source@^7.24.1": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.24.7.tgz#1198aab2548ad19582013815c938d3ebd8291ee3" + integrity sha512-J2z+MWzZHVOemyLweMqngXrgGC42jQ//R0KdxqkIz/OrbVIIlhFI3WigZ5fO+nwFvBlncr4MGapd8vTyc7RPNQ== + dependencies: + "@babel/helper-plugin-utils" "^7.24.7" + "@babel/plugin-transform-react-jsx@^7.22.15", "@babel/plugin-transform-react-jsx@^7.22.5": version "7.23.4" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.23.4.tgz#393f99185110cea87184ea47bcb4a7b0c2e39312" @@ -1180,6 +1348,15 @@ "@babel/parser" "^7.24.0" "@babel/types" "^7.24.0" +"@babel/template@^7.24.7": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.24.7.tgz#02efcee317d0609d2c07117cb70ef8fb17ab7315" + integrity sha512-jYqfPrU9JTF0PmPy1tLYHW4Mp4KlgxJD9l2nP9fD6yT/ICi554DmrWBAEYpIelzjHf1msDP3PxJIRt/nFNfBig== + dependencies: + "@babel/code-frame" "^7.24.7" + "@babel/parser" "^7.24.7" + "@babel/types" "^7.24.7" + "@babel/traverse@^7.13.0", "@babel/traverse@^7.24.0": version "7.24.0" resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.24.0.tgz#4a408fbf364ff73135c714a2ab46a5eab2831b1e" @@ -1196,6 +1373,31 @@ debug "^4.3.1" globals "^11.1.0" +"@babel/traverse@^7.24.7", "@babel/traverse@^7.24.8": + version "7.24.8" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.24.8.tgz#6c14ed5232b7549df3371d820fbd9abfcd7dfab7" + integrity sha512-t0P1xxAPzEDcEPmjprAQq19NWum4K0EQPjMwZQZbHt+GiZqvjCHjj755Weq1YRPVzBI+3zSfvScfpnuIecVFJQ== + dependencies: + "@babel/code-frame" "^7.24.7" + "@babel/generator" "^7.24.8" + "@babel/helper-environment-visitor" "^7.24.7" + "@babel/helper-function-name" "^7.24.7" + "@babel/helper-hoist-variables" "^7.24.7" + "@babel/helper-split-export-declaration" "^7.24.7" + "@babel/parser" "^7.24.8" + "@babel/types" "^7.24.8" + debug "^4.3.1" + globals "^11.1.0" + +"@babel/types@^7.0.0", "@babel/types@^7.20.7", "@babel/types@^7.24.7", "@babel/types@^7.24.8", "@babel/types@^7.24.9": + version "7.24.9" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.24.9.tgz#228ce953d7b0d16646e755acf204f4cf3d08cc73" + integrity sha512-xm8XrMKz0IlUdocVbYJe0Z9xEgidU7msskG8BbhnTPK/HZ2z/7FP7ykqPgrUH+C+r414mNfNWam1f2vqOjqjYQ== + dependencies: + "@babel/helper-string-parser" "^7.24.8" + "@babel/helper-validator-identifier" "^7.24.7" + to-fast-properties "^2.0.0" + "@babel/types@^7.22.15", "@babel/types@^7.22.19", "@babel/types@^7.22.5", "@babel/types@^7.23.0", "@babel/types@^7.23.4", "@babel/types@^7.23.6", "@babel/types@^7.24.0", "@babel/types@^7.4.4": version "7.24.0" resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.24.0.tgz#3b951f435a92e7333eba05b7566fd297960ea1bf" @@ -1205,10 +1407,19 @@ "@babel/helper-validator-identifier" "^7.22.20" to-fast-properties "^2.0.0" -"@colors/colors@1.5.0": - version "1.5.0" - resolved "https://registry.yarnpkg.com/@colors/colors/-/colors-1.5.0.tgz#bb504579c1cae923e6576a4f5da43d25f97bdbd9" - integrity sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ== +"@bundled-es-modules/cookie@^2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@bundled-es-modules/cookie/-/cookie-2.0.0.tgz#c3b82703969a61cf6a46e959a012b2c257f6b164" + integrity sha512-Or6YHg/kamKHpxULAdSqhGqnWFneIXu1NKvvfBBzKGwpVsYuFIQ5aBPHDnnoR3ghW1nvSkALd+EF9iMtY7Vjxw== + dependencies: + cookie "^0.5.0" + +"@bundled-es-modules/statuses@^1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@bundled-es-modules/statuses/-/statuses-1.0.1.tgz#761d10f44e51a94902c4da48675b71a76cc98872" + integrity sha512-yn7BklA5acgcBr+7w064fGV+SGIFySjCKpqjcWgBAIfrAkY+4GQTJJHQMeT3V/sgz23VTEVV8TtOmkvJAhFVfg== + dependencies: + statuses "^2.0.1" "@definitelytyped/header-parser@latest": version "0.2.8" @@ -1238,6 +1449,121 @@ tar-stream "^3.1.6" which "^4.0.0" +"@esbuild/aix-ppc64@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz#c7184a326533fcdf1b8ee0733e21c713b975575f" + integrity sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ== + +"@esbuild/android-arm64@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz#09d9b4357780da9ea3a7dfb833a1f1ff439b4052" + integrity sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A== + +"@esbuild/android-arm@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.21.5.tgz#9b04384fb771926dfa6d7ad04324ecb2ab9b2e28" + integrity sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg== + +"@esbuild/android-x64@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.21.5.tgz#29918ec2db754cedcb6c1b04de8cd6547af6461e" + integrity sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA== + +"@esbuild/darwin-arm64@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz#e495b539660e51690f3928af50a76fb0a6ccff2a" + integrity sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ== + +"@esbuild/darwin-x64@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz#c13838fa57372839abdddc91d71542ceea2e1e22" + integrity sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw== + +"@esbuild/freebsd-arm64@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz#646b989aa20bf89fd071dd5dbfad69a3542e550e" + integrity sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g== + +"@esbuild/freebsd-x64@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz#aa615cfc80af954d3458906e38ca22c18cf5c261" + integrity sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ== + +"@esbuild/linux-arm64@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz#70ac6fa14f5cb7e1f7f887bcffb680ad09922b5b" + integrity sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q== + +"@esbuild/linux-arm@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz#fc6fd11a8aca56c1f6f3894f2bea0479f8f626b9" + integrity sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA== + +"@esbuild/linux-ia32@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz#3271f53b3f93e3d093d518d1649d6d68d346ede2" + integrity sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg== + +"@esbuild/linux-loong64@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz#ed62e04238c57026aea831c5a130b73c0f9f26df" + integrity sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg== + +"@esbuild/linux-mips64el@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz#e79b8eb48bf3b106fadec1ac8240fb97b4e64cbe" + integrity sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg== + +"@esbuild/linux-ppc64@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz#5f2203860a143b9919d383ef7573521fb154c3e4" + integrity sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w== + +"@esbuild/linux-riscv64@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz#07bcafd99322d5af62f618cb9e6a9b7f4bb825dc" + integrity sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA== + +"@esbuild/linux-s390x@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz#b7ccf686751d6a3e44b8627ababc8be3ef62d8de" + integrity sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A== + +"@esbuild/linux-x64@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz#6d8f0c768e070e64309af8004bb94e68ab2bb3b0" + integrity sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ== + +"@esbuild/netbsd-x64@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz#bbe430f60d378ecb88decb219c602667387a6047" + integrity sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg== + +"@esbuild/openbsd-x64@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz#99d1cf2937279560d2104821f5ccce220cb2af70" + integrity sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow== + +"@esbuild/sunos-x64@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz#08741512c10d529566baba837b4fe052c8f3487b" + integrity sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg== + +"@esbuild/win32-arm64@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz#675b7385398411240735016144ab2e99a60fc75d" + integrity sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A== + +"@esbuild/win32-ia32@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz#1bfc3ce98aa6ca9a0969e4d2af72144c59c1193b" + integrity sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA== + +"@esbuild/win32-x64@0.21.5": + version "0.21.5" + resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz#acad351d582d157bb145535db2a6ff53dd514b5c" + integrity sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw== + "@eslint-community/eslint-utils@^4.2.0", "@eslint-community/eslint-utils@^4.4.0": version "4.4.0" resolved "https://registry.yarnpkg.com/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz#a23514e8fb9af1269d5f7788aa556798d61c6b59" @@ -1299,6 +1625,45 @@ resolved "https://registry.yarnpkg.com/@hutson/parse-repository-url/-/parse-repository-url-3.0.2.tgz#98c23c950a3d9b6c8f0daed06da6c3af06981340" integrity sha512-H9XAx3hc0BQHY6l+IFSWHDySypcXsvsuLhgYLUGywmJ5pswRVQJUHpOsobnLYp2ZUaUlKiKDrgWWhosOwAEM8Q== +"@inquirer/confirm@^3.0.0": + version "3.1.17" + resolved "https://registry.yarnpkg.com/@inquirer/confirm/-/confirm-3.1.17.tgz#adca3b0f35e2d2ace53f652a92f987aaccb8482a" + integrity sha512-qCpt/AABzPynz8tr69VDvhcjwmzAryipWXtW8Vi6m651da4H/d0Bdn55LkxXD7Rp2gfgxvxzTdb66AhIA8gzBA== + dependencies: + "@inquirer/core" "^9.0.5" + "@inquirer/type" "^1.5.1" + +"@inquirer/core@^9.0.5": + version "9.0.5" + resolved "https://registry.yarnpkg.com/@inquirer/core/-/core-9.0.5.tgz#b5e14d80e87419231981f48fa86f63d15cb8805b" + integrity sha512-QWG41I7vn62O9stYKg/juKXt1PEbr/4ZZCPb4KgXDQGwgA9M5NBTQ7FnOvT1ridbxkm/wTxLCNraUs7y47pIRQ== + dependencies: + "@inquirer/figures" "^1.0.5" + "@inquirer/type" "^1.5.1" + "@types/mute-stream" "^0.0.4" + "@types/node" "^20.14.11" + "@types/wrap-ansi" "^3.0.0" + ansi-escapes "^4.3.2" + cli-spinners "^2.9.2" + cli-width "^4.1.0" + mute-stream "^1.0.0" + signal-exit "^4.1.0" + strip-ansi "^6.0.1" + wrap-ansi "^6.2.0" + yoctocolors-cjs "^2.1.2" + +"@inquirer/figures@^1.0.5": + version "1.0.5" + resolved "https://registry.yarnpkg.com/@inquirer/figures/-/figures-1.0.5.tgz#57f9a996d64d3e3345d2a3ca04d36912e94f8790" + integrity sha512-79hP/VWdZ2UVc9bFGJnoQ/lQMpL74mGgzSYX1xUqCVk7/v73vJCMw1VuyWN1jGkZ9B3z7THAbySqGbCNefcjfA== + +"@inquirer/type@^1.5.1": + version "1.5.1" + resolved "https://registry.yarnpkg.com/@inquirer/type/-/type-1.5.1.tgz#cdd36732e38ea5d2b1a4336aada65ebe7d2765e0" + integrity sha512-m3YgGQlKNS0BM+8AFiJkCsTqHEFCWn6s/Rqye3mYwvqY6LdfUv12eSwbsgNzrYyrLXiy7IrrjDLPysaSBwEfhw== + dependencies: + mute-stream "^1.0.0" + "@istanbuljs/load-nyc-config@^1.0.0": version "1.1.0" resolved "https://registry.yarnpkg.com/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz#fd3db1d59ecf7cf121e80650bb86712f9b55eced" @@ -1347,6 +1712,11 @@ resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz#d7c6e6755c78567a951e04ab52ef0fd26de59f32" integrity sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg== +"@jridgewell/sourcemap-codec@^1.4.15": + version "1.5.0" + resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz#3188bcb273a414b0d215fd22a58540b989b9409a" + integrity sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ== + "@jridgewell/trace-mapping@^0.3.17", "@jridgewell/trace-mapping@^0.3.20", "@jridgewell/trace-mapping@^0.3.24", "@jridgewell/trace-mapping@^0.3.25": version "0.3.25" resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz#15f190e98895f3fc23276ee14bc76b675c2e50f0" @@ -1363,6 +1733,23 @@ call-me-maybe "^1.0.1" glob-to-regexp "^0.3.0" +"@mswjs/cookies@^1.1.0": + version "1.1.1" + resolved "https://registry.yarnpkg.com/@mswjs/cookies/-/cookies-1.1.1.tgz#8b519e2bd8f1577c530beed44a25578eb9a6e72c" + integrity sha512-W68qOHEjx1iD+4VjQudlx26CPIoxmIAtK4ZCexU0/UJBG6jYhcuyzKJx+Iw8uhBIGd9eba64XgWVgo20it1qwA== + +"@mswjs/interceptors@^0.29.0": + version "0.29.1" + resolved "https://registry.yarnpkg.com/@mswjs/interceptors/-/interceptors-0.29.1.tgz#e77fc58b5188569041d0440b25c9e9ebb1ccd60a" + integrity sha512-3rDakgJZ77+RiQUuSK69t1F0m8BQKA8Vh5DCS5V0DWvNY67zob2JhhQrhCO0AKLGINTRSFd1tBaHcJTkhefoSw== + dependencies: + "@open-draft/deferred-promise" "^2.2.0" + "@open-draft/logger" "^0.3.0" + "@open-draft/until" "^2.0.0" + is-node-process "^1.2.0" + outvariant "^1.2.1" + strict-event-emitter "^0.5.1" + "@nicolo-ribaudo/chokidar-2@2.1.8-no-fsevents.3": version "2.1.8-no-fsevents.3" resolved "https://registry.yarnpkg.com/@nicolo-ribaudo/chokidar-2/-/chokidar-2-2.1.8-no-fsevents.3.tgz#323d72dd25103d0c4fbdce89dadf574a787b1f9b" @@ -1401,11 +1788,34 @@ "@nodelib/fs.scandir" "2.1.5" fastq "^1.6.0" +"@open-draft/deferred-promise@^2.2.0": + version "2.2.0" + resolved "https://registry.yarnpkg.com/@open-draft/deferred-promise/-/deferred-promise-2.2.0.tgz#4a822d10f6f0e316be4d67b4d4f8c9a124b073bd" + integrity sha512-CecwLWx3rhxVQF6V4bAgPS5t+So2sTbPgAzafKkVizyi7tlwpcFpdFqq+wqF2OwNBmqFuu6tOyouTuxgpMfzmA== + +"@open-draft/logger@^0.3.0": + version "0.3.0" + resolved "https://registry.yarnpkg.com/@open-draft/logger/-/logger-0.3.0.tgz#2b3ab1242b360aa0adb28b85f5d7da1c133a0954" + integrity sha512-X2g45fzhxH238HKO4xbSr7+wBS8Fvw6ixhTDuvLd5mqh6bJJCFAPwU9mPDxbcrRtfxv4u5IHCEH77BmxvXmmxQ== + dependencies: + is-node-process "^1.2.0" + outvariant "^1.4.0" + +"@open-draft/until@^2.0.0", "@open-draft/until@^2.1.0": + version "2.1.0" + resolved "https://registry.yarnpkg.com/@open-draft/until/-/until-2.1.0.tgz#0acf32f470af2ceaf47f095cdecd40d68666efda" + integrity sha512-U69T3ItWHvLwGg5eJ0n3I62nWuE6ilHlmz7zM0npLBRvPRd7e6NYmg54vvRtP5mZG7kZqZCFVdsTWo7BPtBujg== + "@pkgr/core@^0.1.0": version "0.1.1" resolved "https://registry.yarnpkg.com/@pkgr/core/-/core-0.1.1.tgz#1ec17e2edbec25c8306d424ecfbf13c7de1aaa31" integrity sha512-cq8o4cWH0ibXh9VGi5P20Tu9XF/0fFXl9EUinr9QfTM7a7p0oTA4iJRCQWppXR1Pg8dSM0UCItCkPwsk9qWWYA== +"@polka/url@^1.0.0-next.24": + version "1.0.0-next.25" + resolved "https://registry.yarnpkg.com/@polka/url/-/url-1.0.0-next.25.tgz#f077fdc0b5d0078d30893396ff4827a13f99e817" + integrity sha512-j7P6Rgr3mmtdkeDGTe0E/aYyWEWVtc5yFXtHCRHs28/jptDEWfaVOc5T7cblqy1XKPPfCxJc/8DwQ5YgLOZOVQ== + "@popperjs/core@^2.11.6": version "2.11.8" resolved "https://registry.yarnpkg.com/@popperjs/core/-/core-2.11.8.tgz#6b79032e760a0899cd4204710beede972a3a185f" @@ -1489,6 +1899,86 @@ uncontrollable "^8.0.1" warning "^4.0.3" +"@rollup/rollup-android-arm-eabi@4.19.0": + version "4.19.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.19.0.tgz#3d9fd50164b94964f5de68c3c4ce61933b3a338d" + integrity sha512-JlPfZ/C7yn5S5p0yKk7uhHTTnFlvTgLetl2VxqE518QgyM7C9bSfFTYvB/Q/ftkq0RIPY4ySxTz+/wKJ/dXC0w== + +"@rollup/rollup-android-arm64@4.19.0": + version "4.19.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.19.0.tgz#e1a6d4bca2eb08c84fd996a4bf896ce4b6f4014c" + integrity sha512-RDxUSY8D1tWYfn00DDi5myxKgOk6RvWPxhmWexcICt/MEC6yEMr4HNCu1sXXYLw8iAsg0D44NuU+qNq7zVWCrw== + +"@rollup/rollup-darwin-arm64@4.19.0": + version "4.19.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.19.0.tgz#0a3fffea69489a24a96079af414b0be78df8abbc" + integrity sha512-emvKHL4B15x6nlNTBMtIaC9tLPRpeA5jMvRLXVbl/W9Ie7HhkrE7KQjvgS9uxgatL1HmHWDXk5TTS4IaNJxbAA== + +"@rollup/rollup-darwin-x64@4.19.0": + version "4.19.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.19.0.tgz#13fbdb15f58f090871b0ffff047ece06ad6ad74c" + integrity sha512-fO28cWA1dC57qCd+D0rfLC4VPbh6EOJXrreBmFLWPGI9dpMlER2YwSPZzSGfq11XgcEpPukPTfEVFtw2q2nYJg== + +"@rollup/rollup-linux-arm-gnueabihf@4.19.0": + version "4.19.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.19.0.tgz#e9d9219ddf6f6e946e2ee322198af12466d2c868" + integrity sha512-2Rn36Ubxdv32NUcfm0wB1tgKqkQuft00PtM23VqLuCUR4N5jcNWDoV5iBC9jeGdgS38WK66ElncprqgMUOyomw== + +"@rollup/rollup-linux-arm-musleabihf@4.19.0": + version "4.19.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.19.0.tgz#4ba804a00b5e793196a622f6977e05f23e01f59a" + integrity sha512-gJuzIVdq/X1ZA2bHeCGCISe0VWqCoNT8BvkQ+BfsixXwTOndhtLUpOg0A1Fcx/+eA6ei6rMBzlOz4JzmiDw7JQ== + +"@rollup/rollup-linux-arm64-gnu@4.19.0": + version "4.19.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.19.0.tgz#d871e3f41de759a6db27fc99235b782ba47c15cc" + integrity sha512-0EkX2HYPkSADo9cfeGFoQ7R0/wTKb7q6DdwI4Yn/ULFE1wuRRCHybxpl2goQrx4c/yzK3I8OlgtBu4xvted0ug== + +"@rollup/rollup-linux-arm64-musl@4.19.0": + version "4.19.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.19.0.tgz#6e63f7ad4cc51bd2c693a2826fd279de9eaa05b5" + integrity sha512-GlIQRj9px52ISomIOEUq/IojLZqzkvRpdP3cLgIE1wUWaiU5Takwlzpz002q0Nxxr1y2ZgxC2obWxjr13lvxNQ== + +"@rollup/rollup-linux-powerpc64le-gnu@4.19.0": + version "4.19.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.19.0.tgz#1540b284d91c440bc9fa7a1714cfb71a5597e94d" + integrity sha512-N6cFJzssruDLUOKfEKeovCKiHcdwVYOT1Hs6dovDQ61+Y9n3Ek4zXvtghPPelt6U0AH4aDGnDLb83uiJMkWYzQ== + +"@rollup/rollup-linux-riscv64-gnu@4.19.0": + version "4.19.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.19.0.tgz#70ae58103b5bc7ba2e2235738b51d97022c8ef92" + integrity sha512-2DnD3mkS2uuam/alF+I7M84koGwvn3ZVD7uG+LEWpyzo/bq8+kKnus2EVCkcvh6PlNB8QPNFOz6fWd5N8o1CYg== + +"@rollup/rollup-linux-s390x-gnu@4.19.0": + version "4.19.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.19.0.tgz#579ca5f271421a961d3c73d221202c79e02ff03a" + integrity sha512-D6pkaF7OpE7lzlTOFCB2m3Ngzu2ykw40Nka9WmKGUOTS3xcIieHe82slQlNq69sVB04ch73thKYIWz/Ian8DUA== + +"@rollup/rollup-linux-x64-gnu@4.19.0": + version "4.19.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.19.0.tgz#f0282d761b8b4e7b92b236813475248e37231849" + integrity sha512-HBndjQLP8OsdJNSxpNIN0einbDmRFg9+UQeZV1eiYupIRuZsDEoeGU43NQsS34Pp166DtwQOnpcbV/zQxM+rWA== + +"@rollup/rollup-linux-x64-musl@4.19.0": + version "4.19.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.19.0.tgz#65da807ac66c505ad14b76f1e5976006cb67dd5f" + integrity sha512-HxfbvfCKJe/RMYJJn0a12eiOI9OOtAUF4G6ozrFUK95BNyoJaSiBjIOHjZskTUffUrB84IPKkFG9H9nEvJGW6A== + +"@rollup/rollup-win32-arm64-msvc@4.19.0": + version "4.19.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.19.0.tgz#1eed24b91f421c2eea8bb7ca8889ba0c867e1780" + integrity sha512-HxDMKIhmcguGTiP5TsLNolwBUK3nGGUEoV/BO9ldUBoMLBssvh4J0X8pf11i1fTV7WShWItB1bKAKjX4RQeYmg== + +"@rollup/rollup-win32-ia32-msvc@4.19.0": + version "4.19.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.19.0.tgz#1ed93c9cdc84e185359797a686f4d1576afcea58" + integrity sha512-xItlIAZZaiG/u0wooGzRsx11rokP4qyc/79LkAOdznGRAbOFc+SfEdfUOszG1odsHNgwippUJavag/+W/Etc6Q== + +"@rollup/rollup-win32-x64-msvc@4.19.0": + version "4.19.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.19.0.tgz#baf9b65023ea2ecc5e6ec68f787a0fecfd8ee84c" + integrity sha512-xNo5fV5ycvCCKqiZcpB65VMR11NJB+StnxHz20jdqRAktfdfzhgjTiJ2doTDQE/7dqGaV5I7ZGqKpgph6lCIag== + "@samverschueren/stream-to-observable@^0.3.0": version "0.3.1" resolved "https://registry.yarnpkg.com/@samverschueren/stream-to-observable/-/stream-to-observable-0.3.1.tgz#a21117b19ee9be70c379ec1877537ef2e1c63301" @@ -1496,46 +1986,6 @@ dependencies: any-observable "^0.3.0" -"@sinonjs/commons@^2.0.0": - version "2.0.0" - resolved "https://registry.yarnpkg.com/@sinonjs/commons/-/commons-2.0.0.tgz#fd4ca5b063554307e8327b4564bd56d3b73924a3" - integrity sha512-uLa0j859mMrg2slwQYdO/AkrOfmH+X6LTVmNTS9CqexuE2IvVORIkSpJLqePAbEnKJ77aMmCwr1NUZ57120Xcg== - dependencies: - type-detect "4.0.8" - -"@sinonjs/commons@^3.0.0", "@sinonjs/commons@^3.0.1": - version "3.0.1" - resolved "https://registry.yarnpkg.com/@sinonjs/commons/-/commons-3.0.1.tgz#1029357e44ca901a615585f6d27738dbc89084cd" - integrity sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ== - dependencies: - type-detect "4.0.8" - -"@sinonjs/fake-timers@^11.2.2": - version "11.2.2" - resolved "https://registry.yarnpkg.com/@sinonjs/fake-timers/-/fake-timers-11.2.2.tgz#50063cc3574f4a27bd8453180a04171c85cc9699" - integrity sha512-G2piCSxQ7oWOxwGSAyFHfPIsyeJGXYtc6mFbnFA+kRXkiEnTl8c/8jul2S329iFBnDI9HGoeWWAZvuvOkZccgw== - dependencies: - "@sinonjs/commons" "^3.0.0" - -"@sinonjs/samsam@^8.0.0": - version "8.0.0" - resolved "https://registry.yarnpkg.com/@sinonjs/samsam/-/samsam-8.0.0.tgz#0d488c91efb3fa1442e26abea81759dfc8b5ac60" - integrity sha512-Bp8KUVlLp8ibJZrnvq2foVhP0IVX2CIprMJPK0vqGqgrDa0OHVKeZyBykqskkrdxV6yKBPmGasO8LVjAKR3Gew== - dependencies: - "@sinonjs/commons" "^2.0.0" - lodash.get "^4.4.2" - type-detect "^4.0.8" - -"@sinonjs/text-encoding@^0.7.2": - version "0.7.2" - resolved "https://registry.yarnpkg.com/@sinonjs/text-encoding/-/text-encoding-0.7.2.tgz#5981a8db18b56ba38ef0efb7d995b12aa7b51918" - integrity sha512-sXXKG+uL9IrKqViTtao2Ws6dy0znu9sOaP1di/jKGW1M6VssO8vlpXCQcpZ+jisQ1tTFAC5Jo/EOzFbggBagFQ== - -"@socket.io/component-emitter@~3.1.0": - version "3.1.0" - resolved "https://registry.yarnpkg.com/@socket.io/component-emitter/-/component-emitter-3.1.0.tgz#96116f2a912e0c02817345b3c10751069920d553" - integrity sha512-+9jVqKhRSpsc591z5vX+X5Yyw+he/HCB4iQ/RYxw35CEPaY1gnsNE43nf9n9AaYjAQrTiI/mOwKUKdUs9vf7Xg== - "@swc/helpers@^0.5.0": version "0.5.7" resolved "https://registry.yarnpkg.com/@swc/helpers/-/helpers-0.5.7.tgz#36c05f61b412abcff3616ecc8634623bcc7c9618" @@ -1543,10 +1993,10 @@ dependencies: tslib "^2.4.0" -"@testing-library/dom@^10.1.0": - version "10.1.0" - resolved "https://registry.yarnpkg.com/@testing-library/dom/-/dom-10.1.0.tgz#2d073e49771ad614da999ca48f199919e5176fb6" - integrity sha512-wdsYKy5zupPyLCW2Je5DLHSxSfbIp6h80WoHOQc+RPtmPGA52O9x5MJEkv92Sjonpq+poOAtUKhh1kBGAXBrNA== +"@testing-library/dom@^10.3.1", "@testing-library/dom@^10.4.0": + version "10.4.0" + resolved "https://registry.yarnpkg.com/@testing-library/dom/-/dom-10.4.0.tgz#82a9d9462f11d240ecadbf406607c6ceeeff43a8" + integrity sha512-pemlzrSESWbdAloYml3bAJMEfNh1Z7EduzqPKprCH5S341frlpYnUEW0H72dLxa6IsYr+mPno20GiSm+h9dEdQ== dependencies: "@babel/code-frame" "^7.10.4" "@babel/runtime" "^7.12.5" @@ -1564,6 +2014,11 @@ dependencies: "@babel/runtime" "^7.12.5" +"@testing-library/user-event@^14.5.2": + version "14.5.2" + resolved "https://registry.yarnpkg.com/@testing-library/user-event/-/user-event-14.5.2.tgz#db7257d727c891905947bd1c1a99da20e03c2ebd" + integrity sha512-YAh82Wh4TIrxYLmfGcixwD18oIjyC1pFQC2Y01F2lzV2HTMiYrI0nze0FD0ocB//CKS/7jIUgae+adPqxK5yCQ== + "@tootallnate/once@1": version "1.1.2" resolved "https://registry.yarnpkg.com/@tootallnate/once/-/once-1.1.2.tgz#ccb91445360179a04e7fe6aff78c00ffc1eeaf82" @@ -1574,27 +2029,43 @@ resolved "https://registry.yarnpkg.com/@types/aria-query/-/aria-query-5.0.4.tgz#1a31c3d378850d2778dabb6374d036dcba4ba708" integrity sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw== -"@types/chai@*": - version "4.3.12" - resolved "https://registry.yarnpkg.com/@types/chai/-/chai-4.3.12.tgz#b192fe1c553b54f45d20543adc2ab88455a07d5e" - integrity sha512-zNKDHG/1yxm8Il6uCCVsm+dRdEsJlFoDu73X17y09bId6UwoYww+vFBsAcRzl8knM1sab3Dp1VRikFQwDOtDDw== +"@types/babel__core@^7.20.5": + version "7.20.5" + resolved "https://registry.yarnpkg.com/@types/babel__core/-/babel__core-7.20.5.tgz#3df15f27ba85319caa07ba08d0721889bb39c017" + integrity sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA== + dependencies: + "@babel/parser" "^7.20.7" + "@babel/types" "^7.20.7" + "@types/babel__generator" "*" + "@types/babel__template" "*" + "@types/babel__traverse" "*" -"@types/chai@^4.3.16": - version "4.3.16" - resolved "https://registry.yarnpkg.com/@types/chai/-/chai-4.3.16.tgz#b1572967f0b8b60bf3f87fe1d854a5604ea70c82" - integrity sha512-PatH4iOdyh3MyWtmHVFXLWCCIhUbopaltqddG9BzB+gMIzee2MJrvd+jouii9Z3wzQJruGWAm7WOMjgfG8hQlQ== +"@types/babel__generator@*": + version "7.6.8" + resolved "https://registry.yarnpkg.com/@types/babel__generator/-/babel__generator-7.6.8.tgz#f836c61f48b1346e7d2b0d93c6dacc5b9535d3ab" + integrity sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw== + dependencies: + "@babel/types" "^7.0.0" -"@types/cookie@^0.4.1": - version "0.4.1" - resolved "https://registry.yarnpkg.com/@types/cookie/-/cookie-0.4.1.tgz#bfd02c1f2224567676c1545199f87c3a861d878d" - integrity sha512-XW/Aa8APYr6jSVVA1y/DEIZX0/GMKLEVekNG727R8cs56ahETkRAy/3DR7+fJyh7oUgGwNQaRfXCun0+KbWY7Q== +"@types/babel__template@*": + version "7.4.4" + resolved "https://registry.yarnpkg.com/@types/babel__template/-/babel__template-7.4.4.tgz#5672513701c1b2199bc6dad636a9d7491586766f" + integrity sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A== + dependencies: + "@babel/parser" "^7.1.0" + "@babel/types" "^7.0.0" -"@types/cors@^2.8.12": - version "2.8.17" - resolved "https://registry.yarnpkg.com/@types/cors/-/cors-2.8.17.tgz#5d718a5e494a8166f569d986794e49c48b216b2b" - integrity sha512-8CGDvrBj1zgo2qE+oS3pOCyYNqCPryMWY2bGfwA0dcfopWGgxs+78df0Rs3rc9THP4JkOhLsAa+15VdpAqkcUA== +"@types/babel__traverse@*": + version "7.20.6" + resolved "https://registry.yarnpkg.com/@types/babel__traverse/-/babel__traverse-7.20.6.tgz#8dc9f0ae0f202c08d8d4dab648912c8d6038e3f7" + integrity sha512-r1bzfrm0tomOI8g1SzvCaQHo6Lcv6zu0EA+W2kHrt8dyrHQxGzBBL4kdkzIS+jBMV+EYcMAEAqXqYaLJq5rOZg== dependencies: - "@types/node" "*" + "@babel/types" "^7.20.7" + +"@types/cookie@^0.6.0": + version "0.6.0" + resolved "https://registry.yarnpkg.com/@types/cookie/-/cookie-0.6.0.tgz#eac397f28bf1d6ae0ae081363eca2f425bedf0d5" + integrity sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA== "@types/eslint-scope@^3.7.3": version "3.7.7" @@ -1605,14 +2076,14 @@ "@types/estree" "*" "@types/eslint@*": - version "8.56.5" - resolved "https://registry.yarnpkg.com/@types/eslint/-/eslint-8.56.5.tgz#94b88cab77588fcecdd0771a6d576fa1c0af9d02" - integrity sha512-u5/YPJHo1tvkSF2CE0USEkxon82Z5DBy2xR+qfyYNszpX9qcs4sT6uq2kBbj4BXY1+DBGDPnrhMZV3pKWGNukw== + version "9.6.0" + resolved "https://registry.yarnpkg.com/@types/eslint/-/eslint-9.6.0.tgz#51d4fe4d0316da9e9f2c80884f2c20ed5fb022ff" + integrity sha512-gi6WQJ7cHRgZxtkQEoyHMppPjq9Kxo5Tjn2prSKDSmZrCz8TZ3jSRCeTJm+WoM+oB0WG37bRqLzaaU3q7JypGg== dependencies: "@types/estree" "*" "@types/json-schema" "*" -"@types/estree@*", "@types/estree@^1.0.5": +"@types/estree@*", "@types/estree@1.0.5", "@types/estree@^1.0.0", "@types/estree@^1.0.5": version "1.0.5" resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.5.tgz#a6ce3e556e00fd9895dd872dd172ad0d4bd687f4" integrity sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw== @@ -1655,7 +2126,14 @@ resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-10.0.6.tgz#818551d39113081048bdddbef96701b4e8bb9d1b" integrity sha512-dJvrYWxP/UcXm36Qn36fxhUKu8A/xMRXVT2cliFF1Z7UA9liG5Psj3ezNSZw+5puH2czDXRLcXQxf8JbJt0ejg== -"@types/node@*", "@types/node@>=10.0.0": +"@types/mute-stream@^0.0.4": + version "0.0.4" + resolved "https://registry.yarnpkg.com/@types/mute-stream/-/mute-stream-0.0.4.tgz#77208e56a08767af6c5e1237be8888e2f255c478" + integrity sha512-CPM9nzrCPPJHQNA9keH9CVkVI+WR5kMa+7XEs5jcGQ0VoAGnLv242w8lIVgwAEfmE4oufJRaTc9PNLQl0ioAow== + dependencies: + "@types/node" "*" + +"@types/node@*": version "20.11.28" resolved "https://registry.yarnpkg.com/@types/node/-/node-20.11.28.tgz#4fd5b2daff2e580c12316e457473d68f15ee6f66" integrity sha512-M/GPWVS2wLkSkNHVeLkrF2fD5Lx5UC4PxA0uZcKc6QqbIQUJyW1jVjueJYi1z8n0I5PxYrtpnPnWglE+y9A0KA== @@ -1669,6 +2147,13 @@ dependencies: undici-types "~5.26.4" +"@types/node@^20.14.11": + version "20.14.11" + resolved "https://registry.yarnpkg.com/@types/node/-/node-20.14.11.tgz#09b300423343460455043ddd4d0ded6ac579b74b" + integrity sha512-kprQpL8MMeszbz6ojB5/tU8PLN4kesnN8Gjzw349rDlNgsSzg90lAVj3llK99Dh7JON+t9AuscPPFW6mPbTnSA== + dependencies: + undici-types "~5.26.4" + "@types/normalize-package-data@^2.4.0", "@types/normalize-package-data@^2.4.1": version "2.4.4" resolved "https://registry.yarnpkg.com/@types/normalize-package-data/-/normalize-package-data-2.4.4.tgz#56e2cc26c397c038fab0e3a917a12d5c5909e901" @@ -1684,10 +2169,10 @@ resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.12.tgz#12bb1e2be27293c1406acb6af1c3f3a1481d98c6" integrity sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q== -"@types/react-dom@^18.2.22": - version "18.2.22" - resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-18.2.22.tgz#d332febf0815403de6da8a97e5fe282cbe609bae" - integrity sha512-fHkBXPeNtfvri6gdsMYyW+dW7RXFo6Ad09nLFK0VQWR7yGLai/Cyvyj696gbwYvBnhGtevUG9cET0pmUbMtoPQ== +"@types/react-dom@^18.3.0": + version "18.3.0" + resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-18.3.0.tgz#0cbc818755d87066ab6ca74fbedb2547d74a82b0" + integrity sha512-EhwApuTmMBmXuFOikhQLIBUn6uFg81SwLMOAUgodJF14SOBOCMdU04gDoYi0WOJJHD144TL32z4yDqCW3dnkQg== dependencies: "@types/react" "*" @@ -1698,7 +2183,7 @@ dependencies: "@types/react" "*" -"@types/react@*", "@types/react@>=16.9.11", "@types/react@^18.2.66": +"@types/react@*", "@types/react@>=16.9.11": version "18.2.66" resolved "https://registry.yarnpkg.com/@types/react/-/react-18.2.66.tgz#d2eafc8c4e70939c5432221adb23d32d76bfe451" integrity sha512-OYTmMI4UigXeFMF/j4uv0lBBEbongSgptPrHBxqME44h9+yNov+oL6Z3ocJKo0WyXR84sQUNeyIp9MRfckvZpg== @@ -1707,36 +2192,34 @@ "@types/scheduler" "*" csstype "^3.0.2" +"@types/react@^18.3.3": + version "18.3.3" + resolved "https://registry.yarnpkg.com/@types/react/-/react-18.3.3.tgz#9679020895318b0915d7a3ab004d92d33375c45f" + integrity sha512-hti/R0pS0q1/xx+TsI73XIqk26eBsISZ2R0wUijXIngRK9R/e7Xw/cXVxQK7R5JjW+SV4zGcn5hXjudkN/pLIw== + dependencies: + "@types/prop-types" "*" + csstype "^3.0.2" + "@types/scheduler@*": version "0.16.8" resolved "https://registry.yarnpkg.com/@types/scheduler/-/scheduler-0.16.8.tgz#ce5ace04cfeabe7ef87c0091e50752e36707deff" integrity sha512-WZLiwShhwLRmeV6zH+GkbOFT6Z6VklCItrDioxUnv+u4Ll+8vKeFySoFyK/0ctcRpOmwAicELfmys1sDc/Rw+A== -"@types/sinon-chai@^3.2.12": - version "3.2.12" - resolved "https://registry.yarnpkg.com/@types/sinon-chai/-/sinon-chai-3.2.12.tgz#c7cb06bee44a534ec84f3a5534c3a3a46fd779b6" - integrity sha512-9y0Gflk3b0+NhQZ/oxGtaAJDvRywCa5sIyaVnounqLvmf93yBF4EgIRspePtkMs3Tr844nCclYMlcCNmLCvjuQ== - dependencies: - "@types/chai" "*" - "@types/sinon" "*" - -"@types/sinon@*", "@types/sinon@^17.0.3": - version "17.0.3" - resolved "https://registry.yarnpkg.com/@types/sinon/-/sinon-17.0.3.tgz#9aa7e62f0a323b9ead177ed23a36ea757141a5fa" - integrity sha512-j3uovdn8ewky9kRBG19bOwaZbexJu/XjtkHyjvUgt4xfPFz18dcORIMqnYh66Fx3Powhcr85NT5+er3+oViapw== - dependencies: - "@types/sinonjs__fake-timers" "*" - -"@types/sinonjs__fake-timers@*": - version "8.1.5" - resolved "https://registry.yarnpkg.com/@types/sinonjs__fake-timers/-/sinonjs__fake-timers-8.1.5.tgz#5fd3592ff10c1e9695d377020c033116cc2889f2" - integrity sha512-mQkU2jY8jJEF7YHjHvsQO8+3ughTL1mcnn96igfhONmR+fUPSKIkefQYpSe8bsly2Ep7oQbn/6VG5/9/0qcArQ== +"@types/statuses@^2.0.4": + version "2.0.5" + resolved "https://registry.yarnpkg.com/@types/statuses/-/statuses-2.0.5.tgz#f61ab46d5352fd73c863a1ea4e1cef3b0b51ae63" + integrity sha512-jmIUGWrAiwu3dZpxntxieC+1n/5c3mjrImkmOSQ2NC5uP6cYO4aAZDdSmRcI5C1oiTmqlZGHC+/NmJrKogbP5A== "@types/warning@^3.0.0", "@types/warning@^3.0.3": version "3.0.3" resolved "https://registry.yarnpkg.com/@types/warning/-/warning-3.0.3.tgz#d1884c8cc4a426d1ac117ca2611bf333834c6798" integrity sha512-D1XC7WK8K+zZEveUPY+cf4+kgauk8N4eHr/XIHXGlGYkHLud6hK9lYfZk1ry1TNh798cZUCgb6MqGEG8DkJt6Q== +"@types/wrap-ansi@^3.0.0": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@types/wrap-ansi/-/wrap-ansi-3.0.0.tgz#18b97a972f94f60a679fd5c796d96421b9abb9fd" + integrity sha512-ltIpx+kM7g/MLRZfkbL7EsCEjfzCcScLpkg37eXEtx5kmrAKBkTJwd1GIAjDSL8wTpM6Hzn5YO4pSb91BEwu1g== + "@typescript-eslint/eslint-plugin@^7.13.0": version "7.13.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.13.0.tgz#3cdeb5d44d051b21a9567535dd90702b2a42c6ff" @@ -1823,6 +2306,81 @@ resolved "https://registry.yarnpkg.com/@ungap/structured-clone/-/structured-clone-1.2.0.tgz#756641adb587851b5ccb3e095daf27ae581c8406" integrity sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ== +"@vitejs/plugin-react@^4.3.1": + version "4.3.1" + resolved "https://registry.yarnpkg.com/@vitejs/plugin-react/-/plugin-react-4.3.1.tgz#d0be6594051ded8957df555ff07a991fb618b48e" + integrity sha512-m/V2syj5CuVnaxcUJOQRel/Wr31FFXRFlnOoq1TVtkCxsY5veGMTEmpWHndrhB2U8ScHtCQB1e+4hWYExQc6Lg== + dependencies: + "@babel/core" "^7.24.5" + "@babel/plugin-transform-react-jsx-self" "^7.24.5" + "@babel/plugin-transform-react-jsx-source" "^7.24.1" + "@types/babel__core" "^7.20.5" + react-refresh "^0.14.2" + +"@vitest/browser@^2.0.4": + version "2.0.4" + resolved "https://registry.yarnpkg.com/@vitest/browser/-/browser-2.0.4.tgz#6569258b4a8085f348007acd5ecf61db4eec4340" + integrity sha512-QsIkbqPqHsXvgxjCjjgKjuWKmrC0VJgpaDkuEmOy5gTnErhhifWIfp3HpH92K7cscfaIao+RlKv5f8nUMgjfmA== + dependencies: + "@testing-library/dom" "^10.3.1" + "@testing-library/user-event" "^14.5.2" + "@vitest/utils" "2.0.4" + magic-string "^0.30.10" + msw "^2.3.1" + sirv "^2.0.4" + ws "^8.18.0" + +"@vitest/expect@2.0.4": + version "2.0.4" + resolved "https://registry.yarnpkg.com/@vitest/expect/-/expect-2.0.4.tgz#d365c106c84f2a3aae96000e95be21956acc099c" + integrity sha512-39jr5EguIoanChvBqe34I8m1hJFI4+jxvdOpD7gslZrVQBKhh8H9eD7J/LJX4zakrw23W+dITQTDqdt43xVcJw== + dependencies: + "@vitest/spy" "2.0.4" + "@vitest/utils" "2.0.4" + chai "^5.1.1" + tinyrainbow "^1.2.0" + +"@vitest/pretty-format@2.0.4", "@vitest/pretty-format@^2.0.4": + version "2.0.4" + resolved "https://registry.yarnpkg.com/@vitest/pretty-format/-/pretty-format-2.0.4.tgz#9a3934932e7f8ddd836b38c34ddaeec91bd0f82e" + integrity sha512-RYZl31STbNGqf4l2eQM1nvKPXE0NhC6Eq0suTTePc4mtMQ1Fn8qZmjV4emZdEdG2NOWGKSCrHZjmTqDCDoeFBw== + dependencies: + tinyrainbow "^1.2.0" + +"@vitest/runner@2.0.4": + version "2.0.4" + resolved "https://registry.yarnpkg.com/@vitest/runner/-/runner-2.0.4.tgz#0b1edb8ab5f81a1c7dfd50090e5e7e971a117891" + integrity sha512-Gk+9Su/2H2zNfNdeJR124gZckd5st4YoSuhF1Rebi37qTXKnqYyFCd9KP4vl2cQHbtuVKjfEKrNJxHHCW8thbQ== + dependencies: + "@vitest/utils" "2.0.4" + pathe "^1.1.2" + +"@vitest/snapshot@2.0.4": + version "2.0.4" + resolved "https://registry.yarnpkg.com/@vitest/snapshot/-/snapshot-2.0.4.tgz#7d7dea9df17c5c13386f1a7a433b99dc0ffe3c14" + integrity sha512-or6Mzoz/pD7xTvuJMFYEtso1vJo1S5u6zBTinfl+7smGUhqybn6VjzCDMhmTyVOFWwkCMuNjmNNxnyXPgKDoPw== + dependencies: + "@vitest/pretty-format" "2.0.4" + magic-string "^0.30.10" + pathe "^1.1.2" + +"@vitest/spy@2.0.4": + version "2.0.4" + resolved "https://registry.yarnpkg.com/@vitest/spy/-/spy-2.0.4.tgz#19083386a741a158c2f142beffe43be68b1375cf" + integrity sha512-uTXU56TNoYrTohb+6CseP8IqNwlNdtPwEO0AWl+5j7NelS6x0xZZtP0bDWaLvOfUbaYwhhWp1guzXUxkC7mW7Q== + dependencies: + tinyspy "^3.0.0" + +"@vitest/utils@2.0.4": + version "2.0.4" + resolved "https://registry.yarnpkg.com/@vitest/utils/-/utils-2.0.4.tgz#2db1df35aaeb5caa932770a190df636a68d284d5" + integrity sha512-Zc75QuuoJhOBnlo99ZVUkJIuq4Oj0zAkrQ2VzCqNCx6wAwViHEh5Fnp4fiJTE9rA+sAoXRf00Z9xGgfEzV6fzQ== + dependencies: + "@vitest/pretty-format" "2.0.4" + estree-walker "^3.0.3" + loupe "^3.1.1" + tinyrainbow "^1.2.0" + "@webassemblyjs/ast@1.12.1", "@webassemblyjs/ast@^1.12.1": version "1.12.1" resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.12.1.tgz#bb16a0e8b1914f979f45864c23819cc3e3f0d4bb" @@ -1962,14 +2520,6 @@ JSONStream@^1.0.4: jsonparse "^1.2.0" through ">=2.2.7 <3" -accepts@~1.3.4: - version "1.3.8" - resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.8.tgz#0bf0be125b67014adcb0b0921e62db7bffe16b2e" - integrity sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw== - dependencies: - mime-types "~2.1.34" - negotiator "0.6.3" - acorn-import-attributes@^1.9.5: version "1.9.5" resolved "https://registry.yarnpkg.com/acorn-import-attributes/-/acorn-import-attributes-1.9.5.tgz#7eb1557b1ba05ef18b5ed0ec67591bfab04688ef" @@ -1980,7 +2530,12 @@ acorn-jsx@^5.3.2: resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937" integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ== -acorn@^8.7.1, acorn@^8.8.2, acorn@^8.9.0: +acorn@^8.7.1, acorn@^8.8.2: + version "8.12.1" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.12.1.tgz#71616bdccbe25e27a54439e0046e89ca76df2248" + integrity sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg== + +acorn@^8.9.0: version "8.11.3" resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.11.3.tgz#71e0b14e13a4ec160724b38fb7b0f233b1b81d7a" integrity sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg== @@ -2044,17 +2599,12 @@ ajv@^8.0.0, ajv@^8.9.0: require-from-string "^2.0.2" uri-js "^4.2.2" -ansi-colors@4.1.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.1.tgz#cbb9ae256bf750af1eab344f229aa27fe94ba348" - integrity sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA== - ansi-escapes@^3.0.0, ansi-escapes@^3.2.0: version "3.2.0" resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-3.2.0.tgz#8780b98ff9dbf5638152d1f1fe5c1d7b4442976b" integrity sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ== -ansi-escapes@^4.2.1: +ansi-escapes@^4.2.1, ansi-escapes@^4.3.2: version "4.3.2" resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-4.3.2.tgz#6b2291d1db7d98b6521d5f1efa42d0f3a9feb65e" integrity sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ== @@ -2369,10 +2919,10 @@ assert-plus@1.0.0, assert-plus@^1.0.0: resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525" integrity sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw== -assertion-error@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/assertion-error/-/assertion-error-1.1.0.tgz#e60b6b0e8f301bd97e5375215bda406c85118c0b" - integrity sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw== +assertion-error@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/assertion-error/-/assertion-error-2.0.1.tgz#f641a196b335690b1070bf00b6e7593fec190bf7" + integrity sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA== assign-symbols@^1.0.0: version "1.0.0" @@ -2539,11 +3089,6 @@ base64-js@^1.3.1: resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== -base64id@2.0.0, base64id@~2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/base64id/-/base64id-2.0.0.tgz#2770ac6bc47d312af97a8bf9a634342e0cd25cb6" - integrity sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog== - base@^0.11.1: version "0.11.2" resolved "https://registry.yarnpkg.com/base/-/base-0.11.2.tgz#7bde5ced145b6d551a90db87f83c558b4eb48a8f" @@ -2587,24 +3132,6 @@ bl@^5.0.0: inherits "^2.0.4" readable-stream "^3.4.0" -body-parser@^1.19.0: - version "1.20.2" - resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.20.2.tgz#6feb0e21c4724d06de7ff38da36dad4f57a747fd" - integrity sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA== - dependencies: - bytes "3.1.2" - content-type "~1.0.5" - debug "2.6.9" - depd "2.0.0" - destroy "1.2.0" - http-errors "2.0.0" - iconv-lite "0.4.24" - on-finished "2.4.1" - qs "6.11.0" - raw-body "2.5.2" - type-is "~1.6.18" - unpipe "1.0.0" - brace-expansion@^1.1.7: version "1.1.11" resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" @@ -2650,12 +3177,7 @@ braces@^3.0.3: dependencies: fill-range "^7.1.1" -browser-stdout@1.3.1: - version "1.3.1" - resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.1.tgz#baa559ee14ced73452229bad7326467c61fabd60" - integrity sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw== - -browserslist@^4.16.1, browserslist@^4.21.10, browserslist@^4.22.2, browserslist@^4.22.3: +browserslist@^4.16.1, browserslist@^4.22.2, browserslist@^4.22.3: version "4.23.0" resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.23.0.tgz#8f3acc2bbe73af7213399430890f86c63a5674ab" integrity sha512-QW8HiM1shhT2GuzkvklfjcKDiWFXHOeFCIA/huJPwHsslwcydgk7X+z2zXpEijP98UCY7HbubZt5J2Zgvf0CaQ== @@ -2665,6 +3187,16 @@ browserslist@^4.16.1, browserslist@^4.21.10, browserslist@^4.22.2, browserslist@ node-releases "^2.0.14" update-browserslist-db "^1.0.13" +browserslist@^4.21.10, browserslist@^4.23.1: + version "4.23.2" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.23.2.tgz#244fe803641f1c19c28c48c4b6ec9736eb3d32ed" + integrity sha512-qkqSyistMYdxAcw+CzbZwlBy8AGmS/eEWs+sEV5TnLRGDOL+C5M2EnH6tlZyg0YoAxGJAFKh61En9BR941GnHA== + dependencies: + caniuse-lite "^1.0.30001640" + electron-to-chromium "^1.4.820" + node-releases "^2.0.14" + update-browserslist-db "^1.1.0" + buffer-from@^1.0.0: version "1.1.2" resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" @@ -2696,10 +3228,10 @@ builtins@^1.0.3: resolved "https://registry.yarnpkg.com/builtins/-/builtins-1.0.3.tgz#cb94faeb61c8696451db36534e1422f94f0aee88" integrity sha512-uYBjakWipfaO/bXI7E8rq6kpwHRZK5cNYrUv2OzZSI/FvmdMyXJ2tG9dKcjEC5YHmHpUAwsargWIZNWdxb/bnQ== -bytes@3.1.2: - version "3.1.2" - resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.2.tgz#8b0beeb98605adf1b128fa4386403c009e0221a5" - integrity sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg== +cac@^6.7.14: + version "6.7.14" + resolved "https://registry.yarnpkg.com/cac/-/cac-6.7.14.tgz#804e1e6f506ee363cb0e3ccbb09cad5dd9870959" + integrity sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ== cache-base@^1.0.1: version "1.0.1" @@ -2756,33 +3288,31 @@ camelcase@^5.0.0, camelcase@^5.3.1: resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== -camelcase@^6.0.0: - version "6.3.0" - resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.3.0.tgz#5685b95eb209ac9c0c177467778c9c84df58ba9a" - integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== - caniuse-lite@^1.0.30001587: version "1.0.30001599" resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001599.tgz#571cf4f3f1506df9bf41fcbb6d10d5d017817bce" integrity sha512-LRAQHZ4yT1+f9LemSMeqdMpMxZcc4RMWdj4tiFe3G8tNkWK+E58g+/tzotb5cU6TbcVJLr4fySiAW7XmxQvZQA== +caniuse-lite@^1.0.30001640: + version "1.0.30001643" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001643.tgz#9c004caef315de9452ab970c3da71085f8241dbd" + integrity sha512-ERgWGNleEilSrHM6iUz/zJNSQTP8Mr21wDWpdgvRwcTXGAq6jMtOUPP4dqFPTdKqZ2wKTdtB+uucZ3MRpAUSmg== + caseless@~0.12.0: version "0.12.0" resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" integrity sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw== -chai@^4.3.10: - version "4.4.1" - resolved "https://registry.yarnpkg.com/chai/-/chai-4.4.1.tgz#3603fa6eba35425b0f2ac91a009fe924106e50d1" - integrity sha512-13sOfMv2+DWduEU+/xbun3LScLoqN17nBeTLUsmDfKdoiC1fr0n9PU4guu4AhRcOVFk/sW8LyZWHuhWtQZiF+g== +chai@^5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/chai/-/chai-5.1.1.tgz#f035d9792a22b481ead1c65908d14bb62ec1c82c" + integrity sha512-pT1ZgP8rPNqUgieVaEY+ryQr6Q4HXNg8Ei9UnLUrjN4IA7dvQC5JB+/kxVcPNDHyBcc/26CXPkbNzq3qwrOEKA== dependencies: - assertion-error "^1.1.0" - check-error "^1.0.3" - deep-eql "^4.1.3" - get-func-name "^2.0.2" - loupe "^2.3.6" - pathval "^1.1.1" - type-detect "^4.0.8" + assertion-error "^2.0.1" + check-error "^2.1.1" + deep-eql "^5.0.1" + loupe "^3.1.0" + pathval "^2.0.0" chalk@^1.0.0, chalk@^1.1.3: version "1.1.3" @@ -2795,7 +3325,7 @@ chalk@^1.0.0, chalk@^1.1.3: strip-ansi "^3.0.0" supports-color "^2.0.0" -chalk@^2.0.1, chalk@^2.1.0, chalk@^2.3.0, chalk@^2.4.1, chalk@^2.4.2: +chalk@^2.3.0, chalk@^2.4.1, chalk@^2.4.2: version "2.4.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== @@ -2829,12 +3359,10 @@ charm@^1.0.2: dependencies: inherits "^2.0.1" -check-error@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/check-error/-/check-error-1.0.3.tgz#a6502e4312a7ee969f646e83bb3ddd56281bd694" - integrity sha512-iKEoDYaRmd1mxM90a2OEfWhjsjPpYPuQ+lMYsoxB126+t8fw7ySEO48nmDg5COTjxDI65/Y2OWpeEHk3ZOe8zg== - dependencies: - get-func-name "^2.0.2" +check-error@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/check-error/-/check-error-2.1.1.tgz#87eb876ae71ee388fa0471fe423f494be1d96ccc" + integrity sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw== cherry-pick@^0.5.0: version "0.5.0" @@ -2847,22 +3375,7 @@ cherry-pick@^0.5.0: tiny-glob "^0.2.6" yargs "^13.2.4" -chokidar@3.5.3: - version "3.5.3" - resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.3.tgz#1cf37c8707b932bd1af1ae22c0432e2acd1903bd" - integrity sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw== - dependencies: - anymatch "~3.1.2" - braces "~3.0.2" - glob-parent "~5.1.2" - is-binary-path "~2.1.0" - is-glob "~4.0.1" - normalize-path "~3.0.0" - readdirp "~3.6.0" - optionalDependencies: - fsevents "~2.3.2" - -chokidar@^3.4.0, chokidar@^3.5.1: +chokidar@^3.4.0: version "3.6.0" resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.6.0.tgz#197c6cc669ef2a8dc5e7b4d97ee4e092c3eb0d5b" integrity sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw== @@ -2883,9 +3396,9 @@ chownr@^2.0.0: integrity sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ== chrome-trace-event@^1.0.2: - version "1.0.3" - resolved "https://registry.yarnpkg.com/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz#1015eced4741e15d06664a957dbbf50d041e26ac" - integrity sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg== + version "1.0.4" + resolved "https://registry.yarnpkg.com/chrome-trace-event/-/chrome-trace-event-1.0.4.tgz#05bffd7ff928465093314708c93bdfa9bd1f0f5b" + integrity sha512-rNjApaLzuwaOTjCiT8lSDdGN1APCiqkChLMJxJPWLunPAt5fy8xgU9/jNOchV84wfIxrA0lRQB7oCT8jrn/wrQ== ci-info@^3.2.0: version "3.9.0" @@ -2933,7 +3446,7 @@ cli-cursor@^4.0.0: dependencies: restore-cursor "^4.0.0" -cli-spinners@^2.5.0, cli-spinners@^2.6.1: +cli-spinners@^2.5.0, cli-spinners@^2.6.1, cli-spinners@^2.9.2: version "2.9.2" resolved "https://registry.yarnpkg.com/cli-spinners/-/cli-spinners-2.9.2.tgz#1773a8f4b9c4d6ac31563df53b3fc1d79462fe41" integrity sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg== @@ -2964,6 +3477,11 @@ cli-width@^3.0.0: resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-3.0.0.tgz#a2f48437a2caa9a22436e794bf071ec9e61cedf6" integrity sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw== +cli-width@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-4.1.0.tgz#42daac41d3c254ef38ad8ac037672130173691c5" + integrity sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ== + cliui@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/cliui/-/cliui-5.0.0.tgz#deefcfdb2e800784aa34f46fa08e06851c7bbbc5" @@ -3137,26 +3655,11 @@ confusing-browser-globals@^1.0.10: resolved "https://registry.yarnpkg.com/confusing-browser-globals/-/confusing-browser-globals-1.0.11.tgz#ae40e9b57cdd3915408a2805ebd3a5585608dc81" integrity sha512-JsPKdmh8ZkmnHxDk55FZ1TqVLvEQTvoByJZRN9jzI0UjxK/QgAmsphz7PGtqgPieQZ/CQcHWXCR7ATDNhGe+YA== -connect@^3.7.0: - version "3.7.0" - resolved "https://registry.yarnpkg.com/connect/-/connect-3.7.0.tgz#5d49348910caa5e07a01800b030d0c35f20484f8" - integrity sha512-ZqRXc+tZukToSNmh5C2iWMSoV3X1YUcPbqEM4DkEG5tNQXrQUZCNVGGv3IuicnkMtPfGf3Xtp8WCXs295iQ1pQ== - dependencies: - debug "2.6.9" - finalhandler "1.1.2" - parseurl "~1.3.3" - utils-merge "1.0.1" - console-control-strings@^1.0.0, console-control-strings@~1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e" integrity sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ== -content-type@~1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.5.tgz#8b773162656d1d1086784c8f23a54ce6d73d7918" - integrity sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA== - conventional-changelog-angular@^5.0.12: version "5.0.13" resolved "https://registry.yarnpkg.com/conventional-changelog-angular/-/conventional-changelog-angular-5.0.13.tgz#896885d63b914a70d4934b59d2fe7bde1832b28c" @@ -3331,10 +3834,10 @@ convert-source-map@^2.0.0: resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-2.0.0.tgz#4b560f649fc4e918dd0ab75cf4961e8bc882d82a" integrity sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg== -cookie@~0.4.1: - version "0.4.2" - resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.4.2.tgz#0e41f24de5ecf317947c82fc789e06a884824432" - integrity sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA== +cookie@^0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.5.0.tgz#d1f5d71adec6558c58f389987c366aa47e994f8b" + integrity sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw== copy-descriptor@^0.1.0: version "0.1.1" @@ -3358,14 +3861,6 @@ core-util-is@~1.0.0: resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.3.tgz#a6042d3634c2b27e9328f837b965fac83808db85" integrity sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ== -cors@~2.8.5: - version "2.8.5" - resolved "https://registry.yarnpkg.com/cors/-/cors-2.8.5.tgz#eac11da51592dd86b9f06f6e7ac293b3df875d29" - integrity sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g== - dependencies: - object-assign "^4" - vary "^1" - cp-file@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/cp-file/-/cp-file-7.0.0.tgz#b9454cfd07fe3b974ab9ea0e5f29655791a9b8cd" @@ -3420,11 +3915,6 @@ csstype@^3.0.2: resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.1.3.tgz#d80ff294d114fb0e6ac500fbf85b60137d7eff81" integrity sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw== -custom-event@~1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/custom-event/-/custom-event-1.0.1.tgz#5d02a46850adf1b4a317946a3928fccb5bfd0425" - integrity sha512-GAj5FOq0Hd+RsCGVJxZuKaIDXDf3h6GQoNEjFgbLLI/trgtavwUbSnZ5pVfg27DVCaWjIohryS0JFwIJyT2cMg== - damerau-levenshtein@^1.0.8: version "1.0.8" resolved "https://registry.yarnpkg.com/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz#b43d286ccbd36bc5b2f7ed41caf2d0aba1f8a6e7" @@ -3474,30 +3964,25 @@ date-fns@^1.27.2: resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-1.30.1.tgz#2e71bf0b119153dbb4cc4e88d9ea5acfb50dc05c" integrity sha512-hBSVCvSmWC+QypYObzwGOd9wqdDpOt+0wl0KbU+R+uuZBS1jN8VsD1ss3irQDknRj5NvxiTF6oj/nDRnN/UQNw== -date-format@^4.0.14: - version "4.0.14" - resolved "https://registry.yarnpkg.com/date-format/-/date-format-4.0.14.tgz#7a8e584434fb169a521c8b7aa481f355810d9400" - integrity sha512-39BOQLs9ZjKh0/patS9nrT8wc3ioX3/eA/zgbKNopnF2wCqJEoxywwwElATYvRsXdnOxA/OQeQoFZ3rFjVajhg== - dateformat@^3.0.0: version "3.0.3" resolved "https://registry.yarnpkg.com/dateformat/-/dateformat-3.0.3.tgz#a6e37499a4d9a9cf85ef5872044d62901c9889ae" integrity sha512-jyCETtSl3VMZMWeRo7iY1FL19ges1t55hMo5yaam4Jrsm5EPL89UQkoQRyiI+Yf4k8r2ZpdngkV8hr1lIdjb3Q== -debug@2.6.9, debug@^2.2.0, debug@^2.3.3: - version "2.6.9" - resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" - integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== - dependencies: - ms "2.0.0" - -debug@4, debug@4.3.4, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.2, debug@^4.3.4, debug@~4.3.1, debug@~4.3.2, debug@~4.3.4: +debug@4, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.2, debug@^4.3.4, debug@~4.3.4: version "4.3.4" resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== dependencies: ms "2.1.2" +debug@^2.2.0, debug@^2.3.3: + version "2.6.9" + resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" + integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== + dependencies: + ms "2.0.0" + debug@^3.2.7: version "3.2.7" resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a" @@ -3505,6 +3990,13 @@ debug@^3.2.7: dependencies: ms "^2.1.1" +debug@^4.3.5: + version "4.3.5" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.5.tgz#e83444eceb9fedd4a1da56d671ae2446a01a6e1e" + integrity sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg== + dependencies: + ms "2.1.2" + decamelize-keys@^1.1.0: version "1.1.1" resolved "https://registry.yarnpkg.com/decamelize-keys/-/decamelize-keys-1.1.1.tgz#04a2d523b2f18d80d0158a43b895d56dff8d19d8" @@ -3518,22 +4010,15 @@ decamelize@^1.1.0, decamelize@^1.2.0: resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" integrity sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA== -decamelize@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-4.0.0.tgz#aa472d7bf660eb15f3494efd531cab7f2a709837" - integrity sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ== - decode-uri-component@^0.2.0: version "0.2.2" resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.2.tgz#e69dbe25d37941171dd540e024c444cd5188e1e9" integrity sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ== -deep-eql@^4.1.3: - version "4.1.3" - resolved "https://registry.yarnpkg.com/deep-eql/-/deep-eql-4.1.3.tgz#7c7775513092f7df98d8df9996dd085eb668cc6d" - integrity sha512-WaEtAOpRA1MQ0eohqZjpGD8zdI0Ovsm8mmFhaDN8dvDZzyoUMcYDnf5Y6iu7HTXxf8JDS23qWa4a+hKCDyOPzw== - dependencies: - type-detect "^4.0.0" +deep-eql@^5.0.1: + version "5.0.2" + resolved "https://registry.yarnpkg.com/deep-eql/-/deep-eql-5.0.2.tgz#4b756d8d770a9257300825d52a2c2cff99c3a341" + integrity sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q== deep-is@^0.1.3: version "0.1.4" @@ -3597,41 +4082,16 @@ delegates@^1.0.0: resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a" integrity sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ== -depd@2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/depd/-/depd-2.0.0.tgz#b696163cc757560d09cf22cc8fad1571b79e76df" - integrity sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw== - dequal@^2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/dequal/-/dequal-2.0.3.tgz#2644214f1997d39ed0ee0ece72335490a7ac67be" integrity sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA== -destroy@1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.2.0.tgz#4803735509ad8be552934c67df614f94e66fa015" - integrity sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg== - -di@^0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/di/-/di-0.0.1.tgz#806649326ceaa7caa3306d75d985ea2748ba913c" - integrity sha512-uJaamHkagcZtHPqCIHZxnFrXlunQXgBOsZSUOWwFw31QJCAbyTBoHMW75YOTur5ZNx8pIeAKgf6GWIgaqqiLhA== - -diff@5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/diff/-/diff-5.0.0.tgz#7ed6ad76d859d030787ec35855f5b1daf31d852b" - integrity sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w== - diff@^3.2.0: version "3.5.0" resolved "https://registry.yarnpkg.com/diff/-/diff-3.5.0.tgz#800c0dd1e0a8bfbc95835c202ad220fe317e5a12" integrity sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA== -diff@^5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/diff/-/diff-5.2.0.tgz#26ded047cd1179b78b9537d5ef725503ce1ae531" - integrity sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A== - dir-glob@^2.2.2: version "2.2.2" resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-2.2.2.tgz#fa09f0694153c8918b18ba0deafae94769fc50c4" @@ -3673,16 +4133,6 @@ dom-helpers@^5.0.1, dom-helpers@^5.2.0, dom-helpers@^5.2.1: "@babel/runtime" "^7.8.7" csstype "^3.0.2" -dom-serialize@^2.2.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/dom-serialize/-/dom-serialize-2.2.1.tgz#562ae8999f44be5ea3076f5419dcd59eb43ac95b" - integrity sha512-Yra4DbvoW7/Z6LBN560ZwXMjoNOSAN2wRsKFGc4iBeso+mpIA6qj1vfdf9HpMaKAqG6wXTy+1SYEzmNpKXOSsQ== - dependencies: - custom-event "~1.0.0" - ent "~2.2.0" - extend "^3.0.0" - void-elements "^2.0.0" - dot-prop@^5.1.0: version "5.3.0" resolved "https://registry.yarnpkg.com/dot-prop/-/dot-prop-5.3.0.tgz#90ccce708cd9cd82cc4dc8c3ddd9abdd55b20e88" @@ -3726,16 +4176,16 @@ ecc-jsbn@~0.1.1: jsbn "~0.1.0" safer-buffer "^2.1.0" -ee-first@1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" - integrity sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow== - electron-to-chromium@^1.4.668: version "1.4.708" resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.708.tgz#d54d3b47cb44ae6b190067439c42135456907893" integrity sha512-iWgEEvREL4GTXXHKohhh33+6Y8XkPI5eHihDmm8zUk5Zo7HICEW+wI/j5kJ2tbuNUCXJ/sNXa03ajW635DiJXA== +electron-to-chromium@^1.4.820: + version "1.4.833" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.833.tgz#463a37538b40ece154d4741eac4e9f076d9c3b32" + integrity sha512-aVGP9xK70Ysrzip1m5LoJjCp1EDrYzZ7Pg/O3QR1h3PAhmc8SNfSXV3kmmtkg5rNO42EcTYmLX3eFMgqALlGIA== + elegant-spinner@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/elegant-spinner/-/elegant-spinner-1.0.1.tgz#db043521c95d7e303fd8f345bedc3349cfb0729e" @@ -3761,32 +4211,6 @@ emoji-regex@^9.2.2: resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-9.2.2.tgz#840c8803b0d8047f4ff0cf963176b32d4ef3ed72" integrity sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg== -encodeurl@~1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" - integrity sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w== - -engine.io-parser@~5.2.1: - version "5.2.2" - resolved "https://registry.yarnpkg.com/engine.io-parser/-/engine.io-parser-5.2.2.tgz#37b48e2d23116919a3453738c5720455e64e1c49" - integrity sha512-RcyUFKA93/CXH20l4SoVvzZfrSDMOTUS3bWVpTt2FuFP+XYrL8i8oonHP7WInRyVHXh0n/ORtoeiE1os+8qkSw== - -engine.io@~6.5.2: - version "6.5.4" - resolved "https://registry.yarnpkg.com/engine.io/-/engine.io-6.5.4.tgz#6822debf324e781add2254e912f8568508850cdc" - integrity sha512-KdVSDKhVKyOi+r5uEabrDLZw2qXStVvCsEB/LN3mw4WFi6Gx50jTyuxYVCwAAC0U46FdnzP/ScKRBTXb/NiEOg== - dependencies: - "@types/cookie" "^0.4.1" - "@types/cors" "^2.8.12" - "@types/node" ">=10.0.0" - accepts "~1.3.4" - base64id "2.0.0" - cookie "~0.4.1" - cors "~2.8.5" - debug "~4.3.1" - engine.io-parser "~5.2.1" - ws "~8.11.0" - enhanced-resolve@^0.9.1: version "0.9.1" resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-0.9.1.tgz#4d6e689b3725f86090927ccc86cd9f1635b89e2e" @@ -3797,18 +4221,13 @@ enhanced-resolve@^0.9.1: tapable "^0.1.8" enhanced-resolve@^5.17.0: - version "5.17.0" - resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.17.0.tgz#d037603789dd9555b89aaec7eb78845c49089bc5" - integrity sha512-dwDPwZL0dmye8Txp2gzFmA6sxALaSvdRDjPH0viLcKrtlOL3tw62nWWweVD1SdILDTJrbrL6tdWVN58Wo6U3eA== + version "5.17.1" + resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.17.1.tgz#67bfbbcc2f81d511be77d686a90267ef7f898a15" + integrity sha512-LMHl3dXhTcfv8gM4kEzIUeTQ+7fpdA0l2tUf34BddXPkz2A5xJ5L/Pchd5BL6rdccM9QGvu0sWZzK1Z1t4wwyg== dependencies: graceful-fs "^4.2.4" tapable "^2.2.0" -ent@~2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/ent/-/ent-2.2.0.tgz#e964219325a21d05f44466a2f686ed6ce5f5dd1d" - integrity sha512-GHrMyVZQWvTIdDtpiEXdHZnFQKzeO09apj8Cbl4pKWy4i0Oprcq17usfDt5aO63swf0JOeMWjWQE/LzgSRuWpA== - error-ex@^1.3.1: version "1.3.2" resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" @@ -4025,9 +4444,9 @@ es-iterator-helpers@^1.0.19: safe-array-concat "^1.1.2" es-module-lexer@^1.2.1: - version "1.4.1" - resolved "https://registry.yarnpkg.com/es-module-lexer/-/es-module-lexer-1.4.1.tgz#41ea21b43908fe6a287ffcbe4300f790555331f5" - integrity sha512-cXLGjP0c4T3flZJKQSuziYoq7MlT+rnvfZjfp7h+I7K9BNX54kP9nyWvdbwjQ4u1iWbOL4u96fgeZLToQlZC7w== + version "1.5.4" + resolved "https://registry.yarnpkg.com/es-module-lexer/-/es-module-lexer-1.5.4.tgz#a8efec3a3da991e60efa6b633a7cad6ab8d26b78" + integrity sha512-MVNK56NiMrOwitFB7cqDwq0CQutbw+0BvLshJSse0MUNU+y1FC3bUS/AQg7oUng+/wKrrki7JfmwtVHkVfPLlw== es-object-atoms@^1.0.0: version "1.0.0" @@ -4061,26 +4480,50 @@ es-to-primitive@^1.2.1: is-date-object "^1.0.1" is-symbol "^1.0.2" -escalade@^3.1.1: +esbuild@^0.21.3: + version "0.21.5" + resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.21.5.tgz#9ca301b120922959b766360d8ac830da0d02997d" + integrity sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw== + optionalDependencies: + "@esbuild/aix-ppc64" "0.21.5" + "@esbuild/android-arm" "0.21.5" + "@esbuild/android-arm64" "0.21.5" + "@esbuild/android-x64" "0.21.5" + "@esbuild/darwin-arm64" "0.21.5" + "@esbuild/darwin-x64" "0.21.5" + "@esbuild/freebsd-arm64" "0.21.5" + "@esbuild/freebsd-x64" "0.21.5" + "@esbuild/linux-arm" "0.21.5" + "@esbuild/linux-arm64" "0.21.5" + "@esbuild/linux-ia32" "0.21.5" + "@esbuild/linux-loong64" "0.21.5" + "@esbuild/linux-mips64el" "0.21.5" + "@esbuild/linux-ppc64" "0.21.5" + "@esbuild/linux-riscv64" "0.21.5" + "@esbuild/linux-s390x" "0.21.5" + "@esbuild/linux-x64" "0.21.5" + "@esbuild/netbsd-x64" "0.21.5" + "@esbuild/openbsd-x64" "0.21.5" + "@esbuild/sunos-x64" "0.21.5" + "@esbuild/win32-arm64" "0.21.5" + "@esbuild/win32-ia32" "0.21.5" + "@esbuild/win32-x64" "0.21.5" + +escalade@^3.1.1, escalade@^3.1.2: version "3.1.2" resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.2.tgz#54076e9ab29ea5bf3d8f1ed62acffbb88272df27" integrity sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA== -escape-html@~1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" - integrity sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow== - -escape-string-regexp@4.0.0, escape-string-regexp@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" - integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== - escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" integrity sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg== +escape-string-regexp@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" + integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== + eslint-config-4catalyzer-typescript@^3.3.0: version "3.3.0" resolved "https://registry.yarnpkg.com/eslint-config-4catalyzer-typescript/-/eslint-config-4catalyzer-typescript-3.3.0.tgz#d383f74080ceb10ee80ea9030019b3bd074cf8f5" @@ -4190,15 +4633,6 @@ eslint-plugin-jsx-a11y@^6.8.0: object.entries "^1.1.7" object.fromentries "^2.0.7" -eslint-plugin-mocha@^10.4.3: - version "10.4.3" - resolved "https://registry.yarnpkg.com/eslint-plugin-mocha/-/eslint-plugin-mocha-10.4.3.tgz#bf641379d9f1c7d6a84646a3fc1a0baa50da8bfd" - integrity sha512-emc4TVjq5Ht0/upR+psftuz6IBG5q279p+1dSRDeHf+NS9aaerBi3lXKo1SEzwC29hFIW21gO89CEWSvRsi8IQ== - dependencies: - eslint-utils "^3.0.0" - globals "^13.24.0" - rambda "^7.4.0" - eslint-plugin-prettier@^5.1.3: version "5.1.3" resolved "https://registry.yarnpkg.com/eslint-plugin-prettier/-/eslint-plugin-prettier-5.1.3.tgz#17cfade9e732cef32b5f5be53bd4e07afd8e67e1" @@ -4252,14 +4686,7 @@ eslint-scope@^7.2.2: esrecurse "^4.3.0" estraverse "^5.2.0" -eslint-utils@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-3.0.0.tgz#8aebaface7345bb33559db0a1f13a1d2d48c3672" - integrity sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA== - dependencies: - eslint-visitor-keys "^2.0.0" - -eslint-visitor-keys@^2.0.0, eslint-visitor-keys@^2.1.0: +eslint-visitor-keys@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz#f65328259305927392c938ed44eb0a5c9b2bd303" integrity sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw== @@ -4351,16 +4778,18 @@ estraverse@^5.1.0, estraverse@^5.2.0, estraverse@^5.3.0: resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.3.0.tgz#2eea5290702f26ab8fe5370370ff86c965d21123" integrity sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA== +estree-walker@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-3.0.3.tgz#67c3e549ec402a487b4fc193d1953a524752340d" + integrity sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g== + dependencies: + "@types/estree" "^1.0.0" + esutils@^2.0.2: version "2.0.3" resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== -eventemitter3@^4.0.0: - version "4.0.7" - resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.7.tgz#2de9b68f6528d5644ef5c59526a1b4a07306169f" - integrity sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw== - eventemitter3@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-5.0.1.tgz#53f5ffd0a492ac800721bb42c66b841de96423c4" @@ -4401,7 +4830,7 @@ execa@^6.0.0: signal-exit "^3.0.7" strip-final-newline "^3.0.0" -execa@~8.0.1: +execa@^8.0.1, execa@~8.0.1: version "8.0.1" resolved "https://registry.yarnpkg.com/execa/-/execa-8.0.1.tgz#51f6a5943b580f963c3ca9c6321796db8cc39b8c" integrity sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg== @@ -4444,7 +4873,7 @@ extend-shallow@^3.0.0, extend-shallow@^3.0.2: assign-symbols "^1.0.0" is-extendable "^1.0.1" -extend@^3.0.0, extend@~3.0.2: +extend@~3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g== @@ -4597,19 +5026,6 @@ fill-range@^7.1.1: dependencies: to-regex-range "^5.0.1" -finalhandler@1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.1.2.tgz#b7e7d000ffd11938d0fdb053506f6ebabe9f587d" - integrity sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA== - dependencies: - debug "2.6.9" - encodeurl "~1.0.2" - escape-html "~1.0.3" - on-finished "~2.3.0" - parseurl "~1.3.3" - statuses "~1.5.0" - unpipe "~1.0.0" - find-cache-dir@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-2.1.0.tgz#8d0f94cd13fe43c6c7c261a0d86115ca918c05f7" @@ -4632,14 +5048,6 @@ find-root@^1.1.0: resolved "https://registry.yarnpkg.com/find-root/-/find-root-1.1.0.tgz#abcfc8ba76f708c42a97b3d685b7e9450bfb9ce4" integrity sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng== -find-up@5.0.0, find-up@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/find-up/-/find-up-5.0.0.tgz#4c92819ecb7083561e4f4a240a86be5198f536fc" - integrity sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng== - dependencies: - locate-path "^6.0.0" - path-exists "^4.0.0" - find-up@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/find-up/-/find-up-2.1.0.tgz#45d1b7e506c717ddd482775a2b77920a3c0c57a7" @@ -4662,6 +5070,14 @@ find-up@^4.0.0, find-up@^4.1.0: locate-path "^5.0.0" path-exists "^4.0.0" +find-up@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-5.0.0.tgz#4c92819ecb7083561e4f4a240a86be5198f536fc" + integrity sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng== + dependencies: + locate-path "^6.0.0" + path-exists "^4.0.0" + find-up@^6.3.0: version "6.3.0" resolved "https://registry.yarnpkg.com/find-up/-/find-up-6.3.0.tgz#2abab3d3280b2dc7ac10199ef324c4e002c8c790" @@ -4679,21 +5095,11 @@ flat-cache@^3.0.4: keyv "^4.5.3" rimraf "^3.0.2" -flat@^5.0.2: - version "5.0.2" - resolved "https://registry.yarnpkg.com/flat/-/flat-5.0.2.tgz#8ca6fe332069ffa9d324c327198c598259ceb241" - integrity sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ== - -flatted@^3.2.7, flatted@^3.2.9: +flatted@^3.2.9: version "3.3.1" resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.3.1.tgz#21db470729a6734d4997002f439cb308987f567a" integrity sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw== -follow-redirects@^1.0.0: - version "1.15.6" - resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.6.tgz#7f815c0cda4249c74ff09e95ef97c23b5fd0399b" - integrity sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA== - for-each@^0.3.3: version "0.3.3" resolved "https://registry.yarnpkg.com/for-each/-/for-each-0.3.3.tgz#69b447e88a0a5d32c3e7084f3f1710034b21376e" @@ -4745,15 +5151,6 @@ fs-extra@^6.0.1: jsonfile "^4.0.0" universalify "^0.1.0" -fs-extra@^8.1.0: - version "8.1.0" - resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-8.1.0.tgz#49d43c45a88cd9677668cb7be1b46efdb8d2e1c0" - integrity sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g== - dependencies: - graceful-fs "^4.2.0" - jsonfile "^4.0.0" - universalify "^0.1.0" - fs-minipass@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-2.1.0.tgz#7f5036fdbf12c63c169190cbe4199c852271f9fb" @@ -4771,7 +5168,12 @@ fs.realpath@^1.0.0: resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== -fsevents@~2.3.2: +fsevents@2.3.2: + version "2.3.2" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a" + integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA== + +fsevents@~2.3.2, fsevents@~2.3.3: version "2.3.3" resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6" integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw== @@ -4825,7 +5227,7 @@ get-east-asian-width@^1.0.0: resolved "https://registry.yarnpkg.com/get-east-asian-width/-/get-east-asian-width-1.2.0.tgz#5e6ebd9baee6fb8b7b6bd505221065f0cd91f64e" integrity sha512-2nk+7SIVb14QrgXFHcm84tD4bKQz0RxPuMT8Ag5KPOq7J5fEmAg0UbXdTOSHqNuHSU28k55qnceesxXRZGzKWA== -get-func-name@^2.0.1, get-func-name@^2.0.2: +get-func-name@^2.0.1: version "2.0.2" resolved "https://registry.yarnpkg.com/get-func-name/-/get-func-name-2.0.2.tgz#0d7cf20cd13fda808669ffa88f4ffc7a3943fc41" integrity sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ== @@ -4958,18 +5360,7 @@ glob-to-regexp@^0.4.1: resolved "https://registry.yarnpkg.com/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz#c75297087c851b9a578bd217dd59a92f59fe546e" integrity sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw== -glob@8.1.0: - version "8.1.0" - resolved "https://registry.yarnpkg.com/glob/-/glob-8.1.0.tgz#d388f656593ef708ee3e34640fdfb99a9fd1c33e" - integrity sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ== - dependencies: - fs.realpath "^1.0.0" - inflight "^1.0.4" - inherits "2" - minimatch "^5.0.1" - once "^1.3.0" - -glob@^7.1.1, glob@^7.1.3, glob@^7.1.4, glob@^7.1.7, glob@^7.2.0: +glob@^7.1.1, glob@^7.1.3, glob@^7.1.4, glob@^7.2.0: version "7.2.3" resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b" integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q== @@ -4986,7 +5377,7 @@ globals@^11.1.0: resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== -globals@^13.19.0, globals@^13.24.0: +globals@^13.19.0: version "13.24.0" resolved "https://registry.yarnpkg.com/globals/-/globals-13.24.0.tgz#8432a19d78ce0c1e833949c36adb345400bb1171" integrity sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ== @@ -5055,7 +5446,7 @@ gopd@^1.0.1: dependencies: get-intrinsic "^1.1.3" -graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.10, graceful-fs@^4.2.11, graceful-fs@^4.2.4, graceful-fs@^4.2.6: +graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.11, graceful-fs@^4.2.4: version "4.2.11" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3" integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== @@ -5065,6 +5456,11 @@ graphemer@^1.4.0: resolved "https://registry.yarnpkg.com/graphemer/-/graphemer-1.4.0.tgz#fb2f1d55e0e3a1849aeffc90c4fa0dd53a0e66c6" integrity sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag== +graphql@^16.8.1: + version "16.9.0" + resolved "https://registry.yarnpkg.com/graphql/-/graphql-16.9.0.tgz#1c310e63f16a49ce1fbb230bd0a000e99f6f115f" + integrity sha512-GGTKBX4SD7Wdb8mqeDLni2oaRGYQWjWHGKPQ24ZMnUtKfcsVoiv4uX8+LJr1K6U5VW2Lu1BwJnj7uiori0YtRw== + handlebars@^4.7.7: version "4.7.8" resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.7.8.tgz#41c42c18b1be2365439188c77c6afae71c0cd9e9" @@ -5196,10 +5592,10 @@ hasown@^2.0.0, hasown@^2.0.1, hasown@^2.0.2: dependencies: function-bind "^1.1.2" -he@1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" - integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== +headers-polyfill@^4.0.2: + version "4.0.3" + resolved "https://registry.yarnpkg.com/headers-polyfill/-/headers-polyfill-4.0.3.tgz#922a0155de30ecc1f785bcf04be77844ca95ad07" + integrity sha512-IScLbePpkvO846sIwOtOTDjutRMWdXdJmXdMvk6gCBHxFO8d+QKOQedyZSxFTTFYRSmlgSTDtXqqq4pcenBXLQ== hosted-git-info@^2.1.4: version "2.8.9" @@ -5213,22 +5609,6 @@ hosted-git-info@^4.0.0, hosted-git-info@^4.0.1: dependencies: lru-cache "^6.0.0" -html-escaper@^2.0.0: - version "2.0.2" - resolved "https://registry.yarnpkg.com/html-escaper/-/html-escaper-2.0.2.tgz#dfd60027da36a36dfcbe236262c00a5822681453" - integrity sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg== - -http-errors@2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-2.0.0.tgz#b7774a1486ef73cf7667ac9ae0858c012c57b9d3" - integrity sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ== - dependencies: - depd "2.0.0" - inherits "2.0.4" - setprototypeof "1.2.0" - statuses "2.0.1" - toidentifier "1.0.1" - http-proxy-agent@^4.0.0: version "4.0.1" resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz#8a8c8ef7f5932ccf953c296ca8291b95aa74aa3a" @@ -5238,15 +5618,6 @@ http-proxy-agent@^4.0.0: agent-base "6" debug "4" -http-proxy@^1.18.1: - version "1.18.1" - resolved "https://registry.yarnpkg.com/http-proxy/-/http-proxy-1.18.1.tgz#401541f0534884bbf95260334e72f88ee3976549" - integrity sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ== - dependencies: - eventemitter3 "^4.0.0" - follow-redirects "^1.0.0" - requires-port "^1.0.0" - http-signature@~1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1" @@ -5284,7 +5655,7 @@ husky@^9.0.11: resolved "https://registry.yarnpkg.com/husky/-/husky-9.0.11.tgz#fc91df4c756050de41b3e478b2158b87c1e79af9" integrity sha512-AB6lFlbwwyIqMdHYhwPe+kjOC3Oc5P3nThEoW/AaO2BX3vJDjWPFxYLxokUZOo6RNX20He3AaT8sESs9NJcmEw== -iconv-lite@0.4.24, iconv-lite@^0.4.24: +iconv-lite@^0.4.24: version "0.4.24" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== @@ -5344,7 +5715,7 @@ inflight@^1.0.4: once "^1.3.0" wrappy "1" -inherits@2, inherits@2.0.4, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.3: +inherits@2, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.3: version "2.0.4" resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== @@ -5450,14 +5821,6 @@ is-accessor-descriptor@^1.0.1: dependencies: hasown "^2.0.0" -is-arguments@^1.0.4: - version "1.1.1" - resolved "https://registry.yarnpkg.com/is-arguments/-/is-arguments-1.1.1.tgz#15b3f88fda01f2a97fec84ca761a560f123efa9b" - integrity sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA== - dependencies: - call-bind "^1.0.2" - has-tostringtag "^1.0.0" - is-array-buffer@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/is-array-buffer/-/is-array-buffer-3.0.4.tgz#7a1f92b3d61edd2bc65d24f130530ea93d7fae98" @@ -5561,11 +5924,6 @@ is-descriptor@^1.0.0, is-descriptor@^1.0.2: is-accessor-descriptor "^1.0.1" is-data-descriptor "^1.0.1" -is-docker@^2.0.0: - version "2.2.1" - resolved "https://registry.yarnpkg.com/is-docker/-/is-docker-2.2.1.tgz#33eeabe23cfe86f14bde4408a02c0cfb853acdaa" - integrity sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ== - is-extendable@^0.1.0, is-extendable@^0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89" @@ -5619,7 +5977,7 @@ is-fullwidth-code-point@^5.0.0: dependencies: get-east-asian-width "^1.0.0" -is-generator-function@^1.0.10, is-generator-function@^1.0.7: +is-generator-function@^1.0.10: version "1.0.10" resolved "https://registry.yarnpkg.com/is-generator-function/-/is-generator-function-1.0.10.tgz#f1558baf1ac17e0deea7c0415c438351ff2b3c72" integrity sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A== @@ -5660,6 +6018,11 @@ is-negative-zero@^2.0.3: resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.3.tgz#ced903a027aca6381b777a5743069d7376a49747" integrity sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw== +is-node-process@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/is-node-process/-/is-node-process-1.2.0.tgz#ea02a1b90ddb3934a19aea414e88edef7e11d134" + integrity sha512-Vg4o6/fqPxIjtxgUH5QLJhwZ7gW5diGCVlXpuUfELC62CuxM1iHcRe51f2W1FDy04Ai4KJkagKjx3XaqyfRKXw== + is-number-object@^1.0.4: version "1.0.7" resolved "https://registry.yarnpkg.com/is-number-object/-/is-number-object-1.0.7.tgz#59d50ada4c45251784e9904f5246c742f07a42fc" @@ -5701,11 +6064,6 @@ is-plain-obj@^1.1.0: resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-1.1.0.tgz#71a50c8429dfca773c92a390a4a03b39fcd51d3e" integrity sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg== -is-plain-obj@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-2.1.0.tgz#45e42e37fccf1f40da8e5f76ee21515840c09287" - integrity sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA== - is-plain-object@^2.0.3, is-plain-object@^2.0.4: version "2.0.4" resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677" @@ -5774,7 +6132,7 @@ is-text-path@^1.0.1: dependencies: text-extensions "^1.0.0" -is-typed-array@^1.1.13, is-typed-array@^1.1.3: +is-typed-array@^1.1.13: version "1.1.13" resolved "https://registry.yarnpkg.com/is-typed-array/-/is-typed-array-1.1.13.tgz#d6c5ca56df62334959322d7d7dd1cca50debe229" integrity sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw== @@ -5821,13 +6179,6 @@ is-windows@^1.0.2: resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d" integrity sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA== -is-wsl@^2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-2.2.0.tgz#74a4c76e77ca9fd3f932f290c17ea326cd157271" - integrity sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww== - dependencies: - is-docker "^2.0.0" - isarray@1.0.0, isarray@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" @@ -5838,11 +6189,6 @@ isarray@^2.0.5: resolved "https://registry.yarnpkg.com/isarray/-/isarray-2.0.5.tgz#8af1e4c1221244cc62459faf38940d4e644a5723" integrity sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw== -isbinaryfile@^4.0.8: - version "4.0.10" - resolved "https://registry.yarnpkg.com/isbinaryfile/-/isbinaryfile-4.0.10.tgz#0c5b5e30c2557a2f06febd37b7322946aaee42b3" - integrity sha512-iHrqe5shvBUcFbmZq9zOQHBoeOhZJu6RQGrDpBgenUm/Am+F3JM2MgQj+rK3Z601fzrL5gLZWtAPH2OBaSVcyw== - isexe@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" @@ -5870,12 +6216,12 @@ isstream@~0.1.2: resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" integrity sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g== -istanbul-lib-coverage@^3.0.0, istanbul-lib-coverage@^3.2.0: +istanbul-lib-coverage@^3.2.0: version "3.2.2" resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz#2d166c4b0644d43a39f04bf6c2edd1e585f31756" integrity sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg== -istanbul-lib-instrument@^5.0.4, istanbul-lib-instrument@^5.1.0: +istanbul-lib-instrument@^5.0.4: version "5.2.1" resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz#d10c8885c2125574e1c231cacadf955675e1ce3d" integrity sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg== @@ -5886,32 +6232,6 @@ istanbul-lib-instrument@^5.0.4, istanbul-lib-instrument@^5.1.0: istanbul-lib-coverage "^3.2.0" semver "^6.3.0" -istanbul-lib-report@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz#908305bac9a5bd175ac6a74489eafd0fc2445a7d" - integrity sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw== - dependencies: - istanbul-lib-coverage "^3.0.0" - make-dir "^4.0.0" - supports-color "^7.1.0" - -istanbul-lib-source-maps@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz#895f3a709fcfba34c6de5a42939022f3e4358551" - integrity sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw== - dependencies: - debug "^4.1.1" - istanbul-lib-coverage "^3.0.0" - source-map "^0.6.1" - -istanbul-reports@^3.0.5: - version "3.1.7" - resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-3.1.7.tgz#daed12b9e1dca518e15c056e1e537e741280fa0b" - integrity sha512-BewmUXImeuRk2YY0PVbxgKAysvhRPUQE0h5QRM++nVWyubKGV0l8qQ5op8+B2DOmwSe63Jivj0BjkPQVf8fP5g== - dependencies: - html-escaper "^2.0.0" - istanbul-lib-report "^3.0.0" - iterator.prototype@^1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/iterator.prototype/-/iterator.prototype-1.1.2.tgz#5e29c8924f01916cb9335f1ff80619dcff22b0c0" @@ -5950,7 +6270,7 @@ js-yaml@3.14.1, js-yaml@^3.13.1, js-yaml@^3.7.0: argparse "^1.0.7" esprima "^4.0.0" -js-yaml@4.1.0, js-yaml@^4.1.0: +js-yaml@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602" integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA== @@ -6085,112 +6405,6 @@ junk@^3.1.0: resolved "https://registry.yarnpkg.com/junk/-/junk-3.1.0.tgz#31499098d902b7e98c5d9b9c80f43457a88abfa1" integrity sha512-pBxcB3LFc8QVgdggvZWyeys+hnrNWg4OcZIU/1X59k5jQdLBlCsYGRQaz234SqoRLTCgMH00fY0xRJH+F9METQ== -just-extend@^6.2.0: - version "6.2.0" - resolved "https://registry.yarnpkg.com/just-extend/-/just-extend-6.2.0.tgz#b816abfb3d67ee860482e7401564672558163947" - integrity sha512-cYofQu2Xpom82S6qD778jBDpwvvy39s1l/hrYij2u9AMdQcGRpaBu6kY4mVhuno5kJVi1DAz4aiphA2WI1/OAw== - -karma-chrome-launcher@^3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/karma-chrome-launcher/-/karma-chrome-launcher-3.2.0.tgz#eb9c95024f2d6dfbb3748d3415ac9b381906b9a9" - integrity sha512-rE9RkUPI7I9mAxByQWkGJFXfFD6lE4gC5nPuZdobf/QdTEJI6EU4yIay/cfU/xV4ZxlM5JiTv7zWYgA64NpS5Q== - dependencies: - which "^1.2.1" - -karma-cli@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/karma-cli/-/karma-cli-2.0.0.tgz#481548d28661af4cc68f3d8e09708f17d2cba931" - integrity sha512-1Kb28UILg1ZsfqQmeELbPzuEb5C6GZJfVIk0qOr8LNYQuYWmAaqP16WpbpKEjhejDrDYyYOwwJXSZO6u7q5Pvw== - dependencies: - resolve "^1.3.3" - -karma-coverage@^2.2.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/karma-coverage/-/karma-coverage-2.2.1.tgz#e1cc074f93ace9dc4fb7e7aeca7135879c2e358c" - integrity sha512-yj7hbequkQP2qOSb20GuNSIyE//PgJWHwC2IydLE6XRtsnaflv+/OSGNssPjobYUlhVVagy99TQpqUt3vAUG7A== - dependencies: - istanbul-lib-coverage "^3.2.0" - istanbul-lib-instrument "^5.1.0" - istanbul-lib-report "^3.0.0" - istanbul-lib-source-maps "^4.0.1" - istanbul-reports "^3.0.5" - minimatch "^3.0.4" - -karma-firefox-launcher@^2.1.3: - version "2.1.3" - resolved "https://registry.yarnpkg.com/karma-firefox-launcher/-/karma-firefox-launcher-2.1.3.tgz#b278a4cbffa92ab81394b1a398813847b0624a85" - integrity sha512-LMM2bseebLbYjODBOVt7TCPP9OI2vZIXCavIXhkO9m+10Uj5l7u/SKoeRmYx8FYHTVGZSpk6peX+3BMHC1WwNw== - dependencies: - is-wsl "^2.2.0" - which "^3.0.0" - -karma-mocha-reporter@^2.2.5: - version "2.2.5" - resolved "https://registry.yarnpkg.com/karma-mocha-reporter/-/karma-mocha-reporter-2.2.5.tgz#15120095e8ed819186e47a0b012f3cd741895560" - integrity sha512-Hr6nhkIp0GIJJrvzY8JFeHpQZNseuIakGac4bpw8K1+5F0tLb6l7uvXRa8mt2Z+NVwYgCct4QAfp2R2QP6o00w== - dependencies: - chalk "^2.1.0" - log-symbols "^2.1.0" - strip-ansi "^4.0.0" - -karma-mocha@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/karma-mocha/-/karma-mocha-2.0.1.tgz#4b0254a18dfee71bdbe6188d9a6861bf86b0cd7d" - integrity sha512-Tzd5HBjm8his2OA4bouAsATYEpZrp9vC7z5E5j4C5Of5Rrs1jY67RAwXNcVmd/Bnk1wgvQRou0zGVLey44G4tQ== - dependencies: - minimist "^1.2.3" - -karma-sinon-chai@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/karma-sinon-chai/-/karma-sinon-chai-2.0.2.tgz#e28c109b989973abafc28a7c9f09ef24a05e07c2" - integrity sha512-SDgh6V0CUd+7ruL1d3yG6lFzmJNGRNQuEuCYXLaorruNP9nwQfA7hpsp4clx4CbOo5Gsajh3qUOT7CrVStUKMw== - -karma-sourcemap-loader@^0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/karma-sourcemap-loader/-/karma-sourcemap-loader-0.4.0.tgz#b01d73f8f688f533bcc8f5d273d43458e13b5488" - integrity sha512-xCRL3/pmhAYF3I6qOrcn0uhbQevitc2DERMPH82FMnG+4WReoGcGFZb1pURf2a5apyrOHRdvD+O6K7NljqKHyA== - dependencies: - graceful-fs "^4.2.10" - -karma-webpack@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/karma-webpack/-/karma-webpack-5.0.1.tgz#4eafd31bbe684a747a6e8f3e4ad373e53979ced4" - integrity sha512-oo38O+P3W2mSPCSUrQdySSPv1LvPpXP+f+bBimNomS5sW+1V4SuhCuW8TfJzV+rDv921w2fDSDw0xJbPe6U+kQ== - dependencies: - glob "^7.1.3" - minimatch "^9.0.3" - webpack-merge "^4.1.5" - -karma@^6.4.3: - version "6.4.3" - resolved "https://registry.yarnpkg.com/karma/-/karma-6.4.3.tgz#763e500f99597218bbb536de1a14acc4ceea7ce8" - integrity sha512-LuucC/RE92tJ8mlCwqEoRWXP38UMAqpnq98vktmS9SznSoUPPUJQbc91dHcxcunROvfQjdORVA/YFviH+Xci9Q== - dependencies: - "@colors/colors" "1.5.0" - body-parser "^1.19.0" - braces "^3.0.2" - chokidar "^3.5.1" - connect "^3.7.0" - di "^0.0.1" - dom-serialize "^2.2.1" - glob "^7.1.7" - graceful-fs "^4.2.6" - http-proxy "^1.18.1" - isbinaryfile "^4.0.8" - lodash "^4.17.21" - log4js "^6.4.1" - mime "^2.5.2" - minimatch "^3.0.4" - mkdirp "^0.5.5" - qjobs "^1.2.0" - range-parser "^1.2.1" - rimraf "^3.0.2" - socket.io "^4.7.2" - source-map "^0.6.1" - tmp "^0.2.1" - ua-parser-js "^0.7.30" - yargs "^16.1.1" - keyv@^4.5.3: version "4.5.4" resolved "https://registry.yarnpkg.com/keyv/-/keyv-4.5.4.tgz#a879a99e29452f942439f2a405e3af8b31d4de93" @@ -6386,11 +6600,6 @@ lodash.debounce@^4.0.8: resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af" integrity sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow== -lodash.get@^4.4.2: - version "4.4.2" - resolved "https://registry.yarnpkg.com/lodash.get/-/lodash.get-4.4.2.tgz#2d177f652fa31e939b4438d5341499dfa3825e99" - integrity sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ== - lodash.ismatch@^4.4.0: version "4.4.0" resolved "https://registry.yarnpkg.com/lodash.ismatch/-/lodash.ismatch-4.4.0.tgz#756cb5150ca3ba6f11085a78849645f188f85f37" @@ -6406,14 +6615,6 @@ lodash@^4.17.12, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.20, lodash@^4.17 resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== -log-symbols@4.1.0, log-symbols@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-4.1.0.tgz#3fbdbb95b4683ac9fc785111e792e558d4abd503" - integrity sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg== - dependencies: - chalk "^4.1.0" - is-unicode-supported "^0.1.0" - log-symbols@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-1.0.2.tgz#376ff7b58ea3086a0f09facc74617eca501e1a18" @@ -6421,12 +6622,13 @@ log-symbols@^1.0.2: dependencies: chalk "^1.0.0" -log-symbols@^2.1.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-2.2.0.tgz#5740e1c5d6f0dfda4ad9323b5332107ef6b4c40a" - integrity sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg== +log-symbols@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-4.1.0.tgz#3fbdbb95b4683ac9fc785111e792e558d4abd503" + integrity sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg== dependencies: - chalk "^2.0.1" + chalk "^4.1.0" + is-unicode-supported "^0.1.0" log-symbols@^5.1.0: version "5.1.0" @@ -6456,17 +6658,6 @@ log-update@^6.0.0: strip-ansi "^7.1.0" wrap-ansi "^9.0.0" -log4js@^6.4.1: - version "6.9.1" - resolved "https://registry.yarnpkg.com/log4js/-/log4js-6.9.1.tgz#aba5a3ff4e7872ae34f8b4c533706753709e38b6" - integrity sha512-1somDdy9sChrr9/f4UlzhdaGfDR2c/SaD2a4T7qEkG4jTS57/B3qmnjLYePwQ8cqWnUHZI0iAKxMBpCZICiZ2g== - dependencies: - date-format "^4.0.14" - debug "^4.3.4" - flatted "^3.2.7" - rfdc "^1.3.0" - streamroller "^3.1.5" - loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf" @@ -6474,10 +6665,10 @@ loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.4.0: dependencies: js-tokens "^3.0.0 || ^4.0.0" -loupe@^2.3.6: - version "2.3.7" - resolved "https://registry.yarnpkg.com/loupe/-/loupe-2.3.7.tgz#6e69b7d4db7d3ab436328013d37d1c8c3540c697" - integrity sha512-zSMINGVYkdpYSOBmLi0D1Uo7JU9nVdQKrHxC8eYlV+9YKK9WePqAlL7lSlorG/U2Fw1w0hTBmaa/jrQ3UbPHtA== +loupe@^3.1.0, loupe@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/loupe/-/loupe-3.1.1.tgz#71d038d59007d890e3247c5db97c1ec5a92edc54" + integrity sha512-edNu/8D5MKVfGVFRhFf8aAxiTM6Wumfz5XsaatSxlD3w4R1d/WEKUTydCdPGbl9K7QG/Ca3GnDV2sIKIpXRQcw== dependencies: get-func-name "^2.0.1" @@ -6500,6 +6691,13 @@ lz-string@^1.5.0: resolved "https://registry.yarnpkg.com/lz-string/-/lz-string-1.5.0.tgz#c1ab50f77887b712621201ba9fd4e3a6ed099941" integrity sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ== +magic-string@^0.30.10: + version "0.30.10" + resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.30.10.tgz#123d9c41a0cb5640c892b041d4cfb3bd0aa4b39e" + integrity sha512-iIRwTIf0QKV3UAnYK4PU8uiEc4SRh5jX0mwpIwETPpHdhVM4f53RSwS/vXvN1JhGX+Cs7B8qIq3d6AH49O5fAQ== + dependencies: + "@jridgewell/sourcemap-codec" "^1.4.15" + make-dir@^2.0.0, make-dir@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-2.1.0.tgz#5f0310e18b8be898cc07009295a30ae41e91e6f5" @@ -6515,13 +6713,6 @@ make-dir@^3.0.0: dependencies: semver "^6.0.0" -make-dir@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-4.0.0.tgz#c3c2307a771277cd9638305f915c29ae741b614e" - integrity sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw== - dependencies: - semver "^7.5.3" - map-cache@^0.2.2: version "0.2.2" resolved "https://registry.yarnpkg.com/map-cache/-/map-cache-0.2.2.tgz#c32abd0bd6525d9b051645bb4f26ac5dc98a0dbf" @@ -6544,11 +6735,6 @@ map-visit@^1.0.0: dependencies: object-visit "^1.0.0" -media-typer@0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" - integrity sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ== - memory-fs@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/memory-fs/-/memory-fs-0.2.0.tgz#f2bb25368bc121e391c2520de92969caee0a0290" @@ -6638,18 +6824,13 @@ mime-db@1.52.0: resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== -mime-types@^2.1.12, mime-types@^2.1.27, mime-types@~2.1.19, mime-types@~2.1.24, mime-types@~2.1.34: +mime-types@^2.1.12, mime-types@^2.1.27, mime-types@~2.1.19: version "2.1.35" resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a" integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== dependencies: mime-db "1.52.0" -mime@^2.5.2: - version "2.6.0" - resolved "https://registry.yarnpkg.com/mime/-/mime-2.6.0.tgz#a2a682a95cd4d0cb1d6257e28f83da7e35800367" - integrity sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg== - mimic-fn@^1.0.0: version "1.2.0" resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-1.2.0.tgz#820c86a39334640e99516928bd03fca88057d022" @@ -6670,13 +6851,6 @@ min-indent@^1.0.0: resolved "https://registry.yarnpkg.com/min-indent/-/min-indent-1.0.1.tgz#a63f681673b30571fbe8bc25686ae746eefa9869" integrity sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg== -minimatch@5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-5.0.1.tgz#fb9022f7528125187c92bd9e9b6366be1cf3415b" - integrity sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g== - dependencies: - brace-expansion "^2.0.1" - minimatch@^3.0.4, minimatch@^3.0.5, minimatch@^3.1.1, minimatch@^3.1.2: version "3.1.2" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" @@ -6684,13 +6858,6 @@ minimatch@^3.0.4, minimatch@^3.0.5, minimatch@^3.1.1, minimatch@^3.1.2: dependencies: brace-expansion "^1.1.7" -minimatch@^5.0.1: - version "5.1.6" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-5.1.6.tgz#1cfcb8cf5522ea69952cd2af95ae09477f122a96" - integrity sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g== - dependencies: - brace-expansion "^2.0.1" - minimatch@^9.0.3: version "9.0.3" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.3.tgz#a6e00c3de44c3a542bfaae70abfc22420a6da825" @@ -6714,7 +6881,7 @@ minimist-options@4.1.0, minimist-options@^4.0.2: is-plain-obj "^1.1.0" kind-of "^6.0.3" -minimist@^1.2.0, minimist@^1.2.3, minimist@^1.2.5, minimist@^1.2.6: +minimist@^1.2.0, minimist@^1.2.5, minimist@^1.2.6: version "1.2.8" resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c" integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA== @@ -6747,7 +6914,7 @@ mixin-deep@^1.2.0: for-in "^1.0.2" is-extendable "^1.0.1" -mkdirp@^0.5.1, mkdirp@^0.5.5: +mkdirp@^0.5.1: version "0.5.6" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.6.tgz#7def03d2432dcae4ba1d611445c48396062255f6" integrity sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw== @@ -6759,37 +6926,16 @@ mkdirp@^1.0.3: resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e" integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw== -mocha@^10.4.0: - version "10.4.0" - resolved "https://registry.yarnpkg.com/mocha/-/mocha-10.4.0.tgz#ed03db96ee9cfc6d20c56f8e2af07b961dbae261" - integrity sha512-eqhGB8JKapEYcC4ytX/xrzKforgEc3j1pGlAXVy3eRwrtAy5/nIfT1SvgGzfN0XZZxeLq0aQWkOUAmqIJiv+bA== - dependencies: - ansi-colors "4.1.1" - browser-stdout "1.3.1" - chokidar "3.5.3" - debug "4.3.4" - diff "5.0.0" - escape-string-regexp "4.0.0" - find-up "5.0.0" - glob "8.1.0" - he "1.2.0" - js-yaml "4.1.0" - log-symbols "4.1.0" - minimatch "5.0.1" - ms "2.1.3" - serialize-javascript "6.0.0" - strip-json-comments "3.1.1" - supports-color "8.1.1" - workerpool "6.2.1" - yargs "16.2.0" - yargs-parser "20.2.4" - yargs-unparser "2.0.0" - modify-values@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/modify-values/-/modify-values-1.0.1.tgz#b3939fa605546474e3e3e3c63d64bd43b4ee6022" integrity sha512-xV2bxeN6F7oYjZWTe/YPAy6MN2M+sL4u/Rlm2AHCIVGfo2p1yGmBHQ6vHehl4bRTZBdHu3TSkWdYgkwpYzAGSw== +mrmime@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/mrmime/-/mrmime-2.0.0.tgz#151082a6e06e59a9a39b46b3e14d5cfe92b3abb4" + integrity sha512-eu38+hdgojoyq63s+yTpN4XMBdt5l8HhMhc4VKLO9KM5caLIBvUm4thi7fFaxyTmCKeNnXZ5pAlBwCUnhA09uw== + ms@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" @@ -6800,11 +6946,34 @@ ms@2.1.2: resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== -ms@2.1.3, ms@^2.1.1: +ms@^2.1.1: version "2.1.3" resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== +msw@^2.3.1: + version "2.3.2" + resolved "https://registry.yarnpkg.com/msw/-/msw-2.3.2.tgz#ea4f45b51f833fa3b2215c4093bcda28dbe25a83" + integrity sha512-vDn6d6a50vxPE+HnaKQfpmZ4SVXlOjF97yD5FJcUT3v2/uZ65qvTYNL25yOmnrfCNWZ4wtAS7EbtXxygMug2Tw== + dependencies: + "@bundled-es-modules/cookie" "^2.0.0" + "@bundled-es-modules/statuses" "^1.0.1" + "@inquirer/confirm" "^3.0.0" + "@mswjs/cookies" "^1.1.0" + "@mswjs/interceptors" "^0.29.0" + "@open-draft/until" "^2.1.0" + "@types/cookie" "^0.6.0" + "@types/statuses" "^2.0.4" + chalk "^4.1.2" + graphql "^16.8.1" + headers-polyfill "^4.0.2" + is-node-process "^1.2.0" + outvariant "^1.4.2" + path-to-regexp "^6.2.0" + strict-event-emitter "^0.5.1" + type-fest "^4.9.0" + yargs "^17.7.2" + mute-stream@0.0.7: version "0.0.7" resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.7.tgz#3075ce93bc21b8fab43e1bc4da7e8115ed1e7bab" @@ -6815,6 +6984,16 @@ mute-stream@0.0.8: resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.8.tgz#1630c42b2251ff81e2a283de96a5497ea92e5e0d" integrity sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA== +mute-stream@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-1.0.0.tgz#e31bd9fe62f0aed23520aa4324ea6671531e013e" + integrity sha512-avsJQhyd+680gKXyG/sQc0nXaC6rBkPOfyHYcFb9+hdkqQkR9bdnkJ0AMZhke0oesPqIO+mFFJ+IdBc7mst4IA== + +nanoid@^3.3.7: + version "3.3.7" + resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.7.tgz#d0c301a691bc8d54efa0a2226ccf3fe2fd656bd8" + integrity sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g== + nanomatch@^1.2.9: version "1.2.13" resolved "https://registry.yarnpkg.com/nanomatch/-/nanomatch-1.2.13.tgz#b87a8aa4fc0de8fe6be88895b38983ff265bd119" @@ -6837,11 +7016,6 @@ natural-compare@^1.4.0: resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" integrity sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw== -negotiator@0.6.3: - version "0.6.3" - resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.3.tgz#58e323a72fedc0d6f9cd4d31fe49f51479590ccd" - integrity sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg== - neo-async@^2.6.2: version "2.6.2" resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f" @@ -6852,17 +7026,6 @@ nested-error-stacks@^2.0.0, nested-error-stacks@^2.1.0: resolved "https://registry.yarnpkg.com/nested-error-stacks/-/nested-error-stacks-2.1.1.tgz#26c8a3cee6cc05fbcf1e333cd2fc3e003326c0b5" integrity sha512-9iN1ka/9zmX1ZvLV9ewJYEk9h7RyRRtqdK0woXcqohu8EWIerfPUjYJPg0ULy0UqP7cslmdGc8xKDJcojlKiaw== -nise@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/nise/-/nise-6.0.0.tgz#ae56fccb5d912037363c3b3f29ebbfa28bde8b48" - integrity sha512-K8ePqo9BFvN31HXwEtTNGzgrPpmvgciDsFz8aztFjt4LqKO/JeFD8tBOeuDiCMXrIl/m1YvfH8auSpxfaD09wg== - dependencies: - "@sinonjs/commons" "^3.0.0" - "@sinonjs/fake-timers" "^11.2.2" - "@sinonjs/text-encoding" "^0.7.2" - just-extend "^6.2.0" - path-to-regexp "^6.2.1" - node-fetch@^2.6.1: version "2.7.0" resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.7.0.tgz#d0f0fa6e3e2dc1d27efcd8ad99d550bda94d187d" @@ -6943,7 +7106,7 @@ oauth-sign@~0.9.0: resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455" integrity sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ== -object-assign@^4, object-assign@^4.1.0, object-assign@^4.1.1: +object-assign@^4.1.0, object-assign@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" integrity sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg== @@ -7066,20 +7229,6 @@ object.values@^1.2.0: define-properties "^1.2.1" es-object-atoms "^1.0.0" -on-finished@2.4.1: - version "2.4.1" - resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.4.1.tgz#58c8c44116e54845ad57f14ab10b03533184ac3f" - integrity sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg== - dependencies: - ee-first "1.1.1" - -on-finished@~2.3.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.3.0.tgz#20f1336481b083cd75337992a16971aa2d906947" - integrity sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww== - dependencies: - ee-first "1.1.1" - once@^1.3.0, once@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" @@ -7155,6 +7304,11 @@ os-tmpdir@~1.0.2: resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" integrity sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g== +outvariant@^1.2.1, outvariant@^1.4.0, outvariant@^1.4.2: + version "1.4.3" + resolved "https://registry.yarnpkg.com/outvariant/-/outvariant-1.4.3.tgz#221c1bfc093e8fec7075497e7799fdbf43d14873" + integrity sha512-+Sl2UErvtsoajRDKCE5/dBz4DIvHXQQnAxtQTF04OJxY0+DyZXSo5P5Bb7XYWOh81syohlYL24hbDwxedPUJCA== + p-all@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/p-all/-/p-all-2.1.0.tgz#91419be56b7dee8fe4c5db875d55e0da084244a0" @@ -7298,11 +7452,6 @@ parse-json@^5.0.0, parse-json@^5.2.0: json-parse-even-better-errors "^2.3.0" lines-and-columns "^1.1.6" -parseurl@~1.3.3: - version "1.3.3" - resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4" - integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ== - pascalcase@^0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/pascalcase/-/pascalcase-0.1.1.tgz#b363e55e8006ca6fe21784d2db22bd15d7917f14" @@ -7348,10 +7497,10 @@ path-parse@^1.0.7: resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== -path-to-regexp@^6.2.1: - version "6.2.1" - resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-6.2.1.tgz#d54934d6798eb9e5ef14e7af7962c945906918e5" - integrity sha512-JLyh7xT1kizaEvcaXOQwOc2/Yhw6KZOvPf1S8401UyLk86CU79LN3vl7ztXGm/pZ+YjoyAJ4rxmHwbkBXJX+yw== +path-to-regexp@^6.2.0: + version "6.2.2" + resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-6.2.2.tgz#324377a83e5049cbecadc5554d6a63a9a4866b36" + integrity sha512-GQX3SSMokngb36+whdpRXE+3f9V8UzyAorlYvOGx87ufGHehNTn5lCxrKtLyZ4Yl/wEKnNnr98ZzOwwDZV5ogw== path-type@^3.0.0: version "3.0.0" @@ -7365,10 +7514,15 @@ path-type@^4.0.0: resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== -pathval@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/pathval/-/pathval-1.1.1.tgz#8534e77a77ce7ac5a2512ea21e0fdb8fcf6c3d8d" - integrity sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ== +pathe@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/pathe/-/pathe-1.1.2.tgz#6c4cb47a945692e48a1ddd6e4094d170516437ec" + integrity sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ== + +pathval@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/pathval/-/pathval-2.0.0.tgz#7e2550b422601d4f6b8e26f1301bc8f15a741a25" + integrity sha512-vE7JKRyES09KiunauX7nd2Q9/L7lhok4smP9RZTDeD4MVs72Dp2qNFVz39Nz5a0FVEW0BJR6C0DYrq6unoziZA== performance-now@^2.1.0: version "2.1.0" @@ -7380,6 +7534,11 @@ picocolors@^1.0.0: resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c" integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ== +picocolors@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.1.tgz#a8ad579b571952f0e5d25892de5445bcfe25aaa1" + integrity sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew== + picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.3.1: version "2.3.1" resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" @@ -7424,6 +7583,20 @@ pkg-dir@^7.0.0: dependencies: find-up "^6.3.0" +playwright-core@1.45.3: + version "1.45.3" + resolved "https://registry.yarnpkg.com/playwright-core/-/playwright-core-1.45.3.tgz#e77bc4c78a621b96c3e629027534ee1d25faac93" + integrity sha512-+ym0jNbcjikaOwwSZycFbwkWgfruWvYlJfThKYAlImbxUgdWFO2oW70ojPm4OpE4t6TAo2FY/smM+hpVTtkhDA== + +playwright@^1.45.3: + version "1.45.3" + resolved "https://registry.yarnpkg.com/playwright/-/playwright-1.45.3.tgz#75143f73093a6e1467f7097083d2f0846fb8dd2f" + integrity sha512-QhVaS+lpluxCaioejDZ95l4Y4jSFCsBvl2UZkpeXlzxmqS+aABr5c82YmfMHrL6x27nvrvykJAFpkzT2eWdJww== + dependencies: + playwright-core "1.45.3" + optionalDependencies: + fsevents "2.3.2" + posix-character-classes@^0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/posix-character-classes/-/posix-character-classes-0.1.1.tgz#01eac0fe3b5af71a2a6c02feabb8c1fef7e00eab" @@ -7434,6 +7607,15 @@ possible-typed-array-names@^1.0.0: resolved "https://registry.yarnpkg.com/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz#89bb63c6fada2c3e90adc4a647beeeb39cc7bf8f" integrity sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q== +postcss@^8.4.39: + version "8.4.39" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.39.tgz#aa3c94998b61d3a9c259efa51db4b392e1bde0e3" + integrity sha512-0vzE+lAiG7hZl1/9I8yzKLx3aR9Xbof3fBHKunvMfOCYAtMhrsnccJY2iTURb9EZd5+pLuiNV9/c/GZJOHsgIw== + dependencies: + nanoid "^3.3.7" + picocolors "^1.0.1" + source-map-js "^1.2.0" + prelude-ls@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396" @@ -7507,18 +7689,6 @@ q@^1.5.1: resolved "https://registry.yarnpkg.com/q/-/q-1.5.1.tgz#7e32f75b41381291d04611f1bf14109ac00651d7" integrity sha512-kV/CThkXo6xyFEZUugw/+pIOywXcDbFYgSct5cT3gqlbkBE1SJdwy6UQoZvodiWF/ckQLZyDE/Bu1M6gVu5lVw== -qjobs@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/qjobs/-/qjobs-1.2.0.tgz#c45e9c61800bd087ef88d7e256423bdd49e5d071" - integrity sha512-8YOJEHtxpySA3fFDyCRxA+UUV+fA+rTWnuWvylOK/NCjhY+b4ocCtmu8TtsWb+mYeU+GCHf/S66KZF/AsteKHg== - -qs@6.11.0: - version "6.11.0" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.11.0.tgz#fd0d963446f7a65e1367e01abd85429453f0c37a" - integrity sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q== - dependencies: - side-channel "^1.0.4" - qs@~6.5.2: version "6.5.3" resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.3.tgz#3aeeffc91967ef6e35c0e488ef46fb296ab76aad" @@ -7539,11 +7709,6 @@ quick-lru@^4.0.1: resolved "https://registry.yarnpkg.com/quick-lru/-/quick-lru-4.0.1.tgz#5b8878f113a58217848c6482026c73e1ba57727f" integrity sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g== -rambda@^7.4.0: - version "7.5.0" - resolved "https://registry.yarnpkg.com/rambda/-/rambda-7.5.0.tgz#1865044c59bc0b16f63026c6e5a97e4b1bbe98fe" - integrity sha512-y/M9weqWAH4iopRd7EHDEQQvpFPHj1AA3oHozE9tfITHUtTR7Z9PSlIRRG2l1GuW7sefC1cXFfIcF+cgnShdBA== - randombytes@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" @@ -7551,28 +7716,13 @@ randombytes@^2.1.0: dependencies: safe-buffer "^5.1.0" -range-parser@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031" - integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg== - -raw-body@2.5.2: - version "2.5.2" - resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.5.2.tgz#99febd83b90e08975087e8f1f9419a149366b68a" - integrity sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA== - dependencies: - bytes "3.1.2" - http-errors "2.0.0" - iconv-lite "0.4.24" - unpipe "1.0.0" - -react-dom@^18.2.0: - version "18.2.0" - resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-18.2.0.tgz#22aaf38708db2674ed9ada224ca4aa708d821e3d" - integrity sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g== +react-dom@^18.3.1: + version "18.3.1" + resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-18.3.1.tgz#c2265d79511b57d479b3dd3fdfa51536494c5cb4" + integrity sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw== dependencies: loose-envify "^1.1.0" - scheduler "^0.23.0" + scheduler "^0.23.2" react-is@^16.13.1, react-is@^16.3.2: version "16.13.1" @@ -7589,6 +7739,11 @@ react-lifecycles-compat@^3.0.4: resolved "https://registry.yarnpkg.com/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz#4f1a273afdfc8f3488a8c516bfda78f872352362" integrity sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA== +react-refresh@^0.14.2: + version "0.14.2" + resolved "https://registry.yarnpkg.com/react-refresh/-/react-refresh-0.14.2.tgz#3833da01ce32da470f1f936b9d477da5c7028bf9" + integrity sha512-jCvmsr+1IUSMUyzOkRcvnVbX3ZYC6g9TDrDbFuFmRDq7PD4yaGbLKNQL6k2jnArV8hjYxh7hVhAZB6s9HDGpZA== + react-transition-group@^4.4.5: version "4.4.5" resolved "https://registry.yarnpkg.com/react-transition-group/-/react-transition-group-4.4.5.tgz#e53d4e3f3344da8521489fbef8f2581d42becdd1" @@ -7599,10 +7754,10 @@ react-transition-group@^4.4.5: loose-envify "^1.4.0" prop-types "^15.6.2" -react@^18.2.0: - version "18.2.0" - resolved "https://registry.yarnpkg.com/react/-/react-18.2.0.tgz#555bd98592883255fa00de14f1151a917b5d77d5" - integrity sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ== +react@^18.3.1: + version "18.3.1" + resolved "https://registry.yarnpkg.com/react/-/react-18.3.1.tgz#49ab892009c53933625bd16b2533fc754cab2891" + integrity sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ== dependencies: loose-envify "^1.1.0" @@ -7832,11 +7987,6 @@ require-main-filename@^2.0.0: resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-2.0.0.tgz#d0b329ecc7cc0f61649f62215be69af54aa8989b" integrity sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg== -requires-port@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff" - integrity sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ== - resolve-from@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" @@ -7852,7 +8002,7 @@ resolve-url@^0.2.1: resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a" integrity sha512-ZuF55hVUQaaczgOIwqWzkEcEidmlD/xl44x1UZnhOXcYuFN2S6+rcxpG+C1N3So0wvNI3DmJICUFfu2SxhBmvg== -resolve@^1.10.0, resolve@^1.14.2, resolve@^1.22.4, resolve@^1.3.2, resolve@^1.3.3: +resolve@^1.10.0, resolve@^1.14.2, resolve@^1.22.4, resolve@^1.3.2: version "1.22.8" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.8.tgz#b6c87a9f2aa06dfab52e3d70ac8cde321fa5a48d" integrity sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw== @@ -7909,11 +8059,6 @@ reusify@^1.0.4: resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== -rfdc@^1.3.0: - version "1.3.1" - resolved "https://registry.yarnpkg.com/rfdc/-/rfdc-1.3.1.tgz#2b6d4df52dffe8bb346992a10ea9451f24373a8f" - integrity sha512-r5a3l5HzYlIC68TpmYKlxWjmOP6wiPJ1vWv2HeLhNsRZMrCkxeqxiHlQ21oXmQ4F3SiryXBHhAD7JZqvOJjFmg== - rfdc@^1.3.1: version "1.4.1" resolved "https://registry.yarnpkg.com/rfdc/-/rfdc-1.4.1.tgz#778f76c4fb731d93414e8f925fbecf64cce7f6ca" @@ -7933,6 +8078,31 @@ rimraf@^3.0.0, rimraf@^3.0.2: dependencies: glob "^7.1.3" +rollup@^4.13.0: + version "4.19.0" + resolved "https://registry.yarnpkg.com/rollup/-/rollup-4.19.0.tgz#83b08cc0b2bc38c26c194cb7f2cdabd84a2a8c02" + integrity sha512-5r7EYSQIowHsK4eTZ0Y81qpZuJz+MUuYeqmmYmRMl1nwhdmbiYqt5jwzf6u7wyOzJgYqtCRMtVRKOtHANBz7rA== + dependencies: + "@types/estree" "1.0.5" + optionalDependencies: + "@rollup/rollup-android-arm-eabi" "4.19.0" + "@rollup/rollup-android-arm64" "4.19.0" + "@rollup/rollup-darwin-arm64" "4.19.0" + "@rollup/rollup-darwin-x64" "4.19.0" + "@rollup/rollup-linux-arm-gnueabihf" "4.19.0" + "@rollup/rollup-linux-arm-musleabihf" "4.19.0" + "@rollup/rollup-linux-arm64-gnu" "4.19.0" + "@rollup/rollup-linux-arm64-musl" "4.19.0" + "@rollup/rollup-linux-powerpc64le-gnu" "4.19.0" + "@rollup/rollup-linux-riscv64-gnu" "4.19.0" + "@rollup/rollup-linux-s390x-gnu" "4.19.0" + "@rollup/rollup-linux-x64-gnu" "4.19.0" + "@rollup/rollup-linux-x64-musl" "4.19.0" + "@rollup/rollup-win32-arm64-msvc" "4.19.0" + "@rollup/rollup-win32-ia32-msvc" "4.19.0" + "@rollup/rollup-win32-x64-msvc" "4.19.0" + fsevents "~2.3.2" + run-async@^2.2.0, run-async@^2.4.0: version "2.4.1" resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.4.1.tgz#8440eccf99ea3e70bd409d49aab88e10c189a455" @@ -8000,10 +8170,10 @@ safe-regex@^1.1.0: resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== -scheduler@^0.23.0: - version "0.23.0" - resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.23.0.tgz#ba8041afc3d30eb206a487b6b384002e4e61fdfe" - integrity sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw== +scheduler@^0.23.2: + version "0.23.2" + resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.23.2.tgz#414ba64a3b282892e944cf2108ecc078d115cdc3" + integrity sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ== dependencies: loose-envify "^1.1.0" @@ -8026,7 +8196,7 @@ schema-utils@^4.0.0: ajv-formats "^2.1.1" ajv-keywords "^5.1.0" -"semver@2 >=2.2.1 || 3.x || 4 || 5 || 7", semver@^7.3.4, semver@^7.3.5, semver@^7.5.3, semver@^7.5.4: +"semver@2 >=2.2.1 || 3.x || 4 || 5 || 7", semver@^7.3.4, semver@^7.3.5, semver@^7.5.4: version "7.6.0" resolved "https://registry.yarnpkg.com/semver/-/semver-7.6.0.tgz#1a46a4db4bffcccd97b743b5005c8325f23d4e2d" integrity sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg== @@ -8048,13 +8218,6 @@ semver@^7.6.0: resolved "https://registry.yarnpkg.com/semver/-/semver-7.6.2.tgz#1e3b34759f896e8f14d6134732ce798aeb0c6e13" integrity sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w== -serialize-javascript@6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-6.0.0.tgz#efae5d88f45d7924141da8b5c3a7a7e663fefeb8" - integrity sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag== - dependencies: - randombytes "^2.1.0" - serialize-javascript@^6.0.1: version "6.0.2" resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-6.0.2.tgz#defa1e055c83bf6d59ea805d8da862254eb6a6c2" @@ -8099,11 +8262,6 @@ set-value@^2.0.0, set-value@^2.0.1: is-plain-object "^2.0.3" split-string "^3.0.1" -setprototypeof@1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.2.0.tgz#66c9a24a73f9fc28cbe66b09fed3d33dcaf1b424" - integrity sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw== - shallow-clone@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/shallow-clone/-/shallow-clone-3.0.1.tgz#8f2981ad92531f55035b01fb230769a40e02efa3" @@ -8133,6 +8291,11 @@ side-channel@^1.0.4, side-channel@^1.0.6: get-intrinsic "^1.2.4" object-inspect "^1.13.1" +siginfo@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/siginfo/-/siginfo-2.0.0.tgz#32e76c70b79724e3bb567cb9d543eb858ccfaf30" + integrity sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g== + signal-exit@^3.0.0, signal-exit@^3.0.2, signal-exit@^3.0.3, signal-exit@^3.0.7: version "3.0.7" resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" @@ -8143,22 +8306,14 @@ signal-exit@^4.1.0: resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-4.1.0.tgz#952188c1cbd546070e2dd20d0f41c0ae0530cb04" integrity sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw== -sinon-chai@^3.7.0: - version "3.7.0" - resolved "https://registry.yarnpkg.com/sinon-chai/-/sinon-chai-3.7.0.tgz#cfb7dec1c50990ed18c153f1840721cf13139783" - integrity sha512-mf5NURdUaSdnatJx3uhoBOrY9dtL19fiOtAdT1Azxg3+lNJFiuN0uzaU3xX1LeAfL17kHQhTAJgpsfhbMJMY2g== - -sinon@^18.0.0: - version "18.0.0" - resolved "https://registry.yarnpkg.com/sinon/-/sinon-18.0.0.tgz#69ca293dbc3e82590a8b0d46c97f63ebc1e5fc01" - integrity sha512-+dXDXzD1sBO6HlmZDd7mXZCR/y5ECiEiGCBSGuFD/kZ0bDTofPYc6JaeGmPSF+1j1MejGUWkORbYOLDyvqCWpA== +sirv@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/sirv/-/sirv-2.0.4.tgz#5dd9a725c578e34e449f332703eb2a74e46a29b0" + integrity sha512-94Bdh3cC2PKrbgSOUqTiGPWVZeSiXfKOVZNJniWoqrWrRkB1CJzBU3NEbiTsPcYy1lDsANA/THzS+9WBiy5nfQ== dependencies: - "@sinonjs/commons" "^3.0.1" - "@sinonjs/fake-timers" "^11.2.2" - "@sinonjs/samsam" "^8.0.0" - diff "^5.2.0" - nise "^6.0.0" - supports-color "^7" + "@polka/url" "^1.0.0-next.24" + mrmime "^2.0.0" + totalist "^3.0.0" slash@^2.0.0: version "2.0.0" @@ -8231,34 +8386,10 @@ snapdragon@^0.8.1: source-map-resolve "^0.5.0" use "^3.1.0" -socket.io-adapter@~2.5.2: - version "2.5.4" - resolved "https://registry.yarnpkg.com/socket.io-adapter/-/socket.io-adapter-2.5.4.tgz#4fdb1358667f6d68f25343353bd99bd11ee41006" - integrity sha512-wDNHGXGewWAjQPt3pyeYBtpWSq9cLE5UW1ZUPL/2eGK9jtse/FpXib7epSTsz0Q0m+6sg6Y4KtcFTlah1bdOVg== - dependencies: - debug "~4.3.4" - ws "~8.11.0" - -socket.io-parser@~4.2.4: - version "4.2.4" - resolved "https://registry.yarnpkg.com/socket.io-parser/-/socket.io-parser-4.2.4.tgz#c806966cf7270601e47469ddeec30fbdfda44c83" - integrity sha512-/GbIKmo8ioc+NIWIhwdecY0ge+qVBSMdgxGygevmdHj24bsfgtCmcUUcQ5ZzcylGFHsN3k4HB4Cgkl96KVnuew== - dependencies: - "@socket.io/component-emitter" "~3.1.0" - debug "~4.3.1" - -socket.io@^4.7.2: - version "4.7.5" - resolved "https://registry.yarnpkg.com/socket.io/-/socket.io-4.7.5.tgz#56eb2d976aef9d1445f373a62d781a41c7add8f8" - integrity sha512-DmeAkF6cwM9jSfmp6Dr/5/mfMwb5Z5qRrSXLpo3Fq5SqyU8CMF15jIN4ZhfSwu35ksM1qmHZDQ/DK5XTccSTvA== - dependencies: - accepts "~1.3.4" - base64id "~2.0.0" - cors "~2.8.5" - debug "~4.3.2" - engine.io "~6.5.2" - socket.io-adapter "~2.5.2" - socket.io-parser "~4.2.4" +source-map-js@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.2.0.tgz#16b809c162517b5b8c3e7dcd315a2a5c2612b2af" + integrity sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg== source-map-resolve@^0.5.0: version "0.5.3" @@ -8368,6 +8499,11 @@ ssri@^8.0.0: dependencies: minipass "^3.1.1" +stackback@0.0.2: + version "0.0.2" + resolved "https://registry.yarnpkg.com/stackback/-/stackback-0.0.2.tgz#1ac8a0d9483848d1695e418b6d031a3c3ce68e3b" + integrity sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw== + static-extend@^0.1.1: version "0.1.2" resolved "https://registry.yarnpkg.com/static-extend/-/static-extend-0.1.2.tgz#60809c39cbff55337226fd5e0b520f341f1fb5c6" @@ -8376,15 +8512,15 @@ static-extend@^0.1.1: define-property "^0.2.5" object-copy "^0.1.0" -statuses@2.0.1: +statuses@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/statuses/-/statuses-2.0.1.tgz#55cb000ccf1d48728bd23c685a063998cf1a1b63" integrity sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ== -statuses@~1.5.0: - version "1.5.0" - resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c" - integrity sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA== +std-env@^3.7.0: + version "3.7.0" + resolved "https://registry.yarnpkg.com/std-env/-/std-env-3.7.0.tgz#c9f7386ced6ecf13360b6c6c55b8aaa4ef7481d2" + integrity sha512-JPbdCEQLj1w5GilpiHAx3qJvFndqybBysA3qUOnznweH4QbNYUsW/ea8QzSrnh0vNsezMMw5bcVool8lM0gwzg== stdin-discarder@^0.1.0: version "0.1.0" @@ -8400,15 +8536,6 @@ stream-events@^1.0.5: dependencies: stubs "^3.0.0" -streamroller@^3.1.5: - version "3.1.5" - resolved "https://registry.yarnpkg.com/streamroller/-/streamroller-3.1.5.tgz#1263182329a45def1ffaef58d31b15d13d2ee7ff" - integrity sha512-KFxaM7XT+irxvdqSP1LGLgNWbYN7ay5owZ3r/8t77p+EtSUAfUgtl7be3xtqtOmGUl9K9YPO2ca8133RlTjvKw== - dependencies: - date-format "^4.0.14" - debug "^4.3.4" - fs-extra "^8.1.0" - streamx@^2.15.0: version "2.16.1" resolved "https://registry.yarnpkg.com/streamx/-/streamx-2.16.1.tgz#2b311bd34832f08aa6bb4d6a80297c9caef89614" @@ -8419,6 +8546,11 @@ streamx@^2.15.0: optionalDependencies: bare-events "^2.2.0" +strict-event-emitter@^0.5.1: + version "0.5.1" + resolved "https://registry.yarnpkg.com/strict-event-emitter/-/strict-event-emitter-0.5.1.tgz#1602ece81c51574ca39c6815e09f1a3e8550bd93" + integrity sha512-vMgjE/GGEPEFnhFub6pa4FmJBRBVOLpIII2hvCZ8Kzb7K0hlHo7mQv6xYrBvCL2LtAIBwFUK8wvuJgTVSQ5MFQ== + string-argv@~0.3.2: version "0.3.2" resolved "https://registry.yarnpkg.com/string-argv/-/string-argv-0.3.2.tgz#2b6d0ef24b656274d957d54e0a4bbf6153dc02b6" @@ -8594,28 +8726,21 @@ strip-indent@^3.0.0: dependencies: min-indent "^1.0.0" -strip-json-comments@3.1.1, strip-json-comments@^3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" - integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== - strip-json-comments@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" integrity sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ== +strip-json-comments@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" + integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== + stubs@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/stubs/-/stubs-3.0.0.tgz#e8d2ba1fa9c90570303c030b6900f7d5f89abe5b" integrity sha512-PdHt7hHUJKxvTCgbKX9C1V/ftOcjJQgz8BZwNfV5c4B6dcGqlpelTbJ999jBGZ2jYiPAwcX5dP6oBwVlBlUbxw== -supports-color@8.1.1, supports-color@^8.0.0: - version "8.1.1" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c" - integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q== - dependencies: - has-flag "^4.0.0" - supports-color@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" @@ -8628,13 +8753,20 @@ supports-color@^5.3.0: dependencies: has-flag "^3.0.0" -supports-color@^7, supports-color@^7.1.0: +supports-color@^7.1.0: version "7.2.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== dependencies: has-flag "^4.0.0" +supports-color@^8.0.0: + version "8.1.1" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c" + integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q== + dependencies: + has-flag "^4.0.0" + supports-preserve-symlinks-flag@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" @@ -8720,9 +8852,9 @@ terser-webpack-plugin@^5.3.10: terser "^5.26.0" terser@^5.26.0: - version "5.29.2" - resolved "https://registry.yarnpkg.com/terser/-/terser-5.29.2.tgz#c17d573ce1da1b30f21a877bffd5655dd86fdb35" - integrity sha512-ZiGkhUBIM+7LwkNjXYJq8svgkd+QK3UUr0wJqY4MieaezBSAIPgbSPZyIx0idM6XWK5CMzSWa8MJIzmRcB8Caw== + version "5.31.3" + resolved "https://registry.yarnpkg.com/terser/-/terser-5.31.3.tgz#b24b7beb46062f4653f049eea4f0cd165d0f0c38" + integrity sha512-pAfYn3NIZLyZpa83ZKigvj6Rn9c/vd5KfYGX7cN1mnzqgDcxWvrU5ZtAfIKhEXz9nRecw4z3LXkjaq96/qZqAA== dependencies: "@jridgewell/source-map" "^0.3.3" acorn "^8.8.2" @@ -8776,6 +8908,26 @@ tiny-glob@^0.2.6: globalyzer "0.1.0" globrex "^0.1.2" +tinybench@^2.8.0: + version "2.8.0" + resolved "https://registry.yarnpkg.com/tinybench/-/tinybench-2.8.0.tgz#30e19ae3a27508ee18273ffed9ac7018949acd7b" + integrity sha512-1/eK7zUnIklz4JUUlL+658n58XO2hHLQfSk1Zf2LKieUjxidN16eKFEoDEfjHc3ohofSSqK3X5yO6VGb6iW8Lw== + +tinypool@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/tinypool/-/tinypool-1.0.0.tgz#a68965218e04f4ad9de037d2a1cd63cda9afb238" + integrity sha512-KIKExllK7jp3uvrNtvRBYBWBOAXSX8ZvoaD8T+7KB/QHIuoJW3Pmr60zucywjAlMb5TeXUkcs/MWeWLu0qvuAQ== + +tinyrainbow@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/tinyrainbow/-/tinyrainbow-1.2.0.tgz#5c57d2fc0fb3d1afd78465c33ca885d04f02abb5" + integrity sha512-weEDEq7Z5eTHPDh4xjX789+fHfF+P8boiFB+0vbWzpbnbsEr/GRaohi/uMKxg8RZMXnl1ItAi/IUHWMsjDV7kQ== + +tinyspy@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/tinyspy/-/tinyspy-3.0.0.tgz#cb61644f2713cd84dee184863f4642e06ddf0585" + integrity sha512-q5nmENpTHgiPVd1cJDDc9cVoYN5x4vCvwT3FMilvKPKneCBZAxn2YWQjDF0UMcE9k0Cay1gBiDfTMU0g+mPMQA== + tmp@^0.0.33: version "0.0.33" resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9" @@ -8825,10 +8977,10 @@ to-regex@^3.0.1, to-regex@^3.0.2: regex-not "^1.0.2" safe-regex "^1.1.0" -toidentifier@1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.1.tgz#3be34321a88a820ed1bd80dfaa33e479fbb8dd35" - integrity sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA== +totalist@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/totalist/-/totalist-3.0.1.tgz#ba3a3d600c915b1a97872348f79c127475f6acf8" + integrity sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ== tough-cookie@~2.5.0: version "2.5.0" @@ -8918,11 +9070,6 @@ type-check@^0.4.0, type-check@~0.4.0: dependencies: prelude-ls "^1.2.1" -type-detect@4.0.8, type-detect@^4.0.0, type-detect@^4.0.8: - version "4.0.8" - resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c" - integrity sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g== - type-fest@^0.13.1: version "0.13.1" resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.13.1.tgz#0172cb5bce80b0bd542ea348db50c7e21834d934" @@ -8963,13 +9110,10 @@ type-fest@^2.0.0, type-fest@^2.5.0: resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-2.19.0.tgz#88068015bb33036a598b952e55e9311a60fd3a9b" integrity sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA== -type-is@~1.6.18: - version "1.6.18" - resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131" - integrity sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g== - dependencies: - media-typer "0.3.0" - mime-types "~2.1.24" +type-fest@^4.9.0: + version "4.23.0" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-4.23.0.tgz#8196561a6b835175473be744f3e41e2dece1496b" + integrity sha512-ZiBujro2ohr5+Z/hZWHESLz3g08BBdrdLMieYFULJO+tWc437sn8kQsWLJoZErY8alNhxre9K4p3GURAG11n+w== typed-array-buffer@^1.0.2: version "1.0.2" @@ -9037,15 +9181,10 @@ typescript-workspace-plugin@^2.0.1: resolved "https://registry.yarnpkg.com/typescript-workspace-plugin/-/typescript-workspace-plugin-2.0.1.tgz#3d88be1c35a7fdf2c0160c8cf569ca8993439a12" integrity sha512-xjIYNFlPIA7IWXvnOFJoAeHPbPJSo0AiQDCRJzaAp3+xZwz6maTgeRLB0oEHVtCqz4Q1CDN6U9kh/2z8sxdDBQ== -typescript@^5.4.5: - version "5.4.5" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.4.5.tgz#42ccef2c571fdbd0f6718b1d1f5e6e5ef006f611" - integrity sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ== - -ua-parser-js@^0.7.30: - version "0.7.37" - resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.37.tgz#e464e66dac2d33a7a1251d7d7a99d6157ec27832" - integrity sha512-xV8kqRKM+jhMvcHWUKthV9fNebIzrNy//2O9ZwWcfiBFR5f25XVZPLlEajk/sf3Ra15V92isyQqnIEXRDaZWEA== +typescript@^5.5.4: + version "5.5.4" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.5.4.tgz#d9852d6c82bad2d2eda4fd74a5762a8f5909e9ba" + integrity sha512-Mtq29sKDAEYP7aljRgtPOpTvOfbwRWlS6dPRzwjdE+C0R4brX/GUyhHSecbHMFLNBLcJIPt9nl9yG5TZ1weH+Q== uglify-js@^3.1.4: version "3.17.4" @@ -9125,11 +9264,6 @@ universalify@^2.0.0: resolved "https://registry.yarnpkg.com/universalify/-/universalify-2.0.1.tgz#168efc2180964e6386d061e094df61afe239b18d" integrity sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw== -unpipe@1.0.0, unpipe@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" - integrity sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ== - unset-value@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/unset-value/-/unset-value-1.0.0.tgz#8376873f7d2335179ffb1e6fc3a8ed0dfc8ab559" @@ -9146,6 +9280,14 @@ update-browserslist-db@^1.0.13: escalade "^3.1.1" picocolors "^1.0.0" +update-browserslist-db@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.1.0.tgz#7ca61c0d8650766090728046e416a8cde682859e" + integrity sha512-EdRAaAyk2cUE1wOf2DkEhzxqOQvFOoRJFNS6NeyJ01Gp2beMRpBAINjM2iDXE3KCuKhwnvHIQCJm6ThL2Z+HzQ== + dependencies: + escalade "^3.1.2" + picocolors "^1.0.1" + uri-js@^4.2.2: version "4.4.1" resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" @@ -9175,22 +9317,6 @@ util-deprecate@^1.0.1, util-deprecate@~1.0.1: resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw== -util@^0.12.5: - version "0.12.5" - resolved "https://registry.yarnpkg.com/util/-/util-0.12.5.tgz#5f17a6059b73db61a875668781a1c2b136bd6fbc" - integrity sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA== - dependencies: - inherits "^2.0.3" - is-arguments "^1.0.4" - is-generator-function "^1.0.7" - is-typed-array "^1.1.3" - which-typed-array "^1.1.2" - -utils-merge@1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713" - integrity sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA== - uuid@^3.3.2: version "3.4.0" resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee" @@ -9216,11 +9342,6 @@ validate-npm-package-name@^3.0.0: dependencies: builtins "^1.0.3" -vary@^1: - version "1.1.2" - resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" - integrity sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg== - verror@1.10.0: version "1.10.0" resolved "https://registry.yarnpkg.com/verror/-/verror-1.10.0.tgz#3a105ca17053af55d6e270c1f8288682e18da400" @@ -9230,10 +9351,52 @@ verror@1.10.0: core-util-is "1.0.2" extsprintf "^1.2.0" -void-elements@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/void-elements/-/void-elements-2.0.1.tgz#c066afb582bb1cb4128d60ea92392e94d5e9dbec" - integrity sha512-qZKX4RnBzH2ugr8Lxa7x+0V6XD9Sb/ouARtiasEQCHB1EVU4NXtmHsDDrx1dO4ne5fc3J6EW05BP1Dl0z0iung== +vite-node@2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/vite-node/-/vite-node-2.0.4.tgz#5600cc9f0d9c3ff9a64050c6858e7e1b62fb3fcd" + integrity sha512-ZpJVkxcakYtig5iakNeL7N3trufe3M6vGuzYAr4GsbCTwobDeyPJpE4cjDhhPluv8OvQCFzu2LWp6GkoKRITXA== + dependencies: + cac "^6.7.14" + debug "^4.3.5" + pathe "^1.1.2" + tinyrainbow "^1.2.0" + vite "^5.0.0" + +vite@^5.0.0: + version "5.3.4" + resolved "https://registry.yarnpkg.com/vite/-/vite-5.3.4.tgz#b36ebd47c8a5e3a8727046375d5f10bf9fdf8715" + integrity sha512-Cw+7zL3ZG9/NZBB8C+8QbQZmR54GwqIz+WMI4b3JgdYJvX+ny9AjJXqkGQlDXSXRP9rP0B4tbciRMOVEKulVOA== + dependencies: + esbuild "^0.21.3" + postcss "^8.4.39" + rollup "^4.13.0" + optionalDependencies: + fsevents "~2.3.3" + +vitest@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/vitest/-/vitest-2.0.4.tgz#ac6bfbaee53e502cee864b07a5b2edf1fcba793e" + integrity sha512-luNLDpfsnxw5QSW4bISPe6tkxVvv5wn2BBs/PuDRkhXZ319doZyLOBr1sjfB5yCEpTiU7xCAdViM8TNVGPwoog== + dependencies: + "@ampproject/remapping" "^2.3.0" + "@vitest/expect" "2.0.4" + "@vitest/pretty-format" "^2.0.4" + "@vitest/runner" "2.0.4" + "@vitest/snapshot" "2.0.4" + "@vitest/spy" "2.0.4" + "@vitest/utils" "2.0.4" + chai "^5.1.1" + debug "^4.3.5" + execa "^8.0.1" + magic-string "^0.30.10" + pathe "^1.1.2" + std-env "^3.7.0" + tinybench "^2.8.0" + tinypool "^1.0.0" + tinyrainbow "^1.2.0" + vite "^5.0.0" + vite-node "2.0.4" + why-is-node-running "^2.3.0" warning@^4.0.0, warning@^4.0.3: version "4.0.3" @@ -9262,22 +9425,15 @@ webidl-conversions@^3.0.0: resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871" integrity sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ== -webpack-merge@^4.1.5: - version "4.2.2" - resolved "https://registry.yarnpkg.com/webpack-merge/-/webpack-merge-4.2.2.tgz#a27c52ea783d1398afd2087f547d7b9d2f43634d" - integrity sha512-TUE1UGoTX2Cd42j3krGYqObZbOD+xF7u28WB7tfUordytSjbWTIjK/8V0amkBfTYN4/pB/GIDlJZZ657BGG19g== - dependencies: - lodash "^4.17.15" - webpack-sources@^3.2.3: version "3.2.3" resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-3.2.3.tgz#2d4daab8451fd4b240cc27055ff6a0c2ccea0cde" integrity sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w== -webpack@^5.92.0: - version "5.92.0" - resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.92.0.tgz#cc114c71e6851d220b1feaae90159ed52c876bdf" - integrity sha512-Bsw2X39MYIgxouNATyVpCNVWBCuUwDgWtN78g6lSdPJRLaQ/PUVm/oXcaRAyY/sMFoKFQrsPeqvTizWtq7QPCA== +webpack@^5.93.0: + version "5.93.0" + resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.93.0.tgz#2e89ec7035579bdfba9760d26c63ac5c3462a5e5" + integrity sha512-Y0m5oEY1LRuwly578VqluorkXbvXKh7U3rLoQCEO04M97ScRr44afGVkI0FQFsXzysk5OgFAxjZAb9rsGQVihA== dependencies: "@types/eslint-scope" "^3.7.3" "@types/estree" "^1.0.5" @@ -9356,7 +9512,7 @@ which-module@^2.0.0: resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.1.tgz#776b1fe35d90aebe99e8ac15eb24093389a4a409" integrity sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ== -which-typed-array@^1.1.14, which-typed-array@^1.1.15, which-typed-array@^1.1.2, which-typed-array@^1.1.9: +which-typed-array@^1.1.14, which-typed-array@^1.1.15, which-typed-array@^1.1.9: version "1.1.15" resolved "https://registry.yarnpkg.com/which-typed-array/-/which-typed-array-1.1.15.tgz#264859e9b11a649b388bfaaf4f767df1f779b38d" integrity sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA== @@ -9367,13 +9523,6 @@ which-typed-array@^1.1.14, which-typed-array@^1.1.15, which-typed-array@^1.1.2, gopd "^1.0.1" has-tostringtag "^1.0.2" -which@^1.2.1: - version "1.3.1" - resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" - integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ== - dependencies: - isexe "^2.0.0" - which@^2.0.1: version "2.0.2" resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" @@ -9381,13 +9530,6 @@ which@^2.0.1: dependencies: isexe "^2.0.0" -which@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/which/-/which-3.0.1.tgz#89f1cd0c23f629a8105ffe69b8172791c87b4be1" - integrity sha512-XA1b62dzQzLfaEOSQFTCOd5KFf/1VSzZo7/7TUjnya6u0vGGKzU96UQBZTAThCb2j4/xjBAyii1OhRLJEivHvg== - dependencies: - isexe "^2.0.0" - which@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/which/-/which-4.0.0.tgz#cd60b5e74503a3fbcfbf6cd6b4138a8bae644c1a" @@ -9395,6 +9537,14 @@ which@^4.0.0: dependencies: isexe "^3.1.1" +why-is-node-running@^2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/why-is-node-running/-/why-is-node-running-2.3.0.tgz#a3f69a97107f494b3cdc3bdddd883a7d65cebf04" + integrity sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w== + dependencies: + siginfo "^2.0.0" + stackback "0.0.2" + wide-align@^1.1.0: version "1.1.5" resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.5.tgz#df1d4c206854369ecf3c9a4898f1b23fbd9d15d3" @@ -9407,11 +9557,6 @@ wordwrap@^1.0.0: resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb" integrity sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q== -workerpool@6.2.1: - version "6.2.1" - resolved "https://registry.yarnpkg.com/workerpool/-/workerpool-6.2.1.tgz#46fc150c17d826b86a008e5a4508656777e9c343" - integrity sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw== - wrap-ansi@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-3.0.1.tgz#288a04d87eda5c286e060dfe8f135ce8d007f8ba" @@ -9461,10 +9606,10 @@ wrappy@1: resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== -ws@~8.11.0: - version "8.11.0" - resolved "https://registry.yarnpkg.com/ws/-/ws-8.11.0.tgz#6a0d36b8edfd9f96d8b25683db2f8d7de6e8e143" - integrity sha512-HPG3wQd9sNQoT9xHyNCXoDUa+Xw/VevmY9FoHyQ+g+rrMn4j6FB4np7Z0OhdTgjx6MgQLK7jwSy1YecU1+4Asg== +ws@^8.18.0: + version "8.18.0" + resolved "https://registry.yarnpkg.com/ws/-/ws-8.18.0.tgz#0d7505a6eafe2b0e712d232b42279f53bc289bbc" + integrity sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw== xtend@~4.0.1: version "4.0.2" @@ -9496,11 +9641,6 @@ yaml@~2.4.2: resolved "https://registry.yarnpkg.com/yaml/-/yaml-2.4.5.tgz#60630b206dd6d84df97003d33fc1ddf6296cca5e" integrity sha512-aBx2bnqDzVOyNKfsysjA2ms5ZlnjSAW2eG3/L5G/CSujfjLJTJsEw1bGw8kCf04KodQWk1pxlGnZ56CRxiawmg== -yargs-parser@20.2.4: - version "20.2.4" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.4.tgz#b42890f14566796f85ae8e3a25290d205f154a54" - integrity sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA== - yargs-parser@^13.1.2: version "13.1.2" resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-13.1.2.tgz#130f09702ebaeef2650d54ce6e3e5706f7a4fb38" @@ -9527,29 +9667,6 @@ yargs-parser@^21.1.1: resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-21.1.1.tgz#9096bceebf990d21bb31fa9516e0ede294a77d35" integrity sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw== -yargs-unparser@2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/yargs-unparser/-/yargs-unparser-2.0.0.tgz#f131f9226911ae5d9ad38c432fe809366c2325eb" - integrity sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA== - dependencies: - camelcase "^6.0.0" - decamelize "^4.0.0" - flat "^5.0.2" - is-plain-obj "^2.1.0" - -yargs@16.2.0, yargs@^16.1.1, yargs@^16.2.0: - version "16.2.0" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-16.2.0.tgz#1c82bf0f6b6a66eafce7ef30e376f49a12477f66" - integrity sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw== - dependencies: - cliui "^7.0.2" - escalade "^3.1.1" - get-caller-file "^2.0.5" - require-directory "^2.1.1" - string-width "^4.2.0" - y18n "^5.0.5" - yargs-parser "^20.2.2" - yargs@^13.2.4: version "13.3.2" resolved "https://registry.yarnpkg.com/yargs/-/yargs-13.3.2.tgz#ad7ffefec1aa59565ac915f82dccb38a9c31a2dd" @@ -9583,7 +9700,20 @@ yargs@^15.1.0, yargs@^15.3.1: y18n "^4.0.0" yargs-parser "^18.1.2" -yargs@^17.3.0: +yargs@^16.2.0: + version "16.2.0" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-16.2.0.tgz#1c82bf0f6b6a66eafce7ef30e376f49a12477f66" + integrity sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw== + dependencies: + cliui "^7.0.2" + escalade "^3.1.1" + get-caller-file "^2.0.5" + require-directory "^2.1.1" + string-width "^4.2.0" + y18n "^5.0.5" + yargs-parser "^20.2.2" + +yargs@^17.3.0, yargs@^17.7.2: version "17.7.2" resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.7.2.tgz#991df39aca675a192b816e1e0363f9d75d2aa269" integrity sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w== @@ -9605,3 +9735,8 @@ yocto-queue@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-1.0.0.tgz#7f816433fb2cbc511ec8bf7d263c3b58a1a3c251" integrity sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g== + +yoctocolors-cjs@^2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/yoctocolors-cjs/-/yoctocolors-cjs-2.1.2.tgz#f4b905a840a37506813a7acaa28febe97767a242" + integrity sha512-cYVsTjKl8b+FrnidjibDWskAv7UKOfcwaVZdp/it9n1s9fU3IkgDbhdIRKCW4JDsAlECJY0ytoVPT3sK6kideA== From eec36e5d89e7bdae83b0b2a9c1177ebb0c794443 Mon Sep 17 00:00:00 2001 From: kyletsang <6854874+kyletsang@users.noreply.github.com> Date: Wed, 25 Sep 2024 23:30:04 -0700 Subject: [PATCH 5/5] Publish v2.10.5 --- CHANGELOG.md | 12 ++++++++++++ package.json | 2 +- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0a26c02448..7686a68176 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,15 @@ +## [2.10.5](https://github.com/react-bootstrap/react-bootstrap/compare/v2.10.4...v2.10.5) (2024-09-26) + + +### Bug Fixes + +* **Fade:** fix ref warning for react 18.3+ ([#6820](https://github.com/react-bootstrap/react-bootstrap/issues/6820)) ([9b8bcd7](https://github.com/react-bootstrap/react-bootstrap/commit/9b8bcd783c65632f43cb3fc544547a93ed670c1b)) +* **Offcanvas:** do not trigger Navbar onToggle when closing ([#6829](https://github.com/react-bootstrap/react-bootstrap/issues/6829)) ([6836e99](https://github.com/react-bootstrap/react-bootstrap/commit/6836e997305bbb5d899e1e5de196f584685456ad)) + + + + + ## [2.10.4](https://github.com/react-bootstrap/react-bootstrap/compare/v2.10.3...v2.10.4) (2024-06-30) diff --git a/package.json b/package.json index d4c4ed659f..8727a80de4 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "react-bootstrap", - "version": "2.10.4", + "version": "2.10.5", "description": "Bootstrap 5 components built with React", "keywords": [ "bootstrap",