import { act, render, screen, within } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import { MemoryRouter } from 'react-router-dom'; import { Navbar } from './navbar'; import { useGlobalStore } from '../../stores'; import { ENV, useFeatureFlags } from '@vegaprotocol/environment'; import { mockConfig, MockedWalletProvider, } from '@vegaprotocol/wallet-react/testing'; import { MockedProvider, type MockedResponse } from '@apollo/react-testing'; import { PartyProfilesDocument, type PartyProfilesQuery, type PartyProfilesQueryVariables, } from '../vega-wallet-connect-button/__generated__/PartyProfiles'; jest.mock('@vegaprotocol/proposals', () => ({ ProtocolUpgradeCountdown: () => null, })); describe('Navbar', () => { const mockKeys = [ { name: 'Key 1', publicKey: '1'.repeat(64), }, { name: 'Key 2', publicKey: '2'.repeat(64), }, ]; const key1Alias = 'key 1 alias'; const marketId = 'abc'; const navbarContent = 'navbar-menu-content'; const partyProfilesMock: MockedResponse< PartyProfilesQuery, PartyProfilesQueryVariables > = { request: { query: PartyProfilesDocument, variables: { partyIds: mockKeys.map((k) => k.publicKey), }, }, result: { data: { partiesProfilesConnection: { edges: [ { node: { partyId: mockKeys[0].publicKey, alias: key1Alias, metadata: [], }, }, ], }, }, }, }; const renderComponent = (initialEntries?: string[]) => { return render( ); }; beforeAll(() => { useGlobalStore.setState({ marketId }); useFeatureFlags.setState({ flags: { REFERRALS: true } }); const mockedENV = jest.mocked(ENV); mockedENV.VEGA_TOKEN_URL = 'governance'; }); afterAll(() => { jest.clearAllMocks(); }); afterEach(() => { act(() => { mockConfig.reset(); }); }); it('should be properly rendered', () => { renderComponent(); const expectedLinks = [ ['/', ''], ['/markets', 'Markets'], [`/markets/${marketId}`, 'Trading'], ['/portfolio', 'Portfolio'], ['/referrals', 'Referrals'], ['/fees', 'Fees'], ['/rewards', 'Rewards'], [expect.stringContaining('governance'), 'Governance'], ]; const links = screen.getAllByRole('link'); links.forEach((link, i) => { const [href, text] = expectedLinks[i]; expect(link).toHaveAttribute('href', href); expect(link).toHaveTextContent(text); }); }); it('Markets page route should not match empty market page', () => { renderComponent(['/markets']); expect(screen.getByRole('link', { name: 'Markets' })).toHaveClass('active'); expect(screen.getByRole('link', { name: 'Trading' })).not.toHaveClass( 'active' ); }); it('can open menu and navigate on small screens', async () => { renderComponent(); await userEvent.click(screen.getByRole('button', { name: 'Menu' })); const menuEl = screen.getByTestId(navbarContent); expect(menuEl).toBeInTheDocument(); const menu = within(menuEl); const expectedLinks = [ ['/markets', 'Markets'], [`/markets/${marketId}`, 'Trading'], ['/portfolio', 'Portfolio'], ['/referrals', 'Referrals'], ['/fees', 'Fees'], ['/rewards', 'Rewards'], [expect.stringContaining('governance'), 'Governance'], ]; const links = menu.getAllByRole('link'); links.forEach((link, i) => { const [href, text] = expectedLinks[i]; expect(link).toHaveAttribute('href', href); expect(link).toHaveTextContent(text); }); await userEvent.click(screen.getByRole('button', { name: 'Close menu' })); expect(screen.queryByTestId(navbarContent)).not.toBeInTheDocument(); }); it('can close menu by clicking overlay', async () => { renderComponent(); await userEvent.click(screen.getByRole('button', { name: 'Menu' })); expect(screen.getByTestId(navbarContent)).toBeInTheDocument(); await userEvent.click(screen.getByTestId('navbar-menu-overlay')); expect(screen.queryByTestId(navbarContent)).not.toBeInTheDocument(); }); it('can open wallet menu on small screens and change pubkey', async () => { mockConfig.store.setState({ status: 'connected', keys: mockKeys, pubKey: mockKeys[0].publicKey, }); const mockSelectPubKey = jest.spyOn(mockConfig.store, 'setState'); renderComponent(undefined); await userEvent.click(screen.getByRole('button', { name: 'Wallet' })); const menuEl = screen.getByTestId(navbarContent); expect(menuEl).toBeInTheDocument(); const menu = within(menuEl); expect(menu.getAllByTestId(/key-\d+-mobile/)).toHaveLength(mockKeys.length); const activeKey = within(menu.getByTestId(/key-1+-mobile/)); expect(activeKey.getByText(mockKeys[0].name)).toBeInTheDocument(); expect(activeKey.getByTestId('icon-tick')).toBeInTheDocument(); expect(screen.getByText(key1Alias)).toBeInTheDocument(); const inactiveKey = within(menu.getByTestId(/key-2+-mobile/)); await userEvent.click(inactiveKey.getByText(mockKeys[1].name)); expect(mockSelectPubKey).toHaveBeenCalledWith({ pubKey: mockKeys[1].publicKey, }); }); it('can transfer and close menu', async () => { mockConfig.store.setState({ status: 'connected', keys: mockKeys, pubKey: mockKeys[0].publicKey, }); renderComponent(); await userEvent.click(screen.getByRole('button', { name: 'Wallet' })); const menuEl = screen.getByTestId(navbarContent); expect(menuEl).toBeInTheDocument(); const menu = within(menuEl); await userEvent.click(menu.getByText('Transfer')); expect(screen.queryByTestId(navbarContent)).not.toBeInTheDocument(); }); it('can disconnect and close menu', async () => { mockConfig.store.setState({ status: 'connected', keys: mockKeys, pubKey: mockKeys[0].publicKey, }); const mockDisconnect = jest.spyOn(mockConfig, 'disconnect'); renderComponent(undefined); await userEvent.click(screen.getByRole('button', { name: 'Wallet' })); const menuEl = screen.getByTestId(navbarContent); expect(menuEl).toBeInTheDocument(); const menu = within(menuEl); await userEvent.click(menu.getByText('Disconnect')); expect(mockDisconnect).toHaveBeenCalled(); expect(screen.queryByTestId(navbarContent)).not.toBeInTheDocument(); }); it('does not render the language selector until we have more languages', () => { renderComponent(); expect(screen.queryByTestId('icon-globe')).not.toBeInTheDocument(); }); it('renders the theme switcher', async () => { renderComponent(); await userEvent.click(screen.getByTestId('icon-moon')); expect(screen.queryByTestId('icon-moon')).not.toBeInTheDocument(); expect(screen.getByTestId('icon-sun')).toBeInTheDocument(); await userEvent.click(screen.getByTestId('icon-sun')); expect(screen.queryByTestId('icon-sun')).not.toBeInTheDocument(); expect(screen.getByTestId('icon-moon')).toBeInTheDocument(); }); });