Replace splitter e2e test with unit test

Signed-off-by: Tilman Vatteroth <git@tilmanvatteroth.de>
This commit is contained in:
Tilman Vatteroth 2022-04-03 16:45:30 +02:00
parent 8a12755164
commit 3a74ce9267
10 changed files with 449 additions and 97 deletions

View file

@ -30,6 +30,7 @@ import { EditorView } from '@codemirror/view'
import { autocompletion } from '@codemirror/autocomplete'
import { useCodeMirrorFocusReference } from './hooks/use-code-mirror-focus-reference'
import { useOffScreenScrollProtection } from './hooks/use-off-screen-scroll-protection'
import { cypressId } from '../../../utils/cypress-attribute'
const logger = new Logger('EditorPane')
@ -94,7 +95,8 @@ export const EditorPane: React.FC<ScrollProps> = ({ scrollState, onScroll, onMak
<div
className={`d-flex flex-column h-100 position-relative`}
onTouchStart={onMakeScrollSource}
onMouseEnter={onMakeScrollSource}>
onMouseEnter={onMakeScrollSource}
{...cypressId('editor-pane')}>
<MaxLengthWarning />
<ToolBar />
<ReactCodeMirror

View file

@ -0,0 +1,304 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`Splitter can render both panes 1`] = `
<div>
<div
class="flex-fill flex-row d-flex "
>
<div
class="splitter left "
style="width: calc(50% - 5px);"
>
left
</div>
<div
class="splitter separator"
>
<div
class="split-divider"
data-testid="splitter-divider"
/>
</div>
<div
class="splitter right "
style="width: calc(100% - 50%);"
>
right
</div>
</div>
</div>
`;
exports[`Splitter can render only the left pane 1`] = `
<div>
<div
class="flex-fill flex-row d-flex "
>
<div
class="splitter left "
style="width: calc(100% - 5px);"
>
left
</div>
<div
class="splitter right d-none"
style="width: calc(100% - 100%);"
>
right
</div>
</div>
</div>
`;
exports[`Splitter can render only the right pane 1`] = `
<div>
<div
class="flex-fill flex-row d-flex "
>
<div
class="splitter left d-none"
style="width: calc(0% - 5px);"
>
left
</div>
<div
class="splitter right "
style="width: calc(100% - 0%);"
>
right
</div>
</div>
</div>
`;
exports[`Splitter resize can change size with mouse 1`] = `
<div>
<div
class="flex-fill flex-row d-flex "
>
<div
class="splitter left "
style="width: calc(50% - 5px);"
>
left
</div>
<div
class="splitter separator"
>
<div
class="split-divider"
data-testid="splitter-divider"
/>
</div>
<div
class="splitter right "
style="width: calc(100% - 50%);"
>
right
</div>
</div>
</div>
`;
exports[`Splitter resize can change size with mouse 2`] = `
<div>
<div
class="flex-fill flex-row d-flex "
>
<div
class="splitter left "
style="width: calc(100% - 5px);"
>
left
</div>
<div
class="splitter separator"
>
<div
class="split-divider"
data-testid="splitter-divider"
/>
</div>
<div
class="splitter right "
style="width: calc(100% - 100%);"
>
right
</div>
</div>
</div>
`;
exports[`Splitter resize can change size with mouse 3`] = `
<div>
<div
class="flex-fill flex-row d-flex "
>
<div
class="splitter left "
style="width: calc(0% - 5px);"
>
left
</div>
<div
class="splitter separator"
>
<div
class="split-divider"
data-testid="splitter-divider"
/>
</div>
<div
class="splitter right "
style="width: calc(100% - 0%);"
>
right
</div>
</div>
</div>
`;
exports[`Splitter resize can change size with mouse 4`] = `
<div>
<div
class="flex-fill flex-row d-flex "
>
<div
class="splitter left "
style="width: calc(0% - 5px);"
>
left
</div>
<div
class="splitter separator"
>
<div
class="split-divider"
data-testid="splitter-divider"
/>
</div>
<div
class="splitter right "
style="width: calc(100% - 0%);"
>
right
</div>
</div>
</div>
`;
exports[`Splitter resize can change size with touch 1`] = `
<div>
<div
class="flex-fill flex-row d-flex "
>
<div
class="splitter left "
style="width: calc(50% - 5px);"
>
left
</div>
<div
class="splitter separator"
>
<div
class="split-divider"
data-testid="splitter-divider"
/>
</div>
<div
class="splitter right "
style="width: calc(100% - 50%);"
>
right
</div>
</div>
</div>
`;
exports[`Splitter resize can change size with touch 2`] = `
<div>
<div
class="flex-fill flex-row d-flex "
>
<div
class="splitter left "
style="width: calc(NaN% - 5px);"
>
left
</div>
<div
class="splitter separator"
>
<div
class="split-divider"
data-testid="splitter-divider"
/>
</div>
<div
class="splitter right "
style="width: calc(100% - NaN%);"
>
right
</div>
</div>
</div>
`;
exports[`Splitter resize can change size with touch 3`] = `
<div>
<div
class="flex-fill flex-row d-flex "
>
<div
class="splitter left "
style="width: calc(NaN% - 5px);"
>
left
</div>
<div
class="splitter separator"
>
<div
class="split-divider"
data-testid="splitter-divider"
/>
</div>
<div
class="splitter right "
style="width: calc(100% - NaN%);"
>
right
</div>
</div>
</div>
`;
exports[`Splitter resize can change size with touch 4`] = `
<div>
<div
class="flex-fill flex-row d-flex "
>
<div
class="splitter left "
style="width: calc(NaN% - 5px);"
>
left
</div>
<div
class="splitter separator"
>
<div
class="split-divider"
data-testid="splitter-divider"
/>
</div>
<div
class="splitter right "
style="width: calc(100% - NaN%);"
>
right
</div>
</div>
</div>
`;

View file

@ -6,7 +6,7 @@
import React from 'react'
import styles from './split-divider.module.scss'
import { cypressId } from '../../../../utils/cypress-attribute'
import { testId } from '../../../../utils/test-id'
export interface SplitDividerProps {
onGrab: () => void
@ -18,7 +18,7 @@ export const SplitDivider: React.FC<SplitDividerProps> = ({ onGrab }) => {
onMouseDown={onGrab}
onTouchStart={onGrab}
className={styles['split-divider']}
{...cypressId('split-divider')}
{...testId('splitter-divider')}
/>
)
}

View file

@ -0,0 +1,70 @@
/*
* SPDX-FileCopyrightText: 2022 The HedgeDoc developers (see AUTHORS file)
*
* SPDX-License-Identifier: AGPL-3.0-only
*/
import { fireEvent, render, screen } from '@testing-library/react'
import { Splitter } from './splitter'
describe('Splitter', () => {
it('can render only the left pane', () => {
const view = render(<Splitter showLeft={true} showRight={false} left={<>left</>} right={<>right</>} />)
expect(view.container).toMatchSnapshot()
})
it('can render only the right pane', () => {
const view = render(<Splitter showLeft={false} showRight={true} left={<>left</>} right={<>right</>} />)
expect(view.container).toMatchSnapshot()
})
it('can render both panes', () => {
const view = render(<Splitter showLeft={true} showRight={true} left={<>left</>} right={<>right</>} />)
expect(view.container).toMatchSnapshot()
})
describe('resize', () => {
beforeEach(() => {
Object.defineProperty(window.HTMLDivElement.prototype, 'clientWidth', { value: 1920 })
Object.defineProperty(window.HTMLDivElement.prototype, 'offsetLeft', { value: 0 })
})
it('can change size with mouse', async () => {
const view = render(<Splitter showLeft={true} showRight={true} left={<>left</>} right={<>right</>} />)
expect(view.container).toMatchSnapshot()
const divider = await screen.findByTestId('splitter-divider')
fireEvent.mouseDown(divider, {})
fireEvent.mouseMove(window, { buttons: 1, clientX: 1920 })
fireEvent.mouseUp(window)
expect(view.container).toMatchSnapshot()
fireEvent.mouseDown(divider, {})
fireEvent.mouseMove(window, { buttons: 1, clientX: 0 })
fireEvent.mouseUp(window)
expect(view.container).toMatchSnapshot()
fireEvent.mouseMove(window, { buttons: 1, clientX: 1920 })
expect(view.container).toMatchSnapshot()
})
it('can change size with touch', async () => {
const view = render(<Splitter showLeft={true} showRight={true} left={<>left</>} right={<>right</>} />)
expect(view.container).toMatchSnapshot()
const divider = await screen.findByTestId('splitter-divider')
fireEvent.touchStart(divider, {})
fireEvent.touchMove(window, { buttons: 1, clientX: 1920 })
fireEvent.touchEnd(window)
expect(view.container).toMatchSnapshot()
fireEvent.touchStart(divider, {})
fireEvent.touchMove(window, { buttons: 1, clientX: 0 })
fireEvent.touchCancel(window)
expect(view.container).toMatchSnapshot()
fireEvent.touchMove(window, { buttons: 1, clientX: 1920 })
expect(view.container).toMatchSnapshot()
})
})
})

View file

@ -5,12 +5,12 @@
*/
import type { ReactElement } from 'react'
import React, { useCallback, useEffect, useRef, useState } from 'react'
import React, { useCallback, useRef, useState } from 'react'
import { ShowIf } from '../../common/show-if/show-if'
import { SplitDivider } from './split-divider/split-divider'
import styles from './splitter.module.scss'
import { useAdjustedRelativeSplitValue } from './hooks/use-adjusted-relative-split-value'
import { cypressId } from '../../../utils/cypress-attribute'
import { useBindPointerMovementEventOnWindow } from '../../../hooks/common/use-bind-pointer-movement-event-on-window'
export interface SplitterProps {
left?: ReactElement
@ -41,9 +41,9 @@ const isLeftMouseButtonClicked = (mouseEvent: MouseEvent): boolean => {
*/
const extractHorizontalPosition = (moveEvent: MouseEvent | TouchEvent): number => {
if (isMouseEvent(moveEvent)) {
return moveEvent.pageX
return moveEvent.clientX
} else {
return moveEvent.touches[0]?.pageX
return moveEvent.touches[0]?.clientX
}
}
@ -107,42 +107,21 @@ export const Splitter: React.FC<SplitterProps> = ({
moveEvent.preventDefault()
}, [])
/**
* Registers and unregisters necessary event listeners on the body so you can use the split even if the mouse isn't moving over it.
*/
useEffect(() => {
const moveHandler = onMove
const stopResizeHandler = onStopResizing
window.addEventListener('touchmove', moveHandler)
window.addEventListener('mousemove', moveHandler)
window.addEventListener('touchcancel', stopResizeHandler)
window.addEventListener('touchend', stopResizeHandler)
window.addEventListener('mouseup', stopResizeHandler)
return () => {
window.removeEventListener('touchmove', moveHandler)
window.removeEventListener('mousemove', moveHandler)
window.removeEventListener('touchcancel', stopResizeHandler)
window.removeEventListener('touchend', stopResizeHandler)
window.removeEventListener('mouseup', stopResizeHandler)
}
}, [resizingInProgress, onMove, onStopResizing])
useBindPointerMovementEventOnWindow(onMove, onStopResizing)
return (
<div ref={splitContainer} className={`flex-fill flex-row d-flex ${additionalContainerClassName || ''}`}>
<div
{...cypressId('splitter-left')}
className={`${styles['splitter']} ${styles['left']} ${!showLeft ? 'd-none' : ''}`}
style={{ width: `calc(${adjustedRelativeSplitValue}% - 5px)` }}>
{left}
</div>
<ShowIf condition={showLeft && showRight}>
<div className={`${styles['splitter']} ${styles['separator']}`} {...cypressId('splitter-separator')}>
<div className={`${styles['splitter']} ${styles['separator']}`}>
<SplitDivider onGrab={onStartResizing} />
</div>
</ShowIf>
<div
{...cypressId('splitter-right')}
className={`${styles['splitter']} ${styles['right']} ${!showRight ? 'd-none' : ''}`}
style={{ width: `calc(100% - ${adjustedRelativeSplitValue}%)` }}>
{right}

View file

@ -5,7 +5,8 @@
*/
import type React from 'react'
import { useCallback, useEffect, useRef, useState } from 'react'
import { useCallback, useRef, useState } from 'react'
import { useBindPointerMovementEventOnWindow } from '../../../../hooks/common/use-bind-pointer-movement-event-on-window'
/**
* Determines if the left mouse button is pressed in the given event
@ -82,23 +83,7 @@ export const useResizeGistFrame = (initialFrameHeight: number): [number, Pointer
}
}, [])
useEffect(() => {
const moveHandler = onMove
const stopResizeHandler = onStopResizing
window.addEventListener('touchmove', moveHandler)
window.addEventListener('mousemove', moveHandler)
window.addEventListener('touchcancel', stopResizeHandler)
window.addEventListener('touchend', stopResizeHandler)
window.addEventListener('mouseup', stopResizeHandler)
return () => {
window.removeEventListener('touchmove', moveHandler)
window.removeEventListener('mousemove', moveHandler)
window.removeEventListener('touchcancel', stopResizeHandler)
window.removeEventListener('touchend', stopResizeHandler)
window.removeEventListener('mouseup', stopResizeHandler)
}
}, [onMove, onStopResizing])
useBindPointerMovementEventOnWindow(onMove, onStopResizing)
return [frameHeight, onStartResizing]
}