From f40a4c5c7a7d7dfed968c3768d24d380e37d9941 Mon Sep 17 00:00:00 2001 From: yyh Date: Mon, 9 Feb 2026 17:15:21 +0800 Subject: [PATCH] lint --- .../search-error-handling.test.ts | 94 +-- .../time-range-picker/range-selector.tsx | 2 +- .../(commonLayout)/account-page/index.tsx | 4 +- .../components/app/app-publisher/index.tsx | 2 +- .../config-prompt/confirm-add-var/index.tsx | 2 +- .../config-prompt/message-type-selector.tsx | 2 +- .../config-var/config-select/index.tsx | 2 +- .../config-var/input-type-icon.tsx | 2 +- .../config-var/select-type-item/index.tsx | 2 +- .../app/configuration/config-var/var-item.tsx | 2 +- .../app/configuration/config-vision/index.tsx | 4 +- .../config-vision/param-config-content.tsx | 2 +- .../config/agent/agent-tools/index.tsx | 2 +- .../agent-tools/setting-built-in-tool.tsx | 2 +- .../config/agent/prompt-editor.tsx | 2 +- .../config/assistant-type-picker/index.tsx | 6 +- .../config/automatic/idea-output.tsx | 2 +- .../config/automatic/version-selector.tsx | 2 +- .../code-generator/get-code-generator-res.tsx | 2 +- .../configuration/ctrl-btn-group/index.tsx | 2 +- .../dataset-config/context-var/index.tsx | 2 +- .../dataset-config/context-var/var-picker.tsx | 8 +- .../dataset-config/select-dataset/index.tsx | 4 +- .../components/app/configuration/index.tsx | 4 +- .../tools/external-data-tool-modal.tsx | 2 +- .../app/configuration/tools/index.tsx | 2 +- .../app/create-app-dialog/app-card/index.tsx | 2 +- .../app/create-from-dsl-modal/uploader.tsx | 2 +- .../app/overview/apikey-info-panel/index.tsx | 6 +- web/app/components/app/overview/app-card.tsx | 2 +- .../app/overview/embedded/index.tsx | 2 +- .../app/text-generate/item/result-tab.tsx | 2 +- .../saved-items/no-data/index.tsx | 2 +- web/app/components/base/alert.tsx | 2 +- web/app/components/base/app-icon/index.tsx | 30 +- .../base/auto-height-textarea/index.tsx | 2 +- web/app/components/base/block-input/index.tsx | 4 +- .../chat-with-history/header/operation.tsx | 2 +- web/app/components/base/divider/index.tsx | 4 +- .../conversation-opener/modal.tsx | 2 +- .../new-feature-panel/dialog-wrapper.tsx | 2 +- web/app/components/base/file-thumb/index.tsx | 2 +- .../base/file-uploader/file-list-in-log.tsx | 2 +- .../file-image-item.tsx | 2 +- web/app/components/base/input/index.tsx | 4 +- .../base/linked-apps-panel/index.tsx | 2 +- web/app/components/base/mermaid/index.tsx | 4 +- web/app/components/base/node-status/index.tsx | 2 +- .../component-picker-block/prompt-option.tsx | 2 +- .../plugins/context-block/component.tsx | 2 +- .../plugins/current-block/component.tsx | 2 +- .../plugins/error-message-block/component.tsx | 2 +- .../plugins/hitl-input-block/input-field.tsx | 2 +- .../plugins/hitl-input-block/tag-label.tsx | 2 +- .../plugins/last-run-block/component.tsx | 2 +- web/app/components/base/select/locale.tsx | 2 +- web/app/components/base/slider/index.tsx | 2 +- web/app/components/base/switch/index.tsx | 2 +- .../base/tab-slider-plain/index.tsx | 4 +- .../components/base/tag-management/index.tsx | 2 +- web/app/components/base/textarea/index.tsx | 6 +- web/app/components/base/voice-input/index.tsx | 4 +- .../plans/self-hosted-plan-item/index.tsx | 2 +- .../custom/custom-web-app-brand/index.tsx | 2 +- .../datasets/create-from-pipeline/header.tsx | 2 +- .../datasets/create/step-one/upgrade-card.tsx | 2 +- .../create/website/firecrawl/options.tsx | 2 +- .../create/website/jina-reader/options.tsx | 2 +- .../create/website/watercrawl/options.tsx | 2 +- .../create-from-pipeline/left-header.tsx | 2 +- .../preview/web-preview.tsx | 2 +- .../detail/batch-modal/csv-uploader.tsx | 2 +- .../pipeline-settings/left-header.tsx | 2 +- .../components/child-chunks-item.tsx | 2 +- .../hit-testing/components/records.tsx | 6 +- .../metadata/edit-metadata-batch/edit-row.tsx | 2 +- .../input-has-set-multiple-value.tsx | 2 +- .../dataset-metadata-drawer.tsx | 2 +- .../metadata-dataset/select-metadata.tsx | 4 +- .../metadata/metadata-document/info-group.tsx | 4 +- web/app/components/explore/category.tsx | 2 +- .../explore/try-app/app/text-generation.tsx | 2 +- .../try-app/preview/basic-app-preview.tsx | 4 +- .../workplace-selector/index.tsx | 4 +- .../model-provider-page/model-modal/index.tsx | 2 +- .../presets-parameter.tsx | 2 +- .../model-parameter-modal/trigger.tsx | 4 +- web/app/components/header/index.tsx | 2 +- .../header/nav/nav-selector/index.tsx | 2 +- .../plugins/base/key-value-item.tsx | 2 +- .../plugins/card/base/corner-mark.tsx | 2 +- .../plugins/marketplace/list/card-wrapper.tsx | 2 +- .../marketplace/list/list-with-collection.tsx | 2 +- .../auto-update-setting/tool-item.tsx | 2 +- .../publish-as-knowledge-pipeline-modal.tsx | 2 +- .../components/update-dsl-modal.spec.tsx | 26 - .../get-schema.tsx | 4 +- .../edit-custom-collection-modal/index.tsx | 4 +- .../edit-custom-collection-modal/test-api.tsx | 2 +- web/app/components/tools/labels/filter.tsx | 2 +- web/app/components/tools/labels/selector.tsx | 2 +- .../components/tools/mcp/provider-card.tsx | 2 +- .../setting/build-in/config-credentials.tsx | 2 +- .../components/tools/workflow-tool/index.tsx | 2 +- .../tools/workflow-tool/method-selector.tsx | 2 +- .../block-selector/featured-tools.tsx | 2 +- .../block-selector/featured-triggers.tsx | 2 +- .../market-place-plugin/item.tsx | 2 +- .../block-selector/view-type-select.tsx | 2 +- .../workflow/header/header-in-restoring.tsx | 2 +- .../components/before-run-form/panel-wrap.tsx | 2 +- .../components/input-support-select-var.tsx | 2 +- .../nodes/_base/components/node-handle.tsx | 2 +- .../nodes/_base/components/prompt/editor.tsx | 4 +- .../nodes/_base/components/selector.tsx | 4 +- .../variable/var-full-path-panel.tsx | 2 +- .../variable/var-reference-picker.tsx | 2 +- .../variable/var-reference-vars.tsx | 6 +- .../_base/components/workflow-panel/index.tsx | 4 +- .../components/workflow/nodes/_base/node.tsx | 2 +- .../nodes/http/components/api-input.tsx | 2 +- .../components/workflow/nodes/http/panel.tsx | 4 +- .../human-input/components/form-content.tsx | 4 +- .../workflow/nodes/human-input/panel.tsx | 2 +- .../components/condition-files-list-value.tsx | 2 +- .../components/condition-number-input.tsx | 2 +- .../if-else/components/condition-wrap.tsx | 4 +- .../workflow/nodes/iteration/panel.tsx | 2 +- .../components/dataset-item.tsx | 2 +- .../components/retrieval-config.tsx | 2 +- .../components/extract-input.tsx | 2 +- .../components/sub-variable-picker.tsx | 2 +- .../components/condition-files-list-value.tsx | 2 +- .../components/condition-number-input.tsx | 2 +- .../nodes/loop/components/condition-wrap.tsx | 2 +- .../components/workflow/nodes/start/node.tsx | 2 +- .../nodes/tool/components/copy-id.tsx | 2 +- .../components/workflow/nodes/tool/node.tsx | 2 +- .../components/var-group-item.tsx | 2 +- .../components/object-value-item.tsx | 4 +- .../context-menu/menu-item.tsx | 2 +- .../delete-confirm-modal.tsx | 2 +- .../version-history-panel/filter/index.tsx | 2 +- .../version-history-panel/loading/item.tsx | 2 +- .../restore-confirm-modal.tsx | 2 +- .../version-history-item.tsx | 2 +- .../workflow/run/loop-result-panel.tsx | 2 +- .../components/workflow/run/result-text.tsx | 2 +- .../components/nodes/base.tsx | 2 +- web/app/education-apply/role-selector.tsx | 2 +- web/app/install/installForm.tsx | 2 +- web/eslint-suppressions.json | 686 +----------------- 152 files changed, 260 insertions(+), 946 deletions(-) diff --git a/web/__tests__/goto-anything/search-error-handling.test.ts b/web/__tests__/goto-anything/search-error-handling.test.ts index 2651d98f36..fe786689f7 100644 --- a/web/__tests__/goto-anything/search-error-handling.test.ts +++ b/web/__tests__/goto-anything/search-error-handling.test.ts @@ -10,9 +10,7 @@ import type { MockedFunction } from 'vitest' */ import { appScope, knowledgeScope, pluginScope, searchAnything } from '@/app/components/goto-anything/actions' -import { fetchAppList } from '@/service/apps' -import { postMarketplace } from '@/service/base' -import { fetchDatasets } from '@/service/datasets' +import { searchApps, searchDatasets, searchPlugins } from '@/service/use-goto-anything' // Mock react-i18next before importing modules that use it vi.mock('react-i18next', () => ({ @@ -22,30 +20,21 @@ vi.mock('react-i18next', () => ({ }), })) -// Mock API functions -vi.mock('@/service/base', () => ({ - postMarketplace: vi.fn(), +// Mock the actual service functions used by the scopes +vi.mock('@/service/use-goto-anything', () => ({ + searchPlugins: vi.fn(), + searchApps: vi.fn(), + searchDatasets: vi.fn(), })) -vi.mock('@/service/apps', () => ({ - fetchAppList: vi.fn(), -})) - -vi.mock('@/service/datasets', () => ({ - fetchDatasets: vi.fn(), -})) - -const mockPostMarketplace = postMarketplace as MockedFunction -const mockFetchAppList = fetchAppList as MockedFunction -const mockFetchDatasets = fetchDatasets as MockedFunction +const mockSearchPlugins = searchPlugins as MockedFunction +const mockSearchApps = searchApps as MockedFunction +const mockSearchDatasets = searchDatasets as MockedFunction describe('GotoAnything Search Error Handling', () => { beforeEach(() => { vi.clearAllMocks() - // Suppress console.warn for clean test output - vi.spyOn(console, 'warn').mockImplementation(() => { - // Suppress console.warn for clean test output - }) + vi.spyOn(console, 'warn').mockImplementation(() => {}) }) afterEach(() => { @@ -54,29 +43,17 @@ describe('GotoAnything Search Error Handling', () => { describe('@plugin search error handling', () => { it('should return empty array when API fails instead of throwing error', async () => { - // Mock marketplace API failure (403 permission denied) - mockPostMarketplace.mockRejectedValue(new Error('HTTP 403: Forbidden')) + mockSearchPlugins.mockRejectedValue(new Error('HTTP 403: Forbidden')) - // Directly call plugin action's search method const result = await pluginScope.search('@plugin', 'test', 'en') - // Should return empty array instead of throwing error expect(result).toEqual([]) - expect(mockPostMarketplace).toHaveBeenCalledWith('/plugins/search/advanced', { - body: { - page: 1, - page_size: 10, - query: 'test', - type: 'plugin', - }, - }) + expect(mockSearchPlugins).toHaveBeenCalledWith('test') }) it('should return empty array when user has no plugin data', async () => { - // Mock marketplace returning empty data - mockPostMarketplace.mockResolvedValue({ - data: { plugins: [] }, - }) + // eslint-disable-next-line ts/no-explicit-any + mockSearchPlugins.mockResolvedValue({ data: { plugins: [] } } as any) const result = await pluginScope.search('@plugin', '', 'en') @@ -84,10 +61,8 @@ describe('GotoAnything Search Error Handling', () => { }) it('should return empty array when API returns unexpected data structure', async () => { - // Mock API returning unexpected data structure - mockPostMarketplace.mockResolvedValue({ - data: null, - }) + // eslint-disable-next-line ts/no-explicit-any + mockSearchPlugins.mockResolvedValue({ data: null } as any) const result = await pluginScope.search('@plugin', 'test', 'en') @@ -97,8 +72,7 @@ describe('GotoAnything Search Error Handling', () => { describe('Other search types error handling', () => { it('@app search should return empty array when API fails', async () => { - // Mock app API failure - mockFetchAppList.mockRejectedValue(new Error('API Error')) + mockSearchApps.mockRejectedValue(new Error('API Error')) const result = await appScope.search('@app', 'test', 'en') @@ -106,8 +80,7 @@ describe('GotoAnything Search Error Handling', () => { }) it('@knowledge search should return empty array when API fails', async () => { - // Mock knowledge API failure - mockFetchDatasets.mockRejectedValue(new Error('API Error')) + mockSearchDatasets.mockRejectedValue(new Error('API Error')) const result = await knowledgeScope.search('@knowledge', 'test', 'en') @@ -117,33 +90,30 @@ describe('GotoAnything Search Error Handling', () => { describe('Unified search entry error handling', () => { it('regular search (without @prefix) should return successful results even when partial APIs fail', async () => { - // Set app and knowledge success, plugin failure - mockFetchAppList.mockResolvedValue({ data: [], has_more: false, limit: 10, page: 1, total: 0 }) - mockFetchDatasets.mockResolvedValue({ data: [], has_more: false, limit: 10, page: 1, total: 0 }) - mockPostMarketplace.mockRejectedValue(new Error('Plugin API failed')) + // eslint-disable-next-line ts/no-explicit-any + mockSearchApps.mockResolvedValue({ data: [], has_more: false, limit: 10, page: 1, total: 0 } as any) + // eslint-disable-next-line ts/no-explicit-any + mockSearchDatasets.mockResolvedValue({ data: [], has_more: false, limit: 10, page: 1, total: 0 } as any) + mockSearchPlugins.mockRejectedValue(new Error('Plugin API failed')) const allScopes = [appScope, knowledgeScope, pluginScope] const result = await searchAnything('en', 'test', undefined, allScopes) - // Should return successful results even if plugin search fails expect(result).toEqual([]) expect(console.warn).toHaveBeenCalled() }) it('@plugin dedicated search should return empty array when API fails', async () => { - // Mock plugin API failure - mockPostMarketplace.mockRejectedValue(new Error('Plugin service unavailable')) + mockSearchPlugins.mockRejectedValue(new Error('Plugin service unavailable')) const allScopes = [appScope, knowledgeScope, pluginScope] const result = await searchAnything('en', '@plugin test', pluginScope, allScopes) - // Should return empty array instead of throwing error expect(result).toEqual([]) }) it('@app dedicated search should return empty array when API fails', async () => { - // Mock app API failure - mockFetchAppList.mockRejectedValue(new Error('App service unavailable')) + mockSearchApps.mockRejectedValue(new Error('App service unavailable')) const allScopes = [appScope, knowledgeScope, pluginScope] const result = await searchAnything('en', '@app test', appScope, allScopes) @@ -154,10 +124,9 @@ describe('GotoAnything Search Error Handling', () => { describe('Error handling consistency validation', () => { it('all search types should return empty array when encountering errors', async () => { - // Mock all APIs to fail - mockPostMarketplace.mockRejectedValue(new Error('Plugin API failed')) - mockFetchAppList.mockRejectedValue(new Error('App API failed')) - mockFetchDatasets.mockRejectedValue(new Error('Dataset API failed')) + mockSearchPlugins.mockRejectedValue(new Error('Plugin API failed')) + mockSearchApps.mockRejectedValue(new Error('App API failed')) + mockSearchDatasets.mockRejectedValue(new Error('Dataset API failed')) const actions = [ { name: '@plugin', scope: pluginScope }, @@ -174,7 +143,8 @@ describe('GotoAnything Search Error Handling', () => { describe('Edge case testing', () => { it('empty search term should be handled properly', async () => { - mockPostMarketplace.mockResolvedValue({ data: { plugins: [] } }) + // eslint-disable-next-line ts/no-explicit-any + mockSearchPlugins.mockResolvedValue({ data: { plugins: [] } } as any) const allScopes = [appScope, knowledgeScope, pluginScope] const result = await searchAnything('en', '@plugin ', pluginScope, allScopes) @@ -185,7 +155,7 @@ describe('GotoAnything Search Error Handling', () => { const timeoutError = new Error('Network timeout') timeoutError.name = 'TimeoutError' - mockPostMarketplace.mockRejectedValue(timeoutError) + mockSearchPlugins.mockRejectedValue(timeoutError) const allScopes = [appScope, knowledgeScope, pluginScope] const result = await searchAnything('en', '@plugin test', pluginScope, allScopes) @@ -194,7 +164,7 @@ describe('GotoAnything Search Error Handling', () => { it('JSON parsing errors should be handled correctly', async () => { const parseError = new SyntaxError('Unexpected token in JSON') - mockPostMarketplace.mockRejectedValue(parseError) + mockSearchPlugins.mockRejectedValue(parseError) const allScopes = [appScope, knowledgeScope, pluginScope] const result = await searchAnything('en', '@plugin test', pluginScope, allScopes) diff --git a/web/app/(commonLayout)/app/(appDetailLayout)/[appId]/overview/time-range-picker/range-selector.tsx b/web/app/(commonLayout)/app/(appDetailLayout)/[appId]/overview/time-range-picker/range-selector.tsx index 986170728f..9f6df25aa6 100644 --- a/web/app/(commonLayout)/app/(appDetailLayout)/[appId]/overview/time-range-picker/range-selector.tsx +++ b/web/app/(commonLayout)/app/(appDetailLayout)/[appId]/overview/time-range-picker/range-selector.tsx @@ -57,7 +57,7 @@ const RangeSelector: FC = ({ {selected && (