diff --git a/web/app/components/billing/utils/index.spec.ts b/web/app/components/billing/utils/index.spec.ts index 03a159c18a..d85155d6ff 100644 --- a/web/app/components/billing/utils/index.spec.ts +++ b/web/app/components/billing/utils/index.spec.ts @@ -94,6 +94,7 @@ describe('billing utils', () => { knowledge_pipeline: { publish_enabled: false, }, + human_input_email_delivery_enabled: false, ...overrides, }) diff --git a/web/app/components/share/text-generation/result/content.spec.tsx b/web/app/components/share/text-generation/result/content.spec.tsx deleted file mode 100644 index 242ae7aa5f..0000000000 --- a/web/app/components/share/text-generation/result/content.spec.tsx +++ /dev/null @@ -1,133 +0,0 @@ -import type { FeedbackType } from '@/app/components/base/chat/chat/type' -import { cleanup, render, screen } from '@testing-library/react' -import { afterEach, describe, expect, it, vi } from 'vitest' -import Result from './content' - -// Only mock react-i18next for translations -vi.mock('react-i18next', () => ({ - useTranslation: () => ({ - t: (key: string) => key, - }), -})) - -// Mock copy-to-clipboard for the Header component -vi.mock('copy-to-clipboard', () => ({ - default: vi.fn(() => true), -})) - -// Mock the format function from service/base -vi.mock('@/service/base', () => ({ - format: (content: string) => content.replace(/\n/g, '
'), -})) - -afterEach(() => { - cleanup() -}) - -describe('Result (content)', () => { - const mockOnFeedback = vi.fn() - - const defaultProps = { - content: 'Test content here', - showFeedback: true, - feedback: { rating: null } as FeedbackType, - onFeedback: mockOnFeedback, - } - - beforeEach(() => { - vi.clearAllMocks() - }) - - describe('rendering', () => { - it('should render the Header component', () => { - render() - - // Header renders the result title - expect(screen.getByText('generation.resultTitle')).toBeInTheDocument() - }) - - it('should render content', () => { - render() - - expect(screen.getByText('Test content here')).toBeInTheDocument() - }) - - it('should render formatted content with line breaks', () => { - render( - , - ) - - // The format function converts \n to
- const contentDiv = document.querySelector('[class*="overflow-scroll"]') - expect(contentDiv?.innerHTML).toContain('Line 1
Line 2') - }) - - it('should have max height style', () => { - render() - - const contentDiv = document.querySelector('[class*="overflow-scroll"]') - expect(contentDiv).toHaveStyle({ maxHeight: '70vh' }) - }) - - it('should render with empty content', () => { - render( - , - ) - - expect(screen.getByText('generation.resultTitle')).toBeInTheDocument() - }) - - it('should render with HTML content safely', () => { - render( - , - ) - - // Content is rendered via dangerouslySetInnerHTML - const contentDiv = document.querySelector('[class*="overflow-scroll"]') - expect(contentDiv).toBeInTheDocument() - }) - }) - - describe('feedback props', () => { - it('should pass showFeedback to Header', () => { - render( - , - ) - - // Feedback buttons should not be visible - const feedbackArea = document.querySelector('[class*="space-x-1 rounded-lg border"]') - expect(feedbackArea).not.toBeInTheDocument() - }) - - it('should pass feedback to Header', () => { - render( - , - ) - - // Like button should be highlighted - const likeButton = document.querySelector('[class*="primary"]') - expect(likeButton).toBeInTheDocument() - }) - }) - - describe('memoization', () => { - it('should be wrapped with React.memo', () => { - expect((Result as unknown as { $$typeof: symbol }).$$typeof).toBe(Symbol.for('react.memo')) - }) - }) -}) diff --git a/web/app/components/share/text-generation/result/header.spec.tsx b/web/app/components/share/text-generation/result/header.spec.tsx deleted file mode 100644 index b2ef0fadc4..0000000000 --- a/web/app/components/share/text-generation/result/header.spec.tsx +++ /dev/null @@ -1,176 +0,0 @@ -import type { FeedbackType } from '@/app/components/base/chat/chat/type' -import { cleanup, fireEvent, render, screen } from '@testing-library/react' -import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest' -import Header from './header' - -// Only mock react-i18next for translations -vi.mock('react-i18next', () => ({ - useTranslation: () => ({ - t: (key: string) => key, - }), -})) - -// Mock copy-to-clipboard -const mockCopy = vi.fn((_text: string) => true) -vi.mock('copy-to-clipboard', () => ({ - default: (text: string) => mockCopy(text), -})) - -afterEach(() => { - cleanup() -}) - -describe('Header', () => { - const mockOnFeedback = vi.fn() - - const defaultProps = { - result: 'Test result content', - showFeedback: true, - feedback: { rating: null } as FeedbackType, - onFeedback: mockOnFeedback, - } - - beforeEach(() => { - vi.clearAllMocks() - }) - - describe('rendering', () => { - it('should render the result title', () => { - render(
) - - expect(screen.getByText('generation.resultTitle')).toBeInTheDocument() - }) - - it('should render the copy button', () => { - render(
) - - expect(screen.getByText('generation.copy')).toBeInTheDocument() - }) - }) - - describe('copy functionality', () => { - it('should copy result when copy button is clicked', () => { - render(
) - - const copyButton = screen.getByText('generation.copy').closest('button') - fireEvent.click(copyButton!) - - expect(mockCopy).toHaveBeenCalledWith('Test result content') - }) - }) - - describe('feedback buttons when showFeedback is true', () => { - it('should show feedback buttons when no rating is given', () => { - render(
) - - // Should show both thumbs up and down buttons - const buttons = document.querySelectorAll('[class*="cursor-pointer"]') - expect(buttons.length).toBeGreaterThan(0) - }) - - it('should show like button highlighted when rating is like', () => { - render( -
, - ) - - // Should show the undo button for like - const likeButton = document.querySelector('[class*="primary"]') - expect(likeButton).toBeInTheDocument() - }) - - it('should show dislike button highlighted when rating is dislike', () => { - render( -
, - ) - - // Should show the undo button for dislike - const dislikeButton = document.querySelector('[class*="red"]') - expect(dislikeButton).toBeInTheDocument() - }) - - it('should call onFeedback with like when thumbs up is clicked', () => { - render(
) - - // Find the thumbs up button (first one in the feedback area) - const thumbButtons = document.querySelectorAll('[class*="cursor-pointer"]') - const thumbsUp = Array.from(thumbButtons).find(btn => - btn.className.includes('rounded-md') && !btn.className.includes('primary'), - ) - - if (thumbsUp) { - fireEvent.click(thumbsUp) - expect(mockOnFeedback).toHaveBeenCalledWith({ rating: 'like' }) - } - }) - - it('should call onFeedback with dislike when thumbs down is clicked', () => { - render(
) - - // Find the thumbs down button - const thumbButtons = document.querySelectorAll('[class*="cursor-pointer"]') - const thumbsDown = Array.from(thumbButtons).pop() - - if (thumbsDown) { - fireEvent.click(thumbsDown) - expect(mockOnFeedback).toHaveBeenCalledWith({ rating: 'dislike' }) - } - }) - - it('should call onFeedback with null when undo like is clicked', () => { - render( -
, - ) - - // When liked, clicking the like button again should undo it (has bg-primary-100 class) - const likeButton = document.querySelector('[class*="bg-primary-100"]') - expect(likeButton).toBeInTheDocument() - fireEvent.click(likeButton!) - expect(mockOnFeedback).toHaveBeenCalledWith({ rating: null }) - }) - - it('should call onFeedback with null when undo dislike is clicked', () => { - render( -
, - ) - - // When disliked, clicking the dislike button again should undo it (has bg-red-100 class) - const dislikeButton = document.querySelector('[class*="bg-red-100"]') - expect(dislikeButton).toBeInTheDocument() - fireEvent.click(dislikeButton!) - expect(mockOnFeedback).toHaveBeenCalledWith({ rating: null }) - }) - }) - - describe('feedback buttons when showFeedback is false', () => { - it('should not show feedback buttons', () => { - render( -
, - ) - - // Should not show feedback area buttons (only copy button) - const feedbackArea = document.querySelector('[class*="space-x-1 rounded-lg border"]') - expect(feedbackArea).not.toBeInTheDocument() - }) - }) - - describe('memoization', () => { - it('should be wrapped with React.memo', () => { - expect((Header as unknown as { $$typeof: symbol }).$$typeof).toBe(Symbol.for('react.memo')) - }) - }) -})