mirror of
https://github.com/langgenius/dify.git
synced 2026-07-19 16:44:00 -04:00
Merge branch 'main' into tp
This commit is contained in:
@@ -3,14 +3,17 @@ import type { AppContextStateMockState } from '@/__tests__/utils/mock-app-contex
|
||||
import type { ModalContextState } from '@/context/modal-context'
|
||||
import type { ProviderContextState } from '@/context/provider-context'
|
||||
import { fireEvent, screen, waitFor } from '@testing-library/react'
|
||||
import userEvent from '@testing-library/user-event'
|
||||
import { renderToString } from 'react-dom/server'
|
||||
import { renderWithSystemFeatures } from '@/__tests__/utils/mock-system-features'
|
||||
import { Plan } from '@/app/components/billing/type'
|
||||
import { ACCOUNT_SETTING_TAB } from '@/app/components/header/account-setting/constants'
|
||||
import AccountSection from '@/app/components/main-nav/components/account-section'
|
||||
import { useModalContext } from '@/context/modal-context'
|
||||
import { useProviderContext } from '@/context/provider-context'
|
||||
import { useRouter } from '@/next/navigation'
|
||||
import { useLogout } from '@/service/use-common'
|
||||
import { createAccountProfileQueryClient } from '@/test/account-profile-query'
|
||||
import AppSelector from '../index'
|
||||
|
||||
type DeepPartial<T> =
|
||||
@@ -147,15 +150,17 @@ vi.mock('@/config', async (importOriginal) => {
|
||||
})
|
||||
vi.mock('@/env', () => mockEnv)
|
||||
|
||||
const baseUserProfile = {
|
||||
id: '1',
|
||||
name: 'Test User',
|
||||
email: 'test@example.com',
|
||||
avatar: '',
|
||||
avatar_url: 'avatar.png',
|
||||
is_password_set: false,
|
||||
}
|
||||
|
||||
const baseAppContextValue: AppContextStateMockState = {
|
||||
userProfile: {
|
||||
id: '1',
|
||||
name: 'Test User',
|
||||
email: 'test@example.com',
|
||||
avatar: '',
|
||||
avatar_url: 'avatar.png',
|
||||
is_password_set: false,
|
||||
},
|
||||
userProfile: baseUserProfile,
|
||||
mutateUserProfile: vi.fn(),
|
||||
currentWorkspace: {
|
||||
id: '1',
|
||||
@@ -201,7 +206,12 @@ describe('AccountDropdown', () => {
|
||||
ui: React.ReactElement,
|
||||
options: { systemFeatures?: DeepPartial<GetSystemFeaturesResponse> } = {},
|
||||
) => {
|
||||
const queryClient = createAccountProfileQueryClient({
|
||||
...baseUserProfile,
|
||||
...(mockAppContextState.current?.userProfile ?? {}),
|
||||
})
|
||||
return renderWithSystemFeatures(ui, {
|
||||
queryClient,
|
||||
systemFeatures: options.systemFeatures ?? { branding: { enabled: false } },
|
||||
})
|
||||
}
|
||||
@@ -238,6 +248,29 @@ describe('AccountDropdown', () => {
|
||||
})
|
||||
|
||||
describe('Rendering', () => {
|
||||
it('should show the signed-in account in the main navigation menu', async () => {
|
||||
const user = userEvent.setup()
|
||||
const queryClient = createAccountProfileQueryClient({
|
||||
id: 'current-user',
|
||||
name: 'Current User',
|
||||
email: 'current@example.com',
|
||||
avatar_url: 'current-avatar.png',
|
||||
})
|
||||
|
||||
renderWithSystemFeatures(<AccountSection />, {
|
||||
queryClient,
|
||||
systemFeatures: { branding: { enabled: false } },
|
||||
})
|
||||
|
||||
expect(screen.getByText('Current User')).toBeInTheDocument()
|
||||
expect(screen.queryByText('Test User')).not.toBeInTheDocument()
|
||||
|
||||
await user.click(screen.getByRole('button', { name: 'common.account.account' }))
|
||||
|
||||
expect(await screen.findByText('current@example.com')).toBeInTheDocument()
|
||||
expect(screen.queryByText('test@example.com')).not.toBeInTheDocument()
|
||||
})
|
||||
|
||||
it('should render user profile correctly', () => {
|
||||
// Act
|
||||
renderWithRouter(<AppSelector />)
|
||||
|
||||
@@ -16,14 +16,14 @@ import {
|
||||
DropdownMenuSubContent,
|
||||
DropdownMenuSubTrigger,
|
||||
} from '@langgenius/dify-ui/dropdown-menu'
|
||||
import { useAtomValue } from 'jotai'
|
||||
import { useSuspenseQuery } from '@tanstack/react-query'
|
||||
import { useTheme } from 'next-themes'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import PremiumBadge from '@/app/components/base/premium-badge'
|
||||
import { ACCOUNT_SETTING_TAB } from '@/app/components/header/account-setting/constants'
|
||||
import { userProfileAtom } from '@/context/account-state'
|
||||
import { useModalContext } from '@/context/modal-context'
|
||||
import { useProviderContext } from '@/context/provider-context'
|
||||
import { userProfileQueryOptions } from '@/features/account-profile/client'
|
||||
import Link from '@/next/link'
|
||||
import { ExternalLinkIndicator, MenuItemContent } from './menu-item-content'
|
||||
|
||||
@@ -102,7 +102,10 @@ type MainNavMenuContentProps = {
|
||||
|
||||
export function MainNavMenuContent({ onLogout }: MainNavMenuContentProps) {
|
||||
const { t } = useTranslation()
|
||||
const userProfile = useAtomValue(userProfileAtom)
|
||||
const { data: userProfile } = useSuspenseQuery({
|
||||
...userProfileQueryOptions(),
|
||||
select: (data) => data.profile,
|
||||
})
|
||||
const { isEducationAccount } = useProviderContext()
|
||||
const { setShowAccountSettingModal } = useModalContext()
|
||||
|
||||
|
||||
@@ -19,6 +19,7 @@ import { gotoAnythingDialogHandle } from '@/app/components/goto-anything/dialog-
|
||||
import { ACCOUNT_SETTING_TAB } from '@/app/components/header/account-setting/constants'
|
||||
import { useModalContext } from '@/context/modal-context'
|
||||
import { useProviderContext } from '@/context/provider-context'
|
||||
import { userProfileQueryOptions } from '@/features/account-profile/client'
|
||||
import { usePathname, useRouter } from '@/next/navigation'
|
||||
import { consoleQuery } from '@/service/client'
|
||||
import { useGetInstalledApps, useUninstallApp, useUpdateAppPinStatus } from '@/service/use-explore'
|
||||
@@ -211,15 +212,17 @@ const createInstalledApp = (overrides: Partial<InstalledApp> = {}): InstalledApp
|
||||
},
|
||||
})
|
||||
|
||||
const mainNavUserProfile = {
|
||||
id: 'user-1',
|
||||
name: 'Evan Z',
|
||||
email: 'evan@example.com',
|
||||
avatar: '',
|
||||
avatar_url: '',
|
||||
is_password_set: true,
|
||||
}
|
||||
|
||||
const appContextValue: AppContextStateMockState = {
|
||||
userProfile: {
|
||||
id: 'user-1',
|
||||
name: 'Evan Z',
|
||||
email: 'evan@example.com',
|
||||
avatar: '',
|
||||
avatar_url: '',
|
||||
is_password_set: true,
|
||||
},
|
||||
userProfile: mainNavUserProfile,
|
||||
mutateUserProfile: vi.fn(),
|
||||
currentWorkspace: {
|
||||
id: 'workspace-1',
|
||||
@@ -273,6 +276,16 @@ const renderMainNav = (
|
||||
consoleQuery.workspaces.current.post.queryKey(),
|
||||
currentAppContext.currentWorkspace as ICurrentWorkspace,
|
||||
)
|
||||
queryClient.setQueryData(userProfileQueryOptions().queryKey, {
|
||||
profile: {
|
||||
...mainNavUserProfile,
|
||||
...(currentAppContext.userProfile ?? {}),
|
||||
},
|
||||
meta: {
|
||||
currentVersion: null,
|
||||
currentEnv: null,
|
||||
},
|
||||
})
|
||||
queryClient.setQueryData(consoleQuery.workspaces.get.queryKey(), { workspaces: mockWorkspaces })
|
||||
const resolvedSystemFeatures = {
|
||||
...defaultMainNavSystemFeatures,
|
||||
|
||||
@@ -2,16 +2,19 @@
|
||||
|
||||
import { Avatar } from '@langgenius/dify-ui/avatar'
|
||||
import { cn } from '@langgenius/dify-ui/cn'
|
||||
import { useAtomValue } from 'jotai'
|
||||
import { useSuspenseQuery } from '@tanstack/react-query'
|
||||
import AccountDropdown from '@/app/components/header/account-dropdown'
|
||||
import { userProfileAtom } from '@/context/account-state'
|
||||
import { userProfileQueryOptions } from '@/features/account-profile/client'
|
||||
|
||||
type AccountSectionProps = {
|
||||
compact?: boolean
|
||||
}
|
||||
|
||||
const AccountSection = ({ compact = false }: AccountSectionProps) => {
|
||||
const userProfile = useAtomValue(userProfileAtom)
|
||||
const { data: userProfile } = useSuspenseQuery({
|
||||
...userProfileQueryOptions(),
|
||||
select: (data) => data.profile,
|
||||
})
|
||||
|
||||
return (
|
||||
<AccountDropdown
|
||||
|
||||
Reference in New Issue
Block a user