Skip to content

Commit

Permalink
test: notification, drawer, dropdown, and select (#3756)
Browse files Browse the repository at this point in the history
  • Loading branch information
sashuk authored Aug 3, 2023
1 parent d2c83ba commit 6b65be1
Show file tree
Hide file tree
Showing 15 changed files with 217 additions and 63 deletions.
7 changes: 7 additions & 0 deletions .changeset/nasty-meals-shout.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
'@toptal/picasso': patch
---

### Popper

- use compact layout on extra-small screens
34 changes: 34 additions & 0 deletions cypress/component/Drawer.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
Typography,
} from '@toptal/picasso'
import { useModal, useNotifications } from '@toptal/picasso/utils'
import { HAPPO_TARGETS } from '@toptal/picasso/test-utils'

const DrawerExample = (
props: Partial<DrawerProps> & { open: boolean; onOpen: () => void }
Expand Down Expand Up @@ -148,4 +149,37 @@ describe('Drawer', () => {
variant: 'ultra-wide/behind-modal',
})
})

const testedDrawerVariants: DrawerProps['width'][] = [
'narrow',
'regular',
'ultra-wide',
]

Cypress._.each(HAPPO_TARGETS, happoTarget => {
const { width } = happoTarget

describe(`when screen has ${width}px width`, () => {
Cypress._.each(testedDrawerVariants, variant => {
it(`renders ${variant} drawer`, () => {
cy.viewport(width, 1000)
cy.mount(
<TestDrawer title={`${variant} drawer title`}>
<Container>
<Typography>${variant} drawer content</Typography>
</Container>
</TestDrawer>
)

cy.getByTestId('trigger').click()
cy.getByRole('presentation').should('be.visible')
cy.get('body').happoScreenshot({
component,
variant: `drawer-${variant}-width/${width}-default`,
targets: [happoTarget],
})
})
})
})
})
})
37 changes: 37 additions & 0 deletions cypress/component/Dropdown.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
Form,
Input,
} from '@toptal/picasso'
import { HAPPO_TARGETS } from '@toptal/picasso/test-utils'

const LongListExample = () => (
<Container padded='medium' style={{ height: 900 }}>
Expand Down Expand Up @@ -111,6 +112,42 @@ describe('Dropdown', () => {
variant: 'custom-content-style/after-clicked',
})
})

// Based on screen height, dropdown has different styling
// 250px was selected as a height that shrinks the dropdown enough, 586+px is a
// breakpoint that disables any extra styling
const heights = [250, 586]

heights.forEach(height => {
Cypress._.each(HAPPO_TARGETS, happoTarget => {
const { width } = happoTarget

describe(`when screen has ${width}px width and ${height}px height`, () => {
it(`renders dropdown`, () => {
cy.viewport(width, height)

cy.mount(
<Dropdown content={menu}>
Open menu
<Dropdown.Arrow data-testid='trigger' />
</Dropdown>
)

cy.getByTestId('trigger').realClick()
cy.get('body').happoScreenshot({
component,
variant: `dropdown/${width}x${height}-default`,
targets: [
{
...happoTarget,
viewport: `${happoTarget.width}x${height}`,
},
],
})
})
})
})
})
})

const menuItems = [
Expand Down
44 changes: 44 additions & 0 deletions cypress/component/NotificationStream.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,28 @@ import {
Link,
Pencil16,
} from '@toptal/picasso'
import { HAPPO_TARGETS } from '@toptal/picasso/test-utils'
import { PicassoBreakpoints } from '@toptal/picasso-provider/index'

const DefaultExample = () => {
const { showInfo } = useNotifications()

return (
<Container padded='medium'>
<Button
data-testid='trigger-default'
variant='secondary'
onClick={() =>
showInfo(
"That's one small step for a man, one giant leap for mankind."
)
}
>
Trigger
</Button>
</Container>
)
}

const VariantsExample = () => {
const { showInfo, showSuccess, showError } = useNotifications()
Expand Down Expand Up @@ -114,4 +136,26 @@ describe('NotificationStream', () => {
variant: 'custom-icon',
})
})

Cypress._.each(HAPPO_TARGETS, happoTarget => {
const { width } = happoTarget
const isNarrowScreenSize = width < PicassoBreakpoints.breakpoints.values.lg

describe(`when screen has ${width}px width`, () => {
it(`notification uses ${
isNarrowScreenSize ? 'compact' : 'regular'
} layout`, () => {
cy.viewport(width, 1000)

cy.mount(<DefaultExample />)

cy.getByTestId('trigger-default').click()
cy.get('body').happoScreenshot({
component,
variant: `notification/${width}-default`,
targets: [happoTarget],
})
})
})
})
})
64 changes: 21 additions & 43 deletions cypress/component/Page.spec.tsx
Original file line number Diff line number Diff line change
@@ -1,39 +1,11 @@
import React from 'react'
import type { PageSidebarProps } from '@toptal/picasso'
import { Container, Menu, Page, Typography } from '@toptal/picasso'
import { getCheckpoints } from '@toptal/picasso/test-utils'
import { HAPPO_TARGETS, getHappoTargets } from '@toptal/picasso/test-utils'

const component = 'Page'
const containerHeight = '30rem'

const checkpoints = getCheckpoints()

// Sidebar menu has custom breakpoint at 1280px that changes its behavior, so 1280px
// acts as a divider for "small" and "wide" page checkpoints
const smallScreenCheckpoints = [
...checkpoints.filter(width => width < 1280),
1279,
]
const wideScreenCheckpoints = [
1280,
...checkpoints.filter(width => width >= 1280),
]

const responsiveHappoTargets = [
...smallScreenCheckpoints,
...wideScreenCheckpoints,
].reduce<Record<string, any>>((acc, width) => {
const name = `chrome-desktop-width-${width}`

acc[name] = {
name,
browser: 'chrome',
viewport: `${width}x1024`,
}

return acc
}, {})

enum TestIds {
WRAPPER = 'wrapper',
SIDEBAR_SCROLLABLE_CONTAINER = 'sidebar-scrollable-container',
Expand Down Expand Up @@ -203,17 +175,27 @@ describe('Page', () => {
})
})

describe('for screen sizes smaller than 1280px', () => {
Cypress._.each(smallScreenCheckpoints, width => {
describe(`when page is rendered on a ${width} screen width`, () => {
// Sidebar menu has custom breakpoint at 1280px that changes its behavior
const customBreakpoint = 1280
const extendedHappoTargets = [
...HAPPO_TARGETS,
...getHappoTargets([customBreakpoint - 1, customBreakpoint]),
]

Cypress._.each(extendedHappoTargets, happoTarget => {
const { width } = happoTarget
const isSmallScreenTarget = width < customBreakpoint

if (isSmallScreenTarget) {
describe(`when screen has ${width}px width`, () => {
it('renders hamburger menu and hides sidebar', () => {
cy.viewport(width, 1000)
cy.mount(<Example />)

cy.get('body').happoScreenshot({
component,
variant: `page-menu-screen-smaller-than-1280/${width}-initial`,
targets: [responsiveHappoTargets[`chrome-desktop-width-${width}`]],
targets: [happoTarget],
})

cy.getByTestId('hamburger-button').should('be.visible')
Expand All @@ -224,7 +206,7 @@ describe('Page', () => {
cy.get('body').happoScreenshot({
component,
variant: `page-menu-screen-smaller-than-1280/${width}-opened-menu`,
targets: [responsiveHappoTargets[`chrome-desktop-width-${width}`]],
targets: [happoTarget],
})

cy.getByTestId('hamburger-button').realClick()
Expand All @@ -234,16 +216,12 @@ describe('Page', () => {
cy.get('body').happoScreenshot({
component,
variant: `page-menu-screen-smaller-than-1280/${width}-closed-menu`,
targets: [responsiveHappoTargets[`chrome-desktop-width-${width}`]],
targets: [happoTarget],
})
})
})
})
})

describe('for screen sizes equal or bigger than 1280px', () => {
Cypress._.each(wideScreenCheckpoints, width => {
describe(`when page is rendered on a ${width} screen width`, () => {
} else {
describe(`when screen has ${width}px width`, () => {
it('does not show hamburger menu button and renders sidebar', () => {
cy.viewport(width, 1000)
cy.mount(<Example />)
Expand All @@ -253,10 +231,10 @@ describe('Page', () => {
cy.get('body').happoScreenshot({
component,
variant: `page-menu-screen-bigger-or-equal-than-1280/${width}-default`,
targets: [responsiveHappoTargets[`chrome-desktop-width-${width}`]],
targets: [happoTarget],
})
})
})
})
}
})
})
33 changes: 33 additions & 0 deletions cypress/component/Select.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import React, { useState } from 'react'
import type { SelectValueType, SelectProps } from '@toptal/picasso'
import { Select, Form, Container, Drawer } from '@toptal/picasso'
import { noop, palette } from '@toptal/picasso/utils'
import { HAPPO_TARGETS } from '@toptal/picasso/test-utils'

const TestSelect = ({
onChange = noop,
Expand Down Expand Up @@ -395,4 +396,36 @@ describe('Select', () => {
cy.getByTestId('search-input').find('input').should('be.focused')
})
})

// Based on screen height, select (scroll menu) has different styling
// 250px was selected as a height that shrinks the select enough, 586+px is a
// breakpoint that disables any extra styling
const heights = [250, 586]

heights.forEach(height => {
Cypress._.each(HAPPO_TARGETS, happoTarget => {
const { width } = happoTarget

describe(`when screen has ${width}px width and ${height}px height`, () => {
it(`renders select`, () => {
cy.viewport(width, height)

cy.mount(<TestSelect options={MANY_OPTIONS} />)

openSelect()

cy.get('body').happoScreenshot({
component,
variant: `select/${width}x${height}-default`,
targets: [
{
...happoTarget,
viewport: `${happoTarget.width}x${height}`,
},
],
})
})
})
})
})
})
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@
"@toptal/davinci-syntax": "^20.2.1",
"@types/debounce": "^1.2.1",
"@types/esprima": "^4.0.3",
"@types/happo-cypress": "^4.1.0",
"@types/happo-cypress": "^4.1.1",
"@types/jest-image-snapshot": "^3.1.0",
"@types/react-truncate": "^2.3.4",
"babel-loader": "^9.1.2",
Expand Down
9 changes: 3 additions & 6 deletions packages/picasso/src/Dropdown/styles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,17 +28,14 @@ export default ({ screens, shadows, palette }: Theme) =>
maxHeight: '14.75rem', // 6.5 lines of menu to show
overflowY: 'auto',
boxShadow: shadows[0],
[screens('xs', 'sm')]: {
maxHeight: '14.75rem', // 6.5 lines of menu to show
},

// height under which maxHeight menu starts to overflow
// and needs to reduce height dynamically to avoid overflow
'@media screen and (max-height: 585px)': {
maxHeight: 'calc(50vh - 3.5rem)', // half of screen minus header and anchor
maxHeight: 'calc(50vh - 3rem)', // half of viewport minus header and anchor

[screens('xs', 'sm')]: {
maxHeight: 'calc(50vh - 3rem)', // half of viewport minus header and anchor
[screens('md', 'lg', 'xl')]: {
maxHeight: 'calc(50vh - 3.5rem)', // half of screen minus header and anchor
},
},
},
Expand Down
2 changes: 1 addition & 1 deletion packages/picasso/src/Popper/Popper.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ export const Popper = forwardRef<PopperJs, Props>(function Popper(props, ref) {
const isInsideModal = useContext(ModalContext)

const classes = useStyles()
const isCompactLayoutResolution = useBreakpoint(['sm', 'md'])
const isCompactLayoutResolution = useBreakpoint(['xs', 'sm', 'md'])
const isCompactLayout = enableCompactMode && isCompactLayoutResolution
const widthStyle = useWidthStyle({ autoWidth, width, anchorEl })
const anchorElWidthStyle = !isCompactLayout && widthStyle
Expand Down
10 changes: 3 additions & 7 deletions packages/picasso/src/ScrollMenu/styles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,13 @@ export default ({ palette, screens }: Theme) =>
maxHeight: '26.875rem', // ~8.5 lines of menu to show
overflowY: 'auto',

[screens('xs', 'sm')]: {
maxHeight: '26.875rem', // ~8.5 lines of menu to show
},

// height under which maxHeight menu starts to overflow
// and needs to reduce height dynamically to avoid overflow
'@media screen and (max-height: 585px)': {
maxHeight: 'calc(50vh - 4.8125rem)', // half of viewport minus header and anchor
maxHeight: 'calc(50vh - 4.3125rem)', // half of viewport minus header and anchor

[screens('xs', 'sm')]: {
maxHeight: 'calc(50vh - 4.3125rem)', // half of viewport minus header and anchor
[screens('md', 'lg', 'xl')]: {
maxHeight: 'calc(50vh - 4.8125rem)', // half of viewport minus header and anchor
},
},
},
Expand Down
Loading

0 comments on commit 6b65be1

Please sign in to comment.