Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

11/29/24 Port Order Trades components #1032

Draft
wants to merge 20 commits into
base: main
Choose a base branch
from
Draft
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
26 changes: 26 additions & 0 deletions packages/ui-components/src/__tests__/EditableSpan.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { describe, test, expect } from 'vitest';
import { render } from '@testing-library/svelte';
import EditableSpan from '../lib/components/EditableSpan.svelte';

describe('Editable Span', () => {
test('should show the correct value', async () => {
const screen = render(EditableSpan, {
displayValue: '123'
});

expect(screen.getByText('Block:')).toBeInTheDocument();

// test that the input is not visible
expect(screen.getByTestId('editableSpan')).toHaveClass('opacity-0');

// test that the input is visible when clicked
await screen.getByTestId('editableSpanWrapper').click();
expect(screen.getByTestId('editableSpan')).not.toHaveClass('opacity-0');

// test that the input is hidden when the enter key is pressed
screen.getByTestId('editableSpan').click();
screen
.getByTestId('editableSpan')
.dispatchEvent(new KeyboardEvent('keydown', { key: 'Enter' }));
});
});
227 changes: 227 additions & 0 deletions packages/ui-components/src/__tests__/OrderTradesListTable.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,227 @@
import { render, screen, waitFor } from '@testing-library/svelte';
import { test, vi, type Mock } from 'vitest';
import { expect } from '../lib/test/matchers';
import { mockIPC } from '@tauri-apps/api/mocks';
import type { Trade } from '../lib/typeshare/subgraphTypes';
import { formatUnits } from 'viem';
import OrderTradesListTable from '../lib/components/tables/OrderTradesListTable.svelte';
import { QueryClient } from '@tanstack/svelte-query';

const mockTradeOrdersList: Trade[] = [
{
id: '1',
timestamp: '1632000000',
tradeEvent: {
sender: 'sender_address',
transaction: {
id: 'transaction_id',
from: 'sender_address',
timestamp: '1632000000',
blockNumber: '0'
}
},
outputVaultBalanceChange: {
amount: '-100',
vault: {
id: 'id',
vault_id: 'vault-id',
token: {
id: 'output_token',
address: 'output_token',
name: 'output_token',
symbol: 'output_token',
decimals: '1'
}
},
id: '1',
typename: 'Withdraw',
newVaultBalance: '0',
oldVaultBalance: '0',
timestamp: '0',
transaction: {
id: 'transaction_id',
from: 'sender_address',
timestamp: '1632000000',
blockNumber: '0'
},
orderbook: { id: '1' }
},
order: {
id: 'order_id',
orderHash: 'orderHash'
},
inputVaultBalanceChange: {
vault: {
id: 'id',
vault_id: 'vault-id',
token: {
id: 'output_token',
address: 'output_token',
name: 'output_token',
symbol: 'output_token',
decimals: '1'
}
},
amount: '50',
id: '1',
typename: 'Withdraw',
newVaultBalance: '0',
oldVaultBalance: '0',
timestamp: '0',
transaction: {
id: 'transaction_id',
from: 'sender_address',
timestamp: '1632000000',
blockNumber: '0'
},
orderbook: { id: '1' }
},
orderbook: {
id: '0x00'
}
},
{
id: '2',
timestamp: '1632000000',
tradeEvent: {
sender: 'sender_address',
transaction: {
id: 'transaction_id',
from: 'sender_address',
timestamp: '1632000000',
blockNumber: '0'
}
},
outputVaultBalanceChange: {
amount: '-100',
vault: {
id: 'id',
vault_id: 'vault-id',
token: {
id: 'output_token',
address: 'output_token',
name: 'output_token',
symbol: 'output_token',
decimals: '1'
}
},
id: '1',
typename: 'Withdraw',
newVaultBalance: '0',
oldVaultBalance: '0',
timestamp: '0',
transaction: {
id: 'transaction_id',
from: 'sender_address',
timestamp: '1632000000',
blockNumber: '0'
},
orderbook: { id: '1' }
},
order: {
id: 'order_id',
orderHash: 'orderHash'
},
inputVaultBalanceChange: {
vault: {
id: 'id',
vault_id: 'vault-id',
token: {
id: 'output_token',
address: 'output_token',
name: 'output_token',
symbol: 'output_token',
decimals: '1'
}
},
amount: '50',
id: '1',
typename: 'Withdraw',
newVaultBalance: '0',
oldVaultBalance: '0',
timestamp: '0',
transaction: {
id: 'transaction_id',
from: 'sender_address',
timestamp: '1632000000',
blockNumber: '0'
},
orderbook: { id: '1' }
},
orderbook: {
id: '0x00'
}
}
];

vi.mock('@tanstack/svelte-query');

test('renders table with correct data', async () => {
const queryClient = new QueryClient();

const mockQuery = vi.mocked(await import('@tanstack/svelte-query'));
// eslint-disable-next-line @typescript-eslint/no-unused-vars
mockQuery.createInfiniteQuery = vi.fn((__options, _queryClient) => ({
// eslint-disable-next-line @typescript-eslint/no-explicit-any
subscribe: (fn: (value: any) => void) => {
fn({
data: { pages: [mockTradeOrdersList] },
status: 'success',
isFetching: false,
isFetched: true
});
return { unsubscribe: () => {} };
}
})) as Mock;

render(OrderTradesListTable, {
context: new Map([['$$_queryClient', queryClient]]),
props: { id: '1', subgraphUrl: 'https://example.com' }
});

await waitFor(async () => {
// get all the io ratios
const rows = screen.getAllByTestId('io-ratio');

// checking the io ratios
for (let i = 0; i < mockTradeOrdersList.length; i++) {
const inputDisplay = formatUnits(
BigInt(mockTradeOrdersList[i].inputVaultBalanceChange.amount),
Number(mockTradeOrdersList[i].inputVaultBalanceChange.vault.token.decimals)
);
const outputDisplay = formatUnits(
BigInt(mockTradeOrdersList[i].outputVaultBalanceChange.amount),
Number(mockTradeOrdersList[i].outputVaultBalanceChange.vault.token.decimals)
);
const ioRatio = Number(inputDisplay) / (Number(outputDisplay) * -1);
const oiRatio = (Number(outputDisplay) * -1) / Number(inputDisplay);
expect(rows[i]).toHaveTextContent(ioRatio.toString());
expect(rows[i]).toHaveTextContent(oiRatio.toString());
}
});
});

test('renders a debug button for each trade', async () => {
const queryClient = new QueryClient();

mockIPC((cmd) => {
if (cmd === 'order_trades_list') {
return mockTradeOrdersList;
}
});

render(OrderTradesListTable, {
context: new Map([['$$_queryClient', queryClient]]),
props: {
id: '1',
subgraphUrl: 'https://example.com',
rpcUrl: 'example.com',
handleDebugTradeModal: () => {}
}
});

await waitFor(async () => {
const buttons = screen.getAllByTestId('debug-trade-button');
expect(buttons).toHaveLength(mockTradeOrdersList.length);
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<script>
import TableTimeFilters from '../lib/components/charts/TableTimeFilters.svelte';
import { writable } from 'svelte/store';

export let startTimeStore = writable();
export let endTimeStore = writable();
</script>

<TableTimeFilters bind:startTimestamp={$startTimeStore} bind:endTimestamp={$endTimeStore} />
59 changes: 59 additions & 0 deletions packages/ui-components/src/__tests__/TableTimeFilters.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import { render, fireEvent, screen } from '@testing-library/svelte';
import { get, writable } from 'svelte/store';
import { test, expect } from 'vitest';
import TableTimeFiltersTest from './TableTimeFilters.test.svelte';

const TIME_DELTA_24_HOURS = 60 * 60 * 24;
const TIME_DELTA_48_HOURS = TIME_DELTA_24_HOURS * 2;

test('initial start/end time difference is set to all time', async () => {
const startTimeStore = writable<number | undefined>();
const endTimeStore = writable<number | undefined>();

render(TableTimeFiltersTest, { startTimeStore, endTimeStore });

const twentyFourHoursButton = screen.getByText('24 Hours');
expect(twentyFourHoursButton).toBeEnabled();
expect(get(endTimeStore)).toBe(undefined);
expect(get(startTimeStore)).toBe(undefined);
});

test('clicking All Time button updates timeDelta', async () => {
const startTimeStore = writable(0);
const endTimeStore = writable(0);

render(TableTimeFiltersTest, { startTimeStore, endTimeStore });

const allTimeButton = screen.getByText('All Time');
await fireEvent.click(allTimeButton);

expect(allTimeButton).toBeDisabled();
expect(get(startTimeStore)).toBe(undefined);
expect(get(endTimeStore)).toBe(undefined);
});

test('clicking 48 Hours button updates start/end timestamp', async () => {
const startTimeStore = writable(0);
const endTimeStore = writable(0);

render(TableTimeFiltersTest, { startTimeStore, endTimeStore });

const fortyEightHoursButton = screen.getByText('48 Hours');
await fireEvent.click(fortyEightHoursButton);

expect(fortyEightHoursButton).toBeDisabled();
expect(get(endTimeStore) - get(startTimeStore)).toBe(TIME_DELTA_48_HOURS);
});

test('clicking 24 Hours button updates start/end timestamp', async () => {
const startTimeStore = writable(0);
const endTimeStore = writable(0);

render(TableTimeFiltersTest, { startTimeStore, endTimeStore });

const twentyFourHoursButton = screen.getByText('24 Hours');
await fireEvent.click(twentyFourHoursButton);

expect(twentyFourHoursButton).toBeDisabled();
expect(get(endTimeStore) - get(startTimeStore)).toBe(TIME_DELTA_24_HOURS);
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<script lang="ts">
import TanstackPageContentDetail from '../lib/components/detail/TanstackPageContentDetail.svelte';

export let query;
export let emptyMessage: string;
export let below: string;
</script>

<TanstackPageContentDetail {query} {emptyMessage}>
<svelte:fragment slot="top" let:data>
<span data-testid="top">{data}</span>
</svelte:fragment>
<svelte:fragment slot="card" let:data>
<span data-testid="card">{data}</span>
</svelte:fragment>
<svelte:fragment slot="chart" let:data>
<span data-testid="chart">{data}</span>
</svelte:fragment>
<svelte:fragment slot="below">
<span data-testid="below">{below}</span>
</svelte:fragment>
</TanstackPageContentDetail>
Loading
Loading