@skroz/frontend 0.0.6 → 0.0.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (74) hide show
  1. package/dist/auth/Auth.js +19 -36
  2. package/dist/auth/AuthButtons.d.ts +18 -0
  3. package/dist/auth/AuthButtons.js +29 -0
  4. package/dist/auth/AuthFooterLinks.js +9 -25
  5. package/dist/auth/AuthModal.d.ts +9 -0
  6. package/dist/auth/AuthModal.js +5 -0
  7. package/dist/auth/Forgot.js +47 -59
  8. package/dist/auth/Login.js +33 -48
  9. package/dist/auth/LoginForm.js +18 -47
  10. package/dist/auth/LogoutButton.d.ts +3 -0
  11. package/dist/auth/LogoutButton.js +39 -0
  12. package/dist/auth/RecoverPassword.js +64 -80
  13. package/dist/auth/Register.js +47 -55
  14. package/dist/auth/ResendLinkButton.d.ts +3 -3
  15. package/dist/auth/ResendLinkButton.js +39 -40
  16. package/dist/auth/__tests__/Login.test.d.ts +1 -0
  17. package/dist/auth/__tests__/Login.test.js +75 -0
  18. package/dist/auth/index.d.ts +3 -0
  19. package/dist/auth/index.js +11 -22
  20. package/dist/graphql/ForgotMutation.graphql.d.ts +2 -2
  21. package/dist/graphql/ForgotMutation.graphql.js +5 -7
  22. package/dist/graphql/LoginMutation.graphql.d.ts +5 -5
  23. package/dist/graphql/LoginMutation.graphql.js +6 -8
  24. package/dist/graphql/LogoutButtonMutation.graphql.d.ts +18 -0
  25. package/dist/graphql/LogoutButtonMutation.graphql.js +55 -0
  26. package/dist/graphql/RecoverPasswordMutation.graphql.d.ts +2 -2
  27. package/dist/graphql/RecoverPasswordMutation.graphql.js +5 -7
  28. package/dist/graphql/RegisterMutation.graphql.d.ts +7 -6
  29. package/dist/graphql/RegisterMutation.graphql.js +15 -10
  30. package/dist/graphql/ResendLinkButtonMutation.graphql.d.ts +2 -2
  31. package/dist/graphql/ResendLinkButtonMutation.graphql.js +5 -7
  32. package/dist/index.d.ts +0 -1
  33. package/dist/index.js +3 -20
  34. package/dist/ui/AreYouSure.js +9 -23
  35. package/dist/ui/FormError.js +9 -14
  36. package/dist/ui/FormItem.js +8 -22
  37. package/dist/ui/H.d.ts +1 -1
  38. package/dist/ui/H.js +15 -32
  39. package/dist/ui/Panel.d.ts +1 -1
  40. package/dist/ui/Panel.js +6 -23
  41. package/dist/ui/SeoHead.js +7 -13
  42. package/dist/ui/index.js +6 -18
  43. package/dist/utils/FrontendContext.js +6 -25
  44. package/dist/utils/getError.js +12 -20
  45. package/dist/utils/handleFormErrors.js +20 -29
  46. package/dist/utils/index.js +5 -28
  47. package/dist/utils/isObject.js +2 -6
  48. package/dist/utils/limitExpiresAt.js +9 -12
  49. package/package.json +8 -6
  50. package/src/auth/Auth.tsx +2 -2
  51. package/src/auth/AuthButtons.tsx +119 -0
  52. package/src/auth/AuthModal.tsx +28 -0
  53. package/src/auth/Forgot.tsx +29 -22
  54. package/src/auth/Login.tsx +25 -10
  55. package/src/auth/LoginForm.tsx +4 -4
  56. package/src/auth/LogoutButton.tsx +53 -0
  57. package/src/auth/RecoverPassword.tsx +34 -24
  58. package/src/auth/Register.tsx +29 -13
  59. package/src/auth/ResendLinkButton.tsx +34 -23
  60. package/src/auth/__tests__/Login.test.tsx +99 -0
  61. package/src/auth/index.ts +3 -0
  62. package/src/graphql/ForgotMutation.graphql.ts +77 -77
  63. package/src/graphql/LoginMutation.graphql.ts +73 -73
  64. package/src/graphql/LogoutButtonMutation.graphql.ts +74 -0
  65. package/src/graphql/RecoverPasswordMutation.graphql.ts +70 -74
  66. package/src/graphql/RegisterMutation.graphql.ts +81 -73
  67. package/src/graphql/ResendLinkButtonMutation.graphql.ts +77 -77
  68. package/src/index.ts +0 -1
  69. package/src/ui/H.tsx +1 -1
  70. package/src/ui/Panel.tsx +1 -1
  71. package/src/utils/limitExpiresAt.ts +3 -1
  72. package/dist/graphql/index.d.ts +0 -5
  73. package/dist/graphql/index.js +0 -16
  74. package/src/graphql/index.ts +0 -5
@@ -4,7 +4,7 @@ import { LockOutlined, UserOutlined } from '@ant-design/icons';
4
4
  import { useTranslation } from 'next-i18next';
5
5
  import { useExistingForm } from '@os-design/form';
6
6
  import FormItem from '../ui/FormItem';
7
- import { RegisterInput } from '../graphql/LoginMutation.graphql';
7
+ import { AuthInput } from '../graphql/LoginMutation.graphql';
8
8
  import FormError from '../ui/FormError';
9
9
 
10
10
  interface LoginFormProps {
@@ -12,8 +12,8 @@ interface LoginFormProps {
12
12
  }
13
13
 
14
14
  const LoginForm: React.FC<LoginFormProps> = ({ onPressEnter }) => {
15
- const { t } = useTranslation();
16
- const { Field } = useExistingForm<RegisterInput>();
15
+ const { t } = useTranslation('common');
16
+ const { Field } = useExistingForm<AuthInput>();
17
17
 
18
18
  return (
19
19
  <Form size='large'>
@@ -62,7 +62,7 @@ const LoginForm: React.FC<LoginFormProps> = ({ onPressEnter }) => {
62
62
  onKeyDown={(e: React.KeyboardEvent) => {
63
63
  if (e.key === 'Enter') onPressEnter();
64
64
  }}
65
- placeholder={t('common:auth.passwordPlaceholder')}
65
+ placeholder={t('auth.passwordPlaceholder')}
66
66
  />
67
67
  </FormItem>
68
68
  )}
@@ -0,0 +1,53 @@
1
+ import React, { useCallback } from 'react';
2
+ import { Button, message } from 'antd';
3
+ import { useRouter } from 'next/router';
4
+ import { useMutation } from 'react-relay';
5
+ import { LogoutOutlined } from '@ant-design/icons';
6
+ import getError from '../utils/getError';
7
+ import LogoutButtonMutationNode, {
8
+ LogoutButtonMutation,
9
+ } from '../graphql/LogoutButtonMutation.graphql';
10
+
11
+ /*
12
+ SKROZ_PROTECTION NOTE:
13
+ The Relay compiler has generated artifacts for this mutation.
14
+ Explicit import of LogoutButtonMutationNode is used.
15
+
16
+ Mutation definition (for reference/regeneration):
17
+ graphql`
18
+ mutation LogoutButtonMutation {
19
+ logout {
20
+ ok
21
+ }
22
+ }
23
+ `
24
+ */
25
+
26
+ const LogoutButton: React.FC = () => {
27
+ const router = useRouter();
28
+
29
+ const [commit] = useMutation<LogoutButtonMutation>(LogoutButtonMutationNode);
30
+
31
+ const logoutHandler = useCallback(() => {
32
+ commit({
33
+ variables: {},
34
+ onError: (error) => {
35
+ message.error(getError(error).message);
36
+ },
37
+ onCompleted: () => {
38
+ router.reload();
39
+ },
40
+ });
41
+ }, [commit, router]);
42
+
43
+ return (
44
+ <Button
45
+ shape="circle"
46
+ onClick={logoutHandler}
47
+ icon={<LogoutOutlined />}
48
+ type="link"
49
+ />
50
+ );
51
+ };
52
+
53
+ export default LogoutButton;
@@ -3,7 +3,7 @@ import { useCallback, useEffect, useState } from 'react';
3
3
  import { useRouter } from 'next/router';
4
4
  import { useTranslation } from 'next-i18next';
5
5
  import { FormProvider, useForm } from '@os-design/form';
6
- import { graphql, useMutation } from 'react-relay';
6
+ import { useMutation } from 'react-relay';
7
7
  import Link from 'next/link';
8
8
  import useInterval from '@os-design/use-interval';
9
9
  import handleFormErrors from '../utils/handleFormErrors';
@@ -12,6 +12,7 @@ import {
12
12
  RecoverPasswordInput,
13
13
  RecoverPasswordMutation,
14
14
  } from '../graphql/RecoverPasswordMutation.graphql';
15
+ import RecoverPasswordMutationNode from '../graphql/RecoverPasswordMutation.graphql';
15
16
  import H from '../ui/H';
16
17
  import Panel from '../ui/Panel';
17
18
  import FormItem from '../ui/FormItem';
@@ -21,7 +22,7 @@ import { getLimitExpiresIn, setLimitExpiresAt } from '../utils/limitExpiresAt';
21
22
 
22
23
  const RecoverPassword = () => {
23
24
  const router = useRouter();
24
- const { t } = useTranslation(['common']);
25
+ const { t } = useTranslation('common');
25
26
  const config = useFrontendConfig();
26
27
 
27
28
  let { email } = router.query;
@@ -32,13 +33,22 @@ const RecoverPassword = () => {
32
33
  password: '',
33
34
  });
34
35
 
35
- const [commit, loading] = useMutation<RecoverPasswordMutation>(graphql`
36
- mutation RecoverPasswordMutation($input: RecoverPasswordInput!) {
37
- recoverPassword(input: $input) {
38
- ok
39
- }
40
- }
41
- `);
36
+ /*
37
+ SKROZ_PROTECTION NOTE:
38
+ The Relay compiler has generated artifacts for this mutation.
39
+ Explicit import of RecoverPasswordMutationNode is used.
40
+
41
+ Mutation definition (for reference/regeneration):
42
+ graphql`
43
+ mutation RecoverPasswordMutation($input: RecoverPasswordInput!) {
44
+ recoverPassword(input: $input) {
45
+ ok
46
+ }
47
+ }
48
+ `
49
+ */
50
+
51
+ const [commit, loading] = useMutation<RecoverPasswordMutation>(RecoverPasswordMutationNode);
42
52
 
43
53
  const recoverPasswordHandler = useCallback(() => {
44
54
  commit({
@@ -49,7 +59,7 @@ const RecoverPassword = () => {
49
59
  },
50
60
  onError: (error) => handleFormErrors(form, error),
51
61
  onCompleted: () => {
52
- message.success(t('common:auth.recoverySuccess'));
62
+ message.success(t('auth.recoverySuccess'));
53
63
  const profilePath = config.defaultPath
54
64
  ? `${config.defaultPath === '/' ? '' : config.defaultPath}/profile`
55
65
  : '/profile';
@@ -72,21 +82,21 @@ const RecoverPassword = () => {
72
82
 
73
83
  const getResendButtonTitle = () => {
74
84
  if (resendIsDenied) {
75
- return `${t('common:auth.openEmailResendDenied')} ${Math.ceil(
85
+ return `${t('auth.openEmailResendDenied')} ${Math.ceil(
76
86
  limitExpiresIn / 1000
77
- )} ${t('common:sec')}`;
87
+ )} ${t('sec')}`;
78
88
  }
79
- return t('common:auth.openEmailResend');
89
+ return t('auth.openEmailResend');
80
90
  };
81
91
 
82
92
  return (
83
93
  <div className='recovery'>
84
- <div className='recovery-header'>{t('common:auth.setNewPassword')}</div>
94
+ <div className='recovery-header'>{t('auth.setNewPassword')}</div>
85
95
 
86
96
  {email.length > 0 ? (
87
97
  <>
88
98
  <div style={{ color: 'red', marginBottom: 15 }}>
89
- {t('common:auth.findCodeOnEmail')}
99
+ {t('auth.findCodeOnEmail')}
90
100
  </div>
91
101
  <FormProvider form={form}>
92
102
  <Form layout='vertical' size='large'>
@@ -101,7 +111,7 @@ const RecoverPassword = () => {
101
111
  { error }: { error?: string }
102
112
  ) => (
103
113
  <FormItem
104
- label={t('common:auth.setNewCodeLabel')}
114
+ label={t('auth.setNewCodeLabel')}
105
115
  error={error}
106
116
  style={{ marginBottom: 0 }}
107
117
  >
@@ -126,8 +136,8 @@ const RecoverPassword = () => {
126
136
 
127
137
  // Отображаем сообщение
128
138
  if (res.resendLink.ok)
129
- message.success(t('common:auth.openEmailResendOk'));
130
- else message.error(t('common:auth.openEmailResendError'));
139
+ message.success(t('auth.openEmailResendOk'));
140
+ else message.error(t('auth.openEmailResendError'));
131
141
  }}
132
142
  >
133
143
  {getResendButtonTitle()}
@@ -145,7 +155,7 @@ const RecoverPassword = () => {
145
155
  { error }: { error?: string }
146
156
  ) => (
147
157
  <FormItem
148
- label={t('common:auth.setNewPassword')}
158
+ label={t('auth.setNewPassword')}
149
159
  error={error}
150
160
  >
151
161
  <Input.Password
@@ -153,7 +163,7 @@ const RecoverPassword = () => {
153
163
  onChange={(e: React.ChangeEvent<HTMLInputElement>) =>
154
164
  onChange(e.target.value)
155
165
  }
156
- placeholder={t('common:auth.newPassword')}
166
+ placeholder={t('auth.newPassword')}
157
167
  />
158
168
  </FormItem>
159
169
  )}
@@ -163,7 +173,7 @@ const RecoverPassword = () => {
163
173
  onClick={recoverPasswordHandler}
164
174
  type='primary'
165
175
  >
166
- {t('common:auth.saveNewPassword')}
176
+ {t('auth.saveNewPassword')}
167
177
  </Button>
168
178
  </Panel>
169
179
  </Form>
@@ -173,15 +183,15 @@ const RecoverPassword = () => {
173
183
  <>
174
184
  <H
175
185
  type='h2'
176
- subHeader={t('common:auth.wrongParamsSubtitle')}
186
+ subHeader={t('auth.wrongParamsSubtitle')}
177
187
  textAlign='center'
178
188
  >
179
- {t('common:auth.wrongParamsTitle')}
189
+ {t('auth.wrongParamsTitle')}
180
190
  </H>
181
191
  <div style={{ textAlign: 'center' }}>
182
192
  <Link href={config.forgotPasswordPath || '/forgot'}>
183
193
  <Button type='primary' shape='round' size='large'>
184
- {t('common:auth.goBack')}
194
+ {t('auth.goBack')}
185
195
  </Button>
186
196
  </Link>
187
197
  </div>
@@ -10,8 +10,8 @@ import AuthFooterLinks from './AuthFooterLinks';
10
10
  import H from '../ui/H';
11
11
  import { useFrontendConfig } from '../utils/FrontendContext';
12
12
  import RegisterMutationNode, {
13
- RegisterInput,
14
13
  RegisterMutation,
14
+ AuthInput,
15
15
  } from '../graphql/RegisterMutation.graphql';
16
16
  import LoginForm from './LoginForm';
17
17
  import FormItem from '../ui/FormItem';
@@ -27,11 +27,27 @@ const Register: React.FC<RegisterProps> = ({
27
27
  isModal,
28
28
  onForgotClick,
29
29
  }) => {
30
- const { t } = useTranslation();
30
+ const { t } = useTranslation('common');
31
31
  const router = useRouter();
32
32
  const config = useFrontendConfig();
33
33
 
34
- const { form, Field } = useExistingForm<RegisterInput>();
34
+ const { form, Field } = useExistingForm<AuthInput>();
35
+
36
+ /*
37
+ SKROZ_PROTECTION NOTE:
38
+ The Relay compiler has generated artifacts for this mutation.
39
+ Explicit import of RegisterMutationNode is used.
40
+
41
+ Mutation definition (for reference/regeneration):
42
+ graphql`
43
+ mutation RegisterMutation($input: AuthInput!) {
44
+ register(input: $input) {
45
+ id
46
+ email
47
+ }
48
+ }
49
+ `
50
+ */
35
51
 
36
52
  const [commit, loading] = useMutation<RegisterMutation>(RegisterMutationNode);
37
53
 
@@ -46,30 +62,30 @@ const Register: React.FC<RegisterProps> = ({
46
62
  onCompleted: () => {
47
63
  onFinish();
48
64
  router.push(config.defaultPath || '/');
49
- message.success(t('common:auth.successRegister'));
65
+ message.success(t('auth.successRegister'));
50
66
  },
51
67
  });
52
68
  }, [commit, form, onFinish, router, t, config.defaultPath]);
53
69
 
54
70
  const forgotButton = (
55
71
  <Button type='link' onClick={onForgotClick}>
56
- {t('common:auth.forgot')}
72
+ {t('auth.forgot')}
57
73
  </Button>
58
74
  );
59
75
  const loginButton = (
60
76
  <Button type='link' shape='round'>
61
- {t('common:buttons.login')}
77
+ {t('buttons.login')}
62
78
  </Button>
63
79
  );
64
80
 
65
81
  return (
66
82
  <div className='auth no-text-selection'>
67
83
  <H type='h1' textAlign='center'>
68
- {t('common:auth.registerTitle')}
84
+ {t('auth.registerTitle')}
69
85
  </H>
70
86
  {!isModal && (
71
87
  <div className='auth-subtitle'>
72
- {t('common:auth.registerSubtitle')}{' '}
88
+ {t('auth.registerSubtitle')}{' '}
73
89
  <Link href={config.loginPath || '/login'} passHref>
74
90
  {loginButton}
75
91
  </Link>
@@ -98,9 +114,9 @@ const Register: React.FC<RegisterProps> = ({
98
114
  checked={value || false}
99
115
  onChange={(e: any) => onChange(e.target.checked)}
100
116
  >
101
- {t('common:auth.acceptUserAgreement')}{' '}
117
+ {t('auth.acceptUserAgreement')}{' '}
102
118
  <Link href='/docs/user-agreement'>
103
- {t('common:links.userAgreement')}
119
+ {t('links.userAgreement')}
104
120
  </Link>
105
121
  </Checkbox>
106
122
  </FormItem>
@@ -125,9 +141,9 @@ const Register: React.FC<RegisterProps> = ({
125
141
  onChange={(e: any) => onChange(e.target.checked)}
126
142
  style={{ fontSize: '16px' }}
127
143
  >
128
- {t('common:auth.acceptPrivacyPolicy')}{' '}
144
+ {t('auth.acceptPrivacyPolicy')}{' '}
129
145
  <Link href='/docs/privacy-policy'>
130
- {t('common:links.privacyPolicy')}
146
+ {t('links.privacyPolicy')}
131
147
  </Link>
132
148
  </Checkbox>
133
149
  </FormItem>
@@ -143,7 +159,7 @@ const Register: React.FC<RegisterProps> = ({
143
159
  loading={loading}
144
160
  onClick={registerHandler}
145
161
  >
146
- {t('common:buttons.register')}
162
+ {t('buttons.register')}
147
163
  </Button>
148
164
  </div>
149
165
 
@@ -1,40 +1,49 @@
1
1
  import React, { useCallback } from 'react';
2
- import { graphql, useMutation } from 'react-relay';
2
+ import { useMutation } from 'react-relay';
3
3
  import { Button, message } from 'antd';
4
4
  import { useTranslation } from 'next-i18next';
5
- import {
5
+ import ResendLinkButtonMutationNode, {
6
6
  ResendLinkButtonMutation,
7
7
  } from '../graphql/ResendLinkButtonMutation.graphql';
8
8
 
9
9
  interface ResendLinkButtonProps {
10
10
  email: string;
11
- children: React.ReactNode;
11
+ onCompleted?: (res: any) => void;
12
+ onError?: (error: any) => void;
12
13
  disabled?: boolean;
13
- onCompleted: (res: any) => void;
14
- onError: (res: any) => void;
14
+ children: React.ReactNode;
15
15
  }
16
16
 
17
17
  const ResendLinkButton: React.FC<ResendLinkButtonProps> = ({
18
18
  email,
19
- children,
20
- disabled,
21
19
  onCompleted,
22
20
  onError,
21
+ disabled,
22
+ children,
23
23
  }) => {
24
- const { t } = useTranslation();
24
+ const { t } = useTranslation('common');
25
25
 
26
- const [commit, loading] = useMutation<ResendLinkButtonMutation>(graphql`
27
- mutation ResendLinkButtonMutation($input: SendTokenInput!) {
28
- sendToken(input: $input) {
29
- codeIsSent
30
- limitExpiresAt
31
- }
32
- }
33
- `);
26
+ /*
27
+ SKROZ_PROTECTION NOTE:
28
+ The Relay compiler has generated artifacts for this mutation.
29
+ Explicit import of ResendLinkButtonMutationNode is used.
30
+
31
+ Mutation definition (for reference/regeneration):
32
+ graphql`
33
+ mutation ResendLinkButtonMutation($input: SendTokenInput!) {
34
+ sendToken(input: $input) {
35
+ codeIsSent
36
+ limitExpiresAt
37
+ }
38
+ }
39
+ `
40
+ */
41
+
42
+ const [commit, loading] = useMutation<ResendLinkButtonMutation>(ResendLinkButtonMutationNode);
34
43
 
35
44
  const resendLinkHandler = useCallback(() => {
36
45
  if (!email) {
37
- message.error(t('common:error.emailNotProvided'));
46
+ message.error(t('error.emailNotProvided'));
38
47
  return;
39
48
  }
40
49
  commit({
@@ -45,12 +54,14 @@ const ResendLinkButton: React.FC<ResendLinkButtonProps> = ({
45
54
  },
46
55
  onError,
47
56
  onCompleted: (res: any) => {
48
- onCompleted({
49
- resendLink: {
50
- ok: res.sendToken.codeIsSent,
51
- limitExpiresAt: res.sendToken.limitExpiresAt,
52
- },
53
- });
57
+ if (onCompleted) {
58
+ onCompleted({
59
+ resendLink: {
60
+ ok: res.sendToken.codeIsSent,
61
+ limitExpiresAt: res.sendToken.limitExpiresAt,
62
+ },
63
+ });
64
+ }
54
65
  },
55
66
  });
56
67
  }, [commit, email, onCompleted, onError, t]);
@@ -0,0 +1,99 @@
1
+ import React from 'react';
2
+ import { render } from '@testing-library/react';
3
+ import { useRouter } from 'next/router';
4
+ import { useMutation } from 'react-relay';
5
+ import { useExistingForm } from '@os-design/form';
6
+ import Login from '../Login';
7
+
8
+ // Mocking dependencies with verified relative paths
9
+ jest.mock('next/router', () => ({
10
+ useRouter: jest.fn(),
11
+ }));
12
+
13
+ jest.mock('next/link', () => ({
14
+ __esModule: true,
15
+ default: ({ children, href }: any) => <a href={href}>{children}</a>,
16
+ }));
17
+
18
+ jest.mock('next-i18next', () => ({
19
+ useTranslation: () => ({
20
+ t: (key: string) => key,
21
+ }),
22
+ }));
23
+
24
+ jest.mock('antd', () => ({
25
+ Button: ({ children, onClick }: any) => <button onClick={onClick}>{children}</button>,
26
+ message: {
27
+ success: jest.fn(),
28
+ error: jest.fn(),
29
+ },
30
+ }));
31
+
32
+ jest.mock('react-relay', () => ({
33
+ useMutation: jest.fn(),
34
+ graphql: jest.fn(),
35
+ }));
36
+
37
+ jest.mock('../../graphql/LoginMutation.graphql', () => ({
38
+ __esModule: true,
39
+ default: {},
40
+ }));
41
+
42
+ jest.mock('@os-design/form', () => ({
43
+ useExistingForm: jest.fn(),
44
+ }));
45
+
46
+ jest.mock('../../ui/H', () => ({ children }: { children: React.ReactNode }) => <h1>{children}</h1>);
47
+ jest.mock('../LoginForm', () => () => <div data-testid="login-form" />);
48
+ jest.mock('../AuthFooterLinks', () => () => <div data-testid="auth-footer-links" />);
49
+ jest.mock('../../utils/FrontendContext', () => ({
50
+ useFrontendConfig: () => ({
51
+ loginPath: '/login',
52
+ registerPath: '/register',
53
+ forgotPasswordPath: '/forgot',
54
+ defaultPath: '/',
55
+ }),
56
+ }));
57
+ jest.mock('../../utils/handleFormErrors', () => jest.fn());
58
+
59
+ describe('Login Component', () => {
60
+ const mockOnFinish = jest.fn();
61
+ const mockOnForgotClick = jest.fn();
62
+ const mockCommit = jest.fn();
63
+
64
+ beforeEach(() => {
65
+ (useRouter as jest.Mock).mockReturnValue({
66
+ reload: jest.fn(),
67
+ });
68
+ (useMutation as jest.Mock).mockReturnValue([mockCommit, false]);
69
+ (useExistingForm as jest.Mock).mockReturnValue({
70
+ form: {
71
+ values: {
72
+ getAll: jest.fn().mockReturnValue({}),
73
+ },
74
+ },
75
+ });
76
+ });
77
+
78
+ it('should render the login title', () => {
79
+ const { getByText } = render(
80
+ <Login
81
+ onFinish={mockOnFinish}
82
+ onForgotClick={mockOnForgotClick}
83
+ isModal={false}
84
+ />
85
+ );
86
+ expect(getByText('common:auth.loginTitle')).toBeDefined();
87
+ });
88
+
89
+ it('should render the login form', () => {
90
+ const { getByTestId } = render(
91
+ <Login
92
+ onFinish={mockOnFinish}
93
+ onForgotClick={mockOnForgotClick}
94
+ isModal={false}
95
+ />
96
+ );
97
+ expect(getByTestId('login-form')).toBeDefined();
98
+ });
99
+ });
package/src/auth/index.ts CHANGED
@@ -6,3 +6,6 @@ export { default as RecoverPassword } from './RecoverPassword';
6
6
  export { default as AuthFooterLinks } from './AuthFooterLinks';
7
7
  export { default as LoginForm } from './LoginForm';
8
8
  export { default as ResendLinkButton } from './ResendLinkButton';
9
+ export { default as LogoutButton } from './LogoutButton';
10
+ export { default as AuthModal } from './AuthModal';
11
+ export { default as AuthButtons } from './AuthButtons';