Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 53 additions & 0 deletions web/AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,56 @@
- Use `web/testing/testing.md` as the canonical instruction set for generating frontend automated tests.
- When proposing or saving tests, re-read that document and follow every requirement.
- All frontend tests MUST also comply with the `frontend-testing` skill. Treat the skill as a mandatory constraint, not optional guidance.

<!--VITE PLUS START-->
# Using Vite+, the Unified Toolchain for the Web

This project is using Vite+, a modern toolchain built on top of Vite, Rolldown, Vitest, tsdown, Oxlint, and Oxfmt. Vite+ wraps these tools and package manager commands in a single, global CLI called `vite`. Vite+ is distinct from Vite, but it invokes Vite through `vite dev` and `vite build`.

## Vite+ Workflow

`vite` is a global binary that handles the full development lifecycle. Run `vite help` to print a list of commands and `vite <command> --help` for information about a specific command.

### Vite+ Commands

- dev - Run the development server
- build - Build for production
- lint - Lint code
- test - Run tests
- fmt - Format code
- lib - Build library
- new - Create a new monorepo package (in-project) or a new project (global)
- run - Run tasks from `package.json` scripts

These commands map to their corresponding tools. For example, `vite dev --port 3000` runs Vite's dev server and works the same as Vite. `vite test` runs JavaScript tests through the bundled Vitest. The versions of individual tools can be checked using `vite <command> --version`. For example, `vite lint --version` prints the bundled Oxlint version, and `vite test --version` prints the bundled Vitest version. This is useful when researching documentation, features, and bugs.

### Package Manager Commands

Vite+ automatically detects and wraps the underlying package manager such as pnpm, npm, or Yarn through the `packageManager` field in `package.json` or package manager-specific lockfiles.

- install - Install all dependencies, or add packages if package names are provided
- add - Add packages to dependencies
- remove - Remove packages from dependencies
- dlx - Execute a package binary without installing it as a dependency
- info - View package information from the registry, including latest versions
- link - Link packages for local development
- outdated - Check for outdated packages
- pm - Forward a command to the package manager
- unlink - Unlink packages
- update - Update packages to their latest versions
- why - Show why a package is installed

## Common Pitfalls

- **Using the package manager directly:** Do not use pnpm, npm, or Yarn directly. Vite+ can handle all package manager operations.
- **Always use Vite commands to run tools:** Don't attempt to run `vite vitest` or `vite oxlint`. They do not exist. Use `vite test` and `vite lint` instead.
- **Running scripts:** Vite+ commands take precedence over `package.json` scripts. If there is a `test` script defined in `scripts` that conflicts with the built-in `vite test` command, run it using `vite run test`.
- **Do not install Vitest, Oxlint, Oxfmt, or tsdown directly:** Vite+ wraps these tools. They must not be installed directly. You cannot upgrade these tools by installing their latest versions. Always use Vite+ commands.
- **Import JavaScript modules from `vite-plus`:** Instead of importing from `vite` or `vitest`, all modules should be imported from the project's `vite-plus` dependency. For example, `import { defineConfig } from 'vite-plus';` or `import { expect, test, vi } from 'vite-plus/test';`. You must not install `vitest` to import test utilities.
- **Type-Aware Linting:** There is no need to install `oxlint-tsgolint`, `vite lint --type-aware` works out of the box.

## Review Checklist for Agents

- [ ] Run `vite install` after pulling remote changes and before getting started.
- [ ] Run `vite lint`, `vite fmt`, and `vite test` to validate changes.
<!--VITE PLUS END-->
2 changes: 1 addition & 1 deletion web/__tests__/document-detail-navigation-fix.test.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { Mock } from 'vitest'
import type { Mock } from 'vite-plus/test'
/**
* Document Detail Navigation Fix Verification Test
*
Expand Down
2 changes: 1 addition & 1 deletion web/__tests__/goto-anything/match-action.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { Mock } from 'vitest'
import type { Mock } from 'vite-plus/test'
import type { ActionItem } from '../../app/components/goto-anything/actions/types'

// Import after mocking to get mocked version
Expand Down
2 changes: 1 addition & 1 deletion web/__tests__/goto-anything/search-error-handling.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { MockedFunction } from 'vitest'
import type { MockedFunction } from 'vite-plus/test'
/**
* Test GotoAnything search error handling mechanisms
*
Expand Down
2 changes: 1 addition & 1 deletion web/__tests__/workflow-onboarding-integration.test.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { Mock } from 'vitest'
import type { Mock } from 'vite-plus/test'
import { useWorkflowStore } from '@/app/components/workflow/store'
import { BlockEnum } from '@/app/components/workflow/types'

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { Mock } from 'vitest'
import type { Mock } from 'vite-plus/test'
import { act, fireEvent, render, screen, waitFor } from '@testing-library/react'
import * as React from 'react'
import { useProviderContext } from '@/context/provider-context'
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { Mock } from 'vitest'
import type { Mock } from 'vite-plus/test'
import type { Locale } from '@/i18n-config'
import { render, screen } from '@testing-library/react'
import * as React from 'react'
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { Mock } from 'vitest'
import type { Mock } from 'vite-plus/test'
import type { IBatchModalProps } from './index'
import { act, fireEvent, render, screen, waitFor } from '@testing-library/react'
import * as React from 'react'
Expand Down
2 changes: 1 addition & 1 deletion web/app/components/app/annotation/filter.spec.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { UseQueryResult } from '@tanstack/react-query'
import type { Mock } from 'vitest'
import type { Mock } from 'vite-plus/test'
import type { QueryParam } from './filter'
import type { AnnotationsCountResponse } from '@/models/log'
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { ComponentProps } from 'react'
import type { Mock } from 'vitest'
import type { Mock } from 'vite-plus/test'
import type { AnnotationItemBasic } from '../type'
import type { Locale } from '@/i18n-config'
import { render, screen, waitFor } from '@testing-library/react'
Expand Down
2 changes: 1 addition & 1 deletion web/app/components/app/annotation/index.spec.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { Mock } from 'vitest'
import type { Mock } from 'vite-plus/test'
import type { AnnotationItem } from './type'
import type { App } from '@/types/app'
import { act, fireEvent, render, screen, waitFor } from '@testing-library/react'
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { Mock } from 'vitest'
import type { Mock } from 'vite-plus/test'
import type { AnnotationItem, HitHistoryItem } from '../type'
import { fireEvent, render, screen, waitFor } from '@testing-library/react'
import * as React from 'react'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import type { ExternalDataTool } from '@/models/common'
import type { PromptVariable } from '@/models/debug'
import { act, fireEvent, render, screen } from '@testing-library/react'
import * as React from 'react'
import { vi } from 'vitest'
import { vi } from 'vite-plus/test'
import Toast from '@/app/components/base/toast'
import DebugConfigurationContext from '@/context/debug-configuration'
import { AppModeEnum } from '@/types/app'
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { Mock } from 'vitest'
import type { Mock } from 'vite-plus/test'
import type { FeatureStoreState } from '@/app/components/base/features/store'
import type { FileUpload } from '@/app/components/base/features/types'
import { fireEvent, render, screen } from '@testing-library/react'
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import type {
PropsWithChildren,
} from 'react'
import type { Mock } from 'vitest'
import type { Mock } from 'vite-plus/test'
import type SettingBuiltInToolType from './setting-built-in-tool'
import type { Tool, ToolParameter } from '@/app/components/tools/types'
import type ToolPickerType from '@/app/components/workflow/block-selector/tool-picker'
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { Mock } from 'vitest'
import type { Mock } from 'vite-plus/test'
import type { FeatureStoreState } from '@/app/components/base/features/store'
import { render, screen } from '@testing-library/react'
import userEvent from '@testing-library/user-event'
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { Mock } from 'vitest'
import type { Mock } from 'vite-plus/test'
import type { FeatureStoreState } from '@/app/components/base/features/store'
import { render, screen } from '@testing-library/react'
import userEvent from '@testing-library/user-event'
Expand Down
2 changes: 1 addition & 1 deletion web/app/components/app/configuration/config/index.spec.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { Mock } from 'vitest'
import type { Mock } from 'vite-plus/test'
import type { ModelConfig, PromptVariable } from '@/models/debug'
import type { ToolItem } from '@/types/app'
import { render, screen } from '@testing-library/react'
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type * as React from 'react'
import type { MockedFunction } from 'vitest'
import type { MockedFunction } from 'vite-plus/test'
import type { IndexingType } from '@/app/components/datasets/create/step-two'
import type { DataSet } from '@/models/datasets'
import type { RetrievalConfig } from '@/types/app'
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { MockedFunction, MockInstance } from 'vitest'
import type { MockedFunction, MockInstance } from 'vite-plus/test'
import type { IndexingType } from '@/app/components/datasets/create/step-two'
import type { DataSet } from '@/models/datasets'
import type { DatasetConfigs } from '@/models/debug'
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { MockedFunction, MockInstance } from 'vitest'
import type { MockedFunction, MockInstance } from 'vite-plus/test'
import type { DatasetConfigs } from '@/models/debug'
import { render, screen, waitFor, within } from '@testing-library/react'
import userEvent from '@testing-library/user-event'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import type { DataSet } from '@/models/datasets'
import { act, fireEvent, render, screen } from '@testing-library/react'
import * as React from 'react'

import { describe, expect, it, vi } from 'vitest'
import { describe, expect, it, vi } from 'vite-plus/test'
import { IndexingType } from '@/app/components/datasets/create/step-two'
import { DatasetPermission } from '@/models/datasets'
import { RETRIEVE_METHOD } from '@/types/app'
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { MockedFunction } from 'vitest'
import type { MockedFunction } from 'vite-plus/test'
import type { DataSet } from '@/models/datasets'
import type { RetrievalConfig } from '@/types/app'
import { render, screen, waitFor } from '@testing-library/react'
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import type { IPromptValuePanelProps } from './index'
import { fireEvent, render, screen, waitFor } from '@testing-library/react'
import * as React from 'react'
import { beforeEach, describe, expect, it, vi } from 'vitest'
import { beforeEach, describe, expect, it, vi } from 'vite-plus/test'
import { useStore } from '@/app/components/app/store'
import ConfigContext from '@/context/debug-configuration'
import { AppModeEnum, ModelModeType, Resolution } from '@/types/app'
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import type { PromptVariable } from '@/models/debug'

import { describe, expect, it } from 'vitest'
import { describe, expect, it } from 'vite-plus/test'
import { replaceStringWithValues } from './utils'

const promptVariables: PromptVariable[] = [
Expand Down
2 changes: 1 addition & 1 deletion web/app/components/app/create-app-modal/index.spec.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { fireEvent, render, screen, waitFor } from '@testing-library/react'
import { useRouter } from 'next/navigation'
import { afterAll, beforeEach, describe, expect, it, vi } from 'vitest'
import { afterAll, beforeEach, describe, expect, it, vi } from 'vite-plus/test'
import { trackEvent } from '@/app/components/base/amplitude'

import { ToastContext } from '@/app/components/base/toast'
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { MockedFunction } from 'vitest'
import type { MockedFunction } from 'vite-plus/test'
import type { Node } from '@/app/components/workflow/types'
import { getWorkflowEntryNode } from '@/app/components/workflow/utils/workflow-entry'

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { RenderOptions } from '@testing-library/react'
import type { Mock, MockedFunction } from 'vitest'
import type { Mock, MockedFunction } from 'vite-plus/test'
import type { ModalContextState } from '@/context/modal-context'
import { fireEvent, render } from '@testing-library/react'
import { noop } from 'es-toolkit/function'
Expand Down
2 changes: 1 addition & 1 deletion web/app/components/app/overview/embedded/index.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import copy from 'copy-to-clipboard'
import * as React from 'react'

import { act } from 'react'
import { afterAll, afterEach, describe, expect, it, vi } from 'vitest'
import { afterAll, afterEach, describe, expect, it, vi } from 'vite-plus/test'
import Embedded from './index'

vi.mock('./style.module.css', () => ({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { fireEvent, render, screen } from '@testing-library/react'
import copy from 'copy-to-clipboard'

import * as React from 'react'
import { beforeEach, describe, expect, it, vi } from 'vitest'
import { beforeEach, describe, expect, it, vi } from 'vite-plus/test'
import Toast from '@/app/components/base/toast'
import SavedItems from './index'

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { fireEvent, render, screen } from '@testing-library/react'
import { describe, expect, it, vi } from 'vitest'
import { describe, expect, it, vi } from 'vite-plus/test'

import NoData from './index'

Expand Down
2 changes: 1 addition & 1 deletion web/app/components/app/workflow-log/index.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import type { UseQueryResult } from '@tanstack/react-query'
* - trigger-by-display.spec.tsx
*/

import type { MockedFunction } from 'vitest'
import type { MockedFunction } from 'vite-plus/test'
import type { ILogsProps } from './index'
import type { WorkflowAppLogDetail, WorkflowLogsResponse, WorkflowRunDetail } from '@/models/log'
import type { App, AppIconType, AppModeEnum } from '@/types/app'
Expand Down
2 changes: 1 addition & 1 deletion web/app/components/apps/app-card.spec.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { Mock } from 'vitest'
import type { Mock } from 'vite-plus/test'
import { fireEvent, render, screen, waitFor } from '@testing-library/react'
import * as React from 'react'
import { AccessMode } from '@/models/access-control'
Expand Down
2 changes: 1 addition & 1 deletion web/app/components/apps/hooks/use-dsl-drag-drop.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
* - Enable/disable toggle for conditional drag-and-drop
* - Cleanup on unmount (removes event listeners)
*/
import type { Mock } from 'vitest'
import type { Mock } from 'vite-plus/test'
import { act, renderHook } from '@testing-library/react'
import { useDSLDragDrop } from './use-dsl-drag-drop'

Expand Down
2 changes: 1 addition & 1 deletion web/app/components/base/file-uploader/utils.spec.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { MockInstance } from 'vitest'
import type { MockInstance } from 'vite-plus/test'
import mime from 'mime'
import { SupportUploadFileTypes } from '@/app/components/workflow/types'
import { upload } from '@/service/base'
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { act, render, screen } from '@testing-library/react'
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
import { afterEach, beforeEach, describe, expect, it, vi } from 'vite-plus/test'
import { ChatContextProvider } from '@/app/components/base/chat/chat/context'
import ThinkBlock from './think-block'

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { Mock } from 'vitest'
import type { Mock } from 'vite-plus/test'
import type { UsagePlanInfo } from '@/app/components/billing/type'
import type { AppContextValue } from '@/context/app-context'
import type { ProviderContextState } from '@/context/provider-context'
Expand Down
2 changes: 1 addition & 1 deletion web/app/components/billing/pricing/index.spec.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { Mock } from 'vitest'
import type { Mock } from 'vite-plus/test'
import type { UsagePlanInfo } from '../type'
import { fireEvent, render, screen } from '@testing-library/react'
import { useKeyPress } from 'ahooks'
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { Mock } from 'vitest'
import type { Mock } from 'vite-plus/test'
import { fireEvent, render, screen, waitFor } from '@testing-library/react'
import * as React from 'react'
import { useAppContext } from '@/context/app-context'
Expand Down
2 changes: 1 addition & 1 deletion web/app/components/billing/pricing/plans/index.spec.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { Mock } from 'vitest'
import type { Mock } from 'vite-plus/test'
import type { UsagePlanInfo } from '../../type'
import { render, screen } from '@testing-library/react'
import * as React from 'react'
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { MockedFunction } from 'vitest'
import type { MockedFunction } from 'vite-plus/test'
import { fireEvent, render, screen } from '@testing-library/react'
import * as React from 'react'
import useTheme from '@/hooks/use-theme'
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { Mock } from 'vitest'
import type { Mock } from 'vite-plus/test'
import { fireEvent, render, screen } from '@testing-library/react'
import * as React from 'react'
import { useAppContext } from '@/context/app-context'
Expand Down
2 changes: 1 addition & 1 deletion web/app/components/billing/priority-label/index.spec.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { Mock } from 'vitest'
import type { Mock } from 'vite-plus/test'
import { fireEvent, render, screen } from '@testing-library/react'
import { createMockPlan } from '@/__mocks__/provider-context'
import { useProviderContext } from '@/context/provider-context'
Expand Down
2 changes: 1 addition & 1 deletion web/app/components/billing/upgrade-btn/index.spec.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { Mock } from 'vitest'
import type { Mock } from 'vite-plus/test'
import { render, screen, waitFor } from '@testing-library/react'
import userEvent from '@testing-library/user-event'
import UpgradeBtn from './index'
Expand Down
2 changes: 1 addition & 1 deletion web/app/components/custom/custom-page/index.spec.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { Mock } from 'vitest'
import type { Mock } from 'vite-plus/test'
import { render, screen } from '@testing-library/react'
import userEvent from '@testing-library/user-event'
import * as React from 'react'
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { fireEvent, render, screen, waitFor } from '@testing-library/react'
import { beforeEach, describe, expect, it, vi } from 'vitest'
import { beforeEach, describe, expect, it, vi } from 'vite-plus/test'
import { getImageUploadErrorMessage, imageUpload } from '@/app/components/base/image-uploader/utils'
import { useToastContext } from '@/app/components/base/toast'
import { Plan } from '@/app/components/billing/type'
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { MockedFunction } from 'vitest'
import type { MockedFunction } from 'vite-plus/test'
import { fireEvent, render, screen, waitFor } from '@testing-library/react'
import * as React from 'react'
import { createEmptyDataset } from '@/service/datasets'
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { MockedFunction } from 'vitest'
import type { MockedFunction } from 'vite-plus/test'
import type { CustomFile as File } from '@/models/datasets'
import { act, fireEvent, render, screen, waitFor } from '@testing-library/react'
import { fetchFilePreview } from '@/service/common'
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { MockedFunction } from 'vitest'
import type { MockedFunction } from 'vite-plus/test'
import type { NotionPage } from '@/models/common'
import { act, fireEvent, render, screen, waitFor } from '@testing-library/react'
import { fetchNotionPagePreview } from '@/service/datasets'
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { MockInstance } from 'vitest'
import type { MockInstance } from 'vite-plus/test'
import { act, fireEvent, render, screen, waitFor } from '@testing-library/react'
import StopEmbeddingModal from './index'

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { Mock } from 'vitest'
import type { Mock } from 'vite-plus/test'
import type { CrawlOptions, CrawlResultItem } from '@/models/datasets'
import { fireEvent, render, screen, waitFor } from '@testing-library/react'
import userEvent from '@testing-library/user-event'
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { Mock } from 'vitest'
import type { Mock } from 'vite-plus/test'
import type { CrawlOptions, CrawlResultItem } from '@/models/datasets'
import { fireEvent, render, screen, waitFor } from '@testing-library/react'
import userEvent from '@testing-library/user-event'
Expand Down
Loading