Skip to content

Commit

Permalink
Added a basic settings link for now
Browse files Browse the repository at this point in the history
  • Loading branch information
crismali committed Oct 12, 2023
1 parent ade1ffc commit 63113d2
Show file tree
Hide file tree
Showing 10 changed files with 186 additions and 28 deletions.
7 changes: 7 additions & 0 deletions src/features.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
export interface Features {
settings: () => boolean
}

export const availableFeatures: Features = {
settings: () => false,
}
16 changes: 16 additions & 0 deletions src/pages/__tests__/settings.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import React from 'react'
import { render } from '@testing-library/react'
import Settings from '../settings'
import { TEST_ID as sidebarNavigationTestId } from 'src/ui/SidebarNavigation'

describe('Library page', () => {
it('is displayed in a layout', () => {
const { baseElement } = render(<Settings />)
expect(baseElement.querySelector('.layout')).not.toBeNull()
})

it('displays the sidebar navigation', () => {
const { queryByTestId } = render(<Settings />)
expect(queryByTestId(sidebarNavigationTestId)).not.toBeNull()
})
})
26 changes: 26 additions & 0 deletions src/pages/settings.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import React, { FC } from 'react'
import { HeadFC } from 'gatsby'
import { SkipNavContent } from '@reach/skip-nav'
import { Heading, Layout, PageContent, Paragraph, Sidebar, SpacedContainer } from 'src/ui/Layout'
import { SidebarNavigation } from 'src/ui/SidebarNavigation'

const SettingsPage: FC = () => {
return (
<Layout element="div">
<Sidebar>
<SidebarNavigation />
</Sidebar>
<SkipNavContent />
<PageContent element="main">
<SpacedContainer>
<Heading element="h1">Settings</Heading>
<Paragraph>Coming soon.</Paragraph>
</SpacedContainer>
</PageContent>
</Layout>
)
}

export default SettingsPage

export const Head: HeadFC = () => <title>Settings</title>
4 changes: 4 additions & 0 deletions src/testHelpers.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -109,3 +109,7 @@ export const expectEmailPartContentFor = (key: string, element: HTMLElement) =>
const li = ul!.querySelector(`[data-testid="${key}"]`)
expect(li).not.toBeNull()
}

export const asMock = <T extends (...args: any) => any>(func: T): jest.Mock<ReturnType<T>> => {
return func as any
}
24 changes: 23 additions & 1 deletion src/ui/Layout.css
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,16 @@
display: flex;
flex: 1;
flex-direction: column;
padding: 3.25rem 0;
padding-top: 3.25rem;
}

.spaced-sidebar-container {
padding: 0 2rem;
}

.sidebar nav {
display: flex;
flex: 1;
padding-top: 2.5rem;
}

Expand All @@ -35,9 +37,14 @@
font-size: 1.35rem;
font-weight: var(--weight-bold);
gap: 1.25rem;
flex: 1;
line-height: 2rem;
}

.sidebar-spacer {
flex: 1;
}

.sidebar-list a {
color: var(--black);
text-decoration: none;
Expand All @@ -47,6 +54,21 @@
text-decoration: underline;
}

.sidebar-list-item-bottom {
background-color: #d9d9d9;
padding: 1.5rem 0;
}

.sidebar-list-item-bottom:has(a.sidebar-active-link) {
background-color: var(--blue);
}

.sidebar-list-item-bottom a.sidebar-active-link {
border-bottom: 2px solid var(--white);
color: var(--white);
text-decoration: none;
}

.page-content {
flex: 4;
}
Expand Down
13 changes: 11 additions & 2 deletions src/ui/Layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -58,10 +58,19 @@ export const SideBarList: FC<SidebarListProps> = ({ children }) => {

interface SidebarListItemProps {
children: ReactNode
className?: string
}

export const SideBarListItem: FC<SidebarListItemProps> = ({ children, className }) => {
return <li className={classNames('sidebar-list-item', className)}>{children}</li>
}

interface SideBarListItemBottomProps {
children: ReactNode
}

export const SideBarListItem: FC<SidebarListItemProps> = ({ children }) => {
return <li className="sidebar-list-item">{children}</li>
export const SideBarListItemBottom: FC<SideBarListItemBottomProps> = ({ children }) => {
return <SideBarListItem className="sidebar-list-item-bottom">{children}</SideBarListItem>
}

interface HeadingProps {
Expand Down
64 changes: 41 additions & 23 deletions src/ui/SidebarNavigation.tsx
Original file line number Diff line number Diff line change
@@ -1,33 +1,51 @@
import React, { FC } from 'react'
import { SideBarList, SideBarListItem, SpacedSidebarContainer } from './Layout'
import React, { FC, ReactNode } from 'react'
import {
SideBarList,
SideBarListItem,
SideBarListItemBottom,
SpacedSidebarContainer,
} from './Layout'
import { Link } from 'gatsby'
import { availableFeatures } from 'src/features'

interface Props {}

export const TEST_ID = 'sidebar-navigation'

export const SidebarNavigation: FC<Props> = () => {
return (
<SpacedSidebarContainer>
<nav data-testid={TEST_ID}>
<SideBarList>
<SideBarListItem>
<Link activeClassName="sidebar-active-link" to="/">
Home
</Link>
</SideBarListItem>
<SideBarListItem>
<Link activeClassName="sidebar-active-link" to="/library">
Library
</Link>
</SideBarListItem>
<SideBarListItem>
<Link activeClassName="sidebar-active-link" to="/tips-and-tricks">
Tips & Tricks
</Link>
</SideBarListItem>
</SideBarList>
</nav>
</SpacedSidebarContainer>
<nav data-testid={TEST_ID}>
<SideBarList>
<SpacedLink to="/">Home</SpacedLink>
<SpacedLink to="/library">Library</SpacedLink>
<SpacedLink to="/tips-and-tricks">Tips & Tricks</SpacedLink>
<li aria-hidden className="sidebar-spacer" />
{availableFeatures.settings() && (
<SpacedLink bottom to="/settings">
Settings
</SpacedLink>
)}
</SideBarList>
</nav>
)
}

interface SpacedLinkProps {
bottom?: boolean
children: ReactNode
to: string
}

const SpacedLink: FC<SpacedLinkProps> = ({ bottom, children, to }) => {
const Comp = bottom ? SideBarListItemBottom : SideBarListItem

return (
<Comp>
<SpacedSidebarContainer>
<Link activeClassName="sidebar-active-link" to={to}>
{children}
</Link>
</SpacedSidebarContainer>
</Comp>
)
}
22 changes: 22 additions & 0 deletions src/ui/__tests__/Layout.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
Sidebar,
SideBarList,
SideBarListItem,
SideBarListItemBottom,
SpacedContainer,
SpacedSidebarContainer,
} from '../Layout'
Expand Down Expand Up @@ -154,6 +155,27 @@ describe('SideBarListItem', () => {
)
expect(baseElement).toContainHTML(`<div>${text}</div>`)
})

it('accepts a className', () => {
const { baseElement } = render(
<SideBarListItem className="my-class">
<div />
</SideBarListItem>,
)
expect(baseElement).toContainHTML('<li class="sidebar-list-item my-class"><div></div></li>')
})
})

describe('SideBarListItemBottom', () => {
it('displays its children', () => {
const text = faker.lorem.paragraph()
const { baseElement } = render(
<SideBarListItemBottom>
<div>{text}</div>
</SideBarListItemBottom>,
)
expect(baseElement).toContainHTML(`<div>${text}</div>`)
})
})

describe('Heading', () => {
Expand Down
35 changes: 34 additions & 1 deletion src/ui/__tests__/SidebarNavigation.test.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,16 @@
import { render } from '@testing-library/react'
import React from 'react'
import { SidebarNavigation } from '../SidebarNavigation'
import { urlFor } from 'src/testHelpers'
import { asMock, urlFor } from 'src/testHelpers'
import { availableFeatures, Features } from 'src/features'

jest.mock('src/features', () => {
return {
availableFeatures: {
settings: jest.fn().mockReturnValue(true),
} as Features,
}
})

describe('SidebarNavigation', () => {
it('displays a home link', () => {
Expand All @@ -24,4 +33,28 @@ describe('SidebarNavigation', () => {
expect(link.tagName).toEqual('A')
expect(link.href).toEqual(urlFor('/tips-and-tricks'))
})

describe('settings is available', () => {
beforeEach(() => {
asMock(availableFeatures.settings).mockReturnValue(true)
})

it('displays a settings link', () => {
const { getByText } = render(<SidebarNavigation />)
const link: HTMLAnchorElement = getByText('Settings') as any
expect(link.tagName).toEqual('A')
expect(link.href).toEqual(urlFor('/settings'))
})
})

describe('settings is not available', () => {
beforeEach(() => {
asMock(availableFeatures.settings).mockReturnValue(false)
})

it('does not display a settings link', () => {
const { queryByText } = render(<SidebarNavigation />)
expect(queryByText('Settings')).toBeNull()
})
})
})
3 changes: 2 additions & 1 deletion src/utils/__tests__/useEmailTemplatesData.test.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import { renderHook } from '@testing-library/react'
import { useStaticQuery } from 'gatsby'
import { useEmailTemplatesData } from '../useEmailTemplatesData'
import { asMock } from 'src/testHelpers'

jest.unmock('../useEmailTemplatesData')

describe('useEmailTemplatesData', () => {
beforeEach(() => {
;(useStaticQuery as any).mockImplementation((): Queries.EmailTemplatesDataQuery => {
asMock(useStaticQuery).mockImplementation((): Queries.EmailTemplatesDataQuery => {
return {
emailTemplates: {
edges: [
Expand Down

0 comments on commit 63113d2

Please sign in to comment.