TWNTY-3794 - ESLint rule: only take explicit boolean predicates in if statements (#4354)

* ESLint rule: only take explicit boolean predicates in if statements

Co-authored-by: v1b3m <vibenjamin6@gmail.com>
Co-authored-by: Toledodev <rafael.toledo@engenharia.ufjf.br>

* Merge main

Co-authored-by: v1b3m <vibenjamin6@gmail.com>
Co-authored-by: Toledodev <rafael.toledo@engenharia.ufjf.br>

* Fix frontend linter errors

Co-authored-by: v1b3m <vibenjamin6@gmail.com>
Co-authored-by: Toledodev <rafael.toledo@engenharia.ufjf.br>

* Fix jest

Co-authored-by: v1b3m <vibenjamin6@gmail.com>
Co-authored-by: Toledodev <rafael.toledo@engenharia.ufjf.br>

* Refactor according to review

Co-authored-by: v1b3m <vibenjamin6@gmail.com>
Co-authored-by: Toledodev <rafael.toledo@engenharia.ufjf.br>

* Refactor according to review

Co-authored-by: v1b3m <vibenjamin6@gmail.com>
Co-authored-by: Toledodev <rafael.toledo@engenharia.ufjf.br>

* Fix lint on new code

Co-authored-by: v1b3m <vibenjamin6@gmail.com>
Co-authored-by: Toledodev <rafael.toledo@engenharia.ufjf.br>

---------

Co-authored-by: gitstart-twenty <gitstart-twenty@users.noreply.github.com>
Co-authored-by: v1b3m <vibenjamin6@gmail.com>
Co-authored-by: Toledodev <rafael.toledo@engenharia.ufjf.br>
This commit is contained in:
gitstart-app[bot]
2024-03-09 10:48:19 +01:00
committed by GitHub
parent 40bea0d95e
commit 17511be0cf
164 changed files with 655 additions and 367 deletions

View File

@ -1,6 +1,7 @@
import * as React from 'react';
import { useNavigate } from 'react-router-dom';
import { useTheme } from '@emotion/react';
import { isNonEmptyString } from '@sniptt/guards';
import { IconComponent } from '@/ui/display/icon/types/IconComponent';
import { Avatar, AvatarType } from '@/users/components/Avatar';
@ -41,7 +42,7 @@ export const EntityChip = ({
const theme = useTheme();
const handleLinkClick = (event: React.MouseEvent<HTMLDivElement>) => {
if (linkToEntity) {
if (isNonEmptyString(linkToEntity)) {
event.preventDefault();
event.stopPropagation();
navigate(linkToEntity);

View File

@ -5,6 +5,7 @@ import { Key } from 'ts-key-enum';
import { Button } from '@/ui/input/button/components/Button';
import { useScopedHotkeys } from '@/ui/utilities/hotkey/hooks/useScopedHotkeys';
import { isNonNullable } from '~/utils/isNonNullable';
import { DialogHotkeyScope } from '../types/DialogHotkeyScope';
@ -104,7 +105,7 @@ export const Dialog = ({
event.preventDefault();
if (confirmButton) {
if (isNonNullable(confirmButton)) {
confirmButton?.onClick?.(event);
closeSnackbar();
}

View File

@ -8,6 +8,7 @@ import {
ProgressBarControls,
} from '@/ui/feedback/progress-bar/components/ProgressBar';
import { RGBA } from '@/ui/theme/constants/Rgba';
import { isNonNullable } from '~/utils/isNonNullable';
import { usePausableTimeout } from '../hooks/usePausableTimeout';
@ -131,7 +132,7 @@ export const SnackBar = ({
);
const icon = useMemo(() => {
if (iconComponent) {
if (isNonNullable(iconComponent)) {
return iconComponent;
}

View File

@ -1,5 +1,7 @@
import { useCallback, useEffect, useRef } from 'react';
import { isNonNullable } from '~/utils/isNonNullable';
export const usePausableTimeout = (callback: () => void, delay: number) => {
// eslint-disable-next-line @nx/workspace-no-state-useref
const savedCallback = useRef<() => void>(callback);
@ -11,7 +13,7 @@ export const usePausableTimeout = (callback: () => void, delay: number) => {
const timeoutId = useRef<ReturnType<typeof setTimeout> | null>(null);
const tick = () => {
if (savedCallback.current) {
if (isNonNullable(savedCallback.current)) {
savedCallback.current();
}
};
@ -31,7 +33,7 @@ export const usePausableTimeout = (callback: () => void, delay: number) => {
if (delay !== null) {
startTimeout();
return () => {
if (timeoutId.current) {
if (isNonNullable(timeoutId.current)) {
clearTimeout(timeoutId.current);
}
};
@ -39,7 +41,7 @@ export const usePausableTimeout = (callback: () => void, delay: number) => {
}, [delay, startTimeout]);
const pauseTimeout = () => {
if (timeoutId.current) {
if (isNonNullable(timeoutId.current)) {
clearTimeout(timeoutId.current);
}
const elapsedTime = Date.now() - startTime.current;

View File

@ -7,6 +7,7 @@ import { SETTINGS_FIELD_CURRENCY_CODES } from '@/settings/data-model/constants/S
import { IconComponent } from '@/ui/display/icon/types/IconComponent';
import { CurrencyPickerDropdownButton } from '@/ui/input/components/internal/currency/components/CurrencyPickerDropdownButton';
import { TEXT_INPUT_STYLE } from '@/ui/theme/constants/TextInputStyle';
import { isNonNullable } from '~/utils/isNonNullable';
export const StyledInput = styled.input`
margin: 0;
@ -117,7 +118,7 @@ export const CurrencyInput = ({
useEffect(() => {
const currency = currencies.find(({ value }) => value === currencyCode);
if (currency) {
if (isNonNullable(currency)) {
setInternalCurrency(currency);
}
}, [currencies, currencyCode]);

View File

@ -4,6 +4,7 @@ import styled from '@emotion/styled';
import { useRegisterInputEvents } from '@/object-record/record-field/meta-types/input/hooks/useRegisterInputEvents';
import { TEXT_INPUT_STYLE } from '@/ui/theme/constants/TextInputStyle';
import { isNonNullable } from '~/utils/isNonNullable';
export type TextAreaInputProps = {
disabled?: boolean;
@ -55,7 +56,7 @@ export const TextAreaInput = ({
const wrapperRef = useRef<HTMLTextAreaElement>(null);
useEffect(() => {
if (wrapperRef.current) {
if (isNonNullable(wrapperRef.current)) {
wrapperRef.current.setSelectionRange(
wrapperRef.current.value.length,
wrapperRef.current.value.length,

View File

@ -1,6 +1,8 @@
import React, { ReactNode } from 'react';
import styled from '@emotion/styled';
import { isNonNullable } from '~/utils/isNonNullable';
import { ButtonPosition, ButtonProps } from './Button';
const StyledButtonGroupContainer = styled.div`
@ -39,15 +41,15 @@ export const ButtonGroup = ({
const additionalProps: any = { position, variant, accent, size };
if (variant) {
if (isNonNullable(variant)) {
additionalProps.variant = variant;
}
if (accent) {
if (isNonNullable(accent)) {
additionalProps.variant = variant;
}
if (size) {
if (isNonNullable(size)) {
additionalProps.size = size;
}

View File

@ -1,6 +1,8 @@
import React from 'react';
import styled from '@emotion/styled';
import { isNonNullable } from '~/utils/isNonNullable';
import { FloatingButtonPosition, FloatingButtonProps } from './FloatingButton';
const StyledFloatingButtonGroupContainer = styled.div`
@ -40,7 +42,7 @@ export const FloatingButtonGroup = ({
applyBlur: false,
};
if (size) {
if (isNonNullable(size)) {
additionalProps.size = size;
}

View File

@ -19,7 +19,7 @@ const StyledButton = styled.button<
>`
align-items: center;
background: ${({ theme, variant, disabled }) => {
if (disabled) {
if (disabled === true) {
return theme.background.secondary;
}
@ -34,7 +34,7 @@ const StyledButton = styled.button<
}};
border: 1px solid;
border-color: ${({ theme, disabled, variant }) => {
if (disabled) {
if (disabled === true) {
return theme.background.transparent.lighter;
}
@ -49,14 +49,14 @@ const StyledButton = styled.button<
}};
border-radius: ${({ theme }) => theme.border.radius.md};
${({ theme, disabled }) => {
if (disabled) {
if (disabled === true) {
return '';
}
return `box-shadow: ${theme.boxShadow.light};`;
}}
color: ${({ theme, variant, disabled }) => {
if (disabled) {
if (disabled === true) {
return theme.font.color.light;
}

View File

@ -9,6 +9,7 @@ import {
IconX,
} from '@/ui/display/icon';
import { Button } from '@/ui/input/button/components/Button';
import { isNonNullable } from '~/utils/isNonNullable';
const StyledContainer = styled.div`
display: flex;
@ -39,7 +40,7 @@ const StyledPicture = styled.button<{ withPicture: boolean }>`
}
${({ theme, withPicture, disabled }) => {
if (withPicture || disabled) {
if ((withPicture || disabled) === true) {
return '';
}
@ -132,10 +133,11 @@ export const ImageInput = ({
ref={hiddenFileInput}
accept="image/jpeg, image/png, image/gif" // to desired specification
onChange={(event) => {
if (onUpload) {
if (event.target.files) {
onUpload(event.target.files[0]);
}
if (
isNonNullable(onUpload) &&
isNonNullable(event.target.files)
) {
onUpload(event.target.files[0]);
}
}}
/>

View File

@ -2,6 +2,8 @@ import { useEffect, useState } from 'react';
import styled from '@emotion/styled';
import { motion } from 'framer-motion';
import { isNonNullable } from '~/utils/isNonNullable';
export type ToggleSize = 'small' | 'medium';
type ContainerProps = {
@ -56,7 +58,7 @@ export const Toggle = ({
const handleChange = () => {
setIsOn(!isOn);
if (onChange) {
if (isNonNullable(onChange)) {
onChange(!isOn);
}
};

View File

@ -6,6 +6,7 @@ import { CurrencyCode } from '@/object-record/record-field/types/CurrencyCode';
import { IconChevronDown } from '@/ui/display/icon';
import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown';
import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown';
import { isNonNullable } from '~/utils/isNonNullable';
import { CurrencyPickerHotkeyScope } from '../types/CurrencyPickerHotkeyScope';
@ -76,7 +77,7 @@ export const CurrencyPickerDropdownButton = ({
useEffect(() => {
const currency = currencies.find(({ value }) => value === valueCode);
if (currency) {
if (isNonNullable(currency)) {
setSelectedCurrency(currency);
}
}, [valueCode, currencies]);

View File

@ -9,6 +9,7 @@ import { CountryCallingCode } from 'libphonenumber-js';
import { IconChevronDown, IconWorld } from '@/ui/display/icon';
import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown';
import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown';
import { isNonNullable } from '~/utils/isNonNullable';
import { CountryPickerHotkeyScope } from '../types/CountryPickerHotkeyScope';
@ -112,7 +113,7 @@ export const CountryPickerDropdownButton = ({
useEffect(() => {
const country = countries.find(({ countryCode }) => countryCode === value);
if (country) {
if (isNonNullable(country)) {
setSelectedCountry(country);
}
}, [countries, value]);

View File

@ -14,6 +14,7 @@ import { HotkeyEffect } from '@/ui/utilities/hotkey/components/HotkeyEffect';
import { useScopedHotkeys } from '@/ui/utilities/hotkey/hooks/useScopedHotkeys';
import { HotkeyScope } from '@/ui/utilities/hotkey/types/HotkeyScope';
import { useListenClickOutside } from '@/ui/utilities/pointer-event/hooks/useListenClickOutside';
import { isNonNullable } from '~/utils/isNonNullable';
import { useDropdown } from '../hooks/useDropdown';
import { useInternalHotkeyScopeManagement } from '../hooks/useInternalHotkeyScopeManagement';
@ -59,11 +60,11 @@ export const Dropdown = ({
useDropdown(dropdownId);
const offsetMiddlewares = [];
if (dropdownOffset.x) {
if (isNonNullable(dropdownOffset.x)) {
offsetMiddlewares.push(offset({ crossAxis: dropdownOffset.x }));
}
if (dropdownOffset.y) {
if (isNonNullable(dropdownOffset.y)) {
offsetMiddlewares.push(offset({ mainAxis: dropdownOffset.y }));
}

View File

@ -3,6 +3,7 @@ import { useRecoilState } from 'recoil';
import { useDropdownStates } from '@/ui/layout/dropdown/hooks/internal/useDropdownStates';
import { usePreviousHotkeyScope } from '@/ui/utilities/hotkey/hooks/usePreviousHotkeyScope';
import { getScopeIdOrUndefinedFromComponentId } from '@/ui/utilities/recoil-scope/utils/getScopeIdOrUndefinedFromComponentId';
import { isNonNullable } from '~/utils/isNonNullable';
export const useDropdown = (dropdownId?: string) => {
const {
@ -35,7 +36,7 @@ export const useDropdown = (dropdownId?: string) => {
const openDropdown = () => {
setIsDropdownOpen(true);
if (dropdownHotkeyScope) {
if (isNonNullable(dropdownHotkeyScope)) {
setHotkeyScopeAndMemorizePreviousScope(
dropdownHotkeyScope.scope,
dropdownHotkeyScope.customScopes,

View File

@ -4,6 +4,7 @@ import { useSelectableListHotKeys } from '@/ui/layout/selectable-list/hooks/inte
import { useSelectableList } from '@/ui/layout/selectable-list/hooks/useSelectableList';
import { SelectableListScope } from '@/ui/layout/selectable-list/scopes/SelectableListScope';
import { arrayToChunks } from '~/utils/array/arrayToChunks';
import { isNonNullable } from '~/utils/isNonNullable';
type SelectableListProps = {
children: ReactNode;
@ -39,11 +40,11 @@ export const SelectableList = ({
);
}
if (selectableItemIdMatrix) {
if (isNonNullable(selectableItemIdMatrix)) {
setSelectableItemIds(selectableItemIdMatrix);
}
if (selectableItemIdArray) {
if (isNonNullable(selectableItemIdArray)) {
setSelectableItemIds(arrayToChunks(selectableItemIdArray, 1));
}
}, [selectableItemIdArray, selectableItemIdMatrix, setSelectableItemIds]);

View File

@ -1,3 +1,4 @@
import { isNonEmptyString } from '@sniptt/guards';
import { useRecoilCallback } from 'recoil';
import { Key } from 'ts-key-enum';
@ -104,12 +105,12 @@ export const useSelectableListHotKeys = (
const nextId = computeNextId(direction);
if (selectedItemId !== nextId) {
if (nextId) {
if (isNonEmptyString(nextId)) {
set(isSelectedItemIdSelector(nextId), true);
set(selectedItemIdState(), nextId);
}
if (selectedItemId) {
if (isNonEmptyString(selectedItemId)) {
set(isSelectedItemIdSelector(selectedItemId), false);
}
}
@ -144,7 +145,7 @@ export const useSelectableListHotKeys = (
selectableListOnEnterState(),
);
if (selectedItemId) {
if (isNonEmptyString(selectedItemId)) {
onEnter?.(selectedItemId);
}
},

View File

@ -8,6 +8,7 @@ import {
beautifyExactDateTime,
beautifyPastDateRelativeToNow,
} from '~/utils/date-utils';
import { isNonNullable } from '~/utils/isNonNullable';
type ShowPageSummaryCardProps = {
avatarPlaceholder: string;
@ -85,7 +86,7 @@ export const ShowPageSummaryCard = ({
const inputFileRef = useRef<HTMLInputElement>(null);
const onFileChange = (e: ChangeEvent<HTMLInputElement>) => {
if (e.target.files) onUploadPicture?.(e.target.files[0]);
if (isNonNullable(e.target.files)) onUploadPicture?.(e.target.files[0]);
};
const handleAvatarClick = () => {

View File

@ -20,7 +20,7 @@ export const StyledMenuItemSelect = styled(StyledMenuItemBase)<{
background: ${theme.background.transparent.medium};
}
`;
} else if (disabled) {
} else if (disabled === true) {
return css`
background: inherit;
&:hover {
@ -31,7 +31,7 @@ export const StyledMenuItemSelect = styled(StyledMenuItemBase)<{
cursor: default;
`;
} else if (hovered) {
} else if (hovered === true) {
return css`
background: ${theme.background.transparent.light};
`;

View File

@ -1,12 +1,14 @@
import { useNavigate } from 'react-router-dom';
import { useTheme } from '@emotion/react';
import styled from '@emotion/styled';
import { isNonEmptyString } from '@sniptt/guards';
import { useSetRecoilState } from 'recoil';
import { IconComponent } from '@/ui/display/icon/types/IconComponent';
import { isNavigationDrawerOpenState } from '@/ui/navigation/states/isNavigationDrawerOpenState';
import { MOBILE_VIEWPORT } from '@/ui/theme/constants/MobileViewport';
import { useIsMobile } from '@/ui/utilities/responsive/hooks/useIsMobile';
import { isNonNullable } from '~/utils/isNonNullable';
export type NavigationDrawerItemProps = {
className?: string;
@ -36,13 +38,13 @@ const StyledItem = styled.div<StyledItemProps>`
border: none;
border-radius: ${({ theme }) => theme.border.radius.sm};
color: ${(props) => {
if (props.active) {
if (props.active === true) {
return props.theme.font.color.primary;
}
if (props.danger) {
if (props.danger === true) {
return props.theme.color.red;
}
if (props.soon) {
if (props.soon === true) {
return props.theme.font.color.light;
}
return props.theme.font.color.secondary;
@ -146,12 +148,12 @@ export const NavigationDrawerItem = ({
setIsNavigationDrawerOpen(false);
}
if (onClick) {
if (isNonNullable(onClick)) {
onClick();
return;
}
if (to) navigate(to);
if (isNonEmptyString(to)) navigate(to);
};
return (

View File

@ -1,6 +1,7 @@
import { useEffect, useMemo, useState } from 'react';
import { ColorScheme } from '@/workspace-member/types/WorkspaceMember';
import { isNullable } from '~/utils/isNullable';
export const useSystemColorScheme = (): ColorScheme => {
const mediaQuery = useMemo(
@ -13,7 +14,7 @@ export const useSystemColorScheme = (): ColorScheme => {
);
useEffect(() => {
if (!window.matchMedia) {
if (isNullable(window.matchMedia)) {
return;
}

View File

@ -1,6 +1,8 @@
import { ReactNode, useLayoutEffect, useRef, useState } from 'react';
import styled from '@emotion/styled';
import { isNonNullable } from '~/utils/isNonNullable';
type ComputeNodeDimensionsProps = {
children: (
dimensions: { height: number; width: number } | undefined,
@ -32,7 +34,7 @@ export const ComputeNodeDimensions = ({
return;
}
const resizeObserver = new ResizeObserver(() => {
if (nodeWrapperRef.current) {
if (isNonNullable(nodeWrapperRef.current)) {
setNodeDimensions({
width: nodeWrapperRef.current.offsetWidth,
height: nodeWrapperRef.current.offsetHeight,

View File

@ -28,6 +28,7 @@ export const useScopedHotkeyCallback = () =>
.getValue();
if (!currentHotkeyScopes.includes(scope)) {
// eslint-disable-next-line @nx/workspace-explicit-boolean-predicates-in-if
if (DEBUG_HOTKEY_SCOPE) {
logDebug(
`%cI can't call hotkey (${
@ -42,6 +43,7 @@ export const useScopedHotkeyCallback = () =>
return;
}
// eslint-disable-next-line @nx/workspace-explicit-boolean-predicates-in-if
if (DEBUG_HOTKEY_SCOPE) {
logDebug(
`%cI can call hotkey (${

View File

@ -2,6 +2,8 @@ import { Options, useHotkeys } from 'react-hotkeys-hook';
import { Keys } from 'react-hotkeys-hook/dist/types';
import { useRecoilState } from 'recoil';
import { isNonNullable } from '~/utils/isNonNullable';
import { pendingHotkeyState } from '../states/internal/pendingHotkeysState';
import { useScopedHotkeyCallback } from './useScopedHotkeyCallback';
@ -55,7 +57,7 @@ export const useSequenceHotkeys = (
setPendingHotkey(null);
if (options.preventDefault) {
if (isNonNullable(options.preventDefault)) {
keyboardEvent.stopImmediatePropagation();
keyboardEvent.stopPropagation();
keyboardEvent.preventDefault();

View File

@ -63,15 +63,15 @@ export const useSetHotkeyScope = () =>
const scopesToSet: string[] = [];
if (newHotkeyScope.customScopes?.commandMenu) {
if (newHotkeyScope.customScopes?.commandMenu === true) {
scopesToSet.push(AppHotkeyScope.CommandMenu);
}
if (newHotkeyScope?.customScopes?.goto) {
if (newHotkeyScope?.customScopes?.goto === true) {
scopesToSet.push(AppHotkeyScope.Goto);
}
if (newHotkeyScope?.customScopes?.keyboardShortcutMenu) {
if (newHotkeyScope?.customScopes?.keyboardShortcutMenu === true) {
scopesToSet.push(AppHotkeyScope.KeyboardShortcutMenu);
}

View File

@ -2,6 +2,8 @@ import React from 'react';
import { act } from 'react-dom/test-utils';
import { fireEvent, render, renderHook } from '@testing-library/react';
import { isNonNullable } from '~/utils/isNonNullable';
import {
ClickOutsideMode,
useListenClickOutside,
@ -46,7 +48,7 @@ describe('useListenClickOutside', () => {
);
act(() => {
if (containerRef.current) {
if (isNonNullable(containerRef.current)) {
fireEvent.mouseDown(containerRef.current);
fireEvent.click(containerRef.current);
}
@ -95,7 +97,7 @@ describe('useListenClickOutsideByClassName', () => {
act(() => {
const notClickableElement = container.querySelector('.will-trigger');
if (notClickableElement) {
if (isNonNullable(notClickableElement)) {
fireEvent.mouseDown(notClickableElement);
fireEvent.click(notClickableElement);
}
@ -122,7 +124,7 @@ describe('useListenClickOutsideByClassName', () => {
act(() => {
const notClickableElement = container.querySelector('.wont-trigger');
if (notClickableElement) {
if (isNonNullable(notClickableElement)) {
fireEvent.mouseDown(notClickableElement);
fireEvent.click(notClickableElement);
}

View File

@ -7,6 +7,7 @@ import {
ClickOutsideMode,
useListenClickOutsideV2,
} from '@/ui/utilities/pointer-event/hooks/useListenClickOutsideV2';
import { isNonNullable } from '~/utils/isNonNullable';
const containerRef = React.createRef<HTMLDivElement>();
const nullRef = React.createRef<HTMLDivElement>();
@ -76,7 +77,7 @@ describe('useListenClickOutsideV2', () => {
);
act(() => {
if (containerRef.current) {
if (isNonNullable(containerRef.current)) {
fireEvent.mouseDown(containerRef.current);
fireEvent.click(containerRef.current);
}
@ -100,7 +101,7 @@ describe('useListenClickOutsideV2', () => {
);
act(() => {
if (containerRef.current) {
if (isNonNullable(containerRef.current)) {
fireEvent.mouseDown(containerRef.current);
fireEvent.click(containerRef.current);
}

View File

@ -1,3 +1,5 @@
import { isNonEmptyString } from '@sniptt/guards';
import { ScopeInternalContext } from '../types/ScopeInternalContext';
import { useScopeInternalContext } from './useScopeInternalContext';
@ -10,9 +12,9 @@ export const useAvailableScopeIdOrThrow = <T extends { scopeId: string }>(
const scopeIdFromContext = scopeInternalContext?.scopeId;
if (scopeIdFromProps) {
if (isNonEmptyString(scopeIdFromProps)) {
return scopeIdFromProps;
} else if (scopeIdFromContext) {
} else if (isNonEmptyString(scopeIdFromContext)) {
return scopeIdFromContext;
} else {
throw new Error('Scope id is not provided and cannot be found in context.');

View File

@ -1,9 +1,11 @@
import React from 'react';
import { expect } from '@storybook/test';
import { act, fireEvent, renderHook } from '@testing-library/react';
import { RecoilRoot, useRecoilValue } from 'recoil';
import { useListenScroll } from '@/ui/utilities/scroll/hooks/useListenScroll';
import { isScrollingState } from '@/ui/utilities/scroll/states/isScrollingState';
import { isNonNullable } from '~/utils/isNonNullable';
const containerRef = React.createRef<HTMLDivElement>();
@ -38,7 +40,7 @@ describe('useListenScroll', () => {
const container = document.querySelector('#container');
act(() => {
if (container) fireEvent.scroll(container);
if (isNonNullable(container)) fireEvent.scroll(container);
});
expect(result.current.isScrolling).toBe(true);

View File

@ -1,11 +1,13 @@
import { useContext } from 'react';
import { isNullable } from '~/utils/isNullable';
import { ScrollWrapperContext } from '../components/ScrollWrapper';
export const useScrollWrapperScopedRef = () => {
const scrollWrapperRef = useContext(ScrollWrapperContext);
if (!scrollWrapperRef)
if (isNullable(scrollWrapperRef))
throw new Error(
`Using a scroll ref without a ScrollWrapper : verify that you are using a ScrollWrapper if you intended to do so.`,
);