{
@@ -15,7 +14,7 @@ describe('SegmentedControl', () => {
{ value: 'option3', text: 'Option 3' },
]
- const onSelectMock = jest.fn((value: string | number | symbol) => value)
+ const onSelectMock = vi.fn((value: string | number | symbol) => value)
beforeEach(() => {
onSelectMock.mockClear()
diff --git a/web/app/components/base/spinner/index.spec.tsx b/web/app/components/base/spinner/index.spec.tsx
index 0c4f0f6700..2f8ff9f378 100644
--- a/web/app/components/base/spinner/index.spec.tsx
+++ b/web/app/components/base/spinner/index.spec.tsx
@@ -1,6 +1,5 @@
import React from 'react'
import { render } from '@testing-library/react'
-import '@testing-library/jest-dom'
import Spinner from './index'
describe('Spinner component', () => {
diff --git a/web/app/components/base/timezone-label/__tests__/index.test.tsx b/web/app/components/base/timezone-label/__tests__/index.test.tsx
index 1c36ac929a..926c60dcd5 100644
--- a/web/app/components/base/timezone-label/__tests__/index.test.tsx
+++ b/web/app/components/base/timezone-label/__tests__/index.test.tsx
@@ -3,7 +3,7 @@ import { render, screen } from '@testing-library/react'
import TimezoneLabel from '../index'
// Mock the convertTimezoneToOffsetStr function
-jest.mock('@/app/components/base/date-and-time-picker/utils/dayjs', () => ({
+vi.mock('@/app/components/base/date-and-time-picker/utils/dayjs', () => ({
convertTimezoneToOffsetStr: (timezone?: string) => {
if (!timezone) return 'UTC+0'
diff --git a/web/app/components/base/toast/index.spec.tsx b/web/app/components/base/toast/index.spec.tsx
index 97540cf5b1..b9d855c637 100644
--- a/web/app/components/base/toast/index.spec.tsx
+++ b/web/app/components/base/toast/index.spec.tsx
@@ -2,12 +2,8 @@ import type { ReactNode } from 'react'
import React from 'react'
import { act, render, screen, waitFor } from '@testing-library/react'
import Toast, { ToastProvider, useToastContext } from '.'
-import '@testing-library/jest-dom'
import { noop } from 'lodash-es'
-// Mock timers for testing timeouts
-jest.useFakeTimers()
-
const TestComponent = () => {
const { notify, close } = useToastContext()
@@ -22,6 +18,15 @@ const TestComponent = () => {
}
describe('Toast', () => {
+ beforeEach(() => {
+ vi.useFakeTimers({ shouldAdvanceTime: true })
+ })
+
+ afterEach(() => {
+ vi.runOnlyPendingTimers()
+ vi.useRealTimers()
+ })
+
describe('Toast Component', () => {
test('renders toast with correct type and message', () => {
render(
@@ -138,7 +143,7 @@ describe('Toast', () => {
// Fast-forward timer
act(() => {
- jest.advanceTimersByTime(3000) // Default for info type is 3000ms
+ vi.advanceTimersByTime(3000) // Default for info type is 3000ms
})
// Toast should be gone
@@ -160,7 +165,7 @@ describe('Toast', () => {
// Fast-forward timer
act(() => {
- jest.advanceTimersByTime(6000) // Default for warning type is 6000ms
+ vi.advanceTimersByTime(6000) // Default for warning type is 6000ms
})
// Toast should be removed
@@ -170,7 +175,7 @@ describe('Toast', () => {
})
test('calls onClose callback after duration', async () => {
- const onCloseMock = jest.fn()
+ const onCloseMock = vi.fn()
act(() => {
Toast.notify({
message: 'Closing notification',
@@ -181,7 +186,7 @@ describe('Toast', () => {
// Fast-forward timer
act(() => {
- jest.advanceTimersByTime(3000) // Default for success type is 3000ms
+ vi.advanceTimersByTime(3000) // Default for success type is 3000ms
})
// onClose should be called
diff --git a/web/app/components/base/tooltip/index.spec.tsx b/web/app/components/base/tooltip/index.spec.tsx
index 38cb107197..31c19bb30f 100644
--- a/web/app/components/base/tooltip/index.spec.tsx
+++ b/web/app/components/base/tooltip/index.spec.tsx
@@ -1,6 +1,5 @@
import React from 'react'
import { act, cleanup, fireEvent, render, screen } from '@testing-library/react'
-import '@testing-library/jest-dom'
import Tooltip from './index'
afterEach(cleanup)
diff --git a/web/app/components/base/with-input-validation/index.spec.tsx b/web/app/components/base/with-input-validation/index.spec.tsx
index 732a16d8f1..e9e4120e66 100644
--- a/web/app/components/base/with-input-validation/index.spec.tsx
+++ b/web/app/components/base/with-input-validation/index.spec.tsx
@@ -1,5 +1,4 @@
import { render, screen } from '@testing-library/react'
-import '@testing-library/jest-dom'
import { z } from 'zod'
import withValidation from '.'
import { noop } from 'lodash-es'
@@ -17,11 +16,11 @@ describe('withValidation HOC', () => {
const WrappedComponent = withValidation(TestComponent, schema)
beforeAll(() => {
- jest.spyOn(console, 'error').mockImplementation(noop)
+ vi.spyOn(console, 'error').mockImplementation(noop)
})
afterAll(() => {
- jest.restoreAllMocks()
+ vi.restoreAllMocks()
})
it('renders the component when validation passes', () => {
diff --git a/web/app/components/billing/annotation-full/index.spec.tsx b/web/app/components/billing/annotation-full/index.spec.tsx
index e95900777c..5ea7e6022e 100644
--- a/web/app/components/billing/annotation-full/index.spec.tsx
+++ b/web/app/components/billing/annotation-full/index.spec.tsx
@@ -1,7 +1,7 @@
import { render, screen } from '@testing-library/react'
import AnnotationFull from './index'
-jest.mock('./usage', () => ({
+vi.mock('./usage', () => ({
__esModule: true,
default: (props: { className?: string }) => {
return (
@@ -12,7 +12,7 @@ jest.mock('./usage', () => ({
},
}))
-jest.mock('../upgrade-btn', () => ({
+vi.mock('../upgrade-btn', () => ({
__esModule: true,
default: (props: { loc?: string }) => {
return (
@@ -25,7 +25,7 @@ jest.mock('../upgrade-btn', () => ({
describe('AnnotationFull', () => {
beforeEach(() => {
- jest.clearAllMocks()
+ vi.clearAllMocks()
})
// Rendering marketing copy with action button
diff --git a/web/app/components/billing/annotation-full/modal.spec.tsx b/web/app/components/billing/annotation-full/modal.spec.tsx
index f898402218..6a1ce879d1 100644
--- a/web/app/components/billing/annotation-full/modal.spec.tsx
+++ b/web/app/components/billing/annotation-full/modal.spec.tsx
@@ -1,7 +1,7 @@
import { fireEvent, render, screen } from '@testing-library/react'
import AnnotationFullModal from './modal'
-jest.mock('./usage', () => ({
+vi.mock('./usage', () => ({
__esModule: true,
default: (props: { className?: string }) => {
return (
@@ -13,7 +13,7 @@ jest.mock('./usage', () => ({
}))
let mockUpgradeBtnProps: { loc?: string } | null = null
-jest.mock('../upgrade-btn', () => ({
+vi.mock('../upgrade-btn', () => ({
__esModule: true,
default: (props: { loc?: string }) => {
mockUpgradeBtnProps = props
@@ -31,7 +31,7 @@ type ModalSnapshot = {
className?: string
}
let mockModalProps: ModalSnapshot | null = null
-jest.mock('../../base/modal', () => ({
+vi.mock('../../base/modal', () => ({
__esModule: true,
default: ({ isShow, children, onClose, closable, className }: { isShow: boolean; children: React.ReactNode; onClose: () => void; closable?: boolean; className?: string }) => {
mockModalProps = {
@@ -56,7 +56,7 @@ jest.mock('../../base/modal', () => ({
describe('AnnotationFullModal', () => {
beforeEach(() => {
- jest.clearAllMocks()
+ vi.clearAllMocks()
mockUpgradeBtnProps = null
mockModalProps = null
})
@@ -65,7 +65,7 @@ describe('AnnotationFullModal', () => {
describe('Rendering', () => {
it('should display main info when visible', () => {
// Act
- render(
)
+ render(
)
// Assert
expect(screen.getByText('billing.annotatedResponse.fullTipLine1')).toBeInTheDocument()
@@ -85,7 +85,7 @@ describe('AnnotationFullModal', () => {
describe('Visibility', () => {
it('should not render content when hidden', () => {
// Act
- const { container } = render(
)
+ const { container } = render(
)
// Assert
expect(container).toBeEmptyDOMElement()
@@ -97,7 +97,7 @@ describe('AnnotationFullModal', () => {
describe('Close handling', () => {
it('should trigger onHide when close control is clicked', () => {
// Arrange
- const onHide = jest.fn()
+ const onHide = vi.fn()
// Act
render(
)
diff --git a/web/app/components/billing/plan-upgrade-modal/index.spec.tsx b/web/app/components/billing/plan-upgrade-modal/index.spec.tsx
index cd1be7cc6c..28b41fa3b1 100644
--- a/web/app/components/billing/plan-upgrade-modal/index.spec.tsx
+++ b/web/app/components/billing/plan-upgrade-modal/index.spec.tsx
@@ -3,9 +3,9 @@ import { render, screen } from '@testing-library/react'
import userEvent from '@testing-library/user-event'
import PlanUpgradeModal from './index'
-const mockSetShowPricingModal = jest.fn()
+const mockSetShowPricingModal = vi.fn()
-jest.mock('@/app/components/base/modal', () => {
+vi.mock('@/app/components/base/modal', () => {
const MockModal = ({ isShow, children }: { isShow: boolean; children: React.ReactNode }) => (
isShow ?
{children}
: null
)
@@ -15,7 +15,7 @@ jest.mock('@/app/components/base/modal', () => {
}
})
-jest.mock('@/context/modal-context', () => ({
+vi.mock('@/context/modal-context', () => ({
useModalContext: () => ({
setShowPricingModal: mockSetShowPricingModal,
}),
@@ -25,7 +25,7 @@ const baseProps = {
title: 'Upgrade Required',
description: 'You need to upgrade your plan.',
show: true,
- onClose: jest.fn(),
+ onClose: vi.fn(),
}
const renderComponent = (props: Partial
> = {}) => {
@@ -35,7 +35,7 @@ const renderComponent = (props: Partial {
beforeEach(() => {
- jest.clearAllMocks()
+ vi.clearAllMocks()
})
// Rendering and props-driven content
@@ -68,7 +68,7 @@ describe('PlanUpgradeModal', () => {
it('should call onClose when dismiss button is clicked', async () => {
// Arrange
const user = userEvent.setup()
- const onClose = jest.fn()
+ const onClose = vi.fn()
renderComponent({ onClose })
// Act
@@ -82,8 +82,8 @@ describe('PlanUpgradeModal', () => {
it('should call onUpgrade and onClose when upgrade button is clicked with onUpgrade provided', async () => {
// Arrange
const user = userEvent.setup()
- const onClose = jest.fn()
- const onUpgrade = jest.fn()
+ const onClose = vi.fn()
+ const onUpgrade = vi.fn()
renderComponent({ onClose, onUpgrade })
// Act
@@ -99,7 +99,7 @@ describe('PlanUpgradeModal', () => {
it('should open pricing modal when upgrade button is clicked without onUpgrade', async () => {
// Arrange
const user = userEvent.setup()
- const onClose = jest.fn()
+ const onClose = vi.fn()
renderComponent({ onClose, onUpgrade: undefined })
// Act
diff --git a/web/app/components/billing/plan/assets/enterprise.spec.tsx b/web/app/components/billing/plan/assets/enterprise.spec.tsx
index 831370f5d9..8d5dd8347a 100644
--- a/web/app/components/billing/plan/assets/enterprise.spec.tsx
+++ b/web/app/components/billing/plan/assets/enterprise.spec.tsx
@@ -154,7 +154,10 @@ describe('Enterprise Icon Component', () => {
describe('CSS Variables', () => {
it('should use CSS custom properties for colors', () => {
const { container } = render()
- const elementsWithCSSVars = container.querySelectorAll('[fill*="var("]')
+ const allFillElements = container.querySelectorAll('[fill]')
+ const elementsWithCSSVars = Array.from(allFillElements).filter(el =>
+ el.getAttribute('fill')?.startsWith('var('),
+ )
expect(elementsWithCSSVars.length).toBeGreaterThan(0)
})
diff --git a/web/app/components/billing/plan/assets/professional.spec.tsx b/web/app/components/billing/plan/assets/professional.spec.tsx
index 0fb84e2870..f8cccac40f 100644
--- a/web/app/components/billing/plan/assets/professional.spec.tsx
+++ b/web/app/components/billing/plan/assets/professional.spec.tsx
@@ -119,7 +119,10 @@ describe('Professional Icon Component', () => {
describe('CSS Variables', () => {
it('should use CSS custom properties for colors', () => {
const { container } = render()
- const elementsWithCSSVars = container.querySelectorAll('[fill*="var("]')
+ const allFillElements = container.querySelectorAll('[fill]')
+ const elementsWithCSSVars = Array.from(allFillElements).filter(el =>
+ el.getAttribute('fill')?.startsWith('var('),
+ )
// All fill attributes should use CSS variables
expect(elementsWithCSSVars.length).toBeGreaterThan(0)
diff --git a/web/app/components/billing/plan/assets/sandbox.spec.tsx b/web/app/components/billing/plan/assets/sandbox.spec.tsx
index 5a5accf362..0c70f979df 100644
--- a/web/app/components/billing/plan/assets/sandbox.spec.tsx
+++ b/web/app/components/billing/plan/assets/sandbox.spec.tsx
@@ -110,7 +110,10 @@ describe('Sandbox Icon Component', () => {
describe('CSS Variables', () => {
it('should use CSS custom properties for colors', () => {
const { container } = render()
- const elementsWithCSSVars = container.querySelectorAll('[fill*="var("]')
+ const allFillElements = container.querySelectorAll('[fill]')
+ const elementsWithCSSVars = Array.from(allFillElements).filter(el =>
+ el.getAttribute('fill')?.startsWith('var('),
+ )
// All fill attributes should use CSS variables
expect(elementsWithCSSVars.length).toBeGreaterThan(0)
diff --git a/web/app/components/billing/plan/assets/team.spec.tsx b/web/app/components/billing/plan/assets/team.spec.tsx
index 60e69aa280..d4d1e713d8 100644
--- a/web/app/components/billing/plan/assets/team.spec.tsx
+++ b/web/app/components/billing/plan/assets/team.spec.tsx
@@ -133,7 +133,10 @@ describe('Team Icon Component', () => {
describe('CSS Variables', () => {
it('should use CSS custom properties for colors', () => {
const { container } = render()
- const elementsWithCSSVars = container.querySelectorAll('[fill*="var("]')
+ const allFillElements = container.querySelectorAll('[fill]')
+ const elementsWithCSSVars = Array.from(allFillElements).filter(el =>
+ el.getAttribute('fill')?.startsWith('var('),
+ )
expect(elementsWithCSSVars.length).toBeGreaterThan(0)
})
diff --git a/web/app/components/billing/pricing/plans/cloud-plan-item/button.spec.tsx b/web/app/components/billing/pricing/plans/cloud-plan-item/button.spec.tsx
index 0c50c80c87..d9f6008580 100644
--- a/web/app/components/billing/pricing/plans/cloud-plan-item/button.spec.tsx
+++ b/web/app/components/billing/pricing/plans/cloud-plan-item/button.spec.tsx
@@ -6,7 +6,7 @@ import { Plan } from '../../../type'
describe('CloudPlanButton', () => {
describe('Disabled state', () => {
test('should disable button and hide arrow when plan is not available', () => {
- const handleGetPayUrl = jest.fn()
+ const handleGetPayUrl = vi.fn()
// Arrange
render(