From 8a8eb9c6599b218e9742babb08ef4de2eb0c612d Mon Sep 17 00:00:00 2001 From: Tiago Silva Date: Fri, 5 Jul 2024 15:24:44 +0100 Subject: [PATCH 01/31] Add inline deps to bancor/carbon-sdk to fix CommonJS issue with parseUnits --- vitest.config.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/vitest.config.ts b/vitest.config.ts index 1125bd1d6..1407f7aac 100644 --- a/vitest.config.ts +++ b/vitest.config.ts @@ -10,6 +10,11 @@ export default defineConfig({ 'src/**/*.test.{js,mjs,cjs,ts,mts,cts,jsx,tsx}', 'e2e/**/*.test.ts', ], + server: { + deps: { + inline: ['/@bancor/carbon-sdk/'], + }, + }, }, plugins: [tsconfigPaths(), svgrPlugin()], }); From afa2a3d518c79fa254fc78566685d44a7d325b1d Mon Sep 17 00:00:00 2001 From: Tiago Silva Date: Fri, 5 Jul 2024 15:25:06 +0100 Subject: [PATCH 02/31] Remove unnecessary mock from testing-library --- src/libs/testing-library/setup.ts | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/libs/testing-library/setup.ts b/src/libs/testing-library/setup.ts index dc64fe5ee..f71dfc2fb 100644 --- a/src/libs/testing-library/setup.ts +++ b/src/libs/testing-library/setup.ts @@ -45,13 +45,6 @@ vitest.mock('libs/sdk/index.ts', () => { }; }); -vitest.mock('@bancor/carbon-sdk/strategy-management', () => ({ - MarginalPriceOptions: { - reset: 'RESET', - maintain: 'MAINTAIN', - }, -})); - // MOCK WAGMI WALLET const mockedWallet = await vitest.hoisted(async () => { const { mock } = await import('wagmi/connectors'); From c182c0e2c2fb47bcc927c4b9e3e1061344117af0 Mon Sep 17 00:00:00 2001 From: Tiago Silva Date: Fri, 5 Jul 2024 15:25:49 +0100 Subject: [PATCH 03/31] Fix loadRouter search params encoder --- src/libs/testing-library/utils.ts | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/src/libs/testing-library/utils.ts b/src/libs/testing-library/utils.ts index 7f3b19b03..bc05167b3 100644 --- a/src/libs/testing-library/utils.ts +++ b/src/libs/testing-library/utils.ts @@ -1,5 +1,4 @@ import { - encode, RootRoute, Route, Router, @@ -7,6 +6,8 @@ import { } from '@tanstack/react-router'; import { RouterRenderParams } from './types'; import { debugTokens } from '../../../e2e/utils/types'; +import { parseSearchWith } from 'libs/routing/utils'; +import { isAddress } from 'ethers/lib/utils'; export const tokens = [ { @@ -21,6 +22,20 @@ export const tokens = [ }, ]; +const encodeValue = (value: string | number | symbol) => { + if (typeof value == 'string' && isAddress(value)) return `${String(value)}`; + if (!isNaN(Number(value))) return `"${String(value)}"`; + return `${String(value)}`; +}; + +const encodeParams = ( + searchParams: Record +): string => { + return Object.entries(searchParams) + .map(([key, value]) => `${key}=${encodeValue(value)}`) + .join('&'); +}; + /** * Asynchronously created and loads a custom router with the specified component and optional base path and search parameters. * @@ -39,7 +54,7 @@ export const loadRouter = async ({ search = {}, }: RouterRenderParams) => { const rootRoute = new RootRoute(); - const subPath = encode(search); + const subPath = encodeParams(search); const path = `${basePath}?${subPath}`; const componentRoute = new Route({ @@ -50,6 +65,7 @@ export const loadRouter = async ({ const customRouter = new Router({ routeTree: rootRoute.addChildren([componentRoute]), + parseSearch: parseSearchWith(JSON.parse), history: createMemoryHistory({ initialEntries: [path] }), }); From 571acfcb13071387c0ed5442dc6cf6d35439e5fb Mon Sep 17 00:00:00 2001 From: Tiago Silva Date: Fri, 5 Jul 2024 15:26:03 +0100 Subject: [PATCH 04/31] Add overlapping create deeplink form test --- .../strategies/create/overlapping.test.tsx | 70 +++++++++++++++++++ 1 file changed, 70 insertions(+) create mode 100644 src/pages/strategies/create/overlapping.test.tsx diff --git a/src/pages/strategies/create/overlapping.test.tsx b/src/pages/strategies/create/overlapping.test.tsx new file mode 100644 index 000000000..86769a823 --- /dev/null +++ b/src/pages/strategies/create/overlapping.test.tsx @@ -0,0 +1,70 @@ +import { test, expect, afterEach, vitest } from 'vitest'; +import { renderWithRouter, screen } from 'libs/testing-library'; +import { debugTokens } from '../../../../e2e/utils/types'; +import { CreateOverlappingStrategyPage } from './overlapping'; +import userEvent from '@testing-library/user-event'; + +vitest.mock('hooks/useMarketPrice', () => { + return { + useMarketPrice: () => { + return { marketPrice: 2800, isPending: false }; + }, + }; +}); + +const basePath = '/strategies/create/overlapping'; +afterEach(async () => { + window.history.replaceState(null, 'root', '/'); +}); + +test('run overlapping form with deeplink and user market price', async () => { + // Initialize user and set params + const user = userEvent.setup(); + const search = { + base: debugTokens.ETH, + quote: debugTokens.USDC, + marketPrice: '2500', + min: '2000', + max: '3000', + spread: '0.01', + anchor: 'buy', + budget: '100', + }; + + // Render page + const { router } = await renderWithRouter({ + component: () => , + basePath, + search, + }); + + // Check search params + expect(router.state.location.pathname).toBe(basePath); + expect(router.state.location.search).toStrictEqual(search); + + // Close price chart + await user.click(screen.getByText('Close Chart')); + const priceChart = screen.queryByRole('heading', { + name: 'Price Chart', + }); + expect(priceChart).not.toBeInTheDocument(); + + // Check price range input and market price indication + const priceRangeMin = await screen.findByTestId('input-min'); + const priceRangeMax = await screen.findByTestId('input-max'); + const marketPriceIndications = await screen.findAllByTestId( + 'market-price-indication' + ); + expect(priceRangeMin).toHaveValue(search.min); + expect(priceRangeMax).toHaveValue(search.max); + expect(marketPriceIndications[0]).toHaveTextContent('20.00% below'); + expect(marketPriceIndications[1]).toHaveTextContent('20.00% above'); + + // Check budget + const inputBudget = screen.getByTestId('input-budget'); + expect(inputBudget).toHaveValue(search.budget); + + // Check warning to approve deposit exists + const depositWarning = screen.queryByTestId('approve-warnings'); + expect(depositWarning).toBeInTheDocument(); +}); From 14695dcedf8f28a5d052b35b9b31fc8505a94b0b Mon Sep 17 00:00:00 2001 From: Tiago Silva Date: Fri, 5 Jul 2024 15:26:18 +0100 Subject: [PATCH 05/31] Remove unnecessary console output form recurring test --- src/pages/strategies/create/recurring.test.tsx | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/pages/strategies/create/recurring.test.tsx b/src/pages/strategies/create/recurring.test.tsx index 48b7fb94e..c231f166e 100644 --- a/src/pages/strategies/create/recurring.test.tsx +++ b/src/pages/strategies/create/recurring.test.tsx @@ -1,5 +1,5 @@ import { test, expect, afterEach } from 'vitest'; -import { renderWithRouter, screen } from 'libs/testing-library'; +import { renderWithRouter } from 'libs/testing-library'; import { debugTokens } from '../../../../e2e/utils/types'; import { CreateRecurringStrategyPage } from './recurring'; @@ -19,14 +19,9 @@ test('run recurring form', async () => { }, }); - // ACT - - // ASSERT expect(router.state.location.pathname).toBe(basePath); expect(router.state.location.search).toStrictEqual({ base: debugTokens.ETH, quote: debugTokens.USDC, }); - screen.debug(); - screen.logTestingPlaygroundURL(); }); From 3de1d0cc3523b04cc0c8f66e0ef442381e8000ec Mon Sep 17 00:00:00 2001 From: Tiago Silva Date: Fri, 5 Jul 2024 15:26:38 +0100 Subject: [PATCH 06/31] Add keys to InputLimit and InputRange to remove unique key for components in list warning --- src/components/strategies/common/InputLimit.tsx | 4 ++-- src/components/strategies/common/InputRange.tsx | 8 ++++++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/components/strategies/common/InputLimit.tsx b/src/components/strategies/common/InputLimit.tsx index 18b592c28..cbaf8c811 100644 --- a/src/components/strategies/common/InputLimit.tsx +++ b/src/components/strategies/common/InputLimit.tsx @@ -127,8 +127,8 @@ export const InputLimit: FC = ({ )} {showWarning && - displayWarnings.map((warning) => ( - + displayWarnings.map((warning, i) => ( + ))} ); diff --git a/src/components/strategies/common/InputRange.tsx b/src/components/strategies/common/InputRange.tsx index 563dcbe97..f9f7108b9 100644 --- a/src/components/strategies/common/InputRange.tsx +++ b/src/components/strategies/common/InputRange.tsx @@ -226,8 +226,12 @@ export const InputRange: FC = ({ /> )} {showWarning && - displayWarnings.map((warning) => ( - + displayWarnings.map((warning, i) => ( + ))} ); From 7c8977a95cc170c9ee1b3a55c6a87b41612a5c34 Mon Sep 17 00:00:00 2001 From: Tiago Silva Date: Fri, 5 Jul 2024 20:00:55 +0100 Subject: [PATCH 07/31] Add close-chart test id prop --- src/components/strategies/common/StrategyGraph.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/src/components/strategies/common/StrategyGraph.tsx b/src/components/strategies/common/StrategyGraph.tsx index 39f22c36c..b5357a09a 100644 --- a/src/components/strategies/common/StrategyGraph.tsx +++ b/src/components/strategies/common/StrategyGraph.tsx @@ -22,6 +22,7 @@ export const StrategyGraph: FC = ({ setShowGraph, children }) => { className="bg-background-800 hover:border-background-600 gap-12 self-end" variant="secondary" size="md" + data-testid="close-chart" onClick={() => { carbonEvents.strategy.strategyChartClose(undefined); setShowGraph(false); From 040d709955622aa8f728255a305891f10c2a20e1 Mon Sep 17 00:00:00 2001 From: Tiago Silva Date: Fri, 5 Jul 2024 20:01:15 +0100 Subject: [PATCH 08/31] Delete unused graph component --- .../strategies/create/CreateStrategyGraph.tsx | 37 ------------------- 1 file changed, 37 deletions(-) delete mode 100644 src/components/strategies/create/CreateStrategyGraph.tsx diff --git a/src/components/strategies/create/CreateStrategyGraph.tsx b/src/components/strategies/create/CreateStrategyGraph.tsx deleted file mode 100644 index 9151c562c..000000000 --- a/src/components/strategies/create/CreateStrategyGraph.tsx +++ /dev/null @@ -1,37 +0,0 @@ -import { m } from 'libs/motion'; -import { items } from 'components/strategies/common/variants'; -import { Button } from 'components/common/button'; -import { ReactComponent as IconX } from 'assets/icons/X.svg'; -import { carbonEvents } from 'services/events'; -import { FC, ReactNode } from 'react'; - -interface Props { - setShowGraph: (value: boolean) => void; - children: ReactNode; -} -export const CreateStrategyGraph: FC = ({ setShowGraph, children }) => { - return ( - -
-

Price Chart

- -
- {children} -
- ); -}; From 1274b63a2ecd590d90eab63a07fef7918d20781e Mon Sep 17 00:00:00 2001 From: Tiago Silva Date: Fri, 5 Jul 2024 20:01:34 +0100 Subject: [PATCH 09/31] Add route history clean-up to setup --- src/libs/testing-library/setup.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/libs/testing-library/setup.ts b/src/libs/testing-library/setup.ts index f71dfc2fb..a418821fe 100644 --- a/src/libs/testing-library/setup.ts +++ b/src/libs/testing-library/setup.ts @@ -3,11 +3,12 @@ import { afterEach, vitest } from 'vitest'; import { tokens } from './utils'; import { cleanup } from '@testing-library/react'; -// Set up clean-up after each test. See issue https://github.com/vitest-dev/vitest/issues/1430 -afterEach(() => cleanup()); +afterEach(() => { + window.history.replaceState(null, 'root', '/'); + cleanup(); +}); // MOCK STORE PROVIDER CONTEXTS - vitest.mock('store/useTokensStore.ts', async (importOriginal) => { const mod = await importOriginal(); const tokensMap = new Map( @@ -30,7 +31,6 @@ vitest.mock('store/useTokensStore.ts', async (importOriginal) => { }); // MOCK CARBON SDK - vitest.mock('libs/sdk/index.ts', () => { return { carbonSDK: { From cbd502abea094bae86e15cd9b7f36b3ba7ac13ef Mon Sep 17 00:00:00 2001 From: Tiago Silva Date: Fri, 5 Jul 2024 20:02:29 +0100 Subject: [PATCH 10/31] Add server mock to utils --- package.json | 1 + src/libs/testing-library/utils.ts | 24 ++++++++++++++++++++++++ 2 files changed, 25 insertions(+) diff --git a/package.json b/package.json index fa6ea72b3..e9de66644 100644 --- a/package.json +++ b/package.json @@ -67,6 +67,7 @@ "lodash": "^4.17.21", "lz-string": "^1.5.0", "mipd": "^0.0.7", + "msw": "^2.3.1", "numbro": "^2.3.6", "numeral": "^2.0.6", "postcss": "^8.4.31", diff --git a/src/libs/testing-library/utils.ts b/src/libs/testing-library/utils.ts index bc05167b3..64f1e05d4 100644 --- a/src/libs/testing-library/utils.ts +++ b/src/libs/testing-library/utils.ts @@ -8,6 +8,30 @@ import { RouterRenderParams } from './types'; import { debugTokens } from '../../../e2e/utils/types'; import { parseSearchWith } from 'libs/routing/utils'; import { isAddress } from 'ethers/lib/utils'; +import { RequestHandler } from 'msw'; +import { setupServer } from 'msw/node'; +import { afterAll, beforeAll } from 'vitest'; + +export class MockServer { + private server; + constructor(private handlers: RequestHandler[] = []) { + this.server = setupServer(...this.handlers); + } + + addHandler(handler: RequestHandler) { + this.handlers.push(handler); + this.server.resetHandlers(...this.handlers); + } + + reset() { + this.server.resetHandlers(); + } + + start() { + beforeAll(() => this.server.listen({ onUnhandledRequest: 'error' })); + afterAll(() => this.server.close()); + } +} export const tokens = [ { From 357e0731ecc8be727fa6d9ac651444a7b8b47ed1 Mon Sep 17 00:00:00 2001 From: Tiago Silva Date: Fri, 5 Jul 2024 20:03:25 +0100 Subject: [PATCH 11/31] Update overlapping test - Add endpoint mock instead of import mock - Use data-testid instead of text to get elements from screen - Add tests to cover user market price below min and above max --- .../strategies/create/overlapping.test.tsx | 247 +++++++++++++----- 1 file changed, 188 insertions(+), 59 deletions(-) diff --git a/src/pages/strategies/create/overlapping.test.tsx b/src/pages/strategies/create/overlapping.test.tsx index 86769a823..dff62f9cb 100644 --- a/src/pages/strategies/create/overlapping.test.tsx +++ b/src/pages/strategies/create/overlapping.test.tsx @@ -1,70 +1,199 @@ -import { test, expect, afterEach, vitest } from 'vitest'; +import { describe, test, expect } from 'vitest'; +import { HttpResponse, http } from 'msw'; import { renderWithRouter, screen } from 'libs/testing-library'; +import userEvent from '@testing-library/user-event'; import { debugTokens } from '../../../../e2e/utils/types'; import { CreateOverlappingStrategyPage } from './overlapping'; -import userEvent from '@testing-library/user-event'; - -vitest.mock('hooks/useMarketPrice', () => { - return { - useMarketPrice: () => { - return { marketPrice: 2800, isPending: false }; - }, - }; -}); +import { MockServer } from 'libs/testing-library/utils'; const basePath = '/strategies/create/overlapping'; -afterEach(async () => { - window.history.replaceState(null, 'root', '/'); -}); -test('run overlapping form with deeplink and user market price', async () => { - // Initialize user and set params - const user = userEvent.setup(); - const search = { - base: debugTokens.ETH, - quote: debugTokens.USDC, - marketPrice: '2500', - min: '2000', - max: '3000', - spread: '0.01', - anchor: 'buy', - budget: '100', - }; - - // Render page - const { router } = await renderWithRouter({ - component: () => , - basePath, - search, +const marketRates: Record> = { + '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48': { USD: 1 }, + '0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee': { USD: 2800 }, +}; + +const marketRateHandler = ( + marketRates: Record> +) => { + return http.get('**/*/market-rate', ({ request }) => { + const queryParams = new URL(request.url).searchParams; + const address = queryParams.get('address')?.toLowerCase(); + if (!address) return new HttpResponse(null, { status: 404 }); + return HttpResponse.json({ + data: marketRates[address], + }); }); +}; + +const mockServer = new MockServer([marketRateHandler(marketRates)]); + +describe('overlapping page', () => { + mockServer.start(); + test('run overlapping form with deeplink and user market price', async () => { + // Initialize user and set search params + const user = userEvent.setup(); + const search = { + base: debugTokens.ETH, + quote: debugTokens.USDC, + marketPrice: '2500', + min: '2000', + max: '3000', + spread: '0.01', + anchor: 'buy', + budget: '100', + }; + + // Render page + const { router } = await renderWithRouter({ + component: () => , + basePath, + search, + }); + + // Check search params + expect(router.state.location.pathname).toBe(basePath); + expect(router.state.location.search).toStrictEqual(search); + + // Close price chart + await user.click(screen.getByTestId('close-chart')); + const priceChart = screen.queryByRole('heading', { + name: 'Price Chart', + }); + expect(priceChart).not.toBeInTheDocument(); + + // Check price range input and market price indication + const priceRangeMin = await screen.findByTestId('input-min'); + const priceRangeMax = await screen.findByTestId('input-max'); + const marketPriceIndications = await screen.findAllByTestId( + 'market-price-indication' + ); + expect(priceRangeMin).toHaveValue(search.min); + expect(priceRangeMax).toHaveValue(search.max); + expect(marketPriceIndications[0]).toHaveTextContent('20.00% below'); + expect(marketPriceIndications[1]).toHaveTextContent('20.00% above'); + + // Check budget + const inputBudget = screen.getByTestId('input-budget'); + expect(inputBudget).toHaveValue(search.budget); + + // Check warning to approve deposit exists + const depositWarning = screen.queryByTestId('approve-warnings'); + expect(depositWarning).toBeInTheDocument(); + }); + + test('run overlapping form with external market price', async () => { + // Set search params + const search = { + base: debugTokens.ETH, + quote: debugTokens.USDC, + min: '2000', + max: '3000', + spread: '0.01', + anchor: 'buy', + budget: '100', + }; + + // Render page + const { router } = await renderWithRouter({ + component: () => , + basePath, + search, + }); + + // Check search params + expect(router.state.location.pathname).toBe(basePath); + expect(router.state.location.search).toStrictEqual(search); + + // Check price range input and market price indication + const priceRangeMin = await screen.findByTestId('input-min'); + const priceRangeMax = await screen.findByTestId('input-max'); + const marketPriceIndications = await screen.findAllByTestId( + 'market-price-indication' + ); + expect(priceRangeMin).toHaveValue(search.min); + expect(priceRangeMax).toHaveValue(search.max); + expect(marketPriceIndications[0]).toHaveTextContent('28.57% below'); + expect(marketPriceIndications[1]).toHaveTextContent('7.14% above'); + }); + + test('run overlapping form with user market price below min price', async () => { + // Set search params + const search = { + base: debugTokens.ETH, + quote: debugTokens.USDC, + min: '2000', + max: '3000', + marketPrice: '1500', + spread: '0.01', + anchor: 'buy', + budget: '100', + }; + + // Render page + const { router } = await renderWithRouter({ + component: () => , + basePath, + search, + }); + + // Check search params + const { budget, ...rest } = search; + expect(router.state.location.pathname).toBe(basePath); + expect(router.state.location.search).toStrictEqual({ + ...rest, + anchor: 'sell', + }); + + // Check price range input and market price indication + const priceRangeMin = await screen.findByTestId('input-min'); + const priceRangeMax = await screen.findByTestId('input-max'); + const marketPriceIndications = await screen.findAllByTestId( + 'market-price-indication' + ); + expect(priceRangeMin).toHaveValue(search.min); + expect(priceRangeMax).toHaveValue(search.max); + expect(marketPriceIndications[0]).toHaveTextContent('33.33% above'); + expect(marketPriceIndications[1]).toHaveTextContent('>99.99% above'); + }); + + test('run overlapping form with user market price above max price', async () => { + // Set search params + const search = { + base: debugTokens.ETH, + quote: debugTokens.USDC, + min: '2000', + max: '3000', + marketPrice: '3200', + spread: '0.01', + anchor: 'sell', + budget: '100', + }; + + // Render page + const { router } = await renderWithRouter({ + component: () => , + basePath, + search, + }); - // Check search params - expect(router.state.location.pathname).toBe(basePath); - expect(router.state.location.search).toStrictEqual(search); + // Check search params + const { budget, ...rest } = search; + expect(router.state.location.pathname).toBe(basePath); + expect(router.state.location.search).toStrictEqual({ + ...rest, + anchor: 'buy', + }); - // Close price chart - await user.click(screen.getByText('Close Chart')); - const priceChart = screen.queryByRole('heading', { - name: 'Price Chart', + // Check price range input and market price indication + const priceRangeMin = await screen.findByTestId('input-min'); + const priceRangeMax = await screen.findByTestId('input-max'); + const marketPriceIndications = await screen.findAllByTestId( + 'market-price-indication' + ); + expect(priceRangeMin).toHaveValue(search.min); + expect(priceRangeMax).toHaveValue(search.max); + expect(marketPriceIndications[0]).toHaveTextContent('37.50% below'); + expect(marketPriceIndications[1]).toHaveTextContent('6.25% below'); }); - expect(priceChart).not.toBeInTheDocument(); - - // Check price range input and market price indication - const priceRangeMin = await screen.findByTestId('input-min'); - const priceRangeMax = await screen.findByTestId('input-max'); - const marketPriceIndications = await screen.findAllByTestId( - 'market-price-indication' - ); - expect(priceRangeMin).toHaveValue(search.min); - expect(priceRangeMax).toHaveValue(search.max); - expect(marketPriceIndications[0]).toHaveTextContent('20.00% below'); - expect(marketPriceIndications[1]).toHaveTextContent('20.00% above'); - - // Check budget - const inputBudget = screen.getByTestId('input-budget'); - expect(inputBudget).toHaveValue(search.budget); - - // Check warning to approve deposit exists - const depositWarning = screen.queryByTestId('approve-warnings'); - expect(depositWarning).toBeInTheDocument(); }); From 0e613e4e77e1733b306a5b51b05e8d6a3d3c35d7 Mon Sep 17 00:00:00 2001 From: Tiago Silva Date: Fri, 5 Jul 2024 20:09:16 +0100 Subject: [PATCH 12/31] Add vitest coverage --- package.json | 2 ++ vitest.config.ts | 5 +++++ 2 files changed, 7 insertions(+) diff --git a/package.json b/package.json index e9de66644..6a8ea967e 100644 --- a/package.json +++ b/package.json @@ -35,6 +35,7 @@ "@typescript-eslint/eslint-plugin": "^5.59.9", "@typescript-eslint/parser": "^5.59.9", "@vitejs/plugin-react": "^4.3.1", + "@vitest/coverage-v8": "^1.6.0", "autoprefixer": "^10.4.12", "body-scroll-lock": "^4.0.0-beta.0", "buffer": "^6.0.3", @@ -101,6 +102,7 @@ "serve": "vite preview", "pretest": "yarn compile-abis", "test": "vitest run --mode production", + "coverage": "yarn test --coverage", "pree2e": "yarn playwright install --with-deps chromium", "e2e": "playwright test", "lint": "eslint --ext .tsx,.ts .", diff --git a/vitest.config.ts b/vitest.config.ts index 1407f7aac..df2149722 100644 --- a/vitest.config.ts +++ b/vitest.config.ts @@ -15,6 +15,11 @@ export default defineConfig({ inline: ['/@bancor/carbon-sdk/'], }, }, + coverage: { + reporter: ['text', 'json', 'html'], + include: ['**/src/**'], + exclude: ['**/src/abis/**'], + }, }, plugins: [tsconfigPaths(), svgrPlugin()], }); From 21bf516055f3cd574e7d078f2b6289223a05e670 Mon Sep 17 00:00:00 2001 From: Tiago Silva Date: Fri, 5 Jul 2024 20:09:44 +0100 Subject: [PATCH 13/31] Update yarn lock --- yarn.lock | 329 ++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 322 insertions(+), 7 deletions(-) diff --git a/yarn.lock b/yarn.lock index 0d9b5e6d3..d072a45f5 100644 --- a/yarn.lock +++ b/yarn.lock @@ -35,6 +35,14 @@ "@jridgewell/gen-mapping" "^0.3.0" "@jridgewell/trace-mapping" "^0.3.9" +"@ampproject/remapping@^2.2.1": + version "2.3.0" + resolved "https://registry.yarnpkg.com/@ampproject/remapping/-/remapping-2.3.0.tgz#ed441b6fa600072520ce18b43d2c8cc8caecc7f4" + integrity sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw== + dependencies: + "@jridgewell/gen-mapping" "^0.3.5" + "@jridgewell/trace-mapping" "^0.3.24" + "@babel/code-frame@^7.0.0", "@babel/code-frame@^7.10.4", "@babel/code-frame@^7.22.5": version "7.22.5" resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.22.5.tgz#234d98e1551960604f1246e6475891a570ad5658" @@ -479,7 +487,7 @@ js-tokens "^4.0.0" picocolors "^1.0.0" -"@babel/parser@^7.1.0", "@babel/parser@^7.20.7", "@babel/parser@^7.24.7": +"@babel/parser@^7.1.0", "@babel/parser@^7.20.7", "@babel/parser@^7.24.4", "@babel/parser@^7.24.7": version "7.24.7" resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.24.7.tgz#9a5226f92f0c5c8ead550b750f5608e766c8ce85" integrity sha512-9uUYRm6OqQrCqQdG1iCBwBPZgN8ciDBro2nIOFaiRz1/BCxaI7CNvQbDHvsArAC7Tw9Hda/B3U+6ui9u4HWXPw== @@ -1407,7 +1415,7 @@ debug "^4.3.1" globals "^11.1.0" -"@babel/types@^7.0.0", "@babel/types@^7.20.7", "@babel/types@^7.24.7": +"@babel/types@^7.0.0", "@babel/types@^7.20.7", "@babel/types@^7.24.0", "@babel/types@^7.24.7": version "7.24.7" resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.24.7.tgz#6027fe12bc1aa724cd32ab113fb7f1988f1f66f2" integrity sha512-XEFXSlxiG5td2EJRe8vOmRbaXVgfcBlszKujvVmWIK/UpywWljQCfzAv3RQCGujWQ1RD4YYWEAqDXfuJiy8f5Q== @@ -1448,6 +1456,25 @@ ethers "^5.7.2" events "^3.3.0" +"@bcoe/v8-coverage@^0.2.3": + version "0.2.3" + resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39" + integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw== + +"@bundled-es-modules/cookie@^2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@bundled-es-modules/cookie/-/cookie-2.0.0.tgz#c3b82703969a61cf6a46e959a012b2c257f6b164" + integrity sha512-Or6YHg/kamKHpxULAdSqhGqnWFneIXu1NKvvfBBzKGwpVsYuFIQ5aBPHDnnoR3ghW1nvSkALd+EF9iMtY7Vjxw== + dependencies: + cookie "^0.5.0" + +"@bundled-es-modules/statuses@^1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@bundled-es-modules/statuses/-/statuses-1.0.1.tgz#761d10f44e51a94902c4da48675b71a76cc98872" + integrity sha512-yn7BklA5acgcBr+7w064fGV+SGIFySjCKpqjcWgBAIfrAkY+4GQTJJHQMeT3V/sgz23VTEVV8TtOmkvJAhFVfg== + dependencies: + statuses "^2.0.1" + "@cloudflare/workers-types@^4.20230717.0": version "4.20230801.0" resolved "https://registry.yarnpkg.com/@cloudflare/workers-types/-/workers-types-4.20230801.0.tgz#d23ec9671a08d91ad027fb4c783e94dee275d279" @@ -2053,6 +2080,45 @@ resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz#b520529ec21d8e5945a1851dfd1c32e94e39ff45" integrity sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA== +"@inquirer/confirm@^3.0.0": + version "3.1.14" + resolved "https://registry.yarnpkg.com/@inquirer/confirm/-/confirm-3.1.14.tgz#b50a156f2cc0a6f874f2d2ab1739e988fbf950f4" + integrity sha512-nbLSX37b2dGPtKWL3rPuR/5hOuD30S+pqJ/MuFiUEgN6GiMs8UMxiurKAMDzKt6C95ltjupa8zH6+3csXNHWpA== + dependencies: + "@inquirer/core" "^9.0.2" + "@inquirer/type" "^1.4.0" + +"@inquirer/core@^9.0.2": + version "9.0.2" + resolved "https://registry.yarnpkg.com/@inquirer/core/-/core-9.0.2.tgz#8be8782266f00129acb5c804537d1231b2fe3ac6" + integrity sha512-nguvH3TZar3ACwbytZrraRTzGqyxJfYJwv+ZwqZNatAosdWQMP1GV8zvmkNlBe2JeZSaw0WYBHZk52pDpWC9qA== + dependencies: + "@inquirer/figures" "^1.0.3" + "@inquirer/type" "^1.4.0" + "@types/mute-stream" "^0.0.4" + "@types/node" "^20.14.9" + "@types/wrap-ansi" "^3.0.0" + ansi-escapes "^4.3.2" + cli-spinners "^2.9.2" + cli-width "^4.1.0" + mute-stream "^1.0.0" + signal-exit "^4.1.0" + strip-ansi "^6.0.1" + wrap-ansi "^6.2.0" + yoctocolors-cjs "^2.1.2" + +"@inquirer/figures@^1.0.3": + version "1.0.3" + resolved "https://registry.yarnpkg.com/@inquirer/figures/-/figures-1.0.3.tgz#1227cc980f88e6d6ab85abadbf164f5038041edd" + integrity sha512-ErXXzENMH5pJt5/ssXV0DfWUZqly8nGzf0UcBV9xTnP+KyffE2mqyxIMBrZ8ijQck2nU0TQm40EQB53YreyWHw== + +"@inquirer/type@^1.4.0": + version "1.4.0" + resolved "https://registry.yarnpkg.com/@inquirer/type/-/type-1.4.0.tgz#3dd0c8f78c0548bbc18b9c07af16a86c4007e1f0" + integrity sha512-AjOqykVyjdJQvtfkNDGUyMYGF8xN50VUxftCQWsOyIo4DFRLr6VQhW0VItGI1JIyQGCGgIpKa7hMMwNhZb4OIw== + dependencies: + mute-stream "^1.0.0" + "@isaacs/cliui@^8.0.2": version "8.0.2" resolved "https://registry.yarnpkg.com/@isaacs/cliui/-/cliui-8.0.2.tgz#b37667b7bc181c168782259bab42474fbf52b550" @@ -2065,6 +2131,11 @@ wrap-ansi "^8.1.0" wrap-ansi-cjs "npm:wrap-ansi@^7.0.0" +"@istanbuljs/schema@^0.1.2": + version "0.1.3" + resolved "https://registry.yarnpkg.com/@istanbuljs/schema/-/schema-0.1.3.tgz#e45e384e4b8ec16bce2fd903af78450f6bf7ec98" + integrity sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA== + "@jest/schemas@^29.6.3": version "29.6.3" resolved "https://registry.yarnpkg.com/@jest/schemas/-/schemas-29.6.3.tgz#430b5ce8a4e0044a7e3819663305a7b3091c8e03" @@ -2128,7 +2199,7 @@ "@jridgewell/resolve-uri" "3.1.0" "@jridgewell/sourcemap-codec" "1.4.14" -"@jridgewell/trace-mapping@^0.3.24", "@jridgewell/trace-mapping@^0.3.25": +"@jridgewell/trace-mapping@^0.3.23", "@jridgewell/trace-mapping@^0.3.24", "@jridgewell/trace-mapping@^0.3.25": version "0.3.25" resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz#15f190e98895f3fc23276ee14bc76b675c2e50f0" integrity sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ== @@ -2380,6 +2451,23 @@ "@motionone/dom" "^10.16.2" tslib "^2.3.1" +"@mswjs/cookies@^1.1.0": + version "1.1.1" + resolved "https://registry.yarnpkg.com/@mswjs/cookies/-/cookies-1.1.1.tgz#8b519e2bd8f1577c530beed44a25578eb9a6e72c" + integrity sha512-W68qOHEjx1iD+4VjQudlx26CPIoxmIAtK4ZCexU0/UJBG6jYhcuyzKJx+Iw8uhBIGd9eba64XgWVgo20it1qwA== + +"@mswjs/interceptors@^0.29.0": + version "0.29.1" + resolved "https://registry.yarnpkg.com/@mswjs/interceptors/-/interceptors-0.29.1.tgz#e77fc58b5188569041d0440b25c9e9ebb1ccd60a" + integrity sha512-3rDakgJZ77+RiQUuSK69t1F0m8BQKA8Vh5DCS5V0DWvNY67zob2JhhQrhCO0AKLGINTRSFd1tBaHcJTkhefoSw== + dependencies: + "@open-draft/deferred-promise" "^2.2.0" + "@open-draft/logger" "^0.3.0" + "@open-draft/until" "^2.0.0" + is-node-process "^1.2.0" + outvariant "^1.2.1" + strict-event-emitter "^0.5.1" + "@nicolo-ribaudo/eslint-scope-5-internals@5.1.1-v1": version "5.1.1-v1" resolved "https://registry.yarnpkg.com/@nicolo-ribaudo/eslint-scope-5-internals/-/eslint-scope-5-internals-5.1.1-v1.tgz#dbf733a965ca47b1973177dc0bb6c889edcfb129" @@ -2454,6 +2542,24 @@ "@nodelib/fs.scandir" "2.1.5" fastq "^1.6.0" +"@open-draft/deferred-promise@^2.2.0": + version "2.2.0" + resolved "https://registry.yarnpkg.com/@open-draft/deferred-promise/-/deferred-promise-2.2.0.tgz#4a822d10f6f0e316be4d67b4d4f8c9a124b073bd" + integrity sha512-CecwLWx3rhxVQF6V4bAgPS5t+So2sTbPgAzafKkVizyi7tlwpcFpdFqq+wqF2OwNBmqFuu6tOyouTuxgpMfzmA== + +"@open-draft/logger@^0.3.0": + version "0.3.0" + resolved "https://registry.yarnpkg.com/@open-draft/logger/-/logger-0.3.0.tgz#2b3ab1242b360aa0adb28b85f5d7da1c133a0954" + integrity sha512-X2g45fzhxH238HKO4xbSr7+wBS8Fvw6ixhTDuvLd5mqh6bJJCFAPwU9mPDxbcrRtfxv4u5IHCEH77BmxvXmmxQ== + dependencies: + is-node-process "^1.2.0" + outvariant "^1.4.0" + +"@open-draft/until@^2.0.0", "@open-draft/until@^2.1.0": + version "2.1.0" + resolved "https://registry.yarnpkg.com/@open-draft/until/-/until-2.1.0.tgz#0acf32f470af2ceaf47f095cdecd40d68666efda" + integrity sha512-U69T3ItWHvLwGg5eJ0n3I62nWuE6ilHlmz7zM0npLBRvPRd7e6NYmg54vvRtP5mZG7kZqZCFVdsTWo7BPtBujg== + "@parcel/watcher-android-arm64@2.4.1": version "2.4.1" resolved "https://registry.yarnpkg.com/@parcel/watcher-android-arm64/-/watcher-android-arm64-2.4.1.tgz#c2c19a3c442313ff007d2d7a9c2c1dd3e1c9ca84" @@ -3275,6 +3381,11 @@ resolved "https://registry.yarnpkg.com/@types/body-scroll-lock/-/body-scroll-lock-3.1.0.tgz#435f6abf682bf58640e1c2ee5978320b891970e7" integrity sha512-3owAC4iJub5WPqRhxd8INarF2bWeQq1yQHBgYhN0XLBJMpd5ED10RrJ3aKiAwlTyL5wK7RkBD4SZUQz2AAAMdA== +"@types/cookie@^0.6.0": + version "0.6.0" + resolved "https://registry.yarnpkg.com/@types/cookie/-/cookie-0.6.0.tgz#eac397f28bf1d6ae0ae081363eca2f425bedf0d5" + integrity sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA== + "@types/d3-array@*": version "3.2.1" resolved "https://registry.yarnpkg.com/@types/d3-array/-/d3-array-3.2.1.tgz#1f6658e3d2006c4fceac53fde464166859f8b8c5" @@ -3532,6 +3643,13 @@ resolved "https://registry.yarnpkg.com/@types/ms/-/ms-0.7.31.tgz#31b7ca6407128a3d2bbc27fe2d21b345397f6197" integrity sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA== +"@types/mute-stream@^0.0.4": + version "0.0.4" + resolved "https://registry.yarnpkg.com/@types/mute-stream/-/mute-stream-0.0.4.tgz#77208e56a08767af6c5e1237be8888e2f255c478" + integrity sha512-CPM9nzrCPPJHQNA9keH9CVkVI+WR5kMa+7XEs5jcGQ0VoAGnLv242w8lIVgwAEfmE4oufJRaTc9PNLQl0ioAow== + dependencies: + "@types/node" "*" + "@types/node@*": version "20.4.8" resolved "https://registry.yarnpkg.com/@types/node/-/node-20.4.8.tgz#b5dda19adaa473a9bf0ab5cbd8f30ec7d43f5c85" @@ -3544,6 +3662,13 @@ dependencies: undici-types "~5.26.4" +"@types/node@^20.14.9": + version "20.14.10" + resolved "https://registry.yarnpkg.com/@types/node/-/node-20.14.10.tgz#a1a218290f1b6428682e3af044785e5874db469a" + integrity sha512-MdiXf+nDuMvY0gJKxyfZ7/6UFsETO7mGKF54MVD/ekJS6HdFtpZFBgrh6Pseu64XTb2MLyFPlbW6hj8HYRQNOQ== + dependencies: + undici-types "~5.26.4" + "@types/numeral@^2.0.2": version "2.0.2" resolved "https://registry.yarnpkg.com/@types/numeral/-/numeral-2.0.2.tgz#8ea2c4f4e64c0cc948ad7da375f6f827778a7912" @@ -3597,6 +3722,11 @@ resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.5.0.tgz#591c1ce3a702c45ee15f47a42ade72c2fd78978a" integrity sha512-G8hZ6XJiHnuhQKR7ZmysCeJWE08o8T0AXtk5darsCaTVsYZhhgUrq53jizaR2FvsoeCwJhlmwTjkXBY5Pn/ZHw== +"@types/statuses@^2.0.4": + version "2.0.5" + resolved "https://registry.yarnpkg.com/@types/statuses/-/statuses-2.0.5.tgz#f61ab46d5352fd73c863a1ea4e1cef3b0b51ae63" + integrity sha512-jmIUGWrAiwu3dZpxntxieC+1n/5c3mjrImkmOSQ2NC5uP6cYO4aAZDdSmRcI5C1oiTmqlZGHC+/NmJrKogbP5A== + "@types/trusted-types@^2.0.2": version "2.0.3" resolved "https://registry.yarnpkg.com/@types/trusted-types/-/trusted-types-2.0.3.tgz#a136f83b0758698df454e328759dbd3d44555311" @@ -3607,6 +3737,11 @@ resolved "https://registry.yarnpkg.com/@types/ua-parser-js/-/ua-parser-js-0.7.36.tgz#9bd0b47f26b5a3151be21ba4ce9f5fa457c5f190" integrity sha512-N1rW+njavs70y2cApeIw1vLMYXRwfBy+7trgavGuuTfOd7j1Yh7QTRc/yqsPl6ncokt72ZXuxEU0PiCp9bSwNQ== +"@types/wrap-ansi@^3.0.0": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@types/wrap-ansi/-/wrap-ansi-3.0.0.tgz#18b97a972f94f60a679fd5c796d96421b9abb9fd" + integrity sha512-ltIpx+kM7g/MLRZfkbL7EsCEjfzCcScLpkg37eXEtx5kmrAKBkTJwd1GIAjDSL8wTpM6Hzn5YO4pSb91BEwu1g== + "@types/ws@^8.5.4": version "8.5.5" resolved "https://registry.yarnpkg.com/@types/ws/-/ws-8.5.5.tgz#af587964aa06682702ee6dcbc7be41a80e4b28eb" @@ -3716,6 +3851,25 @@ "@types/babel__core" "^7.20.5" react-refresh "^0.14.2" +"@vitest/coverage-v8@^1.6.0": + version "1.6.0" + resolved "https://registry.yarnpkg.com/@vitest/coverage-v8/-/coverage-v8-1.6.0.tgz#2f54ccf4c2d9f23a71294aba7f95b3d2e27d14e7" + integrity sha512-KvapcbMY/8GYIG0rlwwOKCVNRc0OL20rrhFkg/CHNzncV03TE2XWvO5w9uZYoxNiMEBacAJt3unSOiZ7svePew== + dependencies: + "@ampproject/remapping" "^2.2.1" + "@bcoe/v8-coverage" "^0.2.3" + debug "^4.3.4" + istanbul-lib-coverage "^3.2.2" + istanbul-lib-report "^3.0.1" + istanbul-lib-source-maps "^5.0.4" + istanbul-reports "^3.1.6" + magic-string "^0.30.5" + magicast "^0.3.3" + picocolors "^1.0.0" + std-env "^3.5.0" + strip-literal "^2.0.0" + test-exclude "^6.0.0" + "@vitest/expect@1.6.0": version "1.6.0" resolved "https://registry.yarnpkg.com/@vitest/expect/-/expect-1.6.0.tgz#0b3ba0914f738508464983f4d811bc122b51fb30" @@ -4145,6 +4299,13 @@ ajv@^6.12.4: json-schema-traverse "^0.4.1" uri-js "^4.2.2" +ansi-escapes@^4.3.2: + version "4.3.2" + resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-4.3.2.tgz#6b2291d1db7d98b6521d5f1efa42d0f3a9feb65e" + integrity sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ== + dependencies: + type-fest "^0.21.3" + ansi-escapes@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-5.0.0.tgz#b6a0caf0eef0c41af190e9a749e0c00ec04bb2a6" @@ -4709,7 +4870,7 @@ chalk@^3.0.0: ansi-styles "^4.1.0" supports-color "^7.1.0" -chalk@^4.0.0, chalk@^4.0.2, chalk@^4.1.0: +chalk@^4.0.0, chalk@^4.0.2, chalk@^4.1.0, chalk@^4.1.2: version "4.1.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== @@ -4781,6 +4942,11 @@ cli-cursor@^4.0.0: dependencies: restore-cursor "^4.0.0" +cli-spinners@^2.9.2: + version "2.9.2" + resolved "https://registry.yarnpkg.com/cli-spinners/-/cli-spinners-2.9.2.tgz#1773a8f4b9c4d6ac31563df53b3fc1d79462fe41" + integrity sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg== + cli-truncate@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/cli-truncate/-/cli-truncate-3.1.0.tgz#3f23ab12535e3d73e839bb43e73c9de487db1389" @@ -4789,6 +4955,11 @@ cli-truncate@^3.1.0: slice-ansi "^5.0.0" string-width "^5.0.0" +cli-width@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-4.1.0.tgz#42daac41d3c254ef38ad8ac037672130173691c5" + integrity sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ== + clipboardy@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/clipboardy/-/clipboardy-4.0.0.tgz#e73ced93a76d19dd379ebf1f297565426dffdca1" @@ -4946,6 +5117,11 @@ cookie@^0.4.1: resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.4.2.tgz#0e41f24de5ecf317947c82fc789e06a884824432" integrity sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA== +cookie@^0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.5.0.tgz#d1f5d71adec6558c58f389987c366aa47e994f8b" + integrity sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw== + core-js-compat@^3.31.0: version "3.32.0" resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.32.0.tgz#f41574b6893ab15ddb0ac1693681bd56c8550a90" @@ -6552,7 +6728,7 @@ glob@^10.3.10: minipass "^5.0.0 || ^6.0.2 || ^7.0.0" path-scurry "^1.10.1" -glob@^7.1.3, glob@^7.1.6: +glob@^7.1.3, glob@^7.1.4, glob@^7.1.6: version "7.2.3" resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b" integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q== @@ -6617,6 +6793,11 @@ graphemer@^1.4.0: resolved "https://registry.yarnpkg.com/graphemer/-/graphemer-1.4.0.tgz#fb2f1d55e0e3a1849aeffc90c4fa0dd53a0e66c6" integrity sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag== +graphql@^16.8.1: + version "16.9.0" + resolved "https://registry.yarnpkg.com/graphql/-/graphql-16.9.0.tgz#1c310e63f16a49ce1fbb230bd0a000e99f6f115f" + integrity sha512-GGTKBX4SD7Wdb8mqeDLni2oaRGYQWjWHGKPQ24ZMnUtKfcsVoiv4uX8+LJr1K6U5VW2Lu1BwJnj7uiori0YtRw== + gzip-size@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/gzip-size/-/gzip-size-6.0.0.tgz#065367fd50c239c0671cbcbad5be3e2eeb10e462" @@ -6711,6 +6892,11 @@ hash.js@1.1.7, hash.js@^1.0.0, hash.js@^1.0.3: inherits "^2.0.3" minimalistic-assert "^1.0.1" +headers-polyfill@^4.0.2: + version "4.0.3" + resolved "https://registry.yarnpkg.com/headers-polyfill/-/headers-polyfill-4.0.3.tgz#922a0155de30ecc1f785bcf04be77844ca95ad07" + integrity sha512-IScLbePpkvO846sIwOtOTDjutRMWdXdJmXdMvk6gCBHxFO8d+QKOQedyZSxFTTFYRSmlgSTDtXqqq4pcenBXLQ== + hey-listen@^1.0.8: version "1.0.8" resolved "https://registry.yarnpkg.com/hey-listen/-/hey-listen-1.0.8.tgz#8e59561ff724908de1aa924ed6ecc84a56a9aa68" @@ -6749,6 +6935,11 @@ html-encoding-sniffer@^3.0.0: dependencies: whatwg-encoding "^2.0.0" +html-escaper@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/html-escaper/-/html-escaper-2.0.2.tgz#dfd60027da36a36dfcbe236262c00a5822681453" + integrity sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg== + http-proxy-agent@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz#5129800203520d434f142bc78ff3c170800f2b43" @@ -6993,6 +7184,11 @@ is-negative-zero@^2.0.2: resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.2.tgz#7bf6f03a28003b8b3965de3ac26f664d765f3150" integrity sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA== +is-node-process@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/is-node-process/-/is-node-process-1.2.0.tgz#ea02a1b90ddb3934a19aea414e88edef7e11d134" + integrity sha512-Vg4o6/fqPxIjtxgUH5QLJhwZ7gW5diGCVlXpuUfELC62CuxM1iHcRe51f2W1FDy04Ai4KJkagKjx3XaqyfRKXw== + is-number-object@^1.0.4: version "1.0.7" resolved "https://registry.yarnpkg.com/is-number-object/-/is-number-object-1.0.7.tgz#59d50ada4c45251784e9904f5246c742f07a42fc" @@ -7127,6 +7323,37 @@ isows@1.0.4: resolved "https://registry.yarnpkg.com/isows/-/isows-1.0.4.tgz#810cd0d90cc4995c26395d2aa4cfa4037ebdf061" integrity sha512-hEzjY+x9u9hPmBom9IIAqdJCwNLax+xrPb51vEPpERoFlIxgmZcHzsT5jKG06nvInKOBGvReAVz80Umed5CczQ== +istanbul-lib-coverage@^3.0.0, istanbul-lib-coverage@^3.2.2: + version "3.2.2" + resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz#2d166c4b0644d43a39f04bf6c2edd1e585f31756" + integrity sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg== + +istanbul-lib-report@^3.0.0, istanbul-lib-report@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz#908305bac9a5bd175ac6a74489eafd0fc2445a7d" + integrity sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw== + dependencies: + istanbul-lib-coverage "^3.0.0" + make-dir "^4.0.0" + supports-color "^7.1.0" + +istanbul-lib-source-maps@^5.0.4: + version "5.0.6" + resolved "https://registry.yarnpkg.com/istanbul-lib-source-maps/-/istanbul-lib-source-maps-5.0.6.tgz#acaef948df7747c8eb5fbf1265cb980f6353a441" + integrity sha512-yg2d+Em4KizZC5niWhQaIomgf5WlL4vOOjZ5xGCmF8SnPE/mDWWXgvRExdcpCgh9lLRRa1/fSYp2ymmbJ1pI+A== + dependencies: + "@jridgewell/trace-mapping" "^0.3.23" + debug "^4.1.1" + istanbul-lib-coverage "^3.0.0" + +istanbul-reports@^3.1.6: + version "3.1.7" + resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-3.1.7.tgz#daed12b9e1dca518e15c056e1e537e741280fa0b" + integrity sha512-BewmUXImeuRk2YY0PVbxgKAysvhRPUQE0h5QRM++nVWyubKGV0l8qQ5op8+B2DOmwSe63Jivj0BjkPQVf8fP5g== + dependencies: + html-escaper "^2.0.0" + istanbul-lib-report "^3.0.0" + jackspeak@^2.3.5: version "2.3.6" resolved "https://registry.yarnpkg.com/jackspeak/-/jackspeak-2.3.6.tgz#647ecc472238aee4b06ac0e461acc21a8c505ca8" @@ -7530,6 +7757,22 @@ magic-string@^0.30.5: dependencies: "@jridgewell/sourcemap-codec" "^1.4.15" +magicast@^0.3.3: + version "0.3.4" + resolved "https://registry.yarnpkg.com/magicast/-/magicast-0.3.4.tgz#bbda1791d03190a24b00ff3dd18151e7fd381d19" + integrity sha512-TyDF/Pn36bBji9rWKHlZe+PZb6Mx5V8IHCSxk7X4aljM4e/vyDvZZYwHewdVaqiA0nb3ghfHU/6AUpDxWoER2Q== + dependencies: + "@babel/parser" "^7.24.4" + "@babel/types" "^7.24.0" + source-map-js "^1.2.0" + +make-dir@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-4.0.0.tgz#c3c2307a771277cd9638305f915c29ae741b614e" + integrity sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw== + dependencies: + semver "^7.5.3" + md5.js@^1.3.4: version "1.3.5" resolved "https://registry.yarnpkg.com/md5.js/-/md5.js-1.3.5.tgz#b5d07b8e3216e3e27cd728d72f70d1e6a342005f" @@ -7736,11 +7979,39 @@ ms@^2.1.1: resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== +msw@^2.3.1: + version "2.3.1" + resolved "https://registry.yarnpkg.com/msw/-/msw-2.3.1.tgz#bfc73e256ffc2c74ec4381b604abb258df35f32b" + integrity sha512-ocgvBCLn/5l3jpl1lssIb3cniuACJLoOfZu01e3n5dbJrpA5PeeWn28jCLgQDNt6d7QT8tF2fYRzm9JoEHtiig== + dependencies: + "@bundled-es-modules/cookie" "^2.0.0" + "@bundled-es-modules/statuses" "^1.0.1" + "@inquirer/confirm" "^3.0.0" + "@mswjs/cookies" "^1.1.0" + "@mswjs/interceptors" "^0.29.0" + "@open-draft/until" "^2.1.0" + "@types/cookie" "^0.6.0" + "@types/statuses" "^2.0.4" + chalk "^4.1.2" + graphql "^16.8.1" + headers-polyfill "^4.0.2" + is-node-process "^1.2.0" + outvariant "^1.4.2" + path-to-regexp "^6.2.0" + strict-event-emitter "^0.5.1" + type-fest "^4.9.0" + yargs "^17.7.2" + multiformats@^9.4.2: version "9.9.0" resolved "https://registry.yarnpkg.com/multiformats/-/multiformats-9.9.0.tgz#c68354e7d21037a8f1f8833c8ccd68618e8f1d37" integrity sha512-HoMUjhH9T8DDBNT+6xzkrd9ga/XiBI4xLr58LJACwK6G3HTOPeMz4nB4KJs33L2BelrIJa7P0VuNaVF3hMYfjg== +mute-stream@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-1.0.0.tgz#e31bd9fe62f0aed23520aa4324ea6671531e013e" + integrity sha512-avsJQhyd+680gKXyG/sQc0nXaC6rBkPOfyHYcFb9+hdkqQkR9bdnkJ0AMZhke0oesPqIO+mFFJ+IdBc7mst4IA== + mz@^2.7.0: version "2.7.0" resolved "https://registry.yarnpkg.com/mz/-/mz-2.7.0.tgz#95008057a56cafadc2bc63dde7f9ff6955948e32" @@ -8011,6 +8282,11 @@ optionator@^0.9.3: prelude-ls "^1.2.1" type-check "^0.4.0" +outvariant@^1.2.1, outvariant@^1.4.0, outvariant@^1.4.2: + version "1.4.3" + resolved "https://registry.yarnpkg.com/outvariant/-/outvariant-1.4.3.tgz#221c1bfc093e8fec7075497e7799fdbf43d14873" + integrity sha512-+Sl2UErvtsoajRDKCE5/dBz4DIvHXQQnAxtQTF04OJxY0+DyZXSo5P5Bb7XYWOh81syohlYL24hbDwxedPUJCA== + p-limit@^2.2.0: version "2.3.0" resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1" @@ -8131,6 +8407,11 @@ path-scurry@^1.10.1, path-scurry@^1.6.1: lru-cache "^9.1.1 || ^10.0.0" minipass "^5.0.0 || ^6.0.2 || ^7.0.0" +path-to-regexp@^6.2.0: + version "6.2.2" + resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-6.2.2.tgz#324377a83e5049cbecadc5554d6a63a9a4866b36" + integrity sha512-GQX3SSMokngb36+whdpRXE+3f9V8UzyAorlYvOGx87ufGHehNTn5lCxrKtLyZ4Yl/wEKnNnr98ZzOwwDZV5ogw== + path-type@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" @@ -8948,7 +9229,7 @@ semver@^7.3.7, semver@^7.3.8: dependencies: lru-cache "^6.0.0" -semver@^7.5.4: +semver@^7.5.3, semver@^7.5.4: version "7.6.2" resolved "https://registry.yarnpkg.com/semver/-/semver-7.6.2.tgz#1e3b34759f896e8f14d6134732ce798aeb0c6e13" integrity sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w== @@ -9093,6 +9374,11 @@ stackback@0.0.2: resolved "https://registry.yarnpkg.com/stackback/-/stackback-0.0.2.tgz#1ac8a0d9483848d1695e418b6d031a3c3ce68e3b" integrity sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw== +statuses@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/statuses/-/statuses-2.0.1.tgz#55cb000ccf1d48728bd23c685a063998cf1a1b63" + integrity sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ== + std-env@^3.5.0, std-env@^3.7.0: version "3.7.0" resolved "https://registry.yarnpkg.com/std-env/-/std-env-3.7.0.tgz#c9f7386ced6ecf13360b6c6c55b8aaa4ef7481d2" @@ -9103,6 +9389,11 @@ stream-shift@^1.0.0: resolved "https://registry.yarnpkg.com/stream-shift/-/stream-shift-1.0.1.tgz#d7088281559ab2778424279b0877da3c392d5a3d" integrity sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ== +strict-event-emitter@^0.5.1: + version "0.5.1" + resolved "https://registry.yarnpkg.com/strict-event-emitter/-/strict-event-emitter-0.5.1.tgz#1602ece81c51574ca39c6815e09f1a3e8550bd93" + integrity sha512-vMgjE/GGEPEFnhFub6pa4FmJBRBVOLpIII2hvCZ8Kzb7K0hlHo7mQv6xYrBvCL2LtAIBwFUK8wvuJgTVSQ5MFQ== + strict-uri-encode@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-2.0.0.tgz#b9c7330c7042862f6b142dc274bbcc5866ce3546" @@ -9357,6 +9648,15 @@ temp@^0.9.4: mkdirp "^0.5.1" rimraf "~2.6.2" +test-exclude@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/test-exclude/-/test-exclude-6.0.0.tgz#04a8698661d805ea6fa293b6cb9e63ac044ef15e" + integrity sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w== + dependencies: + "@istanbuljs/schema" "^0.1.2" + glob "^7.1.4" + minimatch "^3.0.4" + text-table@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" @@ -9523,11 +9823,21 @@ type-fest@^0.20.2: resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.20.2.tgz#1bf207f4b28f91583666cb5fbd327887301cd5f4" integrity sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ== +type-fest@^0.21.3: + version "0.21.3" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.21.3.tgz#d260a24b0198436e133fa26a524a6d65fa3b2e37" + integrity sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w== + type-fest@^1.0.2: version "1.4.0" resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-1.4.0.tgz#e9fb813fe3bf1744ec359d55d1affefa76f14be1" integrity sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA== +type-fest@^4.9.0: + version "4.21.0" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-4.21.0.tgz#2eec399d9bda4ac686286314d07c6675fef3fdd8" + integrity sha512-ADn2w7hVPcK6w1I0uWnM//y1rLXZhzB9mr0a3OirzclKF1Wp6VzevUmzz/NRAWunOT6E8HrnpGY7xOfc6K57fA== + typechain@^8.1.0: version "8.3.1" resolved "https://registry.yarnpkg.com/typechain/-/typechain-8.3.1.tgz#dccbc839b94877997536c356380eff7325395cfb" @@ -10216,7 +10526,7 @@ yargs@^16.2.0: y18n "^5.0.5" yargs-parser "^20.2.2" -yargs@^17.5.1: +yargs@^17.5.1, yargs@^17.7.2: version "17.7.2" resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.7.2.tgz#991df39aca675a192b816e1e0363f9d75d2aa269" integrity sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w== @@ -10239,6 +10549,11 @@ yocto-queue@^1.0.0: resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-1.0.0.tgz#7f816433fb2cbc511ec8bf7d263c3b58a1a3c251" integrity sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g== +yoctocolors-cjs@^2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/yoctocolors-cjs/-/yoctocolors-cjs-2.1.2.tgz#f4b905a840a37506813a7acaa28febe97767a242" + integrity sha512-cYVsTjKl8b+FrnidjibDWskAv7UKOfcwaVZdp/it9n1s9fU3IkgDbhdIRKCW4JDsAlECJY0ytoVPT3sK6kideA== + zustand@4.4.1: version "4.4.1" resolved "https://registry.yarnpkg.com/zustand/-/zustand-4.4.1.tgz#0cd3a3e4756f21811bd956418fdc686877e8b3b0" From 06a351a18a113a8be388acf22f12c65773be69d7 Mon Sep 17 00:00:00 2001 From: Tiago Silva Date: Thu, 11 Jul 2024 11:52:40 +0100 Subject: [PATCH 14/31] Update readme - Add instruction on how to run tests with coverage - Update title to include integration tests --- README.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index eea905bdf..557aa52de 100644 --- a/README.md +++ b/README.md @@ -47,7 +47,7 @@ Open [http://localhost:3000](http://localhost:3000) to view it in the browser. # Test -## Unit tests +## Unit/Integration tests & coverage To launch the test runner, run the following command: @@ -55,6 +55,12 @@ To launch the test runner, run the following command: yarn test ``` +If you wish to check the test coverage, run the following command: + +```bash +yarn coverage +``` + ## E2E tests To run the E2E tests, you must have a Tenderly API key to create and delete forks. You can set it in the `.env` file. Please refer to the [E2E readme](/e2e/README) for more information. From 5154333db1c43ab3e5dcb3808847d78795c0bef7 Mon Sep 17 00:00:00 2001 From: Tiago Silva Date: Fri, 12 Jul 2024 19:06:14 +0100 Subject: [PATCH 15/31] Update test utils - Add jsdoc to mock server class - Add mock tokenListHandlers --- src/libs/testing-library/utils.ts | 92 +++++++++++++++++++++++++++++-- 1 file changed, 87 insertions(+), 5 deletions(-) diff --git a/src/libs/testing-library/utils.ts b/src/libs/testing-library/utils.ts index 64f1e05d4..bd2f13eae 100644 --- a/src/libs/testing-library/utils.ts +++ b/src/libs/testing-library/utils.ts @@ -10,26 +10,98 @@ import { parseSearchWith } from 'libs/routing/utils'; import { isAddress } from 'ethers/lib/utils'; import { RequestHandler } from 'msw'; import { setupServer } from 'msw/node'; -import { afterAll, beforeAll } from 'vitest'; +import { HttpResponse, http } from 'msw'; +import tokenListsMock from '../../../e2e/mocks/tokenLists.json'; +/** + * Creates a handler for fetching market rates based on the provided market rates object. + * This handler intercepts HTTP GET requests to the 'market-rate' endpoint, + * extracts the 'address' query parameter, and returns the corresponding market rates + * from the provided marketRates object. If the address is not found, it returns a 404 response. + * + * @param {Record>} marketRates - An object mapping addresses + * to their respective market rates. Each address key maps to another object where + * each key is a market identifier and its value is the rate. + * @returns An HTTP handler function that can be passed to the MockServer handlers + */ +export const marketRateHandler = ( + marketRates: Record> +) => { + return http.get('**/*/market-rate', ({ request }) => { + const queryParams = new URL(request.url).searchParams; + const address = queryParams.get('address')?.toLowerCase(); + if (!address || !marketRates[address]) + return new HttpResponse(null, { status: 404 }); + + return HttpResponse.json({ + data: marketRates[address], + }); + }); +}; + +/** + * Array of HTTP GET request handlers for each token list URL defined in `tokenLists.json`. + * Each handler intercepts requests to its corresponding URL and returns the associated token list data + * as a JSON response. If the requested token list does not exist in `tokenListsMock`, a 404 response is returned. + */ +export const tokenListHandlers = Object.keys(tokenListsMock).map( + (tokenList) => { + return http.get(tokenList, () => { + const json = tokenListsMock[tokenList as keyof typeof tokenListsMock]; + if (!json) return new HttpResponse(null, { status: 404 }); + + return HttpResponse.json({ + data: json, + }); + }); + } +); + +/** + * MockServer is a utility class for managing a mock server for testing. + * It allows adding and resetting request handlers for the server. + */ export class MockServer { private server; + + /** + * Constructs a new instance of MockServer. + * @param {RequestHandler[]} handlers - An optional array of initial request handlers. + */ constructor(private handlers: RequestHandler[] = []) { this.server = setupServer(...this.handlers); } + /** + * Adds a new request handler to the server. + * @param {RequestHandler} handler - The request handler to add. + */ addHandler(handler: RequestHandler) { this.handlers.push(handler); this.server.resetHandlers(...this.handlers); } - reset() { - this.server.resetHandlers(); + /** + * Resets the server's request handlers to their initial state. + * @param {RequestHandler[]} handlers - An optional array of initial request handlers. + */ + reset(handlers?: RequestHandler[]) { + this.server.resetHandlers(...(handlers ?? [])); } + /** + * Starts the mock server and sets up vitest lifecycle hooks to listen for requests + * and close the server before and after all tests, respectively. + */ start() { - beforeAll(() => this.server.listen({ onUnhandledRequest: 'error' })); - afterAll(() => this.server.close()); + this.server.listen({ onUnhandledRequest: 'error' }); + } + + /** + * Close the mock server. + */ + close() { + this.server.close(); } } @@ -44,6 +116,16 @@ export const tokens = [ decimals: 6, symbol: 'USDC', }, + { + address: debugTokens.WBTC, + decimals: 8, + symbol: 'WBTC', + }, + { + address: debugTokens.USDT, + decimals: 6, + symbol: 'USDT', + }, ]; const encodeValue = (value: string | number | symbol) => { From eb4e3681f69feea4f37d90b59052672d17a77b16 Mon Sep 17 00:00:00 2001 From: Tiago Silva Date: Fri, 12 Jul 2024 19:15:11 +0100 Subject: [PATCH 16/31] Add set user price with no external price test to overlapping --- .../strategies/create/overlapping.test.tsx | 68 +++++++++++++------ 1 file changed, 46 insertions(+), 22 deletions(-) diff --git a/src/pages/strategies/create/overlapping.test.tsx b/src/pages/strategies/create/overlapping.test.tsx index dff62f9cb..ea4071331 100644 --- a/src/pages/strategies/create/overlapping.test.tsx +++ b/src/pages/strategies/create/overlapping.test.tsx @@ -1,36 +1,24 @@ -import { describe, test, expect } from 'vitest'; -import { HttpResponse, http } from 'msw'; +import { describe, test, expect, beforeAll, afterAll } from 'vitest'; import { renderWithRouter, screen } from 'libs/testing-library'; import userEvent from '@testing-library/user-event'; import { debugTokens } from '../../../../e2e/utils/types'; import { CreateOverlappingStrategyPage } from './overlapping'; -import { MockServer } from 'libs/testing-library/utils'; +import { MockServer, marketRateHandler } from 'libs/testing-library/utils'; const basePath = '/strategies/create/overlapping'; const marketRates: Record> = { - '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48': { USD: 1 }, - '0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee': { USD: 2800 }, -}; - -const marketRateHandler = ( - marketRates: Record> -) => { - return http.get('**/*/market-rate', ({ request }) => { - const queryParams = new URL(request.url).searchParams; - const address = queryParams.get('address')?.toLowerCase(); - if (!address) return new HttpResponse(null, { status: 404 }); - return HttpResponse.json({ - data: marketRates[address], - }); - }); + '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48': { USD: 1 }, // USDC + '0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee': { USD: 2800 }, // ETH }; const mockServer = new MockServer([marketRateHandler(marketRates)]); +beforeAll(() => mockServer.start()); +afterAll(() => mockServer.close()); + describe('overlapping page', () => { - mockServer.start(); - test('run overlapping form with deeplink and user market price', async () => { + test('check search params with deeplink and user market price defined', async () => { // Initialize user and set search params const user = userEvent.setup(); const search = { @@ -82,7 +70,43 @@ describe('overlapping page', () => { expect(depositWarning).toBeInTheDocument(); }); - test('run overlapping form with external market price', async () => { + test('check search params with no external price after setting user market price', async () => { + const user = userEvent.setup(); + const search = { + base: debugTokens.USDT, + quote: debugTokens.WBTC, + min: '45000', + max: '55000', + spread: '0.01', + anchor: 'buy', + budget: '10', + }; + const marketPrice = '50000'; + + // Render page + const { router } = await renderWithRouter({ + component: () => , + basePath, + search, + }); + + const userPriceInput = await screen.findByTestId('input-price'); + const userWarning = await screen.findByTestId('approve-warnings'); + const setMarketPriceButton = await screen.findByTestId( + 'set-overlapping-price' + ); + await user.click(userPriceInput); + await user.keyboard(marketPrice); + await user.click(userWarning); + await user.click(setMarketPriceButton); + + expect(router.state.location.search).toStrictEqual({ + ...search, + marketPrice: marketPrice, + }); + }); + + test('check search params with external market price', async () => { // Set search params const search = { base: debugTokens.ETH, @@ -117,7 +141,7 @@ describe('overlapping page', () => { expect(marketPriceIndications[1]).toHaveTextContent('7.14% above'); }); - test('run overlapping form with user market price below min price', async () => { + test('create with user market price below min price', async () => { // Set search params const search = { base: debugTokens.ETH, From c39f7f6606f2a88c6cec40c6e8ced761996bf094 Mon Sep 17 00:00:00 2001 From: Tiago Silva Date: Fri, 12 Jul 2024 19:28:45 +0100 Subject: [PATCH 17/31] Add testid tags to overlapping market price form --- .../strategies/overlapping/OverlappingMarketPrice.tsx | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/components/strategies/overlapping/OverlappingMarketPrice.tsx b/src/components/strategies/overlapping/OverlappingMarketPrice.tsx index cdc450c4d..624c4c152 100644 --- a/src/components/strategies/overlapping/OverlappingMarketPrice.tsx +++ b/src/components/strategies/overlapping/OverlappingMarketPrice.tsx @@ -135,12 +135,15 @@ export const OverlappingInitMarketPrice = (props: FieldProps) => { id={checkboxId} type="checkbox" className="size-18" + data-testid="approve-warnings" checked={approved} onChange={(e) => setApproved(e.target.checked)} /> I've reviewed the warning(s) but choose to proceed. - + ); }; From dca4e55491b7d694145f8bbb48b4a183590168ef Mon Sep 17 00:00:00 2001 From: Tiago Silva Date: Mon, 15 Jul 2024 13:12:52 +0100 Subject: [PATCH 18/31] Change test description --- src/pages/strategies/create/overlapping.test.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/strategies/create/overlapping.test.tsx b/src/pages/strategies/create/overlapping.test.tsx index ea4071331..70b9cda18 100644 --- a/src/pages/strategies/create/overlapping.test.tsx +++ b/src/pages/strategies/create/overlapping.test.tsx @@ -106,7 +106,7 @@ describe('overlapping page', () => { }); }); - test('check search params with external market price', async () => { + test('check form prices with external market price', async () => { // Set search params const search = { base: debugTokens.ETH, From 4c1b10d926f79fc944e432a5d25e35ea46da5cbe Mon Sep 17 00:00:00 2001 From: Tiago Silva Date: Mon, 15 Jul 2024 22:45:32 +0100 Subject: [PATCH 19/31] Add create overlapping tests to 100% coverage and refactor tests and library --- .../overlapping/OverlappingSpread.tsx | 1 + src/libs/testing-library/index.tsx | 26 +++- src/libs/testing-library/utils/index.ts | 8 ++ .../{utils.ts => utils/mock.ts} | 65 +--------- src/libs/testing-library/utils/routing.ts | 61 +++++++++ src/libs/testing-library/{ => utils}/types.ts | 0 .../strategies/create/overlapping.test.tsx | 117 +++++++++++++++++- 7 files changed, 209 insertions(+), 69 deletions(-) create mode 100644 src/libs/testing-library/utils/index.ts rename src/libs/testing-library/{utils.ts => utils/mock.ts} (62%) create mode 100644 src/libs/testing-library/utils/routing.ts rename src/libs/testing-library/{ => utils}/types.ts (100%) diff --git a/src/components/strategies/overlapping/OverlappingSpread.tsx b/src/components/strategies/overlapping/OverlappingSpread.tsx index 233788970..f1a4c4978 100644 --- a/src/components/strategies/overlapping/OverlappingSpread.tsx +++ b/src/components/strategies/overlapping/OverlappingSpread.tsx @@ -119,6 +119,7 @@ export const OverlappingSpread: FC = (props) => { tabIndex={spread === option ? 0 : -1} onChange={() => selectSpread(option)} onFocus={() => selectSpread(option)} + data-testid={'spread-' + option} />