Skip to content
This repository was archived by the owner on May 13, 2024. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/contexts/auth/auth.context.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ export type IUserAccounts = AuthorizeResponse['authorize']['account_list'];
export type IUser = Omit<AuthorizeResponse['authorize'], 'account_list'>;

export interface IAuthContext {
is_switching_account: boolean;
is_logged_in: boolean;
is_authorized: boolean;
loginAccounts: IUserLoginAccount[];
Expand Down
5 changes: 5 additions & 0 deletions src/contexts/auth/auth.provider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ if (getIsBrowser()) {
const AuthProvider = ({ children }: TAuthProviderProps) => {
const [is_logged_in, setIsLoggedIn] = useState(false);
const [is_authorized, setIsAuthorized] = useState(false);
const [is_switching_account, setisSwitchingAccount] = useState(false);

const [loginAccounts, setLoginAccounts] = useSessionStorage<IUserLoginAccount[]>(
LOGIN_ACCOUNTS_SESSION_STORAGE_KEY,
Expand All @@ -46,6 +47,7 @@ const AuthProvider = ({ children }: TAuthProviderProps) => {
if (currentLoginAccount.token) {
const { authorize } = await apiManager.authorize(currentLoginAccount.token);
setIsAuthorized(true);
setisSwitchingAccount(false);
const { account_list, ...user } = authorize;
setUserAccounts(account_list);
setUser(user);
Expand Down Expand Up @@ -76,6 +78,7 @@ const AuthProvider = ({ children }: TAuthProviderProps) => {
const updateCurrentLoginAccount = useCallback(
(account: IUserLoginAccount) => {
setIsAuthorized(false);
setisSwitchingAccount(true);
setCurrentLoginAccount(account);
},
[setCurrentLoginAccount],
Expand All @@ -91,6 +94,7 @@ const AuthProvider = ({ children }: TAuthProviderProps) => {

const context_object: IAuthContext = useMemo(() => {
return {
is_switching_account,
is_logged_in,
is_authorized,
loginAccounts,
Expand All @@ -102,6 +106,7 @@ const AuthProvider = ({ children }: TAuthProviderProps) => {
};
}, [
currentLoginAccount,
is_switching_account,
is_authorized,
is_logged_in,
loginAccounts,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,25 +10,21 @@ const ReactJson = React.lazy(() => import('react-json-view'));

type TJsonData<T extends TSocketEndpointNames> = {
history_reponse: TSocketResponse<T>;
error: unknown;
};

const JsonData = <T extends TSocketEndpointNames | TSocketSubscribableEndpointNames>({
history_reponse,
error,
}: TJsonData<T>) => {
return (
<React.Fragment>
{history_reponse !== null && history_reponse?.echo_req ? (
{history_reponse !== null && history_reponse?.echo_req && (
<div
className={styles.reactJsonContainer}
data-testid={`dt_json_container-${history_reponse.req_id}`}
>
<ReactJson src={history_reponse.echo_req} theme='tube' />
<ReactJson src={history_reponse} theme='tube' />
</div>
) : (
<ReactJson src={{ error }} theme='tube' />
)}
</React.Fragment>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ mockUsePlaygroundContext.mockImplementation(() => ({

describe('JsonView', () => {
it('should be able to render the JsonView', () => {
render(<JsonView error={'test'} />);
render(<JsonView />);
// req_id determines the index number of dt_json_container-(idx);
const response_block = screen.getByTestId('dt_json_container-3');
expect(response_block).toBeInTheDocument();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,7 @@ import {
import styles from './JsonView.module.scss';
import Spinner from '@site/src/components/Spinner';

type TJsonView = {
error: unknown;
};

const JsonView = <T extends TSocketEndpointNames | TSocketSubscribableEndpointNames>({
error,
}: TJsonView) => {
const JsonView = <T extends TSocketEndpointNames | TSocketSubscribableEndpointNames>() => {
const { playground_history } = usePlaygroundContext();
return (
<Suspense fallback={<Spinner />}>
Expand All @@ -24,7 +18,7 @@ const JsonView = <T extends TSocketEndpointNames | TSocketSubscribableEndpointNa
const key = response.subscription ? JSON.stringify(response) : response.req_id;
return (
<React.Fragment key={key}>
<JsonData history_reponse={response} error={error} />
<JsonData history_reponse={response} />
</React.Fragment>
);
})}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@ const PlaygroundSection = <T extends TSocketEndpointNames | TSocketSubscribableE
if (full_response) {
setPlaygroundHistory((prev: TSocketResponse<T>[]) => [...prev, full_response]);
}
if (error) {
setPlaygroundHistory((prev: TSocketResponse<T>[]) => [...prev, error]);
}
};

const toggleScrolling = (e) => {
Expand All @@ -51,7 +54,7 @@ const PlaygroundSection = <T extends TSocketEndpointNames | TSocketSubscribableE

useEffect(() => {
updateHistory();
}, [full_response]);
}, [full_response, error]);

if (loader && playground_history.length === 0) return <Spinner />;

Expand All @@ -65,7 +68,7 @@ const PlaygroundSection = <T extends TSocketEndpointNames | TSocketSubscribableE
>
{response_state && (
<React.Fragment>
<JsonView error={error} />
<JsonView />
</React.Fragment>
)}
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -141,15 +141,69 @@ describe('SubscribeRenderer', () => {
expect(mockSubscribe).toBeCalledWith({ ticks: 'R_50', subscribe: 1 });
});

it('should unsubscribe any subscriptions when switching accounts', () => {
cleanup();
jest.clearAllMocks();

mockUseSubscription.mockImplementation(() => ({
subscribe: mockSubscribe,
unsubscribe: mockUnsubscribe,
error: { code: '' },
full_response: {
tick: 1,
echo_req: { tick: 1 },
},
is_subscribed: false,
}));

mockUseAuthContext.mockImplementation(() => ({
is_logged_in: true,
is_authorized: true,
is_switching_account: true,
currentLoginAccount: {
name: 'someAccount',
token: 'asdf1234',
currency: 'USD',
},
}));

render(<SubscribeRenderer name='ticks' auth={1} reqData={request_data} />);
expect(mockUnsubscribe).toHaveBeenCalledTimes(1);
});

it('should call unsubscribe when pressing the clear button', async () => {
cleanup();
jest.clearAllMocks();

mockUseSubscription.mockImplementation(() => ({
subscribe: mockSubscribe,
unsubscribe: mockUnsubscribe,
error: { code: '' },
full_response: {
tick: 1,
echo_req: { tick: 1 },
},
is_subscribed: true,
}));

mockUseAuthContext.mockImplementation(() => ({
is_logged_in: true,
is_authorized: true,
is_switching_account: false,
currentLoginAccount: {
name: 'someAccount',
token: 'asdf1234',
currency: 'USD',
},
}));

render(<SubscribeRenderer name='ticks' auth={1} reqData={request_data} />);
const button = await screen.findByRole('button', { name: 'Clear' });
expect(button).toBeVisible();

await userEvent.click(button);
expect(mockUnsubscribe).toBeCalledTimes(1);
});

it('should call unsubscribe when unmounting the component', async () => {
const { unmount } = render(<SubscribeRenderer name='ticks' auth={1} reqData={request_data} />);
unmount();
Expand All @@ -159,27 +213,26 @@ describe('SubscribeRenderer', () => {
cleanup();
jest.clearAllMocks();

const setToggleModal = jest.fn();
jest.spyOn(React, 'useState').mockReturnValue([false, setToggleModal]);
mockUseAuthContext.mockImplementation(() => ({
is_logged_in: false,
is_authorized: false,
is_authorized: true,
}));
mockUseSubscription.mockImplementation(() => ({
subscribe: mockSubscribe,
unsubscribe: mockUnsubscribe,
error: { code: 'AuthorizationRequired' },
full_response: {
tick: 1,
echo_req: { tick: 1 },
app_list: 1,
echo_req: { app_list: 1 },
},
}));

render(<SubscribeRenderer name='ticks' auth={1} reqData={request_data} />);
const button = await screen.findByRole('button', { name: /Send Request/i });
await userEvent.click(button);
const login_dialog = await screen.findByText(
/This API call must be authorised because it requires access to your account information./i,
);
await waitFor(() => {
expect(setToggleModal).toHaveBeenCalled();
expect(login_dialog).toBeVisible();
});
});
});
25 changes: 12 additions & 13 deletions src/features/Apiexplorer/SubscribeRenderer/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ function SubscribeRenderer<T extends TSocketSubscribableEndpointNames>({
reqData,
auth,
}: IResponseRendererProps<T>) {
const { is_logged_in, is_authorized } = useAuthContext();
const { is_logged_in, is_switching_account } = useAuthContext();
const { disableSendRequest } = useDisableSendRequest();
const { full_response, is_loading, subscribe, unsubscribe, is_subscribed, error } =
useSubscription<T>(name);
Expand All @@ -44,9 +44,8 @@ function SubscribeRenderer<T extends TSocketSubscribableEndpointNames>({
}, [is_subscribed]);

useEffect(() => {
const has_active_subscription = full_response !== undefined && !is_authorized;
if (has_active_subscription) unsubscribe();
}, [full_response, is_authorized]);
if (is_switching_account) unsubscribe();
}, [is_switching_account]);

const parseRequestJSON = useCallback(() => {
let request_data: TSocketRequestProps<T> extends never ? undefined : TSocketRequestProps<T>;
Expand Down Expand Up @@ -86,18 +85,18 @@ function SubscribeRenderer<T extends TSocketSubscribableEndpointNames>({
Clear
</Button>
</div>
{is_not_valid ? (
{is_not_valid && (
<ValidDialog setIsNotValid={setIsNotValid} setToggleModal={setToggleModal} />
) : !is_logged_in && auth == 1 && toggle_modal ? (
)}
{!is_logged_in && auth == 1 && toggle_modal && (
<LoginDialog setToggleModal={setToggleModal} />
) : (
<PlaygroundSection
loader={is_loading}
response_state={response_state}
full_response={full_response}
error={error}
/>
)}
<PlaygroundSection
loader={is_loading}
response_state={response_state}
full_response={full_response}
error={error}
/>
</div>
);
}
Expand Down