diff --git a/libs/environment/src/components/network-switcher/network-switcher.spec.tsx b/libs/environment/src/components/network-switcher/network-switcher.spec.tsx index a5b0470d7..c7014e7db 100644 --- a/libs/environment/src/components/network-switcher/network-switcher.spec.tsx +++ b/libs/environment/src/components/network-switcher/network-switcher.spec.tsx @@ -13,6 +13,24 @@ import { Networks } from '../../'; jest.mock('../../hooks/use-environment'); describe('Network switcher', () => { + const { location } = window; + let hrefSetSpy: jest.SpyInstance; + + beforeEach(() => { + hrefSetSpy = jest.fn(); + // @ts-ignore can't set location as optional + delete window.location; + window.location = {} as Location; + Object.defineProperty(window.location, 'href', { + // @ts-ignore set cannot take SpyInstance + set: hrefSetSpy, + }); + }); + + afterEach(() => { + window.location = location; + }); + it.each` network | label ${Networks.CUSTOM} | ${envTriggerMapping[Networks.CUSTOM]} @@ -49,21 +67,29 @@ describe('Network switcher', () => { render(); await userEvent.click(screen.getByRole('button')); + let links = screen.getAllByRole('link'); + + expect(links[0]).toHaveTextContent(envNameMapping[Networks.MAINNET]); + expect(links[1]).toHaveTextContent(envNameMapping[Networks.TESTNET]); + expect(links[0]).not.toHaveTextContent(t('current')); + expect(links[1]).not.toHaveTextContent(t('current')); + expect(links[0]).not.toHaveTextContent(t('not available')); + expect(links[1]).not.toHaveTextContent(t('not available')); + expect(links[2]).toHaveTextContent(t('Propose a network parameter change')); const menuitems = screen.getAllByRole('menuitem'); - expect(menuitems[0]).toHaveTextContent(envNameMapping[Networks.MAINNET]); - expect(menuitems[1]).toHaveTextContent(envNameMapping[Networks.TESTNET]); - expect(menuitems[0]).not.toHaveTextContent(t('current')); - expect(menuitems[1]).not.toHaveTextContent(t('current')); - expect(menuitems[0]).not.toHaveTextContent(t('not available')); - expect(menuitems[1]).not.toHaveTextContent(t('not available')); - expect(menuitems[2]).toHaveTextContent(t('Advanced')); + expect(menuitems[0]).toHaveTextContent('Advanced'); - const links = screen.getAllByRole('link'); + await userEvent.click(links[0]); + expect(hrefSetSpy).toHaveBeenCalledWith(mainnetUrl); - expect(links[0]).toHaveAttribute('href', mainnetUrl); - expect(links[1]).toHaveAttribute('href', testnetUrl); + // re open dropdown as clicking an item will close it + await userEvent.click(screen.getByRole('button')); + links = screen.getAllByRole('link'); + + await userEvent.click(links[1]); + expect(hrefSetSpy).toHaveBeenCalledWith(testnetUrl); }); it('displays the correct selected network on the default dropdown view', async () => { @@ -82,10 +108,10 @@ describe('Network switcher', () => { await userEvent.click(screen.getByRole('button')); - const menuitems = screen.getAllByRole('menuitem'); + const links = screen.getAllByRole('link'); - expect(menuitems[0]).toHaveTextContent(envNameMapping[Networks.MAINNET]); - expect(menuitems[0]).toHaveTextContent(t('current')); + expect(links[0]).toHaveTextContent(envNameMapping[Networks.MAINNET]); + expect(links[0]).toHaveTextContent(t('current')); }); it('displays the correct selected network on the default dropdown view when it does not have an associated url', async () => { @@ -103,10 +129,10 @@ describe('Network switcher', () => { await userEvent.click(screen.getByRole('button')); - const menuitems = screen.getAllByRole('menuitem'); + const links = screen.getAllByRole('link'); - expect(menuitems[0]).toHaveTextContent(envNameMapping[Networks.MAINNET]); - expect(menuitems[0]).toHaveTextContent(t('current')); + expect(links[0]).toHaveTextContent(envNameMapping[Networks.MAINNET]); + expect(links[0]).toHaveTextContent(t('current')); }); it('displays the correct state for a network without url on the default dropdown view', async () => { @@ -123,44 +149,59 @@ describe('Network switcher', () => { render(); await userEvent.click(screen.getByRole('button')); + const links = screen.getAllByRole('link'); - const menuitems = screen.getAllByRole('menuitem'); - - expect(menuitems[0]).toHaveTextContent(envNameMapping[Networks.MAINNET]); - expect(menuitems[0]).toHaveTextContent(t('not available')); + expect(links[0]).toHaveTextContent(envNameMapping[Networks.MAINNET]); + expect(links[0]).toHaveTextContent(t('not available')); }); - it('displays the advanced view in the correct state', async () => { - const VEGA_NETWORKS: Record = { - [Networks.CUSTOM]: undefined, - [Networks.MAINNET]: 'https://main.net', - [Networks.TESTNET]: 'https://test.net', - [Networks.VALIDATOR_TESTNET]: 'https://validator-test.net', - [Networks.DEVNET]: 'https://dev.net', - [Networks.STAGNET1]: 'https://stag1.net', - }; - // @ts-ignore Typescript doesn't know about this module being mocked - useEnvironment.mockImplementation(() => ({ - VEGA_ENV: Networks.DEVNET, - VEGA_NETWORKS, - })); + it.each([Networks.MAINNET, Networks.TESTNET, Networks.DEVNET])( + 'displays the advanced view in the correct state', + async (network) => { + const VEGA_NETWORKS: Record = { + [Networks.CUSTOM]: undefined, + [Networks.MAINNET]: 'https://main.net', + [Networks.TESTNET]: 'https://test.net', + [Networks.VALIDATOR_TESTNET]: 'https://validator-test.net', + [Networks.DEVNET]: 'https://dev.net', + [Networks.STAGNET1]: 'https://stag1.net', + }; + // @ts-ignore Typescript doesn't know about this module being mocked + useEnvironment.mockImplementation(() => ({ + VEGA_ENV: Networks.DEVNET, + VEGA_NETWORKS, + })); - render(); + render(); - await userEvent.click(screen.getByRole('button')); - await userEvent.click( - screen.getByRole('menuitem', { name: t('Advanced') }) - ); + await userEvent.click(screen.getByTestId('network-switcher')); - [Networks.MAINNET, Networks.TESTNET, Networks.DEVNET].forEach((network) => { expect( - screen.getByRole('link', { name: envNameMapping[network] }) - ).toHaveAttribute('href', VEGA_NETWORKS[network]); - expect( - screen.getByText(envDescriptionMapping[network]) + await screen.findByRole('menuitem', { name: t('Advanced') }) ).toBeInTheDocument(); - }); - }); + + await userEvent.click( + screen.getByRole('menuitem', { name: t('Advanced') }) + ); + + expect( + await screen.findByText(envDescriptionMapping[network]) + ).toBeInTheDocument(); + expect( + screen.getByRole('link', { + name: new RegExp(`^${envNameMapping[network]}`), + }) + ).toBeInTheDocument(); + + await userEvent.click( + screen.getByRole('link', { + name: new RegExp(`^${envNameMapping[network]}`), + }) + ); + + expect(hrefSetSpy).toHaveBeenCalledWith(VEGA_NETWORKS[network]); + } + ); it('labels the selected network in the advanced view', async () => { const selectedNetwork = Networks.DEVNET; @@ -188,7 +229,7 @@ describe('Network switcher', () => { const label = screen.getByText(`(${t('current')})`); expect(label).toBeInTheDocument(); - expect(label.parentNode?.firstElementChild).toHaveTextContent( + expect(label.parentNode?.parentNode?.firstElementChild).toHaveTextContent( envNameMapping[selectedNetwork] ); }); @@ -217,7 +258,7 @@ describe('Network switcher', () => { const label = screen.getByText('(not available)'); expect(label).toBeInTheDocument(); - expect(label.parentNode?.firstElementChild).toHaveTextContent( + expect(label.parentNode?.parentNode?.firstElementChild).toHaveTextContent( envNameMapping[Networks.MAINNET] ); }); diff --git a/libs/environment/src/components/network-switcher/network-switcher.tsx b/libs/environment/src/components/network-switcher/network-switcher.tsx index c4442aca5..ee30cf01a 100644 --- a/libs/environment/src/components/network-switcher/network-switcher.tsx +++ b/libs/environment/src/components/network-switcher/network-switcher.tsx @@ -1,7 +1,6 @@ -import { useState, useCallback, useRef } from 'react'; +import { useState, useCallback } from 'react'; import { t } from '@vegaprotocol/i18n'; import { - Link, DropdownMenu, DropdownMenuContent, DropdownMenuItem, @@ -99,7 +98,6 @@ export const NetworkSwitcher = ({ }, [setOpen, setAdvancedView] ); - const menuRef = useRef(null); const current = currentNetwork || VEGA_ENV; @@ -110,7 +108,6 @@ export const NetworkSwitcher = ({ trigger={ } > - + {!isAdvancedView && ( <> {standardNetworkKeys.map((key) => ( @@ -134,14 +128,16 @@ export const NetworkSwitcher = ({ key={key} data-testid="network-item" disabled={!VEGA_NETWORKS[key]} + role="link" + onClick={() => + (window.location.href = VEGA_NETWORKS[key] || '') + } > - - {envNameMapping[key]} - - + {envNameMapping[key]} + ))} {advancedNetworkKeys.map((key) => ( - + + (window.location.href = VEGA_NETWORKS[key] || '') + } + > - {envNameMapping[key]} + {envNameMapping[key]}