Skip to content

Commit

Permalink
feat: add increase decrease token percentage
Browse files Browse the repository at this point in the history
  • Loading branch information
salimtb committed Jun 27, 2024
1 parent 7b0aab4 commit b0acb00
Show file tree
Hide file tree
Showing 17 changed files with 914 additions and 210 deletions.
2 changes: 2 additions & 0 deletions .storybook/storybook.requires.js
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,8 @@ const getStories = () => {
'./app/component-library/components-temp/TagColored/TagColored.stories.tsx': require('../app/component-library/components-temp/TagColored/TagColored.stories.tsx'),
'./app/components/UI/Name/Name.stories.tsx': require('../app/components/UI/Name/Name.stories.tsx'),
"./app/components/UI/SimulationDetails/SimulationDetails.stories.tsx": require("../app/components/UI/SimulationDetails/SimulationDetails.stories.tsx"),
'./app/component-library/components-temp/Price/AggregatedPercentage/AggregatedPercentage.stories': require('../app/component-library/components-temp/Price/AggregatedPercentage/AggregatedPercentage.stories.js'),
'./app/component-library/components-temp/Price/PercentageChange/PercentageChange.stories': require('../app/component-library/components-temp/Price/PercentageChange/PercentageChange.stories.js'),
};
};

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import React from 'react';
import { Provider } from 'react-redux';
import AggregatedPercentage from './AggregatedPercentage';
import { createStore } from 'redux';
import initialBackgroundState from '../../../../util/test/initial-background-state.json';

const mockInitialState = {
wizard: {
step: 1,
},
engine: {
backgroundState: initialBackgroundState,
},
};

const rootReducer = (state = mockInitialState) => state;
const store = createStore(rootReducer);

export default {
title: 'Component Library / AggregatedPercentage',
component: AggregatedPercentage,
decorators: [
(Story) => (
<Provider store={store}>
<Story />
</Provider>
),
],
};

const Template = (args) => <AggregatedPercentage {...args} />;

export const Default = Template.bind({});
Default.args = {
ethFiat: 1000,
tokenFiat: 500,
tokenFiat1dAgo: 950,
ethFiat1dAgo: 450,
};

export const NegativePercentageChange = Template.bind({});
NegativePercentageChange.args = {
ethFiat: 900,
tokenFiat: 400,
tokenFiat1dAgo: 950,
ethFiat1dAgo: 1000,
};

export const PositivePercentageChange = Template.bind({});
PositivePercentageChange.args = {
ethFiat: 1100,
tokenFiat: 600,
tokenFiat1dAgo: 500,
ethFiat1dAgo: 1000,
};

export const MixedPercentageChange = Template.bind({});
MixedPercentageChange.args = {
ethFiat: 1050,
tokenFiat: 450,
tokenFiat1dAgo: 500,
ethFiat1dAgo: 1000,
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import React from 'react';
import { render } from '@testing-library/react-native';
import AggregatedPercentage from './AggregatedPercentage';
import { mockTheme } from '../../../../util/theme';
import { useSelector } from 'react-redux';
import { selectCurrentCurrency } from '../../../../selectors/currencyRateController';

jest.mock('react-redux', () => ({
...jest.requireActual('react-redux'),
useSelector: jest.fn(),
}));
describe('AggregatedPercentage', () => {
beforeEach(() => {
(useSelector as jest.Mock).mockImplementation((selector) => {
if (selector === selectCurrentCurrency) return 'USD';
});
});
afterEach(() => {
(useSelector as jest.Mock).mockClear();
});
it('should render correctly', () => {
const { toJSON } = render(
<AggregatedPercentage
ethFiat={100}
tokenFiat={100}
tokenFiat1dAgo={90}
ethFiat1dAgo={90}
/>,
);
expect(toJSON()).toMatchSnapshot();
});

it('renders positive percentage change correctly', () => {
const { getByText } = render(
<AggregatedPercentage
ethFiat={200}
tokenFiat={300}
tokenFiat1dAgo={250}
ethFiat1dAgo={150}
/>,
);

expect(getByText('(+25.00%)')).toBeTruthy();
expect(getByText('+100 USD')).toBeTruthy();

expect(getByText('(+25.00%)').props.style).toMatchObject({
color: mockTheme.colors.success.default,
textTransform: 'uppercase',
});
});

it('renders negative percentage change correctly', () => {
const { getByText } = render(
<AggregatedPercentage
ethFiat={150}
tokenFiat={200}
tokenFiat1dAgo={300}
ethFiat1dAgo={200}
/>,
);

expect(getByText('(-30.00%)')).toBeTruthy();
expect(getByText('-150 USD')).toBeTruthy();

expect(getByText('(-30.00%)').props.style).toMatchObject({
color: mockTheme.colors.error.default,
textTransform: 'uppercase',
});
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
import React from 'react';
import { fontStyles } from '../../../../styles/common';
import Text from '../../../../component-library/components/Texts/Text';
import { View, StyleSheet } from 'react-native';
import { useTheme } from '../../../../util/theme';
import { Colors } from '../../../../util/theme/models';
import { renderFiat } from '../../../../util/number';
import { useSelector } from 'react-redux';
import { selectCurrentCurrency } from '../../../../selectors/currencyRateController';

const createStyles = (colors: Colors) =>
StyleSheet.create({
wrapper: {
flexDirection: 'row',
alignItems: 'center',
},
balanceZeroStyle: {
color: colors.text.default,
...fontStyles.normal,
textTransform: 'uppercase',
},
balancePositiveStyle: {
color: colors.success.default,
...fontStyles.normal,
textTransform: 'uppercase',
},
balanceNegativeStyle: {
color: colors.error.default,
...fontStyles.normal,
textTransform: 'uppercase',
},
});

const isValidAmount = (amount: number | null | undefined): boolean =>
amount !== null && amount !== undefined && !Number.isNaN(amount);

const AggregatedPercentage = ({
ethFiat,
tokenFiat,
tokenFiat1dAgo,
ethFiat1dAgo,
}: {
ethFiat: number;
tokenFiat: number;
tokenFiat1dAgo: number;
ethFiat1dAgo: number;
}) => {
const { colors } = useTheme();
const styles = createStyles(colors);
const currentCurrency = useSelector(selectCurrentCurrency);
const DECIMALS_TO_SHOW = 2;

const totalBalance = ethFiat + tokenFiat;
const totalBalance1dAgo = ethFiat1dAgo + tokenFiat1dAgo;

const amountChange = totalBalance - totalBalance1dAgo;

const percentageChange =
((totalBalance - totalBalance1dAgo) / totalBalance1dAgo) * 100 || 0;

let percentageStyle = styles.balanceZeroStyle;

if (percentageChange === 0) {
percentageStyle = styles.balanceZeroStyle;
} else if (percentageChange > 0) {
percentageStyle = styles.balancePositiveStyle;
} else {
percentageStyle = styles.balanceNegativeStyle;
}

const formattedPercentage = isValidAmount(percentageChange)
? `(${(percentageChange as number) >= 0 ? '+' : ''}${(
percentageChange as number
).toFixed(2)}%)`
: '';

const formattedValuePrice = isValidAmount(amountChange)
? `${(amountChange as number) >= 0 ? '+' : ''}${renderFiat(
amountChange,
currentCurrency,
DECIMALS_TO_SHOW,
)} `
: '';

return (
<View style={styles.wrapper}>
<Text style={percentageStyle}>{formattedValuePrice}</Text>
<Text style={percentageStyle}>{formattedPercentage}</Text>
</View>
);
};

export default AggregatedPercentage;
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`AggregatedPercentage should render correctly 1`] = `
<View
style={
{
"alignItems": "center",
"flexDirection": "row",
}
}
>
<Text
accessibilityRole="text"
style={
{
"color": "#1c8234",
"fontFamily": "EuclidCircularB-Regular",
"fontSize": 14,
"fontWeight": "400",
"letterSpacing": 0,
"lineHeight": 22,
"textTransform": "uppercase",
}
}
>
+20 USD
</Text>
<Text
accessibilityRole="text"
style={
{
"color": "#1c8234",
"fontFamily": "EuclidCircularB-Regular",
"fontSize": 14,
"fontWeight": "400",
"letterSpacing": 0,
"lineHeight": 22,
"textTransform": "uppercase",
}
}
>
(+11.11%)
</Text>
</View>
`;
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default } from './AggregatedPercentage';
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import React from 'react';
import { Provider } from 'react-redux';
import PercentageChange from './PercentageChange';
import { createStore } from 'redux';
import initialBackgroundState from '../../../../util/test/initial-background-state.json';

const mockInitialState = {
wizard: {
step: 1,
},
engine: {
backgroundState: initialBackgroundState,
},
};

const rootReducer = (state = mockInitialState) => state;
const store = createStore(rootReducer);

export default {
title: 'Component Library / PercentageChange',
component: PercentageChange,
decorators: [
(Story) => (
<Provider store={store}>
<Story />
</Provider>
),
],
};

const Template = (args) => <PercentageChange {...args} />;

export const Default = Template.bind({});
Default.args = {
value: 0,
};

export const PositiveChange = Template.bind({});
PositiveChange.args = {
value: 5.5,
};

export const NegativeChange = Template.bind({});
NegativeChange.args = {
value: -3.75,
};

export const NoChange = Template.bind({});
NoChange.args = {
value: 0,
};

export const InvalidValue = Template.bind({});
InvalidValue.args = {
value: null,
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import React from 'react';
import { render } from '@testing-library/react-native';
import PercentageChange from './PercentageChange';
import { mockTheme } from '../../../../util/theme';

describe('PercentageChange', () => {
it('should render correctly', () => {
const { toJSON } = render(<PercentageChange value={5.5} />);
expect(toJSON()).toMatchSnapshot();
});
it('displays a positive value correctly', () => {
const { getByText } = render(<PercentageChange value={5.5} />);
const positiveText = getByText('+5.50%');
expect(positiveText).toBeTruthy();
expect(positiveText.props.style).toMatchObject({
color: mockTheme.colors.success.default,
textTransform: 'uppercase',
});
});

it('displays a negative value correctly', () => {
const { getByText } = render(<PercentageChange value={-3.25} />);
const negativeText = getByText('-3.25%');
expect(negativeText).toBeTruthy();
expect(negativeText.props.style).toMatchObject({
color: mockTheme.colors.error.default,
textTransform: 'uppercase',
});
});

it('handles null value correctly', () => {
const { queryByText } = render(<PercentageChange value={null} />);
expect(queryByText(/\+/)).toBeNull();
expect(queryByText(/-/)).toBeNull();
});

it('handles undefined value correctly', () => {
const { queryByText } = render(<PercentageChange value={undefined} />);
expect(queryByText(/\+/)).toBeNull();
expect(queryByText(/-/)).toBeNull();
});
});
Loading

0 comments on commit b0acb00

Please sign in to comment.