chore: add back telemetry approval - refactor a solution

This commit is contained in:
maciek
2023-08-29 13:00:20 +02:00
parent 58c91db560
commit 3964acc3ac
6 changed files with 98 additions and 74 deletions
@@ -24,8 +24,8 @@ export const Settings = () => {
>
<Switch
name="settings-telemetry-switch"
onCheckedChange={(isOn) => setIsApproved(isOn)}
checked={isApproved}
onCheckedChange={(isOn) => setIsApproved(isOn ? 'true' : 'false')}
checked={isApproved === 'true'}
/>
</SettingsGroup>
<SettingsGroup label={t('Toast location')}>
@@ -2,29 +2,35 @@ import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { TelemetryApproval } from './telemetry-approval';
jest.mock('@vegaprotocol/logger', () => ({
SentryInit: () => undefined,
SentryClose: () => undefined,
}));
jest.mock('@vegaprotocol/environment', () => ({
useEnvironment: () => ({ VEGA_ENV: 'test', SENTRY_DSN: 'sentry-dsn' }),
}));
describe('TelemetryApproval', () => {
it('click on checkbox should be properly handled', async () => {
const helpText = 'My help text';
render(<TelemetryApproval helpText={helpText} />);
expect(screen.getByRole('checkbox')).toHaveAttribute(
'data-state',
'unchecked'
it('click on buttons should be properly handled', async () => {
const mockSetTelemetryValue = jest.fn();
render(
<TelemetryApproval
telemetryValue="false"
setTelemetryValue={mockSetTelemetryValue}
/>
);
await userEvent.click(screen.getByRole('checkbox'));
expect(screen.getByRole('checkbox')).toHaveAttribute(
'data-state',
'checked'
expect(
screen.getByRole('button', { name: 'No thanks' })
).toBeInTheDocument();
await userEvent.click(screen.getByRole('button', { name: 'No thanks' }));
expect(mockSetTelemetryValue).toHaveBeenCalledWith('false');
expect(screen.getByText('Share data')).toBeInTheDocument();
await userEvent.click(screen.getByText('Share data'));
expect(mockSetTelemetryValue).toHaveBeenCalledWith('true');
});
it('confirm button should have proper text', async () => {
const mockSetTelemetryValue = jest.fn();
render(
<TelemetryApproval
telemetryValue="true"
setTelemetryValue={mockSetTelemetryValue}
/>
);
expect(screen.getByText('Share usage data')).toBeInTheDocument();
expect(screen.getByText(helpText)).toBeInTheDocument();
expect(screen.getByText('Continue sharing data')).toBeInTheDocument();
await userEvent.click(screen.getByText('Continue sharing data'));
expect(mockSetTelemetryValue).toHaveBeenCalledWith('true');
});
});
@@ -2,11 +2,14 @@ import { Button, Icon } from '@vegaprotocol/ui-toolkit';
import { t } from '@vegaprotocol/i18n';
interface Props {
isApproved: string;
setApproved: (value: string) => void;
telemetryValue: string;
setTelemetryValue: (value: string) => void;
}
export const TelemetryApproval = ({ isApproved, setApproved }: Props) => {
export const TelemetryApproval = ({
telemetryValue,
setTelemetryValue,
}: Props) => {
return (
<div className="flex flex-col py-3">
<div className="mr-4" role="form">
@@ -32,7 +35,7 @@ export const TelemetryApproval = ({ isApproved, setApproved }: Props) => {
</div>
<div className="flex justify-around items-center mt-10 gap-4 w-full">
<Button
onClick={() => setApproved('false')}
onClick={() => setTelemetryValue('false')}
variant="default"
data-testid="do-not-share-data-button"
>
@@ -40,11 +43,11 @@ export const TelemetryApproval = ({ isApproved, setApproved }: Props) => {
</Button>
<Button
onClick={() => setApproved('true')}
onClick={() => setTelemetryValue('true')}
variant="primary"
data-testid="share-data-button"
>
{isApproved === 'true'
{telemetryValue === 'true'
? t('Continue sharing data')
: t('Share data')}
</Button>
@@ -1,4 +1,3 @@
import React, { useCallback, useEffect } from 'react';
import { useNavigate } from 'react-router-dom';
import { Dialog, Intent } from '@vegaprotocol/ui-toolkit';
import { t } from '@vegaprotocol/i18n';
@@ -16,19 +15,8 @@ import { TelemetryApproval } from './telemetry-approval';
import { useTelemetryApproval } from '../../lib/hooks/use-telemetry-approval';
export const WelcomeDialog = () => {
const [
telemetryOn,
setTelemetryOn,
defaultTelemetryValue,
isTelemetryNeeded,
closeTelemetry,
] = useTelemetryApproval();
useEffect(() => {
if (!telemetryOn) {
setTelemetryOn(defaultTelemetryValue);
}
}, [telemetryOn, setTelemetryOn, defaultTelemetryValue]);
const [telemetryValue, setTelemetryValue, isTelemetryNeeded, closeTelemetry] =
useTelemetryApproval();
const { VEGA_ENV } = useEnvironment();
const [onBoardingViewed] = useLocalStorage(constants.ONBOARDING_VIEWED_KEY);
const update = useGlobalStore((store) => store.update);
@@ -43,17 +31,9 @@ export const WelcomeDialog = () => {
!dismissed;
const marketId = useGlobalStore((store) => store.marketId);
const setApproved = useCallback(
(value: string) => {
setTelemetryOn(value);
closeTelemetry();
},
[setTelemetryOn, closeTelemetry]
);
const onClose = () => {
if (isTelemetryNeeded) {
setApproved(telemetryOn || defaultTelemetryValue);
closeTelemetry();
} else {
const link = marketId
? Links[Routes.MARKET](marketId)
@@ -78,7 +58,10 @@ export const WelcomeDialog = () => {
);
const content = isTelemetryNeeded ? (
<TelemetryApproval isApproved={telemetryOn} setApproved={setApproved} />
<TelemetryApproval
telemetryValue={telemetryValue}
setTelemetryValue={setTelemetryValue}
/>
) : isOnboardingDialogNeeded ? (
<WelcomeDialogContent />
) : null;
@@ -2,18 +2,22 @@ import { renderHook, act, waitFor } from '@testing-library/react';
import { useLocalStorage } from '@vegaprotocol/react-helpers';
import { SentryInit, SentryClose } from '@vegaprotocol/logger';
import { STORAGE_KEY, useTelemetryApproval } from './use-telemetry-approval';
import { Networks } from '@vegaprotocol/environment';
const mockSetValue = jest.fn();
const mockRemoveValue = jest.fn();
let mockStorageHookResult = [null, mockSetValue];
jest.mock('@vegaprotocol/logger');
jest.mock('@vegaprotocol/react-helpers', () => ({
...jest.requireActual('@vegaprotocol/react-helpers'),
useLocalStorage: jest
.fn()
.mockImplementation(() => [false, mockSetValue, mockRemoveValue]),
useLocalStorage: jest.fn().mockImplementation(() => mockStorageHookResult),
}));
let mockVegaEnv = 'test';
jest.mock('@vegaprotocol/environment', () => ({
useEnvironment: () => ({ VEGA_ENV: 'test', SENTRY_DSN: 'sentry-dsn' }),
...jest.requireActual('@vegaprotocol/environment'),
useEnvironment: jest.fn(() => ({
VEGA_ENV: mockVegaEnv,
SENTRY_DSN: 'sentry-dsn',
})),
}));
describe('useTelemetryApproval', () => {
@@ -21,32 +25,53 @@ describe('useTelemetryApproval', () => {
jest.clearAllMocks();
});
it('hook should return proper array', () => {
it('when empty hook should return proper array', () => {
const { result } = renderHook(() => useTelemetryApproval());
expect(result.current[0]).toEqual(false);
expect(result.current[0]).toEqual('');
expect(result.current[1]).toEqual(expect.any(Function));
expect(result.current[2]).toEqual(true);
expect(result.current[3]).toEqual(expect.any(Function));
expect(useLocalStorage).toHaveBeenCalledWith(STORAGE_KEY);
expect(mockSetValue).toHaveBeenCalledWith('true');
});
it('when NOT empty hook should return proper array', () => {
mockStorageHookResult = ['false', mockSetValue];
const { result } = renderHook(() => useTelemetryApproval());
expect(result.current[0]).toEqual('false');
expect(result.current[1]).toEqual(expect.any(Function));
expect(result.current[2]).toEqual(false);
expect(result.current[3]).toEqual(expect.any(Function));
expect(useLocalStorage).toHaveBeenCalledWith(STORAGE_KEY);
expect(mockSetValue).not.toHaveBeenCalled();
});
it('on mainnet hook should init properly', () => {
mockStorageHookResult = [null, mockSetValue];
mockVegaEnv = Networks.MAINNET;
renderHook(() => useTelemetryApproval());
expect(mockSetValue).toHaveBeenCalledWith('false');
});
it('hook should init stuff properly', async () => {
const { result } = renderHook(() => useTelemetryApproval());
await act(() => {
result.current[1](true);
result.current[1]('true');
});
await waitFor(() => {
expect(SentryInit).toHaveBeenCalled();
expect(mockSetValue).toHaveBeenCalledWith('1');
expect(mockSetValue).toHaveBeenCalledWith('true');
});
});
it('hook should close stuff properly', async () => {
const { result } = renderHook(() => useTelemetryApproval());
await act(() => {
result.current[1](false);
result.current[1]('false');
});
await waitFor(() => {
expect(SentryClose).toHaveBeenCalled();
expect(mockRemoveValue).toHaveBeenCalledWith();
expect(mockSetValue).toHaveBeenCalledWith('false');
});
});
});
@@ -1,13 +1,13 @@
import { useLocalStorage } from '@vegaprotocol/react-helpers';
import { useCallback, useEffect, useRef, useState } from 'react';
import { useCallback, useEffect, useState } from 'react';
import { SentryInit, SentryClose } from '@vegaprotocol/logger';
import { Networks, useEnvironment } from '@vegaprotocol/environment';
export const STORAGE_KEY = 'vega_telemetry_approval';
export const useTelemetryApproval = (): [
value: string,
setValue: (value: string) => void,
defaultValue: string,
shouldOpen: boolean,
close: () => void
] => {
@@ -16,16 +16,10 @@ export const useTelemetryApproval = (): [
VEGA_ENV === Networks.MAINNET ? 'false' : 'true';
const [value, setValue] = useLocalStorage(STORAGE_KEY);
const [shouldOpen, setShouldOpen] = useState(!value);
const valueRef = useRef(Boolean(value));
useEffect(() => {
if (!valueRef.current) {
setShouldOpen(true);
}
}, []);
const close = useCallback(() => {
setShouldOpen(false);
}, []);
const setApprove = useCallback(
const manageValue = useCallback(
(value: string) => {
if (value === 'true' && SENTRY_DSN) {
SentryInit(SENTRY_DSN, VEGA_ENV);
@@ -36,5 +30,18 @@ export const useTelemetryApproval = (): [
},
[setValue, SENTRY_DSN, VEGA_ENV]
);
return [value || '', setApprove, defaultTelemetryValue, shouldOpen, close];
const setTelemetryValue = useCallback(
(value: string) => {
setShouldOpen(false);
manageValue(value);
},
[manageValue]
);
useEffect(() => {
if (!value) {
manageValue(defaultTelemetryValue);
}
}, [value, manageValue, defaultTelemetryValue]);
return [value || '', setTelemetryValue, shouldOpen, close];
};