fix(trading): fix proposals not showing (#3859)
This commit is contained in:
parent
65747e8d26
commit
b499c293e3
@ -12,7 +12,7 @@ export const Proposed = () => {
|
||||
const externalLink = tokenLink(TOKEN_NEW_MARKET_PROPOSAL);
|
||||
return (
|
||||
<>
|
||||
<div className="min-h-[200px]">
|
||||
<div className="h-[400px]">
|
||||
<ProposalsList />
|
||||
</div>
|
||||
<ExternalLink className="py-4 px-[11px] text-sm" href={externalLink}>
|
||||
|
@ -5,57 +5,74 @@ import {
|
||||
waitFor,
|
||||
getAllByRole,
|
||||
} from '@testing-library/react';
|
||||
import merge from 'lodash/merge';
|
||||
import type { MockedResponse } from '@apollo/client/testing';
|
||||
import { MockedProvider } from '@apollo/client/testing';
|
||||
import { ProposalsList } from './proposals-list';
|
||||
import type { ProposalListFieldsFragment } from '../../lib/proposals-data-provider';
|
||||
import * as Types from '@vegaprotocol/types';
|
||||
|
||||
const votesMock = {
|
||||
yes: {
|
||||
totalTokens: '5000',
|
||||
},
|
||||
no: {
|
||||
totalTokens: '2000',
|
||||
},
|
||||
};
|
||||
let marketsProposalMock: ProposalListFieldsFragment[] | null = [
|
||||
{
|
||||
id: 'id-1',
|
||||
state: Types.ProposalState.STATE_OPEN,
|
||||
votes: { ...votesMock },
|
||||
},
|
||||
{
|
||||
id: 'id-2',
|
||||
state: Types.ProposalState.STATE_PASSED,
|
||||
votes: { ...votesMock },
|
||||
},
|
||||
{
|
||||
id: 'id-3',
|
||||
state: Types.ProposalState.STATE_WAITING_FOR_NODE_VOTE,
|
||||
votes: { ...votesMock },
|
||||
},
|
||||
] as ProposalListFieldsFragment[];
|
||||
|
||||
const useDataProvider = () => {
|
||||
return {
|
||||
data: marketsProposalMock,
|
||||
loading: false,
|
||||
error: false,
|
||||
};
|
||||
};
|
||||
jest.mock('@vegaprotocol/data-provider', () => ({
|
||||
...jest.requireActual('@vegaprotocol/data-provider'),
|
||||
useDataProvider: jest.fn(() => useDataProvider()),
|
||||
}));
|
||||
import { createProposalListFieldsFragment } from '../../lib/proposals-data-provider/proposals.mock';
|
||||
import type { ProposalsListQuery } from '../../lib';
|
||||
import { ProposalsListDocument } from '../../lib';
|
||||
import type { PartialDeep } from 'type-fest';
|
||||
|
||||
describe('ProposalsList', () => {
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
const createProposalsMock = (override?: PartialDeep<ProposalsListQuery>) => {
|
||||
const defaultProposalEdges = [
|
||||
{
|
||||
__typename: 'ProposalEdge' as const,
|
||||
node: createProposalListFieldsFragment({
|
||||
id: 'id-1',
|
||||
state: Types.ProposalState.STATE_OPEN,
|
||||
}),
|
||||
},
|
||||
{
|
||||
__typename: 'ProposalEdge' as const,
|
||||
node: createProposalListFieldsFragment({
|
||||
id: 'id-2',
|
||||
state: Types.ProposalState.STATE_PASSED,
|
||||
}),
|
||||
},
|
||||
{
|
||||
__typename: 'ProposalEdge' as const,
|
||||
node: createProposalListFieldsFragment({
|
||||
id: 'id-3',
|
||||
state: Types.ProposalState.STATE_WAITING_FOR_NODE_VOTE,
|
||||
}),
|
||||
},
|
||||
];
|
||||
const data = merge(
|
||||
{
|
||||
proposalsConnection: {
|
||||
__typename: 'ProposalsConnection' as const,
|
||||
edges: defaultProposalEdges,
|
||||
},
|
||||
},
|
||||
override
|
||||
);
|
||||
|
||||
const mock: MockedResponse<ProposalsListQuery> = {
|
||||
request: {
|
||||
query: ProposalsListDocument,
|
||||
variables: {
|
||||
proposalType: Types.ProposalType.TYPE_NEW_MARKET,
|
||||
},
|
||||
},
|
||||
result: {
|
||||
data,
|
||||
},
|
||||
};
|
||||
|
||||
return mock;
|
||||
};
|
||||
|
||||
it('should be properly rendered', async () => {
|
||||
const mock = createProposalsMock();
|
||||
await act(() => {
|
||||
render(<ProposalsList />, { wrapper: MockedProvider });
|
||||
render(
|
||||
<MockedProvider mocks={[mock]}>
|
||||
<ProposalsList />
|
||||
</MockedProvider>
|
||||
);
|
||||
});
|
||||
const container = document.querySelector('.ag-center-cols-container');
|
||||
await waitFor(() => {
|
||||
@ -65,15 +82,25 @@ describe('ProposalsList', () => {
|
||||
});
|
||||
|
||||
it('some of states should be filtered out', async () => {
|
||||
marketsProposalMock = [
|
||||
{
|
||||
...(marketsProposalMock as ProposalListFieldsFragment[])[0],
|
||||
state: Types.ProposalState.STATE_ENACTED,
|
||||
const mock = createProposalsMock({
|
||||
proposalsConnection: {
|
||||
edges: [
|
||||
{
|
||||
__typename: 'ProposalEdge',
|
||||
node: createProposalListFieldsFragment({
|
||||
id: 'id-1',
|
||||
state: Types.ProposalState.STATE_ENACTED,
|
||||
}),
|
||||
},
|
||||
],
|
||||
},
|
||||
...(marketsProposalMock as ProposalListFieldsFragment[]).slice(1),
|
||||
];
|
||||
});
|
||||
await act(() => {
|
||||
render(<ProposalsList />, { wrapper: MockedProvider });
|
||||
render(
|
||||
<MockedProvider mocks={[mock]}>
|
||||
<ProposalsList />
|
||||
</MockedProvider>
|
||||
);
|
||||
});
|
||||
const container = document.querySelector('.ag-center-cols-container');
|
||||
await waitFor(() => {
|
||||
@ -83,9 +110,12 @@ describe('ProposalsList', () => {
|
||||
});
|
||||
|
||||
it('empty response should causes no data message display', async () => {
|
||||
marketsProposalMock = null;
|
||||
await act(() => {
|
||||
render(<ProposalsList />, { wrapper: MockedProvider });
|
||||
render(
|
||||
<MockedProvider>
|
||||
<ProposalsList />
|
||||
</MockedProvider>
|
||||
);
|
||||
});
|
||||
const container = document.querySelector('.ag-center-cols-container');
|
||||
await waitFor(() => {
|
||||
|
@ -1,13 +1,13 @@
|
||||
import { useCallback, useEffect, useRef, useState } from 'react';
|
||||
import { AsyncRenderer } from '@vegaprotocol/ui-toolkit';
|
||||
import { AgGridLazy as AgGrid } from '@vegaprotocol/datagrid';
|
||||
import { useDataProvider } from '@vegaprotocol/data-provider';
|
||||
import { t } from '@vegaprotocol/i18n';
|
||||
import * as Types from '@vegaprotocol/types';
|
||||
import { proposalsDataProvider } from '../../lib/proposals-data-provider';
|
||||
import type { AgGridReact } from 'ag-grid-react';
|
||||
import { useColumnDefs } from './use-column-defs';
|
||||
import type { ProposalListFieldsFragment } from '../../lib/proposals-data-provider/__generated__/Proposals';
|
||||
import { useProposalsListQuery } from '../../lib/proposals-data-provider/__generated__/Proposals';
|
||||
import { removePaginationWrapper } from '@vegaprotocol/utils';
|
||||
|
||||
export const getNewMarketProposals = (data: ProposalListFieldsFragment[]) =>
|
||||
data.filter((proposal) =>
|
||||
@ -21,13 +21,15 @@ export const getNewMarketProposals = (data: ProposalListFieldsFragment[]) =>
|
||||
export const ProposalsList = () => {
|
||||
const gridRef = useRef<AgGridReact | null>(null);
|
||||
const [dataCount, setDataCount] = useState(0);
|
||||
const { data, loading, error, reload } = useDataProvider({
|
||||
dataProvider: proposalsDataProvider,
|
||||
const { data, loading, error, refetch } = useProposalsListQuery({
|
||||
variables: {
|
||||
proposalType: Types.ProposalType.TYPE_NEW_MARKET,
|
||||
},
|
||||
errorPolicy: 'all', // currently there are some proposals failing due to proposals existing without settlement asset ids
|
||||
});
|
||||
const filteredData = getNewMarketProposals(data || []);
|
||||
const filteredData = getNewMarketProposals(
|
||||
removePaginationWrapper(data?.proposalsConnection?.edges)
|
||||
);
|
||||
const { columnDefs, defaultColDef } = useColumnDefs();
|
||||
useEffect(() => {
|
||||
setDataCount(gridRef.current?.api?.getModel().getRowCount() ?? 0);
|
||||
@ -36,11 +38,10 @@ export const ProposalsList = () => {
|
||||
setDataCount(gridRef.current?.api?.getModel().getRowCount() ?? 0);
|
||||
}, []);
|
||||
return (
|
||||
<div className="relative">
|
||||
<div className="relative h-full">
|
||||
<AgGrid
|
||||
ref={gridRef}
|
||||
className="w-full h-full"
|
||||
domLayout="autoHeight"
|
||||
columnDefs={columnDefs}
|
||||
rowData={filteredData}
|
||||
defaultColDef={defaultColDef}
|
||||
@ -48,6 +49,8 @@ export const ProposalsList = () => {
|
||||
suppressNoRowsOverlay
|
||||
onFilterChanged={onFilterChanged}
|
||||
storeKey="proposedMarkets"
|
||||
getRowId={({ data }) => data.id}
|
||||
style={{ width: '100%', height: '100%' }}
|
||||
/>
|
||||
<div className="pointer-events-none absolute inset-0">
|
||||
<AsyncRenderer
|
||||
@ -56,7 +59,7 @@ export const ProposalsList = () => {
|
||||
data={filteredData}
|
||||
noDataMessage={t('No markets')}
|
||||
noDataCondition={() => !dataCount}
|
||||
reload={reload}
|
||||
reload={refetch}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -11,6 +11,7 @@ export const proposalListQuery = (
|
||||
): ProposalsListQuery => {
|
||||
const defaultResult: ProposalsListQuery = {
|
||||
proposalsConnection: {
|
||||
__typename: 'ProposalsConnection',
|
||||
edges: proposalListFields.map((node) => ({
|
||||
__typename: 'ProposalEdge',
|
||||
node,
|
||||
@ -104,8 +105,10 @@ export const marketUpdateProposal: ProposalListFieldsFragment = {
|
||||
},
|
||||
};
|
||||
|
||||
const proposalListFields: ProposalListFieldsFragment[] = [
|
||||
{
|
||||
export const createProposalListFieldsFragment = (
|
||||
override?: PartialDeep<ProposalListFieldsFragment>
|
||||
): ProposalListFieldsFragment => {
|
||||
const defaultProposal: ProposalListFieldsFragment = {
|
||||
id: 'e9ec6d5c46a7e7bcabf9ba7a893fa5a5eeeec08b731f06f7a6eb7bf0e605b829',
|
||||
reference: 'injected_at_runtime',
|
||||
state: Schema.ProposalState.STATE_OPEN,
|
||||
@ -194,7 +197,12 @@ const proposalListFields: ProposalListFieldsFragment[] = [
|
||||
__typename: 'ProposalTerms',
|
||||
},
|
||||
__typename: 'Proposal',
|
||||
},
|
||||
};
|
||||
return merge(defaultProposal, override);
|
||||
};
|
||||
|
||||
const proposalListFields: ProposalListFieldsFragment[] = [
|
||||
createProposalListFieldsFragment(),
|
||||
{
|
||||
id: '1cd1deb532b97fbeb9262fe94499ecec5835e60ae564b7c5af530c90a13c29cb',
|
||||
reference: 'injected_at_runtime',
|
||||
|
Loading…
Reference in New Issue
Block a user