From 86f1ac5b1ec9d1abed6b793635bee5a0b73e2127 Mon Sep 17 00:00:00 2001 From: sanjam chhatwal Date: Tue, 4 Jul 2023 17:20:21 +0400 Subject: [PATCH 1/7] feat: added resrictions --- .../ApiTokenForm/api-token.form.tsx | 4 +++- .../TokenNameRestrictions.module.scss | 9 +++++++++ .../TokenNameRestrictions.tsx | 19 +++++++++++++++++++ 3 files changed, 31 insertions(+), 1 deletion(-) create mode 100644 src/features/dashboard/components/TokenNameRestrictions/TokenNameRestrictions.module.scss create mode 100644 src/features/dashboard/components/TokenNameRestrictions/TokenNameRestrictions.tsx diff --git a/src/features/dashboard/components/ApiTokenForm/api-token.form.tsx b/src/features/dashboard/components/ApiTokenForm/api-token.form.tsx index 173446f1..59fe85f9 100644 --- a/src/features/dashboard/components/ApiTokenForm/api-token.form.tsx +++ b/src/features/dashboard/components/ApiTokenForm/api-token.form.tsx @@ -8,6 +8,7 @@ import ApiTokenCard from '../ApiTokenCard'; import useCreateToken from '@site/src/features/dashboard/hooks/useCreateToken'; import * as yup from 'yup'; import styles from './api-token.form.module.scss'; +import TokenNameRestrictions from '../TokenNameRestrictions/TokenNameRestrictions'; const schema = yup .object({ @@ -63,6 +64,7 @@ const scopes: TScope[] = [ const ApiTokenForm = (props: HTMLAttributes) => { const { createToken, isCreatingToken } = useCreateToken(); + const [restrictions, setRestrictions] = useState(false); const { handleSubmit, register, setValue, getValues, reset } = useForm({ resolver: yupResolver(schema), @@ -139,7 +141,7 @@ const ApiTokenForm = (props: HTMLAttributes) => {
-

Length of token name must be between 2 and 32 characters.

+
diff --git a/src/features/dashboard/components/TokenNameRestrictions/TokenNameRestrictions.module.scss b/src/features/dashboard/components/TokenNameRestrictions/TokenNameRestrictions.module.scss new file mode 100644 index 00000000..10063391 --- /dev/null +++ b/src/features/dashboard/components/TokenNameRestrictions/TokenNameRestrictions.module.scss @@ -0,0 +1,9 @@ +@use 'src/styles/utility' as *; + +.tokenrestrictions { + font-size: rem(1.4); + font-weight: 400; + line-height: 18px; + padding-left: rem(2.8); + color: var(--colors-greyLight600); +} diff --git a/src/features/dashboard/components/TokenNameRestrictions/TokenNameRestrictions.tsx b/src/features/dashboard/components/TokenNameRestrictions/TokenNameRestrictions.tsx new file mode 100644 index 00000000..2c882c6f --- /dev/null +++ b/src/features/dashboard/components/TokenNameRestrictions/TokenNameRestrictions.tsx @@ -0,0 +1,19 @@ +import React from 'react'; +import styles from './TokenNameRestrictions.module.scss'; + +const TokenNameRestrictions = () => { + return ( +
    +
  1. Only alphanumeric characters with spaces and underscores are allowed.
  2. +
  3. Only 2-32 characters are allowed
  4. +
  5. No duplicate token names are allowed for the same account.
  6. +
  7. + { + 'No keywords "deriv" or "binary" or words that look similar, e.g. "_binary_" or "d3eriv" are allowed.' + } +
  8. +
+ ); +}; + +export default TokenNameRestrictions; From 88afda9fc29ede64ebeeec79b63403c26a7c284c Mon Sep 17 00:00:00 2001 From: sanjam chhatwal Date: Wed, 19 Jul 2023 13:39:16 +0400 Subject: [PATCH 2/7] chore: added tests and states --- .../__tests__/api-token.form.test.tsx | 9 ++++++ .../ApiTokenForm/api-token.form.tsx | 11 ++++--- .../__tests__/TokenNameRestrictions.test.tsx | 31 +++++++++++++++++++ 3 files changed, 47 insertions(+), 4 deletions(-) create mode 100644 src/features/dashboard/components/TokenNameRestrictions/__tests__/TokenNameRestrictions.test.tsx diff --git a/src/features/dashboard/components/ApiTokenForm/__tests__/api-token.form.test.tsx b/src/features/dashboard/components/ApiTokenForm/__tests__/api-token.form.test.tsx index 16bb238f..588c1d61 100644 --- a/src/features/dashboard/components/ApiTokenForm/__tests__/api-token.form.test.tsx +++ b/src/features/dashboard/components/ApiTokenForm/__tests__/api-token.form.test.tsx @@ -4,6 +4,7 @@ import userEvent from '@testing-library/user-event'; import ApiTokenForm from '../api-token.form'; import useCreateToken from '../../../hooks/useCreateToken'; import useApiToken from '@site/src/hooks/useApiToken'; +import TokenNameRestrictions from '../../TokenNameRestrictions/TokenNameRestrictions'; jest.mock('@site/src/hooks/useApiToken'); @@ -138,6 +139,14 @@ describe('Home Page', () => { expect(error).toBeVisible; }); + it('should hide restrictions if error is present', async () => { + const nameInput = screen.getByRole('textbox'); + const restrictions = screen.getByRole('list'); + expect(restrictions).toBeVisible(); + await userEvent.type(nameInput, 'testtoken1'); + expect(restrictions).not.toBeVisible(); + }); + it('Should not create token when name input is empty', async () => { const nameInput = screen.getByRole('textbox'); diff --git a/src/features/dashboard/components/ApiTokenForm/api-token.form.tsx b/src/features/dashboard/components/ApiTokenForm/api-token.form.tsx index c7db9526..4c983566 100644 --- a/src/features/dashboard/components/ApiTokenForm/api-token.form.tsx +++ b/src/features/dashboard/components/ApiTokenForm/api-token.form.tsx @@ -1,4 +1,4 @@ -import React, { HTMLAttributes, useCallback, useState } from 'react'; +import React, { HTMLAttributes, useCallback, useEffect, useState } from 'react'; import { Text } from '@deriv/ui'; import { useForm } from 'react-hook-form'; import { Circles } from 'react-loader-spinner'; @@ -80,7 +80,7 @@ const scopes: TScope[] = [ const ApiTokenForm = (props: HTMLAttributes) => { const { createToken, isCreatingToken } = useCreateToken(); - const [restrictions, setRestrictions] = useState(false); + const [hiderestrictions, setHideRestrictions] = useState(false); const [form_is_cleared, setFormIsCleared] = useState(false); const { @@ -94,7 +94,6 @@ const ApiTokenForm = (props: HTMLAttributes) => { resolver: yupResolver(schema), mode: 'all', }); - const onSubmit = useCallback( (data: TApiTokenForm) => { const { name } = data; @@ -120,6 +119,10 @@ const ApiTokenForm = (props: HTMLAttributes) => { [getValues, setValue], ); + useEffect(() => { + errors.name?.message ? setHideRestrictions(true) : setHideRestrictions(false); + }, [errors.name?.message]); + return (
@@ -160,7 +163,7 @@ const ApiTokenForm = (props: HTMLAttributes) => { form_is_cleared={form_is_cleared} setFormIsCleared={setFormIsCleared} /> - + {!hiderestrictions && }
diff --git a/src/features/dashboard/components/TokenNameRestrictions/__tests__/TokenNameRestrictions.test.tsx b/src/features/dashboard/components/TokenNameRestrictions/__tests__/TokenNameRestrictions.test.tsx new file mode 100644 index 00000000..834f5591 --- /dev/null +++ b/src/features/dashboard/components/TokenNameRestrictions/__tests__/TokenNameRestrictions.test.tsx @@ -0,0 +1,31 @@ +import React from 'react'; +import { render, screen } from '@site/src/test-utils'; +import TokenNameRestrictions from '../TokenNameRestrictions'; + +describe('Restrictions for App name', () => { + beforeEach(() => { + render(); + }); + it('Should render the list', () => { + const RestrictonList = screen.getByRole('list'); + expect(RestrictonList).toBeInTheDocument(); + }); + + it('Should display correct content inside list items', () => { + const listItem1 = screen.getByText( + 'Only alphanumeric characters with spaces and underscores are allowed.', + ); + const listItem2 = screen.getByText('Only 2-32 characters are allowed'); + const listItem3 = screen.getByText( + 'No duplicate token names are allowed for the same account.', + ); + const listItem4 = screen.getByText( + 'No keywords "deriv" or "binary" or words that look similar, e.g. "_binary_" or "d3eriv" are allowed.', + ); + + expect(listItem1).toBeInTheDocument(); + expect(listItem2).toBeInTheDocument(); + expect(listItem3).toBeInTheDocument(); + expect(listItem4).toBeInTheDocument(); + }); +}); From 04a642251bf519fdfdccffbe874f91f8788815a3 Mon Sep 17 00:00:00 2001 From: sanjam chhatwal Date: Wed, 26 Jul 2023 11:07:52 +0400 Subject: [PATCH 3/7] chore: hide token --- .../components/ApiTokenForm/CreateTokenField/index.tsx | 7 +++++++ .../dashboard/components/ApiTokenForm/api-token.form.tsx | 1 + 2 files changed, 8 insertions(+) diff --git a/src/features/dashboard/components/ApiTokenForm/CreateTokenField/index.tsx b/src/features/dashboard/components/ApiTokenForm/CreateTokenField/index.tsx index 1cd53547..6242bc1a 100644 --- a/src/features/dashboard/components/ApiTokenForm/CreateTokenField/index.tsx +++ b/src/features/dashboard/components/ApiTokenForm/CreateTokenField/index.tsx @@ -18,6 +18,7 @@ type TCreateTokenField = { >; form_is_cleared: boolean; setFormIsCleared: Dispatch>; + setHideRestriction: Dispatch>; }; const CreateTokenField = ({ @@ -25,6 +26,7 @@ const CreateTokenField = ({ register, form_is_cleared, setFormIsCleared, + setHideRestriction, }: TCreateTokenField) => { const { tokens } = useApiToken(); const [input_value, setInputValue] = useState(''); @@ -49,6 +51,11 @@ const CreateTokenField = ({ const disable_button = token_name_exists || Object.keys(errors).length > 0 || input_value === ''; const error_border_active = token_name_exists || errors.name; + useEffect(() => { + if (error_border_active) { + setHideRestriction(true); + } + }, [error_border_active, setHideRestriction]); return (
diff --git a/src/features/dashboard/components/ApiTokenForm/api-token.form.tsx b/src/features/dashboard/components/ApiTokenForm/api-token.form.tsx index 4c983566..48b0233f 100644 --- a/src/features/dashboard/components/ApiTokenForm/api-token.form.tsx +++ b/src/features/dashboard/components/ApiTokenForm/api-token.form.tsx @@ -162,6 +162,7 @@ const ApiTokenForm = (props: HTMLAttributes) => { errors={errors} form_is_cleared={form_is_cleared} setFormIsCleared={setFormIsCleared} + setHideRestriction={setHideRestrictions} /> {!hiderestrictions && }
From 3c56d41157c58c3ec96c4121e1794025ea4fa0f9 Mon Sep 17 00:00:00 2001 From: sanjam chhatwal Date: Wed, 26 Jul 2023 11:45:18 +0400 Subject: [PATCH 4/7] chore: hide token --- .../components/ApiTokenForm/CreateTokenField/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/features/dashboard/components/ApiTokenForm/CreateTokenField/index.tsx b/src/features/dashboard/components/ApiTokenForm/CreateTokenField/index.tsx index 6242bc1a..6d076c68 100644 --- a/src/features/dashboard/components/ApiTokenForm/CreateTokenField/index.tsx +++ b/src/features/dashboard/components/ApiTokenForm/CreateTokenField/index.tsx @@ -87,7 +87,7 @@ const CreateTokenField = ({ )} {token_name_exists && (
-

That name is taken. Choose another.

+

No duplicate token names are allowed for the same account.

)} From 803574ac9d60c6c9e840912215759b45d7c8242e Mon Sep 17 00:00:00 2001 From: sanjam chhatwal Date: Wed, 26 Jul 2023 11:57:19 +0400 Subject: [PATCH 5/7] fix: test case --- .../components/ApiTokenForm/__tests__/api-token.form.test.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/features/dashboard/components/ApiTokenForm/__tests__/api-token.form.test.tsx b/src/features/dashboard/components/ApiTokenForm/__tests__/api-token.form.test.tsx index 588c1d61..b6efd33c 100644 --- a/src/features/dashboard/components/ApiTokenForm/__tests__/api-token.form.test.tsx +++ b/src/features/dashboard/components/ApiTokenForm/__tests__/api-token.form.test.tsx @@ -135,7 +135,7 @@ describe('Home Page', () => { await userEvent.type(nameInput, 'testtoken1'); - const error = screen.getByText(/That name is taken. Choose another./i); + const error = screen.getByText(/ No duplicate token names are allowed for the same account./i); expect(error).toBeVisible; }); From 087c1ce0793e9d3f07113a7c119385ca97d4c641 Mon Sep 17 00:00:00 2001 From: sanjam chhatwal Date: Wed, 26 Jul 2023 12:01:04 +0400 Subject: [PATCH 6/7] fix: test case --- .../components/ApiTokenForm/__tests__/api-token.form.test.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/features/dashboard/components/ApiTokenForm/__tests__/api-token.form.test.tsx b/src/features/dashboard/components/ApiTokenForm/__tests__/api-token.form.test.tsx index b6efd33c..2f929cf1 100644 --- a/src/features/dashboard/components/ApiTokenForm/__tests__/api-token.form.test.tsx +++ b/src/features/dashboard/components/ApiTokenForm/__tests__/api-token.form.test.tsx @@ -135,7 +135,7 @@ describe('Home Page', () => { await userEvent.type(nameInput, 'testtoken1'); - const error = screen.getByText(/ No duplicate token names are allowed for the same account./i); + const error = screen.getByText(/No duplicate token names are allowed for the same account./i); expect(error).toBeVisible; }); From 254cf6b702b2af6bcbd7628409fa5017eed38251 Mon Sep 17 00:00:00 2001 From: sanjam chhatwal Date: Fri, 28 Jul 2023 10:20:53 +0400 Subject: [PATCH 7/7] fix: test case --- .../components/ApiTokenForm/CreateTokenField/index.tsx | 2 +- .../components/ApiTokenForm/__tests__/api-token.form.test.tsx | 2 +- .../components/ApiTokenForm/api-token.form.module.scss | 1 - .../TokenNameRestrictions/TokenNameRestrictions.module.scss | 1 + 4 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/features/dashboard/components/ApiTokenForm/CreateTokenField/index.tsx b/src/features/dashboard/components/ApiTokenForm/CreateTokenField/index.tsx index 6d076c68..6242bc1a 100644 --- a/src/features/dashboard/components/ApiTokenForm/CreateTokenField/index.tsx +++ b/src/features/dashboard/components/ApiTokenForm/CreateTokenField/index.tsx @@ -87,7 +87,7 @@ const CreateTokenField = ({ )} {token_name_exists && (
-

No duplicate token names are allowed for the same account.

+

That name is taken. Choose another.

)} diff --git a/src/features/dashboard/components/ApiTokenForm/__tests__/api-token.form.test.tsx b/src/features/dashboard/components/ApiTokenForm/__tests__/api-token.form.test.tsx index 2f929cf1..588c1d61 100644 --- a/src/features/dashboard/components/ApiTokenForm/__tests__/api-token.form.test.tsx +++ b/src/features/dashboard/components/ApiTokenForm/__tests__/api-token.form.test.tsx @@ -135,7 +135,7 @@ describe('Home Page', () => { await userEvent.type(nameInput, 'testtoken1'); - const error = screen.getByText(/No duplicate token names are allowed for the same account./i); + const error = screen.getByText(/That name is taken. Choose another./i); expect(error).toBeVisible; }); diff --git a/src/features/dashboard/components/ApiTokenForm/api-token.form.module.scss b/src/features/dashboard/components/ApiTokenForm/api-token.form.module.scss index 4571be41..865d41bb 100644 --- a/src/features/dashboard/components/ApiTokenForm/api-token.form.module.scss +++ b/src/features/dashboard/components/ApiTokenForm/api-token.form.module.scss @@ -55,7 +55,6 @@ form { display: flex; position: relative; box-sizing: border-box; - margin: rem(1) 0; &:hover { border: 1px solid var(--colors-greyLight600); } diff --git a/src/features/dashboard/components/TokenNameRestrictions/TokenNameRestrictions.module.scss b/src/features/dashboard/components/TokenNameRestrictions/TokenNameRestrictions.module.scss index 10063391..56a1aa36 100644 --- a/src/features/dashboard/components/TokenNameRestrictions/TokenNameRestrictions.module.scss +++ b/src/features/dashboard/components/TokenNameRestrictions/TokenNameRestrictions.module.scss @@ -5,5 +5,6 @@ font-weight: 400; line-height: 18px; padding-left: rem(2.8); + margin-top: rem(1); color: var(--colors-greyLight600); }