From f7f4bd565859bba22f95ac57c4377908e3a8fe69 Mon Sep 17 00:00:00 2001 From: louis Date: Tue, 24 Oct 2023 15:15:37 +0200 Subject: [PATCH] =?UTF-8?q?=F0=9F=90=9B=20Fix=20TickersDropdown?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/api/User.ts | 3 +- .../ticker/TickersDropdown.test.tsx | 53 +++++++++++++++++++ src/components/ticker/TickersDropdown.tsx | 47 ++++++++++------ src/components/user/UserForm.tsx | 3 +- 4 files changed, 87 insertions(+), 19 deletions(-) create mode 100644 src/components/ticker/TickersDropdown.test.tsx diff --git a/src/api/User.ts b/src/api/User.ts index 8de5bfc9..a82bcf09 100644 --- a/src/api/User.ts +++ b/src/api/User.ts @@ -1,4 +1,5 @@ import { ApiUrl, Response } from './Api' +import { Ticker } from './Ticker' export interface UsersResponseData { users: Array @@ -14,7 +15,7 @@ export interface User { email: string role: string isSuperAdmin: boolean - tickers?: Array + tickers?: Array } export interface UserData { diff --git a/src/components/ticker/TickersDropdown.test.tsx b/src/components/ticker/TickersDropdown.test.tsx new file mode 100644 index 00000000..e89f6460 --- /dev/null +++ b/src/components/ticker/TickersDropdown.test.tsx @@ -0,0 +1,53 @@ +import React from 'react' +import { fireEvent, render, screen } from '@testing-library/react' +import TickersDropdown from './TickersDropdown' +import { QueryClient, QueryClientProvider } from '@tanstack/react-query' +import { Ticker } from '../../api/Ticker' + +describe('TickersDropdown', () => { + beforeEach(() => { + fetchMock.resetMocks() + }) + + function setup(defaultValue: Array, onChange: (tickers: Array) => void) { + const client = new QueryClient({ + defaultOptions: { + queries: { + retry: false, + }, + }, + }) + return render( + + + + ) + } + + it('should renders correctly', async () => { + const ticker = { + id: 1, + title: 'Ticker 1', + } + fetchMock.mockResponseOnce( + JSON.stringify({ + data: { + tickers: [ticker], + }, + status: 'success', + }) + ) + const handleChange = jest.fn() + setup([], handleChange) + + fireEvent.mouseDown(screen.getByRole('button')) + const listbox = await screen.findByRole('listbox') + expect(listbox).toBeInTheDocument() + const option = await screen.findByRole('option') + expect(option).toBeInTheDocument() + fireEvent.click(option) + expect(handleChange).toHaveBeenCalledTimes(1) + expect(handleChange).toHaveBeenCalledWith([ticker]) + expect(fetchMock).toHaveBeenCalledTimes(1) + }) +}) diff --git a/src/components/ticker/TickersDropdown.tsx b/src/components/ticker/TickersDropdown.tsx index 876c3f70..1a48a70d 100644 --- a/src/components/ticker/TickersDropdown.tsx +++ b/src/components/ticker/TickersDropdown.tsx @@ -5,23 +5,25 @@ import useAuth from '../useAuth' interface Props { name: string - defaultValue: Array - onChange: (tickers: number[]) => void + defaultValue: Array + onChange: (tickers: Array) => void sx?: SxProps } const TickersDropdown: FC = ({ name, defaultValue, onChange, sx }) => { const [options, setOptions] = useState>([]) - const [tickers, setTickers] = useState>(defaultValue) + const [tickers, setTickers] = useState>(defaultValue) const { token } = useAuth() const { getTickers } = useTickerApi(token) const theme = useTheme() - const handleChange = (event: SelectChangeEvent) => { - if (typeof event.target.value !== 'string') { - setTickers(event.target.value) - onChange(event.target.value) - } + const handleChange = (event: SelectChangeEvent) => { + const tickerIds = event.target.value as Array + const selectedTickers = options.filter(ticker => { + return tickerIds.includes(ticker.id) + }) + setTickers(selectedTickers) + onChange(selectedTickers) } useEffect(() => { @@ -40,13 +42,13 @@ const TickersDropdown: FC = ({ name, defaultValue, onChange, sx }) => { return ( - {selectedTickers.map(ticker => ( + {selectedTickers.map(selectedTicker => ( { - const reduced = tickers.filter(id => { - return id !== ticker.id + const reduced = tickers.filter(ticker => { + return selectedTicker.id !== ticker.id }) setTickers(reduced) onChange(reduced) @@ -60,18 +62,29 @@ const TickersDropdown: FC = ({ name, defaultValue, onChange, sx }) => { ) } - const getStyle = (value: number, tickers: number[]) => { + const getStyle = (value: Ticker, tickers: Array) => { + const tickerIds = tickers.map(ticker => ticker.id) return { - fontWeight: tickers.indexOf(value) === -1 ? theme.typography.fontWeightRegular : theme.typography.fontWeightMedium, + fontWeight: tickerIds.indexOf(value.id) === -1 ? theme.typography.fontWeightRegular : theme.typography.fontWeightMedium, } } + const tickerIds = tickers.map(ticker => ticker.id) + return ( Tickers - } + label="Tickers" + multiple + name={name} + onChange={handleChange} + renderValue={renderValue} + value={tickerIds} + > {options.map(ticker => ( - + {ticker.title} ))} diff --git a/src/components/user/UserForm.tsx b/src/components/user/UserForm.tsx index ae2b631c..4c209cf7 100644 --- a/src/components/user/UserForm.tsx +++ b/src/components/user/UserForm.tsx @@ -5,6 +5,7 @@ import { useQueryClient } from '@tanstack/react-query' import useAuth from '../useAuth' import { FormControlLabel, Checkbox, FormGroup, TextField, Typography, Grid, Divider } from '@mui/material' import TickersDropdown from '../ticker/TickersDropdown' +import { Ticker } from '../../api/Ticker' interface Props { id: string @@ -17,7 +18,7 @@ interface FormValues { isSuperAdmin: boolean password: string password_validate: string - tickers: Array + tickers: Array } const UserForm: FC = ({ id, user, callback }) => {