From 7bf0f479ea0eed6b3b5533e368f16b2dcb9c20e0 Mon Sep 17 00:00:00 2001 From: Sandoche Date: Thu, 12 Sep 2024 11:52:05 +0100 Subject: [PATCH 1/7] fix: fixing typo --- next.config.mjs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/next.config.mjs b/next.config.mjs index a6d8ca4..089ce93 100644 --- a/next.config.mjs +++ b/next.config.mjs @@ -6,7 +6,7 @@ const nextConfig = { protocol: 'https', hostname: 'raw.githubusercontent.com', port: '', - pathname: 'm/evmos/chain-token-registry/main/assets/tokens/', + pathname: '/evmos/chain-token-registry/main/assets/tokens/', }, ], }, From bd08b3940e86f4e4686473f360a191efd96f0e6c Mon Sep 17 00:00:00 2001 From: Sandoche Date: Thu, 12 Sep 2024 11:55:37 +0100 Subject: [PATCH 2/7] fix: forcing dynamic rendering --- src/app/api/v1/indexer/auction-end-events/route.ts | 2 ++ src/app/api/v1/indexer/bid-events/route.ts | 2 ++ src/app/layout.tsx | 2 ++ 3 files changed, 6 insertions(+) diff --git a/src/app/api/v1/indexer/auction-end-events/route.ts b/src/app/api/v1/indexer/auction-end-events/route.ts index 513bd67..03fa6f5 100644 --- a/src/app/api/v1/indexer/auction-end-events/route.ts +++ b/src/app/api/v1/indexer/auction-end-events/route.ts @@ -74,3 +74,5 @@ export async function GET() { return Response.json({ error: 'Failed to index auction end events' }, { status: 500 }); } } + +export const dynamic = 'force-dynamic'; diff --git a/src/app/api/v1/indexer/bid-events/route.ts b/src/app/api/v1/indexer/bid-events/route.ts index d0ebc69..1503d72 100644 --- a/src/app/api/v1/indexer/bid-events/route.ts +++ b/src/app/api/v1/indexer/bid-events/route.ts @@ -64,3 +64,5 @@ export async function GET() { return Response.json({ error: 'Failed to index bid events' }, { status: 500 }); } } + +export const dynamic = 'force-dynamic'; diff --git a/src/app/layout.tsx b/src/app/layout.tsx index 0e22df3..578598b 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -41,3 +41,5 @@ const RootLayout = ({ }; export default RootLayout; + +export const dynamic = 'force-dynamic'; From 3c3f5d5b36446b2e46b5bef34dda6a743800391b Mon Sep 17 00:00:00 2001 From: Sandoche ADITTANE Date: Thu, 12 Sep 2024 13:31:21 +0100 Subject: [PATCH 3/7] --- src/app/__tests__/CurrentAuctionPage.spec.ts | 52 ++++++++++++++++++++ src/app/_components/Countdown.spec.ts | 34 +++++++++++++ src/app/_components/DiscountChip.spec.ts | 19 +++++++ 3 files changed, 105 insertions(+) create mode 100644 src/app/__tests__/CurrentAuctionPage.spec.ts create mode 100644 src/app/_components/Countdown.spec.ts create mode 100644 src/app/_components/DiscountChip.spec.ts diff --git a/src/app/__tests__/CurrentAuctionPage.spec.ts b/src/app/__tests__/CurrentAuctionPage.spec.ts new file mode 100644 index 0000000..0934b7a --- /dev/null +++ b/src/app/__tests__/CurrentAuctionPage.spec.ts @@ -0,0 +1,52 @@ +import { render, screen } from '@testing-library/react'; +import { vi } from 'vitest'; +import CurrentAuction from '../page'; +import { mockCoinGeckoResponse, mockAuctionResponse, epochInfoResponse } from '../../queries/__tests__/mockedData'; + +vi.mock('../../queries/fetchCurrentCryptoPrice', async (importOriginal) => { + const actual = await importOriginal(); + return { + ...actual, + fetchCurrentCryptoPrice: vi.fn(() => mockCoinGeckoResponse), + }; +}); + +vi.mock('../../queries/rpcFetchCurrentAuctionInfo', async (importOriginal) => { + const actual = await importOriginal(); + return { + ...actual, + rpcFetchCurrentAuctionInfo: vi.fn(() => mockAuctionResponse), + }; +}); + +vi.mock('../../queries/rpcFetchEpochInfo', async (importOriginal) => { + const actual = await importOriginal(); + return { + ...actual, + rpcFetchEpochInfo: vi.fn(() => epochInfoResponse), + }; +}); + +describe('CurrentAuction Page', () => { + it('renders without crashing', async () => { + render(); + expect(screen.getByText(/Auction #/)).toBeInTheDocument(); + }); + + it('displays the error icon when coingecko is failing', async () => { + const failingMockCoinGeckoResponse = { + cosmos: { + usd: null, + }, + 'wrapped-bitcoin': { + usd: null, + }, + evmos: { usd: null }, + }; + + vi.mocked(fetchCurrentCryptoPrice).mockImplementation(() => failingMockCoinGeckoResponse); + + render(); + expect(screen.getByAltText('Info')).toBeInTheDocument(); + }); +}); diff --git a/src/app/_components/Countdown.spec.ts b/src/app/_components/Countdown.spec.ts new file mode 100644 index 0000000..8f3cfdb --- /dev/null +++ b/src/app/_components/Countdown.spec.ts @@ -0,0 +1,34 @@ +import { render, screen } from '@testing-library/react'; +import { vi } from 'vitest'; +import { Countdown } from './Countdown'; +import reloadData from '../_actions/reloadData'; + +vi.mock('../_actions/reloadData', () => ({ + default: vi.fn(), +})); + +describe('Countdown Component', () => { + beforeEach(() => { + vi.useFakeTimers(); + }); + + afterEach(() => { + vi.clearAllTimers(); + }); + + it('renders correctly', () => { + const targetDate = new Date(Date.now() + 10000); // 10 seconds from now + render(); + expect(screen.getByText(/d/)).toBeInTheDocument(); + expect(screen.getByText(/h/)).toBeInTheDocument(); + expect(screen.getByText(/m/)).toBeInTheDocument(); + expect(screen.getByText(/s/)).toBeInTheDocument(); + }); + + it('reloads when reaching 0', () => { + const targetDate = new Date(Date.now() + 1000); // 1 second from now + render(); + vi.advanceTimersByTime(1000); + expect(reloadData).toHaveBeenCalled(); + }); +}); diff --git a/src/app/_components/DiscountChip.spec.ts b/src/app/_components/DiscountChip.spec.ts new file mode 100644 index 0000000..ea8f002 --- /dev/null +++ b/src/app/_components/DiscountChip.spec.ts @@ -0,0 +1,19 @@ +import { render, screen } from '@testing-library/react'; +import { DiscountChip } from './DiscountChip'; + +describe('DiscountChip Component', () => { + it('displays the correct message when highestBidUsd is 0', () => { + render(); + expect(screen.getByText('🤯 Be the first to bid')).toBeInTheDocument(); + }); + + it('displays the correct discount message when highestBidUsd is less than currentValueUsd', () => { + render(); + expect(screen.getByText('🔥 2x cheaper than market value')).toBeInTheDocument(); + }); + + it('does not render anything when highestBidUsd is greater than currentValueUsd', () => { + const { container } = render(); + expect(container).toBeEmptyDOMElement(); + }); +}); From 4f3a0fdc9eaeb5668b932670968a69870bbd0c79 Mon Sep 17 00:00:00 2001 From: Sandoche Date: Thu, 12 Sep 2024 16:13:45 +0100 Subject: [PATCH 4/7] tests: adding tests for some components --- src/app/__tests__/CurrentAuctionPage.spec.ts | 52 ------------------ src/app/_components/Countdown.spec.ts | 34 ------------ src/app/_components/Countdown.tsx | 2 +- .../_components/__tests__/Countdown.spec.tsx | 54 +++++++++++++++++++ .../DiscountChip.spec.tsx} | 13 +++-- 5 files changed, 64 insertions(+), 91 deletions(-) delete mode 100644 src/app/__tests__/CurrentAuctionPage.spec.ts delete mode 100644 src/app/_components/Countdown.spec.ts create mode 100644 src/app/_components/__tests__/Countdown.spec.tsx rename src/app/_components/{DiscountChip.spec.ts => __tests__/DiscountChip.spec.tsx} (65%) diff --git a/src/app/__tests__/CurrentAuctionPage.spec.ts b/src/app/__tests__/CurrentAuctionPage.spec.ts deleted file mode 100644 index 0934b7a..0000000 --- a/src/app/__tests__/CurrentAuctionPage.spec.ts +++ /dev/null @@ -1,52 +0,0 @@ -import { render, screen } from '@testing-library/react'; -import { vi } from 'vitest'; -import CurrentAuction from '../page'; -import { mockCoinGeckoResponse, mockAuctionResponse, epochInfoResponse } from '../../queries/__tests__/mockedData'; - -vi.mock('../../queries/fetchCurrentCryptoPrice', async (importOriginal) => { - const actual = await importOriginal(); - return { - ...actual, - fetchCurrentCryptoPrice: vi.fn(() => mockCoinGeckoResponse), - }; -}); - -vi.mock('../../queries/rpcFetchCurrentAuctionInfo', async (importOriginal) => { - const actual = await importOriginal(); - return { - ...actual, - rpcFetchCurrentAuctionInfo: vi.fn(() => mockAuctionResponse), - }; -}); - -vi.mock('../../queries/rpcFetchEpochInfo', async (importOriginal) => { - const actual = await importOriginal(); - return { - ...actual, - rpcFetchEpochInfo: vi.fn(() => epochInfoResponse), - }; -}); - -describe('CurrentAuction Page', () => { - it('renders without crashing', async () => { - render(); - expect(screen.getByText(/Auction #/)).toBeInTheDocument(); - }); - - it('displays the error icon when coingecko is failing', async () => { - const failingMockCoinGeckoResponse = { - cosmos: { - usd: null, - }, - 'wrapped-bitcoin': { - usd: null, - }, - evmos: { usd: null }, - }; - - vi.mocked(fetchCurrentCryptoPrice).mockImplementation(() => failingMockCoinGeckoResponse); - - render(); - expect(screen.getByAltText('Info')).toBeInTheDocument(); - }); -}); diff --git a/src/app/_components/Countdown.spec.ts b/src/app/_components/Countdown.spec.ts deleted file mode 100644 index 8f3cfdb..0000000 --- a/src/app/_components/Countdown.spec.ts +++ /dev/null @@ -1,34 +0,0 @@ -import { render, screen } from '@testing-library/react'; -import { vi } from 'vitest'; -import { Countdown } from './Countdown'; -import reloadData from '../_actions/reloadData'; - -vi.mock('../_actions/reloadData', () => ({ - default: vi.fn(), -})); - -describe('Countdown Component', () => { - beforeEach(() => { - vi.useFakeTimers(); - }); - - afterEach(() => { - vi.clearAllTimers(); - }); - - it('renders correctly', () => { - const targetDate = new Date(Date.now() + 10000); // 10 seconds from now - render(); - expect(screen.getByText(/d/)).toBeInTheDocument(); - expect(screen.getByText(/h/)).toBeInTheDocument(); - expect(screen.getByText(/m/)).toBeInTheDocument(); - expect(screen.getByText(/s/)).toBeInTheDocument(); - }); - - it('reloads when reaching 0', () => { - const targetDate = new Date(Date.now() + 1000); // 1 second from now - render(); - vi.advanceTimersByTime(1000); - expect(reloadData).toHaveBeenCalled(); - }); -}); diff --git a/src/app/_components/Countdown.tsx b/src/app/_components/Countdown.tsx index 510f4ae..58632a2 100644 --- a/src/app/_components/Countdown.tsx +++ b/src/app/_components/Countdown.tsx @@ -16,7 +16,7 @@ type TimeLeft = { }; const REFRESH_INTERVAL = 1000; -const DELAY_BEFORE_RELOAD_AFTER_COUNTDOWN_GOES_TO_ZERO = 5000; +export const DELAY_BEFORE_RELOAD_AFTER_COUNTDOWN_GOES_TO_ZERO = 5000; const calculateTimeLeft = (date: Date): TimeLeft => { const difference = +date - +new Date(); diff --git a/src/app/_components/__tests__/Countdown.spec.tsx b/src/app/_components/__tests__/Countdown.spec.tsx new file mode 100644 index 0000000..1f00aff --- /dev/null +++ b/src/app/_components/__tests__/Countdown.spec.tsx @@ -0,0 +1,54 @@ +// Copyright Tharsis Labs Ltd.(Evmos) +// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/burn-auction-dapp/blob/main/LICENSE) + +import { render, act, screen } from '@testing-library/react'; +import { expect, describe, it, beforeEach, afterEach, vi } from 'vitest'; + +import { Countdown, DELAY_BEFORE_RELOAD_AFTER_COUNTDOWN_GOES_TO_ZERO } from '../Countdown'; +import * as reloadDataModule from '../../_actions/reloadData'; + +const ONE_SECOND = 1000; +const ONE_HOUR_ONE_MINUTE_AND_TEN_SECONDS = 3670000; + +// Mock the entire module +vi.mock('../../_actions/reloadData'); + +describe('Countdown Component', () => { + beforeEach(() => { + vi.useFakeTimers(); + // Create a mock function for reloadData + vi.spyOn(reloadDataModule, 'default').mockImplementation(vi.fn()); + }); + + afterEach(() => { + vi.clearAllTimers(); + vi.clearAllMocks(); + }); + + it('renders correctly', () => { + const targetDate: Date = new Date(Date.now() + ONE_HOUR_ONE_MINUTE_AND_TEN_SECONDS); + render(); + expect(screen.getByText(/0d/)).toBeDefined(); + expect(screen.getByText(/1h/)).toBeDefined(); + expect(screen.getByText(/1m/)).toBeDefined(); + expect(screen.getByText(/10s/)).toBeDefined(); + }); + + it('reloads when reaching 0', () => { + const targetDate = new Date(Date.now() + ONE_SECOND); // Set to 1 second in the future + render(); + + // Fast-forward time to just after the countdown should reach zero + act(() => { + vi.advanceTimersByTime(ONE_SECOND + 1); + }); + + // Fast-forward time to trigger the delayed reload + act(() => { + vi.advanceTimersByTime(DELAY_BEFORE_RELOAD_AFTER_COUNTDOWN_GOES_TO_ZERO); + }); + + // Check if reloadData was called + expect(reloadDataModule.default).toHaveBeenCalledTimes(1); + }); +}); diff --git a/src/app/_components/DiscountChip.spec.ts b/src/app/_components/__tests__/DiscountChip.spec.tsx similarity index 65% rename from src/app/_components/DiscountChip.spec.ts rename to src/app/_components/__tests__/DiscountChip.spec.tsx index ea8f002..090ec69 100644 --- a/src/app/_components/DiscountChip.spec.ts +++ b/src/app/_components/__tests__/DiscountChip.spec.tsx @@ -1,19 +1,24 @@ +// Copyright Tharsis Labs Ltd.(Evmos) +// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/burn-auction-dapp/blob/main/LICENSE) + import { render, screen } from '@testing-library/react'; -import { DiscountChip } from './DiscountChip'; +import { expect, describe, it } from 'vitest'; + +import { DiscountChip } from '../DiscountChip'; describe('DiscountChip Component', () => { it('displays the correct message when highestBidUsd is 0', () => { render(); - expect(screen.getByText('🤯 Be the first to bid')).toBeInTheDocument(); + expect(screen.getByText('🤯 Be the first to bid')).toBeDefined(); }); it('displays the correct discount message when highestBidUsd is less than currentValueUsd', () => { render(); - expect(screen.getByText('🔥 2x cheaper than market value')).toBeInTheDocument(); + expect(screen.getByText('🔥 2x cheaper than market value')).toBeDefined(); }); it('does not render anything when highestBidUsd is greater than currentValueUsd', () => { const { container } = render(); - expect(container).toBeEmptyDOMElement(); + expect(container.firstChild).toBeNull(); }); }); From b6e60ab8d206ed69e7728ad60455db87e05c7d78 Mon Sep 17 00:00:00 2001 From: Sandoche Date: Thu, 12 Sep 2024 16:59:09 +0100 Subject: [PATCH 5/7] fix: add attribution to coingecko --- src/app/layout.tsx | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/app/layout.tsx b/src/app/layout.tsx index 578598b..21a71fd 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -35,6 +35,12 @@ const RootLayout = ({
{children}
+

+ Data provided by{' '} + + CoinGecko + +

); From 4e27b1404111c1347da40c0ea2fda66bd2bcbdc6 Mon Sep 17 00:00:00 2001 From: Sandoche Date: Fri, 13 Sep 2024 11:28:17 +0100 Subject: [PATCH 6/7] fix: fixing crash because of negative number in the prisma query --- src/queries/prismaFetchAuctionEvents.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/queries/prismaFetchAuctionEvents.ts b/src/queries/prismaFetchAuctionEvents.ts index 3d6ba11..bda6fa9 100644 --- a/src/queries/prismaFetchAuctionEvents.ts +++ b/src/queries/prismaFetchAuctionEvents.ts @@ -14,7 +14,7 @@ export const prismaFetchAuctionEvents = async (page: number, itemsPerPage: numbe include: { coins: true, }, - skip: (page - 1) * itemsPerPage, + skip: page > 0 ? (page - 1) * itemsPerPage : 0, take: itemsPerPage, }), ); From 414fb268f8e7d6472710aac0bb2dd318a2a641e9 Mon Sep 17 00:00:00 2001 From: Sandoche Date: Fri, 13 Sep 2024 11:33:15 +0100 Subject: [PATCH 7/7] fix: input is blocked when it should not --- src/app/_components/BiddingForm.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/_components/BiddingForm.tsx b/src/app/_components/BiddingForm.tsx index adb53e6..b234918 100644 --- a/src/app/_components/BiddingForm.tsx +++ b/src/app/_components/BiddingForm.tsx @@ -67,7 +67,7 @@ export const BiddingForm = ({ evmosToUsdRate, priceError }: { evmosToUsdRate: nu placeholder="Amount" value={state.context.bidAmount} onChange={(e) => send({ type: 'SET_BID_AMOUNT', value: e.target.value })} - disabled={isSubmitDisabled} + disabled={state.matches('submitting') || state.matches('success')} /> EVMOS