diff --git a/web/app/(shareLayout)/webapp-signin/components/__tests__/mail-and-password-auth.spec.tsx b/web/app/(shareLayout)/webapp-signin/components/__tests__/mail-and-password-auth.spec.tsx index 5dda7a0cceb..4c39b09f9f3 100644 --- a/web/app/(shareLayout)/webapp-signin/components/__tests__/mail-and-password-auth.spec.tsx +++ b/web/app/(shareLayout)/webapp-signin/components/__tests__/mail-and-password-auth.spec.tsx @@ -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, + }, + }) }) }) diff --git a/web/app/(shareLayout)/webapp-signin/components/mail-and-password-auth.tsx b/web/app/(shareLayout)/webapp-signin/components/mail-and-password-auth.tsx index 5bd56a71024..0c741a89a12 100644 --- a/web/app/(shareLayout)/webapp-signin/components/mail-and-password-auth.tsx +++ b/web/app/(shareLayout)/webapp-signin/components/mail-and-password-auth.tsx @@ -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, } diff --git a/web/app/components/header/account-setting/preference-page/__tests__/index.spec.tsx b/web/app/components/header/account-setting/preference-page/__tests__/index.spec.tsx index 10e966091bf..028ab895c2d 100644 --- a/web/app/components/header/account-setting/preference-page/__tests__/index.spec.tsx +++ b/web/app/components/header/account-setting/preference-page/__tests__/index.spec.tsx @@ -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 => ({ @@ -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) diff --git a/web/app/components/header/account-setting/preference-page/index.tsx b/web/app/components/header/account-setting/preference-page/index.tsx index 3392578f77b..f1690f0a773 100644 --- a/web/app/components/header/account-setting/preference-page/index.tsx +++ b/web/app/components/header/account-setting/preference-page/index.tsx @@ -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) diff --git a/web/app/signin/components/mail-and-password-auth.tsx b/web/app/signin/components/mail-and-password-auth.tsx index 22ebfe757aa..e0065482830 100644 --- a/web/app/signin/components/mail-and-password-auth.tsx +++ b/web/app/signin/components/mail-and-password-auth.tsx @@ -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) diff --git a/web/service/client.spec.ts b/web/service/client.spec.ts index 295992f5819..d07362aba49 100644 --- a/web/service/client.spec.ts +++ b/web/service/client.spec.ts @@ -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', diff --git a/web/service/client.ts b/web/service/client.ts index ab33773c830..bf5075a6232 100644 --- a/web/service/client.ts +++ b/web/service/client.ts @@ -459,8 +459,8 @@ export const consoleQuery: RouterUtils = createTanstackQue }, }, }, - timezone: { - post: { + profile: { + patch: { mutationOptions: { onSuccess: async (_data, _variables, _onMutateResult, context) => { await context.client.invalidateQueries({