diff --git a/web/app/components/billing/annotation-full/index.spec.tsx b/web/app/components/billing/annotation-full/index.spec.tsx
new file mode 100644
index 0000000000..77a0940f12
--- /dev/null
+++ b/web/app/components/billing/annotation-full/index.spec.tsx
@@ -0,0 +1,71 @@
+import { render, screen } from '@testing-library/react'
+import AnnotationFull from './index'
+
+jest.mock('react-i18next', () => ({
+ useTranslation: () => ({
+ t: (key: string) => key,
+ }),
+}))
+
+let mockUsageProps: { className?: string } | null = null
+jest.mock('./usage', () => ({
+ __esModule: true,
+ default: (props: { className?: string }) => {
+ mockUsageProps = props
+ return (
+
+ usage
+
+ )
+ },
+}))
+
+let mockUpgradeBtnProps: { loc?: string } | null = null
+jest.mock('../upgrade-btn', () => ({
+ __esModule: true,
+ default: (props: { loc?: string }) => {
+ mockUpgradeBtnProps = props
+ return (
+
+ )
+ },
+}))
+
+describe('AnnotationFull', () => {
+ beforeEach(() => {
+ jest.clearAllMocks()
+ mockUsageProps = null
+ mockUpgradeBtnProps = null
+ })
+
+ // Rendering marketing copy with action button
+ describe('Rendering', () => {
+ it('should render tips when rendered', () => {
+ // Act
+ render()
+
+ // Assert
+ expect(screen.getByText('billing.annotatedResponse.fullTipLine1')).toBeInTheDocument()
+ expect(screen.getByText('billing.annotatedResponse.fullTipLine2')).toBeInTheDocument()
+ })
+
+ it('should render upgrade button when rendered', () => {
+ // Act
+ render()
+
+ // Assert
+ expect(screen.getByTestId('upgrade-btn')).toBeInTheDocument()
+ })
+
+ it('should render Usage component when rendered', () => {
+ // Act
+ render()
+
+ // Assert
+ const usageComponent = screen.getByTestId('usage-component')
+ expect(usageComponent).toBeInTheDocument()
+ })
+ })
+})
diff --git a/web/app/components/billing/annotation-full/modal.spec.tsx b/web/app/components/billing/annotation-full/modal.spec.tsx
new file mode 100644
index 0000000000..da2b2041b0
--- /dev/null
+++ b/web/app/components/billing/annotation-full/modal.spec.tsx
@@ -0,0 +1,119 @@
+import { fireEvent, render, screen } from '@testing-library/react'
+import AnnotationFullModal from './modal'
+
+jest.mock('react-i18next', () => ({
+ useTranslation: () => ({
+ t: (key: string) => key,
+ }),
+}))
+
+let mockUsageProps: { className?: string } | null = null
+jest.mock('./usage', () => ({
+ __esModule: true,
+ default: (props: { className?: string }) => {
+ mockUsageProps = props
+ return (
+
+ usage
+
+ )
+ },
+}))
+
+let mockUpgradeBtnProps: { loc?: string } | null = null
+jest.mock('../upgrade-btn', () => ({
+ __esModule: true,
+ default: (props: { loc?: string }) => {
+ mockUpgradeBtnProps = props
+ return (
+
+ )
+ },
+}))
+
+type ModalSnapshot = {
+ isShow: boolean
+ closable?: boolean
+ className?: string
+}
+let mockModalProps: ModalSnapshot | null = null
+jest.mock('../../base/modal', () => ({
+ __esModule: true,
+ default: ({ isShow, children, onClose, closable, className }: { isShow: boolean; children: React.ReactNode; onClose: () => void; closable?: boolean; className?: string }) => {
+ mockModalProps = {
+ isShow,
+ closable,
+ className,
+ }
+ if (!isShow)
+ return null
+ return (
+
+ {closable && (
+
+ )}
+ {children}
+
+ )
+ },
+}))
+
+describe('AnnotationFullModal', () => {
+ beforeEach(() => {
+ jest.clearAllMocks()
+ mockUsageProps = null
+ mockUpgradeBtnProps = null
+ mockModalProps = null
+ })
+
+ // Rendering marketing copy inside modal
+ describe('Rendering', () => {
+ it('should display main info when visible', () => {
+ // Act
+ render()
+
+ // Assert
+ expect(screen.getByText('billing.annotatedResponse.fullTipLine1')).toBeInTheDocument()
+ expect(screen.getByText('billing.annotatedResponse.fullTipLine2')).toBeInTheDocument()
+ expect(screen.getByTestId('usage-component')).toHaveAttribute('data-classname', 'mt-4')
+ expect(screen.getByTestId('upgrade-btn')).toHaveTextContent('annotation-create')
+ expect(mockUpgradeBtnProps?.loc).toBe('annotation-create')
+ expect(mockModalProps).toEqual(expect.objectContaining({
+ isShow: true,
+ closable: true,
+ className: '!p-0',
+ }))
+ })
+ })
+
+ // Controlling modal visibility
+ describe('Visibility', () => {
+ it('should not render content when hidden', () => {
+ // Act
+ const { container } = render()
+
+ // Assert
+ expect(container).toBeEmptyDOMElement()
+ expect(mockModalProps).toEqual(expect.objectContaining({ isShow: false }))
+ })
+ })
+
+ // Handling close interactions
+ describe('Close handling', () => {
+ it('should trigger onHide when close control is clicked', () => {
+ // Arrange
+ const onHide = jest.fn()
+
+ // Act
+ render()
+ fireEvent.click(screen.getByTestId('mock-modal-close'))
+
+ // Assert
+ expect(onHide).toHaveBeenCalledTimes(1)
+ })
+ })
+})
diff --git a/web/app/components/billing/pricing/plans/cloud-plan-item/list/item/index.spec.tsx b/web/app/components/billing/pricing/plans/cloud-plan-item/list/item/index.spec.tsx
new file mode 100644
index 0000000000..25ee1fb8c8
--- /dev/null
+++ b/web/app/components/billing/pricing/plans/cloud-plan-item/list/item/index.spec.tsx
@@ -0,0 +1,52 @@
+import { render, screen } from '@testing-library/react'
+import Item from './index'
+
+describe('Item', () => {
+ beforeEach(() => {
+ jest.clearAllMocks()
+ })
+
+ // Rendering the plan item row
+ describe('Rendering', () => {
+ it('should render the provided label when tooltip is absent', () => {
+ // Arrange
+ const label = 'Monthly credits'
+
+ // Act
+ const { container } = render( )
+
+ // Assert
+ expect(screen.getByText(label)).toBeInTheDocument()
+ expect(container.querySelector('.group')).toBeNull()
+ })
+ })
+
+ // Toggling the optional tooltip indicator
+ describe('Tooltip behavior', () => {
+ it('should render tooltip content when tooltip text is provided', () => {
+ // Arrange
+ const label = 'Workspace seats'
+ const tooltip = 'Seats define how many teammates can join the workspace.'
+
+ // Act
+ const { container } = render( )
+
+ // Assert
+ expect(screen.getByText(label)).toBeInTheDocument()
+ expect(screen.getByText(tooltip)).toBeInTheDocument()
+ expect(container.querySelector('.group')).not.toBeNull()
+ })
+
+ it('should treat an empty tooltip string as absent', () => {
+ // Arrange
+ const label = 'Vector storage'
+
+ // Act
+ const { container } = render( )
+
+ // Assert
+ expect(screen.getByText(label)).toBeInTheDocument()
+ expect(container.querySelector('.group')).toBeNull()
+ })
+ })
+})
diff --git a/web/app/components/billing/pricing/plans/cloud-plan-item/list/item/tooltip.spec.tsx b/web/app/components/billing/pricing/plans/cloud-plan-item/list/item/tooltip.spec.tsx
new file mode 100644
index 0000000000..b1a6750fd7
--- /dev/null
+++ b/web/app/components/billing/pricing/plans/cloud-plan-item/list/item/tooltip.spec.tsx
@@ -0,0 +1,46 @@
+import { render, screen } from '@testing-library/react'
+import Tooltip from './tooltip'
+
+describe('Tooltip', () => {
+ beforeEach(() => {
+ jest.clearAllMocks()
+ })
+
+ // Rendering the info tooltip container
+ describe('Rendering', () => {
+ it('should render the content panel when provide with text', () => {
+ // Arrange
+ const content = 'Usage resets on the first day of every month.'
+
+ // Act
+ render()
+
+ // Assert
+ expect(() => screen.getByText(content)).not.toThrow()
+ })
+ })
+
+ describe('Icon rendering', () => {
+ it('should render the icon when provided with content', () => {
+ // Arrange
+ const content = 'Tooltips explain each plan detail.'
+
+ // Act
+ render()
+
+ // Assert
+ expect(screen.getByTestId('tooltip-icon')).toBeInTheDocument()
+ })
+ })
+
+ // Handling empty strings while keeping structure consistent
+ describe('Edge cases', () => {
+ it('should render without crashing when passed empty content', () => {
+ // Arrange
+ const content = ''
+
+ // Act and Assert
+ expect(() => render()).not.toThrow()
+ })
+ })
+})
diff --git a/web/app/components/billing/pricing/plans/cloud-plan-item/list/item/tooltip.tsx b/web/app/components/billing/pricing/plans/cloud-plan-item/list/item/tooltip.tsx
index 84e0282993..cf6517b292 100644
--- a/web/app/components/billing/pricing/plans/cloud-plan-item/list/item/tooltip.tsx
+++ b/web/app/components/billing/pricing/plans/cloud-plan-item/list/item/tooltip.tsx
@@ -8,13 +8,15 @@ type TooltipProps = {
const Tooltip = ({
content,
}: TooltipProps) => {
+ if (!content)
+ return null
return (
)