While adding test for am facing this particular issue can someone please help me to resolve this issue , just want to know how to set queryclient inside register page it self
Register.jsx---主页面,该主页面是尝试对该进行dom测试的用户注册
/* eslint-disable no-console */
import React, { useState, useEffect } from 'react';
import { Form, Input, Button, Checkbox, Divider } from 'antd';
import {
UserOutlined,
LockOutlined,
MailOutlined,
} from '@ant-design/icons';
import { Link, Redirect } from 'react-router-dom';
import { useMutation } from 'react-query';
import { withTranslation } from 'react-i18next';
import { func } from 'prop-types';
import { registerUser } from '../../api/auth.api';
const Register = ({ t }) => {
const [form] = Form.useForm();
const [isMailInUse, setIsMailInUse] = useState(false);
const {
mutate,
isSuccess,
isError,
isLoading,
error,
} = useMutation(registerUser);
useEffect(() => {
if (isError && error.response.status === 409) {
setIsMailInUse(true);
form.validateFields();
}
}, [isError, error, form]);
const onFinish = (inputs) => {
// console.log('Received values of form: ', inputs);
mutate(inputs);
};
if (isSuccess) {
return <Redirect to="/Dashboard" />;
}
return (
<Form
form={form}
name="normal_login"
className="login-form"
initialValues={{
remember: true,
}}
onFinish={onFinish}
>
<Form.Item
name="fullname"
data-testid="fullname"
rules={[
{
required: true,
message: t('form_errors.enter_full_name'),
},
{
min: 4,
message: t('form_errors.name_atleast_four_chars'),
},
{
max: 20,
message: t('form_errors.name_max_twenty_chars'),
},
{
pattern: new RegExp(
/^[A-Za-zs]{1,}[.]{0,1}[A-Za-zs]{0,}$/,
),
message: t('form_errors.valid_name'),
},
]}
>
<Input
type="text"
data-testid="username"
prefix={<UserOutlined className="site-form-item-icon" />}
placeholder={t('name')}
/>
</Form.Item>
<Form.Item
name="email"
rules={[
{
required: true,
message: t('form_errors.email_required'),
},
{
pattern: new RegExp(
/^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:.[a-zA-Z0-9-]+)*$/,
),
message: t('form_errors.valid_email_id'),
},
{
validator: () =>
!isMailInUse
? Promise.resolve()
: Promise.reject(new Error(t('errors.email_in_use'))),
},
]}
>
<Input
type="email"
onChange={() =>
isMailInUse ? setIsMailInUse(false) : null
}
prefix={<MailOutlined className="site-form-item-icon" />}
placeholder={t('email')}
/>
</Form.Item>
<Form.Item
name="password"
rules={[
{
required: true,
message: t('form_errors.password_not_found'),
},
{
min: 8,
message: t('form_errors.password_min_eight_chars'),
},
]}
hasFeedback
>
<Input.Password
prefix={<LockOutlined className="site-form-item-icon" />}
type="password"
autoComplete="new-password"
placeholder={t('password')}
/>
</Form.Item>
<Form.Item
name="confirmpassword"
dependencies={['password']}
rules={[
{
required: true,
message: t('form_errors.password_confirmation'),
},
({ getFieldValue }) => ({
validator(_, value) {
if (!value || getFieldValue('password') === value) {
return Promise.resolve();
}
return Promise.reject(
new Error(t('errors.passwords_do_not_match')),
);
},
}),
]}
hasFeedback
>
<Input.Password
prefix={<LockOutlined className="site-form-item-icon" />}
type="password"
autoComplete="new-password"
placeholder={t('tasks.confirm_password')}
/>
</Form.Item>
<Form.Item>
<Form.Item name="remember" valuePropName="checked" noStyle>
<Checkbox>{t('tasks.remember_me')}</Checkbox>
</Form.Item>
<Link
className="login-form-forgot"
style={{ float: 'right' }}
to="#/something"
>
{t('forgot_password')}
</Link>
</Form.Item>
<Form.Item>
<Button
type="primary"
loading={isLoading}
htmlType="submit"
className="login-form-button"
>
{t('tasks.register')}
</Button>
{'n'}
Or
{'n'}
<Button
type="ghost"
htmlType="submit"
className="login-form-button"
onClick={() =>
window.open(
'http://api.realdev.in/oauth/redirect/github',
'_self',
)
}
>
{t('tasks.login_with_github')}
</Button>
<Divider plain>OR</Divider>
<Link to="/login"> {t('tasks.login_now')}</Link>
</Form.Item>
</Form>
);
};
Register.propTypes = {
t: func.isRequired,
};
export default withTranslation()(Register);
--在页面呈现中加载的主要组件,在这里我添加了queryclient用于reactqueryApp.jsx
import React, { useEffect } from 'react';
import { withTranslation } from 'react-i18next';
import { func, shape } from 'prop-types';
import { Row, Col, Typography, Tabs } from 'antd';
import '../css/form.css';
import {
BrowserRouter as Router,
Switch,
Route,
} from 'react-router-dom';
import { Helmet } from 'react-helmet';
import { QueryClientProvider, QueryClient } from 'react-query';
import { ReactQueryDevtools } from 'react-query/devtools';
import Login from './Authentication/Login';
import Register from './Authentication/Register';
import OAuth from './Authentication/OAuth';
import GithubAuth from './Authentication/GithubAuth';
import Dashboard from './Authentication/Dashboard';
import Error from './Authentication/Error';
const { TabPane } = Tabs;
// import StoreDemo from './StoreDemo';
//
const queryClient = new QueryClient();
const App = ({ t, i18n }) => {
useEffect(() => {
i18n.changeLanguage('en');
}, [i18n]);
const { Text, Title } = Typography;
return (
<>
<QueryClientProvider client={queryClient}>
<Router>
<Switch>
<Route path="/oauth">
<OAuth />
</Route>
<Route path="/projects">
<h2>Projects</h2>
</Route>
<Route path="/Dashboard">
<Dashboard />
</Route>
<Route path="/Error">
<Error />
</Route>
<Route
path="/:route"
render={({ match, history }) => {
if (
match.params.route === 'login' ||
match.params.route === 'register'
) {
return (
<>
<div className="form--wrapper">
<Row>
<Col span={24} offset={0}>
<Title className="site--logo">
{t('easy_collab')}
</Title>
<div className="form--container">
<Title level={3}>
{t('tasks.login_to_easycollab')}
</Title>
<Text type="secondary">
{t('tasks.continue_with_email')}
</Text>
<br />
<br />
<Switch>
<>
<Tabs
activeKey={match.params.route}
onChange={(route) => {
history.push(`/${route}`);
}}
>
<TabPane tab="Login" key="login">
<Helmet>
<title>
{t('tasks.login')} •{' '}
{t('easy_collab')}
</title>
</Helmet>
<Login />
</TabPane>
<TabPane
tab="Register"
key="register"
>
<Helmet>
<title>
{t('tasks.register')} •{' '}
{t('easy_collab')}
</title>
</Helmet>
<Register />
</TabPane>
</Tabs>
</>
</Switch>
</div>
</Col>
</Row>
</div>
</>
);
}
return null;
}}
/>
<Route path="/login/github" exact>
<GithubAuth />
</Route>
<Route path="/" exact>
<Helmet>
<title />
{t('home')} • {t('easy_collab')}
</Helmet>
{t('errors.unauthorized_access')}
</Route>
</Switch>
</Router>
<ReactQueryDevtools />
</QueryClientProvider>
</>
);
};
App.propTypes = {
t: func.isRequired,
i18n: shape({ changeLanguage: func }).isRequired,
};
export default withTranslation()(App);
注册.test.jsx
import React from 'react';
import {
render,
fireEvent,
findByText,
} from '@testing-library/react';
import { expect } from 'chai';
import '../i18n/index';
import Register from '../components/Authentication/Register';
import App from '../components/App';
describe('App', () => {
it('renders App component', async () => {
const { getByTestId, container } = render(<Register />);
const usernameEl = getByTestId('username');
// const nameEl = getByTestId('fullname');
fireEvent.change(usernameEl, {
target: {
value: 'po',
},
});
expect(
await findByText(
container,
'Name must be atleast 4 characters',
),
).toBeVisible();
});
});
面向错误
Browser logs:
Error: No QueryClient set, use QueryClientProvider to set one
at useQueryClient (_snowpackpkgcommonQueryClientProvider-dd42f785.js:27:11)
at useMutation (_snowpackpkgreact-query.js:3092:21)
at Register (distcomponentsAuthenticationRegister.js:22:7)
at renderWithHooks (_snowpackpkgcommonindex-163c0f63.js:16160:18)
at mountIndeterminateComponent (_snowpackpkgcommonindex-163c0f63.js:18986:13)
at beginWork (_snowpackpkgcommonindex-163c0f63.js:20224:16)
at HTMLUnknownElement.callCallback (_snowpackpkgcommonindex-163c0f63.js:5123:14)
at Object.invokeGuardedCallbackDev (_snowpackpkgcommonindex-163c0f63.js:5172:16)
at invokeGuardedCallback (_snowpackpkgcommonindex-163c0f63.js:5234:31)
at beginWork$1 (_snowpackpkgcommonindex-163c0f63.js:25128:7)
Error: No QueryClient set, use QueryClientProvider to set one
at useQueryClient (_snowpackpkgcommonQueryClientProvider-dd42f785.js:27:11)
at useMutation (_snowpackpkgreact-query.js:3092:21)
at Register (distcomponentsAuthenticationRegister.js:22:7)
at renderWithHooks (_snowpackpkgcommonindex-163c0f63.js:16160:18)
at mountIndeterminateComponent (_snowpackpkgcommonindex-163c0f63.js:18986:13)
at beginWork (_snowpackpkgcommonindex-163c0f63.js:20224:16)
at HTMLUnknownElement.callCallback (_snowpackpkgcommonindex-163c0f63.js:5123:14)
at Object.invokeGuardedCallbackDev (_snowpackpkgcommonindex-163c0f63.js:5172:16)
at invokeGuardedCallback (_snowpackpkgcommonindex-163c0f63.js:5234:31)
at beginWork$1 (_snowpackpkgcommonindex-163c0f63.js:25128:7)
The above error occurred in the <Register> component:
at Register (http://localhost:8000/dist/components/Authentication/Register.js:13:20)
at withI18nextTranslation(Register) (http://localhost:8000/_snowpack/pkg/react-i18next.js:918:31)
Consider adding an error boundary to your tree to customize error handling behavior.
Visit https://reactjs.org/link/error-boundaries to learn more about error boundaries.
Error: done() called multiple times in test <App renders App component>; in addition, done() received error: Error: No QueryClient set, use QueryClientProvider to set one
at createMultipleDoneError (....D:Opensourceeasy-collab-frontendnode_modules@webtest-runner-mochadistautorun.js:1:242101)
at ....D:Opensourceeasy-collab-frontendnode_modules@webtest-runner-mochadistautorun.js:1:254722
at a (....D:Opensourceeasy-collab-frontendnode_modules@webtest-runner-mochadistautorun.js:1:254732)
at ....D:Opensourceeasy-collab-frontendnode_modules@webtest-runner-mochadistautorun.js:1:255788
❌ App > renders App component
Error: Uncaught Error: No QueryClient set, use QueryClientProvider to set one (http://localhost:8000/_snowpack/pkg/common/QueryClientProvider-dd42f785.js:27)
at Object.invokeGuardedCallbackDev (_snowpackpkgcommonindex-163c0f63.js:5172:16)
at invokeGuardedCallback (_snowpackpkgcommonindex-163c0f63.js:5234:31)
at beginWork$1 (_snowpackpkgcommonindex-163c0f63.js:25128:7)
at performUnitOfWork (_snowpackpkgcommonindex-163c0f63.js:23943:12)
at workLoopSync (_snowpackpkgcommonindex-163c0f63.js:23871:5)
at renderRootSync (_snowpackpkgcommonindex-163c0f63.js:23834:7)
at performSyncWorkOnRoot (_snowpackpkgcommonindex-163c0f63.js:23457:18)
at scheduleUpdateOnFiber (_snowpackpkgcommonindex-163c0f63.js:23045:7)
at updateContainer (_snowpackpkgcommonindex-163c0f63.js:26646:3)
Chrome: |██████████████████████████████| 2/2 test files | 1 passed, 1 failed
Code coverage: 48.42 %
View full coverage report at coveragelcov-reportindex.html
Finished running tests in 19.1s with 1 failed tests.
试图解决这个问题我得到这样的错误,如果有人面临或可以帮助我解决这个问题,请回答我的问题
从错误中,您丢失了QueryProvider.
- 创建一个新客户端。将其设置为不重试非常有用:
const cleanClient = new QueryClient(
{
defaultOptions: {
queries: {
retry: false,
},
},
});
- 创建一个包装器组件:
const QueryProviderWrapper = ({ children }: { children: ReactElement}): ReactElement<QueryClientProviderProps> => {
return (
<QueryClientProvider client={client}>{children}</QueryClientProvider>
);
};
- 修改渲染:
const { getByTestId, container } = render(
<QueryProviderWrapper client={cleanClient}>
<Register />
</QueryProviderWrapper>
);
- 根据您的测试,您可能希望清除该客户端;以下是它的示例:
afterEach(() => {
cleanClient.clear();
});