From 94277709d196d860a0ed5a6cef3f04d9bee09d07 Mon Sep 17 00:00:00 2001 From: Brian Donovan <1938+eventualbuddha@users.noreply.github.com> Date: Fri, 17 Jan 2025 09:58:53 -0800 Subject: [PATCH] test(central-scan/frontend): replace `jest` with `vitest` Closes #5831 Part of #5706 --- .../frontend/config/jest/cssTransform.js | 16 ---- apps/central-scan/frontend/jest.config.js | 30 ------- apps/central-scan/frontend/package.json | 19 ++--- .../frontend/src/api/hmpb.test.ts | 1 + apps/central-scan/frontend/src/app.test.tsx | 3 +- .../components/delete_batch_modal.test.tsx | 7 +- .../components/export_results_modal.test.tsx | 9 ++- .../src/components/scan_button.test.tsx | 3 +- .../src/components/test_scan_button.test.tsx | 3 +- .../toggle_test_mode_button.test.tsx | 3 +- .../src/screens/ballot_eject_screen.test.tsx | 20 ++--- .../src/screens/diagnostics_screen.test.tsx | 1 + .../src/screens/scan_ballots_screen.test.tsx | 1 + .../src/screens/settings_screen.test.tsx | 16 ++-- ...tem_administrator_settings_screen.test.tsx | 1 + apps/central-scan/frontend/src/setupTests.ts | 19 ++--- .../frontend/src/util/relative_rect.test.ts | 1 + apps/central-scan/frontend/test/api.tsx | 7 +- apps/central-scan/frontend/vitest.config.ts | 24 ++++++ pnpm-lock.yaml | 81 ++++++++++++------- 20 files changed, 134 insertions(+), 131 deletions(-) delete mode 100644 apps/central-scan/frontend/config/jest/cssTransform.js delete mode 100644 apps/central-scan/frontend/jest.config.js create mode 100644 apps/central-scan/frontend/vitest.config.ts diff --git a/apps/central-scan/frontend/config/jest/cssTransform.js b/apps/central-scan/frontend/config/jest/cssTransform.js deleted file mode 100644 index 74c21818a3..0000000000 --- a/apps/central-scan/frontend/config/jest/cssTransform.js +++ /dev/null @@ -1,16 +0,0 @@ -'use strict'; - -// This is a custom Jest transformer turning style imports into empty objects. -// http://facebook.github.io/jest/docs/en/webpack.html - -module.exports = { - process() { - return { - code: 'module.exports = {};' - }; - }, - getCacheKey() { - // The output is always the same. - return 'cssTransform'; - }, -}; diff --git a/apps/central-scan/frontend/jest.config.js b/apps/central-scan/frontend/jest.config.js deleted file mode 100644 index 00fc3d0898..0000000000 --- a/apps/central-scan/frontend/jest.config.js +++ /dev/null @@ -1,30 +0,0 @@ -const shared = require('../../../jest.config.shared'); - -/** - * @type {import('@jest/types').Config.InitialOptions} - */ -module.exports = { - ...shared, - collectCoverageFrom: [ - 'src/**/*.{js,jsx,ts,tsx}', - '!src/config/*', - '!src/**/*.d.ts', - '!src/index.tsx', - ], - coverageThreshold: { - global: { - branches: -66, - lines: -77, - }, - }, - resetMocks: true, - setupFiles: ['react-app-polyfill/jsdom'], - setupFilesAfterEnv: ['/src/setupTests.ts'], - testEnvironment: 'jsdom', - transform: { - '^.+\\.css$': '/config/jest/cssTransform.js', - }, - transformIgnorePatterns: [ - '[/\\\\]node_modules[/\\\\].+\\.(js|jsx|mjs|cjs|ts|tsx)$', - ], -}; diff --git a/apps/central-scan/frontend/package.json b/apps/central-scan/frontend/package.json index c807087a6d..b962b3c17f 100644 --- a/apps/central-scan/frontend/package.json +++ b/apps/central-scan/frontend/package.json @@ -22,9 +22,9 @@ "stylelint:run": "stylelint 'src/**/*.{js,jsx,ts,tsx}'", "stylelint:run:fix": "stylelint 'src/**/*.{js,jsx,ts,tsx}' --fix", "test": "is-ci test:ci test:watch", - "test:ci": "TZ=America/Anchorage jest --coverage --reporters=default --reporters=jest-junit --maxWorkers=6", - "test:coverage": "TZ=America/Anchorage jest --coverage", - "test:watch": "TZ=America/Anchorage jest --watch", + "test:ci": "TZ=America/Anchorage vitest run --coverage", + "test:coverage": "TZ=America/Anchorage vitest --coverage", + "test:watch": "TZ=America/Anchorage vitest", "type-check": "tsc --build" }, "browserslist": { @@ -77,7 +77,6 @@ "@types/fast-text-encoding": "^1.0.1", "@types/fetch-mock": "^7.3.2", "@types/history": "4.7.11", - "@types/jest": "^29.5.3", "@types/kiosk-browser": "workspace:*", "@types/node": "20.16.0", "@types/pify": "^3.0.2", @@ -89,6 +88,7 @@ "@types/styled-components": "^5.1.26", "@types/testing-library__jest-dom": "^5.14.9", "@vitejs/plugin-react": "^1.3.2", + "@vitest/coverage-istanbul": "^2.1.8", "@votingworks/backend": "workspace:*", "@votingworks/central-scan-backend": "workspace:*", "@votingworks/fixtures": "workspace:*", @@ -102,20 +102,15 @@ "fetch-mock": "9.11.0", "history": "4.10.1", "is-ci-cli": "2.2.0", - "jest": "^29.6.2", - "jest-environment-jsdom": "^29.6.2", - "jest-fetch-mock": "^3.0.3", - "jest-junit": "^16.0.0", - "jest-styled-components": "^7.1.1", - "jest-watch-typeahead": "^2.2.2", "lint-staged": "11.0.0", "node-fetch": "^2.6.0", "react-app-polyfill": "3.0.0", "react-refresh": "^0.9.0", "sort-package-json": "^1.50.0", - "ts-jest": "29.1.1", "type-fest": "^0.18.0", - "vite": "4.5.2" + "vite": "4.5.2", + "vitest": "^2.1.8", + "vitest-styled-components": "^1.0.0" }, "packageManager": "pnpm@8.15.5", "vx": { diff --git a/apps/central-scan/frontend/src/api/hmpb.test.ts b/apps/central-scan/frontend/src/api/hmpb.test.ts index 754829b171..726e7e71df 100644 --- a/apps/central-scan/frontend/src/api/hmpb.test.ts +++ b/apps/central-scan/frontend/src/api/hmpb.test.ts @@ -1,3 +1,4 @@ +import { expect, test } from 'vitest'; import fetchMock from 'fetch-mock'; import { Scan } from '@votingworks/api'; import { fetchNextBallotSheetToReview } from './hmpb'; diff --git a/apps/central-scan/frontend/src/app.test.tsx b/apps/central-scan/frontend/src/app.test.tsx index d07cca21d7..50be03214e 100644 --- a/apps/central-scan/frontend/src/app.test.tsx +++ b/apps/central-scan/frontend/src/app.test.tsx @@ -1,3 +1,4 @@ +import { afterEach, beforeEach, expect, test, vi } from 'vitest'; import fetchMock from 'fetch-mock'; import { readElectionGeneralDefinition } from '@votingworks/fixtures'; import { @@ -27,7 +28,7 @@ const electionKey = constructElectionKey(electionDefinition.election); let apiMock: ApiMock; beforeEach(() => { - jest.restoreAllMocks(); + vi.restoreAllMocks(); apiMock = createApiMock(); apiMock.setAuthStatus({ diff --git a/apps/central-scan/frontend/src/components/delete_batch_modal.test.tsx b/apps/central-scan/frontend/src/components/delete_batch_modal.test.tsx index 7e97511131..5acfd28f34 100644 --- a/apps/central-scan/frontend/src/components/delete_batch_modal.test.tsx +++ b/apps/central-scan/frontend/src/components/delete_batch_modal.test.tsx @@ -1,3 +1,4 @@ +import { afterEach, beforeEach, expect, test, vi } from 'vitest'; import userEvent from '@testing-library/user-event'; import { ApiMock, createApiMock, provideApi } from '../../test/api'; import { render, screen, waitFor } from '../../test/react_testing_library'; @@ -6,7 +7,7 @@ import { DeleteBatchModal } from './delete_batch_modal'; let apiMock: ApiMock; beforeEach(() => { - jest.restoreAllMocks(); + vi.restoreAllMocks(); apiMock = createApiMock(); }); @@ -15,7 +16,7 @@ afterEach(() => { }); test('allows canceling', async () => { - const onClose = jest.fn(); + const onClose = vi.fn(); render( provideApi( @@ -32,7 +33,7 @@ test('allows canceling', async () => { }); test('closes on success', async () => { - const onClose = jest.fn(); + const onClose = vi.fn(); render( provideApi( diff --git a/apps/central-scan/frontend/src/components/export_results_modal.test.tsx b/apps/central-scan/frontend/src/components/export_results_modal.test.tsx index c0f6fb7ad2..7d4cdfadb1 100644 --- a/apps/central-scan/frontend/src/components/export_results_modal.test.tsx +++ b/apps/central-scan/frontend/src/components/export_results_modal.test.tsx @@ -1,3 +1,4 @@ +import { afterEach, beforeEach, expect, test, vi } from 'vitest'; import { err } from '@votingworks/basics'; import type { UsbDriveStatus } from '@votingworks/usb-drive'; import userEvent from '@testing-library/user-event'; @@ -26,7 +27,7 @@ test('render insert USB screen when there is not a valid, mounted usb drive', as for (const usbDriveStatus of usbDriveStatuses) { apiMock.setUsbDriveStatus(usbDriveStatus); - const closeFn = jest.fn(); + const closeFn = vi.fn(); const { unmount } = renderInAppContext( , { @@ -43,7 +44,7 @@ test('render insert USB screen when there is not a valid, mounted usb drive', as }); test('render export modal when a usb drive is mounted as expected and allows export', async () => { - const closeFn = jest.fn(); + const closeFn = vi.fn(); apiMock.setUsbDriveStatus(mockUsbDriveStatus('mounted')); renderInAppContext(, { apiMock, @@ -64,7 +65,7 @@ test('render export modal when a usb drive is mounted as expected and allows exp }); test('render export modal with errors when appropriate', async () => { - const closeFn = jest.fn(); + const closeFn = vi.fn(); apiMock.setUsbDriveStatus(mockUsbDriveStatus('mounted')); renderInAppContext(, { apiMock, @@ -83,7 +84,7 @@ test('render export modal with errors when appropriate', async () => { }); test('render export modal with errors when appropriate - backup', async () => { - const closeFn = jest.fn(); + const closeFn = vi.fn(); apiMock.setUsbDriveStatus(mockUsbDriveStatus('mounted')); renderInAppContext(, { apiMock, diff --git a/apps/central-scan/frontend/src/components/scan_button.test.tsx b/apps/central-scan/frontend/src/components/scan_button.test.tsx index 20e386538a..24f88c454b 100644 --- a/apps/central-scan/frontend/src/components/scan_button.test.tsx +++ b/apps/central-scan/frontend/src/components/scan_button.test.tsx @@ -1,3 +1,4 @@ +import { afterEach, beforeEach, expect, test, vi } from 'vitest'; import userEvent from '@testing-library/user-event'; import { screen } from '../../test/react_testing_library'; import { ScanButton } from './scan_button'; @@ -7,7 +8,7 @@ import { renderInAppContext } from '../../test/render_in_app_context'; let apiMock: ApiMock; beforeEach(() => { - jest.restoreAllMocks(); + vi.restoreAllMocks(); apiMock = createApiMock(); }); diff --git a/apps/central-scan/frontend/src/components/test_scan_button.test.tsx b/apps/central-scan/frontend/src/components/test_scan_button.test.tsx index 0192152359..76ab693328 100644 --- a/apps/central-scan/frontend/src/components/test_scan_button.test.tsx +++ b/apps/central-scan/frontend/src/components/test_scan_button.test.tsx @@ -1,3 +1,4 @@ +import { afterEach, beforeEach, expect, test, vi } from 'vitest'; import userEvent from '@testing-library/user-event'; import { deferred } from '@votingworks/basics'; import { ScanDiagnosticOutcome } from '@votingworks/central-scan-backend'; @@ -14,7 +15,7 @@ import { TestScanButton } from './test_scan_button'; let apiMock: ApiMock; beforeEach(() => { - jest.restoreAllMocks(); + vi.restoreAllMocks(); apiMock = createApiMock(); }); diff --git a/apps/central-scan/frontend/src/components/toggle_test_mode_button.test.tsx b/apps/central-scan/frontend/src/components/toggle_test_mode_button.test.tsx index 0734fbc232..8eb56a8beb 100644 --- a/apps/central-scan/frontend/src/components/toggle_test_mode_button.test.tsx +++ b/apps/central-scan/frontend/src/components/toggle_test_mode_button.test.tsx @@ -1,3 +1,4 @@ +import { afterEach, beforeEach, expect, test, vi } from 'vitest'; import userEvent from '@testing-library/user-event'; import { render, screen, within } from '../../test/react_testing_library'; import { ToggleTestModeButton } from './toggle_test_mode_button'; @@ -7,7 +8,7 @@ import { mockStatus } from '../../test/fixtures'; let apiMock: ApiMock; beforeEach(() => { - jest.restoreAllMocks(); + vi.restoreAllMocks(); apiMock = createApiMock(); }); diff --git a/apps/central-scan/frontend/src/screens/ballot_eject_screen.test.tsx b/apps/central-scan/frontend/src/screens/ballot_eject_screen.test.tsx index da96ee3f63..67698d2579 100644 --- a/apps/central-scan/frontend/src/screens/ballot_eject_screen.test.tsx +++ b/apps/central-scan/frontend/src/screens/ballot_eject_screen.test.tsx @@ -1,3 +1,4 @@ +import { afterEach, beforeEach, expect, test, vi } from 'vitest'; import { mockBaseLogger, LogEventId } from '@votingworks/logging'; import { AdjudicationReason, @@ -48,7 +49,7 @@ test('says the sheet is unreadable if it is', async () => { }) ); - const logger = mockBaseLogger({ fn: jest.fn }); + const logger = mockBaseLogger({ fn: vi.fn }); renderInAppContext(, { apiMock, logger }); @@ -63,7 +64,6 @@ test('says the sheet is unreadable if it is', async () => { 'Confirm Ballot Removed' ); - expect(logger.log).toHaveBeenCalledTimes(1); expect(logger.log).toHaveBeenCalledWith( LogEventId.ScanAdjudicationInfo, 'election_manager', @@ -159,7 +159,7 @@ test('says the ballot sheet is overvoted if it is', async () => { }) ); - const logger = mockBaseLogger({ fn: jest.fn }); + const logger = mockBaseLogger({ fn: vi.fn }); renderInAppContext(, { apiMock, logger }); @@ -271,7 +271,7 @@ test('says the ballot sheet is undervoted if it is', async () => { }) ); - const logger = mockBaseLogger({ fn: jest.fn }); + const logger = mockBaseLogger({ fn: vi.fn }); renderInAppContext(, { apiMock, logger }); @@ -390,7 +390,7 @@ test('says the ballot sheet is blank if it is', async () => { }) ); - const logger = mockBaseLogger({ fn: jest.fn }); + const logger = mockBaseLogger({ fn: vi.fn }); renderInAppContext(, { apiMock, logger }); @@ -458,7 +458,7 @@ test('calls out official ballot sheets in test mode', async () => { }) ); - const logger = mockBaseLogger({ fn: jest.fn }); + const logger = mockBaseLogger({ fn: vi.fn }); renderInAppContext(, { apiMock, logger }); @@ -524,7 +524,7 @@ test('calls out test ballot sheets in live mode', async () => { }) ); - const logger = mockBaseLogger({ fn: jest.fn }); + const logger = mockBaseLogger({ fn: vi.fn }); renderInAppContext(, { apiMock, @@ -577,7 +577,7 @@ test('shows invalid election screen when appropriate', async () => { }) ); - const logger = mockBaseLogger({ fn: jest.fn }); + const logger = mockBaseLogger({ fn: vi.fn }); renderInAppContext(, { apiMock, @@ -695,7 +695,7 @@ test('does not allow tabulating the overvote if disallowCastingOvervotes is set' }) ); - const logger = mockBaseLogger({ fn: jest.fn }); + const logger = mockBaseLogger({ fn: vi.fn }); renderInAppContext(, { apiMock, logger }); @@ -736,7 +736,7 @@ test('says the scanner needs cleaning if a streak is detected', async () => { }) ); - const logger = mockBaseLogger({ fn: jest.fn }); + const logger = mockBaseLogger({ fn: vi.fn }); renderInAppContext(, { apiMock, logger }); diff --git a/apps/central-scan/frontend/src/screens/diagnostics_screen.test.tsx b/apps/central-scan/frontend/src/screens/diagnostics_screen.test.tsx index 60481eb8df..445b5f87aa 100644 --- a/apps/central-scan/frontend/src/screens/diagnostics_screen.test.tsx +++ b/apps/central-scan/frontend/src/screens/diagnostics_screen.test.tsx @@ -1,3 +1,4 @@ +import { afterEach, beforeEach, test } from 'vitest'; import { mockUsbDriveStatus } from '@votingworks/ui'; import { readElectionTwoPartyPrimaryDefinition } from '@votingworks/fixtures'; import { screen } from '../../test/react_testing_library'; diff --git a/apps/central-scan/frontend/src/screens/scan_ballots_screen.test.tsx b/apps/central-scan/frontend/src/screens/scan_ballots_screen.test.tsx index d322be9a9d..409a552a90 100644 --- a/apps/central-scan/frontend/src/screens/scan_ballots_screen.test.tsx +++ b/apps/central-scan/frontend/src/screens/scan_ballots_screen.test.tsx @@ -1,3 +1,4 @@ +import { afterEach, beforeEach, describe, expect, test } from 'vitest'; import { hasTextAcrossElements } from '@votingworks/test-utils'; import userEvent from '@testing-library/user-event'; import type { ScanStatus } from '@votingworks/central-scan-backend'; diff --git a/apps/central-scan/frontend/src/screens/settings_screen.test.tsx b/apps/central-scan/frontend/src/screens/settings_screen.test.tsx index 78cbc8ae06..268cfcfb25 100644 --- a/apps/central-scan/frontend/src/screens/settings_screen.test.tsx +++ b/apps/central-scan/frontend/src/screens/settings_screen.test.tsx @@ -1,12 +1,8 @@ +import { afterEach, beforeEach, expect, test, vi } from 'vitest'; import userEvent from '@testing-library/user-event'; import { createMemoryHistory } from 'history'; import { mockUsbDriveStatus } from '@votingworks/ui'; -import { - screen, - waitFor, - waitForElementToBeRemoved, - within, -} from '../../test/react_testing_library'; +import { screen, waitFor, within } from '../../test/react_testing_library'; import { renderInAppContext } from '../../test/render_in_app_context'; import { SettingsScreenProps, SettingsScreen } from './settings_screen'; import { ApiMock, createApiMock } from '../../test/api'; @@ -87,7 +83,7 @@ test('clicking "Unconfigure Machine" calls backend', async () => { }); test('clicking "Update Date and Time" shows modal to set clock', async () => { - jest.useFakeTimers().setSystemTime(new Date('2020-10-31T00:00:00.000')); + vi.useFakeTimers().setSystemTime(new Date('2020-10-31T00:00:00.000')); renderScreen(); @@ -114,7 +110,9 @@ test('clicking "Update Date and Time" shows modal to set clock', async () => { .resolves(); apiMock.expectLogOut(); userEvent.click(within(modal).getByRole('button', { name: 'Save' })); - await waitForElementToBeRemoved(screen.queryByRole('alertdialog')); + await vi.waitFor(() => { + expect(screen.queryByRole('alertdialog')).not.toBeInTheDocument(); + }); - jest.useRealTimers(); + vi.useRealTimers(); }); diff --git a/apps/central-scan/frontend/src/screens/system_administrator_settings_screen.test.tsx b/apps/central-scan/frontend/src/screens/system_administrator_settings_screen.test.tsx index ab6e568d60..36ba5f818e 100644 --- a/apps/central-scan/frontend/src/screens/system_administrator_settings_screen.test.tsx +++ b/apps/central-scan/frontend/src/screens/system_administrator_settings_screen.test.tsx @@ -1,3 +1,4 @@ +import { afterEach, beforeEach, expect, test } from 'vitest'; import userEvent from '@testing-library/user-event'; import { ok } from '@votingworks/basics'; import { mockUsbDriveStatus } from '@votingworks/ui'; diff --git a/apps/central-scan/frontend/src/setupTests.ts b/apps/central-scan/frontend/src/setupTests.ts index 49eb93d4ed..04431a44ff 100644 --- a/apps/central-scan/frontend/src/setupTests.ts +++ b/apps/central-scan/frontend/src/setupTests.ts @@ -1,24 +1,21 @@ -import '@testing-library/jest-dom/extend-expect'; +import matchers from '@testing-library/jest-dom/matchers'; +import { afterAll, beforeAll, beforeEach, expect, vi } from 'vitest'; import { clearTemporaryRootDir, setupTemporaryRootDir, } from '@votingworks/fixtures'; import fetchMock from 'fetch-mock'; -import jestFetchMock from 'jest-fetch-mock'; -import 'jest-styled-components'; +import 'vitest-styled-components'; import { TextDecoder, TextEncoder } from 'node:util'; -import { configure } from '../test/react_testing_library'; +import { cleanup, configure } from '../test/react_testing_library'; -configure({ asyncUtilTimeout: 5_000 }); +expect.extend(matchers); -// styled-components version 5.3.1 and above requires this remapping for jest -// environments, reference: https://github.com/styled-components/styled-components/issues/3570 -jest.mock('styled-components', () => - jest.requireActual('styled-components/dist/styled-components.browser.cjs.js') -); +configure({ asyncUtilTimeout: 5_000 }); beforeEach(() => { - jestFetchMock.enableMocks(); + vi.clearAllMocks(); + cleanup(); fetchMock.reset(); fetchMock.mock(); }); diff --git a/apps/central-scan/frontend/src/util/relative_rect.test.ts b/apps/central-scan/frontend/src/util/relative_rect.test.ts index 9992813722..846102d903 100644 --- a/apps/central-scan/frontend/src/util/relative_rect.test.ts +++ b/apps/central-scan/frontend/src/util/relative_rect.test.ts @@ -1,3 +1,4 @@ +import { expect, test } from 'vitest'; import { relativeRect } from './relative_rect'; test('ratio rect', () => { diff --git a/apps/central-scan/frontend/test/api.tsx b/apps/central-scan/frontend/test/api.tsx index d84dace220..46dd3a7ea3 100644 --- a/apps/central-scan/frontend/test/api.tsx +++ b/apps/central-scan/frontend/test/api.tsx @@ -1,3 +1,4 @@ +import { Mock, vi } from 'vitest'; import React from 'react'; import type { Api, @@ -21,16 +22,16 @@ import { ApiClientContext, createQueryClient, systemCallApi } from '../src/api'; import { DEFAULT_STATUS } from './fixtures'; export type MockApiClient = Omit, 'getBatteryInfo'> & { - // Because this is polled so frequently, we opt for a standard jest mock instead of a + // Because this is polled so frequently, we opt for a standard vitest mock instead of a // libs/test-utils mock since the latter requires every call to be explicitly mocked - getBatteryInfo: jest.Mock; + getBatteryInfo: Mock; }; export function createMockApiClient(): MockApiClient { const mockApiClient = createMockClient(); // For some reason, using an object spread to override the polling methods breaks the rest // of the mockApiClient, so we override like this instead - (mockApiClient.getBatteryInfo as unknown as jest.Mock) = jest.fn(() => + (mockApiClient.getBatteryInfo as unknown as Mock) = vi.fn(() => Promise.resolve({ level: 1, discharging: false }) ); return mockApiClient as unknown as MockApiClient; diff --git a/apps/central-scan/frontend/vitest.config.ts b/apps/central-scan/frontend/vitest.config.ts new file mode 100644 index 0000000000..51750dcbf1 --- /dev/null +++ b/apps/central-scan/frontend/vitest.config.ts @@ -0,0 +1,24 @@ +import { join } from 'path'; +import { defineConfig } from '../../../vitest.config.shared.mjs'; + +export default defineConfig({ + test: { + environment: 'jsdom', + mockReset: true, + setupFiles: ['react-app-polyfill/jsdom', 'src/setupTests.ts'], + coverage: { + exclude: [ + 'src/config/*', + 'src/**/*.d.ts', + 'src/index.tsx', + '**/*.test.{ts,tsx}', + ], + }, + alias: [ + { + find: '@votingworks/ui', + replacement: join(__dirname, '../../../libs/ui/src/index.ts'), + }, + ], + }, +}); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 05b6ed24d1..9ee5876ad0 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -965,9 +965,6 @@ importers: '@types/history': specifier: 4.7.11 version: 4.7.11 - '@types/jest': - specifier: ^29.5.3 - version: 29.5.3 '@types/kiosk-browser': specifier: workspace:* version: link:../../../libs/@types/kiosk-browser @@ -1001,6 +998,9 @@ importers: '@vitejs/plugin-react': specifier: ^1.3.2 version: 1.3.2 + '@vitest/coverage-istanbul': + specifier: ^2.1.8 + version: 2.1.8(vitest@2.1.8) '@votingworks/backend': specifier: workspace:* version: link:../../../libs/backend @@ -1040,24 +1040,6 @@ importers: is-ci-cli: specifier: 2.2.0 version: 2.2.0 - jest: - specifier: ^29.6.2 - version: 29.6.2(@types/node@20.16.0) - jest-environment-jsdom: - specifier: ^29.6.2 - version: 29.6.2 - jest-fetch-mock: - specifier: ^3.0.3 - version: 3.0.3 - jest-junit: - specifier: ^16.0.0 - version: 16.0.0 - jest-styled-components: - specifier: ^7.1.1 - version: 7.1.1(styled-components@5.3.11) - jest-watch-typeahead: - specifier: ^2.2.2 - version: 2.2.2(jest@29.6.2) lint-staged: specifier: 11.0.0 version: 11.0.0 @@ -1073,15 +1055,18 @@ importers: sort-package-json: specifier: ^1.50.0 version: 1.53.1 - ts-jest: - specifier: 29.1.1 - version: 29.1.1(@babel/core@7.26.0)(@jest/types@29.6.1)(esbuild@0.21.2)(jest@29.6.2)(typescript@5.6.2) type-fest: specifier: ^0.18.0 version: 0.18.1 vite: specifier: 4.5.2 version: 4.5.2(@types/node@20.16.0) + vitest: + specifier: ^2.1.8 + version: 2.1.8(@types/node@20.16.0)(jsdom@20.0.1) + vitest-styled-components: + specifier: ^1.0.0 + version: 1.0.0(styled-components@5.3.11) apps/central-scan/frontend/prodserver: dependencies: @@ -5612,6 +5597,10 @@ packages: resolution: {integrity: sha512-E09FiIft46CmH5Qnjb0wsW54/YQd69LsxeKUOWawmws1XWvyFGURnAChH0mlr7YPFR1ofwvUQfcL0J3lMxXqPA==} dev: true + /@adobe/css-tools@4.4.1: + resolution: {integrity: sha512-12WGKBQzjUAI4ayyF4IAtfw2QR/IDoqk6jTddXDhtYTJF9ASmoE1zst7cVtP0aL/F1jUJL5r+JxKXKEgHNbEUQ==} + dev: true + /@ampproject/remapping@2.2.1: resolution: {integrity: sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg==} engines: {node: '>=6.0.0'} @@ -11976,7 +11965,7 @@ packages: vitest: 2.1.8 dependencies: '@istanbuljs/schema': 0.1.3 - debug: 4.3.7 + debug: 4.4.0 istanbul-lib-coverage: 3.2.2 istanbul-lib-instrument: 6.0.3 istanbul-lib-report: 3.0.1 @@ -14001,6 +13990,14 @@ packages: source-map-js: 1.2.0 dev: true + /css-tree@3.1.0: + resolution: {integrity: sha512-0eW44TGN5SQXU1mWSkKwFstI/22X2bG1nYzZTYMAWjylYURhse752YgbE4Cx46AC+bAvI+/dYTPRk1LqSUnu6w==} + engines: {node: ^10 || ^12.20.0 || ^14.13.0 || >=15.0.0} + dependencies: + mdn-data: 2.12.2 + source-map-js: 1.2.1 + dev: true + /css-what@6.1.0: resolution: {integrity: sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==} engines: {node: '>= 6'} @@ -14110,6 +14107,17 @@ packages: dependencies: ms: 2.1.3 + /debug@4.4.0: + resolution: {integrity: sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==} + engines: {node: '>=6.0'} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + dependencies: + ms: 2.1.3 + /decamelize-keys@1.1.0: resolution: {integrity: sha512-ocLWuYzRPoS9bfiSdDd3cxvrzovVMZnRDVEzAs+hWIVXGDbHxWMECij2OBuyB/An0FFW/nLuq6Kv1i/YC5Qfzg==} engines: {node: '>=0.10.0'} @@ -14630,8 +14638,8 @@ packages: resolution: {integrity: sha512-1HQ2M2sPtxwnvOvT1ZClHyQDiggdNjURWpY2we6aMKCQiUVxTmVs2UYPLIrD84sS+kMdUwfBSylbJPwNnBrnHQ==} dev: true - /es-module-lexer@1.5.4: - resolution: {integrity: sha512-MVNK56NiMrOwitFB7cqDwq0CQutbw+0BvLshJSse0MUNU+y1FC3bUS/AQg7oUng+/wKrrki7JfmwtVHkVfPLlw==} + /es-module-lexer@1.6.0: + resolution: {integrity: sha512-qqnD1yMU6tk/jnaMosogGySTZP8YtUgAffA9nMN+E/rjxcfRQ6IEk7IiozUjgxKoFHBGjTLnrHB/YC45r/59EQ==} /es-set-tostringtag@2.0.1: resolution: {integrity: sha512-g3OMbtlwY3QewlqAiMLI47KywjWZoEytKr8pf6iTC8uJq5bIAH52Z9pnQ8pVL6whrCto53JZDuUIsifGeLorTg==} @@ -18609,6 +18617,10 @@ packages: resolution: {integrity: sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA==} dev: true + /mdn-data@2.12.2: + resolution: {integrity: sha512-IEn+pegP1aManZuckezWCO+XZQDplx1366JoVhTpMpBB1sPey/SbveZQUosKiKiGYjg1wH4pMlNgXbCiYgihQA==} + dev: true + /mdurl@2.0.0: resolution: {integrity: sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w==} dev: false @@ -23284,8 +23296,8 @@ packages: hasBin: true dependencies: cac: 6.7.14 - debug: 4.3.7 - es-module-lexer: 1.5.4 + debug: 4.4.0 + es-module-lexer: 1.6.0 pathe: 1.1.2 vite: 5.4.11(@types/node@20.16.0) transitivePeerDependencies: @@ -23373,6 +23385,17 @@ packages: optionalDependencies: fsevents: 2.3.3 + /vitest-styled-components@1.0.0(styled-components@5.3.11): + resolution: {integrity: sha512-whznjRp523PO74nYoiZW1d2DtyE7g0jDZnoZtaJdKt8Lj/uS/1T2ech1K7iWaDfwY6Xw8/KBlZt0+JeQWhUDAQ==} + engines: {node: '>= 20'} + peerDependencies: + styled-components: '>= 5' + dependencies: + '@adobe/css-tools': 4.4.1 + css-tree: 3.1.0 + styled-components: 5.3.11(react-dom@18.3.1)(react-is@18.2.0)(react@18.3.1) + dev: true + /vitest@2.1.8: resolution: {integrity: sha512-1vBKTZskHw/aosXqQUlVWWlGUxSJR8YtiyZDJAFeW2kPAeX6S3Sool0mjspO+kXLuxVWlEDDowBAeqeAQefqLQ==} engines: {node: ^18.0.0 || >=20.0.0}