diff --git a/src/App.tsx b/src/App.tsx index 4bb9ebf8..7bd43c23 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,12 +1,17 @@ +import { BrowserRouter } from 'react-router-dom'; import { QueryParamProvider } from 'use-query-params'; import { ReactRouter5Adapter } from 'use-query-params/adapters/react-router-5'; +import { Header } from '@/components'; import AppContent from './routes/AppContent'; const App = () => { return ( - - - + + +
+ + + ); }; export default App; diff --git a/src/components/Header/Header.scss b/src/components/Header/Header.scss new file mode 100644 index 00000000..35393ae9 --- /dev/null +++ b/src/components/Header/Header.scss @@ -0,0 +1,16 @@ +.header { + height: 4rem; + display: flex; + justify-content: end; + align-items: center; + font-size: 1.6rem; + font-weight: 800; + border-bottom: 2px solid #f2f3f4; + padding: 2.4rem; + margin-bottom: 2.4rem; + + @include mobile { + padding: 0.8rem 2.4rem; + margin-bottom: 0; + } +} diff --git a/src/components/Header/Header.tsx b/src/components/Header/Header.tsx new file mode 100644 index 00000000..8c993684 --- /dev/null +++ b/src/components/Header/Header.tsx @@ -0,0 +1,32 @@ +import { useAuthData } from '@deriv-com/api-hooks'; +import { Button } from '@deriv-com/ui'; +import { LocalStorageConstants, LocalStorageUtils, URLUtils } from '@deriv-com/utils'; + +import './Header.scss'; + +const Header = () => { + const { activeLoginid, logout } = useAuthData(); + const appId = LocalStorageUtils.getValue(LocalStorageConstants.configAppId); + const serverUrl = localStorage.getItem(LocalStorageConstants.configServerURL.toString()); + const oauthUrl = + appId && serverUrl + ? `https://${serverUrl}/oauth2/authorize?app_id=${appId}&l=EN&&brand=deriv` + : URLUtils.getOauthURL(); + + return ( +
+ {activeLoginid ? ( + + ) : ( + + Login + + )} +
+ ); +}; + +export default Header; diff --git a/src/components/Header/__tests__/Header.spec.tsx b/src/components/Header/__tests__/Header.spec.tsx new file mode 100644 index 00000000..94c73b43 --- /dev/null +++ b/src/components/Header/__tests__/Header.spec.tsx @@ -0,0 +1,36 @@ +import { useAuthData } from '@deriv-com/api-hooks'; +import { URLUtils } from '@deriv-com/utils'; +import { render, screen } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; + +import Header from '../Header'; + +const mockUseAuthData = useAuthData as jest.Mock; +jest.mock('@deriv-com/api-hooks', () => ({ + useAuthData: jest.fn(() => ({ activeLoginid: null, logout: jest.fn() })), +})); + +jest.mock('@deriv-com/ui', () => ({ + ...jest.requireActual('@deriv-com/ui'), + Button: ({ children, onClick }: { children: React.ReactNode; onClick: () => void }) => ( + + ), +})); + +describe('
', () => { + it('should render the header', () => { + render(
); + expect(screen.getByRole('link', { name: 'Login' })).toHaveAttribute('href', URLUtils.getOauthURL()); + }); + it('should handle the logout functionality if there is an active login id', async () => { + mockUseAuthData.mockReturnValue({ activeLoginid: '12345', logout: jest.fn() }); + render(
); + + const logoutButton = screen.getByRole('button', { name: 'Logout' }); + const { logout } = mockUseAuthData(); + expect(logoutButton).toBeInTheDocument(); + + await userEvent.click(logoutButton); + expect(logout).toHaveBeenCalled(); + }); +}); diff --git a/src/components/Header/index.ts b/src/components/Header/index.ts new file mode 100644 index 00000000..5653319d --- /dev/null +++ b/src/components/Header/index.ts @@ -0,0 +1 @@ +export { default as Header } from './Header'; diff --git a/src/components/index.ts b/src/components/index.ts index 26dd7955..7bd31164 100644 --- a/src/components/index.ts +++ b/src/components/index.ts @@ -11,6 +11,7 @@ export * from './FloatingRate'; export * from './FlyoutMenu'; export * from './FormProgress'; export * from './FullPageMobileWrapper'; +export * from './Header'; export * from './Input'; export * from './LightDivider'; export * from './MobileTabs';