mirror of
https://github.com/langgenius/dify.git
synced 2026-09-05 00:31:19 +08:00
fix(web): restore webapp password form submission (#40222)
This commit is contained in:
parent
e7da213f93
commit
908f6ada4e
@ -139,9 +139,6 @@
|
||||
}
|
||||
},
|
||||
"web/app/(shareLayout)/webapp-signin/components/mail-and-password-auth.tsx": {
|
||||
"jsx_a11y/tabindex-no-positive": {
|
||||
"count": 3
|
||||
},
|
||||
"no-restricted-imports": {
|
||||
"count": 1
|
||||
}
|
||||
|
||||
@ -0,0 +1,76 @@
|
||||
import { render, screen, waitFor } from '@testing-library/react'
|
||||
import userEvent from '@testing-library/user-event'
|
||||
import MailAndPasswordAuth from '../mail-and-password-auth'
|
||||
|
||||
const replaceMock = vi.fn()
|
||||
const webAppLoginMock = vi.fn()
|
||||
const fetchAccessTokenMock = vi.fn()
|
||||
const searchParams = new URLSearchParams({
|
||||
redirect_url: encodeURIComponent('/chatbot/test-app'),
|
||||
})
|
||||
|
||||
vi.mock('@/next/navigation', () => ({
|
||||
useRouter: () => ({ replace: replaceMock }),
|
||||
useSearchParams: () => searchParams,
|
||||
}))
|
||||
|
||||
vi.mock('@/context/i18n', () => ({
|
||||
useLocale: () => 'en-US',
|
||||
}))
|
||||
|
||||
vi.mock('@/context/web-app-context', () => ({
|
||||
useWebAppStore: (selector: (state: { embeddedUserId: string }) => unknown) =>
|
||||
selector({ embeddedUserId: 'embedded-user-99' }),
|
||||
}))
|
||||
|
||||
vi.mock('@/service/common', () => ({
|
||||
webAppLogin: (...args: unknown[]) => webAppLoginMock(...args),
|
||||
}))
|
||||
|
||||
vi.mock('@/service/share', () => ({
|
||||
fetchAccessToken: (...args: unknown[]) => fetchAccessTokenMock(...args),
|
||||
}))
|
||||
|
||||
vi.mock('@/service/webapp-auth', () => ({
|
||||
setWebAppAccessToken: vi.fn(),
|
||||
setWebAppPassport: vi.fn(),
|
||||
}))
|
||||
|
||||
describe('MailAndPasswordAuth', () => {
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks()
|
||||
webAppLoginMock.mockResolvedValue({
|
||||
result: 'success',
|
||||
data: { access_token: 'login-token' },
|
||||
})
|
||||
fetchAccessTokenMock.mockResolvedValue({ access_token: 'passport-token' })
|
||||
})
|
||||
|
||||
it('submits from the password field through the native form', async () => {
|
||||
const user = userEvent.setup()
|
||||
render(<MailAndPasswordAuth isEmailSetup />)
|
||||
|
||||
const emailInput = screen.getByRole('textbox', { name: 'login.email' })
|
||||
const passwordInput = screen.getByLabelText(/login\.password/)
|
||||
const submitButton = screen.getByRole('button', { name: 'login.signBtn' })
|
||||
|
||||
expect(emailInput).toHaveAttribute('name', 'email')
|
||||
expect(emailInput).toHaveAttribute('autocomplete', 'email')
|
||||
expect(passwordInput).toHaveAttribute('name', 'password')
|
||||
expect(passwordInput).toHaveAttribute('autocomplete', 'current-password')
|
||||
expect(submitButton).toHaveAttribute('type', 'submit')
|
||||
|
||||
await user.tab()
|
||||
expect(emailInput).toHaveFocus()
|
||||
await user.type(emailInput, 'user@example.com')
|
||||
await user.tab()
|
||||
expect(screen.getByRole('link', { name: 'login.forget' })).toHaveFocus()
|
||||
await user.tab()
|
||||
expect(passwordInput).toHaveFocus()
|
||||
await user.type(passwordInput, 'strong-password{Enter}')
|
||||
|
||||
await waitFor(() => {
|
||||
expect(webAppLoginMock).toHaveBeenCalledTimes(1)
|
||||
})
|
||||
})
|
||||
})
|
||||
@ -1,7 +1,6 @@
|
||||
'use client'
|
||||
import { Button } from '@langgenius/dify-ui/button'
|
||||
import { toast } from '@langgenius/dify-ui/toast'
|
||||
import { noop } from 'es-toolkit/function'
|
||||
import { useEffect, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { resolveWebAppLoginRedirect } from '@/app/(shareLayout)/webapp-signin/login-redirect'
|
||||
@ -101,20 +100,26 @@ export default function MailAndPasswordAuth({ isEmailSetup }: MailAndPasswordAut
|
||||
}
|
||||
|
||||
return (
|
||||
<form onSubmit={noop}>
|
||||
<form
|
||||
onSubmit={(event) => {
|
||||
event.preventDefault()
|
||||
void handleEmailPasswordLogin()
|
||||
}}
|
||||
>
|
||||
<div className="mb-3">
|
||||
<label htmlFor="email" className="my-2 system-md-semibold text-text-secondary">
|
||||
{t(($) => $.email, { ns: 'login' })}
|
||||
</label>
|
||||
<div className="mt-1">
|
||||
<Input
|
||||
name="email"
|
||||
value={email}
|
||||
onChange={(e) => setEmail(e.target.value)}
|
||||
id="email"
|
||||
type="email"
|
||||
autoComplete="email"
|
||||
spellCheck={false}
|
||||
placeholder={t(($) => $.emailPlaceholder, { ns: 'login' }) || ''}
|
||||
tabIndex={1}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@ -135,16 +140,14 @@ export default function MailAndPasswordAuth({ isEmailSetup }: MailAndPasswordAut
|
||||
</label>
|
||||
<div className="relative mt-1">
|
||||
<Input
|
||||
name="password"
|
||||
value={password}
|
||||
onChange={(e) => setPassword(e.target.value)}
|
||||
id="password"
|
||||
onKeyDown={(e) => {
|
||||
if (e.key === 'Enter') handleEmailPasswordLogin()
|
||||
}}
|
||||
type={showPassword ? 'text' : 'password'}
|
||||
autoComplete="current-password"
|
||||
spellCheck={false}
|
||||
placeholder={t(($) => $.passwordPlaceholder, { ns: 'login' }) || ''}
|
||||
tabIndex={2}
|
||||
/>
|
||||
<div className="absolute inset-y-0 right-0 flex items-center">
|
||||
<Button type="button" variant="ghost" onClick={() => setShowPassword(!showPassword)}>
|
||||
@ -156,9 +159,8 @@ export default function MailAndPasswordAuth({ isEmailSetup }: MailAndPasswordAut
|
||||
|
||||
<div className="mb-2">
|
||||
<Button
|
||||
tabIndex={2}
|
||||
type="submit"
|
||||
variant="primary"
|
||||
onClick={handleEmailPasswordLogin}
|
||||
disabled={isLoading || !email || !password}
|
||||
className="w-full"
|
||||
>
|
||||
|
||||
Loading…
Reference in New Issue
Block a user