From 3445469385527ac67242f44c954d712ab3589707 Mon Sep 17 00:00:00 2001 From: yyh <92089059+lyzno1@users.noreply.github.com> Date: Thu, 16 Apr 2026 17:53:16 +0800 Subject: [PATCH 01/76] perf(web): optimize first-screen rendering performance (#35313) --- web/app/(commonLayout)/layout.tsx | 6 +++++- web/app/components/devtools/react-scan/loader.tsx | 2 +- web/app/components/splash.tsx | 8 +++----- 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/web/app/(commonLayout)/layout.tsx b/web/app/(commonLayout)/layout.tsx index 5ac39f1e39..49e9431940 100644 --- a/web/app/(commonLayout)/layout.tsx +++ b/web/app/(commonLayout)/layout.tsx @@ -5,7 +5,6 @@ import InSiteMessageNotification from '@/app/components/app/in-site-message/noti import AmplitudeProvider from '@/app/components/base/amplitude' import GA, { GaType } from '@/app/components/base/ga' import Zendesk from '@/app/components/base/zendesk' -import GotoAnything from '@/app/components/goto-anything' import Header from '@/app/components/header' import HeaderWrapper from '@/app/components/header/header-wrapper' import ReadmePanel from '@/app/components/plugins/readme-panel' @@ -13,10 +12,15 @@ import { AppContextProvider } from '@/context/app-context-provider' import { EventEmitterContextProvider } from '@/context/event-emitter-provider' import { ModalContextProvider } from '@/context/modal-context-provider' import { ProviderContextProvider } from '@/context/provider-context-provider' +import dynamic from '@/next/dynamic' import PartnerStack from '../components/billing/partner-stack' import Splash from '../components/splash' import RoleRouteGuard from './role-route-guard' +const GotoAnything = dynamic(() => import('@/app/components/goto-anything'), { + ssr: false, +}) + const Layout = ({ children }: { children: ReactNode }) => { return ( <> diff --git a/web/app/components/devtools/react-scan/loader.tsx b/web/app/components/devtools/react-scan/loader.tsx index 8e933c2b24..bd310f292f 100644 --- a/web/app/components/devtools/react-scan/loader.tsx +++ b/web/app/components/devtools/react-scan/loader.tsx @@ -9,7 +9,7 @@ export function ReactScanLoader() { .txt' }) render(, { wrapper: createWrapper() }) - expect(screen.getByText('.txt')).toBeInTheDocument() + expect(screen.getByText('.txt'))!.toBeInTheDocument() }) it('should memoize the component', () => { @@ -343,7 +344,7 @@ describe('DocumentTableRow', () => { const { rerender } = render(, { wrapper }) rerender() - expect(screen.getByRole('row')).toBeInTheDocument() + expect(screen.getByRole('row'))!.toBeInTheDocument() }) }) }) diff --git a/web/app/components/datasets/documents/components/document-list/components/document-source-icon.tsx b/web/app/components/datasets/documents/components/document-list/components/document-source-icon.tsx index 5461f34921..0d51837cf2 100644 --- a/web/app/components/datasets/documents/components/document-list/components/document-source-icon.tsx +++ b/web/app/components/datasets/documents/components/document-list/components/document-source-icon.tsx @@ -39,7 +39,7 @@ const getFileExtension = (fileName: string): string => { const parts = fileName.split('.') if (parts.length <= 1 || (parts[0] === '' && parts.length === 2)) return '' - return parts[parts.length - 1].toLowerCase() + return parts[parts.length - 1]!.toLowerCase() } const DocumentSourceIcon: FC = React.memo(({ diff --git a/web/app/components/datasets/documents/create-from-pipeline/__tests__/index.spec.tsx b/web/app/components/datasets/documents/create-from-pipeline/__tests__/index.spec.tsx index 8a2e251770..7daff43a8b 100644 --- a/web/app/components/datasets/documents/create-from-pipeline/__tests__/index.spec.tsx +++ b/web/app/components/datasets/documents/create-from-pipeline/__tests__/index.spec.tsx @@ -569,7 +569,7 @@ describe('StepOneContent', () => { it('should render VectorSpaceFull when isShowVectorSpaceFull is true', () => { render() - expect(screen.getByTestId('vector-space-full')).toBeInTheDocument() + expect(screen.getByTestId('vector-space-full'))!.toBeInTheDocument() }) it('should not render VectorSpaceFull when isShowVectorSpaceFull is false', () => { @@ -587,7 +587,7 @@ describe('StepOneContent', () => { localFileListLength={2} />, ) - expect(screen.getByTestId('upgrade-card')).toBeInTheDocument() + expect(screen.getByTestId('upgrade-card'))!.toBeInTheDocument() }) it('should not render UpgradeCard when supportBatchUpload is true', () => { @@ -618,7 +618,7 @@ describe('StepOneContent', () => { render() const nextButton = screen.getByRole('button', { name: /datasetCreation.stepOne.button/i }) - expect(nextButton).toBeDisabled() + expect(nextButton)!.toBeDisabled() }) }) @@ -664,17 +664,17 @@ describe('StepTwoContent', () => { it('should render ProcessDocuments component', () => { render() - expect(screen.getByTestId('process-documents')).toBeInTheDocument() + expect(screen.getByTestId('process-documents'))!.toBeInTheDocument() }) it('should pass dataSourceNodeId to ProcessDocuments', () => { render() - expect(screen.getByTestId('datasource-node-id')).toHaveTextContent('custom-node') + expect(screen.getByTestId('datasource-node-id'))!.toHaveTextContent('custom-node') }) it('should pass isRunning to ProcessDocuments', () => { render() - expect(screen.getByTestId('is-running')).toHaveTextContent('true') + expect(screen.getByTestId('is-running'))!.toHaveTextContent('true') }) it('should call onProcess when process button is clicked', () => { @@ -709,18 +709,18 @@ describe('StepThreeContent', () => { it('should render Processing component', () => { render() - expect(screen.getByTestId('processing')).toBeInTheDocument() + expect(screen.getByTestId('processing'))!.toBeInTheDocument() }) it('should pass batchId to Processing', () => { render() - expect(screen.getByTestId('batch-id')).toHaveTextContent('batch-123') + expect(screen.getByTestId('batch-id'))!.toHaveTextContent('batch-123') }) it('should pass documents count to Processing', () => { const documents = [{ id: '1' }, { id: '2' }] render() - expect(screen.getByTestId('documents-count')).toHaveTextContent('2') + expect(screen.getByTestId('documents-count'))!.toHaveTextContent('2') }) }) @@ -787,8 +787,8 @@ describe('StepOnePreview', () => { currentLocalFile={createMockFile()} />, ) - expect(screen.getByTestId('file-preview')).toBeInTheDocument() - expect(screen.getByTestId('file-name')).toHaveTextContent('test.txt') + expect(screen.getByTestId('file-preview'))!.toBeInTheDocument() + expect(screen.getByTestId('file-name'))!.toHaveTextContent('test.txt') }) it('should render OnlineDocumentPreview when currentDocument is set', () => { @@ -799,7 +799,7 @@ describe('StepOnePreview', () => { currentDocument={createMockNotionPage()} />, ) - expect(screen.getByTestId('online-document-preview')).toBeInTheDocument() + expect(screen.getByTestId('online-document-preview'))!.toBeInTheDocument() }) it('should render WebsitePreview when currentWebsite is set', () => { @@ -809,7 +809,7 @@ describe('StepOnePreview', () => { currentWebsite={createMockCrawlResult()} />, ) - expect(screen.getByTestId('web-preview')).toBeInTheDocument() + expect(screen.getByTestId('web-preview'))!.toBeInTheDocument() }) it('should call hidePreviewLocalFile when hide button is clicked', () => { @@ -868,22 +868,22 @@ describe('StepTwoPreview', () => { it('should render ChunkPreview component', () => { render() - expect(screen.getByTestId('chunk-preview')).toBeInTheDocument() + expect(screen.getByTestId('chunk-preview'))!.toBeInTheDocument() }) it('should pass datasourceType to ChunkPreview', () => { render() - expect(screen.getByTestId('datasource-type')).toHaveTextContent(DatasourceType.onlineDocument) + expect(screen.getByTestId('datasource-type'))!.toHaveTextContent(DatasourceType.onlineDocument) }) it('should pass isIdle to ChunkPreview', () => { render() - expect(screen.getByTestId('is-idle')).toHaveTextContent('false') + expect(screen.getByTestId('is-idle'))!.toHaveTextContent('false') }) it('should pass isPendingPreview to ChunkPreview', () => { render() - expect(screen.getByTestId('is-pending')).toHaveTextContent('true') + expect(screen.getByTestId('is-pending'))!.toHaveTextContent('true') }) it('should call onPreview when preview button is clicked', () => { @@ -1092,7 +1092,7 @@ describe('Store Hooks', () => { mockStoreState.selectedFileIds = ['file-1'] const { result } = renderHook(() => useOnlineDrive()) expect(result.current.selectedOnlineDriveFileList).toHaveLength(1) - expect(result.current.selectedOnlineDriveFileList[0].id).toBe('file-1') + expect(result.current.selectedOnlineDriveFileList[0]!.id).toBe('file-1') }) }) }) @@ -1166,8 +1166,8 @@ describe('useDatasourceOptions', () => { const { result } = renderHook(() => useDatasourceOptions(mockNodes)) expect(result.current).toHaveLength(1) - expect(result.current[0].label).toBe('Local File Source') - expect(result.current[0].value).toBe('node-1') + expect(result.current[0]!.label).toBe('Local File Source') + expect(result.current[0]!.value).toBe('node-1') }) it('should return multiple options for multiple data source nodes', () => { @@ -1616,7 +1616,7 @@ describe('StepOneContent - All Datasource Types', () => { datasourceType={DatasourceType.onlineDocument} />, ) - expect(screen.getByTestId('online-documents-component')).toBeInTheDocument() + expect(screen.getByTestId('online-documents-component'))!.toBeInTheDocument() }) it('should render WebsiteCrawl when datasourceType is websiteCrawl', () => { @@ -1632,7 +1632,7 @@ describe('StepOneContent - All Datasource Types', () => { datasourceType={DatasourceType.websiteCrawl} />, ) - expect(screen.getByTestId('website-crawl-component')).toBeInTheDocument() + expect(screen.getByTestId('website-crawl-component'))!.toBeInTheDocument() }) it('should render OnlineDrive when datasourceType is onlineDrive', () => { @@ -1648,7 +1648,7 @@ describe('StepOneContent - All Datasource Types', () => { datasourceType={DatasourceType.onlineDrive} />, ) - expect(screen.getByTestId('online-drive-component')).toBeInTheDocument() + expect(screen.getByTestId('online-drive-component'))!.toBeInTheDocument() }) it('should render LocalFile when datasourceType is localFile', () => { @@ -1659,7 +1659,7 @@ describe('StepOneContent - All Datasource Types', () => { datasourceType={DatasourceType.localFile} />, ) - expect(screen.getByTestId('local-file-component')).toBeInTheDocument() + expect(screen.getByTestId('local-file-component'))!.toBeInTheDocument() }) }) @@ -1690,7 +1690,8 @@ describe('StepTwoPreview - File List Mapping', () => { ) // ChunkPreview should be rendered - expect(screen.getByTestId('chunk-preview')).toBeInTheDocument() + // ChunkPreview should be rendered + expect(screen.getByTestId('chunk-preview'))!.toBeInTheDocument() }) }) diff --git a/web/app/components/datasets/documents/create-from-pipeline/__tests__/step-indicator.spec.tsx b/web/app/components/datasets/documents/create-from-pipeline/__tests__/step-indicator.spec.tsx index 7103dced26..7bffe3577e 100644 --- a/web/app/components/datasets/documents/create-from-pipeline/__tests__/step-indicator.spec.tsx +++ b/web/app/components/datasets/documents/create-from-pipeline/__tests__/step-indicator.spec.tsx @@ -19,14 +19,14 @@ describe('StepIndicator', () => { const { container } = render() const dots = container.querySelectorAll('.rounded-lg') // Second step (index 1) should be active - expect(dots[1].className).toContain('bg-state-accent-solid') - expect(dots[1].className).toContain('w-2') + expect(dots[1]!.className).toContain('bg-state-accent-solid') + expect(dots[1]!.className).toContain('w-2') }) it('should not apply active style to non-current steps', () => { const { container } = render() const dots = container.querySelectorAll('.rounded-lg') - expect(dots[1].className).toContain('bg-divider-solid') - expect(dots[2].className).toContain('bg-divider-solid') + expect(dots[1]!.className).toContain('bg-divider-solid') + expect(dots[2]!.className).toContain('bg-divider-solid') }) }) diff --git a/web/app/components/datasets/documents/create-from-pipeline/data-source-options/__tests__/index.spec.tsx b/web/app/components/datasets/documents/create-from-pipeline/data-source-options/__tests__/index.spec.tsx index 0ac2dfce20..78542ad522 100644 --- a/web/app/components/datasets/documents/create-from-pipeline/data-source-options/__tests__/index.spec.tsx +++ b/web/app/components/datasets/documents/create-from-pipeline/data-source-options/__tests__/index.spec.tsx @@ -129,7 +129,7 @@ describe('DatasourceIcon', () => { it('should render without crashing', () => { const { container } = render() - expect(container.firstChild).toBeInTheDocument() + expect(container.firstChild)!.toBeInTheDocument() }) it('should render icon with background image', () => { @@ -138,15 +138,16 @@ describe('DatasourceIcon', () => { const { container } = render() const iconDiv = container.querySelector('[style*="background-image"]') - expect(iconDiv).toHaveStyle({ backgroundImage: `url(${iconUrl})` }) + expect(iconDiv)!.toHaveStyle({ backgroundImage: `url(${iconUrl})` }) }) it('should render with default size (sm)', () => { const { container } = render() // Assert - Default size is 'sm' which maps to 'w-5 h-5' - expect(container.firstChild).toHaveClass('w-5') - expect(container.firstChild).toHaveClass('h-5') + // Assert - Default size is 'sm' which maps to 'w-5 h-5' + expect(container.firstChild)!.toHaveClass('w-5') + expect(container.firstChild)!.toHaveClass('h-5') }) }) @@ -157,9 +158,9 @@ describe('DatasourceIcon', () => { , ) - expect(container.firstChild).toHaveClass('w-4') - expect(container.firstChild).toHaveClass('h-4') - expect(container.firstChild).toHaveClass('rounded-[5px]') + expect(container.firstChild)!.toHaveClass('w-4') + expect(container.firstChild)!.toHaveClass('h-4') + expect(container.firstChild)!.toHaveClass('rounded-[5px]') }) it('should render with sm size', () => { @@ -167,9 +168,9 @@ describe('DatasourceIcon', () => { , ) - expect(container.firstChild).toHaveClass('w-5') - expect(container.firstChild).toHaveClass('h-5') - expect(container.firstChild).toHaveClass('rounded-md') + expect(container.firstChild)!.toHaveClass('w-5') + expect(container.firstChild)!.toHaveClass('h-5') + expect(container.firstChild)!.toHaveClass('rounded-md') }) it('should render with md size', () => { @@ -177,9 +178,9 @@ describe('DatasourceIcon', () => { , ) - expect(container.firstChild).toHaveClass('w-6') - expect(container.firstChild).toHaveClass('h-6') - expect(container.firstChild).toHaveClass('rounded-lg') + expect(container.firstChild)!.toHaveClass('w-6') + expect(container.firstChild)!.toHaveClass('h-6') + expect(container.firstChild)!.toHaveClass('rounded-lg') }) }) @@ -189,7 +190,7 @@ describe('DatasourceIcon', () => { , ) - expect(container.firstChild).toHaveClass('custom-class') + expect(container.firstChild)!.toHaveClass('custom-class') }) it('should merge custom className with default classes', () => { @@ -197,9 +198,9 @@ describe('DatasourceIcon', () => { , ) - expect(container.firstChild).toHaveClass('custom-class') - expect(container.firstChild).toHaveClass('w-5') - expect(container.firstChild).toHaveClass('h-5') + expect(container.firstChild)!.toHaveClass('custom-class') + expect(container.firstChild)!.toHaveClass('w-5') + expect(container.firstChild)!.toHaveClass('h-5') }) }) @@ -208,7 +209,7 @@ describe('DatasourceIcon', () => { const { container } = render() const iconDiv = container.querySelector('[style*="background-image"]') - expect(iconDiv).toHaveStyle({ backgroundImage: 'url()' }) + expect(iconDiv)!.toHaveStyle({ backgroundImage: 'url()' }) }) it('should handle special characters in iconUrl', () => { @@ -217,7 +218,7 @@ describe('DatasourceIcon', () => { const { container } = render() const iconDiv = container.querySelector('[style*="background-image"]') - expect(iconDiv).toHaveStyle({ backgroundImage: `url(${iconUrl})` }) + expect(iconDiv)!.toHaveStyle({ backgroundImage: `url(${iconUrl})` }) }) it('should handle data URL as iconUrl', () => { @@ -226,7 +227,7 @@ describe('DatasourceIcon', () => { const { container } = render() const iconDiv = container.querySelector('[style*="background-image"]') - expect(iconDiv).toBeInTheDocument() + expect(iconDiv)!.toBeInTheDocument() }) }) }) @@ -235,25 +236,26 @@ describe('DatasourceIcon', () => { it('should have flex container classes', () => { const { container } = render() - expect(container.firstChild).toHaveClass('flex') - expect(container.firstChild).toHaveClass('items-center') - expect(container.firstChild).toHaveClass('justify-center') + expect(container.firstChild)!.toHaveClass('flex') + expect(container.firstChild)!.toHaveClass('items-center') + expect(container.firstChild)!.toHaveClass('justify-center') }) it('should have shadow-xs class from size map', () => { const { container } = render() // Assert - Default size 'sm' has shadow-xs - expect(container.firstChild).toHaveClass('shadow-xs') + // Assert - Default size 'sm' has shadow-xs + expect(container.firstChild)!.toHaveClass('shadow-xs') }) it('should have inner div with bg-cover class', () => { const { container } = render() const innerDiv = container.querySelector('.bg-cover') - expect(innerDiv).toBeInTheDocument() - expect(innerDiv).toHaveClass('bg-center') - expect(innerDiv).toHaveClass('rounded-md') + expect(innerDiv)!.toBeInTheDocument() + expect(innerDiv)!.toHaveClass('bg-center') + expect(innerDiv)!.toHaveClass('rounded-md') }) }) }) @@ -519,13 +521,13 @@ describe('OptionCard', () => { it('should render without crashing', () => { renderWithProviders() - expect(screen.getByText('Test Option')).toBeInTheDocument() + expect(screen.getByText('Test Option'))!.toBeInTheDocument() }) it('should render label text', () => { renderWithProviders() - expect(screen.getByText('Custom Label')).toBeInTheDocument() + expect(screen.getByText('Custom Label'))!.toBeInTheDocument() }) it('should render DatasourceIcon component', () => { @@ -533,7 +535,7 @@ describe('OptionCard', () => { // Assert - DatasourceIcon container should exist const iconContainer = container.querySelector('.size-8') - expect(iconContainer).toBeInTheDocument() + expect(iconContainer)!.toBeInTheDocument() }) it('should set title attribute for label truncation', () => { @@ -542,7 +544,7 @@ describe('OptionCard', () => { renderWithProviders() const labelElement = screen.getByText(longLabel) - expect(labelElement).toHaveAttribute('title', longLabel) + expect(labelElement)!.toHaveAttribute('title', longLabel) }) }) @@ -554,8 +556,8 @@ describe('OptionCard', () => { ) const card = container.firstChild - expect(card).toHaveClass('border-components-option-card-option-selected-border') - expect(card).toHaveClass('bg-components-option-card-option-selected-bg') + expect(card)!.toHaveClass('border-components-option-card-option-selected-border') + expect(card)!.toHaveClass('bg-components-option-card-option-selected-bg') }) it('should apply unselected styles when selected is false', () => { @@ -564,22 +566,22 @@ describe('OptionCard', () => { ) const card = container.firstChild - expect(card).toHaveClass('border-components-option-card-option-border') - expect(card).toHaveClass('bg-components-option-card-option-bg') + expect(card)!.toHaveClass('border-components-option-card-option-border') + expect(card)!.toHaveClass('bg-components-option-card-option-bg') }) it('should apply text-text-primary to label when selected', () => { renderWithProviders() const label = screen.getByText('Test Option') - expect(label).toHaveClass('text-text-primary') + expect(label)!.toHaveClass('text-text-primary') }) it('should apply text-text-secondary to label when not selected', () => { renderWithProviders() const label = screen.getByText('Test Option') - expect(label).toHaveClass('text-text-secondary') + expect(label)!.toHaveClass('text-text-secondary') }) }) @@ -593,7 +595,7 @@ describe('OptionCard', () => { // Act - Click on the label text's parent card const labelElement = screen.getByText('Test Option') const card = labelElement.closest('[class*="cursor-pointer"]') - expect(card).toBeInTheDocument() + expect(card)!.toBeInTheDocument() fireEvent.click(card!) expect(mockOnClick).toHaveBeenCalledTimes(1) @@ -607,11 +609,12 @@ describe('OptionCard', () => { // Act - Click on the label text's parent card should not throw const labelElement = screen.getByText('Test Option') const card = labelElement.closest('[class*="cursor-pointer"]') - expect(card).toBeInTheDocument() + expect(card)!.toBeInTheDocument() fireEvent.click(card!) // Assert - Component should still be rendered - expect(screen.getByText('Test Option')).toBeInTheDocument() + // Assert - Component should still be rendered + expect(screen.getByText('Test Option'))!.toBeInTheDocument() }) }) @@ -631,35 +634,35 @@ describe('OptionCard', () => { it('should have cursor-pointer class', () => { const { container } = renderWithProviders() - expect(container.firstChild).toHaveClass('cursor-pointer') + expect(container.firstChild)!.toHaveClass('cursor-pointer') }) it('should have flex layout classes', () => { const { container } = renderWithProviders() - expect(container.firstChild).toHaveClass('flex') - expect(container.firstChild).toHaveClass('items-center') - expect(container.firstChild).toHaveClass('gap-2') + expect(container.firstChild)!.toHaveClass('flex') + expect(container.firstChild)!.toHaveClass('items-center') + expect(container.firstChild)!.toHaveClass('gap-2') }) it('should have rounded-xl border', () => { const { container } = renderWithProviders() - expect(container.firstChild).toHaveClass('rounded-xl') - expect(container.firstChild).toHaveClass('border') + expect(container.firstChild)!.toHaveClass('rounded-xl') + expect(container.firstChild)!.toHaveClass('border') }) it('should have padding p-3', () => { const { container } = renderWithProviders() - expect(container.firstChild).toHaveClass('p-3') + expect(container.firstChild)!.toHaveClass('p-3') }) it('should have line-clamp-2 for label truncation', () => { renderWithProviders() const label = screen.getByText('Test Option') - expect(label).toHaveClass('line-clamp-2') + expect(label)!.toHaveClass('line-clamp-2') }) }) @@ -669,7 +672,7 @@ describe('OptionCard', () => { expect(OptionCard).toBeDefined() // React.memo wraps the component, so we check it renders correctly const { container } = renderWithProviders() - expect(container.firstChild).toBeInTheDocument() + expect(container.firstChild)!.toBeInTheDocument() }) }) }) @@ -698,27 +701,27 @@ describe('DataSourceOptions', () => { it('should render without crashing', () => { renderWithProviders() - expect(screen.getByText('Data Source 1')).toBeInTheDocument() - expect(screen.getByText('Data Source 2')).toBeInTheDocument() - expect(screen.getByText('Data Source 3')).toBeInTheDocument() + expect(screen.getByText('Data Source 1'))!.toBeInTheDocument() + expect(screen.getByText('Data Source 2'))!.toBeInTheDocument() + expect(screen.getByText('Data Source 3'))!.toBeInTheDocument() }) it('should render correct number of option cards', () => { renderWithProviders() - expect(screen.getByText('Data Source 1')).toBeInTheDocument() - expect(screen.getByText('Data Source 2')).toBeInTheDocument() - expect(screen.getByText('Data Source 3')).toBeInTheDocument() + expect(screen.getByText('Data Source 1'))!.toBeInTheDocument() + expect(screen.getByText('Data Source 2'))!.toBeInTheDocument() + expect(screen.getByText('Data Source 3'))!.toBeInTheDocument() }) it('should render with grid layout', () => { const { container } = renderWithProviders() const gridContainer = container.firstChild - expect(gridContainer).toHaveClass('grid') - expect(gridContainer).toHaveClass('w-full') - expect(gridContainer).toHaveClass('grid-cols-4') - expect(gridContainer).toHaveClass('gap-1') + expect(gridContainer)!.toHaveClass('grid') + expect(gridContainer)!.toHaveClass('w-full') + expect(gridContainer)!.toHaveClass('grid-cols-4') + expect(gridContainer)!.toHaveClass('gap-1') }) it('should render no option cards when options is empty', () => { @@ -728,16 +731,17 @@ describe('DataSourceOptions', () => { expect(screen.queryByText('Data Source')).not.toBeInTheDocument() // Grid container should still exist - expect(container.firstChild).toHaveClass('grid') + // Grid container should still exist + expect(container.firstChild)!.toHaveClass('grid') }) it('should render single option card when only one option exists', () => { - const singleOption = [createMockDatasourceOption(defaultNodes[0])] + const singleOption = [createMockDatasourceOption(defaultNodes[0]!)] mockUseDatasourceOptions.mockReturnValue(singleOption) renderWithProviders() - expect(screen.getByText('Data Source 1')).toBeInTheDocument() + expect(screen.getByText('Data Source 1'))!.toBeInTheDocument() expect(screen.queryByText('Data Source 2')).not.toBeInTheDocument() }) }) @@ -778,7 +782,7 @@ describe('DataSourceOptions', () => { // Assert - Check for selected styling on second card const cards = container.querySelectorAll('.rounded-xl.border') - expect(cards[1]).toHaveClass('border-components-option-card-option-selected-border') + expect(cards[1])!.toHaveClass('border-components-option-card-option-selected-border') }) it('should show no selection when datasourceNodeId is empty', () => { @@ -816,7 +820,7 @@ describe('DataSourceOptions', () => { // Assert initial selection let cards = container.querySelectorAll('.rounded-xl.border') - expect(cards[0]).toHaveClass('border-components-option-card-option-selected-border') + expect(cards[0])!.toHaveClass('border-components-option-card-option-selected-border') // Act - Change selection rerender( @@ -831,7 +835,7 @@ describe('DataSourceOptions', () => { // Assert new selection cards = container.querySelectorAll('.rounded-xl.border') expect(cards[0]).not.toHaveClass('border-components-option-card-option-selected-border') - expect(cards[1]).toHaveClass('border-components-option-card-option-selected-border') + expect(cards[1])!.toHaveClass('border-components-option-card-option-selected-border') }) }) @@ -847,7 +851,8 @@ describe('DataSourceOptions', () => { ) // Assert - Component renders without error - expect(screen.getByText('Data Source 1')).toBeInTheDocument() + // Assert - Component renders without error + expect(screen.getByText('Data Source 1'))!.toBeInTheDocument() }) }) }) @@ -870,7 +875,7 @@ describe('DataSourceOptions', () => { expect(mockOnSelect).toHaveBeenCalledTimes(1) expect(mockOnSelect).toHaveBeenCalledWith({ nodeId: 'node-1', - nodeData: defaultOptions[0].data, + nodeData: defaultOptions[0]!.data, } satisfies Datasource) }) @@ -948,7 +953,8 @@ describe('DataSourceOptions', () => { ) // Get initial click handlers - expect(screen.getByText('Data Source 1')).toBeInTheDocument() + // Get initial click handlers + expect(screen.getByText('Data Source 1'))!.toBeInTheDocument() // Trigger clicks to test handlers work fireEvent.click(screen.getByText('Data Source 1')) @@ -1003,7 +1009,7 @@ describe('DataSourceOptions', () => { expect(mockOnSelect2).toHaveBeenCalledTimes(1) expect(mockOnSelect2).toHaveBeenCalledWith({ nodeId: 'node-3', - nodeData: defaultOptions[2].data, + nodeData: defaultOptions[2]!.data, }) }) @@ -1022,7 +1028,7 @@ describe('DataSourceOptions', () => { fireEvent.click(screen.getByText('Data Source 1')) expect(mockOnSelect).toHaveBeenCalledWith({ nodeId: 'node-1', - nodeData: defaultOptions[0].data, + nodeData: defaultOptions[0]!.data, }) // Act - Change options @@ -1045,8 +1051,8 @@ describe('DataSourceOptions', () => { // Assert - Callback receives new option data expect(mockOnSelect).toHaveBeenLastCalledWith({ - nodeId: newOptions[0].value, - nodeData: newOptions[0].data, + nodeId: newOptions[0]!.value, + nodeData: newOptions[0]!.data, }) }) }) @@ -1070,7 +1076,7 @@ describe('DataSourceOptions', () => { expect(mockOnSelect).toHaveBeenCalledTimes(1) expect(mockOnSelect).toHaveBeenCalledWith({ nodeId: 'node-2', - nodeData: defaultOptions[1].data, + nodeData: defaultOptions[1]!.data, } satisfies Datasource) }) @@ -1090,7 +1096,7 @@ describe('DataSourceOptions', () => { expect(mockOnSelect).toHaveBeenCalledTimes(1) expect(mockOnSelect).toHaveBeenCalledWith({ nodeId: 'node-1', - nodeData: defaultOptions[0].data, + nodeData: defaultOptions[0]!.data, }) }) @@ -1112,15 +1118,15 @@ describe('DataSourceOptions', () => { expect(mockOnSelect).toHaveBeenCalledTimes(3) expect(mockOnSelect).toHaveBeenNthCalledWith(1, { nodeId: 'node-1', - nodeData: defaultOptions[0].data, + nodeData: defaultOptions[0]!.data, }) expect(mockOnSelect).toHaveBeenNthCalledWith(2, { nodeId: 'node-2', - nodeData: defaultOptions[1].data, + nodeData: defaultOptions[1]!.data, }) expect(mockOnSelect).toHaveBeenNthCalledWith(3, { nodeId: 'node-3', - nodeData: defaultOptions[2].data, + nodeData: defaultOptions[2]!.data, }) }) }) @@ -1164,7 +1170,7 @@ describe('DataSourceOptions', () => { />, ) - expect(container.firstChild).toBeInTheDocument() + expect(container.firstChild)!.toBeInTheDocument() }) it('should not crash when datasourceNodeId is undefined', () => { @@ -1176,7 +1182,7 @@ describe('DataSourceOptions', () => { />, ) - expect(screen.getByText('Data Source 1')).toBeInTheDocument() + expect(screen.getByText('Data Source 1'))!.toBeInTheDocument() }) }) @@ -1202,7 +1208,7 @@ describe('DataSourceOptions', () => { renderWithProviders() - expect(screen.getByText('Minimal Option')).toBeInTheDocument() + expect(screen.getByText('Minimal Option'))!.toBeInTheDocument() }) }) @@ -1219,8 +1225,8 @@ describe('DataSourceOptions', () => { />, ) - expect(screen.getByText('Data Source 1')).toBeInTheDocument() - expect(screen.getByText('Data Source 50')).toBeInTheDocument() + expect(screen.getByText('Data Source 1'))!.toBeInTheDocument() + expect(screen.getByText('Data Source 50'))!.toBeInTheDocument() }) }) @@ -1243,7 +1249,8 @@ describe('DataSourceOptions', () => { ) // Assert - Special characters should be escaped/rendered safely - expect(screen.getByText('Data Source ')).toBeInTheDocument() + // Assert - Special characters should be escaped/rendered safely + expect(screen.getByText('Data Source '))!.toBeInTheDocument() }) it('should handle unicode characters in option labels', () => { @@ -1263,7 +1270,7 @@ describe('DataSourceOptions', () => { />, ) - expect(screen.getByText('数据源 📁 Source émoji')).toBeInTheDocument() + expect(screen.getByText('数据源 📁 Source émoji'))!.toBeInTheDocument() }) it('should handle empty string as option value', () => { @@ -1276,13 +1283,13 @@ describe('DataSourceOptions', () => { renderWithProviders() - expect(screen.getByText('Empty Value Option')).toBeInTheDocument() + expect(screen.getByText('Empty Value Option'))!.toBeInTheDocument() }) }) describe('Boundary Conditions', () => { it('should handle single option selection correctly', () => { - const singleOption = [createMockDatasourceOption(defaultNodes[0])] + const singleOption = [createMockDatasourceOption(defaultNodes[0]!)] mockUseDatasourceOptions.mockReturnValue(singleOption) const mockOnSelect = vi.fn() @@ -1327,7 +1334,7 @@ describe('DataSourceOptions', () => { const labels = screen.getAllByText('Duplicate Label') expect(labels).toHaveLength(2) - fireEvent.click(labels[1]) + fireEvent.click(labels[1]!) expect(mockOnSelect).toHaveBeenCalledWith({ nodeId: 'node-b', nodeData: expect.objectContaining({ plugin_id: 'plugin-b' }), @@ -1347,6 +1354,37 @@ describe('DataSourceOptions', () => { unmount() + // Assert - No errors thrown, component cleanly unmounted + // Assert - No errors thrown, component cleanly unmounted + // Assert - No errors thrown, component cleanly unmounted + // Assert - No errors thrown, component cleanly unmounted + // Assert - No errors thrown, component cleanly unmounted + // Assert - No errors thrown, component cleanly unmounted + // Assert - No errors thrown, component cleanly unmounted + // Assert - No errors thrown, component cleanly unmounted + // Assert - No errors thrown, component cleanly unmounted + // Assert - No errors thrown, component cleanly unmounted + // Assert - No errors thrown, component cleanly unmounted + // Assert - No errors thrown, component cleanly unmounted + // Assert - No errors thrown, component cleanly unmounted + // Assert - No errors thrown, component cleanly unmounted + // Assert - No errors thrown, component cleanly unmounted + // Assert - No errors thrown, component cleanly unmounted + // Assert - No errors thrown, component cleanly unmounted + // Assert - No errors thrown, component cleanly unmounted + // Assert - No errors thrown, component cleanly unmounted + // Assert - No errors thrown, component cleanly unmounted + // Assert - No errors thrown, component cleanly unmounted + // Assert - No errors thrown, component cleanly unmounted + // Assert - No errors thrown, component cleanly unmounted + // Assert - No errors thrown, component cleanly unmounted + // Assert - No errors thrown, component cleanly unmounted + // Assert - No errors thrown, component cleanly unmounted + // Assert - No errors thrown, component cleanly unmounted + // Assert - No errors thrown, component cleanly unmounted + // Assert - No errors thrown, component cleanly unmounted + // Assert - No errors thrown, component cleanly unmounted + // Assert - No errors thrown, component cleanly unmounted // Assert - No errors thrown, component cleanly unmounted expect(screen.queryByText('Data Source 1')).not.toBeInTheDocument() }) @@ -1367,6 +1405,37 @@ describe('DataSourceOptions', () => { // Unmount during/after interaction unmount() + // Assert - Should not throw + // Assert - Should not throw + // Assert - Should not throw + // Assert - Should not throw + // Assert - Should not throw + // Assert - Should not throw + // Assert - Should not throw + // Assert - Should not throw + // Assert - Should not throw + // Assert - Should not throw + // Assert - Should not throw + // Assert - Should not throw + // Assert - Should not throw + // Assert - Should not throw + // Assert - Should not throw + // Assert - Should not throw + // Assert - Should not throw + // Assert - Should not throw + // Assert - Should not throw + // Assert - Should not throw + // Assert - Should not throw + // Assert - Should not throw + // Assert - Should not throw + // Assert - Should not throw + // Assert - Should not throw + // Assert - Should not throw + // Assert - Should not throw + // Assert - Should not throw + // Assert - Should not throw + // Assert - Should not throw + // Assert - Should not throw // Assert - Should not throw expect(screen.queryByText('Data Source 1')).not.toBeInTheDocument() }) @@ -1392,7 +1461,7 @@ describe('DataSourceOptions', () => { const cards = container.querySelectorAll('.rounded-xl.border') expect(cards[0]).not.toHaveClass('border-components-option-card-option-selected-border') - expect(cards[1]).toHaveClass('border-components-option-card-option-selected-border') + expect(cards[1])!.toHaveClass('border-components-option-card-option-selected-border') expect(cards[2]).not.toHaveClass('border-components-option-card-option-selected-border') }) @@ -1427,7 +1496,7 @@ describe('DataSourceOptions', () => { />, ) - expect(screen.getByText('Data Source 1')).toBeInTheDocument() + expect(screen.getByText('Data Source 1'))!.toBeInTheDocument() }) it.each([ @@ -1449,7 +1518,7 @@ describe('DataSourceOptions', () => { ) if (count > 0) - expect(screen.getByText('Data Source 1')).toBeInTheDocument() + expect(screen.getByText('Data Source 1'))!.toBeInTheDocument() else expect(screen.queryByText('Data Source 1')).not.toBeInTheDocument() }) diff --git a/web/app/components/datasets/documents/create-from-pipeline/data-source-options/index.tsx b/web/app/components/datasets/documents/create-from-pipeline/data-source-options/index.tsx index 8e3a29cfe5..51cf34d273 100644 --- a/web/app/components/datasets/documents/create-from-pipeline/data-source-options/index.tsx +++ b/web/app/components/datasets/documents/create-from-pipeline/data-source-options/index.tsx @@ -31,7 +31,7 @@ const DataSourceOptions = ({ useEffect(() => { if (options.length > 0 && !datasourceNodeId) - handelSelect(options[0].value) + handelSelect(options[0]!.value) }, []) return ( diff --git a/web/app/components/datasets/documents/create-from-pipeline/data-source/base/credential-selector/__tests__/index.spec.tsx b/web/app/components/datasets/documents/create-from-pipeline/data-source/base/credential-selector/__tests__/index.spec.tsx index d595a50fe1..49b0cb0789 100644 --- a/web/app/components/datasets/documents/create-from-pipeline/data-source/base/credential-selector/__tests__/index.spec.tsx +++ b/web/app/components/datasets/documents/create-from-pipeline/data-source/base/credential-selector/__tests__/index.spec.tsx @@ -97,8 +97,8 @@ describe('CredentialSelector', () => { render() - expect(screen.getByTestId('portal-root')).toBeInTheDocument() - expect(screen.getByTestId('portal-trigger')).toBeInTheDocument() + expect(screen.getByTestId('portal-root'))!.toBeInTheDocument() + expect(screen.getByTestId('portal-trigger'))!.toBeInTheDocument() }) it('should render current credential name in trigger', () => { @@ -106,7 +106,7 @@ describe('CredentialSelector', () => { render() - expect(screen.getByText('Credential 1')).toBeInTheDocument() + expect(screen.getByText('Credential 1'))!.toBeInTheDocument() }) it('should render credential icon with correct props', () => { @@ -116,8 +116,8 @@ describe('CredentialSelector', () => { // Assert - CredentialIcon renders an img when avatarUrl is provided const iconImg = container.querySelector('img') - expect(iconImg).toBeInTheDocument() - expect(iconImg).toHaveAttribute('src', 'https://example.com/avatar-1.png') + expect(iconImg)!.toBeInTheDocument() + expect(iconImg)!.toHaveAttribute('src', 'https://example.com/avatar-1.png') }) it('should render dropdown arrow icon', () => { @@ -126,7 +126,7 @@ describe('CredentialSelector', () => { const { container } = render() const svgIcon = container.querySelector('svg') - expect(svgIcon).toBeInTheDocument() + expect(svgIcon)!.toBeInTheDocument() }) it('should not render dropdown content initially', () => { @@ -146,7 +146,8 @@ describe('CredentialSelector', () => { fireEvent.click(trigger) // Assert - All credentials should be visible (current credential appears in both trigger and list) - expect(screen.getByTestId('portal-content')).toBeInTheDocument() + // Assert - All credentials should be visible (current credential appears in both trigger and list) + expect(screen.getByTestId('portal-content'))!.toBeInTheDocument() // 3 in dropdown list + 1 in trigger (current) = 4 total expect(screen.getAllByText(/Credential \d/)).toHaveLength(4) }) @@ -160,7 +161,7 @@ describe('CredentialSelector', () => { render() - expect(screen.getByText('Credential 1')).toBeInTheDocument() + expect(screen.getByText('Credential 1'))!.toBeInTheDocument() }) it('should display second credential when currentCredentialId matches second', () => { @@ -168,7 +169,7 @@ describe('CredentialSelector', () => { render() - expect(screen.getByText('Credential 2')).toBeInTheDocument() + expect(screen.getByText('Credential 2'))!.toBeInTheDocument() }) it('should display third credential when currentCredentialId matches third', () => { @@ -176,7 +177,7 @@ describe('CredentialSelector', () => { render() - expect(screen.getByText('Credential 3')).toBeInTheDocument() + expect(screen.getByText('Credential 3'))!.toBeInTheDocument() }) it.each([ @@ -188,7 +189,7 @@ describe('CredentialSelector', () => { render() - expect(screen.getByText(expectedName)).toBeInTheDocument() + expect(screen.getByText(expectedName))!.toBeInTheDocument() }) }) @@ -201,7 +202,7 @@ describe('CredentialSelector', () => { render() - expect(screen.getByText('Test Credential')).toBeInTheDocument() + expect(screen.getByText('Test Credential'))!.toBeInTheDocument() }) it('should render multiple credentials in dropdown', () => { @@ -226,7 +227,7 @@ describe('CredentialSelector', () => { render() - expect(screen.getByText('Test & Credential ')).toBeInTheDocument() + expect(screen.getByText('Test & Credential '))!.toBeInTheDocument() }) }) @@ -293,6 +294,37 @@ describe('CredentialSelector', () => { const props = createDefaultProps() render() + // Assert - Initially closed + // Assert - Initially closed + // Assert - Initially closed + // Assert - Initially closed + // Assert - Initially closed + // Assert - Initially closed + // Assert - Initially closed + // Assert - Initially closed + // Assert - Initially closed + // Assert - Initially closed + // Assert - Initially closed + // Assert - Initially closed + // Assert - Initially closed + // Assert - Initially closed + // Assert - Initially closed + // Assert - Initially closed + // Assert - Initially closed + // Assert - Initially closed + // Assert - Initially closed + // Assert - Initially closed + // Assert - Initially closed + // Assert - Initially closed + // Assert - Initially closed + // Assert - Initially closed + // Assert - Initially closed + // Assert - Initially closed + // Assert - Initially closed + // Assert - Initially closed + // Assert - Initially closed + // Assert - Initially closed + // Assert - Initially closed // Assert - Initially closed expect(screen.queryByTestId('portal-content')).not.toBeInTheDocument() @@ -301,7 +333,8 @@ describe('CredentialSelector', () => { fireEvent.click(trigger) // Assert - Now open - expect(screen.getByTestId('portal-content')).toBeInTheDocument() + // Assert - Now open + expect(screen.getByTestId('portal-content'))!.toBeInTheDocument() }) it('should call onCredentialChange when clicking a credential item', () => { @@ -327,7 +360,7 @@ describe('CredentialSelector', () => { const trigger = screen.getByTestId('portal-trigger') fireEvent.click(trigger) - expect(screen.getByTestId('portal-content')).toBeInTheDocument() + expect(screen.getByTestId('portal-content'))!.toBeInTheDocument() const credential2 = screen.getByText('Credential 2') fireEvent.click(credential2) @@ -347,7 +380,8 @@ describe('CredentialSelector', () => { fireEvent.click(trigger) // Assert - Should not crash - expect(trigger).toBeInTheDocument() + // Assert - Should not crash + expect(trigger)!.toBeInTheDocument() }) it('should allow selecting credentials multiple times', () => { @@ -504,7 +538,8 @@ describe('CredentialSelector', () => { render() // Assert - Should display credential 2 - expect(screen.getByText('Credential 2')).toBeInTheDocument() + // Assert - Should display credential 2 + expect(screen.getByText('Credential 2'))!.toBeInTheDocument() }) it('should update currentCredential when currentCredentialId changes', () => { @@ -512,13 +547,15 @@ describe('CredentialSelector', () => { const { rerender } = render() // Assert initial - expect(screen.getByText('Credential 1')).toBeInTheDocument() + // Assert initial + expect(screen.getByText('Credential 1'))!.toBeInTheDocument() // Act - Change currentCredentialId rerender() // Assert - Should now display credential 3 - expect(screen.getByText('Credential 3')).toBeInTheDocument() + // Assert - Should now display credential 3 + expect(screen.getByText('Credential 3'))!.toBeInTheDocument() }) it('should update currentCredential when credentials array changes', () => { @@ -526,7 +563,8 @@ describe('CredentialSelector', () => { const { rerender } = render() // Assert initial - expect(screen.getByText('Credential 1')).toBeInTheDocument() + // Assert initial + expect(screen.getByText('Credential 1'))!.toBeInTheDocument() // Act - Change credentials const newCredentials = [ @@ -535,7 +573,8 @@ describe('CredentialSelector', () => { rerender() // Assert - Should display updated name - expect(screen.getByText('Updated Credential 1')).toBeInTheDocument() + // Assert - Should display updated name + expect(screen.getByText('Updated Credential 1'))!.toBeInTheDocument() }) it('should return undefined currentCredential when id not found', () => { @@ -581,11 +620,12 @@ describe('CredentialSelector', () => { const { rerender } = render() // Assert initial - expect(screen.getByText('Credential 1')).toBeInTheDocument() + // Assert initial + expect(screen.getByText('Credential 1'))!.toBeInTheDocument() rerender() - expect(screen.getByText('Credential 2')).toBeInTheDocument() + expect(screen.getByText('Credential 2'))!.toBeInTheDocument() }) it('should re-render when credentials array reference changes', () => { @@ -598,7 +638,7 @@ describe('CredentialSelector', () => { ] rerender() - expect(screen.getByText('New Name 1')).toBeInTheDocument() + expect(screen.getByText('New Name 1'))!.toBeInTheDocument() }) it('should re-render when onCredentialChange reference changes', () => { @@ -631,7 +671,8 @@ describe('CredentialSelector', () => { render() // Assert - Should render without crashing - expect(screen.getByTestId('portal-root')).toBeInTheDocument() + // Assert - Should render without crashing + expect(screen.getByTestId('portal-root'))!.toBeInTheDocument() }) it('should handle undefined avatar_url in credential', () => { @@ -648,12 +689,14 @@ describe('CredentialSelector', () => { const { container } = render() // Assert - Should render without crashing and show first letter fallback - expect(screen.getByText('No Avatar Credential')).toBeInTheDocument() + // Assert - Should render without crashing and show first letter fallback + expect(screen.getByText('No Avatar Credential'))!.toBeInTheDocument() // When avatar_url is undefined, CredentialIcon shows first letter instead of img const iconImg = container.querySelector('img') expect(iconImg).not.toBeInTheDocument() // First letter 'N' should be displayed - expect(screen.getByText('N')).toBeInTheDocument() + // First letter 'N' should be displayed + expect(screen.getByText('N'))!.toBeInTheDocument() }) it('should handle empty string name in credential', () => { @@ -669,7 +712,8 @@ describe('CredentialSelector', () => { render() // Assert - Should render without crashing - expect(screen.getByTestId('portal-trigger')).toBeInTheDocument() + // Assert - Should render without crashing + expect(screen.getByTestId('portal-trigger'))!.toBeInTheDocument() }) it('should handle very long credential name', () => { @@ -685,7 +729,7 @@ describe('CredentialSelector', () => { render() - expect(screen.getByText(longName)).toBeInTheDocument() + expect(screen.getByText(longName))!.toBeInTheDocument() }) it('should handle special characters in credential name', () => { @@ -701,7 +745,7 @@ describe('CredentialSelector', () => { render() - expect(screen.getByText(specialName)).toBeInTheDocument() + expect(screen.getByText(specialName))!.toBeInTheDocument() }) it('should handle numeric id as string', () => { @@ -716,7 +760,7 @@ describe('CredentialSelector', () => { render() - expect(screen.getByText('Numeric ID Credential')).toBeInTheDocument() + expect(screen.getByText('Numeric ID Credential'))!.toBeInTheDocument() }) it('should handle large number of credentials', () => { @@ -728,7 +772,7 @@ describe('CredentialSelector', () => { render() - expect(screen.getByText('Credential 50')).toBeInTheDocument() + expect(screen.getByText('Credential 50'))!.toBeInTheDocument() }) it('should handle credential selection with duplicate names', () => { @@ -752,7 +796,7 @@ describe('CredentialSelector', () => { const sameNameElements = screen.getAllByText('Same Name') expect(sameNameElements.length).toBe(3) - fireEvent.click(sameNameElements[2]) + fireEvent.click(sameNameElements[2]!) // Assert - Should call with the correct id even with duplicate names expect(mockOnChange).toHaveBeenCalledWith('cred-2') @@ -787,7 +831,8 @@ describe('CredentialSelector', () => { render() // Assert - Should render without crashing - expect(screen.getByTestId('portal-trigger')).toBeInTheDocument() + // Assert - Should render without crashing + expect(screen.getByTestId('portal-trigger'))!.toBeInTheDocument() }) }) @@ -799,7 +844,7 @@ describe('CredentialSelector', () => { render() const trigger = screen.getByTestId('portal-trigger') - expect(trigger).toHaveClass('overflow-hidden') + expect(trigger)!.toHaveClass('overflow-hidden') }) it('should apply grow class to trigger', () => { @@ -808,7 +853,7 @@ describe('CredentialSelector', () => { render() const trigger = screen.getByTestId('portal-trigger') - expect(trigger).toHaveClass('grow') + expect(trigger)!.toHaveClass('grow') }) it('should apply z-10 class to dropdown content', () => { @@ -819,7 +864,7 @@ describe('CredentialSelector', () => { fireEvent.click(trigger) const content = screen.getByTestId('portal-content') - expect(content).toHaveClass('z-10') + expect(content)!.toHaveClass('z-10') }) }) @@ -831,7 +876,8 @@ describe('CredentialSelector', () => { render() // Assert - Trigger should display the correct credential - expect(screen.getByText('Credential 2')).toBeInTheDocument() + // Assert - Trigger should display the correct credential + expect(screen.getByText('Credential 2'))!.toBeInTheDocument() }) it('should pass isOpen state to Trigger component', () => { @@ -840,14 +886,15 @@ describe('CredentialSelector', () => { // Assert - Initially closed const portalRoot = screen.getByTestId('portal-root') - expect(portalRoot).toHaveAttribute('data-open', 'false') + expect(portalRoot)!.toHaveAttribute('data-open', 'false') // Act - Open const trigger = screen.getByTestId('portal-trigger') fireEvent.click(trigger) // Assert - Now open - expect(portalRoot).toHaveAttribute('data-open', 'true') + // Assert - Now open + expect(portalRoot)!.toHaveAttribute('data-open', 'true') }) it('should pass credentials to List component', () => { @@ -899,7 +946,7 @@ describe('CredentialSelector', () => { const props = createDefaultProps() render() - expect(screen.getByTestId('portal-root')).toBeInTheDocument() + expect(screen.getByTestId('portal-root'))!.toBeInTheDocument() }) it('should configure PortalToFollowElem with offset mainAxis 4', () => { @@ -907,7 +954,7 @@ describe('CredentialSelector', () => { const props = createDefaultProps() render() - expect(screen.getByTestId('portal-root')).toBeInTheDocument() + expect(screen.getByTestId('portal-root'))!.toBeInTheDocument() }) }) }) diff --git a/web/app/components/datasets/documents/create-from-pipeline/data-source/base/credential-selector/index.tsx b/web/app/components/datasets/documents/create-from-pipeline/data-source/base/credential-selector/index.tsx index 2f14b0f3b8..116b762277 100644 --- a/web/app/components/datasets/documents/create-from-pipeline/data-source/base/credential-selector/index.tsx +++ b/web/app/components/datasets/documents/create-from-pipeline/data-source/base/credential-selector/index.tsx @@ -29,7 +29,7 @@ const CredentialSelector = ({ useEffect(() => { if (!currentCredential && credentials.length) - onCredentialChange(credentials[0].id) + onCredentialChange(credentials[0]!.id) }, [currentCredential, credentials]) const handleCredentialChange = useCallback((credentialId: string) => { diff --git a/web/app/components/datasets/documents/create-from-pipeline/data-source/local-file/hooks/__tests__/use-local-file-upload.spec.tsx b/web/app/components/datasets/documents/create-from-pipeline/data-source/local-file/hooks/__tests__/use-local-file-upload.spec.tsx index cc531aad8f..80a8fc854d 100644 --- a/web/app/components/datasets/documents/create-from-pipeline/data-source/local-file/hooks/__tests__/use-local-file-upload.spec.tsx +++ b/web/app/components/datasets/documents/create-from-pipeline/data-source/local-file/hooks/__tests__/use-local-file-upload.spec.tsx @@ -404,7 +404,7 @@ describe('useLocalFileUpload', () => { // Should only process first 5 files (batch_count_limit) const firstCall = mockSetLocalFileList.mock.calls[0] - expect(firstCall[0].length).toBeLessThanOrEqual(5) + expect(firstCall![0].length).toBeLessThanOrEqual(5) }) }) @@ -591,7 +591,8 @@ describe('useLocalFileUpload', () => { }) // dragover should not throw - expect(dropzone).toBeInTheDocument() + // dragover should not throw + expect(dropzone)!.toBeInTheDocument() }) it('should set dragging false on dragleave from drag overlay', async () => { @@ -715,7 +716,7 @@ describe('useLocalFileUpload', () => { await waitFor(() => { expect(mockSetLocalFileList).toHaveBeenCalled() // Should only have 1 file (limited by supportBatchUpload: false) - const callArgs = mockSetLocalFileList.mock.calls[0][0] + const callArgs = mockSetLocalFileList.mock.calls[0]![0] expect(callArgs.length).toBe(1) }) }) @@ -873,7 +874,7 @@ describe('useLocalFileUpload', () => { }) await waitFor(() => { - const callArgs = mockSetLocalFileList.mock.calls[0][0] + const callArgs = mockSetLocalFileList.mock.calls[0]![0] expect(callArgs[0].progress).toBe(PROGRESS_NOT_STARTED) }) }) @@ -899,7 +900,7 @@ describe('useLocalFileUpload', () => { await waitFor(() => { const calls = mockSetLocalFileList.mock.calls - const lastCall = calls[calls.length - 1][0] + const lastCall = calls[calls.length - 1]![0] expect(lastCall.some((f: FileItem) => f.progress === PROGRESS_ERROR)).toBe(true) }) }) diff --git a/web/app/components/datasets/documents/create-from-pipeline/data-source/online-documents/index.tsx b/web/app/components/datasets/documents/create-from-pipeline/data-source/online-documents/index.tsx index 5051d343cb..5321986cd7 100644 --- a/web/app/components/datasets/documents/create-from-pipeline/data-source/online-documents/index.tsx +++ b/web/app/components/datasets/documents/create-from-pipeline/data-source/online-documents/index.tsx @@ -115,7 +115,7 @@ const OnlineDocuments = ({ const handleSelectPages = useCallback((newSelectedPagesId: Set) => { const { setSelectedPagesId, setOnlineDocuments } = dataSourceStore.getState() - const selectedPages = Array.from(newSelectedPagesId).map(pageId => PagesMapAndSelectedPagesId[pageId]) + const selectedPages = Array.from(newSelectedPagesId).map(pageId => PagesMapAndSelectedPagesId[pageId]!) setSelectedPagesId(new Set(Array.from(newSelectedPagesId))) setOnlineDocuments(selectedPages) }, [dataSourceStore, PagesMapAndSelectedPagesId]) @@ -160,7 +160,7 @@ const OnlineDocuments = ({ checkedIds={selectedPagesId} disabledValue={new Set()} searchValue={searchValue} - list={documentsData[0].pages || []} + list={documentsData[0]!.pages || []} pagesMap={PagesMapAndSelectedPagesId} onSelect={handleSelectPages} canPreview={!isInPipeline} diff --git a/web/app/components/datasets/documents/create-from-pipeline/data-source/online-documents/page-selector/__tests__/index.spec.tsx b/web/app/components/datasets/documents/create-from-pipeline/data-source/online-documents/page-selector/__tests__/index.spec.tsx index a6d5738e2d..04676156e6 100644 --- a/web/app/components/datasets/documents/create-from-pipeline/data-source/online-documents/page-selector/__tests__/index.spec.tsx +++ b/web/app/components/datasets/documents/create-from-pipeline/data-source/online-documents/page-selector/__tests__/index.spec.tsx @@ -83,7 +83,7 @@ describe('PageSelector', () => { render() - expect(screen.getByTestId('virtual-list')).toBeInTheDocument() + expect(screen.getByTestId('virtual-list'))!.toBeInTheDocument() }) it('should render empty state when list is empty', () => { @@ -94,7 +94,7 @@ describe('PageSelector', () => { render() - expect(screen.getByText('common.dataSource.notion.selector.noSearchResult')).toBeInTheDocument() + expect(screen.getByText('common.dataSource.notion.selector.noSearchResult'))!.toBeInTheDocument() expect(screen.queryByTestId('virtual-list')).not.toBeInTheDocument() }) @@ -110,8 +110,8 @@ describe('PageSelector', () => { render() - expect(screen.getByText('Page 1')).toBeInTheDocument() - expect(screen.getByText('Page 2')).toBeInTheDocument() + expect(screen.getByText('Page 1'))!.toBeInTheDocument() + expect(screen.getByText('Page 2'))!.toBeInTheDocument() }) it('should render checkboxes when isMultipleChoice is true', () => { @@ -119,7 +119,7 @@ describe('PageSelector', () => { render() - expect(getCheckbox()).toBeInTheDocument() + expect(getCheckbox())!.toBeInTheDocument() }) it('should render radio buttons when isMultipleChoice is false', () => { @@ -127,7 +127,7 @@ describe('PageSelector', () => { render() - expect(getRadio()).toBeInTheDocument() + expect(getRadio())!.toBeInTheDocument() }) it('should render preview button when canPreview is true', () => { @@ -135,7 +135,7 @@ describe('PageSelector', () => { render() - expect(screen.getByText('common.dataSource.notion.selector.preview')).toBeInTheDocument() + expect(screen.getByText('common.dataSource.notion.selector.preview'))!.toBeInTheDocument() }) it('should not render preview button when canPreview is false', () => { @@ -153,7 +153,7 @@ describe('PageSelector', () => { // Assert - NotionIcon renders svg when page_icon is null const notionIcon = document.querySelector('.h-5.w-5') - expect(notionIcon).toBeInTheDocument() + expect(notionIcon)!.toBeInTheDocument() }) it('should render page name', () => { @@ -164,7 +164,7 @@ describe('PageSelector', () => { render() - expect(screen.getByText('My Custom Page')).toBeInTheDocument() + expect(screen.getByText('My Custom Page'))!.toBeInTheDocument() }) }) @@ -181,7 +181,7 @@ describe('PageSelector', () => { render() const checkbox = getCheckbox() - expect(checkbox).toBeInTheDocument() + expect(checkbox)!.toBeInTheDocument() expect(isCheckboxChecked(checkbox)).toBe(true) }) @@ -196,7 +196,7 @@ describe('PageSelector', () => { render() const checkbox = getCheckbox() - expect(checkbox).toBeInTheDocument() + expect(checkbox)!.toBeInTheDocument() expect(isCheckboxChecked(checkbox)).toBe(false) }) @@ -206,7 +206,7 @@ describe('PageSelector', () => { render() const checkbox = getCheckbox() - expect(checkbox).toBeInTheDocument() + expect(checkbox)!.toBeInTheDocument() expect(isCheckboxChecked(checkbox)).toBe(false) }) @@ -225,9 +225,9 @@ describe('PageSelector', () => { render() const checkboxes = getAllCheckboxes() - expect(isCheckboxChecked(checkboxes[0])).toBe(true) - expect(isCheckboxChecked(checkboxes[1])).toBe(false) - expect(isCheckboxChecked(checkboxes[2])).toBe(true) + expect(isCheckboxChecked(checkboxes[0]!)).toBe(true) + expect(isCheckboxChecked(checkboxes[1]!)).toBe(false) + expect(isCheckboxChecked(checkboxes[2]!)).toBe(true) }) }) @@ -243,7 +243,7 @@ describe('PageSelector', () => { render() const checkbox = getCheckbox() - expect(checkbox).toBeInTheDocument() + expect(checkbox)!.toBeInTheDocument() expect(isCheckboxDisabled(checkbox)).toBe(true) }) @@ -258,7 +258,7 @@ describe('PageSelector', () => { render() const checkbox = getCheckbox() - expect(checkbox).toBeInTheDocument() + expect(checkbox)!.toBeInTheDocument() expect(isCheckboxDisabled(checkbox)).toBe(false) }) @@ -276,8 +276,8 @@ describe('PageSelector', () => { render() const checkboxes = getAllCheckboxes() - expect(isCheckboxDisabled(checkboxes[0])).toBe(true) - expect(isCheckboxDisabled(checkboxes[1])).toBe(false) + expect(isCheckboxDisabled(checkboxes[0]!)).toBe(true) + expect(isCheckboxDisabled(checkboxes[1]!)).toBe(false) }) }) @@ -301,6 +301,37 @@ describe('PageSelector', () => { expect(screen.getAllByText('Apple Page').length).toBeGreaterThan(0) expect(screen.getAllByText('Apple Pie').length).toBeGreaterThan(0) // Banana Page is filtered out because it doesn't contain "Apple" + // Banana Page is filtered out because it doesn't contain "Apple" + // Banana Page is filtered out because it doesn't contain "Apple" + // Banana Page is filtered out because it doesn't contain "Apple" + // Banana Page is filtered out because it doesn't contain "Apple" + // Banana Page is filtered out because it doesn't contain "Apple" + // Banana Page is filtered out because it doesn't contain "Apple" + // Banana Page is filtered out because it doesn't contain "Apple" + // Banana Page is filtered out because it doesn't contain "Apple" + // Banana Page is filtered out because it doesn't contain "Apple" + // Banana Page is filtered out because it doesn't contain "Apple" + // Banana Page is filtered out because it doesn't contain "Apple" + // Banana Page is filtered out because it doesn't contain "Apple" + // Banana Page is filtered out because it doesn't contain "Apple" + // Banana Page is filtered out because it doesn't contain "Apple" + // Banana Page is filtered out because it doesn't contain "Apple" + // Banana Page is filtered out because it doesn't contain "Apple" + // Banana Page is filtered out because it doesn't contain "Apple" + // Banana Page is filtered out because it doesn't contain "Apple" + // Banana Page is filtered out because it doesn't contain "Apple" + // Banana Page is filtered out because it doesn't contain "Apple" + // Banana Page is filtered out because it doesn't contain "Apple" + // Banana Page is filtered out because it doesn't contain "Apple" + // Banana Page is filtered out because it doesn't contain "Apple" + // Banana Page is filtered out because it doesn't contain "Apple" + // Banana Page is filtered out because it doesn't contain "Apple" + // Banana Page is filtered out because it doesn't contain "Apple" + // Banana Page is filtered out because it doesn't contain "Apple" + // Banana Page is filtered out because it doesn't contain "Apple" + // Banana Page is filtered out because it doesn't contain "Apple" + // Banana Page is filtered out because it doesn't contain "Apple" + // Banana Page is filtered out because it doesn't contain "Apple" expect(screen.queryByText('Banana Page')).not.toBeInTheDocument() }) @@ -314,7 +345,7 @@ describe('PageSelector', () => { render() - expect(screen.getByText('common.dataSource.notion.selector.noSearchResult')).toBeInTheDocument() + expect(screen.getByText('common.dataSource.notion.selector.noSearchResult'))!.toBeInTheDocument() }) it('should show all pages when searchValue is empty', () => { @@ -330,8 +361,8 @@ describe('PageSelector', () => { render() - expect(screen.getByText('Page 1')).toBeInTheDocument() - expect(screen.getByText('Page 2')).toBeInTheDocument() + expect(screen.getByText('Page 1'))!.toBeInTheDocument() + expect(screen.getByText('Page 2'))!.toBeInTheDocument() }) it('should show breadcrumbs when searchValue is present', () => { @@ -345,7 +376,8 @@ describe('PageSelector', () => { render() // Assert - page name should be visible - expect(screen.getByText('Grandchild 1')).toBeInTheDocument() + // Assert - page name should be visible + expect(screen.getByText('Grandchild 1'))!.toBeInTheDocument() }) it('should perform case-sensitive search', () => { @@ -374,7 +406,7 @@ describe('PageSelector', () => { render() - expect(screen.getByText('common.dataSource.notion.selector.preview')).toBeInTheDocument() + expect(screen.getByText('common.dataSource.notion.selector.preview'))!.toBeInTheDocument() }) it('should hide preview button when canPreview is false', () => { @@ -391,7 +423,7 @@ describe('PageSelector', () => { render() - expect(screen.getByText('common.dataSource.notion.selector.preview')).toBeInTheDocument() + expect(screen.getByText('common.dataSource.notion.selector.preview'))!.toBeInTheDocument() }) }) @@ -401,7 +433,7 @@ describe('PageSelector', () => { render() - expect(getCheckbox()).toBeInTheDocument() + expect(getCheckbox())!.toBeInTheDocument() expect(getRadio()).not.toBeInTheDocument() }) @@ -410,7 +442,7 @@ describe('PageSelector', () => { render() - expect(getRadio()).toBeInTheDocument() + expect(getRadio())!.toBeInTheDocument() expect(getCheckbox()).not.toBeInTheDocument() }) @@ -420,7 +452,7 @@ describe('PageSelector', () => { render() - expect(getCheckbox()).toBeInTheDocument() + expect(getCheckbox())!.toBeInTheDocument() }) }) @@ -449,7 +481,7 @@ describe('PageSelector', () => { render() fireEvent.click(getCheckbox()) - const calledSet = mockOnSelect.mock.calls[0][0] as Set + const calledSet = mockOnSelect.mock.calls[0]![0] as Set expect(calledSet.has('page-1')).toBe(true) }) }) @@ -498,13 +530,15 @@ describe('PageSelector', () => { const { rerender } = render() // Assert - Initial render - expect(screen.getByText('Page 1')).toBeInTheDocument() + // Assert - Initial render + expect(screen.getByText('Page 1'))!.toBeInTheDocument() // Rerender with new credential rerender() // Assert - Should still show pages (reset and rebuild) - expect(screen.getByText('Page 1')).toBeInTheDocument() + // Assert - Should still show pages (reset and rebuild) + expect(screen.getByText('Page 1'))!.toBeInTheDocument() }) }) }) @@ -521,7 +555,39 @@ describe('PageSelector', () => { render() // Assert - Only root level page should be visible initially - expect(screen.getByText(rootPage.page_name)).toBeInTheDocument() + // Assert - Only root level page should be visible initially + expect(screen.getByText(rootPage.page_name))!.toBeInTheDocument() + // Child pages should not be visible until expanded + // Child pages should not be visible until expanded + // Child pages should not be visible until expanded + // Child pages should not be visible until expanded + // Child pages should not be visible until expanded + // Child pages should not be visible until expanded + // Child pages should not be visible until expanded + // Child pages should not be visible until expanded + // Child pages should not be visible until expanded + // Child pages should not be visible until expanded + // Child pages should not be visible until expanded + // Child pages should not be visible until expanded + // Child pages should not be visible until expanded + // Child pages should not be visible until expanded + // Child pages should not be visible until expanded + // Child pages should not be visible until expanded + // Child pages should not be visible until expanded + // Child pages should not be visible until expanded + // Child pages should not be visible until expanded + // Child pages should not be visible until expanded + // Child pages should not be visible until expanded + // Child pages should not be visible until expanded + // Child pages should not be visible until expanded + // Child pages should not be visible until expanded + // Child pages should not be visible until expanded + // Child pages should not be visible until expanded + // Child pages should not be visible until expanded + // Child pages should not be visible until expanded + // Child pages should not be visible until expanded + // Child pages should not be visible until expanded + // Child pages should not be visible until expanded // Child pages should not be visible until expanded expect(screen.queryByText(childPage1.page_name)).not.toBeInTheDocument() }) @@ -540,9 +606,9 @@ describe('PageSelector', () => { if (arrowButton) fireEvent.click(arrowButton) - expect(screen.getByText(rootPage.page_name)).toBeInTheDocument() - expect(screen.getByText(childPage1.page_name)).toBeInTheDocument() - expect(screen.getByText(childPage2.page_name)).toBeInTheDocument() + expect(screen.getByText(rootPage.page_name))!.toBeInTheDocument() + expect(screen.getByText(childPage1.page_name))!.toBeInTheDocument() + expect(screen.getByText(childPage2.page_name))!.toBeInTheDocument() }) it('should maintain currentPreviewPageId state', () => { @@ -560,7 +626,7 @@ describe('PageSelector', () => { render() const previewButtons = screen.getAllByText('common.dataSource.notion.selector.preview') - fireEvent.click(previewButtons[0]) + fireEvent.click(previewButtons[0]!) expect(mockOnPreview).toHaveBeenCalledWith('page-1') }) @@ -596,13 +662,14 @@ describe('PageSelector', () => { }) const { rerender } = render() - expect(screen.getByText('Page 1')).toBeInTheDocument() + expect(screen.getByText('Page 1'))!.toBeInTheDocument() // Change credential rerender() // Assert - Component should still render correctly - expect(screen.getByText('Page 1')).toBeInTheDocument() + // Assert - Component should still render correctly + expect(screen.getByText('Page 1'))!.toBeInTheDocument() }) it('should filter root pages correctly on initialization', () => { @@ -615,7 +682,8 @@ describe('PageSelector', () => { render() // Assert - Only root level pages visible - expect(screen.getByText(rootPage.page_name)).toBeInTheDocument() + // Assert - Only root level pages visible + expect(screen.getByText(rootPage.page_name))!.toBeInTheDocument() expect(screen.queryByText(childPage1.page_name)).not.toBeInTheDocument() }) @@ -633,7 +701,8 @@ describe('PageSelector', () => { render() // Assert - Orphan page should be visible at root level - expect(screen.getByText('Orphan Page')).toBeInTheDocument() + // Assert - Orphan page should be visible at root level + expect(screen.getByText('Orphan Page'))!.toBeInTheDocument() }) }) @@ -654,8 +723,9 @@ describe('PageSelector', () => { fireEvent.click(expandArrow) // Assert - Children should be visible - expect(screen.getByText(childPage1.page_name)).toBeInTheDocument() - expect(screen.getByText(childPage2.page_name)).toBeInTheDocument() + // Assert - Children should be visible + expect(screen.getByText(childPage1.page_name))!.toBeInTheDocument() + expect(screen.getByText(childPage2.page_name))!.toBeInTheDocument() }) it('should have stable handleToggle that collapses descendants', () => { @@ -675,6 +745,37 @@ describe('PageSelector', () => { fireEvent.click(expandArrow) } + // Assert - Children should be hidden again + // Assert - Children should be hidden again + // Assert - Children should be hidden again + // Assert - Children should be hidden again + // Assert - Children should be hidden again + // Assert - Children should be hidden again + // Assert - Children should be hidden again + // Assert - Children should be hidden again + // Assert - Children should be hidden again + // Assert - Children should be hidden again + // Assert - Children should be hidden again + // Assert - Children should be hidden again + // Assert - Children should be hidden again + // Assert - Children should be hidden again + // Assert - Children should be hidden again + // Assert - Children should be hidden again + // Assert - Children should be hidden again + // Assert - Children should be hidden again + // Assert - Children should be hidden again + // Assert - Children should be hidden again + // Assert - Children should be hidden again + // Assert - Children should be hidden again + // Assert - Children should be hidden again + // Assert - Children should be hidden again + // Assert - Children should be hidden again + // Assert - Children should be hidden again + // Assert - Children should be hidden again + // Assert - Children should be hidden again + // Assert - Children should be hidden again + // Assert - Children should be hidden again + // Assert - Children should be hidden again // Assert - Children should be hidden again expect(screen.queryByText(childPage1.page_name)).not.toBeInTheDocument() expect(screen.queryByText(childPage2.page_name)).not.toBeInTheDocument() @@ -698,7 +799,7 @@ describe('PageSelector', () => { // Assert - onSelect should be called with the page and its descendants expect(mockOnSelect).toHaveBeenCalled() - const selectedSet = mockOnSelect.mock.calls[0][0] as Set + const selectedSet = mockOnSelect.mock.calls[0]![0] as Set expect(selectedSet.has('root-page')).toBe(true) }) @@ -752,7 +853,7 @@ describe('PageSelector', () => { // Assert - Tree structure should be built (verified by expand functionality) const expandArrow = document.querySelector('[class*="hover:bg-components-button-ghost-bg-hover"]') - expect(expandArrow).toBeInTheDocument() // Root page has children + expect(expandArrow)!.toBeInTheDocument() // Root page has children }) it('should recompute listMapWithChildrenAndDescendants when list changes', () => { @@ -763,7 +864,7 @@ describe('PageSelector', () => { }) const { rerender } = render() - expect(screen.getByText('Page 1')).toBeInTheDocument() + expect(screen.getByText('Page 1'))!.toBeInTheDocument() // Update with new list const newList = [ @@ -772,7 +873,7 @@ describe('PageSelector', () => { ] rerender() - expect(screen.getByText('Page 1')).toBeInTheDocument() + expect(screen.getByText('Page 1'))!.toBeInTheDocument() // Page 2 won't show because dataList state hasn't updated (only resets on credentialId change) }) @@ -793,7 +894,8 @@ describe('PageSelector', () => { rerender() // Assert - Should not throw - expect(screen.getByText('Page 1')).toBeInTheDocument() + // Assert - Should not throw + expect(screen.getByText('Page 1'))!.toBeInTheDocument() }) it('should handle empty list in memoization', () => { @@ -804,7 +906,7 @@ describe('PageSelector', () => { render() - expect(screen.getByText('common.dataSource.notion.selector.noSearchResult')).toBeInTheDocument() + expect(screen.getByText('common.dataSource.notion.selector.noSearchResult'))!.toBeInTheDocument() }) }) @@ -819,6 +921,37 @@ describe('PageSelector', () => { render() + // Initially children are hidden + // Initially children are hidden + // Initially children are hidden + // Initially children are hidden + // Initially children are hidden + // Initially children are hidden + // Initially children are hidden + // Initially children are hidden + // Initially children are hidden + // Initially children are hidden + // Initially children are hidden + // Initially children are hidden + // Initially children are hidden + // Initially children are hidden + // Initially children are hidden + // Initially children are hidden + // Initially children are hidden + // Initially children are hidden + // Initially children are hidden + // Initially children are hidden + // Initially children are hidden + // Initially children are hidden + // Initially children are hidden + // Initially children are hidden + // Initially children are hidden + // Initially children are hidden + // Initially children are hidden + // Initially children are hidden + // Initially children are hidden + // Initially children are hidden + // Initially children are hidden // Initially children are hidden expect(screen.queryByText(childPage1.page_name)).not.toBeInTheDocument() @@ -827,7 +960,8 @@ describe('PageSelector', () => { fireEvent.click(expandArrow) // Children become visible - expect(screen.getByText(childPage1.page_name)).toBeInTheDocument() + // Children become visible + expect(screen.getByText(childPage1.page_name))!.toBeInTheDocument() }) it('should check/uncheck page when clicking checkbox', () => { @@ -873,11 +1007,11 @@ describe('PageSelector', () => { render() const radios = getAllRadios() - fireEvent.click(radios[1]) // Click on page-2 + fireEvent.click(radios[1]!) // Click on page-2 // Assert - Should clear page-1 and select page-2 expect(mockOnSelect).toHaveBeenCalled() - const selectedSet = mockOnSelect.mock.calls[0][0] as Set + const selectedSet = mockOnSelect.mock.calls[0]![0] as Set expect(selectedSet.has('page-2')).toBe(true) expect(selectedSet.has('page-1')).toBe(false) }) @@ -912,7 +1046,7 @@ describe('PageSelector', () => { // Assert - Only the clicked page should be selected (no descendants) expect(mockOnSelect).toHaveBeenCalled() - const selectedSet = mockOnSelect.mock.calls[0][0] as Set + const selectedSet = mockOnSelect.mock.calls[0]![0] as Set expect(selectedSet.size).toBe(1) expect(selectedSet.has('root-page')).toBe(true) }) @@ -927,7 +1061,7 @@ describe('PageSelector', () => { render() - expect(screen.getByText('common.dataSource.notion.selector.noSearchResult')).toBeInTheDocument() + expect(screen.getByText('common.dataSource.notion.selector.noSearchResult'))!.toBeInTheDocument() }) it('should handle null page_icon', () => { @@ -941,7 +1075,7 @@ describe('PageSelector', () => { // Assert - NotionIcon renders svg (RiFileTextLine) when page_icon is null const notionIcon = document.querySelector('.h-5.w-5') - expect(notionIcon).toBeInTheDocument() + expect(notionIcon)!.toBeInTheDocument() }) it('should handle page_icon with all properties', () => { @@ -956,7 +1090,8 @@ describe('PageSelector', () => { render() // Assert - NotionIcon renders the emoji - expect(screen.getByText('📄')).toBeInTheDocument() + // Assert - NotionIcon renders the emoji + expect(screen.getByText('📄'))!.toBeInTheDocument() }) it('should handle empty searchValue correctly', () => { @@ -964,7 +1099,7 @@ describe('PageSelector', () => { render() - expect(screen.getByTestId('virtual-list')).toBeInTheDocument() + expect(screen.getByTestId('virtual-list'))!.toBeInTheDocument() }) it('should handle special characters in page name', () => { @@ -976,7 +1111,7 @@ describe('PageSelector', () => { render() - expect(screen.getByText('Test ')).toBeInTheDocument() + expect(screen.getByText('Test '))!.toBeInTheDocument() }) it('should handle unicode characters in page name', () => { @@ -988,7 +1123,7 @@ describe('PageSelector', () => { render() - expect(screen.getByText('测试页面 🔍 привет')).toBeInTheDocument() + expect(screen.getByText('测试页面 🔍 привет'))!.toBeInTheDocument() }) it('should handle very long page names', () => { @@ -1001,7 +1136,7 @@ describe('PageSelector', () => { render() - expect(screen.getByText(longName)).toBeInTheDocument() + expect(screen.getByText(longName))!.toBeInTheDocument() }) it('should handle deeply nested hierarchy', () => { @@ -1027,7 +1162,8 @@ describe('PageSelector', () => { render() // Assert - Only root level visible - expect(screen.getByText('Level 0')).toBeInTheDocument() + // Assert - Only root level visible + expect(screen.getByText('Level 0'))!.toBeInTheDocument() expect(screen.queryByText('Level 1')).not.toBeInTheDocument() }) @@ -1048,7 +1184,8 @@ describe('PageSelector', () => { render() // Assert - Should render the orphan page at root level - expect(screen.getByText('Orphan Page')).toBeInTheDocument() + // Assert - Should render the orphan page at root level + expect(screen.getByText('Orphan Page'))!.toBeInTheDocument() }) it('should handle empty checkedIds Set', () => { @@ -1057,7 +1194,7 @@ describe('PageSelector', () => { render() const checkbox = getCheckbox() - expect(checkbox).toBeInTheDocument() + expect(checkbox)!.toBeInTheDocument() expect(isCheckboxChecked(checkbox)).toBe(false) }) @@ -1067,7 +1204,7 @@ describe('PageSelector', () => { render() const checkbox = getCheckbox() - expect(checkbox).toBeInTheDocument() + expect(checkbox)!.toBeInTheDocument() expect(isCheckboxDisabled(checkbox)).toBe(false) }) @@ -1112,16 +1249,16 @@ describe('PageSelector', () => { render() - expect(screen.getByTestId('virtual-list')).toBeInTheDocument() + expect(screen.getByTestId('virtual-list'))!.toBeInTheDocument() if (propVariation.canPreview) - expect(screen.getByText('common.dataSource.notion.selector.preview')).toBeInTheDocument() + expect(screen.getByText('common.dataSource.notion.selector.preview'))!.toBeInTheDocument() else expect(screen.queryByText('common.dataSource.notion.selector.preview')).not.toBeInTheDocument() if (propVariation.isMultipleChoice) - expect(getCheckbox()).toBeInTheDocument() + expect(getCheckbox())!.toBeInTheDocument() else - expect(getRadio()).toBeInTheDocument() + expect(getRadio())!.toBeInTheDocument() }) it('should handle all default prop values', () => { @@ -1140,8 +1277,9 @@ describe('PageSelector', () => { render() // Assert - Defaults should be applied - expect(getCheckbox()).toBeInTheDocument() - expect(screen.getByText('common.dataSource.notion.selector.preview')).toBeInTheDocument() + // Assert - Defaults should be applied + expect(getCheckbox())!.toBeInTheDocument() + expect(screen.getByText('common.dataSource.notion.selector.preview'))!.toBeInTheDocument() }) }) @@ -1166,8 +1304,8 @@ describe('PageSelector', () => { recursivePushInParentDescendants(pagesMap, listTreeMap, childEntry, childEntry) expect(listTreeMap.parent).toBeDefined() - expect(listTreeMap.parent.children.has('child')).toBe(true) - expect(listTreeMap.parent.descendants.has('child')).toBe(true) + expect(listTreeMap.parent!.children.has('child')).toBe(true) + expect(listTreeMap.parent!.descendants.has('child')).toBe(true) expect(childEntry.depth).toBe(1) expect(childEntry.ancestors).toContain('Parent') }) @@ -1274,8 +1412,8 @@ describe('PageSelector', () => { expect(l2Entry.depth).toBe(2) expect(l2Entry.ancestors).toEqual(['Level 0', 'Level 1']) - expect(listTreeMap.l1.children.has('l2')).toBe(true) - expect(listTreeMap.l0.descendants.has('l2')).toBe(true) + expect(listTreeMap.l1!.children.has('l2')).toBe(true) + expect(listTreeMap.l0!.descendants.has('l2')).toBe(true) }) it('should update existing parent entry', () => { @@ -1329,7 +1467,7 @@ describe('PageSelector', () => { // Assert - Item should have preview styling class const itemContainer = screen.getByText('Test Page').closest('[class*="group"]') - expect(itemContainer).toHaveClass('bg-state-base-hover') + expect(itemContainer)!.toHaveClass('bg-state-base-hover') }) it('should show arrow for pages with children', () => { @@ -1343,7 +1481,7 @@ describe('PageSelector', () => { // Assert - Root page should have expand arrow const arrowContainer = document.querySelector('[class*="hover:bg-components-button-ghost-bg-hover"]') - expect(arrowContainer).toBeInTheDocument() + expect(arrowContainer)!.toBeInTheDocument() }) it('should not show arrow for leaf pages', () => { diff --git a/web/app/components/datasets/documents/create-from-pipeline/data-source/online-documents/page-selector/__tests__/utils.spec.ts b/web/app/components/datasets/documents/create-from-pipeline/data-source/online-documents/page-selector/__tests__/utils.spec.ts index 2a081ef418..a7175a47de 100644 --- a/web/app/components/datasets/documents/create-from-pipeline/data-source/online-documents/page-selector/__tests__/utils.spec.ts +++ b/web/app/components/datasets/documents/create-from-pipeline/data-source/online-documents/page-selector/__tests__/utils.spec.ts @@ -28,11 +28,11 @@ describe('recursivePushInParentDescendants', () => { child1: makePageEntry({ page_id: 'child1', parent_id: 'parent1', page_name: 'Child' }), } - recursivePushInParentDescendants(pagesMap, listTreeMap, listTreeMap.child1, listTreeMap.child1) + recursivePushInParentDescendants(pagesMap, listTreeMap, listTreeMap.child1!, listTreeMap.child1!) expect(listTreeMap.parent1).toBeDefined() - expect(listTreeMap.parent1.children.has('child1')).toBe(true) - expect(listTreeMap.parent1.descendants.has('child1')).toBe(true) + expect(listTreeMap.parent1!.children.has('child1')).toBe(true) + expect(listTreeMap.parent1!.descendants.has('child1')).toBe(true) }) it('should recursively populate ancestors for deeply nested items', () => { @@ -47,11 +47,11 @@ describe('recursivePushInParentDescendants', () => { child: makePageEntry({ page_id: 'child', parent_id: 'parent', page_name: 'Child' }), } - recursivePushInParentDescendants(pagesMap, listTreeMap, listTreeMap.child, listTreeMap.child) + recursivePushInParentDescendants(pagesMap, listTreeMap, listTreeMap.child!, listTreeMap.child!) - expect(listTreeMap.child.depth).toBe(2) - expect(listTreeMap.child.ancestors).toContain('Grandparent') - expect(listTreeMap.child.ancestors).toContain('Parent') + expect(listTreeMap.child!.depth).toBe(2) + expect(listTreeMap.child!.ancestors).toContain('Grandparent') + expect(listTreeMap.child!.ancestors).toContain('Parent') }) it('should do nothing for root parent', () => { @@ -63,7 +63,7 @@ describe('recursivePushInParentDescendants', () => { root_child: makePageEntry({ page_id: 'root_child', parent_id: 'root', page_name: 'Root Child' }), } - recursivePushInParentDescendants(pagesMap, listTreeMap, listTreeMap.root_child, listTreeMap.root_child) + recursivePushInParentDescendants(pagesMap, listTreeMap, listTreeMap.root_child!, listTreeMap.root_child!) // No new entries should be added since parent is root expect(Object.keys(listTreeMap)).toEqual(['root_child']) @@ -76,7 +76,7 @@ describe('recursivePushInParentDescendants', () => { // Should not throw recursivePushInParentDescendants(pagesMap, listTreeMap, current, current) - expect(listTreeMap.orphan.depth).toBe(0) + expect(listTreeMap.orphan!.depth).toBe(0) }) it('should add to existing parent entry when parent already in tree', () => { @@ -91,10 +91,10 @@ describe('recursivePushInParentDescendants', () => { child2: makePageEntry({ page_id: 'child2', parent_id: 'parent', page_name: 'Child2' }), } - recursivePushInParentDescendants(pagesMap, listTreeMap, listTreeMap.child2, listTreeMap.child2) + recursivePushInParentDescendants(pagesMap, listTreeMap, listTreeMap.child2!, listTreeMap.child2!) - expect(listTreeMap.parent.children.has('child2')).toBe(true) - expect(listTreeMap.parent.descendants.has('child2')).toBe(true) - expect(listTreeMap.parent.children.has('child1')).toBe(true) + expect(listTreeMap.parent!.children.has('child2')).toBe(true) + expect(listTreeMap.parent!.descendants.has('child2')).toBe(true) + expect(listTreeMap.parent!.children.has('child1')).toBe(true) }) }) diff --git a/web/app/components/datasets/documents/create-from-pipeline/data-source/online-drive/__tests__/index.spec.tsx b/web/app/components/datasets/documents/create-from-pipeline/data-source/online-drive/__tests__/index.spec.tsx index 7c1941afd9..6eed119ede 100644 --- a/web/app/components/datasets/documents/create-from-pipeline/data-source/online-drive/__tests__/index.spec.tsx +++ b/web/app/components/datasets/documents/create-from-pipeline/data-source/online-drive/__tests__/index.spec.tsx @@ -259,8 +259,8 @@ describe('OnlineDrive', () => { render() - expect(screen.getByTestId('header')).toBeInTheDocument() - expect(screen.getByTestId('file-list')).toBeInTheDocument() + expect(screen.getByTestId('header'))!.toBeInTheDocument() + expect(screen.getByTestId('file-list'))!.toBeInTheDocument() }) it('should render Header with correct props', () => { @@ -271,9 +271,9 @@ describe('OnlineDrive', () => { render() - expect(screen.getByTestId('header-doc-title')).toHaveTextContent('Docs') - expect(screen.getByTestId('header-plugin-name')).toHaveTextContent('My Online Drive') - expect(screen.getByTestId('header-credential-id')).toHaveTextContent('cred-123') + expect(screen.getByTestId('header-doc-title'))!.toHaveTextContent('Docs') + expect(screen.getByTestId('header-plugin-name'))!.toHaveTextContent('My Online Drive') + expect(screen.getByTestId('header-credential-id'))!.toHaveTextContent('cred-123') }) it('should render FileList with correct props', () => { @@ -290,11 +290,11 @@ describe('OnlineDrive', () => { render() - expect(screen.getByTestId('file-list')).toBeInTheDocument() - expect(screen.getByTestId('file-list-keywords')).toHaveTextContent('search-term') - expect(screen.getByTestId('file-list-breadcrumbs')).toHaveTextContent('folder1/folder2') - expect(screen.getByTestId('file-list-bucket')).toHaveTextContent('my-bucket') - expect(screen.getByTestId('file-list-selected-count')).toHaveTextContent('2') + expect(screen.getByTestId('file-list'))!.toBeInTheDocument() + expect(screen.getByTestId('file-list-keywords'))!.toHaveTextContent('search-term') + expect(screen.getByTestId('file-list-breadcrumbs'))!.toHaveTextContent('folder1/folder2') + expect(screen.getByTestId('file-list-bucket'))!.toHaveTextContent('my-bucket') + expect(screen.getByTestId('file-list-selected-count'))!.toHaveTextContent('2') }) it('should pass docLink with correct path to Header', () => { @@ -371,7 +371,7 @@ describe('OnlineDrive', () => { render() - expect(screen.getByTestId('header-plugin-name')).toHaveTextContent('Custom Online Drive') + expect(screen.getByTestId('header-plugin-name'))!.toHaveTextContent('Custom Online Drive') }) }) @@ -411,7 +411,7 @@ describe('OnlineDrive', () => { render() - expect(screen.getByTestId('file-list-is-in-pipeline')).toHaveTextContent('true') + expect(screen.getByTestId('file-list-is-in-pipeline'))!.toHaveTextContent('true') }) }) @@ -421,7 +421,7 @@ describe('OnlineDrive', () => { render() - expect(screen.getByTestId('file-list-support-batch')).toHaveTextContent('true') + expect(screen.getByTestId('file-list-support-batch'))!.toHaveTextContent('true') }) it('should pass supportBatchUpload false to FileList when supportBatchUpload is false', () => { @@ -429,7 +429,7 @@ describe('OnlineDrive', () => { render() - expect(screen.getByTestId('file-list-support-batch')).toHaveTextContent('false') + expect(screen.getByTestId('file-list-support-batch'))!.toHaveTextContent('false') }) it.each([ @@ -441,7 +441,7 @@ describe('OnlineDrive', () => { render() - expect(screen.getByTestId('file-list-support-batch')).toHaveTextContent(expected) + expect(screen.getByTestId('file-list-support-batch'))!.toHaveTextContent(expected) }) }) @@ -504,7 +504,7 @@ describe('OnlineDrive', () => { render() await waitFor(() => { - expect(screen.getByTestId('file-list-loading')).toHaveTextContent('true') + expect(screen.getByTestId('file-list-loading'))!.toHaveTextContent('true') }) }) @@ -566,7 +566,8 @@ describe('OnlineDrive', () => { render() // Assert - filteredOnlineDriveFileList should have 2 items matching 'test' - expect(screen.getByTestId('file-list-count')).toHaveTextContent('2') + // Assert - filteredOnlineDriveFileList should have 2 items matching 'test' + expect(screen.getByTestId('file-list-count'))!.toHaveTextContent('2') }) it('should return all files when keywords is empty', () => { @@ -580,7 +581,7 @@ describe('OnlineDrive', () => { render() - expect(screen.getByTestId('file-list-count')).toHaveTextContent('3') + expect(screen.getByTestId('file-list-count'))!.toHaveTextContent('3') }) it('should filter files case-insensitively', () => { @@ -594,7 +595,7 @@ describe('OnlineDrive', () => { render() - expect(screen.getByTestId('file-list-count')).toHaveTextContent('2') + expect(screen.getByTestId('file-list-count'))!.toHaveTextContent('2') }) }) @@ -932,7 +933,7 @@ describe('OnlineDrive', () => { render() - expect(screen.getByTestId('header-credentials-count')).toHaveTextContent('0') + expect(screen.getByTestId('header-credentials-count'))!.toHaveTextContent('0') }) it('should handle undefined credentials data', () => { @@ -943,7 +944,7 @@ describe('OnlineDrive', () => { render() - expect(screen.getByTestId('header-credentials-count')).toHaveTextContent('0') + expect(screen.getByTestId('header-credentials-count'))!.toHaveTextContent('0') }) it('should handle undefined pipelineId', async () => { @@ -969,7 +970,7 @@ describe('OnlineDrive', () => { render() - expect(screen.getByTestId('file-list-count')).toHaveTextContent('0') + expect(screen.getByTestId('file-list-count'))!.toHaveTextContent('0') }) it('should handle empty breadcrumbs', () => { @@ -978,7 +979,7 @@ describe('OnlineDrive', () => { render() - expect(screen.getByTestId('file-list-breadcrumbs')).toHaveTextContent('') + expect(screen.getByTestId('file-list-breadcrumbs'))!.toHaveTextContent('') }) it('should handle empty bucket', () => { @@ -987,7 +988,7 @@ describe('OnlineDrive', () => { render() - expect(screen.getByTestId('file-list-bucket')).toHaveTextContent('') + expect(screen.getByTestId('file-list-bucket'))!.toHaveTextContent('') }) it('should handle special characters in keywords', () => { @@ -1001,7 +1002,8 @@ describe('OnlineDrive', () => { render() // Assert - Should find file with special characters - expect(screen.getByTestId('file-list-count')).toHaveTextContent('1') + // Assert - Should find file with special characters + expect(screen.getByTestId('file-list-count'))!.toHaveTextContent('1') }) it('should handle very long file names', () => { @@ -1013,7 +1015,7 @@ describe('OnlineDrive', () => { render() - expect(screen.getByTestId('file-list-count')).toHaveTextContent('1') + expect(screen.getByTestId('file-list-count'))!.toHaveTextContent('1') }) it('should handle bucket list initiation response', async () => { @@ -1051,10 +1053,10 @@ describe('OnlineDrive', () => { render() - expect(screen.getByTestId('header')).toBeInTheDocument() - expect(screen.getByTestId('file-list')).toBeInTheDocument() - expect(screen.getByTestId('file-list-is-in-pipeline')).toHaveTextContent(String(propVariation.isInPipeline)) - expect(screen.getByTestId('file-list-support-batch')).toHaveTextContent(String(propVariation.supportBatchUpload)) + expect(screen.getByTestId('header'))!.toBeInTheDocument() + expect(screen.getByTestId('file-list'))!.toBeInTheDocument() + expect(screen.getByTestId('file-list-is-in-pipeline'))!.toHaveTextContent(String(propVariation.isInPipeline)) + expect(screen.getByTestId('file-list-support-batch'))!.toHaveTextContent(String(propVariation.supportBatchUpload)) }) it.each([ @@ -1117,7 +1119,7 @@ describe('Header', () => { render(
) - expect(screen.getByText('Documentation')).toBeInTheDocument() + expect(screen.getByText('Documentation'))!.toBeInTheDocument() }) it('should render doc link with correct href', () => { @@ -1129,9 +1131,9 @@ describe('Header', () => { render(
) const link = screen.getByRole('link') - expect(link).toHaveAttribute('href', 'https://custom-docs.com/path') - expect(link).toHaveAttribute('target', '_blank') - expect(link).toHaveAttribute('rel', 'noopener noreferrer') + expect(link)!.toHaveAttribute('href', 'https://custom-docs.com/path') + expect(link)!.toHaveAttribute('target', '_blank') + expect(link)!.toHaveAttribute('rel', 'noopener noreferrer') }) it('should render doc title text', () => { @@ -1139,7 +1141,7 @@ describe('Header', () => { render(
) - expect(screen.getByText('My Documentation Title')).toBeInTheDocument() + expect(screen.getByText('My Documentation Title'))!.toBeInTheDocument() }) it('should render configuration button', () => { @@ -1147,7 +1149,7 @@ describe('Header', () => { render(
) - expect(screen.getByRole('button')).toBeInTheDocument() + expect(screen.getByRole('button'))!.toBeInTheDocument() }) }) @@ -1164,7 +1166,7 @@ describe('Header', () => { render(
) if (docTitle) - expect(screen.getByText(docTitle)).toBeInTheDocument() + expect(screen.getByText(docTitle))!.toBeInTheDocument() }) }) @@ -1178,7 +1180,7 @@ describe('Header', () => { render(
) - expect(screen.getByRole('link')).toHaveAttribute('href', docLink) + expect(screen.getByRole('link'))!.toHaveAttribute('href', docLink) }) }) @@ -1209,7 +1211,7 @@ describe('Header', () => { render(
) const titleSpan = screen.getByTitle('Accessible Title') - expect(titleSpan).toBeInTheDocument() + expect(titleSpan)!.toBeInTheDocument() }) }) }) @@ -1437,10 +1439,10 @@ describe('utils', () => { const result = convertOnlineDriveData(data, [], 'my-bucket') expect(result.fileList).toHaveLength(4) - expect(result.fileList[0].type).toBe(OnlineDriveFileType.folder) - expect(result.fileList[1].type).toBe(OnlineDriveFileType.file) - expect(result.fileList[2].type).toBe(OnlineDriveFileType.folder) - expect(result.fileList[3].type).toBe(OnlineDriveFileType.file) + expect(result.fileList[0]!.type).toBe(OnlineDriveFileType.folder) + expect(result.fileList[1]!.type).toBe(OnlineDriveFileType.file) + expect(result.fileList[2]!.type).toBe(OnlineDriveFileType.folder) + expect(result.fileList[3]!.type).toBe(OnlineDriveFileType.file) }) }) @@ -1539,7 +1541,7 @@ describe('utils', () => { const result = convertOnlineDriveData(data, [], 'my-bucket') - expect(result.fileList[0].size).toBe(0) + expect(result.fileList[0]!.size).toBe(0) }) it('should handle files with very large size', () => { @@ -1555,7 +1557,7 @@ describe('utils', () => { const result = convertOnlineDriveData(data, [], 'my-bucket') - expect(result.fileList[0].size).toBe(largeSize) + expect(result.fileList[0]!.size).toBe(largeSize) }) it('should handle files with special characters in name', () => { @@ -1574,9 +1576,9 @@ describe('utils', () => { const result = convertOnlineDriveData(data, [], 'my-bucket') - expect(result.fileList[0].name).toBe('file[1] (copy).txt') - expect(result.fileList[1].name).toBe('doc-with-dash_and_underscore.pdf') - expect(result.fileList[2].name).toBe('file with spaces.txt') + expect(result.fileList[0]!.name).toBe('file[1] (copy).txt') + expect(result.fileList[1]!.name).toBe('doc-with-dash_and_underscore.pdf') + expect(result.fileList[2]!.name).toBe('file with spaces.txt') }) it('should handle complex next_page_parameters', () => { diff --git a/web/app/components/datasets/documents/create-from-pipeline/data-source/online-drive/__tests__/utils.spec.ts b/web/app/components/datasets/documents/create-from-pipeline/data-source/online-drive/__tests__/utils.spec.ts index 7c5761be8a..9ac2ef9f89 100644 --- a/web/app/components/datasets/documents/create-from-pipeline/data-source/online-drive/__tests__/utils.spec.ts +++ b/web/app/components/datasets/documents/create-from-pipeline/data-source/online-drive/__tests__/utils.spec.ts @@ -93,10 +93,10 @@ describe('online-drive utils', () => { const result = convertOnlineDriveData(data, [], 'bucket-1') expect(result.fileList).toHaveLength(2) - expect(result.fileList[0].type).toBe(OnlineDriveFileType.file) - expect(result.fileList[0].size).toBe(100) - expect(result.fileList[1].type).toBe(OnlineDriveFileType.folder) - expect(result.fileList[1].size).toBeUndefined() + expect(result.fileList[0]!.type).toBe(OnlineDriveFileType.file) + expect(result.fileList[0]!.size).toBe(100) + expect(result.fileList[1]!.type).toBe(OnlineDriveFileType.folder) + expect(result.fileList[1]!.size).toBeUndefined() expect(result.isTruncated).toBe(true) expect(result.nextPageParameters).toEqual({ token: 'next' }) expect(result.hasBucket).toBe(true) diff --git a/web/app/components/datasets/documents/create-from-pipeline/data-source/online-drive/file-list/header/__tests__/index.spec.tsx b/web/app/components/datasets/documents/create-from-pipeline/data-source/online-drive/file-list/header/__tests__/index.spec.tsx index 07308361ad..dcb1922fe9 100644 --- a/web/app/components/datasets/documents/create-from-pipeline/data-source/online-drive/file-list/header/__tests__/index.spec.tsx +++ b/web/app/components/datasets/documents/create-from-pipeline/data-source/online-drive/file-list/header/__tests__/index.spec.tsx @@ -60,7 +60,8 @@ describe('Header', () => { render(
) // Assert - search input should be visible - expect(screen.getByPlaceholderText('datasetPipeline.onlineDrive.breadcrumbs.searchPlaceholder')).toBeInTheDocument() + // Assert - search input should be visible + expect(screen.getByPlaceholderText('datasetPipeline.onlineDrive.breadcrumbs.searchPlaceholder'))!.toBeInTheDocument() }) it('should render with correct container styles', () => { @@ -70,12 +71,12 @@ describe('Header', () => { // Assert - container should have correct class names const wrapper = container.firstChild as HTMLElement - expect(wrapper).toHaveClass('flex') - expect(wrapper).toHaveClass('items-center') - expect(wrapper).toHaveClass('gap-x-2') - expect(wrapper).toHaveClass('bg-components-panel-bg') - expect(wrapper).toHaveClass('p-1') - expect(wrapper).toHaveClass('pl-3') + expect(wrapper)!.toHaveClass('flex') + expect(wrapper)!.toHaveClass('items-center') + expect(wrapper)!.toHaveClass('gap-x-2') + expect(wrapper)!.toHaveClass('bg-components-panel-bg') + expect(wrapper)!.toHaveClass('p-1') + expect(wrapper)!.toHaveClass('pl-3') }) it('should render Input component with correct props', () => { @@ -84,8 +85,8 @@ describe('Header', () => { render(
) const input = screen.getByPlaceholderText('datasetPipeline.onlineDrive.breadcrumbs.searchPlaceholder') - expect(input).toBeInTheDocument() - expect(input).toHaveValue('test-value') + expect(input)!.toBeInTheDocument() + expect(input)!.toHaveValue('test-value') }) it('should render Input with search icon', () => { @@ -95,7 +96,7 @@ describe('Header', () => { // Assert - Input should have search icon class const searchIcon = container.querySelector('.i-ri-search-line.h-4.w-4') - expect(searchIcon).toBeInTheDocument() + expect(searchIcon)!.toBeInTheDocument() }) it('should render Input with correct wrapper width', () => { @@ -105,7 +106,7 @@ describe('Header', () => { // Assert - Input wrapper should have w-[200px] class const inputWrapper = container.querySelector('.w-\\[200px\\]') - expect(inputWrapper).toBeInTheDocument() + expect(inputWrapper)!.toBeInTheDocument() }) }) @@ -117,7 +118,7 @@ describe('Header', () => { render(
) const input = screen.getByPlaceholderText('datasetPipeline.onlineDrive.breadcrumbs.searchPlaceholder') - expect(input).toHaveValue('') + expect(input)!.toHaveValue('') }) it('should display input value correctly', () => { @@ -126,7 +127,7 @@ describe('Header', () => { render(
) const input = screen.getByPlaceholderText('datasetPipeline.onlineDrive.breadcrumbs.searchPlaceholder') - expect(input).toHaveValue('search-query') + expect(input)!.toHaveValue('search-query') }) it('should handle special characters in inputValue', () => { @@ -136,7 +137,7 @@ describe('Header', () => { render(
) const input = screen.getByPlaceholderText('datasetPipeline.onlineDrive.breadcrumbs.searchPlaceholder') - expect(input).toHaveValue(specialChars) + expect(input)!.toHaveValue(specialChars) }) it('should handle unicode characters in inputValue', () => { @@ -146,7 +147,7 @@ describe('Header', () => { render(
) const input = screen.getByPlaceholderText('datasetPipeline.onlineDrive.breadcrumbs.searchPlaceholder') - expect(input).toHaveValue(unicodeValue) + expect(input)!.toHaveValue(unicodeValue) }) }) @@ -157,7 +158,8 @@ describe('Header', () => { render(
) // Assert - Component should render without errors - expect(screen.getByPlaceholderText('datasetPipeline.onlineDrive.breadcrumbs.searchPlaceholder')).toBeInTheDocument() + // Assert - Component should render without errors + expect(screen.getByPlaceholderText('datasetPipeline.onlineDrive.breadcrumbs.searchPlaceholder'))!.toBeInTheDocument() }) it('should render with single breadcrumb', () => { @@ -165,7 +167,7 @@ describe('Header', () => { render(
) - expect(screen.getByPlaceholderText('datasetPipeline.onlineDrive.breadcrumbs.searchPlaceholder')).toBeInTheDocument() + expect(screen.getByPlaceholderText('datasetPipeline.onlineDrive.breadcrumbs.searchPlaceholder'))!.toBeInTheDocument() }) it('should render with multiple breadcrumbs', () => { @@ -173,7 +175,7 @@ describe('Header', () => { render(
) - expect(screen.getByPlaceholderText('datasetPipeline.onlineDrive.breadcrumbs.searchPlaceholder')).toBeInTheDocument() + expect(screen.getByPlaceholderText('datasetPipeline.onlineDrive.breadcrumbs.searchPlaceholder'))!.toBeInTheDocument() }) }) @@ -184,7 +186,8 @@ describe('Header', () => { render(
) // Assert - keywords are passed through, component renders - expect(screen.getByPlaceholderText('datasetPipeline.onlineDrive.breadcrumbs.searchPlaceholder')).toBeInTheDocument() + // Assert - keywords are passed through, component renders + expect(screen.getByPlaceholderText('datasetPipeline.onlineDrive.breadcrumbs.searchPlaceholder'))!.toBeInTheDocument() }) }) @@ -194,7 +197,7 @@ describe('Header', () => { render(
) - expect(screen.getByPlaceholderText('datasetPipeline.onlineDrive.breadcrumbs.searchPlaceholder')).toBeInTheDocument() + expect(screen.getByPlaceholderText('datasetPipeline.onlineDrive.breadcrumbs.searchPlaceholder'))!.toBeInTheDocument() }) it('should render with bucket value', () => { @@ -202,7 +205,7 @@ describe('Header', () => { render(
) - expect(screen.getByPlaceholderText('datasetPipeline.onlineDrive.breadcrumbs.searchPlaceholder')).toBeInTheDocument() + expect(screen.getByPlaceholderText('datasetPipeline.onlineDrive.breadcrumbs.searchPlaceholder'))!.toBeInTheDocument() }) }) @@ -212,7 +215,7 @@ describe('Header', () => { render(
) - expect(screen.getByPlaceholderText('datasetPipeline.onlineDrive.breadcrumbs.searchPlaceholder')).toBeInTheDocument() + expect(screen.getByPlaceholderText('datasetPipeline.onlineDrive.breadcrumbs.searchPlaceholder'))!.toBeInTheDocument() }) it('should handle positive search results', () => { @@ -221,7 +224,8 @@ describe('Header', () => { render(
) // Assert - Breadcrumbs will show search results text when keywords exist and results > 0 - expect(screen.getByPlaceholderText('datasetPipeline.onlineDrive.breadcrumbs.searchPlaceholder')).toBeInTheDocument() + // Assert - Breadcrumbs will show search results text when keywords exist and results > 0 + expect(screen.getByPlaceholderText('datasetPipeline.onlineDrive.breadcrumbs.searchPlaceholder'))!.toBeInTheDocument() }) it('should handle large search results count', () => { @@ -229,7 +233,7 @@ describe('Header', () => { render(
) - expect(screen.getByPlaceholderText('datasetPipeline.onlineDrive.breadcrumbs.searchPlaceholder')).toBeInTheDocument() + expect(screen.getByPlaceholderText('datasetPipeline.onlineDrive.breadcrumbs.searchPlaceholder'))!.toBeInTheDocument() }) }) @@ -239,7 +243,7 @@ describe('Header', () => { render(
) - expect(screen.getByPlaceholderText('datasetPipeline.onlineDrive.breadcrumbs.searchPlaceholder')).toBeInTheDocument() + expect(screen.getByPlaceholderText('datasetPipeline.onlineDrive.breadcrumbs.searchPlaceholder'))!.toBeInTheDocument() }) it('should render correctly when isInPipeline is true', () => { @@ -247,7 +251,7 @@ describe('Header', () => { render(
) - expect(screen.getByPlaceholderText('datasetPipeline.onlineDrive.breadcrumbs.searchPlaceholder')).toBeInTheDocument() + expect(screen.getByPlaceholderText('datasetPipeline.onlineDrive.breadcrumbs.searchPlaceholder'))!.toBeInTheDocument() }) }) }) @@ -265,7 +269,7 @@ describe('Header', () => { expect(mockHandleInputChange).toHaveBeenCalledTimes(1) // Verify that onChange event was triggered (React's synthetic event structure) - expect(mockHandleInputChange.mock.calls[0][0]).toHaveProperty('type', 'change') + expect(mockHandleInputChange.mock.calls[0]![0]).toHaveProperty('type', 'change') }) it('should call handleInputChange on each keystroke', () => { @@ -290,7 +294,7 @@ describe('Header', () => { fireEvent.change(input, { target: { value: '' } }) expect(mockHandleInputChange).toHaveBeenCalledTimes(1) - expect(mockHandleInputChange.mock.calls[0][0]).toHaveProperty('type', 'change') + expect(mockHandleInputChange.mock.calls[0]![0]).toHaveProperty('type', 'change') }) it('should handle whitespace-only input', () => { @@ -302,7 +306,7 @@ describe('Header', () => { fireEvent.change(input, { target: { value: ' ' } }) expect(mockHandleInputChange).toHaveBeenCalledTimes(1) - expect(mockHandleInputChange.mock.calls[0][0]).toHaveProperty('type', 'change') + expect(mockHandleInputChange.mock.calls[0]![0]).toHaveProperty('type', 'change') }) }) @@ -317,7 +321,7 @@ describe('Header', () => { // Act - Find and click the clear icon container const clearButton = screen.getByTestId('input-clear') - expect(clearButton).toBeInTheDocument() + expect(clearButton)!.toBeInTheDocument() fireEvent.click(clearButton!) expect(mockHandleResetKeywords).toHaveBeenCalledTimes(1) @@ -338,7 +342,7 @@ describe('Header', () => { // Act & Assert - Clear icon should be visible const clearIcon = screen.getByTestId('input-clear') - expect(clearIcon).toBeInTheDocument() + expect(clearIcon)!.toBeInTheDocument() }) }) }) @@ -365,21 +369,23 @@ describe('Header', () => { rerender(
) // Assert - Component renders without errors - expect(screen.getByPlaceholderText('datasetPipeline.onlineDrive.breadcrumbs.searchPlaceholder')).toBeInTheDocument() + // Assert - Component renders without errors + expect(screen.getByPlaceholderText('datasetPipeline.onlineDrive.breadcrumbs.searchPlaceholder'))!.toBeInTheDocument() }) it('should re-render when inputValue changes', () => { const props = createDefaultProps({ inputValue: 'initial' }) const { rerender } = render(
) const input = screen.getByPlaceholderText('datasetPipeline.onlineDrive.breadcrumbs.searchPlaceholder') - expect(input).toHaveValue('initial') + expect(input)!.toHaveValue('initial') // Act - Rerender with different inputValue const newProps = createDefaultProps({ inputValue: 'changed' }) rerender(
) // Assert - Input value should be updated - expect(input).toHaveValue('changed') + // Assert - Input value should be updated + expect(input)!.toHaveValue('changed') }) it('should re-render when breadcrumbs change', () => { @@ -391,7 +397,8 @@ describe('Header', () => { rerender(
) // Assert - Component renders without errors - expect(screen.getByPlaceholderText('datasetPipeline.onlineDrive.breadcrumbs.searchPlaceholder')).toBeInTheDocument() + // Assert - Component renders without errors + expect(screen.getByPlaceholderText('datasetPipeline.onlineDrive.breadcrumbs.searchPlaceholder'))!.toBeInTheDocument() }) it('should re-render when keywords change', () => { @@ -403,7 +410,8 @@ describe('Header', () => { rerender(
) // Assert - Component renders without errors - expect(screen.getByPlaceholderText('datasetPipeline.onlineDrive.breadcrumbs.searchPlaceholder')).toBeInTheDocument() + // Assert - Component renders without errors + expect(screen.getByPlaceholderText('datasetPipeline.onlineDrive.breadcrumbs.searchPlaceholder'))!.toBeInTheDocument() }) }) @@ -415,7 +423,7 @@ describe('Header', () => { render(
) const input = screen.getByPlaceholderText('datasetPipeline.onlineDrive.breadcrumbs.searchPlaceholder') - expect(input).toHaveValue(longValue) + expect(input)!.toHaveValue(longValue) }) it('should handle very long breadcrumb paths', () => { @@ -424,7 +432,7 @@ describe('Header', () => { render(
) - expect(screen.getByPlaceholderText('datasetPipeline.onlineDrive.breadcrumbs.searchPlaceholder')).toBeInTheDocument() + expect(screen.getByPlaceholderText('datasetPipeline.onlineDrive.breadcrumbs.searchPlaceholder'))!.toBeInTheDocument() }) it('should handle breadcrumbs with special characters', () => { @@ -433,7 +441,7 @@ describe('Header', () => { render(
) - expect(screen.getByPlaceholderText('datasetPipeline.onlineDrive.breadcrumbs.searchPlaceholder')).toBeInTheDocument() + expect(screen.getByPlaceholderText('datasetPipeline.onlineDrive.breadcrumbs.searchPlaceholder'))!.toBeInTheDocument() }) it('should handle breadcrumbs with unicode names', () => { @@ -442,7 +450,7 @@ describe('Header', () => { render(
) - expect(screen.getByPlaceholderText('datasetPipeline.onlineDrive.breadcrumbs.searchPlaceholder')).toBeInTheDocument() + expect(screen.getByPlaceholderText('datasetPipeline.onlineDrive.breadcrumbs.searchPlaceholder'))!.toBeInTheDocument() }) it('should handle bucket with special characters', () => { @@ -450,7 +458,7 @@ describe('Header', () => { render(
) - expect(screen.getByPlaceholderText('datasetPipeline.onlineDrive.breadcrumbs.searchPlaceholder')).toBeInTheDocument() + expect(screen.getByPlaceholderText('datasetPipeline.onlineDrive.breadcrumbs.searchPlaceholder'))!.toBeInTheDocument() }) it('should pass the event object to handleInputChange callback', () => { @@ -463,7 +471,7 @@ describe('Header', () => { // Assert - Verify the event object is passed correctly expect(mockHandleInputChange).toHaveBeenCalledTimes(1) - const eventArg = mockHandleInputChange.mock.calls[0][0] + const eventArg = mockHandleInputChange.mock.calls[0]![0] expect(eventArg).toHaveProperty('type', 'change') expect(eventArg).toHaveProperty('target') }) @@ -480,7 +488,7 @@ describe('Header', () => { render(
) - expect(screen.getByPlaceholderText('datasetPipeline.onlineDrive.breadcrumbs.searchPlaceholder')).toBeInTheDocument() + expect(screen.getByPlaceholderText('datasetPipeline.onlineDrive.breadcrumbs.searchPlaceholder'))!.toBeInTheDocument() }) it.each([ @@ -493,7 +501,7 @@ describe('Header', () => { render(
) - expect(screen.getByPlaceholderText('datasetPipeline.onlineDrive.breadcrumbs.searchPlaceholder')).toBeInTheDocument() + expect(screen.getByPlaceholderText('datasetPipeline.onlineDrive.breadcrumbs.searchPlaceholder'))!.toBeInTheDocument() }) it.each([ @@ -507,7 +515,7 @@ describe('Header', () => { render(
) const input = screen.getByPlaceholderText('datasetPipeline.onlineDrive.breadcrumbs.searchPlaceholder') - expect(input).toHaveValue(inputValue) + expect(input)!.toHaveValue(inputValue) }) }) @@ -525,7 +533,8 @@ describe('Header', () => { render(
) // Assert - Component should render successfully, meaning props are passed correctly - expect(screen.getByPlaceholderText('datasetPipeline.onlineDrive.breadcrumbs.searchPlaceholder')).toBeInTheDocument() + // Assert - Component should render successfully, meaning props are passed correctly + expect(screen.getByPlaceholderText('datasetPipeline.onlineDrive.breadcrumbs.searchPlaceholder'))!.toBeInTheDocument() }) it('should pass correct props to Input component', () => { @@ -540,7 +549,7 @@ describe('Header', () => { render(
) const input = screen.getByPlaceholderText('datasetPipeline.onlineDrive.breadcrumbs.searchPlaceholder') - expect(input).toHaveValue('test-input') + expect(input)!.toHaveValue('test-input') // Test onChange handler fireEvent.change(input, { target: { value: 'new-value' } }) diff --git a/web/app/components/datasets/documents/create-from-pipeline/data-source/online-drive/file-list/header/breadcrumbs/__tests__/bucket.spec.tsx b/web/app/components/datasets/documents/create-from-pipeline/data-source/online-drive/file-list/header/breadcrumbs/__tests__/bucket.spec.tsx index c407be51ac..83e17e6e04 100644 --- a/web/app/components/datasets/documents/create-from-pipeline/data-source/online-drive/file-list/header/breadcrumbs/__tests__/bucket.spec.tsx +++ b/web/app/components/datasets/documents/create-from-pipeline/data-source/online-drive/file-list/header/breadcrumbs/__tests__/bucket.spec.tsx @@ -22,18 +22,18 @@ describe('Bucket', () => { it('should render bucket name', () => { render() - expect(screen.getByText('my-bucket')).toBeInTheDocument() + expect(screen.getByText('my-bucket'))!.toBeInTheDocument() }) it('should render bucket icon', () => { render() - expect(screen.getByTestId('buckets-gray')).toBeInTheDocument() + expect(screen.getByTestId('buckets-gray'))!.toBeInTheDocument() }) it('should call handleBackToBucketList on icon button click', () => { render() const buttons = screen.getAllByRole('button') - fireEvent.click(buttons[0]) + fireEvent.click(buttons[0]!) expect(defaultProps.handleBackToBucketList).toHaveBeenCalledOnce() }) diff --git a/web/app/components/datasets/documents/create-from-pipeline/data-source/online-drive/file-list/header/breadcrumbs/__tests__/index.spec.tsx b/web/app/components/datasets/documents/create-from-pipeline/data-source/online-drive/file-list/header/breadcrumbs/__tests__/index.spec.tsx index a6aaf3a50b..24a241ff93 100644 --- a/web/app/components/datasets/documents/create-from-pipeline/data-source/online-drive/file-list/header/breadcrumbs/__tests__/index.spec.tsx +++ b/web/app/components/datasets/documents/create-from-pipeline/data-source/online-drive/file-list/header/breadcrumbs/__tests__/index.spec.tsx @@ -58,7 +58,7 @@ describe('Breadcrumbs', () => { // Assert - Container should be in the document const container = document.querySelector('.flex.grow') - expect(container).toBeInTheDocument() + expect(container)!.toBeInTheDocument() }) it('should render with correct container styles', () => { @@ -67,10 +67,10 @@ describe('Breadcrumbs', () => { const { container } = render() const wrapper = container.firstChild as HTMLElement - expect(wrapper).toHaveClass('flex') - expect(wrapper).toHaveClass('grow') - expect(wrapper).toHaveClass('items-center') - expect(wrapper).toHaveClass('overflow-hidden') + expect(wrapper)!.toHaveClass('flex') + expect(wrapper)!.toHaveClass('grow') + expect(wrapper)!.toHaveClass('items-center') + expect(wrapper)!.toHaveClass('overflow-hidden') }) describe('Search Results Display', () => { @@ -84,7 +84,8 @@ describe('Breadcrumbs', () => { render() // Assert - Search result text should be displayed - expect(screen.getByText(/datasetPipeline\.onlineDrive\.breadcrumbs\.searchResult/)).toBeInTheDocument() + // Assert - Search result text should be displayed + expect(screen.getByText(/datasetPipeline\.onlineDrive\.breadcrumbs\.searchResult/))!.toBeInTheDocument() }) it('should not show search results when keywords is empty', () => { @@ -121,7 +122,8 @@ describe('Breadcrumbs', () => { render() // Assert - Should use bucket name in search result - expect(screen.getByText(/searchResult.*my-bucket/i)).toBeInTheDocument() + // Assert - Should use bucket name in search result + expect(screen.getByText(/searchResult.*my-bucket/i))!.toBeInTheDocument() }) it('should use last breadcrumb as folderName when breadcrumbs exist', () => { @@ -135,7 +137,8 @@ describe('Breadcrumbs', () => { render() // Assert - Should use last breadcrumb in search result - expect(screen.getByText(/searchResult.*folder2/i)).toBeInTheDocument() + // Assert - Should use last breadcrumb in search result + expect(screen.getByText(/searchResult.*folder2/i))!.toBeInTheDocument() }) }) @@ -150,7 +153,7 @@ describe('Breadcrumbs', () => { render() - expect(screen.getByText('datasetPipeline.onlineDrive.breadcrumbs.allBuckets')).toBeInTheDocument() + expect(screen.getByText('datasetPipeline.onlineDrive.breadcrumbs.allBuckets'))!.toBeInTheDocument() }) it('should not show all buckets title when breadcrumbs exist', () => { @@ -174,6 +177,37 @@ describe('Breadcrumbs', () => { render() + // Assert - Should show bucket name instead + // Assert - Should show bucket name instead + // Assert - Should show bucket name instead + // Assert - Should show bucket name instead + // Assert - Should show bucket name instead + // Assert - Should show bucket name instead + // Assert - Should show bucket name instead + // Assert - Should show bucket name instead + // Assert - Should show bucket name instead + // Assert - Should show bucket name instead + // Assert - Should show bucket name instead + // Assert - Should show bucket name instead + // Assert - Should show bucket name instead + // Assert - Should show bucket name instead + // Assert - Should show bucket name instead + // Assert - Should show bucket name instead + // Assert - Should show bucket name instead + // Assert - Should show bucket name instead + // Assert - Should show bucket name instead + // Assert - Should show bucket name instead + // Assert - Should show bucket name instead + // Assert - Should show bucket name instead + // Assert - Should show bucket name instead + // Assert - Should show bucket name instead + // Assert - Should show bucket name instead + // Assert - Should show bucket name instead + // Assert - Should show bucket name instead + // Assert - Should show bucket name instead + // Assert - Should show bucket name instead + // Assert - Should show bucket name instead + // Assert - Should show bucket name instead // Assert - Should show bucket name instead expect(screen.queryByText('datasetPipeline.onlineDrive.breadcrumbs.allBuckets')).not.toBeInTheDocument() }) @@ -190,7 +224,8 @@ describe('Breadcrumbs', () => { render() // Assert - Bucket name should be displayed - expect(screen.getByText('test-bucket')).toBeInTheDocument() + // Assert - Bucket name should be displayed + expect(screen.getByText('test-bucket'))!.toBeInTheDocument() }) it('should not render Bucket when hasBucket is false', () => { @@ -202,6 +237,37 @@ describe('Breadcrumbs', () => { render() + // Assert - Bucket should not be displayed, Drive should be shown instead + // Assert - Bucket should not be displayed, Drive should be shown instead + // Assert - Bucket should not be displayed, Drive should be shown instead + // Assert - Bucket should not be displayed, Drive should be shown instead + // Assert - Bucket should not be displayed, Drive should be shown instead + // Assert - Bucket should not be displayed, Drive should be shown instead + // Assert - Bucket should not be displayed, Drive should be shown instead + // Assert - Bucket should not be displayed, Drive should be shown instead + // Assert - Bucket should not be displayed, Drive should be shown instead + // Assert - Bucket should not be displayed, Drive should be shown instead + // Assert - Bucket should not be displayed, Drive should be shown instead + // Assert - Bucket should not be displayed, Drive should be shown instead + // Assert - Bucket should not be displayed, Drive should be shown instead + // Assert - Bucket should not be displayed, Drive should be shown instead + // Assert - Bucket should not be displayed, Drive should be shown instead + // Assert - Bucket should not be displayed, Drive should be shown instead + // Assert - Bucket should not be displayed, Drive should be shown instead + // Assert - Bucket should not be displayed, Drive should be shown instead + // Assert - Bucket should not be displayed, Drive should be shown instead + // Assert - Bucket should not be displayed, Drive should be shown instead + // Assert - Bucket should not be displayed, Drive should be shown instead + // Assert - Bucket should not be displayed, Drive should be shown instead + // Assert - Bucket should not be displayed, Drive should be shown instead + // Assert - Bucket should not be displayed, Drive should be shown instead + // Assert - Bucket should not be displayed, Drive should be shown instead + // Assert - Bucket should not be displayed, Drive should be shown instead + // Assert - Bucket should not be displayed, Drive should be shown instead + // Assert - Bucket should not be displayed, Drive should be shown instead + // Assert - Bucket should not be displayed, Drive should be shown instead + // Assert - Bucket should not be displayed, Drive should be shown instead + // Assert - Bucket should not be displayed, Drive should be shown instead // Assert - Bucket should not be displayed, Drive should be shown instead expect(screen.queryByText('test-bucket')).not.toBeInTheDocument() }) @@ -217,7 +283,8 @@ describe('Breadcrumbs', () => { render() // Assert - "All Files" should be displayed - expect(screen.getByText('datasetPipeline.onlineDrive.breadcrumbs.allFiles')).toBeInTheDocument() + // Assert - "All Files" should be displayed + expect(screen.getByText('datasetPipeline.onlineDrive.breadcrumbs.allFiles'))!.toBeInTheDocument() }) it('should not render Drive component when hasBucket is true', () => { @@ -243,8 +310,8 @@ describe('Breadcrumbs', () => { render() - expect(screen.getByText('folder1')).toBeInTheDocument() - expect(screen.getByText('folder2')).toBeInTheDocument() + expect(screen.getByText('folder1'))!.toBeInTheDocument() + expect(screen.getByText('folder2'))!.toBeInTheDocument() }) it('should render last breadcrumb as active', () => { @@ -257,8 +324,8 @@ describe('Breadcrumbs', () => { // Assert - Last breadcrumb should have active styles const lastBreadcrumb = screen.getByText('folder2') - expect(lastBreadcrumb).toHaveClass('system-sm-medium') - expect(lastBreadcrumb).toHaveClass('text-text-secondary') + expect(lastBreadcrumb)!.toHaveClass('system-sm-medium') + expect(lastBreadcrumb)!.toHaveClass('text-text-secondary') }) it('should render non-last breadcrumbs with tertiary styles', () => { @@ -271,8 +338,8 @@ describe('Breadcrumbs', () => { // Assert - First breadcrumb should have tertiary styles const firstBreadcrumb = screen.getByText('folder1') - expect(firstBreadcrumb).toHaveClass('system-sm-regular') - expect(firstBreadcrumb).toHaveClass('text-text-tertiary') + expect(firstBreadcrumb)!.toHaveClass('system-sm-regular') + expect(firstBreadcrumb)!.toHaveClass('text-text-tertiary') }) }) @@ -287,7 +354,8 @@ describe('Breadcrumbs', () => { render() // Assert - Dropdown trigger (more button) should be present - expect(screen.getByRole('button', { name: '' })).toBeInTheDocument() + // Assert - Dropdown trigger (more button) should be present + expect(screen.getByRole('button', { name: '' }))!.toBeInTheDocument() }) it('should not show dropdown when breadcrumbs do not exceed displayBreadcrumbNum', () => { @@ -301,8 +369,10 @@ describe('Breadcrumbs', () => { // Assert - Should not have dropdown, just regular breadcrumbs // All breadcrumbs should be directly visible - expect(screen.getByText('folder1')).toBeInTheDocument() - expect(screen.getByText('folder2')).toBeInTheDocument() + // Assert - Should not have dropdown, just regular breadcrumbs + // All breadcrumbs should be directly visible + expect(screen.getByText('folder1'))!.toBeInTheDocument() + expect(screen.getByText('folder2'))!.toBeInTheDocument() // Count buttons - should be 3 (allFiles + folder1 + folder2) const buttons = container.querySelectorAll('button') expect(buttons.length).toBe(3) @@ -318,9 +388,41 @@ describe('Breadcrumbs', () => { render() // Assert - First breadcrumb and last breadcrumb should be visible - expect(screen.getByText('folder1')).toBeInTheDocument() - expect(screen.getByText('folder2')).toBeInTheDocument() - expect(screen.getByText('folder5')).toBeInTheDocument() + // Assert - First breadcrumb and last breadcrumb should be visible + expect(screen.getByText('folder1'))!.toBeInTheDocument() + expect(screen.getByText('folder2'))!.toBeInTheDocument() + expect(screen.getByText('folder5'))!.toBeInTheDocument() + // Middle breadcrumbs should be in dropdown + // Middle breadcrumbs should be in dropdown + // Middle breadcrumbs should be in dropdown + // Middle breadcrumbs should be in dropdown + // Middle breadcrumbs should be in dropdown + // Middle breadcrumbs should be in dropdown + // Middle breadcrumbs should be in dropdown + // Middle breadcrumbs should be in dropdown + // Middle breadcrumbs should be in dropdown + // Middle breadcrumbs should be in dropdown + // Middle breadcrumbs should be in dropdown + // Middle breadcrumbs should be in dropdown + // Middle breadcrumbs should be in dropdown + // Middle breadcrumbs should be in dropdown + // Middle breadcrumbs should be in dropdown + // Middle breadcrumbs should be in dropdown + // Middle breadcrumbs should be in dropdown + // Middle breadcrumbs should be in dropdown + // Middle breadcrumbs should be in dropdown + // Middle breadcrumbs should be in dropdown + // Middle breadcrumbs should be in dropdown + // Middle breadcrumbs should be in dropdown + // Middle breadcrumbs should be in dropdown + // Middle breadcrumbs should be in dropdown + // Middle breadcrumbs should be in dropdown + // Middle breadcrumbs should be in dropdown + // Middle breadcrumbs should be in dropdown + // Middle breadcrumbs should be in dropdown + // Middle breadcrumbs should be in dropdown + // Middle breadcrumbs should be in dropdown + // Middle breadcrumbs should be in dropdown // Middle breadcrumbs should be in dropdown expect(screen.queryByText('folder3')).not.toBeInTheDocument() expect(screen.queryByText('folder4')).not.toBeInTheDocument() @@ -341,8 +443,8 @@ describe('Breadcrumbs', () => { // Assert - Collapsed breadcrumbs should be visible await waitFor(() => { - expect(screen.getByText('folder3')).toBeInTheDocument() - expect(screen.getByText('folder4')).toBeInTheDocument() + expect(screen.getByText('folder3'))!.toBeInTheDocument() + expect(screen.getByText('folder4'))!.toBeInTheDocument() }) }) }) @@ -357,7 +459,8 @@ describe('Breadcrumbs', () => { render() // Assert - Only Drive should be visible - expect(screen.getByText('datasetPipeline.onlineDrive.breadcrumbs.allFiles')).toBeInTheDocument() + // Assert - Only Drive should be visible + expect(screen.getByText('datasetPipeline.onlineDrive.breadcrumbs.allFiles'))!.toBeInTheDocument() }) it('should handle single breadcrumb', () => { @@ -366,7 +469,7 @@ describe('Breadcrumbs', () => { render() - expect(screen.getByText('single-folder')).toBeInTheDocument() + expect(screen.getByText('single-folder'))!.toBeInTheDocument() }) it('should handle breadcrumbs with special characters', () => { @@ -377,8 +480,8 @@ describe('Breadcrumbs', () => { render() - expect(screen.getByText('folder [1]')).toBeInTheDocument() - expect(screen.getByText('folder (copy)')).toBeInTheDocument() + expect(screen.getByText('folder [1]'))!.toBeInTheDocument() + expect(screen.getByText('folder (copy)'))!.toBeInTheDocument() }) it('should handle breadcrumbs with unicode characters', () => { @@ -389,8 +492,8 @@ describe('Breadcrumbs', () => { render() - expect(screen.getByText('文件夹')).toBeInTheDocument() - expect(screen.getByText('フォルダ')).toBeInTheDocument() + expect(screen.getByText('文件夹'))!.toBeInTheDocument() + expect(screen.getByText('フォルダ'))!.toBeInTheDocument() }) }) @@ -403,7 +506,7 @@ describe('Breadcrumbs', () => { render() - expect(screen.getByText(/searchResult/)).toBeInTheDocument() + expect(screen.getByText(/searchResult/))!.toBeInTheDocument() }) it('should handle whitespace keywords', () => { @@ -415,7 +518,8 @@ describe('Breadcrumbs', () => { render() // Assert - Whitespace is truthy, so should show search results - expect(screen.getByText(/searchResult/)).toBeInTheDocument() + // Assert - Whitespace is truthy, so should show search results + expect(screen.getByText(/searchResult/))!.toBeInTheDocument() }) }) @@ -428,7 +532,7 @@ describe('Breadcrumbs', () => { render() - expect(screen.getByText('production-bucket')).toBeInTheDocument() + expect(screen.getByText('production-bucket'))!.toBeInTheDocument() }) it('should handle bucket with special characters', () => { @@ -439,7 +543,7 @@ describe('Breadcrumbs', () => { render() - expect(screen.getByText('bucket-v2.0_backup')).toBeInTheDocument() + expect(screen.getByText('bucket-v2.0_backup'))!.toBeInTheDocument() }) }) @@ -452,6 +556,37 @@ describe('Breadcrumbs', () => { render() + // Assert - Should not show search results + // Assert - Should not show search results + // Assert - Should not show search results + // Assert - Should not show search results + // Assert - Should not show search results + // Assert - Should not show search results + // Assert - Should not show search results + // Assert - Should not show search results + // Assert - Should not show search results + // Assert - Should not show search results + // Assert - Should not show search results + // Assert - Should not show search results + // Assert - Should not show search results + // Assert - Should not show search results + // Assert - Should not show search results + // Assert - Should not show search results + // Assert - Should not show search results + // Assert - Should not show search results + // Assert - Should not show search results + // Assert - Should not show search results + // Assert - Should not show search results + // Assert - Should not show search results + // Assert - Should not show search results + // Assert - Should not show search results + // Assert - Should not show search results + // Assert - Should not show search results + // Assert - Should not show search results + // Assert - Should not show search results + // Assert - Should not show search results + // Assert - Should not show search results + // Assert - Should not show search results // Assert - Should not show search results expect(screen.queryByText(/searchResult/)).not.toBeInTheDocument() }) @@ -464,7 +599,7 @@ describe('Breadcrumbs', () => { render() - expect(screen.getByText(/searchResult.*10000/)).toBeInTheDocument() + expect(screen.getByText(/searchResult.*10000/))!.toBeInTheDocument() }) }) @@ -495,9 +630,10 @@ describe('Breadcrumbs', () => { render() // Assert - Should NOT collapse because 3 <= 3 - expect(screen.getByText('folder1')).toBeInTheDocument() - expect(screen.getByText('folder2')).toBeInTheDocument() - expect(screen.getByText('folder3')).toBeInTheDocument() + // Assert - Should NOT collapse because 3 <= 3 + expect(screen.getByText('folder1'))!.toBeInTheDocument() + expect(screen.getByText('folder2'))!.toBeInTheDocument() + expect(screen.getByText('folder3'))!.toBeInTheDocument() }) it('should reduce displayBreadcrumbNum by 1 when bucket is set', () => { @@ -533,9 +669,11 @@ describe('Breadcrumbs', () => { // Assert - displayBreadcrumbNum = 3, so 4 breadcrumbs should collapse // First 2 visible, dropdown, last 1 visible - expect(screen.getByText('a')).toBeInTheDocument() - expect(screen.getByText('b')).toBeInTheDocument() - expect(screen.getByText('d')).toBeInTheDocument() + // Assert - displayBreadcrumbNum = 3, so 4 breadcrumbs should collapse + // First 2 visible, dropdown, last 1 visible + expect(screen.getByText('a'))!.toBeInTheDocument() + expect(screen.getByText('b'))!.toBeInTheDocument() + expect(screen.getByText('d'))!.toBeInTheDocument() expect(screen.queryByText('c')).not.toBeInTheDocument() }) @@ -550,8 +688,9 @@ describe('Breadcrumbs', () => { render() // Assert - displayBreadcrumbNum = 2, so 3 breadcrumbs should collapse - expect(screen.getByText('a')).toBeInTheDocument() - expect(screen.getByText('c')).toBeInTheDocument() + // Assert - displayBreadcrumbNum = 2, so 3 breadcrumbs should collapse + expect(screen.getByText('a'))!.toBeInTheDocument() + expect(screen.getByText('c'))!.toBeInTheDocument() expect(screen.queryByText('b')).not.toBeInTheDocument() }) @@ -566,8 +705,9 @@ describe('Breadcrumbs', () => { render() // Assert - displayBreadcrumbNum = 3 - 1 = 2, so 3 breadcrumbs should collapse - expect(screen.getByText('a')).toBeInTheDocument() - expect(screen.getByText('c')).toBeInTheDocument() + // Assert - displayBreadcrumbNum = 3 - 1 = 2, so 3 breadcrumbs should collapse + expect(screen.getByText('a'))!.toBeInTheDocument() + expect(screen.getByText('c'))!.toBeInTheDocument() expect(screen.queryByText('b')).not.toBeInTheDocument() }) }) @@ -589,12 +729,15 @@ describe('Breadcrumbs', () => { // prefixBreadcrumbs = ['f1', 'f2'] // collapsedBreadcrumbs = ['f3', 'f4'] // lastBreadcrumb = 'f5' - expect(screen.getByText('f1')).toBeInTheDocument() - expect(screen.getByText('f2')).toBeInTheDocument() - expect(screen.getByText('f5')).toBeInTheDocument() + // prefixBreadcrumbs = ['f1', 'f2'] + // collapsedBreadcrumbs = ['f3', 'f4'] + // lastBreadcrumb = 'f5' + expect(screen.getByText('f1'))!.toBeInTheDocument() + expect(screen.getByText('f2'))!.toBeInTheDocument() + expect(screen.getByText('f5'))!.toBeInTheDocument() await waitFor(() => { - expect(screen.getByText('f3')).toBeInTheDocument() - expect(screen.getByText('f4')).toBeInTheDocument() + expect(screen.getByText('f3'))!.toBeInTheDocument() + expect(screen.getByText('f4'))!.toBeInTheDocument() }) }) @@ -608,8 +751,9 @@ describe('Breadcrumbs', () => { render() // Assert - All breadcrumbs should be visible - expect(screen.getByText('f1')).toBeInTheDocument() - expect(screen.getByText('f2')).toBeInTheDocument() + // Assert - All breadcrumbs should be visible + expect(screen.getByText('f1'))!.toBeInTheDocument() + expect(screen.getByText('f2'))!.toBeInTheDocument() }) }) }) @@ -627,7 +771,7 @@ describe('Breadcrumbs', () => { // Act - Click bucket icon button (first button in Bucket component) const buttons = screen.getAllByRole('button') - fireEvent.click(buttons[0]) // Bucket icon button + fireEvent.click(buttons[0]!) // Bucket icon button expect(mockStoreState.setOnlineDriveFileList).toHaveBeenCalledWith([]) expect(mockStoreState.setSelectedFileIds).toHaveBeenCalledWith([]) @@ -744,7 +888,7 @@ describe('Breadcrumbs', () => { fireEvent.click(dropdownTrigger) await waitFor(() => { - expect(screen.getByText('f3')).toBeInTheDocument() + expect(screen.getByText('f3'))!.toBeInTheDocument() }) fireEvent.click(screen.getByText('f3')) @@ -771,19 +915,19 @@ describe('Breadcrumbs', () => { // Assert - Component should render without errors const container = document.querySelector('.flex.grow') - expect(container).toBeInTheDocument() + expect(container)!.toBeInTheDocument() }) it('should re-render when breadcrumbs change', () => { mockStoreState.hasBucket = false const props = createDefaultProps({ breadcrumbs: ['folder1'] }) const { rerender } = render() - expect(screen.getByText('folder1')).toBeInTheDocument() + expect(screen.getByText('folder1'))!.toBeInTheDocument() // Act - Rerender with different breadcrumbs rerender() - expect(screen.getByText('folder2')).toBeInTheDocument() + expect(screen.getByText('folder2'))!.toBeInTheDocument() }) }) @@ -798,7 +942,7 @@ describe('Breadcrumbs', () => { render() - expect(screen.getByText(longName)).toBeInTheDocument() + expect(screen.getByText(longName))!.toBeInTheDocument() }) it('should handle many breadcrumbs', async () => { @@ -815,11 +959,12 @@ describe('Breadcrumbs', () => { fireEvent.click(dropdownTrigger) // Assert - First, last, and collapsed should be accessible - expect(screen.getByText('folder-0')).toBeInTheDocument() - expect(screen.getByText('folder-1')).toBeInTheDocument() - expect(screen.getByText('folder-19')).toBeInTheDocument() + // Assert - First, last, and collapsed should be accessible + expect(screen.getByText('folder-0'))!.toBeInTheDocument() + expect(screen.getByText('folder-1'))!.toBeInTheDocument() + expect(screen.getByText('folder-19'))!.toBeInTheDocument() await waitFor(() => { - expect(screen.getByText('folder-2')).toBeInTheDocument() + expect(screen.getByText('folder-2'))!.toBeInTheDocument() }) }) @@ -833,7 +978,8 @@ describe('Breadcrumbs', () => { render() // Assert - Should show all buckets title - expect(screen.getByText('datasetPipeline.onlineDrive.breadcrumbs.allBuckets')).toBeInTheDocument() + // Assert - Should show all buckets title + expect(screen.getByText('datasetPipeline.onlineDrive.breadcrumbs.allBuckets'))!.toBeInTheDocument() }) it('should handle breadcrumb with only whitespace', () => { @@ -845,7 +991,8 @@ describe('Breadcrumbs', () => { render() // Assert - Both should be rendered - expect(screen.getByText('normal-folder')).toBeInTheDocument() + // Assert - Both should be rendered + expect(screen.getByText('normal-folder'))!.toBeInTheDocument() }) }) @@ -863,7 +1010,7 @@ describe('Breadcrumbs', () => { // Assert - Component should render without errors const container = document.querySelector('.flex.grow') - expect(container).toBeInTheDocument() + expect(container)!.toBeInTheDocument() }) it.each([ @@ -916,7 +1063,8 @@ describe('Breadcrumbs', () => { render() // Assert - Search result should be shown, navigation elements should be hidden - expect(screen.getByText(/searchResult/)).toBeInTheDocument() + // Assert - Search result should be shown, navigation elements should be hidden + expect(screen.getByText(/searchResult/))!.toBeInTheDocument() expect(screen.queryByText('my-bucket')).not.toBeInTheDocument() }) }) diff --git a/web/app/components/datasets/documents/create-from-pipeline/data-source/online-drive/file-list/header/breadcrumbs/dropdown/__tests__/index.spec.tsx b/web/app/components/datasets/documents/create-from-pipeline/data-source/online-drive/file-list/header/breadcrumbs/dropdown/__tests__/index.spec.tsx index 0157d3cf79..f7112c243b 100644 --- a/web/app/components/datasets/documents/create-from-pipeline/data-source/online-drive/file-list/header/breadcrumbs/dropdown/__tests__/index.spec.tsx +++ b/web/app/components/datasets/documents/create-from-pipeline/data-source/online-drive/file-list/header/breadcrumbs/dropdown/__tests__/index.spec.tsx @@ -23,7 +23,8 @@ describe('Dropdown', () => { render() // Assert - Trigger button should be visible - expect(screen.getByRole('button')).toBeInTheDocument() + // Assert - Trigger button should be visible + expect(screen.getByRole('button'))!.toBeInTheDocument() }) it('should render trigger button with more icon', () => { @@ -33,8 +34,8 @@ describe('Dropdown', () => { // Assert - Button should have RiMoreFill icon (rendered as svg) const button = screen.getByRole('button') - expect(button).toBeInTheDocument() - expect(container.querySelector('svg')).toBeInTheDocument() + expect(button)!.toBeInTheDocument() + expect(container.querySelector('svg'))!.toBeInTheDocument() }) it('should render separator after dropdown', () => { @@ -43,7 +44,8 @@ describe('Dropdown', () => { render() // Assert - Separator "/" should be visible - expect(screen.getByText('/')).toBeInTheDocument() + // Assert - Separator "/" should be visible + expect(screen.getByText('/'))!.toBeInTheDocument() }) it('should render trigger button with correct default styles', () => { @@ -52,11 +54,11 @@ describe('Dropdown', () => { render() const button = screen.getByRole('button') - expect(button).toHaveClass('flex') - expect(button).toHaveClass('size-6') - expect(button).toHaveClass('items-center') - expect(button).toHaveClass('justify-center') - expect(button).toHaveClass('rounded-md') + expect(button)!.toHaveClass('flex') + expect(button)!.toHaveClass('size-6') + expect(button)!.toHaveClass('items-center') + expect(button)!.toHaveClass('justify-center') + expect(button)!.toHaveClass('rounded-md') }) it('should not render menu content when closed', () => { @@ -64,6 +66,37 @@ describe('Dropdown', () => { render() + // Assert - Menu content should not be visible when dropdown is closed + // Assert - Menu content should not be visible when dropdown is closed + // Assert - Menu content should not be visible when dropdown is closed + // Assert - Menu content should not be visible when dropdown is closed + // Assert - Menu content should not be visible when dropdown is closed + // Assert - Menu content should not be visible when dropdown is closed + // Assert - Menu content should not be visible when dropdown is closed + // Assert - Menu content should not be visible when dropdown is closed + // Assert - Menu content should not be visible when dropdown is closed + // Assert - Menu content should not be visible when dropdown is closed + // Assert - Menu content should not be visible when dropdown is closed + // Assert - Menu content should not be visible when dropdown is closed + // Assert - Menu content should not be visible when dropdown is closed + // Assert - Menu content should not be visible when dropdown is closed + // Assert - Menu content should not be visible when dropdown is closed + // Assert - Menu content should not be visible when dropdown is closed + // Assert - Menu content should not be visible when dropdown is closed + // Assert - Menu content should not be visible when dropdown is closed + // Assert - Menu content should not be visible when dropdown is closed + // Assert - Menu content should not be visible when dropdown is closed + // Assert - Menu content should not be visible when dropdown is closed + // Assert - Menu content should not be visible when dropdown is closed + // Assert - Menu content should not be visible when dropdown is closed + // Assert - Menu content should not be visible when dropdown is closed + // Assert - Menu content should not be visible when dropdown is closed + // Assert - Menu content should not be visible when dropdown is closed + // Assert - Menu content should not be visible when dropdown is closed + // Assert - Menu content should not be visible when dropdown is closed + // Assert - Menu content should not be visible when dropdown is closed + // Assert - Menu content should not be visible when dropdown is closed + // Assert - Menu content should not be visible when dropdown is closed // Assert - Menu content should not be visible when dropdown is closed expect(screen.queryByText('visible-folder')).not.toBeInTheDocument() }) @@ -77,8 +110,8 @@ describe('Dropdown', () => { // Assert - Menu items should be visible await waitFor(() => { - expect(screen.getByText('test-folder1')).toBeInTheDocument() - expect(screen.getByText('test-folder2')).toBeInTheDocument() + expect(screen.getByText('test-folder1'))!.toBeInTheDocument() + expect(screen.getByText('test-folder2'))!.toBeInTheDocument() }) }) }) @@ -98,7 +131,7 @@ describe('Dropdown', () => { fireEvent.click(screen.getByRole('button')) await waitFor(() => { - expect(screen.getByText('folder1')).toBeInTheDocument() + expect(screen.getByText('folder1'))!.toBeInTheDocument() }) fireEvent.click(screen.getByText('folder1')) @@ -120,7 +153,7 @@ describe('Dropdown', () => { fireEvent.click(screen.getByRole('button')) await waitFor(() => { - expect(screen.getByText('folder2')).toBeInTheDocument() + expect(screen.getByText('folder2'))!.toBeInTheDocument() }) fireEvent.click(screen.getByText('folder2')) @@ -140,9 +173,9 @@ describe('Dropdown', () => { fireEvent.click(screen.getByRole('button')) await waitFor(() => { - expect(screen.getByText('folder-a')).toBeInTheDocument() - expect(screen.getByText('folder-b')).toBeInTheDocument() - expect(screen.getByText('folder-c')).toBeInTheDocument() + expect(screen.getByText('folder-a'))!.toBeInTheDocument() + expect(screen.getByText('folder-b'))!.toBeInTheDocument() + expect(screen.getByText('folder-c'))!.toBeInTheDocument() }) }) @@ -155,7 +188,7 @@ describe('Dropdown', () => { fireEvent.click(screen.getByRole('button')) await waitFor(() => { - expect(screen.getByText('single-folder')).toBeInTheDocument() + expect(screen.getByText('single-folder'))!.toBeInTheDocument() }) }) @@ -170,7 +203,8 @@ describe('Dropdown', () => { // Assert - Menu should be rendered but with no items await waitFor(() => { // The menu container should exist but be empty - expect(screen.getByRole('button')).toBeInTheDocument() + // The menu container should exist but be empty + expect(screen.getByRole('button'))!.toBeInTheDocument() }) }) @@ -183,9 +217,9 @@ describe('Dropdown', () => { fireEvent.click(screen.getByRole('button')) await waitFor(() => { - expect(screen.getByText('folder [1]')).toBeInTheDocument() - expect(screen.getByText('folder (copy)')).toBeInTheDocument() - expect(screen.getByText('folder-v2.0')).toBeInTheDocument() + expect(screen.getByText('folder [1]'))!.toBeInTheDocument() + expect(screen.getByText('folder (copy)'))!.toBeInTheDocument() + expect(screen.getByText('folder-v2.0'))!.toBeInTheDocument() }) }) @@ -198,9 +232,9 @@ describe('Dropdown', () => { fireEvent.click(screen.getByRole('button')) await waitFor(() => { - expect(screen.getByText('文件夹')).toBeInTheDocument() - expect(screen.getByText('フォルダ')).toBeInTheDocument() - expect(screen.getByText('Папка')).toBeInTheDocument() + expect(screen.getByText('文件夹'))!.toBeInTheDocument() + expect(screen.getByText('フォルダ'))!.toBeInTheDocument() + expect(screen.getByText('Папка'))!.toBeInTheDocument() }) }) }) @@ -218,7 +252,7 @@ describe('Dropdown', () => { fireEvent.click(screen.getByRole('button')) await waitFor(() => { - expect(screen.getByText('folder1')).toBeInTheDocument() + expect(screen.getByText('folder1'))!.toBeInTheDocument() }) fireEvent.click(screen.getByText('folder1')) @@ -236,6 +270,37 @@ describe('Dropdown', () => { render() + // Assert - Menu content should not be visible + // Assert - Menu content should not be visible + // Assert - Menu content should not be visible + // Assert - Menu content should not be visible + // Assert - Menu content should not be visible + // Assert - Menu content should not be visible + // Assert - Menu content should not be visible + // Assert - Menu content should not be visible + // Assert - Menu content should not be visible + // Assert - Menu content should not be visible + // Assert - Menu content should not be visible + // Assert - Menu content should not be visible + // Assert - Menu content should not be visible + // Assert - Menu content should not be visible + // Assert - Menu content should not be visible + // Assert - Menu content should not be visible + // Assert - Menu content should not be visible + // Assert - Menu content should not be visible + // Assert - Menu content should not be visible + // Assert - Menu content should not be visible + // Assert - Menu content should not be visible + // Assert - Menu content should not be visible + // Assert - Menu content should not be visible + // Assert - Menu content should not be visible + // Assert - Menu content should not be visible + // Assert - Menu content should not be visible + // Assert - Menu content should not be visible + // Assert - Menu content should not be visible + // Assert - Menu content should not be visible + // Assert - Menu content should not be visible + // Assert - Menu content should not be visible // Assert - Menu content should not be visible expect(screen.queryByText('test-folder')).not.toBeInTheDocument() }) @@ -247,7 +312,7 @@ describe('Dropdown', () => { fireEvent.click(screen.getByRole('button')) await waitFor(() => { - expect(screen.getByText('test-folder')).toBeInTheDocument() + expect(screen.getByText('test-folder'))!.toBeInTheDocument() }) }) @@ -258,7 +323,7 @@ describe('Dropdown', () => { // Act - Open and then close fireEvent.click(screen.getByRole('button')) await waitFor(() => { - expect(screen.getByText('test-folder')).toBeInTheDocument() + expect(screen.getByText('test-folder'))!.toBeInTheDocument() }) fireEvent.click(screen.getByRole('button')) @@ -280,7 +345,7 @@ describe('Dropdown', () => { fireEvent.click(screen.getByRole('button')) await waitFor(() => { - expect(screen.getByText('test-folder')).toBeInTheDocument() + expect(screen.getByText('test-folder'))!.toBeInTheDocument() }) fireEvent.click(screen.getByText('test-folder')) @@ -297,14 +362,15 @@ describe('Dropdown', () => { const button = screen.getByRole('button') // Assert - Initial state (closed): should have hover:bg-state-base-hover - expect(button).toHaveClass('hover:bg-state-base-hover') + // Assert - Initial state (closed): should have hover:bg-state-base-hover + expect(button)!.toHaveClass('hover:bg-state-base-hover') // Act - Open dropdown fireEvent.click(button) // Assert - Open state: should have bg-state-base-hover await waitFor(() => { - expect(button).toHaveClass('bg-state-base-hover') + expect(button)!.toHaveClass('bg-state-base-hover') }) }) }) @@ -317,6 +383,37 @@ describe('Dropdown', () => { const props = createDefaultProps({ breadcrumbs: ['folder'] }) render() + // Act & Assert - Initially closed + // Act & Assert - Initially closed + // Act & Assert - Initially closed + // Act & Assert - Initially closed + // Act & Assert - Initially closed + // Act & Assert - Initially closed + // Act & Assert - Initially closed + // Act & Assert - Initially closed + // Act & Assert - Initially closed + // Act & Assert - Initially closed + // Act & Assert - Initially closed + // Act & Assert - Initially closed + // Act & Assert - Initially closed + // Act & Assert - Initially closed + // Act & Assert - Initially closed + // Act & Assert - Initially closed + // Act & Assert - Initially closed + // Act & Assert - Initially closed + // Act & Assert - Initially closed + // Act & Assert - Initially closed + // Act & Assert - Initially closed + // Act & Assert - Initially closed + // Act & Assert - Initially closed + // Act & Assert - Initially closed + // Act & Assert - Initially closed + // Act & Assert - Initially closed + // Act & Assert - Initially closed + // Act & Assert - Initially closed + // Act & Assert - Initially closed + // Act & Assert - Initially closed + // Act & Assert - Initially closed // Act & Assert - Initially closed expect(screen.queryByText('folder')).not.toBeInTheDocument() @@ -325,7 +422,7 @@ describe('Dropdown', () => { // Assert - Now open await waitFor(() => { - expect(screen.getByText('folder')).toBeInTheDocument() + expect(screen.getByText('folder'))!.toBeInTheDocument() }) }) @@ -338,7 +435,7 @@ describe('Dropdown', () => { // 1st click - open fireEvent.click(button) await waitFor(() => { - expect(screen.getByText('folder')).toBeInTheDocument() + expect(screen.getByText('folder'))!.toBeInTheDocument() }) // 2nd click - close @@ -350,7 +447,7 @@ describe('Dropdown', () => { // 3rd click - open again fireEvent.click(button) await waitFor(() => { - expect(screen.getByText('folder')).toBeInTheDocument() + expect(screen.getByText('folder'))!.toBeInTheDocument() }) }) }) @@ -368,7 +465,7 @@ describe('Dropdown', () => { fireEvent.click(screen.getByRole('button')) await waitFor(() => { - expect(screen.getByText('folder1')).toBeInTheDocument() + expect(screen.getByText('folder1'))!.toBeInTheDocument() }) fireEvent.click(screen.getByText('folder1')) @@ -394,7 +491,7 @@ describe('Dropdown', () => { fireEvent.click(screen.getByRole('button')) await waitFor(() => { - expect(screen.getByText('folder1')).toBeInTheDocument() + expect(screen.getByText('folder1'))!.toBeInTheDocument() }) fireEvent.click(screen.getByText('folder1')) @@ -423,7 +520,7 @@ describe('Dropdown', () => { // Act - Open and click fireEvent.click(screen.getByRole('button')) await waitFor(() => { - expect(screen.getByText('folder')).toBeInTheDocument() + expect(screen.getByText('folder'))!.toBeInTheDocument() }) fireEvent.click(screen.getByText('folder')) @@ -431,7 +528,7 @@ describe('Dropdown', () => { rerender() fireEvent.click(screen.getByRole('button')) await waitFor(() => { - expect(screen.getByText('folder')).toBeInTheDocument() + expect(screen.getByText('folder'))!.toBeInTheDocument() }) fireEvent.click(screen.getByText('folder')) @@ -450,7 +547,7 @@ describe('Dropdown', () => { // Act - Open and click with first callback fireEvent.click(screen.getByRole('button')) await waitFor(() => { - expect(screen.getByText('folder')).toBeInTheDocument() + expect(screen.getByText('folder'))!.toBeInTheDocument() }) fireEvent.click(screen.getByText('folder')) @@ -466,7 +563,7 @@ describe('Dropdown', () => { // Open and click with second callback fireEvent.click(screen.getByRole('button')) await waitFor(() => { - expect(screen.getByText('folder')).toBeInTheDocument() + expect(screen.getByText('folder'))!.toBeInTheDocument() }) fireEvent.click(screen.getByText('folder')) @@ -482,7 +579,8 @@ describe('Dropdown', () => { rerender() // Assert - Component should render without errors - expect(screen.getByRole('button')).toBeInTheDocument() + // Assert - Component should render without errors + expect(screen.getByRole('button'))!.toBeInTheDocument() }) }) @@ -499,7 +597,7 @@ describe('Dropdown', () => { // Assert - Should handle gracefully (open after odd number of clicks) await waitFor(() => { - expect(screen.getByText('folder')).toBeInTheDocument() + expect(screen.getByText('folder'))!.toBeInTheDocument() }) }) @@ -513,7 +611,7 @@ describe('Dropdown', () => { fireEvent.click(screen.getByRole('button')) await waitFor(() => { - expect(screen.getByText(longName)).toBeInTheDocument() + expect(screen.getByText(longName))!.toBeInTheDocument() }) }) @@ -528,8 +626,8 @@ describe('Dropdown', () => { // Assert - First and last items should be visible await waitFor(() => { - expect(screen.getByText('folder-0')).toBeInTheDocument() - expect(screen.getByText('folder-19')).toBeInTheDocument() + expect(screen.getByText('folder-0'))!.toBeInTheDocument() + expect(screen.getByText('folder-19'))!.toBeInTheDocument() }) }) @@ -544,7 +642,7 @@ describe('Dropdown', () => { fireEvent.click(screen.getByRole('button')) await waitFor(() => { - expect(screen.getByText('folder')).toBeInTheDocument() + expect(screen.getByText('folder'))!.toBeInTheDocument() }) fireEvent.click(screen.getByText('folder')) @@ -562,7 +660,7 @@ describe('Dropdown', () => { fireEvent.click(screen.getByRole('button')) await waitFor(() => { - expect(screen.getByText('folder')).toBeInTheDocument() + expect(screen.getByText('folder'))!.toBeInTheDocument() }) fireEvent.click(screen.getByText('folder')) @@ -578,7 +676,7 @@ describe('Dropdown', () => { fireEvent.click(screen.getByRole('button')) await waitFor(() => { - expect(screen.getByText('normal-folder')).toBeInTheDocument() + expect(screen.getByText('normal-folder'))!.toBeInTheDocument() }) }) @@ -591,7 +689,7 @@ describe('Dropdown', () => { fireEvent.click(screen.getByRole('button')) await waitFor(() => { - expect(screen.getByText('folder')).toBeInTheDocument() + expect(screen.getByText('folder'))!.toBeInTheDocument() }) }) }) @@ -613,9 +711,9 @@ describe('Dropdown', () => { fireEvent.click(screen.getByRole('button')) await waitFor(() => { - expect(screen.getByText(breadcrumbs[0])).toBeInTheDocument() + expect(screen.getByText(breadcrumbs[0]!))!.toBeInTheDocument() }) - fireEvent.click(screen.getByText(breadcrumbs[0])) + fireEvent.click(screen.getByText(breadcrumbs[0]!)) expect(mockOnBreadcrumbClick).toHaveBeenCalledWith(expectedIndex) }) @@ -634,7 +732,7 @@ describe('Dropdown', () => { // Assert - Should render without errors await waitFor(() => { if (breadcrumbs.length > 0) - expect(screen.getByText(breadcrumbs[0])).toBeInTheDocument() + expect(screen.getByText(breadcrumbs[0]!))!.toBeInTheDocument() }) }) }) @@ -650,9 +748,9 @@ describe('Dropdown', () => { fireEvent.click(screen.getByRole('button')) await waitFor(() => { - expect(screen.getByText('Documents')).toBeInTheDocument() - expect(screen.getByText('Projects')).toBeInTheDocument() - expect(screen.getByText('Archive')).toBeInTheDocument() + expect(screen.getByText('Documents'))!.toBeInTheDocument() + expect(screen.getByText('Projects'))!.toBeInTheDocument() + expect(screen.getByText('Archive'))!.toBeInTheDocument() }) }) @@ -668,7 +766,7 @@ describe('Dropdown', () => { // Act - Open and click on second item fireEvent.click(screen.getByRole('button')) await waitFor(() => { - expect(screen.getByText('second')).toBeInTheDocument() + expect(screen.getByText('second'))!.toBeInTheDocument() }) fireEvent.click(screen.getByText('second')) @@ -687,7 +785,7 @@ describe('Dropdown', () => { // Act - Open and click on middle item fireEvent.click(screen.getByRole('button')) await waitFor(() => { - expect(screen.getByText('item2')).toBeInTheDocument() + expect(screen.getByText('item2'))!.toBeInTheDocument() }) fireEvent.click(screen.getByText('item2')) @@ -714,7 +812,7 @@ describe('Dropdown', () => { fireEvent.click(screen.getByRole('button')) await waitFor(() => { - expect(screen.getByText(`folder-${String.fromCharCode(97 + i)}`)).toBeInTheDocument() + expect(screen.getByText(`folder-${String.fromCharCode(97 + i)}`))!.toBeInTheDocument() }) fireEvent.click(screen.getByText(`folder-${String.fromCharCode(97 + i)}`)) @@ -731,7 +829,7 @@ describe('Dropdown', () => { render() const button = screen.getByRole('button') - expect(button).toBeInTheDocument() + expect(button)!.toBeInTheDocument() expect(button.tagName).toBe('BUTTON') }) @@ -741,7 +839,7 @@ describe('Dropdown', () => { render() const button = screen.getByRole('button') - expect(button).toHaveAttribute('type', 'button') + expect(button)!.toHaveAttribute('type', 'button') }) }) }) diff --git a/web/app/components/datasets/documents/create-from-pipeline/data-source/online-drive/file-list/header/breadcrumbs/index.tsx b/web/app/components/datasets/documents/create-from-pipeline/data-source/online-drive/file-list/header/breadcrumbs/index.tsx index 714b393d03..91d3acc1d1 100644 --- a/web/app/components/datasets/documents/create-from-pipeline/data-source/online-drive/file-list/header/breadcrumbs/index.tsx +++ b/web/app/components/datasets/documents/create-from-pipeline/data-source/online-drive/file-list/header/breadcrumbs/index.tsx @@ -152,7 +152,7 @@ const Breadcrumbs = ({ { const { setNextPageParameters, currentNextPageParametersRef, isTruncated } = dataSourceStore.getState() - if (entries[0].isIntersecting && isTruncated.current && !isLoading) + if (entries[0]!.isIntersecting && isTruncated.current && !isLoading) setNextPageParameters(currentNextPageParametersRef.current) }, { rootMargin: '100px', diff --git a/web/app/components/datasets/documents/create-from-pipeline/data-source/online-drive/file-list/list/utils.ts b/web/app/components/datasets/documents/create-from-pipeline/data-source/online-drive/file-list/list/utils.ts index 6b367ebe3c..07b23a56ff 100644 --- a/web/app/components/datasets/documents/create-from-pipeline/data-source/online-drive/file-list/list/utils.ts +++ b/web/app/components/datasets/documents/create-from-pipeline/data-source/online-drive/file-list/list/utils.ts @@ -8,7 +8,7 @@ export const getFileExtension = (fileName: string): string => { if (parts.length <= 1 || (parts[0] === '' && parts.length === 2)) return '' - return parts[parts.length - 1].toLowerCase() + return parts[parts.length - 1]!.toLowerCase() } export const getFileType = (fileName: string) => { @@ -17,13 +17,13 @@ export const getFileType = (fileName: string) => { if (extension === 'gif') return FileAppearanceTypeEnum.gif - if (FILE_EXTS.image.includes(extension.toUpperCase())) + if (FILE_EXTS.image!.includes(extension.toUpperCase())) return FileAppearanceTypeEnum.image - if (FILE_EXTS.video.includes(extension.toUpperCase())) + if (FILE_EXTS.video!.includes(extension.toUpperCase())) return FileAppearanceTypeEnum.video - if (FILE_EXTS.audio.includes(extension.toUpperCase())) + if (FILE_EXTS.audio!.includes(extension.toUpperCase())) return FileAppearanceTypeEnum.audio if (extension === 'html' || extension === 'htm' || extension === 'xml' || extension === 'json') @@ -44,7 +44,7 @@ export const getFileType = (fileName: string) => { if (extension === 'pptx' || extension === 'ppt') return FileAppearanceTypeEnum.ppt - if (FILE_EXTS.document.includes(extension.toUpperCase())) + if (FILE_EXTS.document!.includes(extension.toUpperCase())) return FileAppearanceTypeEnum.document return FileAppearanceTypeEnum.custom diff --git a/web/app/components/datasets/documents/create-from-pipeline/data-source/online-drive/utils.ts b/web/app/components/datasets/documents/create-from-pipeline/data-source/online-drive/utils.ts index 89b84069fe..8f0ff13ac5 100644 --- a/web/app/components/datasets/documents/create-from-pipeline/data-source/online-drive/utils.ts +++ b/web/app/components/datasets/documents/create-from-pipeline/data-source/online-drive/utils.ts @@ -10,7 +10,7 @@ export const isBucketListInitiation = (data: OnlineDriveData[], prefix: string[] if (bucket || prefix.length > 0) return false const hasBucket = data.every(item => !!item.bucket) - return hasBucket && (data.length > 1 || (data.length === 1 && !!data[0].bucket && data[0].files.length === 0)) + return hasBucket && (data.length > 1 || (data.length === 1 && !!data[0]!.bucket && data[0]!.files.length === 0)) } export const convertOnlineDriveData = (data: OnlineDriveData[], prefix: string[], bucket: string): { @@ -38,7 +38,7 @@ export const convertOnlineDriveData = (data: OnlineDriveData[], prefix: string[] hasBucket = true } else { - data[0].files.forEach((file) => { + data[0]!.files.forEach((file) => { const { id, name, size, type } = file const isFileType = isFile(type) fileList.push({ @@ -48,9 +48,9 @@ export const convertOnlineDriveData = (data: OnlineDriveData[], prefix: string[] type: isFileType ? OnlineDriveFileType.file : OnlineDriveFileType.folder, }) }) - isTruncated = data[0].is_truncated ?? false - nextPageParameters = data[0].next_page_parameters ?? {} - hasBucket = !!data[0].bucket + isTruncated = data[0]!.is_truncated ?? false + nextPageParameters = data[0]!.next_page_parameters ?? {} + hasBucket = !!data[0]!.bucket } return { fileList, isTruncated, nextPageParameters, hasBucket } } diff --git a/web/app/components/datasets/documents/create-from-pipeline/data-source/website-crawl/base/__tests__/crawled-result.spec.tsx b/web/app/components/datasets/documents/create-from-pipeline/data-source/website-crawl/base/__tests__/crawled-result.spec.tsx index 9c71f91d8d..6c476e6dd6 100644 --- a/web/app/components/datasets/documents/create-from-pipeline/data-source/website-crawl/base/__tests__/crawled-result.spec.tsx +++ b/web/app/components/datasets/documents/create-from-pipeline/data-source/website-crawl/base/__tests__/crawled-result.spec.tsx @@ -49,9 +49,9 @@ const createItem = (url: string): CrawlResultItem => ({ }) const defaultList: CrawlResultItem[] = [ - createItem('https://example.com/a'), - createItem('https://example.com/b'), - createItem('https://example.com/c'), + createItem('https://example.com/a')!, + createItem('https://example.com/b')!, + createItem('https://example.com/c')!, ] describe('CrawledResult', () => { @@ -70,19 +70,18 @@ describe('CrawledResult', () => { it('should render scrap time info with correct total and time', () => { render() - expect( - screen.getByText(/scrapTimeInfo/), - ).toBeInTheDocument() + expect(screen.getByText(/scrapTimeInfo/))!.toBeInTheDocument() // The global i18n mock serialises params, so verify total and time appear - expect(screen.getByText(/"total":3/)).toBeInTheDocument() - expect(screen.getByText(/"time":"12.3"/)).toBeInTheDocument() + // The global i18n mock serialises params, so verify total and time appear + expect(screen.getByText(/"total":3/))!.toBeInTheDocument() + expect(screen.getByText(/"time":"12.3"/))!.toBeInTheDocument() }) it('should render all items from list', () => { render() for (const item of defaultList) { - expect(screen.getByTestId(`crawled-item-${item.source_url}`)).toBeInTheDocument() + expect(screen.getByTestId(`crawled-item-${item.source_url}`))!.toBeInTheDocument() } }) @@ -91,7 +90,7 @@ describe('CrawledResult', () => { , ) - expect(container.firstChild).toHaveClass('my-custom-class') + expect(container.firstChild)!.toHaveClass('my-custom-class') }) }) @@ -100,7 +99,7 @@ describe('CrawledResult', () => { it('should show check-all checkbox in multiple choice mode', () => { render() - expect(screen.getByTestId('check-all-checkbox')).toBeInTheDocument() + expect(screen.getByTestId('check-all-checkbox'))!.toBeInTheDocument() }) it('should hide check-all checkbox in single choice mode', () => { @@ -117,7 +116,7 @@ describe('CrawledResult', () => { render( , ) @@ -150,13 +149,13 @@ describe('CrawledResult', () => { render( , ) - fireEvent.click(screen.getByTestId(`check-${defaultList[1].source_url}`)) + fireEvent.click(screen.getByTestId(`check-${defaultList[1]!.source_url}`)) expect(onSelectedChange).toHaveBeenCalledWith([defaultList[0], defaultList[1]]) }) @@ -166,13 +165,13 @@ describe('CrawledResult', () => { render( , ) - fireEvent.click(screen.getByTestId(`check-${defaultList[1].source_url}`)) + fireEvent.click(screen.getByTestId(`check-${defaultList[1]!.source_url}`)) expect(onSelectedChange).toHaveBeenCalledWith([defaultList[1]]) }) @@ -182,13 +181,13 @@ describe('CrawledResult', () => { render( , ) - fireEvent.click(screen.getByTestId(`check-${defaultList[0].source_url}`)) + fireEvent.click(screen.getByTestId(`check-${defaultList[0]!.source_url}`)) expect(onSelectedChange).toHaveBeenCalledWith([defaultList[1]]) }) @@ -206,7 +205,7 @@ describe('CrawledResult', () => { />, ) - fireEvent.click(screen.getByTestId(`preview-${defaultList[1].source_url}`)) + fireEvent.click(screen.getByTestId(`preview-${defaultList[1]!.source_url}`)) expect(onPreview).toHaveBeenCalledWith(defaultList[1], 1) }) diff --git a/web/app/components/datasets/documents/create-from-pipeline/data-source/website-crawl/base/__tests__/index.spec.tsx b/web/app/components/datasets/documents/create-from-pipeline/data-source/website-crawl/base/__tests__/index.spec.tsx index 99002e687c..fa5633e2df 100644 --- a/web/app/components/datasets/documents/create-from-pipeline/data-source/website-crawl/base/__tests__/index.spec.tsx +++ b/web/app/components/datasets/documents/create-from-pipeline/data-source/website-crawl/base/__tests__/index.spec.tsx @@ -39,7 +39,7 @@ describe('CheckboxWithLabel', () => { it('should render without crashing', () => { render() - expect(screen.getByText('Test Label')).toBeInTheDocument() + expect(screen.getByText('Test Label'))!.toBeInTheDocument() }) it('should render checkbox in unchecked state', () => { @@ -47,7 +47,7 @@ describe('CheckboxWithLabel', () => { // Assert - Custom checkbox component uses div with data-testid const checkbox = container.querySelector('[data-testid^="checkbox"]') - expect(checkbox).toBeInTheDocument() + expect(checkbox)!.toBeInTheDocument() expect(checkbox).not.toHaveClass('bg-components-checkbox-bg') }) @@ -56,7 +56,7 @@ describe('CheckboxWithLabel', () => { // Assert - Checked state has check icon const checkIcon = container.querySelector('[data-testid^="check-icon"]') - expect(checkIcon).toBeInTheDocument() + expect(checkIcon)!.toBeInTheDocument() }) it('should render tooltip when provided', () => { @@ -64,7 +64,7 @@ describe('CheckboxWithLabel', () => { // Assert - Tooltip trigger should be present const tooltipTrigger = document.querySelector('[class*="ml-0.5"]') - expect(tooltipTrigger).toBeInTheDocument() + expect(tooltipTrigger)!.toBeInTheDocument() }) it('should not render tooltip when not provided', () => { @@ -82,14 +82,14 @@ describe('CheckboxWithLabel', () => { ) const label = container.querySelector('label') - expect(label).toHaveClass('custom-class') + expect(label)!.toHaveClass('custom-class') }) it('should apply custom labelClassName', () => { render() const labelText = screen.getByText('Test Label') - expect(labelText).toHaveClass('custom-label-class') + expect(labelText)!.toHaveClass('custom-label-class') }) }) @@ -147,8 +147,8 @@ describe('CrawledResultItem', () => { it('should render without crashing', () => { render() - expect(screen.getByText('Test Page Title')).toBeInTheDocument() - expect(screen.getByText('https://example.com/page1')).toBeInTheDocument() + expect(screen.getByText('Test Page Title'))!.toBeInTheDocument() + expect(screen.getByText('https://example.com/page1'))!.toBeInTheDocument() }) it('should render checkbox when isMultipleChoice is true', () => { @@ -156,7 +156,7 @@ describe('CrawledResultItem', () => { // Assert - Custom checkbox uses data-testid const checkbox = container.querySelector('[data-testid^="checkbox"]') - expect(checkbox).toBeInTheDocument() + expect(checkbox)!.toBeInTheDocument() }) it('should render radio when isMultipleChoice is false', () => { @@ -164,7 +164,7 @@ describe('CrawledResultItem', () => { // Assert - Radio component has size-4 rounded-full classes const radio = container.querySelector('.size-4.rounded-full') - expect(radio).toBeInTheDocument() + expect(radio)!.toBeInTheDocument() }) it('should render checkbox as checked when isChecked is true', () => { @@ -172,13 +172,13 @@ describe('CrawledResultItem', () => { // Assert - Checked state shows check icon const checkIcon = container.querySelector('[data-testid^="check-icon"]') - expect(checkIcon).toBeInTheDocument() + expect(checkIcon)!.toBeInTheDocument() }) it('should render preview button when showPreview is true', () => { render() - expect(screen.getByRole('button')).toBeInTheDocument() + expect(screen.getByRole('button'))!.toBeInTheDocument() }) it('should not render preview button when showPreview is false', () => { @@ -191,15 +191,15 @@ describe('CrawledResultItem', () => { const { container } = render() const item = container.firstChild - expect(item).toHaveClass('bg-state-base-active') + expect(item)!.toHaveClass('bg-state-base-active') }) it('should apply hover styles when isPreview is false', () => { const { container } = render() const item = container.firstChild - expect(item).toHaveClass('group') - expect(item).toHaveClass('hover:bg-state-base-hover') + expect(item)!.toHaveClass('group') + expect(item)!.toHaveClass('hover:bg-state-base-hover') }) }) @@ -209,7 +209,7 @@ describe('CrawledResultItem', () => { render() - expect(screen.getByText('Custom Title')).toBeInTheDocument() + expect(screen.getByText('Custom Title'))!.toBeInTheDocument() }) it('should display payload source_url', () => { @@ -217,7 +217,7 @@ describe('CrawledResultItem', () => { render() - expect(screen.getByText('https://custom.url/path')).toBeInTheDocument() + expect(screen.getByText('https://custom.url/path'))!.toBeInTheDocument() }) it('should set title attribute for truncation tooltip', () => { @@ -226,7 +226,7 @@ describe('CrawledResultItem', () => { render() const titleElement = screen.getByText('Very Long Title') - expect(titleElement).toHaveAttribute('title', 'Very Long Title') + expect(titleElement)!.toHaveAttribute('title', 'Very Long Title') }) }) @@ -310,22 +310,24 @@ describe('CrawledResult', () => { render() // Assert - Check for time info which contains total count - expect(screen.getByText(/1.5/)).toBeInTheDocument() + // Assert - Check for time info which contains total count + expect(screen.getByText(/1.5/))!.toBeInTheDocument() }) it('should render all list items', () => { render() - expect(screen.getByText('Page 1')).toBeInTheDocument() - expect(screen.getByText('Page 2')).toBeInTheDocument() - expect(screen.getByText('Page 3')).toBeInTheDocument() + expect(screen.getByText('Page 1'))!.toBeInTheDocument() + expect(screen.getByText('Page 2'))!.toBeInTheDocument() + expect(screen.getByText('Page 3'))!.toBeInTheDocument() }) it('should display scrape time info', () => { render() // Assert - Check for the time display - expect(screen.getByText(/2.5/)).toBeInTheDocument() + // Assert - Check for the time display + expect(screen.getByText(/2.5/))!.toBeInTheDocument() }) it('should render select all checkbox when isMultipleChoice is true', () => { @@ -350,7 +352,7 @@ describe('CrawledResult', () => { it('should show "Select All" when not all items are checked', () => { render() - expect(screen.getByText(/selectAll|Select All/i)).toBeInTheDocument() + expect(screen.getByText(/selectAll|Select All/i))!.toBeInTheDocument() }) it('should show "Reset All" when all items are checked', () => { @@ -358,7 +360,7 @@ describe('CrawledResult', () => { render() - expect(screen.getByText(/resetAll|Reset All/i)).toBeInTheDocument() + expect(screen.getByText(/resetAll|Reset All/i))!.toBeInTheDocument() }) }) @@ -368,7 +370,7 @@ describe('CrawledResult', () => { , ) - expect(container.firstChild).toHaveClass('custom-class') + expect(container.firstChild)!.toHaveClass('custom-class') }) it('should highlight item at previewIndex', () => { @@ -378,7 +380,7 @@ describe('CrawledResult', () => { // Assert - Second item should have active state const items = container.querySelectorAll('[class*="rounded-lg"][class*="cursor-pointer"]') - expect(items[1]).toHaveClass('bg-state-base-active') + expect(items[1])!.toHaveClass('bg-state-base-active') }) it('should pass showPreview to items', () => { @@ -411,7 +413,7 @@ describe('CrawledResult', () => { // Act - Click select all checkbox (first checkbox) const checkboxes = container.querySelectorAll('[data-testid^="checkbox"]') - fireEvent.click(checkboxes[0]) + fireEvent.click(checkboxes[0]!) expect(mockOnSelectedChange).toHaveBeenCalledWith(list) }) @@ -429,7 +431,7 @@ describe('CrawledResult', () => { ) const checkboxes = container.querySelectorAll('[data-testid^="checkbox"]') - fireEvent.click(checkboxes[0]) + fireEvent.click(checkboxes[0]!) expect(mockOnSelectedChange).toHaveBeenCalledWith([]) }) @@ -441,14 +443,14 @@ describe('CrawledResult', () => { , ) // Act - Click second item checkbox (index 2, accounting for select all) const checkboxes = container.querySelectorAll('[data-testid^="checkbox"]') - fireEvent.click(checkboxes[2]) + fireEvent.click(checkboxes[2]!) expect(mockOnSelectedChange).toHaveBeenCalledWith([list[0], list[1]]) }) @@ -460,14 +462,14 @@ describe('CrawledResult', () => { , ) // Act - Uncheck first item (index 1, after select all) const checkboxes = container.querySelectorAll('[data-testid^="checkbox"]') - fireEvent.click(checkboxes[1]) + fireEvent.click(checkboxes[1]!) expect(mockOnSelectedChange).toHaveBeenCalledWith([list[1]]) }) @@ -479,7 +481,7 @@ describe('CrawledResult', () => { , @@ -487,7 +489,7 @@ describe('CrawledResult', () => { // Act - Click second item radio (Radio uses size-4 rounded-full classes) const radios = container.querySelectorAll('.size-4.rounded-full') - fireEvent.click(radios[1]) + fireEvent.click(radios[1]!) // Assert - Should only select the clicked item expect(mockOnSelectedChange).toHaveBeenCalledWith([list[1]]) @@ -506,7 +508,7 @@ describe('CrawledResult', () => { ) const buttons = screen.getAllByRole('button') - fireEvent.click(buttons[1]) // Second item's preview button + fireEvent.click(buttons[1]!) // Second item's preview button expect(mockOnPreview).toHaveBeenCalledWith(list[1], 1) }) @@ -525,10 +527,11 @@ describe('CrawledResult', () => { // Act - Click preview button should trigger early return in handlePreview const buttons = screen.getAllByRole('button') - fireEvent.click(buttons[0]) + fireEvent.click(buttons[0]!) // Assert - Should not throw error, component still renders - expect(screen.getByText('Page 1')).toBeInTheDocument() + // Assert - Should not throw error, component still renders + expect(screen.getByText('Page 1'))!.toBeInTheDocument() }) }) @@ -537,7 +540,8 @@ describe('CrawledResult', () => { render() // Assert - Should show time info with 0 count - expect(screen.getByText(/0.5/)).toBeInTheDocument() + // Assert - Should show time info with 0 count + expect(screen.getByText(/0.5/))!.toBeInTheDocument() }) it('should handle single item list', () => { @@ -545,13 +549,13 @@ describe('CrawledResult', () => { render() - expect(screen.getByText('Test Page Title')).toBeInTheDocument() + expect(screen.getByText('Test Page Title'))!.toBeInTheDocument() }) it('should format usedTime to one decimal place', () => { render() - expect(screen.getByText(/1.6/)).toBeInTheDocument() + expect(screen.getByText(/1.6/))!.toBeInTheDocument() }) }) }) @@ -571,13 +575,13 @@ describe('Crawling', () => { it('should render without crashing', () => { render() - expect(screen.getByText(/5\/10/)).toBeInTheDocument() + expect(screen.getByText(/5\/10/))!.toBeInTheDocument() }) it('should display crawled count and total', () => { render() - expect(screen.getByText(/3\/15/)).toBeInTheDocument() + expect(screen.getByText(/3\/15/))!.toBeInTheDocument() }) it('should render skeleton items', () => { @@ -602,19 +606,19 @@ describe('Crawling', () => { , ) - expect(container.firstChild).toHaveClass('custom-crawling-class') + expect(container.firstChild)!.toHaveClass('custom-crawling-class') }) it('should handle zero values', () => { render() - expect(screen.getByText(/0\/0/)).toBeInTheDocument() + expect(screen.getByText(/0\/0/))!.toBeInTheDocument() }) it('should handle large numbers', () => { render() - expect(screen.getByText(/999\/1000/)).toBeInTheDocument() + expect(screen.getByText(/999\/1000/))!.toBeInTheDocument() }) }) @@ -623,9 +627,10 @@ describe('Crawling', () => { const { container } = render() // Assert - Check for various width classes - expect(container.querySelector('.w-\\[35\\%\\]')).toBeInTheDocument() - expect(container.querySelector('.w-\\[50\\%\\]')).toBeInTheDocument() - expect(container.querySelector('.w-\\[40\\%\\]')).toBeInTheDocument() + // Assert - Check for various width classes + expect(container.querySelector('.w-\\[35\\%\\]'))!.toBeInTheDocument() + expect(container.querySelector('.w-\\[50\\%\\]'))!.toBeInTheDocument() + expect(container.querySelector('.w-\\[40\\%\\]'))!.toBeInTheDocument() }) }) }) @@ -644,27 +649,27 @@ describe('ErrorMessage', () => { it('should render without crashing', () => { render() - expect(screen.getByText('Error Title')).toBeInTheDocument() + expect(screen.getByText('Error Title'))!.toBeInTheDocument() }) it('should render error icon', () => { const { container } = render() const icon = container.querySelector('svg') - expect(icon).toBeInTheDocument() - expect(icon).toHaveClass('text-text-destructive') + expect(icon)!.toBeInTheDocument() + expect(icon)!.toHaveClass('text-text-destructive') }) it('should render title', () => { render() - expect(screen.getByText('Custom Error Title')).toBeInTheDocument() + expect(screen.getByText('Custom Error Title'))!.toBeInTheDocument() }) it('should render error message when provided', () => { render() - expect(screen.getByText('Detailed error description')).toBeInTheDocument() + expect(screen.getByText('Detailed error description'))!.toBeInTheDocument() }) it('should not render error message when not provided', () => { @@ -682,14 +687,15 @@ describe('ErrorMessage', () => { , ) - expect(container.firstChild).toHaveClass('custom-error-class') + expect(container.firstChild)!.toHaveClass('custom-error-class') }) it('should render with empty errorMsg', () => { render() // Assert - Empty string should not render message div - expect(screen.getByText('Error Title')).toBeInTheDocument() + // Assert - Empty string should not render message div + expect(screen.getByText('Error Title'))!.toBeInTheDocument() }) it('should handle long title text', () => { @@ -697,7 +703,7 @@ describe('ErrorMessage', () => { render() - expect(screen.getByText(longTitle)).toBeInTheDocument() + expect(screen.getByText(longTitle))!.toBeInTheDocument() }) it('should handle long error message', () => { @@ -705,7 +711,7 @@ describe('ErrorMessage', () => { render() - expect(screen.getByText(longErrorMsg)).toBeInTheDocument() + expect(screen.getByText(longErrorMsg))!.toBeInTheDocument() }) }) @@ -713,19 +719,19 @@ describe('ErrorMessage', () => { it('should have error background styling', () => { const { container } = render() - expect(container.firstChild).toHaveClass('bg-toast-error-bg') + expect(container.firstChild)!.toHaveClass('bg-toast-error-bg') }) it('should have border styling', () => { const { container } = render() - expect(container.firstChild).toHaveClass('border-components-panel-border') + expect(container.firstChild)!.toHaveClass('border-components-panel-border') }) it('should have rounded-sm corners', () => { const { container } = render() - expect(container.firstChild).toHaveClass('rounded-xl') + expect(container.firstChild)!.toHaveClass('rounded-xl') }) }) }) @@ -744,8 +750,9 @@ describe('Base Components Integration', () => { ) // Assert - Both items should render - expect(screen.getByText('Page 1')).toBeInTheDocument() - expect(screen.getByText('Page 2')).toBeInTheDocument() + // Assert - Both items should render + expect(screen.getByText('Page 1'))!.toBeInTheDocument() + expect(screen.getByText('Page 2'))!.toBeInTheDocument() }) it('should render CrawledResult with CheckboxWithLabel for select all', () => { @@ -784,13 +791,13 @@ describe('Base Components Integration', () => { // Act - Select first item (index 1, after select all) const checkboxes = container.querySelectorAll('[data-testid^="checkbox"]') - fireEvent.click(checkboxes[1]) + fireEvent.click(checkboxes[1]!) expect(mockOnSelectedChange).toHaveBeenCalledWith([list[0]]) // Act - Preview second item const previewButtons = screen.getAllByRole('button') - fireEvent.click(previewButtons[1]) + fireEvent.click(previewButtons[1]!) expect(mockOnPreview).toHaveBeenCalledWith(list[1], 1) }) diff --git a/web/app/components/datasets/documents/create-from-pipeline/data-source/website-crawl/base/crawled-result.tsx b/web/app/components/datasets/documents/create-from-pipeline/data-source/website-crawl/base/crawled-result.tsx index 8cd9a46054..b91c5bd6bc 100644 --- a/web/app/components/datasets/documents/create-from-pipeline/data-source/website-crawl/base/crawled-result.tsx +++ b/web/app/components/datasets/documents/create-from-pipeline/data-source/website-crawl/base/crawled-result.tsx @@ -59,7 +59,7 @@ const CrawledResult = ({ const handlePreview = useCallback((index: number) => { if (!onPreview) return - onPreview(list[index], index) + onPreview(list[index]!, index) }, [list, onPreview]) return ( diff --git a/web/app/components/datasets/documents/create-from-pipeline/data-source/website-crawl/base/options/index.tsx b/web/app/components/datasets/documents/create-from-pipeline/data-source/website-crawl/base/options/index.tsx index 899c70e216..c8a06ea807 100644 --- a/web/app/components/datasets/documents/create-from-pipeline/data-source/website-crawl/base/options/index.tsx +++ b/web/app/components/datasets/documents/create-from-pipeline/data-source/website-crawl/base/options/index.tsx @@ -43,7 +43,7 @@ const Options = ({ if (!result.success) { const issues = result.error.issues const firstIssue = issues[0] - const errorMessage = `"${firstIssue.path.join('.')}" ${firstIssue.message}` + const errorMessage = `"${firstIssue!.path.join('.')}" ${firstIssue!.message}` toast.error(errorMessage) return errorMessage } diff --git a/web/app/components/datasets/documents/create-from-pipeline/hooks/__tests__/use-datasource-store.spec.ts b/web/app/components/datasets/documents/create-from-pipeline/hooks/__tests__/use-datasource-store.spec.ts index 155b41541b..70d95000d7 100644 --- a/web/app/components/datasets/documents/create-from-pipeline/hooks/__tests__/use-datasource-store.spec.ts +++ b/web/app/components/datasets/documents/create-from-pipeline/hooks/__tests__/use-datasource-store.spec.ts @@ -85,7 +85,7 @@ describe('useOnlineDocument', () => { const { result } = renderHook(() => useOnlineDocument(), { wrapper: createWrapper(store) }) expect(result.current.PagesMapAndSelectedPagesId).toHaveProperty('p1') - expect(result.current.PagesMapAndSelectedPagesId.p1.workspace_id).toBe('w1') + expect(result.current.PagesMapAndSelectedPagesId.p1!.workspace_id).toBe('w1') }) it('should hide preview online document', () => { diff --git a/web/app/components/datasets/documents/create-from-pipeline/hooks/use-datasource-actions.ts b/web/app/components/datasets/documents/create-from-pipeline/hooks/use-datasource-actions.ts index 66bd325c33..bad3b779fa 100644 --- a/web/app/components/datasets/documents/create-from-pipeline/hooks/use-datasource-actions.ts +++ b/web/app/components/datasets/documents/create-from-pipeline/hooks/use-datasource-actions.ts @@ -251,7 +251,7 @@ export const useDatasourceActions = ({ if (datasourceType === DatasourceType.onlineDocument) { const allIds = currentWorkspacePages?.map(page => page.page_id) || [] if (onlineDocuments.length < allIds.length) { - const selectedPages = Array.from(allIds).map(pageId => PagesMapAndSelectedPagesId[pageId]) + const selectedPages = Array.from(allIds).map(pageId => PagesMapAndSelectedPagesId[pageId]!) setOnlineDocuments(selectedPages) setSelectedPagesId(new Set(allIds)) } diff --git a/web/app/components/datasets/documents/create-from-pipeline/hooks/use-datasource-ui-state.ts b/web/app/components/datasets/documents/create-from-pipeline/hooks/use-datasource-ui-state.ts index e398f90a48..f4c222f652 100644 --- a/web/app/components/datasets/documents/create-from-pipeline/hooks/use-datasource-ui-state.ts +++ b/web/app/components/datasets/documents/create-from-pipeline/hooks/use-datasource-ui-state.ts @@ -122,7 +122,7 @@ export const useDatasourceUIState = ({ return { datasourceType, - isShowVectorSpaceFull, + isShowVectorSpaceFull: isShowVectorSpaceFull!, nextBtnDisabled, showSelect, totalOptions, diff --git a/web/app/components/datasets/documents/create-from-pipeline/index.tsx b/web/app/components/datasets/documents/create-from-pipeline/index.tsx index 62c1b919fe..8b8fad5885 100644 --- a/web/app/components/datasets/documents/create-from-pipeline/index.tsx +++ b/web/app/components/datasets/documents/create-from-pipeline/index.tsx @@ -133,7 +133,7 @@ const CreateFormPipeline = () => { [DatasourceType.onlineDrive]: selectedFileIds.length, } const count = datasourceType ? multipleCheckMap[datasourceType] : 0 - if (count > 1) { + if (count! > 1) { showPlanUpgradeModal() return } diff --git a/web/app/components/datasets/documents/create-from-pipeline/preview/__tests__/file-preview.spec.tsx b/web/app/components/datasets/documents/create-from-pipeline/preview/__tests__/file-preview.spec.tsx index 715d1650df..82011102b6 100644 --- a/web/app/components/datasets/documents/create-from-pipeline/preview/__tests__/file-preview.spec.tsx +++ b/web/app/components/datasets/documents/create-from-pipeline/preview/__tests__/file-preview.spec.tsx @@ -39,30 +39,30 @@ describe('FilePreview', () => { it('should render preview label', () => { render() - expect(screen.getByText('datasetPipeline.addDocuments.stepOne.preview')).toBeInTheDocument() + expect(screen.getByText('datasetPipeline.addDocuments.stepOne.preview'))!.toBeInTheDocument() }) it('should render file name', () => { render() - expect(screen.getByText('document.pdf')).toBeInTheDocument() + expect(screen.getByText('document.pdf'))!.toBeInTheDocument() }) it('should render file content when loaded', () => { render() - expect(screen.getByText('file content here with some text')).toBeInTheDocument() + expect(screen.getByText('file content here with some text'))!.toBeInTheDocument() }) it('should render loading state', () => { mockIsFetching = true render() - expect(screen.getByTestId('loading')).toBeInTheDocument() + expect(screen.getByTestId('loading'))!.toBeInTheDocument() }) it('should call hidePreview when close button clicked', () => { render() const buttons = screen.getAllByRole('button') const closeBtn = buttons[buttons.length - 1] - fireEvent.click(closeBtn) + fireEvent.click(closeBtn!) expect(defaultProps.hidePreview).toHaveBeenCalled() }) }) diff --git a/web/app/components/datasets/documents/create-from-pipeline/preview/__tests__/web-preview.spec.tsx b/web/app/components/datasets/documents/create-from-pipeline/preview/__tests__/web-preview.spec.tsx index 1f59e11035..7bef4d0716 100644 --- a/web/app/components/datasets/documents/create-from-pipeline/preview/__tests__/web-preview.spec.tsx +++ b/web/app/components/datasets/documents/create-from-pipeline/preview/__tests__/web-preview.spec.tsx @@ -20,29 +20,29 @@ describe('WebPreview', () => { it('should render preview label', () => { render() - expect(screen.getByText('datasetPipeline.addDocuments.stepOne.preview')).toBeInTheDocument() + expect(screen.getByText('datasetPipeline.addDocuments.stepOne.preview'))!.toBeInTheDocument() }) it('should render page title', () => { render() - expect(screen.getByText('Test Page')).toBeInTheDocument() + expect(screen.getByText('Test Page'))!.toBeInTheDocument() }) it('should render source URL', () => { render() - expect(screen.getByText('https://example.com')).toBeInTheDocument() + expect(screen.getByText('https://example.com'))!.toBeInTheDocument() }) it('should render markdown content', () => { render() - expect(screen.getByText('Hello **markdown** content')).toBeInTheDocument() + expect(screen.getByText('Hello **markdown** content'))!.toBeInTheDocument() }) it('should call hidePreview when close button clicked', () => { render() const buttons = screen.getAllByRole('button') const closeBtn = buttons[buttons.length - 1] - fireEvent.click(closeBtn) + fireEvent.click(closeBtn!) expect(defaultProps.hidePreview).toHaveBeenCalled() }) }) diff --git a/web/app/components/datasets/documents/create-from-pipeline/preview/chunk-preview.tsx b/web/app/components/datasets/documents/create-from-pipeline/preview/chunk-preview.tsx index a56e5bd6dc..2d729ee079 100644 --- a/web/app/components/datasets/documents/create-from-pipeline/preview/chunk-preview.tsx +++ b/web/app/components/datasets/documents/create-from-pipeline/preview/chunk-preview.tsx @@ -55,9 +55,9 @@ const ChunkPreview = ({ const currentDocForm = useDatasetDetailContextWithSelector(s => s.dataset?.doc_form) const [previewFile, setPreviewFile] = useState(localFiles[0] as DocumentItem) - const [previewOnlineDocument, setPreviewOnlineDocument] = useState(onlineDocuments[0]) - const [previewWebsitePage, setPreviewWebsitePage] = useState(websitePages[0]) - const [previewOnlineDriveFile, setPreviewOnlineDriveFile] = useState(onlineDriveFiles[0]) + const [previewOnlineDocument, setPreviewOnlineDocument] = useState(onlineDocuments[0]!) + const [previewWebsitePage, setPreviewWebsitePage] = useState(websitePages[0]!) + const [previewOnlineDriveFile, setPreviewOnlineDriveFile] = useState(onlineDriveFiles[0]!) return ( { diff --git a/web/app/components/datasets/documents/create-from-pipeline/steps/__tests__/step-three-content.spec.tsx b/web/app/components/datasets/documents/create-from-pipeline/steps/__tests__/step-three-content.spec.tsx index e217248d2b..8e80ab2878 100644 --- a/web/app/components/datasets/documents/create-from-pipeline/steps/__tests__/step-three-content.spec.tsx +++ b/web/app/components/datasets/documents/create-from-pipeline/steps/__tests__/step-three-content.spec.tsx @@ -56,42 +56,42 @@ describe('StepThreeContent', () => { describe('Rendering', () => { it('should render without crashing', () => { render() - expect(screen.getByTestId('embedding-process')).toBeInTheDocument() + expect(screen.getByTestId('embedding-process'))!.toBeInTheDocument() }) it('should render Processing component', () => { render() - expect(screen.getByTestId('embedding-process')).toBeInTheDocument() + expect(screen.getByTestId('embedding-process'))!.toBeInTheDocument() }) }) describe('Props', () => { it('should pass batchId to Processing component', () => { render() - expect(screen.getByTestId('batch-id')).toHaveTextContent('test-batch-id') + expect(screen.getByTestId('batch-id'))!.toHaveTextContent('test-batch-id') }) it('should pass documents to Processing component', () => { render() - expect(screen.getByTestId('documents-count')).toHaveTextContent('2') + expect(screen.getByTestId('documents-count'))!.toHaveTextContent('2') }) it('should handle empty documents array', () => { render() - expect(screen.getByTestId('documents-count')).toHaveTextContent('0') + expect(screen.getByTestId('documents-count'))!.toHaveTextContent('0') }) }) describe('Edge Cases', () => { it('should render with different batchId', () => { render() - expect(screen.getByTestId('batch-id')).toHaveTextContent('another-batch-id') + expect(screen.getByTestId('batch-id'))!.toHaveTextContent('another-batch-id') }) it('should render with single document', () => { - const singleDocument = [mockDocuments[0]] + const singleDocument = [mockDocuments[0]!] render() - expect(screen.getByTestId('documents-count')).toHaveTextContent('1') + expect(screen.getByTestId('documents-count'))!.toHaveTextContent('1') }) }) }) diff --git a/web/app/components/datasets/documents/detail/__tests__/new-segment.spec.tsx b/web/app/components/datasets/documents/detail/__tests__/new-segment.spec.tsx index f243f85f29..a46b659f11 100644 --- a/web/app/components/datasets/documents/detail/__tests__/new-segment.spec.tsx +++ b/web/app/components/datasets/documents/detail/__tests__/new-segment.spec.tsx @@ -145,37 +145,37 @@ describe('NewSegmentModal', () => { it('should render without crashing', () => { const { container } = render() - expect(container.firstChild).toBeInTheDocument() + expect(container.firstChild)!.toBeInTheDocument() }) it('should render title text', () => { render() - expect(screen.getByText(/segment\.addChunk/i)).toBeInTheDocument() + expect(screen.getByText(/segment\.addChunk/i))!.toBeInTheDocument() }) it('should render chunk content component', () => { render() - expect(screen.getByTestId('chunk-content')).toBeInTheDocument() + expect(screen.getByTestId('chunk-content'))!.toBeInTheDocument() }) it('should render image uploader', () => { render() - expect(screen.getByTestId('image-uploader')).toBeInTheDocument() + expect(screen.getByTestId('image-uploader'))!.toBeInTheDocument() }) it('should render segment index tag', () => { render() - expect(screen.getByTestId('segment-index-tag')).toBeInTheDocument() + expect(screen.getByTestId('segment-index-tag'))!.toBeInTheDocument() }) it('should render dot separator', () => { render() - expect(screen.getByTestId('dot')).toBeInTheDocument() + expect(screen.getByTestId('dot'))!.toBeInTheDocument() }) }) @@ -186,7 +186,7 @@ describe('NewSegmentModal', () => { render() - expect(screen.getByTestId('keywords')).toBeInTheDocument() + expect(screen.getByTestId('keywords'))!.toBeInTheDocument() }) it('should not show keywords when indexing is QUALIFIED', () => { @@ -207,7 +207,7 @@ describe('NewSegmentModal', () => { const closeButtons = container.querySelectorAll('.cursor-pointer') // The close button is the second cursor-pointer element if (closeButtons.length > 1) - fireEvent.click(closeButtons[1]) + fireEvent.click(closeButtons[1]!) expect(mockOnCancel).toHaveBeenCalled() }) @@ -218,7 +218,7 @@ describe('NewSegmentModal', () => { fireEvent.change(questionInput, { target: { value: 'New question content' } }) - expect(questionInput).toHaveValue('New question content') + expect(questionInput)!.toHaveValue('New question content') }) it('should update answer when docForm is QA and typing', () => { @@ -227,7 +227,7 @@ describe('NewSegmentModal', () => { fireEvent.change(answerInput, { target: { value: 'New answer content' } }) - expect(answerInput).toHaveValue('New answer content') + expect(answerInput)!.toHaveValue('New answer content') }) it('should toggle add another checkbox', () => { @@ -237,7 +237,8 @@ describe('NewSegmentModal', () => { fireEvent.click(checkbox) // Assert - checkbox state should toggle - expect(checkbox).toBeInTheDocument() + // Assert - checkbox state should toggle + expect(checkbox)!.toBeInTheDocument() }) }) @@ -329,7 +330,7 @@ describe('NewSegmentModal', () => { const { container } = render() const header = container.querySelector('.border-divider-subtle') - expect(header).toBeInTheDocument() + expect(header)!.toBeInTheDocument() }) it('should show action buttons in header when fullScreen', () => { @@ -337,7 +338,7 @@ describe('NewSegmentModal', () => { render() - expect(screen.getByTestId('action-buttons')).toBeInTheDocument() + expect(screen.getByTestId('action-buttons'))!.toBeInTheDocument() }) it('should show add another in header when fullScreen', () => { @@ -345,7 +346,7 @@ describe('NewSegmentModal', () => { render() - expect(screen.getByTestId('add-another')).toBeInTheDocument() + expect(screen.getByTestId('add-another'))!.toBeInTheDocument() }) it('should call toggleFullScreen when expand button is clicked', () => { @@ -354,7 +355,7 @@ describe('NewSegmentModal', () => { // Act - click the expand button (first cursor-pointer) const expandButtons = container.querySelectorAll('.cursor-pointer') if (expandButtons.length > 0) - fireEvent.click(expandButtons[0]) + fireEvent.click(expandButtons[0]!) expect(mockToggleFullScreen).toHaveBeenCalled() }) @@ -365,13 +366,13 @@ describe('NewSegmentModal', () => { it('should pass actionType add to ActionButtons', () => { render() - expect(screen.getByTestId('action-type')).toHaveTextContent('add') + expect(screen.getByTestId('action-type'))!.toHaveTextContent('add') }) it('should pass isEditMode true to ChunkContent', () => { render() - expect(screen.getByTestId('edit-mode')).toHaveTextContent('editing') + expect(screen.getByTestId('edit-mode'))!.toHaveTextContent('editing') }) }) @@ -384,7 +385,7 @@ describe('NewSegmentModal', () => { target: { value: 'keyword1,keyword2' }, }) - expect(screen.getByTestId('keywords-input')).toHaveValue('keyword1,keyword2') + expect(screen.getByTestId('keywords-input'))!.toHaveValue('keyword1,keyword2') }) it('should handle image upload', () => { @@ -393,7 +394,8 @@ describe('NewSegmentModal', () => { fireEvent.click(screen.getByTestId('upload-image-btn')) // Assert - image uploader should be rendered - expect(screen.getByTestId('image-uploader')).toBeInTheDocument() + // Assert - image uploader should be rendered + expect(screen.getByTestId('image-uploader'))!.toBeInTheDocument() }) it('should maintain structure when rerendered with different docForm', () => { @@ -401,7 +403,7 @@ describe('NewSegmentModal', () => { rerender() - expect(screen.getByTestId('answer-input')).toBeInTheDocument() + expect(screen.getByTestId('answer-input'))!.toBeInTheDocument() }) }) @@ -591,7 +593,9 @@ describe('NewSegmentModal', () => { // Assert - should show count of 5 (3 + 2) // The component uses formatNumber and shows "X characters" - expect(screen.getByText(/5/)).toBeInTheDocument() + // Assert - should show count of 5 (3 + 2) + // The component uses formatNumber and shows "X characters" + expect(screen.getByText(/5/))!.toBeInTheDocument() }) }) @@ -602,8 +606,9 @@ describe('NewSegmentModal', () => { render() // Assert - footer should have both AddAnother and ActionButtons - expect(screen.getByTestId('add-another')).toBeInTheDocument() - expect(screen.getByTestId('action-buttons')).toBeInTheDocument() + // Assert - footer should have both AddAnother and ActionButtons + expect(screen.getByTestId('add-another'))!.toBeInTheDocument() + expect(screen.getByTestId('action-buttons'))!.toBeInTheDocument() }) }) }) diff --git a/web/app/components/datasets/documents/detail/completed/__tests__/child-segment-detail.spec.tsx b/web/app/components/datasets/documents/detail/completed/__tests__/child-segment-detail.spec.tsx index 4e3c7acd2b..b3bec1b0b8 100644 --- a/web/app/components/datasets/documents/detail/completed/__tests__/child-segment-detail.spec.tsx +++ b/web/app/components/datasets/documents/detail/completed/__tests__/child-segment-detail.spec.tsx @@ -92,37 +92,37 @@ describe('ChildSegmentDetail', () => { it('should render without crashing', () => { const { container } = render() - expect(container.firstChild).toBeInTheDocument() + expect(container.firstChild)!.toBeInTheDocument() }) it('should render edit child chunk title', () => { render() - expect(screen.getByText(/segment\.editChildChunk/i)).toBeInTheDocument() + expect(screen.getByText(/segment\.editChildChunk/i))!.toBeInTheDocument() }) it('should render chunk content component', () => { render() - expect(screen.getByTestId('chunk-content')).toBeInTheDocument() + expect(screen.getByTestId('chunk-content'))!.toBeInTheDocument() }) it('should render segment index tag', () => { render() - expect(screen.getByTestId('segment-index-tag')).toBeInTheDocument() + expect(screen.getByTestId('segment-index-tag'))!.toBeInTheDocument() }) it('should render word count', () => { render() - expect(screen.getByText(/segment\.characters/i)).toBeInTheDocument() + expect(screen.getByText(/segment\.characters/i))!.toBeInTheDocument() }) it('should render edit time', () => { render() - expect(screen.getByText(/segment\.editedAt/i)).toBeInTheDocument() + expect(screen.getByText(/segment\.editedAt/i))!.toBeInTheDocument() }) }) @@ -135,7 +135,7 @@ describe('ChildSegmentDetail', () => { const closeButtons = container.querySelectorAll('.cursor-pointer') if (closeButtons.length > 1) - fireEvent.click(closeButtons[1]) + fireEvent.click(closeButtons[1]!) expect(mockOnCancel).toHaveBeenCalled() }) @@ -145,7 +145,7 @@ describe('ChildSegmentDetail', () => { const expandButtons = container.querySelectorAll('.cursor-pointer') if (expandButtons.length > 0) - fireEvent.click(expandButtons[0]) + fireEvent.click(expandButtons[0]!) expect(mockToggleFullScreen).toHaveBeenCalled() }) @@ -170,7 +170,7 @@ describe('ChildSegmentDetail', () => { target: { value: 'Updated content' }, }) - expect(screen.getByTestId('content-input')).toHaveValue('Updated content') + expect(screen.getByTestId('content-input'))!.toHaveValue('Updated content') }) }) @@ -181,7 +181,7 @@ describe('ChildSegmentDetail', () => { render() - expect(screen.getByTestId('action-buttons')).toBeInTheDocument() + expect(screen.getByTestId('action-buttons'))!.toBeInTheDocument() }) it('should not show footer action buttons when fullScreen is true', () => { @@ -200,7 +200,7 @@ describe('ChildSegmentDetail', () => { render() - expect(screen.getByTestId('action-buttons')).toBeInTheDocument() + expect(screen.getByTestId('action-buttons'))!.toBeInTheDocument() }) }) @@ -209,13 +209,13 @@ describe('ChildSegmentDetail', () => { it('should pass isChildChunk true to ActionButtons', () => { render() - expect(screen.getByTestId('is-child-chunk')).toHaveTextContent('true') + expect(screen.getByTestId('is-child-chunk'))!.toHaveTextContent('true') }) it('should pass isEditMode true to ChunkContent', () => { render() - expect(screen.getByTestId('edit-mode')).toHaveTextContent('editing') + expect(screen.getByTestId('edit-mode'))!.toHaveTextContent('editing') }) }) @@ -225,7 +225,7 @@ describe('ChildSegmentDetail', () => { , ) - expect(container.firstChild).toBeInTheDocument() + expect(container.firstChild)!.toBeInTheDocument() }) it('should handle empty content', () => { @@ -233,7 +233,7 @@ describe('ChildSegmentDetail', () => { render() - expect(screen.getByTestId('content-input')).toHaveValue('') + expect(screen.getByTestId('content-input'))!.toHaveValue('') }) it('should maintain structure when rerendered', () => { @@ -242,7 +242,7 @@ describe('ChildSegmentDetail', () => { const updatedInfo = { ...defaultChildChunkInfo, content: 'New content' } rerender() - expect(screen.getByTestId('content-input')).toBeInTheDocument() + expect(screen.getByTestId('content-input'))!.toBeInTheDocument() }) }) @@ -258,6 +258,37 @@ describe('ChildSegmentDetail', () => { it('should have save button enabled by default', () => { render() + // Assert - save button should be enabled initially + // Assert - save button should be enabled initially + // Assert - save button should be enabled initially + // Assert - save button should be enabled initially + // Assert - save button should be enabled initially + // Assert - save button should be enabled initially + // Assert - save button should be enabled initially + // Assert - save button should be enabled initially + // Assert - save button should be enabled initially + // Assert - save button should be enabled initially + // Assert - save button should be enabled initially + // Assert - save button should be enabled initially + // Assert - save button should be enabled initially + // Assert - save button should be enabled initially + // Assert - save button should be enabled initially + // Assert - save button should be enabled initially + // Assert - save button should be enabled initially + // Assert - save button should be enabled initially + // Assert - save button should be enabled initially + // Assert - save button should be enabled initially + // Assert - save button should be enabled initially + // Assert - save button should be enabled initially + // Assert - save button should be enabled initially + // Assert - save button should be enabled initially + // Assert - save button should be enabled initially + // Assert - save button should be enabled initially + // Assert - save button should be enabled initially + // Assert - save button should be enabled initially + // Assert - save button should be enabled initially + // Assert - save button should be enabled initially + // Assert - save button should be enabled initially // Assert - save button should be enabled initially expect(screen.getByTestId('save-btn')).not.toBeDisabled() }) diff --git a/web/app/components/datasets/documents/detail/completed/__tests__/index.spec.tsx b/web/app/components/datasets/documents/detail/completed/__tests__/index.spec.tsx index aae0b226db..b7344d7a0f 100644 --- a/web/app/components/datasets/documents/detail/completed/__tests__/index.spec.tsx +++ b/web/app/components/datasets/documents/detail/completed/__tests__/index.spec.tsx @@ -287,10 +287,10 @@ describe('SegmentListContext', () => { render() - expect(screen.getByTestId('isCollapsed')).toHaveTextContent('true') - expect(screen.getByTestId('fullScreen')).toHaveTextContent('false') - expect(screen.getByTestId('currSegmentShowModal')).toHaveTextContent('false') - expect(screen.getByTestId('currChildChunkShowModal')).toHaveTextContent('false') + expect(screen.getByTestId('isCollapsed'))!.toHaveTextContent('true') + expect(screen.getByTestId('fullScreen'))!.toHaveTextContent('false') + expect(screen.getByTestId('currSegmentShowModal'))!.toHaveTextContent('false') + expect(screen.getByTestId('currChildChunkShowModal'))!.toHaveTextContent('false') }) }) @@ -324,9 +324,9 @@ describe('SegmentListContext', () => { , ) - expect(screen.getByTestId('isCollapsed')).toHaveTextContent('false') - expect(screen.getByTestId('fullScreen')).toHaveTextContent('true') - expect(screen.getByTestId('currSegmentShowModal')).toHaveTextContent('true') + expect(screen.getByTestId('isCollapsed'))!.toHaveTextContent('false') + expect(screen.getByTestId('fullScreen'))!.toHaveTextContent('true') + expect(screen.getByTestId('currSegmentShowModal'))!.toHaveTextContent('true') }) }) @@ -356,8 +356,8 @@ describe('SegmentListContext', () => { , ) - expect(screen.getByTestId('isCollapsed')).toHaveTextContent('true') - expect(screen.getByTestId('fullScreen')).toHaveTextContent('false') + expect(screen.getByTestId('isCollapsed'))!.toHaveTextContent('true') + expect(screen.getByTestId('fullScreen'))!.toHaveTextContent('false') // Rerender with changed values rerender( @@ -373,8 +373,8 @@ describe('SegmentListContext', () => { , ) - expect(screen.getByTestId('isCollapsed')).toHaveTextContent('false') - expect(screen.getByTestId('fullScreen')).toHaveTextContent('true') + expect(screen.getByTestId('isCollapsed'))!.toHaveTextContent('false') + expect(screen.getByTestId('fullScreen'))!.toHaveTextContent('true') }) }) }) @@ -400,7 +400,7 @@ describe('Completed Component', () => { it('should render MenuBar when not in full-doc mode', () => { render(, { wrapper: createWrapper() }) - expect(screen.getByTestId('menu-bar')).toBeInTheDocument() + expect(screen.getByTestId('menu-bar'))!.toBeInTheDocument() }) it('should not render MenuBar when in full-doc mode', () => { @@ -415,7 +415,7 @@ describe('Completed Component', () => { it('should render GeneralModeContent when not in full-doc mode', () => { render(, { wrapper: createWrapper() }) - expect(screen.getByTestId('general-mode-content')).toBeInTheDocument() + expect(screen.getByTestId('general-mode-content'))!.toBeInTheDocument() }) it('should render FullDocModeContent when in full-doc mode', () => { @@ -424,25 +424,25 @@ describe('Completed Component', () => { render(, { wrapper: createWrapper() }) - expect(screen.getByTestId('full-doc-mode-content')).toBeInTheDocument() + expect(screen.getByTestId('full-doc-mode-content'))!.toBeInTheDocument() }) it('should render Pagination component', () => { render(, { wrapper: createWrapper() }) - expect(screen.getByTestId('pagination')).toBeInTheDocument() + expect(screen.getByTestId('pagination'))!.toBeInTheDocument() }) it('should render Divider component', () => { render(, { wrapper: createWrapper() }) - expect(screen.getByTestId('divider')).toBeInTheDocument() + expect(screen.getByTestId('divider'))!.toBeInTheDocument() }) it('should render DrawerGroup when docForm is available', () => { render(, { wrapper: createWrapper() }) - expect(screen.getByTestId('drawer-group')).toBeInTheDocument() + expect(screen.getByTestId('drawer-group'))!.toBeInTheDocument() }) it('should not render DrawerGroup when docForm is undefined', () => { @@ -458,7 +458,7 @@ describe('Completed Component', () => { it('should start with page 0 (current - 1)', () => { render(, { wrapper: createWrapper() }) - expect(screen.getByTestId('current-page')).toHaveTextContent('0') + expect(screen.getByTestId('current-page'))!.toHaveTextContent('0') }) it('should update page when pagination changes', async () => { @@ -468,7 +468,7 @@ describe('Completed Component', () => { fireEvent.click(nextPageButton) await waitFor(() => { - expect(screen.getByTestId('current-page')).toHaveTextContent('1') + expect(screen.getByTestId('current-page'))!.toHaveTextContent('1') }) }) @@ -479,7 +479,8 @@ describe('Completed Component', () => { fireEvent.click(changeLimitButton) // Limit change is handled internally - expect(changeLimitButton).toBeInTheDocument() + // Limit change is handled internally + expect(changeLimitButton)!.toBeInTheDocument() }) }) @@ -495,19 +496,19 @@ describe('Completed Component', () => { it('should handle archived prop', () => { render(, { wrapper: createWrapper() }) - expect(screen.getByTestId('general-mode-content')).toBeInTheDocument() + expect(screen.getByTestId('general-mode-content'))!.toBeInTheDocument() }) it('should handle embeddingAvailable prop', () => { render(, { wrapper: createWrapper() }) - expect(screen.getByTestId('general-mode-content')).toBeInTheDocument() + expect(screen.getByTestId('general-mode-content'))!.toBeInTheDocument() }) it('should handle showNewSegmentModal prop', () => { render(, { wrapper: createWrapper() }) - expect(screen.getByTestId('drawer-group')).toBeInTheDocument() + expect(screen.getByTestId('drawer-group'))!.toBeInTheDocument() }) }) @@ -517,7 +518,8 @@ describe('Completed Component', () => { render(, { wrapper: createWrapper() }) // Context is provided, components should render without errors - expect(screen.getByTestId('general-mode-content')).toBeInTheDocument() + // Context is provided, components should render without errors + expect(screen.getByTestId('general-mode-content'))!.toBeInTheDocument() }) }) }) @@ -544,7 +546,7 @@ describe('Edge Cases', () => { render(, { wrapper: createWrapper() }) - expect(screen.getByTestId('general-mode-content')).toBeInTheDocument() + expect(screen.getByTestId('general-mode-content'))!.toBeInTheDocument() }) it('should handle empty documentId', () => { @@ -552,19 +554,19 @@ describe('Edge Cases', () => { render(, { wrapper: createWrapper() }) - expect(screen.getByTestId('general-mode-content')).toBeInTheDocument() + expect(screen.getByTestId('general-mode-content'))!.toBeInTheDocument() }) it('should handle undefined importStatus', () => { render(, { wrapper: createWrapper() }) - expect(screen.getByTestId('general-mode-content')).toBeInTheDocument() + expect(screen.getByTestId('general-mode-content'))!.toBeInTheDocument() }) it('should handle ProcessStatus.COMPLETED importStatus', () => { render(, { wrapper: createWrapper() }) - expect(screen.getByTestId('general-mode-content')).toBeInTheDocument() + expect(screen.getByTestId('general-mode-content'))!.toBeInTheDocument() }) it('should handle all ChunkingMode values', () => { @@ -575,7 +577,7 @@ describe('Edge Cases', () => { const { unmount } = render(, { wrapper: createWrapper() }) - expect(screen.getByTestId('pagination')).toBeInTheDocument() + expect(screen.getByTestId('pagination'))!.toBeInTheDocument() unmount() }) @@ -591,7 +593,7 @@ describe('Edge Cases', () => { const { unmount } = render(, { wrapper: createWrapper() }) - expect(screen.getByTestId('pagination')).toBeInTheDocument() + expect(screen.getByTestId('pagination'))!.toBeInTheDocument() unmount() }) @@ -617,33 +619,34 @@ describe('Integration Tests', () => { render(, { wrapper: createWrapper() }) // All components should render without errors - expect(screen.getByTestId('menu-bar')).toBeInTheDocument() - expect(screen.getByTestId('general-mode-content')).toBeInTheDocument() - expect(screen.getByTestId('pagination')).toBeInTheDocument() - expect(screen.getByTestId('drawer-group')).toBeInTheDocument() + // All components should render without errors + expect(screen.getByTestId('menu-bar'))!.toBeInTheDocument() + expect(screen.getByTestId('general-mode-content'))!.toBeInTheDocument() + expect(screen.getByTestId('pagination'))!.toBeInTheDocument() + expect(screen.getByTestId('drawer-group'))!.toBeInTheDocument() }) it('should update UI when mode changes', () => { const { rerender } = render(, { wrapper: createWrapper() }) - expect(screen.getByTestId('general-mode-content')).toBeInTheDocument() + expect(screen.getByTestId('general-mode-content'))!.toBeInTheDocument() mockDocForm.current = ChunkingModeEnum.parentChild mockParentMode.current = 'full-doc' rerender() - expect(screen.getByTestId('full-doc-mode-content')).toBeInTheDocument() + expect(screen.getByTestId('full-doc-mode-content'))!.toBeInTheDocument() }) it('should handle prop updates correctly', () => { const { rerender } = render(, { wrapper: createWrapper() }) - expect(screen.getByTestId('drawer-group')).toBeInTheDocument() + expect(screen.getByTestId('drawer-group'))!.toBeInTheDocument() rerender() - expect(screen.getByTestId('drawer-group')).toBeInTheDocument() + expect(screen.getByTestId('drawer-group'))!.toBeInTheDocument() }) }) @@ -696,6 +699,37 @@ describe('Batch Action Callbacks', () => { it('should not render batch actions when no segments are selected initially', async () => { render(, { wrapper: createWrapper() }) + // Initially no segments are selected, so batch action should not be visible + // Initially no segments are selected, so batch action should not be visible + // Initially no segments are selected, so batch action should not be visible + // Initially no segments are selected, so batch action should not be visible + // Initially no segments are selected, so batch action should not be visible + // Initially no segments are selected, so batch action should not be visible + // Initially no segments are selected, so batch action should not be visible + // Initially no segments are selected, so batch action should not be visible + // Initially no segments are selected, so batch action should not be visible + // Initially no segments are selected, so batch action should not be visible + // Initially no segments are selected, so batch action should not be visible + // Initially no segments are selected, so batch action should not be visible + // Initially no segments are selected, so batch action should not be visible + // Initially no segments are selected, so batch action should not be visible + // Initially no segments are selected, so batch action should not be visible + // Initially no segments are selected, so batch action should not be visible + // Initially no segments are selected, so batch action should not be visible + // Initially no segments are selected, so batch action should not be visible + // Initially no segments are selected, so batch action should not be visible + // Initially no segments are selected, so batch action should not be visible + // Initially no segments are selected, so batch action should not be visible + // Initially no segments are selected, so batch action should not be visible + // Initially no segments are selected, so batch action should not be visible + // Initially no segments are selected, so batch action should not be visible + // Initially no segments are selected, so batch action should not be visible + // Initially no segments are selected, so batch action should not be visible + // Initially no segments are selected, so batch action should not be visible + // Initially no segments are selected, so batch action should not be visible + // Initially no segments are selected, so batch action should not be visible + // Initially no segments are selected, so batch action should not be visible + // Initially no segments are selected, so batch action should not be visible // Initially no segments are selected, so batch action should not be visible expect(screen.queryByTestId('batch-action')).not.toBeInTheDocument() }) @@ -708,7 +742,7 @@ describe('Batch Action Callbacks', () => { // Now batch actions should be visible await waitFor(() => { - expect(screen.getByTestId('batch-action')).toBeInTheDocument() + expect(screen.getByTestId('batch-action'))!.toBeInTheDocument() }) }) @@ -721,7 +755,7 @@ describe('Batch Action Callbacks', () => { // Wait for batch actions to appear await waitFor(() => { - expect(screen.getByTestId('batch-action')).toBeInTheDocument() + expect(screen.getByTestId('batch-action'))!.toBeInTheDocument() }) const enableButton = screen.getByTestId('batch-enable') @@ -739,7 +773,7 @@ describe('Batch Action Callbacks', () => { // Wait for batch actions to appear await waitFor(() => { - expect(screen.getByTestId('batch-action')).toBeInTheDocument() + expect(screen.getByTestId('batch-action'))!.toBeInTheDocument() }) const disableButton = screen.getByTestId('batch-disable') @@ -757,7 +791,7 @@ describe('Batch Action Callbacks', () => { // Wait for batch actions to appear await waitFor(() => { - expect(screen.getByTestId('batch-action')).toBeInTheDocument() + expect(screen.getByTestId('batch-action'))!.toBeInTheDocument() }) const deleteButton = screen.getByTestId('batch-delete') @@ -887,14 +921,15 @@ describe('refreshChunkListDataWithDetailChanged branch coverage', () => { // Create a refreshMap similar to the component const refreshMap: Record void> = { - true: () => { + true: (() => { mockInvalidAll() mockInvalidDisabled() - }, + })!, } // Execute the 'true' branch - refreshMap.true() + // Execute the 'true' branch + refreshMap.true!() expect(mockInvalidAll).toHaveBeenCalled() expect(mockInvalidDisabled).toHaveBeenCalled() @@ -907,14 +942,15 @@ describe('refreshChunkListDataWithDetailChanged branch coverage', () => { // Create a refreshMap similar to the component const refreshMap: Record void> = { - false: () => { + false: (() => { mockInvalidAll() mockInvalidEnabled() - }, + })!, } // Execute the 'false' branch - refreshMap.false() + // Execute the 'false' branch + refreshMap.false!() expect(mockInvalidAll).toHaveBeenCalled() expect(mockInvalidEnabled).toHaveBeenCalled() @@ -989,13 +1025,13 @@ describe('Inline callback and hook initialization coverage', () => { fireEvent.click(screen.getByTestId('next-page')) await waitFor(() => { - expect(screen.getByTestId('current-page')).toHaveTextContent('1') + expect(screen.getByTestId('current-page'))!.toHaveTextContent('1') }) fireEvent.click(screen.getByTestId('status-enabled')) await waitFor(() => { - expect(screen.getByTestId('current-page')).toHaveTextContent('0') + expect(screen.getByTestId('current-page'))!.toHaveTextContent('0') }) }) @@ -1006,7 +1042,7 @@ describe('Inline callback and hook initialization coverage', () => { , { wrapper: createWrapper() }, ) - expect(screen.getByTestId('drawer-group')).toBeInTheDocument() + expect(screen.getByTestId('drawer-group'))!.toBeInTheDocument() }) // Covers lines 74-90: refreshChunkListDataWithDetailChanged with status true @@ -1056,7 +1092,7 @@ describe('Inline callback and hook initialization coverage', () => { fireEvent.click(screen.getByTestId('select-all-button')) await waitFor(() => { - expect(screen.getByTestId('batch-action')).toBeInTheDocument() + expect(screen.getByTestId('batch-action'))!.toBeInTheDocument() }) fireEvent.click(screen.getByTestId('cancel-batch')) @@ -1072,7 +1108,7 @@ describe('Inline callback and hook initialization coverage', () => { fireEvent.click(screen.getByTestId('select-all-button')) await waitFor(() => { - expect(screen.getByTestId('batch-action')).toBeInTheDocument() + expect(screen.getByTestId('batch-action'))!.toBeInTheDocument() }) fireEvent.click(screen.getByTestId('batch-enable')) @@ -1086,7 +1122,7 @@ describe('Inline callback and hook initialization coverage', () => { fireEvent.click(screen.getByTestId('select-all-button')) await waitFor(() => { - expect(screen.getByTestId('batch-action')).toBeInTheDocument() + expect(screen.getByTestId('batch-action'))!.toBeInTheDocument() }) fireEvent.click(screen.getByTestId('batch-disable')) @@ -1100,7 +1136,7 @@ describe('Inline callback and hook initialization coverage', () => { fireEvent.click(screen.getByTestId('select-all-button')) await waitFor(() => { - expect(screen.getByTestId('batch-action')).toBeInTheDocument() + expect(screen.getByTestId('batch-action'))!.toBeInTheDocument() }) fireEvent.click(screen.getByTestId('batch-delete')) @@ -1115,12 +1151,12 @@ describe('Inline callback and hook initialization coverage', () => { fireEvent.click(screen.getByTestId('next-page')) await waitFor(() => { - expect(screen.getByTestId('current-page')).toHaveTextContent('1') + expect(screen.getByTestId('current-page'))!.toHaveTextContent('1') }) fireEvent.click(screen.getByTestId('next-page')) await waitFor(() => { - expect(screen.getByTestId('current-page')).toHaveTextContent('2') + expect(screen.getByTestId('current-page'))!.toHaveTextContent('2') }) }) @@ -1132,7 +1168,7 @@ describe('Inline callback and hook initialization coverage', () => { render(, { wrapper: createWrapper() }) - expect(screen.getByTestId('total-items')).toHaveTextContent('42') + expect(screen.getByTestId('total-items'))!.toHaveTextContent('42') }) // Covers search input change @@ -1142,6 +1178,6 @@ describe('Inline callback and hook initialization coverage', () => { const searchInput = screen.getByTestId('search-input') fireEvent.change(searchInput, { target: { value: 'test query' } }) - expect(searchInput).toHaveValue('test query') + expect(searchInput)!.toHaveValue('test query') }) }) diff --git a/web/app/components/datasets/documents/detail/completed/__tests__/new-child-segment.spec.tsx b/web/app/components/datasets/documents/detail/completed/__tests__/new-child-segment.spec.tsx index 150d399a5d..ff9fb4c524 100644 --- a/web/app/components/datasets/documents/detail/completed/__tests__/new-child-segment.spec.tsx +++ b/web/app/components/datasets/documents/detail/completed/__tests__/new-child-segment.spec.tsx @@ -110,31 +110,31 @@ describe('NewChildSegmentModal', () => { it('should render without crashing', () => { const { container } = render() - expect(container.firstChild).toBeInTheDocument() + expect(container.firstChild)!.toBeInTheDocument() }) it('should render add child chunk title', () => { render() - expect(screen.getByText(/segment\.addChildChunk/i)).toBeInTheDocument() + expect(screen.getByText(/segment\.addChildChunk/i))!.toBeInTheDocument() }) it('should render chunk content component', () => { render() - expect(screen.getByTestId('chunk-content')).toBeInTheDocument() + expect(screen.getByTestId('chunk-content'))!.toBeInTheDocument() }) it('should render segment index tag with new child chunk label', () => { render() - expect(screen.getByTestId('segment-index-tag')).toBeInTheDocument() + expect(screen.getByTestId('segment-index-tag'))!.toBeInTheDocument() }) it('should render add another checkbox', () => { render() - expect(screen.getByTestId('add-another')).toBeInTheDocument() + expect(screen.getByTestId('add-another'))!.toBeInTheDocument() }) }) @@ -147,7 +147,7 @@ describe('NewChildSegmentModal', () => { const closeButtons = container.querySelectorAll('.cursor-pointer') if (closeButtons.length > 1) - fireEvent.click(closeButtons[1]) + fireEvent.click(closeButtons[1]!) expect(mockOnCancel).toHaveBeenCalled() }) @@ -157,7 +157,7 @@ describe('NewChildSegmentModal', () => { const expandButtons = container.querySelectorAll('.cursor-pointer') if (expandButtons.length > 0) - fireEvent.click(expandButtons[0]) + fireEvent.click(expandButtons[0]!) expect(mockToggleFullScreen).toHaveBeenCalled() }) @@ -169,7 +169,7 @@ describe('NewChildSegmentModal', () => { target: { value: 'New content' }, }) - expect(screen.getByTestId('content-input')).toHaveValue('New content') + expect(screen.getByTestId('content-input'))!.toHaveValue('New content') }) it('should toggle add another checkbox', () => { @@ -178,7 +178,7 @@ describe('NewChildSegmentModal', () => { fireEvent.click(checkbox) - expect(checkbox).toBeInTheDocument() + expect(checkbox)!.toBeInTheDocument() }) }) @@ -253,7 +253,7 @@ describe('NewChildSegmentModal', () => { render() - expect(screen.getByTestId('action-buttons')).toBeInTheDocument() + expect(screen.getByTestId('action-buttons'))!.toBeInTheDocument() }) it('should show add another in header when fullScreen', () => { @@ -261,7 +261,7 @@ describe('NewChildSegmentModal', () => { render() - expect(screen.getByTestId('add-another')).toBeInTheDocument() + expect(screen.getByTestId('add-another'))!.toBeInTheDocument() }) }) @@ -270,19 +270,19 @@ describe('NewChildSegmentModal', () => { it('should pass actionType add to ActionButtons', () => { render() - expect(screen.getByTestId('action-type')).toHaveTextContent('add') + expect(screen.getByTestId('action-type'))!.toHaveTextContent('add') }) it('should pass isChildChunk true to ActionButtons', () => { render() - expect(screen.getByTestId('is-child-chunk')).toHaveTextContent('true') + expect(screen.getByTestId('is-child-chunk'))!.toHaveTextContent('true') }) it('should pass isEditMode true to ChunkContent', () => { render() - expect(screen.getByTestId('edit-mode')).toHaveTextContent('editing') + expect(screen.getByTestId('edit-mode'))!.toHaveTextContent('editing') }) }) @@ -292,7 +292,7 @@ describe('NewChildSegmentModal', () => { const { container } = render() - expect(container.firstChild).toBeInTheDocument() + expect(container.firstChild)!.toBeInTheDocument() }) it('should maintain structure when rerendered', () => { @@ -300,7 +300,7 @@ describe('NewChildSegmentModal', () => { rerender() - expect(screen.getByTestId('chunk-content')).toBeInTheDocument() + expect(screen.getByTestId('chunk-content'))!.toBeInTheDocument() }) }) @@ -351,7 +351,7 @@ describe('NewChildSegmentModal', () => { // Assert - modal should not close, only content cleared await waitFor(() => { - expect(screen.getByTestId('content-input')).toHaveValue('') + expect(screen.getByTestId('content-input'))!.toHaveValue('') }) }) }) diff --git a/web/app/components/datasets/documents/detail/completed/__tests__/segment-detail.spec.tsx b/web/app/components/datasets/documents/detail/completed/__tests__/segment-detail.spec.tsx index dbce9b7f22..4e17cd39b3 100644 --- a/web/app/components/datasets/documents/detail/completed/__tests__/segment-detail.spec.tsx +++ b/web/app/components/datasets/documents/detail/completed/__tests__/segment-detail.spec.tsx @@ -174,37 +174,37 @@ describe('SegmentDetail', () => { it('should render without crashing', () => { const { container } = render() - expect(container.firstChild).toBeInTheDocument() + expect(container.firstChild)!.toBeInTheDocument() }) it('should render title for view mode', () => { render() - expect(screen.getByText(/segment\.chunkDetail/i)).toBeInTheDocument() + expect(screen.getByText(/segment\.chunkDetail/i))!.toBeInTheDocument() }) it('should render title for edit mode', () => { render() - expect(screen.getByText(/segment\.editChunk/i)).toBeInTheDocument() + expect(screen.getByText(/segment\.editChunk/i))!.toBeInTheDocument() }) it('should render chunk content component', () => { render() - expect(screen.getByTestId('chunk-content')).toBeInTheDocument() + expect(screen.getByTestId('chunk-content'))!.toBeInTheDocument() }) it('should render image uploader', () => { render() - expect(screen.getByTestId('image-uploader')).toBeInTheDocument() + expect(screen.getByTestId('image-uploader'))!.toBeInTheDocument() }) it('should render segment index tag', () => { render() - expect(screen.getByTestId('segment-index-tag')).toBeInTheDocument() + expect(screen.getByTestId('segment-index-tag'))!.toBeInTheDocument() }) }) @@ -213,25 +213,25 @@ describe('SegmentDetail', () => { it('should pass isEditMode to ChunkContent', () => { render() - expect(screen.getByTestId('edit-mode')).toHaveTextContent('editing') + expect(screen.getByTestId('edit-mode'))!.toHaveTextContent('editing') }) it('should disable image uploader in view mode', () => { render() - expect(screen.getByTestId('uploader-disabled')).toHaveTextContent('disabled') + expect(screen.getByTestId('uploader-disabled'))!.toHaveTextContent('disabled') }) it('should enable image uploader in edit mode', () => { render() - expect(screen.getByTestId('uploader-disabled')).toHaveTextContent('enabled') + expect(screen.getByTestId('uploader-disabled'))!.toHaveTextContent('enabled') }) it('should show action buttons in edit mode', () => { render() - expect(screen.getByTestId('action-buttons')).toBeInTheDocument() + expect(screen.getByTestId('action-buttons'))!.toBeInTheDocument() }) it('should not show action buttons in view mode (non-fullscreen)', () => { @@ -248,7 +248,7 @@ describe('SegmentDetail', () => { render() - expect(screen.getByTestId('keywords')).toBeInTheDocument() + expect(screen.getByTestId('keywords'))!.toBeInTheDocument() }) it('should not show keywords when indexing is QUALIFIED', () => { @@ -264,7 +264,7 @@ describe('SegmentDetail', () => { render() - expect(screen.getByTestId('keywords-action')).toHaveTextContent('view') + expect(screen.getByTestId('keywords-action'))!.toHaveTextContent('view') }) it('should pass edit action type when in edit mode', () => { @@ -272,7 +272,7 @@ describe('SegmentDetail', () => { render() - expect(screen.getByTestId('keywords-action')).toHaveTextContent('edit') + expect(screen.getByTestId('keywords-action'))!.toHaveTextContent('edit') }) }) @@ -283,7 +283,7 @@ describe('SegmentDetail', () => { const closeButtons = container.querySelectorAll('.cursor-pointer') if (closeButtons.length > 1) - fireEvent.click(closeButtons[1]) + fireEvent.click(closeButtons[1]!) expect(mockOnCancel).toHaveBeenCalled() }) @@ -293,7 +293,7 @@ describe('SegmentDetail', () => { const expandButtons = container.querySelectorAll('.cursor-pointer') if (expandButtons.length > 0) - fireEvent.click(expandButtons[0]) + fireEvent.click(expandButtons[0]!) expect(mockToggleFullScreen).toHaveBeenCalled() }) @@ -322,7 +322,7 @@ describe('SegmentDetail', () => { target: { value: 'Updated content' }, }) - expect(screen.getByTestId('question-input')).toHaveValue('Updated content') + expect(screen.getByTestId('question-input'))!.toHaveValue('Updated content') }) }) @@ -333,7 +333,7 @@ describe('SegmentDetail', () => { render() - expect(screen.getByTestId('regenerate-btn')).toBeInTheDocument() + expect(screen.getByTestId('regenerate-btn'))!.toBeInTheDocument() }) it('should not show regeneration button when runtimeMode is not general', () => { @@ -349,7 +349,7 @@ describe('SegmentDetail', () => { fireEvent.click(screen.getByTestId('regenerate-btn')) - expect(screen.getByTestId('regeneration-modal')).toBeInTheDocument() + expect(screen.getByTestId('regeneration-modal'))!.toBeInTheDocument() }) it('should call onModalStateChange when regeneration modal opens', () => { @@ -392,7 +392,7 @@ describe('SegmentDetail', () => { render() - expect(screen.getByTestId('action-buttons')).toBeInTheDocument() + expect(screen.getByTestId('action-buttons'))!.toBeInTheDocument() }) it('should apply full screen styling when fullScreen is true', () => { @@ -401,7 +401,7 @@ describe('SegmentDetail', () => { const { container } = render() const header = container.querySelector('.border-divider-subtle') - expect(header).toBeInTheDocument() + expect(header)!.toBeInTheDocument() }) }) @@ -415,7 +415,7 @@ describe('SegmentDetail', () => { const { container } = render() - expect(container.firstChild).toBeInTheDocument() + expect(container.firstChild)!.toBeInTheDocument() }) it('should handle empty keywords array', () => { @@ -424,7 +424,7 @@ describe('SegmentDetail', () => { render() - expect(screen.getByTestId('keywords-input')).toHaveValue('') + expect(screen.getByTestId('keywords-input'))!.toHaveValue('') }) it('should maintain structure when rerendered', () => { @@ -432,7 +432,7 @@ describe('SegmentDetail', () => { rerender() - expect(screen.getByTestId('action-buttons')).toBeInTheDocument() + expect(screen.getByTestId('action-buttons'))!.toBeInTheDocument() }) }) @@ -443,7 +443,7 @@ describe('SegmentDetail', () => { fireEvent.click(screen.getByTestId('add-attachment-btn')) - expect(screen.getByTestId('attachments-count')).toHaveTextContent('1') + expect(screen.getByTestId('attachments-count'))!.toHaveTextContent('1') }) it('should pass attachments to onUpdate when save is clicked', () => { @@ -476,7 +476,7 @@ describe('SegmentDetail', () => { render() - expect(screen.getByTestId('attachments-count')).toHaveTextContent('1') + expect(screen.getByTestId('attachments-count'))!.toHaveTextContent('1') }) }) @@ -529,7 +529,7 @@ describe('SegmentDetail', () => { it('should render answer input in QA mode', () => { render() - expect(screen.getByTestId('answer-input')).toBeInTheDocument() + expect(screen.getByTestId('answer-input'))!.toBeInTheDocument() }) it('should update answer when input changes', () => { @@ -539,14 +539,15 @@ describe('SegmentDetail', () => { target: { value: 'Updated answer' }, }) - expect(screen.getByTestId('answer-input')).toHaveValue('Updated answer') + expect(screen.getByTestId('answer-input'))!.toHaveValue('Updated answer') }) it('should calculate word count correctly in QA mode', () => { render() // Assert - should show combined length of question and answer - expect(screen.getByText(/segment\.characters/i)).toBeInTheDocument() + // Assert - should show combined length of question and answer + expect(screen.getByText(/segment\.characters/i))!.toBeInTheDocument() }) }) @@ -557,7 +558,7 @@ describe('SegmentDetail', () => { render() - expect(screen.getByTestId('segment-index-tag')).toBeInTheDocument() + expect(screen.getByTestId('segment-index-tag'))!.toBeInTheDocument() }) }) @@ -571,7 +572,7 @@ describe('SegmentDetail', () => { target: { value: 'new,keywords' }, }) - expect(screen.getByTestId('keywords-input')).toHaveValue('new,keywords') + expect(screen.getByTestId('keywords-input'))!.toHaveValue('new,keywords') }) }) }) diff --git a/web/app/components/datasets/documents/detail/completed/common/__tests__/action-buttons.spec.tsx b/web/app/components/datasets/documents/detail/completed/common/__tests__/action-buttons.spec.tsx index edf4b30922..c8500e3769 100644 --- a/web/app/components/datasets/documents/detail/completed/common/__tests__/action-buttons.spec.tsx +++ b/web/app/components/datasets/documents/detail/completed/common/__tests__/action-buttons.spec.tsx @@ -63,7 +63,7 @@ describe('ActionButtons', () => { { wrapper: createWrapper({}) }, ) - expect(container.firstChild).toBeInTheDocument() + expect(container.firstChild)!.toBeInTheDocument() }) it('should render cancel button', () => { @@ -76,7 +76,7 @@ describe('ActionButtons', () => { { wrapper: createWrapper({}) }, ) - expect(screen.getByText(/operation\.cancel/i)).toBeInTheDocument() + expect(screen.getByText(/operation\.cancel/i))!.toBeInTheDocument() }) it('should render save button', () => { @@ -89,7 +89,7 @@ describe('ActionButtons', () => { { wrapper: createWrapper({}) }, ) - expect(screen.getByText(/operation\.save/i)).toBeInTheDocument() + expect(screen.getByText(/operation\.save/i))!.toBeInTheDocument() }) it('should render ESC keyboard hint on cancel button', () => { @@ -102,7 +102,7 @@ describe('ActionButtons', () => { { wrapper: createWrapper({}) }, ) - expect(screen.getByText('ESC')).toBeInTheDocument() + expect(screen.getByText('ESC'))!.toBeInTheDocument() }) it('should render S keyboard hint on save button', () => { @@ -115,7 +115,7 @@ describe('ActionButtons', () => { { wrapper: createWrapper({}) }, ) - expect(screen.getByText('S')).toBeInTheDocument() + expect(screen.getByText('S'))!.toBeInTheDocument() }) }) @@ -132,7 +132,7 @@ describe('ActionButtons', () => { ) const cancelButton = screen.getAllByRole('button')[0] - fireEvent.click(cancelButton) + fireEvent.click(cancelButton!) expect(mockHandleCancel).toHaveBeenCalledTimes(1) }) @@ -150,7 +150,7 @@ describe('ActionButtons', () => { const buttons = screen.getAllByRole('button') const saveButton = buttons[buttons.length - 1] // Save button is last - fireEvent.click(saveButton) + fireEvent.click(saveButton!) expect(mockHandleSave).toHaveBeenCalledTimes(1) }) @@ -167,7 +167,7 @@ describe('ActionButtons', () => { const buttons = screen.getAllByRole('button') const saveButton = buttons[buttons.length - 1] - expect(saveButton).toBeDisabled() + expect(saveButton)!.toBeDisabled() }) }) @@ -187,7 +187,7 @@ describe('ActionButtons', () => { { wrapper: createWrapper({ docForm: ChunkingMode.parentChild, parentMode: 'paragraph' }) }, ) - expect(screen.getByText(/operation\.saveAndRegenerate/i)).toBeInTheDocument() + expect(screen.getByText(/operation\.saveAndRegenerate/i))!.toBeInTheDocument() }) it('should not show regeneration button when isChildChunk is true', () => { @@ -278,7 +278,7 @@ describe('ActionButtons', () => { ) const regenerationButton = screen.getByText(/operation\.saveAndRegenerate/i).closest('button') - expect(regenerationButton).toBeDisabled() + expect(regenerationButton)!.toBeDisabled() }) }) @@ -298,7 +298,8 @@ describe('ActionButtons', () => { ) // Assert - regeneration button should show with default actionType='edit' - expect(screen.getByText(/operation\.saveAndRegenerate/i)).toBeInTheDocument() + // Assert - regeneration button should show with default actionType='edit' + expect(screen.getByText(/operation\.saveAndRegenerate/i))!.toBeInTheDocument() }) it('should use default isChildChunk of false', () => { @@ -316,7 +317,8 @@ describe('ActionButtons', () => { ) // Assert - regeneration button should show with default isChildChunk=false - expect(screen.getByText(/operation\.saveAndRegenerate/i)).toBeInTheDocument() + // Assert - regeneration button should show with default isChildChunk=false + expect(screen.getByText(/operation\.saveAndRegenerate/i))!.toBeInTheDocument() }) it('should use default showRegenerationButton of true', () => { @@ -334,7 +336,8 @@ describe('ActionButtons', () => { ) // Assert - regeneration button should show with default showRegenerationButton=true - expect(screen.getByText(/operation\.saveAndRegenerate/i)).toBeInTheDocument() + // Assert - regeneration button should show with default showRegenerationButton=true + expect(screen.getByText(/operation\.saveAndRegenerate/i))!.toBeInTheDocument() }) }) @@ -373,8 +376,8 @@ describe('ActionButtons', () => { , ) - expect(screen.getByText(/operation\.cancel/i)).toBeInTheDocument() - expect(screen.getByText(/operation\.save/i)).toBeInTheDocument() + expect(screen.getByText(/operation\.cancel/i))!.toBeInTheDocument() + expect(screen.getByText(/operation\.save/i))!.toBeInTheDocument() }) }) diff --git a/web/app/components/datasets/documents/detail/completed/common/__tests__/chunk-content.spec.tsx b/web/app/components/datasets/documents/detail/completed/common/__tests__/chunk-content.spec.tsx index 115db9ad61..a92cc9d350 100644 --- a/web/app/components/datasets/documents/detail/completed/common/__tests__/chunk-content.spec.tsx +++ b/web/app/components/datasets/documents/detail/completed/common/__tests__/chunk-content.spec.tsx @@ -34,19 +34,50 @@ describe('ChunkContent', () => { it('should render without crashing', () => { const { container } = render() - expect(container.firstChild).toBeInTheDocument() + expect(container.firstChild)!.toBeInTheDocument() }) it('should render textarea in edit mode with text docForm', () => { render() const textarea = screen.getByRole('textbox') - expect(textarea).toBeInTheDocument() + expect(textarea)!.toBeInTheDocument() }) it('should render Markdown content in view mode with text docForm', () => { const { container } = render() + // Assert - In view mode, textarea should not be present, Markdown renders instead + // Assert - In view mode, textarea should not be present, Markdown renders instead + // Assert - In view mode, textarea should not be present, Markdown renders instead + // Assert - In view mode, textarea should not be present, Markdown renders instead + // Assert - In view mode, textarea should not be present, Markdown renders instead + // Assert - In view mode, textarea should not be present, Markdown renders instead + // Assert - In view mode, textarea should not be present, Markdown renders instead + // Assert - In view mode, textarea should not be present, Markdown renders instead + // Assert - In view mode, textarea should not be present, Markdown renders instead + // Assert - In view mode, textarea should not be present, Markdown renders instead + // Assert - In view mode, textarea should not be present, Markdown renders instead + // Assert - In view mode, textarea should not be present, Markdown renders instead + // Assert - In view mode, textarea should not be present, Markdown renders instead + // Assert - In view mode, textarea should not be present, Markdown renders instead + // Assert - In view mode, textarea should not be present, Markdown renders instead + // Assert - In view mode, textarea should not be present, Markdown renders instead + // Assert - In view mode, textarea should not be present, Markdown renders instead + // Assert - In view mode, textarea should not be present, Markdown renders instead + // Assert - In view mode, textarea should not be present, Markdown renders instead + // Assert - In view mode, textarea should not be present, Markdown renders instead + // Assert - In view mode, textarea should not be present, Markdown renders instead + // Assert - In view mode, textarea should not be present, Markdown renders instead + // Assert - In view mode, textarea should not be present, Markdown renders instead + // Assert - In view mode, textarea should not be present, Markdown renders instead + // Assert - In view mode, textarea should not be present, Markdown renders instead + // Assert - In view mode, textarea should not be present, Markdown renders instead + // Assert - In view mode, textarea should not be present, Markdown renders instead + // Assert - In view mode, textarea should not be present, Markdown renders instead + // Assert - In view mode, textarea should not be present, Markdown renders instead + // Assert - In view mode, textarea should not be present, Markdown renders instead + // Assert - In view mode, textarea should not be present, Markdown renders instead // Assert - In view mode, textarea should not be present, Markdown renders instead expect(container.querySelector('textarea')).not.toBeInTheDocument() }) @@ -66,8 +97,9 @@ describe('ChunkContent', () => { ) // Assert - QA mode has QUESTION and ANSWER labels - expect(screen.getByText('QUESTION')).toBeInTheDocument() - expect(screen.getByText('ANSWER')).toBeInTheDocument() + // Assert - QA mode has QUESTION and ANSWER labels + expect(screen.getByText('QUESTION'))!.toBeInTheDocument() + expect(screen.getByText('ANSWER'))!.toBeInTheDocument() }) it('should display question value in QA mode', () => { @@ -83,7 +115,7 @@ describe('ChunkContent', () => { ) const textareas = screen.getAllByRole('textbox') - expect(textareas[0]).toHaveValue('My question') + expect(textareas[0])!.toHaveValue('My question') }) it('should display answer value in QA mode', () => { @@ -99,7 +131,7 @@ describe('ChunkContent', () => { ) const textareas = screen.getAllByRole('textbox') - expect(textareas[1]).toHaveValue('My answer') + expect(textareas[1])!.toHaveValue('My answer') }) }) @@ -133,7 +165,7 @@ describe('ChunkContent', () => { ) const textareas = screen.getAllByRole('textbox') - fireEvent.change(textareas[0], { target: { value: 'New question' } }) + fireEvent.change(textareas[0]!, { target: { value: 'New question' } }) expect(mockOnQuestionChange).toHaveBeenCalledWith('New question') }) @@ -151,7 +183,7 @@ describe('ChunkContent', () => { ) const textareas = screen.getAllByRole('textbox') - fireEvent.change(textareas[1], { target: { value: 'New answer' } }) + fireEvent.change(textareas[1]!, { target: { value: 'New answer' } }) expect(mockOnAnswerChange).toHaveBeenCalledWith('New answer') }) @@ -161,6 +193,37 @@ describe('ChunkContent', () => { , ) + // Assert - In view mode, Markdown is rendered instead of textarea + // Assert - In view mode, Markdown is rendered instead of textarea + // Assert - In view mode, Markdown is rendered instead of textarea + // Assert - In view mode, Markdown is rendered instead of textarea + // Assert - In view mode, Markdown is rendered instead of textarea + // Assert - In view mode, Markdown is rendered instead of textarea + // Assert - In view mode, Markdown is rendered instead of textarea + // Assert - In view mode, Markdown is rendered instead of textarea + // Assert - In view mode, Markdown is rendered instead of textarea + // Assert - In view mode, Markdown is rendered instead of textarea + // Assert - In view mode, Markdown is rendered instead of textarea + // Assert - In view mode, Markdown is rendered instead of textarea + // Assert - In view mode, Markdown is rendered instead of textarea + // Assert - In view mode, Markdown is rendered instead of textarea + // Assert - In view mode, Markdown is rendered instead of textarea + // Assert - In view mode, Markdown is rendered instead of textarea + // Assert - In view mode, Markdown is rendered instead of textarea + // Assert - In view mode, Markdown is rendered instead of textarea + // Assert - In view mode, Markdown is rendered instead of textarea + // Assert - In view mode, Markdown is rendered instead of textarea + // Assert - In view mode, Markdown is rendered instead of textarea + // Assert - In view mode, Markdown is rendered instead of textarea + // Assert - In view mode, Markdown is rendered instead of textarea + // Assert - In view mode, Markdown is rendered instead of textarea + // Assert - In view mode, Markdown is rendered instead of textarea + // Assert - In view mode, Markdown is rendered instead of textarea + // Assert - In view mode, Markdown is rendered instead of textarea + // Assert - In view mode, Markdown is rendered instead of textarea + // Assert - In view mode, Markdown is rendered instead of textarea + // Assert - In view mode, Markdown is rendered instead of textarea + // Assert - In view mode, Markdown is rendered instead of textarea // Assert - In view mode, Markdown is rendered instead of textarea expect(container.querySelector('textarea')).not.toBeInTheDocument() }) @@ -178,7 +241,7 @@ describe('ChunkContent', () => { const textareas = screen.getAllByRole('textbox') textareas.forEach((textarea) => { - expect(textarea).toBeDisabled() + expect(textarea)!.toBeDisabled() }) }) }) @@ -188,7 +251,7 @@ describe('ChunkContent', () => { it('should handle ChunkingMode.text', () => { render() - expect(screen.getByRole('textbox')).toBeInTheDocument() + expect(screen.getByRole('textbox'))!.toBeInTheDocument() }) it('should handle ChunkingMode.qa', () => { @@ -203,8 +266,9 @@ describe('ChunkContent', () => { ) // Assert - QA mode should show both question and answer - expect(screen.getByText('QUESTION')).toBeInTheDocument() - expect(screen.getByText('ANSWER')).toBeInTheDocument() + // Assert - QA mode should show both question and answer + expect(screen.getByText('QUESTION'))!.toBeInTheDocument() + expect(screen.getByText('ANSWER'))!.toBeInTheDocument() }) it('should handle ChunkingMode.parentChild similar to text mode', () => { @@ -217,7 +281,8 @@ describe('ChunkContent', () => { ) // Assert - parentChild should render like text mode - expect(screen.getByRole('textbox')).toBeInTheDocument() + // Assert - parentChild should render like text mode + expect(screen.getByRole('textbox'))!.toBeInTheDocument() }) }) @@ -232,7 +297,7 @@ describe('ChunkContent', () => { ) const textarea = screen.getByRole('textbox') - expect(textarea).toHaveValue('') + expect(textarea)!.toHaveValue('') }) it('should handle empty answer in QA mode', () => { @@ -248,7 +313,7 @@ describe('ChunkContent', () => { ) const textareas = screen.getAllByRole('textbox') - expect(textareas[1]).toHaveValue('') + expect(textareas[1])!.toHaveValue('') }) it('should handle undefined answer in QA mode', () => { @@ -261,7 +326,8 @@ describe('ChunkContent', () => { ) // Assert - should render without crashing - expect(screen.getByText('QUESTION')).toBeInTheDocument() + // Assert - should render without crashing + expect(screen.getByText('QUESTION'))!.toBeInTheDocument() }) it('should maintain structure when rerendered', () => { @@ -274,7 +340,7 @@ describe('ChunkContent', () => { ) const textarea = screen.getByRole('textbox') - expect(textarea).toHaveValue('Updated') + expect(textarea)!.toHaveValue('Updated') }) }) }) diff --git a/web/app/components/datasets/documents/detail/completed/components/segment-list-content.tsx b/web/app/components/datasets/documents/detail/completed/components/segment-list-content.tsx index 116ba38856..d675763843 100644 --- a/web/app/components/datasets/documents/detail/completed/components/segment-list-content.tsx +++ b/web/app/components/datasets/documents/detail/completed/components/segment-list-content.tsx @@ -49,7 +49,7 @@ export const FullDocModeContent: FC = ({ > onClickCard(firstSegment)} + onClick={() => onClickCard(firstSegment!)} loading={isLoadingSegmentList} focused={{ segmentIndex: currSegmentId === firstSegment?.id, @@ -57,7 +57,7 @@ export const FullDocModeContent: FC = ({ }} /> { expect(updateSegmentInCache).toHaveBeenCalledWith('seg-1', expect.any(Function)) // Verify the updater function filters correctly - const updaterFn = updateSegmentInCache.mock.calls[0][1] + const updaterFn = updateSegmentInCache.mock.calls[0]![1] const testSegment = createMockSegment({ child_chunks: [ createMockChildChunk({ id: 'child-1' }), @@ -499,7 +499,7 @@ describe('useChildSegmentData', () => { expect(updateSegmentInCache).toHaveBeenCalledWith('seg-1', expect.any(Function)) // Verify the updater function maps correctly - const updaterFn = updateSegmentInCache.mock.calls[0][1] + const updaterFn = updateSegmentInCache.mock.calls[0]![1] const testSegment = createMockSegment({ child_chunks: [ createMockChildChunk({ id: 'child-1', content: 'old content' }), @@ -564,8 +564,8 @@ describe('useChildSegmentData', () => { total: 2, total_pages: 1, }) as ChildSegmentsResponse - expect(resultWithData.data[0].content).toBe('new content') - expect(resultWithData.data[1].content).toBe('other') + expect(resultWithData.data[0]!.content).toBe('new content') + expect(resultWithData.data[1]!.content).toBe('other') } }) diff --git a/web/app/components/datasets/documents/detail/completed/segment-list.tsx b/web/app/components/datasets/documents/detail/completed/segment-list.tsx index 9e5f0ab2fe..3a554fc0b6 100644 --- a/web/app/components/datasets/documents/detail/completed/segment-list.tsx +++ b/web/app/components/datasets/documents/detail/completed/segment-list.tsx @@ -71,7 +71,7 @@ const SegmentList = (
{ items.map((segItem) => { - const isLast = items[items.length - 1].id === segItem.id + const isLast = items[items.length - 1]!.id === segItem.id const segmentIndexFocused = currSegment?.segInfo?.id === segItem.id || (!currSegment && currChildChunk?.childChunkInfo?.segment_id === segItem.id) diff --git a/web/app/components/datasets/documents/detail/embedding/hooks/__tests__/use-embedding-status.spec.tsx b/web/app/components/datasets/documents/detail/embedding/hooks/__tests__/use-embedding-status.spec.tsx index 893484afeb..149d0a60ea 100644 --- a/web/app/components/datasets/documents/detail/embedding/hooks/__tests__/use-embedding-status.spec.tsx +++ b/web/app/components/datasets/documents/detail/embedding/hooks/__tests__/use-embedding-status.spec.tsx @@ -342,7 +342,7 @@ describe('use-embedding-status', () => { await waitFor(() => { expect(onError).toHaveBeenCalled() - expect(onError.mock.calls[0][0]).toEqual(error) + expect(onError.mock.calls[0]![0]).toEqual(error) }) }) }) diff --git a/web/app/components/datasets/documents/detail/metadata/__tests__/index.spec.tsx b/web/app/components/datasets/documents/detail/metadata/__tests__/index.spec.tsx index 2d60e5f322..5b268e554c 100644 --- a/web/app/components/datasets/documents/detail/metadata/__tests__/index.spec.tsx +++ b/web/app/components/datasets/documents/detail/metadata/__tests__/index.spec.tsx @@ -181,24 +181,55 @@ describe('Metadata', () => { it('should render without crashing', () => { const { container } = render() - expect(container.firstChild).toBeInTheDocument() + expect(container.firstChild)!.toBeInTheDocument() }) it('should render metadata title', () => { render() - expect(screen.getByText(/metadata\.title/i)).toBeInTheDocument() + expect(screen.getByText(/metadata\.title/i))!.toBeInTheDocument() }) it('should render edit button', () => { render() - expect(screen.getByText(/operation\.edit/i)).toBeInTheDocument() + expect(screen.getByText(/operation\.edit/i))!.toBeInTheDocument() }) it('should show loading state', () => { render() + // Assert - Loading component should be rendered, title should not + // Assert - Loading component should be rendered, title should not + // Assert - Loading component should be rendered, title should not + // Assert - Loading component should be rendered, title should not + // Assert - Loading component should be rendered, title should not + // Assert - Loading component should be rendered, title should not + // Assert - Loading component should be rendered, title should not + // Assert - Loading component should be rendered, title should not + // Assert - Loading component should be rendered, title should not + // Assert - Loading component should be rendered, title should not + // Assert - Loading component should be rendered, title should not + // Assert - Loading component should be rendered, title should not + // Assert - Loading component should be rendered, title should not + // Assert - Loading component should be rendered, title should not + // Assert - Loading component should be rendered, title should not + // Assert - Loading component should be rendered, title should not + // Assert - Loading component should be rendered, title should not + // Assert - Loading component should be rendered, title should not + // Assert - Loading component should be rendered, title should not + // Assert - Loading component should be rendered, title should not + // Assert - Loading component should be rendered, title should not + // Assert - Loading component should be rendered, title should not + // Assert - Loading component should be rendered, title should not + // Assert - Loading component should be rendered, title should not + // Assert - Loading component should be rendered, title should not + // Assert - Loading component should be rendered, title should not + // Assert - Loading component should be rendered, title should not + // Assert - Loading component should be rendered, title should not + // Assert - Loading component should be rendered, title should not + // Assert - Loading component should be rendered, title should not + // Assert - Loading component should be rendered, title should not // Assert - Loading component should be rendered, title should not expect(screen.queryByText(/metadata\.title/i)).not.toBeInTheDocument() }) @@ -206,7 +237,7 @@ describe('Metadata', () => { it('should display document type icon and text', () => { render() - expect(screen.getByText('Book')).toBeInTheDocument() + expect(screen.getByText('Book'))!.toBeInTheDocument() }) }) @@ -217,8 +248,8 @@ describe('Metadata', () => { fireEvent.click(screen.getByText(/operation\.edit/i)) - expect(screen.getByText(/operation\.cancel/i)).toBeInTheDocument() - expect(screen.getByText(/operation\.save/i)).toBeInTheDocument() + expect(screen.getByText(/operation\.cancel/i))!.toBeInTheDocument() + expect(screen.getByText(/operation\.save/i))!.toBeInTheDocument() }) it('should show change link in edit mode', () => { @@ -226,7 +257,7 @@ describe('Metadata', () => { fireEvent.click(screen.getByText(/operation\.edit/i)) - expect(screen.getByText(/operation\.change/i)).toBeInTheDocument() + expect(screen.getByText(/operation\.change/i))!.toBeInTheDocument() }) it('should cancel edit and restore values when cancel is clicked', () => { @@ -238,7 +269,8 @@ describe('Metadata', () => { fireEvent.click(screen.getByText(/operation\.cancel/i)) // Assert - should be back to view mode - expect(screen.getByText(/operation\.edit/i)).toBeInTheDocument() + // Assert - should be back to view mode + expect(screen.getByText(/operation\.edit/i))!.toBeInTheDocument() }) it('should save metadata when save button is clicked', async () => { @@ -299,7 +331,7 @@ describe('Metadata', () => { render() - expect(screen.getByText(/metadata\.docTypeSelectTitle/i)).toBeInTheDocument() + expect(screen.getByText(/metadata\.docTypeSelectTitle/i))!.toBeInTheDocument() }) it('should show description when no doc_type exists', () => { @@ -307,7 +339,7 @@ describe('Metadata', () => { render() - expect(screen.getByText(/metadata\.desc/i)).toBeInTheDocument() + expect(screen.getByText(/metadata\.desc/i))!.toBeInTheDocument() }) it('should show change link in edit mode when doc_type exists', () => { @@ -316,7 +348,7 @@ describe('Metadata', () => { // Enter edit mode fireEvent.click(screen.getByText(/operation\.edit/i)) - expect(screen.getByText(/operation\.change/i)).toBeInTheDocument() + expect(screen.getByText(/operation\.change/i))!.toBeInTheDocument() }) it('should show doc type change title after clicking change', () => { @@ -327,7 +359,7 @@ describe('Metadata', () => { fireEvent.click(screen.getByText(/operation\.change/i)) - expect(screen.getByText(/metadata\.docTypeChangeTitle/i)).toBeInTheDocument() + expect(screen.getByText(/metadata\.docTypeChangeTitle/i))!.toBeInTheDocument() }) }) @@ -337,14 +369,15 @@ describe('Metadata', () => { render() // Assert - expect(screen.getByText('Data Source Type')).toBeInTheDocument() + // Assert + expect(screen.getByText('Data Source Type'))!.toBeInTheDocument() }) it('should render technical parameters fields', () => { render() - expect(screen.getByText('Segment Count')).toBeInTheDocument() - expect(screen.getByText('Hit Count')).toBeInTheDocument() + expect(screen.getByText('Segment Count'))!.toBeInTheDocument() + expect(screen.getByText('Hit Count'))!.toBeInTheDocument() }) }) @@ -355,27 +388,30 @@ describe('Metadata', () => { const { container } = render() // Assert - expect(container.firstChild).toBeInTheDocument() + // Assert + expect(container.firstChild)!.toBeInTheDocument() }) it('should handle undefined docDetail gracefully', () => { const { container } = render() // Assert - expect(container.firstChild).toBeInTheDocument() + // Assert + expect(container.firstChild)!.toBeInTheDocument() }) it('should update document type display when docDetail changes', () => { const { rerender } = render() // Act - verify initial state shows Book - expect(screen.getByText('Book')).toBeInTheDocument() + // Act - verify initial state shows Book + expect(screen.getByText('Book'))!.toBeInTheDocument() // Update with new doc type const updatedDocDetail = createMockDocDetail({ doc_type: 'paper' }) rerender() - expect(screen.getByText('Paper')).toBeInTheDocument() + expect(screen.getByText('Paper'))!.toBeInTheDocument() }) }) @@ -386,7 +422,7 @@ describe('Metadata', () => { render() - expect(screen.getByText(/metadata\.firstMetaAction/i)).toBeInTheDocument() + expect(screen.getByText(/metadata\.firstMetaAction/i))!.toBeInTheDocument() }) }) }) @@ -407,19 +443,19 @@ describe('FieldInfo', () => { it('should render without crashing', () => { const { container } = render() - expect(container.firstChild).toBeInTheDocument() + expect(container.firstChild)!.toBeInTheDocument() }) it('should render label', () => { render() - expect(screen.getByText('Test Label')).toBeInTheDocument() + expect(screen.getByText('Test Label'))!.toBeInTheDocument() }) it('should render displayed value in view mode', () => { render() - expect(screen.getByText('Test Display Value')).toBeInTheDocument() + expect(screen.getByText('Test Display Value'))!.toBeInTheDocument() }) }) @@ -428,7 +464,7 @@ describe('FieldInfo', () => { it('should render input when showEdit is true and inputType is input', () => { render() - expect(screen.getByRole('textbox')).toBeInTheDocument() + expect(screen.getByRole('textbox'))!.toBeInTheDocument() }) it('should render select when showEdit is true and inputType is select', () => { @@ -443,13 +479,14 @@ describe('FieldInfo', () => { ) // Assert - SimpleSelect should be rendered - expect(screen.getByRole('button')).toBeInTheDocument() + // Assert - SimpleSelect should be rendered + expect(screen.getByRole('button'))!.toBeInTheDocument() }) it('should render textarea when showEdit is true and inputType is textarea', () => { render() - expect(screen.getByRole('textbox')).toBeInTheDocument() + expect(screen.getByRole('textbox'))!.toBeInTheDocument() }) it('should call onUpdate when input value changes', () => { @@ -476,14 +513,14 @@ describe('FieldInfo', () => { it('should render value icon when provided', () => { render(Icon} />) - expect(screen.getByTestId('value-icon')).toBeInTheDocument() + expect(screen.getByTestId('value-icon'))!.toBeInTheDocument() }) it('should use defaultValue when provided', () => { render() const input = screen.getByRole('textbox') - expect(input).toHaveAttribute('placeholder') + expect(input)!.toHaveAttribute('placeholder') }) }) }) @@ -510,13 +547,15 @@ describe('useMetadataState coverage', () => { fireEvent.click(screen.getByText(/operation\.change/i)) // Now in doc type selector mode — should show cancel button - expect(screen.getByText(/operation\.cancel/i)).toBeInTheDocument() + // Now in doc type selector mode — should show cancel button + expect(screen.getByText(/operation\.cancel/i))!.toBeInTheDocument() // Act — cancel the doc type change fireEvent.click(screen.getByText(/operation\.cancel/i)) // Assert — should be back to edit mode (cancel + save buttons visible) - expect(screen.getByText(/operation\.save/i)).toBeInTheDocument() + // Assert — should be back to edit mode (cancel + save buttons visible) + expect(screen.getByText(/operation\.save/i))!.toBeInTheDocument() }) }) @@ -530,14 +569,16 @@ describe('useMetadataState coverage', () => { fireEvent.click(screen.getByText(/operation\.change/i)) // DocTypeSelector shows save/cancel buttons - expect(screen.getByText(/metadata\.docTypeChangeTitle/i)).toBeInTheDocument() + // DocTypeSelector shows save/cancel buttons + expect(screen.getByText(/metadata\.docTypeChangeTitle/i))!.toBeInTheDocument() // Act — click save to confirm same doc type (tempDocType='book') fireEvent.click(screen.getByText(/operation\.save/i)) // Assert — should return to edit mode with metadata fields visible - expect(screen.getByText(/operation\.cancel/i)).toBeInTheDocument() - expect(screen.getByText(/operation\.save/i)).toBeInTheDocument() + // Assert — should return to edit mode with metadata fields visible + expect(screen.getByText(/operation\.cancel/i))!.toBeInTheDocument() + expect(screen.getByText(/operation\.save/i))!.toBeInTheDocument() }) }) @@ -551,17 +592,20 @@ describe('useMetadataState coverage', () => { // 'others' is normalized to '' → useEffect fires (doc_type truthy) → view mode // The rendered type uses default 'book' fallback for display - expect(screen.getByText(/operation\.edit/i)).toBeInTheDocument() + // 'others' is normalized to '' → useEffect fires (doc_type truthy) → view mode + // The rendered type uses default 'book' fallback for display + expect(screen.getByText(/operation\.edit/i))!.toBeInTheDocument() // Enter edit mode fireEvent.click(screen.getByText(/operation\.edit/i)) - expect(screen.getByText(/operation\.cancel/i)).toBeInTheDocument() + expect(screen.getByText(/operation\.cancel/i))!.toBeInTheDocument() // Act — cancel edit; internally docType is '' so cancelEdit goes to showDocTypes fireEvent.click(screen.getByText(/operation\.cancel/i)) // Assert — should show doc type selection since normalized docType was '' - expect(screen.getByText(/metadata\.docTypeSelectTitle/i)).toBeInTheDocument() + // Assert — should show doc type selection since normalized docType was '' + expect(screen.getByText(/metadata\.docTypeSelectTitle/i))!.toBeInTheDocument() }) }) @@ -576,10 +620,11 @@ describe('useMetadataState coverage', () => { // Act — find an input and change its value (Title field) const inputs = screen.getAllByRole('textbox') expect(inputs.length).toBeGreaterThan(0) - fireEvent.change(inputs[0], { target: { value: 'Updated Title' } }) + fireEvent.change(inputs[0]!, { target: { value: 'Updated Title' } }) // Assert — the input should have the new value - expect(inputs[0]).toHaveValue('Updated Title') + // Assert — the input should have the new value + expect(inputs[0])!.toHaveValue('Updated Title') }) }) @@ -629,7 +674,8 @@ describe('useMetadataState coverage', () => { ) // Assert — should render without crashing, showing Paper type - expect(screen.getByText('Paper')).toBeInTheDocument() + // Assert — should render without crashing, showing Paper type + expect(screen.getByText('Paper'))!.toBeInTheDocument() }) }) }) diff --git a/web/app/components/datasets/documents/detail/metadata/components/__tests__/metadata-field-list.spec.tsx b/web/app/components/datasets/documents/detail/metadata/components/__tests__/metadata-field-list.spec.tsx index cc5b16fc3e..9f07c06d77 100644 --- a/web/app/components/datasets/documents/detail/metadata/components/__tests__/metadata-field-list.spec.tsx +++ b/web/app/components/datasets/documents/detail/metadata/components/__tests__/metadata-field-list.spec.tsx @@ -42,9 +42,9 @@ describe('MetadataFieldList', () => { />, ) - expect(screen.getByText('Title')).toBeInTheDocument() - expect(screen.getByText('Language')).toBeInTheDocument() - expect(screen.getByText('Author')).toBeInTheDocument() + expect(screen.getByText('Title'))!.toBeInTheDocument() + expect(screen.getByText('Language'))!.toBeInTheDocument() + expect(screen.getByText('Author'))!.toBeInTheDocument() }) it('should return null when mainField is empty', () => { @@ -76,7 +76,7 @@ describe('MetadataFieldList', () => { />, ) - expect(screen.getByText('English')).toBeInTheDocument() + expect(screen.getByText('English'))!.toBeInTheDocument() }) }) @@ -109,7 +109,7 @@ describe('MetadataFieldList', () => { // Find the first textbox and type in it const inputs = screen.getAllByRole('textbox') - fireEvent.change(inputs[0], { target: { value: 'New Title' } }) + fireEvent.change(inputs[0]!, { target: { value: 'New Title' } }) expect(onUpdate).toHaveBeenCalled() }) @@ -128,8 +128,8 @@ describe('MetadataFieldList', () => { />, ) - expect(screen.getByText('Source')).toBeInTheDocument() - expect(screen.getByText('Web')).toBeInTheDocument() + expect(screen.getByText('Source'))!.toBeInTheDocument() + expect(screen.getByText('Web'))!.toBeInTheDocument() }) it('should render custom render function output for fields with render', () => { @@ -143,7 +143,7 @@ describe('MetadataFieldList', () => { />, ) - expect(screen.getByText('15 / 5')).toBeInTheDocument() + expect(screen.getByText('15 / 5'))!.toBeInTheDocument() }) }) }) diff --git a/web/app/components/datasets/documents/detail/metadata/components/metadata-field-list.tsx b/web/app/components/datasets/documents/detail/metadata/components/metadata-field-list.tsx index 9f452279ed..03af49359d 100644 --- a/web/app/components/datasets/documents/detail/metadata/components/metadata-field-list.tsx +++ b/web/app/components/datasets/documents/detail/metadata/components/metadata-field-list.tsx @@ -7,7 +7,7 @@ import { useBookCategories, useBusinessDocCategories, useLanguages, useMetadataM import FieldInfo from './field-info' const map2Options = (map: Record) => { - return Object.keys(map).map(key => ({ value: key, name: map[key] })) + return Object.keys(map).map(key => ({ value: key, name: map[key]! })) } function useCategoryMapResolver(mainField: metadataType | '') { @@ -72,7 +72,7 @@ const MetadataFieldList: FC = ({ {Object.keys(fieldMap).map(field => ( { }) await waitFor(() => expect(onUrlUpdate).toHaveBeenCalled()) - const update = onUrlUpdate.mock.calls[onUrlUpdate.mock.calls.length - 1][0] + const update = onUrlUpdate.mock.calls[onUrlUpdate.mock.calls.length - 1]![0] expect(update.searchParams.get('page')).toBe('2') expect(update.options.history).toBe('push') }) @@ -177,7 +177,7 @@ describe('useDocumentListQueryState', () => { }) await waitFor(() => expect(onUrlUpdate).toHaveBeenCalled()) - const update = onUrlUpdate.mock.calls[onUrlUpdate.mock.calls.length - 1][0] + const update = onUrlUpdate.mock.calls[onUrlUpdate.mock.calls.length - 1]![0] expect(update.searchParams.get('status')).toBe('error') }) @@ -189,7 +189,7 @@ describe('useDocumentListQueryState', () => { }) await waitFor(() => expect(onUrlUpdate).toHaveBeenCalled()) - const update = onUrlUpdate.mock.calls[onUrlUpdate.mock.calls.length - 1][0] + const update = onUrlUpdate.mock.calls[onUrlUpdate.mock.calls.length - 1]![0] expect(update.searchParams.has('status')).toBe(false) }) @@ -201,7 +201,7 @@ describe('useDocumentListQueryState', () => { }) await waitFor(() => expect(onUrlUpdate).toHaveBeenCalled()) - const update = onUrlUpdate.mock.calls[onUrlUpdate.mock.calls.length - 1][0] + const update = onUrlUpdate.mock.calls[onUrlUpdate.mock.calls.length - 1]![0] expect(update.searchParams.get('sort')).toBe('hit_count') }) @@ -213,7 +213,7 @@ describe('useDocumentListQueryState', () => { }) await waitFor(() => expect(onUrlUpdate).toHaveBeenCalled()) - const update = onUrlUpdate.mock.calls[onUrlUpdate.mock.calls.length - 1][0] + const update = onUrlUpdate.mock.calls[onUrlUpdate.mock.calls.length - 1]![0] expect(update.searchParams.has('sort')).toBe(false) }) @@ -225,7 +225,7 @@ describe('useDocumentListQueryState', () => { }) await waitFor(() => expect(onUrlUpdate).toHaveBeenCalled()) - const update = onUrlUpdate.mock.calls[onUrlUpdate.mock.calls.length - 1][0] + const update = onUrlUpdate.mock.calls[onUrlUpdate.mock.calls.length - 1]![0] expect(update.searchParams.get('keyword')).toBe('test query') expect(update.options.history).toBe('replace') }) @@ -238,7 +238,7 @@ describe('useDocumentListQueryState', () => { }) await waitFor(() => expect(onUrlUpdate).toHaveBeenCalled()) - const update = onUrlUpdate.mock.calls[onUrlUpdate.mock.calls.length - 1][0] + const update = onUrlUpdate.mock.calls[onUrlUpdate.mock.calls.length - 1]![0] expect(update.searchParams.get('keyword')).toBe('hello') expect(update.searchParams.has('page')).toBe(false) expect(update.options.history).toBe('replace') @@ -252,7 +252,7 @@ describe('useDocumentListQueryState', () => { }) await waitFor(() => expect(onUrlUpdate).toHaveBeenCalled()) - const update = onUrlUpdate.mock.calls[onUrlUpdate.mock.calls.length - 1][0] + const update = onUrlUpdate.mock.calls[onUrlUpdate.mock.calls.length - 1]![0] expect(update.searchParams.has('keyword')).toBe(false) expect(update.options.history).toBe('replace') }) @@ -265,7 +265,7 @@ describe('useDocumentListQueryState', () => { }) await waitFor(() => expect(onUrlUpdate).toHaveBeenCalled()) - const update = onUrlUpdate.mock.calls[onUrlUpdate.mock.calls.length - 1][0] + const update = onUrlUpdate.mock.calls[onUrlUpdate.mock.calls.length - 1]![0] expect(update.searchParams.has('keyword')).toBe(false) expect(result.current.query.keyword).toBe('') }) @@ -278,7 +278,7 @@ describe('useDocumentListQueryState', () => { }) await waitFor(() => expect(onUrlUpdate).toHaveBeenCalled()) - const update = onUrlUpdate.mock.calls[onUrlUpdate.mock.calls.length - 1][0] + const update = onUrlUpdate.mock.calls[onUrlUpdate.mock.calls.length - 1]![0] expect(update.searchParams.get('keyword')).toBe('%2F') expect(result.current.query.keyword).toBe('%2F') }) @@ -302,7 +302,7 @@ describe('useDocumentListQueryState', () => { }) await waitFor(() => expect(onUrlUpdate).toHaveBeenCalled()) - const update = onUrlUpdate.mock.calls[onUrlUpdate.mock.calls.length - 1][0] + const update = onUrlUpdate.mock.calls[onUrlUpdate.mock.calls.length - 1]![0] expect(update.searchParams.has('status')).toBe(false) }) @@ -314,7 +314,7 @@ describe('useDocumentListQueryState', () => { }) await waitFor(() => expect(onUrlUpdate).toHaveBeenCalled()) - const update = onUrlUpdate.mock.calls[onUrlUpdate.mock.calls.length - 1][0] + const update = onUrlUpdate.mock.calls[onUrlUpdate.mock.calls.length - 1]![0] expect(update.searchParams.has('sort')).toBe(false) }) @@ -326,7 +326,7 @@ describe('useDocumentListQueryState', () => { }) await waitFor(() => expect(onUrlUpdate).toHaveBeenCalled()) - const update = onUrlUpdate.mock.calls[onUrlUpdate.mock.calls.length - 1][0] + const update = onUrlUpdate.mock.calls[onUrlUpdate.mock.calls.length - 1]![0] expect(update.searchParams.has('page')).toBe(false) }) @@ -338,7 +338,7 @@ describe('useDocumentListQueryState', () => { }) await waitFor(() => expect(onUrlUpdate).toHaveBeenCalled()) - const update = onUrlUpdate.mock.calls[onUrlUpdate.mock.calls.length - 1][0] + const update = onUrlUpdate.mock.calls[onUrlUpdate.mock.calls.length - 1]![0] expect(update.searchParams.get('page')).toBe('2') }) @@ -350,7 +350,7 @@ describe('useDocumentListQueryState', () => { }) await waitFor(() => expect(onUrlUpdate).toHaveBeenCalled()) - const update = onUrlUpdate.mock.calls[onUrlUpdate.mock.calls.length - 1][0] + const update = onUrlUpdate.mock.calls[onUrlUpdate.mock.calls.length - 1]![0] expect(update.searchParams.get('limit')).toBe('25') }) @@ -362,7 +362,7 @@ describe('useDocumentListQueryState', () => { }) await waitFor(() => expect(onUrlUpdate).toHaveBeenCalled()) - const update = onUrlUpdate.mock.calls[onUrlUpdate.mock.calls.length - 1][0] + const update = onUrlUpdate.mock.calls[onUrlUpdate.mock.calls.length - 1]![0] expect(update.searchParams.has('page')).toBe(false) expect(result.current.query.page).toBe(1) }) @@ -375,7 +375,7 @@ describe('useDocumentListQueryState', () => { }) await waitFor(() => expect(onUrlUpdate).toHaveBeenCalled()) - const update = onUrlUpdate.mock.calls[onUrlUpdate.mock.calls.length - 1][0] + const update = onUrlUpdate.mock.calls[onUrlUpdate.mock.calls.length - 1]![0] expect(update.searchParams.has('limit')).toBe(false) expect(result.current.query.limit).toBe(10) }) @@ -406,7 +406,7 @@ describe('useDocumentListQueryState', () => { }) await waitFor(() => expect(onUrlUpdate).toHaveBeenCalled()) - const update = onUrlUpdate.mock.calls[onUrlUpdate.mock.calls.length - 1][0] + const update = onUrlUpdate.mock.calls[onUrlUpdate.mock.calls.length - 1]![0] expect(update.searchParams.has('page')).toBe(false) expect(update.searchParams.has('status')).toBe(false) }) diff --git a/web/app/components/datasets/external-api/external-api-modal/__tests__/index.spec.tsx b/web/app/components/datasets/external-api/external-api-modal/__tests__/index.spec.tsx index 73579db413..e24712887a 100644 --- a/web/app/components/datasets/external-api/external-api-modal/__tests__/index.spec.tsx +++ b/web/app/components/datasets/external-api/external-api-modal/__tests__/index.spec.tsx @@ -46,42 +46,42 @@ describe('AddExternalAPIModal', () => { describe('Rendering', () => { it('should render without crashing', () => { render() - expect(screen.getByText('dataset.createExternalAPI')).toBeInTheDocument() + expect(screen.getByText('dataset.createExternalAPI'))!.toBeInTheDocument() }) it('should render create title when not in edit mode', () => { render() - expect(screen.getByText('dataset.createExternalAPI')).toBeInTheDocument() + expect(screen.getByText('dataset.createExternalAPI'))!.toBeInTheDocument() }) it('should render edit title when in edit mode', () => { render() - expect(screen.getByText('dataset.editExternalAPIFormTitle')).toBeInTheDocument() + expect(screen.getByText('dataset.editExternalAPIFormTitle'))!.toBeInTheDocument() }) it('should render form fields', () => { render() - expect(screen.getByLabelText(/name/i)).toBeInTheDocument() - expect(screen.getByLabelText(/api endpoint/i)).toBeInTheDocument() - expect(screen.getByLabelText(/api key/i)).toBeInTheDocument() + expect(screen.getByLabelText(/name/i))!.toBeInTheDocument() + expect(screen.getByLabelText(/api endpoint/i))!.toBeInTheDocument() + expect(screen.getByLabelText(/api key/i))!.toBeInTheDocument() }) it('should render cancel and save buttons', () => { render() - expect(screen.getByText('dataset.externalAPIForm.cancel')).toBeInTheDocument() - expect(screen.getByText('dataset.externalAPIForm.save')).toBeInTheDocument() + expect(screen.getByText('dataset.externalAPIForm.cancel'))!.toBeInTheDocument() + expect(screen.getByText('dataset.externalAPIForm.save'))!.toBeInTheDocument() }) it('should render encryption notice', () => { render() - expect(screen.getByText('PKCS1_OAEP')).toBeInTheDocument() + expect(screen.getByText('PKCS1_OAEP'))!.toBeInTheDocument() }) it('should render close button', () => { render() // Close button is rendered in a portal const closeButton = document.body.querySelector('.action-btn') - expect(closeButton).toBeInTheDocument() + expect(closeButton)!.toBeInTheDocument() }) }) @@ -99,7 +99,7 @@ describe('AddExternalAPIModal', () => { datasetBindings={datasetBindings} />, ) - expect(screen.getByText('dataset.editExternalAPIFormWarning.front')).toBeInTheDocument() + expect(screen.getByText('dataset.editExternalAPIFormWarning.front'))!.toBeInTheDocument() // Verify the count is displayed in the warning section const warningElement = screen.getByText('dataset.editExternalAPIFormWarning.front').parentElement expect(warningElement?.textContent).toContain('2') @@ -124,22 +124,22 @@ describe('AddExternalAPIModal', () => { const nameInput = screen.getByLabelText(/name/i) fireEvent.change(nameInput, { target: { value: 'New API Name' } }) - expect(nameInput).toHaveValue('New API Name') + expect(nameInput)!.toHaveValue('New API Name') }) it('should initialize form with data in edit mode', () => { render() - expect(screen.getByLabelText(/name/i)).toHaveValue('Test API') - expect(screen.getByLabelText(/api endpoint/i)).toHaveValue('https://api.example.com') - expect(screen.getByLabelText(/api key/i)).toHaveValue('test-key-12345') + expect(screen.getByLabelText(/name/i))!.toHaveValue('Test API') + expect(screen.getByLabelText(/api endpoint/i))!.toHaveValue('https://api.example.com') + expect(screen.getByLabelText(/api key/i))!.toHaveValue('test-key-12345') }) it('should disable save button when form has empty inputs', () => { render() const saveButton = screen.getByText('dataset.externalAPIForm.save').closest('button') - expect(saveButton).toBeDisabled() + expect(saveButton)!.toBeDisabled() }) it('should enable save button when all fields are filled', () => { @@ -302,7 +302,7 @@ describe('AddExternalAPIModal', () => { fireEvent.click(saveButton) await waitFor(() => { - expect(screen.getByRole('button', { name: /confirm/i })).toBeInTheDocument() + expect(screen.getByRole('button', { name: /confirm/i }))!.toBeInTheDocument() }) }) @@ -334,7 +334,7 @@ describe('AddExternalAPIModal', () => { fireEvent.click(saveButton) await waitFor(() => { - expect(screen.getByRole('button', { name: /confirm/i })).toBeInTheDocument() + expect(screen.getByRole('button', { name: /confirm/i }))!.toBeInTheDocument() }) const confirmButton = screen.getByRole('button', { name: /confirm/i }) @@ -363,13 +363,13 @@ describe('AddExternalAPIModal', () => { fireEvent.click(saveButton) await waitFor(() => { - expect(screen.getByRole('button', { name: /confirm/i })).toBeInTheDocument() + expect(screen.getByRole('button', { name: /confirm/i }))!.toBeInTheDocument() }) // There are multiple cancel buttons, find the one in the confirm dialog const cancelButtons = screen.getAllByRole('button', { name: /cancel/i }) const confirmDialogCancelButton = cancelButtons[cancelButtons.length - 1] - fireEvent.click(confirmDialogCancelButton) + fireEvent.click(confirmDialogCancelButton!) await waitFor(() => { // Confirm button should be gone after canceling @@ -404,7 +404,7 @@ describe('AddExternalAPIModal', () => { describe('Edge Cases', () => { it('should handle undefined data in edit mode', () => { render() - expect(screen.getByLabelText(/name/i)).toHaveValue('') + expect(screen.getByLabelText(/name/i))!.toHaveValue('') }) it('should handle null datasetBindings', () => { @@ -422,8 +422,8 @@ describe('AddExternalAPIModal', () => { it('should render documentation link in encryption notice', () => { render() const link = screen.getByRole('link', { name: 'PKCS1_OAEP' }) - expect(link).toHaveAttribute('href', 'https://pycryptodome.readthedocs.io/en/latest/src/cipher/oaep.html') - expect(link).toHaveAttribute('target', '_blank') + expect(link)!.toHaveAttribute('href', 'https://pycryptodome.readthedocs.io/en/latest/src/cipher/oaep.html') + expect(link)!.toHaveAttribute('target', '_blank') }) }) }) diff --git a/web/app/components/datasets/external-api/external-api-panel/__tests__/index.spec.tsx b/web/app/components/datasets/external-api/external-api-panel/__tests__/index.spec.tsx index eb7c0558ac..964b8fe344 100644 --- a/web/app/components/datasets/external-api/external-api-panel/__tests__/index.spec.tsx +++ b/web/app/components/datasets/external-api/external-api-panel/__tests__/index.spec.tsx @@ -50,31 +50,31 @@ describe('ExternalAPIPanel', () => { describe('Rendering', () => { it('should render without crashing', () => { render() - expect(screen.getByText('dataset.externalAPIPanelTitle')).toBeInTheDocument() + expect(screen.getByText('dataset.externalAPIPanelTitle'))!.toBeInTheDocument() }) it('should render panel title and description', () => { render() - expect(screen.getByText('dataset.externalAPIPanelTitle')).toBeInTheDocument() - expect(screen.getByText('dataset.externalAPIPanelDescription')).toBeInTheDocument() + expect(screen.getByText('dataset.externalAPIPanelTitle'))!.toBeInTheDocument() + expect(screen.getByText('dataset.externalAPIPanelDescription'))!.toBeInTheDocument() }) it('should render documentation link', () => { render() const docLink = screen.getByText('dataset.externalAPIPanelDocumentation') - expect(docLink).toBeInTheDocument() - expect(docLink.closest('a')).toHaveAttribute('href', 'https://docs.example.com/use-dify/knowledge/external-knowledge-api') + expect(docLink)!.toBeInTheDocument() + expect(docLink.closest('a'))!.toHaveAttribute('href', 'https://docs.example.com/use-dify/knowledge/external-knowledge-api') }) it('should render create button', () => { render() - expect(screen.getByText('dataset.createExternalAPI')).toBeInTheDocument() + expect(screen.getByText('dataset.createExternalAPI'))!.toBeInTheDocument() }) it('should render close button', () => { const { container } = render() const closeButton = container.querySelector('[class*="action-button"]') || screen.getAllByRole('button')[0] - expect(closeButton).toBeInTheDocument() + expect(closeButton)!.toBeInTheDocument() }) }) @@ -121,10 +121,10 @@ describe('ExternalAPIPanel', () => { }, ] render() - expect(screen.getByTestId('api-card-api-1')).toBeInTheDocument() - expect(screen.getByTestId('api-card-api-2')).toBeInTheDocument() - expect(screen.getByText('Test API 1')).toBeInTheDocument() - expect(screen.getByText('Test API 2')).toBeInTheDocument() + expect(screen.getByTestId('api-card-api-1'))!.toBeInTheDocument() + expect(screen.getByTestId('api-card-api-2'))!.toBeInTheDocument() + expect(screen.getByText('Test API 1'))!.toBeInTheDocument() + expect(screen.getByText('Test API 2'))!.toBeInTheDocument() }) }) @@ -136,7 +136,7 @@ describe('ExternalAPIPanel', () => { const buttons = screen.getAllByRole('button') const closeButton = buttons.find(btn => btn.querySelector('svg[class*="ri-close"]')) || buttons[0] - fireEvent.click(closeButton) + fireEvent.click(closeButton!) expect(onClose).toHaveBeenCalledTimes(1) }) @@ -162,7 +162,7 @@ describe('ExternalAPIPanel', () => { const createButton = screen.getByText('dataset.createExternalAPI').closest('button')! fireEvent.click(createButton) - const callArgs = mockSetShowExternalKnowledgeAPIModal.mock.calls[0][0] + const callArgs = mockSetShowExternalKnowledgeAPIModal.mock.calls[0]![0] callArgs.onSaveCallback() expect(mockMutateExternalKnowledgeApis).toHaveBeenCalled() @@ -173,7 +173,7 @@ describe('ExternalAPIPanel', () => { const createButton = screen.getByText('dataset.createExternalAPI').closest('button')! fireEvent.click(createButton) - const callArgs = mockSetShowExternalKnowledgeAPIModal.mock.calls[0][0] + const callArgs = mockSetShowExternalKnowledgeAPIModal.mock.calls[0]![0] callArgs.onCancelCallback() expect(mockMutateExternalKnowledgeApis).toHaveBeenCalled() @@ -195,13 +195,13 @@ describe('ExternalAPIPanel', () => { }, ] render() - expect(screen.getByTestId('api-card-single-api')).toBeInTheDocument() + expect(screen.getByTestId('api-card-single-api'))!.toBeInTheDocument() }) it('should render documentation link with correct target', () => { render() const docLink = screen.getByText('dataset.externalAPIPanelDocumentation').closest('a') - expect(docLink).toHaveAttribute('target', '_blank') + expect(docLink)!.toHaveAttribute('target', '_blank') }) }) }) diff --git a/web/app/components/datasets/external-api/external-knowledge-api-card/__tests__/index.spec.tsx b/web/app/components/datasets/external-api/external-knowledge-api-card/__tests__/index.spec.tsx index bc1c923876..6dfd8ff13d 100644 --- a/web/app/components/datasets/external-api/external-knowledge-api-card/__tests__/index.spec.tsx +++ b/web/app/components/datasets/external-api/external-knowledge-api-card/__tests__/index.spec.tsx @@ -56,17 +56,17 @@ describe('ExternalKnowledgeAPICard', () => { describe('Rendering', () => { it('should render without crashing', () => { render() - expect(screen.getByText('Test External API')).toBeInTheDocument() + expect(screen.getByText('Test External API'))!.toBeInTheDocument() }) it('should render API name', () => { render() - expect(screen.getByText('Test External API')).toBeInTheDocument() + expect(screen.getByText('Test External API'))!.toBeInTheDocument() }) it('should render API endpoint', () => { render() - expect(screen.getByText('https://api.example.com/knowledge')).toBeInTheDocument() + expect(screen.getByText('https://api.example.com/knowledge'))!.toBeInTheDocument() }) it('should render edit and delete buttons', () => { @@ -78,7 +78,7 @@ describe('ExternalKnowledgeAPICard', () => { it('should render API connection icon', () => { const { container } = render() const icon = container.querySelector('svg') - expect(icon).toBeInTheDocument() + expect(icon)!.toBeInTheDocument() }) }) @@ -103,7 +103,7 @@ describe('ExternalKnowledgeAPICard', () => { const buttons = container.querySelectorAll('button') const editButton = buttons[0] - fireEvent.click(editButton) + fireEvent.click(editButton!) await waitFor(() => { expect(fetchExternalAPI).toHaveBeenCalledWith({ apiTemplateId: 'api-123' }) @@ -131,7 +131,7 @@ describe('ExternalKnowledgeAPICard', () => { const buttons = container.querySelectorAll('button') const editButton = buttons[0] - fireEvent.click(editButton) + fireEvent.click(editButton!) await waitFor(() => { expect(consoleSpy).toHaveBeenCalledWith( @@ -162,14 +162,14 @@ describe('ExternalKnowledgeAPICard', () => { const { container } = render() const editButton = container.querySelectorAll('button')[0] - fireEvent.click(editButton) + fireEvent.click(editButton!) await waitFor(() => { expect(mockSetShowExternalKnowledgeAPIModal).toHaveBeenCalled() }) // Simulate save callback - const modalCall = mockSetShowExternalKnowledgeAPIModal.mock.calls[0][0] + const modalCall = mockSetShowExternalKnowledgeAPIModal.mock.calls[0]![0] modalCall.onSaveCallback() expect(mockMutateExternalKnowledgeApis).toHaveBeenCalled() @@ -194,14 +194,14 @@ describe('ExternalKnowledgeAPICard', () => { const { container } = render() const editButton = container.querySelectorAll('button')[0] - fireEvent.click(editButton) + fireEvent.click(editButton!) await waitFor(() => { expect(mockSetShowExternalKnowledgeAPIModal).toHaveBeenCalled() }) // Simulate cancel callback - const modalCall = mockSetShowExternalKnowledgeAPIModal.mock.calls[0][0] + const modalCall = mockSetShowExternalKnowledgeAPIModal.mock.calls[0]![0] modalCall.onCancelCallback() expect(mockMutateExternalKnowledgeApis).toHaveBeenCalled() @@ -216,7 +216,7 @@ describe('ExternalKnowledgeAPICard', () => { const buttons = container.querySelectorAll('button') const deleteButton = buttons[1] - fireEvent.click(deleteButton) + fireEvent.click(deleteButton!) await waitFor(() => { expect(checkUsageExternalAPI).toHaveBeenCalledWith({ apiTemplateId: 'api-123' }) @@ -224,7 +224,7 @@ describe('ExternalKnowledgeAPICard', () => { // Confirm dialog should be shown await waitFor(() => { - expect(screen.getByRole('button', { name: /cancel/i })).toBeInTheDocument() + expect(screen.getByRole('button', { name: /cancel/i }))!.toBeInTheDocument() }) }) @@ -234,10 +234,10 @@ describe('ExternalKnowledgeAPICard', () => { const { container } = render() const deleteButton = container.querySelectorAll('button')[1] - fireEvent.click(deleteButton) + fireEvent.click(deleteButton!) await waitFor(() => { - expect(screen.getByText(/3/)).toBeInTheDocument() + expect(screen.getByText(/3/))!.toBeInTheDocument() }) }) @@ -248,10 +248,10 @@ describe('ExternalKnowledgeAPICard', () => { const { container } = render() const deleteButton = container.querySelectorAll('button')[1] - fireEvent.click(deleteButton) + fireEvent.click(deleteButton!) await waitFor(() => { - expect(screen.getByRole('button', { name: /confirm/i })).toBeInTheDocument() + expect(screen.getByRole('button', { name: /confirm/i }))!.toBeInTheDocument() }) const confirmButton = screen.getByRole('button', { name: /confirm/i }) @@ -269,10 +269,10 @@ describe('ExternalKnowledgeAPICard', () => { const { container } = render() const deleteButton = container.querySelectorAll('button')[1] - fireEvent.click(deleteButton) + fireEvent.click(deleteButton!) await waitFor(() => { - expect(screen.getByRole('button', { name: /cancel/i })).toBeInTheDocument() + expect(screen.getByRole('button', { name: /cancel/i }))!.toBeInTheDocument() }) const cancelButton = screen.getByRole('button', { name: /cancel/i }) @@ -291,10 +291,10 @@ describe('ExternalKnowledgeAPICard', () => { const { container } = render() const deleteButton = container.querySelectorAll('button')[1] - fireEvent.click(deleteButton) + fireEvent.click(deleteButton!) await waitFor(() => { - expect(screen.getByRole('button', { name: /confirm/i })).toBeInTheDocument() + expect(screen.getByRole('button', { name: /confirm/i }))!.toBeInTheDocument() }) const confirmButton = screen.getByRole('button', { name: /confirm/i }) @@ -317,7 +317,7 @@ describe('ExternalKnowledgeAPICard', () => { const { container } = render() const deleteButton = container.querySelectorAll('button')[1] - fireEvent.click(deleteButton) + fireEvent.click(deleteButton!) await waitFor(() => { expect(consoleSpy).toHaveBeenCalledWith( @@ -336,11 +336,11 @@ describe('ExternalKnowledgeAPICard', () => { const deleteButton = container.querySelectorAll('button')[1] const cardContainer = container.querySelector('[class*="shadows-shadow"]') - fireEvent.mouseEnter(deleteButton) - expect(cardContainer).toHaveClass('border-state-destructive-border') - expect(cardContainer).toHaveClass('bg-state-destructive-hover') + fireEvent.mouseEnter(deleteButton!) + expect(cardContainer)!.toHaveClass('border-state-destructive-border') + expect(cardContainer)!.toHaveClass('bg-state-destructive-hover') - fireEvent.mouseLeave(deleteButton) + fireEvent.mouseLeave(deleteButton!) expect(cardContainer).not.toHaveClass('border-state-destructive-border') }) }) @@ -352,7 +352,7 @@ describe('ExternalKnowledgeAPICard', () => { settings: { endpoint: '', api_key: 'key' }, } render() - expect(screen.getByText('Test External API')).toBeInTheDocument() + expect(screen.getByText('Test External API'))!.toBeInTheDocument() }) it('should handle delete response with unsuccessful result', async () => { @@ -363,10 +363,10 @@ describe('ExternalKnowledgeAPICard', () => { const { container } = render() const deleteButton = container.querySelectorAll('button')[1] - fireEvent.click(deleteButton) + fireEvent.click(deleteButton!) await waitFor(() => { - expect(screen.getByRole('button', { name: /confirm/i })).toBeInTheDocument() + expect(screen.getByRole('button', { name: /confirm/i }))!.toBeInTheDocument() }) const confirmButton = screen.getByRole('button', { name: /confirm/i }) diff --git a/web/app/components/datasets/external-knowledge-base/create/ExternalApiSelection.tsx b/web/app/components/datasets/external-knowledge-base/create/ExternalApiSelection.tsx index 387bf9843c..fea71a7e78 100644 --- a/web/app/components/datasets/external-knowledge-base/create/ExternalApiSelection.tsx +++ b/web/app/components/datasets/external-knowledge-base/create/ExternalApiSelection.tsx @@ -33,7 +33,7 @@ const ExternalApiSelection: React.FC = ({ external_kn useEffect(() => { if (apiItems.length > 0) { - const newSelectedId = external_knowledge_api_id || apiItems[0].value + const newSelectedId = external_knowledge_api_id || apiItems[0]!.value setSelectedApiId(newSelectedId) if (newSelectedId !== external_knowledge_api_id) onChange({ external_knowledge_api_id: newSelectedId, external_knowledge_id }) @@ -56,7 +56,7 @@ const ExternalApiSelection: React.FC = ({ external_kn useEffect(() => { if (!external_knowledge_api_id && apiItems.length > 0) - onChange({ external_knowledge_api_id: apiItems[0].value, external_knowledge_id }) + onChange({ external_knowledge_api_id: apiItems[0]!.value, external_knowledge_id }) }, []) return ( diff --git a/web/app/components/datasets/external-knowledge-base/create/__tests__/index.spec.tsx b/web/app/components/datasets/external-knowledge-base/create/__tests__/index.spec.tsx index a3282e441c..f132def602 100644 --- a/web/app/components/datasets/external-knowledge-base/create/__tests__/index.spec.tsx +++ b/web/app/components/datasets/external-knowledge-base/create/__tests__/index.spec.tsx @@ -90,64 +90,68 @@ describe('ExternalKnowledgeBaseCreate', () => { it('should render without crashing', () => { renderComponent() - expect(screen.getByText('dataset.connectDataset')).toBeInTheDocument() + expect(screen.getByText('dataset.connectDataset'))!.toBeInTheDocument() }) it('should render KnowledgeBaseInfo component with correct labels', () => { renderComponent() // KnowledgeBaseInfo renders these labels - expect(screen.getByText('dataset.externalKnowledgeName')).toBeInTheDocument() - expect(screen.getByText('dataset.externalKnowledgeDescription')).toBeInTheDocument() + // KnowledgeBaseInfo renders these labels + expect(screen.getByText('dataset.externalKnowledgeName'))!.toBeInTheDocument() + expect(screen.getByText('dataset.externalKnowledgeDescription'))!.toBeInTheDocument() }) it('should render ExternalApiSelection component', () => { renderComponent() // ExternalApiSelection renders this label - expect(screen.getByText('dataset.externalAPIPanelTitle')).toBeInTheDocument() - expect(screen.getByText('dataset.externalKnowledgeId')).toBeInTheDocument() + // ExternalApiSelection renders this label + expect(screen.getByText('dataset.externalAPIPanelTitle'))!.toBeInTheDocument() + expect(screen.getByText('dataset.externalKnowledgeId'))!.toBeInTheDocument() }) it('should render RetrievalSettings component', () => { renderComponent() // RetrievalSettings renders this label - expect(screen.getByText('dataset.retrievalSettings')).toBeInTheDocument() + // RetrievalSettings renders this label + expect(screen.getByText('dataset.retrievalSettings'))!.toBeInTheDocument() }) it('should render InfoPanel component', () => { renderComponent() // InfoPanel renders these texts - expect(screen.getByText('dataset.connectDatasetIntro.title')).toBeInTheDocument() - expect(screen.getByText('dataset.connectDatasetIntro.learnMore')).toBeInTheDocument() + // InfoPanel renders these texts + expect(screen.getByText('dataset.connectDatasetIntro.title'))!.toBeInTheDocument() + expect(screen.getByText('dataset.connectDatasetIntro.learnMore'))!.toBeInTheDocument() }) it('should render helper text with translation keys', () => { renderComponent() - expect(screen.getByText('dataset.connectHelper.helper1')).toBeInTheDocument() - expect(screen.getByText('dataset.connectHelper.helper2')).toBeInTheDocument() - expect(screen.getByText('dataset.connectHelper.helper3')).toBeInTheDocument() - expect(screen.getByText('dataset.connectHelper.helper4')).toBeInTheDocument() - expect(screen.getByText('dataset.connectHelper.helper5')).toBeInTheDocument() + expect(screen.getByText('dataset.connectHelper.helper1'))!.toBeInTheDocument() + expect(screen.getByText('dataset.connectHelper.helper2'))!.toBeInTheDocument() + expect(screen.getByText('dataset.connectHelper.helper3'))!.toBeInTheDocument() + expect(screen.getByText('dataset.connectHelper.helper4'))!.toBeInTheDocument() + expect(screen.getByText('dataset.connectHelper.helper5'))!.toBeInTheDocument() }) it('should render cancel and connect buttons', () => { renderComponent() - expect(screen.getByText('dataset.externalKnowledgeForm.cancel')).toBeInTheDocument() - expect(screen.getByText('dataset.externalKnowledgeForm.connect')).toBeInTheDocument() + expect(screen.getByText('dataset.externalKnowledgeForm.cancel'))!.toBeInTheDocument() + expect(screen.getByText('dataset.externalKnowledgeForm.connect'))!.toBeInTheDocument() }) it('should render documentation link with correct href', () => { renderComponent() const docLink = screen.getByText('dataset.connectHelper.helper4') - expect(docLink).toHaveAttribute('href', 'https://docs.dify.ai/en/use-dify/knowledge/connect-external-knowledge-base') - expect(docLink).toHaveAttribute('target', '_blank') - expect(docLink).toHaveAttribute('rel', 'noopener noreferrer') + expect(docLink)!.toHaveAttribute('href', 'https://docs.dify.ai/en/use-dify/knowledge/connect-external-knowledge-base') + expect(docLink)!.toHaveAttribute('target', '_blank') + expect(docLink)!.toHaveAttribute('rel', 'noopener noreferrer') }) }) @@ -157,7 +161,7 @@ describe('ExternalKnowledgeBaseCreate', () => { renderComponent({ loading: true }) const connectButton = screen.getByText('dataset.externalKnowledgeForm.connect').closest('button') - expect(connectButton).toBeInTheDocument() + expect(connectButton)!.toBeInTheDocument() }) it('should call onConnect with form data when connect button is clicked', async () => { @@ -198,7 +202,7 @@ describe('ExternalKnowledgeBaseCreate', () => { renderComponent({ onConnect }) const connectButton = screen.getByText('dataset.externalKnowledgeForm.connect').closest('button') - expect(connectButton).toBeDisabled() + expect(connectButton)!.toBeDisabled() await user.click(connectButton!) expect(onConnect).not.toHaveBeenCalled() @@ -280,7 +284,7 @@ describe('ExternalKnowledgeBaseCreate', () => { fireEvent.change(knowledgeIdInput, { target: { value: 'knowledge-456' } }) const connectButton = screen.getByText('dataset.externalKnowledgeForm.connect').closest('button') - expect(connectButton).toBeDisabled() + expect(connectButton)!.toBeDisabled() }) it('should disable connect button when name is only whitespace', async () => { @@ -293,7 +297,7 @@ describe('ExternalKnowledgeBaseCreate', () => { fireEvent.change(knowledgeIdInput, { target: { value: 'knowledge-456' } }) const connectButton = screen.getByText('dataset.externalKnowledgeForm.connect').closest('button') - expect(connectButton).toBeDisabled() + expect(connectButton)!.toBeDisabled() }) it('should disable connect button when external_knowledge_id is empty', () => { @@ -303,7 +307,7 @@ describe('ExternalKnowledgeBaseCreate', () => { fireEvent.change(nameInput, { target: { value: 'Test Name' } }) const connectButton = screen.getByText('dataset.externalKnowledgeForm.connect').closest('button') - expect(connectButton).toBeDisabled() + expect(connectButton)!.toBeDisabled() }) it('should enable connect button when all required fields are filled', async () => { @@ -429,7 +433,8 @@ describe('ExternalKnowledgeBaseCreate', () => { renderComponent() // The ExternalApiSelect should show the first selected API name - expect(screen.getByText('Test API 1')).toBeInTheDocument() + // The ExternalApiSelect should show the first selected API name + expect(screen.getByText('Test API 1'))!.toBeInTheDocument() }) it('should allow selecting different API from dropdown', async () => { @@ -473,7 +478,8 @@ describe('ExternalKnowledgeBaseCreate', () => { renderComponent() // Should show "no external knowledge" button - expect(screen.getByText('dataset.noExternalKnowledge')).toBeInTheDocument() + // Should show "no external knowledge" button + expect(screen.getByText('dataset.noExternalKnowledge'))!.toBeInTheDocument() }) it('should open add API modal when add button is clicked', async () => { @@ -504,7 +510,7 @@ describe('ExternalKnowledgeBaseCreate', () => { await user.click(addButton!) // Get the callback and invoke it - const modalCall = mockSetShowExternalKnowledgeAPIModal.mock.calls[0][0] + const modalCall = mockSetShowExternalKnowledgeAPIModal.mock.calls[0]![0] await modalCall.onSaveCallback() expect(mockMutateExternalKnowledgeApis).toHaveBeenCalled() @@ -521,7 +527,7 @@ describe('ExternalKnowledgeBaseCreate', () => { await user.click(addButton!) // Get the callback and invoke it - const modalCall = mockSetShowExternalKnowledgeAPIModal.mock.calls[0][0] + const modalCall = mockSetShowExternalKnowledgeAPIModal.mock.calls[0]![0] modalCall.onCancelCallback() expect(mockMutateExternalKnowledgeApis).toHaveBeenCalled() @@ -535,8 +541,9 @@ describe('ExternalKnowledgeBaseCreate', () => { await user.click(apiSelector) // Should show API URLs - expect(screen.getByText('https://api1.example.com')).toBeInTheDocument() - expect(screen.getByText('https://api2.example.com')).toBeInTheDocument() + // Should show API URLs + expect(screen.getByText('https://api1.example.com'))!.toBeInTheDocument() + expect(screen.getByText('https://api2.example.com'))!.toBeInTheDocument() }) it('should show create new API option in dropdown', async () => { @@ -547,7 +554,8 @@ describe('ExternalKnowledgeBaseCreate', () => { await user.click(apiSelector) // Should show create new API option - expect(screen.getByText('dataset.createNewExternalAPI')).toBeInTheDocument() + // Should show create new API option + expect(screen.getByText('dataset.createNewExternalAPI'))!.toBeInTheDocument() }) it('should open add API modal when clicking create new API in dropdown', async () => { @@ -580,7 +588,7 @@ describe('ExternalKnowledgeBaseCreate', () => { await user.click(createNewApiOption) // Get the callback from the modal call and invoke it - const modalCall = mockSetShowExternalKnowledgeAPIModal.mock.calls[0][0] + const modalCall = mockSetShowExternalKnowledgeAPIModal.mock.calls[0]![0] await modalCall.onSaveCallback() expect(mockMutateExternalKnowledgeApis).toHaveBeenCalled() @@ -598,7 +606,7 @@ describe('ExternalKnowledgeBaseCreate', () => { await user.click(createNewApiOption) // Get the callback from the modal call and invoke it - const modalCall = mockSetShowExternalKnowledgeAPIModal.mock.calls[0][0] + const modalCall = mockSetShowExternalKnowledgeAPIModal.mock.calls[0]![0] modalCall.onCancelCallback() expect(mockMutateExternalKnowledgeApis).toHaveBeenCalled() @@ -612,12 +620,44 @@ describe('ExternalKnowledgeBaseCreate', () => { await user.click(apiSelector) // Dropdown should be open - API URLs visible - expect(screen.getByText('https://api1.example.com')).toBeInTheDocument() + // Dropdown should be open - API URLs visible + expect(screen.getByText('https://api1.example.com'))!.toBeInTheDocument() // Select the second API const secondApi = screen.getByText('Test API 2') await user.click(secondApi) + // Dropdown should be closed - API URLs not visible + // Dropdown should be closed - API URLs not visible + // Dropdown should be closed - API URLs not visible + // Dropdown should be closed - API URLs not visible + // Dropdown should be closed - API URLs not visible + // Dropdown should be closed - API URLs not visible + // Dropdown should be closed - API URLs not visible + // Dropdown should be closed - API URLs not visible + // Dropdown should be closed - API URLs not visible + // Dropdown should be closed - API URLs not visible + // Dropdown should be closed - API URLs not visible + // Dropdown should be closed - API URLs not visible + // Dropdown should be closed - API URLs not visible + // Dropdown should be closed - API URLs not visible + // Dropdown should be closed - API URLs not visible + // Dropdown should be closed - API URLs not visible + // Dropdown should be closed - API URLs not visible + // Dropdown should be closed - API URLs not visible + // Dropdown should be closed - API URLs not visible + // Dropdown should be closed - API URLs not visible + // Dropdown should be closed - API URLs not visible + // Dropdown should be closed - API URLs not visible + // Dropdown should be closed - API URLs not visible + // Dropdown should be closed - API URLs not visible + // Dropdown should be closed - API URLs not visible + // Dropdown should be closed - API URLs not visible + // Dropdown should be closed - API URLs not visible + // Dropdown should be closed - API URLs not visible + // Dropdown should be closed - API URLs not visible + // Dropdown should be closed - API URLs not visible + // Dropdown should be closed - API URLs not visible // Dropdown should be closed - API URLs not visible expect(screen.queryByText('https://api1.example.com')).not.toBeInTheDocument() }) @@ -628,7 +668,7 @@ describe('ExternalKnowledgeBaseCreate', () => { const apiSelector = screen.getByText('Test API 1') await user.click(apiSelector) - expect(screen.getByText('https://api1.example.com')).toBeInTheDocument() + expect(screen.getByText('https://api1.example.com'))!.toBeInTheDocument() await user.click(apiSelector) expect(screen.queryByText('https://api1.example.com')).not.toBeInTheDocument() @@ -783,14 +823,14 @@ describe('ExternalKnowledgeBaseCreate', () => { renderComponent({ loading: true }) const connectButton = screen.getByText('dataset.externalKnowledgeForm.connect').closest('button') - expect(connectButton).toBeInTheDocument() + expect(connectButton)!.toBeInTheDocument() }) it('should render correctly when not loading', () => { renderComponent({ loading: false }) const connectButton = screen.getByText('dataset.externalKnowledgeForm.connect').closest('button') - expect(connectButton).toBeInTheDocument() + expect(connectButton)!.toBeInTheDocument() }) }) @@ -804,7 +844,7 @@ describe('ExternalKnowledgeBaseCreate', () => { // Find and click the switch for score threshold const switches = screen.getAllByRole('switch') const scoreThresholdSwitch = switches[0] // The score threshold switch - await user.click(scoreThresholdSwitch) + await user.click(scoreThresholdSwitch!) // Fill required fields const nameInput = screen.getByPlaceholderText('dataset.externalKnowledgeNamePlaceholder') @@ -834,10 +874,12 @@ describe('ExternalKnowledgeBaseCreate', () => { renderComponent() // Should show the retrieval settings section title - expect(screen.getByText('dataset.retrievalSettings')).toBeInTheDocument() + // Should show the retrieval settings section title + expect(screen.getByText('dataset.retrievalSettings'))!.toBeInTheDocument() // Should show Top K and Score Threshold labels - expect(screen.getByText('appDebug.datasetConfig.top_k')).toBeInTheDocument() - expect(screen.getByText('appDebug.datasetConfig.score_threshold')).toBeInTheDocument() + // Should show Top K and Score Threshold labels + expect(screen.getByText('appDebug.datasetConfig.top_k'))!.toBeInTheDocument() + expect(screen.getByText('appDebug.datasetConfig.score_threshold'))!.toBeInTheDocument() }) }) @@ -855,6 +897,37 @@ describe('ExternalKnowledgeBaseCreate', () => { />, ) + // In hit testing mode, the title should not be shown + // In hit testing mode, the title should not be shown + // In hit testing mode, the title should not be shown + // In hit testing mode, the title should not be shown + // In hit testing mode, the title should not be shown + // In hit testing mode, the title should not be shown + // In hit testing mode, the title should not be shown + // In hit testing mode, the title should not be shown + // In hit testing mode, the title should not be shown + // In hit testing mode, the title should not be shown + // In hit testing mode, the title should not be shown + // In hit testing mode, the title should not be shown + // In hit testing mode, the title should not be shown + // In hit testing mode, the title should not be shown + // In hit testing mode, the title should not be shown + // In hit testing mode, the title should not be shown + // In hit testing mode, the title should not be shown + // In hit testing mode, the title should not be shown + // In hit testing mode, the title should not be shown + // In hit testing mode, the title should not be shown + // In hit testing mode, the title should not be shown + // In hit testing mode, the title should not be shown + // In hit testing mode, the title should not be shown + // In hit testing mode, the title should not be shown + // In hit testing mode, the title should not be shown + // In hit testing mode, the title should not be shown + // In hit testing mode, the title should not be shown + // In hit testing mode, the title should not be shown + // In hit testing mode, the title should not be shown + // In hit testing mode, the title should not be shown + // In hit testing mode, the title should not be shown // In hit testing mode, the title should not be shown expect(screen.queryByText('dataset.retrievalSettings')).not.toBeInTheDocument() }) @@ -871,6 +944,37 @@ describe('ExternalKnowledgeBaseCreate', () => { />, ) + // In retrieval setting mode, the title should not be shown + // In retrieval setting mode, the title should not be shown + // In retrieval setting mode, the title should not be shown + // In retrieval setting mode, the title should not be shown + // In retrieval setting mode, the title should not be shown + // In retrieval setting mode, the title should not be shown + // In retrieval setting mode, the title should not be shown + // In retrieval setting mode, the title should not be shown + // In retrieval setting mode, the title should not be shown + // In retrieval setting mode, the title should not be shown + // In retrieval setting mode, the title should not be shown + // In retrieval setting mode, the title should not be shown + // In retrieval setting mode, the title should not be shown + // In retrieval setting mode, the title should not be shown + // In retrieval setting mode, the title should not be shown + // In retrieval setting mode, the title should not be shown + // In retrieval setting mode, the title should not be shown + // In retrieval setting mode, the title should not be shown + // In retrieval setting mode, the title should not be shown + // In retrieval setting mode, the title should not be shown + // In retrieval setting mode, the title should not be shown + // In retrieval setting mode, the title should not be shown + // In retrieval setting mode, the title should not be shown + // In retrieval setting mode, the title should not be shown + // In retrieval setting mode, the title should not be shown + // In retrieval setting mode, the title should not be shown + // In retrieval setting mode, the title should not be shown + // In retrieval setting mode, the title should not be shown + // In retrieval setting mode, the title should not be shown + // In retrieval setting mode, the title should not be shown + // In retrieval setting mode, the title should not be shown // In retrieval setting mode, the title should not be shown expect(screen.queryByText('dataset.retrievalSettings')).not.toBeInTheDocument() }) @@ -889,7 +993,7 @@ describe('ExternalKnowledgeBaseCreate', () => { // Find and click the switch const switches = screen.getAllByRole('switch') - await user.click(switches[0]) + await user.click(switches[0]!) expect(onChange).toHaveBeenCalledWith({ score_threshold_enabled: true }) }) @@ -908,7 +1012,7 @@ describe('ExternalKnowledgeBaseCreate', () => { // The TopKItem renders the visible number-field input as a textbox. const inputs = screen.getAllByRole('textbox') const topKInput = inputs[0] - fireEvent.change(topKInput, { target: { value: '8' } }) + fireEvent.change(topKInput!, { target: { value: '8' } }) expect(onChange).toHaveBeenCalledWith({ top_k: 8 }) }) @@ -927,7 +1031,7 @@ describe('ExternalKnowledgeBaseCreate', () => { // The ScoreThresholdItem renders the visible number-field input as a textbox. const inputs = screen.getAllByRole('textbox') const scoreThresholdInput = inputs[1] - fireEvent.change(scoreThresholdInput, { target: { value: '0.8' } }) + fireEvent.change(scoreThresholdInput!, { target: { value: '0.8' } }) expect(onChange).toHaveBeenCalledWith({ score_threshold: 0.8 }) }) @@ -976,7 +1080,7 @@ describe('ExternalKnowledgeBaseCreate', () => { // Toggle score threshold switch const switches = screen.getAllByRole('switch') const scoreThresholdSwitch = switches[0] - await user.click(scoreThresholdSwitch) + await user.click(scoreThresholdSwitch!) // Fill required fields const nameInput = screen.getByPlaceholderText('dataset.externalKnowledgeNamePlaceholder') @@ -1018,17 +1122,18 @@ describe('ExternalKnowledgeBaseCreate', () => { const externalLink = screen.getByText('dataset.connectHelper.helper4') expect(externalLink.tagName).toBe('A') - expect(externalLink).toHaveAttribute('target', '_blank') - expect(externalLink).toHaveAttribute('rel', 'noopener noreferrer') + expect(externalLink)!.toHaveAttribute('target', '_blank') + expect(externalLink)!.toHaveAttribute('rel', 'noopener noreferrer') }) it('should have labels for form inputs', () => { renderComponent() // Check labels exist - expect(screen.getByText('dataset.externalKnowledgeName')).toBeInTheDocument() - expect(screen.getByText('dataset.externalKnowledgeDescription')).toBeInTheDocument() - expect(screen.getByText('dataset.externalKnowledgeId')).toBeInTheDocument() + // Check labels exist + expect(screen.getByText('dataset.externalKnowledgeName'))!.toBeInTheDocument() + expect(screen.getByText('dataset.externalKnowledgeDescription'))!.toBeInTheDocument() + expect(screen.getByText('dataset.externalKnowledgeId'))!.toBeInTheDocument() }) }) }) diff --git a/web/app/components/datasets/hit-testing/__tests__/index.spec.tsx b/web/app/components/datasets/hit-testing/__tests__/index.spec.tsx index 2dda6ecaae..df0e39554a 100644 --- a/web/app/components/datasets/hit-testing/__tests__/index.spec.tsx +++ b/web/app/components/datasets/hit-testing/__tests__/index.spec.tsx @@ -309,25 +309,26 @@ describe('HitTestingPage', () => { describe('Rendering', () => { it('should render without crashing', () => { const { container } = renderWithProviders() - expect(container.firstChild).toBeInTheDocument() + expect(container.firstChild)!.toBeInTheDocument() }) it('should render page title', () => { renderWithProviders() // Look for heading element const heading = screen.getByRole('heading', { level: 1 }) - expect(heading).toBeInTheDocument() + expect(heading)!.toBeInTheDocument() }) it('should render records section', () => { const { container } = renderWithProviders() // The records section should be present - expect(container.querySelector('.flex-col')).toBeInTheDocument() + // The records section should be present + expect(container.querySelector('.flex-col'))!.toBeInTheDocument() }) it('should render query input', () => { renderWithProviders() - expect(screen.getByRole('textbox')).toBeInTheDocument() + expect(screen.getByRole('textbox'))!.toBeInTheDocument() }) }) @@ -343,7 +344,7 @@ describe('HitTestingPage', () => { const { container } = renderWithProviders() // Loading component should be visible - look for the loading animation const loadingElement = container.querySelector('[class*="animate"]') || container.querySelector('.flex-1') - expect(loadingElement).toBeInTheDocument() + expect(loadingElement)!.toBeInTheDocument() }) }) @@ -353,7 +354,7 @@ describe('HitTestingPage', () => { // EmptyRecords component should be rendered - check that the component is mounted // The EmptyRecords has a specific structure with bg-workflow-process-bg class const mainContainer = container.querySelector('.flex.h-full') - expect(mainContainer).toBeInTheDocument() + expect(mainContainer)!.toBeInTheDocument() }) }) @@ -373,7 +374,7 @@ describe('HitTestingPage', () => { } as unknown as ReturnType) renderWithProviders() - expect(screen.getByText('Test query')).toBeInTheDocument() + expect(screen.getByText('Test query'))!.toBeInTheDocument() }) }) @@ -404,7 +405,7 @@ describe('HitTestingPage', () => { const { container } = renderWithProviders() // The right panel should be present (on non-mobile) const rightPanel = container.querySelector('.rounded-tl-2xl') - expect(rightPanel).toBeInTheDocument() + expect(rightPanel)!.toBeInTheDocument() }) }) @@ -423,7 +424,8 @@ describe('HitTestingPage', () => { fireEvent.click(methodSelector) // The component should still be functional after the click - expect(container.firstChild).toBeInTheDocument() + // The component should still be functional after the click + expect(container.firstChild)!.toBeInTheDocument() }) }) @@ -445,7 +447,8 @@ describe('HitTestingPage', () => { const { container } = renderWithProviders() // The right panel should show empty state initially - expect(container.querySelector('.rounded-tl-2xl')).toBeInTheDocument() + // The right panel should show empty state initially + expect(container.querySelector('.rounded-tl-2xl'))!.toBeInTheDocument() }) it('should render loading skeleton when retrieval is in progress', async () => { @@ -458,7 +461,8 @@ describe('HitTestingPage', () => { const { container } = renderWithProviders() // Component should render without crashing - expect(container.firstChild).toBeInTheDocument() + // Component should render without crashing + expect(container.firstChild)!.toBeInTheDocument() }) it('should render results when hit testing returns data', async () => { @@ -479,7 +483,8 @@ describe('HitTestingPage', () => { const { container } = renderWithProviders() // The component should render the result display area - expect(container.querySelector('.bg-background-body')).toBeInTheDocument() + // The component should render the result display area + expect(container.querySelector('.bg-background-body'))!.toBeInTheDocument() }) }) @@ -513,7 +518,8 @@ describe('HitTestingPage', () => { fireEvent.click(row) // The query input should be updated - this causes re-render with new key - expect(screen.getByRole('textbox')).toBeInTheDocument() + // The query input should be updated - this causes re-render with new key + expect(screen.getByRole('textbox'))!.toBeInTheDocument() }) }) @@ -536,7 +542,8 @@ describe('HitTestingPage', () => { const { container } = renderWithProviders() // Component should render - expect(container.firstChild).toBeInTheDocument() + // Component should render + expect(container.firstChild)!.toBeInTheDocument() }) }) @@ -549,7 +556,8 @@ describe('HitTestingPage', () => { const { container } = renderWithProviders() // Component should still render - expect(container.firstChild).toBeInTheDocument() + // Component should still render + expect(container.firstChild)!.toBeInTheDocument() }) }) @@ -562,7 +570,7 @@ describe('HitTestingPage', () => { const { rerender, container } = renderWithProviders() - expect(container.firstChild).toBeInTheDocument() + expect(container.firstChild)!.toBeInTheDocument() // Re-render with mobile vi.mocked(useBreakpoints.default).mockReturnValue('mobile' as unknown as ReturnType) @@ -573,7 +581,7 @@ describe('HitTestingPage', () => { , ) - expect(container.firstChild).toBeInTheDocument() + expect(container.firstChild)!.toBeInTheDocument() }) }) }) @@ -638,7 +646,8 @@ describe('Integration: Hit Testing Flow', () => { fireEvent.change(textarea, { target: { value: 'Test query' } }) // Component should still be functional - check for the main container - expect(container.firstChild).toBeInTheDocument() + // Component should still be functional - check for the main container + expect(container.firstChild)!.toBeInTheDocument() }) it('should render hit results after successful submission', async () => { @@ -762,7 +771,8 @@ describe('Integration: Hit Testing Flow', () => { const { container } = renderWithProviders() // Component should render - expect(container.firstChild).toBeInTheDocument() + // Component should render + expect(container.firstChild)!.toBeInTheDocument() // Wait for textbox with timeout for CI const textarea = await waitFor( @@ -781,7 +791,7 @@ describe('Integration: Hit Testing Flow', () => { // Verify component is still functional after submission await waitFor( () => { - expect(screen.getByRole('textbox')).toBeInTheDocument() + expect(screen.getByRole('textbox'))!.toBeInTheDocument() }, { timeout: 3000 }, ) @@ -819,12 +829,14 @@ describe('Drawer and Modal Interactions', () => { await waitFor(() => { // The drawer should open - verify container is still there - expect(container.firstChild).toBeInTheDocument() + // The drawer should open - verify container is still there + expect(container.firstChild)!.toBeInTheDocument() }) } // Component should still be functional - verify main container - expect(container.querySelector('.overflow-y-auto')).toBeInTheDocument() + // Component should still be functional - verify main container + expect(container.querySelector('.overflow-y-auto'))!.toBeInTheDocument() }) it('should close retrieval modal when onHide is called', async () => { @@ -841,7 +853,8 @@ describe('Drawer and Modal Interactions', () => { } // Component should still be functional - expect(container.firstChild).toBeInTheDocument() + // Component should still be functional + expect(container.firstChild)!.toBeInTheDocument() }) }) @@ -901,7 +914,7 @@ describe('renderHitResults Coverage', () => { // Verify component is functional await waitFor(() => { - expect(container.firstChild).toBeInTheDocument() + expect(container.firstChild)!.toBeInTheDocument() }) }) @@ -928,7 +941,7 @@ describe('renderHitResults Coverage', () => { fireEvent.click(submitButton) await waitFor(() => { - expect(container.firstChild).toBeInTheDocument() + expect(container.firstChild)!.toBeInTheDocument() }) }) }) @@ -954,12 +967,13 @@ describe('ModifyRetrievalModal onSave Coverage', () => { // Wait for drawer to open await waitFor(() => { - expect(container.firstChild).toBeInTheDocument() + expect(container.firstChild)!.toBeInTheDocument() }) } // Verify component renders correctly - expect(container.querySelector('.overflow-y-auto')).toBeInTheDocument() + // Verify component renders correctly + expect(container.querySelector('.overflow-y-auto'))!.toBeInTheDocument() }) it('should close modal after saving', async () => { @@ -975,7 +989,8 @@ describe('ModifyRetrievalModal onSave Coverage', () => { fireEvent.click(methodSelector) // Component should still be rendered - expect(container.firstChild).toBeInTheDocument() + // Component should still be rendered + expect(container.firstChild)!.toBeInTheDocument() }) }) @@ -1038,7 +1053,7 @@ describe('HitTestingPage Internal Functions Coverage', () => { // Wait for state updates await waitFor(() => { - expect(container.firstChild).toBeInTheDocument() + expect(container.firstChild)!.toBeInTheDocument() }, { timeout: 3000 }) // Verify mutation was called @@ -1059,18 +1074,19 @@ describe('HitTestingPage Internal Functions Coverage', () => { // Wait for drawer content await waitFor(() => { - expect(container.firstChild).toBeInTheDocument() + expect(container.firstChild)!.toBeInTheDocument() }) // Try to find save button in the drawer const saveButtons = screen.queryAllByText(/save/i) if (saveButtons.length > 0) { - fireEvent.click(saveButtons[0]) + fireEvent.click(saveButtons[0]!) } } // Component should still work - expect(container.firstChild).toBeInTheDocument() + // Component should still work + expect(container.firstChild)!.toBeInTheDocument() }) it('should show hit count in results panel after successful query', async () => { @@ -1101,7 +1117,7 @@ describe('HitTestingPage Internal Functions Coverage', () => { // Verify the component renders await waitFor(() => { - expect(container.firstChild).toBeInTheDocument() + expect(container.firstChild)!.toBeInTheDocument() }, { timeout: 3000 }) }) }) diff --git a/web/app/components/datasets/hit-testing/components/query-input/__tests__/index.spec.tsx b/web/app/components/datasets/hit-testing/components/query-input/__tests__/index.spec.tsx index 25b7abe7ea..d9427f5117 100644 --- a/web/app/components/datasets/hit-testing/components/query-input/__tests__/index.spec.tsx +++ b/web/app/components/datasets/hit-testing/components/query-input/__tests__/index.spec.tsx @@ -79,17 +79,17 @@ describe('QueryInput', () => { it('should render title', () => { render() - expect(screen.getByText('datasetHitTesting.input.title')).toBeInTheDocument() + expect(screen.getByText('datasetHitTesting.input.title'))!.toBeInTheDocument() }) it('should render textarea with query text', () => { render() - expect(screen.getByTestId('textarea')).toBeInTheDocument() + expect(screen.getByTestId('textarea'))!.toBeInTheDocument() }) it('should render submit button', () => { render() - expect(screen.getByRole('button', { name: /input\.testing/ })).toBeInTheDocument() + expect(screen.getByRole('button', { name: /input\.testing/ }))!.toBeInTheDocument() }) it('should disable submit button when text is empty', () => { @@ -98,17 +98,17 @@ describe('QueryInput', () => { queries: [{ content: '', content_type: 'text_query', file_info: null }] satisfies Query[], } render() - expect(screen.getByRole('button', { name: /input\.testing/ })).toBeDisabled() + expect(screen.getByRole('button', { name: /input\.testing/ }))!.toBeDisabled() }) it('should render retrieval method for non-external mode', () => { render() - expect(screen.getByText('dataset.retrieval.semantic_search.title')).toBeInTheDocument() + expect(screen.getByText('dataset.retrieval.semantic_search.title'))!.toBeInTheDocument() }) it('should render settings button for external mode', () => { render() - expect(screen.getByText('datasetHitTesting.settingTitle')).toBeInTheDocument() + expect(screen.getByText('datasetHitTesting.settingTitle'))!.toBeInTheDocument() }) it('should disable submit button when text exceeds 200 characters', () => { @@ -117,15 +117,15 @@ describe('QueryInput', () => { queries: [{ content: 'a'.repeat(201), content_type: 'text_query', file_info: null }] satisfies Query[], } render() - expect(screen.getByRole('button', { name: /input\.testing/ })).toBeDisabled() + expect(screen.getByRole('button', { name: /input\.testing/ }))!.toBeDisabled() }) it('should show loading state on submit button when loading', () => { render() const submitButton = screen.getByRole('button', { name: /input\.testing/ }) - expect(submitButton).toBeDisabled() - expect(submitButton).toHaveAttribute('aria-busy', 'true') - expect(submitButton.querySelector('.animate-spin')).toBeInTheDocument() + expect(submitButton)!.toBeDisabled() + expect(submitButton)!.toHaveAttribute('aria-busy', 'true') + expect(submitButton.querySelector('.animate-spin'))!.toBeInTheDocument() }) // Cover line 83: images useMemo with image_query data @@ -141,6 +141,37 @@ describe('QueryInput', () => { ] render() + // Submit should be enabled since we have text + uploaded image + // Submit should be enabled since we have text + uploaded image + // Submit should be enabled since we have text + uploaded image + // Submit should be enabled since we have text + uploaded image + // Submit should be enabled since we have text + uploaded image + // Submit should be enabled since we have text + uploaded image + // Submit should be enabled since we have text + uploaded image + // Submit should be enabled since we have text + uploaded image + // Submit should be enabled since we have text + uploaded image + // Submit should be enabled since we have text + uploaded image + // Submit should be enabled since we have text + uploaded image + // Submit should be enabled since we have text + uploaded image + // Submit should be enabled since we have text + uploaded image + // Submit should be enabled since we have text + uploaded image + // Submit should be enabled since we have text + uploaded image + // Submit should be enabled since we have text + uploaded image + // Submit should be enabled since we have text + uploaded image + // Submit should be enabled since we have text + uploaded image + // Submit should be enabled since we have text + uploaded image + // Submit should be enabled since we have text + uploaded image + // Submit should be enabled since we have text + uploaded image + // Submit should be enabled since we have text + uploaded image + // Submit should be enabled since we have text + uploaded image + // Submit should be enabled since we have text + uploaded image + // Submit should be enabled since we have text + uploaded image + // Submit should be enabled since we have text + uploaded image + // Submit should be enabled since we have text + uploaded image + // Submit should be enabled since we have text + uploaded image + // Submit should be enabled since we have text + uploaded image + // Submit should be enabled since we have text + uploaded image + // Submit should be enabled since we have text + uploaded image // Submit should be enabled since we have text + uploaded image expect(screen.getByRole('button', { name: /input\.testing/ })).not.toBeDisabled() }) @@ -153,7 +184,7 @@ describe('QueryInput', () => { // Click settings button to open modal fireEvent.click(screen.getByRole('button', { name: /settingTitle/ })) - expect(screen.getByTestId('external-retrieval-modal')).toBeInTheDocument() + expect(screen.getByTestId('external-retrieval-modal'))!.toBeInTheDocument() // Close modal fireEvent.click(screen.getByTestId('modal-close')) @@ -165,7 +196,7 @@ describe('QueryInput', () => { // Open modal fireEvent.click(screen.getByRole('button', { name: /settingTitle/ })) - expect(screen.getByTestId('external-retrieval-modal')).toBeInTheDocument() + expect(screen.getByTestId('external-retrieval-modal'))!.toBeInTheDocument() // Save settings fireEvent.click(screen.getByTestId('modal-save')) @@ -274,7 +305,7 @@ describe('QueryInput', () => { ]), ) // Should not contain image_query - const calledWith = defaultProps.setQueries.mock.calls[0][0] as Query[] + const calledWith = defaultProps.setQueries.mock.calls[0]![0] as Query[] expect(calledWith.filter(q => q.content_type === 'image_query')).toHaveLength(0) }) }) @@ -412,7 +443,7 @@ describe('QueryInput', () => { it('should show keyword_search when isEconomy is true', () => { render() - expect(screen.getByText('dataset.retrieval.keyword_search.title')).toBeInTheDocument() + expect(screen.getByText('dataset.retrieval.keyword_search.title'))!.toBeInTheDocument() }) }) }) diff --git a/web/app/components/datasets/list/datasets.tsx b/web/app/components/datasets/list/datasets.tsx index 817b927e6b..8d7006a08a 100644 --- a/web/app/components/datasets/list/datasets.tsx +++ b/web/app/components/datasets/list/datasets.tsx @@ -45,7 +45,7 @@ const Datasets = ({ useEffect(() => { if (anchorRef.current) { observerRef.current = new IntersectionObserver((entries) => { - if (entries[0].isIntersecting && hasNextPage && !isFetching) + if (entries[0]!.isIntersecting && hasNextPage && !isFetching) fetchNextPage() }, { rootMargin: '100px', diff --git a/web/app/components/datasets/metadata/edit-metadata-batch/__tests__/modal.spec.tsx b/web/app/components/datasets/metadata/edit-metadata-batch/__tests__/modal.spec.tsx index d9b88e20bb..40c925222c 100644 --- a/web/app/components/datasets/metadata/edit-metadata-batch/__tests__/modal.spec.tsx +++ b/web/app/components/datasets/metadata/edit-metadata-batch/__tests__/modal.spec.tsx @@ -120,14 +120,14 @@ describe('EditMetadataBatchModal', () => { it('should render without crashing', async () => { render() await waitFor(() => { - expect(screen.getByRole('dialog')).toBeInTheDocument() + expect(screen.getByRole('dialog'))!.toBeInTheDocument() }) }) it('should render document count', async () => { render() await waitFor(() => { - expect(screen.getByText(/5/)).toBeInTheDocument() + expect(screen.getByText(/5/))!.toBeInTheDocument() }) }) @@ -142,8 +142,8 @@ describe('EditMetadataBatchModal', () => { it('should render field names for existing items', async () => { render() await waitFor(() => { - expect(screen.getByText('field_one')).toBeInTheDocument() - expect(screen.getByText('field_two')).toBeInTheDocument() + expect(screen.getByText('field_one'))!.toBeInTheDocument() + expect(screen.getByText('field_two'))!.toBeInTheDocument() }) }) @@ -158,7 +158,7 @@ describe('EditMetadataBatchModal', () => { it('should render select metadata modal', async () => { render() await waitFor(() => { - expect(screen.getByTestId('select-modal')).toBeInTheDocument() + expect(screen.getByTestId('select-modal'))!.toBeInTheDocument() }) }) }) @@ -169,7 +169,7 @@ describe('EditMetadataBatchModal', () => { render() await waitFor(() => { - expect(screen.getByRole('dialog')).toBeInTheDocument() + expect(screen.getByRole('dialog'))!.toBeInTheDocument() }) const cancelButton = screen.getByText(/cancel/i) @@ -183,7 +183,7 @@ describe('EditMetadataBatchModal', () => { render() await waitFor(() => { - expect(screen.getByRole('dialog')).toBeInTheDocument() + expect(screen.getByRole('dialog'))!.toBeInTheDocument() }) // Find the primary save button (not the one in SelectMetadataModal) @@ -196,17 +196,17 @@ describe('EditMetadataBatchModal', () => { render() await waitFor(() => { - expect(screen.getByRole('dialog')).toBeInTheDocument() + expect(screen.getByRole('dialog'))!.toBeInTheDocument() }) const checkboxContainer = document.querySelector('[data-testid*="checkbox"]') - expect(checkboxContainer).toBeInTheDocument() + expect(checkboxContainer)!.toBeInTheDocument() if (checkboxContainer) { fireEvent.click(checkboxContainer) await waitFor(() => { const checkIcon = screen.getByTestId('check-icon-apply-to-all') - expect(checkIcon).toBeInTheDocument() + expect(checkIcon)!.toBeInTheDocument() }) } }) @@ -216,7 +216,7 @@ describe('EditMetadataBatchModal', () => { render() await waitFor(() => { - expect(screen.getByRole('dialog')).toBeInTheDocument() + expect(screen.getByRole('dialog'))!.toBeInTheDocument() }) }) }) @@ -226,7 +226,7 @@ describe('EditMetadataBatchModal', () => { render() await waitFor(() => { - expect(screen.getByRole('dialog')).toBeInTheDocument() + expect(screen.getByRole('dialog'))!.toBeInTheDocument() }) fireEvent.click(screen.getByTestId('change-1')) @@ -239,7 +239,7 @@ describe('EditMetadataBatchModal', () => { render() await waitFor(() => { - expect(screen.getByRole('dialog')).toBeInTheDocument() + expect(screen.getByRole('dialog'))!.toBeInTheDocument() }) fireEvent.click(screen.getByTestId('remove-1')) @@ -252,7 +252,7 @@ describe('EditMetadataBatchModal', () => { render() await waitFor(() => { - expect(screen.getByRole('dialog')).toBeInTheDocument() + expect(screen.getByRole('dialog'))!.toBeInTheDocument() }) // First change the item @@ -269,14 +269,14 @@ describe('EditMetadataBatchModal', () => { render() await waitFor(() => { - expect(screen.getByRole('dialog')).toBeInTheDocument() + expect(screen.getByRole('dialog'))!.toBeInTheDocument() }) fireEvent.click(screen.getByTestId('select-metadata')) // Should now have add-row for the new item await waitFor(() => { - expect(screen.getByTestId('add-row')).toBeInTheDocument() + expect(screen.getByTestId('add-row'))!.toBeInTheDocument() }) }) @@ -284,14 +284,14 @@ describe('EditMetadataBatchModal', () => { render() await waitFor(() => { - expect(screen.getByRole('dialog')).toBeInTheDocument() + expect(screen.getByRole('dialog'))!.toBeInTheDocument() }) // First add an item fireEvent.click(screen.getByTestId('select-metadata')) await waitFor(() => { - expect(screen.getByTestId('add-row')).toBeInTheDocument() + expect(screen.getByTestId('add-row'))!.toBeInTheDocument() }) // Then remove it @@ -306,20 +306,20 @@ describe('EditMetadataBatchModal', () => { render() await waitFor(() => { - expect(screen.getByRole('dialog')).toBeInTheDocument() + expect(screen.getByRole('dialog'))!.toBeInTheDocument() }) // First add an item fireEvent.click(screen.getByTestId('select-metadata')) await waitFor(() => { - expect(screen.getByTestId('add-row')).toBeInTheDocument() + expect(screen.getByTestId('add-row'))!.toBeInTheDocument() }) // Then change it fireEvent.click(screen.getByTestId('add-change-new-1')) - expect(screen.getByTestId('add-row')).toBeInTheDocument() + expect(screen.getByTestId('add-row'))!.toBeInTheDocument() }) it('should call doAddMetaData when saving new metadata with valid name', async () => { @@ -328,7 +328,7 @@ describe('EditMetadataBatchModal', () => { render() await waitFor(() => { - expect(screen.getByRole('dialog')).toBeInTheDocument() + expect(screen.getByRole('dialog'))!.toBeInTheDocument() }) fireEvent.click(screen.getByTestId('save-metadata')) @@ -344,7 +344,7 @@ describe('EditMetadataBatchModal', () => { render() await waitFor(() => { - expect(screen.getByRole('dialog')).toBeInTheDocument() + expect(screen.getByRole('dialog'))!.toBeInTheDocument() }) fireEvent.click(screen.getByTestId('save-metadata')) @@ -368,7 +368,7 @@ describe('EditMetadataBatchModal', () => { render() await waitFor(() => { - expect(screen.getByRole('dialog')).toBeInTheDocument() + expect(screen.getByRole('dialog'))!.toBeInTheDocument() }) fireEvent.click(screen.getByTestId('save-metadata')) @@ -388,7 +388,7 @@ describe('EditMetadataBatchModal', () => { render() await waitFor(() => { - expect(screen.getByRole('dialog')).toBeInTheDocument() + expect(screen.getByRole('dialog'))!.toBeInTheDocument() }) fireEvent.click(screen.getByTestId('manage-metadata')) @@ -401,14 +401,14 @@ describe('EditMetadataBatchModal', () => { it('should pass correct datasetId', async () => { render() await waitFor(() => { - expect(screen.getByRole('dialog')).toBeInTheDocument() + expect(screen.getByRole('dialog'))!.toBeInTheDocument() }) }) it('should display correct document number', async () => { render() await waitFor(() => { - expect(screen.getByText(/10/)).toBeInTheDocument() + expect(screen.getByText(/10/))!.toBeInTheDocument() }) }) @@ -427,7 +427,7 @@ describe('EditMetadataBatchModal', () => { ] render() await waitFor(() => { - expect(screen.getByTestId('edit-row')).toBeInTheDocument() + expect(screen.getByTestId('edit-row'))!.toBeInTheDocument() }) }) @@ -436,7 +436,7 @@ describe('EditMetadataBatchModal', () => { render() await waitFor(() => { - expect(screen.getByRole('dialog')).toBeInTheDocument() + expect(screen.getByRole('dialog'))!.toBeInTheDocument() }) // Find the primary save button @@ -453,7 +453,7 @@ describe('EditMetadataBatchModal', () => { render() await waitFor(() => { - expect(screen.getByRole('dialog')).toBeInTheDocument() + expect(screen.getByRole('dialog'))!.toBeInTheDocument() }) fireEvent.click(screen.getByRole('button', { name: 'common.operation.save' })) @@ -470,7 +470,7 @@ describe('EditMetadataBatchModal', () => { render() await waitFor(() => { - expect(screen.getByRole('dialog')).toBeInTheDocument() + expect(screen.getByRole('dialog'))!.toBeInTheDocument() }) const checkboxContainer = document.querySelector('[data-testid*="checkbox"]') @@ -493,7 +493,7 @@ describe('EditMetadataBatchModal', () => { render() await waitFor(() => { - expect(screen.getByRole('dialog')).toBeInTheDocument() + expect(screen.getByRole('dialog'))!.toBeInTheDocument() }) // Remove an item @@ -503,7 +503,7 @@ describe('EditMetadataBatchModal', () => { expect(onSave).toHaveBeenCalled() // The first argument should not contain the deleted item (id '1') - const savedList = onSave.mock.calls[0][0] as MetadataItemInBatchEdit[] + const savedList = onSave.mock.calls[0]![0] as MetadataItemInBatchEdit[] const hasDeletedItem = savedList.some(item => item.id === '1') expect(hasDeletedItem).toBe(false) }) @@ -512,13 +512,13 @@ describe('EditMetadataBatchModal', () => { render() await waitFor(() => { - expect(screen.getByRole('dialog')).toBeInTheDocument() + expect(screen.getByRole('dialog'))!.toBeInTheDocument() }) // Add first item fireEvent.click(screen.getByTestId('select-metadata')) await waitFor(() => { - expect(screen.getByTestId('add-row')).toBeInTheDocument() + expect(screen.getByTestId('add-row'))!.toBeInTheDocument() }) // Remove it @@ -531,7 +531,7 @@ describe('EditMetadataBatchModal', () => { // Add again fireEvent.click(screen.getByTestId('select-metadata')) await waitFor(() => { - expect(screen.getByTestId('add-row')).toBeInTheDocument() + expect(screen.getByTestId('add-row'))!.toBeInTheDocument() }) }) }) diff --git a/web/app/components/datasets/metadata/edit-metadata-batch/modal.tsx b/web/app/components/datasets/metadata/edit-metadata-batch/modal.tsx index 2dfff611ed..974ce977e7 100644 --- a/web/app/components/datasets/metadata/edit-metadata-batch/modal.tsx +++ b/web/app/components/datasets/metadata/edit-metadata-batch/modal.tsx @@ -47,8 +47,8 @@ const EditMetadataBatchModal: FC = ({ datasetId, documentNum, list, onSav const newTempleList = produce(templeList, (draft) => { const index = draft.findIndex(i => i.id === id) if (index !== -1) { - draft[index].isUpdated = true - draft[index].updateType = UpdateType.delete + draft[index]!.isUpdated = true + draft[index]!.updateType = UpdateType.delete } }) setTempleList(newTempleList) @@ -57,9 +57,9 @@ const EditMetadataBatchModal: FC = ({ datasetId, documentNum, list, onSav const newTempleList = produce(templeList, (draft) => { const index = draft.findIndex(i => i.id === id) if (index !== -1) { - draft[index] = { ...list[index] } - draft[index].isUpdated = false - delete draft[index].updateType + draft[index] = { ...list[index]! } + draft[index]!.isUpdated = false + delete draft[index]!.updateType } }) setTempleList(newTempleList) diff --git a/web/app/components/datasets/metadata/hooks/__tests__/use-batch-edit-document-metadata.spec.ts b/web/app/components/datasets/metadata/hooks/__tests__/use-batch-edit-document-metadata.spec.ts index 05088cabec..a4650bac43 100644 --- a/web/app/components/datasets/metadata/hooks/__tests__/use-batch-edit-document-metadata.spec.ts +++ b/web/app/components/datasets/metadata/hooks/__tests__/use-batch-edit-document-metadata.spec.ts @@ -239,7 +239,7 @@ describe('useBatchEditDocumentMetadata', () => { // Should only have one item for field '1', marked as multiple const fieldItems = result.current.originalList.filter(item => item.id === '1') expect(fieldItems.length).toBe(1) - expect(fieldItems[0].isMultipleValue).toBe(true) + expect(fieldItems[0]!.isMultipleValue).toBe(true) }) }) @@ -458,7 +458,7 @@ describe('useBatchEditDocumentMetadata', () => { // Both documents should have the field after applying to all expect(mockMutateAsync).toHaveBeenCalled() - const callArgs = mockMutateAsync.mock.calls[0][0] + const callArgs = mockMutateAsync.mock.calls[0]![0] expect(callArgs.metadata_list.length).toBe(2) }) @@ -651,7 +651,7 @@ describe('useBatchEditDocumentMetadata', () => { await result.current.handleSave(editedList, [], false) }) - const callArgs = mockMutateAsync.mock.calls[0][0] + const callArgs = mockMutateAsync.mock.calls[0]![0] const sentItem = callArgs.metadata_list[0].metadata_list[0] // Only id, name, type, value should be present @@ -693,7 +693,7 @@ describe('useBatchEditDocumentMetadata', () => { await result.current.handleSave(editedList, [], false) }) - const callArgs = mockMutateAsync.mock.calls[0][0] + const callArgs = mockMutateAsync.mock.calls[0]![0] const sentItem = callArgs.metadata_list[0].metadata_list[0] // value should be null, not undefined diff --git a/web/app/components/datasets/metadata/hooks/__tests__/use-metadata-document.spec.ts b/web/app/components/datasets/metadata/hooks/__tests__/use-metadata-document.spec.ts index 67c8ffe3b3..9d8b73aaaa 100644 --- a/web/app/components/datasets/metadata/hooks/__tests__/use-metadata-document.spec.ts +++ b/web/app/components/datasets/metadata/hooks/__tests__/use-metadata-document.spec.ts @@ -262,7 +262,7 @@ describe('useMetadataDocument', () => { // Try to add existing item if (result.current.tempList.length > 0) { act(() => { - result.current.handleSelectMetaData(result.current.tempList[0]) + result.current.handleSelectMetaData(result.current.tempList[0]!) }) expect(result.current.tempList.length).toBe(initialLength) diff --git a/web/app/components/datasets/metadata/hooks/use-batch-edit-document-metadata.ts b/web/app/components/datasets/metadata/hooks/use-batch-edit-document-metadata.ts index b0feea8c56..16252909a2 100644 --- a/web/app/components/datasets/metadata/hooks/use-batch-edit-document-metadata.ts +++ b/web/app/components/datasets/metadata/hooks/use-batch-edit-document-metadata.ts @@ -45,7 +45,7 @@ const useBatchEditDocumentMetadata = ({ datasetId, docList, selectedDocumentIds, } } if (itemInRes && itemInRes.value !== item.value) { - idNameValue[item.id].isMultipleValue = true + idNameValue[item.id]!.isMultipleValue = true itemInRes.isMultipleValue = true itemInRes.value = null return @@ -82,7 +82,7 @@ const useBatchEditDocumentMetadata = ({ datasetId, docList, selectedDocumentIds, // Find the document in docList to get its metadata const docIndex = docList.findIndex(doc => doc.id === documentId) const oldMetadataList = docIndex >= 0 ? metaDataList[docIndex] : [] - let newMetadataList: MetadataItemWithValue[] = [...oldMetadataList, ...addedList] + let newMetadataList: MetadataItemWithValue[] = [...(oldMetadataList ?? []), ...addedList] .filter((item) => { return !removedList.find(removedItem => removedItem.id === item.id) }) diff --git a/web/app/components/datasets/metadata/hooks/use-metadata-document.ts b/web/app/components/datasets/metadata/hooks/use-metadata-document.ts index 2e9edbfa75..d70870690a 100644 --- a/web/app/components/datasets/metadata/hooks/use-metadata-document.ts +++ b/web/app/components/datasets/metadata/hooks/use-metadata-document.ts @@ -95,9 +95,9 @@ const useMetadataDocument = ({ datasetId, documentId, docDetail }: Props) => { const fieldList = Object.keys(fieldMap).map((key) => { const field = fieldMap[key] return { - id: field?.label, + id: field?.label!, type: DataType.string, - name: field?.label, + name: field?.label!, value: getTargetValue(key), } }) @@ -120,8 +120,8 @@ const useMetadataDocument = ({ datasetId, documentId, docDetail }: Props) => { startToEdit, handleSave, handleCancel, - originInfo, - technicalParameters, + originInfo: originInfo!, + technicalParameters: technicalParameters!, } } export default useMetadataDocument diff --git a/web/app/components/datasets/metadata/metadata-dataset/__tests__/dataset-metadata-drawer.spec.tsx b/web/app/components/datasets/metadata/metadata-dataset/__tests__/dataset-metadata-drawer.spec.tsx index 353a39450e..95e9c130ed 100644 --- a/web/app/components/datasets/metadata/metadata-dataset/__tests__/dataset-metadata-drawer.spec.tsx +++ b/web/app/components/datasets/metadata/metadata-dataset/__tests__/dataset-metadata-drawer.spec.tsx @@ -90,23 +90,23 @@ describe('DatasetMetadataDrawer', () => { it('should render without crashing', async () => { render() await waitFor(() => { - expect(screen.getByRole('dialog')).toBeInTheDocument() + expect(screen.getByRole('dialog'))!.toBeInTheDocument() }) }) it('should render user metadata items', async () => { render() await waitFor(() => { - expect(screen.getByText('field_one')).toBeInTheDocument() - expect(screen.getByText('field_two')).toBeInTheDocument() + expect(screen.getByText('field_one'))!.toBeInTheDocument() + expect(screen.getByText('field_two'))!.toBeInTheDocument() }) }) it('should render built-in metadata items', async () => { render() await waitFor(() => { - expect(screen.getByText('created_at')).toBeInTheDocument() - expect(screen.getByText('modified_at')).toBeInTheDocument() + expect(screen.getByText('created_at'))!.toBeInTheDocument() + expect(screen.getByText('modified_at'))!.toBeInTheDocument() }) }) @@ -121,7 +121,7 @@ describe('DatasetMetadataDrawer', () => { it('should render add metadata button', async () => { render() await waitFor(() => { - expect(screen.getByTestId('create-trigger')).toBeInTheDocument() + expect(screen.getByTestId('create-trigger'))!.toBeInTheDocument() }) }) @@ -129,7 +129,7 @@ describe('DatasetMetadataDrawer', () => { render() await waitFor(() => { const switchBtn = screen.getByRole('switch') - expect(switchBtn).toBeInTheDocument() + expect(switchBtn)!.toBeInTheDocument() }) }) }) @@ -145,7 +145,7 @@ describe('DatasetMetadataDrawer', () => { ) await waitFor(() => { - expect(screen.getByRole('dialog')).toBeInTheDocument() + expect(screen.getByRole('dialog'))!.toBeInTheDocument() }) const switchBtn = screen.getByRole('switch') @@ -160,14 +160,14 @@ describe('DatasetMetadataDrawer', () => { render() await waitFor(() => { - expect(screen.getByRole('dialog')).toBeInTheDocument() + expect(screen.getByRole('dialog'))!.toBeInTheDocument() }) const trigger = screen.getByTestId('create-trigger') fireEvent.click(trigger) await waitFor(() => { - expect(screen.getByTestId('create-modal')).toBeInTheDocument() + expect(screen.getByTestId('create-modal'))!.toBeInTheDocument() }) }) @@ -176,7 +176,7 @@ describe('DatasetMetadataDrawer', () => { render() await waitFor(() => { - expect(screen.getByRole('dialog')).toBeInTheDocument() + expect(screen.getByRole('dialog'))!.toBeInTheDocument() }) // Open create modal @@ -184,7 +184,7 @@ describe('DatasetMetadataDrawer', () => { fireEvent.click(trigger) await waitFor(() => { - expect(screen.getByTestId('create-modal')).toBeInTheDocument() + expect(screen.getByTestId('create-modal'))!.toBeInTheDocument() }) // Save new metadata @@ -208,14 +208,14 @@ describe('DatasetMetadataDrawer', () => { render() await waitFor(() => { - expect(screen.getByRole('dialog')).toBeInTheDocument() + expect(screen.getByRole('dialog'))!.toBeInTheDocument() }) // Open create modal fireEvent.click(screen.getByTestId('create-trigger')) await waitFor(() => { - expect(screen.getByTestId('create-modal')).toBeInTheDocument() + expect(screen.getByTestId('create-modal'))!.toBeInTheDocument() }) fireEvent.click(screen.getByTestId('create-save')) @@ -231,7 +231,7 @@ describe('DatasetMetadataDrawer', () => { render() await waitFor(() => { - expect(screen.getByRole('dialog')).toBeInTheDocument() + expect(screen.getByRole('dialog'))!.toBeInTheDocument() }) // Find user metadata items with group/item class (these have edit/delete icons) @@ -240,14 +240,14 @@ describe('DatasetMetadataDrawer', () => { expect(items.length).toBe(2) // 2 user metadata items // Find the hidden container with edit/delete icons - const actionsContainer = items[0].querySelector('.hidden.items-center') + const actionsContainer = items[0]!.querySelector('.hidden.items-center') expect(actionsContainer).toBeTruthy() // Find and click the first SVG (edit icon) if (actionsContainer) { const svgs = actionsContainer.querySelectorAll('svg') expect(svgs.length).toBeGreaterThan(0) - fireEvent.click(svgs[0]) + fireEvent.click(svgs[0]!) } // Wait for rename modal (contains input) @@ -262,16 +262,16 @@ describe('DatasetMetadataDrawer', () => { render() await waitFor(() => { - expect(screen.getByRole('dialog')).toBeInTheDocument() + expect(screen.getByRole('dialog'))!.toBeInTheDocument() }) // Find and click edit icon const dialog = screen.getByRole('dialog') const items = dialog.querySelectorAll('.group\\/item') - const actionsContainer = items[0].querySelector('.hidden.items-center') + const actionsContainer = items[0]!.querySelector('.hidden.items-center') if (actionsContainer) { const svgs = actionsContainer.querySelectorAll('svg') - fireEvent.click(svgs[0]) + fireEvent.click(svgs[0]!) } // Change name and save @@ -281,7 +281,7 @@ describe('DatasetMetadataDrawer', () => { }) const inputs = document.querySelectorAll('input') - fireEvent.change(inputs[0], { target: { value: 'renamed_field' } }) + fireEvent.change(inputs[0]!, { target: { value: 'renamed_field' } }) // Find and click save button fireEvent.click(screen.getByRole('button', { name: 'common.operation.save' })) @@ -303,16 +303,16 @@ describe('DatasetMetadataDrawer', () => { render() await waitFor(() => { - expect(screen.getByRole('dialog')).toBeInTheDocument() + expect(screen.getByRole('dialog'))!.toBeInTheDocument() }) // Find and click edit icon const dialog = screen.getByRole('dialog') const items = dialog.querySelectorAll('.group\\/item') - const actionsContainer = items[0].querySelector('.hidden.items-center') + const actionsContainer = items[0]!.querySelector('.hidden.items-center') if (actionsContainer) { const svgs = actionsContainer.querySelectorAll('svg') - fireEvent.click(svgs[0]) + fireEvent.click(svgs[0]!) } // Wait for modal and click cancel @@ -323,7 +323,7 @@ describe('DatasetMetadataDrawer', () => { // Change name first const inputs = document.querySelectorAll('input') - fireEvent.change(inputs[0], { target: { value: 'changed_name' } }) + fireEvent.change(inputs[0]!, { target: { value: 'changed_name' } }) // Find and click cancel button fireEvent.click(screen.getByRole('button', { name: 'common.operation.cancel' })) @@ -339,16 +339,16 @@ describe('DatasetMetadataDrawer', () => { render() await waitFor(() => { - expect(screen.getByRole('dialog')).toBeInTheDocument() + expect(screen.getByRole('dialog'))!.toBeInTheDocument() }) // Find and click edit icon const dialog = screen.getByRole('dialog') const items = dialog.querySelectorAll('.group\\/item') - const actionsContainer = items[0].querySelector('.hidden.items-center') + const actionsContainer = items[0]!.querySelector('.hidden.items-center') if (actionsContainer) { const svgs = actionsContainer.querySelectorAll('svg') - fireEvent.click(svgs[0]) + fireEvent.click(svgs[0]!) } // Wait for rename modal @@ -382,7 +382,7 @@ describe('DatasetMetadataDrawer', () => { render() await waitFor(() => { - expect(screen.getByRole('dialog')).toBeInTheDocument() + expect(screen.getByRole('dialog'))!.toBeInTheDocument() }) // Find user metadata items @@ -390,7 +390,7 @@ describe('DatasetMetadataDrawer', () => { const items = dialog.querySelectorAll('.group\\/item') // Find the delete container - const deleteContainer = items[0].querySelector('.hover\\:text-text-destructive') + const deleteContainer = items[0]!.querySelector('.hover\\:text-text-destructive') expect(deleteContainer).toBeTruthy() if (deleteContainer) { @@ -414,13 +414,13 @@ describe('DatasetMetadataDrawer', () => { render() await waitFor(() => { - expect(screen.getByRole('dialog')).toBeInTheDocument() + expect(screen.getByRole('dialog'))!.toBeInTheDocument() }) // Find and click delete icon const dialog = screen.getByRole('dialog') const items = dialog.querySelectorAll('.group\\/item') - const deleteContainer = items[0].querySelector('.hover\\:text-text-destructive') + const deleteContainer = items[0]!.querySelector('.hover\\:text-text-destructive') if (deleteContainer) { const deleteIcon = deleteContainer.querySelector('svg') if (deleteIcon) @@ -460,13 +460,13 @@ describe('DatasetMetadataDrawer', () => { render() await waitFor(() => { - expect(screen.getByRole('dialog')).toBeInTheDocument() + expect(screen.getByRole('dialog'))!.toBeInTheDocument() }) // Find and click delete icon const dialog = screen.getByRole('dialog') const items = dialog.querySelectorAll('.group\\/item') - const deleteContainer = items[0].querySelector('.hover\\:text-text-destructive') + const deleteContainer = items[0]!.querySelector('.hover\\:text-text-destructive') if (deleteContainer) { const deleteIcon = deleteContainer.querySelector('svg') if (deleteIcon) @@ -495,14 +495,14 @@ describe('DatasetMetadataDrawer', () => { it('should handle empty userMetadata', async () => { render() await waitFor(() => { - expect(screen.getByRole('dialog')).toBeInTheDocument() + expect(screen.getByRole('dialog'))!.toBeInTheDocument() }) }) it('should handle empty builtInMetadata', async () => { render() await waitFor(() => { - expect(screen.getByRole('dialog')).toBeInTheDocument() + expect(screen.getByRole('dialog'))!.toBeInTheDocument() }) }) }) @@ -514,7 +514,7 @@ describe('DatasetMetadataDrawer', () => { ) await waitFor(() => { - expect(screen.getByRole('dialog')).toBeInTheDocument() + expect(screen.getByRole('dialog'))!.toBeInTheDocument() }) const dialog = screen.getByRole('dialog') @@ -528,7 +528,7 @@ describe('DatasetMetadataDrawer', () => { ) await waitFor(() => { - expect(screen.getByRole('dialog')).toBeInTheDocument() + expect(screen.getByRole('dialog'))!.toBeInTheDocument() }) }) }) @@ -540,7 +540,7 @@ describe('DatasetMetadataDrawer', () => { ] render() await waitFor(() => { - expect(screen.getByText('field_with_underscore')).toBeInTheDocument() + expect(screen.getByText('field_with_underscore'))!.toBeInTheDocument() }) }) @@ -550,7 +550,7 @@ describe('DatasetMetadataDrawer', () => { ] render() await waitFor(() => { - expect(screen.getByText('only_field')).toBeInTheDocument() + expect(screen.getByText('only_field'))!.toBeInTheDocument() }) }) @@ -560,7 +560,7 @@ describe('DatasetMetadataDrawer', () => { ] render() await waitFor(() => { - expect(screen.getByText('created_at')).toBeInTheDocument() + expect(screen.getByText('created_at'))!.toBeInTheDocument() }) }) @@ -570,7 +570,7 @@ describe('DatasetMetadataDrawer', () => { ] render() await waitFor(() => { - expect(screen.getByText('empty_field')).toBeInTheDocument() + expect(screen.getByText('empty_field'))!.toBeInTheDocument() }) }) }) diff --git a/web/app/components/datasets/metadata/metadata-document/__tests__/index.spec.tsx b/web/app/components/datasets/metadata/metadata-document/__tests__/index.spec.tsx index ddd624a076..71f23324f6 100644 --- a/web/app/components/datasets/metadata/metadata-document/__tests__/index.spec.tsx +++ b/web/app/components/datasets/metadata/metadata-document/__tests__/index.spec.tsx @@ -99,7 +99,7 @@ describe('MetadataDocument', () => { docDetail={mockDocDetail as Parameters[0]['docDetail']} />, ) - expect(container.firstChild).toBeInTheDocument() + expect(container.firstChild)!.toBeInTheDocument() }) it('should render metadata fields when hasData is true', () => { @@ -110,8 +110,8 @@ describe('MetadataDocument', () => { docDetail={mockDocDetail as Parameters[0]['docDetail']} />, ) - expect(screen.getByText('field_one')).toBeInTheDocument() - expect(screen.getByText('field_two')).toBeInTheDocument() + expect(screen.getByText('field_one'))!.toBeInTheDocument() + expect(screen.getByText('field_two'))!.toBeInTheDocument() }) it('should render no-data state when hasData is false and not in edit mode', () => { @@ -147,8 +147,8 @@ describe('MetadataDocument', () => { />, ) - expect(screen.getByText(/save/i)).toBeInTheDocument() - expect(screen.getByText(/cancel/i)).toBeInTheDocument() + expect(screen.getByText(/save/i))!.toBeInTheDocument() + expect(screen.getByText(/cancel/i))!.toBeInTheDocument() }) it('should render built-in section when builtInEnabled is true', () => { @@ -166,7 +166,7 @@ describe('MetadataDocument', () => { />, ) - expect(screen.getByText('created_at')).toBeInTheDocument() + expect(screen.getByText('created_at'))!.toBeInTheDocument() }) it('should render divider when builtInEnabled is true', () => { @@ -185,7 +185,7 @@ describe('MetadataDocument', () => { ) const divider = container.querySelector('.bg-linear-to-r') - expect(divider).toBeInTheDocument() + expect(divider)!.toBeInTheDocument() }) it('should render origin info section', () => { @@ -202,7 +202,7 @@ describe('MetadataDocument', () => { />, ) - expect(screen.getByText('source')).toBeInTheDocument() + expect(screen.getByText('source'))!.toBeInTheDocument() }) it('should render technical parameters section', () => { @@ -219,7 +219,7 @@ describe('MetadataDocument', () => { />, ) - expect(screen.getByText('word_count')).toBeInTheDocument() + expect(screen.getByText('word_count'))!.toBeInTheDocument() }) it('should render all sections together', () => { @@ -239,10 +239,10 @@ describe('MetadataDocument', () => { />, ) - expect(screen.getByText('field_one')).toBeInTheDocument() - expect(screen.getByText('created_at')).toBeInTheDocument() - expect(screen.getByText('source')).toBeInTheDocument() - expect(screen.getByText('word_count')).toBeInTheDocument() + expect(screen.getByText('field_one'))!.toBeInTheDocument() + expect(screen.getByText('created_at'))!.toBeInTheDocument() + expect(screen.getByText('source'))!.toBeInTheDocument() + expect(screen.getByText('word_count'))!.toBeInTheDocument() }) }) @@ -255,7 +255,7 @@ describe('MetadataDocument', () => { docDetail={mockDocDetail as Parameters[0]['docDetail']} />, ) - expect(screen.getByText(/edit/i)).toBeInTheDocument() + expect(screen.getByText(/edit/i))!.toBeInTheDocument() }) it('should call startToEdit when edit button is clicked', () => { @@ -362,8 +362,9 @@ describe('MetadataDocument', () => { ) // Should show save/cancel buttons - expect(screen.getByText(/save/i)).toBeInTheDocument() - expect(screen.getByText(/cancel/i)).toBeInTheDocument() + // Should show save/cancel buttons + expect(screen.getByText(/save/i))!.toBeInTheDocument() + expect(screen.getByText(/cancel/i))!.toBeInTheDocument() }) }) @@ -386,7 +387,7 @@ describe('MetadataDocument', () => { const inputs = container.querySelectorAll('input') if (inputs.length > 0) { - fireEvent.change(inputs[0], { target: { value: 'new value' } }) + fireEvent.change(inputs[0]!, { target: { value: 'new value' } }) await waitFor(() => { expect(setTempList).toHaveBeenCalled() @@ -454,7 +455,7 @@ describe('MetadataDocument', () => { const inputs = container.querySelectorAll('input') if (inputs.length > 0) { - fireEvent.change(inputs[0], { target: { value: 'updated' } }) + fireEvent.change(inputs[0]!, { target: { value: 'updated' } }) await waitFor(() => { expect(setTempList).toHaveBeenCalled() }) @@ -483,7 +484,7 @@ describe('MetadataDocument', () => { expect(deleteContainers.length).toBeGreaterThan(0) if (deleteContainers.length > 0) { - const deleteIcon = deleteContainers[0].querySelector('svg') + const deleteIcon = deleteContainers[0]!.querySelector('svg') if (deleteIcon) fireEvent.click(deleteIcon) @@ -504,7 +505,7 @@ describe('MetadataDocument', () => { className="custom-class" />, ) - expect(container.firstChild).toHaveClass('custom-class') + expect(container.firstChild)!.toHaveClass('custom-class') }) it('should use tempList when in edit mode', () => { @@ -524,7 +525,7 @@ describe('MetadataDocument', () => { />, ) - expect(screen.getByText('temp_field')).toBeInTheDocument() + expect(screen.getByText('temp_field'))!.toBeInTheDocument() }) it('should use list when not in edit mode', () => { @@ -536,8 +537,8 @@ describe('MetadataDocument', () => { />, ) - expect(screen.getByText('field_one')).toBeInTheDocument() - expect(screen.getByText('field_two')).toBeInTheDocument() + expect(screen.getByText('field_one'))!.toBeInTheDocument() + expect(screen.getByText('field_two'))!.toBeInTheDocument() }) it('should pass datasetId to child components', () => { @@ -549,7 +550,8 @@ describe('MetadataDocument', () => { />, ) // Component should render without errors - expect(screen.getByText('field_one')).toBeInTheDocument() + // Component should render without errors + expect(screen.getByText('field_one'))!.toBeInTheDocument() }) }) @@ -588,6 +590,37 @@ describe('MetadataDocument', () => { />, ) + // NoData component should not be rendered + // NoData component should not be rendered + // NoData component should not be rendered + // NoData component should not be rendered + // NoData component should not be rendered + // NoData component should not be rendered + // NoData component should not be rendered + // NoData component should not be rendered + // NoData component should not be rendered + // NoData component should not be rendered + // NoData component should not be rendered + // NoData component should not be rendered + // NoData component should not be rendered + // NoData component should not be rendered + // NoData component should not be rendered + // NoData component should not be rendered + // NoData component should not be rendered + // NoData component should not be rendered + // NoData component should not be rendered + // NoData component should not be rendered + // NoData component should not be rendered + // NoData component should not be rendered + // NoData component should not be rendered + // NoData component should not be rendered + // NoData component should not be rendered + // NoData component should not be rendered + // NoData component should not be rendered + // NoData component should not be rendered + // NoData component should not be rendered + // NoData component should not be rendered + // NoData component should not be rendered // NoData component should not be rendered expect(screen.queryByText(/start/i)).not.toBeInTheDocument() }) @@ -607,6 +640,37 @@ describe('MetadataDocument', () => { />, ) + // headerRight should be null/undefined + // headerRight should be null/undefined + // headerRight should be null/undefined + // headerRight should be null/undefined + // headerRight should be null/undefined + // headerRight should be null/undefined + // headerRight should be null/undefined + // headerRight should be null/undefined + // headerRight should be null/undefined + // headerRight should be null/undefined + // headerRight should be null/undefined + // headerRight should be null/undefined + // headerRight should be null/undefined + // headerRight should be null/undefined + // headerRight should be null/undefined + // headerRight should be null/undefined + // headerRight should be null/undefined + // headerRight should be null/undefined + // headerRight should be null/undefined + // headerRight should be null/undefined + // headerRight should be null/undefined + // headerRight should be null/undefined + // headerRight should be null/undefined + // headerRight should be null/undefined + // headerRight should be null/undefined + // headerRight should be null/undefined + // headerRight should be null/undefined + // headerRight should be null/undefined + // headerRight should be null/undefined + // headerRight should be null/undefined + // headerRight should be null/undefined // headerRight should be null/undefined expect(screen.queryByText(/^edit$/i)).not.toBeInTheDocument() }) @@ -628,7 +692,7 @@ describe('MetadataDocument', () => { docDetail={mockDocDetail as Parameters[0]['docDetail']} />, ) - expect(container.firstChild).toBeInTheDocument() + expect(container.firstChild)!.toBeInTheDocument() }) it('should render correctly with minimal props', () => { @@ -639,7 +703,7 @@ describe('MetadataDocument', () => { docDetail={mockDocDetail as Parameters[0]['docDetail']} />, ) - expect(container.firstChild).toBeInTheDocument() + expect(container.firstChild)!.toBeInTheDocument() }) it('should handle switching between view and edit mode', () => { @@ -651,7 +715,7 @@ describe('MetadataDocument', () => { />, ) - expect(screen.getByText(/edit/i)).toBeInTheDocument() + expect(screen.getByText(/edit/i))!.toBeInTheDocument() unmount() @@ -668,8 +732,8 @@ describe('MetadataDocument', () => { />, ) - expect(screen.getByText(/save/i)).toBeInTheDocument() - expect(screen.getByText(/cancel/i)).toBeInTheDocument() + expect(screen.getByText(/save/i))!.toBeInTheDocument() + expect(screen.getByText(/cancel/i))!.toBeInTheDocument() }) it('should handle multiple items in all sections', () => { @@ -702,11 +766,11 @@ describe('MetadataDocument', () => { />, ) - expect(screen.getByText('user_field_1')).toBeInTheDocument() - expect(screen.getByText('user_field_2')).toBeInTheDocument() - expect(screen.getByText('created_at')).toBeInTheDocument() - expect(screen.getByText('source')).toBeInTheDocument() - expect(screen.getByText('word_count')).toBeInTheDocument() + expect(screen.getByText('user_field_1'))!.toBeInTheDocument() + expect(screen.getByText('user_field_2'))!.toBeInTheDocument() + expect(screen.getByText('created_at'))!.toBeInTheDocument() + expect(screen.getByText('source'))!.toBeInTheDocument() + expect(screen.getByText('word_count'))!.toBeInTheDocument() }) it('should handle null values in metadata', () => { @@ -725,7 +789,7 @@ describe('MetadataDocument', () => { />, ) - expect(screen.getByText('null_field')).toBeInTheDocument() + expect(screen.getByText('null_field'))!.toBeInTheDocument() }) it('should handle undefined values in metadata', () => { @@ -744,7 +808,7 @@ describe('MetadataDocument', () => { />, ) - expect(screen.getByText('undefined_field')).toBeInTheDocument() + expect(screen.getByText('undefined_field'))!.toBeInTheDocument() }) }) }) diff --git a/web/app/components/datasets/metadata/metadata-document/__tests__/info-group.spec.tsx b/web/app/components/datasets/metadata/metadata-document/__tests__/info-group.spec.tsx index d783b882a8..c176979a5a 100644 --- a/web/app/components/datasets/metadata/metadata-document/__tests__/info-group.spec.tsx +++ b/web/app/components/datasets/metadata/metadata-document/__tests__/info-group.spec.tsx @@ -90,14 +90,14 @@ describe('InfoGroup', () => { const { container } = render( , ) - expect(container.firstChild).toBeInTheDocument() + expect(container.firstChild)!.toBeInTheDocument() }) it('should render title when provided', () => { render( , ) - expect(screen.getByText('Test Title')).toBeInTheDocument() + expect(screen.getByText('Test Title'))!.toBeInTheDocument() }) it('should not render header when noHeader is true', () => { @@ -126,7 +126,7 @@ describe('InfoGroup', () => { ) // Tooltip icon should be present const tooltipIcon = screen.getByText('Test').closest('.flex')?.querySelector('svg') - expect(tooltipIcon).toBeInTheDocument() + expect(tooltipIcon)!.toBeInTheDocument() }) it('should render headerRight content', () => { @@ -138,7 +138,7 @@ describe('InfoGroup', () => { headerRight={} />, ) - expect(screen.getByTestId('header-right-btn')).toBeInTheDocument() + expect(screen.getByTestId('header-right-btn'))!.toBeInTheDocument() }) }) @@ -147,7 +147,7 @@ describe('InfoGroup', () => { render( , ) - expect(screen.getByTestId('add-metadata-btn')).toBeInTheDocument() + expect(screen.getByTestId('add-metadata-btn'))!.toBeInTheDocument() }) it('should not render add metadata button when isEdit is false', () => { @@ -182,7 +182,7 @@ describe('InfoGroup', () => { ) const inputs = screen.getAllByTestId('input-combined') - fireEvent.change(inputs[0], { target: { value: 'New Value' } }) + fireEvent.change(inputs[0]!, { target: { value: 'New Value' } }) expect(handleChange).toHaveBeenCalled() }) @@ -196,7 +196,7 @@ describe('InfoGroup', () => { // Find delete icons (RiDeleteBinLine SVGs inside cursor-pointer divs) const deleteButtons = container.querySelectorAll('svg.size-4') if (deleteButtons.length > 0) - fireEvent.click(deleteButtons[0]) + fireEvent.click(deleteButtons[0]!) expect(handleDelete).toHaveBeenCalled() }) @@ -239,7 +239,8 @@ describe('InfoGroup', () => { fireEvent.click(screen.getByTestId('manage-action')) // The onManage callback triggers the navigation - expect(screen.getByTestId('manage-action')).toBeInTheDocument() + // The onManage callback triggers the navigation + expect(screen.getByTestId('manage-action'))!.toBeInTheDocument() }) }) @@ -248,7 +249,7 @@ describe('InfoGroup', () => { const { container } = render( , ) - expect(container.firstChild).toHaveClass('custom-class') + expect(container.firstChild)!.toHaveClass('custom-class') }) it('should apply contentClassName', () => { @@ -256,7 +257,7 @@ describe('InfoGroup', () => { , ) const contentDiv = container.querySelector('.content-custom') - expect(contentDiv).toBeInTheDocument() + expect(contentDiv)!.toBeInTheDocument() }) it('should use uppercase title by default', () => { @@ -264,7 +265,7 @@ describe('InfoGroup', () => { , ) const titleElement = screen.getByText('Test Title') - expect(titleElement).toHaveClass('system-xs-semibold-uppercase') + expect(titleElement)!.toHaveClass('system-xs-semibold-uppercase') }) it('should not use uppercase when uppercaseTitle is false', () => { @@ -272,7 +273,7 @@ describe('InfoGroup', () => { , ) const titleElement = screen.getByText('Test Title') - expect(titleElement).toHaveClass('system-md-semibold') + expect(titleElement)!.toHaveClass('system-md-semibold') }) }) @@ -284,7 +285,7 @@ describe('InfoGroup', () => { render( , ) - expect(screen.getByText('Test Value')).toBeInTheDocument() + expect(screen.getByText('Test Value'))!.toBeInTheDocument() }) it('should display number value', () => { @@ -294,7 +295,7 @@ describe('InfoGroup', () => { render( , ) - expect(screen.getByText('123')).toBeInTheDocument() + expect(screen.getByText('123'))!.toBeInTheDocument() }) it('should format time value', () => { @@ -305,7 +306,8 @@ describe('InfoGroup', () => { , ) // The mock formatTime returns formatted date - expect(screen.getByTestId('field-content')).toBeInTheDocument() + // The mock formatTime returns formatted date + expect(screen.getByTestId('field-content'))!.toBeInTheDocument() }) }) @@ -314,7 +316,7 @@ describe('InfoGroup', () => { const { container } = render( , ) - expect(container.firstChild).toBeInTheDocument() + expect(container.firstChild)!.toBeInTheDocument() }) it('should handle null value in list', () => { @@ -324,7 +326,7 @@ describe('InfoGroup', () => { render( , ) - expect(screen.getByTestId('field')).toBeInTheDocument() + expect(screen.getByTestId('field'))!.toBeInTheDocument() }) it('should handle items with built-in id', () => { @@ -334,7 +336,7 @@ describe('InfoGroup', () => { render( , ) - expect(screen.getByTestId('field')).toBeInTheDocument() + expect(screen.getByTestId('field'))!.toBeInTheDocument() }) }) }) diff --git a/web/app/components/datasets/preview/__tests__/container.spec.tsx b/web/app/components/datasets/preview/__tests__/container.spec.tsx index 86f6e3f85b..473d91f857 100644 --- a/web/app/components/datasets/preview/__tests__/container.spec.tsx +++ b/web/app/components/datasets/preview/__tests__/container.spec.tsx @@ -12,16 +12,16 @@ describe('PreviewContainer', () => { it('should render header content in a header element', () => { render(Header Title}>Body) - expect(screen.getByText('Header Title')).toBeInTheDocument() + expect(screen.getByText('Header Title'))!.toBeInTheDocument() const headerEl = screen.getByText('Header Title').closest('header') - expect(headerEl).toBeInTheDocument() + expect(headerEl)!.toBeInTheDocument() }) it('should render children in a main element', () => { render(Main content) const mainEl = screen.getByRole('main') - expect(mainEl).toHaveTextContent('Main content') + expect(mainEl)!.toHaveTextContent('Main content') }) it('should render both header and children simultaneously', () => { @@ -31,14 +31,14 @@ describe('PreviewContainer', () => { , ) - expect(screen.getByText('My Header')).toBeInTheDocument() - expect(screen.getByText('Body paragraph')).toBeInTheDocument() + expect(screen.getByText('My Header'))!.toBeInTheDocument() + expect(screen.getByText('Body paragraph'))!.toBeInTheDocument() }) it('should render without children', () => { render() - expect(screen.getByRole('main')).toBeInTheDocument() + expect(screen.getByRole('main'))!.toBeInTheDocument() expect(screen.getByRole('main').childElementCount).toBe(0) }) }) @@ -49,7 +49,7 @@ describe('PreviewContainer', () => { Content, ) - expect(container.firstElementChild).toHaveClass('outer-class') + expect(container.firstElementChild)!.toHaveClass('outer-class') }) it('should apply mainClassName to the main element', () => { @@ -58,9 +58,10 @@ describe('PreviewContainer', () => { ) const mainEl = screen.getByRole('main') - expect(mainEl).toHaveClass('custom-main') + expect(mainEl)!.toHaveClass('custom-main') // Default classes should still be present - expect(mainEl).toHaveClass('w-full', 'grow', 'overflow-y-auto', 'px-6', 'py-5') + // Default classes should still be present + expect(mainEl)!.toHaveClass('w-full', 'grow', 'overflow-y-auto', 'px-6', 'py-5') }) it('should forward ref to the inner container div', () => { @@ -70,7 +71,7 @@ describe('PreviewContainer', () => { ) expect(ref).toHaveBeenCalled() - const refArg = ref.mock.calls[0][0] + const refArg = ref.mock.calls[0]![0] expect(refArg).toBeInstanceOf(HTMLDivElement) }) @@ -82,7 +83,7 @@ describe('PreviewContainer', () => { ) const inner = screen.getByTestId('inner-container') - expect(inner).toHaveAttribute('id', 'container-1') + expect(inner)!.toHaveAttribute('id', 'container-1') }) it('should render ReactNode as header', () => { @@ -92,8 +93,8 @@ describe('PreviewContainer', () => { , ) - expect(screen.getByTestId('complex-header')).toBeInTheDocument() - expect(screen.getByText('Complex')).toBeInTheDocument() + expect(screen.getByTestId('complex-header'))!.toBeInTheDocument() + expect(screen.getByText('Complex'))!.toBeInTheDocument() }) }) @@ -103,7 +104,7 @@ describe('PreviewContainer', () => { render(Content) const headerEl = screen.getByText('Header').closest('header') - expect(headerEl).toHaveClass('border-b', 'border-divider-subtle') + expect(headerEl)!.toHaveClass('border-b', 'border-divider-subtle') }) it('should have inner div with flex column layout', () => { @@ -112,13 +113,13 @@ describe('PreviewContainer', () => { ) const inner = screen.getByTestId('inner') - expect(inner).toHaveClass('flex', 'h-full', 'w-full', 'flex-col') + expect(inner)!.toHaveClass('flex', 'h-full', 'w-full', 'flex-col') }) it('should have main with overflow-y-auto for scrolling', () => { render(Content) - expect(screen.getByRole('main')).toHaveClass('overflow-y-auto') + expect(screen.getByRole('main'))!.toHaveClass('overflow-y-auto') }) }) @@ -134,13 +135,13 @@ describe('PreviewContainer', () => { render(Content) const headerEl = screen.getByRole('banner') - expect(headerEl).toBeInTheDocument() + expect(headerEl)!.toBeInTheDocument() }) it('should render with null children', () => { render({null}) - expect(screen.getByRole('main')).toBeInTheDocument() + expect(screen.getByRole('main'))!.toBeInTheDocument() }) it('should render with multiple children', () => { @@ -152,9 +153,9 @@ describe('PreviewContainer', () => { , ) - expect(screen.getByText('Child 1')).toBeInTheDocument() - expect(screen.getByText('Child 2')).toBeInTheDocument() - expect(screen.getByText('Child 3')).toBeInTheDocument() + expect(screen.getByText('Child 1'))!.toBeInTheDocument() + expect(screen.getByText('Child 2'))!.toBeInTheDocument() + expect(screen.getByText('Child 3'))!.toBeInTheDocument() }) it('should not crash on re-render with different props', () => { @@ -166,8 +167,8 @@ describe('PreviewContainer', () => { Content B, ) - expect(screen.getByText('Second')).toBeInTheDocument() - expect(screen.getByText('Content B')).toBeInTheDocument() + expect(screen.getByText('Second'))!.toBeInTheDocument() + expect(screen.getByText('Content B'))!.toBeInTheDocument() }) }) }) diff --git a/web/app/components/datasets/rename-modal/__tests__/index.spec.tsx b/web/app/components/datasets/rename-modal/__tests__/index.spec.tsx index dbae959d8d..600e6c3434 100644 --- a/web/app/components/datasets/rename-modal/__tests__/index.spec.tsx +++ b/web/app/components/datasets/rename-modal/__tests__/index.spec.tsx @@ -138,43 +138,46 @@ describe('RenameDatasetModal', () => { it('should render without crashing', () => { render() // Check title is rendered (translation mock returns 'datasetSettings.title') - expect(screen.getByText('datasetSettings.title')).toBeInTheDocument() + // Check title is rendered (translation mock returns 'datasetSettings.title') + expect(screen.getByText('datasetSettings.title'))!.toBeInTheDocument() }) it('should render modal when show is true', () => { render() - expect(screen.getByText('datasetSettings.title')).toBeInTheDocument() + expect(screen.getByText('datasetSettings.title'))!.toBeInTheDocument() }) it('should render name input with dataset name', () => { render() const nameInput = screen.getByDisplayValue('Test Dataset') - expect(nameInput).toBeInTheDocument() + expect(nameInput)!.toBeInTheDocument() }) it('should render description textarea with dataset description', () => { render() const descriptionTextarea = screen.getByDisplayValue('Test description') - expect(descriptionTextarea).toBeInTheDocument() + expect(descriptionTextarea)!.toBeInTheDocument() }) it('should render cancel and save buttons', () => { render() - expect(screen.getByText('common.operation.cancel')).toBeInTheDocument() - expect(screen.getByText('common.operation.save')).toBeInTheDocument() + expect(screen.getByText('common.operation.cancel'))!.toBeInTheDocument() + expect(screen.getByText('common.operation.save'))!.toBeInTheDocument() }) it('should render close icon button', () => { render() // The modal renders with title and other elements // The close functionality is tested in user interactions - expect(screen.getByText('datasetSettings.title')).toBeInTheDocument() + // The modal renders with title and other elements + // The close functionality is tested in user interactions + expect(screen.getByText('datasetSettings.title'))!.toBeInTheDocument() }) it('should render form labels', () => { render() - expect(screen.getByText('datasetSettings.form.name')).toBeInTheDocument() - expect(screen.getByText('datasetSettings.form.desc')).toBeInTheDocument() + expect(screen.getByText('datasetSettings.form.name'))!.toBeInTheDocument() + expect(screen.getByText('datasetSettings.form.desc'))!.toBeInTheDocument() }) }) @@ -182,13 +185,13 @@ describe('RenameDatasetModal', () => { it('should render with emoji icon dataset', () => { const dataset = createMockDataset() render() - expect(screen.getByDisplayValue('Test Dataset')).toBeInTheDocument() + expect(screen.getByDisplayValue('Test Dataset'))!.toBeInTheDocument() }) it('should render with image icon dataset', () => { const dataset = createMockDatasetWithImageIcon() render() - expect(screen.getByDisplayValue('Test Dataset')).toBeInTheDocument() + expect(screen.getByDisplayValue('Test Dataset'))!.toBeInTheDocument() }) it('should render with empty description', () => { @@ -196,30 +199,30 @@ describe('RenameDatasetModal', () => { render() // Find the textarea by its placeholder const descriptionTextarea = screen.getByPlaceholderText('datasetSettings.form.descPlaceholder') - expect(descriptionTextarea).toHaveValue('') + expect(descriptionTextarea)!.toHaveValue('') }) it('should render with external knowledge dataset', () => { const dataset = createMockExternalDataset() render() - expect(screen.getByDisplayValue('Test Dataset')).toBeInTheDocument() + expect(screen.getByDisplayValue('Test Dataset'))!.toBeInTheDocument() }) it('should handle undefined onSuccess callback', () => { render() - expect(screen.getByDisplayValue('Test Dataset')).toBeInTheDocument() + expect(screen.getByDisplayValue('Test Dataset'))!.toBeInTheDocument() }) }) describe('State Management', () => { it('should initialize name state with dataset name', () => { render() - expect(screen.getByDisplayValue('Test Dataset')).toBeInTheDocument() + expect(screen.getByDisplayValue('Test Dataset'))!.toBeInTheDocument() }) it('should initialize description state with dataset description', () => { render() - expect(screen.getByDisplayValue('Test description')).toBeInTheDocument() + expect(screen.getByDisplayValue('Test description'))!.toBeInTheDocument() }) it('should update name state when input changes', () => { @@ -228,7 +231,7 @@ describe('RenameDatasetModal', () => { fireEvent.change(nameInput, { target: { value: 'New Dataset Name' } }) - expect(screen.getByDisplayValue('New Dataset Name')).toBeInTheDocument() + expect(screen.getByDisplayValue('New Dataset Name'))!.toBeInTheDocument() }) it('should update description state when textarea changes', () => { @@ -237,7 +240,7 @@ describe('RenameDatasetModal', () => { fireEvent.change(descriptionTextarea, { target: { value: 'New description' } }) - expect(screen.getByDisplayValue('New description')).toBeInTheDocument() + expect(screen.getByDisplayValue('New description'))!.toBeInTheDocument() }) it('should clear name when input is cleared', () => { @@ -246,7 +249,7 @@ describe('RenameDatasetModal', () => { fireEvent.change(nameInput, { target: { value: '' } }) - expect(nameInput).toHaveValue('') + expect(nameInput)!.toHaveValue('') }) it('should handle special characters in name', () => { @@ -255,7 +258,7 @@ describe('RenameDatasetModal', () => { fireEvent.change(nameInput, { target: { value: 'Dataset ' } }) - expect(screen.getByDisplayValue('Dataset ')).toBeInTheDocument() + expect(screen.getByDisplayValue('Dataset '))!.toBeInTheDocument() }) it('should handle very long name input', () => { @@ -265,7 +268,7 @@ describe('RenameDatasetModal', () => { fireEvent.change(nameInput, { target: { value: longName } }) - expect(screen.getByDisplayValue(longName)).toBeInTheDocument() + expect(screen.getByDisplayValue(longName))!.toBeInTheDocument() }) it('should handle multiline description', () => { @@ -276,7 +279,8 @@ describe('RenameDatasetModal', () => { fireEvent.change(descriptionTextarea, { target: { value: multilineDesc } }) // Verify the textarea contains the multiline value - expect(descriptionTextarea).toHaveValue(multilineDesc) + // Verify the textarea contains the multiline value + expect(descriptionTextarea)!.toHaveValue(multilineDesc) }) }) @@ -338,7 +342,7 @@ describe('RenameDatasetModal', () => { }) await waitFor(() => { - expect(saveButton).toBeDisabled() + expect(saveButton)!.toBeDisabled() }) // Resolve the promise to clean up @@ -354,6 +358,37 @@ describe('RenameDatasetModal', () => { // Verify the input can receive focus nameInput.focus() + // Just verify the element is focusable (don't check activeElement as it may differ in test environment) + // Just verify the element is focusable (don't check activeElement as it may differ in test environment) + // Just verify the element is focusable (don't check activeElement as it may differ in test environment) + // Just verify the element is focusable (don't check activeElement as it may differ in test environment) + // Just verify the element is focusable (don't check activeElement as it may differ in test environment) + // Just verify the element is focusable (don't check activeElement as it may differ in test environment) + // Just verify the element is focusable (don't check activeElement as it may differ in test environment) + // Just verify the element is focusable (don't check activeElement as it may differ in test environment) + // Just verify the element is focusable (don't check activeElement as it may differ in test environment) + // Just verify the element is focusable (don't check activeElement as it may differ in test environment) + // Just verify the element is focusable (don't check activeElement as it may differ in test environment) + // Just verify the element is focusable (don't check activeElement as it may differ in test environment) + // Just verify the element is focusable (don't check activeElement as it may differ in test environment) + // Just verify the element is focusable (don't check activeElement as it may differ in test environment) + // Just verify the element is focusable (don't check activeElement as it may differ in test environment) + // Just verify the element is focusable (don't check activeElement as it may differ in test environment) + // Just verify the element is focusable (don't check activeElement as it may differ in test environment) + // Just verify the element is focusable (don't check activeElement as it may differ in test environment) + // Just verify the element is focusable (don't check activeElement as it may differ in test environment) + // Just verify the element is focusable (don't check activeElement as it may differ in test environment) + // Just verify the element is focusable (don't check activeElement as it may differ in test environment) + // Just verify the element is focusable (don't check activeElement as it may differ in test environment) + // Just verify the element is focusable (don't check activeElement as it may differ in test environment) + // Just verify the element is focusable (don't check activeElement as it may differ in test environment) + // Just verify the element is focusable (don't check activeElement as it may differ in test environment) + // Just verify the element is focusable (don't check activeElement as it may differ in test environment) + // Just verify the element is focusable (don't check activeElement as it may differ in test environment) + // Just verify the element is focusable (don't check activeElement as it may differ in test environment) + // Just verify the element is focusable (don't check activeElement as it may differ in test environment) + // Just verify the element is focusable (don't check activeElement as it may differ in test environment) + // Just verify the element is focusable (don't check activeElement as it may differ in test environment) // Just verify the element is focusable (don't check activeElement as it may differ in test environment) expect(nameInput).not.toBeDisabled() }) @@ -365,6 +400,37 @@ describe('RenameDatasetModal', () => { // Verify the textarea can receive focus descriptionTextarea.focus() + // Just verify the element is focusable + // Just verify the element is focusable + // Just verify the element is focusable + // Just verify the element is focusable + // Just verify the element is focusable + // Just verify the element is focusable + // Just verify the element is focusable + // Just verify the element is focusable + // Just verify the element is focusable + // Just verify the element is focusable + // Just verify the element is focusable + // Just verify the element is focusable + // Just verify the element is focusable + // Just verify the element is focusable + // Just verify the element is focusable + // Just verify the element is focusable + // Just verify the element is focusable + // Just verify the element is focusable + // Just verify the element is focusable + // Just verify the element is focusable + // Just verify the element is focusable + // Just verify the element is focusable + // Just verify the element is focusable + // Just verify the element is focusable + // Just verify the element is focusable + // Just verify the element is focusable + // Just verify the element is focusable + // Just verify the element is focusable + // Just verify the element is focusable + // Just verify the element is focusable + // Just verify the element is focusable // Just verify the element is focusable expect(descriptionTextarea).not.toBeDisabled() }) @@ -429,7 +495,7 @@ describe('RenameDatasetModal', () => { await waitFor(() => { expect(mockUpdateDatasetSetting).toHaveBeenCalled() - const callArgs = mockUpdateDatasetSetting.mock.calls[0][0] + const callArgs = mockUpdateDatasetSetting.mock.calls[0]![0] expect(callArgs.body.external_knowledge_id).toBeUndefined() expect(callArgs.body.external_knowledge_api_id).toBeUndefined() }) @@ -604,6 +670,37 @@ describe('RenameDatasetModal', () => { expect(mockToast.error).toHaveBeenCalled() }) + // Save button should be enabled again + // Save button should be enabled again + // Save button should be enabled again + // Save button should be enabled again + // Save button should be enabled again + // Save button should be enabled again + // Save button should be enabled again + // Save button should be enabled again + // Save button should be enabled again + // Save button should be enabled again + // Save button should be enabled again + // Save button should be enabled again + // Save button should be enabled again + // Save button should be enabled again + // Save button should be enabled again + // Save button should be enabled again + // Save button should be enabled again + // Save button should be enabled again + // Save button should be enabled again + // Save button should be enabled again + // Save button should be enabled again + // Save button should be enabled again + // Save button should be enabled again + // Save button should be enabled again + // Save button should be enabled again + // Save button should be enabled again + // Save button should be enabled again + // Save button should be enabled again + // Save button should be enabled again + // Save button should be enabled again + // Save button should be enabled again // Save button should be enabled again expect(saveButton).not.toBeDisabled() }) @@ -660,8 +757,10 @@ describe('RenameDatasetModal', () => { render() // The modal should render with name label and input // AppIcon is rendered alongside the name input - expect(screen.getByText('datasetSettings.form.name')).toBeInTheDocument() - expect(screen.getByDisplayValue('Test Dataset')).toBeInTheDocument() + // The modal should render with name label and input + // AppIcon is rendered alongside the name input + expect(screen.getByText('datasetSettings.form.name'))!.toBeInTheDocument() + expect(screen.getByDisplayValue('Test Dataset'))!.toBeInTheDocument() }) it('should initialize icon state from dataset', () => { @@ -669,14 +768,16 @@ describe('RenameDatasetModal', () => { render() // The component initializes with the dataset's icon_info // This is verified by checking the form renders correctly - expect(screen.getByDisplayValue('Test Dataset')).toBeInTheDocument() + // The component initializes with the dataset's icon_info + // This is verified by checking the form renders correctly + expect(screen.getByDisplayValue('Test Dataset'))!.toBeInTheDocument() }) it('should initialize icon state from image icon dataset', () => { // Test with image icon - this triggers the icon_type === 'image' branch const imageDataset = createMockDatasetWithImageIcon() render() - expect(screen.getByDisplayValue('Test Dataset')).toBeInTheDocument() + expect(screen.getByDisplayValue('Test Dataset'))!.toBeInTheDocument() // The component should render successfully with image icon dataset }) @@ -734,6 +835,37 @@ describe('RenameDatasetModal', () => { it('should open icon picker when app icon is clicked (handleOpenAppIconPicker)', async () => { render() + // Initially picker should not be visible + // Initially picker should not be visible + // Initially picker should not be visible + // Initially picker should not be visible + // Initially picker should not be visible + // Initially picker should not be visible + // Initially picker should not be visible + // Initially picker should not be visible + // Initially picker should not be visible + // Initially picker should not be visible + // Initially picker should not be visible + // Initially picker should not be visible + // Initially picker should not be visible + // Initially picker should not be visible + // Initially picker should not be visible + // Initially picker should not be visible + // Initially picker should not be visible + // Initially picker should not be visible + // Initially picker should not be visible + // Initially picker should not be visible + // Initially picker should not be visible + // Initially picker should not be visible + // Initially picker should not be visible + // Initially picker should not be visible + // Initially picker should not be visible + // Initially picker should not be visible + // Initially picker should not be visible + // Initially picker should not be visible + // Initially picker should not be visible + // Initially picker should not be visible + // Initially picker should not be visible // Initially picker should not be visible expect(screen.queryByTestId('app-icon-picker')).not.toBeInTheDocument() @@ -743,7 +875,8 @@ describe('RenameDatasetModal', () => { }) // Picker should now be visible - expect(screen.getByTestId('app-icon-picker')).toBeInTheDocument() + // Picker should now be visible + expect(screen.getByTestId('app-icon-picker'))!.toBeInTheDocument() }) it('should select emoji icon and close picker (handleSelectAppIcon)', async () => { @@ -761,6 +894,37 @@ describe('RenameDatasetModal', () => { fireEvent.click(selectEmojiBtn) }) + // Picker should close after selection + // Picker should close after selection + // Picker should close after selection + // Picker should close after selection + // Picker should close after selection + // Picker should close after selection + // Picker should close after selection + // Picker should close after selection + // Picker should close after selection + // Picker should close after selection + // Picker should close after selection + // Picker should close after selection + // Picker should close after selection + // Picker should close after selection + // Picker should close after selection + // Picker should close after selection + // Picker should close after selection + // Picker should close after selection + // Picker should close after selection + // Picker should close after selection + // Picker should close after selection + // Picker should close after selection + // Picker should close after selection + // Picker should close after selection + // Picker should close after selection + // Picker should close after selection + // Picker should close after selection + // Picker should close after selection + // Picker should close after selection + // Picker should close after selection + // Picker should close after selection // Picker should close after selection expect(screen.queryByTestId('app-icon-picker')).not.toBeInTheDocument() @@ -800,6 +964,37 @@ describe('RenameDatasetModal', () => { fireEvent.click(selectImageBtn) }) + // Picker should close after selection + // Picker should close after selection + // Picker should close after selection + // Picker should close after selection + // Picker should close after selection + // Picker should close after selection + // Picker should close after selection + // Picker should close after selection + // Picker should close after selection + // Picker should close after selection + // Picker should close after selection + // Picker should close after selection + // Picker should close after selection + // Picker should close after selection + // Picker should close after selection + // Picker should close after selection + // Picker should close after selection + // Picker should close after selection + // Picker should close after selection + // Picker should close after selection + // Picker should close after selection + // Picker should close after selection + // Picker should close after selection + // Picker should close after selection + // Picker should close after selection + // Picker should close after selection + // Picker should close after selection + // Picker should close after selection + // Picker should close after selection + // Picker should close after selection + // Picker should close after selection // Picker should close after selection expect(screen.queryByTestId('app-icon-picker')).not.toBeInTheDocument() @@ -839,6 +1034,37 @@ describe('RenameDatasetModal', () => { fireEvent.click(closeBtn) }) + // Picker should close + // Picker should close + // Picker should close + // Picker should close + // Picker should close + // Picker should close + // Picker should close + // Picker should close + // Picker should close + // Picker should close + // Picker should close + // Picker should close + // Picker should close + // Picker should close + // Picker should close + // Picker should close + // Picker should close + // Picker should close + // Picker should close + // Picker should close + // Picker should close + // Picker should close + // Picker should close + // Picker should close + // Picker should close + // Picker should close + // Picker should close + // Picker should close + // Picker should close + // Picker should close + // Picker should close // Picker should close expect(screen.queryByTestId('app-icon-picker')).not.toBeInTheDocument() @@ -876,7 +1102,7 @@ describe('RenameDatasetModal', () => { }) render() - expect(screen.getByDisplayValue('Test Dataset')).toBeInTheDocument() + expect(screen.getByDisplayValue('Test Dataset'))!.toBeInTheDocument() }) it('should handle image icon with empty icon_url', async () => { @@ -891,7 +1117,7 @@ describe('RenameDatasetModal', () => { }) render() - expect(screen.getByDisplayValue('Test Dataset')).toBeInTheDocument() + expect(screen.getByDisplayValue('Test Dataset'))!.toBeInTheDocument() // Save and verify the icon_url is handled correctly const saveButton = screen.getByText('common.operation.save') @@ -925,7 +1151,7 @@ describe('RenameDatasetModal', () => { }) render() - expect(screen.getByDisplayValue('Test Dataset')).toBeInTheDocument() + expect(screen.getByDisplayValue('Test Dataset'))!.toBeInTheDocument() // Save and verify the icon is handled correctly const saveButton = screen.getByText('common.operation.save') @@ -958,7 +1184,7 @@ describe('RenameDatasetModal', () => { }) render() - expect(screen.getByDisplayValue('Test Dataset')).toBeInTheDocument() + expect(screen.getByDisplayValue('Test Dataset'))!.toBeInTheDocument() }) it('should handle rapid input changes', async () => { @@ -975,7 +1201,7 @@ describe('RenameDatasetModal', () => { fireEvent.change(nameInput, { target: { value: 'New Nam' } }) fireEvent.change(nameInput, { target: { value: 'New Name' } }) - expect(screen.getByDisplayValue('New Name')).toBeInTheDocument() + expect(screen.getByDisplayValue('New Name'))!.toBeInTheDocument() }) it('should handle double click on save button', async () => { @@ -995,7 +1221,8 @@ describe('RenameDatasetModal', () => { }) // Button should be disabled now - expect(saveButton).toBeDisabled() + // Button should be disabled now + expect(saveButton)!.toBeDisabled() // Second click should not trigger another API call because button is disabled await act(async () => { @@ -1017,7 +1244,7 @@ describe('RenameDatasetModal', () => { fireEvent.change(nameInput, { target: { value: '数据集 🎉 Dataset' } }) - expect(screen.getByDisplayValue('数据集 🎉 Dataset')).toBeInTheDocument() + expect(screen.getByDisplayValue('数据集 🎉 Dataset'))!.toBeInTheDocument() }) it('should handle unicode characters in description', () => { @@ -1026,7 +1253,7 @@ describe('RenameDatasetModal', () => { fireEvent.change(descriptionTextarea, { target: { value: '这是一个测试描述 🚀' } }) - expect(screen.getByDisplayValue('这是一个测试描述 🚀')).toBeInTheDocument() + expect(screen.getByDisplayValue('这是一个测试描述 🚀'))!.toBeInTheDocument() }) it('should preserve whitespace in description', () => { @@ -1036,7 +1263,7 @@ describe('RenameDatasetModal', () => { const testValue = 'Leading spaces with content' fireEvent.change(descriptionTextarea, { target: { value: testValue } }) - expect(descriptionTextarea).toHaveValue(testValue) + expect(descriptionTextarea)!.toHaveValue(testValue) }) }) @@ -1044,20 +1271,22 @@ describe('RenameDatasetModal', () => { it('should update when dataset prop changes', () => { const { rerender } = render() - expect(screen.getByDisplayValue('Test Dataset')).toBeInTheDocument() + expect(screen.getByDisplayValue('Test Dataset'))!.toBeInTheDocument() const newDataset = createMockDataset({ name: 'Different Dataset', description: 'Different description' }) rerender() // Note: The component uses useState with initial value, so it won't update // This tests that the initial render works correctly with different props - expect(screen.getByDisplayValue('Test Dataset')).toBeInTheDocument() + // Note: The component uses useState with initial value, so it won't update + // This tests that the initial render works correctly with different props + expect(screen.getByDisplayValue('Test Dataset'))!.toBeInTheDocument() }) it('should handle show prop toggle', () => { const { rerender } = render() - expect(screen.getByText('datasetSettings.title')).toBeInTheDocument() + expect(screen.getByText('datasetSettings.title'))!.toBeInTheDocument() rerender() @@ -1084,8 +1313,8 @@ describe('RenameDatasetModal', () => { const cancelButton = screen.getByText('common.operation.cancel') const saveButton = screen.getByText('common.operation.save') - expect(cancelButton).toBeEnabled() - expect(saveButton).toBeEnabled() + expect(cancelButton)!.toBeEnabled() + expect(saveButton)!.toBeEnabled() }) }) @@ -1105,7 +1334,7 @@ describe('RenameDatasetModal', () => { // Button should be disabled during loading await waitFor(() => { - expect(saveButton).toBeDisabled() + expect(saveButton)!.toBeDisabled() }) // Resolve promise to complete the test @@ -1148,6 +1377,37 @@ describe('RenameDatasetModal', () => { expect(mockToast.error).toHaveBeenCalledWith('common.actionMsg.modifiedUnsuccessfully') }) + // Button should be re-enabled after error + // Button should be re-enabled after error + // Button should be re-enabled after error + // Button should be re-enabled after error + // Button should be re-enabled after error + // Button should be re-enabled after error + // Button should be re-enabled after error + // Button should be re-enabled after error + // Button should be re-enabled after error + // Button should be re-enabled after error + // Button should be re-enabled after error + // Button should be re-enabled after error + // Button should be re-enabled after error + // Button should be re-enabled after error + // Button should be re-enabled after error + // Button should be re-enabled after error + // Button should be re-enabled after error + // Button should be re-enabled after error + // Button should be re-enabled after error + // Button should be re-enabled after error + // Button should be re-enabled after error + // Button should be re-enabled after error + // Button should be re-enabled after error + // Button should be re-enabled after error + // Button should be re-enabled after error + // Button should be re-enabled after error + // Button should be re-enabled after error + // Button should be re-enabled after error + // Button should be re-enabled after error + // Button should be re-enabled after error + // Button should be re-enabled after error // Button should be re-enabled after error expect(saveButton).not.toBeDisabled() }) diff --git a/web/app/components/datasets/settings/chunk-structure/__tests__/hooks.spec.tsx b/web/app/components/datasets/settings/chunk-structure/__tests__/hooks.spec.tsx index 8d44d19d09..518c74d0e1 100644 --- a/web/app/components/datasets/settings/chunk-structure/__tests__/hooks.spec.tsx +++ b/web/app/components/datasets/settings/chunk-structure/__tests__/hooks.spec.tsx @@ -23,49 +23,49 @@ describe('useChunkStructure', () => { const { result } = renderHook(() => useChunkStructure()) const generalOption = result.current.options[0] - expect(generalOption.id).toBe('text_model') + expect(generalOption!.id).toBe('text_model') }) it('should have icon for General option', () => { const { result } = renderHook(() => useChunkStructure()) const generalOption = result.current.options[0] - expect(generalOption.icon).toBeDefined() + expect(generalOption!.icon).toBeDefined() }) it('should have correct iconActiveColor for General option', () => { const { result } = renderHook(() => useChunkStructure()) const generalOption = result.current.options[0] - expect(generalOption.iconActiveColor).toBe('text-util-colors-indigo-indigo-600') + expect(generalOption!.iconActiveColor).toBe('text-util-colors-indigo-indigo-600') }) it('should have title for General option', () => { const { result } = renderHook(() => useChunkStructure()) const generalOption = result.current.options[0] - expect(generalOption.title).toBe('General') + expect(generalOption!.title).toBe('General') }) it('should have description for General option', () => { const { result } = renderHook(() => useChunkStructure()) const generalOption = result.current.options[0] - expect(generalOption.description).toBeDefined() + expect(generalOption!.description).toBeDefined() }) it('should have indigo effectColor for General option', () => { const { result } = renderHook(() => useChunkStructure()) const generalOption = result.current.options[0] - expect(generalOption.effectColor).toBe(EffectColor.indigo) + expect(generalOption!.effectColor).toBe(EffectColor.indigo) }) it('should have showEffectColor true for General option', () => { const { result } = renderHook(() => useChunkStructure()) const generalOption = result.current.options[0] - expect(generalOption.showEffectColor).toBe(true) + expect(generalOption!.showEffectColor).toBe(true) }) }) @@ -74,49 +74,49 @@ describe('useChunkStructure', () => { const { result } = renderHook(() => useChunkStructure()) const parentChildOption = result.current.options[1] - expect(parentChildOption.id).toBe('hierarchical_model') + expect(parentChildOption!.id).toBe('hierarchical_model') }) it('should have icon for Parent-Child option', () => { const { result } = renderHook(() => useChunkStructure()) const parentChildOption = result.current.options[1] - expect(parentChildOption.icon).toBeDefined() + expect(parentChildOption!.icon).toBeDefined() }) it('should have correct iconActiveColor for Parent-Child option', () => { const { result } = renderHook(() => useChunkStructure()) const parentChildOption = result.current.options[1] - expect(parentChildOption.iconActiveColor).toBe('text-util-colors-blue-light-blue-light-500') + expect(parentChildOption!.iconActiveColor).toBe('text-util-colors-blue-light-blue-light-500') }) it('should have title for Parent-Child option', () => { const { result } = renderHook(() => useChunkStructure()) const parentChildOption = result.current.options[1] - expect(parentChildOption.title).toBe('Parent-Child') + expect(parentChildOption!.title).toBe('Parent-Child') }) it('should have description for Parent-Child option', () => { const { result } = renderHook(() => useChunkStructure()) const parentChildOption = result.current.options[1] - expect(parentChildOption.description).toBeDefined() + expect(parentChildOption!.description).toBeDefined() }) it('should have blueLight effectColor for Parent-Child option', () => { const { result } = renderHook(() => useChunkStructure()) const parentChildOption = result.current.options[1] - expect(parentChildOption.effectColor).toBe(EffectColor.blueLight) + expect(parentChildOption!.effectColor).toBe(EffectColor.blueLight) }) it('should have showEffectColor true for Parent-Child option', () => { const { result } = renderHook(() => useChunkStructure()) const parentChildOption = result.current.options[1] - expect(parentChildOption.showEffectColor).toBe(true) + expect(parentChildOption!.showEffectColor).toBe(true) }) }) @@ -125,49 +125,49 @@ describe('useChunkStructure', () => { const { result } = renderHook(() => useChunkStructure()) const qaOption = result.current.options[2] - expect(qaOption.id).toBe('qa_model') + expect(qaOption!.id).toBe('qa_model') }) it('should have icon for Q&A option', () => { const { result } = renderHook(() => useChunkStructure()) const qaOption = result.current.options[2] - expect(qaOption.icon).toBeDefined() + expect(qaOption!.icon).toBeDefined() }) it('should have title for Q&A option', () => { const { result } = renderHook(() => useChunkStructure()) const qaOption = result.current.options[2] - expect(qaOption.title).toBe('Q&A') + expect(qaOption!.title).toBe('Q&A') }) it('should have description for Q&A option', () => { const { result } = renderHook(() => useChunkStructure()) const qaOption = result.current.options[2] - expect(qaOption.description).toBeDefined() + expect(qaOption!.description).toBeDefined() }) it('should not have effectColor for Q&A option', () => { const { result } = renderHook(() => useChunkStructure()) const qaOption = result.current.options[2] - expect(qaOption.effectColor).toBeUndefined() + expect(qaOption!.effectColor).toBeUndefined() }) it('should not have showEffectColor for Q&A option', () => { const { result } = renderHook(() => useChunkStructure()) const qaOption = result.current.options[2] - expect(qaOption.showEffectColor).toBeUndefined() + expect(qaOption!.showEffectColor).toBeUndefined() }) it('should not have iconActiveColor for Q&A option', () => { const { result } = renderHook(() => useChunkStructure()) const qaOption = result.current.options[2] - expect(qaOption.iconActiveColor).toBeUndefined() + expect(qaOption!.iconActiveColor).toBeUndefined() }) }) diff --git a/web/app/components/datasets/settings/form/components/__tests__/basic-info-section.spec.tsx b/web/app/components/datasets/settings/form/components/__tests__/basic-info-section.spec.tsx index 618a28d498..f34269f058 100644 --- a/web/app/components/datasets/settings/form/components/__tests__/basic-info-section.spec.tsx +++ b/web/app/components/datasets/settings/form/components/__tests__/basic-info-section.spec.tsx @@ -142,42 +142,43 @@ describe('BasicInfoSection', () => { describe('Rendering', () => { it('should render without crashing', () => { render() - expect(screen.getByText(/form\.nameAndIcon/i)).toBeInTheDocument() + expect(screen.getByText(/form\.nameAndIcon/i))!.toBeInTheDocument() }) it('should render name and icon section', () => { render() - expect(screen.getByText(/form\.nameAndIcon/i)).toBeInTheDocument() + expect(screen.getByText(/form\.nameAndIcon/i))!.toBeInTheDocument() }) it('should render description section', () => { render() - expect(screen.getByText(/form\.desc/i)).toBeInTheDocument() + expect(screen.getByText(/form\.desc/i))!.toBeInTheDocument() }) it('should render permissions section', () => { render() // Use exact match to avoid matching "permissionsOnlyMe" - expect(screen.getByText('datasetSettings.form.permissions')).toBeInTheDocument() + // Use exact match to avoid matching "permissionsOnlyMe" + expect(screen.getByText('datasetSettings.form.permissions'))!.toBeInTheDocument() }) it('should render name input with correct value', () => { render() const nameInput = screen.getByDisplayValue('Test Dataset') - expect(nameInput).toBeInTheDocument() + expect(nameInput)!.toBeInTheDocument() }) it('should render description textarea with correct value', () => { render() const descriptionTextarea = screen.getByDisplayValue('Test description') - expect(descriptionTextarea).toBeInTheDocument() + expect(descriptionTextarea)!.toBeInTheDocument() }) it('should render app icon with emoji', () => { const { container } = render() // The icon section should be rendered (emoji may be in a span or SVG) const iconSection = container.querySelector('[class*="cursor-pointer"]') - expect(iconSection).toBeInTheDocument() + expect(iconSection)!.toBeInTheDocument() }) }) @@ -197,7 +198,7 @@ describe('BasicInfoSection', () => { render() const nameInput = screen.getByDisplayValue('Test Dataset') - expect(nameInput).toBeDisabled() + expect(nameInput)!.toBeDisabled() }) it('should enable name input when embedding is available', () => { @@ -212,7 +213,7 @@ describe('BasicInfoSection', () => { // Find the name input by its structure - may be type=text or just input const nameInput = container.querySelector('input') - expect(nameInput).toHaveValue('') + expect(nameInput)!.toHaveValue('') }) }) @@ -232,14 +233,14 @@ describe('BasicInfoSection', () => { render() const descriptionTextarea = screen.getByDisplayValue('Test description') - expect(descriptionTextarea).toBeDisabled() + expect(descriptionTextarea)!.toBeDisabled() }) it('should render placeholder', () => { render() const descriptionTextarea = screen.getByPlaceholderText(/form\.descPlaceholder/i) - expect(descriptionTextarea).toBeInTheDocument() + expect(descriptionTextarea)!.toBeInTheDocument() }) }) @@ -261,12 +262,45 @@ describe('BasicInfoSection', () => { // AppIconPicker renders a modal with emoji tabs and options via portal // We just verify the component renders without crashing when picker is shown - expect(baseElement).toBeInTheDocument() + // AppIconPicker renders a modal with emoji tabs and options via portal + // We just verify the component renders without crashing when picker is shown + expect(baseElement)!.toBeInTheDocument() }) it('should not render AppIconPicker when showAppIconPicker is false', () => { const { container } = render() + // Check that AppIconPicker is not rendered + // Check that AppIconPicker is not rendered + // Check that AppIconPicker is not rendered + // Check that AppIconPicker is not rendered + // Check that AppIconPicker is not rendered + // Check that AppIconPicker is not rendered + // Check that AppIconPicker is not rendered + // Check that AppIconPicker is not rendered + // Check that AppIconPicker is not rendered + // Check that AppIconPicker is not rendered + // Check that AppIconPicker is not rendered + // Check that AppIconPicker is not rendered + // Check that AppIconPicker is not rendered + // Check that AppIconPicker is not rendered + // Check that AppIconPicker is not rendered + // Check that AppIconPicker is not rendered + // Check that AppIconPicker is not rendered + // Check that AppIconPicker is not rendered + // Check that AppIconPicker is not rendered + // Check that AppIconPicker is not rendered + // Check that AppIconPicker is not rendered + // Check that AppIconPicker is not rendered + // Check that AppIconPicker is not rendered + // Check that AppIconPicker is not rendered + // Check that AppIconPicker is not rendered + // Check that AppIconPicker is not rendered + // Check that AppIconPicker is not rendered + // Check that AppIconPicker is not rendered + // Check that AppIconPicker is not rendered + // Check that AppIconPicker is not rendered + // Check that AppIconPicker is not rendered // Check that AppIconPicker is not rendered expect(container.querySelector('[data-testid="app-icon-picker"]')).not.toBeInTheDocument() }) @@ -283,7 +317,7 @@ describe('BasicInfoSection', () => { // For image type, it renders an img element const img = screen.queryByRole('img') if (img) { - expect(img).toHaveAttribute('src', expect.stringContaining('icon.png')) + expect(img)!.toHaveAttribute('src', expect.stringContaining('icon.png')) } }) }) @@ -292,13 +326,13 @@ describe('BasicInfoSection', () => { it('should render with correct permission value', () => { render() - expect(screen.getByText(/form\.permissionsOnlyMe/i)).toBeInTheDocument() + expect(screen.getByText(/form\.permissionsOnlyMe/i))!.toBeInTheDocument() }) it('should render all team members permission', () => { render() - expect(screen.getByText(/form\.permissionsAllMember/i)).toBeInTheDocument() + expect(screen.getByText(/form\.permissionsAllMember/i))!.toBeInTheDocument() }) it('should be disabled when embedding is not available', () => { @@ -309,7 +343,7 @@ describe('BasicInfoSection', () => { // Check for disabled state via cursor-not-allowed class const disabledElement = container.querySelector('[class*="cursor-not-allowed"]') - expect(disabledElement).toBeInTheDocument() + expect(disabledElement)!.toBeInTheDocument() }) it('should be disabled when user is dataset operator', () => { @@ -318,7 +352,7 @@ describe('BasicInfoSection', () => { ) const disabledElement = container.querySelector('[class*="cursor-not-allowed"]') - expect(disabledElement).toBeInTheDocument() + expect(disabledElement)!.toBeInTheDocument() }) it('should call setPermission when permission changes', async () => { @@ -330,7 +364,7 @@ describe('BasicInfoSection', () => { await waitFor(() => { const allMemberOptions = screen.getAllByText(/form\.permissionsAllMember/i) - fireEvent.click(allMemberOptions[0]) + fireEvent.click(allMemberOptions[0]!) }) expect(setPermission).toHaveBeenCalledWith(DatasetPermission.allTeamMembers) @@ -349,7 +383,10 @@ describe('BasicInfoSection', () => { // For partial members permission, the member selector should be visible // The exact interaction depends on the MemberSelector component // We verify the component renders without crashing - expect(container).toBeInTheDocument() + // For partial members permission, the member selector should be visible + // The exact interaction depends on the MemberSelector component + // We verify the component renders without crashing + expect(container)!.toBeInTheDocument() }) }) @@ -358,7 +395,8 @@ describe('BasicInfoSection', () => { render() // Should still render but inputs might behave differently - expect(screen.getByText(/form\.nameAndIcon/i)).toBeInTheDocument() + // Should still render but inputs might behave differently + expect(screen.getByText(/form\.nameAndIcon/i))!.toBeInTheDocument() }) }) @@ -366,31 +404,31 @@ describe('BasicInfoSection', () => { it('should update when name prop changes', () => { const { rerender } = render() - expect(screen.getByDisplayValue('Initial Name')).toBeInTheDocument() + expect(screen.getByDisplayValue('Initial Name'))!.toBeInTheDocument() rerender() - expect(screen.getByDisplayValue('Updated Name')).toBeInTheDocument() + expect(screen.getByDisplayValue('Updated Name'))!.toBeInTheDocument() }) it('should update when description prop changes', () => { const { rerender } = render() - expect(screen.getByDisplayValue('Initial Description')).toBeInTheDocument() + expect(screen.getByDisplayValue('Initial Description'))!.toBeInTheDocument() rerender() - expect(screen.getByDisplayValue('Updated Description')).toBeInTheDocument() + expect(screen.getByDisplayValue('Updated Description'))!.toBeInTheDocument() }) it('should update when permission prop changes', () => { const { rerender } = render() - expect(screen.getByText(/form\.permissionsOnlyMe/i)).toBeInTheDocument() + expect(screen.getByText(/form\.permissionsOnlyMe/i))!.toBeInTheDocument() rerender() - expect(screen.getByText(/form\.permissionsAllMember/i)).toBeInTheDocument() + expect(screen.getByText(/form\.permissionsAllMember/i))!.toBeInTheDocument() }) }) @@ -406,7 +444,9 @@ describe('BasicInfoSection', () => { // For partial members, a member selector component should be rendered // We verify it renders without crashing - expect(container).toBeInTheDocument() + // For partial members, a member selector component should be rendered + // We verify it renders without crashing + expect(container)!.toBeInTheDocument() }) it('should handle empty member list', () => { @@ -417,7 +457,7 @@ describe('BasicInfoSection', () => { />, ) - expect(screen.getByText(/form\.permissionsOnlyMe/i)).toBeInTheDocument() + expect(screen.getByText(/form\.permissionsOnlyMe/i))!.toBeInTheDocument() }) }) diff --git a/web/app/components/datasets/settings/form/hooks/__tests__/use-form-state.spec.ts b/web/app/components/datasets/settings/form/hooks/__tests__/use-form-state.spec.ts index 00462619aa..ece275c433 100644 --- a/web/app/components/datasets/settings/form/hooks/__tests__/use-form-state.spec.ts +++ b/web/app/components/datasets/settings/form/hooks/__tests__/use-form-state.spec.ts @@ -174,7 +174,7 @@ describe('useFormState', () => { const { result } = renderHook(() => useFormState()) expect(result.current.memberList).toHaveLength(2) - expect(result.current.memberList[0].name).toBe('User 1') + expect(result.current.memberList[0]!.name).toBe('User 1') }) it('should return currentDataset from context', () => { diff --git a/web/app/components/datasets/settings/index-method/__tests__/index.spec.tsx b/web/app/components/datasets/settings/index-method/__tests__/index.spec.tsx index 7441274155..5e81611fc4 100644 --- a/web/app/components/datasets/settings/index-method/__tests__/index.spec.tsx +++ b/web/app/components/datasets/settings/index-method/__tests__/index.spec.tsx @@ -19,12 +19,12 @@ describe('IndexMethod', () => { describe('Rendering', () => { it('should render without crashing', () => { render() - expect(screen.getByText(/stepTwo\.qualified/)).toBeInTheDocument() + expect(screen.getByText(/stepTwo\.qualified/))!.toBeInTheDocument() }) it('should render High Quality option', () => { render() - expect(screen.getByText(/stepTwo\.qualified/)).toBeInTheDocument() + expect(screen.getByText(/stepTwo\.qualified/))!.toBeInTheDocument() }) it('should render Economy option', () => { @@ -34,17 +34,17 @@ describe('IndexMethod', () => { it('should render High Quality description', () => { render() - expect(screen.getByText(/form\.indexMethodHighQualityTip/)).toBeInTheDocument() + expect(screen.getByText(/form\.indexMethodHighQualityTip/))!.toBeInTheDocument() }) it('should render Economy description', () => { render() - expect(screen.getByText(/form\.indexMethodEconomyTip/)).toBeInTheDocument() + expect(screen.getByText(/form\.indexMethodEconomyTip/))!.toBeInTheDocument() }) it('should render recommended badge on High Quality', () => { render() - expect(screen.getByText(/stepTwo\.recommend/)).toBeInTheDocument() + expect(screen.getByText(/stepTwo\.recommend/))!.toBeInTheDocument() }) }) @@ -82,7 +82,7 @@ describe('IndexMethod', () => { // Find and click Economy option - use getAllByText and get the first one (title) const economyTitles = screen.getAllByText(/form\.indexMethodEconomy/) const economyTitle = economyTitles[0] - const card = economyTitle.closest('div')?.parentElement?.parentElement?.parentElement + const card = economyTitle!.closest('div')?.parentElement?.parentElement?.parentElement fireEvent.click(card!) expect(handleChange).toHaveBeenCalledWith(IndexingType.ECONOMICAL) @@ -114,7 +114,7 @@ describe('IndexMethod', () => { // Try to click Economy option - use getAllByText and get the first one (title) const economyTitles = screen.getAllByText(/form\.indexMethodEconomy/) const economyTitle = economyTitles[0] - const card = economyTitle.closest('div')?.parentElement?.parentElement?.parentElement + const card = economyTitle!.closest('div')?.parentElement?.parentElement?.parentElement fireEvent.click(card!) // Should not call onChange because Economy is disabled when current is QUALIFIED @@ -125,13 +125,13 @@ describe('IndexMethod', () => { describe('KeywordNumber', () => { it('should render KeywordNumber component inside Economy option', () => { render() - expect(getKeywordSlider()).toBeInTheDocument() + expect(getKeywordSlider())!.toBeInTheDocument() }) it('should pass keywordNumber to KeywordNumber component', () => { render() const input = screen.getByRole('textbox') - expect(input).toHaveValue('25') + expect(input)!.toHaveValue('25') }) it('should call onKeywordNumberChange when KeywordNumber changes', () => { @@ -160,13 +160,13 @@ describe('IndexMethod', () => { it('should show orange effect color for High Quality option', () => { const { container } = render() const orangeEffect = container.querySelector('.bg-util-colors-orange-orange-500') - expect(orangeEffect).toBeInTheDocument() + expect(orangeEffect)!.toBeInTheDocument() }) it('should show indigo effect color for Economy option', () => { const { container } = render() const indigoEffect = container.querySelector('.bg-util-colors-indigo-indigo-600') - expect(indigoEffect).toBeInTheDocument() + expect(indigoEffect)!.toBeInTheDocument() }) }) @@ -188,19 +188,20 @@ describe('IndexMethod', () => { it('should handle undefined currentValue', () => { render() // Should render without error - expect(screen.getByText(/stepTwo\.qualified/)).toBeInTheDocument() + // Should render without error + expect(screen.getByText(/stepTwo\.qualified/))!.toBeInTheDocument() }) it('should handle minimum keywordNumber', () => { render() const input = screen.getByRole('textbox') - expect(input).toHaveValue('0') + expect(input)!.toHaveValue('0') }) it('should handle max keywordNumber', () => { render() const input = screen.getByRole('textbox') - expect(input).toHaveValue('50') + expect(input)!.toHaveValue('50') }) }) }) diff --git a/web/app/components/datasets/settings/permission-selector/__tests__/index.spec.tsx b/web/app/components/datasets/settings/permission-selector/__tests__/index.spec.tsx index b17b1c9b11..355946402b 100644 --- a/web/app/components/datasets/settings/permission-selector/__tests__/index.spec.tsx +++ b/web/app/components/datasets/settings/permission-selector/__tests__/index.spec.tsx @@ -16,15 +16,15 @@ vi.mock('@/context/app-context', () => ({ describe('PermissionSelector', () => { const mockMemberList: Member[] = [ - { id: 'user-1', name: 'Current User', email: 'current@example.com', avatar: '', avatar_url: '', role: 'owner', last_login_at: '', created_at: '', status: 'active' }, - { id: 'user-2', name: 'John Doe', email: 'john@example.com', avatar: '', avatar_url: '', role: 'admin', last_login_at: '', created_at: '', status: 'active' }, - { id: 'user-3', name: 'Jane Smith', email: 'jane@example.com', avatar: '', avatar_url: '', role: 'editor', last_login_at: '', created_at: '', status: 'active' }, - { id: 'user-4', name: 'Dataset Operator', email: 'operator@example.com', avatar: '', avatar_url: '', role: 'dataset_operator', last_login_at: '', created_at: '', status: 'active' }, + { id: 'user-1', name: 'Current User', email: 'current@example.com', avatar: '', avatar_url: '', role: 'owner', last_login_at: '', created_at: '', status: 'active' }!, + { id: 'user-2', name: 'John Doe', email: 'john@example.com', avatar: '', avatar_url: '', role: 'admin', last_login_at: '', created_at: '', status: 'active' }!, + { id: 'user-3', name: 'Jane Smith', email: 'jane@example.com', avatar: '', avatar_url: '', role: 'editor', last_login_at: '', created_at: '', status: 'active' }!, + { id: 'user-4', name: 'Dataset Operator', email: 'operator@example.com', avatar: '', avatar_url: '', role: 'dataset_operator', last_login_at: '', created_at: '', status: 'active' }!, ] const defaultProps = { permission: DatasetPermission.onlyMe, - value: ['user-1'], + value: ['user-1'!], memberList: mockMemberList, onChange: vi.fn(), onMemberSelect: vi.fn(), @@ -37,17 +37,17 @@ describe('PermissionSelector', () => { describe('Rendering', () => { it('should render without crashing', () => { render() - expect(screen.getByText(/form\.permissionsOnlyMe/)).toBeInTheDocument() + expect(screen.getByText(/form\.permissionsOnlyMe/))!.toBeInTheDocument() }) it('should render Only Me option when permission is onlyMe', () => { render() - expect(screen.getByText(/form\.permissionsOnlyMe/)).toBeInTheDocument() + expect(screen.getByText(/form\.permissionsOnlyMe/))!.toBeInTheDocument() }) it('should render All Team Members option when permission is allTeamMembers', () => { render() - expect(screen.getByText(/form\.permissionsAllMember/)).toBeInTheDocument() + expect(screen.getByText(/form\.permissionsAllMember/))!.toBeInTheDocument() }) it('should render selected member names when permission is partialMembers', () => { @@ -59,7 +59,8 @@ describe('PermissionSelector', () => { />, ) // Should show member names - expect(screen.getByTitle(/Current User/)).toBeInTheDocument() + // Should show member names + expect(screen.getByTitle(/Current User/))!.toBeInTheDocument() }) }) @@ -97,7 +98,7 @@ describe('PermissionSelector', () => { await waitFor(() => { const onlyMeOptions = screen.getAllByText(/form\.permissionsOnlyMe/) - fireEvent.click(onlyMeOptions[0]) + fireEvent.click(onlyMeOptions[0]!) }) expect(handleChange).toHaveBeenCalledWith(DatasetPermission.onlyMe) @@ -112,7 +113,7 @@ describe('PermissionSelector', () => { await waitFor(() => { const allMemberOptions = screen.getAllByText(/form\.permissionsAllMember/) - fireEvent.click(allMemberOptions[0]) + fireEvent.click(allMemberOptions[0]!) }) expect(handleChange).toHaveBeenCalledWith(DatasetPermission.allTeamMembers) @@ -134,7 +135,7 @@ describe('PermissionSelector', () => { await waitFor(() => { const invitedOptions = screen.getAllByText(/form\.permissionsInvitedMembers/) - fireEvent.click(invitedOptions[0]) + fireEvent.click(invitedOptions[0]!) }) expect(handleChange).toHaveBeenCalledWith(DatasetPermission.partialMembers) @@ -156,8 +157,9 @@ describe('PermissionSelector', () => { await waitFor(() => { // Should show member list - expect(screen.getByText('John Doe')).toBeInTheDocument() - expect(screen.getByText('Jane Smith')).toBeInTheDocument() + // Should show member list + expect(screen.getByText('John Doe'))!.toBeInTheDocument() + expect(screen.getByText('Jane Smith'))!.toBeInTheDocument() }) }) @@ -222,7 +224,7 @@ describe('PermissionSelector', () => { // Type in search fireEvent.change(searchInput, { target: { value: 'John' } }) - expect(searchInput).toHaveValue('John') + expect(searchInput)!.toHaveValue('John') }) it('should render search input in partial members mode', async () => { @@ -238,7 +240,7 @@ describe('PermissionSelector', () => { // Wait for dropdown to open and search input to be available const searchInput = await screen.findByRole('textbox') - expect(searchInput).toBeInTheDocument() + expect(searchInput)!.toBeInTheDocument() }) it('should filter members after debounce completes', async () => { @@ -261,7 +263,7 @@ describe('PermissionSelector', () => { // Wait for debounce (500ms) + buffer await waitFor( () => { - expect(screen.getByText('John Doe')).toBeInTheDocument() + expect(screen.getByText('John Doe'))!.toBeInTheDocument() }, { timeout: 1000 }, ) @@ -283,14 +285,14 @@ describe('PermissionSelector', () => { // Type in search fireEvent.change(searchInput, { target: { value: 'test' } }) - expect(searchInput).toHaveValue('test') + expect(searchInput)!.toHaveValue('test') const clearButton = screen.getByTestId('input-clear') fireEvent.click(clearButton) // After clicking clear, input should be empty await waitFor(() => { - expect(searchInput).toHaveValue('') + expect(searchInput)!.toHaveValue('') }) }) @@ -314,7 +316,7 @@ describe('PermissionSelector', () => { // Wait for debounce await waitFor( () => { - expect(screen.getByText('John Doe')).toBeInTheDocument() + expect(screen.getByText('John Doe'))!.toBeInTheDocument() }, { timeout: 1000 }, ) @@ -340,7 +342,7 @@ describe('PermissionSelector', () => { // Wait for debounce and no results message await waitFor( () => { - expect(screen.getByText(/form\.onSearchResults/)).toBeInTheDocument() + expect(screen.getByText(/form\.onSearchResults/))!.toBeInTheDocument() }, { timeout: 1000 }, ) @@ -365,7 +367,9 @@ describe('PermissionSelector', () => { // Current user (showMe) should remain visible based on name match // The component uses useMemo to check if userProfile.name.includes(searchKeywords) - expect(searchInput).toHaveValue('Current') + // Current user (showMe) should remain visible based on name match + // The component uses useMemo to check if userProfile.name.includes(searchKeywords) + expect(searchInput)!.toHaveValue('Current') // Current User label appears multiple times (trigger + member list) expect(screen.getAllByText('Current User').length).toBeGreaterThanOrEqual(1) }) @@ -388,7 +392,8 @@ describe('PermissionSelector', () => { fireEvent.change(searchInput, { target: { value: 'current@' } }) // The component checks userProfile.email.includes(searchKeywords) - expect(searchInput).toHaveValue('current@') + // The component checks userProfile.email.includes(searchKeywords) + expect(searchInput)!.toHaveValue('current@') // Current User should remain visible based on email match expect(screen.getAllByText('Current User').length).toBeGreaterThanOrEqual(1) }) @@ -399,7 +404,7 @@ describe('PermissionSelector', () => { const { container } = render() // When disabled, the component has cursor-not-allowed! class (escaped in Tailwind) const triggerElement = container.querySelector('[class*="cursor-not-allowed"]') - expect(triggerElement).toBeInTheDocument() + expect(triggerElement)!.toBeInTheDocument() }) }) @@ -414,7 +419,8 @@ describe('PermissionSelector', () => { ) // Should display single avatar - expect(screen.getByTitle(/Current User/)).toBeInTheDocument() + // Should display single avatar + expect(screen.getByTitle(/Current User/))!.toBeInTheDocument() }) it('should display two avatars when two or more members selected', () => { @@ -427,7 +433,8 @@ describe('PermissionSelector', () => { ) // Should display member names - expect(screen.getByTitle(/Current User, John Doe/)).toBeInTheDocument() + // Should display member names + expect(screen.getByTitle(/Current User, John Doe/))!.toBeInTheDocument() }) }) @@ -440,18 +447,18 @@ describe('PermissionSelector', () => { />, ) - expect(screen.getByText(/form\.permissionsOnlyMe/)).toBeInTheDocument() + expect(screen.getByText(/form\.permissionsOnlyMe/))!.toBeInTheDocument() }) it('should handle member list with only current user', () => { render( , ) - expect(screen.getByText(/form\.permissionsOnlyMe/)).toBeInTheDocument() + expect(screen.getByText(/form\.permissionsOnlyMe/))!.toBeInTheDocument() }) it('should only show members with allowed roles', () => { @@ -472,7 +479,8 @@ describe('PermissionSelector', () => { ) // The component renders - the filtering logic is internal - expect(screen.getByTitle(/Current User/)).toBeInTheDocument() + // The component renders - the filtering logic is internal + expect(screen.getByTitle(/Current User/))!.toBeInTheDocument() }) }) @@ -480,11 +488,11 @@ describe('PermissionSelector', () => { it('should update when permission prop changes', () => { const { rerender } = render() - expect(screen.getByText(/form\.permissionsOnlyMe/)).toBeInTheDocument() + expect(screen.getByText(/form\.permissionsOnlyMe/))!.toBeInTheDocument() rerender() - expect(screen.getByText(/form\.permissionsAllMember/)).toBeInTheDocument() + expect(screen.getByText(/form\.permissionsAllMember/))!.toBeInTheDocument() }) }) }) diff --git a/web/app/components/datasets/settings/permission-selector/index.tsx b/web/app/components/datasets/settings/permission-selector/index.tsx index a7182d8f79..8c31799add 100644 --- a/web/app/components/datasets/settings/permission-selector/index.tsx +++ b/web/app/components/datasets/settings/permission-selector/index.tsx @@ -133,8 +133,8 @@ const PermissionSelector = ({ { selectedMembers.length === 1 && ( ) @@ -143,14 +143,14 @@ const PermissionSelector = ({ selectedMembers.length >= 2 && ( <> diff --git a/web/app/components/develop/code.tsx b/web/app/components/develop/code.tsx index 59d6c94e5d..86d57c806d 100644 --- a/web/app/components/develop/code.tsx +++ b/web/app/components/develop/code.tsx @@ -226,7 +226,7 @@ function useTabGroupProps(availableLanguages: string[]) { const activeLanguage = [...(availableLanguages || [])].sort( (a, z) => preferredLanguages.indexOf(z) - preferredLanguages.indexOf(a), )[0] - const languageIndex = availableLanguages?.indexOf(activeLanguage) || 0 + const languageIndex = availableLanguages?.indexOf(activeLanguage!) || 0 const newSelectedIndex = languageIndex === -1 ? selectedIndex : languageIndex if (newSelectedIndex !== selectedIndex) setSelectedIndex(newSelectedIndex) diff --git a/web/app/components/develop/hooks/use-doc-toc.ts b/web/app/components/develop/hooks/use-doc-toc.ts index d42cb68b00..1eba8ca8e3 100644 --- a/web/app/components/develop/hooks/use-doc-toc.ts +++ b/web/app/components/develop/hooks/use-doc-toc.ts @@ -57,7 +57,7 @@ export const useDocToc = ({ appDetail, locale }: UseDocTocOptions) => { const tocItems = extractTocFromArticle() setToc(tocItems) if (tocItems.length > 0) - setActiveSection(getTargetId(tocItems[0].href)) + setActiveSection(getTargetId(tocItems[0]!.href)) }, 0) return () => clearTimeout(timer) }, [appDetail, locale]) diff --git a/web/app/components/develop/secret-key/__tests__/secret-key-button.spec.tsx b/web/app/components/develop/secret-key/__tests__/secret-key-button.spec.tsx index e5134b995d..b4f5c139e0 100644 --- a/web/app/components/develop/secret-key/__tests__/secret-key-button.spec.tsx +++ b/web/app/components/develop/secret-key/__tests__/secret-key-button.spec.tsx @@ -19,18 +19,18 @@ describe('SecretKeyButton', () => { describe('rendering', () => { it('should render the button', () => { render() - expect(screen.getByRole('button')).toBeInTheDocument() + expect(screen.getByRole('button'))!.toBeInTheDocument() }) it('should render the API key text', () => { render() - expect(screen.getByText('appApi.apiKey')).toBeInTheDocument() + expect(screen.getByText('appApi.apiKey'))!.toBeInTheDocument() }) it('should render the key icon', () => { const { container } = render() const svg = container.querySelector('svg') - expect(svg).toBeInTheDocument() + expect(svg)!.toBeInTheDocument() }) it('should not show modal initially', () => { @@ -49,7 +49,7 @@ describe('SecretKeyButton', () => { await user.click(button) }) - expect(screen.getByTestId('secret-key-modal')).toBeInTheDocument() + expect(screen.getByTestId('secret-key-modal'))!.toBeInTheDocument() }) it('should close modal when onClose is called', async () => { @@ -61,7 +61,7 @@ describe('SecretKeyButton', () => { await user.click(button) }) - expect(screen.getByTestId('secret-key-modal')).toBeInTheDocument() + expect(screen.getByTestId('secret-key-modal'))!.toBeInTheDocument() const closeButton = screen.getByTestId('close-modal') await act(async () => { @@ -80,7 +80,7 @@ describe('SecretKeyButton', () => { await act(async () => { await user.click(button) }) - expect(screen.getByTestId('secret-key-modal')).toBeInTheDocument() + expect(screen.getByTestId('secret-key-modal'))!.toBeInTheDocument() const closeButton = screen.getByTestId('close-modal') await act(async () => { @@ -91,7 +91,7 @@ describe('SecretKeyButton', () => { await act(async () => { await user.click(button) }) - expect(screen.getByTestId('secret-key-modal')).toBeInTheDocument() + expect(screen.getByTestId('secret-key-modal'))!.toBeInTheDocument() }) }) @@ -111,7 +111,7 @@ describe('SecretKeyButton', () => { await user.click(button) }) - expect(screen.getByText('Modal for app-123')).toBeInTheDocument() + expect(screen.getByText('Modal for app-123'))!.toBeInTheDocument() }) it('should handle undefined appId', async () => { @@ -123,7 +123,7 @@ describe('SecretKeyButton', () => { await user.click(button) }) - expect(screen.getByText('Modal for no-app')).toBeInTheDocument() + expect(screen.getByText('Modal for no-app'))!.toBeInTheDocument() }) it('should apply custom textCls', () => { @@ -145,19 +145,19 @@ describe('SecretKeyButton', () => { it('should have icon container with flex layout', () => { const { container } = render() const iconContainer = container.querySelector('.flex.items-center.justify-center') - expect(iconContainer).toBeInTheDocument() + expect(iconContainer)!.toBeInTheDocument() }) it('should have correct icon dimensions', () => { const { container } = render() const iconContainer = container.querySelector('.h-3\\.5.w-3\\.5') - expect(iconContainer).toBeInTheDocument() + expect(iconContainer)!.toBeInTheDocument() }) it('should have tertiary text color on icon', () => { const { container } = render() const icon = container.querySelector('.text-text-tertiary') - expect(icon).toBeInTheDocument() + expect(icon)!.toBeInTheDocument() }) }) @@ -193,7 +193,7 @@ describe('SecretKeyButton', () => { await user.click(button) }) - expect(screen.getByTestId('secret-key-modal')).toBeInTheDocument() + expect(screen.getByTestId('secret-key-modal'))!.toBeInTheDocument() }) it('should pass onClose callback to modal', async () => { @@ -218,7 +218,7 @@ describe('SecretKeyButton', () => { it('should have accessible button', () => { render() const button = screen.getByRole('button') - expect(button).toBeInTheDocument() + expect(button)!.toBeInTheDocument() }) it('should be keyboard accessible', async () => { @@ -233,7 +233,7 @@ describe('SecretKeyButton', () => { await user.keyboard('{Enter}') }) - expect(screen.getByTestId('secret-key-modal')).toBeInTheDocument() + expect(screen.getByTestId('secret-key-modal'))!.toBeInTheDocument() }) }) @@ -251,10 +251,10 @@ describe('SecretKeyButton', () => { expect(buttons).toHaveLength(2) await act(async () => { - await user.click(buttons[0]) + await user.click(buttons[0]!) }) - expect(screen.getByText('Modal for app-1')).toBeInTheDocument() + expect(screen.getByText('Modal for app-1'))!.toBeInTheDocument() const closeButton = screen.getByTestId('close-modal') await act(async () => { @@ -262,10 +262,10 @@ describe('SecretKeyButton', () => { }) await act(async () => { - await user.click(buttons[1]) + await user.click(buttons[1]!) }) - expect(screen.getByText('Modal for app-2')).toBeInTheDocument() + expect(screen.getByText('Modal for app-2'))!.toBeInTheDocument() }) }) }) diff --git a/web/app/components/develop/tag.tsx b/web/app/components/develop/tag.tsx index 3178046338..082d63a798 100644 --- a/web/app/components/develop/tag.tsx +++ b/web/app/components/develop/tag.tsx @@ -53,7 +53,7 @@ export function Tag({ }: ITagProps) { return ( {children} diff --git a/web/app/components/explore/create-app-modal/__tests__/index.spec.tsx b/web/app/components/explore/create-app-modal/__tests__/index.spec.tsx index fd6877d421..5a14807478 100644 --- a/web/app/components/explore/create-app-modal/__tests__/index.spec.tsx +++ b/web/app/components/explore/create-app-modal/__tests__/index.spec.tsx @@ -106,24 +106,24 @@ describe('CreateAppModal', () => { it('should render create title and actions when creating', async () => { await setup({ appName: 'My App', isEditModal: false }) - expect(screen.getByText('explore.appCustomize.title:{"name":"My App"}')).toBeInTheDocument() - expect(screen.getByRole('button', { name: /common\.operation\.create/ })).toBeInTheDocument() - expect(screen.getByRole('button', { name: 'common.operation.cancel' })).toBeInTheDocument() + expect(screen.getByText('explore.appCustomize.title:{"name":"My App"}'))!.toBeInTheDocument() + expect(screen.getByRole('button', { name: /common\.operation\.create/ }))!.toBeInTheDocument() + expect(screen.getByRole('button', { name: 'common.operation.cancel' }))!.toBeInTheDocument() }) it('should render edit-only fields when editing a chat app', async () => { await setup({ isEditModal: true, appMode: AppModeEnum.CHAT, max_active_requests: 5 }) - expect(screen.getByText('app.editAppTitle')).toBeInTheDocument() - expect(screen.getByRole('button', { name: /common\.operation\.save/ })).toBeInTheDocument() - expect(screen.getByRole('switch')).toBeInTheDocument() + expect(screen.getByText('app.editAppTitle'))!.toBeInTheDocument() + expect(screen.getByRole('button', { name: /common\.operation\.save/ }))!.toBeInTheDocument() + expect(screen.getByRole('switch'))!.toBeInTheDocument() expect((screen.getByRole('spinbutton') as HTMLInputElement).value).toBe('5') }) it.each([AppModeEnum.ADVANCED_CHAT, AppModeEnum.AGENT_CHAT])('should render answer icon switch when editing %s app', async (mode) => { await setup({ isEditModal: true, appMode: mode }) - expect(screen.getByRole('switch')).toBeInTheDocument() + expect(screen.getByRole('switch'))!.toBeInTheDocument() }) it('should not render answer icon switch when editing a non-chat app', async () => { @@ -143,13 +143,13 @@ describe('CreateAppModal', () => { it('should disable confirm action when confirmDisabled is true', async () => { await setup({ confirmDisabled: true }) - expect(screen.getByRole('button', { name: /common\.operation\.create/ })).toBeDisabled() + expect(screen.getByRole('button', { name: /common\.operation\.create/ }))!.toBeDisabled() }) it('should disable confirm action when appName is empty', async () => { await setup({ appName: ' ' }) - expect(screen.getByRole('button', { name: /common\.operation\.create/ })).toBeDisabled() + expect(screen.getByRole('button', { name: /common\.operation\.create/ }))!.toBeDisabled() }) }) @@ -204,8 +204,8 @@ describe('CreateAppModal', () => { await setup({ isEditModal: false }) - expect(screen.getByText('billing.apps.fullTip2')).toBeInTheDocument() - expect(screen.getByRole('button', { name: /common\.operation\.create/ })).toBeDisabled() + expect(screen.getByText('billing.apps.fullTip2'))!.toBeInTheDocument() + expect(screen.getByRole('button', { name: /common\.operation\.create/ }))!.toBeDisabled() }) it('should allow saving when apps quota is reached in edit mode', async () => { @@ -217,7 +217,7 @@ describe('CreateAppModal', () => { await setup({ isEditModal: true }) expect(screen.queryByText('billing.apps.fullTip2')).not.toBeInTheDocument() - expect(screen.getByRole('button', { name: /common\.operation\.save/ })).toBeEnabled() + expect(screen.getByRole('button', { name: /common\.operation\.save/ }))!.toBeEnabled() }) }) @@ -314,7 +314,7 @@ describe('CreateAppModal', () => { fireEvent.click(getAppIconTrigger()) - expect(screen.getByRole('button', { name: 'app.iconPicker.cancel' })).toBeInTheDocument() + expect(screen.getByRole('button', { name: 'app.iconPicker.cancel' }))!.toBeInTheDocument() fireEvent.click(screen.getByRole('button', { name: 'app.iconPicker.cancel' })) @@ -347,7 +347,7 @@ describe('CreateAppModal', () => { }) expect(onConfirm).toHaveBeenCalledTimes(1) - const payload = onConfirm.mock.calls[0][0] + const payload = onConfirm.mock.calls[0]![0] expect(payload).toMatchObject({ icon_type: 'emoji', icon: '😀', @@ -392,7 +392,7 @@ describe('CreateAppModal', () => { }) expect(onConfirm).toHaveBeenCalledTimes(1) - const payload = onConfirm.mock.calls[0][0] + const payload = onConfirm.mock.calls[0]![0] expect(payload).toMatchObject({ icon_type: 'emoji', icon: '🤖', @@ -431,7 +431,7 @@ describe('CreateAppModal', () => { expect(onConfirm).toHaveBeenCalledTimes(1) expect(onHide).toHaveBeenCalledTimes(1) - const payload = onConfirm.mock.calls[0][0] + const payload = onConfirm.mock.calls[0]![0] expect(payload).toMatchObject({ name: 'My App', icon_type: 'emoji', @@ -453,7 +453,7 @@ describe('CreateAppModal', () => { }) expect(onConfirm).toHaveBeenCalledTimes(1) - expect(onConfirm.mock.calls[0][0]).toMatchObject({ description: 'Updated description' }) + expect(onConfirm.mock.calls[0]![0]).toMatchObject({ description: 'Updated description' }) }) it('should omit icon_background when submitting with image icon', async () => { @@ -469,7 +469,7 @@ describe('CreateAppModal', () => { vi.advanceTimersByTime(300) }) - const payload = onConfirm.mock.calls[0][0] + const payload = onConfirm.mock.calls[0]![0] expect(payload).toMatchObject({ icon_type: 'image', icon: 'file-123', @@ -493,7 +493,7 @@ describe('CreateAppModal', () => { vi.advanceTimersByTime(300) }) - const payload = onConfirm.mock.calls[0][0] + const payload = onConfirm.mock.calls[0]![0] expect(payload).toMatchObject({ use_icon_as_answer_icon: true, max_active_requests: 12, @@ -508,7 +508,7 @@ describe('CreateAppModal', () => { vi.advanceTimersByTime(300) }) - const payload = onConfirm.mock.calls[0][0] + const payload = onConfirm.mock.calls[0]![0] expect(payload.max_active_requests).toBeUndefined() }) @@ -521,7 +521,7 @@ describe('CreateAppModal', () => { vi.advanceTimersByTime(300) }) - const payload = onConfirm.mock.calls[0][0] + const payload = onConfirm.mock.calls[0]![0] expect(payload.max_active_requests).toBeUndefined() }) diff --git a/web/app/components/explore/try-app/app-info/__tests__/use-get-requirements.spec.ts b/web/app/components/explore/try-app/app-info/__tests__/use-get-requirements.spec.ts index c6c3353a57..076278b3ed 100644 --- a/web/app/components/explore/try-app/app-info/__tests__/use-get-requirements.spec.ts +++ b/web/app/components/explore/try-app/app-info/__tests__/use-get-requirements.spec.ts @@ -59,8 +59,8 @@ describe('useGetRequirements', () => { ) expect(result.current.requirements).toHaveLength(1) - expect(result.current.requirements[0].name).toBe('openai') - expect(result.current.requirements[0].iconUrl).toBe('https://marketplace.api/plugins/langgenius/openai/icon') + expect(result.current.requirements[0]!.name).toBe('openai') + expect(result.current.requirements[0]!.iconUrl).toBe('https://marketplace.api/plugins/langgenius/openai/icon') }) it('returns model provider for completion mode', () => { @@ -84,7 +84,7 @@ describe('useGetRequirements', () => { ) expect(result.current.requirements).toHaveLength(1) - expect(result.current.requirements[0].name).toBe('claude') + expect(result.current.requirements[0]!.name).toBe('claude') }) it('returns model provider and tools for agent-chat mode', () => { @@ -166,7 +166,7 @@ describe('useGetRequirements', () => { ) expect(result.current.requirements).toHaveLength(1) - expect(result.current.requirements[0].name).toBe('openai') + expect(result.current.requirements[0]!.name).toBe('openai') }) }) @@ -232,7 +232,7 @@ describe('useGetRequirements', () => { ) expect(result.current.requirements).toHaveLength(1) - expect(result.current.requirements[0].name).toBe('claude-3-opus') + expect(result.current.requirements[0]!.name).toBe('claude-3-opus') }) it('returns empty requirements when flow data has no nodes', () => { @@ -373,7 +373,7 @@ describe('useGetRequirements', () => { ) expect(result.current.requirements).toHaveLength(1) - expect(result.current.requirements[0].name).toBe('gpt-4') + expect(result.current.requirements[0]!.name).toBe('gpt-4') }) }) @@ -398,7 +398,7 @@ describe('useGetRequirements', () => { useGetRequirements({ appDetail, appId: 'test-app-id' }), ) - expect(result.current.requirements[0].iconUrl).toBe('https://marketplace.api/plugins/org/plugin/icon') + expect(result.current.requirements[0]!.iconUrl).toBe('https://marketplace.api/plugins/org/plugin/icon') }) it('maps google model provider to gemini plugin icon URL', () => { @@ -421,7 +421,7 @@ describe('useGetRequirements', () => { useGetRequirements({ appDetail, appId: 'test-app-id' }), ) - expect(result.current.requirements[0].iconUrl).toBe('https://marketplace.api/plugins/langgenius/gemini/icon') + expect(result.current.requirements[0]!.iconUrl).toBe('https://marketplace.api/plugins/langgenius/gemini/icon') }) it('maps special builtin tool providers to *_tool plugin icon URL', () => { diff --git a/web/app/components/explore/try-app/app-info/use-get-requirements.ts b/web/app/components/explore/try-app/app-info/use-get-requirements.ts index 6458c76037..3ad89eee7e 100644 --- a/web/app/components/explore/try-app/app-info/use-get-requirements.ts +++ b/web/app/components/explore/try-app/app-info/use-get-requirements.ts @@ -44,13 +44,13 @@ const parseProviderId = (providerId: string): ProviderInfo | null => { if (segments.length === 1) { return { organization: 'langgenius', - providerName: segments[0], + providerName: segments[0]!, } } return { - organization: segments[0], - providerName: segments[1], + organization: segments[0]!, + providerName: segments[1]!, } } diff --git a/web/app/components/explore/try-app/preview/basic-app-preview.tsx b/web/app/components/explore/try-app/preview/basic-app-preview.tsx index 6954546b2e..43fb00600f 100644 --- a/web/app/components/explore/try-app/preview/basic-app-preview.tsx +++ b/web/app/components/explore/try-app/preview/basic-app-preview.tsx @@ -238,7 +238,7 @@ const BasicAppPreview: FC = ({ }, enabled: !!(modelConfig.file_upload?.enabled || modelConfig.file_upload?.image?.enabled), allowed_file_types: modelConfig.file_upload?.allowed_file_types || [], - allowed_file_extensions: modelConfig.file_upload?.allowed_file_extensions || [...FILE_EXTS[SupportUploadFileTypes.image], ...FILE_EXTS[SupportUploadFileTypes.video]].map(ext => `.${ext}`), + allowed_file_extensions: modelConfig.file_upload?.allowed_file_extensions || [...(FILE_EXTS[SupportUploadFileTypes.image] ?? []), ...(FILE_EXTS[SupportUploadFileTypes.video] ?? [])].map(ext => `.${ext}`), allowed_file_upload_methods: modelConfig.file_upload?.allowed_file_upload_methods || modelConfig.file_upload?.image?.transfer_methods || ['local_file', 'remote_url'], number_limits: modelConfig.file_upload?.number_limits || modelConfig.file_upload?.image?.number_limits || 3, fileUploadConfig: {}, diff --git a/web/app/components/goto-anything/actions/__tests__/index.spec.ts b/web/app/components/goto-anything/actions/__tests__/index.spec.ts index 12bdb192f2..ff7ab1e575 100644 --- a/web/app/components/goto-anything/actions/__tests__/index.spec.ts +++ b/web/app/components/goto-anything/actions/__tests__/index.spec.ts @@ -81,20 +81,20 @@ describe('createActions', () => { const actions = createActions(true, false) as Record expect(actions).toHaveProperty('node') - expect(actions.node.title).toBe('Workflow Nodes') + expect(actions.node!.title).toBe('Workflow Nodes') }) it('includes rag-pipeline nodes action on rag-pipeline pages', () => { const actions = createActions(false, true) as Record expect(actions).toHaveProperty('node') - expect(actions.node.title).toBe('RAG Pipeline Nodes') + expect(actions.node!.title).toBe('RAG Pipeline Nodes') }) it('rag-pipeline page takes priority over workflow page', () => { const actions = createActions(true, true) as Record - expect(actions.node.title).toBe('RAG Pipeline Nodes') + expect(actions.node!.title).toBe('RAG Pipeline Nodes') }) }) @@ -180,7 +180,7 @@ describe('searchAnything', () => { const results = await searchAnything('en', 'my query', undefined, dynamicActions) - expect(dynamicActions.slash.search).not.toHaveBeenCalled() + expect(dynamicActions.slash!.search).not.toHaveBeenCalled() expect(results).toHaveLength(2) expect(results).toEqual(expect.arrayContaining([ expect.objectContaining({ id: 'a1' }), @@ -206,7 +206,7 @@ describe('searchAnything', () => { const results = await searchAnything('en', 'query', undefined, dynamicActions) expect(results).toHaveLength(1) - expect(results[0].id).toBe('k1') + expect(results[0]!.id).toBe('k1') expect(warnSpy).toHaveBeenCalled() warnSpy.mockRestore() }) diff --git a/web/app/components/goto-anything/actions/__tests__/knowledge.spec.ts b/web/app/components/goto-anything/actions/__tests__/knowledge.spec.ts index 55592cd487..2124eccd81 100644 --- a/web/app/components/goto-anything/actions/__tests__/knowledge.spec.ts +++ b/web/app/components/goto-anything/actions/__tests__/knowledge.spec.ts @@ -59,7 +59,7 @@ describe('knowledgeAction', () => { const results = await knowledgeAction.search('@knowledge', '', 'en') - expect(results[0].path).toBe('/datasets/ds-ext/hitTesting') + expect(results[0]!.path).toBe('/datasets/ds-ext/hitTesting') }) it('generates correct path for non-external provider', async () => { @@ -76,7 +76,7 @@ describe('knowledgeAction', () => { const results = await knowledgeAction.search('@knowledge', '', 'en') - expect(results[0].path).toBe('/datasets/ds-2/documents') + expect(results[0]!.path).toBe('/datasets/ds-2/documents') }) it('returns empty array on API failure', async () => { diff --git a/web/app/components/goto-anything/actions/__tests__/recent-store.spec.ts b/web/app/components/goto-anything/actions/__tests__/recent-store.spec.ts index d2fb346286..da1dc86124 100644 --- a/web/app/components/goto-anything/actions/__tests__/recent-store.spec.ts +++ b/web/app/components/goto-anything/actions/__tests__/recent-store.spec.ts @@ -51,7 +51,7 @@ describe('recent-store', () => { const stored = getRecentItems() expect(stored.map(i => i.id)).toEqual(['a', 'b']) - expect(stored[0].title).toBe('A updated') + expect(stored[0]!.title).toBe('A updated') }) it('caps the list at 8 items, evicting the oldest', () => { @@ -60,8 +60,8 @@ describe('recent-store', () => { const stored = getRecentItems() expect(stored).toHaveLength(8) - expect(stored[0].id).toBe('item-9') - expect(stored[7].id).toBe('item-2') + expect(stored[0]!.id).toBe('item-9') + expect(stored[7]!.id).toBe('item-2') }) it('silently swallows storage errors', () => { diff --git a/web/app/components/goto-anything/actions/commands/__tests__/direct-commands.spec.ts b/web/app/components/goto-anything/actions/commands/__tests__/direct-commands.spec.ts index 88bd8b1045..f14098e970 100644 --- a/web/app/components/goto-anything/actions/commands/__tests__/direct-commands.spec.ts +++ b/web/app/components/goto-anything/actions/commands/__tests__/direct-commands.spec.ts @@ -70,7 +70,7 @@ describe('docsCommand', () => { const results = await docsCommand.search('', 'en') - expect(results[0].description).toBe('Open help documentation') + expect(results[0]!.description).toBe('Open help documentation') mockT.mockImplementation((key: string) => key) }) @@ -82,8 +82,8 @@ describe('docsCommand', () => { it('registered handler opens doc URL with correct locale', async () => { docsCommand.register?.({} as Record) const openSpy = vi.spyOn(window, 'open').mockImplementation(() => null) - const handlers = vi.mocked(registerCommands).mock.calls[0][0] - await handlers['navigation.doc']() + const handlers = vi.mocked(registerCommands).mock.calls[0]![0] + await handlers['navigation.doc']!() expect(openSpy).toHaveBeenCalledWith('https://docs.dify.ai/en', '_blank', 'noopener,noreferrer') openSpy.mockRestore() @@ -183,7 +183,7 @@ describe('communityCommand', () => { const results = await communityCommand.search('', 'en') - expect(results[0].description).toBe('Open Discord community') + expect(results[0]!.description).toBe('Open Discord community') mockT.mockImplementation((key: string) => key) }) @@ -195,8 +195,8 @@ describe('communityCommand', () => { it('registered handler opens URL from args', async () => { communityCommand.register?.({} as Record) const openSpy = vi.spyOn(window, 'open').mockImplementation(() => null) - const handlers = vi.mocked(registerCommands).mock.calls[0][0] - await handlers['navigation.community']({ url: 'https://custom-url.com' }) + const handlers = vi.mocked(registerCommands).mock.calls[0]![0] + await handlers['navigation.community']!({ url: 'https://custom-url.com' }) expect(openSpy).toHaveBeenCalledWith('https://custom-url.com', '_blank', 'noopener,noreferrer') openSpy.mockRestore() @@ -205,8 +205,8 @@ describe('communityCommand', () => { it('registered handler falls back to default URL when no args', async () => { communityCommand.register?.({} as Record) const openSpy = vi.spyOn(window, 'open').mockImplementation(() => null) - const handlers = vi.mocked(registerCommands).mock.calls[0][0] - await handlers['navigation.community']() + const handlers = vi.mocked(registerCommands).mock.calls[0]![0] + await handlers['navigation.community']!() expect(openSpy).toHaveBeenCalledWith('https://discord.gg/5AEfbxcd9k', '_blank', 'noopener,noreferrer') openSpy.mockRestore() @@ -260,7 +260,7 @@ describe('forumCommand', () => { const results = await forumCommand.search('', 'en') - expect(results[0].description).toBe('Open community feedback discussions') + expect(results[0]!.description).toBe('Open community feedback discussions') mockT.mockImplementation((key: string) => key) }) @@ -272,8 +272,8 @@ describe('forumCommand', () => { it('registered handler opens URL from args', async () => { forumCommand.register?.({} as Record) const openSpy = vi.spyOn(window, 'open').mockImplementation(() => null) - const handlers = vi.mocked(registerCommands).mock.calls[0][0] - await handlers['navigation.forum']({ url: 'https://custom-forum.com' }) + const handlers = vi.mocked(registerCommands).mock.calls[0]![0] + await handlers['navigation.forum']!({ url: 'https://custom-forum.com' }) expect(openSpy).toHaveBeenCalledWith('https://custom-forum.com', '_blank', 'noopener,noreferrer') openSpy.mockRestore() @@ -282,8 +282,8 @@ describe('forumCommand', () => { it('registered handler falls back to default URL when no args', async () => { forumCommand.register?.({} as Record) const openSpy = vi.spyOn(window, 'open').mockImplementation(() => null) - const handlers = vi.mocked(registerCommands).mock.calls[0][0] - await handlers['navigation.forum']() + const handlers = vi.mocked(registerCommands).mock.calls[0]![0] + await handlers['navigation.forum']!() expect(openSpy).toHaveBeenCalledWith('https://forum.dify.ai', '_blank', 'noopener,noreferrer') openSpy.mockRestore() diff --git a/web/app/components/goto-anything/actions/commands/__tests__/go.spec.tsx b/web/app/components/goto-anything/actions/commands/__tests__/go.spec.tsx index 719eddf77b..82cdfa330c 100644 --- a/web/app/components/goto-anything/actions/commands/__tests__/go.spec.tsx +++ b/web/app/components/goto-anything/actions/commands/__tests__/go.spec.tsx @@ -40,15 +40,15 @@ describe('goCommand', () => { const results = await goCommand.search('plugins', 'en') expect(results).toHaveLength(1) - expect(results[0].id).toBe('go-plugins') + expect(results[0]!.id).toBe('go-plugins') }) it('filters by label match (case-insensitive)', async () => { const results = await goCommand.search('Knowledge', 'en') expect(results).toHaveLength(1) - expect(results[0].id).toBe('go-datasets') - expect(results[0].title).toBe('Knowledge') + expect(results[0]!.id).toBe('go-datasets') + expect(results[0]!.title).toBe('Knowledge') }) it('returns command results with navigation.go data', async () => { @@ -85,9 +85,9 @@ describe('goCommand', () => { it('registered handler navigates to the provided path', async () => { Object.defineProperty(window, 'location', { value: { href: '' }, writable: true }) goCommand.register?.({} as Record) - const handlers = vi.mocked(registerCommands).mock.calls[0][0] + const handlers = vi.mocked(registerCommands).mock.calls[0]![0] - await handlers['navigation.go']({ path: '/datasets' }) + await handlers['navigation.go']!({ path: '/datasets' }) expect(window.location.href).toBe('/datasets') }) @@ -95,10 +95,10 @@ describe('goCommand', () => { it('registered handler does nothing when path is missing', async () => { Object.defineProperty(window, 'location', { value: { href: '/current' }, writable: true }) goCommand.register?.({} as Record) - const handlers = vi.mocked(registerCommands).mock.calls[0][0] + const handlers = vi.mocked(registerCommands).mock.calls[0]![0] - await handlers['navigation.go']() - await handlers['navigation.go']({}) + await handlers['navigation.go']!() + await handlers['navigation.go']!({}) expect(window.location.href).toBe('/current') }) diff --git a/web/app/components/goto-anything/actions/commands/__tests__/language.spec.ts b/web/app/components/goto-anything/actions/commands/__tests__/language.spec.ts index 54aa28d24a..da6ede6a3a 100644 --- a/web/app/components/goto-anything/actions/commands/__tests__/language.spec.ts +++ b/web/app/components/goto-anything/actions/commands/__tests__/language.spec.ts @@ -42,14 +42,14 @@ describe('languageCommand', () => { const results = await languageCommand.search('english', 'en') expect(results).toHaveLength(1) - expect(results[0].id).toBe('lang-en-US') + expect(results[0]!.id).toBe('lang-en-US') }) it('filters languages by value query', async () => { const results = await languageCommand.search('zh', 'en') expect(results).toHaveLength(1) - expect(results[0].id).toBe('lang-zh-Hans') + expect(results[0]!.id).toBe('lang-zh-Hans') }) it('returns command data with i18n.set command', async () => { diff --git a/web/app/components/goto-anything/actions/commands/__tests__/registry.spec.ts b/web/app/components/goto-anything/actions/commands/__tests__/registry.spec.ts index 2a13ffd1ea..d2623be434 100644 --- a/web/app/components/goto-anything/actions/commands/__tests__/registry.spec.ts +++ b/web/app/components/goto-anything/actions/commands/__tests__/registry.spec.ts @@ -202,7 +202,7 @@ describe('SlashCommandRegistry', () => { const results = await registry.search('/hem') expect(results).toHaveLength(1) - expect(results[0].title).toBe('/theme') + expect(results[0]!.title).toBe('/theme') }) it('fuzzy search also matches aliases', async () => { @@ -236,7 +236,7 @@ describe('SlashCommandRegistry', () => { const results = await registry.search('/') expect(results).toHaveLength(1) - expect(results[0].title).toBe('/docs') + expect(results[0]!.title).toBe('/docs') }) it('skips unavailable handler in exact match', async () => { diff --git a/web/app/components/goto-anything/actions/commands/__tests__/theme.spec.ts b/web/app/components/goto-anything/actions/commands/__tests__/theme.spec.ts index 3dd45aad11..4a79da5518 100644 --- a/web/app/components/goto-anything/actions/commands/__tests__/theme.spec.ts +++ b/web/app/components/goto-anything/actions/commands/__tests__/theme.spec.ts @@ -41,7 +41,7 @@ describe('themeCommand', () => { const results = await themeCommand.search('dark', 'en') expect(results).toHaveLength(1) - expect(results[0].id).toBe('dark') + expect(results[0]!.id).toBe('dark') }) }) diff --git a/web/app/components/goto-anything/command-selector.tsx b/web/app/components/goto-anything/command-selector.tsx index 96385abd0a..93430eafc4 100644 --- a/web/app/components/goto-anything/command-selector.tsx +++ b/web/app/components/goto-anything/command-selector.tsx @@ -64,7 +64,7 @@ const CommandSelector: FC = ({ actions, onCommandSelect, searchFilter, co if (allItems.length > 0 && onCommandValueChange) { const currentValueExists = allItems.some(item => item.shortcut === commandValue) if (!currentValueExists) - onCommandValueChange(allItems[0].shortcut) + onCommandValueChange(allItems[0]!.shortcut) } }, [searchFilter, allItems.length]) diff --git a/web/app/components/goto-anything/hooks/__tests__/use-goto-anything-results.spec.ts b/web/app/components/goto-anything/hooks/__tests__/use-goto-anything-results.spec.ts index b1b543d35a..e5393a05a9 100644 --- a/web/app/components/goto-anything/hooks/__tests__/use-goto-anything-results.spec.ts +++ b/web/app/components/goto-anything/hooks/__tests__/use-goto-anything-results.spec.ts @@ -111,8 +111,8 @@ describe('useGotoAnythingResults', () => { const { result } = renderHook(() => useGotoAnythingResults(createMockOptions())) expect(result.current.dedupedResults).toHaveLength(2) - expect(result.current.dedupedResults[0].id).toBe('1') - expect(result.current.dedupedResults[1].id).toBe('2') + expect(result.current.dedupedResults[0]!.id).toBe('1') + expect(result.current.dedupedResults[1]!.id).toBe('2') }) it('should keep first occurrence when duplicates exist', () => { @@ -129,7 +129,7 @@ describe('useGotoAnythingResults', () => { const { result } = renderHook(() => useGotoAnythingResults(createMockOptions())) expect(result.current.dedupedResults).toHaveLength(1) - expect(result.current.dedupedResults[0].title).toBe('First') + expect(result.current.dedupedResults[0]!.title).toBe('First') }) it('should handle different types with same id', () => { diff --git a/web/app/components/goto-anything/hooks/use-goto-anything-results.ts b/web/app/components/goto-anything/hooks/use-goto-anything-results.ts index 36e8397b6f..2f9174fc53 100644 --- a/web/app/components/goto-anything/hooks/use-goto-anything-results.ts +++ b/web/app/components/goto-anything/hooks/use-goto-anything-results.ts @@ -110,7 +110,7 @@ export const useGotoAnythingResults = ( if (!acc[result.type]) acc[result.type] = [] - acc[result.type].push(result) + acc[result.type]!.push(result) return acc }, {} as Record), [dedupedResults]) @@ -125,7 +125,7 @@ export const useGotoAnythingResults = ( const currentValueExists = dedupedResults.some(result => `${result.type}-${result.id}` === cmdVal) if (!currentValueExists) - setCmdVal(`${dedupedResults[0].type}-${dedupedResults[0].id}`) + setCmdVal(`${dedupedResults[0]!.type}-${dedupedResults[0]!.id}`) }, [isCommandsMode, dedupedResults, cmdVal, setCmdVal]) return { diff --git a/web/app/components/goto-anything/index.tsx b/web/app/components/goto-anything/index.tsx index 829a95f7e7..f3bf40f62a 100644 --- a/web/app/components/goto-anything/index.tsx +++ b/web/app/components/goto-anything/index.tsx @@ -111,7 +111,7 @@ const GotoAnything: FC = ({ // Check if it's a complete slash command if (query.startsWith('/')) { const commandName = query.substring(1).split(' ')[0] - const handler = slashCommandRegistry.findCommand(commandName) + const handler = slashCommandRegistry.findCommand(commandName!) // If it's a direct mode command, execute immediately const isAvailable = handler?.isAvailable?.() ?? true diff --git a/web/app/components/header/account-dropdown/__tests__/compliance.spec.tsx b/web/app/components/header/account-dropdown/__tests__/compliance.spec.tsx index 8165434b3a..15439b157f 100644 --- a/web/app/components/header/account-dropdown/__tests__/compliance.spec.tsx +++ b/web/app/components/header/account-dropdown/__tests__/compliance.spec.tsx @@ -99,7 +99,8 @@ describe('Compliance', () => { renderCompliance() // Assert - expect(screen.getByText('common.userProfile.compliance')).toBeInTheDocument() + // Assert + expect(screen.getByText('common.userProfile.compliance'))!.toBeInTheDocument() }) it('should show SOC2, ISO, GDPR items when opened', () => { @@ -107,10 +108,11 @@ describe('Compliance', () => { openMenuAndRender() // Assert - expect(screen.getByText('common.compliance.soc2Type1')).toBeInTheDocument() - expect(screen.getByText('common.compliance.soc2Type2')).toBeInTheDocument() - expect(screen.getByText('common.compliance.iso27001')).toBeInTheDocument() - expect(screen.getByText('common.compliance.gdpr')).toBeInTheDocument() + // Assert + expect(screen.getByText('common.compliance.soc2Type1'))!.toBeInTheDocument() + expect(screen.getByText('common.compliance.soc2Type2'))!.toBeInTheDocument() + expect(screen.getByText('common.compliance.iso27001'))!.toBeInTheDocument() + expect(screen.getByText('common.compliance.gdpr'))!.toBeInTheDocument() }) }) @@ -158,7 +160,7 @@ describe('Compliance', () => { // Act openMenuAndRender() const downloadButtons = screen.getAllByText('common.operation.download') - fireEvent.click(downloadButtons[0]) + fireEvent.click(downloadButtons[0]!) // Assert await waitFor(() => { @@ -183,7 +185,7 @@ describe('Compliance', () => { // Act openMenuAndRender() const downloadButtons = screen.getAllByText('common.operation.download') - fireEvent.click(downloadButtons[0]) + fireEvent.click(downloadButtons[0]!) // Assert await waitFor(() => { @@ -198,7 +200,7 @@ describe('Compliance', () => { // Act openMenuAndRender() const upgradeBadges = screen.getAllByText('billing.upgradeBtn.encourageShort') - fireEvent.click(upgradeBadges[0]) + fireEvent.click(upgradeBadges[0]!) // Assert expect(mockSetShowPricingModal).toHaveBeenCalled() @@ -218,7 +220,7 @@ describe('Compliance', () => { openMenuAndRender() // SOC2 Type II is restricted for professional const upgradeBadges = screen.getAllByText('billing.upgradeBtn.encourageShort') - fireEvent.click(upgradeBadges[0]) + fireEvent.click(upgradeBadges[0]!) // Assert expect(mockSetShowAccountSettingModal).toHaveBeenCalledWith({ @@ -251,7 +253,7 @@ describe('Compliance', () => { await waitFor(() => { const busyButton = menuItem!.querySelector('button[aria-busy="true"]') expect(busyButton).not.toBeNull() - expect(busyButton).toBeDisabled() + expect(busyButton)!.toBeDisabled() expect(busyButton!.querySelector('.animate-spin')).not.toBeNull() }, { timeout: 10000 }) @@ -286,7 +288,7 @@ describe('Compliance', () => { await waitFor(() => { const busyButton = menuItem!.querySelector('button[aria-busy="true"]') expect(busyButton).not.toBeNull() - expect(busyButton).toBeDisabled() + expect(busyButton)!.toBeDisabled() expect(getDocDownloadUrl).toHaveBeenCalledTimes(1) }, { timeout: 10000 }) diff --git a/web/app/components/header/account-dropdown/workplace-selector/__tests__/index.spec.tsx b/web/app/components/header/account-dropdown/workplace-selector/__tests__/index.spec.tsx index 338096a9e1..e1d5216555 100644 --- a/web/app/components/header/account-dropdown/workplace-selector/__tests__/index.spec.tsx +++ b/web/app/components/header/account-dropdown/workplace-selector/__tests__/index.spec.tsx @@ -115,11 +115,11 @@ describe('WorkplaceSelector', () => { it('should render current workspace and available workspace options', () => { renderComponent() - expect(screen.getByTestId('workplace-selector-trigger')).toHaveTextContent('Workspace 1') - expect(screen.getByTestId('workspace-option-1')).toBeInTheDocument() - expect(screen.getByTestId('workspace-option-2')).toBeInTheDocument() - expect(screen.getByTestId('workspace-option-1')).toHaveTextContent('Workspace 1') - expect(screen.getByTestId('workspace-option-2')).toHaveTextContent('Workspace 2') + expect(screen.getByTestId('workplace-selector-trigger'))!.toHaveTextContent('Workspace 1') + expect(screen.getByTestId('workspace-option-1'))!.toBeInTheDocument() + expect(screen.getByTestId('workspace-option-2'))!.toBeInTheDocument() + expect(screen.getByTestId('workspace-option-1'))!.toHaveTextContent('Workspace 1') + expect(screen.getByTestId('workspace-option-2'))!.toHaveTextContent('Workspace 2') }) }) @@ -127,7 +127,7 @@ describe('WorkplaceSelector', () => { it('should switch workspace successfully', async () => { vi.mocked(switchWorkspace).mockResolvedValue({ result: 'success', - new_tenant: mockWorkspaces[1], + new_tenant: mockWorkspaces[1]!, }) renderComponent() diff --git a/web/app/components/header/account-setting/__tests__/index.spec.tsx b/web/app/components/header/account-setting/__tests__/index.spec.tsx index d4e093bd30..d37b0bbcf2 100644 --- a/web/app/components/header/account-setting/__tests__/index.spec.tsx +++ b/web/app/components/header/account-setting/__tests__/index.spec.tsx @@ -200,13 +200,14 @@ describe('AccountSetting', () => { renderAccountSetting() // Assert - expect(screen.getByText('common.userProfile.settings')).toBeInTheDocument() - expect(screen.getByText('common.settings.provider')).toBeInTheDocument() + // Assert + expect(screen.getByText('common.userProfile.settings'))!.toBeInTheDocument() + expect(screen.getByText('common.settings.provider'))!.toBeInTheDocument() expect(screen.getAllByText('common.settings.members').length).toBeGreaterThan(0) - expect(screen.getByText('common.settings.billing')).toBeInTheDocument() - expect(screen.getByText('common.settings.dataSource')).toBeInTheDocument() - expect(screen.getByText('common.settings.apiBasedExtension')).toBeInTheDocument() - expect(screen.getByText('custom.custom')).toBeInTheDocument() + expect(screen.getByText('common.settings.billing'))!.toBeInTheDocument() + expect(screen.getByText('common.settings.dataSource'))!.toBeInTheDocument() + expect(screen.getByText('common.settings.apiBasedExtension'))!.toBeInTheDocument() + expect(screen.getByText('custom.custom'))!.toBeInTheDocument() expect(screen.getAllByText('common.settings.language').length).toBeGreaterThan(0) }) @@ -228,6 +229,68 @@ describe('AccountSetting', () => { // Act renderAccountSetting() + // Assert + // On mobile, the labels should not be rendered as per the implementation + // Assert + // On mobile, the labels should not be rendered as per the implementation + // Assert + // On mobile, the labels should not be rendered as per the implementation + // Assert + // On mobile, the labels should not be rendered as per the implementation + // Assert + // On mobile, the labels should not be rendered as per the implementation + // Assert + // On mobile, the labels should not be rendered as per the implementation + // Assert + // On mobile, the labels should not be rendered as per the implementation + // Assert + // On mobile, the labels should not be rendered as per the implementation + // Assert + // On mobile, the labels should not be rendered as per the implementation + // Assert + // On mobile, the labels should not be rendered as per the implementation + // Assert + // On mobile, the labels should not be rendered as per the implementation + // Assert + // On mobile, the labels should not be rendered as per the implementation + // Assert + // On mobile, the labels should not be rendered as per the implementation + // Assert + // On mobile, the labels should not be rendered as per the implementation + // Assert + // On mobile, the labels should not be rendered as per the implementation + // Assert + // On mobile, the labels should not be rendered as per the implementation + // Assert + // On mobile, the labels should not be rendered as per the implementation + // Assert + // On mobile, the labels should not be rendered as per the implementation + // Assert + // On mobile, the labels should not be rendered as per the implementation + // Assert + // On mobile, the labels should not be rendered as per the implementation + // Assert + // On mobile, the labels should not be rendered as per the implementation + // Assert + // On mobile, the labels should not be rendered as per the implementation + // Assert + // On mobile, the labels should not be rendered as per the implementation + // Assert + // On mobile, the labels should not be rendered as per the implementation + // Assert + // On mobile, the labels should not be rendered as per the implementation + // Assert + // On mobile, the labels should not be rendered as per the implementation + // Assert + // On mobile, the labels should not be rendered as per the implementation + // Assert + // On mobile, the labels should not be rendered as per the implementation + // Assert + // On mobile, the labels should not be rendered as per the implementation + // Assert + // On mobile, the labels should not be rendered as per the implementation + // Assert + // On mobile, the labels should not be rendered as per the implementation // Assert // On mobile, the labels should not be rendered as per the implementation expect(screen.queryByText('common.settings.provider')).not.toBeInTheDocument() @@ -243,10 +306,41 @@ describe('AccountSetting', () => { // Act renderAccountSetting() + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert // Assert expect(screen.queryByText('common.settings.provider')).not.toBeInTheDocument() expect(screen.queryByText('common.settings.members')).not.toBeInTheDocument() - expect(screen.getByText('common.settings.language')).toBeInTheDocument() + expect(screen.getByText('common.settings.language'))!.toBeInTheDocument() }) it('should hide billing and custom tabs when disabled', () => { @@ -260,6 +354,37 @@ describe('AccountSetting', () => { // Act renderAccountSetting() + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert // Assert expect(screen.queryByText('common.settings.billing')).not.toBeInTheDocument() expect(screen.queryByText('custom.custom')).not.toBeInTheDocument() @@ -277,7 +402,8 @@ describe('AccountSetting', () => { // Assert expect(mockOnTabChange).toHaveBeenCalledWith(ACCOUNT_SETTING_TAB.PROVIDER) // Check for content from ModelProviderPage - expect(screen.getByText('common.modelProvider.models')).toBeInTheDocument() + // Check for content from ModelProviderPage + expect(screen.getByText('common.modelProvider.models'))!.toBeInTheDocument() }) it('should navigate through various tabs and show correct details', () => { @@ -304,11 +430,11 @@ describe('AccountSetting', () => { expect(screen.getAllByText('custom.custom').length).toBeGreaterThan(1) // Language - fireEvent.click(screen.getAllByText('common.settings.language')[0]) + fireEvent.click(screen.getAllByText('common.settings.language')[0]!) expect(screen.getAllByText('common.settings.language').length).toBeGreaterThan(1) // Members - fireEvent.click(screen.getAllByText('common.settings.members')[0]) + fireEvent.click(screen.getAllByText('common.settings.members')[0]!) expect(screen.getAllByText('common.settings.members').length).toBeGreaterThan(1) }) }) @@ -344,8 +470,9 @@ describe('AccountSetting', () => { fireEvent.change(input, { target: { value: 'test-search' } }) // Assert - expect(input).toHaveValue('test-search') - expect(screen.getByText('common.modelProvider.models')).toBeInTheDocument() + // Assert + expect(input)!.toHaveValue('test-search') + expect(screen.getByText('common.modelProvider.models'))!.toBeInTheDocument() }) it('should handle scroll event in panel', () => { @@ -354,11 +481,12 @@ describe('AccountSetting', () => { const scrollContainer = screen.getByRole('dialog').querySelector('.overscroll-contain') // Assert - expect(scrollContainer).toBeInTheDocument() + // Assert + expect(scrollContainer)!.toBeInTheDocument() if (scrollContainer) { // Scroll down fireEvent.scroll(scrollContainer, { target: { scrollTop: 100 } }) - expect(scrollContainer).toHaveClass('overscroll-contain') + expect(scrollContainer)!.toHaveClass('overscroll-contain') // Scroll back up fireEvent.scroll(scrollContainer, { target: { scrollTop: 0 } }) diff --git a/web/app/components/header/account-setting/api-based-extension-page/__tests__/index.spec.tsx b/web/app/components/header/account-setting/api-based-extension-page/__tests__/index.spec.tsx index 58b694e44e..adac0f7c6c 100644 --- a/web/app/components/header/account-setting/api-based-extension-page/__tests__/index.spec.tsx +++ b/web/app/components/header/account-setting/api-based-extension-page/__tests__/index.spec.tsx @@ -38,7 +38,8 @@ describe('ApiBasedExtensionPage', () => { render() // Assert - expect(screen.getByText('common.apiBasedExtension.title')).toBeInTheDocument() + // Assert + expect(screen.getByText('common.apiBasedExtension.title'))!.toBeInTheDocument() }) it('should render list of extensions when data exists', () => { @@ -58,10 +59,11 @@ describe('ApiBasedExtensionPage', () => { render() // Assert - expect(screen.getByText('Extension 1')).toBeInTheDocument() - expect(screen.getByText('url1')).toBeInTheDocument() - expect(screen.getByText('Extension 2')).toBeInTheDocument() - expect(screen.getByText('url2')).toBeInTheDocument() + // Assert + expect(screen.getByText('Extension 1'))!.toBeInTheDocument() + expect(screen.getByText('url1'))!.toBeInTheDocument() + expect(screen.getByText('Extension 2'))!.toBeInTheDocument() + expect(screen.getByText('url2'))!.toBeInTheDocument() }) it('should handle loading state', () => { @@ -75,9 +77,40 @@ describe('ApiBasedExtensionPage', () => { // Act render() + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert // Assert expect(screen.queryByText('common.apiBasedExtension.title')).not.toBeInTheDocument() - expect(screen.getByText('common.apiBasedExtension.add')).toBeInTheDocument() + expect(screen.getByText('common.apiBasedExtension.add'))!.toBeInTheDocument() }) }) @@ -113,7 +146,7 @@ describe('ApiBasedExtensionPage', () => { fireEvent.click(screen.getByText('common.apiBasedExtension.add')) // Trigger callback manually from the mock call - const callArgs = mockSetShowApiBasedExtensionModal.mock.calls[0][0] + const callArgs = mockSetShowApiBasedExtensionModal.mock.calls[0]![0] if (typeof callArgs === 'object' && callArgs !== null && 'onSaveCallback' in callArgs) { if (callArgs.onSaveCallback) { callArgs.onSaveCallback() @@ -138,7 +171,7 @@ describe('ApiBasedExtensionPage', () => { fireEvent.click(screen.getByText('common.operation.edit')) // Retrieve the onSaveCallback from the modal call and execute it - const callArgs = mockSetShowApiBasedExtensionModal.mock.calls[0][0] + const callArgs = mockSetShowApiBasedExtensionModal.mock.calls[0]![0] if (typeof callArgs === 'object' && callArgs !== null && 'onSaveCallback' in callArgs) { if (callArgs.onSaveCallback) callArgs.onSaveCallback() diff --git a/web/app/components/header/account-setting/api-based-extension-page/__tests__/item.spec.tsx b/web/app/components/header/account-setting/api-based-extension-page/__tests__/item.spec.tsx index cf5c46a509..38dcf9dec5 100644 --- a/web/app/components/header/account-setting/api-based-extension-page/__tests__/item.spec.tsx +++ b/web/app/components/header/account-setting/api-based-extension-page/__tests__/item.spec.tsx @@ -39,8 +39,9 @@ describe('Item Component', () => { render() // Assert - expect(screen.getByText('Test Extension')).toBeInTheDocument() - expect(screen.getByText('https://api.example.com')).toBeInTheDocument() + // Assert + expect(screen.getByText('Test Extension'))!.toBeInTheDocument() + expect(screen.getByText('https://api.example.com'))!.toBeInTheDocument() }) it('should render with minimal extension data', () => { @@ -51,8 +52,9 @@ describe('Item Component', () => { render() // Assert - expect(screen.getByText('common.operation.edit')).toBeInTheDocument() - expect(screen.getByText('common.operation.delete')).toBeInTheDocument() + // Assert + expect(screen.getByText('common.operation.edit'))!.toBeInTheDocument() + expect(screen.getByText('common.operation.delete'))!.toBeInTheDocument() }) }) @@ -66,7 +68,7 @@ describe('Item Component', () => { expect(mockSetShowApiBasedExtensionModal).toHaveBeenCalledWith(expect.objectContaining({ payload: mockData, })) - const lastCall = mockSetShowApiBasedExtensionModal.mock.calls[0][0] + const lastCall = mockSetShowApiBasedExtensionModal.mock.calls[0]![0] if (typeof lastCall === 'object' && lastCall !== null && 'onSaveCallback' in lastCall) expect(lastCall.onSaveCallback).toBeInstanceOf(Function) }) @@ -77,7 +79,7 @@ describe('Item Component', () => { fireEvent.click(screen.getByText('common.operation.edit')) // Assert - const modalCallArg = mockSetShowApiBasedExtensionModal.mock.calls[0][0] + const modalCallArg = mockSetShowApiBasedExtensionModal.mock.calls[0]![0] if (typeof modalCallArg === 'object' && modalCallArg !== null && 'onSaveCallback' in modalCallArg) { const onSaveCallback = modalCallArg.onSaveCallback if (onSaveCallback) { @@ -95,7 +97,8 @@ describe('Item Component', () => { fireEvent.click(screen.getByText('common.operation.delete')) // Assert - expect(screen.getByText(/common\.operation\.delete.*Test Extension.*\?/i)).toBeInTheDocument() + // Assert + expect(screen.getByText(/common\.operation\.delete.*Test Extension.*\?/i))!.toBeInTheDocument() }) it('should call delete API and triggers onUpdate when confirming deletion', async () => { @@ -188,7 +191,8 @@ describe('Item Component', () => { fireEvent.click(deleteBtn) // Assert - expect(screen.getByText(/.*Test Extension.*\?/i)).toBeInTheDocument() + // Assert + expect(screen.getByText(/.*Test Extension.*\?/i))!.toBeInTheDocument() useTranslationSpy.mockRestore() }) diff --git a/web/app/components/header/account-setting/api-based-extension-page/__tests__/selector.spec.tsx b/web/app/components/header/account-setting/api-based-extension-page/__tests__/selector.spec.tsx index 3e16528ff0..82acd22d97 100644 --- a/web/app/components/header/account-setting/api-based-extension-page/__tests__/selector.spec.tsx +++ b/web/app/components/header/account-setting/api-based-extension-page/__tests__/selector.spec.tsx @@ -46,7 +46,8 @@ describe('ApiBasedExtensionSelector', () => { render() // Assert - expect(screen.getByText('common.apiBasedExtension.selector.placeholder')).toBeInTheDocument() + // Assert + expect(screen.getByText('common.apiBasedExtension.selector.placeholder'))!.toBeInTheDocument() }) it('should render selected item name', async () => { @@ -54,7 +55,8 @@ describe('ApiBasedExtensionSelector', () => { render() // Assert - expect(screen.getByText('Extension 1')).toBeInTheDocument() + // Assert + expect(screen.getByText('Extension 1'))!.toBeInTheDocument() }) }) @@ -66,7 +68,8 @@ describe('ApiBasedExtensionSelector', () => { fireEvent.click(trigger) // Assert - expect(await screen.findByText('common.apiBasedExtension.selector.title')).toBeInTheDocument() + // Assert + expect(await screen.findByText('common.apiBasedExtension.selector.title'))!.toBeInTheDocument() }) it('should call onChange and closes dropdown when an extension is selected', async () => { @@ -111,7 +114,7 @@ describe('ApiBasedExtensionSelector', () => { })) // Trigger callback - const lastCall = mockSetShowApiBasedExtensionModal.mock.calls[0][0] + const lastCall = mockSetShowApiBasedExtensionModal.mock.calls[0]![0] if (typeof lastCall === 'object' && lastCall !== null && 'onSaveCallback' in lastCall) { if (lastCall.onSaveCallback) { lastCall.onSaveCallback() diff --git a/web/app/components/header/account-setting/data-source-page-new/__tests__/card.spec.tsx b/web/app/components/header/account-setting/data-source-page-new/__tests__/card.spec.tsx index 12e37553fc..fedb7d8a4e 100644 --- a/web/app/components/header/account-setting/data-source-page-new/__tests__/card.spec.tsx +++ b/web/app/components/header/account-setting/data-source-page-new/__tests__/card.spec.tsx @@ -110,7 +110,7 @@ describe('Card Component', () => { type: CredentialTypeEnum.API_KEY, is_default: true, avatar_url: 'avatar1', - }, + }!, ], } @@ -144,11 +144,12 @@ describe('Card Component', () => { render() // Assert - expect(screen.getByText('Test Label')).toBeInTheDocument() - expect(screen.getByText(/Test Author/)).toBeInTheDocument() - expect(screen.getByText(/test-name/)).toBeInTheDocument() - expect(screen.getByRole('img')).toHaveAttribute('src', 'test-icon-url') - expect(screen.getByText('Credential 1')).toBeInTheDocument() + // Assert + expect(screen.getByText('Test Label'))!.toBeInTheDocument() + expect(screen.getByText(/Test Author/))!.toBeInTheDocument() + expect(screen.getByText(/test-name/))!.toBeInTheDocument() + expect(screen.getByRole('img'))!.toHaveAttribute('src', 'test-icon-url') + expect(screen.getByText('Credential 1'))!.toBeInTheDocument() expect(usePluginAuthAction).toHaveBeenCalledWith( expect.objectContaining({ @@ -168,7 +169,8 @@ describe('Card Component', () => { render() // Assert - expect(screen.getByText(/plugin.auth.emptyAuth/)).toBeInTheDocument() + // Assert + expect(screen.getByText(/plugin.auth.emptyAuth/))!.toBeInTheDocument() }) }) @@ -218,7 +220,7 @@ describe('Card Component', () => { const oAuthItem = { ...mockItem, credentials_list: [{ - ...mockItem.credentials_list[0], + ...mockItem.credentials_list[0]!, type: CredentialTypeEnum.OAUTH2, }], } @@ -245,7 +247,7 @@ describe('Card Component', () => { const oAuthItem = { ...mockItem, credentials_list: [{ - ...mockItem.credentials_list[0], + ...mockItem.credentials_list[0]!, type: CredentialTypeEnum.OAUTH2, }], } @@ -268,7 +270,7 @@ describe('Card Component', () => { const oAuthItem = { ...mockItem, credentials_list: [{ - ...mockItem.credentials_list[0], + ...mockItem.credentials_list[0]!, type: CredentialTypeEnum.OAUTH2, }], } @@ -297,9 +299,10 @@ describe('Card Component', () => { render() // Assert - expect(screen.getByText(/list.delete.title/)).toBeInTheDocument() + // Assert + expect(screen.getByText(/list.delete.title/))!.toBeInTheDocument() const confirmButton = screen.getByText(/operation.confirm/).closest('button') - expect(confirmButton).toBeEnabled() + expect(confirmButton)!.toBeEnabled() // Act - Cancel fireEvent.click(screen.getByText(/operation.cancel/)) @@ -317,8 +320,9 @@ describe('Card Component', () => { render() // Assert - expect(screen.getByTestId('mock-api-key-modal')).toBeInTheDocument() - expect(screen.getByTestId('mock-api-key-modal')).toHaveAttribute('data-disabled', 'false') + // Assert + expect(screen.getByTestId('mock-api-key-modal'))!.toBeInTheDocument() + expect(screen.getByTestId('mock-api-key-modal'))!.toHaveAttribute('data-disabled', 'false') // Act fireEvent.click(screen.getByTestId('modal-close')) @@ -337,7 +341,8 @@ describe('Card Component', () => { render() // Assert - expect(screen.getByTestId('mock-api-key-modal')).toHaveAttribute('data-disabled', 'true') + // Assert + expect(screen.getByTestId('mock-api-key-modal'))!.toHaveAttribute('data-disabled', 'true') }) }) diff --git a/web/app/components/header/account-setting/data-source-page-new/hooks/use-marketplace-all-plugins.ts b/web/app/components/header/account-setting/data-source-page-new/hooks/use-marketplace-all-plugins.ts index 90ef6e78a4..7e2dc572fc 100644 --- a/web/app/components/header/account-setting/data-source-page-new/hooks/use-marketplace-all-plugins.ts +++ b/web/app/components/header/account-setting/data-source-page-new/hooks/use-marketplace-all-plugins.ts @@ -54,8 +54,8 @@ export const useMarketplaceAllPlugins = (providers: any[], searchText: string) = for (let i = 0; i < plugins.length; i++) { const plugin = plugins[i] - if (plugin.type !== 'bundle' && !allPlugins.find(p => p.plugin_id === plugin.plugin_id)) - allPlugins.push(plugin) + if (plugin!.type !== 'bundle' && !allPlugins.find(p => p.plugin_id === plugin!.plugin_id)) + allPlugins.push(plugin!) } } diff --git a/web/app/components/header/account-setting/index.tsx b/web/app/components/header/account-setting/index.tsx index 64dff27cf6..3ec6dea315 100644 --- a/web/app/components/header/account-setting/index.tsx +++ b/web/app/components/header/account-setting/index.tsx @@ -130,7 +130,7 @@ export default function AccountSetting({ ], }, ] - const activeItem = [...menuItems[0].items, ...menuItems[1].items].find(item => item.key === activeMenu) + const activeItem = [...menuItems[0]!.items, ...menuItems[1]!.items].find(item => item.key === activeMenu) const [searchValue, setSearchValue] = useState('') diff --git a/web/app/components/header/account-setting/members-page/__tests__/index.spec.tsx b/web/app/components/header/account-setting/members-page/__tests__/index.spec.tsx index 9513eeee02..b50073b1f2 100644 --- a/web/app/components/header/account-setting/members-page/__tests__/index.spec.tsx +++ b/web/app/components/header/account-setting/members-page/__tests__/index.spec.tsx @@ -129,9 +129,9 @@ describe('MembersPage', () => { it('should render workspace and member information', () => { render() - expect(screen.getByText('Test Workspace')).toBeInTheDocument() - expect(screen.getByText('Owner User')).toBeInTheDocument() - expect(screen.getByText('Admin User')).toBeInTheDocument() + expect(screen.getByText('Test Workspace'))!.toBeInTheDocument() + expect(screen.getByText('Owner User'))!.toBeInTheDocument() + expect(screen.getByText('Admin User'))!.toBeInTheDocument() }) it('should open and close invite modal', async () => { @@ -140,7 +140,7 @@ describe('MembersPage', () => { render() await user.click(screen.getByRole('button', { name: /invite/i })) - expect(screen.getByText('Invite Modal')).toBeInTheDocument() + expect(screen.getByText('Invite Modal'))!.toBeInTheDocument() await user.click(screen.getByRole('button', { name: 'Close Invite Modal' })) expect(screen.queryByText('Invite Modal')).not.toBeInTheDocument() @@ -154,7 +154,7 @@ describe('MembersPage', () => { await user.click(screen.getByRole('button', { name: /invite/i })) await user.click(screen.getByRole('button', { name: 'Send Invite Results' })) - expect(screen.getByText('Invited Modal')).toBeInTheDocument() + expect(screen.getByText('Invited Modal'))!.toBeInTheDocument() expect(mockRefetch).toHaveBeenCalled() await user.click(screen.getByRole('button', { name: 'Close Invited Modal' })) @@ -167,7 +167,7 @@ describe('MembersPage', () => { render() await user.click(screen.getByRole('button', { name: /transfer ownership/i })) - expect(screen.getByText('Transfer Ownership Modal')).toBeInTheDocument() + expect(screen.getByText('Transfer Ownership Modal'))!.toBeInTheDocument() }) it('should show non-interactive owner role when transfer ownership is not allowed', () => { @@ -178,7 +178,7 @@ describe('MembersPage', () => { render() - expect(screen.getByText('common.members.owner')).toBeInTheDocument() + expect(screen.getByText('common.members.owner'))!.toBeInTheDocument() expect(screen.queryByRole('button', { name: /transfer ownership/i })).not.toBeInTheDocument() }) @@ -202,7 +202,7 @@ describe('MembersPage', () => { render() await user.click(screen.getByTestId('edit-workspace-pencil')) - expect(screen.getByText('Edit Workspace Modal')).toBeInTheDocument() + expect(screen.getByText('Edit Workspace Modal'))!.toBeInTheDocument() await user.click(screen.getByRole('button', { name: 'Close Edit Workspace' })) expect(screen.queryByText('Edit Workspace Modal')).not.toBeInTheDocument() @@ -214,7 +214,7 @@ describe('MembersPage', () => { render() await user.click(screen.getByRole('button', { name: /transfer ownership/i })) - expect(screen.getByText('Transfer Ownership Modal')).toBeInTheDocument() + expect(screen.getByText('Transfer Ownership Modal'))!.toBeInTheDocument() await user.click(screen.getByRole('button', { name: 'Close Transfer Modal' })) expect(screen.queryByText('Transfer Ownership Modal')).not.toBeInTheDocument() @@ -222,7 +222,7 @@ describe('MembersPage', () => { it('should show pending status and you indicator', () => { const pendingAccount: Member = { - ...mockAccounts[1], + ...mockAccounts[1]!, status: 'pending', } vi.mocked(useMembers).mockReturnValue({ @@ -232,8 +232,8 @@ describe('MembersPage', () => { render() - expect(screen.getByText(/members\.pending/i)).toBeInTheDocument() - expect(screen.getByText(/members\.you/i)).toBeInTheDocument() // Current user is owner@example.com + expect(screen.getByText(/members\.pending/i))!.toBeInTheDocument() + expect(screen.getByText(/members\.you/i))!.toBeInTheDocument() // Current user is owner@example.com }) it('should show billing information for limited plan', () => { @@ -247,10 +247,10 @@ describe('MembersPage', () => { render() - expect(screen.getByText(/plansCommon\.member/i)).toBeInTheDocument() - expect(screen.getByText('2')).toBeInTheDocument() // accounts.length - expect(screen.getByText('/')).toBeInTheDocument() - expect(screen.getByText('5')).toBeInTheDocument() // plan.total.teamMembers + expect(screen.getByText(/plansCommon\.member/i))!.toBeInTheDocument() + expect(screen.getByText('2'))!.toBeInTheDocument() // accounts.length + expect(screen.getByText('/'))!.toBeInTheDocument() + expect(screen.getByText('5'))!.toBeInTheDocument() // plan.total.teamMembers }) it('should show unlimited billing information', () => { @@ -264,7 +264,7 @@ describe('MembersPage', () => { render() - expect(screen.getByText(/plansCommon\.unlimited/i)).toBeInTheDocument() + expect(screen.getByText(/plansCommon\.unlimited/i))!.toBeInTheDocument() }) it('should show non-billing member format for team plan even when billing is enabled', () => { @@ -279,7 +279,8 @@ describe('MembersPage', () => { render() // Plan.team is an unlimited member plan → isNotUnlimitedMemberPlan=false → non-billing layout - expect(screen.getByText(/plansCommon\.memberAfter/i)).toBeInTheDocument() + // Plan.team is an unlimited member plan → isNotUnlimitedMemberPlan=false → non-billing layout + expect(screen.getByText(/plansCommon\.memberAfter/i))!.toBeInTheDocument() }) it('should show invite button when user is manager but not owner', () => { @@ -292,13 +293,13 @@ describe('MembersPage', () => { render() - expect(screen.getByRole('button', { name: /invite/i })).toBeInTheDocument() + expect(screen.getByRole('button', { name: /invite/i }))!.toBeInTheDocument() expect(screen.queryByRole('button', { name: /transfer ownership/i })).not.toBeInTheDocument() }) it('should use created_at as fallback when last_active_at is empty', () => { const memberNoLastActive: Member = { - ...mockAccounts[1], + ...mockAccounts[1]!, last_active_at: '', created_at: '1700000000', } @@ -327,8 +328,8 @@ describe('MembersPage', () => { render() - expect(screen.getByText(/plansCommon\.member/i)).toBeInTheDocument() - expect(screen.getByText('1')).toBeInTheDocument() + expect(screen.getByText(/plansCommon\.member/i))!.toBeInTheDocument() + expect(screen.getByText('1'))!.toBeInTheDocument() }) it('should not show plural s when only one account in non-billing layout', () => { @@ -339,8 +340,8 @@ describe('MembersPage', () => { render() - expect(screen.getByText(/plansCommon\.memberAfter/i)).toBeInTheDocument() - expect(screen.getByText('1')).toBeInTheDocument() + expect(screen.getByText(/plansCommon\.memberAfter/i))!.toBeInTheDocument() + expect(screen.getByText('1'))!.toBeInTheDocument() }) it('should show normal role as fallback for unknown role', () => { @@ -357,7 +358,7 @@ describe('MembersPage', () => { render() - expect(screen.getByText('common.members.normal')).toBeInTheDocument() + expect(screen.getByText('common.members.normal'))!.toBeInTheDocument() }) it('should show upgrade button when member limit is full', () => { @@ -371,6 +372,6 @@ describe('MembersPage', () => { render() - expect(screen.getByText('Upgrade Button')).toBeInTheDocument() + expect(screen.getByText('Upgrade Button'))!.toBeInTheDocument() }) }) diff --git a/web/app/components/header/account-setting/model-provider-page/__tests__/hooks.spec.ts b/web/app/components/header/account-setting/model-provider-page/__tests__/hooks.spec.ts index 1d50ee43b0..9b592e9fff 100644 --- a/web/app/components/header/account-setting/model-provider-page/__tests__/hooks.spec.ts +++ b/web/app/components/header/account-setting/model-provider-page/__tests__/hooks.spec.ts @@ -758,7 +758,7 @@ describe('hooks', () => { expect(result.current.textGenerationModelList).toEqual(modelList) expect(result.current.activeTextGenerationModelList).toHaveLength(1) - expect(result.current.activeTextGenerationModelList[0].provider).toBe('openai') + expect(result.current.activeTextGenerationModelList[0]!.provider).toBe('openai') }) it('should filter active models correctly', () => { @@ -770,7 +770,7 @@ describe('hooks', () => { const { result } = renderHook(() => useTextGenerationCurrentProviderAndModelAndModelList()) expect(result.current.activeTextGenerationModelList).toHaveLength(1) - expect(result.current.activeTextGenerationModelList[0].status).toBe(ModelStatusEnum.active) + expect(result.current.activeTextGenerationModelList[0]!.status).toBe(ModelStatusEnum.active) }) it('should find current provider and model', () => { @@ -1145,7 +1145,7 @@ describe('hooks', () => { const { result } = renderHook(() => useMarketplaceAllPlugins(providers, '')) expect(result.current.plugins!).toHaveLength(1) - expect(result.current.plugins![0].plugin_id).toBe('other') + expect(result.current.plugins![0]!.plugin_id).toBe('other') }) it('should use search when searchText is provided', () => { @@ -1186,7 +1186,7 @@ describe('hooks', () => { const { result } = renderHook(() => useMarketplaceAllPlugins([], '')) expect(result.current.plugins!).toHaveLength(1) - expect(result.current.plugins![0].plugin_id).toBe('plugin1') + expect(result.current.plugins![0]!.plugin_id).toBe('plugin1') }) it('should deduplicate plugins that exist in both collections and regular plugins', () => { @@ -1613,7 +1613,7 @@ describe('hooks', () => { ) }) - const callArgs = setShowModelModal.mock.calls[0][0] + const callArgs = setShowModelModal.mock.calls[0]![0] const newPayload = { test: 'data' } const formValues = { field: 'value' } @@ -1636,7 +1636,7 @@ describe('hooks', () => { result.current(provider, ConfigurationMethodEnum.predefinedModel) }) - const callArgs = setShowModelModal.mock.calls[0][0] + const callArgs = setShowModelModal.mock.calls[0]![0] // Should not throw when onUpdate is not provided expect(() => { diff --git a/web/app/components/header/account-setting/model-provider-page/__tests__/utils.spec.ts b/web/app/components/header/account-setting/model-provider-page/__tests__/utils.spec.ts index d49343e0c6..e2a2aea22c 100644 --- a/web/app/components/header/account-setting/model-provider-page/__tests__/utils.spec.ts +++ b/web/app/components/header/account-setting/model-provider-page/__tests__/utils.spec.ts @@ -277,7 +277,7 @@ describe('utils', () => { const schema = genModelTypeFormSchema([ModelTypeEnum.textGeneration]) expect(schema.type).toBe(FormTypeEnum.select) expect(schema.variable).toBe('__model_type') - expect(schema.options[0].value).toBe(ModelTypeEnum.textGeneration) + expect(schema.options[0]!.value).toBe(ModelTypeEnum.textGeneration) }) }) diff --git a/web/app/components/header/account-setting/model-provider-page/hooks.ts b/web/app/components/header/account-setting/model-provider-page/hooks.ts index 791a42deb5..27b84f81bb 100644 --- a/web/app/components/header/account-setting/model-provider-page/hooks.ts +++ b/web/app/components/header/account-setting/model-provider-page/hooks.ts @@ -313,8 +313,8 @@ export const useMarketplaceAllPlugins = (providers: ModelProvider[], searchText: for (let i = 0; i < plugins.length; i++) { const plugin = plugins[i] - if (plugin.type !== 'bundle' && !allPlugins.find(p => p.plugin_id === plugin.plugin_id)) - allPlugins.push(plugin) + if (plugin!.type !== 'bundle' && !allPlugins.find(p => p.plugin_id === plugin!.plugin_id)) + allPlugins.push(plugin!) } } diff --git a/web/app/components/header/account-setting/model-provider-page/model-auth/__tests__/add-credential-in-load-balancing.spec.tsx b/web/app/components/header/account-setting/model-provider-page/model-auth/__tests__/add-credential-in-load-balancing.spec.tsx index bf26880a8b..c72264dd7a 100644 --- a/web/app/components/header/account-setting/model-provider-page/model-auth/__tests__/add-credential-in-load-balancing.spec.tsx +++ b/web/app/components/header/account-setting/model-provider-page/model-auth/__tests__/add-credential-in-load-balancing.spec.tsx @@ -18,7 +18,7 @@ vi.mock('@/app/components/header/account-setting/model-provider-page/model-auth'
{renderTrigger(false)} - +
), })) @@ -57,7 +57,7 @@ describe('AddCredentialInLoadBalancing', () => { />, ) - expect(screen.getByText(/modelProvider.auth.addCredential/i)).toBeInTheDocument() + expect(screen.getByText(/modelProvider.auth.addCredential/i))!.toBeInTheDocument() }) it('should forward update payload when update action happens', () => { @@ -127,7 +127,7 @@ describe('AddCredentialInLoadBalancing', () => { // The trigger div rendered by renderTrigger(true) should have bg-state-base-hover // (the static class applied when open=true via cn()) const triggerDiv = container.querySelector('[data-testid="open-trigger"] > div') - expect(triggerDiv).toBeInTheDocument() + expect(triggerDiv)!.toBeInTheDocument() expect(triggerDiv!.className).toContain('bg-state-base-hover') } finally { @@ -148,7 +148,7 @@ describe('AddCredentialInLoadBalancing', () => { />, ) - expect(screen.getByText(/modelProvider.auth.addCredential/i)).toBeInTheDocument() + expect(screen.getByText(/modelProvider.auth.addCredential/i))!.toBeInTheDocument() }) it('should handle undefined available_credentials gracefully using nullish coalescing', () => { @@ -169,7 +169,8 @@ describe('AddCredentialInLoadBalancing', () => { ) // Component should render without error - the ?? [] fallback is used - expect(screen.getByText(/modelProvider.auth.addCredential/i)).toBeInTheDocument() + // Component should render without error - the ?? [] fallback is used + expect(screen.getByText(/modelProvider.auth.addCredential/i))!.toBeInTheDocument() }) it('should not throw when update action fires without onUpdate prop', () => { diff --git a/web/app/components/header/account-setting/model-provider-page/model-auth/__tests__/switch-credential-in-load-balancing.spec.tsx b/web/app/components/header/account-setting/model-provider-page/model-auth/__tests__/switch-credential-in-load-balancing.spec.tsx index 9b58984af9..0232adcf4a 100644 --- a/web/app/components/header/account-setting/model-provider-page/model-auth/__tests__/switch-credential-in-load-balancing.spec.tsx +++ b/web/app/components/header/account-setting/model-provider-page/model-auth/__tests__/switch-credential-in-load-balancing.spec.tsx @@ -7,7 +7,7 @@ import SwitchCredentialInLoadBalancing from '../switch-credential-in-load-balanc vi.mock('../authorized', () => ({ default: ({ renderTrigger, onItemClick, items }: { renderTrigger: () => React.ReactNode, onItemClick: (c: unknown) => void, items: { credentials: unknown[] }[] }) => (
-
onItemClick(items[0].credentials[0])}> +
onItemClick(items[0]!.credentials[0])}> {renderTrigger()}
@@ -55,8 +55,8 @@ describe('SwitchCredentialInLoadBalancing', () => { />, ) - expect(screen.getByText('Key 1')).toBeInTheDocument() - expect(screen.getByTestId('indicator-green')).toBeInTheDocument() + expect(screen.getByText('Key 1'))!.toBeInTheDocument() + expect(screen.getByTestId('indicator-green'))!.toBeInTheDocument() }) it('should render auth removed status when selected credential is not in list', () => { @@ -70,8 +70,8 @@ describe('SwitchCredentialInLoadBalancing', () => { />, ) - expect(screen.getByText(/modelProvider.auth.authRemoved/)).toBeInTheDocument() - expect(screen.getByTestId('indicator-red')).toBeInTheDocument() + expect(screen.getByText(/modelProvider.auth.authRemoved/))!.toBeInTheDocument() + expect(screen.getByTestId('indicator-red'))!.toBeInTheDocument() }) it('should render unavailable status when credentials list is empty', () => { @@ -85,7 +85,7 @@ describe('SwitchCredentialInLoadBalancing', () => { />, ) - expect(screen.getByText(/auth.credentialUnavailableInButton/)).toBeInTheDocument() + expect(screen.getByText(/auth.credentialUnavailableInButton/))!.toBeInTheDocument() expect(screen.queryByTestId(/indicator-/)).not.toBeInTheDocument() }) @@ -117,7 +117,7 @@ describe('SwitchCredentialInLoadBalancing', () => { ) fireEvent.mouseEnter(screen.getByText(/auth.credentialUnavailableInButton/)) - expect(screen.getByText('plugin.auth.credentialUnavailable')).toBeInTheDocument() + expect(screen.getByText('plugin.auth.credentialUnavailable'))!.toBeInTheDocument() }) // Empty credentials with allowed custom: no tooltip but still shows unavailable text @@ -134,7 +134,8 @@ describe('SwitchCredentialInLoadBalancing', () => { ) // Assert - expect(screen.getByText(/auth.credentialUnavailableInButton/)).toBeInTheDocument() + // Assert + expect(screen.getByText(/auth.credentialUnavailableInButton/))!.toBeInTheDocument() expect(screen.queryByText('plugin.auth.credentialUnavailable')).not.toBeInTheDocument() }) @@ -152,8 +153,8 @@ describe('SwitchCredentialInLoadBalancing', () => { />, ) - expect(screen.getByTestId('indicator-red')).toBeInTheDocument() - expect(screen.getByText(/auth.credentialUnavailableInButton/)).toBeInTheDocument() + expect(screen.getByTestId('indicator-red'))!.toBeInTheDocument() + expect(screen.getByText(/auth.credentialUnavailableInButton/))!.toBeInTheDocument() }) // from_enterprise=true on the selected credential: Enterprise badge appears in the trigger @@ -170,7 +171,7 @@ describe('SwitchCredentialInLoadBalancing', () => { />, ) - expect(screen.getByText('Enterprise')).toBeInTheDocument() + expect(screen.getByText('Enterprise'))!.toBeInTheDocument() }) // non-empty credentials with allow_custom_token=false: no tooltip (tooltip only for empty+notAllowCustom) @@ -189,7 +190,7 @@ describe('SwitchCredentialInLoadBalancing', () => { fireEvent.mouseEnter(screen.getByText('Key 1')) expect(screen.queryByText('plugin.auth.credentialUnavailable')).not.toBeInTheDocument() - expect(screen.getByText('Key 1')).toBeInTheDocument() + expect(screen.getByText('Key 1'))!.toBeInTheDocument() }) it('should pass undefined currentCustomConfigurationModelFixedFields when model is undefined', () => { @@ -205,8 +206,9 @@ describe('SwitchCredentialInLoadBalancing', () => { ) // Component still renders (Authorized receives undefined currentCustomConfigurationModelFixedFields) - expect(screen.getByTestId('authorized-mock')).toBeInTheDocument() - expect(screen.getByText('Key 1')).toBeInTheDocument() + // Component still renders (Authorized receives undefined currentCustomConfigurationModelFixedFields) + expect(screen.getByTestId('authorized-mock'))!.toBeInTheDocument() + expect(screen.getByText('Key 1'))!.toBeInTheDocument() }) it('should treat undefined credentials as empty list', () => { @@ -221,7 +223,8 @@ describe('SwitchCredentialInLoadBalancing', () => { ) // credentials is undefined → empty=true → unavailable text shown - expect(screen.getByText(/auth.credentialUnavailableInButton/)).toBeInTheDocument() + // credentials is undefined → empty=true → unavailable text shown + expect(screen.getByText(/auth.credentialUnavailableInButton/))!.toBeInTheDocument() expect(screen.queryByTestId(/indicator-/)).not.toBeInTheDocument() }) @@ -239,7 +242,39 @@ describe('SwitchCredentialInLoadBalancing', () => { ) // indicator-green shown (not authRemoved, not unavailable, not empty) - expect(screen.getByTestId('indicator-green')).toBeInTheDocument() + // indicator-green shown (not authRemoved, not unavailable, not empty) + expect(screen.getByTestId('indicator-green'))!.toBeInTheDocument() + // credential_name is empty so nothing printed for name + // credential_name is empty so nothing printed for name + // credential_name is empty so nothing printed for name + // credential_name is empty so nothing printed for name + // credential_name is empty so nothing printed for name + // credential_name is empty so nothing printed for name + // credential_name is empty so nothing printed for name + // credential_name is empty so nothing printed for name + // credential_name is empty so nothing printed for name + // credential_name is empty so nothing printed for name + // credential_name is empty so nothing printed for name + // credential_name is empty so nothing printed for name + // credential_name is empty so nothing printed for name + // credential_name is empty so nothing printed for name + // credential_name is empty so nothing printed for name + // credential_name is empty so nothing printed for name + // credential_name is empty so nothing printed for name + // credential_name is empty so nothing printed for name + // credential_name is empty so nothing printed for name + // credential_name is empty so nothing printed for name + // credential_name is empty so nothing printed for name + // credential_name is empty so nothing printed for name + // credential_name is empty so nothing printed for name + // credential_name is empty so nothing printed for name + // credential_name is empty so nothing printed for name + // credential_name is empty so nothing printed for name + // credential_name is empty so nothing printed for name + // credential_name is empty so nothing printed for name + // credential_name is empty so nothing printed for name + // credential_name is empty so nothing printed for name + // credential_name is empty so nothing printed for name // credential_name is empty so nothing printed for name expect(screen.queryByText('Key 1')).not.toBeInTheDocument() }) diff --git a/web/app/components/header/account-setting/model-provider-page/model-auth/authorized/__tests__/authorized-item.spec.tsx b/web/app/components/header/account-setting/model-provider-page/model-auth/authorized/__tests__/authorized-item.spec.tsx index 57e80fa989..c0ce70a5d0 100644 --- a/web/app/components/header/account-setting/model-provider-page/model-auth/authorized/__tests__/authorized-item.spec.tsx +++ b/web/app/components/header/account-setting/model-provider-page/model-auth/authorized/__tests__/authorized-item.spec.tsx @@ -51,10 +51,10 @@ describe('AuthorizedItem', () => { />, ) - expect(screen.getByTestId('credential-item-cred-1')).toBeInTheDocument() - expect(screen.getByTestId('credential-item-cred-2')).toBeInTheDocument() - expect(screen.getByText('API Key 1')).toBeInTheDocument() - expect(screen.getByText('API Key 2')).toBeInTheDocument() + expect(screen.getByTestId('credential-item-cred-1'))!.toBeInTheDocument() + expect(screen.getByTestId('credential-item-cred-2'))!.toBeInTheDocument() + expect(screen.getByText('API Key 1'))!.toBeInTheDocument() + expect(screen.getByText('API Key 2'))!.toBeInTheDocument() }) it('should render model title when showModelTitle is true', () => { @@ -67,7 +67,7 @@ describe('AuthorizedItem', () => { />, ) - expect(screen.getByTestId('model-icon')).toBeInTheDocument() + expect(screen.getByTestId('model-icon'))!.toBeInTheDocument() expect(screen.getAllByText('gpt-4')).toHaveLength(2) }) @@ -94,7 +94,7 @@ describe('AuthorizedItem', () => { />, ) - expect(screen.getByText('Custom Title')).toBeInTheDocument() + expect(screen.getByText('Custom Title'))!.toBeInTheDocument() }) it('should handle empty credentials array', () => { @@ -122,7 +122,7 @@ describe('AuthorizedItem', () => { />, ) - screen.getAllByText('Edit')[0].click() + screen.getAllByText('Edit')[0]!.click() expect(onEdit).toHaveBeenCalledWith(mockCredentials[0], mockModel) }) @@ -139,7 +139,7 @@ describe('AuthorizedItem', () => { />, ) - screen.getAllByText('Delete')[0].click() + screen.getAllByText('Delete')[0]!.click() expect(onDelete).toHaveBeenCalledWith(mockCredentials[0], mockModel) }) @@ -156,7 +156,7 @@ describe('AuthorizedItem', () => { />, ) - screen.getAllByText('Click')[0].click() + screen.getAllByText('Click')[0]!.click() expect(onItemClick).toHaveBeenCalledWith(mockCredentials[0], mockModel) }) diff --git a/web/app/components/header/account-setting/model-provider-page/model-auth/authorized/__tests__/index.spec.tsx b/web/app/components/header/account-setting/model-provider-page/model-auth/authorized/__tests__/index.spec.tsx index e1d9a611f9..a331181619 100644 --- a/web/app/components/header/account-setting/model-provider-page/model-auth/authorized/__tests__/index.spec.tsx +++ b/web/app/components/header/account-setting/model-provider-page/model-auth/authorized/__tests__/index.spec.tsx @@ -90,8 +90,8 @@ describe('Authorized', () => { ) fireEvent.click(screen.getByRole('button', { name: /trigger\s*closed/i })) - expect(screen.getByTestId('authorized-item')).toBeInTheDocument() - expect(screen.getByRole('button', { name: /addApiKey/i })).toBeInTheDocument() + expect(screen.getByTestId('authorized-item'))!.toBeInTheDocument() + expect(screen.getByRole('button', { name: /addApiKey/i }))!.toBeInTheDocument() }) it('should call handleOpenModal when triggerOnlyOpenModal is true', () => { @@ -123,9 +123,9 @@ describe('Authorized', () => { ) fireEvent.click(screen.getByRole('button', { name: /trigger\s*closed/i })) - fireEvent.click(screen.getAllByRole('button', { name: 'Select' })[0]) + fireEvent.click(screen.getAllByRole('button', { name: 'Select' })[0]!) - expect(onItemClick).toHaveBeenCalledWith(mockCredentials[0], mockItems[0].model) + expect(onItemClick).toHaveBeenCalledWith(mockCredentials[0], mockItems[0]!.model) }) it('should call handleActiveCredential when onItemClick is not provided', () => { @@ -139,9 +139,9 @@ describe('Authorized', () => { ) fireEvent.click(screen.getByRole('button', { name: /trigger\s*closed/i })) - fireEvent.click(screen.getAllByRole('button', { name: 'Select' })[0]) + fireEvent.click(screen.getAllByRole('button', { name: 'Select' })[0]!) - expect(mockHandleActiveCredential).toHaveBeenCalledWith(mockCredentials[0], mockItems[0].model) + expect(mockHandleActiveCredential).toHaveBeenCalledWith(mockCredentials[0], mockItems[0]!.model) }) it('should call handleOpenModal with fixed model fields when adding model credential', () => { @@ -231,6 +231,6 @@ describe('Authorized', () => { ) const dialog = screen.getByRole('alertdialog') - expect(within(dialog).getByRole('button', { name: /common.operation.confirm/i })).toBeDisabled() + expect(within(dialog).getByRole('button', { name: /common.operation.confirm/i }))!.toBeDisabled() }) }) diff --git a/web/app/components/header/account-setting/model-provider-page/model-auth/hooks/__tests__/use-auth-service.spec.tsx b/web/app/components/header/account-setting/model-provider-page/model-auth/hooks/__tests__/use-auth-service.spec.tsx index bd4f857047..7cc1445041 100644 --- a/web/app/components/header/account-setting/model-provider-page/model-auth/hooks/__tests__/use-auth-service.spec.tsx +++ b/web/app/components/header/account-setting/model-provider-page/model-auth/hooks/__tests__/use-auth-service.spec.tsx @@ -80,15 +80,15 @@ describe('useAuthService hooks', () => { const { result } = renderHook(() => useAuthService('openai'), { wrapper }) // Provider services - expect(result.current.getAddCredentialService(false)).toBe(vi.mocked(useAddProviderCredential).mock.results[0].value.mutateAsync) - expect(result.current.getEditCredentialService(false)).toBe(vi.mocked(useEditProviderCredential).mock.results[0].value.mutateAsync) - expect(result.current.getDeleteCredentialService(false)).toBe(vi.mocked(useDeleteProviderCredential).mock.results[0].value.mutateAsync) - expect(result.current.getActiveCredentialService(false)).toBe(vi.mocked(useActiveProviderCredential).mock.results[0].value.mutateAsync) + expect(result.current.getAddCredentialService(false)).toBe(vi.mocked(useAddProviderCredential).mock.results[0]!.value.mutateAsync) + expect(result.current.getEditCredentialService(false)).toBe(vi.mocked(useEditProviderCredential).mock.results[0]!.value.mutateAsync) + expect(result.current.getDeleteCredentialService(false)).toBe(vi.mocked(useDeleteProviderCredential).mock.results[0]!.value.mutateAsync) + expect(result.current.getActiveCredentialService(false)).toBe(vi.mocked(useActiveProviderCredential).mock.results[0]!.value.mutateAsync) // Model services - expect(result.current.getAddCredentialService(true)).toBe(vi.mocked(useAddModelCredential).mock.results[0].value.mutateAsync) - expect(result.current.getEditCredentialService(true)).toBe(vi.mocked(useEditModelCredential).mock.results[0].value.mutateAsync) - expect(result.current.getDeleteCredentialService(true)).toBe(vi.mocked(useDeleteModelCredential).mock.results[0].value.mutateAsync) - expect(result.current.getActiveCredentialService(true)).toBe(vi.mocked(useActiveModelCredential).mock.results[0].value.mutateAsync) + expect(result.current.getAddCredentialService(true)).toBe(vi.mocked(useAddModelCredential).mock.results[0]!.value.mutateAsync) + expect(result.current.getEditCredentialService(true)).toBe(vi.mocked(useEditModelCredential).mock.results[0]!.value.mutateAsync) + expect(result.current.getDeleteCredentialService(true)).toBe(vi.mocked(useDeleteModelCredential).mock.results[0]!.value.mutateAsync) + expect(result.current.getActiveCredentialService(true)).toBe(vi.mocked(useActiveModelCredential).mock.results[0]!.value.mutateAsync) }) }) diff --git a/web/app/components/header/account-setting/model-provider-page/model-auth/hooks/__tests__/use-custom-models.spec.tsx b/web/app/components/header/account-setting/model-provider-page/model-auth/hooks/__tests__/use-custom-models.spec.tsx index 2b5804c3f1..c98ead095f 100644 --- a/web/app/components/header/account-setting/model-provider-page/model-auth/hooks/__tests__/use-custom-models.spec.tsx +++ b/web/app/components/header/account-setting/model-provider-page/model-auth/hooks/__tests__/use-custom-models.spec.tsx @@ -15,7 +15,7 @@ describe('useCustomModels and useCanAddedModels', () => { const { result } = renderHook(() => useCustomModels(mockProvider)) expect(result.current).toHaveLength(2) - expect(result.current[0].model).toBe('gpt-4') + expect(result.current[0]!.model).toBe('gpt-4') const { result: emptyRes } = renderHook(() => useCustomModels({ custom_configuration: {} } as unknown as ModelProvider)) expect(emptyRes.current).toEqual([]) @@ -30,7 +30,7 @@ describe('useCustomModels and useCanAddedModels', () => { const { result } = renderHook(() => useCanAddedModels(mockProvider)) expect(result.current).toHaveLength(1) - expect(result.current[0].model).toBe('gpt-4-turbo') + expect(result.current[0]!.model).toBe('gpt-4-turbo') const { result: emptyRes } = renderHook(() => useCanAddedModels({ custom_configuration: {} } as unknown as ModelProvider)) expect(emptyRes.current).toEqual([]) diff --git a/web/app/components/header/account-setting/model-provider-page/model-auth/hooks/__tests__/use-model-form-schemas.spec.tsx b/web/app/components/header/account-setting/model-provider-page/model-auth/hooks/__tests__/use-model-form-schemas.spec.tsx index 237d99c7e7..dbe513163b 100644 --- a/web/app/components/header/account-setting/model-provider-page/model-auth/hooks/__tests__/use-model-form-schemas.spec.tsx +++ b/web/app/components/header/account-setting/model-provider-page/model-auth/hooks/__tests__/use-model-form-schemas.spec.tsx @@ -69,7 +69,7 @@ describe('useModelFormSchemas', () => { const { result: custom } = renderHook(() => useModelFormSchemas(mockProvider, false)) expect(custom.current.modelNameAndTypeFormSchemas).toHaveLength(2) - expect(custom.current.modelNameAndTypeFormSchemas[0].variable).toBe('__model_name') + expect(custom.current.modelNameAndTypeFormSchemas[0]!.variable).toBe('__model_name') const mockModel = { model: 'custom', model_type: 'text' } as unknown as CustomModelCredential const { result: customWithVal } = renderHook(() => useModelFormSchemas(mockProvider, false, undefined, undefined, mockModel)) diff --git a/web/app/components/header/account-setting/model-provider-page/model-modal/__tests__/Form.spec.tsx b/web/app/components/header/account-setting/model-provider-page/model-modal/__tests__/Form.spec.tsx index 14120ec08c..bf1623fbef 100644 --- a/web/app/components/header/account-setting/model-provider-page/model-modal/__tests__/Form.spec.tsx +++ b/web/app/components/header/account-setting/model-provider-page/model-modal/__tests__/Form.spec.tsx @@ -192,9 +192,9 @@ describe('Form', () => { />, ) - expect(screen.getByPlaceholderText('API Key')).toHaveValue('default-key') - expect(screen.getByPlaceholderText('Secret')).toHaveValue('top-secret') - expect(screen.getByPlaceholderText('Limit')).toHaveValue(5) + expect(screen.getByPlaceholderText('API Key'))!.toHaveValue('default-key') + expect(screen.getByPlaceholderText('Secret'))!.toHaveValue('top-secret') + expect(screen.getByPlaceholderText('Limit'))!.toHaveValue(5) expect(screen.queryByText('Hidden')).not.toBeInTheDocument() expect(screen.getAllByText('*')).toHaveLength(1) }) @@ -234,7 +234,7 @@ describe('Form', () => { await waitFor(() => { expect(onChange).toHaveBeenCalledWith({ api_key: 'new-key', dependent: 'reset' }) - expect(screen.getByText('Validating...')).toBeInTheDocument() + expect(screen.getByText('Validating...'))!.toBeInTheDocument() }) }) @@ -279,7 +279,7 @@ describe('Form', () => { />, ) - expect(screen.getByText('EU')).toBeInTheDocument() + expect(screen.getByText('EU'))!.toBeInTheDocument() expect(screen.queryByText('Hidden Region')).not.toBeInTheDocument() fireEvent.click(screen.getByText('EU')) fireEvent.click(screen.getByText('Locked A')) @@ -338,7 +338,7 @@ describe('Form', () => { />, ) - expect(screen.getByText('Select A')).toBeInTheDocument() + expect(screen.getByText('Select A'))!.toBeInTheDocument() fireEvent.click(screen.getByText('Select A')) fireEvent.click(screen.getByText('Select B')) @@ -459,12 +459,12 @@ describe('Form', () => { />, ) - expect(screen.getByText('Override Field')).toBeInTheDocument() - expect(screen.getByText(/Custom Render:.*custom_field/)).toBeInTheDocument() + expect(screen.getByText('Override Field'))!.toBeInTheDocument() + expect(screen.getByText(/Custom Render:.*custom_field/))!.toBeInTheDocument() expect(screen.getAllByText('allowed')).toHaveLength(3) expect(screen.getAllByText('blocked')).toHaveLength(1) - fireEvent.click(screen.getAllByText('Pick Variable')[0]) + fireEvent.click(screen.getAllByText('Pick Variable')[0]!) expect(onChange).toHaveBeenCalledWith({ override: '', any_var: [{ name: 'var-1' }], any_without_scope: [], custom_field: '' }) expect(screen.getAllByText('Extra Info')).toHaveLength(2) @@ -497,7 +497,8 @@ describe('Form', () => { ) // Assert - expect(screen.getByPlaceholderText('API Key')).toBeDisabled() + // Assert + expect(screen.getByPlaceholderText('API Key'))!.toBeDisabled() }) // Override returns null: falls through to default renderer @@ -528,7 +529,8 @@ describe('Form', () => { ) // Assert - should fall through to default textInput renderer - expect(screen.getByPlaceholderText('Field 1')).toBeInTheDocument() + // Assert - should fall through to default textInput renderer + expect(screen.getByPlaceholderText('Field 1'))!.toBeInTheDocument() }) // isShowDefaultValue=true, value is null → default shown @@ -559,7 +561,8 @@ describe('Form', () => { ) // Assert - expect(screen.getByPlaceholderText('Nullable')).toHaveValue('default-val') + // Assert + expect(screen.getByPlaceholderText('Nullable'))!.toHaveValue('default-val') }) // isShowDefaultValue=true, value is undefined → default shown @@ -590,7 +593,8 @@ describe('Form', () => { ) // Assert - expect(screen.getByPlaceholderText('Undef')).toHaveValue('default-undef') + // Assert + expect(screen.getByPlaceholderText('Undef'))!.toHaveValue('default-undef') }) // isEditMode=true, variable=__model_type → textInput disabled @@ -619,7 +623,8 @@ describe('Form', () => { ) // Assert - expect(screen.getByPlaceholderText('Model Type')).toBeDisabled() + // Assert + expect(screen.getByPlaceholderText('Model Type'))!.toBeDisabled() }) // Label with missing language key → en_US fallback used @@ -649,7 +654,8 @@ describe('Form', () => { ) // Assert - expect(screen.getByText('English Label')).toBeInTheDocument() + // Assert + expect(screen.getByText('English Label'))!.toBeInTheDocument() }) // Select field with isShowDefaultValue=true @@ -680,7 +686,8 @@ describe('Form', () => { ) // Assert - Select B should be the rendered default - expect(screen.getByText('Select B')).toBeInTheDocument() + // Assert - Select B should be the rendered default + expect(screen.getByText('Select B'))!.toBeInTheDocument() }) // Radio option with show_on condition not met → option filtered out @@ -712,7 +719,8 @@ describe('Form', () => { ) // Assert - expect(screen.getByText('Always Visible')).toBeInTheDocument() + // Assert + expect(screen.getByText('Always Visible'))!.toBeInTheDocument() expect(screen.queryByText('Conditional')).not.toBeInTheDocument() }) @@ -804,8 +812,9 @@ describe('Form', () => { ) // Both rendered successfully - expect(screen.getByPlaceholderText('Secret')).toBeInTheDocument() - expect(screen.getByPlaceholderText('Number')).toBeInTheDocument() + // Both rendered successfully + expect(screen.getByPlaceholderText('Secret'))!.toBeInTheDocument() + expect(screen.getByPlaceholderText('Number'))!.toBeInTheDocument() }) // Placeholder fallback: null placeholder @@ -830,7 +839,7 @@ describe('Form', () => { />, ) - expect(screen.getByText('No Placeholder')).toBeInTheDocument() + expect(screen.getByText('No Placeholder'))!.toBeInTheDocument() }) // validating=true + changeKey matches variable: ValidatingTip shown @@ -866,7 +875,8 @@ describe('Form', () => { fireEvent.change(screen.getByPlaceholderText('API Key'), { target: { value: 'new' } }) // ValidatingTip should appear for api_key - expect(screen.getByText('Validating...')).toBeInTheDocument() + // ValidatingTip should appear for api_key + expect(screen.getByText('Validating...'))!.toBeInTheDocument() }) // Select with show_on not met: hidden @@ -923,7 +933,7 @@ describe('Form', () => { />, ) - expect(screen.getByText('Always')).toBeInTheDocument() + expect(screen.getByText('Always'))!.toBeInTheDocument() expect(screen.queryByText('Conditional')).not.toBeInTheDocument() }) @@ -1009,7 +1019,7 @@ describe('Form', () => { />, ) - expect(screen.getByPlaceholderText('Field')).toHaveValue('') + expect(screen.getByPlaceholderText('Field'))!.toHaveValue('') }) // Radio with disabled=true in edit mode for __model_type @@ -1066,7 +1076,7 @@ describe('Form', () => { />, ) - expect(screen.getByText('Select Tools')).toBeInTheDocument() + expect(screen.getByText('Select Tools'))!.toBeInTheDocument() }) // Override with non-matching type: falls through to default @@ -1095,7 +1105,7 @@ describe('Form', () => { ) expect(screen.queryByText('Override Hit')).not.toBeInTheDocument() - expect(screen.getByPlaceholderText('Secret Field')).toBeInTheDocument() + expect(screen.getByPlaceholderText('Secret Field'))!.toBeInTheDocument() }) // Select with isShowDefaultValue: null value shows default @@ -1123,7 +1133,7 @@ describe('Form', () => { />, ) - expect(screen.getByText('Select B')).toBeInTheDocument() + expect(screen.getByText('Select B'))!.toBeInTheDocument() }) // Select with isShowDefaultValue: undefined value shows default @@ -1151,7 +1161,7 @@ describe('Form', () => { />, ) - expect(screen.getByText('Select A')).toBeInTheDocument() + expect(screen.getByText('Select A'))!.toBeInTheDocument() }) // No fieldMoreInfo: should not crash @@ -1177,7 +1187,7 @@ describe('Form', () => { />, ) - expect(screen.getByPlaceholderText('Field 1')).toBeInTheDocument() + expect(screen.getByPlaceholderText('Field 1'))!.toBeInTheDocument() }) it('should render tooltip when schema has tooltip property', () => { @@ -1220,10 +1230,10 @@ describe('Form', () => { />, ) - expect(screen.getByText('API Key')).toBeInTheDocument() - expect(screen.getByText('Region')).toBeInTheDocument() - expect(screen.getByText('Model')).toBeInTheDocument() - expect(screen.getByText('Agree')).toBeInTheDocument() + expect(screen.getByText('API Key'))!.toBeInTheDocument() + expect(screen.getByText('Region'))!.toBeInTheDocument() + expect(screen.getByText('Model'))!.toBeInTheDocument() + expect(screen.getByText('Agree'))!.toBeInTheDocument() }) it('should render required asterisk for radio, select, checkbox, and other field types', () => { @@ -1319,7 +1329,7 @@ describe('Form', () => { ) fireEvent.click(screen.getByText('Option B')) - expect(screen.getByText('Validating...')).toBeInTheDocument() + expect(screen.getByText('Validating...'))!.toBeInTheDocument() }) it('should render textInput with show_on condition met', () => { @@ -1345,7 +1355,7 @@ describe('Form', () => { />, ) - expect(screen.getByPlaceholderText('Conditional')).toBeInTheDocument() + expect(screen.getByPlaceholderText('Conditional'))!.toBeInTheDocument() }) it('should render radio with show_on condition met', () => { @@ -1370,7 +1380,7 @@ describe('Form', () => { />, ) - expect(screen.getByText('Cond Radio')).toBeInTheDocument() + expect(screen.getByText('Cond Radio'))!.toBeInTheDocument() }) it('should proceed with onChange when isEditMode is true but key is not locked', () => { @@ -1424,6 +1434,37 @@ describe('Form', () => { />, ) + // Should not crash - the field simply doesn't render + // Should not crash - the field simply doesn't render + // Should not crash - the field simply doesn't render + // Should not crash - the field simply doesn't render + // Should not crash - the field simply doesn't render + // Should not crash - the field simply doesn't render + // Should not crash - the field simply doesn't render + // Should not crash - the field simply doesn't render + // Should not crash - the field simply doesn't render + // Should not crash - the field simply doesn't render + // Should not crash - the field simply doesn't render + // Should not crash - the field simply doesn't render + // Should not crash - the field simply doesn't render + // Should not crash - the field simply doesn't render + // Should not crash - the field simply doesn't render + // Should not crash - the field simply doesn't render + // Should not crash - the field simply doesn't render + // Should not crash - the field simply doesn't render + // Should not crash - the field simply doesn't render + // Should not crash - the field simply doesn't render + // Should not crash - the field simply doesn't render + // Should not crash - the field simply doesn't render + // Should not crash - the field simply doesn't render + // Should not crash - the field simply doesn't render + // Should not crash - the field simply doesn't render + // Should not crash - the field simply doesn't render + // Should not crash - the field simply doesn't render + // Should not crash - the field simply doesn't render + // Should not crash - the field simply doesn't render + // Should not crash - the field simply doesn't render + // Should not crash - the field simply doesn't render // Should not crash - the field simply doesn't render expect(screen.queryByText('Unknown')).not.toBeInTheDocument() }) @@ -1452,7 +1493,7 @@ describe('Form', () => { />, ) - expect(screen.getByText('Check Extra')).toBeInTheDocument() + expect(screen.getByText('Check Extra'))!.toBeInTheDocument() }) }) @@ -1497,10 +1538,10 @@ describe('Form', () => { />, ) - expect(screen.getByText('API Key Fallback')).toBeInTheDocument() - expect(screen.getByText('Region Fallback')).toBeInTheDocument() - expect(screen.getByText('Model Fallback')).toBeInTheDocument() - expect(screen.getByText('Agree Fallback')).toBeInTheDocument() + expect(screen.getByText('API Key Fallback'))!.toBeInTheDocument() + expect(screen.getByText('Region Fallback'))!.toBeInTheDocument() + expect(screen.getByText('Model Fallback'))!.toBeInTheDocument() + expect(screen.getByText('Agree Fallback'))!.toBeInTheDocument() }) it('should fallback to en_US for modelSelector, toolSelector, and appSelector labels', () => { @@ -1542,10 +1583,10 @@ describe('Form', () => { />, ) - expect(screen.getByText('ModelSel Fallback')).toBeInTheDocument() - expect(screen.getByText('ToolSel Fallback')).toBeInTheDocument() - expect(screen.getByText('AppSel Fallback')).toBeInTheDocument() - expect(screen.getByText('Any Fallback')).toBeInTheDocument() + expect(screen.getByText('ModelSel Fallback'))!.toBeInTheDocument() + expect(screen.getByText('ToolSel Fallback'))!.toBeInTheDocument() + expect(screen.getByText('AppSel Fallback'))!.toBeInTheDocument() + expect(screen.getByText('Any Fallback'))!.toBeInTheDocument() }) it('should not change value when __model_type is edited in edit mode', () => { @@ -1602,7 +1643,7 @@ describe('Form', () => { />, ) - expect(screen.getByDisplayValue('actual-value')).toBeInTheDocument() + expect(screen.getByDisplayValue('actual-value'))!.toBeInTheDocument() }) it('should pass nodeOutputVars and availableNodes to toolSelector', () => { @@ -1632,7 +1673,7 @@ describe('Form', () => { />, ) - expect(screen.getByText('Select Tool')).toBeInTheDocument() + expect(screen.getByText('Select Tool'))!.toBeInTheDocument() expect(toolSelectorPropsSpy).toHaveBeenCalledWith(expect.objectContaining({ nodeOutputVars, availableNodes, @@ -1663,7 +1704,7 @@ describe('Form', () => { />, ) - expect(screen.getByText('Select Model')).toBeInTheDocument() + expect(screen.getByText('Select Model'))!.toBeInTheDocument() expect(modelSelectorPropsSpy).toHaveBeenCalledWith(expect.objectContaining({ isAgentStrategy: true, })) @@ -1695,7 +1736,8 @@ describe('Form', () => { ) // Assert - should render without crash (value[variable] || [] path taken) - expect(screen.getByText('Select Tools')).toBeInTheDocument() + // Assert - should render without crash (value[variable] || [] path taken) + expect(screen.getByText('Select Tools'))!.toBeInTheDocument() }) it('should show ValidatingTip for multiToolSelector field being validated', () => { @@ -1726,7 +1768,8 @@ describe('Form', () => { fireEvent.click(screen.getByText('Select Tools')) // Assert - expect(screen.getByText('Validating...')).toBeInTheDocument() + // Assert + expect(screen.getByText('Validating...'))!.toBeInTheDocument() }) it('should show ValidatingTip for appSelector field being validated', () => { @@ -1757,7 +1800,8 @@ describe('Form', () => { fireEvent.click(screen.getByText('Select App')) // Assert - expect(screen.getByText('Validating...')).toBeInTheDocument() + // Assert + expect(screen.getByText('Validating...'))!.toBeInTheDocument() }) it('should show ValidatingTip for any-type field being validated', () => { @@ -1789,7 +1833,8 @@ describe('Form', () => { fireEvent.click(screen.getByText('Pick Variable')) // Assert - expect(screen.getByText('Validating...')).toBeInTheDocument() + // Assert + expect(screen.getByText('Validating...'))!.toBeInTheDocument() }) it('should use empty string fallback for nodeId in any-type when nodeId is not provided', () => { @@ -1818,7 +1863,8 @@ describe('Form', () => { ) // Assert - should render without crash - expect(screen.getByText('Any Field')).toBeInTheDocument() + // Assert - should render without crash + expect(screen.getByText('Any Field'))!.toBeInTheDocument() }) it('should use en_US label fallback for multiToolSelector when language key is missing', () => { @@ -1849,7 +1895,8 @@ describe('Form', () => { ) // Assert - MultipleToolSelector mock renders with the label prop - expect(screen.getByText('Select Tools')).toBeInTheDocument() + // Assert - MultipleToolSelector mock renders with the label prop + expect(screen.getByText('Select Tools'))!.toBeInTheDocument() }) it('should show ValidatingTip for select field being validated', () => { @@ -1882,7 +1929,8 @@ describe('Form', () => { fireEvent.click(screen.getByText('Select B')) // Assert: ValidatingTip shows for the select field - expect(screen.getByText('Validating...')).toBeInTheDocument() + // Assert: ValidatingTip shows for the select field + expect(screen.getByText('Validating...'))!.toBeInTheDocument() }) it('should show ValidatingTip for toolSelector field being validated', () => { @@ -1914,7 +1962,8 @@ describe('Form', () => { fireEvent.click(screen.getByText('Select Tool')) // Assert - expect(screen.getByText('Validating...')).toBeInTheDocument() + // Assert + expect(screen.getByText('Validating...'))!.toBeInTheDocument() }) it('should not render customRenderField for a FormTypeEnum value that is unhandled by Form', () => { diff --git a/web/app/components/header/account-setting/model-provider-page/model-modal/__tests__/index.spec.tsx b/web/app/components/header/account-setting/model-provider-page/model-modal/__tests__/index.spec.tsx index a47b5eb170..a7e85bd9eb 100644 --- a/web/app/components/header/account-setting/model-provider-page/model-modal/__tests__/index.spec.tsx +++ b/web/app/components/header/account-setting/model-provider-page/model-modal/__tests__/index.spec.tsx @@ -196,10 +196,10 @@ describe('ModelModal', () => { const predefined = renderModal() - expect(screen.getByText('common.modelProvider.auth.apiKeyModal.title')).toBeInTheDocument() - expect(screen.getByText('common.modelProvider.auth.apiKeyModal.desc')).toBeInTheDocument() - expect(screen.getByRole('status')).toBeInTheDocument() - expect(screen.getByRole('button', { name: 'common.operation.save' })).toBeDisabled() + expect(screen.getByText('common.modelProvider.auth.apiKeyModal.title'))!.toBeInTheDocument() + expect(screen.getByText('common.modelProvider.auth.apiKeyModal.desc'))!.toBeInTheDocument() + expect(screen.getByRole('status'))!.toBeInTheDocument() + expect(screen.getByRole('button', { name: 'common.operation.save' }))!.toBeDisabled() predefined.unmount() const customizable = renderModal({ configurateMethod: ConfigurationMethodEnum.customizableModel }) @@ -208,7 +208,7 @@ describe('ModelModal', () => { mockState.credentialData = { credentials: {}, available_credentials: [] } renderModal({ mode: ModelModalModeEnum.configModelCredential, model: { model: 'gpt-4', model_type: ModelTypeEnum.textGeneration } }) - expect(screen.getByText('common.modelProvider.auth.addModelCredential')).toBeInTheDocument() + expect(screen.getByText('common.modelProvider.auth.addModelCredential'))!.toBeInTheDocument() }) it('should reveal the credential label when adding a new credential', () => { @@ -218,7 +218,7 @@ describe('ModelModal', () => { fireEvent.click(screen.getByText('Add New')) - expect(screen.getByText('common.modelProvider.auth.modelCredential')).toBeInTheDocument() + expect(screen.getByText('common.modelProvider.auth.modelCredential'))!.toBeInTheDocument() }) it('should call onCancel when the cancel button is clicked', () => { @@ -245,7 +245,7 @@ describe('ModelModal', () => { const { onCancel } = renderModal({ credential }) const alertDialog = screen.getByRole('alertdialog', { hidden: true }) - expect(alertDialog).toHaveTextContent('common.modelProvider.confirmDelete') + expect(alertDialog)!.toHaveTextContent('common.modelProvider.confirmDelete') fireEvent.click(within(alertDialog).getByRole('button', { hidden: true, name: 'common.operation.confirm' })) @@ -261,7 +261,7 @@ describe('ModelModal', () => { { isCheckValidated: true, values: { __authorization_name__: 'Auth Name', api_key: 'secret' } }, ] const configCustomModel = renderModal({ mode: ModelModalModeEnum.configCustomModel }) - fireEvent.click(screen.getAllByText('Model Name Change')[0]) + fireEvent.click(screen.getAllByText('Model Name Change')[0]!) fireEvent.click(screen.getByRole('button', { name: 'common.operation.add' })) expect(mockFormState.setFieldValue).toHaveBeenCalledWith('__model_name', 'updated-model') diff --git a/web/app/components/header/account-setting/model-provider-page/model-parameter-modal/__tests__/parameter-item.spec.tsx b/web/app/components/header/account-setting/model-provider-page/model-parameter-modal/__tests__/parameter-item.spec.tsx index 8a923d065c..2e928c36cc 100644 --- a/web/app/components/header/account-setting/model-provider-page/model-parameter-modal/__tests__/parameter-item.spec.tsx +++ b/web/app/components/header/account-setting/model-provider-page/model-parameter-modal/__tests__/parameter-item.spec.tsx @@ -68,7 +68,7 @@ describe('ParameterItem', () => { const input = screen.getByRole('spinbutton') fireEvent.change(input, { target: { value: '1.4' } }) expect(onChange).toHaveBeenCalledWith(1) - expect(screen.getByTestId('slider-btn')).toBeInTheDocument() + expect(screen.getByTestId('slider-btn'))!.toBeInTheDocument() }) it('should clamp float numeric input to min', () => { @@ -91,19 +91,19 @@ describe('ParameterItem', () => { it('should adjust step based on max for int type', () => { const { rerender } = render() - expect(screen.getByRole('spinbutton')).toHaveAttribute('step', '1') + expect(screen.getByRole('spinbutton'))!.toHaveAttribute('step', '1') rerender() - expect(screen.getByRole('spinbutton')).toHaveAttribute('step', '10') + expect(screen.getByRole('spinbutton'))!.toHaveAttribute('step', '10') rerender() - expect(screen.getByRole('spinbutton')).toHaveAttribute('step', '100') + expect(screen.getByRole('spinbutton'))!.toHaveAttribute('step', '100') }) it('should render int input without slider if min or max is missing', () => { render() expect(screen.queryByRole('slider')).not.toBeInTheDocument() - expect(screen.getByRole('spinbutton')).toHaveAttribute('step', '0') + expect(screen.getByRole('spinbutton'))!.toHaveAttribute('step', '0') }) it('should handle slide change and clamp values', () => { @@ -125,20 +125,20 @@ describe('ParameterItem', () => { const onChange = vi.fn() const { container } = render() const textarea = container.querySelector('textarea')! - expect(textarea).toBeInTheDocument() + expect(textarea)!.toBeInTheDocument() fireEvent.change(textarea, { target: { value: 'new long text' } }) expect(onChange).toHaveBeenCalledWith('new long text') }) it('should render select for string with options', () => { render() - expect(screen.getByText('a')).toBeInTheDocument() + expect(screen.getByText('a'))!.toBeInTheDocument() }) it('should render tag input for tag type', () => { const onChange = vi.fn() render() - expect(screen.getByText('placeholder')).toBeInTheDocument() + expect(screen.getByText('placeholder'))!.toBeInTheDocument() fireEvent.click(screen.getByTestId('tag-input')) expect(onChange).toHaveBeenCalledWith(['tag1', 'tag2']) }) @@ -166,17 +166,17 @@ describe('ParameterItem', () => { it('should use default values if value is undefined', () => { const { rerender } = render() - expect(screen.getByRole('spinbutton')).toHaveValue(0.5) + expect(screen.getByRole('spinbutton'))!.toHaveValue(0.5) rerender() - expect(screen.getByRole('textbox')).toHaveValue('hello') + expect(screen.getByRole('textbox'))!.toHaveValue('hello') rerender() - expect(screen.getByText('True')).toBeInTheDocument() - expect(screen.getByText('False')).toBeInTheDocument() + expect(screen.getByText('True'))!.toBeInTheDocument() + expect(screen.getByText('False'))!.toBeInTheDocument() rerender() - expect(screen.getByRole('spinbutton')).toHaveValue(0) + expect(screen.getByRole('spinbutton'))!.toHaveValue(0) }) it('should reset input to actual bound value on blur-sm', () => { @@ -184,7 +184,7 @@ describe('ParameterItem', () => { const input = screen.getByRole('spinbutton') fireEvent.change(input, { target: { value: '5' } }) fireEvent.blur(input) - expect(input).toHaveValue(1) + expect(input)!.toHaveValue(1) }) it('should render no input for unsupported parameter type', () => { @@ -216,12 +216,12 @@ describe('ParameterItem', () => { ) const editor = screen.getByTestId('prompt-editor') - expect(editor).toBeInTheDocument() - expect(editor).toHaveAttribute('data-has-workflow-vars', 'true') + expect(editor)!.toBeInTheDocument() + expect(editor)!.toHaveAttribute('data-has-workflow-vars', 'true') expect(capturedWorkflowNodesMap).toBeDefined() - expect(capturedWorkflowNodesMap!.node1.title).toBe('LLM Node') - expect(capturedWorkflowNodesMap!.sys.title).toBe('workflow.blocks.start') - expect(capturedWorkflowNodesMap!.sys.type).toBe(BlockEnum.Start) + expect(capturedWorkflowNodesMap!.node1!.title).toBe('LLM Node') + expect(capturedWorkflowNodesMap!.sys!.title).toBe('workflow.blocks.start') + expect(capturedWorkflowNodesMap!.sys!.type).toBe(BlockEnum.Start) promptEditorOnChange?.('updated text') expect(onChange).toHaveBeenCalledWith('updated text') @@ -241,8 +241,8 @@ describe('ParameterItem', () => { ) const editor = screen.getByTestId('prompt-editor') - expect(editor).toBeInTheDocument() - expect(editor).toHaveAttribute('data-has-workflow-vars', 'true') + expect(editor)!.toBeInTheDocument() + expect(editor)!.toHaveAttribute('data-has-workflow-vars', 'true') expect(capturedWorkflowNodesMap).toBeDefined() promptEditorOnChange?.('new long text') @@ -258,7 +258,7 @@ describe('ParameterItem', () => { ) expect(screen.queryByTestId('prompt-editor')).not.toBeInTheDocument() - expect(screen.getByRole('textbox')).toBeInTheDocument() + expect(screen.getByRole('textbox'))!.toBeInTheDocument() }) it('should return undefined workflowNodesMap when not in workflow mode', () => { diff --git a/web/app/components/header/account-setting/model-provider-page/model-selector/__tests__/popup-item.spec.tsx b/web/app/components/header/account-setting/model-provider-page/model-selector/__tests__/popup-item.spec.tsx index 050bb099d8..6728791120 100644 --- a/web/app/components/header/account-setting/model-provider-page/model-selector/__tests__/popup-item.spec.tsx +++ b/web/app/components/header/account-setting/model-provider-page/model-selector/__tests__/popup-item.spec.tsx @@ -185,7 +185,7 @@ describe('PopupItem', () => { expect(mockSetShowModelModal).toHaveBeenCalled() - const call = mockSetShowModelModal.mock.calls[0][0] as { onSaveCallback?: () => void } + const call = mockSetShowModelModal.mock.calls[0]![0] as { onSaveCallback?: () => void } call.onSaveCallback?.() expect(mockUpdateModelProviders).toHaveBeenCalled() @@ -220,7 +220,7 @@ describe('PopupItem', () => { />, ) - expect(screen.getByText('GPT-4')).toBeInTheDocument() + expect(screen.getByText('GPT-4'))!.toBeInTheDocument() }) it('should fall back to english labels when the current language is unavailable', () => { @@ -237,14 +237,14 @@ describe('PopupItem', () => { />, ) - expect(screen.getByText('OpenAI only')).toBeInTheDocument() - expect(screen.getByText('GPT-4 only')).toBeInTheDocument() + expect(screen.getByText('OpenAI only'))!.toBeInTheDocument() + expect(screen.getByText('GPT-4 only'))!.toBeInTheDocument() }) it('should toggle collapsed state when clicking provider header', () => { render() - expect(screen.getByText('GPT-4')).toBeInTheDocument() + expect(screen.getByText('GPT-4'))!.toBeInTheDocument() fireEvent.click(screen.getByText('OpenAI')) @@ -252,13 +252,13 @@ describe('PopupItem', () => { fireEvent.click(screen.getByText('OpenAI')) - expect(screen.getByText('GPT-4')).toBeInTheDocument() + expect(screen.getByText('GPT-4'))!.toBeInTheDocument() }) it('should show credential name when using custom provider', () => { render() - expect(screen.getByText('my-api-key')).toBeInTheDocument() + expect(screen.getByText('my-api-key'))!.toBeInTheDocument() }) it('should render the inactive credential badge when the api key is not active', () => { @@ -275,7 +275,7 @@ describe('PopupItem', () => { render() - expect(screen.getByText('stale-key')).toBeInTheDocument() + expect(screen.getByText('stale-key'))!.toBeInTheDocument() expect(document.querySelector('.bg-components-badge-status-light-error-bg')).not.toBeNull() }) @@ -301,7 +301,7 @@ describe('PopupItem', () => { render() - expect(screen.getByText(/modelProvider\.selector\.configureRequired/)).toBeInTheDocument() + expect(screen.getByText(/modelProvider\.selector\.configureRequired/))!.toBeInTheDocument() }) it('should show credits info when using system provider with remaining credits', () => { @@ -323,7 +323,7 @@ describe('PopupItem', () => { render() - expect(screen.getByText(/modelProvider\.selector\.aiCredits/)).toBeInTheDocument() + expect(screen.getByText(/modelProvider\.selector\.aiCredits/))!.toBeInTheDocument() }) it('should show credits exhausted when system provider has no credits', () => { @@ -348,7 +348,7 @@ describe('PopupItem', () => { render() - expect(screen.getByText(/modelProvider\.selector\.creditsExhausted/)).toBeInTheDocument() + expect(screen.getByText(/modelProvider\.selector\.creditsExhausted/))!.toBeInTheDocument() }) it('should close the dropdown through dropdown content callbacks', () => { diff --git a/web/app/components/header/account-setting/model-provider-page/model-selector/__tests__/popup.spec.tsx b/web/app/components/header/account-setting/model-provider-page/model-selector/__tests__/popup.spec.tsx index dee16e394e..61d6bb4466 100644 --- a/web/app/components/header/account-setting/model-provider-page/model-selector/__tests__/popup.spec.tsx +++ b/web/app/components/header/account-setting/model-provider-page/model-selector/__tests__/popup.spec.tsx @@ -191,14 +191,14 @@ describe('Popup', () => { />, ) - expect(screen.getByText('openai')).toBeInTheDocument() + expect(screen.getByText('openai'))!.toBeInTheDocument() const input = screen.getByPlaceholderText('datasetSettings.form.searchModel') fireEvent.change(input, { target: { value: 'not-found' } }) - expect(screen.getByText('No model found for \u201Cnot-found\u201D')).toBeInTheDocument() + expect(screen.getByText('No model found for \u201Cnot-found\u201D'))!.toBeInTheDocument() const clearIcon = container.querySelector('.i-custom-vender-solid-general-x-circle') - expect(clearIcon).toBeInTheDocument() + expect(clearIcon)!.toBeInTheDocument() fireEvent.click(clearIcon!) expect((input as HTMLInputElement).value).toBe('') }) @@ -225,9 +225,9 @@ describe('Popup', () => { />, ) - expect(screen.getByTestId('compatible-models-banner')).toBeInTheDocument() - expect(screen.getByText('common.modelProvider.selector.onlyCompatibleModelsShown')).toBeInTheDocument() - expect(container.querySelector('.i-ri-information-2-fill')).toBeInTheDocument() + expect(screen.getByTestId('compatible-models-banner'))!.toBeInTheDocument() + expect(screen.getByText('common.modelProvider.selector.onlyCompatibleModelsShown'))!.toBeInTheDocument() + expect(container.querySelector('.i-ri-information-2-fill'))!.toBeInTheDocument() }) it('should filter by scope features including toolCall and non-toolCall checks', () => { @@ -244,7 +244,7 @@ describe('Popup', () => { scopeFeatures={[ModelFeatureEnum.toolCall, ModelFeatureEnum.vision]} />, ) - expect(screen.getByText('No model found for \u201C\u201D')).toBeInTheDocument() + expect(screen.getByText('No model found for \u201C\u201D'))!.toBeInTheDocument() unmount() mockSupportFunctionCall.mockReturnValue(true) @@ -256,7 +256,7 @@ describe('Popup', () => { scopeFeatures={[ModelFeatureEnum.toolCall, ModelFeatureEnum.vision]} />, ) - expect(screen.getByText('openai')).toBeInTheDocument() + expect(screen.getByText('openai'))!.toBeInTheDocument() unmount2() const { unmount: unmount3 } = render( @@ -267,7 +267,7 @@ describe('Popup', () => { scopeFeatures={[ModelFeatureEnum.vision]} />, ) - expect(screen.getByText('openai')).toBeInTheDocument() + expect(screen.getByText('openai'))!.toBeInTheDocument() unmount3() render( @@ -278,7 +278,7 @@ describe('Popup', () => { scopeFeatures={[ModelFeatureEnum.vision]} />, ) - expect(screen.getByText('No model found for \u201C\u201D')).toBeInTheDocument() + expect(screen.getByText('No model found for \u201C\u201D'))!.toBeInTheDocument() }) it('should match model labels from fallback languages when current language key is missing', () => { @@ -305,7 +305,7 @@ describe('Popup', () => { { target: { value: 'openai' } }, ) - expect(screen.getByText('openai')).toBeInTheDocument() + expect(screen.getByText('openai'))!.toBeInTheDocument() }) it('should show credits exhausted alert when an exhausted provider supports credits', () => { @@ -331,7 +331,7 @@ describe('Popup', () => { />, ) - expect(screen.getByTestId('credits-exhausted-alert')).toHaveAttribute('data-has-api-key-fallback', 'false') + expect(screen.getByTestId('credits-exhausted-alert'))!.toHaveAttribute('data-has-api-key-fallback', 'false') }) it('should not show credits exhausted alert when only non-trial system providers are exhausted', () => { @@ -419,8 +419,8 @@ describe('Popup', () => { />, ) - expect(screen.getByText(/modelProvider\.selector\.noProviderConfigured(?!Desc)/)).toBeInTheDocument() - expect(screen.getByText(/modelProvider\.selector\.noProviderConfiguredDesc/)).toBeInTheDocument() + expect(screen.getByText(/modelProvider\.selector\.noProviderConfigured(?!Desc)/))!.toBeInTheDocument() + expect(screen.getByText(/modelProvider\.selector\.noProviderConfiguredDesc/))!.toBeInTheDocument() fireEvent.click(screen.getByText(/modelProvider\.selector\.configure/)) expect(onHide).toHaveBeenCalled() @@ -441,9 +441,9 @@ describe('Popup', () => { ) expect(screen.queryByText('TestOpenAI')).not.toBeInTheDocument() - expect(screen.getByText('TestAnthropic')).toBeInTheDocument() - expect(screen.getByText(/modelProvider\.selector\.fromMarketplace/)).toBeInTheDocument() - expect(screen.getByText(/modelProvider\.selector\.discoverMoreInMarketplace/)).toBeInTheDocument() + expect(screen.getByText('TestAnthropic'))!.toBeInTheDocument() + expect(screen.getByText(/modelProvider\.selector\.fromMarketplace/))!.toBeInTheDocument() + expect(screen.getByText(/modelProvider\.selector\.discoverMoreInMarketplace/))!.toBeInTheDocument() }) it('should show installed marketplace providers without models when AI credits are available', () => { @@ -462,8 +462,8 @@ describe('Popup', () => { />, ) - expect(screen.getByText('test-anthropic')).toBeInTheDocument() - expect(screen.getByText('TestOpenAI')).toBeInTheDocument() + expect(screen.getByText('test-anthropic'))!.toBeInTheDocument() + expect(screen.getByText('TestOpenAI'))!.toBeInTheDocument() }) it('should hide installed marketplace providers without models when AI credits are exhausted', () => { @@ -489,7 +489,7 @@ describe('Popup', () => { expect(screen.queryByText('test-anthropic')).not.toBeInTheDocument() expect(screen.queryByText('TestAnthropic')).not.toBeInTheDocument() - expect(screen.getByText('TestOpenAI')).toBeInTheDocument() + expect(screen.getByText('TestOpenAI'))!.toBeInTheDocument() }) it('should toggle marketplace section collapse', () => { @@ -501,7 +501,7 @@ describe('Popup', () => { />, ) - expect(screen.getByText('TestOpenAI')).toBeInTheDocument() + expect(screen.getByText('TestOpenAI'))!.toBeInTheDocument() fireEvent.click(screen.getByText(/modelProvider\.selector\.fromMarketplace/)) @@ -509,7 +509,7 @@ describe('Popup', () => { fireEvent.click(screen.getByText(/modelProvider\.selector\.fromMarketplace/)) - expect(screen.getByText('TestOpenAI')).toBeInTheDocument() + expect(screen.getByText('TestOpenAI'))!.toBeInTheDocument() }) it('should install plugin when clicking install button', async () => { @@ -527,7 +527,7 @@ describe('Popup', () => { ) const installButtons = screen.getAllByText(/common\.modelProvider\.selector\.install/) - fireEvent.click(installButtons[0]) + fireEvent.click(installButtons[0]!) await waitFor(() => { expect(mockInstallMutateAsync).toHaveBeenCalledWith('langgenius/openai:1.0.0') @@ -550,7 +550,7 @@ describe('Popup', () => { ) const installButtons = screen.getAllByText(/common\.modelProvider\.selector\.install/) - fireEvent.click(installButtons[0]) + fireEvent.click(installButtons[0]!) await waitFor(() => { expect(mockInstallMutateAsync).toHaveBeenCalled() @@ -576,7 +576,7 @@ describe('Popup', () => { ) const installButtons = screen.getAllByText(/common\.modelProvider\.selector\.install/) - fireEvent.click(installButtons[0]) + fireEvent.click(installButtons[0]!) await waitFor(() => { expect(mockCheck).toHaveBeenCalledWith({ @@ -601,7 +601,7 @@ describe('Popup', () => { />, ) - fireEvent.click(screen.getAllByText(/common\.modelProvider\.selector\.install/)[0]) + fireEvent.click(screen.getAllByText(/common\.modelProvider\.selector\.install/)[0]!) await waitFor(() => { expect(mockInstallMutateAsync).not.toHaveBeenCalled() @@ -619,7 +619,7 @@ describe('Popup', () => { />, ) - fireEvent.click(screen.getAllByText(/common\.modelProvider\.selector\.install/)[0]) + fireEvent.click(screen.getAllByText(/common\.modelProvider\.selector\.install/)[0]!) await waitFor(() => { expect(mockInstallMutateAsync).not.toHaveBeenCalled() @@ -640,6 +640,6 @@ describe('Popup', () => { ) const providerLabels = screen.getAllByText(/openai|anthropic/) - expect(providerLabels[0]).toHaveTextContent('anthropic') + expect(providerLabels[0])!.toHaveTextContent('anthropic') }) }) diff --git a/web/app/components/header/account-setting/model-provider-page/model-selector/popup-item.tsx b/web/app/components/header/account-setting/model-provider-page/model-selector/popup-item.tsx index d1ad017455..e38cc07ca2 100644 --- a/web/app/components/header/account-setting/model-provider-page/model-selector/popup-item.tsx +++ b/web/app/components/header/account-setting/model-provider-page/model-selector/popup-item.tsx @@ -77,7 +77,7 @@ const PopupItem: FC = ({ onSaveCallback: () => { updateModelProviders() - const modelType = model.models[0].model_type + const modelType = model.models[0]!.model_type if (modelType) updateModelList(modelType) diff --git a/web/app/components/header/account-setting/model-provider-page/provider-added-card/__tests__/model-list.spec.tsx b/web/app/components/header/account-setting/model-provider-page/provider-added-card/__tests__/model-list.spec.tsx index 70a0cb985a..e435835807 100644 --- a/web/app/components/header/account-setting/model-provider-page/provider-added-card/__tests__/model-list.spec.tsx +++ b/web/app/components/header/account-setting/model-provider-page/provider-added-card/__tests__/model-list.spec.tsx @@ -59,8 +59,8 @@ describe('ModelList', () => { />, ) expect(screen.getAllByText(/modelProvider\.modelsNum/).length).toBeGreaterThan(0) - expect(screen.getByRole('button', { name: 'gpt-4' })).toBeInTheDocument() - expect(screen.getByRole('button', { name: 'gpt-3.5' })).toBeInTheDocument() + expect(screen.getByRole('button', { name: 'gpt-4' }))!.toBeInTheDocument() + expect(screen.getByRole('button', { name: 'gpt-3.5' }))!.toBeInTheDocument() }) it('should trigger collapse when collapsed label is clicked', () => { @@ -74,7 +74,7 @@ describe('ModelList', () => { ) const countElements = screen.getAllByText(/modelProvider\.modelsNum/) - fireEvent.click(countElements[1]) + fireEvent.click(countElements[1]!) expect(mockOnCollapse).toHaveBeenCalled() }) @@ -125,6 +125,37 @@ describe('ModelList', () => { />, ) + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert // Assert expect(screen.queryByTestId('manage-credentials')).not.toBeInTheDocument() expect(screen.queryByTestId('add-custom-model')).not.toBeInTheDocument() @@ -143,7 +174,7 @@ describe('ModelList', () => { fireEvent.click(screen.getByRole('button', { name: 'gpt-4' })) expect(mockSetShowModelLoadBalancingModal).toHaveBeenCalled() - const callArg = mockSetShowModelLoadBalancingModal.mock.calls[0][0] + const callArg = mockSetShowModelLoadBalancingModal.mock.calls[0]![0] callArg.onSave('test-provider') expect(mockOnChange).toHaveBeenCalledWith('test-provider') @@ -170,6 +201,37 @@ describe('ModelList', () => { />, ) + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert // Assert expect(screen.queryByTestId('manage-credentials')).not.toBeInTheDocument() expect(screen.queryByTestId('add-custom-model')).not.toBeInTheDocument() @@ -195,8 +257,9 @@ describe('ModelList', () => { ) // Assert: custom model actions are shown (isConfigurable=true && isCurrentWorkspaceManager=true) - expect(screen.getByTestId('manage-credentials')).toBeInTheDocument() - expect(screen.getByTestId('add-custom-model')).toBeInTheDocument() + // Assert: custom model actions are shown (isConfigurable=true && isCurrentWorkspaceManager=true) + expect(screen.getByTestId('manage-credentials'))!.toBeInTheDocument() + expect(screen.getByTestId('add-custom-model'))!.toBeInTheDocument() }) it('should hide custom model actions when provider is configurable but user is not workspace manager', () => { @@ -218,6 +281,37 @@ describe('ModelList', () => { />, ) + // Assert: custom model actions are hidden (isCurrentWorkspaceManager=false covers the && short-circuit) + // Assert: custom model actions are hidden (isCurrentWorkspaceManager=false covers the && short-circuit) + // Assert: custom model actions are hidden (isCurrentWorkspaceManager=false covers the && short-circuit) + // Assert: custom model actions are hidden (isCurrentWorkspaceManager=false covers the && short-circuit) + // Assert: custom model actions are hidden (isCurrentWorkspaceManager=false covers the && short-circuit) + // Assert: custom model actions are hidden (isCurrentWorkspaceManager=false covers the && short-circuit) + // Assert: custom model actions are hidden (isCurrentWorkspaceManager=false covers the && short-circuit) + // Assert: custom model actions are hidden (isCurrentWorkspaceManager=false covers the && short-circuit) + // Assert: custom model actions are hidden (isCurrentWorkspaceManager=false covers the && short-circuit) + // Assert: custom model actions are hidden (isCurrentWorkspaceManager=false covers the && short-circuit) + // Assert: custom model actions are hidden (isCurrentWorkspaceManager=false covers the && short-circuit) + // Assert: custom model actions are hidden (isCurrentWorkspaceManager=false covers the && short-circuit) + // Assert: custom model actions are hidden (isCurrentWorkspaceManager=false covers the && short-circuit) + // Assert: custom model actions are hidden (isCurrentWorkspaceManager=false covers the && short-circuit) + // Assert: custom model actions are hidden (isCurrentWorkspaceManager=false covers the && short-circuit) + // Assert: custom model actions are hidden (isCurrentWorkspaceManager=false covers the && short-circuit) + // Assert: custom model actions are hidden (isCurrentWorkspaceManager=false covers the && short-circuit) + // Assert: custom model actions are hidden (isCurrentWorkspaceManager=false covers the && short-circuit) + // Assert: custom model actions are hidden (isCurrentWorkspaceManager=false covers the && short-circuit) + // Assert: custom model actions are hidden (isCurrentWorkspaceManager=false covers the && short-circuit) + // Assert: custom model actions are hidden (isCurrentWorkspaceManager=false covers the && short-circuit) + // Assert: custom model actions are hidden (isCurrentWorkspaceManager=false covers the && short-circuit) + // Assert: custom model actions are hidden (isCurrentWorkspaceManager=false covers the && short-circuit) + // Assert: custom model actions are hidden (isCurrentWorkspaceManager=false covers the && short-circuit) + // Assert: custom model actions are hidden (isCurrentWorkspaceManager=false covers the && short-circuit) + // Assert: custom model actions are hidden (isCurrentWorkspaceManager=false covers the && short-circuit) + // Assert: custom model actions are hidden (isCurrentWorkspaceManager=false covers the && short-circuit) + // Assert: custom model actions are hidden (isCurrentWorkspaceManager=false covers the && short-circuit) + // Assert: custom model actions are hidden (isCurrentWorkspaceManager=false covers the && short-circuit) + // Assert: custom model actions are hidden (isCurrentWorkspaceManager=false covers the && short-circuit) + // Assert: custom model actions are hidden (isCurrentWorkspaceManager=false covers the && short-circuit) // Assert: custom model actions are hidden (isCurrentWorkspaceManager=false covers the && short-circuit) expect(screen.queryByTestId('manage-credentials')).not.toBeInTheDocument() expect(screen.queryByTestId('add-custom-model')).not.toBeInTheDocument() diff --git a/web/app/components/header/account-setting/model-provider-page/provider-added-card/__tests__/model-load-balancing-modal.spec.tsx b/web/app/components/header/account-setting/model-provider-page/provider-added-card/__tests__/model-load-balancing-modal.spec.tsx index c7368a2a54..eedc04115c 100644 --- a/web/app/components/header/account-setting/model-provider-page/provider-added-card/__tests__/model-load-balancing-modal.spec.tsx +++ b/web/app/components/header/account-setting/model-provider-page/provider-added-card/__tests__/model-load-balancing-modal.spec.tsx @@ -180,7 +180,7 @@ describe('ModelLoadBalancingModal', () => { />, ) - expect(screen.getByRole('status')).toBeInTheDocument() + expect(screen.getByRole('status'))!.toBeInTheDocument() }) it('should render predefined model content', () => { @@ -193,9 +193,9 @@ describe('ModelLoadBalancingModal', () => { />, ) - expect(screen.getByText(/modelProvider\.auth\.configLoadBalancing/)).toBeInTheDocument() - expect(screen.getByText(/modelProvider\.auth\.providerManaged$/)).toBeInTheDocument() - expect(screen.getByText(/operation\.save/)).toBeInTheDocument() + expect(screen.getByText(/modelProvider\.auth\.configLoadBalancing/))!.toBeInTheDocument() + expect(screen.getByText(/modelProvider\.auth\.providerManaged$/))!.toBeInTheDocument() + expect(screen.getByText(/operation\.save/))!.toBeInTheDocument() }) it('should render custom model actions and close when update has no credentials', async () => { @@ -211,8 +211,8 @@ describe('ModelLoadBalancingModal', () => { />, ) - expect(screen.getByText(/modelProvider\.auth\.removeModel/)).toBeInTheDocument() - expect(screen.getByRole('button', { name: 'switch credential' })).toBeInTheDocument() + expect(screen.getByText(/modelProvider\.auth\.removeModel/))!.toBeInTheDocument() + expect(screen.getByRole('button', { name: 'switch credential' }))!.toBeInTheDocument() await user.click(screen.getByRole('button', { name: 'config add credential' })) await waitFor(() => { expect(onClose).toHaveBeenCalled() @@ -241,8 +241,8 @@ describe('ModelLoadBalancingModal', () => { await waitFor(() => { expect(mockRefetch).toHaveBeenCalled() expect(mockMutateAsync).toHaveBeenCalled() - const payload = mockMutateAsync.mock.calls[0][0] as { load_balancing: { configs: Array<{ credentials: { api_key: string } }> } } - expect(payload.load_balancing.configs[0].credentials.api_key).toBe('[__HIDDEN__]') + const payload = mockMutateAsync.mock.calls[0]![0] as { load_balancing: { configs: Array<{ credentials: { api_key: string } }> } } + expect(payload.load_balancing.configs[0]!.credentials.api_key).toBe('[__HIDDEN__]') expect(mockNotify).toHaveBeenCalled() expect(mockHandleRefreshModel).toHaveBeenCalled() expect(onSave).toHaveBeenCalledWith('test-provider') @@ -313,7 +313,7 @@ describe('ModelLoadBalancingModal', () => { />, ) - expect(screen.getByText(/modelProvider\.auth\.configModel/)).toBeInTheDocument() + expect(screen.getByText(/modelProvider\.auth\.configModel/))!.toBeInTheDocument() }) // Modal hidden when open=false @@ -409,7 +409,7 @@ describe('ModelLoadBalancingModal', () => { />, ) - expect(screen.getByRole('button', { name: 'switch credential' })).toBeInTheDocument() + expect(screen.getByRole('button', { name: 'switch credential' }))!.toBeInTheDocument() }) it('should disable save button when less than 2 configs are enabled', () => { @@ -433,7 +433,7 @@ describe('ModelLoadBalancingModal', () => { />, ) - expect(screen.getByText(/operation\.save/)).toBeDisabled() + expect(screen.getByText(/operation\.save/))!.toBeDisabled() }) it('should encode config entry without id as non-hidden value', async () => { @@ -463,9 +463,9 @@ describe('ModelLoadBalancingModal', () => { await waitFor(() => { expect(mockMutateAsync).toHaveBeenCalled() - const payload = mockMutateAsync.mock.calls[0][0] as { load_balancing: { configs: Array<{ credentials: { api_key: string } }> } } + const payload = mockMutateAsync.mock.calls[0]![0] as { load_balancing: { configs: Array<{ credentials: { api_key: string } }> } } // Entry without id should NOT be encoded as hidden - expect(payload.load_balancing.configs[0].credentials.api_key).toBe('new-key') + expect(payload.load_balancing.configs[0]!.credentials.api_key).toBe('new-key') }) }) @@ -536,7 +536,7 @@ describe('ModelLoadBalancingModal', () => { await waitFor(() => { expect(mockMutateAsync).toHaveBeenCalled() // The payload configs should only have the original 2 entries (no new one added) - const payload = mockMutateAsync.mock.calls[0][0] as { load_balancing: { configs: unknown[] } } + const payload = mockMutateAsync.mock.calls[0]![0] as { load_balancing: { configs: unknown[] } } expect(payload.load_balancing.configs).toHaveLength(2) }) }) @@ -552,14 +552,16 @@ describe('ModelLoadBalancingModal', () => { ) // draftConfig.enabled=true → title shows configLoadBalancing - expect(screen.getByText(/modelProvider\.auth\.configLoadBalancing/)).toBeInTheDocument() + // draftConfig.enabled=true → title shows configLoadBalancing + expect(screen.getByText(/modelProvider\.auth\.configLoadBalancing/))!.toBeInTheDocument() // Clicking the card when enabled=true toggles to disabled const card = screen.getByText(/modelProvider\.auth\.providerManaged$/).closest('div[class]')!.closest('div[class]')! await user.click(card) // After toggling, title should show configModel (disabled state) - expect(screen.getByText(/modelProvider\.auth\.configModel/)).toBeInTheDocument() + // After toggling, title should show configModel (disabled state) + expect(screen.getByText(/modelProvider\.auth\.configModel/))!.toBeInTheDocument() }) it('should use customModelCredential credential_id when present in handleSave', async () => { @@ -589,7 +591,7 @@ describe('ModelLoadBalancingModal', () => { await waitFor(() => { expect(mockMutateAsync).toHaveBeenCalled() - const payload = mockMutateAsync.mock.calls[0][0] as { credential_id: string } + const payload = mockMutateAsync.mock.calls[0]![0] as { credential_id: string } // credential_id should come from customModelCredential expect(payload.credential_id).toBe('cred-1') }) @@ -665,7 +667,8 @@ describe('ModelLoadBalancingModal', () => { ) // Assert: component renders without error (extendedSecretFormSchemas = []) - expect(screen.getByText(/modelProvider\.auth\.configLoadBalancing/)).toBeInTheDocument() + // Assert: component renders without error (extendedSecretFormSchemas = []) + expect(screen.getByText(/modelProvider\.auth\.configLoadBalancing/))!.toBeInTheDocument() }) it('should use custom model credential schema without fallback when credential_form_schemas is undefined', () => { @@ -727,7 +730,7 @@ describe('ModelLoadBalancingModal', () => { await waitFor(() => { expect(mockMutateAsync).toHaveBeenCalled() - const payload = mockMutateAsync.mock.calls[0][0] as { load_balancing: { configs: unknown[] } } + const payload = mockMutateAsync.mock.calls[0]![0] as { load_balancing: { configs: unknown[] } } // Config count unchanged (still 2 from original) expect(payload.load_balancing.configs).toHaveLength(2) }) diff --git a/web/app/components/header/account-setting/model-provider-page/provider-added-card/model-auth-dropdown/__tests__/usage-priority-section.spec.tsx b/web/app/components/header/account-setting/model-provider-page/provider-added-card/model-auth-dropdown/__tests__/usage-priority-section.spec.tsx index 20ef9cf066..c400d05f22 100644 --- a/web/app/components/header/account-setting/model-provider-page/provider-added-card/model-auth-dropdown/__tests__/usage-priority-section.spec.tsx +++ b/web/app/components/header/account-setting/model-provider-page/provider-added-card/model-auth-dropdown/__tests__/usage-priority-section.spec.tsx @@ -14,7 +14,7 @@ describe('UsagePrioritySection', () => { it('should render title and both option buttons', () => { render() - expect(screen.getByText(/usagePriority/)).toBeInTheDocument() + expect(screen.getByText(/usagePriority/))!.toBeInTheDocument() expect(screen.getAllByRole('button')).toHaveLength(2) }) }) @@ -25,23 +25,23 @@ describe('UsagePrioritySection', () => { render() const buttons = screen.getAllByRole('button') - expect(buttons[0].className).toContain('border-components-option-card-option-selected-border') - expect(buttons[1].className).not.toContain('border-components-option-card-option-selected-border') + expect(buttons[0]!.className).toContain('border-components-option-card-option-selected-border') + expect(buttons[1]!.className).not.toContain('border-components-option-card-option-selected-border') }) it('should highlight API key option when value is apiKey', () => { render() const buttons = screen.getAllByRole('button') - expect(buttons[0].className).not.toContain('border-components-option-card-option-selected-border') - expect(buttons[1].className).toContain('border-components-option-card-option-selected-border') + expect(buttons[0]!.className).not.toContain('border-components-option-card-option-selected-border') + expect(buttons[1]!.className).toContain('border-components-option-card-option-selected-border') }) it('should highlight API key option when value is apiKeyOnly', () => { render() const buttons = screen.getAllByRole('button') - expect(buttons[1].className).toContain('border-components-option-card-option-selected-border') + expect(buttons[1]!.className).toContain('border-components-option-card-option-selected-border') }) }) @@ -50,7 +50,7 @@ describe('UsagePrioritySection', () => { it('should call onSelect with system when clicking AI credits option', () => { render() - fireEvent.click(screen.getAllByRole('button')[0]) + fireEvent.click(screen.getAllByRole('button')[0]!) expect(onSelect).toHaveBeenCalledWith(PreferredProviderTypeEnum.system) }) @@ -58,7 +58,7 @@ describe('UsagePrioritySection', () => { it('should call onSelect with custom when clicking API key option', () => { render() - fireEvent.click(screen.getAllByRole('button')[1]) + fireEvent.click(screen.getAllByRole('button')[1]!) expect(onSelect).toHaveBeenCalledWith(PreferredProviderTypeEnum.custom) }) diff --git a/web/app/components/header/account-setting/model-provider-page/provider-added-card/model-auth-dropdown/__tests__/use-activate-credential.spec.tsx b/web/app/components/header/account-setting/model-provider-page/provider-added-card/model-auth-dropdown/__tests__/use-activate-credential.spec.tsx index c38d783e73..12acf479c0 100644 --- a/web/app/components/header/account-setting/model-provider-page/provider-added-card/model-auth-dropdown/__tests__/use-activate-credential.spec.tsx +++ b/web/app/components/header/account-setting/model-provider-page/provider-added-card/model-auth-dropdown/__tests__/use-activate-credential.spec.tsx @@ -92,7 +92,7 @@ describe('useActivateCredential', () => { }), ) - const [, callbacks] = mockMutate.mock.calls[0] + const [, callbacks] = (mockMutate.mock.calls[0] ?? []) as [unknown, any] act(() => { callbacks.onSuccess() @@ -113,7 +113,7 @@ describe('useActivateCredential', () => { expect(result.current.selectedCredentialId).toBe('cred-2') - const [, callbacks] = mockMutate.mock.calls[0] + const [, callbacks] = (mockMutate.mock.calls[0] ?? []) as [unknown, any] act(() => { callbacks.onError() diff --git a/web/app/components/header/account-setting/model-provider-page/provider-added-card/model-load-balancing-configs.tsx b/web/app/components/header/account-setting/model-provider-page/provider-added-card/model-load-balancing-configs.tsx index 7fd1618d64..ea4edace30 100644 --- a/web/app/components/header/account-setting/model-provider-page/provider-added-card/model-load-balancing-configs.tsx +++ b/web/app/components/header/account-setting/model-provider-page/provider-added-card/model-load-balancing-configs.tsx @@ -64,7 +64,7 @@ const ModelLoadBalancingConfigs = ({ if (!prev) return prev const newConfigs = [...prev.configs] - const modifiedConfig = modifier(newConfigs[index]) + const modifiedConfig = modifier(newConfigs[index]!) if (modifiedConfig) newConfigs[index] = modifiedConfig else diff --git a/web/app/components/header/account-setting/model-provider-page/provider-added-card/model-load-balancing-modal.tsx b/web/app/components/header/account-setting/model-provider-page/provider-added-card/model-load-balancing-modal.tsx index 3556777395..652630be67 100644 --- a/web/app/components/header/account-setting/model-provider-page/provider-added-card/model-load-balancing-modal.tsx +++ b/web/app/components/header/account-setting/model-provider-page/provider-added-card/model-load-balancing-modal.tsx @@ -164,7 +164,7 @@ const ModelLoadBalancingModal = ({ provider, configurateMethod, currentCustomCon const prevIndex = newConfigs.findIndex(item => item.credential_id === modelCredential.credential_id && item.name !== '__inherit__') const newIndex = available_credentials.findIndex(c => c.credential_id === modelCredential.credential_id) if (newIndex > -1 && prevIndex > -1) - newConfigs[prevIndex].name = available_credentials[newIndex].credential_name || '' + newConfigs[prevIndex]!.name = available_credentials[newIndex]!.credential_name || '' return { ...prev, configs: newConfigs, diff --git a/web/app/components/header/account-setting/plugin-page/index.tsx b/web/app/components/header/account-setting/plugin-page/index.tsx index a71c3ee072..7f8e9a32f7 100644 --- a/web/app/components/header/account-setting/plugin-page/index.tsx +++ b/web/app/components/header/account-setting/plugin-page/index.tsx @@ -16,7 +16,7 @@ const PluginPage = () => { return (
- {plugins?.map(plugin => Plugin_MAP[plugin.tool_name](plugin))} + {plugins?.map(plugin => Plugin_MAP[plugin.tool_name]!(plugin))}
diff --git a/web/app/components/header/app-nav/index.tsx b/web/app/components/header/app-nav/index.tsx index 54ddf75711..2e7a77a891 100644 --- a/web/app/components/header/app-nav/index.tsx +++ b/web/app/components/header/app-nav/index.tsx @@ -93,7 +93,7 @@ const AppNav = () => { const newNavItems = produce(navItems, (draft: NavItem[]) => { navItems.forEach((app, index) => { if (app.id === appDetail.id) - draft[index].name = appDetail.name + draft[index]!.name = appDetail.name }) }) setNavItems(newNavItems) diff --git a/web/app/components/header/app-selector/__tests__/index.spec.tsx b/web/app/components/header/app-selector/__tests__/index.spec.tsx index eddb7e52aa..2d255c006e 100644 --- a/web/app/components/header/app-selector/__tests__/index.spec.tsx +++ b/web/app/components/header/app-selector/__tests__/index.spec.tsx @@ -32,7 +32,7 @@ describe('AppSelector Component', () => { { id: '1', name: 'App 1' }, { id: '2', name: 'App 2' }, ] as unknown as AppDetailResponse[] - const mockCurApp = mockAppItems[0] + const mockCurApp = mockAppItems[0]! beforeEach(() => { vi.clearAllMocks() @@ -47,7 +47,7 @@ describe('AppSelector Component', () => { describe('Rendering', () => { it('should render current app name', () => { render() - expect(screen.getByText('App 1')).toBeInTheDocument() + expect(screen.getByText('App 1'))!.toBeInTheDocument() }) }) @@ -60,7 +60,7 @@ describe('AppSelector Component', () => { fireEvent.click(button) }) - expect(screen.getByText('App 2')).toBeInTheDocument() + expect(screen.getByText('App 2'))!.toBeInTheDocument() }) it('should navigate to configuration when an app is clicked and user is editor', async () => { @@ -114,7 +114,7 @@ describe('AppSelector Component', () => { fireEvent.click(newAppBtn) }) - expect(screen.getByTestId('create-app-dialog')).toBeInTheDocument() + expect(screen.getByTestId('create-app-dialog'))!.toBeInTheDocument() }) it('should not show "New App" button for non-editor', async () => { @@ -165,7 +165,8 @@ describe('AppSelector Component', () => { expect(screen.queryByText('App 2')).not.toBeInTheDocument() // "New App" should still be there if editor - expect(screen.getByText('common.menus.newApp')).toBeInTheDocument() + // "New App" should still be there if editor + expect(screen.getByText('common.menus.newApp'))!.toBeInTheDocument() }) }) }) diff --git a/web/app/components/header/nav/nav-selector/__tests__/index.spec.tsx b/web/app/components/header/nav/nav-selector/__tests__/index.spec.tsx index 152901b79c..97443bb759 100644 --- a/web/app/components/header/nav/nav-selector/__tests__/index.spec.tsx +++ b/web/app/components/header/nav/nav-selector/__tests__/index.spec.tsx @@ -105,7 +105,7 @@ describe('NavSelector Component', () => { }, ] - const { link: _link, ...curNavWithoutLink } = navigationItems[0] + const { link: _link, ...curNavWithoutLink } = navigationItems[0]! const defaultProps: INavSelectorProps = { curNav: curNavWithoutLink, @@ -131,7 +131,7 @@ describe('NavSelector Component', () => { describe('Rendering', () => { it('should render current nav name', () => { render() - expect(screen.getByText('Item 1')).toBeInTheDocument() + expect(screen.getByText('Item 1'))!.toBeInTheDocument() }) it('should show loading indicator when isLoadingMore is true', async () => { @@ -140,7 +140,7 @@ describe('NavSelector Component', () => { await act(async () => { fireEvent.click(button) }) - expect(screen.getByRole('status')).toBeInTheDocument() + expect(screen.getByRole('status'))!.toBeInTheDocument() }) }) @@ -151,7 +151,7 @@ describe('NavSelector Component', () => { await act(async () => { fireEvent.click(button) }) - expect(screen.getByText('Item 2')).toBeInTheDocument() + expect(screen.getByText('Item 2'))!.toBeInTheDocument() }) it('should navigate and call setAppDetail when an item is clicked', async () => { diff --git a/web/app/components/plugins/__tests__/hooks.spec.ts b/web/app/components/plugins/__tests__/hooks.spec.ts index b12121d626..1e4f18ec5d 100644 --- a/web/app/components/plugins/__tests__/hooks.spec.ts +++ b/web/app/components/plugins/__tests__/hooks.spec.ts @@ -86,15 +86,15 @@ describe('useCategories', () => { it('should use plural labels by default', () => { const { result } = renderHook(() => useCategories()) - expect(result.current.categoriesMap.tool.label).toBe('plugin.category.tools') - expect(result.current.categoriesMap['agent-strategy'].label).toBe('plugin.category.agents') + expect(result.current.categoriesMap.tool!.label).toBe('plugin.category.tools') + expect(result.current.categoriesMap['agent-strategy']!.label).toBe('plugin.category.agents') }) it('should use singular labels when isSingle is true', () => { const { result } = renderHook(() => useCategories(true)) - expect(result.current.categoriesMap.tool.label).toBe('plugin.categorySingle.tool') - expect(result.current.categoriesMap['agent-strategy'].label).toBe('plugin.categorySingle.agent') + expect(result.current.categoriesMap.tool!.label).toBe('plugin.categorySingle.tool') + expect(result.current.categoriesMap['agent-strategy']!.label).toBe('plugin.categorySingle.agent') }) }) diff --git a/web/app/components/plugins/card/index.tsx b/web/app/components/plugins/card/index.tsx index 9f9b89cbbf..dd7f92184d 100644 --- a/web/app/components/plugins/card/index.tsx +++ b/web/app/components/plugins/card/index.tsx @@ -77,7 +77,7 @@ const Card = ({ return (
- {!hideCornerMark && } + {!hideCornerMark && } {/* Header */}
diff --git a/web/app/components/plugins/install-plugin/hooks.ts b/web/app/components/plugins/install-plugin/hooks.ts index f86e6ad672..4759953e30 100644 --- a/web/app/components/plugins/install-plugin/hooks.ts +++ b/web/app/components/plugins/install-plugin/hooks.ts @@ -52,7 +52,7 @@ export const checkForUpdates = (fetchedReleases: GitHubRepoReleaseResponse[], cu const versions = fetchedReleases.map(release => release.tag_name) const latestVersion = getLatestVersion(versions) try { - needUpdate = compareVersion(latestVersion, currentVersion) === 1 + needUpdate = compareVersion(latestVersion!, currentVersion) === 1 if (needUpdate) toastProps.message = `New version available: ${latestVersion}` } diff --git a/web/app/components/plugins/install-plugin/install-bundle/steps/__tests__/install-multi.spec.tsx b/web/app/components/plugins/install-plugin/install-bundle/steps/__tests__/install-multi.spec.tsx index 4507c1295b..d45b05bfd1 100644 --- a/web/app/components/plugins/install-plugin/install-bundle/steps/__tests__/install-multi.spec.tsx +++ b/web/app/components/plugins/install-plugin/install-bundle/steps/__tests__/install-multi.spec.tsx @@ -260,14 +260,14 @@ describe('InstallMulti Component', () => { it('should render without crashing', () => { render() - expect(screen.getByTestId('package-item')).toBeInTheDocument() + expect(screen.getByTestId('package-item'))!.toBeInTheDocument() }) it('should render PackageItem for package type dependency', () => { render() - expect(screen.getByTestId('package-item')).toBeInTheDocument() - expect(screen.getByTestId('package-item-name')).toHaveTextContent('Package Plugin 0') + expect(screen.getByTestId('package-item'))!.toBeInTheDocument() + expect(screen.getByTestId('package-item-name'))!.toHaveTextContent('Package Plugin 0') }) it('should render GithubItem for github type dependency', async () => { @@ -279,9 +279,9 @@ describe('InstallMulti Component', () => { render() await waitFor(() => { - expect(screen.getByTestId('github-item')).toBeInTheDocument() + expect(screen.getByTestId('github-item'))!.toBeInTheDocument() }) - expect(screen.getByTestId('github-item-repo')).toHaveTextContent('test-org/plugin-0') + expect(screen.getByTestId('github-item-repo'))!.toHaveTextContent('test-org/plugin-0') }) it('should render MarketplaceItem for marketplace type dependency', async () => { @@ -293,7 +293,7 @@ describe('InstallMulti Component', () => { render() await waitFor(() => { - expect(screen.getByTestId('marketplace-item')).toBeInTheDocument() + expect(screen.getByTestId('marketplace-item'))!.toBeInTheDocument() }) }) @@ -309,8 +309,8 @@ describe('InstallMulti Component', () => { render() await waitFor(() => { - expect(screen.getByTestId('package-item')).toBeInTheDocument() - expect(screen.getByTestId('github-item')).toBeInTheDocument() + expect(screen.getByTestId('package-item'))!.toBeInTheDocument() + expect(screen.getByTestId('github-item'))!.toBeInTheDocument() }) }) @@ -328,7 +328,7 @@ describe('InstallMulti Component', () => { render() await waitFor(() => { - expect(screen.queryByTestId('github-item')).toBeInTheDocument() + expect(screen.queryByTestId('github-item'))!.toBeInTheDocument() }) }) }) @@ -355,13 +355,13 @@ describe('InstallMulti Component', () => { render() - expect(screen.getByTestId('package-item-checked')).toHaveTextContent('checked') + expect(screen.getByTestId('package-item-checked'))!.toHaveTextContent('checked') }) it('should show unchecked state when plugin is not selected', () => { render() - expect(screen.getByTestId('package-item-checked')).toHaveTextContent('unchecked') + expect(screen.getByTestId('package-item-checked'))!.toHaveTextContent('unchecked') }) }) @@ -427,7 +427,7 @@ describe('InstallMulti Component', () => { // The getVersionInfo function returns hasInstalled, installedVersion, toInstallVersion // These are passed to child components await waitFor(() => { - expect(screen.getByTestId('package-item')).toBeInTheDocument() + expect(screen.getByTestId('package-item'))!.toBeInTheDocument() }) }) }) @@ -443,7 +443,7 @@ describe('InstallMulti Component', () => { render() await waitFor(() => { - expect(screen.getByTestId('github-item')).toBeInTheDocument() + expect(screen.getByTestId('github-item'))!.toBeInTheDocument() }) // The onFetchedPayload callback should have been called by the mock @@ -462,7 +462,7 @@ describe('InstallMulti Component', () => { render() await waitFor(() => { - expect(screen.getByTestId('marketplace-item')).toBeInTheDocument() + expect(screen.getByTestId('marketplace-item'))!.toBeInTheDocument() }) }) }) @@ -485,7 +485,7 @@ describe('InstallMulti Component', () => { render() await waitFor(() => { - expect(screen.getByTestId('package-item')).toBeInTheDocument() + expect(screen.getByTestId('package-item'))!.toBeInTheDocument() }) }) @@ -498,7 +498,7 @@ describe('InstallMulti Component', () => { render() await waitFor(() => { - expect(screen.getByTestId('package-item')).toBeInTheDocument() + expect(screen.getByTestId('package-item'))!.toBeInTheDocument() }) }) }) @@ -509,7 +509,8 @@ describe('InstallMulti Component', () => { render() // Package plugins are initialized immediately - expect(screen.getByTestId('package-item')).toBeInTheDocument() + // Package plugins are initialized immediately + expect(screen.getByTestId('package-item'))!.toBeInTheDocument() }) it('should update plugins when GitHub plugin is fetched', async () => { @@ -521,7 +522,7 @@ describe('InstallMulti Component', () => { render() await waitFor(() => { - expect(screen.getByTestId('github-item')).toBeInTheDocument() + expect(screen.getByTestId('github-item'))!.toBeInTheDocument() }) }) }) @@ -553,7 +554,7 @@ describe('InstallMulti Component', () => { render() await waitFor(() => { - expect(screen.getByTestId('package-item')).toBeInTheDocument() + expect(screen.getByTestId('package-item'))!.toBeInTheDocument() }) }) @@ -613,11 +614,12 @@ describe('InstallMulti Component', () => { render() await waitFor(() => { - expect(screen.getByTestId('marketplace-item')).toBeInTheDocument() + expect(screen.getByTestId('marketplace-item'))!.toBeInTheDocument() }) // Version should be displayed - expect(screen.getByTestId('marketplace-item-version')).toBeInTheDocument() + // Version should be displayed + expect(screen.getByTestId('marketplace-item-version'))!.toBeInTheDocument() }) }) @@ -706,7 +708,8 @@ describe('InstallMulti Component', () => { await waitFor(() => { // Component should render - expect(document.body).toBeInTheDocument() + // Component should render + expect(document.body)!.toBeInTheDocument() }) }) }) @@ -717,7 +720,7 @@ describe('InstallMulti Component', () => { render() await waitFor(() => { - expect(screen.getByTestId('package-item')).toBeInTheDocument() + expect(screen.getByTestId('package-item'))!.toBeInTheDocument() }) // The getVersionInfo callback should return correct structure @@ -738,10 +741,10 @@ describe('InstallMulti Component', () => { render() await waitFor(() => { - expect(screen.getByTestId('github-item')).toBeInTheDocument() + expect(screen.getByTestId('github-item'))!.toBeInTheDocument() }) - expect(screen.getByTestId('github-item-checked')).toHaveTextContent('checked') + expect(screen.getByTestId('github-item-checked'))!.toHaveTextContent('checked') }) it('should show checked state for marketplace item when selected', async () => { @@ -755,7 +758,7 @@ describe('InstallMulti Component', () => { render() await waitFor(() => { - expect(screen.getByTestId('marketplace-item')).toBeInTheDocument() + expect(screen.getByTestId('marketplace-item'))!.toBeInTheDocument() }) // The checked prop should be passed to the item @@ -771,10 +774,10 @@ describe('InstallMulti Component', () => { render() await waitFor(() => { - expect(screen.getByTestId('github-item')).toBeInTheDocument() + expect(screen.getByTestId('github-item'))!.toBeInTheDocument() }) - expect(screen.getByTestId('github-item-checked')).toHaveTextContent('unchecked') + expect(screen.getByTestId('github-item-checked'))!.toHaveTextContent('unchecked') }) }) @@ -823,7 +826,7 @@ describe('InstallMulti Component', () => { const packageItems = screen.getAllByTestId('package-item') await act(async () => { - fireEvent.click(packageItems[0]) + fireEvent.click(packageItems[0]!) }) // onSelect should be called with filtered plugin count @@ -842,11 +845,12 @@ describe('InstallMulti Component', () => { render() await waitFor(() => { - expect(screen.getByTestId('marketplace-item')).toBeInTheDocument() + expect(screen.getByTestId('marketplace-item'))!.toBeInTheDocument() }) // The version should be displayed (from dependency or plugin) - expect(screen.getByTestId('marketplace-item-version')).toBeInTheDocument() + // The version should be displayed (from dependency or plugin) + expect(screen.getByTestId('marketplace-item-version'))!.toBeInTheDocument() }) }) @@ -856,7 +860,7 @@ describe('InstallMulti Component', () => { render() await waitFor(() => { - expect(screen.getByTestId('package-item')).toBeInTheDocument() + expect(screen.getByTestId('package-item'))!.toBeInTheDocument() }) // The component should pass versionInfo to items @@ -868,7 +872,7 @@ describe('InstallMulti Component', () => { render() await waitFor(() => { - expect(screen.getByTestId('package-item')).toBeInTheDocument() + expect(screen.getByTestId('package-item'))!.toBeInTheDocument() expect(defaultProps.onLoadedAllPlugin).toHaveBeenCalled() }) }) diff --git a/web/app/components/plugins/install-plugin/install-bundle/steps/hooks/use-install-multi-state.ts b/web/app/components/plugins/install-plugin/install-bundle/steps/hooks/use-install-multi-state.ts index 86dd287c99..ca06f33c16 100644 --- a/web/app/components/plugins/install-plugin/install-bundle/steps/hooks/use-install-multi-state.ts +++ b/web/app/components/plugins/install-plugin/install-bundle/steps/hooks/use-install-multi-state.ts @@ -35,7 +35,7 @@ function parseMarketplaceIdentifier(identifier?: string): MarketplacePluginInfo return null const withoutHash = identifier.split('@')[0] - const [organization, nameAndVersionPart] = withoutHash.split('/') + const [organization, nameAndVersionPart] = withoutHash!.split('/') if (!organization || !nameAndVersionPart) return null diff --git a/web/app/components/plugins/install-plugin/install-bundle/steps/install.tsx b/web/app/components/plugins/install-plugin/install-bundle/steps/install.tsx index 9eb4db7a27..df94331d58 100644 --- a/web/app/components/plugins/install-plugin/install-bundle/steps/install.tsx +++ b/web/app/components/plugins/install-plugin/install-bundle/steps/install.tsx @@ -83,7 +83,7 @@ const Install: FC = ({ onInstalled(selectedPlugins, res.map((r, i) => { return ({ success: r.status === TaskStatus.success, - isFromMarketPlace: allPlugins[selectedIndexes[i]].type === 'marketplace', + isFromMarketPlace: allPlugins[selectedIndexes[i]!]!.type === 'marketplace', }) })) const hasInstallSuccess = res.some(r => r.status === TaskStatus.success) @@ -101,7 +101,7 @@ const Install: FC = ({ if (item.status !== TaskStatus.running) { return { success: item.status === TaskStatus.success, - isFromMarketPlace: allPlugins[selectedIndexes[index]].type === 'marketplace', + isFromMarketPlace: allPlugins[selectedIndexes[index]!]!.type === 'marketplace', } } const { status } = await check({ @@ -110,7 +110,7 @@ const Install: FC = ({ }) return { success: status === TaskStatus.success, - isFromMarketPlace: allPlugins[selectedIndexes[index]].type === 'marketplace', + isFromMarketPlace: allPlugins[selectedIndexes[index]!]!.type === 'marketplace', } })) onInstalled(selectedPlugins, installStatus) diff --git a/web/app/components/plugins/install-plugin/install-bundle/steps/installed.tsx b/web/app/components/plugins/install-plugin/install-bundle/steps/installed.tsx index a7808736e9..1c64e73d62 100644 --- a/web/app/components/plugins/install-plugin/install-bundle/steps/installed.tsx +++ b/web/app/components/plugins/install-plugin/install-bundle/steps/installed.tsx @@ -36,10 +36,10 @@ const Installed: FC = ({ className="w-full" payload={{ ...plugin, - icon: installStatus[index].isFromMarketPlace ? `${MARKETPLACE_API_PREFIX}/plugins/${plugin.org}/${plugin.name}/icon` : getIconUrl(plugin.icon), + icon: installStatus[index]!.isFromMarketPlace ? `${MARKETPLACE_API_PREFIX}/plugins/${plugin.org}/${plugin.name}/icon` : getIconUrl(plugin.icon), }} - installed={installStatus[index].success} - installFailed={!installStatus[index].success} + installed={installStatus[index]!.success} + installFailed={!installStatus[index]!.success} titleLeft={plugin.version ? {plugin.version} : null} /> ) diff --git a/web/app/components/plugins/marketplace/__tests__/query.spec.tsx b/web/app/components/plugins/marketplace/__tests__/query.spec.tsx index 80d8e6a932..5353cdba91 100644 --- a/web/app/components/plugins/marketplace/__tests__/query.spec.tsx +++ b/web/app/components/plugins/marketplace/__tests__/query.spec.tsx @@ -143,7 +143,7 @@ describe('useMarketplacePlugins', () => { }) expect(result.current.data?.pages).toHaveLength(1) - expect(result.current.data?.pages[0].plugins).toHaveLength(1) + expect(result.current.data?.pages[0]!.plugins).toHaveLength(1) }) it('should handle bundle type in query params', async () => { @@ -185,8 +185,8 @@ describe('useMarketplacePlugins', () => { expect(result.current.data).toBeDefined() }) - expect(result.current.data?.pages[0].plugins).toEqual([]) - expect(result.current.data?.pages[0].total).toBe(0) + expect(result.current.data?.pages[0]!.plugins).toEqual([]) + expect(result.current.data?.pages[0]!.total).toBe(0) }) it('should determine next page correctly via getNextPageParam', async () => { diff --git a/web/app/components/plugins/marketplace/__tests__/utils.spec.ts b/web/app/components/plugins/marketplace/__tests__/utils.spec.ts index 92bed9be62..972a9ba913 100644 --- a/web/app/components/plugins/marketplace/__tests__/utils.spec.ts +++ b/web/app/components/plugins/marketplace/__tests__/utils.spec.ts @@ -264,7 +264,7 @@ describe('getMarketplacePluginsByCollectionId', () => { expect(mockCollectionPlugins).toHaveBeenCalled() const call = mockCollectionPlugins.mock.calls[0] - expect(call[1]).toMatchObject({ signal: controller.signal }) + expect(call![1]).toMatchObject({ signal: controller.signal }) }) }) @@ -313,7 +313,7 @@ describe('getMarketplaceCollectionsAndPlugins', () => { expect(mockCollections).toHaveBeenCalled() const call = mockCollections.mock.calls[0] - expect(call[0]).toMatchObject({ query: expect.objectContaining({ condition: 'category=tool', type: 'bundle' }) }) + expect(call![0]).toMatchObject({ query: expect.objectContaining({ condition: 'category=tool', type: 'bundle' }) }) }) }) @@ -393,7 +393,7 @@ describe('getMarketplacePlugins', () => { expect(result.plugins).toHaveLength(1) const call = mockSearchAdvanced.mock.calls[0] - expect(call[0].params.kind).toBe('bundles') + expect(call![0].params.kind).toBe('bundles') }) it('should use empty category when category is all', async () => { @@ -408,7 +408,7 @@ describe('getMarketplacePlugins', () => { }, 1) const call = mockSearchAdvanced.mock.calls[0] - expect(call[0].body.category).toBe('') + expect(call![0].body.category).toBe('') }) it('should handle API error and return empty result', async () => { @@ -437,7 +437,7 @@ describe('getMarketplacePlugins', () => { await getMarketplacePlugins({ query: 'test' }, 1, controller.signal) const call = mockSearchAdvanced.mock.calls[0] - expect(call[1]).toMatchObject({ signal: controller.signal }) + expect(call![1]).toMatchObject({ signal: controller.signal }) }) it('should default page_size to 40 when not provided', async () => { diff --git a/web/app/components/plugins/marketplace/list/list-with-collection.tsx b/web/app/components/plugins/marketplace/list/list-with-collection.tsx index 21094f39a5..744885ae09 100644 --- a/web/app/components/plugins/marketplace/list/list-with-collection.tsx +++ b/web/app/components/plugins/marketplace/list/list-with-collection.tsx @@ -60,7 +60,7 @@ const ListWithCollection = ({ )} > { - marketplaceCollectionPluginsMap[collection.name].map((plugin) => { + marketplaceCollectionPluginsMap[collection.name]!.map((plugin) => { if (cardRender) return cardRender(plugin) diff --git a/web/app/components/plugins/marketplace/search-box/__tests__/index.spec.tsx b/web/app/components/plugins/marketplace/search-box/__tests__/index.spec.tsx index 31cb5d8445..8609ba5539 100644 --- a/web/app/components/plugins/marketplace/search-box/__tests__/index.spec.tsx +++ b/web/app/components/plugins/marketplace/search-box/__tests__/index.spec.tsx @@ -124,7 +124,7 @@ describe('SearchBox', () => { it('should render without crashing', () => { render() - expect(screen.getByRole('textbox')).toBeInTheDocument() + expect(screen.getByRole('textbox'))!.toBeInTheDocument() }) it('should render with marketplace mode styling', () => { @@ -133,7 +133,8 @@ describe('SearchBox', () => { ) // In marketplace mode, TagsFilter comes before input - expect(container.querySelector('.rounded-xl')).toBeInTheDocument() + // In marketplace mode, TagsFilter comes before input + expect(container.querySelector('.rounded-xl'))!.toBeInTheDocument() }) it('should render with non-marketplace mode styling', () => { @@ -142,25 +143,26 @@ describe('SearchBox', () => { ) // In non-marketplace mode, search icon appears first - expect(container.querySelector('.rounded-lg')).toBeInTheDocument() + // In non-marketplace mode, search icon appears first + expect(container.querySelector('.rounded-lg'))!.toBeInTheDocument() }) it('should render placeholder correctly', () => { render() - expect(screen.getByPlaceholderText('Search here...')).toBeInTheDocument() + expect(screen.getByPlaceholderText('Search here...'))!.toBeInTheDocument() }) it('should render search input with current value', () => { render() - expect(screen.getByDisplayValue('test query')).toBeInTheDocument() + expect(screen.getByDisplayValue('test query'))!.toBeInTheDocument() }) it('should render TagsFilter component', () => { render() - expect(screen.getByTestId('portal-elem')).toBeInTheDocument() + expect(screen.getByTestId('portal-elem'))!.toBeInTheDocument() }) }) @@ -175,8 +177,9 @@ describe('SearchBox', () => { const input = screen.getByRole('textbox') // Both should be rendered - expect(portalElem).toBeInTheDocument() - expect(input).toBeInTheDocument() + // Both should be rendered + expect(portalElem)!.toBeInTheDocument() + expect(input)!.toBeInTheDocument() }) it('should render clear button when search has value in marketplace mode', () => { @@ -207,7 +210,8 @@ describe('SearchBox', () => { ) // Search icon should be present - expect(container.querySelector('.text-components-input-text-placeholder')).toBeInTheDocument() + // Search icon should be present + expect(container.querySelector('.text-components-input-text-placeholder'))!.toBeInTheDocument() }) it('should render clear button when search has value', () => { @@ -223,8 +227,8 @@ describe('SearchBox', () => { const portalElem = screen.getByTestId('portal-elem') const input = screen.getByRole('textbox') - expect(portalElem).toBeInTheDocument() - expect(input).toBeInTheDocument() + expect(portalElem)!.toBeInTheDocument() + expect(input)!.toBeInTheDocument() }) it('should set autoFocus when prop is true', () => { @@ -232,7 +236,8 @@ describe('SearchBox', () => { const input = screen.getByRole('textbox') // autoFocus is a boolean attribute that React handles specially - expect(input).toBeInTheDocument() + // autoFocus is a boolean attribute that React handles specially + expect(input)!.toBeInTheDocument() }) }) @@ -264,7 +269,7 @@ describe('SearchBox', () => { const buttons = screen.getAllByRole('button') // Find the clear button (the one in the search area) const clearButton = buttons[buttons.length - 1] - fireEvent.click(clearButton) + fireEvent.click(clearButton!) expect(onSearchChange).toHaveBeenCalledWith('') }) @@ -282,7 +287,7 @@ describe('SearchBox', () => { const buttons = screen.getAllByRole('button') // First button should be the clear button in non-marketplace mode - fireEvent.click(buttons[0]) + fireEvent.click(buttons[0]!) expect(onSearchChange).toHaveBeenCalledWith('') }) @@ -356,7 +361,7 @@ describe('SearchBox', () => { , ) - expect(container.querySelector('.custom-wrapper-class')).toBeInTheDocument() + expect(container.querySelector('.custom-wrapper-class'))!.toBeInTheDocument() }) it('should apply inputClassName correctly', () => { @@ -364,19 +369,19 @@ describe('SearchBox', () => { , ) - expect(container.querySelector('.custom-input-class')).toBeInTheDocument() + expect(container.querySelector('.custom-input-class'))!.toBeInTheDocument() }) it('should handle empty placeholder', () => { render() - expect(screen.getByRole('textbox')).toHaveAttribute('placeholder', '') + expect(screen.getByRole('textbox'))!.toHaveAttribute('placeholder', '') }) it('should use default placeholder when not provided', () => { render() - expect(screen.getByRole('textbox')).toHaveAttribute('placeholder', '') + expect(screen.getByRole('textbox'))!.toHaveAttribute('placeholder', '') }) }) @@ -387,14 +392,14 @@ describe('SearchBox', () => { it('should handle empty search value', () => { render() - expect(screen.getByRole('textbox')).toBeInTheDocument() - expect(screen.getByRole('textbox')).toHaveValue('') + expect(screen.getByRole('textbox'))!.toBeInTheDocument() + expect(screen.getByRole('textbox'))!.toHaveValue('') }) it('should handle empty tags array', () => { render() - expect(screen.getByTestId('portal-elem')).toBeInTheDocument() + expect(screen.getByTestId('portal-elem'))!.toBeInTheDocument() }) it('should handle special characters in search', () => { @@ -411,7 +416,7 @@ describe('SearchBox', () => { const longString = 'a'.repeat(1000) render() - expect(screen.getByDisplayValue(longString)).toBeInTheDocument() + expect(screen.getByDisplayValue(longString))!.toBeInTheDocument() }) it('should handle whitespace-only search', () => { @@ -439,20 +444,21 @@ describe('SearchBoxWrapper', () => { it('should render without crashing', () => { render() - expect(screen.getByRole('textbox')).toBeInTheDocument() + expect(screen.getByRole('textbox'))!.toBeInTheDocument() }) it('should render in marketplace mode', () => { const { container } = render() - expect(container.querySelector('.rounded-xl')).toBeInTheDocument() + expect(container.querySelector('.rounded-xl'))!.toBeInTheDocument() }) it('should apply correct wrapper classes', () => { const { container } = render() // Check for z-11 class from wrapper - expect(container.querySelector('.z-11')).toBeInTheDocument() + // Check for z-11 class from wrapper + expect(container.querySelector('.z-11'))!.toBeInTheDocument() }) }) @@ -471,7 +477,7 @@ describe('SearchBoxWrapper', () => { it('should use translation for placeholder', () => { render() - expect(screen.getByPlaceholderText('Search plugins')).toBeInTheDocument() + expect(screen.getByPlaceholderText('Search plugins'))!.toBeInTheDocument() }) }) }) @@ -496,13 +502,13 @@ describe('MarketplaceTrigger', () => { it('should render without crashing', () => { render() - expect(screen.getByText('All Tags')).toBeInTheDocument() + expect(screen.getByText('All Tags'))!.toBeInTheDocument() }) it('should show "All Tags" when no tags selected', () => { render() - expect(screen.getByText('All Tags')).toBeInTheDocument() + expect(screen.getByText('All Tags'))!.toBeInTheDocument() }) it('should show arrow down icon when no tags selected', () => { @@ -511,7 +517,8 @@ describe('MarketplaceTrigger', () => { ) // Arrow down icon should be present - expect(container.querySelector('.size-4')).toBeInTheDocument() + // Arrow down icon should be present + expect(container.querySelector('.size-4'))!.toBeInTheDocument() }) }) @@ -525,7 +532,7 @@ describe('MarketplaceTrigger', () => { />, ) - expect(screen.getByText('Agent')).toBeInTheDocument() + expect(screen.getByText('Agent'))!.toBeInTheDocument() }) it('should show multiple tag labels separated by comma', () => { @@ -537,7 +544,7 @@ describe('MarketplaceTrigger', () => { />, ) - expect(screen.getByText('Agent,RAG')).toBeInTheDocument() + expect(screen.getByText('Agent,RAG'))!.toBeInTheDocument() }) it('should show +N indicator when more than 2 tags selected', () => { @@ -549,7 +556,7 @@ describe('MarketplaceTrigger', () => { />, ) - expect(screen.getByText('+2')).toBeInTheDocument() + expect(screen.getByText('+2'))!.toBeInTheDocument() }) it('should only show first 2 tags in label', () => { @@ -561,7 +568,7 @@ describe('MarketplaceTrigger', () => { />, ) - expect(screen.getByText('Agent,RAG')).toBeInTheDocument() + expect(screen.getByText('Agent,RAG'))!.toBeInTheDocument() expect(screen.queryByText('Search')).not.toBeInTheDocument() }) }) @@ -577,7 +584,8 @@ describe('MarketplaceTrigger', () => { ) // RiCloseCircleFill icon should be present - expect(container.querySelector('.text-text-quaternary')).toBeInTheDocument() + // RiCloseCircleFill icon should be present + expect(container.querySelector('.text-text-quaternary'))!.toBeInTheDocument() }) it('should not show clear button when no tags selected', () => { @@ -585,6 +593,37 @@ describe('MarketplaceTrigger', () => { , ) + // Clear button should not be present + // Clear button should not be present + // Clear button should not be present + // Clear button should not be present + // Clear button should not be present + // Clear button should not be present + // Clear button should not be present + // Clear button should not be present + // Clear button should not be present + // Clear button should not be present + // Clear button should not be present + // Clear button should not be present + // Clear button should not be present + // Clear button should not be present + // Clear button should not be present + // Clear button should not be present + // Clear button should not be present + // Clear button should not be present + // Clear button should not be present + // Clear button should not be present + // Clear button should not be present + // Clear button should not be present + // Clear button should not be present + // Clear button should not be present + // Clear button should not be present + // Clear button should not be present + // Clear button should not be present + // Clear button should not be present + // Clear button should not be present + // Clear button should not be present + // Clear button should not be present // Clear button should not be present expect(container.querySelector('.text-text-quaternary')).not.toBeInTheDocument() }) @@ -614,7 +653,7 @@ describe('MarketplaceTrigger', () => { , ) - expect(container.querySelector('.bg-state-base-hover')).toBeInTheDocument() + expect(container.querySelector('.bg-state-base-hover'))!.toBeInTheDocument() }) it('should apply border styling when tags are selected', () => { @@ -626,7 +665,7 @@ describe('MarketplaceTrigger', () => { />, ) - expect(container.querySelector('.border-components-button-secondary-border')).toBeInTheDocument() + expect(container.querySelector('.border-components-button-secondary-border'))!.toBeInTheDocument() }) }) @@ -636,7 +675,7 @@ describe('MarketplaceTrigger', () => { , ) - expect(container).toBeInTheDocument() + expect(container)!.toBeInTheDocument() }) }) }) @@ -661,13 +700,13 @@ describe('ToolSelectorTrigger', () => { it('should render without crashing', () => { const { container } = render() - expect(container).toBeInTheDocument() + expect(container)!.toBeInTheDocument() }) it('should render price tag icon', () => { const { container } = render() - expect(container.querySelector('.size-4')).toBeInTheDocument() + expect(container.querySelector('.size-4'))!.toBeInTheDocument() }) }) @@ -681,7 +720,7 @@ describe('ToolSelectorTrigger', () => { />, ) - expect(screen.getByText('Agent')).toBeInTheDocument() + expect(screen.getByText('Agent'))!.toBeInTheDocument() }) it('should show multiple tag labels separated by comma', () => { @@ -693,7 +732,7 @@ describe('ToolSelectorTrigger', () => { />, ) - expect(screen.getByText('Agent,RAG')).toBeInTheDocument() + expect(screen.getByText('Agent,RAG'))!.toBeInTheDocument() }) it('should show +N indicator when more than 2 tags selected', () => { @@ -705,7 +744,7 @@ describe('ToolSelectorTrigger', () => { />, ) - expect(screen.getByText('+2')).toBeInTheDocument() + expect(screen.getByText('+2'))!.toBeInTheDocument() }) it('should not show tag labels when no tags selected', () => { @@ -725,7 +764,7 @@ describe('ToolSelectorTrigger', () => { />, ) - expect(container.querySelector('.text-text-quaternary')).toBeInTheDocument() + expect(container.querySelector('.text-text-quaternary'))!.toBeInTheDocument() }) it('should not show clear button when no tags selected', () => { @@ -785,7 +824,7 @@ describe('ToolSelectorTrigger', () => { , ) - expect(container.querySelector('.bg-state-base-hover')).toBeInTheDocument() + expect(container.querySelector('.bg-state-base-hover'))!.toBeInTheDocument() }) it('should apply border styling when tags are selected', () => { @@ -797,7 +836,7 @@ describe('ToolSelectorTrigger', () => { />, ) - expect(container.querySelector('.border-components-button-secondary-border')).toBeInTheDocument() + expect(container.querySelector('.border-components-button-secondary-border'))!.toBeInTheDocument() }) it('should not apply hover styling when open but has tags', () => { @@ -811,7 +850,8 @@ describe('ToolSelectorTrigger', () => { ) // Should have border styling, not hover - expect(container.querySelector('.border-components-button-secondary-border')).toBeInTheDocument() + // Should have border styling, not hover + expect(container.querySelector('.border-components-button-secondary-border'))!.toBeInTheDocument() }) }) @@ -826,7 +866,7 @@ describe('ToolSelectorTrigger', () => { />, ) - expect(screen.getByText('Agent')).toBeInTheDocument() + expect(screen.getByText('Agent'))!.toBeInTheDocument() }) }) }) @@ -854,7 +894,7 @@ describe('TagsFilter', () => { />, ) - expect(screen.getByTestId('portal-elem')).toBeInTheDocument() + expect(screen.getByTestId('portal-elem'))!.toBeInTheDocument() }) it('should pass usedInMarketplace prop to TagsFilter', () => { @@ -869,7 +909,8 @@ describe('TagsFilter', () => { ) // MarketplaceTrigger should show "All Tags" - expect(screen.getByText('All Tags')).toBeInTheDocument() + // MarketplaceTrigger should show "All Tags" + expect(screen.getByText('All Tags'))!.toBeInTheDocument() }) it('should show selected tags count in TagsFilter trigger', () => { @@ -883,7 +924,7 @@ describe('TagsFilter', () => { />, ) - expect(screen.getByText('+1')).toBeInTheDocument() + expect(screen.getByText('+1'))!.toBeInTheDocument() }) }) @@ -902,7 +943,7 @@ describe('TagsFilter', () => { fireEvent.click(trigger) await waitFor(() => { - expect(screen.getByTestId('portal-content')).toBeInTheDocument() + expect(screen.getByTestId('portal-content'))!.toBeInTheDocument() }) }) @@ -921,7 +962,7 @@ describe('TagsFilter', () => { // Open fireEvent.click(trigger) await waitFor(() => { - expect(screen.getByTestId('portal-content')).toBeInTheDocument() + expect(screen.getByTestId('portal-content'))!.toBeInTheDocument() }) // Close @@ -947,8 +988,8 @@ describe('TagsFilter', () => { fireEvent.click(trigger) await waitFor(() => { - expect(screen.getByText('Agent')).toBeInTheDocument() - expect(screen.getByText('RAG')).toBeInTheDocument() + expect(screen.getByText('Agent'))!.toBeInTheDocument() + expect(screen.getByText('RAG'))!.toBeInTheDocument() }) }) @@ -967,7 +1008,7 @@ describe('TagsFilter', () => { fireEvent.click(trigger) await waitFor(() => { - expect(screen.getByText('Agent')).toBeInTheDocument() + expect(screen.getByText('Agent'))!.toBeInTheDocument() }) const agentOption = screen.getByText('Agent') @@ -1018,7 +1059,7 @@ describe('TagsFilter', () => { fireEvent.click(trigger) await waitFor(() => { - expect(screen.getByText('RAG')).toBeInTheDocument() + expect(screen.getByText('RAG'))!.toBeInTheDocument() }) const ragOption = screen.getByText('RAG') @@ -1061,7 +1102,7 @@ describe('TagsFilter', () => { fireEvent.click(trigger) await waitFor(() => { - expect(screen.getByText('Agent')).toBeInTheDocument() + expect(screen.getByText('Agent'))!.toBeInTheDocument() }) const inputs = screen.getAllByRole('textbox') @@ -1071,7 +1112,7 @@ describe('TagsFilter', () => { if (searchInput) { fireEvent.change(searchInput, { target: { value: 'agent' } }) - expect(screen.getByText('Agent')).toBeInTheDocument() + expect(screen.getByText('Agent'))!.toBeInTheDocument() } }) }) @@ -1097,7 +1138,8 @@ describe('TagsFilter', () => { }) // Verify dropdown content is rendered - expect(screen.getByTestId('portal-content')).toBeInTheDocument() + // Verify dropdown content is rendered + expect(screen.getByTestId('portal-content'))!.toBeInTheDocument() }) it('should render tag options when dropdown is open', async () => { @@ -1114,13 +1156,14 @@ describe('TagsFilter', () => { fireEvent.click(trigger) await waitFor(() => { - expect(screen.getByTestId('portal-content')).toBeInTheDocument() + expect(screen.getByTestId('portal-content'))!.toBeInTheDocument() }) // When no tags selected, these should appear once each in dropdown - expect(screen.getByText('Agent')).toBeInTheDocument() - expect(screen.getByText('RAG')).toBeInTheDocument() - expect(screen.getByText('Search')).toBeInTheDocument() + // When no tags selected, these should appear once each in dropdown + expect(screen.getByText('Agent'))!.toBeInTheDocument() + expect(screen.getByText('RAG'))!.toBeInTheDocument() + expect(screen.getByText('Search'))!.toBeInTheDocument() }) }) }) @@ -1146,8 +1189,8 @@ describe('Accessibility', () => { ) const input = screen.getByRole('textbox') - expect(input).toBeInTheDocument() - expect(input).toHaveAttribute('placeholder', 'Search plugins') + expect(input)!.toBeInTheDocument() + expect(input)!.toHaveAttribute('placeholder', 'Search plugins') }) it('should have clickable tag options in dropdown', async () => { @@ -1156,7 +1199,7 @@ describe('Accessibility', () => { fireEvent.click(screen.getByTestId('portal-trigger')) await waitFor(() => { - expect(screen.getByText('Agent')).toBeInTheDocument() + expect(screen.getByText('Agent'))!.toBeInTheDocument() }) }) }) @@ -1192,7 +1235,7 @@ describe('Combined Workflows', () => { fireEvent.click(trigger) await waitFor(() => { - expect(screen.getByText('Agent')).toBeInTheDocument() + expect(screen.getByText('Agent'))!.toBeInTheDocument() }) const agentOption = screen.getByText('Agent') @@ -1217,9 +1260,9 @@ describe('Combined Workflows', () => { />, ) - expect(screen.getByDisplayValue('test')).toBeInTheDocument() - expect(screen.getByText('Agent,RAG')).toBeInTheDocument() - expect(screen.getByTestId('portal-elem')).toBeInTheDocument() + expect(screen.getByDisplayValue('test'))!.toBeInTheDocument() + expect(screen.getByText('Agent,RAG'))!.toBeInTheDocument() + expect(screen.getByTestId('portal-elem'))!.toBeInTheDocument() }) it('should handle prop changes correctly', () => { @@ -1234,7 +1277,7 @@ describe('Combined Workflows', () => { />, ) - expect(screen.getByDisplayValue('initial')).toBeInTheDocument() + expect(screen.getByDisplayValue('initial'))!.toBeInTheDocument() rerender( { />, ) - expect(screen.getByDisplayValue('updated')).toBeInTheDocument() + expect(screen.getByDisplayValue('updated'))!.toBeInTheDocument() }) }) diff --git a/web/app/components/plugins/marketplace/search-box/trigger/marketplace.tsx b/web/app/components/plugins/marketplace/search-box/trigger/marketplace.tsx index 414216c532..167d6fcd70 100644 --- a/web/app/components/plugins/marketplace/search-box/trigger/marketplace.tsx +++ b/web/app/components/plugins/marketplace/search-box/trigger/marketplace.tsx @@ -39,7 +39,7 @@ const MarketplaceTrigger = ({ { !!selectedTagsLength && ( - {tags.map(tag => tagsMap[tag].label).slice(0, 2).join(',')} + {tags.map(tag => tagsMap[tag]!.label).slice(0, 2).join(',')} ) } diff --git a/web/app/components/plugins/marketplace/search-box/trigger/tool-selector.tsx b/web/app/components/plugins/marketplace/search-box/trigger/tool-selector.tsx index 6c733ea546..d351414ee8 100644 --- a/web/app/components/plugins/marketplace/search-box/trigger/tool-selector.tsx +++ b/web/app/components/plugins/marketplace/search-box/trigger/tool-selector.tsx @@ -33,7 +33,7 @@ const ToolSelectorTrigger = ({ !!selectedTagsLength && (
- {tags.map(tag => tagsMap[tag].label).slice(0, 2).join(',')} + {tags.map(tag => tagsMap[tag]!.label).slice(0, 2).join(',')} { selectedTagsLength > 2 && ( diff --git a/web/app/components/plugins/marketplace/sort-dropdown/index.tsx b/web/app/components/plugins/marketplace/sort-dropdown/index.tsx index dddfab5402..d8b6939d1a 100644 --- a/web/app/components/plugins/marketplace/sort-dropdown/index.tsx +++ b/web/app/components/plugins/marketplace/sort-dropdown/index.tsx @@ -56,7 +56,7 @@ const SortDropdown = () => { {t('marketplace.sortBy', { ns: 'plugin' })} - {selectedOption.text} + {selectedOption!.text}
diff --git a/web/app/components/plugins/plugin-auth/__tests__/authorized-in-node.spec.tsx b/web/app/components/plugins/plugin-auth/__tests__/authorized-in-node.spec.tsx index f4eb9462fc..cba8dc96c9 100644 --- a/web/app/components/plugins/plugin-auth/__tests__/authorized-in-node.spec.tsx +++ b/web/app/components/plugins/plugin-auth/__tests__/authorized-in-node.spec.tsx @@ -111,7 +111,7 @@ describe('AuthorizedInNode Component', () => { , { wrapper: createWrapper() }, ) - expect(screen.getByText('plugin.auth.workspaceDefault')).toBeInTheDocument() + expect(screen.getByText('plugin.auth.workspaceDefault'))!.toBeInTheDocument() }) it('should render credential name when credentialId matches', async () => { @@ -127,7 +127,7 @@ describe('AuthorizedInNode Component', () => { , { wrapper: createWrapper() }, ) - expect(screen.getByText('My Credential')).toBeInTheDocument() + expect(screen.getByText('My Credential'))!.toBeInTheDocument() }) it('should show auth removed when credentialId not found', async () => { @@ -142,7 +142,7 @@ describe('AuthorizedInNode Component', () => { , { wrapper: createWrapper() }, ) - expect(screen.getByText('plugin.auth.authRemoved')).toBeInTheDocument() + expect(screen.getByText('plugin.auth.authRemoved'))!.toBeInTheDocument() }) it('should show unavailable when credential is not allowed', async () => { @@ -195,7 +195,7 @@ describe('AuthorizedInNode Component', () => { { wrapper: createWrapper() }, ) const buttons = screen.getAllByRole('button') - fireEvent.click(buttons[0]) + fireEvent.click(buttons[0]!) expect(screen.getAllByRole('button').length).toBeGreaterThan(0) }) diff --git a/web/app/components/plugins/plugin-auth/__tests__/plugin-auth-in-agent.spec.tsx b/web/app/components/plugins/plugin-auth/__tests__/plugin-auth-in-agent.spec.tsx index 4c26712fdc..6afe1ae334 100644 --- a/web/app/components/plugins/plugin-auth/__tests__/plugin-auth-in-agent.spec.tsx +++ b/web/app/components/plugins/plugin-auth/__tests__/plugin-auth-in-agent.spec.tsx @@ -116,7 +116,7 @@ describe('PluginAuthInAgent Component', () => { , { wrapper: createWrapper() }, ) - expect(screen.getByRole('button')).toBeInTheDocument() + expect(screen.getByRole('button'))!.toBeInTheDocument() }) it('should render Authorized with workspace default when authorized', async () => { @@ -126,8 +126,8 @@ describe('PluginAuthInAgent Component', () => { , { wrapper: createWrapper() }, ) - expect(screen.getByRole('button')).toBeInTheDocument() - expect(screen.getByText('plugin.auth.workspaceDefault')).toBeInTheDocument() + expect(screen.getByRole('button'))!.toBeInTheDocument() + expect(screen.getByText('plugin.auth.workspaceDefault'))!.toBeInTheDocument() }) it('should show credential name when credentialId is provided', async () => { @@ -143,7 +143,7 @@ describe('PluginAuthInAgent Component', () => { , { wrapper: createWrapper() }, ) - expect(screen.getByText('Selected Credential')).toBeInTheDocument() + expect(screen.getByText('Selected Credential'))!.toBeInTheDocument() }) it('should show auth removed when credential not found', async () => { @@ -158,7 +158,7 @@ describe('PluginAuthInAgent Component', () => { , { wrapper: createWrapper() }, ) - expect(screen.getByText('plugin.auth.authRemoved')).toBeInTheDocument() + expect(screen.getByText('plugin.auth.authRemoved'))!.toBeInTheDocument() }) it('should show unavailable when credential is not allowed to use', async () => { @@ -192,7 +192,7 @@ describe('PluginAuthInAgent Component', () => { { wrapper: createWrapper() }, ) const buttons = screen.getAllByRole('button') - fireEvent.click(buttons[0]) + fireEvent.click(buttons[0]!) expect(screen.getAllByRole('button').length).toBeGreaterThan(0) }) @@ -214,7 +214,7 @@ describe('PluginAuthInAgent Component', () => { fireEvent.click(triggerButton) const workspaceDefaultItems = screen.getAllByText('plugin.auth.workspaceDefault') const popupItem = workspaceDefaultItems.length > 1 ? workspaceDefaultItems[1] : workspaceDefaultItems[0] - fireEvent.click(popupItem) + fireEvent.click(popupItem!) expect(onAuthorizationItemClick).toHaveBeenCalledWith('') }) @@ -240,7 +240,7 @@ describe('PluginAuthInAgent Component', () => { fireEvent.click(triggerButton) const credentialItems = screen.getAllByText('Specific Credential') const popupItem = credentialItems[credentialItems.length - 1] - fireEvent.click(popupItem) + fireEvent.click(popupItem!) expect(onAuthorizationItemClick).toHaveBeenCalledWith('specific-cred-id') }) diff --git a/web/app/components/plugins/plugin-auth/authorized/__tests__/index.spec.tsx b/web/app/components/plugins/plugin-auth/authorized/__tests__/index.spec.tsx index f911dcd4e0..a127067526 100644 --- a/web/app/components/plugins/plugin-auth/authorized/__tests__/index.spec.tsx +++ b/web/app/components/plugins/plugin-auth/authorized/__tests__/index.spec.tsx @@ -147,7 +147,7 @@ describe('Authorized Component', () => { { wrapper: createWrapper() }, ) - expect(screen.getByRole('button')).toBeInTheDocument() + expect(screen.getByRole('button'))!.toBeInTheDocument() }) it('should render with custom trigger when renderTrigger is provided', () => { @@ -163,8 +163,8 @@ describe('Authorized Component', () => { { wrapper: createWrapper() }, ) - expect(screen.getByTestId('custom-trigger')).toBeInTheDocument() - expect(screen.getByText('Closed')).toBeInTheDocument() + expect(screen.getByTestId('custom-trigger'))!.toBeInTheDocument() + expect(screen.getByText('Closed'))!.toBeInTheDocument() }) it('should show singular authorization text for 1 credential', () => { @@ -180,7 +180,8 @@ describe('Authorized Component', () => { ) // Text is split by elements, use regex to find partial match - expect(screen.getByText(/plugin\.auth\.authorization/)).toBeInTheDocument() + // Text is split by elements, use regex to find partial match + expect(screen.getByText(/plugin\.auth\.authorization/))!.toBeInTheDocument() }) it('should show plural authorizations text for multiple credentials', () => { @@ -199,7 +200,8 @@ describe('Authorized Component', () => { ) // Text is split by elements, use regex to find partial match - expect(screen.getByText(/plugin\.auth\.authorizations/)).toBeInTheDocument() + // Text is split by elements, use regex to find partial match + expect(screen.getByText(/plugin\.auth\.authorizations/))!.toBeInTheDocument() }) it('should show unavailable count when there are unavailable credentials', () => { @@ -217,7 +219,7 @@ describe('Authorized Component', () => { { wrapper: createWrapper() }, ) - expect(screen.getByText(/plugin\.auth\.unavailable/)).toBeInTheDocument() + expect(screen.getByText(/plugin\.auth\.unavailable/))!.toBeInTheDocument() }) it('should show gray indicator when default credential is unavailable', () => { @@ -235,7 +237,8 @@ describe('Authorized Component', () => { ) // The indicator should be rendered - expect(container.querySelector('[data-testid="status-indicator"]')).toBeInTheDocument() + // The indicator should be rendered + expect(container.querySelector('[data-testid="status-indicator"]'))!.toBeInTheDocument() }) }) @@ -257,7 +260,8 @@ describe('Authorized Component', () => { fireEvent.click(trigger) // Popup should be open - check for popup content - expect(screen.getByText('API Keys')).toBeInTheDocument() + // Popup should be open - check for popup content + expect(screen.getByText('API Keys'))!.toBeInTheDocument() }) it('should use controlled open state when isOpen and onOpenChange are provided', () => { @@ -276,11 +280,12 @@ describe('Authorized Component', () => { ) // Popup should be open since isOpen is true - expect(screen.getByText('API Keys')).toBeInTheDocument() + // Popup should be open since isOpen is true + expect(screen.getByText('API Keys'))!.toBeInTheDocument() // Click trigger to close - get all buttons and click the first one (trigger) const buttons = screen.getAllByRole('button') - fireEvent.click(buttons[0]) + fireEvent.click(buttons[0]!) expect(onOpenChange).toHaveBeenCalledWith(false) }) @@ -301,7 +306,7 @@ describe('Authorized Component', () => { // Open fireEvent.click(trigger) - expect(screen.getByText('API Keys')).toBeInTheDocument() + expect(screen.getByText('API Keys'))!.toBeInTheDocument() // Close fireEvent.click(trigger) @@ -326,8 +331,8 @@ describe('Authorized Component', () => { { wrapper: createWrapper() }, ) - expect(screen.getByText('OAuth')).toBeInTheDocument() - expect(screen.getByText('OAuth Cred')).toBeInTheDocument() + expect(screen.getByText('OAuth'))!.toBeInTheDocument() + expect(screen.getByText('OAuth Cred'))!.toBeInTheDocument() }) it('should render API Key credentials section when apiKeyCredentials exist', () => { @@ -345,8 +350,8 @@ describe('Authorized Component', () => { { wrapper: createWrapper() }, ) - expect(screen.getByText('API Keys')).toBeInTheDocument() - expect(screen.getByText('API Key Cred')).toBeInTheDocument() + expect(screen.getByText('API Keys'))!.toBeInTheDocument() + expect(screen.getByText('API Key Cred'))!.toBeInTheDocument() }) it('should render both OAuth and API Key sections when both exist', () => { @@ -365,8 +370,8 @@ describe('Authorized Component', () => { { wrapper: createWrapper() }, ) - expect(screen.getByText('OAuth')).toBeInTheDocument() - expect(screen.getByText('API Keys')).toBeInTheDocument() + expect(screen.getByText('OAuth'))!.toBeInTheDocument() + expect(screen.getByText('API Keys'))!.toBeInTheDocument() }) it('should render extra authorization items when provided', () => { @@ -386,7 +391,7 @@ describe('Authorized Component', () => { { wrapper: createWrapper() }, ) - expect(screen.getByText('Extra Item')).toBeInTheDocument() + expect(screen.getByText('Extra Item'))!.toBeInTheDocument() }) it('should pass showSelectedIcon and selectedCredentialId to items', () => { @@ -405,7 +410,8 @@ describe('Authorized Component', () => { ) // Selected icon should be visible - expect(document.querySelector('.text-text-accent')).toBeInTheDocument() + // Selected icon should be visible + expect(document.querySelector('.text-text-accent'))!.toBeInTheDocument() }) }) @@ -431,7 +437,7 @@ describe('Authorized Component', () => { // Confirm dialog should appear await waitFor(() => { - expect(screen.getByText('datasetDocuments.list.delete.title')).toBeInTheDocument() + expect(screen.getByText('datasetDocuments.list.delete.title'))!.toBeInTheDocument() }) } }) @@ -451,7 +457,7 @@ describe('Authorized Component', () => { // Wait for OAuth section to render await waitFor(() => { - expect(screen.getByText('OAuth')).toBeInTheDocument() + expect(screen.getByText('OAuth'))!.toBeInTheDocument() }) // Find all SVG icons in the action area and try to find delete button @@ -482,7 +488,8 @@ describe('Authorized Component', () => { } // Component should render correctly regardless of button finding - expect(screen.getByText('OAuth')).toBeInTheDocument() + // Component should render correctly regardless of button finding + expect(screen.getByText('OAuth'))!.toBeInTheDocument() }) it('should call deletePluginCredential when confirm is clicked', async () => { @@ -506,7 +513,7 @@ describe('Authorized Component', () => { fireEvent.click(deleteButton) await waitFor(() => { - expect(screen.getByText('datasetDocuments.list.delete.title')).toBeInTheDocument() + expect(screen.getByText('datasetDocuments.list.delete.title'))!.toBeInTheDocument() }) // Click confirm button @@ -693,7 +700,8 @@ describe('Authorized Component', () => { } else { // Verify component renders properly - expect(screen.getByText('OAuth')).toBeInTheDocument() + // Verify component renders properly + expect(screen.getByText('OAuth'))!.toBeInTheDocument() } }) @@ -716,7 +724,8 @@ describe('Authorized Component', () => { ) // Verify component renders - expect(screen.getByText('OAuth')).toBeInTheDocument() + // Verify component renders + expect(screen.getByText('OAuth'))!.toBeInTheDocument() }) it('should execute handleRename function body when saving', async () => { @@ -745,8 +754,9 @@ describe('Authorized Component', () => { ) // Wait for component to render - expect(screen.getByText('OAuth')).toBeInTheDocument() - expect(screen.getByText('Execute Rename Test')).toBeInTheDocument() + // Wait for component to render + expect(screen.getByText('OAuth'))!.toBeInTheDocument() + expect(screen.getByText('Execute Rename Test'))!.toBeInTheDocument() // The handleRename is tested through the "should call updatePluginCredential when rename is confirmed" test // This test verifies the component properly renders OAuth credentials @@ -778,7 +788,8 @@ describe('Authorized Component', () => { ) // Verify OAuth section renders - expect(screen.getByText('OAuth')).toBeInTheDocument() + // Verify OAuth section renders + expect(screen.getByText('OAuth'))!.toBeInTheDocument() // Find all action buttons in the credential item // The rename button should be present for OAuth credentials @@ -857,7 +868,8 @@ describe('Authorized Component', () => { // ApiKeyModal should appear - look for modal content await waitFor(() => { // The modal should be rendered - expect(document.querySelector('.fixed')).toBeInTheDocument() + // The modal should be rendered + expect(document.querySelector('.fixed'))!.toBeInTheDocument() }) } }) @@ -887,7 +899,7 @@ describe('Authorized Component', () => { fireEvent.click(editButton) await waitFor(() => { - expect(document.querySelector('.fixed')).toBeInTheDocument() + expect(document.querySelector('.fixed'))!.toBeInTheDocument() }) // Find and click close/cancel button in the modal @@ -907,7 +919,8 @@ describe('Authorized Component', () => { await waitFor(() => { // Verify component state is cleared by checking we can open again - expect(screen.getByText('API Keys')).toBeInTheDocument() + // Verify component state is cleared by checking we can open again + expect(screen.getByText('API Keys'))!.toBeInTheDocument() }) } } @@ -971,13 +984,14 @@ describe('Authorized Component', () => { // Verify state was reset - we should be able to see the credential list again await waitFor(() => { - expect(screen.getByText('API Keys')).toBeInTheDocument() + expect(screen.getByText('API Keys'))!.toBeInTheDocument() }) } } else { // Verify component renders - expect(screen.getByText('API Keys')).toBeInTheDocument() + // Verify component renders + expect(screen.getByText('API Keys'))!.toBeInTheDocument() } }) @@ -1002,12 +1016,13 @@ describe('Authorized Component', () => { ) // Wait for component to render - expect(screen.getByText('API Keys')).toBeInTheDocument() + // Wait for component to render + expect(screen.getByText('API Keys'))!.toBeInTheDocument() // Find edit button by looking for settings icon const settingsIcons = document.querySelectorAll('svg.ri-equalizer-2-line') if (settingsIcons.length > 0) { - const editButton = settingsIcons[0].closest('button') + const editButton = settingsIcons[0]!.closest('button') if (editButton) { // Click to open edit modal await act(async () => { @@ -1033,7 +1048,7 @@ describe('Authorized Component', () => { // Verify the modal is closed and state is reset // The component should render normally after close await waitFor(() => { - expect(screen.getByText('API Keys')).toBeInTheDocument() + expect(screen.getByText('API Keys'))!.toBeInTheDocument() }) break } @@ -1063,12 +1078,13 @@ describe('Authorized Component', () => { ) // Wait for component to render - expect(screen.getByText('API Keys')).toBeInTheDocument() + // Wait for component to render + expect(screen.getByText('API Keys'))!.toBeInTheDocument() // Find and click edit button to open ApiKeyModal const settingsIcons = document.querySelectorAll('svg.ri-equalizer-2-line') if (settingsIcons.length > 0) { - const editButton = settingsIcons[0].closest('button') + const editButton = settingsIcons[0]!.closest('button') if (editButton) { await act(async () => { fireEvent.click(editButton) @@ -1093,7 +1109,7 @@ describe('Authorized Component', () => { await waitFor(() => { const confirmDialog = screen.queryByText('datasetDocuments.list.delete.title') if (confirmDialog) { - expect(confirmDialog).toBeInTheDocument() + expect(confirmDialog)!.toBeInTheDocument() } }, { timeout: 1000 }) } @@ -1122,7 +1138,8 @@ describe('Authorized Component', () => { ) // Verify API Keys section is shown - expect(screen.getByText('API Keys')).toBeInTheDocument() + // Verify API Keys section is shown + expect(screen.getByText('API Keys'))!.toBeInTheDocument() // Find edit button - look for buttons in the action area const actionAreaButtons = Array.from(document.querySelectorAll('.group-hover\\:flex button, .hidden button')) @@ -1149,7 +1166,8 @@ describe('Authorized Component', () => { } // Verify component renders correctly - expect(screen.getByText('API Keys')).toBeInTheDocument() + // Verify component renders correctly + expect(screen.getByText('API Keys'))!.toBeInTheDocument() }) it('should trigger handleRemove when remove button is clicked in ApiKeyModal', async () => { @@ -1173,7 +1191,8 @@ describe('Authorized Component', () => { ) // Verify component renders - expect(screen.getByText('API Keys')).toBeInTheDocument() + // Verify component renders + expect(screen.getByText('API Keys'))!.toBeInTheDocument() // Find edit button by looking for action buttons (not in the confirm dialog) // These are grouped in hidden elements that show on hover @@ -1203,7 +1222,8 @@ describe('Authorized Component', () => { } // Verify component still works - expect(screen.getByText('API Keys')).toBeInTheDocument() + // Verify component still works + expect(screen.getByText('API Keys'))!.toBeInTheDocument() }) it('should show confirm dialog when remove is clicked from edit modal', async () => { @@ -1230,7 +1250,7 @@ describe('Authorized Component', () => { fireEvent.click(editButton) await waitFor(() => { - expect(document.querySelector('.fixed')).toBeInTheDocument() + expect(document.querySelector('.fixed'))!.toBeInTheDocument() }) // Find remove button in modal (usually has delete/remove text) @@ -1242,7 +1262,7 @@ describe('Authorized Component', () => { // Confirm dialog should appear await waitFor(() => { - expect(screen.getByText('datasetDocuments.list.delete.title')).toBeInTheDocument() + expect(screen.getByText('datasetDocuments.list.delete.title'))!.toBeInTheDocument() }) } } @@ -1284,7 +1304,7 @@ describe('Authorized Component', () => { // Wait for modal to open await waitFor(() => { const modal = document.querySelector('.fixed') - expect(modal).toBeInTheDocument() + expect(modal)!.toBeInTheDocument() }) // Find the close/cancel button @@ -1304,13 +1324,14 @@ describe('Authorized Component', () => { // Verify component still works after closing await waitFor(() => { - expect(screen.getByText('API Keys')).toBeInTheDocument() + expect(screen.getByText('API Keys'))!.toBeInTheDocument() }) } } else { // If no edit button found, just verify the component renders - expect(screen.getByText('API Keys')).toBeInTheDocument() + // If no edit button found, just verify the component renders + expect(screen.getByText('API Keys'))!.toBeInTheDocument() } }) }) @@ -1359,7 +1380,8 @@ describe('Authorized Component', () => { ) // Should have divider and authorize buttons - expect(document.querySelector('.bg-divider-subtle')).toBeInTheDocument() + // Should have divider and authorize buttons + expect(document.querySelector('.bg-divider-subtle'))!.toBeInTheDocument() }) it('should not render Authorize component when notAllowCustomCredential is true', () => { @@ -1400,7 +1422,7 @@ describe('Authorized Component', () => { { wrapper: createWrapper() }, ) - expect(document.querySelector('.custom-popup-class')).toBeInTheDocument() + expect(document.querySelector('.custom-popup-class'))!.toBeInTheDocument() }) it('should pass placement to PortalToFollowElem', () => { @@ -1419,7 +1441,8 @@ describe('Authorized Component', () => { ) // Component should render without error - expect(screen.getByText('API Keys')).toBeInTheDocument() + // Component should render without error + expect(screen.getByText('API Keys'))!.toBeInTheDocument() }) it('should pass disabled to Item components', () => { @@ -1441,11 +1464,12 @@ describe('Authorized Component', () => { const setDefaultButton = screen.queryByText('plugin.auth.setDefault') if (setDefaultButton) { const button = setDefaultButton.closest('button') - expect(button).toBeDisabled() + expect(button)!.toBeDisabled() } else { // If no set default button, verify the component rendered - expect(screen.getByText('API Keys')).toBeInTheDocument() + // If no set default button, verify the component rendered + expect(screen.getByText('API Keys'))!.toBeInTheDocument() } }) @@ -1463,6 +1487,37 @@ describe('Authorized Component', () => { { wrapper: createWrapper() }, ) + // Set default button should not be visible + // Set default button should not be visible + // Set default button should not be visible + // Set default button should not be visible + // Set default button should not be visible + // Set default button should not be visible + // Set default button should not be visible + // Set default button should not be visible + // Set default button should not be visible + // Set default button should not be visible + // Set default button should not be visible + // Set default button should not be visible + // Set default button should not be visible + // Set default button should not be visible + // Set default button should not be visible + // Set default button should not be visible + // Set default button should not be visible + // Set default button should not be visible + // Set default button should not be visible + // Set default button should not be visible + // Set default button should not be visible + // Set default button should not be visible + // Set default button should not be visible + // Set default button should not be visible + // Set default button should not be visible + // Set default button should not be visible + // Set default button should not be visible + // Set default button should not be visible + // Set default button should not be visible + // Set default button should not be visible + // Set default button should not be visible // Set default button should not be visible expect(screen.queryByText('plugin.auth.setDefault')).not.toBeInTheDocument() }) @@ -1492,7 +1547,7 @@ describe('Authorized Component', () => { fireEvent.click(deleteButton) await waitFor(() => { - expect(screen.getByText('datasetDocuments.list.delete.title')).toBeInTheDocument() + expect(screen.getByText('datasetDocuments.list.delete.title'))!.toBeInTheDocument() }) const confirmButton = screen.getByText('common.operation.confirm') @@ -1623,7 +1678,8 @@ describe('Authorized Component', () => { ) // Component should render without error - expect(screen.getByText('API Keys')).toBeInTheDocument() + // Component should render without error + expect(screen.getByText('API Keys'))!.toBeInTheDocument() }) }) @@ -1663,7 +1719,7 @@ describe('Authorized Component', () => { // Wait for component to render await waitFor(() => { - expect(screen.getByText('OAuth')).toBeInTheDocument() + expect(screen.getByText('OAuth'))!.toBeInTheDocument() }) // Find all buttons in the credential item's action area @@ -1698,7 +1754,7 @@ describe('Authorized Component', () => { // Verify confirm dialog appears await waitFor(() => { - expect(screen.getByText('datasetDocuments.list.delete.title')).toBeInTheDocument() + expect(screen.getByText('datasetDocuments.list.delete.title'))!.toBeInTheDocument() }) // Click confirm - this calls handleConfirm @@ -1730,7 +1786,8 @@ describe('Authorized Component', () => { } else { // Component should still render correctly - expect(screen.getByText('OAuth')).toBeInTheDocument() + // Component should still render correctly + expect(screen.getByText('OAuth'))!.toBeInTheDocument() } }) @@ -1753,7 +1810,8 @@ describe('Authorized Component', () => { ) // Verify component renders - expect(screen.getByText('API Keys')).toBeInTheDocument() + // Verify component renders + expect(screen.getByText('API Keys'))!.toBeInTheDocument() }) it('should prevent handleConfirm when doingAction is true', async () => { @@ -1812,7 +1870,8 @@ describe('Authorized Component', () => { if (!foundDeleteButton) { // Verify component renders - expect(screen.getByText('OAuth')).toBeInTheDocument() + // Verify component renders + expect(screen.getByText('OAuth'))!.toBeInTheDocument() } }) @@ -1831,6 +1890,99 @@ describe('Authorized Component', () => { { wrapper: createWrapper() }, ) + // With no credentials, there's no way to trigger openConfirm, + // so pendingOperationCredentialId stays null + // This edge case is handled by the component's internal logic + // With no credentials, there's no way to trigger openConfirm, + // so pendingOperationCredentialId stays null + // This edge case is handled by the component's internal logic + // With no credentials, there's no way to trigger openConfirm, + // so pendingOperationCredentialId stays null + // This edge case is handled by the component's internal logic + // With no credentials, there's no way to trigger openConfirm, + // so pendingOperationCredentialId stays null + // This edge case is handled by the component's internal logic + // With no credentials, there's no way to trigger openConfirm, + // so pendingOperationCredentialId stays null + // This edge case is handled by the component's internal logic + // With no credentials, there's no way to trigger openConfirm, + // so pendingOperationCredentialId stays null + // This edge case is handled by the component's internal logic + // With no credentials, there's no way to trigger openConfirm, + // so pendingOperationCredentialId stays null + // This edge case is handled by the component's internal logic + // With no credentials, there's no way to trigger openConfirm, + // so pendingOperationCredentialId stays null + // This edge case is handled by the component's internal logic + // With no credentials, there's no way to trigger openConfirm, + // so pendingOperationCredentialId stays null + // This edge case is handled by the component's internal logic + // With no credentials, there's no way to trigger openConfirm, + // so pendingOperationCredentialId stays null + // This edge case is handled by the component's internal logic + // With no credentials, there's no way to trigger openConfirm, + // so pendingOperationCredentialId stays null + // This edge case is handled by the component's internal logic + // With no credentials, there's no way to trigger openConfirm, + // so pendingOperationCredentialId stays null + // This edge case is handled by the component's internal logic + // With no credentials, there's no way to trigger openConfirm, + // so pendingOperationCredentialId stays null + // This edge case is handled by the component's internal logic + // With no credentials, there's no way to trigger openConfirm, + // so pendingOperationCredentialId stays null + // This edge case is handled by the component's internal logic + // With no credentials, there's no way to trigger openConfirm, + // so pendingOperationCredentialId stays null + // This edge case is handled by the component's internal logic + // With no credentials, there's no way to trigger openConfirm, + // so pendingOperationCredentialId stays null + // This edge case is handled by the component's internal logic + // With no credentials, there's no way to trigger openConfirm, + // so pendingOperationCredentialId stays null + // This edge case is handled by the component's internal logic + // With no credentials, there's no way to trigger openConfirm, + // so pendingOperationCredentialId stays null + // This edge case is handled by the component's internal logic + // With no credentials, there's no way to trigger openConfirm, + // so pendingOperationCredentialId stays null + // This edge case is handled by the component's internal logic + // With no credentials, there's no way to trigger openConfirm, + // so pendingOperationCredentialId stays null + // This edge case is handled by the component's internal logic + // With no credentials, there's no way to trigger openConfirm, + // so pendingOperationCredentialId stays null + // This edge case is handled by the component's internal logic + // With no credentials, there's no way to trigger openConfirm, + // so pendingOperationCredentialId stays null + // This edge case is handled by the component's internal logic + // With no credentials, there's no way to trigger openConfirm, + // so pendingOperationCredentialId stays null + // This edge case is handled by the component's internal logic + // With no credentials, there's no way to trigger openConfirm, + // so pendingOperationCredentialId stays null + // This edge case is handled by the component's internal logic + // With no credentials, there's no way to trigger openConfirm, + // so pendingOperationCredentialId stays null + // This edge case is handled by the component's internal logic + // With no credentials, there's no way to trigger openConfirm, + // so pendingOperationCredentialId stays null + // This edge case is handled by the component's internal logic + // With no credentials, there's no way to trigger openConfirm, + // so pendingOperationCredentialId stays null + // This edge case is handled by the component's internal logic + // With no credentials, there's no way to trigger openConfirm, + // so pendingOperationCredentialId stays null + // This edge case is handled by the component's internal logic + // With no credentials, there's no way to trigger openConfirm, + // so pendingOperationCredentialId stays null + // This edge case is handled by the component's internal logic + // With no credentials, there's no way to trigger openConfirm, + // so pendingOperationCredentialId stays null + // This edge case is handled by the component's internal logic + // With no credentials, there's no way to trigger openConfirm, + // so pendingOperationCredentialId stays null + // This edge case is handled by the component's internal logic // With no credentials, there's no way to trigger openConfirm, // so pendingOperationCredentialId stays null // This edge case is handled by the component's internal logic @@ -1859,7 +2011,7 @@ describe('Authorized Component', () => { // Wait for component to render await waitFor(() => { - expect(screen.getByText('OAuth')).toBeInTheDocument() + expect(screen.getByText('OAuth'))!.toBeInTheDocument() }) // Find delete button in action area @@ -1908,7 +2060,7 @@ describe('Authorized Component', () => { ) await waitFor(() => { - expect(screen.getByText('OAuth')).toBeInTheDocument() + expect(screen.getByText('OAuth'))!.toBeInTheDocument() }) // Find and trigger delete to open confirm dialog @@ -1921,7 +2073,7 @@ describe('Authorized Component', () => { const confirmTitle = screen.queryByText('datasetDocuments.list.delete.title') if (confirmTitle) { - expect(confirmTitle).toBeInTheDocument() + expect(confirmTitle)!.toBeInTheDocument() // Now click cancel to execute closeConfirm const cancelBtn = screen.getByText('common.operation.cancel') @@ -1940,7 +2092,7 @@ describe('Authorized Component', () => { }) await waitFor(() => { - expect(screen.getByText('datasetDocuments.list.delete.title')).toBeInTheDocument() + expect(screen.getByText('datasetDocuments.list.delete.title'))!.toBeInTheDocument() }) break } @@ -1966,7 +2118,7 @@ describe('Authorized Component', () => { ) await waitFor(() => { - expect(screen.getByText('OAuth')).toBeInTheDocument() + expect(screen.getByText('OAuth'))!.toBeInTheDocument() }) // Find and trigger delete to open confirm dialog @@ -2012,7 +2164,7 @@ describe('Authorized Component', () => { ) await waitFor(() => { - expect(screen.getByText('OAuth')).toBeInTheDocument() + expect(screen.getByText('OAuth'))!.toBeInTheDocument() }) // Find and trigger delete to open confirm dialog @@ -2066,7 +2218,7 @@ describe('Authorized Component', () => { // Wait for component to render await waitFor(() => { - expect(screen.getByText('API Keys')).toBeInTheDocument() + expect(screen.getByText('API Keys'))!.toBeInTheDocument() }) // Find edit button in action area @@ -2093,7 +2245,7 @@ describe('Authorized Component', () => { await waitFor(() => { const confirmTitle = screen.queryByText('datasetDocuments.list.delete.title') if (confirmTitle) { - expect(confirmTitle).toBeInTheDocument() + expect(confirmTitle)!.toBeInTheDocument() } }, { timeout: 2000 }) } @@ -2103,7 +2255,8 @@ describe('Authorized Component', () => { } // Verify component renders correctly - expect(screen.getByText('API Keys')).toBeInTheDocument() + // Verify component renders correctly + expect(screen.getByText('API Keys'))!.toBeInTheDocument() }) it('should execute handleRemove to set deleteCredentialId from pendingOperationCredentialId', async () => { @@ -2127,7 +2280,7 @@ describe('Authorized Component', () => { // Wait for component to render await waitFor(() => { - expect(screen.getByText('API Keys')).toBeInTheDocument() + expect(screen.getByText('API Keys'))!.toBeInTheDocument() }) // Find and click edit button to open ApiKeyModal @@ -2155,7 +2308,7 @@ describe('Authorized Component', () => { const confirmTitle = screen.queryByText('datasetDocuments.list.delete.title') // If confirm dialog appears, handleRemove was called if (confirmTitle) { - expect(confirmTitle).toBeInTheDocument() + expect(confirmTitle)!.toBeInTheDocument() } }, { timeout: 1000 }) } @@ -2165,7 +2318,8 @@ describe('Authorized Component', () => { } // Verify component still renders correctly - expect(screen.getByText('API Keys')).toBeInTheDocument() + // Verify component still renders correctly + expect(screen.getByText('API Keys'))!.toBeInTheDocument() }) }) @@ -2195,7 +2349,7 @@ describe('Authorized Component', () => { // Wait for component to render await waitFor(() => { - expect(screen.getByText('OAuth')).toBeInTheDocument() + expect(screen.getByText('OAuth'))!.toBeInTheDocument() }) // Find rename button in action area @@ -2259,7 +2413,7 @@ describe('Authorized Component', () => { ) await waitFor(() => { - expect(screen.getByText('OAuth')).toBeInTheDocument() + expect(screen.getByText('OAuth'))!.toBeInTheDocument() }) // Find rename button @@ -2324,7 +2478,7 @@ describe('Authorized Component', () => { // Wait for component to render await waitFor(() => { - expect(screen.getByText('API Keys')).toBeInTheDocument() + expect(screen.getByText('API Keys'))!.toBeInTheDocument() }) // Find and click edit button to open modal @@ -2346,12 +2500,12 @@ describe('Authorized Component', () => { if (cancelBtns.length > 0) { // Click the first cancel button (modal's cancel) await act(async () => { - fireEvent.click(cancelBtns[0]) + fireEvent.click(cancelBtns[0]!) }) // Modal should be closed await waitFor(() => { - expect(screen.getByText('API Keys')).toBeInTheDocument() + expect(screen.getByText('API Keys'))!.toBeInTheDocument() }) } break @@ -2380,7 +2534,7 @@ describe('Authorized Component', () => { ) await waitFor(() => { - expect(screen.getByText('API Keys')).toBeInTheDocument() + expect(screen.getByText('API Keys'))!.toBeInTheDocument() }) // Open edit modal by clicking edit button @@ -2398,12 +2552,12 @@ describe('Authorized Component', () => { const cancelButtons = screen.queryAllByText('common.operation.cancel') if (cancelButtons.length > 0) { await act(async () => { - fireEvent.click(cancelButtons[0]) + fireEvent.click(cancelButtons[0]!) }) // After onClose, editValues should be null so modal won't render await waitFor(() => { - expect(screen.getByText('API Keys')).toBeInTheDocument() + expect(screen.getByText('API Keys'))!.toBeInTheDocument() }) // Try opening modal again to verify state was properly reset @@ -2413,7 +2567,7 @@ describe('Authorized Component', () => { await waitFor(() => { const newModal = document.querySelector('.fixed') - expect(newModal).toBeInTheDocument() + expect(newModal)!.toBeInTheDocument() }) } break @@ -2451,7 +2605,7 @@ describe('Authorized Component', () => { // Wait for modal await waitFor(() => { - expect(document.querySelector('.fixed')).toBeInTheDocument() + expect(document.querySelector('.fixed'))!.toBeInTheDocument() }) // Close the modal via cancel @@ -2468,7 +2622,7 @@ describe('Authorized Component', () => { // Verify component can render again normally await waitFor(() => { - expect(screen.getByText('API Keys')).toBeInTheDocument() + expect(screen.getByText('API Keys'))!.toBeInTheDocument() }) // Verify we can open the modal again (state was properly reset) @@ -2481,7 +2635,7 @@ describe('Authorized Component', () => { }) await waitFor(() => { - expect(document.querySelector('.fixed')).toBeInTheDocument() + expect(document.querySelector('.fixed'))!.toBeInTheDocument() }) } } @@ -2518,7 +2672,7 @@ describe('Authorized Component', () => { // Confirm dialog should appear with the correct credential id await waitFor(() => { - expect(screen.getByText('datasetDocuments.list.delete.title')).toBeInTheDocument() + expect(screen.getByText('datasetDocuments.list.delete.title'))!.toBeInTheDocument() }) // Now click confirm to verify the correct id is used diff --git a/web/app/components/plugins/plugin-auth/hooks/__tests__/use-credential.spec.ts b/web/app/components/plugins/plugin-auth/hooks/__tests__/use-credential.spec.ts index 7777fbff97..e0e241cbbe 100644 --- a/web/app/components/plugins/plugin-auth/hooks/__tests__/use-credential.spec.ts +++ b/web/app/components/plugins/plugin-auth/hooks/__tests__/use-credential.spec.ts @@ -90,7 +90,7 @@ describe('use-credential hooks', () => { result.current() - const invalidFn = mockUseInvalidPluginCredentialInfo.mock.results[0].value + const invalidFn = mockUseInvalidPluginCredentialInfo.mock.results[0]!.value expect(invalidFn).toHaveBeenCalled() expect(mockInvalidToolsByType).toHaveBeenCalled() }) diff --git a/web/app/components/plugins/plugin-detail-panel/__tests__/agent-strategy-list.spec.tsx b/web/app/components/plugins/plugin-detail-panel/__tests__/agent-strategy-list.spec.tsx index 34015c0487..02a2431ead 100644 --- a/web/app/components/plugins/plugin-detail-panel/__tests__/agent-strategy-list.spec.tsx +++ b/web/app/components/plugins/plugin-detail-panel/__tests__/agent-strategy-list.spec.tsx @@ -81,15 +81,15 @@ describe('AgentStrategyList', () => { it('should render strategy items when data is available', () => { render() - expect(screen.getByText('plugin.detailPanel.strategyNum:{"num":1,"strategy":"strategy"}')).toBeInTheDocument() - expect(screen.getByTestId('strategy-item')).toBeInTheDocument() + expect(screen.getByText('plugin.detailPanel.strategyNum:{"num":1,"strategy":"strategy"}'))!.toBeInTheDocument() + expect(screen.getByTestId('strategy-item'))!.toBeInTheDocument() }) it('should return null when no strategy provider detail', () => { mockStrategyProviderDetail = undefined const { container } = render() - expect(container).toBeEmptyDOMElement() + expect(container)!.toBeEmptyDOMElement() }) it('should render multiple strategies', () => { @@ -98,13 +98,13 @@ describe('AgentStrategyList', () => { identity: { author: 'test', name: 'test' }, strategies: [ ...mockStrategies, - { ...mockStrategies[0], identity: { ...mockStrategies[0].identity, name: 'strategy-2' } }, + { ...mockStrategies[0]!, identity: { ...mockStrategies[0]!.identity, name: 'strategy-2' } }, ], }, } render() - expect(screen.getByText('plugin.detailPanel.strategyNum:{"num":2,"strategy":"strategies"}')).toBeInTheDocument() + expect(screen.getByText('plugin.detailPanel.strategyNum:{"num":2,"strategy":"strategies"}'))!.toBeInTheDocument() expect(screen.getAllByTestId('strategy-item')).toHaveLength(2) }) }) @@ -115,7 +115,7 @@ describe('AgentStrategyList', () => { detail.tenant_id = 'custom-tenant' render() - expect(screen.getByTestId('strategy-item')).toBeInTheDocument() + expect(screen.getByTestId('strategy-item'))!.toBeInTheDocument() }) }) }) diff --git a/web/app/components/plugins/plugin-detail-panel/__tests__/detail-header.spec.tsx b/web/app/components/plugins/plugin-detail-panel/__tests__/detail-header.spec.tsx index 74ce8525a9..0eacbf3bd3 100644 --- a/web/app/components/plugins/plugin-detail-panel/__tests__/detail-header.spec.tsx +++ b/web/app/components/plugins/plugin-detail-panel/__tests__/detail-header.spec.tsx @@ -297,13 +297,13 @@ describe('DetailHeader', () => { it('should render plugin title', () => { render() - expect(screen.getByTestId('title')).toBeInTheDocument() + expect(screen.getByTestId('title'))!.toBeInTheDocument() }) it('should render plugin icon with correct src', () => { render() - expect(screen.getByTestId('card-icon')).toBeInTheDocument() + expect(screen.getByTestId('card-icon'))!.toBeInTheDocument() }) it('should render icon with http url directly', () => { @@ -315,13 +315,13 @@ describe('DetailHeader', () => { }) render() - expect(screen.getByTestId('card-icon')).toHaveAttribute('data-src', 'https://example.com/icon.png') + expect(screen.getByTestId('card-icon'))!.toHaveAttribute('data-src', 'https://example.com/icon.png') }) it('should render description when not in readme view', () => { render() - expect(screen.getByTestId('description')).toBeInTheDocument() + expect(screen.getByTestId('description'))!.toBeInTheDocument() }) it('should not render description in readme view', () => { @@ -333,7 +333,7 @@ describe('DetailHeader', () => { it('should render verified badge when verified', () => { render() - expect(screen.getByTestId('verified-badge')).toBeInTheDocument() + expect(screen.getByTestId('verified-badge'))!.toBeInTheDocument() }) }) @@ -346,7 +346,8 @@ describe('DetailHeader', () => { render() // Badge component should render with the version - expect(screen.getByText('1.0.0')).toBeInTheDocument() + // Badge component should render with the version + expect(screen.getByText('1.0.0'))!.toBeInTheDocument() }) it('should not show new version indicator when versions match', () => { @@ -357,7 +358,8 @@ describe('DetailHeader', () => { render() // Badge component should render with the version - expect(screen.getByText('1.0.0')).toBeInTheDocument() + // Badge component should render with the version + expect(screen.getByText('1.0.0'))!.toBeInTheDocument() }) it('should show update button when new version is available', () => { @@ -367,7 +369,7 @@ describe('DetailHeader', () => { }) render() - expect(screen.getByText('plugin.detailPanel.operation.update')).toBeInTheDocument() + expect(screen.getByText('plugin.detailPanel.operation.update'))!.toBeInTheDocument() }) it('should show update button for GitHub source', () => { @@ -377,7 +379,7 @@ describe('DetailHeader', () => { }) render() - expect(screen.getByText('plugin.detailPanel.operation.update')).toBeInTheDocument() + expect(screen.getByText('plugin.detailPanel.operation.update'))!.toBeInTheDocument() }) }) @@ -393,7 +395,7 @@ describe('DetailHeader', () => { render() - expect(screen.getByTestId('title')).toBeInTheDocument() + expect(screen.getByTestId('title'))!.toBeInTheDocument() }) it('should render component when strategy is disabled', () => { @@ -407,7 +409,7 @@ describe('DetailHeader', () => { render() - expect(screen.getByTestId('title')).toBeInTheDocument() + expect(screen.getByTestId('title'))!.toBeInTheDocument() }) it('should enable auto upgrade for update_all mode', () => { @@ -422,7 +424,8 @@ describe('DetailHeader', () => { render() // Auto upgrade badge should be rendered - expect(screen.getByTestId('title')).toBeInTheDocument() + // Auto upgrade badge should be rendered + expect(screen.getByTestId('title'))!.toBeInTheDocument() }) it('should enable auto upgrade for partial mode when plugin is included', () => { @@ -436,7 +439,7 @@ describe('DetailHeader', () => { render() - expect(screen.getByTestId('title')).toBeInTheDocument() + expect(screen.getByTestId('title'))!.toBeInTheDocument() }) it('should not enable auto upgrade for partial mode when plugin is not included', () => { @@ -450,7 +453,7 @@ describe('DetailHeader', () => { render() - expect(screen.getByTestId('title')).toBeInTheDocument() + expect(screen.getByTestId('title'))!.toBeInTheDocument() }) it('should enable auto upgrade for exclude mode when plugin is not excluded', () => { @@ -464,7 +467,7 @@ describe('DetailHeader', () => { render() - expect(screen.getByTestId('title')).toBeInTheDocument() + expect(screen.getByTestId('title'))!.toBeInTheDocument() }) it('should not enable auto upgrade for exclude mode when plugin is excluded', () => { @@ -478,7 +481,7 @@ describe('DetailHeader', () => { render() - expect(screen.getByTestId('title')).toBeInTheDocument() + expect(screen.getByTestId('title'))!.toBeInTheDocument() }) it('should not enable auto upgrade for non-marketplace plugins', () => { @@ -496,7 +499,7 @@ describe('DetailHeader', () => { }) render() - expect(screen.getByTestId('title')).toBeInTheDocument() + expect(screen.getByTestId('title'))!.toBeInTheDocument() }) it('should not enable auto upgrade when marketplace feature is disabled', () => { @@ -512,7 +515,8 @@ describe('DetailHeader', () => { render() // Component should still render but auto upgrade should be disabled - expect(screen.getByTestId('title')).toBeInTheDocument() + // Component should still render but auto upgrade should be disabled + expect(screen.getByTestId('title'))!.toBeInTheDocument() }) }) @@ -522,7 +526,7 @@ describe('DetailHeader', () => { // Find the close button (ActionButton with action-btn class) const actionButtons = screen.getAllByRole('button').filter(btn => btn.classList.contains('action-btn')) - fireEvent.click(actionButtons[actionButtons.length - 1]) + fireEvent.click(actionButtons[actionButtons.length - 1]!) expect(mockOnHide).toHaveBeenCalled() }) @@ -533,7 +537,7 @@ describe('DetailHeader', () => { const infoBtn = screen.getByTestId('info-btn') fireEvent.click(infoBtn) - expect(infoBtn).toBeInTheDocument() + expect(infoBtn)!.toBeInTheDocument() }) it('should have check version button available', () => { @@ -542,7 +546,7 @@ describe('DetailHeader', () => { const checkBtn = screen.getByTestId('check-version-btn') fireEvent.click(checkBtn) - expect(checkBtn).toBeInTheDocument() + expect(checkBtn)!.toBeInTheDocument() }) }) @@ -557,7 +561,7 @@ describe('DetailHeader', () => { const updateBtn = screen.getByText('plugin.detailPanel.operation.update') fireEvent.click(updateBtn) - expect(updateBtn).toBeInTheDocument() + expect(updateBtn)!.toBeInTheDocument() }) it('should have version picker select button', () => { @@ -566,7 +570,7 @@ describe('DetailHeader', () => { const selectBtn = screen.getByTestId('select-version-btn') fireEvent.click(selectBtn) - expect(selectBtn).toBeInTheDocument() + expect(selectBtn)!.toBeInTheDocument() }) it('should have downgrade button', () => { @@ -575,7 +579,7 @@ describe('DetailHeader', () => { const downgradeBtn = screen.getByTestId('select-downgrade-btn') fireEvent.click(downgradeBtn) - expect(downgradeBtn).toBeInTheDocument() + expect(downgradeBtn)!.toBeInTheDocument() }) }) @@ -651,7 +655,7 @@ describe('DetailHeader', () => { const removeBtn = screen.getByTestId('remove-btn') fireEvent.click(removeBtn) - expect(removeBtn).toBeInTheDocument() + expect(removeBtn)!.toBeInTheDocument() }) it('should have uninstallPlugin mock defined', () => { @@ -671,13 +675,13 @@ describe('DetailHeader', () => { }) render() - expect(screen.getByTestId('remove-btn')).toBeInTheDocument() + expect(screen.getByTestId('remove-btn'))!.toBeInTheDocument() }) it('should render correctly for tool plugin delete', () => { render() - expect(screen.getByTestId('remove-btn')).toBeInTheDocument() + expect(screen.getByTestId('remove-btn'))!.toBeInTheDocument() }) }) @@ -689,21 +693,21 @@ describe('DetailHeader', () => { }) render() - expect(screen.getByTestId('title')).toBeInTheDocument() + expect(screen.getByTestId('title'))!.toBeInTheDocument() }) it('should render local source icon', () => { const detail = createPluginDetail({ source: PluginSource.local }) render() - expect(screen.getByTestId('title')).toBeInTheDocument() + expect(screen.getByTestId('title'))!.toBeInTheDocument() }) it('should render debugging source icon', () => { const detail = createPluginDetail({ source: PluginSource.debugging }) render() - expect(screen.getByTestId('title')).toBeInTheDocument() + expect(screen.getByTestId('title'))!.toBeInTheDocument() }) it('should not render deprecation notice for non-marketplace source', () => { @@ -722,20 +726,20 @@ describe('DetailHeader', () => { }) render() - expect(screen.getByTestId('operation-dropdown')).toBeInTheDocument() + expect(screen.getByTestId('operation-dropdown'))!.toBeInTheDocument() }) it('should render marketplace source correctly', () => { render() - expect(screen.getByTestId('operation-dropdown')).toBeInTheDocument() + expect(screen.getByTestId('operation-dropdown'))!.toBeInTheDocument() }) it('should render local source correctly', () => { const detail = createPluginDetail({ source: PluginSource.local }) render() - expect(screen.getByTestId('operation-dropdown')).toBeInTheDocument() + expect(screen.getByTestId('operation-dropdown'))!.toBeInTheDocument() }) }) @@ -743,7 +747,7 @@ describe('DetailHeader', () => { it('should render plugin auth for tool category', () => { render() - expect(screen.getByTestId('plugin-auth')).toBeInTheDocument() + expect(screen.getByTestId('plugin-auth'))!.toBeInTheDocument() }) it('should not render plugin auth for non-tool category', () => { @@ -770,7 +774,7 @@ describe('DetailHeader', () => { const detail = createPluginDetail({ version: '' }) render() - expect(screen.getByTestId('title')).toBeInTheDocument() + expect(screen.getByTestId('title'))!.toBeInTheDocument() }) it('should handle plugin with name containing slash', () => { @@ -782,7 +786,7 @@ describe('DetailHeader', () => { }) render() - expect(screen.getByTestId('org-info')).toBeInTheDocument() + expect(screen.getByTestId('org-info'))!.toBeInTheDocument() }) it('should handle empty icon', () => { @@ -794,7 +798,7 @@ describe('DetailHeader', () => { }) render() - expect(screen.getByTestId('card-icon')).toHaveAttribute('data-src', '') + expect(screen.getByTestId('card-icon'))!.toHaveAttribute('data-src', '') }) }) @@ -805,7 +809,7 @@ describe('DetailHeader', () => { fireEvent.click(screen.getByTestId('remove-btn')) await waitFor(() => { - expect(screen.getByRole('alertdialog')).toBeInTheDocument() + expect(screen.getByRole('alertdialog'))!.toBeInTheDocument() }) }) @@ -814,7 +818,7 @@ describe('DetailHeader', () => { fireEvent.click(screen.getByTestId('remove-btn')) await waitFor(() => { - expect(screen.getByRole('alertdialog')).toBeInTheDocument() + expect(screen.getByRole('alertdialog'))!.toBeInTheDocument() }) fireEvent.click(screen.getByRole('button', { name: 'common.operation.cancel' })) @@ -829,7 +833,7 @@ describe('DetailHeader', () => { fireEvent.click(screen.getByTestId('remove-btn')) await waitFor(() => { - expect(screen.getByRole('alertdialog')).toBeInTheDocument() + expect(screen.getByRole('alertdialog'))!.toBeInTheDocument() }) fireEvent.click(screen.getByRole('button', { name: 'common.operation.confirm' })) @@ -844,7 +848,7 @@ describe('DetailHeader', () => { fireEvent.click(screen.getByTestId('remove-btn')) await waitFor(() => { - expect(screen.getByRole('alertdialog')).toBeInTheDocument() + expect(screen.getByRole('alertdialog'))!.toBeInTheDocument() }) fireEvent.click(screen.getByRole('button', { name: 'common.operation.confirm' })) @@ -865,7 +869,7 @@ describe('DetailHeader', () => { fireEvent.click(screen.getByTestId('remove-btn')) await waitFor(() => { - expect(screen.getByRole('alertdialog')).toBeInTheDocument() + expect(screen.getByRole('alertdialog'))!.toBeInTheDocument() }) fireEvent.click(screen.getByRole('button', { name: 'common.operation.confirm' })) @@ -880,7 +884,7 @@ describe('DetailHeader', () => { fireEvent.click(screen.getByTestId('remove-btn')) await waitFor(() => { - expect(screen.getByRole('alertdialog')).toBeInTheDocument() + expect(screen.getByRole('alertdialog'))!.toBeInTheDocument() }) fireEvent.click(screen.getByRole('button', { name: 'common.operation.confirm' })) @@ -895,7 +899,7 @@ describe('DetailHeader', () => { fireEvent.click(screen.getByTestId('remove-btn')) await waitFor(() => { - expect(screen.getByRole('alertdialog')).toBeInTheDocument() + expect(screen.getByRole('alertdialog'))!.toBeInTheDocument() }) fireEvent.click(screen.getByRole('button', { name: 'common.operation.confirm' })) @@ -917,7 +921,7 @@ describe('DetailHeader', () => { fireEvent.click(screen.getByText('plugin.detailPanel.operation.update')) await waitFor(() => { - expect(screen.getByTestId('update-modal')).toBeInTheDocument() + expect(screen.getByTestId('update-modal'))!.toBeInTheDocument() }) }) @@ -930,7 +934,7 @@ describe('DetailHeader', () => { fireEvent.click(screen.getByText('plugin.detailPanel.operation.update')) await waitFor(() => { - expect(screen.getByTestId('update-modal')).toBeInTheDocument() + expect(screen.getByTestId('update-modal'))!.toBeInTheDocument() }) fireEvent.click(screen.getByTestId('update-modal-save')) @@ -949,7 +953,7 @@ describe('DetailHeader', () => { fireEvent.click(screen.getByText('plugin.detailPanel.operation.update')) await waitFor(() => { - expect(screen.getByTestId('update-modal')).toBeInTheDocument() + expect(screen.getByTestId('update-modal'))!.toBeInTheDocument() }) fireEvent.click(screen.getByTestId('update-modal-cancel')) @@ -967,7 +971,7 @@ describe('DetailHeader', () => { fireEvent.click(screen.getByTestId('info-btn')) await waitFor(() => { - expect(screen.getByTestId('plugin-info')).toBeInTheDocument() + expect(screen.getByTestId('plugin-info'))!.toBeInTheDocument() }) }) @@ -976,7 +980,7 @@ describe('DetailHeader', () => { fireEvent.click(screen.getByTestId('info-btn')) await waitFor(() => { - expect(screen.getByTestId('plugin-info')).toBeInTheDocument() + expect(screen.getByTestId('plugin-info'))!.toBeInTheDocument() }) fireEvent.click(screen.getByTestId('plugin-info-close')) @@ -993,7 +997,7 @@ describe('DetailHeader', () => { }) render() - expect(screen.getByTestId('info-btn')).toBeInTheDocument() + expect(screen.getByTestId('info-btn'))!.toBeInTheDocument() }) }) }) diff --git a/web/app/components/plugins/plugin-detail-panel/__tests__/endpoint-card.spec.tsx b/web/app/components/plugins/plugin-detail-panel/__tests__/endpoint-card.spec.tsx index 3b87fdccb6..15c231cb17 100644 --- a/web/app/components/plugins/plugin-detail-panel/__tests__/endpoint-card.spec.tsx +++ b/web/app/components/plugins/plugin-detail-panel/__tests__/endpoint-card.spec.tsx @@ -161,30 +161,30 @@ describe('EndpointCard', () => { it('should render endpoint name', () => { render() - expect(screen.getByText('Test Endpoint')).toBeInTheDocument() + expect(screen.getByText('Test Endpoint'))!.toBeInTheDocument() }) it('should render visible endpoints only', () => { render() - expect(screen.getByText('GET')).toBeInTheDocument() - expect(screen.getByText('https://api.example.com/api/test')).toBeInTheDocument() + expect(screen.getByText('GET'))!.toBeInTheDocument() + expect(screen.getByText('https://api.example.com/api/test'))!.toBeInTheDocument() expect(screen.queryByText('POST')).not.toBeInTheDocument() }) it('should show active status when enabled', () => { render() - expect(screen.getByText('plugin.detailPanel.serviceOk')).toBeInTheDocument() - expect(screen.getByTestId('indicator')).toHaveAttribute('data-color', 'green') + expect(screen.getByText('plugin.detailPanel.serviceOk'))!.toBeInTheDocument() + expect(screen.getByTestId('indicator'))!.toHaveAttribute('data-color', 'green') }) it('should show disabled status when not enabled', () => { const disabledData = { ...mockEndpointData, enabled: false } render() - expect(screen.getByText('plugin.detailPanel.disabled')).toBeInTheDocument() - expect(screen.getByTestId('indicator')).toHaveAttribute('data-color', 'gray') + expect(screen.getByText('plugin.detailPanel.disabled'))!.toBeInTheDocument() + expect(screen.getByTestId('indicator'))!.toHaveAttribute('data-color', 'gray') }) }) @@ -194,7 +194,7 @@ describe('EndpointCard', () => { fireEvent.click(screen.getByRole('switch')) - expect(screen.getByText('plugin.detailPanel.endpointDisableTip')).toBeInTheDocument() + expect(screen.getByText('plugin.detailPanel.endpointDisableTip'))!.toBeInTheDocument() }) it('should call disableEndpoint when confirm disable', () => { @@ -211,16 +211,16 @@ describe('EndpointCard', () => { render() const allButtons = screen.getAllByRole('button') - fireEvent.click(allButtons[1]) + fireEvent.click(allButtons[1]!) - expect(screen.getByText('plugin.detailPanel.endpointDeleteTip')).toBeInTheDocument() + expect(screen.getByText('plugin.detailPanel.endpointDeleteTip'))!.toBeInTheDocument() }) it('should call deleteEndpoint when confirm delete', () => { render() const allButtons = screen.getAllByRole('button') - fireEvent.click(allButtons[1]) + fireEvent.click(allButtons[1]!) fireEvent.click(screen.getByRole('button', { name: 'common.operation.confirm' })) expect(mockDeleteEndpoint).toHaveBeenCalledWith('ep-1') @@ -230,16 +230,16 @@ describe('EndpointCard', () => { render() const allButtons = screen.getAllByRole('button') - fireEvent.click(allButtons[0]) + fireEvent.click(allButtons[0]!) - expect(screen.getByTestId('endpoint-modal')).toBeInTheDocument() + expect(screen.getByTestId('endpoint-modal'))!.toBeInTheDocument() }) it('should call updateEndpoint when save in modal', () => { render() const allButtons = screen.getAllByRole('button') - fireEvent.click(allButtons[0]) + fireEvent.click(allButtons[0]!) fireEvent.click(screen.getByTestId('modal-save')) expect(mockUpdateEndpoint).toHaveBeenCalled() @@ -252,13 +252,13 @@ describe('EndpointCard', () => { render() const allButtons = screen.getAllByRole('button') - fireEvent.click(allButtons[2]) + fireEvent.click(allButtons[2]!) act(() => { vi.advanceTimersByTime(2000) }) - expect(screen.getByText('Test Endpoint')).toBeInTheDocument() + expect(screen.getByText('Test Endpoint'))!.toBeInTheDocument() }) }) @@ -270,7 +270,7 @@ describe('EndpointCard', () => { } render() - expect(screen.getByText('Test Endpoint')).toBeInTheDocument() + expect(screen.getByText('Test Endpoint'))!.toBeInTheDocument() }) it('should call handleChange after enable', () => { @@ -286,20 +286,20 @@ describe('EndpointCard', () => { render() fireEvent.click(screen.getByRole('switch')) - expect(screen.getByText('plugin.detailPanel.endpointDisableTip')).toBeInTheDocument() + expect(screen.getByText('plugin.detailPanel.endpointDisableTip'))!.toBeInTheDocument() fireEvent.click(screen.getByRole('button', { name: 'common.operation.cancel' })) await waitForAlertDialogToClose() - expect(screen.getByRole('switch')).toHaveAttribute('aria-checked', 'true') + expect(screen.getByRole('switch'))!.toHaveAttribute('aria-checked', 'true') }) it('should hide delete confirm when cancel clicked', async () => { render() const allButtons = screen.getAllByRole('button') - fireEvent.click(allButtons[1]) - expect(screen.getByText('plugin.detailPanel.endpointDeleteTip')).toBeInTheDocument() + fireEvent.click(allButtons[1]!) + expect(screen.getByText('plugin.detailPanel.endpointDeleteTip'))!.toBeInTheDocument() fireEvent.click(screen.getByRole('button', { name: 'common.operation.cancel' })) await waitForAlertDialogToClose() @@ -309,8 +309,8 @@ describe('EndpointCard', () => { render() const allButtons = screen.getAllByRole('button') - fireEvent.click(allButtons[0]) - expect(screen.getByTestId('endpoint-modal')).toBeInTheDocument() + fireEvent.click(allButtons[0]!) + expect(screen.getByTestId('endpoint-modal'))!.toBeInTheDocument() fireEvent.click(screen.getByTestId('modal-cancel')) @@ -344,7 +344,7 @@ describe('EndpointCard', () => { render() const allButtons = screen.getAllByRole('button') - fireEvent.click(allButtons[1]) + fireEvent.click(allButtons[1]!) fireEvent.click(screen.getByRole('button', { name: 'common.operation.confirm' })) expect(mockDeleteEndpoint).toHaveBeenCalled() @@ -354,9 +354,9 @@ describe('EndpointCard', () => { render() const allButtons = screen.getAllByRole('button') - fireEvent.click(allButtons[0]) + fireEvent.click(allButtons[0]!) - expect(screen.getByTestId('endpoint-modal')).toBeInTheDocument() + expect(screen.getByTestId('endpoint-modal'))!.toBeInTheDocument() failureFlags.update = true fireEvent.click(screen.getByTestId('modal-save')) diff --git a/web/app/components/plugins/plugin-detail-panel/__tests__/endpoint-list.spec.tsx b/web/app/components/plugins/plugin-detail-panel/__tests__/endpoint-list.spec.tsx index 50d63742ac..e31afc7cb2 100644 --- a/web/app/components/plugins/plugin-detail-panel/__tests__/endpoint-list.spec.tsx +++ b/web/app/components/plugins/plugin-detail-panel/__tests__/endpoint-list.spec.tsx @@ -85,28 +85,28 @@ describe('EndpointList', () => { it('should render endpoint list', () => { render() - expect(screen.getByText('plugin.detailPanel.endpoints')).toBeInTheDocument() + expect(screen.getByText('plugin.detailPanel.endpoints'))!.toBeInTheDocument() }) it('should render endpoint cards', () => { render() - expect(screen.getByTestId('endpoint-card')).toBeInTheDocument() - expect(screen.getByText('Endpoint 1')).toBeInTheDocument() + expect(screen.getByTestId('endpoint-card'))!.toBeInTheDocument() + expect(screen.getByText('Endpoint 1'))!.toBeInTheDocument() }) it('should return null when no data', () => { mockEndpointListData = undefined const { container } = render() - expect(container).toBeEmptyDOMElement() + expect(container)!.toBeEmptyDOMElement() }) it('should show empty message when no endpoints', () => { mockEndpointListData = { endpoints: [] } render() - expect(screen.getByText('plugin.detailPanel.endpointsEmpty')).toBeInTheDocument() + expect(screen.getByText('plugin.detailPanel.endpointsEmpty'))!.toBeInTheDocument() }) it('should render add button', () => { @@ -121,17 +121,17 @@ describe('EndpointList', () => { render() const addButton = screen.getAllByRole('button')[0] - fireEvent.click(addButton) + fireEvent.click(addButton!) - expect(screen.getByTestId('endpoint-modal')).toBeInTheDocument() + expect(screen.getByTestId('endpoint-modal'))!.toBeInTheDocument() }) it('should hide modal when cancel clicked', () => { render() const addButton = screen.getAllByRole('button')[0] - fireEvent.click(addButton) - expect(screen.getByTestId('endpoint-modal')).toBeInTheDocument() + fireEvent.click(addButton!) + expect(screen.getByTestId('endpoint-modal'))!.toBeInTheDocument() fireEvent.click(screen.getByTestId('modal-cancel')) expect(screen.queryByTestId('endpoint-modal')).not.toBeInTheDocument() @@ -141,7 +141,7 @@ describe('EndpointList', () => { render() const addButton = screen.getAllByRole('button')[0] - fireEvent.click(addButton) + fireEvent.click(addButton!) fireEvent.click(screen.getByTestId('modal-save')) expect(mockCreateEndpoint).toHaveBeenCalled() @@ -154,7 +154,7 @@ describe('EndpointList', () => { detail.declaration.tool = {} as PluginDetail['declaration']['tool'] render() - expect(screen.getByText('plugin.detailPanel.endpoints')).toBeInTheDocument() + expect(screen.getByText('plugin.detailPanel.endpoints'))!.toBeInTheDocument() }) }) @@ -177,7 +177,7 @@ describe('EndpointList', () => { render() const addButton = screen.getAllByRole('button')[0] - fireEvent.click(addButton) + fireEvent.click(addButton!) fireEvent.click(screen.getByTestId('modal-save')) expect(mockInvalidateEndpointList).toHaveBeenCalledWith('test-plugin') @@ -187,7 +187,7 @@ describe('EndpointList', () => { render() const addButton = screen.getAllByRole('button')[0] - fireEvent.click(addButton) + fireEvent.click(addButton!) fireEvent.click(screen.getByTestId('modal-save')) expect(mockCreateEndpoint).toHaveBeenCalledWith({ diff --git a/web/app/components/plugins/plugin-detail-panel/__tests__/endpoint-modal.spec.tsx b/web/app/components/plugins/plugin-detail-panel/__tests__/endpoint-modal.spec.tsx index a467de7142..0be17f07d4 100644 --- a/web/app/components/plugins/plugin-detail-panel/__tests__/endpoint-modal.spec.tsx +++ b/web/app/components/plugins/plugin-detail-panel/__tests__/endpoint-modal.spec.tsx @@ -101,7 +101,7 @@ describe('EndpointModal', () => { />, ) - expect(screen.getByRole('dialog')).toBeInTheDocument() + expect(screen.getByRole('dialog'))!.toBeInTheDocument() }) it('should render title and description', () => { @@ -114,8 +114,8 @@ describe('EndpointModal', () => { />, ) - expect(screen.getByText('plugin.detailPanel.endpointModalTitle')).toBeInTheDocument() - expect(screen.getByText('plugin.detailPanel.endpointModalDesc')).toBeInTheDocument() + expect(screen.getByText('plugin.detailPanel.endpointModalTitle'))!.toBeInTheDocument() + expect(screen.getByText('plugin.detailPanel.endpointModalDesc'))!.toBeInTheDocument() }) it('should render form with fieldMoreInfo url link', () => { @@ -128,8 +128,8 @@ describe('EndpointModal', () => { />, ) - expect(screen.getByTestId('field-more-info')).toBeInTheDocument() - expect(screen.getByText('tools.howToGet')).toBeInTheDocument() + expect(screen.getByTestId('field-more-info'))!.toBeInTheDocument() + expect(screen.getByText('tools.howToGet'))!.toBeInTheDocument() }) it('should render readme entrance', () => { @@ -142,7 +142,7 @@ describe('EndpointModal', () => { />, ) - expect(screen.getByTestId('readme-entrance')).toBeInTheDocument() + expect(screen.getByTestId('readme-entrance'))!.toBeInTheDocument() }) }) @@ -173,7 +173,7 @@ describe('EndpointModal', () => { ) const allButtons = screen.getAllByRole('button') - fireEvent.click(allButtons[0]) + fireEvent.click(allButtons[0]!) expect(mockOnCancel).toHaveBeenCalledTimes(1) }) @@ -191,7 +191,7 @@ describe('EndpointModal', () => { const input = screen.getByTestId('form-input') fireEvent.change(input, { target: { value: 'Test Name' } }) - expect(input).toHaveValue('Test Name') + expect(input)!.toHaveValue('Test Name') }) }) @@ -207,7 +207,7 @@ describe('EndpointModal', () => { />, ) - expect(screen.getByTestId('form-input')).toHaveValue('Default Name') + expect(screen.getByTestId('form-input'))!.toHaveValue('Default Name') }) it('should extract default values from schemas when no defaultValues', () => { @@ -224,7 +224,7 @@ describe('EndpointModal', () => { />, ) - expect(screen.getByTestId('form-input')).toHaveValue('Schema Default') + expect(screen.getByTestId('form-input'))!.toHaveValue('Schema Default') }) it('should handle schemas without default values', () => { @@ -241,7 +241,7 @@ describe('EndpointModal', () => { />, ) - expect(screen.getByTestId('form')).toBeInTheDocument() + expect(screen.getByTestId('form'))!.toBeInTheDocument() }) }) diff --git a/web/app/components/plugins/plugin-detail-panel/__tests__/strategy-detail.spec.tsx b/web/app/components/plugins/plugin-detail-panel/__tests__/strategy-detail.spec.tsx index 350bf6956b..b5fbc03b45 100644 --- a/web/app/components/plugins/plugin-detail-panel/__tests__/strategy-detail.spec.tsx +++ b/web/app/components/plugins/plugin-detail-panel/__tests__/strategy-detail.spec.tsx @@ -69,40 +69,40 @@ describe('StrategyDetail', () => { it('should render drawer', () => { render() - expect(screen.getByRole('dialog')).toBeInTheDocument() + expect(screen.getByRole('dialog'))!.toBeInTheDocument() }) it('should render provider label', () => { render() - expect(screen.getByText('Test Provider')).toBeInTheDocument() + expect(screen.getByText('Test Provider'))!.toBeInTheDocument() }) it('should render strategy label', () => { render() - expect(screen.getByText('Strategy Label')).toBeInTheDocument() + expect(screen.getByText('Strategy Label'))!.toBeInTheDocument() }) it('should render parameters section', () => { render() - expect(screen.getByText('tools.setBuiltInTools.parameters')).toBeInTheDocument() - expect(screen.getByText('Parameter 1')).toBeInTheDocument() + expect(screen.getByText('tools.setBuiltInTools.parameters'))!.toBeInTheDocument() + expect(screen.getByText('Parameter 1'))!.toBeInTheDocument() }) it('should render output schema section', () => { render() - expect(screen.getByText('OUTPUT')).toBeInTheDocument() - expect(screen.getByText('result')).toBeInTheDocument() - expect(screen.getByText('String')).toBeInTheDocument() + expect(screen.getByText('OUTPUT'))!.toBeInTheDocument() + expect(screen.getByText('result'))!.toBeInTheDocument() + expect(screen.getByText('String'))!.toBeInTheDocument() }) it('should render BACK button', () => { render() - expect(screen.getByText('BACK')).toBeInTheDocument() + expect(screen.getByText('BACK'))!.toBeInTheDocument() }) }) @@ -131,51 +131,51 @@ describe('StrategyDetail', () => { it('should display correct type for number-input', () => { const detailWithNumber = { ...mockDetail, - parameters: [{ ...mockDetail.parameters[0], type: 'number-input' }], + parameters: [{ ...mockDetail.parameters[0]!, type: 'number-input' }], } render() - expect(screen.getByText('tools.setBuiltInTools.number')).toBeInTheDocument() + expect(screen.getByText('tools.setBuiltInTools.number'))!.toBeInTheDocument() }) it('should display correct type for checkbox', () => { const detailWithCheckbox = { ...mockDetail, - parameters: [{ ...mockDetail.parameters[0], type: 'checkbox' }], + parameters: [{ ...mockDetail.parameters[0]!, type: 'checkbox' }], } render() - expect(screen.getByText('boolean')).toBeInTheDocument() + expect(screen.getByText('boolean'))!.toBeInTheDocument() }) it('should display correct type for file', () => { const detailWithFile = { ...mockDetail, - parameters: [{ ...mockDetail.parameters[0], type: 'file' }], + parameters: [{ ...mockDetail.parameters[0]!, type: 'file' }], } render() - expect(screen.getByText('tools.setBuiltInTools.file')).toBeInTheDocument() + expect(screen.getByText('tools.setBuiltInTools.file'))!.toBeInTheDocument() }) it('should display correct type for array[tools]', () => { const detailWithArrayTools = { ...mockDetail, - parameters: [{ ...mockDetail.parameters[0], type: 'array[tools]' }], + parameters: [{ ...mockDetail.parameters[0]!, type: 'array[tools]' }], } render() - expect(screen.getByText('multiple-tool-select')).toBeInTheDocument() + expect(screen.getByText('multiple-tool-select'))!.toBeInTheDocument() }) it('should display original type for unknown types', () => { const detailWithUnknown = { ...mockDetail, - parameters: [{ ...mockDetail.parameters[0], type: 'custom-type' }], + parameters: [{ ...mockDetail.parameters[0]!, type: 'custom-type' }], } render() - expect(screen.getByText('custom-type')).toBeInTheDocument() + expect(screen.getByText('custom-type'))!.toBeInTheDocument() }) }) @@ -184,7 +184,7 @@ describe('StrategyDetail', () => { const detailEmpty = { ...mockDetail, parameters: [] } render() - expect(screen.getByText('tools.setBuiltInTools.parameters')).toBeInTheDocument() + expect(screen.getByText('tools.setBuiltInTools.parameters'))!.toBeInTheDocument() }) it('should handle no output schema', () => { diff --git a/web/app/components/plugins/plugin-detail-panel/app-selector/__tests__/index.spec.tsx b/web/app/components/plugins/plugin-detail-panel/app-selector/__tests__/index.spec.tsx index 4dd604a03e..f7dd1921e4 100644 --- a/web/app/components/plugins/plugin-detail-panel/app-selector/__tests__/index.spec.tsx +++ b/web/app/components/plugins/plugin-detail-panel/app-selector/__tests__/index.spec.tsx @@ -393,19 +393,20 @@ describe('AppTrigger', () => { it('should render placeholder when no app is selected', () => { render() // i18n mock returns key with namespace in dot format - expect(screen.getByText('app.appSelector.placeholder')).toBeInTheDocument() + // i18n mock returns key with namespace in dot format + expect(screen.getByText('app.appSelector.placeholder'))!.toBeInTheDocument() }) it('should render app details when app is selected', () => { const app = createMockApp({ name: 'My Test App' }) render() - expect(screen.getByText('My Test App')).toBeInTheDocument() + expect(screen.getByText('My Test App'))!.toBeInTheDocument() }) it('should apply open state styling', () => { const { container } = render() const trigger = container.querySelector('.bg-state-base-hover-alt') - expect(trigger).toBeInTheDocument() + expect(trigger)!.toBeInTheDocument() }) it('should render AppIcon when app is provided', () => { @@ -413,21 +414,21 @@ describe('AppTrigger', () => { const { container } = render() // AppIcon renders with a specific class when app is provided const iconContainer = container.querySelector('.mr-2') - expect(iconContainer).toBeInTheDocument() + expect(iconContainer)!.toBeInTheDocument() }) }) describe('Props', () => { it('should handle undefined appDetail gracefully', () => { render() - expect(screen.getByText('app.appSelector.placeholder')).toBeInTheDocument() + expect(screen.getByText('app.appSelector.placeholder'))!.toBeInTheDocument() }) it('should display app name with title attribute', () => { const app = createMockApp({ name: 'Long App Name For Testing' }) render() const nameElement = screen.getByTitle('Long App Name For Testing') - expect(nameElement).toBeInTheDocument() + expect(nameElement)!.toBeInTheDocument() }) }) @@ -435,14 +436,14 @@ describe('AppTrigger', () => { it('should have correct base classes', () => { const { container } = render() const trigger = container.firstChild as HTMLElement - expect(trigger).toHaveClass('group', 'flex', 'cursor-pointer') + expect(trigger)!.toHaveClass('group', 'flex', 'cursor-pointer') }) it('should apply different padding when app is provided', () => { const app = createMockApp() const { container } = render() const trigger = container.firstChild as HTMLElement - expect(trigger).toHaveClass('py-1.5', 'pl-1.5') + expect(trigger)!.toHaveClass('py-1.5', 'pl-1.5') }) }) }) @@ -479,18 +480,18 @@ describe('AppPicker', () => { describe('Rendering', () => { it('should render trigger element', () => { render() - expect(screen.getByText('Select App')).toBeInTheDocument() + expect(screen.getByText('Select App'))!.toBeInTheDocument() }) it('should render app list when open', () => { render() - expect(screen.getByText('App 1')).toBeInTheDocument() - expect(screen.getByText('App 2')).toBeInTheDocument() + expect(screen.getByText('App 1'))!.toBeInTheDocument() + expect(screen.getByText('App 2'))!.toBeInTheDocument() }) it('should show loading indicator when isLoading is true', () => { render() - expect(screen.getByText('common.loading')).toBeInTheDocument() + expect(screen.getByText('common.loading'))!.toBeInTheDocument() }) it('should not render content when isShow is false', () => { @@ -538,31 +539,31 @@ describe('AppPicker', () => { it('should display correct app type for CHAT', () => { const apps = [createMockApp({ id: 'chat-app', name: 'Chat App', mode: AppModeEnum.CHAT })] render() - expect(screen.getByText('chat')).toBeInTheDocument() + expect(screen.getByText('chat'))!.toBeInTheDocument() }) it('should display correct app type for WORKFLOW', () => { const apps = [createMockApp({ id: 'workflow-app', name: 'Workflow App', mode: AppModeEnum.WORKFLOW })] render() - expect(screen.getByText('workflow')).toBeInTheDocument() + expect(screen.getByText('workflow'))!.toBeInTheDocument() }) it('should display correct app type for ADVANCED_CHAT', () => { const apps = [createMockApp({ id: 'chatflow-app', name: 'Chatflow App', mode: AppModeEnum.ADVANCED_CHAT })] render() - expect(screen.getByText('chatflow')).toBeInTheDocument() + expect(screen.getByText('chatflow'))!.toBeInTheDocument() }) it('should display correct app type for AGENT_CHAT', () => { const apps = [createMockApp({ id: 'agent-app', name: 'Agent App', mode: AppModeEnum.AGENT_CHAT })] render() - expect(screen.getByText('agent')).toBeInTheDocument() + expect(screen.getByText('agent'))!.toBeInTheDocument() }) it('should display correct app type for COMPLETION', () => { const apps = [createMockApp({ id: 'completion-app', name: 'Completion App', mode: AppModeEnum.COMPLETION })] render() - expect(screen.getByText('completion')).toBeInTheDocument() + expect(screen.getByText('completion'))!.toBeInTheDocument() }) }) @@ -575,7 +576,7 @@ describe('AppPicker', () => { it('should handle search text with value', () => { render() const input = screen.getByTestId('input') - expect(input).toHaveValue('test search') + expect(input)!.toHaveValue('test search') }) }) @@ -641,7 +642,8 @@ describe('AppPicker', () => { render() // The component should render without errors - expect(screen.getByTestId('portal-to-follow-elem')).toBeInTheDocument() + // The component should render without errors + expect(screen.getByTestId('portal-to-follow-elem'))!.toBeInTheDocument() }) it('should handle isShow toggle correctly', () => { @@ -654,7 +656,8 @@ describe('AppPicker', () => { rerender() // Should not crash - expect(screen.getByTestId('portal-to-follow-elem')).toBeInTheDocument() + // Should not crash + expect(screen.getByTestId('portal-to-follow-elem'))!.toBeInTheDocument() }) it('should setup intersection observer when isShow is true', () => { @@ -674,7 +677,8 @@ describe('AppPicker', () => { rerender() // Component should render without errors - expect(screen.getByTestId('portal-to-follow-elem')).toBeInTheDocument() + // Component should render without errors + expect(screen.getByTestId('portal-to-follow-elem'))!.toBeInTheDocument() }) it('should cleanup observer on component unmount', () => { @@ -691,7 +695,8 @@ describe('AppPicker', () => { triggerMutationObserver() // Component should still work correctly - expect(screen.getByTestId('portal-to-follow-elem')).toBeInTheDocument() + // Component should still work correctly + expect(screen.getByTestId('portal-to-follow-elem'))!.toBeInTheDocument() }) it('should not setup IntersectionObserver when observerTarget is null', () => { @@ -699,7 +704,8 @@ describe('AppPicker', () => { render() // The guard at line 84 should prevent setup - expect(screen.getByTestId('portal-to-follow-elem')).toBeInTheDocument() + // The guard at line 84 should prevent setup + expect(screen.getByTestId('portal-to-follow-elem'))!.toBeInTheDocument() }) it('should debounce onLoadMore calls using loadingRef', () => { @@ -798,8 +804,8 @@ describe('AppInputsForm', () => { { type: InputVarType.textInput, label: 'Name', variable: 'name', required: false }, ] render() - expect(screen.getByText('Name')).toBeInTheDocument() - expect(screen.getByPlaceholderText('Name')).toBeInTheDocument() + expect(screen.getByText('Name'))!.toBeInTheDocument() + expect(screen.getByPlaceholderText('Name'))!.toBeInTheDocument() }) it('should render number input field', () => { @@ -807,7 +813,7 @@ describe('AppInputsForm', () => { { type: InputVarType.number, label: 'Count', variable: 'count', required: false }, ] render() - expect(screen.getByText('Count')).toBeInTheDocument() + expect(screen.getByText('Count'))!.toBeInTheDocument() }) it('should render paragraph (textarea) field', () => { @@ -815,7 +821,7 @@ describe('AppInputsForm', () => { { type: InputVarType.paragraph, label: 'Description', variable: 'desc', required: false }, ] render() - expect(screen.getByText('Description')).toBeInTheDocument() + expect(screen.getByText('Description'))!.toBeInTheDocument() }) it('should render select field', () => { @@ -840,8 +846,8 @@ describe('AppInputsForm', () => { }, ] render() - expect(screen.getByText('Single File Upload')).toBeInTheDocument() - expect(screen.getByTestId('file-uploader')).toBeInTheDocument() + expect(screen.getByText('Single File Upload'))!.toBeInTheDocument() + expect(screen.getByTestId('file-uploader'))!.toBeInTheDocument() }) it('should render file uploader for single file with existing value', () => { @@ -859,7 +865,8 @@ describe('AppInputsForm', () => { ] render() // The file uploader should receive the existing file as an array - expect(screen.getByTestId('file-value')).toHaveTextContent(JSON.stringify([existingFile])) + // The file uploader should receive the existing file as an array + expect(screen.getByTestId('file-value'))!.toHaveTextContent(JSON.stringify([existingFile])) }) it('should render file uploader for multi files', () => { @@ -876,7 +883,7 @@ describe('AppInputsForm', () => { }, ] render() - expect(screen.getByText('Attachments')).toBeInTheDocument() + expect(screen.getByText('Attachments'))!.toBeInTheDocument() }) it('should show optional label for non-required fields', () => { @@ -884,7 +891,7 @@ describe('AppInputsForm', () => { { type: InputVarType.textInput, label: 'Name', variable: 'name', required: false }, ] render() - expect(screen.getByText('workflow.panel.optional')).toBeInTheDocument() + expect(screen.getByText('workflow.panel.optional'))!.toBeInTheDocument() }) it('should not show optional label for required fields', () => { @@ -1026,7 +1033,7 @@ describe('AppInputsForm', () => { render() const input = screen.getByPlaceholderText('Name') - expect(input).toHaveValue('existing') + expect(input)!.toHaveValue('existing') }) it('should handle empty string value', () => { @@ -1036,7 +1043,7 @@ describe('AppInputsForm', () => { render() const input = screen.getByPlaceholderText('Name') - expect(input).toHaveValue('') + expect(input)!.toHaveValue('') }) it('should handle undefined variable value', () => { @@ -1046,7 +1053,7 @@ describe('AppInputsForm', () => { render() const input = screen.getByPlaceholderText('Name') - expect(input).toHaveValue('') + expect(input)!.toHaveValue('') }) it('should handle multiple form fields', () => { @@ -1057,9 +1064,9 @@ describe('AppInputsForm', () => { ] render() - expect(screen.getByText('Name')).toBeInTheDocument() - expect(screen.getByText('Age')).toBeInTheDocument() - expect(screen.getByText('Bio')).toBeInTheDocument() + expect(screen.getByText('Name'))!.toBeInTheDocument() + expect(screen.getByText('Age'))!.toBeInTheDocument() + expect(screen.getByText('Bio'))!.toBeInTheDocument() }) it('should handle unknown form type gracefully', () => { @@ -1068,7 +1075,7 @@ describe('AppInputsForm', () => { ] // Should not throw error, just not render the field render() - expect(screen.getByText('Unknown')).toBeInTheDocument() + expect(screen.getByText('Unknown'))!.toBeInTheDocument() }) }) }) @@ -1093,18 +1100,49 @@ describe('AppInputsPanel', () => { describe('Rendering', () => { it('should render without crashing', () => { renderWithQueryClient() - expect(screen.getByText('app.appSelector.params')).toBeInTheDocument() + expect(screen.getByText('app.appSelector.params'))!.toBeInTheDocument() }) it('should show no params message when form schema is empty', () => { renderWithQueryClient() - expect(screen.getByText('app.appSelector.noParams')).toBeInTheDocument() + expect(screen.getByText('app.appSelector.noParams'))!.toBeInTheDocument() }) it('should show loading state when app is loading', () => { mockAppDetailLoading = true renderWithQueryClient() // Loading component should be rendered + // Loading component should be rendered + // Loading component should be rendered + // Loading component should be rendered + // Loading component should be rendered + // Loading component should be rendered + // Loading component should be rendered + // Loading component should be rendered + // Loading component should be rendered + // Loading component should be rendered + // Loading component should be rendered + // Loading component should be rendered + // Loading component should be rendered + // Loading component should be rendered + // Loading component should be rendered + // Loading component should be rendered + // Loading component should be rendered + // Loading component should be rendered + // Loading component should be rendered + // Loading component should be rendered + // Loading component should be rendered + // Loading component should be rendered + // Loading component should be rendered + // Loading component should be rendered + // Loading component should be rendered + // Loading component should be rendered + // Loading component should be rendered + // Loading component should be rendered + // Loading component should be rendered + // Loading component should be rendered + // Loading component should be rendered + // Loading component should be rendered expect(screen.queryByText('app.appSelector.params')).not.toBeInTheDocument() }) @@ -1119,19 +1157,19 @@ describe('AppInputsPanel', () => { describe('Props', () => { it('should handle undefined value', () => { renderWithQueryClient() - expect(screen.getByText('app.appSelector.params')).toBeInTheDocument() + expect(screen.getByText('app.appSelector.params'))!.toBeInTheDocument() }) it('should handle different app modes', () => { const workflowApp = createMockApp({ mode: AppModeEnum.WORKFLOW }) renderWithQueryClient() - expect(screen.getByText('app.appSelector.params')).toBeInTheDocument() + expect(screen.getByText('app.appSelector.params'))!.toBeInTheDocument() }) it('should handle advanced chat mode', () => { const advancedChatApp = createMockApp({ mode: AppModeEnum.ADVANCED_CHAT }) renderWithQueryClient() - expect(screen.getByText('app.appSelector.params')).toBeInTheDocument() + expect(screen.getByText('app.appSelector.params'))!.toBeInTheDocument() }) }) @@ -1147,7 +1185,7 @@ describe('AppInputsPanel', () => { }, }) renderWithQueryClient() - expect(screen.getByText('app.appSelector.params')).toBeInTheDocument() + expect(screen.getByText('app.appSelector.params'))!.toBeInTheDocument() }) it('should generate schema for number input', () => { @@ -1161,7 +1199,7 @@ describe('AppInputsPanel', () => { }, }) renderWithQueryClient() - expect(screen.getByText('app.appSelector.params')).toBeInTheDocument() + expect(screen.getByText('app.appSelector.params'))!.toBeInTheDocument() }) it('should generate schema for checkbox input', () => { @@ -1175,7 +1213,7 @@ describe('AppInputsPanel', () => { }, }) renderWithQueryClient() - expect(screen.getByText('app.appSelector.params')).toBeInTheDocument() + expect(screen.getByText('app.appSelector.params'))!.toBeInTheDocument() }) it('should generate schema for select input', () => { @@ -1189,7 +1227,7 @@ describe('AppInputsPanel', () => { }, }) renderWithQueryClient() - expect(screen.getByText('app.appSelector.params')).toBeInTheDocument() + expect(screen.getByText('app.appSelector.params'))!.toBeInTheDocument() }) it('should generate schema for file-list input', () => { @@ -1203,7 +1241,7 @@ describe('AppInputsPanel', () => { }, }) renderWithQueryClient() - expect(screen.getByText('app.appSelector.params')).toBeInTheDocument() + expect(screen.getByText('app.appSelector.params'))!.toBeInTheDocument() }) it('should generate schema for file input', () => { @@ -1217,7 +1255,7 @@ describe('AppInputsPanel', () => { }, }) renderWithQueryClient() - expect(screen.getByText('app.appSelector.params')).toBeInTheDocument() + expect(screen.getByText('app.appSelector.params'))!.toBeInTheDocument() }) it('should generate schema for json_object input', () => { @@ -1231,7 +1269,7 @@ describe('AppInputsPanel', () => { }, }) renderWithQueryClient() - expect(screen.getByText('app.appSelector.params')).toBeInTheDocument() + expect(screen.getByText('app.appSelector.params'))!.toBeInTheDocument() }) it('should generate schema for text-input (default)', () => { @@ -1245,7 +1283,7 @@ describe('AppInputsPanel', () => { }, }) renderWithQueryClient() - expect(screen.getByText('app.appSelector.params')).toBeInTheDocument() + expect(screen.getByText('app.appSelector.params'))!.toBeInTheDocument() }) it('should filter external_data_tool items', () => { @@ -1260,7 +1298,7 @@ describe('AppInputsPanel', () => { }, }) renderWithQueryClient() - expect(screen.getByText('app.appSelector.params')).toBeInTheDocument() + expect(screen.getByText('app.appSelector.params'))!.toBeInTheDocument() }) }) @@ -1283,7 +1321,7 @@ describe('AppInputsPanel', () => { } const workflowApp = createMockApp({ mode: AppModeEnum.WORKFLOW }) renderWithQueryClient() - expect(screen.getByText('app.appSelector.params')).toBeInTheDocument() + expect(screen.getByText('app.appSelector.params'))!.toBeInTheDocument() }) it('should generate schema for workflow with singleFile variable', () => { @@ -1304,7 +1342,7 @@ describe('AppInputsPanel', () => { } const workflowApp = createMockApp({ mode: AppModeEnum.WORKFLOW }) renderWithQueryClient() - expect(screen.getByText('app.appSelector.params')).toBeInTheDocument() + expect(screen.getByText('app.appSelector.params'))!.toBeInTheDocument() }) it('should generate schema for workflow with regular variable', () => { @@ -1325,7 +1363,7 @@ describe('AppInputsPanel', () => { } const workflowApp = createMockApp({ mode: AppModeEnum.WORKFLOW }) renderWithQueryClient() - expect(screen.getByText('app.appSelector.params')).toBeInTheDocument() + expect(screen.getByText('app.appSelector.params'))!.toBeInTheDocument() }) }) @@ -1344,7 +1382,7 @@ describe('AppInputsPanel', () => { }) const completionApp = createMockApp({ mode: AppModeEnum.COMPLETION }) renderWithQueryClient() - expect(screen.getByText('app.appSelector.params')).toBeInTheDocument() + expect(screen.getByText('app.appSelector.params'))!.toBeInTheDocument() }) it('should add image upload schema for WORKFLOW mode with file upload enabled', () => { @@ -1364,7 +1402,7 @@ describe('AppInputsPanel', () => { } const workflowApp = createMockApp({ mode: AppModeEnum.WORKFLOW }) renderWithQueryClient() - expect(screen.getByText('app.appSelector.params')).toBeInTheDocument() + expect(screen.getByText('app.appSelector.params'))!.toBeInTheDocument() }) }) @@ -1372,7 +1410,7 @@ describe('AppInputsPanel', () => { it('should call onFormChange when form is updated', () => { const onFormChange = vi.fn() renderWithQueryClient() - expect(screen.getByText('app.appSelector.params')).toBeInTheDocument() + expect(screen.getByText('app.appSelector.params'))!.toBeInTheDocument() }) it('should call onFormChange with updated values when text input changes', () => { @@ -1424,7 +1462,7 @@ describe('AppInputsPanel', () => { , ) - expect(screen.getByText('app.appSelector.params')).toBeInTheDocument() + expect(screen.getByText('app.appSelector.params'))!.toBeInTheDocument() }) }) @@ -1432,7 +1470,7 @@ describe('AppInputsPanel', () => { it('should return empty schema when currentApp is null', () => { mockAppDetailData = null renderWithQueryClient() - expect(screen.getByText('app.appSelector.noParams')).toBeInTheDocument() + expect(screen.getByText('app.appSelector.noParams'))!.toBeInTheDocument() }) it('should handle workflow without start node', () => { @@ -1442,7 +1480,7 @@ describe('AppInputsPanel', () => { } const workflowApp = createMockApp({ mode: AppModeEnum.WORKFLOW }) renderWithQueryClient() - expect(screen.getByText('app.appSelector.params')).toBeInTheDocument() + expect(screen.getByText('app.appSelector.params'))!.toBeInTheDocument() }) }) }) @@ -1477,12 +1515,12 @@ describe('AppSelector', () => { describe('Rendering', () => { it('should render without crashing', () => { renderWithQueryClient() - expect(screen.getByTestId('portal-to-follow-elem')).toBeInTheDocument() + expect(screen.getByTestId('portal-to-follow-elem'))!.toBeInTheDocument() }) it('should render trigger component', () => { renderWithQueryClient() - expect(screen.getByText('app.appSelector.placeholder')).toBeInTheDocument() + expect(screen.getByText('app.appSelector.placeholder'))!.toBeInTheDocument() }) it('should show selected app info when value is provided', () => { @@ -1493,19 +1531,20 @@ describe('AppSelector', () => { />, ) // Should show the app trigger with app info - expect(screen.getByTestId('portal-to-follow-elem')).toBeInTheDocument() + // Should show the app trigger with app info + expect(screen.getByTestId('portal-to-follow-elem'))!.toBeInTheDocument() }) }) describe('Props', () => { it('should handle different placement values', () => { renderWithQueryClient() - expect(screen.getByTestId('portal-to-follow-elem')).toBeInTheDocument() + expect(screen.getByTestId('portal-to-follow-elem'))!.toBeInTheDocument() }) it('should handle different offset values', () => { renderWithQueryClient() - expect(screen.getByTestId('portal-to-follow-elem')).toBeInTheDocument() + expect(screen.getByTestId('portal-to-follow-elem'))!.toBeInTheDocument() }) it('should handle disabled state', () => { @@ -1513,12 +1552,13 @@ describe('AppSelector', () => { const trigger = screen.getByTestId('portal-trigger') fireEvent.click(trigger) // Portal should remain closed when disabled - expect(screen.getByTestId('portal-to-follow-elem')).toHaveAttribute('data-open', 'false') + // Portal should remain closed when disabled + expect(screen.getByTestId('portal-to-follow-elem'))!.toHaveAttribute('data-open', 'false') }) it('should handle scope prop', () => { renderWithQueryClient() - expect(screen.getByTestId('portal-to-follow-elem')).toBeInTheDocument() + expect(screen.getByTestId('portal-to-follow-elem'))!.toBeInTheDocument() }) it('should handle value with inputs', () => { @@ -1528,7 +1568,7 @@ describe('AppSelector', () => { value={{ app_id: 'app-1', inputs: { name: 'test' }, files: [] }} />, ) - expect(screen.getByTestId('portal-to-follow-elem')).toBeInTheDocument() + expect(screen.getByTestId('portal-to-follow-elem'))!.toBeInTheDocument() }) it('should handle value with files', () => { @@ -1538,7 +1578,7 @@ describe('AppSelector', () => { value={{ app_id: 'app-1', inputs: {}, files: [{ id: 'file-1' }] }} />, ) - expect(screen.getByTestId('portal-to-follow-elem')).toBeInTheDocument() + expect(screen.getByTestId('portal-to-follow-elem'))!.toBeInTheDocument() }) }) @@ -1547,10 +1587,11 @@ describe('AppSelector', () => { renderWithQueryClient() const trigger = screen.getAllByTestId('portal-trigger')[0] - fireEvent.click(trigger) + fireEvent.click(trigger!) // The portal state should update synchronously - get the first one (outer portal) - expect(screen.getAllByTestId('portal-to-follow-elem')[0]).toHaveAttribute('data-open', 'true') + // The portal state should update synchronously - get the first one (outer portal) + expect(screen.getAllByTestId('portal-to-follow-elem')[0])!.toHaveAttribute('data-open', 'true') }) it('should not toggle isShow when disabled', () => { @@ -1559,7 +1600,7 @@ describe('AppSelector', () => { const trigger = screen.getByTestId('portal-trigger') fireEvent.click(trigger) - expect(screen.getByTestId('portal-to-follow-elem')).toHaveAttribute('data-open', 'false') + expect(screen.getByTestId('portal-to-follow-elem'))!.toHaveAttribute('data-open', 'false') }) it('should manage search text state', () => { @@ -1569,7 +1610,8 @@ describe('AppSelector', () => { fireEvent.click(trigger) // Portal content should be visible after click - expect(screen.getByTestId('portal-content')).toBeInTheDocument() + // Portal content should be visible after click + expect(screen.getByTestId('portal-content'))!.toBeInTheDocument() }) it('should render correctly during load more setup', () => { @@ -1579,7 +1621,8 @@ describe('AppSelector', () => { renderWithQueryClient() // Trigger should be rendered - expect(screen.getByTestId('portal-trigger')).toBeInTheDocument() + // Trigger should be rendered + expect(screen.getByTestId('portal-trigger'))!.toBeInTheDocument() }) }) @@ -1592,7 +1635,7 @@ describe('AppSelector', () => { // Open the portal fireEvent.click(screen.getByTestId('portal-trigger')) - expect(screen.getByTestId('portal-content')).toBeInTheDocument() + expect(screen.getByTestId('portal-content'))!.toBeInTheDocument() }) it('should call onSelect with correct value structure', () => { @@ -1606,7 +1649,8 @@ describe('AppSelector', () => { ) // The component should maintain the correct value structure - expect(screen.getByTestId('portal-to-follow-elem')).toBeInTheDocument() + // The component should maintain the correct value structure + expect(screen.getByTestId('portal-to-follow-elem'))!.toBeInTheDocument() }) it('should clear inputs when selecting different app', () => { @@ -1620,7 +1664,8 @@ describe('AppSelector', () => { ) // Component renders with existing value - expect(screen.getByTestId('portal-to-follow-elem')).toBeInTheDocument() + // Component renders with existing value + expect(screen.getByTestId('portal-to-follow-elem'))!.toBeInTheDocument() }) it('should preserve inputs when selecting same app', () => { @@ -1633,7 +1678,7 @@ describe('AppSelector', () => { />, ) - expect(screen.getByTestId('portal-to-follow-elem')).toBeInTheDocument() + expect(screen.getByTestId('portal-to-follow-elem'))!.toBeInTheDocument() }) }) @@ -1647,7 +1692,7 @@ describe('AppSelector', () => { } renderWithQueryClient() - expect(screen.getByTestId('portal-to-follow-elem')).toBeInTheDocument() + expect(screen.getByTestId('portal-to-follow-elem'))!.toBeInTheDocument() }) it('should memoize currentAppInfo correctly', () => { @@ -1662,7 +1707,7 @@ describe('AppSelector', () => { />, ) - expect(screen.getByTestId('portal-to-follow-elem')).toBeInTheDocument() + expect(screen.getByTestId('portal-to-follow-elem'))!.toBeInTheDocument() }) it('should memoize formattedValue correctly', () => { @@ -1673,7 +1718,7 @@ describe('AppSelector', () => { />, ) - expect(screen.getByTestId('portal-to-follow-elem')).toBeInTheDocument() + expect(screen.getByTestId('portal-to-follow-elem'))!.toBeInTheDocument() }) it('should be wrapped with React.memo', () => { @@ -1690,7 +1735,7 @@ describe('AppSelector', () => { , ) - expect(screen.getByTestId('portal-to-follow-elem')).toBeInTheDocument() + expect(screen.getByTestId('portal-to-follow-elem'))!.toBeInTheDocument() }) }) @@ -1698,7 +1743,7 @@ describe('AppSelector', () => { it('should handle load more when hasMore is true', async () => { mockHasNextPage = true renderWithQueryClient() - expect(screen.getByTestId('portal-to-follow-elem')).toBeInTheDocument() + expect(screen.getByTestId('portal-to-follow-elem'))!.toBeInTheDocument() }) it('should not trigger load more when already loading', async () => { @@ -1724,7 +1769,7 @@ describe('AppSelector', () => { vi.advanceTimersByTime(500) }) - expect(screen.getByTestId('portal-to-follow-elem')).toBeInTheDocument() + expect(screen.getByTestId('portal-to-follow-elem'))!.toBeInTheDocument() }) it('should render load more area when hasMore is true', () => { @@ -1735,10 +1780,11 @@ describe('AppSelector', () => { renderWithQueryClient() // Open the portal - fireEvent.click(screen.getAllByTestId('portal-trigger')[0]) + fireEvent.click(screen.getAllByTestId('portal-trigger')[0]!) // Should render without errors - expect(screen.getByTestId('portal-content')).toBeInTheDocument() + // Should render without errors + expect(screen.getByTestId('portal-content'))!.toBeInTheDocument() }) it('should handle fetchNextPage rejection gracefully in handleLoadMore', async () => { @@ -1748,7 +1794,8 @@ describe('AppSelector', () => { renderWithQueryClient() // Should not crash even if fetchNextPage rejects - expect(screen.getByTestId('portal-to-follow-elem')).toBeInTheDocument() + // Should not crash even if fetchNextPage rejects + expect(screen.getByTestId('portal-to-follow-elem'))!.toBeInTheDocument() }) it('should call fetchNextPage when intersection observer triggers handleLoadMore', async () => { @@ -1759,11 +1806,11 @@ describe('AppSelector', () => { renderWithQueryClient() // Open the main portal - fireEvent.click(screen.getAllByTestId('portal-trigger')[0]) + fireEvent.click(screen.getAllByTestId('portal-trigger')[0]!) // Open the inner app picker portal const triggers = screen.getAllByTestId('portal-trigger') - fireEvent.click(triggers[1]) + fireEvent.click(triggers[1]!) // Simulate intersection to trigger handleLoadMore triggerIntersection([{ isIntersecting: true } as IntersectionObserverEntry]) @@ -1780,9 +1827,9 @@ describe('AppSelector', () => { renderWithQueryClient() // Open portals - fireEvent.click(screen.getAllByTestId('portal-trigger')[0]) + fireEvent.click(screen.getAllByTestId('portal-trigger')[0]!) const triggers = screen.getAllByTestId('portal-trigger') - fireEvent.click(triggers[1]) + fireEvent.click(triggers[1]!) // Trigger first intersection triggerIntersection([{ isIntersecting: true } as IntersectionObserverEntry]) @@ -1806,9 +1853,9 @@ describe('AppSelector', () => { renderWithQueryClient() // Open portals - fireEvent.click(screen.getAllByTestId('portal-trigger')[0]) + fireEvent.click(screen.getAllByTestId('portal-trigger')[0]!) const triggers = screen.getAllByTestId('portal-trigger') - fireEvent.click(triggers[1]) + fireEvent.click(triggers[1]!) // Trigger intersection triggerIntersection([{ isIntersecting: true } as IntersectionObserverEntry]) @@ -1825,9 +1872,9 @@ describe('AppSelector', () => { renderWithQueryClient() // Open portals - fireEvent.click(screen.getAllByTestId('portal-trigger')[0]) + fireEvent.click(screen.getAllByTestId('portal-trigger')[0]!) const triggers = screen.getAllByTestId('portal-trigger') - fireEvent.click(triggers[1]) + fireEvent.click(triggers[1]!) // Trigger intersection triggerIntersection([{ isIntersecting: true } as IntersectionObserverEntry]) @@ -1847,7 +1894,7 @@ describe('AppSelector', () => { />, ) - expect(screen.getByTestId('portal-to-follow-elem')).toBeInTheDocument() + expect(screen.getByTestId('portal-to-follow-elem'))!.toBeInTheDocument() }) it('should handle form change without image file', () => { @@ -1860,7 +1907,7 @@ describe('AppSelector', () => { />, ) - expect(screen.getByTestId('portal-to-follow-elem')).toBeInTheDocument() + expect(screen.getByTestId('portal-to-follow-elem'))!.toBeInTheDocument() }) it('should extract #image# from inputs and add to files array', () => { @@ -1874,7 +1921,7 @@ describe('AppSelector', () => { />, ) - expect(screen.getByTestId('portal-to-follow-elem')).toBeInTheDocument() + expect(screen.getByTestId('portal-to-follow-elem'))!.toBeInTheDocument() }) it('should preserve existing files when no #image# in inputs', () => { @@ -1887,7 +1934,7 @@ describe('AppSelector', () => { />, ) - expect(screen.getByTestId('portal-to-follow-elem')).toBeInTheDocument() + expect(screen.getByTestId('portal-to-follow-elem'))!.toBeInTheDocument() }) }) @@ -1907,9 +1954,9 @@ describe('AppSelector', () => { ) // Open the main portal - fireEvent.click(screen.getAllByTestId('portal-trigger')[0]) + fireEvent.click(screen.getAllByTestId('portal-trigger')[0]!) - expect(screen.getByTestId('portal-content')).toBeInTheDocument() + expect(screen.getByTestId('portal-content'))!.toBeInTheDocument() }) it('should preserve inputs when selecting the same app', () => { @@ -1926,7 +1973,7 @@ describe('AppSelector', () => { />, ) - expect(screen.getByTestId('portal-to-follow-elem')).toBeInTheDocument() + expect(screen.getByTestId('portal-to-follow-elem'))!.toBeInTheDocument() }) it('should handle app selection with empty value', () => { @@ -1944,34 +1991,34 @@ describe('AppSelector', () => { ) // Open the main portal - fireEvent.click(screen.getAllByTestId('portal-trigger')[0]) + fireEvent.click(screen.getAllByTestId('portal-trigger')[0]!) - expect(screen.getByTestId('portal-content')).toBeInTheDocument() + expect(screen.getByTestId('portal-content'))!.toBeInTheDocument() }) }) describe('Edge Cases', () => { it('should handle undefined value', () => { renderWithQueryClient() - expect(screen.getByText('app.appSelector.placeholder')).toBeInTheDocument() + expect(screen.getByText('app.appSelector.placeholder'))!.toBeInTheDocument() }) it('should handle empty pages array', () => { mockAppListData = { pages: [] } renderWithQueryClient() - expect(screen.getByTestId('portal-to-follow-elem')).toBeInTheDocument() + expect(screen.getByTestId('portal-to-follow-elem'))!.toBeInTheDocument() }) it('should handle undefined data', () => { mockAppListData = undefined renderWithQueryClient() - expect(screen.getByTestId('portal-to-follow-elem')).toBeInTheDocument() + expect(screen.getByTestId('portal-to-follow-elem'))!.toBeInTheDocument() }) it('should handle loading state', () => { mockIsLoading = true renderWithQueryClient() - expect(screen.getByTestId('portal-to-follow-elem')).toBeInTheDocument() + expect(screen.getByTestId('portal-to-follow-elem'))!.toBeInTheDocument() }) it('should handle app not found in displayedApps', () => { @@ -1986,7 +2033,7 @@ describe('AppSelector', () => { />, ) - expect(screen.getByTestId('portal-to-follow-elem')).toBeInTheDocument() + expect(screen.getByTestId('portal-to-follow-elem'))!.toBeInTheDocument() }) it('should handle value with empty inputs and files', () => { @@ -1997,7 +2044,7 @@ describe('AppSelector', () => { />, ) - expect(screen.getByTestId('portal-to-follow-elem')).toBeInTheDocument() + expect(screen.getByTestId('portal-to-follow-elem'))!.toBeInTheDocument() }) }) @@ -2009,7 +2056,8 @@ describe('AppSelector', () => { renderWithQueryClient() // Should not crash - expect(screen.getByTestId('portal-to-follow-elem')).toBeInTheDocument() + // Should not crash + expect(screen.getByTestId('portal-to-follow-elem'))!.toBeInTheDocument() }) }) }) @@ -2043,10 +2091,11 @@ describe('AppSelector Integration', () => { renderWithQueryClient() // 1. Click trigger to open picker - get first trigger (outer portal) - fireEvent.click(screen.getAllByTestId('portal-trigger')[0]) + fireEvent.click(screen.getAllByTestId('portal-trigger')[0]!) // Get the first portal element (outer portal) - expect(screen.getAllByTestId('portal-to-follow-elem')[0]).toHaveAttribute('data-open', 'true') + // Get the first portal element (outer portal) + expect(screen.getAllByTestId('portal-to-follow-elem')[0])!.toHaveAttribute('data-open', 'true') }) it('should handle app change with input preservation logic', () => { @@ -2058,7 +2107,7 @@ describe('AppSelector Integration', () => { />, ) - expect(screen.getByTestId('portal-to-follow-elem')).toBeInTheDocument() + expect(screen.getByTestId('portal-to-follow-elem'))!.toBeInTheDocument() }) }) @@ -2067,7 +2116,8 @@ describe('AppSelector Integration', () => { renderWithQueryClient() // AppTrigger should show placeholder when no app selected - expect(screen.getByText('app.appSelector.placeholder')).toBeInTheDocument() + // AppTrigger should show placeholder when no app selected + expect(screen.getByText('app.appSelector.placeholder'))!.toBeInTheDocument() }) it('should pass correct props to AppPicker', () => { @@ -2075,7 +2125,7 @@ describe('AppSelector Integration', () => { fireEvent.click(screen.getByTestId('portal-trigger')) - expect(screen.getByTestId('portal-content')).toBeInTheDocument() + expect(screen.getByTestId('portal-content'))!.toBeInTheDocument() }) }) @@ -2088,7 +2138,7 @@ describe('AppSelector Integration', () => { />, ) - expect(screen.getByTestId('portal-to-follow-elem')).toBeInTheDocument() + expect(screen.getByTestId('portal-to-follow-elem'))!.toBeInTheDocument() }) it('should handle search filtering through app list', () => { @@ -2096,7 +2146,7 @@ describe('AppSelector Integration', () => { fireEvent.click(screen.getByTestId('portal-trigger')) - expect(screen.getByTestId('portal-content')).toBeInTheDocument() + expect(screen.getByTestId('portal-content'))!.toBeInTheDocument() }) }) @@ -2115,13 +2165,13 @@ describe('AppSelector Integration', () => { ) // Open the main portal - fireEvent.click(screen.getAllByTestId('portal-trigger')[0]) + fireEvent.click(screen.getAllByTestId('portal-trigger')[0]!) // The inner AppPicker portal is closed by default (isShowChooseApp = false) // We need to click on the inner trigger to open it const innerTriggers = screen.getAllByTestId('portal-trigger') // The second trigger is the inner AppPicker trigger - fireEvent.click(innerTriggers[1]) + fireEvent.click(innerTriggers[1]!) // Now the inner portal should be open and show the app list // Find and click on app-2 @@ -2150,16 +2200,16 @@ describe('AppSelector Integration', () => { ) // Open the main portal - fireEvent.click(screen.getAllByTestId('portal-trigger')[0]) + fireEvent.click(screen.getAllByTestId('portal-trigger')[0]!) // Click on the inner trigger to open app picker const innerTriggers = screen.getAllByTestId('portal-trigger') - fireEvent.click(innerTriggers[1]) + fireEvent.click(innerTriggers[1]!) // Click on the same app - need to get the one in the app list, not the trigger const appItems = screen.getAllByText('App 1') // The last one should be in the dropdown list - fireEvent.click(appItems[appItems.length - 1]) + fireEvent.click(appItems[appItems.length - 1]!) // onSelect should be called with preserved inputs since it's the same app expect(onSelect).toHaveBeenCalledWith({ @@ -2183,15 +2233,15 @@ describe('AppSelector Integration', () => { ) // Open the main portal - fireEvent.click(screen.getAllByTestId('portal-trigger')[0]) + fireEvent.click(screen.getAllByTestId('portal-trigger')[0]!) // Click on inner trigger to open app picker const innerTriggers = screen.getAllByTestId('portal-trigger') - fireEvent.click(innerTriggers[1]) + fireEvent.click(innerTriggers[1]!) // Click on an app from the dropdown const app1Elements = screen.getAllByText('App 1') - fireEvent.click(app1Elements[app1Elements.length - 1]) + fireEvent.click(app1Elements[app1Elements.length - 1]!) // onSelect should be called with new app and empty inputs/files expect(onSelect).toHaveBeenCalledWith({ @@ -2211,9 +2261,9 @@ describe('AppSelector Integration', () => { renderWithQueryClient() // Open the portal to render the app picker - fireEvent.click(screen.getAllByTestId('portal-trigger')[0]) + fireEvent.click(screen.getAllByTestId('portal-trigger')[0]!) - expect(screen.getByTestId('portal-content')).toBeInTheDocument() + expect(screen.getByTestId('portal-content'))!.toBeInTheDocument() }) it('should stay stable after fetchNextPage completes', async () => { @@ -2223,9 +2273,9 @@ describe('AppSelector Integration', () => { renderWithQueryClient() - fireEvent.click(screen.getAllByTestId('portal-trigger')[0]) + fireEvent.click(screen.getAllByTestId('portal-trigger')[0]!) - expect(screen.getByTestId('portal-content')).toBeInTheDocument() + expect(screen.getByTestId('portal-content'))!.toBeInTheDocument() }) it('should not call fetchNextPage when conditions prevent it', () => { @@ -2234,7 +2284,7 @@ describe('AppSelector Integration', () => { renderWithQueryClient() - fireEvent.click(screen.getAllByTestId('portal-trigger')[0]) + fireEvent.click(screen.getAllByTestId('portal-trigger')[0]!) // fetchNextPage should not be called expect(mockFetchNextPage).not.toHaveBeenCalled() @@ -2256,7 +2306,7 @@ describe('AppSelector Integration', () => { ) // Open portal - fireEvent.click(screen.getAllByTestId('portal-trigger')[0]) + fireEvent.click(screen.getAllByTestId('portal-trigger')[0]!) // formattedValue should include #image# from files expect(screen.getAllByTestId('portal-content').length).toBeGreaterThan(0) @@ -2275,7 +2325,7 @@ describe('AppSelector Integration', () => { />, ) - fireEvent.click(screen.getAllByTestId('portal-trigger')[0]) + fireEvent.click(screen.getAllByTestId('portal-trigger')[0]!) expect(screen.getAllByTestId('portal-content').length).toBeGreaterThan(0) }) @@ -2293,7 +2343,7 @@ describe('AppSelector Integration', () => { />, ) - fireEvent.click(screen.getAllByTestId('portal-trigger')[0]) + fireEvent.click(screen.getAllByTestId('portal-trigger')[0]!) expect(screen.getAllByTestId('portal-content').length).toBeGreaterThan(0) }) @@ -2324,12 +2374,12 @@ describe('AppSelector Integration', () => { ) // Open portal to render AppInputsPanel - fireEvent.click(screen.getAllByTestId('portal-trigger')[0]) + fireEvent.click(screen.getAllByTestId('portal-trigger')[0]!) // Find and interact with the form input (may not exist if schema is empty) const formInputs = screen.queryAllByPlaceholderText('FormInputField') if (formInputs.length > 0) { - fireEvent.change(formInputs[0], { target: { value: 'test value' } }) + fireEvent.change(formInputs[0]!, { target: { value: 'test value' } }) // handleFormChange in index.tsx should have been called expect(onSelect).toHaveBeenCalledWith({ @@ -2376,12 +2426,12 @@ describe('AppSelector Integration', () => { />, ) - fireEvent.click(screen.getAllByTestId('portal-trigger')[0]) + fireEvent.click(screen.getAllByTestId('portal-trigger')[0]!) // Find file uploader and trigger upload - the #image# field will be extracted const uploadBtns = screen.queryAllByTestId('upload-file-btn') if (uploadBtns.length > 0) { - fireEvent.click(uploadBtns[0]) + fireEvent.click(uploadBtns[0]!) // handleFormChange should extract #image# and convert to files expect(onSelect).toHaveBeenCalled() } @@ -2414,12 +2464,12 @@ describe('AppSelector Integration', () => { />, ) - fireEvent.click(screen.getAllByTestId('portal-trigger')[0]) + fireEvent.click(screen.getAllByTestId('portal-trigger')[0]!) // Find form input (may not exist if schema is empty) const inputs = screen.queryAllByPlaceholderText('PreserveField') if (inputs.length > 0) { - fireEvent.change(inputs[0], { target: { value: 'updated name' } }) + fireEvent.change(inputs[0]!, { target: { value: 'updated name' } }) // onSelect should be called preserving existing files (no #image# in inputs) expect(onSelect).toHaveBeenCalledWith({ @@ -2465,7 +2515,7 @@ describe('AppSelector Integration', () => { />, ) - fireEvent.click(screen.getAllByTestId('portal-trigger')[0]) + fireEvent.click(screen.getAllByTestId('portal-trigger')[0]!) // Try to find and click the upload button which triggers #image# form change const uploadBtn = screen.queryByTestId('upload-file-btn') @@ -2499,11 +2549,11 @@ describe('AppSelector Integration', () => { />, ) - fireEvent.click(screen.getAllByTestId('portal-trigger')[0]) + fireEvent.click(screen.getAllByTestId('portal-trigger')[0]!) const inputs = screen.queryAllByPlaceholderText('SimpleInput') if (inputs.length > 0) { - fireEvent.change(inputs[0], { target: { value: 'changed' } }) + fireEvent.change(inputs[0]!, { target: { value: 'changed' } }) // handleFormChange should preserve existing files when no #image# in inputs expect(onSelect).toHaveBeenCalledWith({ app_id: 'app-1', diff --git a/web/app/components/plugins/plugin-detail-panel/app-selector/app-picker.tsx b/web/app/components/plugins/plugin-detail-panel/app-selector/app-picker.tsx index c4cb4f4da8..4c96b69beb 100644 --- a/web/app/components/plugins/plugin-detail-panel/app-selector/app-picker.tsx +++ b/web/app/components/plugins/plugin-detail-panel/app-selector/app-picker.tsx @@ -78,7 +78,7 @@ const AppPicker: FC = ({ const handleIntersection = useCallback((entries: IntersectionObserverEntry[]) => { const target = entries[0] - if (!target.isIntersecting || loadingRef.current || !hasMore || isLoading) + if (!target!.isIntersecting || loadingRef.current || !hasMore || isLoading) return loadingRef.current = true diff --git a/web/app/components/plugins/plugin-detail-panel/app-selector/hooks/use-app-inputs-form-schema.ts b/web/app/components/plugins/plugin-detail-panel/app-selector/hooks/use-app-inputs-form-schema.ts index 51bbcde18d..8f3d5f0249 100644 --- a/web/app/components/plugins/plugin-detail-panel/app-selector/hooks/use-app-inputs-form-schema.ts +++ b/web/app/components/plugins/plugin-detail-panel/app-selector/hooks/use-app-inputs-form-schema.ts @@ -53,7 +53,7 @@ function buildFileConfig(fileConfig: FileUpload | undefined) { enabled: !!(fileConfig?.enabled || fileConfig?.image?.enabled), allowed_file_types: fileConfig?.allowed_file_types || [SupportUploadFileTypes.image], allowed_file_extensions: fileConfig?.allowed_file_extensions - || [...FILE_EXTS[SupportUploadFileTypes.image]].map(ext => `.${ext}`), + || [...(FILE_EXTS[SupportUploadFileTypes.image] ?? [])].map(ext => `.${ext}`), allowed_file_upload_methods: fileConfig?.allowed_file_upload_methods || fileConfig?.image?.transfer_methods || ['local_file', 'remote_url'], diff --git a/web/app/components/plugins/plugin-detail-panel/model-selector/__tests__/tts-params-panel.spec.tsx b/web/app/components/plugins/plugin-detail-panel/model-selector/__tests__/tts-params-panel.spec.tsx index c3f7f221b5..e423359872 100644 --- a/web/app/components/plugins/plugin-detail-panel/model-selector/__tests__/tts-params-panel.spec.tsx +++ b/web/app/components/plugins/plugin-detail-panel/model-selector/__tests__/tts-params-panel.spec.tsx @@ -161,7 +161,8 @@ describe('TTSParamsPanel', () => { const { container } = render() // Assert - expect(container).toBeInTheDocument() + // Assert + expect(container)!.toBeInTheDocument() }) it('should render language label', () => { @@ -172,7 +173,8 @@ describe('TTSParamsPanel', () => { render() // Assert - expect(screen.getByText('appDebug.voice.voiceSettings.language')).toBeInTheDocument() + // Assert + expect(screen.getByText('appDebug.voice.voiceSettings.language'))!.toBeInTheDocument() }) it('should render voice label', () => { @@ -183,7 +185,8 @@ describe('TTSParamsPanel', () => { render() // Assert - expect(screen.getByText('appDebug.voice.voiceSettings.voice')).toBeInTheDocument() + // Assert + expect(screen.getByText('appDebug.voice.voiceSettings.voice'))!.toBeInTheDocument() }) it('should render two Select components', () => { @@ -207,7 +210,7 @@ describe('TTSParamsPanel', () => { // Assert const values = screen.getAllByTestId('selected-value') - expect(values[0]).toHaveTextContent('zh-Hans') + expect(values[0])!.toHaveTextContent('zh-Hans') }) it('should render voice select with correct value', () => { @@ -219,7 +222,7 @@ describe('TTSParamsPanel', () => { // Assert const values = screen.getAllByTestId('selected-value') - expect(values[1]).toHaveTextContent('echo') + expect(values[1])!.toHaveTextContent('echo') }) it('should only show supported languages in language select', () => { @@ -230,9 +233,10 @@ describe('TTSParamsPanel', () => { render() // Assert - expect(screen.getByTestId('select-item-en-US')).toBeInTheDocument() - expect(screen.getByTestId('select-item-zh-Hans')).toBeInTheDocument() - expect(screen.getByTestId('select-item-ja-JP')).toBeInTheDocument() + // Assert + expect(screen.getByTestId('select-item-en-US'))!.toBeInTheDocument() + expect(screen.getByTestId('select-item-zh-Hans'))!.toBeInTheDocument() + expect(screen.getByTestId('select-item-ja-JP'))!.toBeInTheDocument() expect(screen.queryByTestId('select-item-unsupported-lang')).not.toBeInTheDocument() }) @@ -244,9 +248,10 @@ describe('TTSParamsPanel', () => { render() // Assert - expect(screen.getByTestId('select-item-alloy')).toBeInTheDocument() - expect(screen.getByTestId('select-item-echo')).toBeInTheDocument() - expect(screen.getByTestId('select-item-fable')).toBeInTheDocument() + // Assert + expect(screen.getByTestId('select-item-alloy'))!.toBeInTheDocument() + expect(screen.getByTestId('select-item-echo'))!.toBeInTheDocument() + expect(screen.getByTestId('select-item-fable'))!.toBeInTheDocument() }) }) @@ -260,8 +265,9 @@ describe('TTSParamsPanel', () => { render() // Assert - expect(screen.getByTestId('tts-language-select-trigger')).toHaveAttribute('data-class', 'w-full') - expect(screen.getByTestId('tts-voice-select-trigger')).toHaveAttribute('data-class', 'w-full') + // Assert + expect(screen.getByTestId('tts-language-select-trigger'))!.toHaveAttribute('data-class', 'w-full') + expect(screen.getByTestId('tts-voice-select-trigger'))!.toHaveAttribute('data-class', 'w-full') }) it('should apply popup className to SelectContent', () => { @@ -273,8 +279,8 @@ describe('TTSParamsPanel', () => { // Assert const contents = screen.getAllByTestId('select-content') - expect(contents[0]).toHaveAttribute('data-popup-class', 'w-[354px]') - expect(contents[1]).toHaveAttribute('data-popup-class', 'w-[354px]') + expect(contents[0])!.toHaveAttribute('data-popup-class', 'w-[354px]') + expect(contents[1])!.toHaveAttribute('data-popup-class', 'w-[354px]') }) }) @@ -396,6 +402,37 @@ describe('TTSParamsPanel', () => { // Act render() + // Assert - no voice items should be rendered + // Assert - no voice items should be rendered + // Assert - no voice items should be rendered + // Assert - no voice items should be rendered + // Assert - no voice items should be rendered + // Assert - no voice items should be rendered + // Assert - no voice items should be rendered + // Assert - no voice items should be rendered + // Assert - no voice items should be rendered + // Assert - no voice items should be rendered + // Assert - no voice items should be rendered + // Assert - no voice items should be rendered + // Assert - no voice items should be rendered + // Assert - no voice items should be rendered + // Assert - no voice items should be rendered + // Assert - no voice items should be rendered + // Assert - no voice items should be rendered + // Assert - no voice items should be rendered + // Assert - no voice items should be rendered + // Assert - no voice items should be rendered + // Assert - no voice items should be rendered + // Assert - no voice items should be rendered + // Assert - no voice items should be rendered + // Assert - no voice items should be rendered + // Assert - no voice items should be rendered + // Assert - no voice items should be rendered + // Assert - no voice items should be rendered + // Assert - no voice items should be rendered + // Assert - no voice items should be rendered + // Assert - no voice items should be rendered + // Assert - no voice items should be rendered // Assert - no voice items should be rendered expect(screen.queryByTestId('select-item-alloy')).not.toBeInTheDocument() expect(screen.queryByTestId('select-item-echo')).not.toBeInTheDocument() @@ -413,6 +450,37 @@ describe('TTSParamsPanel', () => { // Act render() + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert // Assert expect(screen.queryByTestId('select-item-alloy')).not.toBeInTheDocument() }) @@ -430,8 +498,9 @@ describe('TTSParamsPanel', () => { render() // Assert - expect(screen.getByTestId('select-item-voice-1')).toBeInTheDocument() - expect(screen.getByTestId('select-item-voice-2')).toBeInTheDocument() + // Assert + expect(screen.getByTestId('select-item-voice-1'))!.toBeInTheDocument() + expect(screen.getByTestId('select-item-voice-2'))!.toBeInTheDocument() }) it('should handle currentModel with empty voices array', () => { @@ -444,7 +513,7 @@ describe('TTSParamsPanel', () => { render() // Assert - no voice items (except language items) - expect(screen.getAllByTestId('select-content')[1].children).toHaveLength(0) + expect(screen.getAllByTestId('select-content')[1]!.children).toHaveLength(0) expect(screen.queryByTestId('select-item-alloy')).not.toBeInTheDocument() }) @@ -460,7 +529,8 @@ describe('TTSParamsPanel', () => { render() // Assert - expect(screen.getByTestId('select-item-single-voice')).toBeInTheDocument() + // Assert + expect(screen.getByTestId('select-item-single-voice'))!.toBeInTheDocument() }) }) @@ -475,7 +545,7 @@ describe('TTSParamsPanel', () => { // Assert const values = screen.getAllByTestId('selected-value') - expect(values[0]).toHaveTextContent('') + expect(values[0])!.toHaveTextContent('') }) it('should handle empty voice value', () => { @@ -487,7 +557,7 @@ describe('TTSParamsPanel', () => { // Assert const values = screen.getAllByTestId('selected-value') - expect(values[1]).toHaveTextContent('') + expect(values[1])!.toHaveTextContent('') }) it('should handle many voices', () => { @@ -504,8 +574,9 @@ describe('TTSParamsPanel', () => { render() // Assert - expect(screen.getByTestId('select-item-voice-0')).toBeInTheDocument() - expect(screen.getByTestId('select-item-voice-19')).toBeInTheDocument() + // Assert + expect(screen.getByTestId('select-item-voice-0'))!.toBeInTheDocument() + expect(screen.getByTestId('select-item-voice-19'))!.toBeInTheDocument() }) it('should handle voice with special characters in mode', () => { @@ -520,7 +591,8 @@ describe('TTSParamsPanel', () => { render() // Assert - expect(screen.getByTestId('select-item-voice-with_special.chars')).toBeInTheDocument() + // Assert + expect(screen.getByTestId('select-item-voice-with_special.chars'))!.toBeInTheDocument() }) it('should handle onChange not being called multiple times', () => { @@ -546,13 +618,13 @@ describe('TTSParamsPanel', () => { // Act const { rerender } = render() const values = screen.getAllByTestId('selected-value') - expect(values[0]).toHaveTextContent('en-US') + expect(values[0])!.toHaveTextContent('en-US') rerender() // Assert const updatedValues = screen.getAllByTestId('selected-value') - expect(updatedValues[0]).toHaveTextContent('zh-Hans') + expect(updatedValues[0])!.toHaveTextContent('zh-Hans') }) it('should update when voice prop changes', () => { @@ -562,13 +634,13 @@ describe('TTSParamsPanel', () => { // Act const { rerender } = render() const values = screen.getAllByTestId('selected-value') - expect(values[1]).toHaveTextContent('alloy') + expect(values[1])!.toHaveTextContent('alloy') rerender() // Assert const updatedValues = screen.getAllByTestId('selected-value') - expect(updatedValues[1]).toHaveTextContent('echo') + expect(updatedValues[1])!.toHaveTextContent('echo') }) it('should update voice list when currentModel changes', () => { @@ -580,7 +652,7 @@ describe('TTSParamsPanel', () => { // Act const { rerender } = render() - expect(screen.getByTestId('select-item-alloy')).toBeInTheDocument() + expect(screen.getByTestId('select-item-alloy'))!.toBeInTheDocument() expect(screen.queryByTestId('select-item-nova')).not.toBeInTheDocument() const newModel = createCurrentModel([ @@ -590,8 +662,9 @@ describe('TTSParamsPanel', () => { rerender() // Assert - expect(screen.getByTestId('select-item-alloy')).toBeInTheDocument() - expect(screen.getByTestId('select-item-nova')).toBeInTheDocument() + // Assert + expect(screen.getByTestId('select-item-alloy'))!.toBeInTheDocument() + expect(screen.getByTestId('select-item-nova'))!.toBeInTheDocument() }) it('should handle currentModel becoming null', () => { @@ -600,10 +673,41 @@ describe('TTSParamsPanel', () => { // Act const { rerender } = render() - expect(screen.getByTestId('select-item-alloy')).toBeInTheDocument() + expect(screen.getByTestId('select-item-alloy'))!.toBeInTheDocument() rerender() + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert // Assert expect(screen.queryByTestId('select-item-alloy')).not.toBeInTheDocument() }) @@ -636,7 +740,7 @@ describe('TTSParamsPanel', () => { // Assert const languageLabel = screen.getByText('appDebug.voice.voiceSettings.language') - expect(languageLabel).toHaveClass('system-sm-semibold') + expect(languageLabel)!.toHaveClass('system-sm-semibold') }) it('should have proper label structure for voice select', () => { @@ -648,7 +752,7 @@ describe('TTSParamsPanel', () => { // Assert const voiceLabel = screen.getByText('appDebug.voice.voiceSettings.voice') - expect(voiceLabel).toHaveClass('system-sm-semibold') + expect(voiceLabel)!.toHaveClass('system-sm-semibold') }) }) }) diff --git a/web/app/components/plugins/plugin-detail-panel/subscription-list/__tests__/index.spec.tsx b/web/app/components/plugins/plugin-detail-panel/subscription-list/__tests__/index.spec.tsx index d41dfaa7d0..19a2d5a9f1 100644 --- a/web/app/components/plugins/plugin-detail-panel/subscription-list/__tests__/index.spec.tsx +++ b/web/app/components/plugins/plugin-detail-panel/subscription-list/__tests__/index.spec.tsx @@ -100,8 +100,8 @@ describe('SubscriptionList', () => { it('should render list view by default', () => { render() - expect(screen.getByText(/pluginTrigger\.subscription\.listNum/)).toBeInTheDocument() - expect(screen.getByText('Subscription One')).toBeInTheDocument() + expect(screen.getByText(/pluginTrigger\.subscription\.listNum/))!.toBeInTheDocument() + expect(screen.getByText('Subscription One'))!.toBeInTheDocument() }) it('should render loading state when subscriptions are loading', () => { @@ -112,7 +112,7 @@ describe('SubscriptionList', () => { render() - expect(screen.getByRole('status')).toBeInTheDocument() + expect(screen.getByRole('status'))!.toBeInTheDocument() expect(screen.queryByText('Subscription One')).not.toBeInTheDocument() }) @@ -121,7 +121,7 @@ describe('SubscriptionList', () => { render() - expect(screen.getByText('Subscription One')).toBeInTheDocument() + expect(screen.getByText('Subscription One'))!.toBeInTheDocument() }) it('should render without list entries when subscriptions are empty', () => { @@ -141,7 +141,7 @@ describe('SubscriptionList', () => { it('should render selector view when mode is selector', () => { render() - expect(screen.getByText('Subscription One')).toBeInTheDocument() + expect(screen.getByText('Subscription One'))!.toBeInTheDocument() }) it('should visually distinguish selected subscription from unselected', () => { @@ -182,7 +182,7 @@ describe('SubscriptionList', () => { fireEvent.click(screen.getByRole('button', { name: 'Subscription One' })) expect(onSelect).toHaveBeenCalledTimes(1) - const [selectedSubscription, callback] = onSelect.mock.calls[0] + const [selectedSubscription, callback] = (onSelect.mock.calls[0] ?? []) as [any, any] expect(selectedSubscription).toMatchObject({ id: 'sub-1', name: 'Subscription One' }) expect(typeof callback).toBe('function') @@ -212,7 +212,7 @@ describe('SubscriptionList', () => { fireEvent.click(deleteButton) expect(onSelect).not.toHaveBeenCalled() - expect(screen.getByText(/pluginTrigger\.subscription\.list\.item\.actions\.deleteConfirm\.title/)).toBeInTheDocument() + expect(screen.getByText(/pluginTrigger\.subscription\.list\.item\.actions\.deleteConfirm\.title/))!.toBeInTheDocument() }) }) @@ -222,7 +222,7 @@ describe('SubscriptionList', () => { render() - expect(await screen.findByText('Something went wrong')).toBeInTheDocument() + expect(await screen.findByText('Something went wrong'))!.toBeInTheDocument() }) }) }) diff --git a/web/app/components/plugins/plugin-detail-panel/subscription-list/__tests__/subscription-card.spec.tsx b/web/app/components/plugins/plugin-detail-panel/subscription-list/__tests__/subscription-card.spec.tsx index 4665c921ca..19edb65dfb 100644 --- a/web/app/components/plugins/plugin-detail-panel/subscription-list/__tests__/subscription-card.spec.tsx +++ b/web/app/components/plugins/plugin-detail-panel/subscription-list/__tests__/subscription-card.spec.tsx @@ -62,14 +62,14 @@ describe('SubscriptionCard', () => { it('should render subscription name and endpoint', () => { render() - expect(screen.getByText('Subscription One')).toBeInTheDocument() - expect(screen.getByText('https://example.com')).toBeInTheDocument() + expect(screen.getByText('Subscription One'))!.toBeInTheDocument() + expect(screen.getByText('https://example.com'))!.toBeInTheDocument() }) it('should render used-by text when workflows are present', () => { render() - expect(screen.getByText(/pluginTrigger\.subscription\.list\.item\.usedByNum/)).toBeInTheDocument() + expect(screen.getByText(/pluginTrigger\.subscription\.list\.item\.usedByNum/))!.toBeInTheDocument() }) it('should open delete confirmation when delete action is clicked', () => { @@ -79,15 +79,15 @@ describe('SubscriptionCard', () => { expect(deleteButton).toBeTruthy() fireEvent.click(deleteButton) - expect(screen.getByText(/pluginTrigger\.subscription\.list\.item\.actions\.deleteConfirm\.title/)).toBeInTheDocument() + expect(screen.getByText(/pluginTrigger\.subscription\.list\.item\.actions\.deleteConfirm\.title/))!.toBeInTheDocument() }) it('should open edit modal when edit action is clicked', () => { const { container } = render() const editButton = container.querySelectorAll('button')[0] - fireEvent.click(editButton) + fireEvent.click(editButton!) - expect(screen.getByText(/pluginTrigger\.subscription\.list\.item\.actions\.edit\.title/)).toBeInTheDocument() + expect(screen.getByText(/pluginTrigger\.subscription\.list\.item\.actions\.edit\.title/))!.toBeInTheDocument() }) }) diff --git a/web/app/components/plugins/plugin-detail-panel/subscription-list/create/__tests__/index.spec.tsx b/web/app/components/plugins/plugin-detail-panel/subscription-list/create/__tests__/index.spec.tsx index a36c108160..0714fbf554 100644 --- a/web/app/components/plugins/plugin-detail-panel/subscription-list/create/__tests__/index.spec.tsx +++ b/web/app/components/plugins/plugin-detail-panel/subscription-list/create/__tests__/index.spec.tsx @@ -246,7 +246,8 @@ describe('CreateSubscriptionButton', () => { const { container } = render() // Assert - expect(container).toBeEmptyDOMElement() + // Assert + expect(container)!.toBeEmptyDOMElement() }) it('should render without crashing when supportedMethods is provided', () => { @@ -260,6 +261,37 @@ describe('CreateSubscriptionButton', () => { // Act const { container } = render() + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert // Assert expect(container).not.toBeEmptyDOMElement() }) @@ -276,7 +308,8 @@ describe('CreateSubscriptionButton', () => { render() // Assert - expect(screen.getByRole('button')).toBeInTheDocument() + // Assert + expect(screen.getByRole('button'))!.toBeInTheDocument() }) it('should render icon button when buttonType is ICON_BUTTON', () => { @@ -292,7 +325,7 @@ describe('CreateSubscriptionButton', () => { // Assert const actionButton = screen.getByTestId('custom-trigger') - expect(actionButton).toBeInTheDocument() + expect(actionButton)!.toBeInTheDocument() }) }) @@ -309,7 +342,8 @@ describe('CreateSubscriptionButton', () => { render() // Assert - expect(screen.getByRole('button')).toBeInTheDocument() + // Assert + expect(screen.getByRole('button'))!.toBeInTheDocument() }) it('should apply shape prop correctly', () => { @@ -324,7 +358,8 @@ describe('CreateSubscriptionButton', () => { render() // Assert - expect(screen.getByTestId('custom-trigger')).toBeInTheDocument() + // Assert + expect(screen.getByTestId('custom-trigger'))!.toBeInTheDocument() }) }) @@ -348,8 +383,8 @@ describe('CreateSubscriptionButton', () => { // Assert await waitFor(() => { - expect(screen.getByTestId('common-create-modal')).toBeInTheDocument() - expect(screen.getByTestId('common-create-modal')).toHaveAttribute('data-create-type', SupportedCreationMethods.MANUAL) + expect(screen.getByTestId('common-create-modal'))!.toBeInTheDocument() + expect(screen.getByTestId('common-create-modal'))!.toHaveAttribute('data-create-type', SupportedCreationMethods.MANUAL) }) }) @@ -371,7 +406,7 @@ describe('CreateSubscriptionButton', () => { fireEvent.click(manualOption) await waitFor(() => { - expect(screen.getByTestId('common-create-modal')).toBeInTheDocument() + expect(screen.getByTestId('common-create-modal'))!.toBeInTheDocument() }) // Close modal @@ -403,7 +438,7 @@ describe('CreateSubscriptionButton', () => { // Assert await waitFor(() => { - expect(screen.getByTestId('oauth-client-modal')).toBeInTheDocument() + expect(screen.getByTestId('oauth-client-modal'))!.toBeInTheDocument() }) }) @@ -432,7 +467,7 @@ describe('CreateSubscriptionButton', () => { fireEvent.click(oauthOption) await waitFor(() => { - expect(screen.getByTestId('oauth-client-modal')).toBeInTheDocument() + expect(screen.getByTestId('oauth-client-modal'))!.toBeInTheDocument() }) // Close modal @@ -463,7 +498,7 @@ describe('CreateSubscriptionButton', () => { // Assert - OAuth mode renders with settings button, use getAllByRole const buttons = screen.getAllByRole('button') - expect(buttons[0]).toHaveTextContent('pluginTrigger.subscription.createButton.oauth') + expect(buttons[0])!.toHaveTextContent('pluginTrigger.subscription.createButton.oauth') }) it('should display correct button text for APIKEY method', () => { @@ -480,7 +515,8 @@ describe('CreateSubscriptionButton', () => { render() // Assert - expect(screen.getByRole('button')).toHaveTextContent('pluginTrigger.subscription.createButton.apiKey') + // Assert + expect(screen.getByRole('button'))!.toHaveTextContent('pluginTrigger.subscription.createButton.apiKey') }) it('should display correct button text for MANUAL method', () => { @@ -497,7 +533,8 @@ describe('CreateSubscriptionButton', () => { render() // Assert - expect(screen.getByRole('button')).toHaveTextContent('pluginTrigger.subscription.createButton.manual') + // Assert + expect(screen.getByRole('button'))!.toHaveTextContent('pluginTrigger.subscription.createButton.manual') }) it('should display default button text when multiple methods are supported', () => { @@ -514,7 +551,8 @@ describe('CreateSubscriptionButton', () => { render() // Assert - expect(screen.getByRole('button')).toHaveTextContent('pluginTrigger.subscription.empty.button') + // Assert + expect(screen.getByRole('button'))!.toHaveTextContent('pluginTrigger.subscription.empty.button') }) }) @@ -535,7 +573,7 @@ describe('CreateSubscriptionButton', () => { // Assert const customSelect = screen.getByTestId('custom-select') - expect(customSelect).toHaveAttribute('data-options-count', '1') + expect(customSelect)!.toHaveAttribute('data-options-count', '1') }) it('should show all options when all methods are supported', () => { @@ -558,7 +596,7 @@ describe('CreateSubscriptionButton', () => { // Assert const customSelect = screen.getByTestId('custom-select') - expect(customSelect).toHaveAttribute('data-options-count', '3') + expect(customSelect)!.toHaveAttribute('data-options-count', '3') }) it('should show custom badge when OAuth custom is enabled and configured', () => { @@ -581,7 +619,7 @@ describe('CreateSubscriptionButton', () => { // Assert - Custom badge should appear in the button const buttons = screen.getAllByRole('button') - expect(buttons[0]).toHaveTextContent('plugin.auth.custom') + expect(buttons[0])!.toHaveTextContent('plugin.auth.custom') }) it('should not show custom badge when OAuth custom is not configured', () => { @@ -624,7 +662,7 @@ describe('CreateSubscriptionButton', () => { // Assert const customSelect = screen.getByTestId('custom-select') - expect(customSelect).toHaveAttribute('data-value', DEFAULT_METHOD) + expect(customSelect)!.toHaveAttribute('data-value', DEFAULT_METHOD) }) it('should set methodType to single method when only one supported', () => { @@ -642,7 +680,7 @@ describe('CreateSubscriptionButton', () => { // Assert const customSelect = screen.getByTestId('custom-select') - expect(customSelect).toHaveAttribute('data-value', SupportedCreationMethods.MANUAL) + expect(customSelect)!.toHaveAttribute('data-value', SupportedCreationMethods.MANUAL) }) }) @@ -669,6 +707,37 @@ describe('CreateSubscriptionButton', () => { const button = screen.getByRole('button') fireEvent.click(button) + // Assert - modal should not open + // Assert - modal should not open + // Assert - modal should not open + // Assert - modal should not open + // Assert - modal should not open + // Assert - modal should not open + // Assert - modal should not open + // Assert - modal should not open + // Assert - modal should not open + // Assert - modal should not open + // Assert - modal should not open + // Assert - modal should not open + // Assert - modal should not open + // Assert - modal should not open + // Assert - modal should not open + // Assert - modal should not open + // Assert - modal should not open + // Assert - modal should not open + // Assert - modal should not open + // Assert - modal should not open + // Assert - modal should not open + // Assert - modal should not open + // Assert - modal should not open + // Assert - modal should not open + // Assert - modal should not open + // Assert - modal should not open + // Assert - modal should not open + // Assert - modal should not open + // Assert - modal should not open + // Assert - modal should not open + // Assert - modal should not open // Assert - modal should not open expect(screen.queryByTestId('common-create-modal')).not.toBeInTheDocument() }) @@ -689,7 +758,8 @@ describe('CreateSubscriptionButton', () => { fireEvent.click(button) // Assert - modal should open - expect(screen.getByTestId('common-create-modal')).toBeInTheDocument() + // Assert - modal should open + expect(screen.getByTestId('common-create-modal'))!.toBeInTheDocument() }) it('should not call onChooseCreateType for DEFAULT_METHOD or single OAuth', () => { @@ -707,8 +777,70 @@ describe('CreateSubscriptionButton', () => { render() // For OAuth mode, there are multiple buttons; get the primary button (first one) const buttons = screen.getAllByRole('button') - fireEvent.click(buttons[0]) + fireEvent.click(buttons[0]!) + // Assert - For single OAuth, should not directly create but wait for dropdown + // The modal should not immediately open + // Assert - For single OAuth, should not directly create but wait for dropdown + // The modal should not immediately open + // Assert - For single OAuth, should not directly create but wait for dropdown + // The modal should not immediately open + // Assert - For single OAuth, should not directly create but wait for dropdown + // The modal should not immediately open + // Assert - For single OAuth, should not directly create but wait for dropdown + // The modal should not immediately open + // Assert - For single OAuth, should not directly create but wait for dropdown + // The modal should not immediately open + // Assert - For single OAuth, should not directly create but wait for dropdown + // The modal should not immediately open + // Assert - For single OAuth, should not directly create but wait for dropdown + // The modal should not immediately open + // Assert - For single OAuth, should not directly create but wait for dropdown + // The modal should not immediately open + // Assert - For single OAuth, should not directly create but wait for dropdown + // The modal should not immediately open + // Assert - For single OAuth, should not directly create but wait for dropdown + // The modal should not immediately open + // Assert - For single OAuth, should not directly create but wait for dropdown + // The modal should not immediately open + // Assert - For single OAuth, should not directly create but wait for dropdown + // The modal should not immediately open + // Assert - For single OAuth, should not directly create but wait for dropdown + // The modal should not immediately open + // Assert - For single OAuth, should not directly create but wait for dropdown + // The modal should not immediately open + // Assert - For single OAuth, should not directly create but wait for dropdown + // The modal should not immediately open + // Assert - For single OAuth, should not directly create but wait for dropdown + // The modal should not immediately open + // Assert - For single OAuth, should not directly create but wait for dropdown + // The modal should not immediately open + // Assert - For single OAuth, should not directly create but wait for dropdown + // The modal should not immediately open + // Assert - For single OAuth, should not directly create but wait for dropdown + // The modal should not immediately open + // Assert - For single OAuth, should not directly create but wait for dropdown + // The modal should not immediately open + // Assert - For single OAuth, should not directly create but wait for dropdown + // The modal should not immediately open + // Assert - For single OAuth, should not directly create but wait for dropdown + // The modal should not immediately open + // Assert - For single OAuth, should not directly create but wait for dropdown + // The modal should not immediately open + // Assert - For single OAuth, should not directly create but wait for dropdown + // The modal should not immediately open + // Assert - For single OAuth, should not directly create but wait for dropdown + // The modal should not immediately open + // Assert - For single OAuth, should not directly create but wait for dropdown + // The modal should not immediately open + // Assert - For single OAuth, should not directly create but wait for dropdown + // The modal should not immediately open + // Assert - For single OAuth, should not directly create but wait for dropdown + // The modal should not immediately open + // Assert - For single OAuth, should not directly create but wait for dropdown + // The modal should not immediately open + // Assert - For single OAuth, should not directly create but wait for dropdown + // The modal should not immediately open // Assert - For single OAuth, should not directly create but wait for dropdown // The modal should not immediately open expect(screen.queryByTestId('common-create-modal')).not.toBeInTheDocument() @@ -736,7 +868,7 @@ describe('CreateSubscriptionButton', () => { // Assert await waitFor(() => { - expect(screen.getByTestId('oauth-client-modal')).toBeInTheDocument() + expect(screen.getByTestId('oauth-client-modal'))!.toBeInTheDocument() }) }) @@ -783,8 +915,8 @@ describe('CreateSubscriptionButton', () => { // Assert await waitFor(() => { - expect(screen.getByTestId('common-create-modal')).toBeInTheDocument() - expect(screen.getByTestId('common-create-modal')).toHaveAttribute('data-create-type', SupportedCreationMethods.APIKEY) + expect(screen.getByTestId('common-create-modal'))!.toBeInTheDocument() + expect(screen.getByTestId('common-create-modal'))!.toHaveAttribute('data-create-type', SupportedCreationMethods.APIKEY) }) }) @@ -807,8 +939,8 @@ describe('CreateSubscriptionButton', () => { // Assert await waitFor(() => { - expect(screen.getByTestId('common-create-modal')).toBeInTheDocument() - expect(screen.getByTestId('common-create-modal')).toHaveAttribute('data-create-type', SupportedCreationMethods.MANUAL) + expect(screen.getByTestId('common-create-modal'))!.toBeInTheDocument() + expect(screen.getByTestId('common-create-modal'))!.toHaveAttribute('data-create-type', SupportedCreationMethods.MANUAL) }) }) }) @@ -831,16 +963,17 @@ describe('CreateSubscriptionButton', () => { // Find the settings div inside the button (p-2 class) const buttons = screen.getAllByRole('button') const primaryButton = buttons[0] - const settingsDiv = primaryButton.querySelector('.p-2') + const settingsDiv = primaryButton!.querySelector('.p-2') // Assert that settings div exists and click it - expect(settingsDiv).toBeInTheDocument() + // Assert that settings div exists and click it + expect(settingsDiv)!.toBeInTheDocument() if (settingsDiv) { fireEvent.click(settingsDiv) // Assert await waitFor(() => { - expect(screen.getByTestId('oauth-client-modal')).toBeInTheDocument() + expect(screen.getByTestId('oauth-client-modal'))!.toBeInTheDocument() }) } }) @@ -860,7 +993,8 @@ describe('CreateSubscriptionButton', () => { render() // Assert - Component renders, which means hook was called - expect(screen.getByTestId('custom-select')).toBeInTheDocument() + // Assert - Component renders, which means hook was called + expect(screen.getByTestId('custom-select'))!.toBeInTheDocument() }) it('should handle OAuth initiation success', async () => { @@ -908,8 +1042,8 @@ describe('CreateSubscriptionButton', () => { // Assert - modal should open with OAuth type and builder await waitFor(() => { - expect(screen.getByTestId('common-create-modal')).toBeInTheDocument() - expect(screen.getByTestId('common-create-modal')).toHaveAttribute('data-has-builder', 'true') + expect(screen.getByTestId('common-create-modal'))!.toBeInTheDocument() + expect(screen.getByTestId('common-create-modal'))!.toHaveAttribute('data-has-builder', 'true') }) }) @@ -956,6 +1090,37 @@ describe('CreateSubscriptionButton', () => { // Act const { container } = render() + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert // Assert expect(container).not.toBeEmptyDOMElement() }) @@ -972,7 +1137,8 @@ describe('CreateSubscriptionButton', () => { render() // Assert - component should still render - expect(screen.getByTestId('custom-select')).toBeInTheDocument() + // Assert - component should still render + expect(screen.getByTestId('custom-select'))!.toBeInTheDocument() }) it('should handle empty oauthConfig gracefully', () => { @@ -990,7 +1156,8 @@ describe('CreateSubscriptionButton', () => { render() // Assert - expect(screen.getByTestId('custom-select')).toBeInTheDocument() + // Assert + expect(screen.getByTestId('custom-select'))!.toBeInTheDocument() }) it('should show max count tooltip when subscriptions reach limit', () => { @@ -1010,7 +1177,8 @@ describe('CreateSubscriptionButton', () => { render() // Assert - ActionButton should be in disabled state - expect(screen.getByTestId('custom-trigger')).toBeInTheDocument() + // Assert - ActionButton should be in disabled state + expect(screen.getByTestId('custom-trigger'))!.toBeInTheDocument() }) it('should handle showOAuthCreateModal callback from OAuthClientSettingsModal', async () => { @@ -1032,7 +1200,7 @@ describe('CreateSubscriptionButton', () => { fireEvent.click(oauthOption) await waitFor(() => { - expect(screen.getByTestId('oauth-client-modal')).toBeInTheDocument() + expect(screen.getByTestId('oauth-client-modal'))!.toBeInTheDocument() }) // Click show create modal button @@ -1040,9 +1208,9 @@ describe('CreateSubscriptionButton', () => { // Assert - CommonCreateModal should be shown with OAuth type and builder await waitFor(() => { - expect(screen.getByTestId('common-create-modal')).toBeInTheDocument() - expect(screen.getByTestId('common-create-modal')).toHaveAttribute('data-create-type', SupportedCreationMethods.OAUTH) - expect(screen.getByTestId('common-create-modal')).toHaveAttribute('data-has-builder', 'true') + expect(screen.getByTestId('common-create-modal'))!.toBeInTheDocument() + expect(screen.getByTestId('common-create-modal'))!.toHaveAttribute('data-create-type', SupportedCreationMethods.OAUTH) + expect(screen.getByTestId('common-create-modal'))!.toHaveAttribute('data-has-builder', 'true') }) }) }) @@ -1066,8 +1234,8 @@ describe('CreateSubscriptionButton', () => { // Assert - settings icon should be present in button, OAuth mode has multiple buttons const buttons = screen.getAllByRole('button') const primaryButton = buttons[0] - const settingsDiv = primaryButton.querySelector('.p-2') - expect(settingsDiv).toBeInTheDocument() + const settingsDiv = primaryButton!.querySelector('.p-2') + expect(settingsDiv)!.toBeInTheDocument() }) it('should not render settings icon for non-OAuth methods', () => { @@ -1106,7 +1274,8 @@ describe('CreateSubscriptionButton', () => { render() // Assert - icon button should exist - expect(screen.getByTestId('custom-trigger')).toBeInTheDocument() + // Assert - icon button should exist + expect(screen.getByTestId('custom-trigger'))!.toBeInTheDocument() }) it('should apply circle shape class when shape is circle', () => { @@ -1123,7 +1292,8 @@ describe('CreateSubscriptionButton', () => { render() // Assert - expect(screen.getByTestId('custom-trigger')).toBeInTheDocument() + // Assert + expect(screen.getByTestId('custom-trigger'))!.toBeInTheDocument() }) }) @@ -1181,7 +1351,7 @@ describe('CreateSubscriptionButton', () => { // Assert - for single non-OAuth, dropdown should be disabled (open = false) const customSelect = screen.getByTestId('custom-select') - expect(customSelect).toHaveAttribute('data-container-open', 'false') + expect(customSelect)!.toHaveAttribute('data-container-open', 'false') }) }) @@ -1202,7 +1372,7 @@ describe('CreateSubscriptionButton', () => { // Assert const button = screen.getByRole('button') - expect(button).toHaveClass('w-full') + expect(button)!.toHaveClass('w-full') }) it('should render icon button with float-right class', () => { @@ -1219,7 +1389,8 @@ describe('CreateSubscriptionButton', () => { render() // Assert - expect(screen.getByTestId('custom-trigger')).toBeInTheDocument() + // Assert + expect(screen.getByTestId('custom-trigger'))!.toBeInTheDocument() }) }) @@ -1265,7 +1436,7 @@ describe('CreateSubscriptionButton', () => { // Assert await waitFor(() => { const modal = screen.getByTestId('common-create-modal') - expect(modal).toHaveAttribute('data-create-type', SupportedCreationMethods.MANUAL) + expect(modal)!.toHaveAttribute('data-create-type', SupportedCreationMethods.MANUAL) }) }) @@ -1289,7 +1460,7 @@ describe('CreateSubscriptionButton', () => { // Assert await waitFor(() => { const modal = screen.getByTestId('common-create-modal') - expect(modal).toHaveAttribute('data-create-type', SupportedCreationMethods.APIKEY) + expect(modal)!.toHaveAttribute('data-create-type', SupportedCreationMethods.APIKEY) }) }) @@ -1339,7 +1510,7 @@ describe('CreateSubscriptionButton', () => { // Assert await waitFor(() => { const modal = screen.getByTestId('common-create-modal') - expect(modal).toHaveAttribute('data-has-builder', 'true') + expect(modal)!.toHaveAttribute('data-has-builder', 'true') }) }) }) @@ -1368,7 +1539,7 @@ describe('CreateSubscriptionButton', () => { // Assert await waitFor(() => { const modal = screen.getByTestId('oauth-client-modal') - expect(modal).toHaveAttribute('data-has-config', 'true') + expect(modal)!.toHaveAttribute('data-has-config', 'true') }) }) @@ -1397,7 +1568,7 @@ describe('CreateSubscriptionButton', () => { fireEvent.click(oauthOption) await waitFor(() => { - expect(screen.getByTestId('oauth-client-modal')).toBeInTheDocument() + expect(screen.getByTestId('oauth-client-modal'))!.toBeInTheDocument() }) // Close modal @@ -1428,7 +1599,7 @@ describe('CreateSubscriptionButton', () => { fireEvent.click(oauthOption) await waitFor(() => { - expect(screen.getByTestId('oauth-client-modal')).toBeInTheDocument() + expect(screen.getByTestId('oauth-client-modal'))!.toBeInTheDocument() }) // Click showOAuthCreateModal button @@ -1436,9 +1607,9 @@ describe('CreateSubscriptionButton', () => { // Assert - CommonCreateModal should appear with OAuth type and builder await waitFor(() => { - expect(screen.getByTestId('common-create-modal')).toBeInTheDocument() - expect(screen.getByTestId('common-create-modal')).toHaveAttribute('data-create-type', SupportedCreationMethods.OAUTH) - expect(screen.getByTestId('common-create-modal')).toHaveAttribute('data-has-builder', 'true') + expect(screen.getByTestId('common-create-modal'))!.toBeInTheDocument() + expect(screen.getByTestId('common-create-modal'))!.toHaveAttribute('data-create-type', SupportedCreationMethods.OAUTH) + expect(screen.getByTestId('common-create-modal'))!.toHaveAttribute('data-has-builder', 'true') }) }) }) @@ -1513,7 +1684,9 @@ describe('CreateSubscriptionButton', () => { // The methodType will be DEFAULT_METHOD since multiple methods // This verifies the render doesn't crash with multiple methods - expect(screen.getByTestId('custom-select')).toHaveAttribute('data-value', 'default') + // The methodType will be DEFAULT_METHOD since multiple methods + // This verifies the render doesn't crash with multiple methods + expect(screen.getByTestId('custom-select'))!.toHaveAttribute('data-value', 'default') }) }) @@ -1534,7 +1707,8 @@ describe('CreateSubscriptionButton', () => { render() // Assert - tooltip should be enabled (disabled prop = false for single method) - expect(screen.getByTestId('custom-trigger')).toBeInTheDocument() + // Assert - tooltip should be enabled (disabled prop = false for single method) + expect(screen.getByTestId('custom-trigger'))!.toBeInTheDocument() }) it('should disable tooltip when multiple methods and not at max count', () => { @@ -1552,7 +1726,8 @@ describe('CreateSubscriptionButton', () => { render() // Assert - tooltip should be disabled (neither single method nor at max) - expect(screen.getByTestId('custom-trigger')).toBeInTheDocument() + // Assert - tooltip should be disabled (neither single method nor at max) + expect(screen.getByTestId('custom-trigger'))!.toBeInTheDocument() }) }) @@ -1574,7 +1749,8 @@ describe('CreateSubscriptionButton', () => { render() // Assert - component renders with max subscriptions - expect(screen.getByTestId('custom-trigger')).toBeInTheDocument() + // Assert - component renders with max subscriptions + expect(screen.getByTestId('custom-trigger'))!.toBeInTheDocument() }) it('should show method description when not at max', () => { @@ -1592,7 +1768,8 @@ describe('CreateSubscriptionButton', () => { render() // Assert - component renders without max subscriptions - expect(screen.getByTestId('custom-trigger')).toBeInTheDocument() + // Assert - component renders without max subscriptions + expect(screen.getByTestId('custom-trigger'))!.toBeInTheDocument() }) }) @@ -1613,7 +1790,8 @@ describe('CreateSubscriptionButton', () => { const { container } = render() // Assert - should render null when supported methods fallback to empty - expect(container).toBeEmptyDOMElement() + // Assert - should render null when supported methods fallback to empty + expect(container)!.toBeEmptyDOMElement() }) it('should handle providerInfo with null supported_creation_methods', () => { @@ -1627,7 +1805,8 @@ describe('CreateSubscriptionButton', () => { const { container } = render() // Assert - should render null - expect(container).toBeEmptyDOMElement() + // Assert - should render null + expect(container)!.toBeEmptyDOMElement() }) }) @@ -1648,7 +1827,7 @@ describe('CreateSubscriptionButton', () => { // Assert const customSelect = screen.getByTestId('custom-select') - expect(customSelect).toHaveAttribute('data-value', SupportedCreationMethods.APIKEY) + expect(customSelect)!.toHaveAttribute('data-value', SupportedCreationMethods.APIKEY) }) }) }) diff --git a/web/app/components/plugins/plugin-detail-panel/subscription-list/create/hooks/__tests__/use-oauth-client-state.spec.ts b/web/app/components/plugins/plugin-detail-panel/subscription-list/create/hooks/__tests__/use-oauth-client-state.spec.ts index 68864b0b80..cebfc947e7 100644 --- a/web/app/components/plugins/plugin-detail-panel/subscription-list/create/hooks/__tests__/use-oauth-client-state.spec.ts +++ b/web/app/components/plugins/plugin-detail-panel/subscription-list/create/hooks/__tests__/use-oauth-client-state.spec.ts @@ -194,8 +194,8 @@ describe('useOAuthClientState', () => { })) expect(result.current.oauthClientSchema).toHaveLength(2) - expect(result.current.oauthClientSchema[0].default).toBe('my-client-id') - expect(result.current.oauthClientSchema[1].default).toBe('my-secret') + expect(result.current.oauthClientSchema[0]!.default).toBe('my-client-id') + expect(result.current.oauthClientSchema[1]!.default).toBe('my-secret') }) it('should return empty array when oauth_client_schema is empty', () => { @@ -239,9 +239,9 @@ describe('useOAuthClientState', () => { })) // client_id should be overridden - expect(result.current.oauthClientSchema[0].default).toBe('only-client-id') + expect(result.current.oauthClientSchema[0]!.default).toBe('only-client-id') // extra_field should keep original default since key not in params - expect(result.current.oauthClientSchema[1].default).toBe('extra-default') + expect(result.current.oauthClientSchema[1]!.default).toBe('extra-default') }) }) diff --git a/web/app/components/plugins/plugin-detail-panel/subscription-list/create/hooks/use-common-modal-state.ts b/web/app/components/plugins/plugin-detail-panel/subscription-list/create/hooks/use-common-modal-state.ts index e55f9525fe..29613c6f4f 100644 --- a/web/app/components/plugins/plugin-detail-panel/subscription-list/create/hooks/use-common-modal-state.ts +++ b/web/app/components/plugins/plugin-detail-panel/subscription-list/create/hooks/use-common-modal-state.ts @@ -202,7 +202,7 @@ export const useCommonModalState = ({ if (!apiKeyCredentialsSchema.length) return apiKeyCredentialsFormRef.current?.setFields([{ - name: apiKeyCredentialsSchema[0].name, + name: apiKeyCredentialsSchema[0]!.name, errors: [], }]) }, [apiKeyCredentialsSchema]) diff --git a/web/app/components/plugins/plugin-detail-panel/subscription-list/create/index.tsx b/web/app/components/plugins/plugin-detail-panel/subscription-list/create/index.tsx index 73b28bd60e..4861f30934 100644 --- a/web/app/components/plugins/plugin-detail-panel/subscription-list/create/index.tsx +++ b/web/app/components/plugins/plugin-detail-panel/subscription-list/create/index.tsx @@ -137,7 +137,7 @@ export const CreateSubscriptionButton = ({ buttonType = CreateButtonType.FULL_BU e.stopPropagation() e.preventDefault() - onChooseCreateType(methodType) + onChooseCreateType(methodType!) } if (!supportedMethods.length) @@ -172,7 +172,7 @@ export const CreateSubscriptionButton = ({ buttonType = CreateButtonType.FULL_BU >
- {buttonTextMap[methodType]} + {buttonTextMap[methodType!]} {methodType === SupportedCreationMethods.OAUTH && oauthConfig?.custom_enabled && oauthConfig?.custom_configured && ( = MAX_COUNT ? t('subscription.maxCount', { ns: 'pluginTrigger', num: MAX_COUNT }) : t(`subscription.addType.options.${methodType.toLowerCase() as Lowercase}.description`, { ns: 'pluginTrigger' })} + popupContent={subscriptionCount >= MAX_COUNT ? t('subscription.maxCount', { ns: 'pluginTrigger', num: MAX_COUNT }) : t(`subscription.addType.options.${methodType!.toLowerCase() as Lowercase}.description`, { ns: 'pluginTrigger' })} disabled={!(supportedMethods?.length === 1 || subscriptionCount >= MAX_COUNT)} > { return produce(value, (draft) => { - draft[variable].value = { + draft[variable]!.value = { type: newType, value: newType === VarKindType.variable ? '' : defaultValue, } @@ -126,7 +126,7 @@ export const updateReasoningValue = ( newValue: unknown, ) => { return produce(value, (draft) => { - draft[variable].value = { + draft[variable]!.value = { type: getVarKindType(type), value: newValue, } @@ -139,8 +139,8 @@ export const mergeReasoningValue = ( newValue: Record, ) => { return produce(value, (draft) => { - const currentValue = draft[variable].value as Record | undefined - draft[variable].value = { + const currentValue = draft[variable]!.value as Record | undefined + draft[variable]!.value = { ...currentValue, ...newValue, } @@ -153,7 +153,7 @@ export const updateVariableSelectorValue = ( newValue: ValueSelector | string, ) => { return produce(value, (draft) => { - draft[variable].value = { + draft[variable]!.value = { type: VarKindType.variable, value: newValue, } diff --git a/web/app/components/plugins/plugin-detail-panel/tool-selector/components/reasoning-config-form.tsx b/web/app/components/plugins/plugin-detail-panel/tool-selector/components/reasoning-config-form.tsx index 8a3642d043..4e6be7d81c 100644 --- a/web/app/components/plugins/plugin-detail-panel/tool-selector/components/reasoning-config-form.tsx +++ b/web/app/components/plugins/plugin-detail-panel/tool-selector/components/reasoning-config-form.tsx @@ -137,7 +137,7 @@ const ReasoningConfigForm: React.FC = ({ asChild={false} /> )) - const varInput = value[variable].value + const varInput = value[variable]!.value const { isString, isNumber, @@ -179,7 +179,7 @@ const ReasoningConfigForm: React.FC = ({ >
showSchema(input_schema as SchemaRoot, fieldTitle)} + onClick={() => showSchema(input_schema as SchemaRoot, fieldTitle!)} >
diff --git a/web/app/components/plugins/plugin-detail-panel/tool-selector/hooks/__tests__/use-tool-selector-state.spec.ts b/web/app/components/plugins/plugin-detail-panel/tool-selector/hooks/__tests__/use-tool-selector-state.spec.ts index 5af624649c..dff369c969 100644 --- a/web/app/components/plugins/plugin-detail-panel/tool-selector/hooks/__tests__/use-tool-selector-state.spec.ts +++ b/web/app/components/plugins/plugin-detail-panel/tool-selector/hooks/__tests__/use-tool-selector-state.spec.ts @@ -112,11 +112,11 @@ describe('useToolSelectorState', () => { // param2 has form='form' (not 'llm'), so it goes to settings expect(result.current.currentToolSettings).toHaveLength(1) - expect(result.current.currentToolSettings[0].name).toBe('param2') + expect(result.current.currentToolSettings[0]!.name).toBe('param2') // param1 has form='llm', so it goes to params expect(result.current.currentToolParams).toHaveLength(1) - expect(result.current.currentToolParams[0].name).toBe('param1') + expect(result.current.currentToolParams[0]!.name).toBe('param1') }) it('should show tab slider when both settings and params exist', () => { diff --git a/web/app/components/plugins/plugin-detail-panel/trigger/__tests__/event-detail-drawer.spec.tsx b/web/app/components/plugins/plugin-detail-panel/trigger/__tests__/event-detail-drawer.spec.tsx index a04aba3e57..77b77c0302 100644 --- a/web/app/components/plugins/plugin-detail-panel/trigger/__tests__/event-detail-drawer.spec.tsx +++ b/web/app/components/plugins/plugin-detail-panel/trigger/__tests__/event-detail-drawer.spec.tsx @@ -91,45 +91,45 @@ describe('EventDetailDrawer', () => { it('should render drawer', () => { render() - expect(screen.getByRole('dialog')).toBeInTheDocument() + expect(screen.getByRole('dialog'))!.toBeInTheDocument() }) it('should render event title', () => { render() - expect(screen.getByText('Test Event')).toBeInTheDocument() + expect(screen.getByText('Test Event'))!.toBeInTheDocument() }) it('should render event description', () => { render() - expect(screen.getByTestId('description')).toHaveTextContent('Test event description') + expect(screen.getByTestId('description'))!.toHaveTextContent('Test event description') }) it('should render org info', () => { render() - expect(screen.getByTestId('org-info')).toBeInTheDocument() + expect(screen.getByTestId('org-info'))!.toBeInTheDocument() }) it('should render parameters section', () => { render() - expect(screen.getByText('tools.setBuiltInTools.parameters')).toBeInTheDocument() - expect(screen.getByText('Parameter 1')).toBeInTheDocument() + expect(screen.getByText('tools.setBuiltInTools.parameters'))!.toBeInTheDocument() + expect(screen.getByText('Parameter 1'))!.toBeInTheDocument() }) it('should render output section', () => { render() - expect(screen.getByText('pluginTrigger.events.output')).toBeInTheDocument() - expect(screen.getByTestId('output-field')).toHaveTextContent('result') + expect(screen.getByText('pluginTrigger.events.output'))!.toBeInTheDocument() + expect(screen.getByTestId('output-field'))!.toHaveTextContent('result') }) it('should render back button', () => { render() - expect(screen.getByText('plugin.detailPanel.operation.back')).toBeInTheDocument() + expect(screen.getByText('plugin.detailPanel.operation.back'))!.toBeInTheDocument() }) }) @@ -159,14 +159,14 @@ describe('EventDetailDrawer', () => { const eventWithNoParams = { ...mockEventInfo, parameters: [] } render() - expect(screen.getByText('pluginTrigger.events.item.noParameters')).toBeInTheDocument() + expect(screen.getByText('pluginTrigger.events.item.noParameters'))!.toBeInTheDocument() }) it('should handle no output schema', () => { const eventWithNoOutput = { ...mockEventInfo, output_schema: {} } render() - expect(screen.getByText('pluginTrigger.events.output')).toBeInTheDocument() + expect(screen.getByText('pluginTrigger.events.output'))!.toBeInTheDocument() expect(screen.queryByTestId('output-field')).not.toBeInTheDocument() }) }) @@ -175,41 +175,41 @@ describe('EventDetailDrawer', () => { it('should display correct type for number-input', () => { const eventWithNumber = { ...mockEventInfo, - parameters: [{ ...mockEventInfo.parameters[0], type: 'number-input' }], + parameters: [{ ...mockEventInfo.parameters[0]!, type: 'number-input' }], } render() - expect(screen.getByText('tools.setBuiltInTools.number')).toBeInTheDocument() + expect(screen.getByText('tools.setBuiltInTools.number'))!.toBeInTheDocument() }) it('should display correct type for checkbox', () => { const eventWithCheckbox = { ...mockEventInfo, - parameters: [{ ...mockEventInfo.parameters[0], type: 'checkbox' }], + parameters: [{ ...mockEventInfo.parameters[0]!, type: 'checkbox' }], } render() - expect(screen.getByText('boolean')).toBeInTheDocument() + expect(screen.getByText('boolean'))!.toBeInTheDocument() }) it('should display correct type for file', () => { const eventWithFile = { ...mockEventInfo, - parameters: [{ ...mockEventInfo.parameters[0], type: 'file' }], + parameters: [{ ...mockEventInfo.parameters[0]!, type: 'file' }], } render() - expect(screen.getByText('tools.setBuiltInTools.file')).toBeInTheDocument() + expect(screen.getByText('tools.setBuiltInTools.file'))!.toBeInTheDocument() }) it('should display original type for unknown types', () => { const eventWithUnknown = { ...mockEventInfo, - parameters: [{ ...mockEventInfo.parameters[0], type: 'custom-type' }], + parameters: [{ ...mockEventInfo.parameters[0]!, type: 'custom-type' }], } render() - expect(screen.getByText('custom-type')).toBeInTheDocument() + expect(screen.getByText('custom-type'))!.toBeInTheDocument() }) }) @@ -226,7 +226,7 @@ describe('EventDetailDrawer', () => { } render() - expect(screen.getByText('pluginTrigger.events.output')).toBeInTheDocument() + expect(screen.getByText('pluginTrigger.events.output'))!.toBeInTheDocument() }) it('should handle nested properties in output schema', () => { @@ -245,7 +245,7 @@ describe('EventDetailDrawer', () => { } render() - expect(screen.getByText('pluginTrigger.events.output')).toBeInTheDocument() + expect(screen.getByText('pluginTrigger.events.output'))!.toBeInTheDocument() }) it('should handle enum in output schema', () => { @@ -260,7 +260,7 @@ describe('EventDetailDrawer', () => { } render() - expect(screen.getByText('pluginTrigger.events.output')).toBeInTheDocument() + expect(screen.getByText('pluginTrigger.events.output'))!.toBeInTheDocument() }) it('should handle array type schema', () => { @@ -275,7 +275,7 @@ describe('EventDetailDrawer', () => { } render() - expect(screen.getByText('pluginTrigger.events.output')).toBeInTheDocument() + expect(screen.getByText('pluginTrigger.events.output'))!.toBeInTheDocument() }) }) }) diff --git a/web/app/components/plugins/plugin-detail-panel/trigger/event-detail-drawer.tsx b/web/app/components/plugins/plugin-detail-panel/trigger/event-detail-drawer.tsx index bacb7bbd66..eb56a0178c 100644 --- a/web/app/components/plugins/plugin-detail-panel/trigger/event-detail-drawer.tsx +++ b/web/app/components/plugins/plugin-detail-panel/trigger/event-detail-drawer.tsx @@ -112,7 +112,7 @@ export const EventDetailDrawer: FC = (props) => { />
{eventInfo?.identity?.label[language]}
- +
{t('setBuiltInTools.parameters', { ns: 'tools' })}
diff --git a/web/app/components/plugins/plugin-item/__tests__/action.spec.tsx b/web/app/components/plugins/plugin-item/__tests__/action.spec.tsx index 82c4d69d1b..0b0d9c7fc8 100644 --- a/web/app/components/plugins/plugin-item/__tests__/action.spec.tsx +++ b/web/app/components/plugins/plugin-item/__tests__/action.spec.tsx @@ -253,10 +253,11 @@ describe('Action Component', () => { // Act render() - fireEvent.click(getActionButtons()[0]) + fireEvent.click(getActionButtons()[0]!) // Assert - expect(screen.getByText('plugin.action.delete')).toBeInTheDocument() + // Assert + expect(screen.getByText('plugin.action.delete'))!.toBeInTheDocument() }) it('should display plugin name in delete confirm content', () => { @@ -270,10 +271,11 @@ describe('Action Component', () => { // Act render() - fireEvent.click(getActionButtons()[0]) + fireEvent.click(getActionButtons()[0]!) // Assert - expect(screen.getByText('my-awesome-plugin')).toBeInTheDocument() + // Assert + expect(screen.getByText('my-awesome-plugin'))!.toBeInTheDocument() }) it('should hide confirm modal when cancel is clicked', () => { @@ -286,8 +288,8 @@ describe('Action Component', () => { // Act render() - fireEvent.click(getActionButtons()[0]) - expect(screen.getByText('plugin.action.delete')).toBeInTheDocument() + fireEvent.click(getActionButtons()[0]!) + expect(screen.getByText('plugin.action.delete'))!.toBeInTheDocument() fireEvent.click(getDeleteCancelButton()) @@ -308,7 +310,7 @@ describe('Action Component', () => { // Act render() - fireEvent.click(getActionButtons()[0]) + fireEvent.click(getActionButtons()[0]!) fireEvent.click(getDeleteConfirmButton()) // Assert @@ -330,7 +332,7 @@ describe('Action Component', () => { // Act render() - fireEvent.click(getActionButtons()[0]) + fireEvent.click(getActionButtons()[0]!) fireEvent.click(getDeleteConfirmButton()) // Assert @@ -352,7 +354,7 @@ describe('Action Component', () => { // Act render() - fireEvent.click(getActionButtons()[0]) + fireEvent.click(getActionButtons()[0]!) fireEvent.click(getDeleteConfirmButton()) // Assert @@ -374,7 +376,7 @@ describe('Action Component', () => { // Act render() - fireEvent.click(getActionButtons()[0]) + fireEvent.click(getActionButtons()[0]!) fireEvent.click(getDeleteConfirmButton()) // Assert @@ -401,12 +403,12 @@ describe('Action Component', () => { // Act render() - fireEvent.click(getActionButtons()[0]) + fireEvent.click(getActionButtons()[0]!) fireEvent.click(getDeleteConfirmButton()) // Assert - Loading state await waitFor(() => { - expect(getDeleteConfirmButton()).toBeDisabled() + expect(getDeleteConfirmButton())!.toBeDisabled() }) // Resolve and check modal closes @@ -434,13 +436,14 @@ describe('Action Component', () => { // Act render() - fireEvent.click(getActionButtons()[0]) + fireEvent.click(getActionButtons()[0]!) // Assert - expect(screen.getByTestId('plugin-info-modal')).toBeInTheDocument() - expect(screen.getByTestId('plugin-info-modal')).toHaveAttribute('data-repo', 'owner/repo-name') - expect(screen.getByTestId('plugin-info-modal')).toHaveAttribute('data-release', '2.0.0') - expect(screen.getByTestId('plugin-info-modal')).toHaveAttribute('data-package', 'my-package.difypkg') + // Assert + expect(screen.getByTestId('plugin-info-modal'))!.toBeInTheDocument() + expect(screen.getByTestId('plugin-info-modal'))!.toHaveAttribute('data-repo', 'owner/repo-name') + expect(screen.getByTestId('plugin-info-modal'))!.toHaveAttribute('data-release', '2.0.0') + expect(screen.getByTestId('plugin-info-modal'))!.toHaveAttribute('data-package', 'my-package.difypkg') }) it('should hide plugin info modal when close is clicked', () => { @@ -453,11 +456,42 @@ describe('Action Component', () => { // Act render() - fireEvent.click(getActionButtons()[0]) - expect(screen.getByTestId('plugin-info-modal')).toBeInTheDocument() + fireEvent.click(getActionButtons()[0]!) + expect(screen.getByTestId('plugin-info-modal'))!.toBeInTheDocument() fireEvent.click(screen.getByTestId('close-plugin-info')) + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert // Assert expect(screen.queryByTestId('plugin-info-modal')).not.toBeInTheDocument() }) @@ -481,7 +515,7 @@ describe('Action Component', () => { // Act render() - fireEvent.click(getActionButtons()[0]) + fireEvent.click(getActionButtons()[0]!) // Assert await waitFor(() => { @@ -507,7 +541,7 @@ describe('Action Component', () => { // Act render() - fireEvent.click(getActionButtons()[0]) + fireEvent.click(getActionButtons()[0]!) // Assert await waitFor(() => { @@ -526,7 +560,7 @@ describe('Action Component', () => { // Act render() - fireEvent.click(getActionButtons()[0]) + fireEvent.click(getActionButtons()[0]!) // Assert await waitFor(() => { @@ -550,7 +584,7 @@ describe('Action Component', () => { // Act render() - fireEvent.click(getActionButtons()[0]) + fireEvent.click(getActionButtons()[0]!) // Assert - toast is called with the translated payload await waitFor(() => { @@ -581,7 +615,7 @@ describe('Action Component', () => { // Act render() - fireEvent.click(getActionButtons()[0]) + fireEvent.click(getActionButtons()[0]!) // Assert await waitFor(() => { @@ -621,7 +655,7 @@ describe('Action Component', () => { // Act render() - fireEvent.click(getActionButtons()[0]) + fireEvent.click(getActionButtons()[0]!) // Wait for modal to be called await waitFor(() => { @@ -629,7 +663,7 @@ describe('Action Component', () => { }) // Invoke the callback - const call = mockSetShowUpdatePluginModal.mock.calls[0][0] + const call = mockSetShowUpdatePluginModal.mock.calls[0]![0] call.onSaveCallback() // Assert @@ -653,7 +687,7 @@ describe('Action Component', () => { // Act render() - fireEvent.click(getActionButtons()[0]) + fireEvent.click(getActionButtons()[0]!) // Assert await waitFor(() => { @@ -678,7 +712,7 @@ describe('Action Component', () => { // Act - First render and delete const { rerender } = render() - fireEvent.click(getActionButtons()[0]) + fireEvent.click(getActionButtons()[0]!) fireEvent.click(getDeleteConfirmButton()) await waitFor(() => { @@ -688,7 +722,7 @@ describe('Action Component', () => { // Re-render with same props mockUninstallPlugin.mockClear() rerender() - fireEvent.click(getActionButtons()[0]) + fireEvent.click(getActionButtons()[0]!) fireEvent.click(getDeleteConfirmButton()) await waitFor(() => { @@ -714,7 +748,7 @@ describe('Action Component', () => { // Act const { rerender } = render() - fireEvent.click(getActionButtons()[0]) + fireEvent.click(getActionButtons()[0]!) fireEvent.click(getDeleteConfirmButton()) await waitFor(() => { @@ -723,7 +757,7 @@ describe('Action Component', () => { mockUninstallPlugin.mockClear() rerender() - fireEvent.click(getActionButtons()[0]) + fireEvent.click(getActionButtons()[0]!) fireEvent.click(getDeleteConfirmButton()) await waitFor(() => { @@ -751,7 +785,7 @@ describe('Action Component', () => { // Act const { rerender } = render() - fireEvent.click(getActionButtons()[0]) + fireEvent.click(getActionButtons()[0]!) fireEvent.click(getDeleteConfirmButton()) await waitFor(() => { @@ -760,7 +794,7 @@ describe('Action Component', () => { expect(onDelete2).not.toHaveBeenCalled() rerender() - fireEvent.click(getActionButtons()[0]) + fireEvent.click(getActionButtons()[0]!) fireEvent.click(getDeleteConfirmButton()) await waitFor(() => { @@ -802,7 +836,7 @@ describe('Action Component', () => { // Act render() - fireEvent.click(getActionButtons()[0]) + fireEvent.click(getActionButtons()[0]!) // Assert - Should use author and pluginName as fallback await waitFor(() => { @@ -826,11 +860,12 @@ describe('Action Component', () => { // Act render() - fireEvent.click(getActionButtons()[0]) + fireEvent.click(getActionButtons()[0]!) fireEvent.click(getDeleteConfirmButton()) // The confirm button should be disabled during deletion - expect(getDeleteConfirmButton()).toBeDisabled() + // The confirm button should be disabled during deletion + expect(getDeleteConfirmButton())!.toBeDisabled() // Resolve the deletion resolveFirst!({ success: true }) @@ -851,10 +886,11 @@ describe('Action Component', () => { // Act render() - fireEvent.click(getActionButtons()[0]) + fireEvent.click(getActionButtons()[0]!) // Assert - expect(screen.getByText('plugin-with-special@chars#123')).toBeInTheDocument() + // Assert + expect(screen.getByText('plugin-with-special@chars#123'))!.toBeInTheDocument() }) }) diff --git a/web/app/components/plugins/plugin-item/index.tsx b/web/app/components/plugins/plugin-item/index.tsx index ad03c002d8..0f19db81e6 100644 --- a/web/app/components/plugins/plugin-item/index.tsx +++ b/web/app/components/plugins/plugin-item/index.tsx @@ -105,7 +105,7 @@ const PluginItem: FC = ({ }} >
- + {/* Header */}
diff --git a/web/app/components/plugins/plugin-page/filter-management/__tests__/category-filter.spec.tsx b/web/app/components/plugins/plugin-page/filter-management/__tests__/category-filter.spec.tsx index 051d16792a..e4b698a5f8 100644 --- a/web/app/components/plugins/plugin-page/filter-management/__tests__/category-filter.spec.tsx +++ b/web/app/components/plugins/plugin-page/filter-management/__tests__/category-filter.spec.tsx @@ -47,7 +47,7 @@ describe('CategoriesFilter', () => { it('should show "allCategories" when no categories selected', () => { render() - expect(screen.getByText('plugin.allCategories')).toBeInTheDocument() + expect(screen.getByText('plugin.allCategories'))!.toBeInTheDocument() }) it('should show selected category labels', () => { @@ -60,7 +60,7 @@ describe('CategoriesFilter', () => { it('should show +N when more than 2 selected', () => { render() - expect(screen.getByText('+1')).toBeInTheDocument() + expect(screen.getByText('+1'))!.toBeInTheDocument() }) it('should clear all selections when clear button clicked', () => { @@ -76,9 +76,9 @@ describe('CategoriesFilter', () => { it('should render category options in dropdown', () => { render() - expect(screen.getByText('Tool')).toBeInTheDocument() - expect(screen.getByText('Model')).toBeInTheDocument() - expect(screen.getByText('Extension')).toBeInTheDocument() + expect(screen.getByText('Tool'))!.toBeInTheDocument() + expect(screen.getByText('Model'))!.toBeInTheDocument() + expect(screen.getByText('Extension'))!.toBeInTheDocument() }) it('should toggle category on option click', () => { @@ -94,7 +94,7 @@ describe('CategoriesFilter', () => { render() const toolElements = screen.getAllByText('Tool') - fireEvent.click(toolElements[toolElements.length - 1]) + fireEvent.click(toolElements[toolElements.length - 1]!) expect(mockOnChange).toHaveBeenCalledWith([]) }) }) diff --git a/web/app/components/plugins/plugin-page/filter-management/__tests__/index.spec.tsx b/web/app/components/plugins/plugin-page/filter-management/__tests__/index.spec.tsx index 95f0c5c120..f30b5fb5fa 100644 --- a/web/app/components/plugins/plugin-page/filter-management/__tests__/index.spec.tsx +++ b/web/app/components/plugins/plugin-page/filter-management/__tests__/index.spec.tsx @@ -338,7 +338,8 @@ describe('SearchBox Component', () => { render() // Assert - expect(screen.getByPlaceholderText('plugin.search')).toBeInTheDocument() + // Assert + expect(screen.getByPlaceholderText('plugin.search'))!.toBeInTheDocument() }) it('should render with provided searchQuery value', () => { @@ -346,7 +347,8 @@ describe('SearchBox Component', () => { render() // Assert - expect(screen.getByDisplayValue('test query')).toBeInTheDocument() + // Assert + expect(screen.getByDisplayValue('test query'))!.toBeInTheDocument() }) it('should render search icon', () => { @@ -355,7 +357,7 @@ describe('SearchBox Component', () => { // Assert - Input should have showLeftIcon which renders search icon const wrapper = container.querySelector('.w-\\[200px\\]') - expect(wrapper).toBeInTheDocument() + expect(wrapper)!.toBeInTheDocument() }) }) @@ -464,7 +466,8 @@ describe('CategoriesFilter Component', () => { render() // Assert - expect(screen.getByText('plugin.allCategories')).toBeInTheDocument() + // Assert + expect(screen.getByText('plugin.allCategories'))!.toBeInTheDocument() }) it('should render dropdown arrow when no selection', () => { @@ -473,7 +476,7 @@ describe('CategoriesFilter Component', () => { // Assert - Arrow icon should be visible const arrowIcon = container.querySelector('svg') - expect(arrowIcon).toBeInTheDocument() + expect(arrowIcon)!.toBeInTheDocument() }) it('should render selected category labels', () => { @@ -481,7 +484,8 @@ describe('CategoriesFilter Component', () => { render() // Assert - expect(screen.getByText('Models')).toBeInTheDocument() + // Assert + expect(screen.getByText('Models'))!.toBeInTheDocument() }) it('should show clear button when categories are selected', () => { @@ -490,7 +494,7 @@ describe('CategoriesFilter Component', () => { // Assert - Close icon should be visible const closeIcon = container.querySelector('[class*="cursor-pointer"]') - expect(closeIcon).toBeInTheDocument() + expect(closeIcon)!.toBeInTheDocument() }) it('should show count badge for more than 2 selections', () => { @@ -498,7 +502,8 @@ describe('CategoriesFilter Component', () => { render() // Assert - expect(screen.getByText('+1')).toBeInTheDocument() + // Assert + expect(screen.getByText('+1'))!.toBeInTheDocument() }) }) @@ -512,7 +517,7 @@ describe('CategoriesFilter Component', () => { // Assert await waitFor(() => { - expect(screen.getByTestId('portal-content')).toBeInTheDocument() + expect(screen.getByTestId('portal-content'))!.toBeInTheDocument() }) }) @@ -525,10 +530,10 @@ describe('CategoriesFilter Component', () => { // Assert await waitFor(() => { - expect(screen.getByText('Models')).toBeInTheDocument() - expect(screen.getByText('Tools')).toBeInTheDocument() - expect(screen.getByText('Extensions')).toBeInTheDocument() - expect(screen.getByText('Agents')).toBeInTheDocument() + expect(screen.getByText('Models'))!.toBeInTheDocument() + expect(screen.getByText('Tools'))!.toBeInTheDocument() + expect(screen.getByText('Extensions'))!.toBeInTheDocument() + expect(screen.getByText('Agents'))!.toBeInTheDocument() }) }) @@ -541,7 +546,7 @@ describe('CategoriesFilter Component', () => { // Assert await waitFor(() => { - expect(screen.getByPlaceholderText('plugin.searchCategories')).toBeInTheDocument() + expect(screen.getByPlaceholderText('plugin.searchCategories'))!.toBeInTheDocument() }) }) }) @@ -555,7 +560,7 @@ describe('CategoriesFilter Component', () => { // Act - Open dropdown and click category fireEvent.click(screen.getByTestId('portal-trigger')) await waitFor(() => { - expect(screen.getByText('Models')).toBeInTheDocument() + expect(screen.getByText('Models'))!.toBeInTheDocument() }) fireEvent.click(screen.getByText('Models')) @@ -592,7 +597,7 @@ describe('CategoriesFilter Component', () => { // Act fireEvent.click(screen.getByTestId('portal-trigger')) await waitFor(() => { - expect(screen.getByText('Tools')).toBeInTheDocument() + expect(screen.getByText('Tools'))!.toBeInTheDocument() }) fireEvent.click(screen.getByText('Tools')) @@ -607,7 +612,7 @@ describe('CategoriesFilter Component', () => { // Act - Find and click the close icon const closeIcon = container.querySelector('.text-text-quaternary') - expect(closeIcon).toBeInTheDocument() + expect(closeIcon)!.toBeInTheDocument() fireEvent.click(closeIcon!) // Assert @@ -623,14 +628,15 @@ describe('CategoriesFilter Component', () => { // Act fireEvent.click(screen.getByTestId('portal-trigger')) await waitFor(() => { - expect(screen.getByPlaceholderText('plugin.searchCategories')).toBeInTheDocument() + expect(screen.getByPlaceholderText('plugin.searchCategories'))!.toBeInTheDocument() }) fireEvent.change(screen.getByPlaceholderText('plugin.searchCategories'), { target: { value: 'mod' }, }) // Assert - expect(screen.getByText('Models')).toBeInTheDocument() + // Assert + expect(screen.getByText('Models'))!.toBeInTheDocument() expect(screen.queryByText('Extensions')).not.toBeInTheDocument() }) @@ -641,14 +647,15 @@ describe('CategoriesFilter Component', () => { // Act fireEvent.click(screen.getByTestId('portal-trigger')) await waitFor(() => { - expect(screen.getByPlaceholderText('plugin.searchCategories')).toBeInTheDocument() + expect(screen.getByPlaceholderText('plugin.searchCategories'))!.toBeInTheDocument() }) fireEvent.change(screen.getByPlaceholderText('plugin.searchCategories'), { target: { value: 'MOD' }, }) // Assert - expect(screen.getByText('Models')).toBeInTheDocument() + // Assert + expect(screen.getByText('Models'))!.toBeInTheDocument() }) }) @@ -696,7 +703,8 @@ describe('TagFilter Component', () => { render() // Assert - expect(screen.getByText('pluginTags.allTags')).toBeInTheDocument() + // Assert + expect(screen.getByText('pluginTags.allTags'))!.toBeInTheDocument() }) it('should render selected tag labels', () => { @@ -704,7 +712,8 @@ describe('TagFilter Component', () => { render() // Assert - expect(screen.getByText('Agent')).toBeInTheDocument() + // Assert + expect(screen.getByText('Agent'))!.toBeInTheDocument() }) it('should show count badge for more than 2 selections', () => { @@ -712,7 +721,8 @@ describe('TagFilter Component', () => { render() // Assert - expect(screen.getByText('+1')).toBeInTheDocument() + // Assert + expect(screen.getByText('+1'))!.toBeInTheDocument() }) it('should show clear button when tags are selected', () => { @@ -721,7 +731,7 @@ describe('TagFilter Component', () => { // Assert const closeIcon = container.querySelector('.text-text-quaternary') - expect(closeIcon).toBeInTheDocument() + expect(closeIcon)!.toBeInTheDocument() }) }) @@ -735,7 +745,7 @@ describe('TagFilter Component', () => { // Assert await waitFor(() => { - expect(screen.getByTestId('portal-content')).toBeInTheDocument() + expect(screen.getByTestId('portal-content'))!.toBeInTheDocument() }) }) @@ -748,10 +758,10 @@ describe('TagFilter Component', () => { // Assert await waitFor(() => { - expect(screen.getByText('Agent')).toBeInTheDocument() - expect(screen.getByText('RAG')).toBeInTheDocument() - expect(screen.getByText('Search')).toBeInTheDocument() - expect(screen.getByText('Image')).toBeInTheDocument() + expect(screen.getByText('Agent'))!.toBeInTheDocument() + expect(screen.getByText('RAG'))!.toBeInTheDocument() + expect(screen.getByText('Search'))!.toBeInTheDocument() + expect(screen.getByText('Image'))!.toBeInTheDocument() }) }) }) @@ -765,7 +775,7 @@ describe('TagFilter Component', () => { // Act fireEvent.click(screen.getByTestId('portal-trigger')) await waitFor(() => { - expect(screen.getByText('Agent')).toBeInTheDocument() + expect(screen.getByText('Agent'))!.toBeInTheDocument() }) fireEvent.click(screen.getByText('Agent')) @@ -783,7 +793,7 @@ describe('TagFilter Component', () => { await waitFor(() => { // Find the Agent option in dropdown const agentOptions = screen.getAllByText('Agent') - fireEvent.click(agentOptions[agentOptions.length - 1]) + fireEvent.click(agentOptions[agentOptions.length - 1]!) }) // Assert @@ -798,7 +808,7 @@ describe('TagFilter Component', () => { // Act fireEvent.click(screen.getByTestId('portal-trigger')) await waitFor(() => { - expect(screen.getByText('RAG')).toBeInTheDocument() + expect(screen.getByText('RAG'))!.toBeInTheDocument() }) fireEvent.click(screen.getByText('RAG')) @@ -828,14 +838,15 @@ describe('TagFilter Component', () => { // Act fireEvent.click(screen.getByTestId('portal-trigger')) await waitFor(() => { - expect(screen.getByPlaceholderText('pluginTags.searchTags')).toBeInTheDocument() + expect(screen.getByPlaceholderText('pluginTags.searchTags'))!.toBeInTheDocument() }) fireEvent.change(screen.getByPlaceholderText('pluginTags.searchTags'), { target: { value: 'rag' }, }) // Assert - expect(screen.getByText('RAG')).toBeInTheDocument() + // Assert + expect(screen.getByText('RAG'))!.toBeInTheDocument() expect(screen.queryByText('Image')).not.toBeInTheDocument() }) }) @@ -855,9 +866,10 @@ describe('FilterManagement Component', () => { renderFilterManagement() // Assert - All three filters should be present - expect(screen.getByText('plugin.allCategories')).toBeInTheDocument() - expect(screen.getByText('pluginTags.allTags')).toBeInTheDocument() - expect(screen.getByPlaceholderText('plugin.search')).toBeInTheDocument() + // Assert - All three filters should be present + expect(screen.getByText('plugin.allCategories'))!.toBeInTheDocument() + expect(screen.getByText('pluginTags.allTags'))!.toBeInTheDocument() + expect(screen.getByPlaceholderText('plugin.search'))!.toBeInTheDocument() }) it('should render with correct container classes', () => { @@ -866,7 +878,7 @@ describe('FilterManagement Component', () => { // Assert const wrapper = container.firstChild as HTMLElement - expect(wrapper).toHaveClass('flex', 'items-center', 'gap-2', 'self-stretch') + expect(wrapper)!.toHaveClass('flex', 'items-center', 'gap-2', 'self-stretch') }) }) @@ -879,9 +891,10 @@ describe('FilterManagement Component', () => { renderFilterManagement() // Assert - expect(screen.getByText('plugin.allCategories')).toBeInTheDocument() - expect(screen.getByText('pluginTags.allTags')).toBeInTheDocument() - expect(screen.getByPlaceholderText('plugin.search')).toHaveValue('') + // Assert + expect(screen.getByText('plugin.allCategories'))!.toBeInTheDocument() + expect(screen.getByText('pluginTags.allTags'))!.toBeInTheDocument() + expect(screen.getByPlaceholderText('plugin.search'))!.toHaveValue('') }) it('should initialize with pre-selected categories', () => { @@ -892,7 +905,8 @@ describe('FilterManagement Component', () => { renderFilterManagement() // Assert - expect(screen.getByText('Models')).toBeInTheDocument() + // Assert + expect(screen.getByText('Models'))!.toBeInTheDocument() }) it('should initialize with pre-selected tags', () => { @@ -903,7 +917,8 @@ describe('FilterManagement Component', () => { renderFilterManagement() // Assert - expect(screen.getByText('Agent')).toBeInTheDocument() + // Assert + expect(screen.getByText('Agent'))!.toBeInTheDocument() }) it('should initialize with search query', () => { @@ -914,7 +929,8 @@ describe('FilterManagement Component', () => { renderFilterManagement() // Assert - expect(screen.getByDisplayValue('initial search')).toBeInTheDocument() + // Assert + expect(screen.getByDisplayValue('initial search'))!.toBeInTheDocument() }) }) @@ -926,10 +942,10 @@ describe('FilterManagement Component', () => { // Act - Open categories dropdown and select const triggers = screen.getAllByTestId('portal-trigger') - fireEvent.click(triggers[0]) // Categories filter trigger + fireEvent.click(triggers[0]!) // Categories filter trigger await waitFor(() => { - expect(screen.getByText('Models')).toBeInTheDocument() + expect(screen.getByText('Models'))!.toBeInTheDocument() }) fireEvent.click(screen.getByText('Models')) @@ -948,10 +964,10 @@ describe('FilterManagement Component', () => { // Act - Open tags dropdown and select const triggers = screen.getAllByTestId('portal-trigger') - fireEvent.click(triggers[1]) // Tags filter trigger + fireEvent.click(triggers[1]!) // Tags filter trigger await waitFor(() => { - expect(screen.getByText('Agent')).toBeInTheDocument() + expect(screen.getByText('Agent'))!.toBeInTheDocument() }) fireEvent.click(screen.getByText('Agent')) @@ -990,9 +1006,9 @@ describe('FilterManagement Component', () => { // Act 1 - Select a category const triggers = screen.getAllByTestId('portal-trigger') - fireEvent.click(triggers[0]) + fireEvent.click(triggers[0]!) await waitFor(() => { - expect(screen.getByText('Models')).toBeInTheDocument() + expect(screen.getByText('Models'))!.toBeInTheDocument() }) fireEvent.click(screen.getByText('Models')) @@ -1003,12 +1019,12 @@ describe('FilterManagement Component', () => { }) // Close dropdown by clicking trigger again - fireEvent.click(triggers[0]) + fireEvent.click(triggers[0]!) // Act 2 - Select a tag (state should include previous category) - fireEvent.click(triggers[1]) + fireEvent.click(triggers[1]!) await waitFor(() => { - expect(screen.getByText('Agent')).toBeInTheDocument() + expect(screen.getByText('Agent'))!.toBeInTheDocument() }) fireEvent.click(screen.getByText('Agent')) @@ -1051,20 +1067,20 @@ describe('FilterManagement Component', () => { // Act 1 - Select categories const triggers = screen.getAllByTestId('portal-trigger') - fireEvent.click(triggers[0]) + fireEvent.click(triggers[0]!) await waitFor(() => { - expect(screen.getByText('Models')).toBeInTheDocument() + expect(screen.getByText('Models'))!.toBeInTheDocument() }) fireEvent.click(screen.getByText('Models')) - fireEvent.click(triggers[0]) // Close + fireEvent.click(triggers[0]!) // Close // Act 2 - Select tags - fireEvent.click(triggers[1]) + fireEvent.click(triggers[1]!) await waitFor(() => { - expect(screen.getByText('RAG')).toBeInTheDocument() + expect(screen.getByText('RAG'))!.toBeInTheDocument() }) fireEvent.click(screen.getByText('RAG')) - fireEvent.click(triggers[1]) // Close + fireEvent.click(triggers[1]!) // Close // Act 3 - Enter search fireEvent.change(screen.getByPlaceholderText('plugin.search'), { @@ -1103,7 +1119,7 @@ describe('FilterManagement Component', () => { // Act - Clear categories (click clear button) const closeIcons = container.querySelectorAll('.text-text-quaternary') - fireEvent.click(closeIcons[0]) // First close icon is for categories + fireEvent.click(closeIcons[0]!) // First close icon is for categories // Assert expect(onFilterChange).toHaveBeenLastCalledWith({ @@ -1124,7 +1140,8 @@ describe('FilterManagement Component', () => { render() // Assert - Should render without errors - expect(screen.getByText('plugin.allCategories')).toBeInTheDocument() + // Assert - Should render without errors + expect(screen.getByText('plugin.allCategories'))!.toBeInTheDocument() }) it('should handle multiple rapid filter changes', () => { diff --git a/web/app/components/plugins/plugin-page/filter-management/category-filter.tsx b/web/app/components/plugins/plugin-page/filter-management/category-filter.tsx index f6ace774e8..8dbef5395d 100644 --- a/web/app/components/plugins/plugin-page/filter-management/category-filter.tsx +++ b/web/app/components/plugins/plugin-page/filter-management/category-filter.tsx @@ -61,7 +61,7 @@ const CategoriesFilter = ({ !selectedTagsLength && t('allCategories', { ns: 'plugin' }) } { - !!selectedTagsLength && value.map(val => categoriesMap[val].label).slice(0, 2).join(',') + !!selectedTagsLength && value.map(val => categoriesMap[val]!.label).slice(0, 2).join(',') } { selectedTagsLength > 2 && ( diff --git a/web/app/components/plugins/plugin-page/list/__tests__/index.spec.tsx b/web/app/components/plugins/plugin-page/list/__tests__/index.spec.tsx index c6326461d4..6537237839 100644 --- a/web/app/components/plugins/plugin-page/list/__tests__/index.spec.tsx +++ b/web/app/components/plugins/plugin-page/list/__tests__/index.spec.tsx @@ -113,7 +113,8 @@ describe('PluginList', () => { const { container } = render() // Assert - expect(container).toBeInTheDocument() + // Assert + expect(container)!.toBeInTheDocument() }) it('should render container with correct structure', () => { @@ -125,10 +126,10 @@ describe('PluginList', () => { // Assert const outerDiv = container.firstChild as HTMLElement - expect(outerDiv).toHaveClass('pb-3') + expect(outerDiv)!.toHaveClass('pb-3') const gridDiv = outerDiv.firstChild as HTMLElement - expect(gridDiv).toHaveClass('grid', 'grid-cols-2', 'gap-3') + expect(gridDiv)!.toHaveClass('grid', 'grid-cols-2', 'gap-3') }) it('should render single plugin correctly', () => { @@ -141,7 +142,7 @@ describe('PluginList', () => { // Assert const pluginItems = screen.getAllByTestId('plugin-item') expect(pluginItems).toHaveLength(1) - expect(pluginItems[0]).toHaveAttribute('data-plugin-name', 'single-plugin') + expect(pluginItems[0])!.toHaveAttribute('data-plugin-name', 'single-plugin') }) it('should render multiple plugins correctly', () => { @@ -169,9 +170,9 @@ describe('PluginList', () => { // Assert const pluginItems = screen.getAllByTestId('plugin-item') - expect(pluginItems[0]).toHaveAttribute('data-plugin-id', 'first') - expect(pluginItems[1]).toHaveAttribute('data-plugin-id', 'second') - expect(pluginItems[2]).toHaveAttribute('data-plugin-id', 'third') + expect(pluginItems[0])!.toHaveAttribute('data-plugin-id', 'first') + expect(pluginItems[1])!.toHaveAttribute('data-plugin-id', 'second') + expect(pluginItems[2])!.toHaveAttribute('data-plugin-id', 'third') }) it('should pass plugin prop to each PluginItem', () => { @@ -185,8 +186,9 @@ describe('PluginList', () => { render() // Assert - expect(screen.getByText('Plugin A')).toBeInTheDocument() - expect(screen.getByText('Plugin B')).toBeInTheDocument() + // Assert + expect(screen.getByText('Plugin A'))!.toBeInTheDocument() + expect(screen.getByText('Plugin B'))!.toBeInTheDocument() }) }) @@ -198,7 +200,7 @@ describe('PluginList', () => { // Assert const gridDiv = container.querySelector('.grid') - expect(gridDiv).toBeEmptyDOMElement() + expect(gridDiv)!.toBeEmptyDOMElement() }) it('should handle pluginList with various categories', () => { @@ -250,6 +252,37 @@ describe('PluginList', () => { // Arrange & Act render() + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert // Assert expect(screen.queryByTestId('plugin-item')).not.toBeInTheDocument() }) @@ -303,7 +336,8 @@ describe('PluginList', () => { render() // Assert - expect(screen.getByTestId('plugin-item')).toBeInTheDocument() + // Assert + expect(screen.getByTestId('plugin-item'))!.toBeInTheDocument() }) it('should handle plugin with minimal data', () => { @@ -317,7 +351,8 @@ describe('PluginList', () => { render() // Assert - expect(screen.getByTestId('plugin-item')).toBeInTheDocument() + // Assert + expect(screen.getByTestId('plugin-item'))!.toBeInTheDocument() }) it('should handle plugins with undefined optional fields', () => { @@ -333,7 +368,8 @@ describe('PluginList', () => { render() // Assert - expect(screen.getByTestId('plugin-item')).toBeInTheDocument() + // Assert + expect(screen.getByTestId('plugin-item'))!.toBeInTheDocument() }) }) @@ -348,7 +384,7 @@ describe('PluginList', () => { // Assert const gridDiv = container.querySelector('.grid') - expect(gridDiv).toHaveClass('grid-cols-2') + expect(gridDiv)!.toHaveClass('grid-cols-2') }) it('should have proper gap between items', () => { @@ -360,7 +396,7 @@ describe('PluginList', () => { // Assert const gridDiv = container.querySelector('.grid') - expect(gridDiv).toHaveClass('gap-3') + expect(gridDiv)!.toHaveClass('gap-3') }) it('should have bottom padding on container', () => { @@ -372,7 +408,7 @@ describe('PluginList', () => { // Assert const outerDiv = container.firstChild as HTMLElement - expect(outerDiv).toHaveClass('pb-3') + expect(outerDiv)!.toHaveClass('pb-3') }) }) @@ -404,6 +440,37 @@ describe('PluginList', () => { rerender() + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert // Assert expect(screen.queryByTestId('plugin-item')).not.toBeInTheDocument() }) @@ -430,12 +497,13 @@ describe('PluginList', () => { // Act const { rerender } = render() - expect(screen.getByText('Original Name')).toBeInTheDocument() + expect(screen.getByText('Original Name'))!.toBeInTheDocument() rerender() // Assert - expect(screen.getByText('Updated Name')).toBeInTheDocument() + // Assert + expect(screen.getByText('Updated Name'))!.toBeInTheDocument() expect(screen.queryByText('Original Name')).not.toBeInTheDocument() }) }) @@ -454,15 +522,15 @@ describe('PluginList', () => { const { rerender } = render() // Reorder the list - const reorderedList = [pluginList[2], pluginList[0], pluginList[1]] + const reorderedList = [pluginList[2]!, pluginList[0]!, pluginList[1]!] rerender() // Assert - All items should still be present const items = screen.getAllByTestId('plugin-item') expect(items).toHaveLength(3) - expect(items[0]).toHaveAttribute('data-plugin-id', 'stable-key-3') - expect(items[1]).toHaveAttribute('data-plugin-id', 'stable-key-1') - expect(items[2]).toHaveAttribute('data-plugin-id', 'stable-key-2') + expect(items[0])!.toHaveAttribute('data-plugin-id', 'stable-key-3') + expect(items[1])!.toHaveAttribute('data-plugin-id', 'stable-key-1') + expect(items[2])!.toHaveAttribute('data-plugin-id', 'stable-key-2') }) }) @@ -476,7 +544,8 @@ describe('PluginList', () => { render() // Assert - expect(screen.getByTestId('plugin-item')).toBeInTheDocument() + // Assert + expect(screen.getByTestId('plugin-item'))!.toBeInTheDocument() }) it('should render deleted/deprecated plugins', () => { @@ -492,7 +561,8 @@ describe('PluginList', () => { render() // Assert - expect(screen.getByTestId('plugin-item')).toBeInTheDocument() + // Assert + expect(screen.getByTestId('plugin-item'))!.toBeInTheDocument() }) it('should render mixed status plugins', () => { @@ -529,7 +599,8 @@ describe('PluginList', () => { render() // Assert - expect(screen.getByTestId('plugin-item')).toBeInTheDocument() + // Assert + expect(screen.getByTestId('plugin-item'))!.toBeInTheDocument() }) it('should render plugins with outdated version', () => { @@ -545,7 +616,8 @@ describe('PluginList', () => { render() // Assert - expect(screen.getByTestId('plugin-item')).toBeInTheDocument() + // Assert + expect(screen.getByTestId('plugin-item'))!.toBeInTheDocument() }) }) @@ -607,9 +679,10 @@ describe('PluginList', () => { render() // Assert - expect(screen.getByText('Marketplace Plugin')).toBeInTheDocument() - expect(screen.getByText('GitHub Plugin')).toBeInTheDocument() - expect(screen.getByText('Local Plugin')).toBeInTheDocument() + // Assert + expect(screen.getByText('Marketplace Plugin'))!.toBeInTheDocument() + expect(screen.getByText('GitHub Plugin'))!.toBeInTheDocument() + expect(screen.getByText('Local Plugin'))!.toBeInTheDocument() }) it('should render plugins of different categories together', () => { @@ -636,9 +709,10 @@ describe('PluginList', () => { render() // Assert - expect(screen.getByText('Tool Plugin')).toBeInTheDocument() - expect(screen.getByText('Model Plugin')).toBeInTheDocument() - expect(screen.getByText('Agent Plugin')).toBeInTheDocument() + // Assert + expect(screen.getByText('Tool Plugin'))!.toBeInTheDocument() + expect(screen.getByText('Model Plugin'))!.toBeInTheDocument() + expect(screen.getByText('Agent Plugin'))!.toBeInTheDocument() }) }) diff --git a/web/app/components/plugins/plugin-page/plugin-tasks/__tests__/index.spec.tsx b/web/app/components/plugins/plugin-page/plugin-tasks/__tests__/index.spec.tsx index 56992b377f..15b4429de8 100644 --- a/web/app/components/plugins/plugin-page/plugin-tasks/__tests__/index.spec.tsx +++ b/web/app/components/plugins/plugin-page/plugin-tasks/__tests__/index.spec.tsx @@ -83,8 +83,8 @@ describe('usePluginTaskStatus Hook', () => { render() - expect(screen.getByTestId('running-count')).toHaveTextContent('1') - expect(screen.getByTestId('running-id')).toHaveTextContent(runningPlugin.plugin_unique_identifier) + expect(screen.getByTestId('running-count'))!.toHaveTextContent('1') + expect(screen.getByTestId('running-id'))!.toHaveTextContent(runningPlugin.plugin_unique_identifier) }) it('should categorize success plugins correctly', () => { @@ -103,8 +103,8 @@ describe('usePluginTaskStatus Hook', () => { render() - expect(screen.getByTestId('success-count')).toHaveTextContent('1') - expect(screen.getByTestId('success-id')).toHaveTextContent(successPlugin.plugin_unique_identifier) + expect(screen.getByTestId('success-count'))!.toHaveTextContent('1') + expect(screen.getByTestId('success-id'))!.toHaveTextContent(successPlugin.plugin_unique_identifier) }) it('should categorize error plugins correctly', () => { @@ -123,8 +123,8 @@ describe('usePluginTaskStatus Hook', () => { render() - expect(screen.getByTestId('error-count')).toHaveTextContent('1') - expect(screen.getByTestId('error-id')).toHaveTextContent(errorPlugin.plugin_unique_identifier) + expect(screen.getByTestId('error-count'))!.toHaveTextContent('1') + expect(screen.getByTestId('error-id'))!.toHaveTextContent(errorPlugin.plugin_unique_identifier) }) it('should categorize mixed plugins correctly', () => { @@ -149,10 +149,10 @@ describe('usePluginTaskStatus Hook', () => { render() - expect(screen.getByTestId('running')).toHaveTextContent('1') - expect(screen.getByTestId('success')).toHaveTextContent('1') - expect(screen.getByTestId('error')).toHaveTextContent('1') - expect(screen.getByTestId('total')).toHaveTextContent('3') + expect(screen.getByTestId('running'))!.toHaveTextContent('1') + expect(screen.getByTestId('success'))!.toHaveTextContent('1') + expect(screen.getByTestId('error'))!.toHaveTextContent('1') + expect(screen.getByTestId('total'))!.toHaveTextContent('3') }) }) @@ -175,11 +175,11 @@ describe('usePluginTaskStatus Hook', () => { render() - expect(screen.getByTestId('isInstalling')).toHaveTextContent('true') - expect(screen.getByTestId('isInstallingWithSuccess')).toHaveTextContent('false') - expect(screen.getByTestId('isInstallingWithError')).toHaveTextContent('false') - expect(screen.getByTestId('isSuccess')).toHaveTextContent('false') - expect(screen.getByTestId('isFailed')).toHaveTextContent('false') + expect(screen.getByTestId('isInstalling'))!.toHaveTextContent('true') + expect(screen.getByTestId('isInstallingWithSuccess'))!.toHaveTextContent('false') + expect(screen.getByTestId('isInstallingWithError'))!.toHaveTextContent('false') + expect(screen.getByTestId('isSuccess'))!.toHaveTextContent('false') + expect(screen.getByTestId('isFailed'))!.toHaveTextContent('false') }) it('should set isInstallingWithSuccess when running and success plugins exist', () => { @@ -194,7 +194,7 @@ describe('usePluginTaskStatus Hook', () => { } render() - expect(screen.getByTestId('flag')).toHaveTextContent('true') + expect(screen.getByTestId('flag'))!.toHaveTextContent('true') }) it('should set isInstallingWithError when running and error plugins exist', () => { @@ -209,7 +209,7 @@ describe('usePluginTaskStatus Hook', () => { } render() - expect(screen.getByTestId('flag')).toHaveTextContent('true') + expect(screen.getByTestId('flag'))!.toHaveTextContent('true') }) it('should set isSuccess when all plugins succeeded', () => { @@ -224,7 +224,7 @@ describe('usePluginTaskStatus Hook', () => { } render() - expect(screen.getByTestId('flag')).toHaveTextContent('true') + expect(screen.getByTestId('flag'))!.toHaveTextContent('true') }) it('should set isFailed when no running plugins and some failed', () => { @@ -239,7 +239,7 @@ describe('usePluginTaskStatus Hook', () => { } render() - expect(screen.getByTestId('flag')).toHaveTextContent('true') + expect(screen.getByTestId('flag'))!.toHaveTextContent('true') }) }) @@ -296,12 +296,12 @@ describe('TaskStatusIndicator Component', () => { describe('Rendering', () => { it('should render without crashing', () => { render() - expect(document.getElementById('plugin-task-trigger')).toBeInTheDocument() + expect(document.getElementById('plugin-task-trigger'))!.toBeInTheDocument() }) it('should render with correct id', () => { render() - expect(document.getElementById('plugin-task-trigger')).toBeInTheDocument() + expect(document.getElementById('plugin-task-trigger'))!.toBeInTheDocument() }) }) @@ -309,17 +309,18 @@ describe('TaskStatusIndicator Component', () => { it('should show downloading icon when installing', () => { render() // DownloadingIcon is rendered when isInstalling is true - expect(document.getElementById('plugin-task-trigger')).toBeInTheDocument() + // DownloadingIcon is rendered when isInstalling is true + expect(document.getElementById('plugin-task-trigger'))!.toBeInTheDocument() }) it('should show downloading icon when installing with error', () => { render() - expect(document.getElementById('plugin-task-trigger')).toBeInTheDocument() + expect(document.getElementById('plugin-task-trigger'))!.toBeInTheDocument() }) it('should show install icon when not installing', () => { render() - expect(document.getElementById('plugin-task-trigger')).toBeInTheDocument() + expect(document.getElementById('plugin-task-trigger'))!.toBeInTheDocument() }) }) @@ -333,7 +334,7 @@ describe('TaskStatusIndicator Component', () => { totalPluginsLength={3} />, ) - expect(document.getElementById('plugin-task-trigger')).toBeInTheDocument() + expect(document.getElementById('plugin-task-trigger'))!.toBeInTheDocument() }) it('should show progress circle when installing with success', () => { @@ -345,7 +346,7 @@ describe('TaskStatusIndicator Component', () => { totalPluginsLength={3} />, ) - expect(document.getElementById('plugin-task-trigger')).toBeInTheDocument() + expect(document.getElementById('plugin-task-trigger'))!.toBeInTheDocument() }) it('should show error progress circle when installing with error', () => { @@ -357,7 +358,7 @@ describe('TaskStatusIndicator Component', () => { totalPluginsLength={3} />, ) - expect(document.getElementById('plugin-task-trigger')).toBeInTheDocument() + expect(document.getElementById('plugin-task-trigger'))!.toBeInTheDocument() }) it('should show success icon when all completed successfully', () => { @@ -370,12 +371,12 @@ describe('TaskStatusIndicator Component', () => { totalPluginsLength={3} />, ) - expect(document.getElementById('plugin-task-trigger')).toBeInTheDocument() + expect(document.getElementById('plugin-task-trigger'))!.toBeInTheDocument() }) it('should show error icon when failed', () => { render() - expect(document.getElementById('plugin-task-trigger')).toBeInTheDocument() + expect(document.getElementById('plugin-task-trigger'))!.toBeInTheDocument() }) }) @@ -383,19 +384,19 @@ describe('TaskStatusIndicator Component', () => { it('should apply error styles when installing with error', () => { render() const trigger = document.getElementById('plugin-task-trigger') - expect(trigger).toHaveClass('bg-state-destructive-hover') + expect(trigger)!.toHaveClass('bg-state-destructive-hover') }) it('should apply error styles when failed', () => { render() const trigger = document.getElementById('plugin-task-trigger') - expect(trigger).toHaveClass('bg-state-destructive-hover') + expect(trigger)!.toHaveClass('bg-state-destructive-hover') }) it('should apply cursor-pointer when clickable', () => { render() const trigger = document.getElementById('plugin-task-trigger') - expect(trigger).toHaveClass('cursor-pointer') + expect(trigger)!.toHaveClass('cursor-pointer') }) }) @@ -429,7 +430,7 @@ describe('PluginTaskList Component', () => { describe('Rendering', () => { it('should render without crashing with empty lists', () => { render() - expect(document.querySelector('.w-\\[360px\\]')).toBeInTheDocument() + expect(document.querySelector('.w-\\[360px\\]'))!.toBeInTheDocument() }) it('should render running plugins section when plugins exist', () => { @@ -439,7 +440,8 @@ describe('PluginTaskList Component', () => { // Translation key is returned as text in tests, multiple matches expected (title + status) expect(screen.getAllByText(/task\.installing/i).length).toBeGreaterThan(0) // Verify section container is rendered - expect(document.querySelector('.max-h-\\[300px\\]')).toBeInTheDocument() + // Verify section container is rendered + expect(document.querySelector('.max-h-\\[300px\\]'))!.toBeInTheDocument() }) it('should render success plugins section when plugins exist', () => { @@ -454,7 +456,7 @@ describe('PluginTaskList Component', () => { const errorPlugins = [createMockPlugin({ status: TaskStatus.failed, message: 'Error occurred' })] render() - expect(screen.getByText('Error occurred')).toBeInTheDocument() + expect(screen.getByText('Error occurred'))!.toBeInTheDocument() }) it('should render all sections when all types exist', () => { @@ -541,7 +543,7 @@ describe('PluginTaskList Component', () => { render() - expect(screen.getByText('My Test Plugin')).toBeInTheDocument() + expect(screen.getByText('My Test Plugin'))!.toBeInTheDocument() }) it('should display plugin message when available', () => { @@ -552,7 +554,7 @@ describe('PluginTaskList Component', () => { render() - expect(screen.getByText('Successfully installed!')).toBeInTheDocument() + expect(screen.getByText('Successfully installed!'))!.toBeInTheDocument() }) it('should display multiple plugins in each section', () => { @@ -563,8 +565,8 @@ describe('PluginTaskList Component', () => { render() - expect(screen.getByText('Plugin A')).toBeInTheDocument() - expect(screen.getByText('Plugin B')).toBeInTheDocument() + expect(screen.getByText('Plugin A'))!.toBeInTheDocument() + expect(screen.getByText('Plugin B'))!.toBeInTheDocument() // Count is rendered, verify multiple items are in list expect(document.querySelectorAll('.hover\\:bg-state-base-hover').length).toBe(2) }) @@ -593,7 +595,7 @@ describe('PluginTasks Component', () => { render() - expect(document.getElementById('plugin-task-trigger')).toBeInTheDocument() + expect(document.getElementById('plugin-task-trigger'))!.toBeInTheDocument() }) }) @@ -604,7 +606,8 @@ describe('PluginTasks Component', () => { render() // The component renders with a tooltip, we verify it exists - expect(document.getElementById('plugin-task-trigger')).toBeInTheDocument() + // The component renders with a tooltip, we verify it exists + expect(document.getElementById('plugin-task-trigger'))!.toBeInTheDocument() }) it('should show success tip when all succeeded', () => { @@ -612,7 +615,7 @@ describe('PluginTasks Component', () => { render() - expect(document.getElementById('plugin-task-trigger')).toBeInTheDocument() + expect(document.getElementById('plugin-task-trigger'))!.toBeInTheDocument() }) it('should show error tip when some failed', () => { @@ -623,7 +626,7 @@ describe('PluginTasks Component', () => { render() - expect(document.getElementById('plugin-task-trigger')).toBeInTheDocument() + expect(document.getElementById('plugin-task-trigger'))!.toBeInTheDocument() }) }) @@ -637,7 +640,8 @@ describe('PluginTasks Component', () => { fireEvent.click(document.getElementById('plugin-task-trigger')!) // The popover content should be visible (PluginTaskList) - expect(document.querySelector('.w-\\[360px\\]')).toBeInTheDocument() + // The popover content should be visible (PluginTaskList) + expect(document.querySelector('.w-\\[360px\\]'))!.toBeInTheDocument() }) it('should not toggle when status does not allow', () => { @@ -647,7 +651,8 @@ describe('PluginTasks Component', () => { render() // Component should still render - expect(document.getElementById('plugin-task-trigger')).toBeInTheDocument() + // Component should still render + expect(document.getElementById('plugin-task-trigger'))!.toBeInTheDocument() }) }) @@ -665,7 +670,7 @@ describe('PluginTasks Component', () => { // Wait for popover content to render await waitFor(() => { - expect(document.querySelector('.w-\\[360px\\]')).toBeInTheDocument() + expect(document.querySelector('.w-\\[360px\\]'))!.toBeInTheDocument() }) // Find and click clear all button @@ -691,13 +696,13 @@ describe('PluginTasks Component', () => { fireEvent.click(document.getElementById('plugin-task-trigger')!) await waitFor(() => { - expect(document.querySelector('.w-\\[360px\\]')).toBeInTheDocument() + expect(document.querySelector('.w-\\[360px\\]'))!.toBeInTheDocument() }) // Find and click the clear all button in error section const clearButtons = screen.getAllByRole('button') if (clearButtons.length > 0) - fireEvent.click(clearButtons[0]) + fireEvent.click(clearButtons[0]!) await waitFor(() => { expect(mockMutateAsync).toHaveBeenCalled() @@ -719,13 +724,13 @@ describe('PluginTasks Component', () => { fireEvent.click(document.getElementById('plugin-task-trigger')!) await waitFor(() => { - expect(document.querySelector('.w-\\[360px\\]')).toBeInTheDocument() + expect(document.querySelector('.w-\\[360px\\]'))!.toBeInTheDocument() }) // Find and click individual clear button (usually the last one) const clearButtons = screen.getAllByRole('button') const individualClearButton = clearButtons[clearButtons.length - 1] - fireEvent.click(individualClearButton) + fireEvent.click(individualClearButton!) await waitFor(() => { expect(mockMutateAsync).toHaveBeenCalledWith({ @@ -750,7 +755,7 @@ describe('PluginTasks Component', () => { render() - expect(document.getElementById('plugin-task-trigger')).toBeInTheDocument() + expect(document.getElementById('plugin-task-trigger'))!.toBeInTheDocument() }) it('should handle many plugins', () => { @@ -763,7 +768,7 @@ describe('PluginTasks Component', () => { render() - expect(document.getElementById('plugin-task-trigger')).toBeInTheDocument() + expect(document.getElementById('plugin-task-trigger'))!.toBeInTheDocument() }) it('should handle plugins with empty labels', () => { @@ -775,7 +780,7 @@ describe('PluginTasks Component', () => { render() - expect(document.getElementById('plugin-task-trigger')).toBeInTheDocument() + expect(document.getElementById('plugin-task-trigger'))!.toBeInTheDocument() }) it('should handle plugins with long messages', () => { @@ -790,7 +795,7 @@ describe('PluginTasks Component', () => { // Open popover fireEvent.click(document.getElementById('plugin-task-trigger')!) - expect(document.querySelector('.w-\\[360px\\]')).toBeInTheDocument() + expect(document.querySelector('.w-\\[360px\\]'))!.toBeInTheDocument() }) }) }) @@ -809,13 +814,13 @@ describe('PluginTasks Integration', () => { const { rerender } = render() - expect(document.getElementById('plugin-task-trigger')).toBeInTheDocument() + expect(document.getElementById('plugin-task-trigger'))!.toBeInTheDocument() // Simulate completion by re-rendering with success setupMocks([createMockPlugin({ status: TaskStatus.success })]) rerender() - expect(document.getElementById('plugin-task-trigger')).toBeInTheDocument() + expect(document.getElementById('plugin-task-trigger'))!.toBeInTheDocument() }) it('should show correct UI flow from installing to failure', async () => { @@ -824,13 +829,13 @@ describe('PluginTasks Integration', () => { const { rerender } = render() - expect(document.getElementById('plugin-task-trigger')).toBeInTheDocument() + expect(document.getElementById('plugin-task-trigger'))!.toBeInTheDocument() // Simulate failure by re-rendering with failed setupMocks([createMockPlugin({ status: TaskStatus.failed, message: 'Network error' })]) rerender() - expect(document.getElementById('plugin-task-trigger')).toBeInTheDocument() + expect(document.getElementById('plugin-task-trigger'))!.toBeInTheDocument() }) it('should handle mixed status during installation', () => { diff --git a/web/app/components/plugins/plugin-page/plugin-tasks/components/__tests__/plugin-section.spec.tsx b/web/app/components/plugins/plugin-page/plugin-tasks/components/__tests__/plugin-section.spec.tsx index fb7429e9be..0c724000dd 100644 --- a/web/app/components/plugins/plugin-page/plugin-tasks/components/__tests__/plugin-section.spec.tsx +++ b/web/app/components/plugins/plugin-page/plugin-tasks/components/__tests__/plugin-section.spec.tsx @@ -41,15 +41,15 @@ describe('PluginSection', () => { it('should render title and count', () => { render() - expect(screen.getByText(/installing plugins/i)).toBeInTheDocument() + expect(screen.getByText(/installing plugins/i))!.toBeInTheDocument() expect(screen.getByText(/installing plugins/i).textContent).toContain('2') }) it('should render all plugin items', () => { render() - expect(screen.getByText('PluginA')).toBeInTheDocument() - expect(screen.getByText('PluginB')).toBeInTheDocument() + expect(screen.getByText('PluginA'))!.toBeInTheDocument() + expect(screen.getByText('PluginB'))!.toBeInTheDocument() }) it('should render status icons for each plugin', () => { @@ -72,14 +72,14 @@ describe('PluginSection', () => { const plugins = [createPlugin('p1', 'PluginA', 'Custom message')] render() - expect(screen.getByText('Custom message')).toBeInTheDocument() + expect(screen.getByText('Custom message'))!.toBeInTheDocument() }) it('should use defaultStatusText when plugin has no message', () => { const plugins = [createPlugin('p1', 'PluginA', '')] render() - expect(screen.getByText('Default status')).toBeInTheDocument() + expect(screen.getByText('Default status'))!.toBeInTheDocument() }) it('should apply statusClassName to items', () => { @@ -104,7 +104,7 @@ describe('PluginSection', () => { />, ) - expect(screen.getByRole('button', { name: /clear all/i })).toBeInTheDocument() + expect(screen.getByRole('button', { name: /clear all/i }))!.toBeInTheDocument() }) it('should not render headerAction when not provided', () => { @@ -123,8 +123,8 @@ describe('PluginSection', () => { />, ) - expect(screen.getByRole('button', { name: /action plugina/i })).toBeInTheDocument() - expect(screen.getByRole('button', { name: /action pluginb/i })).toBeInTheDocument() + expect(screen.getByRole('button', { name: /action plugina/i }))!.toBeInTheDocument() + expect(screen.getByRole('button', { name: /action pluginb/i }))!.toBeInTheDocument() }) }) @@ -140,7 +140,7 @@ describe('PluginSection', () => { // Clear buttons are rendered when onClearSingle is provided const clearButtons = screen.getAllByRole('button') - fireEvent.click(clearButtons[0]) + fireEvent.click(clearButtons[0]!) expect(onClearSingle).toHaveBeenCalledWith('task-1', 'p1') }) @@ -157,8 +157,8 @@ describe('PluginSection', () => { const plugins = [createPlugin('p1', 'Solo')] render() - expect(screen.getByText('Solo')).toBeInTheDocument() - expect(screen.getByText(/solo/i).closest('.max-h-\\[300px\\]')).toBeInTheDocument() + expect(screen.getByText('Solo'))!.toBeInTheDocument() + expect(screen.getByText(/solo/i).closest('.max-h-\\[300px\\]'))!.toBeInTheDocument() }) }) }) diff --git a/web/app/components/plugins/plugin-page/plugin-tasks/components/__tests__/plugin-task-list.spec.tsx b/web/app/components/plugins/plugin-page/plugin-tasks/components/__tests__/plugin-task-list.spec.tsx index 2d0d3f7fd6..07a651e2c5 100644 --- a/web/app/components/plugins/plugin-page/plugin-tasks/components/__tests__/plugin-task-list.spec.tsx +++ b/web/app/components/plugins/plugin-page/plugin-tasks/components/__tests__/plugin-task-list.spec.tsx @@ -67,7 +67,7 @@ describe('PluginTaskList', () => { it('should render empty container when no plugins', () => { const { container } = render() const wrapper = container.firstElementChild! - expect(wrapper).toBeInTheDocument() + expect(wrapper)!.toBeInTheDocument() expect(wrapper.children).toHaveLength(0) }) @@ -77,9 +77,9 @@ describe('PluginTaskList', () => { // Header contains the title text const headers = container.querySelectorAll('.system-sm-semibold-uppercase') expect(headers).toHaveLength(1) - expect(headers[0].textContent).toContain('plugin.task.installing') - expect(screen.getByText('OpenAI')).toBeInTheDocument() - expect(screen.getByText('Anthropic')).toBeInTheDocument() + expect(headers[0]!.textContent).toContain('plugin.task.installing') + expect(screen.getByText('OpenAI'))!.toBeInTheDocument() + expect(screen.getByText('Anthropic'))!.toBeInTheDocument() }) it('should render success section when success plugins exist', () => { @@ -87,8 +87,8 @@ describe('PluginTaskList', () => { const headers = container.querySelectorAll('.system-sm-semibold-uppercase') expect(headers).toHaveLength(1) - expect(headers[0].textContent).toContain('plugin.task.installed') - expect(screen.getByText('Google')).toBeInTheDocument() + expect(headers[0]!.textContent).toContain('plugin.task.installed') + expect(screen.getByText('Google'))!.toBeInTheDocument() }) it('should render error section when error plugins exist', () => { @@ -96,8 +96,8 @@ describe('PluginTaskList', () => { const headers = container.querySelectorAll('.system-sm-semibold-uppercase') expect(headers).toHaveLength(1) - expect(headers[0].textContent).toContain('plugin.task.installedError') - expect(screen.getByText('DALLE')).toBeInTheDocument() + expect(headers[0]!.textContent).toContain('plugin.task.installedError') + expect(screen.getByText('DALLE'))!.toBeInTheDocument() }) it('should render all three sections simultaneously', () => { @@ -110,9 +110,9 @@ describe('PluginTaskList', () => { />, ) - expect(screen.getByText('OpenAI')).toBeInTheDocument() - expect(screen.getByText('Google')).toBeInTheDocument() - expect(screen.getByText('DALLE')).toBeInTheDocument() + expect(screen.getByText('OpenAI'))!.toBeInTheDocument() + expect(screen.getByText('Google'))!.toBeInTheDocument() + expect(screen.getByText('DALLE'))!.toBeInTheDocument() }) }) @@ -183,6 +183,37 @@ describe('PluginTaskList', () => { it('should not render clear buttons for running plugins', () => { render() + // Running section has no headerAction and no onClearSingle + // Running section has no headerAction and no onClearSingle + // Running section has no headerAction and no onClearSingle + // Running section has no headerAction and no onClearSingle + // Running section has no headerAction and no onClearSingle + // Running section has no headerAction and no onClearSingle + // Running section has no headerAction and no onClearSingle + // Running section has no headerAction and no onClearSingle + // Running section has no headerAction and no onClearSingle + // Running section has no headerAction and no onClearSingle + // Running section has no headerAction and no onClearSingle + // Running section has no headerAction and no onClearSingle + // Running section has no headerAction and no onClearSingle + // Running section has no headerAction and no onClearSingle + // Running section has no headerAction and no onClearSingle + // Running section has no headerAction and no onClearSingle + // Running section has no headerAction and no onClearSingle + // Running section has no headerAction and no onClearSingle + // Running section has no headerAction and no onClearSingle + // Running section has no headerAction and no onClearSingle + // Running section has no headerAction and no onClearSingle + // Running section has no headerAction and no onClearSingle + // Running section has no headerAction and no onClearSingle + // Running section has no headerAction and no onClearSingle + // Running section has no headerAction and no onClearSingle + // Running section has no headerAction and no onClearSingle + // Running section has no headerAction and no onClearSingle + // Running section has no headerAction and no onClearSingle + // Running section has no headerAction and no onClearSingle + // Running section has no headerAction and no onClearSingle + // Running section has no headerAction and no onClearSingle // Running section has no headerAction and no onClearSingle expect(screen.queryByText(/plugin\.task\.clearAll/)).not.toBeInTheDocument() }) @@ -243,9 +274,9 @@ describe('PluginTaskList', () => { render() - expect(screen.getByText('PluginA')).toBeInTheDocument() - expect(screen.getByText('PluginB')).toBeInTheDocument() - expect(screen.getByText('PluginC')).toBeInTheDocument() + expect(screen.getByText('PluginA'))!.toBeInTheDocument() + expect(screen.getByText('PluginB'))!.toBeInTheDocument() + expect(screen.getByText('PluginC'))!.toBeInTheDocument() }) }) }) diff --git a/web/app/components/plugins/plugin-page/plugin-tasks/components/error-plugin-item.tsx b/web/app/components/plugins/plugin-page/plugin-tasks/components/error-plugin-item.tsx index 81f559c9aa..ef857cb6c6 100644 --- a/web/app/components/plugins/plugin-page/plugin-tasks/components/error-plugin-item.tsx +++ b/web/app/components/plugins/plugin-page/plugin-tasks/components/error-plugin-item.tsx @@ -30,14 +30,14 @@ const ErrorPluginItem: FC = ({ plugin, getIconUrl, languag const [org, name] = parts setIsFetching(true) try { - const response = await fetchPluginInfoFromMarketPlace({ org, name }) + const response = await fetchPluginInfoFromMarketPlace({ org: org!, name: name! }) const info = response.data.plugin const manifest: Plugin = { plugin_id: plugin.plugin_id, type: info.category as Plugin['type'], category: info.category, - name, - org, + name: name!, + org: org!, version: info.latest_version, latest_version: info.latest_version, latest_package_identifier: info.latest_package_identifier, diff --git a/web/app/components/plugins/plugin-page/use-uploader.ts b/web/app/components/plugins/plugin-page/use-uploader.ts index 7df1cb95e3..17699e7b9d 100644 --- a/web/app/components/plugins/plugin-page/use-uploader.ts +++ b/web/app/components/plugins/plugin-page/use-uploader.ts @@ -38,7 +38,7 @@ export const useUploader = ({ onFileChange, containerRef, enabled = true }: Uplo return const files = Array.from(e.dataTransfer.files) if (files.length > 0) - onFileChange(files[0]) + onFileChange(files[0]!) } const fileChangeHandle = enabled diff --git a/web/app/components/plugins/reference-setting-modal/__tests__/index.spec.tsx b/web/app/components/plugins/reference-setting-modal/__tests__/index.spec.tsx index 26eeb7fe03..f71780e2df 100644 --- a/web/app/components/plugins/reference-setting-modal/__tests__/index.spec.tsx +++ b/web/app/components/plugins/reference-setting-modal/__tests__/index.spec.tsx @@ -148,7 +148,8 @@ describe('reference-setting-modal', () => { render() // Assert - expect(screen.getByText('plugin.privilege.title')).toBeInTheDocument() + // Assert + expect(screen.getByText('plugin.privilege.title'))!.toBeInTheDocument() }) it('should render install permission section', () => { @@ -156,7 +157,8 @@ describe('reference-setting-modal', () => { render() // Assert - expect(screen.getByText('plugin.privilege.whoCanInstall')).toBeInTheDocument() + // Assert + expect(screen.getByText('plugin.privilege.whoCanInstall'))!.toBeInTheDocument() }) it('should render debug permission section', () => { @@ -164,7 +166,8 @@ describe('reference-setting-modal', () => { render() // Assert - expect(screen.getByText('plugin.privilege.whoCanDebug')).toBeInTheDocument() + // Assert + expect(screen.getByText('plugin.privilege.whoCanDebug'))!.toBeInTheDocument() }) it('should render all permission options for install', () => { @@ -180,8 +183,9 @@ describe('reference-setting-modal', () => { render() // Assert - expect(screen.getByText('common.operation.cancel')).toBeInTheDocument() - expect(screen.getByText('common.operation.save')).toBeInTheDocument() + // Assert + expect(screen.getByText('common.operation.cancel'))!.toBeInTheDocument() + expect(screen.getByText('common.operation.save'))!.toBeInTheDocument() }) it('should render AutoUpdateSetting when marketplace is enabled', () => { @@ -192,7 +196,8 @@ describe('reference-setting-modal', () => { render() // Assert - expect(screen.getByTestId('auto-update-setting')).toBeInTheDocument() + // Assert + expect(screen.getByTestId('auto-update-setting'))!.toBeInTheDocument() }) it('should not render AutoUpdateSetting when marketplace is disabled', () => { @@ -202,6 +207,37 @@ describe('reference-setting-modal', () => { // Act render() + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert + // Assert // Assert expect(screen.queryByTestId('auto-update-setting')).not.toBeInTheDocument() }) @@ -211,7 +247,8 @@ describe('reference-setting-modal', () => { render() // Assert - expect(screen.getByTestId('modal-close')).toBeInTheDocument() + // Assert + expect(screen.getByTestId('modal-close'))!.toBeInTheDocument() }) }) @@ -230,11 +267,11 @@ describe('reference-setting-modal', () => { // Assert - admin option should be selected for install (first one) const adminOptions = screen.getAllByTestId('option-card-plugin.privilege.admins') - expect(adminOptions[0]).toHaveAttribute('aria-pressed', 'true') // Install permission + expect(adminOptions[0])!.toHaveAttribute('aria-pressed', 'true') // Install permission // Assert - noOne option should be selected for debug (second one) const noOneOptions = screen.getAllByTestId('option-card-plugin.privilege.noone') - expect(noOneOptions[1]).toHaveAttribute('aria-pressed', 'true') // Debug permission + expect(noOneOptions[1])!.toHaveAttribute('aria-pressed', 'true') // Debug permission }) it('should update tempPrivilege when permission option is clicked', () => { @@ -243,10 +280,11 @@ describe('reference-setting-modal', () => { // Act - click on "No One" for install permission const noOneOptions = screen.getAllByTestId('option-card-plugin.privilege.noone') - fireEvent.click(noOneOptions[0]) // First one is for install permission + fireEvent.click(noOneOptions[0]!) // First one is for install permission // Assert - the option should now be selected - expect(noOneOptions[0]).toHaveAttribute('aria-pressed', 'true') + // Assert - the option should now be selected + expect(noOneOptions[0])!.toHaveAttribute('aria-pressed', 'true') }) it('should initialize with payload auto_upgrade values', () => { @@ -261,7 +299,8 @@ describe('reference-setting-modal', () => { render() // Assert - expect(screen.getByTestId('auto-update-strategy')).toHaveTextContent('latest') + // Assert + expect(screen.getByTestId('auto-update-strategy'))!.toHaveTextContent('latest') }) it('should use default auto_upgrade when payload.auto_upgrade is undefined', () => { @@ -275,7 +314,8 @@ describe('reference-setting-modal', () => { render() // Assert - should use default value (disabled) - expect(screen.getByTestId('auto-update-strategy')).toHaveTextContent('disabled') + // Assert - should use default value (disabled) + expect(screen.getByTestId('auto-update-strategy'))!.toHaveTextContent('disabled') }) }) @@ -351,10 +391,11 @@ describe('reference-setting-modal', () => { // Click Everyone for install permission const everyoneOptions = screen.getAllByTestId('option-card-plugin.privilege.everyone') - fireEvent.click(everyoneOptions[0]) + fireEvent.click(everyoneOptions[0]!) // Assert - expect(everyoneOptions[0]).toHaveAttribute('aria-pressed', 'true') + // Assert + expect(everyoneOptions[0])!.toHaveAttribute('aria-pressed', 'true') }) it('should update debug permission when Admins Only option is clicked', () => { @@ -371,10 +412,11 @@ describe('reference-setting-modal', () => { // Click Admins Only for debug permission (second set of options) const adminOptions = screen.getAllByTestId('option-card-plugin.privilege.admins') - fireEvent.click(adminOptions[1]) // Second one is for debug permission + fireEvent.click(adminOptions[1]!) // Second one is for debug permission // Assert - expect(adminOptions[1]).toHaveAttribute('aria-pressed', 'true') + // Assert + expect(adminOptions[1])!.toHaveAttribute('aria-pressed', 'true') }) it('should update auto_upgrade config when changed in AutoUpdateSetting', async () => { @@ -410,7 +452,8 @@ describe('reference-setting-modal', () => { rerender() // Assert - component should render without issues - expect(screen.getByText('plugin.privilege.title')).toBeInTheDocument() + // Assert - component should render without issues + expect(screen.getByText('plugin.privilege.title'))!.toBeInTheDocument() }) it('handleSave should be memoized with useCallback', async () => { @@ -434,10 +477,11 @@ describe('reference-setting-modal', () => { // Act - click install permission option const everyoneOptions = screen.getAllByTestId('option-card-plugin.privilege.everyone') - fireEvent.click(everyoneOptions[0]) + fireEvent.click(everyoneOptions[0]!) // Assert - install permission should be updated - expect(everyoneOptions[0]).toHaveAttribute('aria-pressed', 'true') + // Assert - install permission should be updated + expect(everyoneOptions[0])!.toHaveAttribute('aria-pressed', 'true') }) }) @@ -456,7 +500,7 @@ describe('reference-setting-modal', () => { // Act & Assert - should not crash render() - expect(screen.getByText('plugin.privilege.title')).toBeInTheDocument() + expect(screen.getByText('plugin.privilege.title'))!.toBeInTheDocument() }) it('should handle undefined permission values', () => { @@ -471,7 +515,7 @@ describe('reference-setting-modal', () => { // Assert - should use default PermissionType.noOne const noOneOptions = screen.getAllByTestId('option-card-plugin.privilege.noone') - expect(noOneOptions[0]).toHaveAttribute('aria-pressed', 'true') + expect(noOneOptions[0])!.toHaveAttribute('aria-pressed', 'true') }) it('should handle missing install_permission', () => { @@ -487,7 +531,8 @@ describe('reference-setting-modal', () => { render() // Assert - should fall back to PermissionType.noOne - expect(screen.getByText('plugin.privilege.title')).toBeInTheDocument() + // Assert - should fall back to PermissionType.noOne + expect(screen.getByText('plugin.privilege.title'))!.toBeInTheDocument() }) it('should handle missing debug_permission', () => { @@ -503,7 +548,8 @@ describe('reference-setting-modal', () => { render() // Assert - should fall back to PermissionType.noOne - expect(screen.getByText('plugin.privilege.title')).toBeInTheDocument() + // Assert - should fall back to PermissionType.noOne + expect(screen.getByText('plugin.privilege.title'))!.toBeInTheDocument() }) it('should handle slow async onSave gracefully', async () => { @@ -555,7 +601,8 @@ describe('reference-setting-modal', () => { const { unmount } = render() // Assert - should render without crashing - expect(screen.getByText('plugin.privilege.title')).toBeInTheDocument() + // Assert - should render without crashing + expect(screen.getByText('plugin.privilege.title'))!.toBeInTheDocument() unmount() }) @@ -582,7 +629,8 @@ describe('reference-setting-modal', () => { const { unmount } = render() // Assert - expect(screen.getByTestId('auto-update-strategy')).toHaveTextContent(strategy) + // Assert + expect(screen.getByTestId('auto-update-strategy'))!.toHaveTextContent(strategy) unmount() }) @@ -608,7 +656,8 @@ describe('reference-setting-modal', () => { const { unmount } = render() // Assert - expect(screen.getByTestId('auto-update-mode')).toHaveTextContent(mode) + // Assert + expect(screen.getByTestId('auto-update-mode'))!.toHaveTextContent(mode) unmount() }) @@ -631,7 +680,7 @@ describe('reference-setting-modal', () => { // Change install permission to noOne const noOneOptions = screen.getAllByTestId('option-card-plugin.privilege.noone') - fireEvent.click(noOneOptions[0]) + fireEvent.click(noOneOptions[0]!) // Save fireEvent.click(screen.getByText('common.operation.save')) @@ -662,7 +711,7 @@ describe('reference-setting-modal', () => { // Change debug permission to noOne const noOneOptions = screen.getAllByTestId('option-card-plugin.privilege.noone') - fireEvent.click(noOneOptions[1]) // Second one is for debug + fireEvent.click(noOneOptions[1]!) // Second one is for debug // Save fireEvent.click(screen.getByText('common.operation.save')) @@ -691,7 +740,7 @@ describe('reference-setting-modal', () => { // Change install permission const everyoneOptions = screen.getAllByTestId('option-card-plugin.privilege.everyone') - fireEvent.click(everyoneOptions[0]) + fireEvent.click(everyoneOptions[0]!) // Save fireEvent.click(screen.getByText('common.operation.save')) @@ -717,7 +766,7 @@ describe('reference-setting-modal', () => { // Assert const modal = screen.getByTestId('modal') - expect(modal).toHaveClass('w-[620px]', 'max-w-[620px]', 'p-0!') + expect(modal)!.toHaveClass('w-[620px]', 'max-w-[620px]', 'p-0!') }) it('should pass isShow=true to Modal', () => { @@ -725,7 +774,8 @@ describe('reference-setting-modal', () => { render() // Assert - modal should be visible - expect(screen.getByTestId('modal')).toBeInTheDocument() + // Assert - modal should be visible + expect(screen.getByTestId('modal'))!.toBeInTheDocument() }) }) @@ -736,8 +786,8 @@ describe('reference-setting-modal', () => { // Assert - check order by getting all section labels const labels = screen.getAllByText(/plugin\.privilege\.whoCan/) - expect(labels[0]).toHaveTextContent('plugin.privilege.whoCanInstall') - expect(labels[1]).toHaveTextContent('plugin.privilege.whoCanDebug') + expect(labels[0])!.toHaveTextContent('plugin.privilege.whoCanInstall') + expect(labels[1])!.toHaveTextContent('plugin.privilege.whoCanDebug') }) it('should render three options per permission section', () => { @@ -762,8 +812,8 @@ describe('reference-setting-modal', () => { const cancelButton = screen.getByText('common.operation.cancel') const saveButton = screen.getByText('common.operation.save') - expect(cancelButton).toBeInTheDocument() - expect(saveButton).toBeInTheDocument() + expect(cancelButton)!.toBeInTheDocument() + expect(saveButton)!.toBeInTheDocument() }) }) }) @@ -797,11 +847,11 @@ describe('reference-setting-modal', () => { // Change install permission to Everyone const everyoneOptions = screen.getAllByTestId('option-card-plugin.privilege.everyone') - fireEvent.click(everyoneOptions[0]) + fireEvent.click(everyoneOptions[0]!) // Change debug permission to Admins Only const adminOptions = screen.getAllByTestId('option-card-plugin.privilege.admins') - fireEvent.click(adminOptions[1]) + fireEvent.click(adminOptions[1]!) // Change auto-update strategy fireEvent.click(screen.getByTestId('auto-update-change')) @@ -841,7 +891,7 @@ describe('reference-setting-modal', () => { // Make some changes const noOneOptions = screen.getAllByTestId('option-card-plugin.privilege.noone') - fireEvent.click(noOneOptions[0]) + fireEvent.click(noOneOptions[0]!) // Cancel fireEvent.click(screen.getByText('common.operation.cancel')) @@ -863,8 +913,9 @@ describe('reference-setting-modal', () => { render() // Assert - Labels are rendered correctly - expect(screen.getByText('plugin.privilege.whoCanInstall')).toBeInTheDocument() - expect(screen.getByText('plugin.privilege.whoCanDebug')).toBeInTheDocument() + // Assert - Labels are rendered correctly + expect(screen.getByText('plugin.privilege.whoCanInstall'))!.toBeInTheDocument() + expect(screen.getByText('plugin.privilege.whoCanDebug'))!.toBeInTheDocument() }) }) }) diff --git a/web/app/components/plugins/update-plugin/plugin-version-picker.tsx b/web/app/components/plugins/update-plugin/plugin-version-picker.tsx index 0266c05069..d590f0c9eb 100644 --- a/web/app/components/plugins/update-plugin/plugin-version-picker.tsx +++ b/web/app/components/plugins/update-plugin/plugin-version-picker.tsx @@ -107,7 +107,7 @@ const PluginVersionPicker: FC = ({
{version.version}
{currentVersion === version.version && }
-
{formatDate(version.created_at, format)}
+
{formatDate(version.created_at, format!)}
))}
diff --git a/web/app/components/rag-pipeline/components/chunk-card-list/__tests__/index.spec.tsx b/web/app/components/rag-pipeline/components/chunk-card-list/__tests__/index.spec.tsx index 2fab56f0ea..4827481579 100644 --- a/web/app/components/rag-pipeline/components/chunk-card-list/__tests__/index.spec.tsx +++ b/web/app/components/rag-pipeline/components/chunk-card-list/__tests__/index.spec.tsx @@ -61,15 +61,15 @@ describe('QAItem', () => { it('should render question type with Q prefix', () => { render() - expect(screen.getByText('Q')).toBeInTheDocument() - expect(screen.getByText('What is this?')).toBeInTheDocument() + expect(screen.getByText('Q'))!.toBeInTheDocument() + expect(screen.getByText('What is this?'))!.toBeInTheDocument() }) it('should render answer type with A prefix', () => { render() - expect(screen.getByText('A')).toBeInTheDocument() - expect(screen.getByText('This is the answer.')).toBeInTheDocument() + expect(screen.getByText('A'))!.toBeInTheDocument() + expect(screen.getByText('This is the answer.'))!.toBeInTheDocument() }) }) @@ -77,7 +77,7 @@ describe('QAItem', () => { it('should render with empty text', () => { render() - expect(screen.getByText('Q')).toBeInTheDocument() + expect(screen.getByText('Q'))!.toBeInTheDocument() }) it('should render with long text content', () => { @@ -85,7 +85,7 @@ describe('QAItem', () => { render() - expect(screen.getByText(longText)).toBeInTheDocument() + expect(screen.getByText(longText))!.toBeInTheDocument() }) it('should render with special characters in text', () => { @@ -93,7 +93,7 @@ describe('QAItem', () => { render() - expect(screen.getByText(specialText)).toBeInTheDocument() + expect(screen.getByText(specialText))!.toBeInTheDocument() }) }) @@ -101,11 +101,11 @@ describe('QAItem', () => { it('should be memoized with React.memo', () => { const { rerender } = render() - expect(screen.getByText('Q')).toBeInTheDocument() - expect(screen.getByText('Test')).toBeInTheDocument() + expect(screen.getByText('Q'))!.toBeInTheDocument() + expect(screen.getByText('Test'))!.toBeInTheDocument() rerender() - expect(screen.getByText('Q')).toBeInTheDocument() + expect(screen.getByText('Q'))!.toBeInTheDocument() }) }) }) @@ -120,14 +120,14 @@ describe('ChunkCard', () => { render( , ) - expect(screen.getByText('This is the first chunk of text content.')).toBeInTheDocument() - expect(screen.getByText(/Chunk-01/)).toBeInTheDocument() + expect(screen.getByText('This is the first chunk of text content.'))!.toBeInTheDocument() + expect(screen.getByText(/Chunk-01/))!.toBeInTheDocument() }) it('should render QA chunk type with question and answer', () => { @@ -145,10 +145,10 @@ describe('ChunkCard', () => { />, ) - expect(screen.getByText('Q')).toBeInTheDocument() - expect(screen.getByText('What is React?')).toBeInTheDocument() - expect(screen.getByText('A')).toBeInTheDocument() - expect(screen.getByText('React is a JavaScript library.')).toBeInTheDocument() + expect(screen.getByText('Q'))!.toBeInTheDocument() + expect(screen.getByText('What is React?'))!.toBeInTheDocument() + expect(screen.getByText('A'))!.toBeInTheDocument() + expect(screen.getByText('React is a JavaScript library.'))!.toBeInTheDocument() }) it('should render parent-child chunk type with child contents', () => { @@ -164,10 +164,10 @@ describe('ChunkCard', () => { />, ) - expect(screen.getByText('Child 1 content')).toBeInTheDocument() - expect(screen.getByText('Child 2 content')).toBeInTheDocument() - expect(screen.getByText('C-1')).toBeInTheDocument() - expect(screen.getByText('C-2')).toBeInTheDocument() + expect(screen.getByText('Child 1 content'))!.toBeInTheDocument() + expect(screen.getByText('Child 2 content'))!.toBeInTheDocument() + expect(screen.getByText('C-1'))!.toBeInTheDocument() + expect(screen.getByText('C-2'))!.toBeInTheDocument() }) }) @@ -183,7 +183,7 @@ describe('ChunkCard', () => { />, ) - expect(screen.getByText(/Parent-Chunk-01/)).toBeInTheDocument() + expect(screen.getByText(/Parent-Chunk-01/))!.toBeInTheDocument() }) it('should hide segment index tag for full-doc mode', () => { @@ -205,13 +205,13 @@ describe('ChunkCard', () => { render( , ) - expect(screen.getByText(/Chunk-05/)).toBeInTheDocument() + expect(screen.getByText(/Chunk-05/))!.toBeInTheDocument() }) }) @@ -220,26 +220,26 @@ describe('ChunkCard', () => { render( , ) - expect(screen.getByText(/1,234/)).toBeInTheDocument() + expect(screen.getByText(/1,234/))!.toBeInTheDocument() }) it('should display word count with character translation key', () => { render( , ) - expect(screen.getByText(/100\s+(?:\S.*)?characters/)).toBeInTheDocument() + expect(screen.getByText(/100\s+(?:\S.*)?characters/))!.toBeInTheDocument() }) it('should not display word count info for full-doc mode', () => { @@ -262,39 +262,39 @@ describe('ChunkCard', () => { render( , ) - expect(screen.getByText(/Chunk-42/)).toBeInTheDocument() + expect(screen.getByText(/Chunk-42/))!.toBeInTheDocument() }) it('should handle string position ID', () => { render( , ) - expect(screen.getByText(/Chunk-99/)).toBeInTheDocument() + expect(screen.getByText(/Chunk-99/))!.toBeInTheDocument() }) it('should pad single digit position ID', () => { render( , ) - expect(screen.getByText(/Chunk-03/)).toBeInTheDocument() + expect(screen.getByText(/Chunk-03/))!.toBeInTheDocument() }) }) @@ -310,7 +310,7 @@ describe('ChunkCard', () => { />, ) - expect(screen.getByText(/Parent-Chunk/)).toBeInTheDocument() + expect(screen.getByText(/Parent-Chunk/))!.toBeInTheDocument() rerender( { />, ) - expect(screen.getByText('Initial content')).toBeInTheDocument() + expect(screen.getByText('Initial content'))!.toBeInTheDocument() rerender( { />, ) - expect(screen.getByText('Updated content')).toBeInTheDocument() + expect(screen.getByText('Updated content'))!.toBeInTheDocument() expect(screen.queryByText('Initial content')).not.toBeInTheDocument() }) @@ -364,7 +364,7 @@ describe('ChunkCard', () => { />, ) - expect(screen.getByText('Text content')).toBeInTheDocument() + expect(screen.getByText('Text content'))!.toBeInTheDocument() const qaContent: QAChunk = { question: 'Q?', answer: 'A.' } rerender( @@ -376,8 +376,8 @@ describe('ChunkCard', () => { />, ) - expect(screen.getByText('Q')).toBeInTheDocument() - expect(screen.getByText('Q?')).toBeInTheDocument() + expect(screen.getByText('Q'))!.toBeInTheDocument() + expect(screen.getByText('Q?'))!.toBeInTheDocument() }) }) @@ -393,7 +393,7 @@ describe('ChunkCard', () => { />, ) - expect(screen.getByText(/Parent-Chunk-01/)).toBeInTheDocument() + expect(screen.getByText(/Parent-Chunk-01/))!.toBeInTheDocument() }) it('should handle QA chunk with empty strings', () => { @@ -408,8 +408,8 @@ describe('ChunkCard', () => { />, ) - expect(screen.getByText('Q')).toBeInTheDocument() - expect(screen.getByText('A')).toBeInTheDocument() + expect(screen.getByText('Q'))!.toBeInTheDocument() + expect(screen.getByText('A'))!.toBeInTheDocument() }) it('should handle very long content', () => { @@ -425,20 +425,20 @@ describe('ChunkCard', () => { />, ) - expect(screen.getByText(longContent)).toBeInTheDocument() + expect(screen.getByText(longContent))!.toBeInTheDocument() }) it('should handle zero word count', () => { render( , ) - expect(screen.getByText(/0\s+(?:\S.*)?characters/)).toBeInTheDocument() + expect(screen.getByText(/0\s+(?:\S.*)?characters/))!.toBeInTheDocument() }) }) }) @@ -459,9 +459,9 @@ describe('ChunkCardList', () => { />, ) - expect(screen.getByText(chunks[0].content)).toBeInTheDocument() - expect(screen.getByText(chunks[1].content)).toBeInTheDocument() - expect(screen.getByText(chunks[2].content)).toBeInTheDocument() + expect(screen.getByText(chunks[0]!.content))!.toBeInTheDocument() + expect(screen.getByText(chunks[1]!.content))!.toBeInTheDocument() + expect(screen.getByText(chunks[2]!.content))!.toBeInTheDocument() }) it('should render parent-child chunks correctly', () => { @@ -475,9 +475,9 @@ describe('ChunkCardList', () => { />, ) - expect(screen.getByText('Child content 1')).toBeInTheDocument() - expect(screen.getByText('Child content 2')).toBeInTheDocument() - expect(screen.getByText('Another child 1')).toBeInTheDocument() + expect(screen.getByText('Child content 1'))!.toBeInTheDocument() + expect(screen.getByText('Child content 2'))!.toBeInTheDocument() + expect(screen.getByText('Another child 1'))!.toBeInTheDocument() }) it('should render QA chunks correctly', () => { @@ -490,10 +490,10 @@ describe('ChunkCardList', () => { />, ) - expect(screen.getByText('What is the answer to life?')).toBeInTheDocument() - expect(screen.getByText('The answer is 42.')).toBeInTheDocument() - expect(screen.getByText('How does this work?')).toBeInTheDocument() - expect(screen.getByText('It works by processing data.')).toBeInTheDocument() + expect(screen.getByText('What is the answer to life?'))!.toBeInTheDocument() + expect(screen.getByText('The answer is 42.'))!.toBeInTheDocument() + expect(screen.getByText('How does this work?'))!.toBeInTheDocument() + expect(screen.getByText('It works by processing data.'))!.toBeInTheDocument() }) }) @@ -511,8 +511,8 @@ describe('ChunkCardList', () => { />, ) - expect(screen.getByText('Chunk 1')).toBeInTheDocument() - expect(screen.getByText('Chunk 2')).toBeInTheDocument() + expect(screen.getByText('Chunk 1'))!.toBeInTheDocument() + expect(screen.getByText('Chunk 2'))!.toBeInTheDocument() }) it('should extract parent_child_chunks from ParentChildChunks for parentChild mode', () => { @@ -530,7 +530,7 @@ describe('ChunkCardList', () => { />, ) - expect(screen.getByText('Specific child')).toBeInTheDocument() + expect(screen.getByText('Specific child'))!.toBeInTheDocument() }) it('should extract qa_chunks from QAChunks for qa mode', () => { @@ -547,8 +547,8 @@ describe('ChunkCardList', () => { />, ) - expect(screen.getByText('Specific Q')).toBeInTheDocument() - expect(screen.getByText('Specific A')).toBeInTheDocument() + expect(screen.getByText('Specific Q'))!.toBeInTheDocument() + expect(screen.getByText('Specific A'))!.toBeInTheDocument() }) it('should update chunkList when chunkInfo changes', () => { @@ -561,7 +561,7 @@ describe('ChunkCardList', () => { />, ) - expect(screen.getByText('Initial chunk')).toBeInTheDocument() + expect(screen.getByText('Initial chunk'))!.toBeInTheDocument() const updatedChunks = createGeneralChunks([{ content: 'Updated chunk' }]) rerender( @@ -571,7 +571,7 @@ describe('ChunkCardList', () => { />, ) - expect(screen.getByText('Updated chunk')).toBeInTheDocument() + expect(screen.getByText('Updated chunk'))!.toBeInTheDocument() expect(screen.queryByText('Initial chunk')).not.toBeInTheDocument() }) }) @@ -587,7 +587,7 @@ describe('ChunkCardList', () => { />, ) - expect(screen.getByText(/5\s+(?:\S.*)?characters/)).toBeInTheDocument() + expect(screen.getByText(/5\s+(?:\S.*)?characters/))!.toBeInTheDocument() }) it('should calculate word count for parent-child chunks using parent_content length', () => { @@ -608,7 +608,7 @@ describe('ChunkCardList', () => { />, ) - expect(screen.getByText(/6\s+(?:\S.*)?characters/)).toBeInTheDocument() + expect(screen.getByText(/6\s+(?:\S.*)?characters/))!.toBeInTheDocument() }) it('should calculate word count for QA chunks using question + answer length', () => { @@ -625,7 +625,7 @@ describe('ChunkCardList', () => { />, ) - expect(screen.getByText(/5\s+(?:\S.*)?characters/)).toBeInTheDocument() + expect(screen.getByText(/5\s+(?:\S.*)?characters/))!.toBeInTheDocument() }) }) @@ -644,9 +644,9 @@ describe('ChunkCardList', () => { />, ) - expect(screen.getByText(/Chunk-01/)).toBeInTheDocument() - expect(screen.getByText(/Chunk-02/)).toBeInTheDocument() - expect(screen.getByText(/Chunk-03/)).toBeInTheDocument() + expect(screen.getByText(/Chunk-01/))!.toBeInTheDocument() + expect(screen.getByText(/Chunk-02/))!.toBeInTheDocument() + expect(screen.getByText(/Chunk-03/))!.toBeInTheDocument() }) }) @@ -662,7 +662,7 @@ describe('ChunkCardList', () => { />, ) - expect(container.firstChild).toHaveClass('custom-class') + expect(container.firstChild)!.toHaveClass('custom-class') }) it('should merge custom className with default classes', () => { @@ -676,10 +676,10 @@ describe('ChunkCardList', () => { />, ) - expect(container.firstChild).toHaveClass('flex') - expect(container.firstChild).toHaveClass('w-full') - expect(container.firstChild).toHaveClass('flex-col') - expect(container.firstChild).toHaveClass('my-custom-class') + expect(container.firstChild)!.toHaveClass('flex') + expect(container.firstChild)!.toHaveClass('w-full') + expect(container.firstChild)!.toHaveClass('flex-col') + expect(container.firstChild)!.toHaveClass('my-custom-class') }) it('should render without className prop', () => { @@ -692,8 +692,8 @@ describe('ChunkCardList', () => { />, ) - expect(container.firstChild).toHaveClass('flex') - expect(container.firstChild).toHaveClass('w-full') + expect(container.firstChild)!.toHaveClass('flex') + expect(container.firstChild)!.toHaveClass('w-full') }) }) @@ -738,7 +738,7 @@ describe('ChunkCardList', () => { />, ) - expect(screen.getByText(/Chunk-01/)).toBeInTheDocument() + expect(screen.getByText(/Chunk-01/))!.toBeInTheDocument() }) }) @@ -753,7 +753,7 @@ describe('ChunkCardList', () => { />, ) - expect(container.firstChild).toBeInTheDocument() + expect(container.firstChild)!.toBeInTheDocument() expect(container.firstChild?.childNodes.length).toBe(0) }) @@ -771,7 +771,7 @@ describe('ChunkCardList', () => { />, ) - expect(container.firstChild).toBeInTheDocument() + expect(container.firstChild)!.toBeInTheDocument() expect(container.firstChild?.childNodes.length).toBe(0) }) @@ -787,7 +787,7 @@ describe('ChunkCardList', () => { />, ) - expect(container.firstChild).toBeInTheDocument() + expect(container.firstChild)!.toBeInTheDocument() expect(container.firstChild?.childNodes.length).toBe(0) }) @@ -801,8 +801,8 @@ describe('ChunkCardList', () => { />, ) - expect(screen.getByText('Single chunk')).toBeInTheDocument() - expect(screen.getByText(/Chunk-01/)).toBeInTheDocument() + expect(screen.getByText('Single chunk'))!.toBeInTheDocument() + expect(screen.getByText(/Chunk-01/))!.toBeInTheDocument() }) it('should handle large number of chunks', () => { @@ -815,9 +815,9 @@ describe('ChunkCardList', () => { />, ) - expect(screen.getByText('Chunk number 1')).toBeInTheDocument() - expect(screen.getByText('Chunk number 100')).toBeInTheDocument() - expect(screen.getByText(/Chunk-100/)).toBeInTheDocument() + expect(screen.getByText('Chunk number 1'))!.toBeInTheDocument() + expect(screen.getByText('Chunk number 100'))!.toBeInTheDocument() + expect(screen.getByText(/Chunk-100/))!.toBeInTheDocument() }) }) @@ -861,15 +861,15 @@ describe('ChunkCardList Integration', () => { />, ) - expect(screen.getByText('First paragraph of the document.')).toBeInTheDocument() - expect(screen.getByText(/Chunk-01/)).toBeInTheDocument() - expect(screen.getByText(/32\s+(?:\S.*)?characters/)).toBeInTheDocument() + expect(screen.getByText('First paragraph of the document.'))!.toBeInTheDocument() + expect(screen.getByText(/Chunk-01/))!.toBeInTheDocument() + expect(screen.getByText(/32\s+(?:\S.*)?characters/))!.toBeInTheDocument() - expect(screen.getByText('Second paragraph with more information.')).toBeInTheDocument() - expect(screen.getByText(/Chunk-02/)).toBeInTheDocument() + expect(screen.getByText('Second paragraph with more information.'))!.toBeInTheDocument() + expect(screen.getByText(/Chunk-02/))!.toBeInTheDocument() - expect(screen.getByText('Final paragraph concluding the content.')).toBeInTheDocument() - expect(screen.getByText(/Chunk-03/)).toBeInTheDocument() + expect(screen.getByText('Final paragraph concluding the content.'))!.toBeInTheDocument() + expect(screen.getByText(/Chunk-03/))!.toBeInTheDocument() }) it('should render complete parent-child chunking workflow', () => { @@ -894,11 +894,11 @@ describe('ChunkCardList Integration', () => { />, ) - expect(screen.getByText('React components are building blocks.')).toBeInTheDocument() - expect(screen.getByText('Lifecycle methods control component behavior.')).toBeInTheDocument() - expect(screen.getByText('C-1')).toBeInTheDocument() - expect(screen.getByText('C-2')).toBeInTheDocument() - expect(screen.getByText(/Parent-Chunk-01/)).toBeInTheDocument() + expect(screen.getByText('React components are building blocks.'))!.toBeInTheDocument() + expect(screen.getByText('Lifecycle methods control component behavior.'))!.toBeInTheDocument() + expect(screen.getByText('C-1'))!.toBeInTheDocument() + expect(screen.getByText('C-2'))!.toBeInTheDocument() + expect(screen.getByText(/Parent-Chunk-01/))!.toBeInTheDocument() }) it('should render complete QA chunking workflow', () => { @@ -927,10 +927,10 @@ describe('ChunkCardList Integration', () => { expect(qLabels.length).toBe(2) expect(aLabels.length).toBe(2) - expect(screen.getByText('What is Dify?')).toBeInTheDocument() - expect(screen.getByText('Dify is an open-source LLM application development platform.')).toBeInTheDocument() - expect(screen.getByText('How do I get started?')).toBeInTheDocument() - expect(screen.getByText('You can start by installing the platform using Docker.')).toBeInTheDocument() + expect(screen.getByText('What is Dify?'))!.toBeInTheDocument() + expect(screen.getByText('Dify is an open-source LLM application development platform.'))!.toBeInTheDocument() + expect(screen.getByText('How do I get started?'))!.toBeInTheDocument() + expect(screen.getByText('You can start by installing the platform using Docker.'))!.toBeInTheDocument() }) }) @@ -946,7 +946,7 @@ describe('ChunkCardList Integration', () => { />, ) - expect(screen.getByText('Text content')).toBeInTheDocument() + expect(screen.getByText('Text content'))!.toBeInTheDocument() rerender( { ) expect(screen.queryByText('Text content')).not.toBeInTheDocument() - expect(screen.getByText('What is the answer to life?')).toBeInTheDocument() + expect(screen.getByText('What is the answer to life?'))!.toBeInTheDocument() }) it('should handle switching from text to parent-child type', () => { @@ -970,8 +970,8 @@ describe('ChunkCardList Integration', () => { />, ) - expect(screen.getByText('Simple text')).toBeInTheDocument() - expect(screen.getByText(/Chunk-01/)).toBeInTheDocument() + expect(screen.getByText('Simple text'))!.toBeInTheDocument() + expect(screen.getByText(/Chunk-01/))!.toBeInTheDocument() rerender( { it('should render panel without crashing', () => { render() - expect( - screen.getByText('datasetPipeline.inputFieldPanel.title'), - ).toBeInTheDocument() + expect(screen.getByText('datasetPipeline.inputFieldPanel.title'))!.toBeInTheDocument() }) it('should render panel title correctly', () => { render() - expect( - screen.getByText('datasetPipeline.inputFieldPanel.title'), - ).toBeInTheDocument() + expect(screen.getByText('datasetPipeline.inputFieldPanel.title'))!.toBeInTheDocument() }) it('should render panel description', () => { render() - expect( - screen.getByText('datasetPipeline.inputFieldPanel.description'), - ).toBeInTheDocument() + expect(screen.getByText('datasetPipeline.inputFieldPanel.description'))!.toBeInTheDocument() }) it('should render preview button', () => { render() - expect( - screen.getByText('datasetPipeline.operations.preview'), - ).toBeInTheDocument() + expect(screen.getByText('datasetPipeline.operations.preview'))!.toBeInTheDocument() }) it('should render close button', () => { render() const closeButton = screen.getByRole('button', { name: '' }) - expect(closeButton).toBeInTheDocument() + expect(closeButton)!.toBeInTheDocument() }) it('should render footer tip component', () => { render() - expect(screen.getByTestId('footer-tip')).toBeInTheDocument() + expect(screen.getByTestId('footer-tip'))!.toBeInTheDocument() }) it('should render unique inputs section title', () => { render() - expect( - screen.getByText('datasetPipeline.inputFieldPanel.uniqueInputs.title'), - ).toBeInTheDocument() + expect(screen.getByText('datasetPipeline.inputFieldPanel.uniqueInputs.title'))!.toBeInTheDocument() }) it('should render global inputs field list', () => { render() - expect(screen.getByTestId('field-list-shared')).toBeInTheDocument() - expect(screen.getByTestId('global-inputs-label')).toBeInTheDocument() + expect(screen.getByTestId('field-list-shared'))!.toBeInTheDocument() + expect(screen.getByTestId('global-inputs-label'))!.toBeInTheDocument() }) }) @@ -263,8 +253,8 @@ describe('InputFieldPanel', () => { render() - expect(screen.getByTestId('field-list-node-1')).toBeInTheDocument() - expect(screen.getByTestId('field-list-node-2')).toBeInTheDocument() + expect(screen.getByTestId('field-list-node-1'))!.toBeInTheDocument() + expect(screen.getByTestId('field-list-node-2'))!.toBeInTheDocument() }) it('should render datasource label for each node', () => { @@ -273,9 +263,7 @@ describe('InputFieldPanel', () => { render() - expect( - screen.getByTestId('datasource-label-My DataSource'), - ).toBeInTheDocument() + expect(screen.getByTestId('datasource-label-My DataSource'))!.toBeInTheDocument() }) it('should not render any datasource field lists when no nodes exist', () => { @@ -284,7 +272,7 @@ describe('InputFieldPanel', () => { render() expect(screen.queryByTestId('field-list-node-1')).not.toBeInTheDocument() - expect(screen.getByTestId('field-list-shared')).toBeInTheDocument() + expect(screen.getByTestId('field-list-shared'))!.toBeInTheDocument() }) it('should filter only DataSource type nodes', () => { @@ -303,10 +291,8 @@ describe('InputFieldPanel', () => { render() - expect(screen.getByTestId('field-list-ds-node')).toBeInTheDocument() - expect( - screen.queryByTestId('field-list-other-node'), - ).not.toBeInTheDocument() + expect(screen.getByTestId('field-list-ds-node'))!.toBeInTheDocument() + expect(screen.queryByTestId('field-list-other-node')).not.toBeInTheDocument() }) }) @@ -322,8 +308,8 @@ describe('InputFieldPanel', () => { render() - expect(screen.getByTestId('field-list-fields-count-node-1')).toHaveTextContent('2') - expect(screen.getByTestId('field-list-fields-count-shared')).toHaveTextContent('1') + expect(screen.getByTestId('field-list-fields-count-node-1'))!.toHaveTextContent('2') + expect(screen.getByTestId('field-list-fields-count-shared'))!.toHaveTextContent('1') }) it('should show zero fields for nodes without variables', () => { @@ -332,7 +318,7 @@ describe('InputFieldPanel', () => { render() - expect(screen.getByTestId('field-list-fields-count-node-1')).toHaveTextContent('0') + expect(screen.getByTestId('field-list-fields-count-node-1'))!.toHaveTextContent('0') }) it('should pass all variable names to field lists', () => { @@ -345,10 +331,10 @@ describe('InputFieldPanel', () => { render() - expect(screen.getByTestId('field-list-all-vars-node-1')).toHaveTextContent( + expect(screen.getByTestId('field-list-all-vars-node-1'))!.toHaveTextContent( 'var1,var2', ) - expect(screen.getByTestId('field-list-all-vars-shared')).toHaveTextContent( + expect(screen.getByTestId('field-list-all-vars-shared'))!.toHaveTextContent( 'var1,var2', ) }) @@ -386,7 +372,7 @@ describe('InputFieldPanel', () => { const previewButton = screen .getByText('datasetPipeline.operations.preview') .closest('button') - expect(previewButton).toBeDisabled() + expect(previewButton)!.toBeDisabled() }) it('should not disable preview button when not editing', () => { @@ -410,8 +396,8 @@ describe('InputFieldPanel', () => { const previewButton = screen .getByText('datasetPipeline.operations.preview') .closest('button') - expect(previewButton).toHaveClass('bg-state-accent-active') - expect(previewButton).toHaveClass('text-text-accent') + expect(previewButton)!.toHaveClass('bg-state-accent-active') + expect(previewButton)!.toHaveClass('text-text-accent') }) it('should set readonly to true when previewing', () => { @@ -419,7 +405,7 @@ describe('InputFieldPanel', () => { render() - expect(screen.getByTestId('field-list-readonly-shared')).toHaveTextContent( + expect(screen.getByTestId('field-list-readonly-shared'))!.toHaveTextContent( 'true', ) }) @@ -429,7 +415,7 @@ describe('InputFieldPanel', () => { render() - expect(screen.getByTestId('field-list-readonly-shared')).toHaveTextContent( + expect(screen.getByTestId('field-list-readonly-shared'))!.toHaveTextContent( 'true', ) }) @@ -439,7 +425,7 @@ describe('InputFieldPanel', () => { render() - expect(screen.getByTestId('field-list-readonly-shared')).toHaveTextContent( + expect(screen.getByTestId('field-list-readonly-shared'))!.toHaveTextContent( 'false', ) }) @@ -484,15 +470,15 @@ describe('InputFieldPanel', () => { expect(mockSetRagPipelineVariables).toHaveBeenCalled() }) - const setVarsCall = mockSetRagPipelineVariables.mock.calls[0][0] as RAGPipelineVariables + const setVarsCall = mockSetRagPipelineVariables.mock.calls[0]![0] as RAGPipelineVariables const isNotShared = (v: RAGPipelineVariable) => v.belong_to_node_id !== 'shared' const isShared = (v: RAGPipelineVariable) => v.belong_to_node_id === 'shared' const dsFields = setVarsCall.filter(isNotShared) const sharedFields = setVarsCall.filter(isShared) if (dsFields.length > 0 && sharedFields.length > 0) { - const firstDsIndex = setVarsCall.indexOf(dsFields[0]) - const firstSharedIndex = setVarsCall.indexOf(sharedFields[0]) + const firstDsIndex = setVarsCall.indexOf(dsFields[0]!) + const firstSharedIndex = setVarsCall.indexOf(sharedFields[0]!) expect(firstDsIndex).toBeLessThan(firstSharedIndex) } }) @@ -523,7 +509,7 @@ describe('InputFieldPanel', () => { expect(mockSetRagPipelineVariables).toHaveBeenCalled() }) - const setVarsCall = mockSetRagPipelineVariables.mock.calls[0][0] as RAGPipelineVariables + const setVarsCall = mockSetRagPipelineVariables.mock.calls[0]![0] as RAGPipelineVariables const isSharedField = (v: RAGPipelineVariable) => v.belong_to_node_id === 'shared' const hasSharedField = setVarsCall.some(isSharedField) expect(hasSharedField).toBe(true) @@ -537,15 +523,13 @@ describe('InputFieldPanel', () => { render() - expect( - screen.getByTestId('field-list-classname-node-1'), - ).toHaveTextContent('pt-1 pb-1') + expect(screen.getByTestId('field-list-classname-node-1'))!.toHaveTextContent('pt-1 pb-1') }) it('should pass correct className to global inputs field list', () => { render() - expect(screen.getByTestId('field-list-classname-shared')).toHaveTextContent( + expect(screen.getByTestId('field-list-classname-shared'))!.toHaveTextContent( 'pt-2 pb-1', ) }) @@ -559,7 +543,7 @@ describe('InputFieldPanel', () => { rerender() - expect(screen.getByTestId('field-list-node-1')).toBeInTheDocument() + expect(screen.getByTestId('field-list-node-1'))!.toBeInTheDocument() }) it('should compute allVariableNames correctly', () => { @@ -572,7 +556,7 @@ describe('InputFieldPanel', () => { render() - expect(screen.getByTestId('field-list-all-vars-shared')).toHaveTextContent( + expect(screen.getByTestId('field-list-all-vars-shared'))!.toHaveTextContent( 'alpha,beta,gamma', ) }) @@ -621,7 +605,7 @@ describe('InputFieldPanel', () => { render() - expect(screen.getByTestId('field-list-all-vars-shared')).toHaveTextContent( + expect(screen.getByTestId('field-list-all-vars-shared'))!.toHaveTextContent( '', ) }) @@ -632,7 +616,7 @@ describe('InputFieldPanel', () => { render() - expect(screen.getByTestId('field-list-shared')).toBeInTheDocument() + expect(screen.getByTestId('field-list-shared'))!.toBeInTheDocument() }) it('should handle null variable names in allVariableNames', () => { @@ -644,7 +628,7 @@ describe('InputFieldPanel', () => { render() - expect(screen.getByTestId('field-list-shared')).toBeInTheDocument() + expect(screen.getByTestId('field-list-shared'))!.toBeInTheDocument() }) it('should handle large number of datasource nodes', () => { @@ -655,7 +639,7 @@ describe('InputFieldPanel', () => { render() nodes.forEach((_, i) => { - expect(screen.getByTestId(`field-list-node-${i}`)).toBeInTheDocument() + expect(screen.getByTestId(`field-list-node-${i}`))!.toBeInTheDocument() }) }) @@ -666,7 +650,7 @@ describe('InputFieldPanel', () => { render() - expect(screen.getByTestId('field-list-fields-count-shared')).toHaveTextContent( + expect(screen.getByTestId('field-list-fields-count-shared'))!.toHaveTextContent( '100', ) }) @@ -680,7 +664,7 @@ describe('InputFieldPanel', () => { render() - expect(screen.getByTestId('field-list-all-vars-shared')).toHaveTextContent( + expect(screen.getByTestId('field-list-all-vars-shared'))!.toHaveTextContent( 'var_with_underscore,varWithCamelCase', ) }) @@ -717,8 +701,8 @@ describe('InputFieldPanel', () => { render() - expect(screen.getByTestId('field-list-fields-count-node-1')).toHaveTextContent('1') - expect(screen.getByTestId('field-list-fields-count-node-2')).toHaveTextContent('2') + expect(screen.getByTestId('field-list-fields-count-node-1'))!.toHaveTextContent('1') + expect(screen.getByTestId('field-list-fields-count-node-2'))!.toHaveTextContent('2') }) }) @@ -727,25 +711,21 @@ describe('InputFieldPanel', () => { const { container } = render() const panel = container.firstChild as HTMLElement - expect(panel).toHaveClass('w-[400px]') + expect(panel)!.toHaveClass('w-[400px]') }) it('should have overflow scroll on content area', () => { const { container } = render() const scrollContainer = container.querySelector('.overflow-y-auto') - expect(scrollContainer).toBeInTheDocument() + expect(scrollContainer)!.toBeInTheDocument() }) it('should render header section with proper spacing', () => { render() - expect( - screen.getByText('datasetPipeline.inputFieldPanel.title'), - ).toBeInTheDocument() - expect( - screen.getByText('datasetPipeline.inputFieldPanel.description'), - ).toBeInTheDocument() + expect(screen.getByText('datasetPipeline.inputFieldPanel.title'))!.toBeInTheDocument() + expect(screen.getByText('datasetPipeline.inputFieldPanel.description'))!.toBeInTheDocument() }) }) @@ -763,9 +743,9 @@ describe('InputFieldPanel', () => { render() - expect(screen.getByTestId('field-list-node-1')).toBeInTheDocument() - expect(screen.getByTestId('field-list-readonly-node-1')).toHaveTextContent('true') - expect(screen.getByTestId('field-list-fields-count-node-1')).toHaveTextContent('1') + expect(screen.getByTestId('field-list-node-1'))!.toBeInTheDocument() + expect(screen.getByTestId('field-list-readonly-node-1'))!.toHaveTextContent('true') + expect(screen.getByTestId('field-list-fields-count-node-1'))!.toHaveTextContent('1') }) it('should pass correct props to FieldList for shared node', () => { @@ -776,9 +756,9 @@ describe('InputFieldPanel', () => { render() - expect(screen.getByTestId('field-list-shared')).toBeInTheDocument() - expect(screen.getByTestId('field-list-readonly-shared')).toHaveTextContent('true') - expect(screen.getByTestId('field-list-fields-count-shared')).toHaveTextContent('1') + expect(screen.getByTestId('field-list-shared'))!.toBeInTheDocument() + expect(screen.getByTestId('field-list-readonly-shared'))!.toHaveTextContent('true') + expect(screen.getByTestId('field-list-fields-count-shared'))!.toHaveTextContent('1') }) }) @@ -793,7 +773,7 @@ describe('InputFieldPanel', () => { render() - expect(screen.getByTestId('field-list-all-vars-shared')).toHaveTextContent( + expect(screen.getByTestId('field-list-all-vars-shared'))!.toHaveTextContent( 'first,second,third', ) }) @@ -810,7 +790,7 @@ describe('useFloatingRight Hook Integration', () => { it('should render panel correctly with default floating state', () => { render() - expect(screen.getByTestId('field-list-shared')).toBeInTheDocument() + expect(screen.getByTestId('field-list-shared'))!.toBeInTheDocument() }) }) @@ -823,7 +803,7 @@ describe('FooterTip Integration', () => { it('should render footer tip at the bottom of the panel', () => { render() - expect(screen.getByTestId('footer-tip')).toBeInTheDocument() + expect(screen.getByTestId('footer-tip'))!.toBeInTheDocument() }) }) @@ -836,7 +816,7 @@ describe('Label Components Integration', () => { it('should render GlobalInputs label for shared field list', () => { render() - expect(screen.getByTestId('global-inputs-label')).toBeInTheDocument() + expect(screen.getByTestId('global-inputs-label'))!.toBeInTheDocument() }) it('should render Datasource label for each datasource node', () => { @@ -848,12 +828,8 @@ describe('Label Components Integration', () => { render() - expect( - screen.getByTestId('datasource-label-First DataSource'), - ).toBeInTheDocument() - expect( - screen.getByTestId('datasource-label-Second DataSource'), - ).toBeInTheDocument() + expect(screen.getByTestId('datasource-label-First DataSource'))!.toBeInTheDocument() + expect(screen.getByTestId('datasource-label-Second DataSource'))!.toBeInTheDocument() }) }) @@ -868,10 +844,8 @@ describe('Component Memo Behavior', () => { rerender() - expect(screen.getByTestId('field-list-shared')).toBeInTheDocument() - expect( - screen.getByText('datasetPipeline.inputFieldPanel.title'), - ).toBeInTheDocument() + expect(screen.getByTestId('field-list-shared'))!.toBeInTheDocument() + expect(screen.getByText('datasetPipeline.inputFieldPanel.title'))!.toBeInTheDocument() }) it('should handle state updates correctly with memo', async () => { diff --git a/web/app/components/rag-pipeline/components/panel/input-field/editor/form/index.tsx b/web/app/components/rag-pipeline/components/panel/input-field/editor/form/index.tsx index de003e78ba..3854b6561a 100644 --- a/web/app/components/rag-pipeline/components/panel/input-field/editor/form/index.tsx +++ b/web/app/components/rag-pipeline/components/panel/input-field/editor/form/index.tsx @@ -28,7 +28,7 @@ const InputFieldForm = ({ initialData, supportFile = false, onCancel, onSubmit, if (!result.success) { const issues = result.error.issues const firstIssue = issues[0] - const errorMessage = `"${firstIssue.path.join('.')}" ${firstIssue.message}` + const errorMessage = `"${firstIssue!.path.join('.')}" ${firstIssue!.message}` toast.error(errorMessage) return errorMessage } diff --git a/web/app/components/rag-pipeline/components/panel/input-field/field-list/__tests__/field-item.spec.tsx b/web/app/components/rag-pipeline/components/panel/input-field/field-list/__tests__/field-item.spec.tsx index 4a738761d0..8f5d9b5386 100644 --- a/web/app/components/rag-pipeline/components/panel/input-field/field-list/__tests__/field-item.spec.tsx +++ b/web/app/components/rag-pipeline/components/panel/input-field/field-list/__tests__/field-item.spec.tsx @@ -35,9 +35,9 @@ describe('FieldItem', () => { />, ) - expect(screen.getByText('field_name')).toBeInTheDocument() - expect(screen.getByText('Field Label')).toBeInTheDocument() - expect(screen.getByText('workflow.nodes.start.required')).toBeInTheDocument() + expect(screen.getByText('field_name'))!.toBeInTheDocument() + expect(screen.getByText('Field Label'))!.toBeInTheDocument() + expect(screen.getByText('workflow.nodes.start.required'))!.toBeInTheDocument() }) it('should show edit and delete controls on hover and trigger both callbacks', () => { @@ -54,8 +54,8 @@ describe('FieldItem', () => { fireEvent.mouseEnter(container.firstChild!) const buttons = screen.getAllByRole('button') - fireEvent.click(buttons[0]) - fireEvent.click(buttons[1]) + fireEvent.click(buttons[0]!) + fireEvent.click(buttons[1]!) expect(onClickEdit).toHaveBeenCalledWith('custom_field') expect(onRemove).toHaveBeenCalledWith(2) diff --git a/web/app/components/rag-pipeline/components/panel/input-field/field-list/__tests__/hooks.spec.ts b/web/app/components/rag-pipeline/components/panel/input-field/field-list/__tests__/hooks.spec.ts index c7f5a11ce3..376751e58f 100644 --- a/web/app/components/rag-pipeline/components/panel/input-field/field-list/__tests__/hooks.spec.ts +++ b/web/app/components/rag-pipeline/components/panel/input-field/field-list/__tests__/hooks.spec.ts @@ -141,7 +141,7 @@ describe('useFieldList', () => { ]) }) - const updatedFields = onInputFieldsChange.mock.calls[0][0] + const updatedFields = onInputFieldsChange.mock.calls[0]![0] expect(updatedFields[0]).not.toHaveProperty('id') expect(updatedFields[0]).not.toHaveProperty('chosen') expect(updatedFields[0]).not.toHaveProperty('selected') @@ -282,7 +282,7 @@ describe('useFieldList', () => { result.current.handleOpenInputFieldEditor() }) - const editorProps = mockToggleInputFieldEditPanel.mock.calls[0][0] + const editorProps = mockToggleInputFieldEditPanel.mock.calls[0]![0] const newField = createInputVar({ variable: 'new_var', label: 'New' }) act(() => { @@ -307,7 +307,7 @@ describe('useFieldList', () => { result.current.handleOpenInputFieldEditor() }) - const editorProps = mockToggleInputFieldEditPanel.mock.calls[0][0] + const editorProps = mockToggleInputFieldEditPanel.mock.calls[0]![0] const duplicateField = createInputVar({ variable: 'existing_var' }) act(() => { @@ -336,7 +336,7 @@ describe('useFieldList', () => { result.current.handleOpenInputFieldEditor('old_name') }) - const editorProps = mockToggleInputFieldEditPanel.mock.calls[0][0] + const editorProps = mockToggleInputFieldEditPanel.mock.calls[0]![0] const updatedField = createInputVar({ variable: 'new_name' }) act(() => { diff --git a/web/app/components/rag-pipeline/components/panel/input-field/field-list/__tests__/index.spec.tsx b/web/app/components/rag-pipeline/components/panel/input-field/field-list/__tests__/index.spec.tsx index e44301e252..b2dbc35601 100644 --- a/web/app/components/rag-pipeline/components/panel/input-field/field-list/__tests__/index.spec.tsx +++ b/web/app/components/rag-pipeline/components/panel/input-field/field-list/__tests__/index.spec.tsx @@ -110,7 +110,7 @@ describe('FieldItem', () => { />, ) - expect(screen.getByText('my_field')).toBeInTheDocument() + expect(screen.getByText('my_field'))!.toBeInTheDocument() }) it('should render field item with label when provided', () => { @@ -125,7 +125,7 @@ describe('FieldItem', () => { />, ) - expect(screen.getByText('Field Label')).toBeInTheDocument() + expect(screen.getByText('Field Label'))!.toBeInTheDocument() }) it('should not render label when empty', () => { @@ -155,7 +155,7 @@ describe('FieldItem', () => { />, ) - expect(screen.getByText(/required/i)).toBeInTheDocument() + expect(screen.getByText(/required/i))!.toBeInTheDocument() }) it('should not render required badge when required is false', () => { @@ -259,7 +259,7 @@ describe('FieldItem', () => { ) fireEvent.mouseEnter(container.firstChild!) const buttons = screen.getAllByRole('button') - fireEvent.click(buttons[0]) // Edit button + fireEvent.click(buttons[0]!) // Edit button expect(onClickEdit).toHaveBeenCalledWith('test_var') }) @@ -278,7 +278,7 @@ describe('FieldItem', () => { ) fireEvent.mouseEnter(container.firstChild!) const buttons = screen.getAllByRole('button') - fireEvent.click(buttons[1]) // Delete button + fireEvent.click(buttons[1]!) // Delete button expect(onRemove).toHaveBeenCalledWith(5) }) @@ -328,7 +328,7 @@ describe('FieldItem', () => { ) fireEvent.mouseEnter(container.querySelector('.handle')!) const buttons = screen.getAllByRole('button') - fireEvent.click(buttons[0]) + fireEvent.click(buttons[0]!) expect(onClickEdit).toHaveBeenCalled() expect(parentClick).not.toHaveBeenCalled() @@ -351,7 +351,7 @@ describe('FieldItem', () => { ) fireEvent.mouseEnter(container.querySelector('.handle')!) const buttons = screen.getAllByRole('button') - fireEvent.click(buttons[1]) + fireEvent.click(buttons[1]!) expect(onRemove).toHaveBeenCalled() expect(parentClick).not.toHaveBeenCalled() @@ -373,7 +373,7 @@ describe('FieldItem', () => { ) fireEvent.mouseEnter(container.firstChild!) const buttons = screen.getAllByRole('button') - fireEvent.click(buttons[0]) + fireEvent.click(buttons[0]!) rerender( { ) fireEvent.mouseEnter(container.firstChild!) const buttonsAfterRerender = screen.getAllByRole('button') - fireEvent.click(buttonsAfterRerender[0]) + fireEvent.click(buttonsAfterRerender[0]!) expect(onClickEdit).toHaveBeenCalledTimes(2) }) @@ -406,7 +406,7 @@ describe('FieldItem', () => { ) const varElement = screen.getByTitle(longVariable) - expect(varElement).toHaveClass('truncate') + expect(varElement)!.toHaveClass('truncate') }) it('should handle very long label names with truncation', () => { @@ -423,7 +423,7 @@ describe('FieldItem', () => { ) const labelElement = screen.getByTitle(longLabel) - expect(labelElement).toHaveClass('truncate') + expect(labelElement)!.toHaveClass('truncate') }) it('should handle special characters in variable and label', () => { @@ -441,8 +441,8 @@ describe('FieldItem', () => { />, ) - expect(screen.getByText('&"var\'')).toBeInTheDocument() - expect(screen.getByText('