mirror of
https://github.com/langgenius/dify.git
synced 2026-09-05 08:48:10 +08:00
refactor(web): align account preference requests with API contracts (#41748)
This commit is contained in:
parent
24f9f07752
commit
8c98e3fad5
@ -70,7 +70,14 @@ describe('MailAndPasswordAuth', () => {
|
||||
await user.type(passwordInput, 'strong-password{Enter}')
|
||||
|
||||
await waitFor(() => {
|
||||
expect(webAppLoginMock).toHaveBeenCalledTimes(1)
|
||||
expect(webAppLoginMock).toHaveBeenCalledWith({
|
||||
url: '/login',
|
||||
body: {
|
||||
email: 'user@example.com',
|
||||
password: expect.any(String),
|
||||
remember_me: true,
|
||||
},
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
@ -10,7 +10,6 @@ import { useEffect, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { resolveWebAppLoginRedirect } from '@/app/(shareLayout)/webapp-signin/login-redirect'
|
||||
import { emailRegex } from '@/config'
|
||||
import { useLocale } from '@/context/i18n'
|
||||
import { useWebAppStore } from '@/context/web-app-context'
|
||||
import Link from '@/next/link'
|
||||
import { useRouter, useSearchParams } from '@/next/navigation'
|
||||
@ -28,7 +27,6 @@ type MailAndPasswordAuthProps = {
|
||||
|
||||
export default function MailAndPasswordAuth({ isEmailSetup }: MailAndPasswordAuthProps) {
|
||||
const { t } = useTranslation()
|
||||
const locale = useLocale()
|
||||
const router = useRouter()
|
||||
const searchParams = useSearchParams()
|
||||
const [showPassword, setShowPassword] = useState(false)
|
||||
@ -69,7 +67,6 @@ export default function MailAndPasswordAuth({ isEmailSetup }: MailAndPasswordAut
|
||||
const loginData = {
|
||||
email,
|
||||
password: encryptPassword(password),
|
||||
language: locale,
|
||||
remember_me: true,
|
||||
}
|
||||
|
||||
|
||||
@ -4,7 +4,6 @@ import { QueryClientProvider } from '@tanstack/react-query'
|
||||
import { screen, waitFor, within } from '@testing-library/react'
|
||||
import userEvent from '@testing-library/user-event'
|
||||
import { languages } from '@/i18n-config/language'
|
||||
import { updateUserProfile } from '@/service/common'
|
||||
import { createAccountProfileQueryClient } from '@/test/console/account-profile'
|
||||
import { render } from '@/test/console/render'
|
||||
import { timezones } from '@/utils/timezone'
|
||||
@ -30,16 +29,10 @@ vi.mock('@/context/i18n', () => ({
|
||||
useLocale: () => mockLocale,
|
||||
}))
|
||||
|
||||
vi.mock('@/service/common', () => ({
|
||||
updateUserProfile: vi.fn(),
|
||||
}))
|
||||
|
||||
vi.mock('@/i18n-config', () => ({
|
||||
setLocaleOnClient: vi.fn(),
|
||||
}))
|
||||
|
||||
const updateUserProfileMock = vi.mocked(updateUserProfile)
|
||||
|
||||
const createUserProfile = (
|
||||
overrides: Partial<GetAccountProfileResponse> = {},
|
||||
): GetAccountProfileResponse => ({
|
||||
@ -149,7 +142,6 @@ describe('PreferencePage - Interactions', () => {
|
||||
it('should show success toast when language updates', async () => {
|
||||
const chinese = getLanguageOption('zh-Hans')
|
||||
mockUserProfile = createUserProfile({ interface_language: 'en-US' })
|
||||
updateUserProfileMock.mockResolvedValueOnce({ result: 'success' })
|
||||
|
||||
renderPage()
|
||||
|
||||
@ -157,16 +149,17 @@ describe('PreferencePage - Interactions', () => {
|
||||
|
||||
expect(await screen.findByText('common.actionMsg.modifiedSuccessfully')).toBeInTheDocument()
|
||||
await waitFor(() => {
|
||||
expect(updateUserProfileMock).toHaveBeenCalledWith({
|
||||
url: '/account/interface-language',
|
||||
body: { interface_language: chinese.value },
|
||||
})
|
||||
expect(mockRequest).toHaveBeenCalled()
|
||||
})
|
||||
expect(mockRequest.mock.calls[0]?.[0]).toEqual(expect.stringContaining('/account/profile'))
|
||||
const request = mockRequest.mock.calls[0]?.[2]?.request as Request
|
||||
expect(request.method).toBe('PATCH')
|
||||
await expect(request.json()).resolves.toEqual({ interface_language: chinese.value })
|
||||
})
|
||||
|
||||
it('should show error toast when language update fails', async () => {
|
||||
const chinese = getLanguageOption('zh-Hans')
|
||||
updateUserProfileMock.mockRejectedValueOnce(new Error('Update failed'))
|
||||
mockRequest.mockRejectedValueOnce(new Error('Update failed'))
|
||||
|
||||
renderPage()
|
||||
|
||||
@ -186,9 +179,9 @@ describe('PreferencePage - Interactions', () => {
|
||||
await waitFor(() => {
|
||||
expect(mockRequest).toHaveBeenCalled()
|
||||
})
|
||||
expect(mockRequest.mock.calls[0]?.[0]).toEqual(expect.stringContaining('/account/timezone'))
|
||||
expect(mockRequest.mock.calls[0]?.[0]).toEqual(expect.stringContaining('/account/profile'))
|
||||
const request = mockRequest.mock.calls[0]?.[2]?.request as Request
|
||||
expect(request.method).toBe('POST')
|
||||
expect(request.method).toBe('PATCH')
|
||||
await expect(request.json()).resolves.toEqual({ timezone: midwayTimezone.value })
|
||||
}, 15000)
|
||||
|
||||
|
||||
@ -19,7 +19,6 @@ import { setLocaleOnClient } from '@/i18n-config'
|
||||
import { languages } from '@/i18n-config/language'
|
||||
import { useRouter } from '@/next/navigation'
|
||||
import { consoleQuery } from '@/service/client'
|
||||
import { updateUserProfile } from '@/service/common'
|
||||
import { timezones } from '@/utils/timezone'
|
||||
|
||||
type SelectOption = {
|
||||
@ -48,7 +47,7 @@ export default function PreferencePage() {
|
||||
...userProfileQueryOptions(),
|
||||
select: (data) => data.profile,
|
||||
})
|
||||
const updateTimezone = useMutation(consoleQuery.account.timezone.post.mutationOptions())
|
||||
const updateProfile = useMutation(consoleQuery.account.profile.patch.mutationOptions())
|
||||
const [editing, setEditing] = useState(false)
|
||||
const { t } = useTranslation()
|
||||
const router = useRouter()
|
||||
@ -68,11 +67,9 @@ export default function PreferencePage() {
|
||||
if (isThemeOption(item.value)) setTheme(item.value)
|
||||
}
|
||||
const handleSelectLanguage = async (item: SelectOption) => {
|
||||
const url = '/account/interface-language'
|
||||
const bodyKey = 'interface_language'
|
||||
setEditing(true)
|
||||
try {
|
||||
await updateUserProfile({ url, body: { [bodyKey]: item.value } })
|
||||
await updateProfile.mutateAsync({ body: { interface_language: item.value } })
|
||||
toast.success(t(($) => $['actionMsg.modifiedSuccessfully'], { ns: 'common' }))
|
||||
setLocaleOnClient(item.value.toString() as Locale, false)
|
||||
router.refresh()
|
||||
@ -85,7 +82,7 @@ export default function PreferencePage() {
|
||||
const handleSelectTimezone = async (item: TimezoneOption) => {
|
||||
setEditing(true)
|
||||
try {
|
||||
await updateTimezone.mutateAsync({ body: { timezone: item.value } })
|
||||
await updateProfile.mutateAsync({ body: { timezone: item.value } })
|
||||
toast.success(t(($) => $['actionMsg.modifiedSuccessfully'], { ns: 'common' }))
|
||||
} catch (e) {
|
||||
toast.error((e as Error).message)
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
import type { LoginPayload } from '@dify/contracts/api/console/login/types.gen'
|
||||
import { Button } from '@langgenius/dify-ui/button'
|
||||
import { Field, FieldError, FieldLabel } from '@langgenius/dify-ui/field'
|
||||
import { Form } from '@langgenius/dify-ui/form'
|
||||
@ -10,7 +11,6 @@ import { useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { trackEvent } from '@/app/components/base/amplitude'
|
||||
import { emailRegex } from '@/config'
|
||||
import { useLocale } from '@/context/i18n'
|
||||
import Link from '@/next/link'
|
||||
import { useRouter, useSearchParams } from '@/next/navigation'
|
||||
import { consoleQuery } from '@/service/client'
|
||||
@ -26,21 +26,12 @@ type MailAndPasswordAuthProps = {
|
||||
isEmailSetup: boolean
|
||||
}
|
||||
|
||||
type LoginRequestBody = {
|
||||
email: string
|
||||
password: string
|
||||
language: string
|
||||
remember_me: boolean
|
||||
invite_token?: string
|
||||
}
|
||||
|
||||
function hasErrorCode(error: unknown, code: string) {
|
||||
return typeof error === 'object' && error !== null && 'code' in error && error.code === code
|
||||
}
|
||||
|
||||
export default function MailAndPasswordAuth({ isInvite, isEmailSetup }: MailAndPasswordAuthProps) {
|
||||
const { t } = useTranslation()
|
||||
const locale = useLocale()
|
||||
const router = useRouter()
|
||||
const queryClient = useQueryClient()
|
||||
const searchParams = useSearchParams()
|
||||
@ -54,10 +45,9 @@ export default function MailAndPasswordAuth({ isInvite, isEmailSetup }: MailAndP
|
||||
if (isLoading) return
|
||||
try {
|
||||
setIsLoading(true)
|
||||
const loginData: LoginRequestBody = {
|
||||
const loginData: LoginPayload = {
|
||||
email,
|
||||
password: encryptPassword(password),
|
||||
language: locale,
|
||||
remember_me: true,
|
||||
}
|
||||
if (isInvite)
|
||||
|
||||
@ -636,12 +636,12 @@ describe('consoleQuery education defaults', () => {
|
||||
})
|
||||
|
||||
describe('consoleQuery account profile mutation defaults', () => {
|
||||
it('should invalidate the account profile after a timezone update', async () => {
|
||||
it('should invalidate the account profile after a profile update', async () => {
|
||||
const consoleQuery = await loadConsoleQuery()
|
||||
const queryClient = new QueryClient()
|
||||
const invalidateQueries = vi.spyOn(queryClient, 'invalidateQueries')
|
||||
|
||||
await consoleQuery.account.timezone.post.mutationOptions().onSuccess?.(
|
||||
await consoleQuery.account.profile.patch.mutationOptions().onSuccess?.(
|
||||
{
|
||||
id: 'user-1',
|
||||
name: 'Test User',
|
||||
|
||||
@ -459,8 +459,8 @@ export const consoleQuery: RouterUtils<typeof consoleClient> = createTanstackQue
|
||||
},
|
||||
},
|
||||
},
|
||||
timezone: {
|
||||
post: {
|
||||
profile: {
|
||||
patch: {
|
||||
mutationOptions: {
|
||||
onSuccess: async (_data, _variables, _onMutateResult, context) => {
|
||||
await context.client.invalidateQueries({
|
||||
|
||||
Loading…
Reference in New Issue
Block a user