Skip to content
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 .yarnrc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ enableScripts: false
nodeLinker: node-modules

npmAuditIgnoreAdvisories:
- 1109627 # TODO: Upgrade @react-native-community/cli to 17.0.1+ when ready. Suppressing for now to unblock CI.

yarnPath: .yarn/releases/yarn-4.10.3.cjs

Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,32 @@
import React, { useRef, useEffect } from 'react';
import { render, fireEvent, act } from '@testing-library/react-native';
import { InteractionManager } from 'react-native';

// Internal dependencies
import PredictConsentSheet, {
PredictConsentSheetRef,
} from './PredictConsentSheet';
import { usePredictAgreement } from '../../hooks/usePredictAgreement';

const mockNavigate = jest.fn();
const runAfterInteractionsCallbacks: (() => void)[] = [];
const mockRunAfterInteractions = jest.spyOn(
InteractionManager,
'runAfterInteractions',
);
const runAfterInteractionsMockImpl: typeof InteractionManager.runAfterInteractions =
(task) => {
if (typeof task === 'function') {
runAfterInteractionsCallbacks.push(task as () => void);
}

return {
then: jest.fn(),
done: jest.fn(),
cancel: jest.fn(),
} as ReturnType<typeof InteractionManager.runAfterInteractions>;
};

// Mock dependencies
jest.mock('react-native/Libraries/Linking/Linking', () => ({
openURL: jest.fn(),
Expand Down Expand Up @@ -36,7 +56,7 @@ jest.mock('@metamask/design-system-twrnc-preset', () => ({

jest.mock('@react-navigation/native', () => ({
useNavigation: () => ({
navigate: jest.fn(),
navigate: mockNavigate,
goBack: jest.fn(),
}),
}));
Expand Down Expand Up @@ -184,14 +204,21 @@ describe('PredictConsentSheet', () => {

beforeEach(() => {
jest.clearAllMocks();
runAfterInteractionsCallbacks.length = 0;
mockRunAfterInteractions.mockImplementation(runAfterInteractionsMockImpl);
(usePredictAgreement as jest.Mock).mockReturnValue({
isAgreementAccepted: false,
acceptAgreement: mockAcceptAgreement,
});
});

afterEach(() => {
jest.resetAllMocks();
jest.clearAllMocks();
mockRunAfterInteractions.mockReset();
});

afterAll(() => {
mockRunAfterInteractions.mockRestore();
});

describe('visibility behavior', () => {
Expand Down Expand Up @@ -526,4 +553,79 @@ describe('PredictConsentSheet', () => {
expect(customAcceptAgreement).toHaveBeenCalledTimes(1);
});
});

describe('Terms Link', () => {
it('renders learn more text', () => {
const TestComponent = () => {
const ref = useRef<PredictConsentSheetRef>(null);

useEffect(() => {
act(() => {
ref.current?.onOpenBottomSheet();
});
}, []);

return (
<PredictConsentSheet
ref={ref}
providerId={mockProviderId}
onDismiss={mockOnDismiss}
onAgree={mockOnAgree}
/>
);
};

const { getByText } = render(<TestComponent />);

expect(getByText('Learn more')).toBeOnTheScreen();
});

it('navigates to polymarket terms webview when description is pressed', () => {
const TestComponent = () => {
const ref = useRef<PredictConsentSheetRef>(null);

useEffect(() => {
act(() => {
ref.current?.onOpenBottomSheet();
});
}, []);

return (
<PredictConsentSheet
ref={ref}
providerId={mockProviderId}
onDismiss={mockOnDismiss}
onAgree={mockOnAgree}
/>
);
};

const { getByText } = render(<TestComponent />);

const learnMoreText = getByText('Learn more');
const touchableParent = learnMoreText.parent;

expect(touchableParent).toBeTruthy();

act(() => {
if (touchableParent) {
fireEvent.press(touchableParent);
}
});

expect(mockRunAfterInteractions).toHaveBeenCalledTimes(1);
const callback = runAfterInteractionsCallbacks[0];
expect(callback).toBeDefined();

callback?.();

expect(mockNavigate).toHaveBeenCalledWith('Webview', {
screen: 'SimpleWebview',
params: {
url: 'https://polymarket.com/tos',
title: 'Terms and Conditions',
},
});
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ import Text, {
TextVariant,
} from '../../../../../component-library/components/Texts/Text';
import { useTailwind } from '@metamask/design-system-twrnc-preset';
import React, { forwardRef, useImperativeHandle } from 'react';
import { Linking } from 'react-native';
import React, { forwardRef, useCallback, useImperativeHandle } from 'react';
import { InteractionManager, TouchableOpacity } from 'react-native';
import { strings } from '../../../../../../locales/i18n';

// Internal dependencies.
Expand All @@ -19,6 +19,7 @@ import {
usePredictBottomSheet,
type PredictBottomSheetRef,
} from '../../hooks/usePredictBottomSheet';
import { useNavigation } from '@react-navigation/native';

interface PredictConsentSheetProps {
providerId: string;
Expand All @@ -33,6 +34,7 @@ const PredictConsentSheet = forwardRef<
PredictConsentSheetProps
>(({ providerId, onDismiss, onAgree }, ref) => {
const tw = useTailwind();
const navigation = useNavigation();
const { acceptAgreement } = usePredictAgreement({ providerId });
const { sheetRef, isVisible, closeSheet, handleSheetClosed, getRefHandlers } =
usePredictBottomSheet({ onDismiss });
Expand All @@ -49,6 +51,18 @@ const PredictConsentSheet = forwardRef<

useImperativeHandle(ref, getRefHandlers, [getRefHandlers]);

const handlePolymarketTerms = useCallback(() => {
InteractionManager.runAfterInteractions(() => {
navigation.navigate('Webview', {
screen: 'SimpleWebview',
params: {
url: 'https://polymarket.com/tos',
title: strings('predict.consent_sheet.title'),
},
});
});
}, [navigation]);

if (!isVisible) {
return null;
}
Expand All @@ -66,19 +80,18 @@ const PredictConsentSheet = forwardRef<
</Text>
</BottomSheetHeader>
<Box twClassName="px-6 pb-6">
<Text variant={TextVariant.BodyMD} color={TextColor.Alternative}>
{strings('predict.consent_sheet.description')}{' '}
</Text>
<Text
variant={TextVariant.BodyMD}
style={tw.style('text-info-default')}
onPress={() => {
Linking.openURL('https://polymarket.com/tos');
}}
suppressHighlighting
>
{strings('predict.consent_sheet.learn_more')}
</Text>
<TouchableOpacity onPress={handlePolymarketTerms}>
<Text variant={TextVariant.BodyMD} color={TextColor.Alternative}>
{strings('predict.consent_sheet.description')}{' '}
<Text
variant={TextVariant.BodyMD}
style={tw.style('text-info-default')}
suppressHighlighting
>
{strings('predict.consent_sheet.learn_more')}
</Text>
</Text>
</TouchableOpacity>
</Box>
<BottomSheetFooter
buttonPropsArray={[
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -164,9 +164,10 @@ describe('PredictDetailsChart', () => {
});

it('renders loading state when isLoading is true', () => {
const { getByText } = setupTest({ isLoading: true });
const { getByTestId } = setupTest({ isLoading: true });

expect(getByText('Loading price history...')).toBeOnTheScreen();
const lineChart = getByTestId('line-chart');
expect(lineChart).toBeOnTheScreen();
});

it('renders empty state when no data provided', () => {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React from 'react';
import { StyleSheet } from 'react-native';
import { StyleSheet, ActivityIndicator } from 'react-native';
import { LineChart } from 'react-native-svg-charts';
import { useTailwind } from '@metamask/design-system-twrnc-preset';
import {
Expand Down Expand Up @@ -97,15 +97,6 @@ const PredictDetailsChart: React.FC<PredictDetailsChartProps> = ({

const renderGraph = () => {
if (isLoading || !hasData) {
const placeholderLabel = isLoading
? 'Loading price history...'
: emptyLabel;
const placeholderAxisLabel = isLoading ? 'Loading...' : '\u00A0';
const placeholderLabels = Array.from(
{ length: 4 },
() => placeholderAxisLabel,
);

return (
<Box twClassName="mb-6">
{isMultipleSeries && (
Expand All @@ -125,26 +116,23 @@ const PredictDetailsChart: React.FC<PredictDetailsChartProps> = ({
<ChartGrid colors={colors} range={range} />
</LineChart>
<Box twClassName="absolute inset-0 items-center justify-center px-4">
<Text variant={TextVariant.BodyMD} color={TextColor.Alternative}>
{placeholderLabel}
</Text>
{isLoading ? (
<ActivityIndicator color={colors.primary.alternative} />
) : (
<Text
variant={TextVariant.BodyMD}
color={TextColor.Alternative}
>
{emptyLabel}
</Text>
)}
</Box>
</Box>
<Box
flexDirection={BoxFlexDirection.Row}
justifyContent={BoxJustifyContent.Between}
twClassName="px-4 pt-4 pb-0"
>
{placeholderLabels.map((label, index) => (
<Text
key={`placeholder-${index}`}
variant={TextVariant.BodyXS}
color={TextColor.Alternative}
>
{label}
</Text>
))}
</Box>
twClassName="px-4 pt-4 pb-0 min-h-[31px]"
/>
</Box>
);
}
Expand All @@ -163,11 +151,11 @@ const PredictDetailsChart: React.FC<PredictDetailsChartProps> = ({
);

return (
<Box twClassName="mb-6">
<Box twClassName="mb-4">
{isMultipleSeries && (
<ChartLegend series={nonEmptySeries} range={range} />
)}
<Box twClassName="h-48 bg-default rounded-lg mb-4 relative overflow-hidden">
<Box twClassName="h-48 bg-default rounded-lg mb-3 relative overflow-hidden">
<LineChart
style={tw.style(`h-[${CHART_HEIGHT}px] w-full`)}
data={primaryChartData}
Expand Down Expand Up @@ -213,8 +201,8 @@ const PredictDetailsChart: React.FC<PredictDetailsChartProps> = ({
{axisLabels.map((point, index) => (
<Text
key={`${point.timestamp}-${index}`}
variant={TextVariant.BodyXS}
color={TextColor.Alternative}
style={tw.style('text-[11px]')}
>
{point.label}
</Text>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ const ChartArea: React.FC<ChartAreaProps> = ({
<LinearGradient id="gradient" x1="0%" y1="0%" x2="0%" y2="100%">
<Stop offset="0%" stopColor={color} stopOpacity={opacity} />
<Stop offset="45%" stopColor={color} stopOpacity={opacity * 0.4} />
<Stop offset="100%" stopColor={color} stopOpacity="0" />
<Stop offset="95%" stopColor={color} stopOpacity="0" />
</LinearGradient>
</Defs>
<Path d={areaPath} fill="url(#gradient)" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ const ChartGrid: React.FC<ChartGridProps> = ({
{ticks.map((tick: number, index: number) => (
<Line
key={`grid-${tick}-${index}`}
x1={0}
x1={8}
x2={x(lastIndex)}
y1={y(tick)}
y2={y(tick)}
Expand All @@ -41,9 +41,9 @@ const ChartGrid: React.FC<ChartGridProps> = ({
<SvgText
key={`label-${tick}-${index}`}
x={x(lastIndex) + 4}
y={y(tick)}
y={y(tick) - 4}
fontSize="12"
fill={colors.text.default}
fill={colors.text.alternative}
textAnchor="start"
alignmentBaseline="middle"
>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ const ChartLegend: React.FC<ChartLegendProps> = ({ series, range }) => {
<Box
flexDirection={BoxFlexDirection.Row}
alignItems={BoxAlignItems.Center}
twClassName="px-4 mb-3 flex-wrap"
twClassName="px-4 mb-2 flex-wrap"
>
{series.map((seriesItem, index) => {
const lastPoint = seriesItem.data[seriesItem.data.length - 1];
Expand Down
Loading
Loading