Skip to content

Commit

Permalink
Merge pull request #86 from utkarsha-deriv/utkarsha/refinement-api-to…
Browse files Browse the repository at this point in the history
…ken-accounts

Utkarsha/refinement api token accounts
  • Loading branch information
utkarsha-deriv committed Sep 12, 2023
2 parents 0564f03 + 0d9a82b commit d099693
Show file tree
Hide file tree
Showing 44 changed files with 1,126 additions and 734 deletions.
6 changes: 3 additions & 3 deletions packages/account/src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import React from 'react';
import { APIProvider } from '@deriv/api';
import Routes from './Containers/routes';
import ResetTradingPassword from './Containers/reset-trading-password';
import { setWebsocket } from '@deriv/shared';
import { StoreProvider } from '@deriv/stores';
import { TCoreStores } from '@deriv/stores/types';
import Routes from './Containers/routes';
import ResetTradingPassword from './Containers/reset-trading-password';
import APIProvider from '../../api/src/APIProvider';

// TODO: add correct types for WS after implementing them
type TAppProps = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -295,7 +295,7 @@ const AccountLimits = observer(
color='colored-background'
size={isMobile() ? 'xxxs' : 'xxs'}
>
{localize('Verify')}
<Localize i18n_default_text='Verify' />
</Text>
</ButtonLink>
</React.Fragment>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import React from 'react';
import { screen, render } from '@testing-library/react';
import ApiTokenArticle from '../api-token-article';

it('should render ApiTokenArticle', () => {
render(<ApiTokenArticle />);
expect(screen.getByText('API token'));
expect(
screen.getByText(
/To access your mobile apps and other third-party apps, you'll first need to generate an API token./i
)
).toBeInTheDocument();
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import React from 'react';
import { Formik, Form } from 'formik';
import { screen, render } from '@testing-library/react';
import ApiTokenCard from '../api-token-card';

describe('<ApiTokenCard />', () => {
const mock_props = {
name: 'Api_token_card_test_case',
value: false,
display_name: <div>API Token Card</div>,
description: <div>API Token Description</div>,
};

const renderComponent = (children?: JSX.Element) => {
render(
<Formik initialValues={{ [mock_props.name]: mock_props.value }} onSubmit={jest.fn()}>
<Form>
<ApiTokenCard {...mock_props}>{children}</ApiTokenCard>
</Form>
</Formik>
);
};

it('should render ApiTokenCard', () => {
renderComponent();
expect(screen.getByText('API Token Card')).toBeInTheDocument();
expect(screen.getByText('API Token Description')).toBeInTheDocument();
});

it('should render ApiTokenCard with children', () => {
const children = <div>API Token Children</div>;
renderComponent(children);
expect(screen.getByText('API Token Children')).toBeInTheDocument();
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
import React from 'react';
import { screen, render, waitFor } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import ApiTokenClipboard from '../api-token-clipboard';

const modal_root_el = document.createElement('div');
modal_root_el.setAttribute('id', 'modal_root');
document.body.appendChild(modal_root_el);

describe('ApiTokenClipboard', () => {
const mock_props = {
scopes: ['read', 'trade', 'Admin'],
text_copy: 'Text Copy',
info_message: 'Copy this token',
success_message: 'Success Message',
};

it('should render ApiTokenClipboard with the copy icon', () => {
render(<ApiTokenClipboard {...mock_props} />);
expect(screen.getByTestId('dt_copy_token_icon')).toBeInTheDocument();
});

it('should display "Copy this token" message when mouse enters', () => {
render(<ApiTokenClipboard {...mock_props} />);
const copy_icon = screen.getByTestId('dt_copy_token_icon');
userEvent.hover(copy_icon);
expect(screen.getByText('Copy this token')).toBeInTheDocument();
});

it('should remove "Copy this token" message when mouse leaves', () => {
render(<ApiTokenClipboard {...mock_props} />);
const copy_icon = screen.getByTestId('dt_copy_token_icon');
userEvent.hover(copy_icon);
expect(screen.getByText('Copy this token')).toBeInTheDocument();
userEvent.unhover(copy_icon);
expect(screen.queryByText('Copy this token')).not.toBeInTheDocument();
});

it('should display Popup Modal when user clicks on copy_icon', () => {
render(<ApiTokenClipboard {...mock_props} />);
const copy_icon = screen.getByTestId('dt_copy_token_icon');
userEvent.click(copy_icon);
expect(
screen.getByText(
'Be careful who you share this token with. Anyone with this token can perform the following actions on your account behalf'
)
).toBeInTheDocument();
expect(screen.getByText('Add accounts')).toBeInTheDocument();
expect(screen.getByText('Create or delete API tokens for trading and withdrawals')).toBeInTheDocument();
expect(screen.getByText('Modify account settings')).toBeInTheDocument();
expect(screen.getByRole('button', { name: 'OK' })).toBeInTheDocument();
});

it('should remove Popup modal when user clicks on OK', async () => {
render(<ApiTokenClipboard {...mock_props} />);
const copy_icon = screen.getByTestId('dt_copy_token_icon');
userEvent.click(copy_icon);
expect(screen.getByRole('button', { name: 'OK' })).toBeInTheDocument();
const ok_button = screen.getByRole('button', { name: 'OK' });
userEvent.click(ok_button);
await waitFor(() => {
expect(screen.queryByText('Add accounts')).not.toBeInTheDocument();
});
});

it('should not display Popup Modal when user clicks on copy_icon with no Admin scope', () => {
mock_props.scopes = ['read', 'trade'];
render(<ApiTokenClipboard {...mock_props} />);
const copy_icon = screen.getByTestId('dt_copy_token_icon');
userEvent.click(copy_icon);
expect(
screen.queryByText(
'Be careful who you share this token with. Anyone with this token can perform the following actions on your account behalf'
)
).not.toBeInTheDocument();
expect(screen.queryByText('Add accounts')).not.toBeInTheDocument();
expect(screen.queryByText('Create or delete API tokens for trading and withdrawals')).not.toBeInTheDocument();
expect(screen.queryByText('Modify account settings')).not.toBeInTheDocument();
expect(screen.queryByRole('button', { name: 'OK' })).not.toBeInTheDocument();
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
import React from 'react';
import { screen, render, waitFor, act } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import ApiTokenContext from '../api-token-context';
import ApiTokenDeleteButton from '../api-token-delete-button';

const modal_root_el = document.createElement('div');
modal_root_el.setAttribute('id', 'modal_root');
document.body.appendChild(modal_root_el);

describe('ApiTokenDeleteButton', () => {
const mock_props = {
api_tokens: [
{
display_name: '',
last_used: '',
scopes: [],
token: '',
},
],
deleteToken: jest.fn(() => Promise.resolve()),
footer_ref: document.createElement('div'),
overlay_ref: document.createElement('div'),
toggleOverlay: jest.fn(),
};
const mock_token = {
token: {
display_name: 'Token 1',
last_used: '12/31/2022',
scopes: ['read', 'trade'],
token: '1234567',
},
};

const renderAPIDeleteButton = () => {
render(
<ApiTokenContext.Provider value={mock_props}>
<ApiTokenDeleteButton {...mock_token} />
</ApiTokenContext.Provider>
);
};

it('should render ApiTokenDeleteButton', () => {
renderAPIDeleteButton();
expect(screen.getByTestId('dt_token_delete_icon')).toBeInTheDocument();
expect(screen.queryByText('Delete this token')).not.toBeInTheDocument();
});

it('should display Delete this token when mouse enter', () => {
renderAPIDeleteButton();
const delete_icon = screen.getByTestId('dt_token_delete_icon');
userEvent.hover(delete_icon);
expect(screen.getByText('Delete this token')).toBeInTheDocument();
});

it('should not display Delete this token when mouse leave', () => {
renderAPIDeleteButton();
const delete_icon = screen.getByTestId('dt_token_delete_icon');
userEvent.hover(delete_icon);
expect(screen.getByText('Delete this token')).toBeInTheDocument();
userEvent.unhover(delete_icon);
expect(screen.queryByText('Delete this token')).not.toBeInTheDocument();
});

it('should display Popup when delete icon is clicked', () => {
renderAPIDeleteButton();
const delete_icon = screen.getByTestId('dt_token_delete_icon');
userEvent.click(delete_icon);
expect(screen.getByText('Delete token')).toBeInTheDocument();
expect(screen.getByText('Are you sure you want to delete this token?')).toBeInTheDocument();
expect(screen.getByRole('button', { name: 'Cancel' })).toBeInTheDocument();
expect(screen.getByRole('button', { name: 'Yes, delete' })).toBeInTheDocument();
});

it('should close the modal when clicked on Cancel', async () => {
renderAPIDeleteButton();
const delete_icon = screen.getByTestId('dt_token_delete_icon');
userEvent.click(delete_icon);
expect(screen.getByRole('button', { name: 'Cancel' })).toBeInTheDocument();
const cancel_button = screen.getByRole('button', { name: 'Cancel' });
userEvent.click(cancel_button);
await waitFor(() => expect(screen.queryByText('Delete token')).not.toBeInTheDocument());
expect(screen.queryByText('Are you sure you want to delete this token?')).not.toBeInTheDocument();
expect(screen.queryByRole('button', { name: 'Cancel' })).not.toBeInTheDocument();
expect(screen.queryByRole('button', { name: 'Yes, delete' })).not.toBeInTheDocument();
});

it('should should trigger deleteToken when clicked on Yes, delete', () => {
renderAPIDeleteButton();
const delete_icon = screen.getByTestId('dt_token_delete_icon');
userEvent.click(delete_icon);
expect(screen.getByRole('button', { name: 'Cancel' })).toBeInTheDocument();
const delete_token_button = screen.getByRole('button', { name: 'Yes, delete' });
userEvent.click(delete_token_button);
expect(mock_props.deleteToken).toBeCalled();
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import React from 'react';
import { screen, render } from '@testing-library/react';
import ApiTokenTableRowCell from '../api-token-table-row-cell';

describe('ApiTokenTableRowCell', () => {
const mock_props = {
className: 'api_token_table_row_cell',
should_bypass_text: false,
};
const children = 'Api Table Row Cell';
it('should render ApiTokenTableRowCell', () => {
render(<ApiTokenTableRowCell {...mock_props}>{children}</ApiTokenTableRowCell>);
const text_message = screen.getByText(children);
expect(text_message).toBeInTheDocument();
expect(text_message).toHaveClass('dc-text');
});

it('should render ApiTokenTableRowCell with table data if should_bypass_text is true', () => {
render(
<ApiTokenTableRowCell {...mock_props} should_bypass_text>
{children}
</ApiTokenTableRowCell>
);
const text_message = screen.getByText(children);
expect(text_message).toBeInTheDocument();
expect(text_message).not.toHaveClass('dc-text');
expect(text_message).toHaveClass('da-api-token__table-cell api_token_table_row_cell');
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import React from 'react';
import { screen, render } from '@testing-library/react';
import ApiTokenTableRowHeader from '../api-token-table-row-header';

describe('ApiTokenTableRowHeader', () => {
const mock_props = {
text: 'Api Token Table Row Header',
};

it('should render ApiTokenTableRowHeader', () => {
render(<ApiTokenTableRowHeader {...mock_props} />);
expect(screen.getByText('Api Token Table Row Header')).toBeInTheDocument();
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import React from 'react';
import { screen, render } from '@testing-library/react';
import ApiTokenTableRowScopesCell from '../api-token-table-row-scopes-cell';

describe('ApiTokenTableRowScopeCell', () => {
const mock_props = {
scopes: ['api scope 1', 'api scope 2'],
};

it('should render ApiTokenTableRowScopesCell', () => {
render(<ApiTokenTableRowScopesCell {...mock_props} />);
expect(screen.getByText('api scope 1')).toBeInTheDocument();
expect(screen.getByText('api scope 2')).toBeInTheDocument();
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import React from 'react';
import { screen, render } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import ApiTokenTableRowTokenCell from '../api-token-table-row-token-cell';

describe('ApiTokenTableRowTokenCell', () => {
const mock_props = {
token: '1234567',
scopes: ['api scope 1', 'api scope 2'],
};
it('should render ApiTokenTableRowTokenCell', () => {
render(<ApiTokenTableRowTokenCell {...mock_props} />);
expect(screen.getByTestId('dt_hidden_tokens')).toBeInTheDocument();
expect(screen.getByTestId('dt_copy_token_icon')).toBeInTheDocument();
expect(screen.getByTestId('dt_toggle_visibility_icon')).toBeInTheDocument();
expect(screen.getByTestId('dt_toggle_visibility_icon')).toHaveClass('dc-icon da-api-token__visibility-icon');
});

it('should show token after clicking on dt_toggle_visibility_icon', () => {
render(<ApiTokenTableRowTokenCell {...mock_props} />);
const toggle_token_button = screen.getByTestId('dt_toggle_visibility_icon');
userEvent.click(toggle_token_button);
expect(screen.getByText('1234567')).toBeInTheDocument();
expect(screen.getByTestId('dt_toggle_visibility_icon')).toBeInTheDocument();
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import React from 'react';
import { screen, render } from '@testing-library/react';
import ApiTokenTableRow from '../api-token-table-row';

describe('ApiTokenTableRow', () => {
const mock_props = {
token: {
display_name: 'Api Token',
last_used: '31/12/2022',
scopes: ['Api scope 1', 'Api scope 2'],
token: '1234567',
},
};
it('should render ApiTokenTableRow', () => {
render(<ApiTokenTableRow {...mock_props} />);
const texts = ['Api Token', 'Api scope 1', 'Api scope 2', '31/12/2022'];

const test_ids = [
'dt_hidden_tokens',
'dt_copy_token_icon',
'dt_toggle_visibility_icon',
'dt_token_delete_icon',
];

texts.forEach(text => {
expect(screen.getByText(text)).toBeInTheDocument();
});

test_ids.forEach(test_id => {
expect(screen.getByTestId(test_id)).toBeInTheDocument();
});
});
});
Loading

0 comments on commit d099693

Please sign in to comment.