feat: [console-lite] - additional unit tests (#1273)
* feat: [console-lite] - additional unit tests * feat: [console-lite] - additional unit tests * feat: [console-lite] - additional unit tests * feat: [console-lite] - additional unit tests - fixes after feedback Co-authored-by: maciek <maciek@vegaprotocol.io>
This commit is contained in:
parent
87ae478b9c
commit
65528a8007
@ -1,7 +1,29 @@
|
|||||||
import '@testing-library/jest-dom';
|
import '@testing-library/jest-dom';
|
||||||
import { defaultFallbackInView } from 'react-intersection-observer';
|
import { defaultFallbackInView } from 'react-intersection-observer';
|
||||||
|
import ResizeObserver from 'resize-observer-polyfill';
|
||||||
|
|
||||||
defaultFallbackInView(true);
|
defaultFallbackInView(true);
|
||||||
|
global.ResizeObserver = ResizeObserver;
|
||||||
|
|
||||||
|
global.DOMRect = class DOMRect {
|
||||||
|
bottom = 0;
|
||||||
|
left = 0;
|
||||||
|
right = 0;
|
||||||
|
top = 0;
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
public x = 0,
|
||||||
|
public y = 0,
|
||||||
|
public width = 0,
|
||||||
|
public height = 0
|
||||||
|
) {}
|
||||||
|
static fromRect(other?: DOMRectInit): DOMRect {
|
||||||
|
return new DOMRect(other?.x, other?.y, other?.width, other?.height);
|
||||||
|
}
|
||||||
|
toJSON() {
|
||||||
|
return JSON.stringify(this);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
Object.defineProperty(window, 'matchMedia', {
|
Object.defineProperty(window, 'matchMedia', {
|
||||||
writable: true,
|
writable: true,
|
||||||
|
@ -6,17 +6,19 @@ import {
|
|||||||
waitFor,
|
waitFor,
|
||||||
cleanup,
|
cleanup,
|
||||||
getAllByRole,
|
getAllByRole,
|
||||||
|
fireEvent,
|
||||||
} from '@testing-library/react';
|
} from '@testing-library/react';
|
||||||
import { MockedProvider } from '@apollo/client/testing';
|
import { MockedProvider } from '@apollo/client/testing';
|
||||||
import type { MockedResponse } from '@apollo/client/testing';
|
import type { MockedResponse } from '@apollo/client/testing';
|
||||||
import { BrowserRouter } from 'react-router-dom';
|
import { BrowserRouter } from 'react-router-dom';
|
||||||
|
import { MarketState } from '@vegaprotocol/types';
|
||||||
import SimpleMarketList from './simple-market-list';
|
import SimpleMarketList from './simple-market-list';
|
||||||
import { MARKETS_QUERY } from './data-provider';
|
import { MARKETS_QUERY } from './data-provider';
|
||||||
import type {
|
import type {
|
||||||
SimpleMarkets_markets,
|
SimpleMarkets_markets,
|
||||||
SimpleMarkets,
|
SimpleMarkets,
|
||||||
} from './__generated__/SimpleMarkets';
|
} from './__generated__/SimpleMarkets';
|
||||||
import { MarketState } from '@vegaprotocol/types';
|
import type { SimpleMarketDataSub_marketData } from './__generated__/SimpleMarketDataSub';
|
||||||
|
|
||||||
const mockedNavigate = jest.fn();
|
const mockedNavigate = jest.fn();
|
||||||
|
|
||||||
@ -30,42 +32,16 @@ jest.mock('date-fns', () => ({
|
|||||||
subDays: () => new Date('2022-06-02T11:11:21.721Z'),
|
subDays: () => new Date('2022-06-02T11:11:21.721Z'),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
describe('SimpleMarketList', () => {
|
let updateMock: ({
|
||||||
afterEach(() => {
|
delta,
|
||||||
jest.clearAllMocks();
|
}: {
|
||||||
cleanup();
|
delta: SimpleMarketDataSub_marketData;
|
||||||
});
|
}) => boolean;
|
||||||
|
|
||||||
it('should be properly renderer as empty', async () => {
|
let mockData = [
|
||||||
const mocks: MockedResponse<SimpleMarkets> = {
|
|
||||||
request: {
|
|
||||||
query: MARKETS_QUERY,
|
|
||||||
variables: {
|
|
||||||
CandleSince: '2022-06-02T11:11:21.721Z',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
result: {
|
|
||||||
data: { markets: [] },
|
|
||||||
},
|
|
||||||
};
|
|
||||||
await act(async () => {
|
|
||||||
render(
|
|
||||||
<MockedProvider mocks={[mocks]}>
|
|
||||||
<SimpleMarketList />
|
|
||||||
</MockedProvider>,
|
|
||||||
{ wrapper: BrowserRouter }
|
|
||||||
);
|
|
||||||
await new Promise((resolve) => setTimeout(resolve, 0));
|
|
||||||
});
|
|
||||||
await waitFor(() => {
|
|
||||||
expect(screen.getByText('No data to display')).toBeInTheDocument();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should be properly rendered with some data', async () => {
|
|
||||||
const data = [
|
|
||||||
{
|
{
|
||||||
id: '1',
|
id: '1',
|
||||||
|
name: 'Market 1',
|
||||||
state: MarketState.STATE_ACTIVE,
|
state: MarketState.STATE_ACTIVE,
|
||||||
tradableInstrument: {
|
tradableInstrument: {
|
||||||
instrument: {
|
instrument: {
|
||||||
@ -82,6 +58,7 @@ describe('SimpleMarketList', () => {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: '2',
|
id: '2',
|
||||||
|
name: 'Market 2',
|
||||||
state: MarketState.STATE_ACTIVE,
|
state: MarketState.STATE_ACTIVE,
|
||||||
tradableInstrument: {
|
tradableInstrument: {
|
||||||
instrument: {
|
instrument: {
|
||||||
@ -98,6 +75,29 @@ describe('SimpleMarketList', () => {
|
|||||||
},
|
},
|
||||||
] as unknown as SimpleMarkets_markets[];
|
] as unknown as SimpleMarkets_markets[];
|
||||||
|
|
||||||
|
const mockUseDataProvider = ({ update }: { update: () => boolean }) => {
|
||||||
|
updateMock = update;
|
||||||
|
return { data: mockData, loading: false, error: false };
|
||||||
|
};
|
||||||
|
|
||||||
|
jest.mock('@vegaprotocol/react-helpers', () => ({
|
||||||
|
...jest.requireActual('@vegaprotocol/react-helpers'),
|
||||||
|
useDataProvider: jest.fn((args) => mockUseDataProvider(args)),
|
||||||
|
}));
|
||||||
|
|
||||||
|
const mockIsTradable = jest.fn((_arg) => true);
|
||||||
|
|
||||||
|
jest.mock('../../constants', () => ({
|
||||||
|
...jest.requireActual('../../constants'),
|
||||||
|
IS_MARKET_TRADABLE: jest.fn((arg) => mockIsTradable(arg)),
|
||||||
|
}));
|
||||||
|
|
||||||
|
describe('SimpleMarketList', () => {
|
||||||
|
afterEach(() => {
|
||||||
|
jest.clearAllMocks();
|
||||||
|
cleanup();
|
||||||
|
});
|
||||||
|
|
||||||
const mocks: MockedResponse<SimpleMarkets> = {
|
const mocks: MockedResponse<SimpleMarkets> = {
|
||||||
request: {
|
request: {
|
||||||
query: MARKETS_QUERY,
|
query: MARKETS_QUERY,
|
||||||
@ -106,9 +106,11 @@ describe('SimpleMarketList', () => {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
result: {
|
result: {
|
||||||
data: { markets: data },
|
data: { markets: mockData },
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
it('should be properly rendered with some data', async () => {
|
||||||
await act(async () => {
|
await act(async () => {
|
||||||
render(
|
render(
|
||||||
<MockedProvider mocks={[mocks]}>
|
<MockedProvider mocks={[mocks]}>
|
||||||
@ -128,4 +130,92 @@ describe('SimpleMarketList', () => {
|
|||||||
expect(getAllByRole(container as HTMLDivElement, 'row')).toHaveLength(2);
|
expect(getAllByRole(container as HTMLDivElement, 'row')).toHaveLength(2);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('update should return proper boolean value', async () => {
|
||||||
|
await act(async () => {
|
||||||
|
render(
|
||||||
|
<MockedProvider mocks={[mocks]}>
|
||||||
|
<SimpleMarketList />
|
||||||
|
</MockedProvider>,
|
||||||
|
{ wrapper: BrowserRouter }
|
||||||
|
);
|
||||||
|
await new Promise((resolve) => setTimeout(resolve, 0));
|
||||||
|
});
|
||||||
|
await waitFor(() => {
|
||||||
|
expect(
|
||||||
|
document.querySelector('.ag-center-cols-container')
|
||||||
|
).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
await expect(
|
||||||
|
updateMock({
|
||||||
|
delta: {
|
||||||
|
__typename: 'MarketData',
|
||||||
|
market: {
|
||||||
|
__typename: 'Market',
|
||||||
|
id: '2',
|
||||||
|
state: MarketState.STATE_ACTIVE,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
).toEqual(true);
|
||||||
|
|
||||||
|
await expect(
|
||||||
|
updateMock({
|
||||||
|
delta: {
|
||||||
|
__typename: 'MarketData',
|
||||||
|
market: {
|
||||||
|
__typename: 'Market',
|
||||||
|
id: '2',
|
||||||
|
state: MarketState.STATE_SUSPENDED,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
).toEqual(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('click on row should be properly handled', async () => {
|
||||||
|
await act(async () => {
|
||||||
|
render(
|
||||||
|
<MockedProvider mocks={[mocks]}>
|
||||||
|
<SimpleMarketList />
|
||||||
|
</MockedProvider>,
|
||||||
|
{ wrapper: BrowserRouter }
|
||||||
|
);
|
||||||
|
await new Promise((resolve) => setTimeout(resolve, 0));
|
||||||
|
});
|
||||||
|
await waitFor(() => {
|
||||||
|
expect(
|
||||||
|
document.querySelector('.ag-center-cols-container')
|
||||||
|
).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
mockIsTradable.mockClear();
|
||||||
|
const container = document.querySelector('.ag-center-cols-container');
|
||||||
|
const firstRow = getAllByRole(container as HTMLDivElement, 'row')[0];
|
||||||
|
expect(firstRow).toHaveAttribute('row-id', '1');
|
||||||
|
fireEvent.click(firstRow);
|
||||||
|
await waitFor(() => {
|
||||||
|
expect(mockIsTradable).toHaveBeenCalledWith({
|
||||||
|
...mockData[0],
|
||||||
|
percentChange: '-',
|
||||||
|
});
|
||||||
|
expect(mockedNavigate).toHaveBeenCalledWith(`/trading/${mockData[0].id}`);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should be properly renderer as empty', async () => {
|
||||||
|
mockData = [];
|
||||||
|
await act(async () => {
|
||||||
|
render(
|
||||||
|
<MockedProvider mocks={[mocks]}>
|
||||||
|
<SimpleMarketList />
|
||||||
|
</MockedProvider>,
|
||||||
|
{ wrapper: BrowserRouter }
|
||||||
|
);
|
||||||
|
await new Promise((resolve) => setTimeout(resolve, 0));
|
||||||
|
});
|
||||||
|
await waitFor(() => {
|
||||||
|
expect(screen.getByText('No data to display')).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
@ -0,0 +1,36 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import { render, screen } from '@testing-library/react';
|
||||||
|
import type { MarketNames_markets } from '@vegaprotocol/deal-ticket';
|
||||||
|
import { MarketState } from '@vegaprotocol/types';
|
||||||
|
import MarketNameRenderer from './simple-market-renderer';
|
||||||
|
|
||||||
|
describe('SimpleMarketRenderer', () => {
|
||||||
|
const market = {
|
||||||
|
id: 'marketId',
|
||||||
|
state: MarketState.STATE_ACTIVE,
|
||||||
|
tradableInstrument: {
|
||||||
|
instrument: {
|
||||||
|
code: 'Market code',
|
||||||
|
name: 'Market Name',
|
||||||
|
product: {
|
||||||
|
quoteName: 'Quote name',
|
||||||
|
},
|
||||||
|
metadata: {
|
||||||
|
tags: null,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
} as MarketNames_markets;
|
||||||
|
|
||||||
|
it('should properly render not mobile', () => {
|
||||||
|
render(<MarketNameRenderer market={market} isMobile={false} />);
|
||||||
|
expect(screen.getByText('Market Name')).toBeInTheDocument();
|
||||||
|
expect(screen.getByText('Quote name')).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should properly render mobile', () => {
|
||||||
|
render(<MarketNameRenderer market={market} isMobile={true} />);
|
||||||
|
expect(screen.getByText('Market code')).toBeInTheDocument();
|
||||||
|
expect(screen.getByText('Quote name')).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
});
|
@ -1,11 +1,35 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { useLocation, useRoutes, BrowserRouter } from 'react-router-dom';
|
import {
|
||||||
import { render, screen, fireEvent, waitFor } from '@testing-library/react';
|
useLocation,
|
||||||
|
useRoutes,
|
||||||
|
BrowserRouter,
|
||||||
|
useParams,
|
||||||
|
} from 'react-router-dom';
|
||||||
|
import {
|
||||||
|
render,
|
||||||
|
screen,
|
||||||
|
fireEvent,
|
||||||
|
waitFor,
|
||||||
|
act,
|
||||||
|
getAllByText,
|
||||||
|
} from '@testing-library/react';
|
||||||
import { MockedProvider } from '@apollo/react-testing';
|
import { MockedProvider } from '@apollo/react-testing';
|
||||||
|
import { MarketState } from '@vegaprotocol/types';
|
||||||
import SimpleMarketToolbar from './simple-market-toolbar';
|
import SimpleMarketToolbar from './simple-market-toolbar';
|
||||||
import type { SimpleMarkets_markets } from './__generated__/SimpleMarkets';
|
import type { SimpleMarkets_markets } from './__generated__/SimpleMarkets';
|
||||||
import { markets as filterData } from './mocks/market-filters.json';
|
import { markets as filterData } from './mocks/market-filters.json';
|
||||||
|
|
||||||
|
const mockedNavigate = jest.fn();
|
||||||
|
|
||||||
|
jest.mock('react-router-dom', () => {
|
||||||
|
const actualRouter = jest.requireActual('react-router-dom');
|
||||||
|
return {
|
||||||
|
...actualRouter,
|
||||||
|
useNavigate: () => mockedNavigate,
|
||||||
|
useParams: jest.fn(() => actualRouter.useParams()),
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
describe('SimpleMarketToolbar', () => {
|
describe('SimpleMarketToolbar', () => {
|
||||||
const WrappedCompForTest = () => {
|
const WrappedCompForTest = () => {
|
||||||
const routes = useRoutes([
|
const routes = useRoutes([
|
||||||
@ -60,9 +84,8 @@ describe('SimpleMarketToolbar', () => {
|
|||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
afterEach(() => {
|
afterEach(() => {
|
||||||
jest.resetAllMocks();
|
jest.clearAllMocks();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should be properly rendered', async () => {
|
it('should be properly rendered', async () => {
|
||||||
@ -83,7 +106,7 @@ describe('SimpleMarketToolbar', () => {
|
|||||||
expect(screen.getByTestId('market-assets-menu').children).toHaveLength(6);
|
expect(screen.getByTestId('market-assets-menu').children).toHaveLength(6);
|
||||||
});
|
});
|
||||||
fireEvent.click(screen.getByTestId('state-trigger'));
|
fireEvent.click(screen.getByTestId('state-trigger'));
|
||||||
waitFor(() => {
|
await waitFor(() => {
|
||||||
expect(screen.getByRole('menu')).toBeInTheDocument();
|
expect(screen.getByRole('menu')).toBeInTheDocument();
|
||||||
expect(screen.getByRole('menu').children).toHaveLength(10);
|
expect(screen.getByRole('menu').children).toHaveLength(10);
|
||||||
});
|
});
|
||||||
@ -104,7 +127,7 @@ describe('SimpleMarketToolbar', () => {
|
|||||||
|
|
||||||
await waitFor(() => {
|
await waitFor(() => {
|
||||||
expect(screen.getByTestId('location-display')).toHaveTextContent(
|
expect(screen.getByTestId('location-display')).toHaveTextContent(
|
||||||
'/markets/STATE_ACTIVE/Future'
|
`/markets/${MarketState.STATE_ACTIVE}/Future`
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -115,17 +138,91 @@ describe('SimpleMarketToolbar', () => {
|
|||||||
);
|
);
|
||||||
await waitFor(() => {
|
await waitFor(() => {
|
||||||
expect(screen.getByTestId('location-display')).toHaveTextContent(
|
expect(screen.getByTestId('location-display')).toHaveTextContent(
|
||||||
'/markets/STATE_ACTIVE/Future/tEURO'
|
`/markets/${MarketState.STATE_ACTIVE}/Future/tEURO`
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
fireEvent.click(screen.getByTestId('state-trigger'));
|
fireEvent.click(screen.getByTestId('state-trigger'));
|
||||||
waitFor(() => {
|
await waitFor(() => {
|
||||||
expect(screen.getByRole('menu')).toBeInTheDocument();
|
expect(screen.getByRole('menu')).toBeInTheDocument();
|
||||||
fireEvent.click(screen.getByText('Pending'));
|
});
|
||||||
expect(screen.getByTestId('location-display')).toHaveTextContent(
|
const menu = screen.getByRole('menu');
|
||||||
'/markets/Pending/Future/tEURO'
|
const pending = getAllByText(menu, 'Pending')[0];
|
||||||
|
await act(() => {
|
||||||
|
fireEvent.click(pending);
|
||||||
|
});
|
||||||
|
await waitFor(() => {
|
||||||
|
expect(mockedNavigate).toHaveBeenCalledWith(
|
||||||
|
`/markets/${MarketState.STATE_PENDING}/Future/tEURO`
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('stateChange callback should work well', async () => {
|
||||||
|
(useParams as jest.Mock).mockImplementation(() => ({
|
||||||
|
asset: 'asset1',
|
||||||
|
product: 'product1',
|
||||||
|
state: 'state1',
|
||||||
|
}));
|
||||||
|
render(
|
||||||
|
<MockedProvider mocks={[]} addTypename={false}>
|
||||||
|
<SimpleMarketToolbar data={filterData as SimpleMarkets_markets[]} />
|
||||||
|
</MockedProvider>,
|
||||||
|
{ wrapper: BrowserRouter }
|
||||||
|
);
|
||||||
|
fireEvent.click(screen.getByTestId('state-trigger'));
|
||||||
|
await waitFor(() => {
|
||||||
|
expect(screen.getByRole('menu')).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
const menu = screen.getByRole('menu');
|
||||||
|
const suspended = getAllByText(menu, 'Suspended')[0];
|
||||||
|
fireEvent.click(suspended);
|
||||||
|
|
||||||
|
expect(mockedNavigate).toHaveBeenCalledWith(
|
||||||
|
`/markets/${MarketState.STATE_SUSPENDED}/product1/asset1`
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('stateChange callback should call navigate with url with state only', async () => {
|
||||||
|
(useParams as jest.Mock).mockImplementation(() => ({}));
|
||||||
|
render(
|
||||||
|
<MockedProvider mocks={[]} addTypename={false}>
|
||||||
|
<SimpleMarketToolbar data={filterData as SimpleMarkets_markets[]} />
|
||||||
|
</MockedProvider>,
|
||||||
|
{ wrapper: BrowserRouter }
|
||||||
|
);
|
||||||
|
fireEvent.click(screen.getByTestId('state-trigger'));
|
||||||
|
await waitFor(() => {
|
||||||
|
expect(screen.getByRole('menu')).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
const menu = screen.getByRole('menu');
|
||||||
|
const closed = getAllByText(menu, 'Closed')[0];
|
||||||
|
fireEvent.click(closed);
|
||||||
|
|
||||||
|
expect(mockedNavigate).toHaveBeenCalledWith(
|
||||||
|
`/markets/${MarketState.STATE_CLOSED}`
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('stateChange callback should call navigate with no asset', async () => {
|
||||||
|
(useParams as jest.Mock).mockImplementation(() => ({
|
||||||
|
asset: 'all',
|
||||||
|
state: 'state1',
|
||||||
|
}));
|
||||||
|
render(
|
||||||
|
<MockedProvider mocks={[]} addTypename={false}>
|
||||||
|
<SimpleMarketToolbar data={filterData as SimpleMarkets_markets[]} />
|
||||||
|
</MockedProvider>,
|
||||||
|
{ wrapper: BrowserRouter }
|
||||||
|
);
|
||||||
|
fireEvent.click(screen.getByTestId('state-trigger'));
|
||||||
|
await waitFor(() => {
|
||||||
|
expect(screen.getByRole('menu')).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
const menu = screen.getByRole('menu');
|
||||||
|
const active = getAllByText(menu, 'Active')[0];
|
||||||
|
fireEvent.click(active);
|
||||||
|
expect(mockedNavigate).toHaveBeenCalledWith('/markets');
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
@ -123,10 +123,11 @@ const SimpleMarketToolbar = ({ data }: Props) => {
|
|||||||
</ul>
|
</ul>
|
||||||
<div className="grid gap-4 pb-2 mt-2 md:mt-6 md:grid-cols-[min-content,min-content,1fr]">
|
<div className="grid gap-4 pb-2 mt-2 md:mt-6 md:grid-cols-[min-content,min-content,1fr]">
|
||||||
<div className="pb-2">
|
<div className="pb-2">
|
||||||
<DropdownMenu onOpenChange={(open) => setOpen(open)}>
|
<DropdownMenu open={isOpen} onOpenChange={(open) => setOpen(open)}>
|
||||||
<DropdownMenuTrigger
|
<DropdownMenuTrigger
|
||||||
className="mr-2 w-auto text-capMenu text-black dark:text-white"
|
className="mr-2 w-auto text-capMenu text-black dark:text-white"
|
||||||
data-testid="state-trigger"
|
data-testid="state-trigger"
|
||||||
|
onClick={() => setOpen(!isOpen)}
|
||||||
>
|
>
|
||||||
<div className="w-full justify-between uppercase inline-flex items-center justify-center box-border">
|
<div className="w-full justify-between uppercase inline-flex items-center justify-center box-border">
|
||||||
{STATES_FILTER.find(
|
{STATES_FILTER.find(
|
||||||
|
Loading…
Reference in New Issue
Block a user