Skip to content
This repository was archived by the owner on May 13, 2024. It is now read-only.

Hubert / Response object incomplete #134

Merged
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
3 changes: 1 addition & 2 deletions src/features/Apiexplorer/LoginDialog/index.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import React, { useCallback } from 'react';
import { Modal } from '@deriv/ui';
import { Modal, Button } from '@deriv/ui';
import useLoginUrl from '@site/src/hooks/useLoginUrl';
import { Button } from '@deriv/ui';
import styles from './LoginDialog.module.scss';

type TLoginDialog = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,39 @@ import '@testing-library/jest-dom';
import { cleanup, render, screen } from '@testing-library/react';
import { TSocketEndpointNames } from '@site/src/configs/websocket/types';
import useAuthContext from '@site/src/hooks/useAuthContext';
import useSubscription from '@site/src/hooks/useSubscription';
import useWS from '@site/src/hooks/useWs';
import { IAuthContext } from '@site/src/contexts/auth/auth.context';
import userEvent from '@testing-library/user-event';
import RequestJSONBox from '..';

const fakeHookObject = {
clear: jest.fn(),
send: jest.fn(),
full_response: {
tick: 1,
echo_req: { tick: 1 },
},
};

jest.mock('@site/src/hooks/useAuthContext');

const mockUseAuthContext = useAuthContext as jest.MockedFunction<() => Partial<IAuthContext>>;

jest.mock('@site/src/hooks/useSubscription');

const mockUseSubscription = useSubscription as jest.MockedFunction<
() => Partial<ReturnType<typeof useSubscription>>
>;

mockUseSubscription.mockImplementation(() => fakeHookObject);

jest.mock('@site/src/hooks/useWs');

const mockuseWS = useWS as jest.MockedFunction<() => Partial<ReturnType<typeof useWS>>>;

mockuseWS.mockImplementation(() => fakeHookObject);

describe('RequestResponseRenderer', () => {
const mockProps = {
handleChange: jest.fn(),
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
@use 'src/styles/utility' as *;

.reactJsonContainer {
display: flex;
flex-direction: column;
gap: rem(2);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import React from 'react';
import styles from './JsonData.module.scss';
import {
TSocketEndpointNames,
TSocketSubscribableEndpointNames,
TSocketResponse,
} from '@site/src/configs/websocket/types';

const ReactJson = React.lazy(() => import('react-json-view'));

type TJsonData<T extends TSocketEndpointNames> = {
full_response: TSocketResponse<T>;
error: unknown;
name: string;
};

const JsonData = <T extends TSocketEndpointNames | TSocketSubscribableEndpointNames>({
full_response,
error,
}: TJsonData<T>) => {
return (
<React.Fragment>
{full_response !== null ? (
<div className={styles.reactJsonContainer}>
<ReactJson src={full_response.echo_req} theme='tube' />
<ReactJson src={full_response} theme='tube' />
</div>
) : (
<ReactJson src={{ error }} theme='tube' />
)}
</React.Fragment>
);
};

export default JsonData;
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,31 @@ import { render, screen } from '@testing-library/react';

describe('PlaygroundSection', () => {
it('should render the loader', async () => {
render(<PlaygroundSection loader response_state={false} data={null} error={null} />);
render(
<PlaygroundSection loader response_state={false} full_response={null} error={null} name='' />,
);
const loader = await screen.findByTestId('circles-loading');
expect(loader).toBeVisible();
});

it('should render the PlaygroundConsole', async () => {
render(<PlaygroundSection loader={false} response_state={false} data={null} error={null} />);
render(
<PlaygroundSection
loader={false}
response_state={false}
full_response={null}
error={null}
name=''
/>,
);
const playground_section = await screen.findByTestId('dt_playground_section');
expect(playground_section).toBeVisible();
});

it('should render the ReactJson', async () => {
render(<PlaygroundSection loader={false} response_state data={null} error={null} />);
render(
<PlaygroundSection loader={false} response_state full_response={null} error={null} name='' />,
);

const playground_section = await screen.findByTestId('dt_playground_section');
expect(playground_section).toBeVisible();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,26 +1,27 @@
import React, { Suspense } from 'react';
import {
TSocketEndpointNames,
TSocketResponseData,
TSocketSubscribableEndpointNames,
TSocketResponse,
} from '@site/src/configs/websocket/types';
import JsonData from './JsonData';
import Loader from '@site/src/components/Loader';
import styles from './PlaygroundSection.module.scss';

const ReactJson = React.lazy(() => import('react-json-view'));

type TPlaygroundSection<T extends TSocketEndpointNames> = {
loader: boolean;
response_state: boolean;
data: TSocketResponseData<T>;
full_response: TSocketResponse<T>;
error: unknown;
name: string;
};

const PlaygroundSection = <T extends TSocketEndpointNames | TSocketSubscribableEndpointNames>({
loader,
response_state,
data,
full_response,
error,
name,
}: TPlaygroundSection<T>) => {
if (loader) return <Loader />;

Expand All @@ -34,11 +35,7 @@ const PlaygroundSection = <T extends TSocketEndpointNames | TSocketSubscribableE
<React.Fragment>
<Suspense fallback={<Loader />}>
<div data-testid='dt_json_view'>
{data !== null ? (
<ReactJson src={{ data }} theme='tube' />
) : (
<ReactJson src={{ error }} theme='tube' />
)}
<JsonData full_response={full_response} name={name} error={error} />
</div>
</Suspense>
</React.Fragment>
Expand Down
5 changes: 3 additions & 2 deletions src/features/Apiexplorer/RequestResponseRenderer/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ function RequestResponseRenderer<T extends TSocketEndpointNames>({
}: IResponseRendererProps<T>) {
const { is_logged_in } = useAuthContext();
const { disableSendRequest } = useDisableSendRequest();
const { data, is_loading, send, clear, error } = useWS<T>(name);
const { full_response, is_loading, send, clear, error } = useWS<T>(name);
const [toggle_modal, setToggleModal] = useState(false);
const [response_state, setResponseState] = useState(false);

Expand Down Expand Up @@ -66,8 +66,9 @@ function RequestResponseRenderer<T extends TSocketEndpointNames>({
<PlaygroundSection
loader={is_loading}
response_state={response_state}
data={data}
full_response={full_response}
error={error}
name={name}
/>
)}
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,10 @@ mockUseSubscription.mockImplementation(() => ({
subscribe: mockSubscribe,
unsubscribe: mockUnsubscribe,
error: 'random error',
full_response: {
tick: 1,
echo_req: { tick: 1 },
},
}));

const request_data = `{
Expand Down Expand Up @@ -96,13 +100,19 @@ describe('SubscribeRenderer', () => {
expect(mockUnsubscribe).toBeCalledTimes(1);
});

it('should throw an error if incorrect json is being parsed', () => {
it('should throw an error if incorrect json is being parsed', async () => {
const consoleOutput = [];
const mockedError = (output) => consoleOutput.push(output);
console.error = mockedError;

render(<SubscribeRenderer name='ticks' auth={1} reqData={'asdawefaewf3232'} />);

expect(consoleOutput[0]).toEqual('something went wrong when parsing the json data: ');
const send_request_button = screen.getByRole('button', { name: 'Send Request' });

await userEvent.click(send_request_button);

expect(consoleOutput[0]).toEqual(
'Could not parse the JSON data while trying to send the request: ',
);
});
});
30 changes: 19 additions & 11 deletions src/features/Apiexplorer/SubscribeRenderer/index.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
import React, { useState, useCallback, useEffect } from 'react';
import { TSocketSubscribableEndpointNames } from '@site/src/configs/websocket/types';
import {
TSocketSubscribableEndpointNames,
TSocketRequestProps,
} from '@site/src/configs/websocket/types';
import { Button } from '@deriv/ui';
import styles from '../RequestJSONBox/RequestJSONBox.module.scss';
import useAuthContext from '@site/src/hooks/useAuthContext';
Expand All @@ -21,7 +24,7 @@ function SubscribeRenderer<T extends TSocketSubscribableEndpointNames>({
}: IResponseRendererProps<T>) {
const { is_logged_in } = useAuthContext();
const { disableSendRequest } = useDisableSendRequest();
const { data, is_loading, subscribe, unsubscribe, error } = useSubscription<T>(name);
const { full_response, is_loading, subscribe, unsubscribe, error } = useSubscription<T>(name);
const [response_state, setResponseState] = useState(false);
const [toggle_modal, setToggleModal] = useState(false);

Expand All @@ -31,17 +34,21 @@ function SubscribeRenderer<T extends TSocketSubscribableEndpointNames>({
}
}, [error]);

let json_data;
try {
json_data = JSON.parse(reqData);
} catch (error) {
json_data = '';
console.error('something went wrong when parsing the json data: ', error);
}
const parseRequestJSON = () => {
let json_data: TSocketRequestProps<T> extends never ? undefined : TSocketRequestProps<T>;

try {
json_data = JSON.parse(reqData);
} catch (error) {
console.error('Could not parse the JSON data while trying to send the request: ', error);
}

return json_data;
};

const handleClick = useCallback(() => {
unsubscribe();
subscribe(json_data);
subscribe(parseRequestJSON());
setResponseState(true);
}, [reqData, subscribe, unsubscribe]);

Expand All @@ -66,8 +73,9 @@ function SubscribeRenderer<T extends TSocketSubscribableEndpointNames>({
<PlaygroundSection
loader={is_loading}
response_state={response_state}
data={data}
full_response={full_response}
error={error}
name={name}
/>
)}
</div>
Expand Down
4 changes: 4 additions & 0 deletions src/features/Apiexplorer/__tests__/ApiExplorer.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,10 @@ const mockClear = jest.fn();
mockuseWS.mockImplementation(() => ({
clear: mockClear,
send: jest.fn(),
full_response: {
tick: 1,
echo_req: { tick: 1 },
},
}));

jest.mock('@site/src/hooks/useDynamicImportJSON');
Expand Down
4 changes: 3 additions & 1 deletion src/hooks/useSubscription/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,14 @@ const useSubscription = <T extends TSocketSubscribableEndpointNames>(name: T) =>
const [is_subscribed, setSubscribed] = useState(false);
const [error, setError] = useState<unknown>();
const [data, setData] = useState<TSocketResponseData<T>>();
const [full_response, setFullResponse] = useState<TSocketResponse<T>>();
const [subscriber, setSubscriber] = useState<{ unsubscribe?: VoidFunction }>();

const onData = useCallback(
(response: TSocketResponse<T>) => {
const key = response['msg_type'] ?? name;
setData(response[key] as TSocketResponseData<T>);
setFullResponse(response);
setIsLoading(false);
},
[name],
Expand All @@ -41,7 +43,7 @@ const useSubscription = <T extends TSocketSubscribableEndpointNames>(name: T) =>
setSubscribed(false);
}, [subscriber]);

return { subscribe, unsubscribe, is_loading, is_subscribed, error, data };
return { subscribe, unsubscribe, is_loading, is_subscribed, error, data, full_response };
};

export default useSubscription;
11 changes: 9 additions & 2 deletions src/hooks/useWs/index.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,21 @@
import apiManager from '@site/src/configs/websocket';
import { TSocketEndpointNames, TSocketResponseData } from '@site/src/configs/websocket/types';
import {
TSocketEndpointNames,
TSocketResponse,
TSocketResponseData,
} from '@site/src/configs/websocket/types';
import { useCallback, useState } from 'react';

const useWS = <T extends TSocketEndpointNames>(name: T) => {
const [is_loading, setIsLoading] = useState(false);
const [error, setError] = useState<unknown>();
const [data, setData] = useState<TSocketResponseData<T>>();
const [full_response, setFullResponse] = useState<TSocketResponse<T>>();

const clear = useCallback(() => {
setError(null);
setData(null);
setFullResponse(null);
}, []);

const send = useCallback(
Expand All @@ -19,6 +25,7 @@ const useWS = <T extends TSocketEndpointNames>(name: T) => {
const response = await apiManager.augmentedSend(name, data);
const key = response['msg_type'] ?? name;
setData(response[key] as TSocketResponseData<T>);
setFullResponse(response);
} catch (e) {
setError(e);
} finally {
Expand All @@ -28,7 +35,7 @@ const useWS = <T extends TSocketEndpointNames>(name: T) => {
[name],
);

return { send, is_loading, error, data, clear };
return { send, full_response, is_loading, error, data, clear };
};

export default useWS;