diff --git a/__tests__/components/waves/drop/SingleWaveDropVoteInput.test.tsx b/__tests__/components/waves/drop/SingleWaveDropVoteInput.test.tsx index 16ac0efce8..1d3b5177ac 100644 --- a/__tests__/components/waves/drop/SingleWaveDropVoteInput.test.tsx +++ b/__tests__/components/waves/drop/SingleWaveDropVoteInput.test.tsx @@ -2,7 +2,6 @@ import React from 'react'; import { render, screen, fireEvent, act } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import { SingleWaveDropVoteInput } from '@/components/waves/drop/SingleWaveDropVoteInput'; -import { ApiWaveCreditType } from '@/generated/models/ObjectSerializer'; // Mock timers for testing interval behavior jest.useFakeTimers(); @@ -12,7 +11,7 @@ describe('SingleWaveDropVoteInput', () => { voteValue: 0, minValue: -1000, maxValue: 1000, - creditType: ApiWaveCreditType.Rep, + label: "Rep", setVoteValue: jest.fn(), onSubmit: jest.fn(), }; @@ -37,8 +36,8 @@ describe('SingleWaveDropVoteInput', () => { }); it('displays credit type in input field', () => { - render(); - + render(); + expect(screen.getByText('TDH')).toBeInTheDocument(); }); diff --git a/__tests__/components/waves/drop/SingleWaveDropVoteSlider.test.tsx b/__tests__/components/waves/drop/SingleWaveDropVoteSlider.test.tsx index 0cfbf99057..3577d9095f 100644 --- a/__tests__/components/waves/drop/SingleWaveDropVoteSlider.test.tsx +++ b/__tests__/components/waves/drop/SingleWaveDropVoteSlider.test.tsx @@ -1,6 +1,5 @@ import { render, screen, fireEvent } from '@testing-library/react'; import SingleWaveDropVoteSlider from '@/components/waves/drop/SingleWaveDropVoteSlider'; -import { ApiWaveCreditType } from '@/generated/models/ApiWaveCreditType'; // Mock framer-motion jest.mock('framer-motion', () => ({ @@ -35,7 +34,7 @@ describe('SingleWaveDropVoteSlider', () => { minValue: -100, maxValue: 100, setVoteValue: jest.fn(), - creditType: ApiWaveCreditType.Rep, + label: "Rep", }; beforeEach(() => { @@ -44,29 +43,29 @@ describe('SingleWaveDropVoteSlider', () => { it('renders slider with basic elements', () => { render(); - + const sliders = screen.getAllByRole('slider'); expect(sliders.length).toBeGreaterThan(0); const tooltips = screen.getAllByText((content, element) => { - return element?.textContent === '50 REP'; + return element?.textContent === '50 Rep'; }); expect(tooltips.length).toBeGreaterThan(0); // Vote value in tooltip }); it('displays vote value in tooltip', () => { render(); - + const tooltips = screen.getAllByText((content, element) => { - return element?.textContent === '75 REP'; + return element?.textContent === '75 Rep'; }); expect(tooltips.length).toBeGreaterThan(0); }); it('handles string vote value by defaulting to 0', () => { render(); - + const tooltips = screen.getAllByText((content, element) => { - return element?.textContent === '0 REP'; + return element?.textContent === '0 Rep'; }); expect(tooltips.length).toBeGreaterThan(0); }); @@ -111,18 +110,18 @@ describe('SingleWaveDropVoteSlider', () => { it('handles zero range case', () => { render(); - + const tooltips = screen.getAllByText((content, element) => { - return element?.textContent === '0 REP'; + return element?.textContent === '0 Rep'; }); expect(tooltips.length).toBeGreaterThan(0); }); it('handles negative vote values', () => { render(); - + const tooltips = screen.getAllByText((content, element) => { - return element?.textContent === '-25 REP'; + return element?.textContent === '-25 Rep'; }); expect(tooltips.length).toBeGreaterThan(0); }); @@ -161,20 +160,20 @@ describe('SingleWaveDropVoteSlider', () => { }); it('displays correct credit type in tooltip', () => { - render(); - + render(); + const tooltips = screen.getAllByText((content, element) => { - return element?.textContent === '50 REP'; + return element?.textContent === '50 Rep'; }); expect(tooltips.length).toBeGreaterThan(0); }); it('handles edge case where all values are zero', () => { render(); - + // Should render without crashing and show 0 value const tooltips = screen.getAllByText((content, element) => { - return element?.textContent === '0 REP'; + return element?.textContent === '0 Rep'; }); expect(tooltips.length).toBeGreaterThan(0); }); diff --git a/__tests__/components/waves/drop/SingleWaveDropVoteSubmit.test.tsx b/__tests__/components/waves/drop/SingleWaveDropVoteSubmit.test.tsx index e98492d639..2e964a5894 100644 --- a/__tests__/components/waves/drop/SingleWaveDropVoteSubmit.test.tsx +++ b/__tests__/components/waves/drop/SingleWaveDropVoteSubmit.test.tsx @@ -142,9 +142,9 @@ describe('SingleWaveDropVoteSubmit', () => { it('renders vote button with correct initial text', () => { renderComponent(); - + expect(screen.getByRole('button')).toBeInTheDocument(); - expect(screen.getByText('Vote!')).toBeInTheDocument(); + expect(screen.getByText('Vote')).toBeInTheDocument(); }); it('applies correct styling based on drop rank', () => { @@ -159,13 +159,13 @@ describe('SingleWaveDropVoteSubmit', () => { mockCommonApiPost.mockResolvedValue(mockDrop); renderComponent(); - + const button = screen.getByRole('button'); fireEvent.click(button); // Should show loading spinner await waitFor(() => { - expect(screen.getByText('Vote!')).toBeInTheDocument(); + expect(screen.getByText('Vote')).toBeInTheDocument(); }); }); @@ -234,12 +234,12 @@ describe('SingleWaveDropVoteSubmit', () => { mockCommonApiPost.mockRejectedValue(mockError); renderComponent(); - + const button = screen.getByRole('button'); fireEvent.click(button); // Button should show initial text - expect(screen.getByText('Vote!')).toBeInTheDocument(); + expect(screen.getByText('Vote')).toBeInTheDocument(); }); it('accepts onVoteSuccess callback prop', () => { @@ -273,10 +273,10 @@ describe('SingleWaveDropVoteSubmit', () => { it('renders button with initial vote text', () => { renderComponent(); - + const button = screen.getByRole('button'); expect(button).toBeInTheDocument(); - expect(screen.getByText('Vote!')).toBeInTheDocument(); + expect(screen.getByText('Vote')).toBeInTheDocument(); }); it('exposes handleClick method through ref', () => { diff --git a/__tests__/components/waves/leaderboard/sidebar/WaveLeaderboardRightSidebarActivityLog.test.tsx b/__tests__/components/waves/leaderboard/sidebar/WaveLeaderboardRightSidebarActivityLog.test.tsx index f4ec7c2bdb..314f8e8656 100644 --- a/__tests__/components/waves/leaderboard/sidebar/WaveLeaderboardRightSidebarActivityLog.test.tsx +++ b/__tests__/components/waves/leaderboard/sidebar/WaveLeaderboardRightSidebarActivityLog.test.tsx @@ -112,13 +112,14 @@ describe('WaveLeaderboardRightSidebarActivityLog', () => { it('displays voter information with profile picture', () => { renderComponent(); - + const voterLink = screen.getByTitle('Voter: voter_user'); expect(voterLink).toHaveAttribute('href', '/voter_user'); expect(screen.getByText('voter_user')).toBeInTheDocument(); - + const voterPfp = voterLink.querySelector('img'); - expect(voterPfp).toHaveAttribute('src', 'https://example.com/voter.jpg'); + expect(voterPfp).toBeInTheDocument(); + expect(voterPfp).toHaveAttribute('src', expect.stringContaining('voter.jpg')); expect(voterPfp).toHaveClass('tw-size-5', 'tw-rounded-md'); }); @@ -138,13 +139,14 @@ describe('WaveLeaderboardRightSidebarActivityLog', () => { it('displays drop author information with profile picture', () => { renderComponent(); - + const authorLink = screen.getByTitle('Drop creator: author_user'); expect(authorLink).toHaveAttribute('href', '/author_user'); expect(screen.getByText('author_user')).toBeInTheDocument(); - + const authorPfp = authorLink.querySelector('img'); - expect(authorPfp).toHaveAttribute('src', 'https://example.com/author.jpg'); + expect(authorPfp).toBeInTheDocument(); + expect(authorPfp).toHaveAttribute('src', expect.stringContaining('author.jpg')); }); it('displays drop author information without profile picture', () => { diff --git a/__tests__/helpers/Helpers.test.ts b/__tests__/helpers/Helpers.test.ts index 3482593e90..3f3cdd518a 100644 --- a/__tests__/helpers/Helpers.test.ts +++ b/__tests__/helpers/Helpers.test.ts @@ -74,7 +74,7 @@ describe("additional helper functions", () => { test("parseNftDescriptionToHtml replaces newlines and links", () => { const input = "line1\nhttps://example.com"; expect(parseNftDescriptionToHtml(input)).toBe( - 'line1
https://example.com' + 'line1
https://example.com' ); }); diff --git a/contexts/wave/hooks/useWaveMessagesStore.ts b/contexts/wave/hooks/useWaveMessagesStore.ts index 692c94c6b4..0782d7a345 100644 --- a/contexts/wave/hooks/useWaveMessagesStore.ts +++ b/contexts/wave/hooks/useWaveMessagesStore.ts @@ -83,12 +83,9 @@ function useWaveMessagesStore() { }, [waveMessages]); // Stable function to get data for a key - const getData = useCallback( - (key: string): WaveMessages | undefined => { - return waveMessages[key]; - }, - [waveMessages] - ); // Dependency on store is fine here + const getData = useCallback((key: string): WaveMessages | undefined => { + return waveMessagesRef.current[key]; + }, []); // Stable function to subscribe a listener for a specific key const subscribe = useCallback( diff --git a/hooks/useDeviceInfo.ts b/hooks/useDeviceInfo.ts index f63cafd8e6..b07e5cf730 100644 --- a/hooks/useDeviceInfo.ts +++ b/hooks/useDeviceInfo.ts @@ -71,7 +71,19 @@ export default function useDeviceInfo(): DeviceInfo { useEffect(() => { const mq = window.matchMedia("(pointer: coarse)"); - const update = () => setInfo(getInfo()); + const update = () => + setInfo((prev) => { + const next = getInfo(); + if ( + prev.isMobileDevice === next.isMobileDevice && + prev.hasTouchScreen === next.hasTouchScreen && + prev.isApp === next.isApp && + prev.isAppleMobile === next.isAppleMobile + ) { + return prev; + } + return next; + }); mq.addEventListener("change", update); window.addEventListener("resize", update);