mirror of
https://github.com/langgenius/dify.git
synced 2026-04-05 19:32:16 +08:00
refactor(web): migrate to Vitest and esm (#29974)
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com> Co-authored-by: yyh <yuanyouhuilyz@gmail.com>
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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(<AnnotationFullModal show onHide={jest.fn()} />)
|
||||
render(<AnnotationFullModal show onHide={vi.fn()} />)
|
||||
|
||||
// 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(<AnnotationFullModal show={false} onHide={jest.fn()} />)
|
||||
const { container } = render(<AnnotationFullModal show={false} onHide={vi.fn()} />)
|
||||
|
||||
// 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(<AnnotationFullModal show onHide={onHide} />)
|
||||
|
||||
@@ -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 ? <div data-testid="plan-upgrade-modal">{children}</div> : 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<React.ComponentProps<typeof PlanUpgradeModal>> = {}) => {
|
||||
@@ -35,7 +35,7 @@ const renderComponent = (props: Partial<React.ComponentProps<typeof PlanUpgradeM
|
||||
|
||||
describe('PlanUpgradeModal', () => {
|
||||
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
|
||||
|
||||
@@ -154,7 +154,10 @@ describe('Enterprise Icon Component', () => {
|
||||
describe('CSS Variables', () => {
|
||||
it('should use CSS custom properties for colors', () => {
|
||||
const { container } = render(<Enterprise />)
|
||||
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)
|
||||
})
|
||||
|
||||
@@ -119,7 +119,10 @@ describe('Professional Icon Component', () => {
|
||||
describe('CSS Variables', () => {
|
||||
it('should use CSS custom properties for colors', () => {
|
||||
const { container } = render(<Professional />)
|
||||
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)
|
||||
|
||||
@@ -110,7 +110,10 @@ describe('Sandbox Icon Component', () => {
|
||||
describe('CSS Variables', () => {
|
||||
it('should use CSS custom properties for colors', () => {
|
||||
const { container } = render(<Sandbox />)
|
||||
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)
|
||||
|
||||
@@ -133,7 +133,10 @@ describe('Team Icon Component', () => {
|
||||
describe('CSS Variables', () => {
|
||||
it('should use CSS custom properties for colors', () => {
|
||||
const { container } = render(<Team />)
|
||||
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)
|
||||
})
|
||||
|
||||
@@ -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(
|
||||
<Button
|
||||
@@ -27,7 +27,7 @@ describe('CloudPlanButton', () => {
|
||||
|
||||
describe('Enabled state', () => {
|
||||
test('should invoke handler and render arrow when plan is available', () => {
|
||||
const handleGetPayUrl = jest.fn()
|
||||
const handleGetPayUrl = vi.fn()
|
||||
// Arrange
|
||||
render(
|
||||
<Button
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import type { Mock } from 'vitest'
|
||||
import React from 'react'
|
||||
import { fireEvent, render, screen, waitFor } from '@testing-library/react'
|
||||
import CloudPlanItem from './index'
|
||||
@@ -9,37 +10,37 @@ import { fetchBillingUrl, fetchSubscriptionUrls } from '@/service/billing'
|
||||
import Toast from '../../../../base/toast'
|
||||
import { ALL_PLANS } from '../../../config'
|
||||
|
||||
jest.mock('../../../../base/toast', () => ({
|
||||
vi.mock('../../../../base/toast', () => ({
|
||||
__esModule: true,
|
||||
default: {
|
||||
notify: jest.fn(),
|
||||
notify: vi.fn(),
|
||||
},
|
||||
}))
|
||||
|
||||
jest.mock('@/context/app-context', () => ({
|
||||
useAppContext: jest.fn(),
|
||||
vi.mock('@/context/app-context', () => ({
|
||||
useAppContext: vi.fn(),
|
||||
}))
|
||||
|
||||
jest.mock('@/service/billing', () => ({
|
||||
fetchBillingUrl: jest.fn(),
|
||||
fetchSubscriptionUrls: jest.fn(),
|
||||
vi.mock('@/service/billing', () => ({
|
||||
fetchBillingUrl: vi.fn(),
|
||||
fetchSubscriptionUrls: vi.fn(),
|
||||
}))
|
||||
|
||||
jest.mock('@/hooks/use-async-window-open', () => ({
|
||||
useAsyncWindowOpen: jest.fn(),
|
||||
vi.mock('@/hooks/use-async-window-open', () => ({
|
||||
useAsyncWindowOpen: vi.fn(),
|
||||
}))
|
||||
|
||||
jest.mock('../../assets', () => ({
|
||||
vi.mock('../../assets', () => ({
|
||||
Sandbox: () => <div>Sandbox Icon</div>,
|
||||
Professional: () => <div>Professional Icon</div>,
|
||||
Team: () => <div>Team Icon</div>,
|
||||
}))
|
||||
|
||||
const mockUseAppContext = useAppContext as jest.Mock
|
||||
const mockUseAsyncWindowOpen = useAsyncWindowOpen as jest.Mock
|
||||
const mockFetchBillingUrl = fetchBillingUrl as jest.Mock
|
||||
const mockFetchSubscriptionUrls = fetchSubscriptionUrls as jest.Mock
|
||||
const mockToastNotify = Toast.notify as jest.Mock
|
||||
const mockUseAppContext = useAppContext as Mock
|
||||
const mockUseAsyncWindowOpen = useAsyncWindowOpen as Mock
|
||||
const mockFetchBillingUrl = fetchBillingUrl as Mock
|
||||
const mockFetchSubscriptionUrls = fetchSubscriptionUrls as Mock
|
||||
const mockToastNotify = Toast.notify as Mock
|
||||
|
||||
let assignedHref = ''
|
||||
const originalLocation = window.location
|
||||
@@ -66,9 +67,9 @@ afterAll(() => {
|
||||
})
|
||||
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks()
|
||||
vi.clearAllMocks()
|
||||
mockUseAppContext.mockReturnValue({ isCurrentWorkspaceManager: true })
|
||||
mockUseAsyncWindowOpen.mockReturnValue(jest.fn(async open => await open()))
|
||||
mockUseAsyncWindowOpen.mockReturnValue(vi.fn(async open => await open()))
|
||||
mockFetchBillingUrl.mockResolvedValue({ url: 'https://billing.example' })
|
||||
mockFetchSubscriptionUrls.mockResolvedValue({ url: 'https://subscription.example' })
|
||||
assignedHref = ''
|
||||
@@ -147,7 +148,7 @@ describe('CloudPlanItem', () => {
|
||||
})
|
||||
|
||||
test('should open billing portal when upgrading current paid plan', async () => {
|
||||
const openWindow = jest.fn(async (cb: () => Promise<string>) => await cb())
|
||||
const openWindow = vi.fn(async (cb: () => Promise<string>) => await cb())
|
||||
mockUseAsyncWindowOpen.mockReturnValue(openWindow)
|
||||
|
||||
render(
|
||||
|
||||
@@ -3,7 +3,7 @@ import Item from './index'
|
||||
|
||||
describe('Item', () => {
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks()
|
||||
vi.clearAllMocks()
|
||||
})
|
||||
|
||||
// Rendering the plan item row
|
||||
|
||||
@@ -3,7 +3,7 @@ import Tooltip from './tooltip'
|
||||
|
||||
describe('Tooltip', () => {
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks()
|
||||
vi.clearAllMocks()
|
||||
})
|
||||
|
||||
// Rendering the info tooltip container
|
||||
|
||||
@@ -3,19 +3,22 @@ import { render, screen } from '@testing-library/react'
|
||||
import Plans from './index'
|
||||
import { Plan, type UsagePlanInfo } from '../../type'
|
||||
import { PlanRange } from '../plan-switcher/plan-range-switcher'
|
||||
import cloudPlanItem from './cloud-plan-item'
|
||||
import selfHostedPlanItem from './self-hosted-plan-item'
|
||||
import type { Mock } from 'vitest'
|
||||
|
||||
jest.mock('./cloud-plan-item', () => ({
|
||||
vi.mock('./cloud-plan-item', () => ({
|
||||
__esModule: true,
|
||||
default: jest.fn(props => (
|
||||
default: vi.fn(props => (
|
||||
<div data-testid={`cloud-plan-${props.plan}`} data-current-plan={props.currentPlan}>
|
||||
Cloud {props.plan}
|
||||
</div>
|
||||
)),
|
||||
}))
|
||||
|
||||
jest.mock('./self-hosted-plan-item', () => ({
|
||||
vi.mock('./self-hosted-plan-item', () => ({
|
||||
__esModule: true,
|
||||
default: jest.fn(props => (
|
||||
default: vi.fn(props => (
|
||||
<div data-testid={`self-plan-${props.plan}`}>
|
||||
Self {props.plan}
|
||||
</div>
|
||||
@@ -56,8 +59,7 @@ describe('Plans', () => {
|
||||
expect(screen.getByTestId('cloud-plan-professional')).toBeInTheDocument()
|
||||
expect(screen.getByTestId('cloud-plan-team')).toBeInTheDocument()
|
||||
|
||||
const cloudPlanItem = jest.requireMock('./cloud-plan-item').default as jest.Mock
|
||||
const firstCallProps = cloudPlanItem.mock.calls[0][0]
|
||||
const firstCallProps = (cloudPlanItem as unknown as Mock).mock.calls[0][0]
|
||||
expect(firstCallProps.plan).toBe(Plan.sandbox)
|
||||
// Enterprise should be normalized to team when passed down
|
||||
expect(firstCallProps.currentPlan).toBe(Plan.team)
|
||||
@@ -80,8 +82,7 @@ describe('Plans', () => {
|
||||
expect(screen.getByTestId('self-plan-premium')).toBeInTheDocument()
|
||||
expect(screen.getByTestId('self-plan-enterprise')).toBeInTheDocument()
|
||||
|
||||
const selfPlanItem = jest.requireMock('./self-hosted-plan-item').default as jest.Mock
|
||||
expect(selfPlanItem).toHaveBeenCalledTimes(3)
|
||||
expect(selfHostedPlanItem).toHaveBeenCalledTimes(3)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import type { MockedFunction } from 'vitest'
|
||||
import React from 'react'
|
||||
import { fireEvent, render, screen } from '@testing-library/react'
|
||||
import Button from './button'
|
||||
@@ -5,23 +6,18 @@ import { SelfHostedPlan } from '../../../type'
|
||||
import useTheme from '@/hooks/use-theme'
|
||||
import { Theme } from '@/types/app'
|
||||
|
||||
jest.mock('@/hooks/use-theme')
|
||||
vi.mock('@/hooks/use-theme')
|
||||
|
||||
jest.mock('@/app/components/base/icons/src/public/billing', () => ({
|
||||
AwsMarketplaceLight: () => <div>AwsMarketplaceLight</div>,
|
||||
AwsMarketplaceDark: () => <div>AwsMarketplaceDark</div>,
|
||||
}))
|
||||
|
||||
const mockUseTheme = useTheme as jest.MockedFunction<typeof useTheme>
|
||||
const mockUseTheme = useTheme as MockedFunction<typeof useTheme>
|
||||
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks()
|
||||
vi.clearAllMocks()
|
||||
mockUseTheme.mockReturnValue({ theme: Theme.light } as unknown as ReturnType<typeof useTheme>)
|
||||
})
|
||||
|
||||
describe('SelfHostedPlanButton', () => {
|
||||
test('should invoke handler when clicked', () => {
|
||||
const handleGetPayUrl = jest.fn()
|
||||
const handleGetPayUrl = vi.fn()
|
||||
render(
|
||||
<Button
|
||||
plan={SelfHostedPlan.community}
|
||||
@@ -33,29 +29,19 @@ describe('SelfHostedPlanButton', () => {
|
||||
expect(handleGetPayUrl).toHaveBeenCalledTimes(1)
|
||||
})
|
||||
|
||||
test('should render AWS marketplace badge for premium plan in light theme', () => {
|
||||
const handleGetPayUrl = jest.fn()
|
||||
test.each([
|
||||
{ label: 'light', theme: Theme.light },
|
||||
{ label: 'dark', theme: Theme.dark },
|
||||
])('should render premium button label when theme is $label', ({ theme }) => {
|
||||
mockUseTheme.mockReturnValue({ theme } as unknown as ReturnType<typeof useTheme>)
|
||||
|
||||
render(
|
||||
<Button
|
||||
plan={SelfHostedPlan.premium}
|
||||
handleGetPayUrl={handleGetPayUrl}
|
||||
handleGetPayUrl={vi.fn()}
|
||||
/>,
|
||||
)
|
||||
|
||||
expect(screen.getByText('AwsMarketplaceLight')).toBeInTheDocument()
|
||||
})
|
||||
|
||||
test('should switch to dark AWS badge in dark theme', () => {
|
||||
mockUseTheme.mockReturnValue({ theme: Theme.dark } as unknown as ReturnType<typeof useTheme>)
|
||||
|
||||
render(
|
||||
<Button
|
||||
plan={SelfHostedPlan.premium}
|
||||
handleGetPayUrl={jest.fn()}
|
||||
/>,
|
||||
)
|
||||
|
||||
expect(screen.getByText('AwsMarketplaceDark')).toBeInTheDocument()
|
||||
expect(screen.getByRole('button', { name: 'billing.plans.premium.btnText' })).toBeInTheDocument()
|
||||
})
|
||||
})
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import type { Mock } from 'vitest'
|
||||
import React from 'react'
|
||||
import { fireEvent, render, screen } from '@testing-library/react'
|
||||
import SelfHostedPlanItem from './index'
|
||||
@@ -12,7 +13,7 @@ const featuresTranslations: Record<string, string[]> = {
|
||||
'billing.plans.enterprise.features': ['enterprise-feature-1'],
|
||||
}
|
||||
|
||||
jest.mock('react-i18next', () => ({
|
||||
vi.mock('react-i18next', () => ({
|
||||
useTranslation: () => ({
|
||||
t: (key: string, options?: Record<string, unknown>) => {
|
||||
if (options?.returnObjects)
|
||||
@@ -23,18 +24,18 @@ jest.mock('react-i18next', () => ({
|
||||
Trans: ({ i18nKey }: { i18nKey: string }) => <span>{i18nKey}</span>,
|
||||
}))
|
||||
|
||||
jest.mock('../../../../base/toast', () => ({
|
||||
vi.mock('../../../../base/toast', () => ({
|
||||
__esModule: true,
|
||||
default: {
|
||||
notify: jest.fn(),
|
||||
notify: vi.fn(),
|
||||
},
|
||||
}))
|
||||
|
||||
jest.mock('@/context/app-context', () => ({
|
||||
useAppContext: jest.fn(),
|
||||
vi.mock('@/context/app-context', () => ({
|
||||
useAppContext: vi.fn(),
|
||||
}))
|
||||
|
||||
jest.mock('../../assets', () => ({
|
||||
vi.mock('../../assets', () => ({
|
||||
Community: () => <div>Community Icon</div>,
|
||||
Premium: () => <div>Premium Icon</div>,
|
||||
Enterprise: () => <div>Enterprise Icon</div>,
|
||||
@@ -42,15 +43,8 @@ jest.mock('../../assets', () => ({
|
||||
EnterpriseNoise: () => <div>EnterpriseNoise</div>,
|
||||
}))
|
||||
|
||||
jest.mock('@/app/components/base/icons/src/public/billing', () => ({
|
||||
Azure: () => <div>Azure</div>,
|
||||
GoogleCloud: () => <div>Google Cloud</div>,
|
||||
AwsMarketplaceDark: () => <div>AwsMarketplaceDark</div>,
|
||||
AwsMarketplaceLight: () => <div>AwsMarketplaceLight</div>,
|
||||
}))
|
||||
|
||||
const mockUseAppContext = useAppContext as jest.Mock
|
||||
const mockToastNotify = Toast.notify as jest.Mock
|
||||
const mockUseAppContext = useAppContext as Mock
|
||||
const mockToastNotify = Toast.notify as Mock
|
||||
|
||||
let assignedHref = ''
|
||||
const originalLocation = window.location
|
||||
@@ -77,7 +71,7 @@ afterAll(() => {
|
||||
})
|
||||
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks()
|
||||
vi.clearAllMocks()
|
||||
mockUseAppContext.mockReturnValue({ isCurrentWorkspaceManager: true })
|
||||
assignedHref = ''
|
||||
})
|
||||
@@ -100,8 +94,6 @@ describe('SelfHostedPlanItem', () => {
|
||||
|
||||
expect(screen.getByText('billing.plans.premium.price')).toBeInTheDocument()
|
||||
expect(screen.getByText('billing.plans.premium.comingSoon')).toBeInTheDocument()
|
||||
expect(screen.getByText('Azure')).toBeInTheDocument()
|
||||
expect(screen.getByText('Google Cloud')).toBeInTheDocument()
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ import { render, screen } from '@testing-library/react'
|
||||
import List from './index'
|
||||
import { SelfHostedPlan } from '@/app/components/billing/type'
|
||||
|
||||
jest.mock('react-i18next', () => ({
|
||||
vi.mock('react-i18next', () => ({
|
||||
useTranslation: () => ({
|
||||
t: (key: string, options?: Record<string, unknown>) => {
|
||||
if (options?.returnObjects)
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import type { Mock } from 'vitest'
|
||||
import { render, screen, waitFor } from '@testing-library/react'
|
||||
import userEvent from '@testing-library/user-event'
|
||||
import UpgradeBtn from './index'
|
||||
@@ -6,20 +7,20 @@ import UpgradeBtn from './index'
|
||||
// PremiumBadge, Button, SparklesSoft are all base components
|
||||
|
||||
// ✅ Mock external dependencies only
|
||||
const mockSetShowPricingModal = jest.fn()
|
||||
jest.mock('@/context/modal-context', () => ({
|
||||
const mockSetShowPricingModal = vi.fn()
|
||||
vi.mock('@/context/modal-context', () => ({
|
||||
useModalContext: () => ({
|
||||
setShowPricingModal: mockSetShowPricingModal,
|
||||
}),
|
||||
}))
|
||||
|
||||
// Mock gtag for tracking tests
|
||||
let mockGtag: jest.Mock | undefined
|
||||
let mockGtag: Mock | undefined
|
||||
|
||||
describe('UpgradeBtn', () => {
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks()
|
||||
mockGtag = jest.fn()
|
||||
vi.clearAllMocks()
|
||||
mockGtag = vi.fn()
|
||||
;(window as any).gtag = mockGtag
|
||||
})
|
||||
|
||||
@@ -110,7 +111,7 @@ describe('UpgradeBtn', () => {
|
||||
|
||||
it('should apply custom style to premium badge', () => {
|
||||
// Arrange
|
||||
const customStyle = { backgroundColor: 'red', padding: '10px' }
|
||||
const customStyle = { padding: '10px' }
|
||||
|
||||
// Act
|
||||
const { container } = render(<UpgradeBtn style={customStyle} />)
|
||||
@@ -122,7 +123,7 @@ describe('UpgradeBtn', () => {
|
||||
|
||||
it('should apply custom style to plain button', () => {
|
||||
// Arrange
|
||||
const customStyle = { backgroundColor: 'blue', margin: '5px' }
|
||||
const customStyle = { margin: '5px' }
|
||||
|
||||
// Act
|
||||
render(<UpgradeBtn isPlain style={customStyle} />)
|
||||
@@ -162,7 +163,7 @@ describe('UpgradeBtn', () => {
|
||||
it('should call custom onClick when provided and premium badge is clicked', async () => {
|
||||
// Arrange
|
||||
const user = userEvent.setup()
|
||||
const handleClick = jest.fn()
|
||||
const handleClick = vi.fn()
|
||||
|
||||
// Act
|
||||
render(<UpgradeBtn onClick={handleClick} />)
|
||||
@@ -177,7 +178,7 @@ describe('UpgradeBtn', () => {
|
||||
it('should call custom onClick when provided and plain button is clicked', async () => {
|
||||
// Arrange
|
||||
const user = userEvent.setup()
|
||||
const handleClick = jest.fn()
|
||||
const handleClick = vi.fn()
|
||||
|
||||
// Act
|
||||
render(<UpgradeBtn isPlain onClick={handleClick} />)
|
||||
@@ -279,7 +280,7 @@ describe('UpgradeBtn', () => {
|
||||
it('should call both custom onClick and track gtag when both are provided', async () => {
|
||||
// Arrange
|
||||
const user = userEvent.setup()
|
||||
const handleClick = jest.fn()
|
||||
const handleClick = vi.fn()
|
||||
const loc = 'settings-page'
|
||||
|
||||
// Act
|
||||
@@ -409,7 +410,7 @@ describe('UpgradeBtn', () => {
|
||||
it('should handle all custom props together', async () => {
|
||||
// Arrange
|
||||
const user = userEvent.setup()
|
||||
const handleClick = jest.fn()
|
||||
const handleClick = vi.fn()
|
||||
const customStyle = { margin: '10px' }
|
||||
const customClass = 'all-custom'
|
||||
|
||||
@@ -445,7 +446,7 @@ describe('UpgradeBtn', () => {
|
||||
it('should be keyboard accessible with plain button', async () => {
|
||||
// Arrange
|
||||
const user = userEvent.setup()
|
||||
const handleClick = jest.fn()
|
||||
const handleClick = vi.fn()
|
||||
|
||||
// Act
|
||||
render(<UpgradeBtn isPlain onClick={handleClick} />)
|
||||
@@ -465,7 +466,7 @@ describe('UpgradeBtn', () => {
|
||||
it('should be keyboard accessible with Space key', async () => {
|
||||
// Arrange
|
||||
const user = userEvent.setup()
|
||||
const handleClick = jest.fn()
|
||||
const handleClick = vi.fn()
|
||||
|
||||
// Act
|
||||
render(<UpgradeBtn isPlain onClick={handleClick} />)
|
||||
@@ -481,7 +482,7 @@ describe('UpgradeBtn', () => {
|
||||
it('should be clickable for premium badge variant', async () => {
|
||||
// Arrange
|
||||
const user = userEvent.setup()
|
||||
const handleClick = jest.fn()
|
||||
const handleClick = vi.fn()
|
||||
|
||||
// Act
|
||||
render(<UpgradeBtn onClick={handleClick} />)
|
||||
@@ -524,7 +525,7 @@ describe('UpgradeBtn', () => {
|
||||
it('should integrate onClick with analytics tracking', async () => {
|
||||
// Arrange
|
||||
const user = userEvent.setup()
|
||||
const handleClick = jest.fn()
|
||||
const handleClick = vi.fn()
|
||||
|
||||
// Act
|
||||
render(<UpgradeBtn onClick={handleClick} loc="integration-test" />)
|
||||
|
||||
Reference in New Issue
Block a user